@bsv/sdk 2.0.11 → 2.0.13

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 (106) hide show
  1. package/dist/cjs/package.json +1 -1
  2. package/dist/cjs/src/auth/clients/__tests__/AuthFetch.additional.test.js +827 -0
  3. package/dist/cjs/src/auth/clients/__tests__/AuthFetch.additional.test.js.map +1 -0
  4. package/dist/cjs/src/auth/transports/__tests__/SimplifiedFetchTransport.additional.test.js +654 -0
  5. package/dist/cjs/src/auth/transports/__tests__/SimplifiedFetchTransport.additional.test.js.map +1 -0
  6. package/dist/cjs/src/overlay-tools/HostReputationTracker.js +21 -13
  7. package/dist/cjs/src/overlay-tools/HostReputationTracker.js.map +1 -1
  8. package/dist/cjs/src/primitives/PrivateKey.js +3 -3
  9. package/dist/cjs/src/primitives/PrivateKey.js.map +1 -1
  10. package/dist/cjs/src/script/Spend.js +17 -9
  11. package/dist/cjs/src/script/Spend.js.map +1 -1
  12. package/dist/cjs/src/storage/StorageDownloader.js +6 -6
  13. package/dist/cjs/src/storage/StorageDownloader.js.map +1 -1
  14. package/dist/cjs/src/storage/StorageUtils.js +1 -1
  15. package/dist/cjs/src/storage/StorageUtils.js.map +1 -1
  16. package/dist/cjs/src/transaction/MerklePath.js +168 -27
  17. package/dist/cjs/src/transaction/MerklePath.js.map +1 -1
  18. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  19. package/dist/esm/src/auth/clients/__tests__/AuthFetch.additional.test.js +825 -0
  20. package/dist/esm/src/auth/clients/__tests__/AuthFetch.additional.test.js.map +1 -0
  21. package/dist/esm/src/auth/transports/__tests__/SimplifiedFetchTransport.additional.test.js +619 -0
  22. package/dist/esm/src/auth/transports/__tests__/SimplifiedFetchTransport.additional.test.js.map +1 -0
  23. package/dist/esm/src/overlay-tools/HostReputationTracker.js +21 -13
  24. package/dist/esm/src/overlay-tools/HostReputationTracker.js.map +1 -1
  25. package/dist/esm/src/primitives/PrivateKey.js +3 -3
  26. package/dist/esm/src/primitives/PrivateKey.js.map +1 -1
  27. package/dist/esm/src/script/Spend.js +17 -9
  28. package/dist/esm/src/script/Spend.js.map +1 -1
  29. package/dist/esm/src/storage/StorageDownloader.js +6 -6
  30. package/dist/esm/src/storage/StorageDownloader.js.map +1 -1
  31. package/dist/esm/src/storage/StorageUtils.js +1 -1
  32. package/dist/esm/src/storage/StorageUtils.js.map +1 -1
  33. package/dist/esm/src/transaction/MerklePath.js +168 -27
  34. package/dist/esm/src/transaction/MerklePath.js.map +1 -1
  35. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  36. package/dist/types/src/auth/clients/__tests__/AuthFetch.additional.test.d.ts +21 -0
  37. package/dist/types/src/auth/clients/__tests__/AuthFetch.additional.test.d.ts.map +1 -0
  38. package/dist/types/src/auth/transports/__tests__/SimplifiedFetchTransport.additional.test.d.ts +2 -0
  39. package/dist/types/src/auth/transports/__tests__/SimplifiedFetchTransport.additional.test.d.ts.map +1 -0
  40. package/dist/types/src/overlay-tools/HostReputationTracker.d.ts.map +1 -1
  41. package/dist/types/src/script/Spend.d.ts.map +1 -1
  42. package/dist/types/src/transaction/MerklePath.d.ts +27 -0
  43. package/dist/types/src/transaction/MerklePath.d.ts.map +1 -1
  44. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  45. package/dist/umd/bundle.js +3 -3
  46. package/dist/umd/bundle.js.map +1 -1
  47. package/docs/reference/storage.md +1 -1
  48. package/docs/reference/transaction.md +40 -0
  49. package/package.json +1 -1
  50. package/src/auth/clients/__tests__/AuthFetch.additional.test.ts +1131 -0
  51. package/src/auth/transports/__tests__/SimplifiedFetchTransport.additional.test.ts +770 -0
  52. package/src/auth/utils/__tests/validateCertificates.test.ts +12 -9
  53. package/src/compat/__tests/Mnemonic.additional.test.ts +64 -0
  54. package/src/identity/__tests/IdentityClient.additional.test.ts +767 -0
  55. package/src/kvstore/__tests/LocalKVStore.additional.test.ts +611 -0
  56. package/src/kvstore/__tests/LocalKVStore.test.ts +4 -6
  57. package/src/kvstore/__tests/kvStoreInterpreter.test.ts +327 -0
  58. package/src/overlay-tools/HostReputationTracker.ts +17 -14
  59. package/src/overlay-tools/__tests/HostReputationTracker.additional.test.ts +561 -0
  60. package/src/overlay-tools/__tests/LookupResolver.additional.test.ts +612 -0
  61. package/src/overlay-tools/__tests/withDoubleSpendRetry.test.ts +278 -0
  62. package/src/primitives/PrivateKey.ts +3 -3
  63. package/src/primitives/__tests/BigNumber.additional.test.ts +79 -0
  64. package/src/primitives/__tests/Curve.additional.test.ts +208 -0
  65. package/src/primitives/__tests/ECDSA.additional.test.ts +122 -0
  66. package/src/primitives/__tests/Hash.additional.test.ts +59 -0
  67. package/src/primitives/__tests/JacobianPoint.test.ts +308 -0
  68. package/src/primitives/__tests/Point.additional.test.ts +503 -0
  69. package/src/primitives/__tests/PublicKey.additional.test.ts +383 -0
  70. package/src/primitives/__tests/Random.additional.test.ts +262 -0
  71. package/src/primitives/__tests/Signature.test.ts +333 -0
  72. package/src/primitives/__tests/TransactionSignature.additional.test.ts +241 -0
  73. package/src/registry/__tests/RegistryClient.additional.test.ts +750 -0
  74. package/src/remittance/__tests/BasicBRC29.additional.test.ts +657 -0
  75. package/src/remittance/__tests/RemittanceManager.additional.test.ts +1272 -0
  76. package/src/script/Spend.ts +19 -11
  77. package/src/script/__tests/LockingUnlockingScript.test.ts +79 -0
  78. package/src/script/__tests/Script.additional.test.ts +100 -0
  79. package/src/script/__tests/ScriptEvaluationError.test.ts +98 -0
  80. package/src/script/__tests/Spend.additional.test.ts +837 -0
  81. package/src/script/templates/__tests/RPuzzle.test.ts +134 -0
  82. package/src/storage/StorageDownloader.ts +6 -6
  83. package/src/storage/StorageUtils.ts +1 -1
  84. package/src/transaction/MerklePath.ts +196 -36
  85. package/src/transaction/__tests/BeefParty.additional.test.ts +22 -0
  86. package/src/transaction/__tests/Broadcaster.test.ts +159 -0
  87. package/src/transaction/__tests/MerklePath.bench.test.ts +105 -0
  88. package/src/transaction/__tests/MerklePath.test.ts +232 -21
  89. package/src/transaction/__tests/Transaction.additional.test.ts +225 -0
  90. package/src/transaction/broadcasters/__tests/ARC.additional.test.ts +585 -0
  91. package/src/transaction/broadcasters/__tests/Teranode.test.ts +349 -0
  92. package/src/transaction/chaintrackers/__tests/BlockHeadersService.test.ts +253 -0
  93. package/src/transaction/chaintrackers/__tests/DefaultChainTracker.test.ts +44 -0
  94. package/src/transaction/chaintrackers/__tests/WhatsOnChain.additional.test.ts +193 -0
  95. package/src/transaction/fee-models/__tests/SatoshisPerKilobyte.test.ts +262 -0
  96. package/src/transaction/http/__tests/BinaryFetchClient.test.ts +212 -0
  97. package/src/transaction/http/__tests/DefaultHttpClient.additional.test.ts +192 -0
  98. package/src/transaction/http/__tests/DefaultHttpClient.test.ts +71 -0
  99. package/src/wallet/__tests/ProtoWallet.additional.test.ts +134 -0
  100. package/src/wallet/__tests/WERR.test.ts +212 -0
  101. package/src/wallet/__tests/WalletClient.additional.test.ts +699 -0
  102. package/src/wallet/__tests/WalletClient.substrate.test.ts +759 -0
  103. package/src/wallet/__tests/WalletError.test.ts +290 -0
  104. package/src/wallet/__tests/validationHelpers.test.ts +1218 -0
  105. package/src/wallet/substrates/__tests/HTTPWalletJSON.test.ts +496 -0
  106. package/src/wallet/substrates/__tests/HTTPWalletWire.test.ts +273 -0
@@ -0,0 +1,496 @@
1
+ import HTTPWalletJSON from '../HTTPWalletJSON'
2
+ import { WERR_INVALID_PARAMETER } from '../../WERR_INVALID_PARAMETER'
3
+ import { WERR_INSUFFICIENT_FUNDS } from '../../WERR_INSUFFICIENT_FUNDS'
4
+ import { WERR_REVIEW_ACTIONS } from '../../WERR_REVIEW_ACTIONS'
5
+
6
+ // ---------------------------------------------------------------------------
7
+ // Helpers
8
+ // ---------------------------------------------------------------------------
9
+
10
+ /** Build a minimal fetch mock that resolves with a JSON-shaped Response. */
11
+ function makeFetch(
12
+ body: unknown,
13
+ { ok = true, status = 200 }: { ok?: boolean; status?: number } = {}
14
+ ): jest.Mock {
15
+ return jest.fn().mockResolvedValue({
16
+ ok,
17
+ status,
18
+ json: () => Promise.resolve(body),
19
+ } as unknown as Response)
20
+ }
21
+
22
+ /** Build a fetch mock that rejects (network-level failure). */
23
+ function makeNetworkErrorFetch(message = 'Network failure'): jest.Mock {
24
+ return jest.fn().mockRejectedValue(new Error(message))
25
+ }
26
+
27
+ // ---------------------------------------------------------------------------
28
+ // Constructor
29
+ // ---------------------------------------------------------------------------
30
+
31
+ describe('HTTPWalletJSON – constructor', () => {
32
+ it('stores the provided baseUrl', () => {
33
+ const client = new HTTPWalletJSON('example.com', 'http://my-server:9000')
34
+ expect(client.baseUrl).toBe('http://my-server:9000')
35
+ })
36
+
37
+ it('uses http://localhost:3321 as the default baseUrl', () => {
38
+ const client = new HTTPWalletJSON('example.com')
39
+ expect(client.baseUrl).toBe('http://localhost:3321')
40
+ })
41
+
42
+ it('stores the originator', () => {
43
+ const client = new HTTPWalletJSON('wallet.example.com')
44
+ expect(client.originator).toBe('wallet.example.com')
45
+ })
46
+
47
+ it('accepts undefined originator', () => {
48
+ const client = new HTTPWalletJSON(undefined)
49
+ expect(client.originator).toBeUndefined()
50
+ })
51
+
52
+ it('stores the custom httpClient', () => {
53
+ const mockFetch = jest.fn()
54
+ const client = new HTTPWalletJSON('example.com', 'http://localhost:3321', mockFetch as unknown as typeof fetch)
55
+ expect(client.httpClient).toBe(mockFetch)
56
+ })
57
+ })
58
+
59
+ // ---------------------------------------------------------------------------
60
+ // api() – happy-path deserialization
61
+ // ---------------------------------------------------------------------------
62
+
63
+ describe('HTTPWalletJSON – api() successful responses', () => {
64
+ it('POSTs to the correct URL and returns the parsed body', async () => {
65
+ const mockFetch = makeFetch({ version: '1.0.0.0.0.0.0' })
66
+ const client = new HTTPWalletJSON(undefined, 'http://localhost:3321', mockFetch as unknown as typeof fetch)
67
+
68
+ const result = await client.getVersion({})
69
+
70
+ expect(mockFetch).toHaveBeenCalledTimes(1)
71
+ const [url, init] = mockFetch.mock.calls[0] as [string, RequestInit]
72
+ expect(url).toBe('http://localhost:3321/getVersion')
73
+ expect(init.method).toBe('POST')
74
+ expect(JSON.parse(init.body as string)).toEqual({})
75
+ expect(result).toEqual({ version: '1.0.0.0.0.0.0' })
76
+ })
77
+
78
+ it('sets Accept and Content-Type headers', async () => {
79
+ const mockFetch = makeFetch({ height: 800000 })
80
+ const client = new HTTPWalletJSON(undefined, 'http://localhost:3321', mockFetch as unknown as typeof fetch)
81
+
82
+ await client.getHeight({})
83
+
84
+ const [, init] = mockFetch.mock.calls[0] as [string, RequestInit]
85
+ const headers = init.headers as Record<string, string>
86
+ expect(headers['Accept']).toBe('application/json')
87
+ expect(headers['Content-Type']).toBe('application/json')
88
+ })
89
+
90
+ it('serialises args as JSON in the request body', async () => {
91
+ const mockFetch = makeFetch({ actions: [], totalActions: 0 })
92
+ const client = new HTTPWalletJSON(undefined, 'http://localhost:3321', mockFetch as unknown as typeof fetch)
93
+
94
+ await client.listActions({ labels: ['test-label'] })
95
+
96
+ const [, init] = mockFetch.mock.calls[0] as [string, RequestInit]
97
+ expect(JSON.parse(init.body as string)).toEqual({ labels: ['test-label'] })
98
+ })
99
+ })
100
+
101
+ // ---------------------------------------------------------------------------
102
+ // api() – error response deserialization
103
+ // ---------------------------------------------------------------------------
104
+
105
+ describe('HTTPWalletJSON – api() error responses', () => {
106
+ it('throws WERR_INVALID_PARAMETER (code 6) when the server returns it', async () => {
107
+ const errorBody = {
108
+ isError: true,
109
+ code: 6,
110
+ parameter: 'description',
111
+ message: 'The description parameter must be at least 5 length.',
112
+ }
113
+ const mockFetch = makeFetch(errorBody, { ok: false, status: 400 })
114
+ const client = new HTTPWalletJSON(undefined, 'http://localhost:3321', mockFetch as unknown as typeof fetch)
115
+
116
+ await expect(client.createAction({ description: 'x' })).rejects.toThrow(WERR_INVALID_PARAMETER)
117
+
118
+ try {
119
+ await client.createAction({ description: 'x' })
120
+ } catch (e: unknown) {
121
+ const err = e as WERR_INVALID_PARAMETER
122
+ expect(err.name).toBe('WERR_INVALID_PARAMETER')
123
+ expect(err.parameter).toBe('description')
124
+ expect(err.code).toBe(6)
125
+ }
126
+ })
127
+
128
+ it('WERR_INVALID_PARAMETER carries the server message verbatim', async () => {
129
+ const errorBody = {
130
+ isError: true,
131
+ code: 6,
132
+ parameter: 'lockingScript',
133
+ message: 'Custom server message for lockingScript.',
134
+ }
135
+ const mockFetch = makeFetch(errorBody, { ok: false, status: 400 })
136
+ const client = new HTTPWalletJSON(undefined, 'http://localhost:3321', mockFetch as unknown as typeof fetch)
137
+
138
+ try {
139
+ await client.createAction({ description: 'hello world' })
140
+ } catch (e: unknown) {
141
+ const err = e as WERR_INVALID_PARAMETER
142
+ expect(err.message).toBe('Custom server message for lockingScript.')
143
+ }
144
+ })
145
+
146
+ it('throws WERR_INSUFFICIENT_FUNDS (code 7) when the server returns it', async () => {
147
+ const errorBody = {
148
+ isError: true,
149
+ code: 7,
150
+ totalSatoshisNeeded: 5000,
151
+ moreSatoshisNeeded: 2000,
152
+ }
153
+ const mockFetch = makeFetch(errorBody, { ok: false, status: 400 })
154
+ const client = new HTTPWalletJSON(undefined, 'http://localhost:3321', mockFetch as unknown as typeof fetch)
155
+
156
+ await expect(client.createAction({ description: 'hello world' })).rejects.toThrow(WERR_INSUFFICIENT_FUNDS)
157
+
158
+ try {
159
+ await client.createAction({ description: 'hello world' })
160
+ } catch (e: unknown) {
161
+ const err = e as WERR_INSUFFICIENT_FUNDS
162
+ expect(err.totalSatoshisNeeded).toBe(5000)
163
+ expect(err.moreSatoshisNeeded).toBe(2000)
164
+ expect(err.code).toBe(7)
165
+ }
166
+ })
167
+
168
+ it('throws WERR_REVIEW_ACTIONS (code 5) when the server returns it', async () => {
169
+ const errorBody = {
170
+ isError: true,
171
+ code: 5,
172
+ reviewActionResults: [{ txid: 'abc', status: 'failed' }],
173
+ sendWithResults: [],
174
+ txid: 'abc123',
175
+ }
176
+ const mockFetch = makeFetch(errorBody, { ok: false, status: 400 })
177
+ const client = new HTTPWalletJSON(undefined, 'http://localhost:3321', mockFetch as unknown as typeof fetch)
178
+
179
+ await expect(client.createAction({ description: 'hello world' })).rejects.toThrow(WERR_REVIEW_ACTIONS)
180
+
181
+ try {
182
+ await client.createAction({ description: 'hello world' })
183
+ } catch (e: unknown) {
184
+ const err = e as WERR_REVIEW_ACTIONS
185
+ expect(err.code).toBe(5)
186
+ expect(err.txid).toBe('abc123')
187
+ expect(err.reviewActionResults).toEqual([{ txid: 'abc', status: 'failed' }])
188
+ }
189
+ })
190
+
191
+ it('throws a generic Error when the server returns a non-400 error status', async () => {
192
+ const mockFetch = makeFetch({ message: 'Internal Server Error' }, { ok: false, status: 500 })
193
+ const client = new HTTPWalletJSON(undefined, 'http://localhost:3321', mockFetch as unknown as typeof fetch)
194
+
195
+ await expect(client.getVersion({})).rejects.toThrow(Error)
196
+
197
+ try {
198
+ await client.getVersion({})
199
+ } catch (e: unknown) {
200
+ const err = e as Error
201
+ expect(err.message).toContain('getVersion')
202
+ expect(err.message).toContain('Internal Server Error')
203
+ }
204
+ })
205
+
206
+ it('falls back to "HTTP Client error <status>" when the 500 body has no message', async () => {
207
+ const mockFetch = makeFetch({}, { ok: false, status: 503 })
208
+ const client = new HTTPWalletJSON(undefined, 'http://localhost:3321', mockFetch as unknown as typeof fetch)
209
+
210
+ try {
211
+ await client.getVersion({})
212
+ } catch (e: unknown) {
213
+ const err = e as Error
214
+ expect(err.message).toContain('HTTP Client error 503')
215
+ }
216
+ })
217
+
218
+ it('does NOT throw for an unknown error code when isError is true', async () => {
219
+ // code 99 is unrecognised – falls through to the generic error path
220
+ const errorBody = { isError: true, code: 99, message: 'Unknown problem' }
221
+ const mockFetch = makeFetch(errorBody, { ok: false, status: 400 })
222
+ const client = new HTTPWalletJSON(undefined, 'http://localhost:3321', mockFetch as unknown as typeof fetch)
223
+
224
+ await expect(client.getVersion({})).rejects.toThrow(Error)
225
+ })
226
+ })
227
+
228
+ // ---------------------------------------------------------------------------
229
+ // Network errors
230
+ // ---------------------------------------------------------------------------
231
+
232
+ describe('HTTPWalletJSON – network errors', () => {
233
+ it('propagates a fetch rejection as-is', async () => {
234
+ const mockFetch = makeNetworkErrorFetch('Failed to fetch')
235
+ const client = new HTTPWalletJSON(undefined, 'http://localhost:3321', mockFetch as unknown as typeof fetch)
236
+
237
+ await expect(client.getVersion({})).rejects.toThrow('Failed to fetch')
238
+ })
239
+ })
240
+
241
+ // ---------------------------------------------------------------------------
242
+ // All wallet interface methods delegate to api()
243
+ // ---------------------------------------------------------------------------
244
+
245
+ describe('HTTPWalletJSON – method routing', () => {
246
+ let client: HTTPWalletJSON
247
+ let mockFetch: jest.Mock
248
+
249
+ beforeEach(() => {
250
+ mockFetch = makeFetch({})
251
+ client = new HTTPWalletJSON(undefined, 'http://localhost:3321', mockFetch as unknown as typeof fetch)
252
+ })
253
+
254
+ const expectCallName = async (method: () => Promise<unknown>, expectedPath: string) => {
255
+ await method().catch(() => { /* ignore deserialization quirks */ })
256
+ const url: string = mockFetch.mock.calls[mockFetch.mock.calls.length - 1][0]
257
+ expect(url).toContain(expectedPath)
258
+ }
259
+
260
+ it('createAction calls /createAction', async () => {
261
+ await expectCallName(
262
+ () => client.createAction({ description: 'hello world' }),
263
+ '/createAction'
264
+ )
265
+ })
266
+
267
+ it('signAction calls /signAction', async () => {
268
+ await expectCallName(
269
+ () => client.signAction({ spends: {}, reference: 'cmVm' }),
270
+ '/signAction'
271
+ )
272
+ })
273
+
274
+ it('abortAction calls /abortAction', async () => {
275
+ await expectCallName(
276
+ () => client.abortAction({ reference: 'cmVm' }),
277
+ '/abortAction'
278
+ )
279
+ })
280
+
281
+ it('listActions calls /listActions', async () => {
282
+ await expectCallName(
283
+ () => client.listActions({ labels: [] }),
284
+ '/listActions'
285
+ )
286
+ })
287
+
288
+ it('internalizeAction calls /internalizeAction', async () => {
289
+ await expectCallName(
290
+ () => client.internalizeAction({ tx: [], outputs: [], description: 'hello world' }),
291
+ '/internalizeAction'
292
+ )
293
+ })
294
+
295
+ it('listOutputs calls /listOutputs', async () => {
296
+ await expectCallName(
297
+ () => client.listOutputs({ basket: 'default' }),
298
+ '/listOutputs'
299
+ )
300
+ })
301
+
302
+ it('relinquishOutput calls /relinquishOutput', async () => {
303
+ await expectCallName(
304
+ () => client.relinquishOutput({ basket: 'default', output: 'abc.0' }),
305
+ '/relinquishOutput'
306
+ )
307
+ })
308
+
309
+ it('getPublicKey calls /getPublicKey', async () => {
310
+ await expectCallName(
311
+ () => client.getPublicKey({ identityKey: true }),
312
+ '/getPublicKey'
313
+ )
314
+ })
315
+
316
+ it('revealCounterpartyKeyLinkage calls /revealCounterpartyKeyLinkage', async () => {
317
+ await expectCallName(
318
+ () => client.revealCounterpartyKeyLinkage({ counterparty: 'aa', verifier: 'bb' }),
319
+ '/revealCounterpartyKeyLinkage'
320
+ )
321
+ })
322
+
323
+ it('revealSpecificKeyLinkage calls /revealSpecificKeyLinkage', async () => {
324
+ await expectCallName(
325
+ () => client.revealSpecificKeyLinkage({
326
+ counterparty: 'aa', verifier: 'bb',
327
+ protocolID: [0, 'proto'], keyID: 'k1',
328
+ }),
329
+ '/revealSpecificKeyLinkage'
330
+ )
331
+ })
332
+
333
+ it('encrypt calls /encrypt', async () => {
334
+ await expectCallName(
335
+ () => client.encrypt({ plaintext: [1, 2], protocolID: [0, 'proto'], keyID: 'k1' }),
336
+ '/encrypt'
337
+ )
338
+ })
339
+
340
+ it('decrypt calls /decrypt', async () => {
341
+ await expectCallName(
342
+ () => client.decrypt({ ciphertext: [1, 2], protocolID: [0, 'proto'], keyID: 'k1' }),
343
+ '/decrypt'
344
+ )
345
+ })
346
+
347
+ it('createHmac calls /createHmac', async () => {
348
+ await expectCallName(
349
+ () => client.createHmac({ data: [1], protocolID: [0, 'proto'], keyID: 'k1' }),
350
+ '/createHmac'
351
+ )
352
+ })
353
+
354
+ it('verifyHmac calls /verifyHmac', async () => {
355
+ await expectCallName(
356
+ () => client.verifyHmac({ data: [1], hmac: [2], protocolID: [0, 'proto'], keyID: 'k1' }),
357
+ '/verifyHmac'
358
+ )
359
+ })
360
+
361
+ it('createSignature calls /createSignature', async () => {
362
+ await expectCallName(
363
+ () => client.createSignature({ data: [1], protocolID: [0, 'proto'], keyID: 'k1' }),
364
+ '/createSignature'
365
+ )
366
+ })
367
+
368
+ it('verifySignature calls /verifySignature', async () => {
369
+ await expectCallName(
370
+ () => client.verifySignature({ data: [1], signature: [2], protocolID: [0, 'proto'], keyID: 'k1' }),
371
+ '/verifySignature'
372
+ )
373
+ })
374
+
375
+ it('acquireCertificate calls /acquireCertificate', async () => {
376
+ await expectCallName(
377
+ () => client.acquireCertificate({
378
+ type: 'dHlwZQ==', certifier: 'aa', acquisitionProtocol: 'issuance',
379
+ fields: {}, certifierUrl: 'https://certifier.example.com',
380
+ } as any),
381
+ '/acquireCertificate'
382
+ )
383
+ })
384
+
385
+ it('listCertificates calls /listCertificates', async () => {
386
+ await expectCallName(
387
+ () => client.listCertificates({ certifiers: [], types: [] }),
388
+ '/listCertificates'
389
+ )
390
+ })
391
+
392
+ it('proveCertificate calls /proveCertificate', async () => {
393
+ await expectCallName(
394
+ () => client.proveCertificate({
395
+ certificate: {} as any, fieldsToReveal: [], verifier: 'vv',
396
+ }),
397
+ '/proveCertificate'
398
+ )
399
+ })
400
+
401
+ it('relinquishCertificate calls /relinquishCertificate', async () => {
402
+ await expectCallName(
403
+ () => client.relinquishCertificate({ type: 'dHlwZQ==', serialNumber: 'c2Vy', certifier: 'aa' }),
404
+ '/relinquishCertificate'
405
+ )
406
+ })
407
+
408
+ it('discoverByIdentityKey calls /discoverByIdentityKey', async () => {
409
+ await expectCallName(
410
+ () => client.discoverByIdentityKey({ identityKey: 'aa' }),
411
+ '/discoverByIdentityKey'
412
+ )
413
+ })
414
+
415
+ it('discoverByAttributes calls /discoverByAttributes', async () => {
416
+ await expectCallName(
417
+ () => client.discoverByAttributes({ attributes: { name: 'Alice' } }),
418
+ '/discoverByAttributes'
419
+ )
420
+ })
421
+
422
+ it('isAuthenticated calls /isAuthenticated', async () => {
423
+ await expectCallName(
424
+ () => client.isAuthenticated({}),
425
+ '/isAuthenticated'
426
+ )
427
+ })
428
+
429
+ it('waitForAuthentication calls /waitForAuthentication', async () => {
430
+ await expectCallName(
431
+ () => client.waitForAuthentication({}),
432
+ '/waitForAuthentication'
433
+ )
434
+ })
435
+
436
+ it('getHeight calls /getHeight', async () => {
437
+ await expectCallName(
438
+ () => client.getHeight({}),
439
+ '/getHeight'
440
+ )
441
+ })
442
+
443
+ it('getHeaderForHeight calls /getHeaderForHeight', async () => {
444
+ await expectCallName(
445
+ () => client.getHeaderForHeight({ height: 1 }),
446
+ '/getHeaderForHeight'
447
+ )
448
+ })
449
+
450
+ it('getNetwork calls /getNetwork', async () => {
451
+ await expectCallName(
452
+ () => client.getNetwork({}),
453
+ '/getNetwork'
454
+ )
455
+ })
456
+
457
+ it('getVersion calls /getVersion', async () => {
458
+ await expectCallName(
459
+ () => client.getVersion({}),
460
+ '/getVersion'
461
+ )
462
+ })
463
+ })
464
+
465
+ // ---------------------------------------------------------------------------
466
+ // Response body passthrough
467
+ // ---------------------------------------------------------------------------
468
+
469
+ describe('HTTPWalletJSON – response body passthrough', () => {
470
+ it('returns the exact JSON body from a successful getVersion call', async () => {
471
+ const expected = { version: '1.0.0.0.0.0.0' }
472
+ const mockFetch = makeFetch(expected)
473
+ const client = new HTTPWalletJSON(undefined, 'http://localhost:3321', mockFetch as unknown as typeof fetch)
474
+
475
+ const result = await client.getVersion({})
476
+ expect(result).toEqual(expected)
477
+ })
478
+
479
+ it('returns the exact JSON body from a successful listActions call', async () => {
480
+ const expected = { totalActions: 2, actions: [{ txid: 'aa', status: 'completed' }] }
481
+ const mockFetch = makeFetch(expected)
482
+ const client = new HTTPWalletJSON(undefined, 'http://localhost:3321', mockFetch as unknown as typeof fetch)
483
+
484
+ const result = await client.listActions({ labels: [] })
485
+ expect(result).toEqual(expected)
486
+ })
487
+
488
+ it('returns the exact JSON body from a successful getNetwork call', async () => {
489
+ const expected = { network: 'mainnet' as const }
490
+ const mockFetch = makeFetch(expected)
491
+ const client = new HTTPWalletJSON(undefined, 'http://localhost:3321', mockFetch as unknown as typeof fetch)
492
+
493
+ const result = await client.getNetwork({})
494
+ expect(result).toEqual(expected)
495
+ })
496
+ })