wallet-brc100

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

BRC-100 Wallet Implementation Guide

BRC-100钱包实现指南

This skill provides comprehensive guidance for implementing BRC-100 conforming wallets using the
@bsv/wallet-toolbox
package (v1.7.18+).
Getting Started: Before implementing, review the Strategic Questionnaire to determine the right architecture for your wallet type.
本技能提供了使用
@bsv/wallet-toolbox
包(v1.7.18+)实现符合BRC-100标准的钱包的全面指导。
入门指南:在开始实现前,请查看战略问卷以确定适合您钱包类型的架构。

Quick Reference

快速参考

Core Dependencies

核心依赖

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

Main Classes

主要类

ClassPurposeUse When
WalletFull BRC-100 walletBuilding production wallet apps
SimpleWalletManagerLightweight wrapperSimple key-based authentication
CWIStyleWalletManagerMulti-profile walletAdvanced UMP token flows
WalletSignerTransaction signingCustom signing logic

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

Table of Contents

目录

1. Installation & Setup

1. 安装与设置

Install Dependencies

安装依赖

bash
npm install @bsv/wallet-toolbox @bsv/sdk
bash
npm install @bsv/wallet-toolbox @bsv/sdk

Optional storage backends:

可选存储后端:

npm install knex sqlite3 # SQLite npm install knex mysql2 # MySQL npm install idb # IndexedDB (browser)
undefined
npm install knex sqlite3 # SQLite npm install knex mysql2 # MySQL npm install idb # IndexedDB(浏览器端)
undefined

Basic Imports

基础导入

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

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

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

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

2. Wallet Initialization

2. 钱包初始化

Pattern A: Simple Wallet (Node.js with SQLite)

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

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

async function createSimpleWallet() {
  // 1. Create root private key (or derive from mnemonic)
  const rootKey = new PrivateKey(Random(32))
  // Use KeyDeriver from @bsv/sdk for proper BRC-42 key derivation
  const keyDeriver = new KeyDeriver(rootKey)

  // 2. Configure SQLite storage
  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. Configure services (mainnet)
  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. Create wallet
  const wallet = new Wallet({
    chain: 'main',
    keyDeriver,
    storage,
    services
  })

  return wallet
}
typescript
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
}

Pattern B: Browser Wallet (IndexedDB)

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

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

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

  // Use IndexedDB for browser storage
  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',
    // ... services config
  })

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

  return wallet
}
typescript
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
}

Pattern C: Multi-Profile Wallet

模式C:多配置文件钱包

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

async function createMultiProfileWallet() {
  const manager = new CWIStyleWalletManager(
    'example.com', // Admin originator
    async (profilePrimaryKey, profilePrivilegedKeyManager, profileId) => {
      // Build wallet for specific profile
      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 token interactor
    async (recoveryKey) => {
      // Save recovery key (e.g., prompt user to write it down)
      console.log('SAVE THIS RECOVERY KEY:', Utils.toBase64(recoveryKey))
      return true
    },
    async (reason, test) => {
      // Retrieve password from user
      const password = prompt(`Enter password for: ${reason}`)
      if (!password) throw new Error('Password required')
      if (!test(password)) throw new Error('Invalid password')
      return password
    }
  )

  // Provide presentation key (e.g., from QR code scan)
  const presentationKey = Random(32)
  await manager.providePresentationKey(presentationKey)

  // Provide password
  await manager.providePassword('user-password')

  // Now authenticated and ready to use
  return manager
}

typescript
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. Transaction Operations

3. 交易操作

Create a Transaction

创建交易

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

async function sendBSV(
  wallet: Wallet,
  recipientAddress: string,
  satoshis: number
) {
  const args: CreateActionArgs = {
    description: 'Send BSV payment',
    outputs: [{
      lockingScript: Script.fromAddress(recipientAddress).toHex(),
      satoshis,
      outputDescription: `Payment to ${recipientAddress}`,
      basket: 'default',
      tags: ['payment']
    }],
    options: {
      acceptDelayedBroadcast: false, // Broadcast immediately
      randomizeOutputs: true          // Privacy
    }
  }

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

  if (result.txid) {
    console.log('Transaction created:', result.txid)
    return result.txid
  } else {
    console.log('Transaction pending signature')
    return result.signableTransaction
  }
}
typescript
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
  }
}

Sign a Transaction

签名交易

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

  console.log('Transaction signed:', result.txid)
  return result
}
typescript
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
}

Check Wallet Balance

查看钱包余额

typescript
async function getWalletBalance(wallet: Wallet) {
  // Method 1: Quick balance (uses special operation)
  const balance = await wallet.balance()
  console.log(`Balance: ${balance} satoshis`)

  // Method 2: Detailed balance with UTXOs
  const detailed = await wallet.balanceAndUtxos('default')
  console.log(`Total: ${detailed.total} satoshis`)
  console.log(`UTXOs: ${detailed.utxos.length}`)
  detailed.utxos.forEach(utxo => {
    console.log(`  ${utxo.outpoint}: ${utxo.satoshis} sats`)
  })

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

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

  return balance
}

List Outputs

列出输出

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

async function listSpendableOutputs(wallet: Wallet) {
  const args: ListOutputsArgs = {
    basket: 'default',  // Change basket
    spendable: true,    // Only spendable outputs
    limit: 100,
    offset: 0,
    tags: ['payment']   // Optional: filter by tags
  }

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

  console.log(`Found ${result.totalOutputs} outputs`)
  result.outputs.forEach(output => {
    console.log(`  ${output.outpoint}: ${output.satoshis} sats`)
  })

  return result
}
typescript
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}`)
  })

  return result
}

List Actions (Transactions)

列出操作(交易历史)

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

  console.log(`Found ${result.totalActions} actions`)
  result.actions.forEach(action => {
    console.log(`  ${action.txid}: ${action.status} - ${action.description}`)
  })

  return result
}

typescript
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. Key Management

4. 密钥管理

Get Public Key

获取公钥

typescript
async function getIdentityKey(wallet: Wallet) {
  // Get wallet's identity key
  const result = await wallet.getPublicKey({ identityKey: true })
  console.log('Identity Key:', result.publicKey)
  return result.publicKey
}

async function getDerivedKey(wallet: Wallet) {
  // Get derived key for specific protocol
  const result = await wallet.getPublicKey({
    protocolID: [2, 'my-app'],
    keyID: 'encryption-key-1',
    counterparty: 'recipient-identity-key'
  })

  return result.publicKey
}
typescript
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
}

Encrypt/Decrypt Data

加密/解密数据

typescript
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)
}
typescript
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)
}

Create Signature

创建签名

typescript
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)
}

typescript
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. Storage Configuration

5. 存储配置

SQLite Storage (Node.js)

SQLite存储(Node.js)

typescript
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
}
typescript
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 Storage

MySQL存储

typescript
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
}
typescript
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 Storage (Browser)

IndexedDB存储(浏览器端)

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

interface WalletDB extends DBSchema {
  // Storage schema is managed by StorageIdb
}

async function setupIndexedDBStorage() {
  const db = await openDB<WalletDB>('wallet-db', 1, {
    upgrade(db) {
      // StorageIdb creates necessary object stores
    }
  })

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

  await storage.makeAvailable()
  return storage
}
typescript
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
}

Multi-Storage Manager

多存储管理器

typescript
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
}

typescript
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. Certificate Operations

6. 证书操作

Acquire Certificate (Direct Protocol)

获取证书(直接协议)

typescript
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: { /* master keyring */ },
    signature: Utils.toArray('signature-bytes', 'base64')
  }

  const result = await wallet.acquireCertificate(args)
  console.log('Certificate acquired:', result.certificateId)
  return result
}
typescript
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
}

Acquire Certificate (Issuance Protocol)

获取证书(颁发协议)

typescript
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('Certificate issued:', result.certificateId)
  return result
}
typescript
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
}

List Certificates

列出证书

typescript
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(`Found ${result.totalCertificates} certificates`)
  result.certificates.forEach(cert => {
    console.log(`  Type: ${cert.type}, Certifier: ${cert.certifier}`)
  })

  return result
}
typescript
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
}

Prove Certificate

证明证书

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

  console.log('Certificate proof:', result.keyringForVerifier)
  return result
}

typescript
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. Error Handling

7. 错误处理

Standard Error Types

标准错误类型

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

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

  if (error.name === 'WERR_INVALID_PARAMETER') {
    console.error('Invalid parameter:', error.message)
    console.error('Stack:', error.stack)
  } else if (error.name === 'WERR_REVIEW_ACTIONS') {
    // Handle transaction review errors
    console.error('Review required:', error.details)
  } else {
    console.error('Wallet error:', error.message)
  }
}
typescript
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)
  }
}

Review Actions Error (Transaction Failed)

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

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

    if (error.name === 'WERR_REVIEW_ACTIONS') {
      // Access detailed failure info
      const details = error as any
      console.error('Delayed results:', details.notDelayedResults)
      console.error('Send results:', details.sendWithResults)
      console.error('Failed txid:', details.txid)

      // Handle double-spend
      if (details.notDelayedResults?.some(r => r.status === 'doubleSpend')) {
        console.error('Double-spend detected!')
        console.error('Competing txs:', details.notDelayedResults[0].competingTxs)
      }
    }

    throw error
  }
}

typescript
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. Production Patterns

8. 生产模式

Pattern: Wallet State Management

模式:钱包状态管理

typescript
class WalletManager {
  private wallet: Wallet | null = null

  async initialize(rootKey: PrivateKey) {
    if (this.wallet) {
      throw new Error('Wallet already initialized')
    }

    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('Wallet not initialized')
    }
    return this.wallet
  }

  private async setupStorage() {
    // Storage setup logic
    return await setupSQLiteStorage()
  }

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

  private createKeyDeriver(rootKey: PrivateKey) {
    // Key derivation logic
    return {
      rootKey,
      identityKey: rootKey.toPublicKey().toString(),
      // ... derivation methods
    }
  }
}
typescript
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(),
      // ... 派生方法
    }
  }
}

Pattern: Transaction Retry Logic

模式:交易重试逻辑

typescript
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
      }

      // Handle signature if needed
      if (result.signableTransaction) {
        const signed = await wallet.signAction({
          reference: result.signableTransaction.reference,
          spends: {} // Provide unlocking scripts
        })
        return signed.txid!
      }

      throw new Error('Unexpected result format')

    } catch (error) {
      lastError = error as Error
      console.error(`Attempt ${attempt} failed:`, error)

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

  throw lastError || new Error('All retries failed')
}
typescript
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('所有重试均失败')
}

Pattern: Background Transaction Monitor

模式:后台交易监控

typescript
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('Transaction update:', status.txid, status.blockHeight)
  })

  monitor.on('error', (error) => {
    console.error('Monitor error:', error)
  })

  await monitor.start()

  return monitor
}

typescript
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
}

Related Skills

相关技能

For comprehensive wallet development, also reference these skills:
SkillRelationship
encrypt-decrypt-backup
Standard backup formats (.bep files, AES-256-GCM)
junglebus
Populate UTXO set from blockchain, real-time streaming
key-derivation
Type42/BRC-42 and BIP32 key derivation details
wallet-encrypt-decrypt
ECDH message encryption patterns
wallet-send-bsv
Basic transaction creation (simpler than BRC-100)
For 1Sat Ordinals / Token Support:
If your BRC-100 wallet needs to handle 1Sat Ordinals, BSV-20/BSV-21 tokens, or inscriptions, use
@1sat/wallet-toolbox
which wraps the core wallet-toolbox with ordinals capabilities.
See 1sat-skills for:
  • wallet-create-ordinals
    - Mint inscriptions
  • extract-blockchain-media
    - Extract media from transactions
  • ordinals-marketplace
    - Browse GorillaPool marketplace

如需全面的钱包开发,还可参考以下技能:
技能关联关系
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
,它在核心wallet-toolbox基础上扩展了Ordinals功能。
查看1sat-skills获取:
  • wallet-create-ordinals
    - 铸造铭文
  • extract-blockchain-media
    - 从交易中提取媒体
  • ordinals-marketplace
    - 浏览GorillaPool市场

Additional Resources

额外资源

Research: For deep dives into BRC specifications or implementation patterns, use the browser-agent to fetch current documentation from bsv.brc.dev.

研究: 如需深入了解BRC规范或实现模式,可使用浏览器代理从bsv.brc.dev获取最新文档。

Platform Guides

平台指南

Platform-specific implementation guides:
PlatformGuideReference Implementation
Browser Extensionextension-guide.mdyours-wallet
Desktop (Electron)desktop-guide.mdbsv-desktop
Web Applicationweb-guide.md-
Mobile (React Native)mobile-guide.md-
Node.js Service/CLInodejs-guide.md-
See references/key-concepts.md for BRC-100 unique concepts:
  • Actions vs Transactions
  • Baskets and Tags
  • Certificate system (BRC-52/53/64/65)
  • Background Monitoring

特定平台的实现指南:
平台指南参考实现
浏览器扩展extension-guide.mdyours-wallet
桌面端(Electron)desktop-guide.mdbsv-desktop
Web应用web-guide.md-
移动端(React Native)mobile-guide.md-
Node.js服务/CLInodejs-guide.md-
查看references/key-concepts.md了解BRC-100的独特概念:
  • 操作与交易的区别
  • 篮子与标签
  • 证书系统(BRC-52/53/64/65)
  • 后台监控

Common Patterns Summary

常见模式总结

TaskMethodKey Args
Send BSV
createAction()
outputs
,
options
Check balance
balance()
None
List UTXOs
listOutputs()
basket
,
spendable
Get history
listActions()
labels
,
limit
Get pubkey
getPublicKey()
protocolID
,
keyID
Encrypt data
encrypt()
plaintext
,
counterparty
Get certificate
acquireCertificate()
type
,
certifier

Remember: Always handle errors properly, use privileged keys securely, and follow BRC-100 security levels for sensitive operations!
任务方法关键参数
发送BSV
createAction()
outputs
,
options
查看余额
balance()
列出UTXO
listOutputs()
basket
,
spendable
获取历史记录
listActions()
labels
,
limit
获取公钥
getPublicKey()
protocolID
,
keyID
加密数据
encrypt()
plaintext
,
counterparty
获取证书
acquireCertificate()
type
,
certifier

注意:请始终正确处理错误,安全使用特权密钥,并对敏感操作遵循BRC-100安全级别!