@bsv/simple-mcp 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +76 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +152 -0
- package/dist/prompts/add-feature.d.ts +16 -0
- package/dist/prompts/add-feature.js +40 -0
- package/dist/prompts/debug.d.ts +16 -0
- package/dist/prompts/debug.js +52 -0
- package/dist/prompts/integrate.d.ts +16 -0
- package/dist/prompts/integrate.js +40 -0
- package/dist/resources/api-reference.d.ts +8 -0
- package/dist/resources/api-reference.js +614 -0
- package/dist/resources/gotchas.d.ts +1 -0
- package/dist/resources/gotchas.js +188 -0
- package/dist/resources/integration.d.ts +1 -0
- package/dist/resources/integration.js +181 -0
- package/dist/resources/patterns.d.ts +1 -0
- package/dist/resources/patterns.js +266 -0
- package/dist/tools/credential.d.ts +6 -0
- package/dist/tools/credential.js +125 -0
- package/dist/tools/did.d.ts +1 -0
- package/dist/tools/did.js +166 -0
- package/dist/tools/inscription.d.ts +1 -0
- package/dist/tools/inscription.js +71 -0
- package/dist/tools/messagebox.d.ts +1 -0
- package/dist/tools/messagebox.js +85 -0
- package/dist/tools/payment.d.ts +1 -0
- package/dist/tools/payment.js +100 -0
- package/dist/tools/scaffold.d.ts +1 -0
- package/dist/tools/scaffold.js +81 -0
- package/dist/tools/server-route.d.ts +1 -0
- package/dist/tools/server-route.js +147 -0
- package/dist/tools/token.d.ts +1 -0
- package/dist/tools/token.js +92 -0
- package/dist/tools/wallet.d.ts +1 -0
- package/dist/tools/wallet.js +127 -0
- package/package.json +46 -0
|
@@ -0,0 +1,614 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// API Reference resources for @bsv/simple
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.overlayApiReference = exports.credentialsApiReference = exports.didApiReference = exports.certificationApiReference = exports.messageboxApiReference = exports.inscriptionsApiReference = exports.tokensApiReference = exports.walletApiReference = void 0;
|
|
5
|
+
exports.walletApiReference = `# @bsv/simple — Wallet API Reference
|
|
6
|
+
|
|
7
|
+
## Initialization
|
|
8
|
+
|
|
9
|
+
### Browser
|
|
10
|
+
\`\`\`typescript
|
|
11
|
+
import { createWallet } from '@bsv/simple/browser'
|
|
12
|
+
const wallet = await createWallet()
|
|
13
|
+
// Optional defaults:
|
|
14
|
+
const wallet = await createWallet({ network: 'main' })
|
|
15
|
+
\`\`\`
|
|
16
|
+
|
|
17
|
+
### Server (Node.js)
|
|
18
|
+
\`\`\`typescript
|
|
19
|
+
const { ServerWallet } = await import('@bsv/simple/server')
|
|
20
|
+
const wallet = await ServerWallet.create({
|
|
21
|
+
privateKey: 'hex_private_key',
|
|
22
|
+
network: 'main',
|
|
23
|
+
storageUrl: 'https://storage.babbage.systems'
|
|
24
|
+
})
|
|
25
|
+
\`\`\`
|
|
26
|
+
|
|
27
|
+
## WalletCore Methods (shared by Browser + Server)
|
|
28
|
+
|
|
29
|
+
### Wallet Info
|
|
30
|
+
- \`getIdentityKey(): string\` — Compressed public key hex (66 chars)
|
|
31
|
+
- \`getAddress(): string\` — P2PKH address from identity key
|
|
32
|
+
- \`getStatus(): WalletStatus\` — { isConnected, identityKey, network }
|
|
33
|
+
- \`getWalletInfo(): WalletInfo\` — { identityKey, address, network, isConnected }
|
|
34
|
+
- \`getClient(): WalletInterface\` — Underlying SDK wallet client
|
|
35
|
+
|
|
36
|
+
### Key Derivation
|
|
37
|
+
- \`derivePublicKey(protocolID: [SecurityLevel, string], keyID: string, counterparty?: string, forSelf?: boolean): Promise<string>\` — Derive public key for any protocol
|
|
38
|
+
- \`derivePaymentKey(counterparty: string, invoiceNumber?: string): Promise<string>\` — Derive BRC-29 payment key (protocol [2, '3241645161d8'])
|
|
39
|
+
|
|
40
|
+
### Payments
|
|
41
|
+
- \`pay(options: PaymentOptions): Promise<TransactionResult>\` — Payment via MessageBox P2P (PeerPayClient)
|
|
42
|
+
- \`send(options: SendOptions): Promise<SendResult>\` — Multi-output: combine P2PKH + OP_RETURN + PushDrop in one tx
|
|
43
|
+
- \`fundServerWallet(request: PaymentRequest, basket?: string): Promise<TransactionResult>\` — Fund a ServerWallet using BRC-29 derivation
|
|
44
|
+
|
|
45
|
+
### PaymentOptions
|
|
46
|
+
\`\`\`typescript
|
|
47
|
+
interface PaymentOptions {
|
|
48
|
+
to: string // recipient identity key
|
|
49
|
+
satoshis: number // amount
|
|
50
|
+
memo?: string // optional memo
|
|
51
|
+
description?: string // tx description
|
|
52
|
+
}
|
|
53
|
+
\`\`\`
|
|
54
|
+
|
|
55
|
+
### SendOptions (multi-output)
|
|
56
|
+
\`\`\`typescript
|
|
57
|
+
interface SendOptions {
|
|
58
|
+
outputs: SendOutputSpec[]
|
|
59
|
+
description?: string
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
interface SendOutputSpec {
|
|
63
|
+
to?: string // recipient key
|
|
64
|
+
satoshis?: number // amount
|
|
65
|
+
data?: Array<string | object | number[]> // data fields
|
|
66
|
+
description?: string
|
|
67
|
+
basket?: string
|
|
68
|
+
protocolID?: [number, string] // for PushDrop
|
|
69
|
+
keyID?: string // for PushDrop
|
|
70
|
+
}
|
|
71
|
+
// Rules: to only → P2PKH | data only → OP_RETURN | to + data → PushDrop
|
|
72
|
+
\`\`\`
|
|
73
|
+
|
|
74
|
+
## ServerWallet-specific Methods
|
|
75
|
+
- \`createPaymentRequest(options: { satoshis: number, memo?: string }): PaymentRequest\` — Generate BRC-29 payment request
|
|
76
|
+
- \`receivePayment(payment: IncomingPayment): Promise<void>\` — Internalize payment using wallet payment protocol
|
|
77
|
+
|
|
78
|
+
## Result Types
|
|
79
|
+
\`\`\`typescript
|
|
80
|
+
interface TransactionResult { txid: string; tx: any; outputs?: OutputInfo[] }
|
|
81
|
+
interface SendResult extends TransactionResult { outputDetails: SendOutputDetail[] }
|
|
82
|
+
interface SendOutputDetail { index: number; type: 'p2pkh' | 'op_return' | 'pushdrop'; satoshis: number; description: string }
|
|
83
|
+
\`\`\`
|
|
84
|
+
`;
|
|
85
|
+
exports.tokensApiReference = `# @bsv/simple — Tokens API Reference
|
|
86
|
+
|
|
87
|
+
## Methods (mixed into wallet via createTokenMethods)
|
|
88
|
+
|
|
89
|
+
### createToken(options: TokenOptions): Promise<TokenResult>
|
|
90
|
+
Create an encrypted PushDrop token.
|
|
91
|
+
\`\`\`typescript
|
|
92
|
+
interface TokenOptions {
|
|
93
|
+
to?: string // recipient key (default: self)
|
|
94
|
+
data: any // JSON-serializable data (encrypted)
|
|
95
|
+
basket?: string // default: 'tokens'
|
|
96
|
+
protocolID?: [number, string] // default: [0, 'token']
|
|
97
|
+
keyID?: string // default: '1'
|
|
98
|
+
satoshis?: number // default: 1
|
|
99
|
+
}
|
|
100
|
+
interface TokenResult extends TransactionResult {
|
|
101
|
+
basket: string
|
|
102
|
+
encrypted: boolean
|
|
103
|
+
}
|
|
104
|
+
\`\`\`
|
|
105
|
+
Example:
|
|
106
|
+
\`\`\`typescript
|
|
107
|
+
const result = await wallet.createToken({
|
|
108
|
+
data: { type: 'loyalty', points: 100 },
|
|
109
|
+
basket: 'my-tokens'
|
|
110
|
+
})
|
|
111
|
+
\`\`\`
|
|
112
|
+
|
|
113
|
+
### listTokenDetails(basket?: string): Promise<TokenDetail[]>
|
|
114
|
+
List and decrypt all tokens in a basket.
|
|
115
|
+
\`\`\`typescript
|
|
116
|
+
interface TokenDetail {
|
|
117
|
+
outpoint: string // txid.vout
|
|
118
|
+
satoshis: number
|
|
119
|
+
data: any // decrypted payload
|
|
120
|
+
protocolID: any
|
|
121
|
+
keyID: string
|
|
122
|
+
counterparty: string
|
|
123
|
+
}
|
|
124
|
+
\`\`\`
|
|
125
|
+
|
|
126
|
+
### sendToken(options: SendTokenOptions): Promise<TransactionResult>
|
|
127
|
+
Transfer a token to another key (on-chain, two-step sign flow).
|
|
128
|
+
\`\`\`typescript
|
|
129
|
+
interface SendTokenOptions { basket: string; outpoint: string; to: string }
|
|
130
|
+
\`\`\`
|
|
131
|
+
|
|
132
|
+
### redeemToken(options: RedeemTokenOptions): Promise<TransactionResult>
|
|
133
|
+
Spend/destroy a token (reclaims satoshis).
|
|
134
|
+
\`\`\`typescript
|
|
135
|
+
interface RedeemTokenOptions { basket: string; outpoint: string }
|
|
136
|
+
\`\`\`
|
|
137
|
+
|
|
138
|
+
### sendTokenViaMessageBox(options: SendTokenOptions): Promise<TransactionResult>
|
|
139
|
+
Transfer a token via MessageBox P2P messaging (off-chain delivery).
|
|
140
|
+
|
|
141
|
+
### listIncomingTokens(): Promise<any[]>
|
|
142
|
+
List tokens waiting in the \`simple_token_inbox\` MessageBox.
|
|
143
|
+
|
|
144
|
+
### acceptIncomingToken(token: any, basket?: string): Promise<any>
|
|
145
|
+
Accept incoming token into a basket via \`basket insertion\` protocol.
|
|
146
|
+
`;
|
|
147
|
+
exports.inscriptionsApiReference = `# @bsv/simple — Inscriptions API Reference
|
|
148
|
+
|
|
149
|
+
All inscriptions create OP_RETURN outputs (0 satoshis).
|
|
150
|
+
|
|
151
|
+
## Methods
|
|
152
|
+
|
|
153
|
+
### inscribeText(text: string, opts?): Promise<InscriptionResult>
|
|
154
|
+
Create an OP_RETURN text inscription.
|
|
155
|
+
- Default basket: \`'text'\`
|
|
156
|
+
|
|
157
|
+
### inscribeJSON(data: object, opts?): Promise<InscriptionResult>
|
|
158
|
+
Create an OP_RETURN JSON inscription.
|
|
159
|
+
- Default basket: \`'json'\`
|
|
160
|
+
|
|
161
|
+
### inscribeFileHash(hash: string, opts?): Promise<InscriptionResult>
|
|
162
|
+
Create an OP_RETURN SHA-256 file hash inscription.
|
|
163
|
+
- Default basket: \`'hash-document'\`
|
|
164
|
+
- Validates: must be 64-char hex string
|
|
165
|
+
|
|
166
|
+
### inscribeImageHash(hash: string, opts?): Promise<InscriptionResult>
|
|
167
|
+
Create an OP_RETURN SHA-256 image hash inscription.
|
|
168
|
+
- Default basket: \`'hash-image'\`
|
|
169
|
+
- Validates: must be 64-char hex string
|
|
170
|
+
|
|
171
|
+
## Shared Options
|
|
172
|
+
\`\`\`typescript
|
|
173
|
+
opts?: { basket?: string; description?: string }
|
|
174
|
+
\`\`\`
|
|
175
|
+
|
|
176
|
+
## Result Type
|
|
177
|
+
\`\`\`typescript
|
|
178
|
+
interface InscriptionResult extends TransactionResult {
|
|
179
|
+
type: 'text' | 'json' | 'file-hash' | 'image-hash'
|
|
180
|
+
dataSize: number
|
|
181
|
+
basket: string
|
|
182
|
+
}
|
|
183
|
+
\`\`\`
|
|
184
|
+
|
|
185
|
+
## Example
|
|
186
|
+
\`\`\`typescript
|
|
187
|
+
const text = await wallet.inscribeText('Hello blockchain!')
|
|
188
|
+
const json = await wallet.inscribeJSON({ title: 'Doc', created: Date.now() })
|
|
189
|
+
const hash = await wallet.inscribeFileHash('a'.repeat(64))
|
|
190
|
+
\`\`\`
|
|
191
|
+
`;
|
|
192
|
+
exports.messageboxApiReference = `# @bsv/simple — MessageBox API Reference
|
|
193
|
+
|
|
194
|
+
## Identity & Certification
|
|
195
|
+
|
|
196
|
+
### certifyForMessageBox(handle: string, registryUrl?: string, host?: string): Promise<{ txid, handle }>
|
|
197
|
+
Register a handle on the identity registry and anoint the MessageBox host.
|
|
198
|
+
|
|
199
|
+
### getMessageBoxHandle(registryUrl?: string): Promise<string | null>
|
|
200
|
+
Check if wallet has a registered handle. Returns null if none found.
|
|
201
|
+
|
|
202
|
+
### revokeMessageBoxCertification(registryUrl?: string): Promise<void>
|
|
203
|
+
Remove all registered handles for this identity key.
|
|
204
|
+
|
|
205
|
+
## Payments
|
|
206
|
+
|
|
207
|
+
### sendMessageBoxPayment(to: string, satoshis: number): Promise<any>
|
|
208
|
+
Send payment via MessageBox using \`createPaymentToken()\` + \`sendMessage()\`.
|
|
209
|
+
Returns: \`{ txid, amount, recipient }\`
|
|
210
|
+
|
|
211
|
+
### listIncomingPayments(): Promise<any[]>
|
|
212
|
+
List payments in the \`payment_inbox\` MessageBox.
|
|
213
|
+
|
|
214
|
+
### acceptIncomingPayment(payment: any, basket?: string): Promise<any>
|
|
215
|
+
Accept a payment. If \`basket\` is provided, uses \`basket insertion\` protocol (recommended). Otherwise uses \`PeerPayClient.acceptPayment()\`.
|
|
216
|
+
|
|
217
|
+
**IMPORTANT:** When not using a basket, PeerPayClient.acceptPayment() swallows errors. The library checks \`typeof result === 'string'\` and throws.
|
|
218
|
+
|
|
219
|
+
## Identity Registry
|
|
220
|
+
|
|
221
|
+
### registerIdentityTag(tag: string, registryUrl?: string): Promise<{ tag }>
|
|
222
|
+
Register a tag in the identity registry.
|
|
223
|
+
|
|
224
|
+
### lookupIdentityByTag(query: string, registryUrl?: string): Promise<{ tag, identityKey }[]>
|
|
225
|
+
Search the identity registry by tag.
|
|
226
|
+
|
|
227
|
+
### listMyTags(registryUrl?: string): Promise<{ tag, createdAt }[]>
|
|
228
|
+
List all tags registered to this identity key.
|
|
229
|
+
|
|
230
|
+
### revokeIdentityTag(tag: string, registryUrl?: string): Promise<void>
|
|
231
|
+
Remove a registered tag.
|
|
232
|
+
|
|
233
|
+
## Registry API Format
|
|
234
|
+
The identity registry expects these API endpoints:
|
|
235
|
+
- \`GET ?action=lookup&query=...\` → \`{ success, results: [{ tag, identityKey }] }\`
|
|
236
|
+
- \`GET ?action=list&identityKey=...\` → \`{ success, tags: [{ tag, createdAt }] }\`
|
|
237
|
+
- \`POST ?action=register\` body: \`{ tag, identityKey }\` → \`{ success }\`
|
|
238
|
+
- \`POST ?action=revoke\` body: \`{ tag, identityKey }\` → \`{ success }\`
|
|
239
|
+
|
|
240
|
+
## Server-side Setup (3 lines)
|
|
241
|
+
\`\`\`typescript
|
|
242
|
+
// app/api/identity-registry/route.ts
|
|
243
|
+
import { createIdentityRegistryHandler } from '@bsv/simple/server'
|
|
244
|
+
const handler = createIdentityRegistryHandler()
|
|
245
|
+
export const GET = handler.GET, POST = handler.POST
|
|
246
|
+
\`\`\`
|
|
247
|
+
`;
|
|
248
|
+
exports.certificationApiReference = `# @bsv/simple — Certification API Reference
|
|
249
|
+
|
|
250
|
+
## Certifier Class (standalone)
|
|
251
|
+
|
|
252
|
+
### Certifier.create(config?): Promise<Certifier>
|
|
253
|
+
\`\`\`typescript
|
|
254
|
+
const certifier = await Certifier.create() // random key
|
|
255
|
+
const certifier = await Certifier.create({
|
|
256
|
+
privateKey: 'hex',
|
|
257
|
+
certificateType: 'base64type',
|
|
258
|
+
defaultFields: { role: 'admin' },
|
|
259
|
+
includeTimestamp: true // default: true
|
|
260
|
+
})
|
|
261
|
+
\`\`\`
|
|
262
|
+
|
|
263
|
+
### certifier.getInfo(): { publicKey, certificateType }
|
|
264
|
+
|
|
265
|
+
### certifier.certify(wallet: WalletCore, additionalFields?): Promise<CertificateData>
|
|
266
|
+
Issues a certificate AND acquires it into the wallet in one call.
|
|
267
|
+
|
|
268
|
+
## Wallet Methods
|
|
269
|
+
|
|
270
|
+
### acquireCertificateFrom(config): Promise<CertificateData>
|
|
271
|
+
\`\`\`typescript
|
|
272
|
+
await wallet.acquireCertificateFrom({
|
|
273
|
+
serverUrl: 'https://certifier.example.com',
|
|
274
|
+
replaceExisting: true // revoke old certs first (default: true)
|
|
275
|
+
})
|
|
276
|
+
\`\`\`
|
|
277
|
+
Server must expose: \`GET ?action=info\` → \`{ certifierPublicKey, certificateType }\`, \`POST ?action=certify\` → CertificateData. Use \`createCredentialIssuerHandler()\` from \`@bsv/simple/server\` to set this up automatically.
|
|
278
|
+
|
|
279
|
+
### listCertificatesFrom(config): Promise<{ totalCertificates, certificates }>
|
|
280
|
+
\`\`\`typescript
|
|
281
|
+
const result = await wallet.listCertificatesFrom({
|
|
282
|
+
certifiers: [certifierPubKey],
|
|
283
|
+
types: [certificateType],
|
|
284
|
+
limit: 100
|
|
285
|
+
})
|
|
286
|
+
\`\`\`
|
|
287
|
+
|
|
288
|
+
### relinquishCert(args): Promise<void>
|
|
289
|
+
\`\`\`typescript
|
|
290
|
+
await wallet.relinquishCert({ type, serialNumber, certifier })
|
|
291
|
+
\`\`\`
|
|
292
|
+
|
|
293
|
+
## CertificateData Type
|
|
294
|
+
\`\`\`typescript
|
|
295
|
+
interface CertificateData {
|
|
296
|
+
type: string; serialNumber: string; subject: string; certifier: string
|
|
297
|
+
revocationOutpoint: string; fields: Record<string, string>
|
|
298
|
+
signature: string; keyringForSubject: Record<string, string>
|
|
299
|
+
}
|
|
300
|
+
\`\`\`
|
|
301
|
+
`;
|
|
302
|
+
exports.didApiReference = `# @bsv/simple — DID API Reference
|
|
303
|
+
|
|
304
|
+
## Overview
|
|
305
|
+
|
|
306
|
+
\`did:bsv:\` DIDs use UTXO chain-linking on the BSV blockchain. The DID identifier
|
|
307
|
+
is the txid of the issuance transaction. The chain of output-0 spends carries
|
|
308
|
+
the DID Document and its updates.
|
|
309
|
+
|
|
310
|
+
## DID Class (standalone, no wallet needed)
|
|
311
|
+
|
|
312
|
+
### DID.buildDocument(txid, subjectPubKeyHex, controllerDID?, services?): DIDDocumentV2
|
|
313
|
+
Build a W3C DID Document with JsonWebKey2020 verification method.
|
|
314
|
+
|
|
315
|
+
### DID.fromTxid(txid: string): string
|
|
316
|
+
Create a DID string from a transaction ID: \`did:bsv:<txid>\`
|
|
317
|
+
|
|
318
|
+
### DID.parse(didString: string): DIDParseResult
|
|
319
|
+
Parse \`did:bsv:<txid>\` → \`{ method: 'bsv', identifier: '<txid>' }\`
|
|
320
|
+
Also accepts legacy 66-char pubkey identifiers.
|
|
321
|
+
|
|
322
|
+
### DID.isValid(didString: string): boolean
|
|
323
|
+
Check if a DID string is valid \`did:bsv:\` format (64-char txid or 66-char pubkey).
|
|
324
|
+
|
|
325
|
+
### DID.fromIdentityKey(identityKey: string): DIDDocument
|
|
326
|
+
**Deprecated.** Generate a legacy DID Document from a compressed public key.
|
|
327
|
+
|
|
328
|
+
### DID.getCertificateType(): string
|
|
329
|
+
Returns the base64 certificate type for DID persistence.
|
|
330
|
+
|
|
331
|
+
## Wallet Methods (V2 — UTXO Chain-Linked)
|
|
332
|
+
|
|
333
|
+
### createDID(options?: DIDCreateOptions): Promise<DIDCreateResult>
|
|
334
|
+
Create a new on-chain DID with UTXO chain linking.
|
|
335
|
+
- TX0: Issuance (chain UTXO + OP_RETURN marker)
|
|
336
|
+
- TX1: Document (spends TX0, new chain UTXO + OP_RETURN with DID Document)
|
|
337
|
+
\`\`\`typescript
|
|
338
|
+
interface DIDCreateOptions {
|
|
339
|
+
basket?: string // default: 'did_v2'
|
|
340
|
+
identityCode?: string // auto-generated if omitted
|
|
341
|
+
services?: DIDService[] // optional services in document
|
|
342
|
+
}
|
|
343
|
+
interface DIDCreateResult {
|
|
344
|
+
did: string // 'did:bsv:<txid>'
|
|
345
|
+
txid: string // issuance txid
|
|
346
|
+
identityCode: string
|
|
347
|
+
document: DIDDocumentV2
|
|
348
|
+
}
|
|
349
|
+
\`\`\`
|
|
350
|
+
|
|
351
|
+
### resolveDID(didString: string): Promise<DIDResolutionResult>
|
|
352
|
+
Resolve any \`did:bsv:\` DID to its Document.
|
|
353
|
+
|
|
354
|
+
**Resolution order:**
|
|
355
|
+
1. Local basket (own DIDs — fastest)
|
|
356
|
+
2. Server-side proxy (\`didProxyUrl\` — handles nChain + WoC fallback)
|
|
357
|
+
3. Direct resolvers (server-side only — no proxy needed)
|
|
358
|
+
|
|
359
|
+
**Important:** In browsers, set \`didProxyUrl\` for cross-wallet resolution:
|
|
360
|
+
\`\`\`typescript
|
|
361
|
+
const wallet = await createWallet({ didProxyUrl: '/api/resolve-did' })
|
|
362
|
+
\`\`\`
|
|
363
|
+
\`\`\`typescript
|
|
364
|
+
interface DIDResolutionResult {
|
|
365
|
+
didDocument: DIDDocumentV2 | null
|
|
366
|
+
didDocumentMetadata: { created?: string; updated?: string; deactivated?: boolean; versionId?: string }
|
|
367
|
+
didResolutionMetadata: { contentType?: string; error?: string; message?: string }
|
|
368
|
+
}
|
|
369
|
+
\`\`\`
|
|
370
|
+
|
|
371
|
+
### updateDID(options: DIDUpdateOptions): Promise<DIDCreateResult>
|
|
372
|
+
Update a DID document by spending the current chain UTXO.
|
|
373
|
+
\`\`\`typescript
|
|
374
|
+
interface DIDUpdateOptions {
|
|
375
|
+
did: string // DID to update
|
|
376
|
+
services?: DIDService[] // new services
|
|
377
|
+
additionalKeys?: string[] // extra verification keys (compressed pubkey hex)
|
|
378
|
+
}
|
|
379
|
+
\`\`\`
|
|
380
|
+
|
|
381
|
+
### deactivateDID(didString: string): Promise<{ txid: string }>
|
|
382
|
+
Revoke a DID. Spends the chain UTXO with payload \`"3"\` (revocation marker).
|
|
383
|
+
Chain terminates — resolvers will return \`deactivated: true\`.
|
|
384
|
+
|
|
385
|
+
### listDIDs(): Promise<DIDChainState[]>
|
|
386
|
+
List all DIDs owned by this wallet.
|
|
387
|
+
\`\`\`typescript
|
|
388
|
+
interface DIDChainState {
|
|
389
|
+
did: string; identityCode: string; issuanceTxid: string
|
|
390
|
+
currentOutpoint: string; status: 'active' | 'deactivated'
|
|
391
|
+
created: string; updated: string
|
|
392
|
+
}
|
|
393
|
+
\`\`\`
|
|
394
|
+
|
|
395
|
+
## Legacy Wallet Methods (deprecated)
|
|
396
|
+
|
|
397
|
+
### getDID(): DIDDocument
|
|
398
|
+
Get legacy identity-key-based DID Document (synchronous).
|
|
399
|
+
|
|
400
|
+
### registerDID(options?: { persist?: boolean }): Promise<DIDDocument>
|
|
401
|
+
Persist legacy DID as a BSV certificate.
|
|
402
|
+
|
|
403
|
+
## DID Document Structure (V2)
|
|
404
|
+
\`\`\`typescript
|
|
405
|
+
interface DIDDocumentV2 {
|
|
406
|
+
'@context': string // 'https://www.w3.org/ns/did/v1'
|
|
407
|
+
id: string // 'did:bsv:<txid>'
|
|
408
|
+
controller?: string
|
|
409
|
+
verificationMethod: DIDVerificationMethodV2[]
|
|
410
|
+
authentication: string[]
|
|
411
|
+
service?: DIDService[]
|
|
412
|
+
}
|
|
413
|
+
interface DIDVerificationMethodV2 {
|
|
414
|
+
id: string // 'did:bsv:<txid>#subject-key'
|
|
415
|
+
type: 'JsonWebKey2020'
|
|
416
|
+
controller: string
|
|
417
|
+
publicKeyJwk: { kty: 'EC'; crv: 'secp256k1'; x: string; y: string }
|
|
418
|
+
}
|
|
419
|
+
interface DIDService {
|
|
420
|
+
id: string; type: string; serviceEndpoint: string
|
|
421
|
+
}
|
|
422
|
+
\`\`\`
|
|
423
|
+
|
|
424
|
+
## Cross-Wallet Resolution (Proxy Setup)
|
|
425
|
+
|
|
426
|
+
Browser-side resolution of other wallets' DIDs requires a server-side proxy
|
|
427
|
+
because:
|
|
428
|
+
- nChain Universal Resolver is unreliable (returns HTTP 500)
|
|
429
|
+
- WhatsOnChain API calls from browsers are blocked by CORS and rate-limited
|
|
430
|
+
|
|
431
|
+
The proxy (\`/api/resolve-did\`) makes all external calls server-side:
|
|
432
|
+
1. Try nChain resolver (10s timeout)
|
|
433
|
+
2. On failure → WoC chain-following: fetch TX → parse OP_RETURN → follow output 0 spend → return last document
|
|
434
|
+
|
|
435
|
+
See the DID guide (\`docs/guides/did.md\`) for the complete proxy implementation.
|
|
436
|
+
|
|
437
|
+
## Example
|
|
438
|
+
\`\`\`typescript
|
|
439
|
+
import { createWallet, DID } from '@bsv/simple/browser'
|
|
440
|
+
|
|
441
|
+
const wallet = await createWallet({ didProxyUrl: '/api/resolve-did' })
|
|
442
|
+
|
|
443
|
+
// Create
|
|
444
|
+
const { did, document } = await wallet.createDID()
|
|
445
|
+
console.log(did) // 'did:bsv:d803b04a...'
|
|
446
|
+
|
|
447
|
+
// Resolve (cross-wallet, goes through proxy)
|
|
448
|
+
const result = await wallet.resolveDID('did:bsv:<other-txid>')
|
|
449
|
+
console.log(result.didDocument)
|
|
450
|
+
|
|
451
|
+
// Update
|
|
452
|
+
await wallet.updateDID({ did, services: [{ id: did + '#api', type: 'API', serviceEndpoint: 'https://...' }] })
|
|
453
|
+
|
|
454
|
+
// List
|
|
455
|
+
const dids = await wallet.listDIDs()
|
|
456
|
+
|
|
457
|
+
// Deactivate
|
|
458
|
+
await wallet.deactivateDID(did)
|
|
459
|
+
|
|
460
|
+
// Static utilities
|
|
461
|
+
DID.isValid('did:bsv:d803b04a...') // true
|
|
462
|
+
DID.parse('did:bsv:d803b04a...') // { method: 'bsv', identifier: 'd803b04a...' }
|
|
463
|
+
\`\`\`
|
|
464
|
+
`;
|
|
465
|
+
exports.credentialsApiReference = `# @bsv/simple — Credentials API Reference
|
|
466
|
+
|
|
467
|
+
## CredentialSchema
|
|
468
|
+
|
|
469
|
+
### Constructor
|
|
470
|
+
\`\`\`typescript
|
|
471
|
+
const schema = new CredentialSchema({
|
|
472
|
+
id: 'my-schema',
|
|
473
|
+
name: 'My Credential',
|
|
474
|
+
description: 'Optional',
|
|
475
|
+
fields: [
|
|
476
|
+
{ key: 'name', label: 'Full Name', type: 'text', required: true },
|
|
477
|
+
{ key: 'email', label: 'Email', type: 'email' },
|
|
478
|
+
{ key: 'role', label: 'Role', type: 'select', options: [{ value: 'admin', label: 'Admin' }] }
|
|
479
|
+
],
|
|
480
|
+
validate: (values) => values.name.length < 2 ? 'Name too short' : null,
|
|
481
|
+
computedFields: (values) => ({ verified: 'true', timestamp: Date.now().toString() })
|
|
482
|
+
})
|
|
483
|
+
\`\`\`
|
|
484
|
+
|
|
485
|
+
### Methods
|
|
486
|
+
- \`validate(values: Record<string, string>): string | null\`
|
|
487
|
+
- \`computeFields(values: Record<string, string>): Record<string, string>\`
|
|
488
|
+
- \`getInfo(): { id, name, description?, certificateTypeBase64, fieldCount }\`
|
|
489
|
+
- \`getConfig(): CredentialSchemaConfig\`
|
|
490
|
+
|
|
491
|
+
## CredentialIssuer
|
|
492
|
+
|
|
493
|
+
### CredentialIssuer.create(config): Promise<CredentialIssuer>
|
|
494
|
+
\`\`\`typescript
|
|
495
|
+
const issuer = await CredentialIssuer.create({
|
|
496
|
+
privateKey: 'hex_key',
|
|
497
|
+
schemas: [schemaConfig],
|
|
498
|
+
revocation: {
|
|
499
|
+
enabled: true,
|
|
500
|
+
wallet: walletInstance, // for creating revocation UTXOs
|
|
501
|
+
store: new MemoryRevocationStore() // or FileRevocationStore
|
|
502
|
+
}
|
|
503
|
+
})
|
|
504
|
+
\`\`\`
|
|
505
|
+
|
|
506
|
+
### Methods
|
|
507
|
+
- \`issue(subjectIdentityKey, schemaId, fields): Promise<VerifiableCredential>\`
|
|
508
|
+
- \`verify(vc: VerifiableCredential): Promise<VerificationResult>\`
|
|
509
|
+
- \`revoke(serialNumber: string): Promise<{ txid }>\`
|
|
510
|
+
- \`isRevoked(serialNumber: string): Promise<boolean>\`
|
|
511
|
+
- \`getInfo(): { publicKey, did, schemas: [{ id, name }] }\`
|
|
512
|
+
|
|
513
|
+
## Revocation Stores
|
|
514
|
+
|
|
515
|
+
### MemoryRevocationStore (browser/tests)
|
|
516
|
+
\`\`\`typescript
|
|
517
|
+
import { MemoryRevocationStore } from '@bsv/simple/browser'
|
|
518
|
+
const store = new MemoryRevocationStore()
|
|
519
|
+
\`\`\`
|
|
520
|
+
|
|
521
|
+
### FileRevocationStore (server only)
|
|
522
|
+
\`\`\`typescript
|
|
523
|
+
import { FileRevocationStore } from '@bsv/simple/server'
|
|
524
|
+
const store = new FileRevocationStore() // default: .revocation-secrets.json
|
|
525
|
+
const store = new FileRevocationStore('/custom/path.json')
|
|
526
|
+
\`\`\`
|
|
527
|
+
|
|
528
|
+
### RevocationStore Interface
|
|
529
|
+
\`\`\`typescript
|
|
530
|
+
interface RevocationStore {
|
|
531
|
+
save(serialNumber: string, record: RevocationRecord): Promise<void>
|
|
532
|
+
load(serialNumber: string): Promise<RevocationRecord | undefined>
|
|
533
|
+
delete(serialNumber: string): Promise<void>
|
|
534
|
+
has(serialNumber: string): Promise<boolean>
|
|
535
|
+
findByOutpoint(outpoint: string): Promise<boolean>
|
|
536
|
+
}
|
|
537
|
+
\`\`\`
|
|
538
|
+
|
|
539
|
+
## W3C VC/VP Utilities
|
|
540
|
+
\`\`\`typescript
|
|
541
|
+
import { toVerifiableCredential, toVerifiablePresentation } from '@bsv/simple/browser'
|
|
542
|
+
|
|
543
|
+
const vc = toVerifiableCredential(certData, issuerPublicKey, { credentialType: 'MyType' })
|
|
544
|
+
const vp = toVerifiablePresentation([vc1, vc2], holderKey)
|
|
545
|
+
\`\`\`
|
|
546
|
+
|
|
547
|
+
## Wallet Methods
|
|
548
|
+
- \`acquireCredential(config): Promise<VerifiableCredential>\` — Acquire VC from remote issuer (uses \`?action=info\` and \`?action=certify\` query params)
|
|
549
|
+
- \`listCredentials(config): Promise<VerifiableCredential[]>\` — List certs as W3C VCs
|
|
550
|
+
- \`createPresentation(credentials): VerifiablePresentation\` — Wrap VCs into a VP
|
|
551
|
+
|
|
552
|
+
## Server-Side Handler
|
|
553
|
+
|
|
554
|
+
\`\`\`typescript
|
|
555
|
+
// app/api/credential-issuer/route.ts (no [[...path]] catch-all needed!)
|
|
556
|
+
import { createCredentialIssuerHandler } from '@bsv/simple/server'
|
|
557
|
+
const handler = createCredentialIssuerHandler({
|
|
558
|
+
schemas: [{ id: 'my-cred', name: 'MyCred', fields: [{ key: 'name', label: 'Name', type: 'text', required: true }] }]
|
|
559
|
+
})
|
|
560
|
+
export const GET = handler.GET, POST = handler.POST
|
|
561
|
+
\`\`\`
|
|
562
|
+
`;
|
|
563
|
+
exports.overlayApiReference = `# @bsv/simple — Overlay API Reference
|
|
564
|
+
|
|
565
|
+
## Overlay Class (standalone)
|
|
566
|
+
|
|
567
|
+
### Overlay.create(config): Promise<Overlay>
|
|
568
|
+
\`\`\`typescript
|
|
569
|
+
const overlay = await Overlay.create({
|
|
570
|
+
topics: ['tm_my_topic'], // MUST start with 'tm_'
|
|
571
|
+
network: 'mainnet', // 'mainnet' | 'testnet' | 'local'
|
|
572
|
+
slapTrackers: ['https://...'], // optional
|
|
573
|
+
hostOverrides: { tm_topic: ['url'] }, // optional
|
|
574
|
+
additionalHosts: { tm_topic: ['url'] } // optional
|
|
575
|
+
})
|
|
576
|
+
\`\`\`
|
|
577
|
+
|
|
578
|
+
### Instance Methods
|
|
579
|
+
- \`getInfo(): OverlayInfo\` — { topics, network }
|
|
580
|
+
- \`addTopic(topic: string): void\` — Add topic (must start with 'tm_')
|
|
581
|
+
- \`removeTopic(topic: string): void\` — Remove topic
|
|
582
|
+
- \`broadcast(tx: Transaction, topics?: string[]): Promise<OverlayBroadcastResult>\`
|
|
583
|
+
- \`query(service: string, query: unknown, timeout?: number): Promise<LookupAnswer>\`
|
|
584
|
+
- \`lookupOutputs(service: string, query: unknown): Promise<OverlayOutput[]>\`
|
|
585
|
+
- \`getBroadcaster(): TopicBroadcaster\` — Raw SDK broadcaster
|
|
586
|
+
- \`getResolver(): LookupResolver\` — Raw SDK resolver
|
|
587
|
+
|
|
588
|
+
## Wallet Methods (overlay module)
|
|
589
|
+
|
|
590
|
+
### advertiseSHIP(domain, topic, basket?): Promise<TransactionResult>
|
|
591
|
+
Create a SHIP advertisement token. Topic must start with 'tm_'.
|
|
592
|
+
|
|
593
|
+
### advertiseSLAP(domain, service, basket?): Promise<TransactionResult>
|
|
594
|
+
Create a SLAP advertisement token. Service must start with 'ls_'.
|
|
595
|
+
|
|
596
|
+
### broadcastAction(overlay, actionOptions, topics?): Promise<{ txid, broadcast }>
|
|
597
|
+
Create an action and broadcast to overlay in one step.
|
|
598
|
+
|
|
599
|
+
### withRetry<T>(operation, overlay, maxRetries?): Promise<T>
|
|
600
|
+
Double-spend retry wrapper using \`withDoubleSpendRetry\`.
|
|
601
|
+
|
|
602
|
+
## Types
|
|
603
|
+
\`\`\`typescript
|
|
604
|
+
interface OverlayConfig {
|
|
605
|
+
topics: string[]
|
|
606
|
+
network?: 'mainnet' | 'testnet' | 'local'
|
|
607
|
+
slapTrackers?: string[]
|
|
608
|
+
hostOverrides?: Record<string, string[]>
|
|
609
|
+
additionalHosts?: Record<string, string[]>
|
|
610
|
+
}
|
|
611
|
+
interface OverlayBroadcastResult { success: boolean; txid?: string; code?: string; description?: string }
|
|
612
|
+
interface OverlayOutput { beef: number[]; outputIndex: number; context?: number[] }
|
|
613
|
+
\`\`\`
|
|
614
|
+
`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const gotchasReference = "# @bsv/simple \u2014 Critical Gotchas\n\n## 1. basket insertion vs wallet payment are MUTUALLY EXCLUSIVE\n\nIn `internalizeAction`, each output can use EITHER `basket insertion` OR `wallet payment`, never both.\n\n- **wallet payment** \u2014 provides derivation info for spending. Output is NOT in any app basket.\n- **basket insertion** \u2014 puts output in a named basket (visible via `listOutputs`). Derivation info must go in `customInstructions`.\n\n```typescript\n// CORRECT: basket insertion\nawait client.internalizeAction({\n tx: txBytes,\n outputs: [{\n outputIndex: 0,\n protocol: 'basket insertion',\n insertionRemittance: {\n basket: 'my-basket',\n customInstructions: JSON.stringify({ derivationPrefix, derivationSuffix }),\n tags: ['payment']\n }\n }]\n})\n\n// CORRECT: wallet payment\nawait client.internalizeAction({\n tx: txBytes,\n outputs: [{\n outputIndex: 0,\n protocol: 'wallet payment',\n paymentRemittance: {\n senderIdentityKey,\n derivationPrefix,\n derivationSuffix\n }\n }]\n})\n\n// WRONG: both on same output \u2014 will fail\n```\n\n## 2. PeerPayClient.acceptPayment() swallows errors\n\nReturns the string `'Unable to receive payment!'` instead of throwing an error.\n\n```typescript\n// WRONG: silently fails\nawait peerPay.acceptPayment(payment)\n\n// CORRECT: always check\nconst result = await peerPay.acceptPayment(payment)\nif (typeof result === 'string') throw new Error(result)\n```\n\nThe simple library handles this internally, but be aware when using `@bsv/message-box-client` directly.\n\n## 3. result.tx from createAction may be undefined\n\nAlways check before using:\n```typescript\nconst result = await client.createAction({ ... })\nif (!result.tx) {\n console.warn('No tx bytes available')\n return\n}\n// Now safe to use result.tx\n```\n\n## 4. BRC-29 Payment Derivation Protocol ID\n\nAlways use: `[2, '3241645161d8']`\n```typescript\nconst protocolID: [SecurityLevel, string] = [2, '3241645161d8']\n```\n\n## 5. FileRevocationStore is server-only\n\nIt uses Node.js `fs` module and will crash in the browser. It's isolated in `file-revocation-store.ts` to prevent Turbopack from bundling it.\n\n```typescript\n// Browser: use MemoryRevocationStore\nimport { MemoryRevocationStore } from '@bsv/simple/browser'\n\n// Server: use FileRevocationStore\nconst { FileRevocationStore } = await import('@bsv/simple/server')\n```\n\n## 6. Overlay topics must start with tm_, services with ls_\n\nThe Overlay class enforces these prefixes and throws if violated:\n```typescript\n// CORRECT\nawait Overlay.create({ topics: ['tm_payments'] })\nawait wallet.advertiseSLAP('domain.com', 'ls_payments')\n\n// WRONG \u2014 throws Error\nawait Overlay.create({ topics: ['payments'] })\nawait wallet.advertiseSLAP('domain.com', 'payments')\n```\n\n## 7. Token send/redeem uses two-step signing\n\nToken transfers require: `createAction` \u2192 get `signableTransaction` \u2192 sign with PushDrop unlock \u2192 `signAction`. Don't try to do it in a single step.\n\n## 8. pay() uses PeerPayClient.sendPayment()\n\nPayments via `wallet.pay()` are routed through MessageBox P2P using PeerPayClient, not direct on-chain P2PKH. For direct on-chain payments, use `wallet.send()` with a P2PKH output:\n\n```typescript\n// MessageBox P2P payment (via pay):\nawait wallet.pay({ to: recipientKey, satoshis: 1000 })\n\n// Direct on-chain P2PKH (via send):\nawait wallet.send({\n outputs: [{ to: recipientKey, satoshis: 1000 }],\n description: 'Direct payment'\n})\n```\n\n## 9. Server exports not available from @bsv/simple\n\nServer-only utilities (ServerWallet, handler factories, FileRevocationStore, generatePrivateKey) must be imported from `@bsv/simple/server`, not from the main `@bsv/simple` entry point.\n\n```typescript\n// WRONG\nimport { ServerWallet } from '@bsv/simple'\n\n// CORRECT\nimport { ServerWallet } from '@bsv/simple/server'\n```\n\n## 10. Dynamic imports for server code in Next.js\n\nAlways use `await import()` for server-only code in API routes:\n```typescript\n// WRONG: static import at top of API route\nimport { ServerWallet } from '@bsv/simple/server'\n\n// CORRECT: dynamic import inside handler\nconst { ServerWallet } = await import('@bsv/simple/server')\n```\n\n## 11. next.config.ts serverExternalPackages is required (updated for v2)\n\nWithout this, Turbopack bundles `@bsv/wallet-toolbox`, `knex`, and database drivers for the browser:\n```typescript\nconst nextConfig: NextConfig = {\n serverExternalPackages: [\n \"@bsv/wallet-toolbox\", \"knex\", \"better-sqlite3\", \"tedious\",\n \"mysql\", \"mysql2\", \"pg\", \"pg-query-stream\", \"oracledb\", \"dotenv\"\n ]\n}\n```\n\n## 12. Server wallet initialization \u2014 use handler factories\n\nThe `createServerWalletHandler()` factory handles lazy-init singleton + key persistence automatically. No manual caching needed:\n```typescript\n// OLD (manual caching pattern \u2014 no longer needed):\n// let serverWallet: any = null\n// let initPromise: Promise<any> | null = null\n// async function getServerWallet() { /* ... 50 lines of boilerplate ... */ }\n\n// NEW (3 lines):\nimport { createServerWalletHandler } from '@bsv/simple/server'\nconst handler = createServerWalletHandler()\nexport const GET = handler.GET, POST = handler.POST\n```\n\nSimilarly, use `createIdentityRegistryHandler()`, `createDIDResolverHandler()`, and `createCredentialIssuerHandler()` \u2014 all handle lazy init and file persistence internally.\n\n## 13. No need to import @bsv/sdk\n\nNever import `@bsv/sdk` in consumer code. Use `generatePrivateKey()` from `@bsv/simple/server`:\n```typescript\n// WRONG\n// import { PrivateKey } from '@bsv/sdk'\n// const key = PrivateKey.fromRandom().toHex()\n\n// CORRECT\nimport { generatePrivateKey } from '@bsv/simple/server'\nconst key = generatePrivateKey()\n```\n";
|