BRC-100钱包实现指南Skill wallet-brc100

这个技能提供了使用 @bsv/wallet-toolbox 包实现 BRC-100 兼容钱包的全面指南,涵盖安装设置、钱包初始化、交易操作、密钥管理、存储配置和证书系统。关键词:BRC-100, 钱包开发, BSV区块链, TypeScript, 交易操作, 密钥管理, UTXO管理, 证书系统, 区块链开发, 量化金融

链开发 0 次安装 0 次浏览 更新于 3/15/2026

名称:钱包-brc100 描述:当用户询问“实现 BRC-100 钱包”、“使用钱包工具箱”、“TypeScript BSV 钱包”、“BRC-100 实现”、“桌面钱包”、“Electron 钱包”、“浏览器钱包”、“IndexedDB 钱包存储”、“钱包操作”、“钱包篮子”、“UTXO 管理”、“createAction”、“listOutputs”、“钱包证书”,或需要指导使用 @bsv/wallet-toolbox 构建符合标准的钱包时,应使用此技能。

BRC-100 钱包实现指南

此技能提供使用 @bsv/wallet-toolbox 包(v1.7.18+)实现 BRC-100 兼容钱包的全面指导。

入门指南:在实现之前,请查看战略问卷以确定适合您钱包类型的架构。

快速参考

核心依赖

{
  "@bsv/wallet-toolbox": "^1.7.18",
  "@bsv/sdk": "^1.9.29"
}

主要类

目的 使用场景
Wallet 完整的 BRC-100 钱包 构建生产级钱包应用
SimpleWalletManager 轻量级包装器 简单的基于密钥的身份验证
CWIStyleWalletManager 多配置文件钱包 高级 UMP 代币流程
WalletSigner 交易签名 自定义签名逻辑

目录

  1. 安装与设置
  2. 钱包初始化
  3. 交易操作
  4. 密钥管理
  5. 存储配置
  6. 证书操作
  7. 错误处理
  8. 生产模式

1. 安装与设置

安装依赖

npm install @bsv/wallet-toolbox @bsv/sdk
# 可选存储后端:
npm install knex sqlite3          # SQLite
npm install knex mysql2           # MySQL
npm install idb                   # IndexedDB(浏览器)

基本导入

import {
  Wallet,
  WalletStorageManager,
  StorageKnex,
  StorageIdb,
  Services,
  WalletServices,
  PrivilegedKeyManager
} from '@bsv/wallet-toolbox'

import {
  PrivateKey,
  KeyDeriver,
  Random,
  Utils
} from '@bsv/sdk'

2. 钱包初始化

模式 A:简单钱包(Node.js 与 SQLite)

import { Wallet, StorageKnex, Services } from '@bsv/wallet-toolbox'
import { PrivateKey, Random } from '@bsv/sdk'
import Knex from 'knex'

async function createSimpleWallet() {
  // 1. 创建根私钥(或从助记词派生)
  const rootKey = new PrivateKey(Random(32))
  // 使用 @bsv/sdk 的 KeyDeriver 进行正确的 BRC-42 密钥派生
  const keyDeriver = new KeyDeriver(rootKey)

  // 2. 配置 SQLite 存储
  const knex = Knex({
    client: 'sqlite3',
    connection: { filename: './wallet.db' },
    useNullAsDefault: true
  })

  const storage = new StorageKnex({
    knex,
    storageIdentityKey: rootKey.toPublicKey().toString(),
    storageName: 'my-wallet-storage'
  })

  await storage.makeAvailable()

  // 3. 配置服务(主网)
  const services = new Services({
    chain: 'main',
    bsvExchangeRate: { timestamp: new Date(), base: 'USD', rate: 50 },
    bsvUpdateMsecs: 15 * 60 * 1000,
    fiatExchangeRates: {
      timestamp: new Date(),
      base: 'USD',
      rates: { EUR: 0.85, GBP: 0.73 }
    },
    fiatUpdateMsecs: 24 * 60 * 60 * 1000,
    arcUrl: 'https://arc.taal.com',
    arcConfig: {}
  })

  // 4. 创建钱包
  const wallet = new Wallet({
    chain: 'main',
    keyDeriver,
    storage,
    services
  })

  return wallet
}

模式 B:浏览器钱包(IndexedDB)

import { Wallet, StorageIdb, Services } from '@bsv/wallet-toolbox'
import { PrivateKey, Random } from '@bsv/sdk'

async function createBrowserWallet() {
  const rootKey = new PrivateKey(Random(32))

  // 使用 IndexedDB 作为浏览器存储
  const storage = new StorageIdb({
    idb: await openDB('my-wallet-db', 1),
    storageIdentityKey: rootKey.toPublicKey().toString(),
    storageName: 'browser-wallet'
  })

  await storage.makeAvailable()

  const services = new Services({
    chain: 'main',
    // ... 服务配置
  })

  const wallet = new Wallet({
    chain: 'main',
    keyDeriver: createKeyDeriver(rootKey),
    storage,
    services
  })

  return wallet
}

模式 C:多配置文件钱包

import { CWIStyleWalletManager, OverlayUMPTokenInteractor } from '@bsv/wallet-toolbox'

async function createMultiProfileWallet() {
  const manager = new CWIStyleWalletManager(
    'example.com', // 管理员发起者
    async (profilePrimaryKey, profilePrivilegedKeyManager, profileId) => {
      // 为特定配置文件构建钱包
      const keyDeriver = createKeyDeriver(new PrivateKey(profilePrimaryKey))
      const storage = await createStorage(profileId)
      const services = new Services({ chain: 'main', /* ... */ })

      return new Wallet({
        chain: 'main',
        keyDeriver,
        storage,
        services,
        privilegedKeyManager: profilePrivilegedKeyManager
      })
    },
    new OverlayUMPTokenInteractor(), // UMP 代币交互器
    async (recoveryKey) => {
      // 保存恢复密钥(例如,提示用户记下)
      console.log('保存此恢复密钥:', Utils.toBase64(recoveryKey))
      return true
    },
    async (reason, test) => {
      // 从用户获取密码
      const password = prompt(`输入密码原因:${reason}`)
      if (!password) throw new Error('需要密码')
      if (!test(password)) throw new Error('密码无效')
      return password
    }
  )

  // 提供展示密钥(例如,从二维码扫描)
  const presentationKey = Random(32)
  await manager.providePresentationKey(presentationKey)

  // 提供密码
  await manager.providePassword('user-password')

  // 现在已认证并准备使用
  return manager
}

3. 交易操作

创建交易

import { CreateActionArgs, CreateActionResult } from '@bsv/sdk'

async function sendBSV(
  wallet: Wallet,
  recipientAddress: string,
  satoshis: number
) {
  const args: CreateActionArgs = {
    description: '发送 BSV 支付',
    outputs: [{
      lockingScript: Script.fromAddress(recipientAddress).toHex(),
      satoshis,
      outputDescription: `支付给 ${recipientAddress}`,
      basket: 'default',
      tags: ['payment']
    }],
    options: {
      acceptDelayedBroadcast: false, // 立即广播
      randomizeOutputs: true          // 隐私
    }
  }

  const result: CreateActionResult = await wallet.createAction(args)

  if (result.txid) {
    console.log('交易已创建:', result.txid)
    return result.txid
  } else {
    console.log('交易待签名')
    return result.signableTransaction
  }
}

签名交易

async function signTransaction(
  wallet: Wallet,
  reference: string,
  unlockingScripts: Record<number, { unlockingScript: string }>
) {
  const result = await wallet.signAction({
    reference,
    spends: unlockingScripts
  })

  console.log('交易已签名:', result.txid)
  return result
}

检查钱包余额

async function getWalletBalance(wallet: Wallet) {
  // 方法 1:快速余额(使用特殊操作)
  const balance = await wallet.balance()
  console.log(`余额:${balance} satoshis`)

  // 方法 2:带 UTXO 的详细余额
  const detailed = await wallet.balanceAndUtxos('default')
  console.log(`总计:${detailed.total} satoshis`)
  console.log(`UTXO 数量:${detailed.utxos.length}`)
  detailed.utxos.forEach(utxo => {
    console.log(`  ${utxo.outpoint}: ${utxo.satoshis} sats`)
  })

  return balance
}

列出输出

import { ListOutputsArgs, ListOutputsResult } from '@bsv/sdk'

async function listSpendableOutputs(wallet: Wallet) {
  const args: ListOutputsArgs = {
    basket: 'default',  // 更改篮子
    spendable: true,    // 仅可花费输出
    limit: 100,
    offset: 0,
    tags: ['payment']   // 可选:按标签过滤
  }

  const result: ListOutputsResult = await wallet.listOutputs(args)

  console.log(`找到 ${result.totalOutputs} 个输出`)
  result.outputs.forEach(output => {
    console.log(`  ${output.outpoint}: ${output.satoshis} sats`)
  })

  return result
}

列出操作(交易)

async function listTransactionHistory(wallet: Wallet) {
  const result = await wallet.listActions({
    labels: [],
    labelQueryMode: 'any',
    limit: 50,
    offset: 0
  })

  console.log(`找到 ${result.totalActions} 个操作`)
  result.actions.forEach(action => {
    console.log(`  ${action.txid}: ${action.status} - ${action.description}`)
  })

  return result
}

4. 密钥管理

获取公钥

async function getIdentityKey(wallet: Wallet) {
  // 获取钱包的身份密钥
  const result = await wallet.getPublicKey({ identityKey: true })
  console.log('身份密钥:', result.publicKey)
  return result.publicKey
}

async function getDerivedKey(wallet: Wallet) {
  // 获取特定协议的派生密钥
  const result = await wallet.getPublicKey({
    protocolID: [2, 'my-app'],
    keyID: 'encryption-key-1',
    counterparty: 'recipient-identity-key'
  })

  return result.publicKey
}

加密/解密数据

async function encryptMessage(
  wallet: Wallet,
  plaintext: string,
  recipientPubKey: string
) {
  const result = await wallet.encrypt({
    plaintext: Utils.toArray(plaintext, 'utf8'),
    protocolID: [2, 'secure-messaging'],
    keyID: 'msg-key',
    counterparty: recipientPubKey
  })

  return Utils.toBase64(result.ciphertext)
}

async function decryptMessage(
  wallet: Wallet,
  ciphertext: string,
  senderPubKey: string
) {
  const result = await wallet.decrypt({
    ciphertext: Utils.toArray(ciphertext, 'base64'),
    protocolID: [2, 'secure-messaging'],
    keyID: 'msg-key',
    counterparty: senderPubKey
  })

  return Utils.toUTF8(result.plaintext)
}

创建签名

async function signData(wallet: Wallet, data: string) {
  const result = await wallet.createSignature({
    data: Utils.toArray(data, 'utf8'),
    protocolID: [2, 'document-signing'],
    keyID: 'sig-key',
    counterparty: 'self'
  })

  return Utils.toBase64(result.signature)
}

5. 存储配置

SQLite 存储(Node.js)

import Knex from 'knex'
import { StorageKnex } from '@bsv/wallet-toolbox'

async function setupSQLiteStorage() {
  const knex = Knex({
    client: 'sqlite3',
    connection: { filename: './wallet.db' },
    useNullAsDefault: true
  })

  const storage = new StorageKnex({
    knex,
    storageIdentityKey: 'your-identity-key',
    storageName: 'main-storage'
  })

  await storage.makeAvailable()
  return storage
}

MySQL 存储

async function setupMySQLStorage() {
  const knex = Knex({
    client: 'mysql2',
    connection: {
      host: 'localhost',
      user: 'wallet_user',
      password: 'secure_password',
      database: 'wallet_db'
    }
  })

  const storage = new StorageKnex({
    knex,
    storageIdentityKey: 'your-identity-key',
    storageName: 'mysql-storage'
  })

  await storage.makeAvailable()
  return storage
}

IndexedDB 存储(浏览器)

import { openDB, DBSchema } from 'idb'
import { StorageIdb } from '@bsv/wallet-toolbox'

interface WalletDB extends DBSchema {
  // 存储模式由 StorageIdb 管理
}

async function setupIndexedDBStorage() {
  const db = await openDB<WalletDB>('wallet-db', 1, {
    upgrade(db) {
      // StorageIdb 创建必要的对象存储
    }
  })

  const storage = new StorageIdb({
    idb: db,
    storageIdentityKey: 'your-identity-key',
    storageName: 'browser-storage'
  })

  await storage.makeAvailable()
  return storage
}

多存储管理器

import { WalletStorageManager } from '@bsv/wallet-toolbox'

async function setupMultiStorage() {
  const primaryStorage = await setupSQLiteStorage()
  const backupStorage = await setupMySQLStorage()

  const manager = new WalletStorageManager(
    primaryStorage,
    [backupStorage]
  )

  return manager
}

6. 证书操作

获取证书(直接协议)

import { AcquireCertificateArgs } from '@bsv/sdk'

async function acquireDirectCertificate(wallet: Wallet) {
  const args: AcquireCertificateArgs = {
    acquisitionProtocol: 'direct',
    type: 'https://example.com/user-certificate',
    certifier: 'certifier-identity-key',
    serialNumber: Utils.toArray('cert-serial-123', 'utf8'),
    subject: await wallet.getIdentityKey(),
    revocationOutpoint: 'txid.vout',
    fields: {
      name: Utils.toArray('Alice Smith', 'utf8'),
      email: Utils.toArray('alice@example.com', 'utf8')
    },
    keyringForSubject: { /* 主密钥环 */ },
    signature: Utils.toArray('signature-bytes', 'base64')
  }

  const result = await wallet.acquireCertificate(args)
  console.log('证书已获取:', result.certificateId)
  return result
}

获取证书(发行协议)

async function requestCertificateIssuance(wallet: Wallet) {
  const args: AcquireCertificateArgs = {
    acquisitionProtocol: 'issuance',
    type: 'https://example.com/kyc-certificate',
    certifier: 'certifier-identity-key',
    certifierUrl: 'https://certifier.example.com',
    fields: {
      name: 'Alice Smith',
      birthdate: '1990-01-01',
      country: 'US'
    }
  }

  const result = await wallet.acquireCertificate(args)
  console.log('证书已发行:', result.certificateId)
  return result
}

列出证书

async function listMyCertificates(wallet: Wallet) {
  const result = await wallet.listCertificates({
    certifiers: ['certifier-identity-key'],
    types: ['https://example.com/user-certificate'],
    limit: 50,
    offset: 0
  })

  console.log(`找到 ${result.totalCertificates} 个证书`)
  result.certificates.forEach(cert => {
    console.log(`  类型:${cert.type}, 认证者:${cert.certifier}`)
  })

  return result
}

证明证书

async function proveCertificate(wallet: Wallet, certificateId: string) {
  const result = await wallet.proveCertificate({
    certificateId,
    fieldsToReveal: ['name', 'email'],
    verifier: 'verifier-identity-key',
    privileged: false
  })

  console.log('证书证明:', result.keyringForVerifier)
  return result
}

7. 错误处理

标准错误类型

import {
  WalletError,
  WERR_INVALID_PARAMETER,
  WERR_INTERNAL,
  WERR_REVIEW_ACTIONS
} from '@bsv/wallet-toolbox'

try {
  const result = await wallet.createAction({
    description: '测试交易',
    outputs: [/* ... */]
  })
} catch (eu: unknown) {
  const error = WalletError.fromUnknown(eu)

  if (error.name === 'WERR_INVALID_PARAMETER') {
    console.error('无效参数:', error.message)
    console.error('堆栈:', error.stack)
  } else if (error.name === 'WERR_REVIEW_ACTIONS') {
    // 处理交易审核错误
    console.error('需要审核:', error.details)
  } else {
    console.error('钱包错误:', error.message)
  }
}

审核操作错误(交易失败)

async function handleCreateAction(wallet: Wallet) {
  try {
    return await wallet.createAction({
      description: '支付',
      outputs: [/* ... */]
    })
  } catch (eu: unknown) {
    const error = WalletError.fromUnknown(eu)

    if (error.name === 'WERR_REVIEW_ACTIONS') {
      // 访问详细失败信息
      const details = error as any
      console.error('延迟结果:', details.notDelayedResults)
      console.error('发送结果:', details.sendWithResults)
      console.error('失败 txid:', details.txid)

      // 处理双重花费
      if (details.notDelayedResults?.some(r => r.status === 'doubleSpend')) {
        console.error('检测到双重花费!')
        console.error('竞争交易:', details.notDelayedResults[0].competingTxs)
      }
    }

    throw error
  }
}

8. 生产模式

模式:钱包状态管理

class WalletManager {
  private wallet: Wallet | null = null

  async initialize(rootKey: PrivateKey) {
    if (this.wallet) {
      throw new Error('钱包已初始化')
    }

    const storage = await this.setupStorage()
    const services = this.setupServices()
    const keyDeriver = this.createKeyDeriver(rootKey)

    this.wallet = new Wallet({
      chain: 'main',
      keyDeriver,
      storage,
      services
    })

    return this.wallet
  }

  async destroy() {
    if (this.wallet) {
      await this.wallet.destroy()
      this.wallet = null
    }
  }

  getWallet(): Wallet {
    if (!this.wallet) {
      throw new Error('钱包未初始化')
    }
    return this.wallet
  }

  private async setupStorage() {
    // 存储设置逻辑
    return await setupSQLiteStorage()
  }

  private setupServices() {
    return new Services({
      chain: 'main',
      // ... 配置
    })
  }

  private createKeyDeriver(rootKey: PrivateKey) {
    // 密钥派生逻辑
    return {
      rootKey,
      identityKey: rootKey.toPublicKey().toString(),
      // ... 派生方法
    }
  }
}

模式:交易重试逻辑

async function sendWithRetry(
  wallet: Wallet,
  args: CreateActionArgs,
  maxRetries = 3
): Promise<string> {
  let lastError: Error | null = null

  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const result = await wallet.createAction(args)

      if (result.txid) {
        return result.txid
      }

      // 如果需要,处理签名
      if (result.signableTransaction) {
        const signed = await wallet.signAction({
          reference: result.signableTransaction.reference,
          spends: {} // 提供解锁脚本
        })
        return signed.txid!
      }

      throw new Error('意外结果格式')

    } catch (error) {
      lastError = error as Error
      console.error(`尝试 ${attempt} 失败:`, error)

      if (attempt < maxRetries) {
        await new Promise(resolve => setTimeout(resolve, 1000 * attempt))
      }
    }
  }

  throw lastError || new Error('所有重试失败')
}

模式:后台交易监控

import { Monitor } from '@bsv/wallet-toolbox'

async function setupMonitor(wallet: Wallet) {
  const monitor = new Monitor({
    storage: wallet.storage,
    services: wallet.services,
    chain: 'main'
  })

  monitor.on('transaction', (status) => {
    console.log('交易更新:', status.txid, status.blockHeight)
  })

  monitor.on('error', (error) => {
    console.error('监控错误:', error)
  })

  await monitor.start()

  return monitor
}

相关技能

对于全面的钱包开发,还参考以下技能:

技能 关系
encrypt-decrypt-backup 标准备份格式(.bep 文件,AES-256-GCM)
junglebus 从区块链填充 UTXO 集,实时流
key-derivation Type42/BRC-42 和 BIP32 密钥派生细节
wallet-encrypt-decrypt ECDH 消息加密模式
wallet-send-bsv 基本交易创建(比 BRC-100 更简单)

对于 1Sat Ordinals / 代币支持:

如果您的 BRC-100 钱包需要处理 1Sat Ordinals、BSV-20/BSV-21 代币或铭文,请使用 @1sat/wallet-toolbox,它在核心钱包工具箱上包装了 ordinals 功能。

参见 1sat-skills

  • wallet-create-ordinals - 铸造铭文
  • extract-blockchain-media - 从交易中提取媒体
  • ordinals-marketplace - 浏览 GorillaPool 市场

附加资源

研究:对于 BRC 规范或实现模式的深入研究,请使用浏览器代理从 bsv.brc.dev 获取当前文档。


平台指南

特定于平台的实现指南:

平台 指南 参考实现
浏览器扩展 extension-guide.md yours-wallet
桌面(Electron) desktop-guide.md bsv-desktop
Web 应用 web-guide.md -
移动(React Native) mobile-guide.md -
Node.js 服务/CLI nodejs-guide.md -

参见 references/key-concepts.md 了解 BRC-100 独特概念:

  • 操作与交易
  • 篮子和标签
  • 证书系统(BRC-52/53/64/65)
  • 后台监控

常见模式总结

任务 方法 关键参数
发送 BSV createAction() outputs, options
检查余额 balance()
列出 UTXO listOutputs() basket, spendable
获取历史 listActions() labels, limit
获取公钥 getPublicKey() protocolID, keyID
加密数据 encrypt() plaintext, counterparty
获取证书 acquireCertificate() type, certifier

记住:始终正确处理错误,安全使用特权密钥,并遵循 BRC-100 安全级别进行敏感操作!