@bsv/sdk 1.1.33 → 1.2.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.
Files changed (214) hide show
  1. package/dist/cjs/mod.js +4 -0
  2. package/dist/cjs/mod.js.map +1 -1
  3. package/dist/cjs/package.json +4 -3
  4. package/dist/cjs/src/auth/Certificate.js +163 -0
  5. package/dist/cjs/src/auth/Certificate.js.map +1 -0
  6. package/dist/cjs/src/auth/index.js +9 -0
  7. package/dist/cjs/src/auth/index.js.map +1 -0
  8. package/dist/cjs/src/compat/BSM.js +17 -7
  9. package/dist/cjs/src/compat/BSM.js.map +1 -1
  10. package/dist/cjs/src/compat/ECIES.js +17 -7
  11. package/dist/cjs/src/compat/ECIES.js.map +1 -1
  12. package/dist/cjs/src/compat/HD.js +17 -7
  13. package/dist/cjs/src/compat/HD.js.map +1 -1
  14. package/dist/cjs/src/compat/Mnemonic.js +17 -7
  15. package/dist/cjs/src/compat/Mnemonic.js.map +1 -1
  16. package/dist/cjs/src/compat/index.js +17 -7
  17. package/dist/cjs/src/compat/index.js.map +1 -1
  18. package/dist/cjs/src/messages/index.js +17 -7
  19. package/dist/cjs/src/messages/index.js.map +1 -1
  20. package/dist/cjs/src/overlay-tools/LookupResolver.js +170 -0
  21. package/dist/cjs/src/overlay-tools/LookupResolver.js.map +1 -0
  22. package/dist/cjs/src/overlay-tools/OverlayAdminTokenTemplate.js +69 -0
  23. package/dist/cjs/src/overlay-tools/OverlayAdminTokenTemplate.js.map +1 -0
  24. package/dist/cjs/src/overlay-tools/SHIPBroadcaster.js +336 -0
  25. package/dist/cjs/src/overlay-tools/SHIPBroadcaster.js.map +1 -0
  26. package/dist/cjs/src/overlay-tools/index.js +29 -0
  27. package/dist/cjs/src/overlay-tools/index.js.map +1 -0
  28. package/dist/cjs/src/primitives/PrivateKey.js +17 -7
  29. package/dist/cjs/src/primitives/PrivateKey.js.map +1 -1
  30. package/dist/cjs/src/primitives/TransactionSignature.js +17 -7
  31. package/dist/cjs/src/primitives/TransactionSignature.js.map +1 -1
  32. package/dist/cjs/src/primitives/index.js +17 -7
  33. package/dist/cjs/src/primitives/index.js.map +1 -1
  34. package/dist/cjs/src/script/Spend.js +17 -7
  35. package/dist/cjs/src/script/Spend.js.map +1 -1
  36. package/dist/cjs/src/script/templates/PushDrop.js +218 -0
  37. package/dist/cjs/src/script/templates/PushDrop.js.map +1 -0
  38. package/dist/cjs/src/script/templates/index.js +3 -1
  39. package/dist/cjs/src/script/templates/index.js.map +1 -1
  40. package/dist/cjs/src/transaction/http/DefaultHttpClient.js +1 -1
  41. package/dist/cjs/src/transaction/http/DefaultHttpClient.js.map +1 -1
  42. package/dist/cjs/src/wallet/CachedKeyDeriver.js +177 -0
  43. package/dist/cjs/src/wallet/CachedKeyDeriver.js.map +1 -0
  44. package/dist/cjs/src/wallet/KeyDeriver.js +174 -0
  45. package/dist/cjs/src/wallet/KeyDeriver.js.map +1 -0
  46. package/dist/cjs/src/wallet/ProtoWallet.js +245 -0
  47. package/dist/cjs/src/wallet/ProtoWallet.js.map +1 -0
  48. package/dist/cjs/src/wallet/Wallet.interfaces.js +3 -0
  49. package/dist/cjs/src/wallet/Wallet.interfaces.js.map +1 -0
  50. package/dist/cjs/src/wallet/WalletClient.js +181 -0
  51. package/dist/cjs/src/wallet/WalletClient.js.map +1 -0
  52. package/dist/cjs/src/wallet/WalletError.js +28 -0
  53. package/dist/cjs/src/wallet/WalletError.js.map +1 -0
  54. package/dist/cjs/src/wallet/index.js +34 -0
  55. package/dist/cjs/src/wallet/index.js.map +1 -0
  56. package/dist/cjs/src/wallet/substrates/HTTPWalletWire.js +45 -0
  57. package/dist/cjs/src/wallet/substrates/HTTPWalletWire.js.map +1 -0
  58. package/dist/cjs/src/wallet/substrates/WalletWire.js +3 -0
  59. package/dist/cjs/src/wallet/substrates/WalletWire.js.map +1 -0
  60. package/dist/cjs/src/wallet/substrates/WalletWireCalls.js +36 -0
  61. package/dist/cjs/src/wallet/substrates/WalletWireCalls.js.map +1 -0
  62. package/dist/cjs/src/wallet/substrates/WalletWireProcessor.js +1821 -0
  63. package/dist/cjs/src/wallet/substrates/WalletWireProcessor.js.map +1 -0
  64. package/dist/cjs/src/wallet/substrates/WalletWireTransceiver.js +1305 -0
  65. package/dist/cjs/src/wallet/substrates/WalletWireTransceiver.js.map +1 -0
  66. package/dist/cjs/src/wallet/substrates/XDM.js +130 -0
  67. package/dist/cjs/src/wallet/substrates/XDM.js.map +1 -0
  68. package/dist/cjs/src/wallet/substrates/index.js +33 -0
  69. package/dist/cjs/src/wallet/substrates/index.js.map +1 -0
  70. package/dist/cjs/src/wallet/substrates/window.CWI.js +102 -0
  71. package/dist/cjs/src/wallet/substrates/window.CWI.js.map +1 -0
  72. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  73. package/dist/esm/mod.js +4 -0
  74. package/dist/esm/mod.js.map +1 -1
  75. package/dist/esm/src/auth/Certificate.js +185 -0
  76. package/dist/esm/src/auth/Certificate.js.map +1 -0
  77. package/dist/esm/src/auth/index.js +2 -0
  78. package/dist/esm/src/auth/index.js.map +1 -0
  79. package/dist/esm/src/overlay-tools/LookupResolver.js +167 -0
  80. package/dist/esm/src/overlay-tools/LookupResolver.js.map +1 -0
  81. package/dist/esm/src/overlay-tools/OverlayAdminTokenTemplate.js +64 -0
  82. package/dist/esm/src/overlay-tools/OverlayAdminTokenTemplate.js.map +1 -0
  83. package/dist/esm/src/overlay-tools/SHIPBroadcaster.js +335 -0
  84. package/dist/esm/src/overlay-tools/SHIPBroadcaster.js.map +1 -0
  85. package/dist/esm/src/overlay-tools/index.js +6 -0
  86. package/dist/esm/src/overlay-tools/index.js.map +1 -0
  87. package/dist/esm/src/script/templates/PushDrop.js +215 -0
  88. package/dist/esm/src/script/templates/PushDrop.js.map +1 -0
  89. package/dist/esm/src/script/templates/index.js +1 -0
  90. package/dist/esm/src/script/templates/index.js.map +1 -1
  91. package/dist/esm/src/transaction/http/DefaultHttpClient.js +1 -1
  92. package/dist/esm/src/transaction/http/DefaultHttpClient.js.map +1 -1
  93. package/dist/esm/src/wallet/CachedKeyDeriver.js +174 -0
  94. package/dist/esm/src/wallet/CachedKeyDeriver.js.map +1 -0
  95. package/dist/esm/src/wallet/KeyDeriver.js +172 -0
  96. package/dist/esm/src/wallet/KeyDeriver.js.map +1 -0
  97. package/dist/esm/src/wallet/ProtoWallet.js +207 -0
  98. package/dist/esm/src/wallet/ProtoWallet.js.map +1 -0
  99. package/dist/esm/src/wallet/Wallet.interfaces.js +2 -0
  100. package/dist/esm/src/wallet/Wallet.interfaces.js.map +1 -0
  101. package/dist/esm/src/wallet/WalletClient.js +177 -0
  102. package/dist/esm/src/wallet/WalletClient.js.map +1 -0
  103. package/dist/esm/src/wallet/WalletError.js +25 -0
  104. package/dist/esm/src/wallet/WalletError.js.map +1 -0
  105. package/dist/esm/src/wallet/index.js +9 -0
  106. package/dist/esm/src/wallet/index.js.map +1 -0
  107. package/dist/esm/src/wallet/substrates/HTTPWalletWire.js +42 -0
  108. package/dist/esm/src/wallet/substrates/HTTPWalletWire.js.map +1 -0
  109. package/dist/esm/src/wallet/substrates/WalletWire.js +2 -0
  110. package/dist/esm/src/wallet/substrates/WalletWire.js.map +1 -0
  111. package/dist/esm/src/wallet/substrates/WalletWireCalls.js +34 -0
  112. package/dist/esm/src/wallet/substrates/WalletWireCalls.js.map +1 -0
  113. package/dist/esm/src/wallet/substrates/WalletWireProcessor.js +1816 -0
  114. package/dist/esm/src/wallet/substrates/WalletWireProcessor.js.map +1 -0
  115. package/dist/esm/src/wallet/substrates/WalletWireTransceiver.js +1300 -0
  116. package/dist/esm/src/wallet/substrates/WalletWireTransceiver.js.map +1 -0
  117. package/dist/esm/src/wallet/substrates/XDM.js +128 -0
  118. package/dist/esm/src/wallet/substrates/XDM.js.map +1 -0
  119. package/dist/esm/src/wallet/substrates/index.js +8 -0
  120. package/dist/esm/src/wallet/substrates/index.js.map +1 -0
  121. package/dist/esm/src/wallet/substrates/window.CWI.js +100 -0
  122. package/dist/esm/src/wallet/substrates/window.CWI.js.map +1 -0
  123. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  124. package/dist/types/mod.d.ts +4 -0
  125. package/dist/types/mod.d.ts.map +1 -1
  126. package/dist/types/src/auth/Certificate.d.ts +76 -0
  127. package/dist/types/src/auth/Certificate.d.ts.map +1 -0
  128. package/dist/types/src/auth/index.d.ts +2 -0
  129. package/dist/types/src/auth/index.d.ts.map +1 -0
  130. package/dist/types/src/overlay-tools/LookupResolver.d.ts +71 -0
  131. package/dist/types/src/overlay-tools/LookupResolver.d.ts.map +1 -0
  132. package/dist/types/src/overlay-tools/OverlayAdminTokenTemplate.d.ts +44 -0
  133. package/dist/types/src/overlay-tools/OverlayAdminTokenTemplate.d.ts.map +1 -0
  134. package/dist/types/src/overlay-tools/SHIPBroadcaster.d.ts +90 -0
  135. package/dist/types/src/overlay-tools/SHIPBroadcaster.d.ts.map +1 -0
  136. package/dist/types/src/overlay-tools/index.d.ts +6 -0
  137. package/dist/types/src/overlay-tools/index.d.ts.map +1 -0
  138. package/dist/types/src/script/templates/PushDrop.d.ts +53 -0
  139. package/dist/types/src/script/templates/PushDrop.d.ts.map +1 -0
  140. package/dist/types/src/script/templates/index.d.ts +1 -0
  141. package/dist/types/src/script/templates/index.d.ts.map +1 -1
  142. package/dist/types/src/wallet/CachedKeyDeriver.d.ts +92 -0
  143. package/dist/types/src/wallet/CachedKeyDeriver.d.ts.map +1 -0
  144. package/dist/types/src/wallet/KeyDeriver.d.ts +72 -0
  145. package/dist/types/src/wallet/KeyDeriver.d.ts.map +1 -0
  146. package/dist/types/src/wallet/ProtoWallet.d.ts +415 -0
  147. package/dist/types/src/wallet/ProtoWallet.d.ts.map +1 -0
  148. package/dist/types/src/wallet/Wallet.interfaces.d.ts +996 -0
  149. package/dist/types/src/wallet/Wallet.interfaces.d.ts.map +1 -0
  150. package/dist/types/src/wallet/WalletClient.d.ts +182 -0
  151. package/dist/types/src/wallet/WalletClient.d.ts.map +1 -0
  152. package/dist/types/src/wallet/WalletError.d.ts +14 -0
  153. package/dist/types/src/wallet/WalletError.d.ts.map +1 -0
  154. package/dist/types/src/wallet/index.d.ts +9 -0
  155. package/dist/types/src/wallet/index.d.ts.map +1 -0
  156. package/dist/types/src/wallet/substrates/HTTPWalletWire.d.ts +9 -0
  157. package/dist/types/src/wallet/substrates/HTTPWalletWire.d.ts.map +1 -0
  158. package/dist/types/src/wallet/substrates/WalletWire.d.ts +7 -0
  159. package/dist/types/src/wallet/substrates/WalletWire.d.ts.map +1 -0
  160. package/dist/types/src/wallet/substrates/WalletWireCalls.d.ts +33 -0
  161. package/dist/types/src/wallet/substrates/WalletWireCalls.d.ts.map +1 -0
  162. package/dist/types/src/wallet/substrates/WalletWireProcessor.d.ts +18 -0
  163. package/dist/types/src/wallet/substrates/WalletWireProcessor.d.ts.map +1 -0
  164. package/dist/types/src/wallet/substrates/WalletWireTransceiver.d.ts +196 -0
  165. package/dist/types/src/wallet/substrates/WalletWireTransceiver.d.ts.map +1 -0
  166. package/dist/types/src/wallet/substrates/XDM.d.ts +412 -0
  167. package/dist/types/src/wallet/substrates/XDM.d.ts.map +1 -0
  168. package/dist/types/src/wallet/substrates/index.d.ts +8 -0
  169. package/dist/types/src/wallet/substrates/index.d.ts.map +1 -0
  170. package/dist/types/src/wallet/substrates/window.CWI.d.ts +410 -0
  171. package/dist/types/src/wallet/substrates/window.CWI.d.ts.map +1 -0
  172. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  173. package/dist/umd/bundle.js +1 -1
  174. package/docs/overlay-tools.md +537 -0
  175. package/docs/script.md +135 -0
  176. package/docs/totp.md +119 -0
  177. package/docs/wallet-substrates.md +10 -0
  178. package/docs/wallet.md +3718 -0
  179. package/mod.ts +5 -1
  180. package/package.json +44 -3
  181. package/src/auth/Certificate.ts +233 -0
  182. package/src/auth/__tests/Certificate.test.ts +282 -0
  183. package/src/auth/index.ts +1 -0
  184. package/src/overlay-tools/LookupResolver.ts +228 -0
  185. package/src/overlay-tools/OverlayAdminTokenTemplate.ts +79 -0
  186. package/src/overlay-tools/SHIPBroadcaster.ts +405 -0
  187. package/src/overlay-tools/__tests/LookupResolver.test.ts +1403 -0
  188. package/src/overlay-tools/__tests/OverlayAdminTokenTemplate.test.ts +69 -0
  189. package/src/overlay-tools/__tests/SHIPBroadcaster.test.ts +904 -0
  190. package/src/overlay-tools/index.ts +5 -0
  191. package/src/script/templates/PushDrop.ts +246 -0
  192. package/src/script/templates/__tests/PushDrop.test.ts +158 -0
  193. package/src/script/templates/index.ts +1 -0
  194. package/src/transaction/http/DefaultHttpClient.ts +1 -1
  195. package/src/wallet/CachedKeyDeriver.ts +193 -0
  196. package/src/wallet/KeyDeriver.ts +178 -0
  197. package/src/wallet/ProtoWallet.ts +732 -0
  198. package/src/wallet/Wallet.interfaces.ts +1170 -0
  199. package/src/wallet/WalletClient.ts +201 -0
  200. package/src/wallet/WalletError.ts +27 -0
  201. package/src/wallet/__tests/CachedKeyDeriver.test.ts +322 -0
  202. package/src/wallet/__tests/KeyDeriver.test.ts +118 -0
  203. package/src/wallet/__tests/ProtoWallet.test.ts +543 -0
  204. package/src/wallet/index.ts +8 -0
  205. package/src/wallet/substrates/HTTPWalletWire.ts +47 -0
  206. package/src/wallet/substrates/WalletWire.ts +6 -0
  207. package/src/wallet/substrates/WalletWireCalls.ts +34 -0
  208. package/src/wallet/substrates/WalletWireProcessor.ts +2046 -0
  209. package/src/wallet/substrates/WalletWireTransceiver.ts +1454 -0
  210. package/src/wallet/substrates/XDM.ts +157 -0
  211. package/src/wallet/substrates/__tests/WalletWire.integration.test.ts +2194 -0
  212. package/src/wallet/substrates/__tests/XDM.test.ts +659 -0
  213. package/src/wallet/substrates/index.ts +7 -0
  214. package/src/wallet/substrates/window.CWI.ts +133 -0
@@ -0,0 +1,543 @@
1
+ import ProtoWallet from '../../../dist/cjs/src/wallet/ProtoWallet.js'
2
+ import { Utils, PrivateKey, Hash } from '../../../dist/cjs/src/primitives/index.js'
3
+
4
+ const sampleData = [3, 1, 4, 1, 5, 9]
5
+
6
+ describe('ProtoWallet', () => {
7
+ it('Throws when functions are not supported', async () => {
8
+ const wallet = new ProtoWallet('anyone')
9
+ await expect(() => {
10
+ return (wallet as any).createAction()
11
+ }).rejects.toThrow()
12
+ await expect(() => {
13
+ return (wallet as any).abortAction()
14
+ }).rejects.toThrow()
15
+ await expect(() => {
16
+ return (wallet as any).signAction()
17
+ }).rejects.toThrow()
18
+ await expect(() => {
19
+ return (wallet as any).listOutputs()
20
+ }).rejects.toThrow()
21
+ await expect(() => {
22
+ return (wallet as any).relinquishOutput()
23
+ }).rejects.toThrow()
24
+ await expect(() => {
25
+ return (wallet as any).listActions()
26
+ }).rejects.toThrow()
27
+ await expect(() => {
28
+ return (wallet as any).internalizeAction()
29
+ }).rejects.toThrow()
30
+ await expect(() => {
31
+ return (wallet as any).acquireCertificate()
32
+ }).rejects.toThrow()
33
+ await expect(() => {
34
+ return (wallet as any).proveCertificate()
35
+ }).rejects.toThrow()
36
+ await expect(() => {
37
+ return (wallet as any).listCertificates()
38
+ }).rejects.toThrow()
39
+ await expect(() => {
40
+ return (wallet as any).relinquishCertificate()
41
+ }).rejects.toThrow()
42
+ await expect(() => {
43
+ return (wallet as any).getHeight()
44
+ }).rejects.toThrow()
45
+ await expect(() => {
46
+ return (wallet as any).getHeaderForHeight()
47
+ }).rejects.toThrow()
48
+ // TODO: Remove these two from the throw list once they are implemented.
49
+ await expect(() => {
50
+ return (wallet as any).discoverByIdentityKey()
51
+ }).rejects.toThrow()
52
+ await expect(() => {
53
+ return (wallet as any).discoverByAttributes()
54
+ }).rejects.toThrow()
55
+ })
56
+ it('Throws the privileged error when the privileged flag is set', async () => {
57
+ const wallet = new ProtoWallet('anyone')
58
+ const privilegedError = 'ProtoWallet is a single-keyring wallet, operating without context about whether its configured keyring is privileged.'
59
+ await expect(() => {
60
+ return (wallet as any).encrypt({ privileged: true })
61
+ }).rejects.toThrow(new Error(privilegedError))
62
+ await expect(() => {
63
+ return (wallet as any).decrypt({ privileged: true })
64
+ }).rejects.toThrow(new Error(privilegedError))
65
+ await expect(() => {
66
+ return (wallet as any).createSignature({ privileged: true })
67
+ }).rejects.toThrow(new Error(privilegedError))
68
+ await expect(() => {
69
+ return (wallet as any).verifySignature({ privileged: true })
70
+ }).rejects.toThrow(new Error(privilegedError))
71
+ await expect(() => {
72
+ return (wallet as any).createHmac({ privileged: true })
73
+ }).rejects.toThrow(new Error(privilegedError))
74
+ await expect(() => {
75
+ return (wallet as any).verifyHmac({ privileged: true })
76
+ }).rejects.toThrow(new Error(privilegedError))
77
+ await expect(() => {
78
+ return (wallet as any).getPublicKey({ privileged: true })
79
+ }).rejects.toThrow(new Error(privilegedError))
80
+ await expect(() => {
81
+ return (wallet as any).revealCounterpartyKeyLinkage({ privileged: true })
82
+ }).rejects.toThrow(new Error(privilegedError))
83
+ await expect(() => {
84
+ return (wallet as any).revealSpecificKeyLinkage({ privileged: true })
85
+ }).rejects.toThrow(new Error(privilegedError))
86
+ })
87
+ it('Validates the BRC-3 compliance vector', async () => {
88
+ const wallet = new ProtoWallet('anyone')
89
+ const { valid } = await wallet.verifySignature({
90
+ data: Utils.toArray('BRC-3 Compliance Validated!', 'utf8'),
91
+ signature: [48, 68, 2, 32, 43, 34, 58, 156, 219, 32, 50, 70, 29, 240, 155, 137, 88, 60, 200, 95, 243, 198, 201, 21, 56, 82, 141, 112, 69, 196, 170, 73, 156, 6, 44, 48, 2, 32, 118, 125, 254, 201, 44, 87, 177, 170, 93, 11, 193, 134, 18, 70, 9, 31, 234, 27, 170, 177, 54, 96, 181, 140, 166, 196, 144, 14, 230, 118, 106, 105],
92
+ protocolID: [2, 'BRC3 Test'],
93
+ keyID: '42',
94
+ counterparty: '0294c479f762f6baa97fbcd4393564c1d7bd8336ebd15928135bbcf575cd1a71a1'
95
+ })
96
+ expect(valid).toBe(true)
97
+ })
98
+ it('Validates the BRC-2 HMAC compliance vector', async () => {
99
+ const wallet = new ProtoWallet(new PrivateKey('6a2991c9de20e38b31d7ea147bf55f5039e4bbc073160f5e0d541d1f17e321b8', 'hex'))
100
+ const { valid } = await wallet.verifyHmac({
101
+ data: Utils.toArray('BRC-2 HMAC Compliance Validated!', 'utf8'),
102
+ hmac: [81, 240, 18, 153, 163, 45, 174, 85, 9, 246, 142, 125, 209, 133, 82, 76, 254, 103, 46, 182, 86, 59, 219, 61, 126, 30, 176, 232, 233, 100, 234, 14],
103
+ protocolID: [2, 'BRC2 Test'],
104
+ keyID: '42',
105
+ counterparty: '0294c479f762f6baa97fbcd4393564c1d7bd8336ebd15928135bbcf575cd1a71a1'
106
+ })
107
+ expect(valid).toBe(true)
108
+ })
109
+ it('Validates the BRC-2 Encryption compliance vector', async () => {
110
+ const wallet = new ProtoWallet(new PrivateKey('6a2991c9de20e38b31d7ea147bf55f5039e4bbc073160f5e0d541d1f17e321b8', 'hex'))
111
+ const { plaintext } = await wallet.decrypt({
112
+ ciphertext: [252, 203, 216, 184, 29, 161, 223, 212, 16, 193, 94, 99, 31, 140, 99, 43, 61, 236, 184, 67, 54, 105, 199, 47, 11, 19, 184, 127, 2, 165, 125, 9, 188, 195, 196, 39, 120, 130, 213, 95, 186, 89, 64, 28, 1, 80, 20, 213, 159, 133, 98, 253, 128, 105, 113, 247, 197, 152, 236, 64, 166, 207, 113, 134, 65, 38, 58, 24, 127, 145, 140, 206, 47, 70, 146, 84, 186, 72, 95, 35, 154, 112, 178, 55, 72, 124],
113
+ protocolID: [2, 'BRC2 Test'],
114
+ keyID: '42',
115
+ counterparty: '0294c479f762f6baa97fbcd4393564c1d7bd8336ebd15928135bbcf575cd1a71a1'
116
+ })
117
+ expect(Utils.toUTF8(plaintext)).toEqual('BRC-2 Encryption Compliance Validated!')
118
+ })
119
+ it('Encrypts messages decryptable by the counterparty', async () => {
120
+ const userKey = PrivateKey.fromRandom()
121
+ const counterpartyKey = PrivateKey.fromRandom()
122
+ const user = new ProtoWallet(userKey)
123
+ const counterparty = new ProtoWallet(counterpartyKey)
124
+ const { ciphertext } = await user.encrypt({
125
+ plaintext: sampleData,
126
+ protocolID: [2, 'tests'],
127
+ keyID: '4',
128
+ counterparty: counterpartyKey.toPublicKey().toString()
129
+ })
130
+ const { plaintext } = await counterparty.decrypt({
131
+ ciphertext,
132
+ protocolID: [2, 'tests'],
133
+ keyID: '4',
134
+ counterparty: userKey.toPublicKey().toString()
135
+ })
136
+ expect(plaintext).toEqual(sampleData)
137
+ expect(ciphertext).not.toEqual(plaintext)
138
+ })
139
+ it('Fails to decryupt messages for the wrong protocol, key, and counterparty', async () => {
140
+ const userKey = PrivateKey.fromRandom()
141
+ const counterpartyKey = PrivateKey.fromRandom()
142
+ const user = new ProtoWallet(userKey)
143
+ const counterparty = new ProtoWallet(counterpartyKey)
144
+ const { ciphertext } = await user.encrypt({
145
+ plaintext: sampleData,
146
+ protocolID: [2, 'tests'],
147
+ keyID: '4',
148
+ counterparty: counterpartyKey.toPublicKey().toString()
149
+ })
150
+ await expect(async () => await counterparty.decrypt({
151
+ ciphertext,
152
+ protocolID: [1, 'tests'],
153
+ keyID: '4',
154
+ counterparty: userKey.toPublicKey().toString()
155
+ })).rejects.toThrow()
156
+ await expect(async () => await counterparty.decrypt({
157
+ ciphertext,
158
+ protocolID: [2, 'tests'],
159
+ keyID: '5',
160
+ counterparty: userKey.toPublicKey().toString()
161
+ })).rejects.toThrow()
162
+ await expect(async () => await counterparty.decrypt({
163
+ ciphertext,
164
+ protocolID: [2, 'tests'],
165
+ keyID: '4',
166
+ counterparty: counterpartyKey.toPublicKey().toString()
167
+ })).rejects.toThrow()
168
+ })
169
+ it('Correctly derives keys for a counterparty', async () => {
170
+ const userKey = PrivateKey.fromRandom()
171
+ const counterpartyKey = PrivateKey.fromRandom()
172
+ const user = new ProtoWallet(userKey)
173
+ const counterparty = new ProtoWallet(counterpartyKey)
174
+ const { publicKey: identityKey } = await user.getPublicKey({
175
+ identityKey: true
176
+ })
177
+ expect(identityKey).toEqual(userKey.toPublicKey().toString())
178
+ const { publicKey: derivedForCounterparty } = await user.getPublicKey({
179
+ protocolID: [2, 'tests'],
180
+ keyID: '4',
181
+ counterparty: counterpartyKey.toPublicKey().toString()
182
+ })
183
+ const { publicKey: derivedByCounterparty } = await counterparty.getPublicKey({
184
+ protocolID: [2, 'tests'],
185
+ keyID: '4',
186
+ counterparty: userKey.toPublicKey().toString(),
187
+ forSelf: true
188
+ })
189
+ expect(derivedForCounterparty).toEqual(derivedByCounterparty)
190
+ })
191
+ it('Signs messages verifiable by the counterparty', async () => {
192
+ const userKey = PrivateKey.fromRandom()
193
+ const counterpartyKey = PrivateKey.fromRandom()
194
+ const user = new ProtoWallet(userKey)
195
+ const counterparty = new ProtoWallet(counterpartyKey)
196
+ const { signature } = await user.createSignature({
197
+ data: sampleData,
198
+ protocolID: [2, 'tests'],
199
+ keyID: '4',
200
+ counterparty: counterpartyKey.toPublicKey().toString()
201
+ })
202
+ const { valid } = await counterparty.verifySignature({
203
+ signature,
204
+ data: sampleData,
205
+ protocolID: [2, 'tests'],
206
+ keyID: '4',
207
+ counterparty: userKey.toPublicKey().toString()
208
+ })
209
+ expect(valid).toEqual(true)
210
+ expect(signature.length).not.toEqual(0)
211
+ })
212
+ it('Directly signs hash of message verifiable by the counterparty', async () => {
213
+ const userKey = PrivateKey.fromRandom()
214
+ const counterpartyKey = PrivateKey.fromRandom()
215
+ const user = new ProtoWallet(userKey)
216
+ const counterparty = new ProtoWallet(counterpartyKey)
217
+ const { signature } = await user.createSignature({
218
+ hashToDirectlySign: Hash.sha256(sampleData),
219
+ protocolID: [2, 'tests'],
220
+ keyID: '4',
221
+ counterparty: counterpartyKey.toPublicKey().toString()
222
+ })
223
+ const { valid } = await counterparty.verifySignature({
224
+ signature,
225
+ data: sampleData,
226
+ protocolID: [2, 'tests'],
227
+ keyID: '4',
228
+ counterparty: userKey.toPublicKey().toString()
229
+ })
230
+ expect(valid).toEqual(true)
231
+ const { valid: hashValid } = await counterparty.verifySignature({
232
+ signature,
233
+ hashToDirectlyVerify: Hash.sha256(sampleData),
234
+ protocolID: [2, 'tests'],
235
+ keyID: '4',
236
+ counterparty: userKey.toPublicKey().toString()
237
+ })
238
+ expect(hashValid).toEqual(true)
239
+ expect(signature.length).not.toEqual(0)
240
+ })
241
+ it('Fails to verify signature for the wrong data, protocol, key, and counterparty', async () => {
242
+ const userKey = PrivateKey.fromRandom()
243
+ const counterpartyKey = PrivateKey.fromRandom()
244
+ const user = new ProtoWallet(userKey)
245
+ const counterparty = new ProtoWallet(counterpartyKey)
246
+ const { signature } = await user.createSignature({
247
+ data: sampleData,
248
+ protocolID: [2, 'tests'],
249
+ keyID: '4',
250
+ counterparty: counterpartyKey.toPublicKey().toString()
251
+ })
252
+ await expect(async () => await counterparty.verifySignature({
253
+ signature,
254
+ data: [0, ...sampleData],
255
+ protocolID: [2, 'tests'],
256
+ keyID: '4',
257
+ counterparty: userKey.toPublicKey().toString()
258
+ })).rejects.toThrow()
259
+ await expect(async () => await counterparty.verifySignature({
260
+ signature,
261
+ data: sampleData,
262
+ protocolID: [2, 'wrong'],
263
+ keyID: '4',
264
+ counterparty: userKey.toPublicKey().toString()
265
+ })).rejects.toThrow()
266
+ await expect(async () => await counterparty.verifySignature({
267
+ signature,
268
+ data: sampleData,
269
+ protocolID: [2, 'tests'],
270
+ keyID: '2',
271
+ counterparty: userKey.toPublicKey().toString()
272
+ })).rejects.toThrow()
273
+ await expect(async () => await counterparty.verifySignature({
274
+ signature,
275
+ data: sampleData,
276
+ protocolID: [2, 'tests'],
277
+ keyID: '4',
278
+ counterparty: counterpartyKey.toPublicKey().toString()
279
+ })).rejects.toThrow()
280
+ })
281
+ it('Computes HMAC over messages verifiable by the counterparty', async () => {
282
+ const userKey = PrivateKey.fromRandom()
283
+ const counterpartyKey = PrivateKey.fromRandom()
284
+ const user = new ProtoWallet(userKey)
285
+ const counterparty = new ProtoWallet(counterpartyKey)
286
+ const { hmac } = await user.createHmac({
287
+ data: sampleData,
288
+ protocolID: [2, 'tests'],
289
+ keyID: '4',
290
+ counterparty: counterpartyKey.toPublicKey().toString()
291
+ })
292
+ const { valid } = await counterparty.verifyHmac({
293
+ hmac,
294
+ data: sampleData,
295
+ protocolID: [2, 'tests'],
296
+ keyID: '4',
297
+ counterparty: userKey.toPublicKey().toString()
298
+ })
299
+ expect(valid).toEqual(true)
300
+ expect(hmac.length).toEqual(32)
301
+ })
302
+ it('Fails to verify HMAC for the wrong data, protocol, key, and counterparty', async () => {
303
+ const userKey = PrivateKey.fromRandom()
304
+ const counterpartyKey = PrivateKey.fromRandom()
305
+ const user = new ProtoWallet(userKey)
306
+ const counterparty = new ProtoWallet(counterpartyKey)
307
+ const { hmac } = await user.createHmac({
308
+ data: sampleData,
309
+ protocolID: [2, 'tests'],
310
+ keyID: '4',
311
+ counterparty: counterpartyKey.toPublicKey().toString()
312
+ })
313
+ await expect(async () => await counterparty.verifyHmac({
314
+ hmac,
315
+ data: [0, ...sampleData],
316
+ protocolID: [2, 'tests'],
317
+ keyID: '4',
318
+ counterparty: userKey.toPublicKey().toString()
319
+ })).rejects.toThrow()
320
+ await expect(async () => await counterparty.verifyHmac({
321
+ hmac,
322
+ data: sampleData,
323
+ protocolID: [2, 'wrong'],
324
+ keyID: '4',
325
+ counterparty: userKey.toPublicKey().toString()
326
+ })).rejects.toThrow()
327
+ await expect(async () => await counterparty.verifyHmac({
328
+ hmac,
329
+ data: sampleData,
330
+ protocolID: [2, 'tests'],
331
+ keyID: '2',
332
+ counterparty: userKey.toPublicKey().toString()
333
+ })).rejects.toThrow()
334
+ await expect(async () => await counterparty.verifyHmac({
335
+ hmac,
336
+ data: sampleData,
337
+ protocolID: [2, 'tests'],
338
+ keyID: '4',
339
+ counterparty: counterpartyKey.toPublicKey().toString()
340
+ })).rejects.toThrow()
341
+ })
342
+ it('Returns the expected version, network, and authentication status', async () => {
343
+ const wallet = new ProtoWallet('anyone')
344
+ expect(await wallet.getVersion({})).toEqual({ version: 'proto-1.0.0' })
345
+ expect(await wallet.getNetwork({})).toEqual({ network: 'mainnet' })
346
+ expect(await wallet.isAuthenticated({})).toEqual({ authenticated: true })
347
+ expect(await wallet.waitForAuthentication({})).toEqual({ authenticated: true })
348
+ })
349
+ it('Uses anyone for creating signatures and self for other operations if no counterparty is provided', async () => {
350
+ const userKey = PrivateKey.fromRandom()
351
+ const user = new ProtoWallet(userKey)
352
+ const { hmac } = await user.createHmac({
353
+ data: sampleData,
354
+ protocolID: [2, 'tests'],
355
+ keyID: '4'
356
+ })
357
+ const { valid: hmacValid } = await user.verifyHmac({
358
+ hmac,
359
+ data: sampleData,
360
+ protocolID: [2, 'tests'],
361
+ keyID: '4'
362
+ })
363
+ expect(hmacValid).toEqual(true)
364
+ const { valid: explicitSelfHmacValid } = await user.verifyHmac({
365
+ hmac,
366
+ data: sampleData,
367
+ protocolID: [2, 'tests'],
368
+ keyID: '4',
369
+ counterparty: 'self'
370
+ })
371
+ expect(explicitSelfHmacValid).toEqual(true)
372
+ expect(hmac.length).toEqual(32)
373
+ const { signature: anyoneSig } = await user.createSignature({
374
+ data: sampleData,
375
+ protocolID: [2, 'tests'],
376
+ keyID: '4'
377
+ // counterparty=anyone is implicit for creating signatures
378
+ })
379
+ const anyone = new ProtoWallet('anyone')
380
+ const { valid: anyoneSigValid } = await anyone.verifySignature({
381
+ signature: anyoneSig,
382
+ data: sampleData,
383
+ protocolID: [2, 'tests'],
384
+ keyID: '4',
385
+ counterparty: userKey.toPublicKey().toString()
386
+ })
387
+ expect(anyoneSigValid).toEqual(true)
388
+ const { signature: selfSig } = await user.createSignature({
389
+ data: sampleData,
390
+ protocolID: [2, 'tests'],
391
+ keyID: '4',
392
+ counterparty: 'self'
393
+ })
394
+ const { valid: selfSigValid } = await user.verifySignature({
395
+ signature: selfSig,
396
+ data: sampleData,
397
+ protocolID: [2, 'tests'],
398
+ keyID: '4'
399
+ // Self is implicit when verifying signatures
400
+ })
401
+ expect(selfSigValid).toEqual(true)
402
+ const { valid: explicitSelfSigValid } = await user.verifySignature({
403
+ signature: selfSig,
404
+ data: sampleData,
405
+ protocolID: [2, 'tests'],
406
+ keyID: '4',
407
+ counterparty: 'self'
408
+ })
409
+ expect(explicitSelfSigValid).toEqual(true)
410
+ const { publicKey } = await user.getPublicKey({
411
+ protocolID: [2, 'tests'],
412
+ keyID: '4'
413
+ })
414
+ const { publicKey: explicitSelfPublicKey } = await user.getPublicKey({
415
+ protocolID: [2, 'tests'],
416
+ keyID: '4',
417
+ counterparty: 'self'
418
+ })
419
+ expect(publicKey).toEqual(explicitSelfPublicKey)
420
+ const { ciphertext } = await user.encrypt({
421
+ plaintext: sampleData,
422
+ protocolID: [2, 'tests'],
423
+ keyID: '4'
424
+ })
425
+ const { plaintext } = await user.decrypt({
426
+ ciphertext,
427
+ protocolID: [2, 'tests'],
428
+ keyID: '4'
429
+ })
430
+ const { plaintext: explicitSelfPlaintext } = await user.decrypt({
431
+ ciphertext,
432
+ protocolID: [2, 'tests'],
433
+ keyID: '4',
434
+ counterparty: 'self'
435
+ })
436
+ expect(plaintext).toEqual(explicitSelfPlaintext)
437
+ expect(plaintext).toEqual(sampleData)
438
+ })
439
+ describe('ProtoWallet Key Linkage Revelation', () => {
440
+ it('Validates the revealCounterpartyKeyLinkage function', async () => {
441
+ // Initialize keys
442
+ const proverKey = PrivateKey.fromRandom()
443
+ const counterpartyKey = PrivateKey.fromRandom()
444
+ const verifierKey = PrivateKey.fromRandom()
445
+
446
+ // Initialize wallets
447
+ const proverWallet = new ProtoWallet(proverKey)
448
+ const verifierWallet = new ProtoWallet(verifierKey)
449
+
450
+ // Prover reveals counterparty key linkage
451
+ const revelation = await proverWallet.revealCounterpartyKeyLinkage({
452
+ counterparty: counterpartyKey.toPublicKey().toString(),
453
+ verifier: verifierKey.toPublicKey().toString()
454
+ })
455
+
456
+ // Verifier decrypts the encrypted linkage
457
+ const { plaintext: linkage } = await verifierWallet.decrypt({
458
+ ciphertext: revelation.encryptedLinkage,
459
+ protocolID: [2, 'counterparty linkage revelation'],
460
+ keyID: revelation.revelationTime,
461
+ counterparty: proverKey.toPublicKey().toString()
462
+ })
463
+
464
+ // Compute expected linkage
465
+ const expectedLinkage = proverKey.deriveSharedSecret(counterpartyKey.toPublicKey()).encode(true)
466
+
467
+ // Compare linkage and expectedLinkage
468
+ expect(linkage).toEqual(expectedLinkage)
469
+ })
470
+
471
+ it('Validates the revealSpecificKeyLinkage function', async () => {
472
+ // Initialize keys
473
+ const proverKey = PrivateKey.fromRandom()
474
+ const counterpartyKey = PrivateKey.fromRandom()
475
+ const verifierKey = PrivateKey.fromRandom()
476
+
477
+ // Initialize wallets
478
+ const proverWallet = new ProtoWallet(proverKey)
479
+ const verifierWallet = new ProtoWallet(verifierKey)
480
+
481
+ const protocolID: [0 | 1 | 2, string] = [0, 'tests']
482
+ const keyID = 'test key id'
483
+
484
+ // Prover reveals specific key linkage
485
+ const revelation = await proverWallet.revealSpecificKeyLinkage({
486
+ counterparty: counterpartyKey.toPublicKey().toString(),
487
+ verifier: verifierKey.toPublicKey().toString(),
488
+ protocolID,
489
+ keyID
490
+ })
491
+
492
+ // Verifier decrypts the encrypted linkage
493
+ const { plaintext: linkage } = await verifierWallet.decrypt({
494
+ ciphertext: revelation.encryptedLinkage,
495
+ protocolID: [2, `specific linkage revelation ${protocolID[0]} ${protocolID[1]}`],
496
+ keyID,
497
+ counterparty: proverKey.toPublicKey().toString()
498
+ })
499
+
500
+ // Compute expected linkage
501
+ const sharedSecret = proverKey.deriveSharedSecret(counterpartyKey.toPublicKey()).encode(true)
502
+
503
+ // Function to compute the invoice number
504
+ const computeInvoiceNumber = function (protocolID, keyID) {
505
+ const securityLevel = protocolID[0]
506
+ if (!Number.isInteger(securityLevel) || securityLevel < 0 || securityLevel > 2) {
507
+ throw new Error('Protocol security level must be 0, 1, or 2')
508
+ }
509
+ const protocolName = protocolID[1].toLowerCase().trim()
510
+ if (keyID.length > 800) {
511
+ throw new Error('Key IDs must be 800 characters or less')
512
+ }
513
+ if (keyID.length < 1) {
514
+ throw new Error('Key IDs must be 1 character or more')
515
+ }
516
+ if (protocolName.length > 400) {
517
+ throw new Error('Protocol names must be 400 characters or less')
518
+ }
519
+ if (protocolName.length < 5) {
520
+ throw new Error('Protocol names must be 5 characters or more')
521
+ }
522
+ if (protocolName.includes(' ')) {
523
+ throw new Error('Protocol names cannot contain multiple consecutive spaces (" ")')
524
+ }
525
+ if (!/^[a-z0-9 ]+$/g.test(protocolName)) {
526
+ throw new Error('Protocol names can only contain letters, numbers and spaces')
527
+ }
528
+ if (protocolName.endsWith(' protocol')) {
529
+ throw new Error('No need to end your protocol name with " protocol"')
530
+ }
531
+ return `${securityLevel}-${protocolName}-${keyID}`
532
+ }
533
+ const invoiceNumber = computeInvoiceNumber(protocolID, keyID)
534
+ const invoiceNumberBin = Utils.toArray(invoiceNumber, 'utf8')
535
+
536
+ // Compute expected linkage
537
+ const expectedLinkage = Hash.sha256hmac(sharedSecret, invoiceNumberBin)
538
+
539
+ // Compare linkage and expectedLinkage
540
+ expect(linkage).toEqual(expectedLinkage)
541
+ })
542
+ })
543
+ })
@@ -0,0 +1,8 @@
1
+ export * from './Wallet.interfaces.js'
2
+ export { default as KeyDeriver } from './KeyDeriver.js'
3
+ export { default as CachedKeyDeriver } from './CachedKeyDeriver.js'
4
+ export { default as ProtoWallet } from './ProtoWallet.js'
5
+ export { default as WalletClient } from './WalletClient.js'
6
+ export { default as WalletErrors } from './WalletError.js'
7
+ export * from './WalletError.js'
8
+ export * from './substrates/index.js'
@@ -0,0 +1,47 @@
1
+ import WalletWire from './WalletWire.js'
2
+ import WalletWireCalls from './WalletWireCalls.js'
3
+ import { Utils } from '../../primitives/index.js'
4
+
5
+ export default class HTTPWalletWire implements WalletWire {
6
+ baseUrl: string
7
+ httpClient: typeof fetch
8
+ originator: string | undefined
9
+
10
+ constructor(originator: string | undefined, baseUrl: string = 'http://localhost:3301', httpClient = fetch) {
11
+ this.baseUrl = baseUrl
12
+ this.httpClient = httpClient
13
+ this.originator = originator
14
+ }
15
+
16
+ async transmitToWallet(message: number[]): Promise<number[]> {
17
+ const messageReader = new Utils.Reader(message)
18
+ // Read call code
19
+ const callCode = messageReader.readUInt8()
20
+
21
+ // Map call code to call name
22
+ const callName = WalletWireCalls[callCode] // calls is enum
23
+ if (!callName) {
24
+ // Invalid call code
25
+ throw new Error(`Invalid call code: ${callCode}`)
26
+ }
27
+
28
+ // Read originator length
29
+ const originatorLength = messageReader.readUInt8()
30
+ let originator: string | undefined
31
+ if (originatorLength > 0) {
32
+ const originatorBytes = messageReader.read(originatorLength)
33
+ originator = Utils.toUTF8(originatorBytes)
34
+ }
35
+ const payload = messageReader.read()
36
+ const response = await fetch(`${this.baseUrl}/${callName}`, {
37
+ method: 'POST',
38
+ headers: {
39
+ 'Content-Type': 'application/octet-stream',
40
+ Origin: originator
41
+ },
42
+ body: new Uint8Array(payload)
43
+ })
44
+ const responseBuffer = await response.arrayBuffer()
45
+ return Array.from(new Uint8Array(responseBuffer))
46
+ }
47
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * A Wallet Wire is an abstraction over a raw transport medium where binary data can be sent to and subsequently received from a wallet.
3
+ */
4
+ export default interface WalletWire {
5
+ transmitToWallet: (message: number[]) => Promise<number[]>
6
+ }
@@ -0,0 +1,34 @@
1
+ // NOTE: Enum values must not exceed the UInt8 range (0–255)
2
+ enum calls {
3
+ createAction = 1,
4
+ signAction = 2,
5
+ abortAction = 3,
6
+ listActions = 4,
7
+ internalizeAction = 5,
8
+ listOutputs = 6,
9
+ relinquishOutput = 7,
10
+ getPublicKey = 8,
11
+ revealCounterpartyKeyLinkage = 9,
12
+ revealSpecificKeyLinkage = 10,
13
+ encrypt = 11,
14
+ decrypt = 12,
15
+ createHmac = 13,
16
+ verifyHmac = 14,
17
+ createSignature = 15,
18
+ verifySignature = 16,
19
+ acquireCertificate = 17,
20
+ listCertificates = 18,
21
+ proveCertificate = 19,
22
+ relinquishCertificate = 20,
23
+ discoverByIdentityKey = 21,
24
+ discoverByAttributes = 22,
25
+ isAuthenticated = 23,
26
+ waitForAuthentication = 24,
27
+ getHeight = 25,
28
+ getHeaderForHeight = 26,
29
+ getNetwork = 27,
30
+ getVersion = 28
31
+ }
32
+
33
+ export default calls
34
+ export type CallType = keyof typeof calls