@bsv/sdk 2.0.12 → 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.
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/src/auth/clients/__tests__/AuthFetch.additional.test.js +827 -0
- package/dist/cjs/src/auth/clients/__tests__/AuthFetch.additional.test.js.map +1 -0
- package/dist/cjs/src/auth/transports/__tests__/SimplifiedFetchTransport.additional.test.js +654 -0
- package/dist/cjs/src/auth/transports/__tests__/SimplifiedFetchTransport.additional.test.js.map +1 -0
- package/dist/cjs/src/transaction/MerklePath.js +132 -0
- package/dist/cjs/src/transaction/MerklePath.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/auth/clients/__tests__/AuthFetch.additional.test.js +825 -0
- package/dist/esm/src/auth/clients/__tests__/AuthFetch.additional.test.js.map +1 -0
- package/dist/esm/src/auth/transports/__tests__/SimplifiedFetchTransport.additional.test.js +619 -0
- package/dist/esm/src/auth/transports/__tests__/SimplifiedFetchTransport.additional.test.js.map +1 -0
- package/dist/esm/src/transaction/MerklePath.js +132 -0
- package/dist/esm/src/transaction/MerklePath.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/auth/clients/__tests__/AuthFetch.additional.test.d.ts +21 -0
- package/dist/types/src/auth/clients/__tests__/AuthFetch.additional.test.d.ts.map +1 -0
- package/dist/types/src/auth/transports/__tests__/SimplifiedFetchTransport.additional.test.d.ts +2 -0
- package/dist/types/src/auth/transports/__tests__/SimplifiedFetchTransport.additional.test.d.ts.map +1 -0
- package/dist/types/src/transaction/MerklePath.d.ts +27 -0
- package/dist/types/src/transaction/MerklePath.d.ts.map +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/dist/umd/bundle.js +1 -1
- package/dist/umd/bundle.js.map +1 -1
- package/docs/reference/storage.md +1 -1
- package/docs/reference/transaction.md +40 -0
- package/package.json +1 -1
- package/src/auth/clients/__tests__/AuthFetch.additional.test.ts +1131 -0
- package/src/auth/transports/__tests__/SimplifiedFetchTransport.additional.test.ts +770 -0
- package/src/compat/__tests/Mnemonic.additional.test.ts +64 -0
- package/src/identity/__tests/IdentityClient.additional.test.ts +767 -0
- package/src/kvstore/__tests/LocalKVStore.additional.test.ts +611 -0
- package/src/kvstore/__tests/kvStoreInterpreter.test.ts +327 -0
- package/src/overlay-tools/__tests/HostReputationTracker.additional.test.ts +561 -0
- package/src/overlay-tools/__tests/LookupResolver.additional.test.ts +612 -0
- package/src/overlay-tools/__tests/withDoubleSpendRetry.test.ts +278 -0
- package/src/primitives/__tests/BigNumber.additional.test.ts +79 -0
- package/src/primitives/__tests/Curve.additional.test.ts +208 -0
- package/src/primitives/__tests/ECDSA.additional.test.ts +122 -0
- package/src/primitives/__tests/Hash.additional.test.ts +59 -0
- package/src/primitives/__tests/JacobianPoint.test.ts +308 -0
- package/src/primitives/__tests/Point.additional.test.ts +503 -0
- package/src/primitives/__tests/PublicKey.additional.test.ts +383 -0
- package/src/primitives/__tests/Random.additional.test.ts +262 -0
- package/src/primitives/__tests/Signature.test.ts +333 -0
- package/src/primitives/__tests/TransactionSignature.additional.test.ts +241 -0
- package/src/registry/__tests/RegistryClient.additional.test.ts +750 -0
- package/src/remittance/__tests/BasicBRC29.additional.test.ts +657 -0
- package/src/remittance/__tests/RemittanceManager.additional.test.ts +1272 -0
- package/src/script/__tests/LockingUnlockingScript.test.ts +79 -0
- package/src/script/__tests/Script.additional.test.ts +100 -0
- package/src/script/__tests/ScriptEvaluationError.test.ts +98 -0
- package/src/script/__tests/Spend.additional.test.ts +837 -0
- package/src/script/templates/__tests/RPuzzle.test.ts +134 -0
- package/src/transaction/MerklePath.ts +155 -0
- package/src/transaction/__tests/BeefParty.additional.test.ts +22 -0
- package/src/transaction/__tests/Broadcaster.test.ts +159 -0
- package/src/transaction/__tests/MerklePath.bench.test.ts +105 -0
- package/src/transaction/__tests/MerklePath.test.ts +80 -0
- package/src/transaction/__tests/Transaction.additional.test.ts +225 -0
- package/src/transaction/broadcasters/__tests/ARC.additional.test.ts +585 -0
- package/src/transaction/broadcasters/__tests/Teranode.test.ts +349 -0
- package/src/transaction/chaintrackers/__tests/BlockHeadersService.test.ts +253 -0
- package/src/transaction/chaintrackers/__tests/DefaultChainTracker.test.ts +44 -0
- package/src/transaction/chaintrackers/__tests/WhatsOnChain.additional.test.ts +193 -0
- package/src/transaction/fee-models/__tests/SatoshisPerKilobyte.test.ts +262 -0
- package/src/transaction/http/__tests/BinaryFetchClient.test.ts +212 -0
- package/src/transaction/http/__tests/DefaultHttpClient.additional.test.ts +192 -0
- package/src/transaction/http/__tests/DefaultHttpClient.test.ts +71 -0
- package/src/wallet/__tests/ProtoWallet.additional.test.ts +134 -0
- package/src/wallet/__tests/WERR.test.ts +212 -0
- package/src/wallet/__tests/WalletClient.additional.test.ts +699 -0
- package/src/wallet/__tests/WalletClient.substrate.test.ts +759 -0
- package/src/wallet/__tests/WalletError.test.ts +290 -0
- package/src/wallet/__tests/validationHelpers.test.ts +1218 -0
- package/src/wallet/substrates/__tests/HTTPWalletJSON.test.ts +496 -0
- package/src/wallet/substrates/__tests/HTTPWalletWire.test.ts +273 -0
|
@@ -0,0 +1,699 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Additional WalletClient tests focusing on:
|
|
3
|
+
* 1. Constructor substrate selection (string aliases)
|
|
4
|
+
* 2. Parameter validation that fires BEFORE connectToSubstrate() is called
|
|
5
|
+
*
|
|
6
|
+
* None of the tests below make real network connections.
|
|
7
|
+
* The validation helpers throw WERR_INVALID_PARAMETER synchronously, so the
|
|
8
|
+
* async methods reject immediately without ever reaching the substrate.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import WalletClient from '../WalletClient'
|
|
12
|
+
import HTTPWalletJSON from '../substrates/HTTPWalletJSON'
|
|
13
|
+
import WalletWireTransceiver from '../substrates/WalletWireTransceiver'
|
|
14
|
+
import { WERR_INVALID_PARAMETER } from '../WERR_INVALID_PARAMETER'
|
|
15
|
+
import type { WalletInterface } from '../Wallet.interfaces'
|
|
16
|
+
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Helpers
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Expect `fn` to throw (or reject) with WERR_INVALID_PARAMETER and the given
|
|
23
|
+
* parameter name. Works for both sync throws and async rejections.
|
|
24
|
+
*/
|
|
25
|
+
async function expectInvalidParam(fn: () => Promise<unknown>, expectedParam: string): Promise<void> {
|
|
26
|
+
try {
|
|
27
|
+
await fn()
|
|
28
|
+
throw new Error('Expected WERR_INVALID_PARAMETER but nothing was thrown')
|
|
29
|
+
} catch (e: unknown) {
|
|
30
|
+
const err = e as WERR_INVALID_PARAMETER
|
|
31
|
+
expect(err.name).toBe('WERR_INVALID_PARAMETER')
|
|
32
|
+
expect(err.parameter).toBe(expectedParam)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// 1. Constructor – substrate string aliases
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
|
|
40
|
+
describe('WalletClient – constructor substrate aliases', () => {
|
|
41
|
+
it('stores "auto" as the substrate when given "auto"', () => {
|
|
42
|
+
const client = new WalletClient('auto', 'my.app.com')
|
|
43
|
+
expect(client.substrate).toBe('auto')
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('creates a WalletWireTransceiver for "Cicada"', () => {
|
|
47
|
+
const client = new WalletClient('Cicada', 'my.app.com')
|
|
48
|
+
expect(client.substrate).toBeInstanceOf(WalletWireTransceiver)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('creates an HTTPWalletJSON instance for "json-api"', () => {
|
|
52
|
+
const client = new WalletClient('json-api', 'my.app.com')
|
|
53
|
+
expect(client.substrate).toBeInstanceOf(HTTPWalletJSON)
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('creates an HTTPWalletJSON instance for "secure-json-api"', () => {
|
|
57
|
+
const client = new WalletClient('secure-json-api', 'my.app.com')
|
|
58
|
+
expect(client.substrate).toBeInstanceOf(HTTPWalletJSON)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it('accepts a pre-built WalletInterface object as substrate', () => {
|
|
62
|
+
const mockWallet: WalletInterface = {
|
|
63
|
+
createAction: jest.fn(),
|
|
64
|
+
signAction: jest.fn(),
|
|
65
|
+
abortAction: jest.fn(),
|
|
66
|
+
listActions: jest.fn(),
|
|
67
|
+
internalizeAction: jest.fn(),
|
|
68
|
+
listOutputs: jest.fn(),
|
|
69
|
+
relinquishOutput: jest.fn(),
|
|
70
|
+
getPublicKey: jest.fn(),
|
|
71
|
+
revealCounterpartyKeyLinkage: jest.fn(),
|
|
72
|
+
revealSpecificKeyLinkage: jest.fn(),
|
|
73
|
+
encrypt: jest.fn(),
|
|
74
|
+
decrypt: jest.fn(),
|
|
75
|
+
createHmac: jest.fn(),
|
|
76
|
+
verifyHmac: jest.fn(),
|
|
77
|
+
createSignature: jest.fn(),
|
|
78
|
+
verifySignature: jest.fn(),
|
|
79
|
+
acquireCertificate: jest.fn(),
|
|
80
|
+
listCertificates: jest.fn(),
|
|
81
|
+
proveCertificate: jest.fn(),
|
|
82
|
+
relinquishCertificate: jest.fn(),
|
|
83
|
+
discoverByIdentityKey: jest.fn(),
|
|
84
|
+
discoverByAttributes: jest.fn(),
|
|
85
|
+
isAuthenticated: jest.fn(),
|
|
86
|
+
waitForAuthentication: jest.fn(),
|
|
87
|
+
getHeight: jest.fn(),
|
|
88
|
+
getHeaderForHeight: jest.fn(),
|
|
89
|
+
getNetwork: jest.fn(),
|
|
90
|
+
getVersion: jest.fn(),
|
|
91
|
+
}
|
|
92
|
+
const client = new WalletClient(mockWallet)
|
|
93
|
+
expect(client.substrate).toBe(mockWallet)
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
it('stores the originator on the instance', () => {
|
|
97
|
+
const client = new WalletClient('auto', 'example.com')
|
|
98
|
+
expect(client.originator).toBe('example.com')
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
it('originator is undefined when not provided', () => {
|
|
102
|
+
const client = new WalletClient('auto')
|
|
103
|
+
expect(client.originator).toBeUndefined()
|
|
104
|
+
})
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
// 2. connectToSubstrate – skips when substrate is already a WalletInterface
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
|
|
111
|
+
describe('WalletClient – connectToSubstrate', () => {
|
|
112
|
+
it('does not attempt discovery when substrate is already an object', async () => {
|
|
113
|
+
const mockWallet: Partial<WalletInterface> = {
|
|
114
|
+
getVersion: jest.fn().mockResolvedValue({ version: '1.0.0.0.0.0.0' }),
|
|
115
|
+
}
|
|
116
|
+
const client = new WalletClient(mockWallet as WalletInterface)
|
|
117
|
+
// connectToSubstrate should return immediately
|
|
118
|
+
await expect(client.connectToSubstrate()).resolves.toBeUndefined()
|
|
119
|
+
// getVersion was NOT called by connectToSubstrate
|
|
120
|
+
expect(mockWallet.getVersion).not.toHaveBeenCalled()
|
|
121
|
+
})
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
// 3. createAction – validation
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
|
|
128
|
+
describe('WalletClient – createAction validation', () => {
|
|
129
|
+
let client: WalletClient
|
|
130
|
+
|
|
131
|
+
beforeEach(() => {
|
|
132
|
+
client = new WalletClient('auto', '0.WalletClient.additional.test')
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
it('throws WERR_INVALID_PARAMETER for description shorter than 5 bytes', async () => {
|
|
136
|
+
await expectInvalidParam(
|
|
137
|
+
() => client.createAction({ description: 'hi' }),
|
|
138
|
+
'description'
|
|
139
|
+
)
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
it('throws WERR_INVALID_PARAMETER for description longer than 2000 bytes', async () => {
|
|
143
|
+
await expectInvalidParam(
|
|
144
|
+
() => client.createAction({ description: 'x'.repeat(2001) }),
|
|
145
|
+
'description'
|
|
146
|
+
)
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
it('throws WERR_INVALID_PARAMETER when output has an empty lockingScript', async () => {
|
|
150
|
+
await expectInvalidParam(
|
|
151
|
+
() => client.createAction({
|
|
152
|
+
description: 'hello world',
|
|
153
|
+
outputs: [{ lockingScript: '', satoshis: 1000, outputDescription: 'my output' }],
|
|
154
|
+
}),
|
|
155
|
+
'lockingScript'
|
|
156
|
+
)
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
it('throws WERR_INVALID_PARAMETER when output lockingScript is odd-length hex', async () => {
|
|
160
|
+
await expectInvalidParam(
|
|
161
|
+
() => client.createAction({
|
|
162
|
+
description: 'hello world',
|
|
163
|
+
outputs: [{ lockingScript: 'abc', satoshis: 1000, outputDescription: 'my output' }],
|
|
164
|
+
}),
|
|
165
|
+
'lockingScript'
|
|
166
|
+
)
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
it('throws WERR_INVALID_PARAMETER when output has no outputDescription', async () => {
|
|
170
|
+
await expectInvalidParam(
|
|
171
|
+
() => client.createAction({
|
|
172
|
+
description: 'hello world',
|
|
173
|
+
outputs: [{ lockingScript: '1234', satoshis: 1000, outputDescription: '' }],
|
|
174
|
+
}),
|
|
175
|
+
'outputDescription'
|
|
176
|
+
)
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
it('throws WERR_INVALID_PARAMETER when output description is shorter than 5 bytes', async () => {
|
|
180
|
+
await expectInvalidParam(
|
|
181
|
+
() => client.createAction({
|
|
182
|
+
description: 'hello world',
|
|
183
|
+
outputs: [{ lockingScript: '1234', satoshis: 1000, outputDescription: 'hi' }],
|
|
184
|
+
}),
|
|
185
|
+
'outputDescription'
|
|
186
|
+
)
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
it('throws WERR_INVALID_PARAMETER when satoshis is negative', async () => {
|
|
190
|
+
await expectInvalidParam(
|
|
191
|
+
() => client.createAction({
|
|
192
|
+
description: 'hello world',
|
|
193
|
+
outputs: [{ lockingScript: '1234', satoshis: -1, outputDescription: 'my output' }],
|
|
194
|
+
}),
|
|
195
|
+
'satoshis'
|
|
196
|
+
)
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
it('throws WERR_INVALID_PARAMETER when satoshis is a float', async () => {
|
|
200
|
+
await expectInvalidParam(
|
|
201
|
+
() => client.createAction({
|
|
202
|
+
description: 'hello world',
|
|
203
|
+
outputs: [{ lockingScript: '1234', satoshis: 1.5, outputDescription: 'my output' }],
|
|
204
|
+
}),
|
|
205
|
+
'satoshis'
|
|
206
|
+
)
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
it('throws WERR_INVALID_PARAMETER when input has neither unlockingScript nor unlockingScriptLength', async () => {
|
|
210
|
+
await expectInvalidParam(
|
|
211
|
+
() => client.createAction({
|
|
212
|
+
description: 'hello world',
|
|
213
|
+
inputs: [{
|
|
214
|
+
outpoint: 'a'.repeat(64) + '.0',
|
|
215
|
+
inputDescription: 'my input',
|
|
216
|
+
}],
|
|
217
|
+
}),
|
|
218
|
+
'unlockingScript, unlockingScriptLength'
|
|
219
|
+
)
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
it('throws WERR_INVALID_PARAMETER when input unlockingScript is odd-length', async () => {
|
|
223
|
+
await expectInvalidParam(
|
|
224
|
+
() => client.createAction({
|
|
225
|
+
description: 'hello world',
|
|
226
|
+
inputs: [{
|
|
227
|
+
outpoint: 'a'.repeat(64) + '.0',
|
|
228
|
+
inputDescription: 'my input',
|
|
229
|
+
unlockingScript: 'abc',
|
|
230
|
+
}],
|
|
231
|
+
}),
|
|
232
|
+
'unlockingScript'
|
|
233
|
+
)
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
it('throws WERR_INVALID_PARAMETER when input inputDescription is too short', async () => {
|
|
237
|
+
await expectInvalidParam(
|
|
238
|
+
() => client.createAction({
|
|
239
|
+
description: 'hello world',
|
|
240
|
+
inputs: [{
|
|
241
|
+
outpoint: 'a'.repeat(64) + '.0',
|
|
242
|
+
inputDescription: 'hi',
|
|
243
|
+
unlockingScriptLength: 10,
|
|
244
|
+
}],
|
|
245
|
+
}),
|
|
246
|
+
'inputDescription'
|
|
247
|
+
)
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
it('throws WERR_INVALID_PARAMETER when label is an empty string', async () => {
|
|
251
|
+
await expectInvalidParam(
|
|
252
|
+
() => client.createAction({
|
|
253
|
+
description: 'hello world',
|
|
254
|
+
labels: [''],
|
|
255
|
+
}),
|
|
256
|
+
'label'
|
|
257
|
+
)
|
|
258
|
+
})
|
|
259
|
+
})
|
|
260
|
+
|
|
261
|
+
// ---------------------------------------------------------------------------
|
|
262
|
+
// 4. signAction – validation (mostly structural, no network needed)
|
|
263
|
+
// ---------------------------------------------------------------------------
|
|
264
|
+
|
|
265
|
+
describe('WalletClient – signAction validation', () => {
|
|
266
|
+
let client: WalletClient
|
|
267
|
+
|
|
268
|
+
beforeEach(() => {
|
|
269
|
+
client = new WalletClient('auto', '0.WalletClient.additional.test')
|
|
270
|
+
})
|
|
271
|
+
|
|
272
|
+
it('does NOT throw for a minimal valid signAction call structure (gets past validation)', async () => {
|
|
273
|
+
// signAction validation is very permissive – it just normalises options.
|
|
274
|
+
// Any rejection here would be a network/substrate error, not validation.
|
|
275
|
+
const promise = client.signAction({ spends: {}, reference: 'cmVm' })
|
|
276
|
+
// We expect it to eventually fail due to no substrate, NOT due to validation.
|
|
277
|
+
await expect(promise).rejects.not.toMatchObject({ name: 'WERR_INVALID_PARAMETER' })
|
|
278
|
+
})
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
// ---------------------------------------------------------------------------
|
|
282
|
+
// 5. abortAction – validation
|
|
283
|
+
// ---------------------------------------------------------------------------
|
|
284
|
+
|
|
285
|
+
describe('WalletClient – abortAction validation', () => {
|
|
286
|
+
let client: WalletClient
|
|
287
|
+
|
|
288
|
+
beforeEach(() => {
|
|
289
|
+
client = new WalletClient('auto', '0.WalletClient.additional.test')
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
it('throws WERR_INVALID_PARAMETER when reference is empty', async () => {
|
|
293
|
+
await expectInvalidParam(
|
|
294
|
+
() => client.abortAction({ reference: '' }),
|
|
295
|
+
'reference'
|
|
296
|
+
)
|
|
297
|
+
})
|
|
298
|
+
|
|
299
|
+
it('throws WERR_INVALID_PARAMETER when reference contains invalid base64 characters', async () => {
|
|
300
|
+
await expectInvalidParam(
|
|
301
|
+
() => client.abortAction({ reference: '!!!not-base64!!!' }),
|
|
302
|
+
'reference'
|
|
303
|
+
)
|
|
304
|
+
})
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
// ---------------------------------------------------------------------------
|
|
308
|
+
// 6. listActions – validation
|
|
309
|
+
// ---------------------------------------------------------------------------
|
|
310
|
+
|
|
311
|
+
describe('WalletClient – listActions validation', () => {
|
|
312
|
+
let client: WalletClient
|
|
313
|
+
|
|
314
|
+
beforeEach(() => {
|
|
315
|
+
client = new WalletClient('auto', '0.WalletClient.additional.test')
|
|
316
|
+
})
|
|
317
|
+
|
|
318
|
+
it('throws WERR_INVALID_PARAMETER for invalid labelQueryMode', async () => {
|
|
319
|
+
await expectInvalidParam(
|
|
320
|
+
() => client.listActions({ labels: [], labelQueryMode: 'invalid' as any }),
|
|
321
|
+
'labelQueryMode'
|
|
322
|
+
)
|
|
323
|
+
})
|
|
324
|
+
|
|
325
|
+
it('throws WERR_INVALID_PARAMETER when limit exceeds 10000', async () => {
|
|
326
|
+
await expectInvalidParam(
|
|
327
|
+
() => client.listActions({ labels: [], limit: 10001 }),
|
|
328
|
+
'limit'
|
|
329
|
+
)
|
|
330
|
+
})
|
|
331
|
+
|
|
332
|
+
it('throws WERR_INVALID_PARAMETER when limit is zero', async () => {
|
|
333
|
+
await expectInvalidParam(
|
|
334
|
+
() => client.listActions({ labels: [], limit: 0 }),
|
|
335
|
+
'limit'
|
|
336
|
+
)
|
|
337
|
+
})
|
|
338
|
+
|
|
339
|
+
it('throws WERR_INVALID_PARAMETER when limit is a float', async () => {
|
|
340
|
+
await expectInvalidParam(
|
|
341
|
+
() => client.listActions({ labels: [], limit: 1.5 }),
|
|
342
|
+
'limit'
|
|
343
|
+
)
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
it('throws WERR_INVALID_PARAMETER when offset is negative', async () => {
|
|
347
|
+
await expectInvalidParam(
|
|
348
|
+
() => client.listActions({ labels: [], offset: -1 }),
|
|
349
|
+
'offset'
|
|
350
|
+
)
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
it('throws WERR_INVALID_PARAMETER when a label is empty', async () => {
|
|
354
|
+
await expectInvalidParam(
|
|
355
|
+
() => client.listActions({ labels: [''] }),
|
|
356
|
+
'label'
|
|
357
|
+
)
|
|
358
|
+
})
|
|
359
|
+
|
|
360
|
+
it('throws WERR_INVALID_PARAMETER when a label is too long (>300 bytes)', async () => {
|
|
361
|
+
await expectInvalidParam(
|
|
362
|
+
() => client.listActions({ labels: ['x'.repeat(301)] }),
|
|
363
|
+
'label'
|
|
364
|
+
)
|
|
365
|
+
})
|
|
366
|
+
})
|
|
367
|
+
|
|
368
|
+
// ---------------------------------------------------------------------------
|
|
369
|
+
// 7. listOutputs – validation
|
|
370
|
+
// ---------------------------------------------------------------------------
|
|
371
|
+
|
|
372
|
+
describe('WalletClient – listOutputs validation', () => {
|
|
373
|
+
let client: WalletClient
|
|
374
|
+
|
|
375
|
+
beforeEach(() => {
|
|
376
|
+
client = new WalletClient('auto', '0.WalletClient.additional.test')
|
|
377
|
+
})
|
|
378
|
+
|
|
379
|
+
it('throws WERR_INVALID_PARAMETER when basket is empty', async () => {
|
|
380
|
+
await expectInvalidParam(
|
|
381
|
+
() => client.listOutputs({ basket: '' }),
|
|
382
|
+
'basket'
|
|
383
|
+
)
|
|
384
|
+
})
|
|
385
|
+
|
|
386
|
+
it('throws WERR_INVALID_PARAMETER for invalid tagQueryMode', async () => {
|
|
387
|
+
await expectInvalidParam(
|
|
388
|
+
() => client.listOutputs({ basket: 'default', tagQueryMode: 'none' as any }),
|
|
389
|
+
'tagQueryMode'
|
|
390
|
+
)
|
|
391
|
+
})
|
|
392
|
+
|
|
393
|
+
it('throws WERR_INVALID_PARAMETER when limit exceeds 10000', async () => {
|
|
394
|
+
await expectInvalidParam(
|
|
395
|
+
() => client.listOutputs({ basket: 'default', limit: 10001 }),
|
|
396
|
+
'limit'
|
|
397
|
+
)
|
|
398
|
+
})
|
|
399
|
+
})
|
|
400
|
+
|
|
401
|
+
// ---------------------------------------------------------------------------
|
|
402
|
+
// 8. relinquishOutput – validation
|
|
403
|
+
// ---------------------------------------------------------------------------
|
|
404
|
+
|
|
405
|
+
describe('WalletClient – relinquishOutput validation', () => {
|
|
406
|
+
let client: WalletClient
|
|
407
|
+
|
|
408
|
+
beforeEach(() => {
|
|
409
|
+
client = new WalletClient('auto', '0.WalletClient.additional.test')
|
|
410
|
+
})
|
|
411
|
+
|
|
412
|
+
it('throws WERR_INVALID_PARAMETER when basket is empty', async () => {
|
|
413
|
+
await expectInvalidParam(
|
|
414
|
+
() => client.relinquishOutput({ basket: '', output: 'a'.repeat(64) + '.0' }),
|
|
415
|
+
'basket'
|
|
416
|
+
)
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
it('throws WERR_INVALID_PARAMETER when output is not a valid outpoint', async () => {
|
|
420
|
+
await expectInvalidParam(
|
|
421
|
+
() => client.relinquishOutput({ basket: 'default', output: 'not-an-outpoint' }),
|
|
422
|
+
'output'
|
|
423
|
+
)
|
|
424
|
+
})
|
|
425
|
+
})
|
|
426
|
+
|
|
427
|
+
// ---------------------------------------------------------------------------
|
|
428
|
+
// 9. acquireCertificate – validation
|
|
429
|
+
// ---------------------------------------------------------------------------
|
|
430
|
+
|
|
431
|
+
describe('WalletClient – acquireCertificate validation', () => {
|
|
432
|
+
let client: WalletClient
|
|
433
|
+
|
|
434
|
+
beforeEach(() => {
|
|
435
|
+
client = new WalletClient('auto', '0.WalletClient.additional.test')
|
|
436
|
+
})
|
|
437
|
+
|
|
438
|
+
it('throws WERR_INVALID_PARAMETER for unrecognised acquisitionProtocol', async () => {
|
|
439
|
+
await expectInvalidParam(
|
|
440
|
+
() => client.acquireCertificate({
|
|
441
|
+
acquisitionProtocol: 'unknown' as any,
|
|
442
|
+
type: 'dHlwZQ==',
|
|
443
|
+
certifier: 'aa',
|
|
444
|
+
fields: {},
|
|
445
|
+
}),
|
|
446
|
+
'acquisitionProtocol'
|
|
447
|
+
)
|
|
448
|
+
})
|
|
449
|
+
|
|
450
|
+
it('throws WERR_INVALID_PARAMETER for direct acquisition missing serialNumber', async () => {
|
|
451
|
+
await expectInvalidParam(
|
|
452
|
+
() => client.acquireCertificate({
|
|
453
|
+
acquisitionProtocol: 'direct',
|
|
454
|
+
type: 'dHlwZQ==',
|
|
455
|
+
certifier: 'aabb',
|
|
456
|
+
fields: {},
|
|
457
|
+
// missing serialNumber, signature, revocationOutpoint, keyringRevealer, keyringForSubject
|
|
458
|
+
} as any),
|
|
459
|
+
'serialNumber'
|
|
460
|
+
)
|
|
461
|
+
})
|
|
462
|
+
|
|
463
|
+
it('throws WERR_INVALID_PARAMETER for issuance acquisition missing certifierUrl', async () => {
|
|
464
|
+
await expectInvalidParam(
|
|
465
|
+
() => client.acquireCertificate({
|
|
466
|
+
acquisitionProtocol: 'issuance',
|
|
467
|
+
type: 'dHlwZQ==',
|
|
468
|
+
certifier: 'aabb',
|
|
469
|
+
fields: {},
|
|
470
|
+
// certifierUrl deliberately omitted
|
|
471
|
+
} as any),
|
|
472
|
+
'certifierUrl'
|
|
473
|
+
)
|
|
474
|
+
})
|
|
475
|
+
|
|
476
|
+
it('throws WERR_INVALID_PARAMETER for issuance with serialNumber (not allowed)', async () => {
|
|
477
|
+
await expectInvalidParam(
|
|
478
|
+
() => client.acquireCertificate({
|
|
479
|
+
acquisitionProtocol: 'issuance',
|
|
480
|
+
type: 'dHlwZQ==',
|
|
481
|
+
certifier: 'aabb',
|
|
482
|
+
certifierUrl: 'https://certifier.example.com',
|
|
483
|
+
fields: {},
|
|
484
|
+
serialNumber: 'c2VyaWFs',
|
|
485
|
+
}),
|
|
486
|
+
'serialNumber'
|
|
487
|
+
)
|
|
488
|
+
})
|
|
489
|
+
})
|
|
490
|
+
|
|
491
|
+
// ---------------------------------------------------------------------------
|
|
492
|
+
// 10. listCertificates – validation
|
|
493
|
+
// ---------------------------------------------------------------------------
|
|
494
|
+
|
|
495
|
+
describe('WalletClient – listCertificates validation', () => {
|
|
496
|
+
let client: WalletClient
|
|
497
|
+
|
|
498
|
+
beforeEach(() => {
|
|
499
|
+
client = new WalletClient('auto', '0.WalletClient.additional.test')
|
|
500
|
+
})
|
|
501
|
+
|
|
502
|
+
it('throws WERR_INVALID_PARAMETER when limit exceeds 10000', async () => {
|
|
503
|
+
await expectInvalidParam(
|
|
504
|
+
() => client.listCertificates({ certifiers: [], types: [], limit: 99999 }),
|
|
505
|
+
'limit'
|
|
506
|
+
)
|
|
507
|
+
})
|
|
508
|
+
|
|
509
|
+
it('throws WERR_INVALID_PARAMETER when limit is zero', async () => {
|
|
510
|
+
await expectInvalidParam(
|
|
511
|
+
() => client.listCertificates({ certifiers: [], types: [], limit: 0 }),
|
|
512
|
+
'limit'
|
|
513
|
+
)
|
|
514
|
+
})
|
|
515
|
+
|
|
516
|
+
it('throws WERR_INVALID_PARAMETER when offset is negative', async () => {
|
|
517
|
+
await expectInvalidParam(
|
|
518
|
+
() => client.listCertificates({ certifiers: [], types: [], offset: -1 }),
|
|
519
|
+
'offset'
|
|
520
|
+
)
|
|
521
|
+
})
|
|
522
|
+
})
|
|
523
|
+
|
|
524
|
+
// ---------------------------------------------------------------------------
|
|
525
|
+
// 11. relinquishCertificate – validation
|
|
526
|
+
// ---------------------------------------------------------------------------
|
|
527
|
+
|
|
528
|
+
describe('WalletClient – relinquishCertificate validation', () => {
|
|
529
|
+
let client: WalletClient
|
|
530
|
+
|
|
531
|
+
beforeEach(() => {
|
|
532
|
+
client = new WalletClient('auto', '0.WalletClient.additional.test')
|
|
533
|
+
})
|
|
534
|
+
|
|
535
|
+
it('throws WERR_INVALID_PARAMETER when type is empty', async () => {
|
|
536
|
+
await expectInvalidParam(
|
|
537
|
+
() => client.relinquishCertificate({ type: '', serialNumber: 'c2Vy', certifier: 'aabb' }),
|
|
538
|
+
'type'
|
|
539
|
+
)
|
|
540
|
+
})
|
|
541
|
+
|
|
542
|
+
it('throws WERR_INVALID_PARAMETER when type is not valid base64', async () => {
|
|
543
|
+
await expectInvalidParam(
|
|
544
|
+
() => client.relinquishCertificate({ type: '!!!', serialNumber: 'c2Vy', certifier: 'aabb' }),
|
|
545
|
+
'type'
|
|
546
|
+
)
|
|
547
|
+
})
|
|
548
|
+
|
|
549
|
+
it('throws WERR_INVALID_PARAMETER when serialNumber is empty', async () => {
|
|
550
|
+
await expectInvalidParam(
|
|
551
|
+
() => client.relinquishCertificate({ type: 'dHlwZQ==', serialNumber: '', certifier: 'aabb' }),
|
|
552
|
+
'serialNumber'
|
|
553
|
+
)
|
|
554
|
+
})
|
|
555
|
+
|
|
556
|
+
it('throws WERR_INVALID_PARAMETER when certifier is odd-length hex', async () => {
|
|
557
|
+
await expectInvalidParam(
|
|
558
|
+
() => client.relinquishCertificate({ type: 'dHlwZQ==', serialNumber: 'c2Vy', certifier: 'aab' }),
|
|
559
|
+
'certifier'
|
|
560
|
+
)
|
|
561
|
+
})
|
|
562
|
+
})
|
|
563
|
+
|
|
564
|
+
// ---------------------------------------------------------------------------
|
|
565
|
+
// 12. discoverByIdentityKey – validation
|
|
566
|
+
// ---------------------------------------------------------------------------
|
|
567
|
+
|
|
568
|
+
describe('WalletClient – discoverByIdentityKey validation', () => {
|
|
569
|
+
let client: WalletClient
|
|
570
|
+
|
|
571
|
+
beforeEach(() => {
|
|
572
|
+
client = new WalletClient('auto', '0.WalletClient.additional.test')
|
|
573
|
+
})
|
|
574
|
+
|
|
575
|
+
it('throws WERR_INVALID_PARAMETER when identityKey is not 66 hex chars', async () => {
|
|
576
|
+
await expectInvalidParam(
|
|
577
|
+
() => client.discoverByIdentityKey({ identityKey: 'aabb' }),
|
|
578
|
+
'identityKey'
|
|
579
|
+
)
|
|
580
|
+
})
|
|
581
|
+
|
|
582
|
+
it('throws WERR_INVALID_PARAMETER when identityKey is empty', async () => {
|
|
583
|
+
await expectInvalidParam(
|
|
584
|
+
() => client.discoverByIdentityKey({ identityKey: '' }),
|
|
585
|
+
'identityKey'
|
|
586
|
+
)
|
|
587
|
+
})
|
|
588
|
+
|
|
589
|
+
it('throws WERR_INVALID_PARAMETER when limit exceeds 10000', async () => {
|
|
590
|
+
await expectInvalidParam(
|
|
591
|
+
() => client.discoverByIdentityKey({ identityKey: 'aa'.repeat(33), limit: 10001 }),
|
|
592
|
+
'limit'
|
|
593
|
+
)
|
|
594
|
+
})
|
|
595
|
+
})
|
|
596
|
+
|
|
597
|
+
// ---------------------------------------------------------------------------
|
|
598
|
+
// 13. discoverByAttributes – validation
|
|
599
|
+
// ---------------------------------------------------------------------------
|
|
600
|
+
|
|
601
|
+
describe('WalletClient – discoverByAttributes validation', () => {
|
|
602
|
+
let client: WalletClient
|
|
603
|
+
|
|
604
|
+
beforeEach(() => {
|
|
605
|
+
client = new WalletClient('auto', '0.WalletClient.additional.test')
|
|
606
|
+
})
|
|
607
|
+
|
|
608
|
+
it('throws WERR_INVALID_PARAMETER when limit is zero', async () => {
|
|
609
|
+
await expectInvalidParam(
|
|
610
|
+
() => client.discoverByAttributes({ attributes: {}, limit: 0 }),
|
|
611
|
+
'limit'
|
|
612
|
+
)
|
|
613
|
+
})
|
|
614
|
+
|
|
615
|
+
it('throws WERR_INVALID_PARAMETER when limit exceeds 10000', async () => {
|
|
616
|
+
await expectInvalidParam(
|
|
617
|
+
() => client.discoverByAttributes({ attributes: {}, limit: 20000 }),
|
|
618
|
+
'limit'
|
|
619
|
+
)
|
|
620
|
+
})
|
|
621
|
+
})
|
|
622
|
+
|
|
623
|
+
// ---------------------------------------------------------------------------
|
|
624
|
+
// 14. proveCertificate – validation
|
|
625
|
+
// ---------------------------------------------------------------------------
|
|
626
|
+
|
|
627
|
+
describe('WalletClient – proveCertificate validation', () => {
|
|
628
|
+
let client: WalletClient
|
|
629
|
+
|
|
630
|
+
beforeEach(() => {
|
|
631
|
+
client = new WalletClient('auto', '0.WalletClient.additional.test')
|
|
632
|
+
})
|
|
633
|
+
|
|
634
|
+
it('throws WERR_INVALID_PARAMETER when privileged is true but privilegedReason is missing', async () => {
|
|
635
|
+
await expectInvalidParam(
|
|
636
|
+
() => client.proveCertificate({
|
|
637
|
+
certificate: {} as any,
|
|
638
|
+
fieldsToReveal: [],
|
|
639
|
+
verifier: 'aa'.repeat(33),
|
|
640
|
+
privileged: true,
|
|
641
|
+
// privilegedReason intentionally omitted
|
|
642
|
+
}),
|
|
643
|
+
'privilegedReason'
|
|
644
|
+
)
|
|
645
|
+
})
|
|
646
|
+
|
|
647
|
+
it('throws WERR_INVALID_PARAMETER when verifier is not valid hex', async () => {
|
|
648
|
+
await expectInvalidParam(
|
|
649
|
+
() => client.proveCertificate({
|
|
650
|
+
certificate: {} as any,
|
|
651
|
+
fieldsToReveal: [],
|
|
652
|
+
verifier: 'not-hex!',
|
|
653
|
+
}),
|
|
654
|
+
'verifier'
|
|
655
|
+
)
|
|
656
|
+
})
|
|
657
|
+
})
|
|
658
|
+
|
|
659
|
+
// ---------------------------------------------------------------------------
|
|
660
|
+
// 15. WERR_INVALID_PARAMETER error class contract
|
|
661
|
+
// ---------------------------------------------------------------------------
|
|
662
|
+
|
|
663
|
+
describe('WERR_INVALID_PARAMETER – class contract', () => {
|
|
664
|
+
it('sets name to WERR_INVALID_PARAMETER', () => {
|
|
665
|
+
const err = new WERR_INVALID_PARAMETER('foo')
|
|
666
|
+
expect(err.name).toBe('WERR_INVALID_PARAMETER')
|
|
667
|
+
})
|
|
668
|
+
|
|
669
|
+
it('sets code to 6', () => {
|
|
670
|
+
const err = new WERR_INVALID_PARAMETER('foo')
|
|
671
|
+
expect(err.code).toBe(6)
|
|
672
|
+
})
|
|
673
|
+
|
|
674
|
+
it('sets isError to true', () => {
|
|
675
|
+
const err = new WERR_INVALID_PARAMETER('foo')
|
|
676
|
+
expect(err.isError).toBe(true)
|
|
677
|
+
})
|
|
678
|
+
|
|
679
|
+
it('stores the parameter name', () => {
|
|
680
|
+
const err = new WERR_INVALID_PARAMETER('myParam')
|
|
681
|
+
expect(err.parameter).toBe('myParam')
|
|
682
|
+
})
|
|
683
|
+
|
|
684
|
+
it('uses "valid." as the default mustBe message', () => {
|
|
685
|
+
const err = new WERR_INVALID_PARAMETER('myParam')
|
|
686
|
+
expect(err.message).toContain('myParam')
|
|
687
|
+
expect(err.message).toContain('valid.')
|
|
688
|
+
})
|
|
689
|
+
|
|
690
|
+
it('includes the mustBe string in message when provided', () => {
|
|
691
|
+
const err = new WERR_INVALID_PARAMETER('myParam', 'a positive integer')
|
|
692
|
+
expect(err.message).toContain('a positive integer')
|
|
693
|
+
})
|
|
694
|
+
|
|
695
|
+
it('is an instance of Error', () => {
|
|
696
|
+
const err = new WERR_INVALID_PARAMETER('x')
|
|
697
|
+
expect(err).toBeInstanceOf(Error)
|
|
698
|
+
})
|
|
699
|
+
})
|