wallet-brc100
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBRC-100 Wallet Implementation Guide
BRC-100钱包实现指南
This skill provides comprehensive guidance for implementing BRC-100 conforming wallets using the package (v1.7.18+).
@bsv/wallet-toolboxGetting Started: Before implementing, review the Strategic Questionnaire to determine the right architecture for your wallet type.
本技能提供了使用包(v1.7.18+)实现符合BRC-100标准的钱包的全面指导。
@bsv/wallet-toolbox入门指南:在开始实现前,请查看战略问卷以确定适合您钱包类型的架构。
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
主要类
| Class | Purpose | Use When |
|---|---|---|
| Wallet | Full BRC-100 wallet | Building production wallet apps |
| SimpleWalletManager | Lightweight wrapper | Simple key-based authentication |
| CWIStyleWalletManager | Multi-profile wallet | Advanced UMP token flows |
| WalletSigner | Transaction signing | Custom 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/sdkbash
npm install @bsv/wallet-toolbox @bsv/sdkOptional storage backends:
可选存储后端:
npm install knex sqlite3 # SQLite
npm install knex mysql2 # MySQL
npm install idb # IndexedDB (browser)
undefinednpm install knex sqlite3 # SQLite
npm install knex mysql2 # MySQL
npm install idb # IndexedDB(浏览器端)
undefinedBasic 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:
| Skill | Relationship |
|---|---|
| Standard backup formats (.bep files, AES-256-GCM) |
| Populate UTXO set from blockchain, real-time streaming |
| Type42/BRC-42 and BIP32 key derivation details |
| ECDH message encryption patterns |
| 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 which wraps the core wallet-toolbox with ordinals capabilities.
@1sat/wallet-toolboxSee 1sat-skills for:
- - Mint inscriptions
wallet-create-ordinals - - Extract media from transactions
extract-blockchain-media - - Browse GorillaPool marketplace
ordinals-marketplace
如需全面的钱包开发,还可参考以下技能:
| 技能 | 关联关系 |
|---|---|
| 标准备份格式(.bep文件,AES-256-GCM) |
| 从区块链填充UTXO集合,实时流处理 |
| Type42/BRC-42和BIP32密钥派生细节 |
| ECDH消息加密模式 |
| 基础交易创建(比BRC-100更简单) |
1Sat Ordinals / 令牌支持:
如果您的BRC-100钱包需要处理1Sat Ordinals、BSV-20/BSV-21令牌或铭文,请使用,它在核心wallet-toolbox基础上扩展了Ordinals功能。
@1sat/wallet-toolbox查看1sat-skills获取:
- - 铸造铭文
wallet-create-ordinals - - 从交易中提取媒体
extract-blockchain-media - - 浏览GorillaPool市场
ordinals-marketplace
Additional Resources
额外资源
- BRC-100 Specification: https://bsv.brc.dev/wallet/0100
- BRC-42 (BKDS): https://bsv.brc.dev/wallet/0042
- BRC-43 (Security Levels): https://bsv.brc.dev/wallet/0043
- Wallet Toolbox Docs: https://bsv-blockchain.github.io/wallet-toolbox
- BSV SDK Docs: https://bsv-blockchain.github.io/ts-sdk
- @1sat/wallet-toolbox: BRC-100 wallet with 1Sat Ordinals support (wraps @bsv/wallet-toolbox)
- 1sat-skills: https://github.com/b-open-io/1sat-skills - Ordinals minting and management
- bsv-desktop (Reference Implementation): https://github.com/bsv-blockchain/bsv-desktop
- Real-world Electron wallet with BRC-100 support
- IPC architecture for storage isolation
- Background monitoring patterns
- HTTPS server on port 2121 for BRC-100 interface
Research: For deep dives into BRC specifications or implementation patterns, use the browser-agent to fetch current documentation from bsv.brc.dev.
- BRC-100规范: https://bsv.brc.dev/wallet/0100
- BRC-42 (BKDS): https://bsv.brc.dev/wallet/0042
- BRC-43 (安全级别): https://bsv.brc.dev/wallet/0043
- Wallet Toolbox文档: https://bsv-blockchain.github.io/wallet-toolbox
- BSV SDK文档: https://bsv-blockchain.github.io/ts-sdk
- @1sat/wallet-toolbox: 支持1Sat Ordinals的BRC-100钱包(基于@bsv/wallet-toolbox封装)
- 1sat-skills: https://github.com/b-open-io/1sat-skills - Ordinals铸造与管理
- bsv-desktop(参考实现): https://github.com/bsv-blockchain/bsv-desktop
- 支持BRC-100的真实Electron钱包
- 存储隔离的IPC架构
- 后台监控模式
- 端口2121上的HTTPS服务器用于BRC-100接口
研究: 如需深入了解BRC规范或实现模式,可使用浏览器代理从bsv.brc.dev获取最新文档。
Platform Guides
平台指南
Platform-specific implementation guides:
| Platform | Guide | Reference Implementation |
|---|---|---|
| Browser Extension | extension-guide.md | yours-wallet |
| Desktop (Electron) | desktop-guide.md | bsv-desktop |
| Web Application | web-guide.md | - |
| Mobile (React Native) | mobile-guide.md | - |
| Node.js Service/CLI | nodejs-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.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)
- 后台监控
Common Patterns Summary
常见模式总结
| Task | Method | Key Args |
|---|---|---|
| Send BSV | | |
| Check balance | | None |
| List UTXOs | | |
| Get history | | |
| Get pubkey | | |
| Encrypt data | | |
| Get certificate | | |
Remember: Always handle errors properly, use privileged keys securely, and follow BRC-100 security levels for sensitive operations!
| 任务 | 方法 | 关键参数 |
|---|---|---|
| 发送BSV | | |
| 查看余额 | | 无 |
| 列出UTXO | | |
| 获取历史记录 | | |
| 获取公钥 | | |
| 加密数据 | | |
| 获取证书 | | |
注意:请始终正确处理错误,安全使用特权密钥,并对敏感操作遵循BRC-100安全级别!