@bsv/sdk 1.9.2 → 1.9.4

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.
Files changed (93) hide show
  1. package/dist/cjs/package.json +1 -1
  2. package/dist/cjs/src/kvstore/GlobalKVStore.js +116 -98
  3. package/dist/cjs/src/kvstore/GlobalKVStore.js.map +1 -1
  4. package/dist/cjs/src/kvstore/types.js.map +1 -1
  5. package/dist/cjs/src/overlay-tools/index.js +1 -0
  6. package/dist/cjs/src/overlay-tools/index.js.map +1 -1
  7. package/dist/cjs/src/overlay-tools/withDoubleSpendRetry.js +55 -0
  8. package/dist/cjs/src/overlay-tools/withDoubleSpendRetry.js.map +1 -0
  9. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  10. package/dist/esm/src/kvstore/GlobalKVStore.js +117 -99
  11. package/dist/esm/src/kvstore/GlobalKVStore.js.map +1 -1
  12. package/dist/esm/src/kvstore/types.js.map +1 -1
  13. package/dist/esm/src/overlay-tools/index.js +1 -0
  14. package/dist/esm/src/overlay-tools/index.js.map +1 -1
  15. package/dist/esm/src/overlay-tools/withDoubleSpendRetry.js +48 -0
  16. package/dist/esm/src/overlay-tools/withDoubleSpendRetry.js.map +1 -0
  17. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  18. package/dist/types/src/kvstore/GlobalKVStore.d.ts.map +1 -1
  19. package/dist/types/src/kvstore/types.d.ts +2 -0
  20. package/dist/types/src/kvstore/types.d.ts.map +1 -1
  21. package/dist/types/src/overlay-tools/index.d.ts +1 -0
  22. package/dist/types/src/overlay-tools/index.d.ts.map +1 -1
  23. package/dist/types/src/overlay-tools/withDoubleSpendRetry.d.ts +14 -0
  24. package/dist/types/src/overlay-tools/withDoubleSpendRetry.d.ts.map +1 -0
  25. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  26. package/dist/umd/bundle.js +2 -2
  27. package/dist/umd/bundle.js.map +1 -1
  28. package/docs/fast-docs.png +0 -0
  29. package/docs/index.md +49 -44
  30. package/docs/reference/kvstore.md +9 -0
  31. package/docs/reference/overlay-tools.md +32 -0
  32. package/docs/swagger.png +0 -0
  33. package/package.json +1 -1
  34. package/src/kvstore/GlobalKVStore.ts +134 -114
  35. package/src/kvstore/__tests/GlobalKVStore.test.ts +11 -1
  36. package/src/kvstore/types.ts +2 -0
  37. package/src/overlay-tools/index.ts +1 -0
  38. package/src/overlay-tools/withDoubleSpendRetry.ts +71 -0
  39. package/docs/MARKDOWN_VALIDATION_GUIDE.md +0 -175
  40. package/docs/concepts/beef.md +0 -92
  41. package/docs/concepts/chain-tracking.md +0 -134
  42. package/docs/concepts/decentralized-identity.md +0 -221
  43. package/docs/concepts/fees.md +0 -249
  44. package/docs/concepts/identity-certificates.md +0 -307
  45. package/docs/concepts/index.md +0 -77
  46. package/docs/concepts/key-management.md +0 -185
  47. package/docs/concepts/script-templates.md +0 -176
  48. package/docs/concepts/sdk-philosophy.md +0 -80
  49. package/docs/concepts/signatures.md +0 -194
  50. package/docs/concepts/spv-verification.md +0 -118
  51. package/docs/concepts/transaction-encoding.md +0 -167
  52. package/docs/concepts/transaction-structure.md +0 -67
  53. package/docs/concepts/trust-model.md +0 -139
  54. package/docs/concepts/verification.md +0 -250
  55. package/docs/concepts/wallet-integration.md +0 -101
  56. package/docs/guides/development-wallet-setup.md +0 -374
  57. package/docs/guides/direct-transaction-creation.md +0 -147
  58. package/docs/guides/http-client-configuration.md +0 -488
  59. package/docs/guides/index.md +0 -138
  60. package/docs/guides/large-transactions.md +0 -448
  61. package/docs/guides/multisig-transactions.md +0 -792
  62. package/docs/guides/security-best-practices.md +0 -494
  63. package/docs/guides/transaction-batching.md +0 -132
  64. package/docs/guides/transaction-signing-methods.md +0 -419
  65. package/docs/reference/arc-config.md +0 -698
  66. package/docs/reference/brc-100.md +0 -33
  67. package/docs/reference/configuration.md +0 -835
  68. package/docs/reference/debugging.md +0 -705
  69. package/docs/reference/errors.md +0 -597
  70. package/docs/reference/index.md +0 -111
  71. package/docs/reference/network-config.md +0 -914
  72. package/docs/reference/op-codes.md +0 -325
  73. package/docs/reference/transaction-signatures.md +0 -95
  74. package/docs/tutorials/advanced-transaction.md +0 -572
  75. package/docs/tutorials/aes-encryption.md +0 -949
  76. package/docs/tutorials/authfetch-tutorial.md +0 -986
  77. package/docs/tutorials/ecdh-key-exchange.md +0 -549
  78. package/docs/tutorials/elliptic-curve-fundamentals.md +0 -606
  79. package/docs/tutorials/error-handling.md +0 -1216
  80. package/docs/tutorials/first-transaction-low-level.md +0 -205
  81. package/docs/tutorials/first-transaction.md +0 -275
  82. package/docs/tutorials/hashes-and-hmacs.md +0 -788
  83. package/docs/tutorials/identity-management.md +0 -729
  84. package/docs/tutorials/index.md +0 -219
  85. package/docs/tutorials/key-management.md +0 -538
  86. package/docs/tutorials/protowallet-development.md +0 -743
  87. package/docs/tutorials/script-construction.md +0 -690
  88. package/docs/tutorials/spv-merkle-proofs.md +0 -685
  89. package/docs/tutorials/testnet-transactions-low-level.md +0 -359
  90. package/docs/tutorials/transaction-broadcasting.md +0 -538
  91. package/docs/tutorials/transaction-types.md +0 -420
  92. package/docs/tutorials/type-42.md +0 -568
  93. package/docs/tutorials/uhrp-storage.md +0 -599
@@ -1,743 +0,0 @@
1
- # Working with ProtoWallet for Development
2
-
3
- **Duration**: 45 minutes
4
- **Prerequisites**: Node.js, basic TypeScript knowledge, completed "Your First BSV Transaction" tutorial
5
- **Learning Goals**:
6
-
7
- - Understand ProtoWallet's role in development and testing
8
- - Implement cryptographic operations without blockchain interaction
9
- - Use ProtoWallet for key derivation and signing
10
- - Build development tools and testing frameworks
11
-
12
- ## Introduction
13
-
14
- ProtoWallet is a lightweight wallet implementation designed for development and testing scenarios. Unlike full wallets, ProtoWallet focuses purely on cryptographic operations without blockchain interaction, making it perfect for:
15
-
16
- - Development and testing environments
17
- - Cryptographic operation prototyping
18
- - Key derivation and signing operations
19
- - Building wallet-like functionality without full wallet complexity
20
-
21
- ## What You'll Build
22
-
23
- In this tutorial, you'll create a development toolkit using ProtoWallet that includes:
24
-
25
- - Key generation and management
26
- - Message signing and verification
27
- - Symmetric encryption/decryption
28
- - HMAC creation and verification
29
-
30
- ## Setting Up ProtoWallet
31
-
32
- ### Basic ProtoWallet Creation
33
-
34
- ```typescript
35
- import { ProtoWallet, PrivateKey } from '@bsv/sdk'
36
-
37
- async function createProtoWallet() {
38
- // Create with a random private key
39
- const randomWallet = new ProtoWallet(PrivateKey.fromRandom())
40
-
41
- // Create with a specific private key
42
- const privateKey = PrivateKey.fromRandom()
43
- const specificWallet = new ProtoWallet(privateKey)
44
-
45
- // Create with 'anyone' key (for testing)
46
- const anyoneWallet = new ProtoWallet('anyone')
47
-
48
- console.log('ProtoWallet instances created successfully')
49
- return { randomWallet, specificWallet, anyoneWallet }
50
- }
51
-
52
- createProtoWallet().catch(console.error)
53
- ```
54
-
55
- ### Getting Public Keys
56
-
57
- ```typescript
58
- import { ProtoWallet } from '@bsv/sdk'
59
-
60
- async function demonstratePublicKeys() {
61
- const wallet = new ProtoWallet(PrivateKey.fromRandom())
62
-
63
- // Get identity public key
64
- const { publicKey: identityKey } = await wallet.getPublicKey({
65
- identityKey: true
66
- })
67
- console.log('Identity Key:', identityKey)
68
-
69
- // Get derived public key for a protocol
70
- const { publicKey: protocolKey } = await wallet.getPublicKey({
71
- protocolID: [1, 'my-app'],
72
- keyID: 'user-signing-key'
73
- })
74
- console.log('Protocol Key:', protocolKey)
75
-
76
- // Get public key for counterparty communication
77
- const { publicKey: counterpartyKey } = await wallet.getPublicKey({
78
- protocolID: [1, 'messaging'],
79
- keyID: 'chat-key',
80
- counterparty: identityKey
81
- })
82
- console.log('Counterparty Key:', counterpartyKey)
83
- }
84
-
85
- demonstratePublicKeys().catch(console.error)
86
- ```
87
-
88
- ## Digital Signatures with ProtoWallet
89
-
90
- ### Creating and Verifying Signatures
91
-
92
- ```typescript
93
- import { ProtoWallet, Utils } from '@bsv/sdk'
94
-
95
- async function demonstrateSignatures() {
96
- const wallet = new ProtoWallet(PrivateKey.fromRandom())
97
-
98
- // Message to sign
99
- const message = 'Hello, BSV development!'
100
- const messageBytes = Utils.toArray(message, 'utf8')
101
-
102
- // Create signature
103
- const { signature } = await wallet.createSignature({
104
- data: messageBytes,
105
- protocolID: [1, 'document signing'],
106
- keyID: 'doc-key',
107
- counterparty: 'self'
108
- })
109
-
110
- console.log('Message:', message)
111
- console.log('Signature:', Utils.toBase64(signature))
112
-
113
- // Verify signature
114
- const { valid } = await wallet.verifySignature({
115
- data: messageBytes,
116
- signature,
117
- protocolID: [1, 'document signing'],
118
- keyID: 'doc-key',
119
- counterparty: 'self'
120
- })
121
-
122
- console.log('Signature valid:', valid)
123
-
124
- return { message, signature, valid }
125
- }
126
-
127
- demonstrateSignatures().catch(console.error)
128
- ```
129
-
130
- ### Advanced Signature Scenarios
131
-
132
- ```typescript
133
- import { ProtoWallet, Utils } from '@bsv/sdk'
134
-
135
- class DocumentSigner {
136
- private wallet: ProtoWallet
137
-
138
- constructor() {
139
- this.wallet = new ProtoWallet(PrivateKey.fromRandom())
140
- }
141
-
142
- async signDocument(content: string, documentId: string): Promise<{
143
- signature: number[]
144
- publicKey: string
145
- timestamp: number
146
- }> {
147
- const timestamp = Date.now()
148
- const documentData = {
149
- content,
150
- documentId,
151
- timestamp
152
- }
153
-
154
- const dataToSign = Utils.toArray(JSON.stringify(documentData), 'utf8')
155
-
156
- const { signature } = await this.wallet.createSignature({
157
- data: dataToSign,
158
- protocolID: [1, 'document system'],
159
- keyID: `doc-${documentId}`,
160
- counterparty: 'self'
161
- })
162
-
163
- const { publicKey } = await this.wallet.getPublicKey({
164
- protocolID: [1, 'document system'],
165
- keyID: `doc-${documentId}`
166
- })
167
-
168
- return { signature, publicKey, timestamp }
169
- }
170
-
171
- async verifyDocument(
172
- content: string,
173
- documentId: string,
174
- signature: number[],
175
- timestamp: number
176
- ): Promise<boolean> {
177
- const documentData = {
178
- content,
179
- documentId,
180
- timestamp
181
- }
182
-
183
- const dataToVerify = Utils.toArray(JSON.stringify(documentData), 'utf8')
184
-
185
- const { valid } = await this.wallet.verifySignature({
186
- data: dataToVerify,
187
- signature,
188
- protocolID: [1, 'document system'],
189
- keyID: `doc-${documentId}`,
190
- counterparty: 'self'
191
- })
192
-
193
- return valid
194
- }
195
- }
196
-
197
- async function demonstrateDocumentSigning() {
198
- const signer = new DocumentSigner()
199
-
200
- const document = {
201
- content: 'This is a confidential document requiring digital signature.',
202
- id: 'contract-2024-001'
203
- }
204
-
205
- // Sign document
206
- const signatureData = await signer.signDocument(document.content, document.id)
207
- console.log('Document signed:', {
208
- documentId: document.id,
209
- publicKey: signatureData.publicKey,
210
- timestamp: new Date(signatureData.timestamp).toISOString()
211
- })
212
-
213
- // Verify document
214
- const isValid = await signer.verifyDocument(
215
- document.content,
216
- document.id,
217
- signatureData.signature,
218
- signatureData.timestamp
219
- )
220
-
221
- console.log('Document verification:', isValid ? 'VALID' : 'INVALID')
222
-
223
- return { signatureData, isValid }
224
- }
225
-
226
- demonstrateDocumentSigning().catch(console.error)
227
- ```
228
-
229
- ## Encryption and Decryption
230
-
231
- ### Symmetric Encryption
232
-
233
- ```typescript
234
- import { ProtoWallet, Utils } from '@bsv/sdk'
235
-
236
- async function demonstrateEncryption() {
237
- const wallet = new ProtoWallet(PrivateKey.fromRandom())
238
-
239
- // Data to encrypt
240
- const secretMessage = 'This is confidential development data'
241
- const plaintext = Utils.toArray(secretMessage, 'utf8')
242
-
243
- // Encrypt data
244
- const { ciphertext } = await wallet.encrypt({
245
- plaintext,
246
- protocolID: [1, 'secure storage'],
247
- keyID: 'data-encryption-key'
248
- })
249
-
250
- console.log('Original message:', secretMessage)
251
- console.log('Encrypted (base64):', Utils.toBase64(ciphertext))
252
-
253
- // Decrypt data
254
- const { plaintext: decrypted } = await wallet.decrypt({
255
- ciphertext,
256
- protocolID: [1, 'secure storage'],
257
- keyID: 'data-encryption-key'
258
- })
259
-
260
- const decryptedMessage = Utils.toUTF8(decrypted)
261
- console.log('Decrypted message:', decryptedMessage)
262
-
263
- return { original: secretMessage, decrypted: decryptedMessage }
264
- }
265
-
266
- demonstrateEncryption().catch(console.error)
267
- ```
268
-
269
- ### Counterparty Encryption
270
-
271
- ```typescript
272
- import { ProtoWallet, Utils } from '@bsv/sdk'
273
-
274
- class SecureMessaging {
275
- private aliceWallet: ProtoWallet
276
- private bobWallet: ProtoWallet
277
- private aliceIdentity: string
278
- private bobIdentity: string
279
-
280
- constructor() {
281
- this.aliceWallet = new ProtoWallet(PrivateKey.fromRandom())
282
- this.bobWallet = new ProtoWallet(PrivateKey.fromRandom())
283
- }
284
-
285
- async initialize() {
286
- // Get identity keys for both parties
287
- const aliceKey = await this.aliceWallet.getPublicKey({ identityKey: true })
288
- const bobKey = await this.bobWallet.getPublicKey({ identityKey: true })
289
-
290
- this.aliceIdentity = aliceKey.publicKey
291
- this.bobIdentity = bobKey.publicKey
292
-
293
- console.log('Alice Identity:', this.aliceIdentity.substring(0, 20) + '...')
294
- console.log('Bob Identity:', this.bobIdentity.substring(0, 20) + '...')
295
- }
296
-
297
- async aliceSendsToBob(message: string): Promise<string> {
298
- const plaintext = Utils.toArray(message, 'utf8')
299
-
300
- const { ciphertext } = await this.aliceWallet.encrypt({
301
- plaintext,
302
- protocolID: [1, 'secure chat'],
303
- keyID: 'message-key',
304
- counterparty: this.bobIdentity
305
- })
306
-
307
- console.log('Alice encrypts message for Bob')
308
- return Utils.toBase64(ciphertext)
309
- }
310
-
311
- async bobReceivesFromAlice(ciphertext: string): Promise<string> {
312
- const ciphertextBytes = Utils.toArray(ciphertext, 'base64')
313
-
314
- const { plaintext } = await this.bobWallet.decrypt({
315
- ciphertext: ciphertextBytes,
316
- protocolID: [1, 'secure chat'],
317
- keyID: 'message-key',
318
- counterparty: this.aliceIdentity
319
- })
320
-
321
- const message = Utils.toUTF8(plaintext)
322
- console.log('Bob decrypts message from Alice')
323
- return message
324
- }
325
- }
326
-
327
- async function demonstrateSecureMessaging() {
328
- const messaging = new SecureMessaging()
329
- await messaging.initialize()
330
-
331
- const originalMessage = 'Hello Bob, this is a secure message from Alice!'
332
-
333
- // Alice encrypts and sends
334
- const encryptedMessage = await messaging.aliceSendsToBob(originalMessage)
335
- console.log('Encrypted message length:', encryptedMessage.length, 'bytes')
336
-
337
- // Bob receives and decrypts
338
- const decryptedMessage = await messaging.bobReceivesFromAlice(encryptedMessage)
339
-
340
- console.log('Original:', originalMessage)
341
- console.log('Decrypted:', decryptedMessage)
342
- console.log('Messages match:', originalMessage === decryptedMessage)
343
-
344
- return { originalMessage, decryptedMessage }
345
- }
346
-
347
- demonstrateSecureMessaging().catch(console.error)
348
- ```
349
-
350
- ## HMAC Operations
351
-
352
- ### Creating and Verifying HMACs
353
-
354
- ```typescript
355
- import { ProtoWallet, Utils } from '@bsv/sdk'
356
-
357
- async function demonstrateHMAC() {
358
- const wallet = new ProtoWallet(PrivateKey.fromRandom())
359
-
360
- // Data to authenticate
361
- const data = Utils.toArray('Important data requiring integrity verification', 'utf8')
362
-
363
- // Create HMAC
364
- const { hmac } = await wallet.createHmac({
365
- data,
366
- protocolID: [1, 'data integrity'],
367
- keyID: 'hmac-key'
368
- })
369
-
370
- console.log('Data:', Utils.toUTF8(data))
371
- console.log('HMAC:', Utils.toHex(hmac))
372
-
373
- // Verify HMAC
374
- const { valid } = await wallet.verifyHmac({
375
- data,
376
- hmac,
377
- protocolID: [1, 'data integrity'],
378
- keyID: 'hmac-key'
379
- })
380
-
381
- console.log('HMAC valid:', valid)
382
-
383
- // Test with tampered data
384
- const tamperedData = Utils.toArray('Tampered data requiring integrity verification', 'utf8')
385
- const { valid: tamperedValid } = await wallet.verifyHmac({
386
- data: tamperedData,
387
- hmac,
388
- protocolID: [1, 'data integrity'],
389
- keyID: 'hmac-key'
390
- })
391
-
392
- console.log('Tampered data HMAC valid:', tamperedValid)
393
-
394
- return { valid, tamperedValid }
395
- }
396
-
397
- demonstrateHMAC().catch(console.error)
398
- ```
399
-
400
- ## Building a Development Toolkit
401
-
402
- ### Complete ProtoWallet Utility Class
403
-
404
- ```typescript
405
- import { ProtoWallet, PrivateKey, Utils } from '@bsv/sdk'
406
-
407
- export class DevelopmentWallet {
408
- private wallet: ProtoWallet
409
- private identityKey: string | null = null
410
-
411
- constructor(privateKey?: PrivateKey) {
412
- this.wallet = new ProtoWallet(privateKey)
413
- }
414
-
415
- async getIdentity(): Promise<string> {
416
- if (!this.identityKey) {
417
- const { publicKey } = await this.wallet.getPublicKey({ identityKey: true })
418
- this.identityKey = publicKey
419
- }
420
- return this.identityKey
421
- }
422
-
423
- async signData(data: string, protocolId: string, keyId: string): Promise<{
424
- signature: string
425
- publicKey: string
426
- data: string
427
- }> {
428
- const dataBytes = Utils.toArray(data, 'utf8')
429
-
430
- const { signature } = await this.wallet.createSignature({
431
- data: dataBytes,
432
- protocolID: [1, protocolId],
433
- keyID: keyId,
434
- counterparty: 'self'
435
- })
436
-
437
- const { publicKey } = await this.wallet.getPublicKey({
438
- protocolID: [1, protocolId],
439
- keyID: keyId
440
- })
441
-
442
- return {
443
- signature: Utils.toBase64(signature),
444
- publicKey,
445
- data
446
- }
447
- }
448
-
449
- async verifyData(
450
- data: string,
451
- signature: string,
452
- protocolId: string,
453
- keyId: string
454
- ): Promise<boolean> {
455
- const dataBytes = Utils.toArray(data, 'utf8')
456
- const signatureBytes = Utils.toArray(signature, 'base64')
457
-
458
- const { valid } = await this.wallet.verifySignature({
459
- data: dataBytes,
460
- signature: signatureBytes,
461
- protocolID: [1, protocolId],
462
- keyID: keyId,
463
- counterparty: 'self'
464
- })
465
-
466
- return valid
467
- }
468
-
469
- async encryptForSelf(data: string, protocolId: string, keyId: string): Promise<string> {
470
- const plaintext = Utils.toArray(data, 'utf8')
471
-
472
- const { ciphertext } = await this.wallet.encrypt({
473
- plaintext,
474
- protocolID: [1, protocolId],
475
- keyID: keyId
476
- })
477
-
478
- return Utils.toBase64(ciphertext)
479
- }
480
-
481
- async decryptFromSelf(
482
- encryptedData: string,
483
- protocolId: string,
484
- keyId: string
485
- ): Promise<string> {
486
- const ciphertext = Utils.toArray(encryptedData, 'base64')
487
-
488
- const { plaintext } = await this.wallet.decrypt({
489
- ciphertext,
490
- protocolID: [1, protocolId],
491
- keyID: keyId
492
- })
493
-
494
- return Utils.toUTF8(plaintext)
495
- }
496
-
497
- async createDataIntegrityTag(data: string, protocolId: string, keyId: string): Promise<string> {
498
- const dataBytes = Utils.toArray(data, 'utf8')
499
-
500
- const { hmac } = await this.wallet.createHmac({
501
- data: dataBytes,
502
- protocolID: [1, protocolId],
503
- keyID: keyId
504
- })
505
-
506
- return Utils.toHex(hmac)
507
- }
508
-
509
- async verifyDataIntegrity(
510
- data: string,
511
- integrityTag: string,
512
- protocolId: string,
513
- keyId: string
514
- ): Promise<boolean> {
515
- const dataBytes = Utils.toArray(data, 'utf8')
516
- const hmac = Utils.toArray(integrityTag, 'hex')
517
-
518
- const { valid } = await this.wallet.verifyHmac({
519
- data: dataBytes,
520
- hmac,
521
- protocolID: [1, protocolId],
522
- keyID: keyId
523
- })
524
-
525
- return valid
526
- }
527
- }
528
-
529
- async function demonstrateDevelopmentToolkit() {
530
- const devWallet = new DevelopmentWallet()
531
-
532
- console.log('=== Development Wallet Toolkit Demo ===')
533
-
534
- // Get identity
535
- const identity = await devWallet.getIdentity()
536
- console.log('Wallet Identity:', identity.substring(0, 20) + '...')
537
-
538
- // Sign and verify data
539
- const testData = 'Development test data for signing'
540
- const signatureResult = await devWallet.signData(testData, 'dev-tools', 'test-key')
541
- console.log('Data signed successfully')
542
-
543
- const isValid = await devWallet.verifyData(
544
- testData,
545
- signatureResult.signature,
546
- 'dev-tools',
547
- 'test-key'
548
- )
549
- console.log('Signature verification:', isValid ? 'PASSED' : 'FAILED')
550
-
551
- // Encrypt and decrypt data
552
- const secretData = 'Confidential development information'
553
- const encrypted = await devWallet.encryptForSelf(secretData, 'dev-storage', 'secret-key')
554
- console.log('Data encrypted successfully')
555
-
556
- const decrypted = await devWallet.decryptFromSelf(encrypted, 'dev-storage', 'secret-key')
557
- console.log('Decryption result:', secretData === decrypted ? 'PASSED' : 'FAILED')
558
-
559
- // Create and verify integrity tag
560
- const importantData = 'Critical development configuration'
561
- const integrityTag = await devWallet.createDataIntegrityTag(
562
- importantData,
563
- 'dev-integrity',
564
- 'config-key'
565
- )
566
- console.log('Integrity tag created')
567
-
568
- const integrityValid = await devWallet.verifyDataIntegrity(
569
- importantData,
570
- integrityTag,
571
- 'dev-integrity',
572
- 'config-key'
573
- )
574
- console.log('Integrity verification:', integrityValid ? 'PASSED' : 'FAILED')
575
-
576
- return {
577
- identity,
578
- signatureValid: isValid,
579
- decryptionValid: secretData === decrypted,
580
- integrityValid
581
- }
582
- }
583
-
584
- demonstrateDevelopmentToolkit().catch(console.error)
585
- ```
586
-
587
- ## Testing Framework Integration
588
-
589
- ### ProtoWallet Test Utilities
590
-
591
- ```typescript
592
- import { ProtoWallet, PrivateKey, Utils } from '@bsv/sdk'
593
-
594
- export class ProtoWalletTestUtils {
595
- static createTestWallet(seed?: string): ProtoWallet {
596
- if (seed) {
597
- // Create deterministic wallet for testing
598
- const hash = Utils.toArray(seed, 'utf8')
599
- const privateKey = PrivateKey.fromString(Utils.toHex(hash).padEnd(64, '0'))
600
- return new ProtoWallet(privateKey)
601
- }
602
- return new ProtoWallet(PrivateKey.fromRandom())
603
- }
604
-
605
- static async createTestIdentities(count: number): Promise<{
606
- wallets: ProtoWallet[]
607
- identities: string[]
608
- }> {
609
- const wallets: ProtoWallet[] = []
610
- const identities: string[] = []
611
-
612
- for (let i = 0; i < count; i++) {
613
- const wallet = this.createTestWallet(`test-identity-${i}`)
614
- const { publicKey } = await wallet.getPublicKey({ identityKey: true })
615
-
616
- wallets.push(wallet)
617
- identities.push(publicKey)
618
- }
619
-
620
- return { wallets, identities }
621
- }
622
-
623
- static async testCryptographicRoundTrip(
624
- wallet: ProtoWallet,
625
- data: string,
626
- protocolId: string,
627
- keyId: string
628
- ): Promise<{
629
- signatureValid: boolean
630
- encryptionValid: boolean
631
- hmacValid: boolean
632
- }> {
633
- const dataBytes = Utils.toArray(data, 'utf8')
634
-
635
- // Test signature round trip
636
- const { signature } = await wallet.createSignature({
637
- data: dataBytes,
638
- protocolID: [1, protocolId],
639
- keyID: keyId,
640
- counterparty: 'self'
641
- })
642
-
643
- const { valid: signatureValid } = await wallet.verifySignature({
644
- data: dataBytes,
645
- signature,
646
- protocolID: [1, protocolId],
647
- keyID: keyId,
648
- counterparty: 'self'
649
- })
650
-
651
- // Test encryption round trip
652
- const { ciphertext } = await wallet.encrypt({
653
- plaintext: dataBytes,
654
- protocolID: [1, protocolId],
655
- keyID: keyId
656
- })
657
-
658
- const { plaintext } = await wallet.decrypt({
659
- ciphertext,
660
- protocolID: [1, protocolId],
661
- keyID: keyId
662
- })
663
-
664
- const encryptionValid = Utils.toUTF8(plaintext) === data
665
-
666
- // Test HMAC round trip
667
- const { hmac } = await wallet.createHmac({
668
- data: dataBytes,
669
- protocolID: [1, protocolId],
670
- keyID: keyId
671
- })
672
-
673
- const { valid: hmacValid } = await wallet.verifyHmac({
674
- data: dataBytes,
675
- hmac,
676
- protocolID: [1, protocolId],
677
- keyID: keyId
678
- })
679
-
680
- return { signatureValid, encryptionValid, hmacValid }
681
- }
682
- }
683
-
684
- async function runTestSuite() {
685
- console.log('=== ProtoWallet Test Suite ===')
686
-
687
- // Test deterministic wallet creation
688
- const wallet1 = ProtoWalletTestUtils.createTestWallet('test-seed-123')
689
- const wallet2 = ProtoWalletTestUtils.createTestWallet('test-seed-123')
690
-
691
- const identity1 = await wallet1.getPublicKey({ identityKey: true })
692
- const identity2 = await wallet2.getPublicKey({ identityKey: true })
693
-
694
- console.log('Deterministic wallet test:',
695
- identity1.publicKey === identity2.publicKey ? 'PASSED' : 'FAILED')
696
-
697
- // Test multiple identities
698
- const { wallets, identities } = await ProtoWalletTestUtils.createTestIdentities(3)
699
- console.log('Created test identities:', identities.length)
700
-
701
- // Test cryptographic operations
702
- const testData = 'Test data for cryptographic operations'
703
- const results = await ProtoWalletTestUtils.testCryptographicRoundTrip(
704
- wallets[0],
705
- testData,
706
- 'test-protocol',
707
- 'test-key'
708
- )
709
-
710
- console.log('Cryptographic tests:')
711
- console.log(' Signature:', results.signatureValid ? 'PASSED' : 'FAILED')
712
- console.log(' Encryption:', results.encryptionValid ? 'PASSED' : 'FAILED')
713
- console.log(' HMAC:', results.hmacValid ? 'PASSED' : 'FAILED')
714
-
715
- return results
716
- }
717
-
718
- runTestSuite().catch(console.error)
719
- ```
720
-
721
- ## Conclusion
722
-
723
- Congratulations! You've successfully built a comprehensive ProtoWallet development framework using the BSV TypeScript SDK. In this tutorial, you've learned how to create, test, and manage prototype wallet implementations for rapid development and testing.
724
-
725
- ### Core Concepts Mastered
726
-
727
- 1. **ProtoWallet Architecture**: Implemented lightweight wallet prototypes for development and testing
728
- 2. **Key Management**: Created deterministic key generation and management systems
729
- 3. **Cryptographic Operations**: Implemented signing, encryption, and HMAC operations
730
- 4. **Protocol Integration**: Built protocol-specific wallet functionality with proper key derivation
731
- 5. **Testing Framework**: Developed comprehensive testing utilities for wallet validation
732
-
733
- ## Next Steps
734
-
735
- - Learn about [Development Wallet Setup](../guides/development-wallet-setup.md) for production-ready wallet implementation
736
- - Explore [Key Management](./key-management.md) for advanced cryptographic key handling
737
- - Understand [Security Best Practices](../guides/security-best-practices.md) for secure wallet development
738
-
739
- ## Additional Resources
740
-
741
- - [Wallet API Reference](../reference/wallet.md)
742
- - [Key Management Concepts](../concepts/key-management.md)
743
- - [BSV Wallet Standards](https://projectbabbage.com/docs/guides/wallet/)