@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.
@@ -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";