@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,273 @@
|
|
|
1
|
+
import HTTPWalletWire from '../HTTPWalletWire'
|
|
2
|
+
import WalletWireCalls from '../WalletWireCalls'
|
|
3
|
+
import * as Utils from '../../../primitives/utils'
|
|
4
|
+
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// Helpers
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Build a valid binary message frame for a given call name with an optional
|
|
11
|
+
* originator string and an arbitrary payload.
|
|
12
|
+
*
|
|
13
|
+
* Frame layout (mirrors WalletWireTransceiver.transmit):
|
|
14
|
+
* [callCode: uint8][originatorLength: uint8][originator: utf8 bytes][payload…]
|
|
15
|
+
*/
|
|
16
|
+
function buildFrame(
|
|
17
|
+
callName: keyof typeof WalletWireCalls,
|
|
18
|
+
originator = '',
|
|
19
|
+
payload: number[] = []
|
|
20
|
+
): number[] {
|
|
21
|
+
const callCode = WalletWireCalls[callName]
|
|
22
|
+
const originatorBytes = Utils.toArray(originator, 'utf8')
|
|
23
|
+
return [callCode, originatorBytes.length, ...originatorBytes, ...payload]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Resolve an ArrayBuffer from an array of byte values. */
|
|
27
|
+
function toArrayBuffer(bytes: number[]): ArrayBuffer {
|
|
28
|
+
return new Uint8Array(bytes).buffer
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Replace the global `fetch` with a jest mock that returns the given bytes.
|
|
33
|
+
* HTTPWalletWire.transmitToWallet calls the *global* fetch, not this.httpClient.
|
|
34
|
+
*/
|
|
35
|
+
function mockGlobalFetch(responseBytes: number[]): jest.Mock {
|
|
36
|
+
const mock = jest.fn().mockResolvedValue({
|
|
37
|
+
arrayBuffer: () => Promise.resolve(toArrayBuffer(responseBytes)),
|
|
38
|
+
} as unknown as Response)
|
|
39
|
+
global.fetch = mock
|
|
40
|
+
return mock
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function mockGlobalFetchWithNetworkError(message = 'Network error'): jest.Mock {
|
|
44
|
+
const mock = jest.fn().mockRejectedValue(new Error(message))
|
|
45
|
+
global.fetch = mock
|
|
46
|
+
return mock
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Preserve the real fetch so we can restore it between tests.
|
|
50
|
+
const realFetch = global.fetch
|
|
51
|
+
|
|
52
|
+
afterEach(() => {
|
|
53
|
+
global.fetch = realFetch
|
|
54
|
+
jest.restoreAllMocks()
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
// Constructor
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
|
|
61
|
+
describe('HTTPWalletWire – constructor', () => {
|
|
62
|
+
it('stores the baseUrl', () => {
|
|
63
|
+
const wire = new HTTPWalletWire('example.com', 'http://my-server:9000')
|
|
64
|
+
expect(wire.baseUrl).toBe('http://my-server:9000')
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
it('uses http://localhost:3301 as the default baseUrl', () => {
|
|
68
|
+
const wire = new HTTPWalletWire('example.com')
|
|
69
|
+
expect(wire.baseUrl).toBe('http://localhost:3301')
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
it('stores the originator', () => {
|
|
73
|
+
const wire = new HTTPWalletWire('wallet.example.com')
|
|
74
|
+
expect(wire.originator).toBe('wallet.example.com')
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
it('accepts undefined originator', () => {
|
|
78
|
+
const wire = new HTTPWalletWire(undefined)
|
|
79
|
+
expect(wire.originator).toBeUndefined()
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
it('stores a custom httpClient (even though transmitToWallet uses global fetch)', () => {
|
|
83
|
+
const mockFetch = jest.fn()
|
|
84
|
+
const wire = new HTTPWalletWire(
|
|
85
|
+
'example.com',
|
|
86
|
+
'http://localhost:3301',
|
|
87
|
+
mockFetch as unknown as typeof fetch
|
|
88
|
+
)
|
|
89
|
+
expect(wire.httpClient).toBe(mockFetch)
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
// transmitToWallet – invalid call code
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
|
|
97
|
+
describe('HTTPWalletWire – transmitToWallet invalid call code', () => {
|
|
98
|
+
it('throws on call code 0 (not in enum)', async () => {
|
|
99
|
+
const wire = new HTTPWalletWire(undefined, 'http://localhost:3301')
|
|
100
|
+
const invalidMessage = [0] // 0 maps to undefined in the enum
|
|
101
|
+
await expect(wire.transmitToWallet(invalidMessage)).rejects.toThrow('Invalid call code')
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
it('throws on call code 255 (out of range)', async () => {
|
|
105
|
+
const wire = new HTTPWalletWire(undefined, 'http://localhost:3301')
|
|
106
|
+
const invalidMessage = [255]
|
|
107
|
+
await expect(wire.transmitToWallet(invalidMessage)).rejects.toThrow('Invalid call code')
|
|
108
|
+
})
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
// transmitToWallet – request building
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
|
|
115
|
+
describe('HTTPWalletWire – transmitToWallet request', () => {
|
|
116
|
+
it('calls global fetch with the correct URL derived from the call name', async () => {
|
|
117
|
+
const mockFetch = mockGlobalFetch([1, 2, 3])
|
|
118
|
+
const wire = new HTTPWalletWire(undefined, 'http://localhost:3301')
|
|
119
|
+
|
|
120
|
+
await wire.transmitToWallet(buildFrame('getVersion'))
|
|
121
|
+
|
|
122
|
+
expect(mockFetch).toHaveBeenCalledTimes(1)
|
|
123
|
+
const [url] = mockFetch.mock.calls[0] as [string, RequestInit]
|
|
124
|
+
expect(url).toBe('http://localhost:3301/getVersion')
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
it('uses POST method', async () => {
|
|
128
|
+
const mockFetch = mockGlobalFetch([])
|
|
129
|
+
const wire = new HTTPWalletWire(undefined, 'http://localhost:3301')
|
|
130
|
+
|
|
131
|
+
await wire.transmitToWallet(buildFrame('getVersion'))
|
|
132
|
+
|
|
133
|
+
const [, init] = mockFetch.mock.calls[0] as [string, RequestInit]
|
|
134
|
+
expect(init.method).toBe('POST')
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
it('sets Content-Type to application/octet-stream', async () => {
|
|
138
|
+
const mockFetch = mockGlobalFetch([])
|
|
139
|
+
const wire = new HTTPWalletWire(undefined, 'http://localhost:3301')
|
|
140
|
+
|
|
141
|
+
await wire.transmitToWallet(buildFrame('getVersion'))
|
|
142
|
+
|
|
143
|
+
const [, init] = mockFetch.mock.calls[0] as [string, RequestInit]
|
|
144
|
+
const headers = init.headers as Record<string, string>
|
|
145
|
+
expect(headers['Content-Type']).toBe('application/octet-stream')
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it('sets Origin header to the originator encoded in the message frame', async () => {
|
|
149
|
+
const mockFetch = mockGlobalFetch([])
|
|
150
|
+
const wire = new HTTPWalletWire(undefined, 'http://localhost:3301')
|
|
151
|
+
|
|
152
|
+
await wire.transmitToWallet(buildFrame('getVersion', 'myapp.example.com'))
|
|
153
|
+
|
|
154
|
+
const [, init] = mockFetch.mock.calls[0] as [string, RequestInit]
|
|
155
|
+
const headers = init.headers as Record<string, string>
|
|
156
|
+
expect(headers['Origin']).toBe('myapp.example.com')
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
it('sets Origin to empty string when frame originator is absent', async () => {
|
|
160
|
+
const mockFetch = mockGlobalFetch([])
|
|
161
|
+
const wire = new HTTPWalletWire(undefined, 'http://localhost:3301')
|
|
162
|
+
|
|
163
|
+
await wire.transmitToWallet(buildFrame('getVersion', ''))
|
|
164
|
+
|
|
165
|
+
const [, init] = mockFetch.mock.calls[0] as [string, RequestInit]
|
|
166
|
+
const headers = init.headers as Record<string, string>
|
|
167
|
+
expect(headers['Origin']).toBe('')
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
it('sends a Uint8Array body containing the payload bytes', async () => {
|
|
171
|
+
const payload = [0xde, 0xad, 0xbe, 0xef]
|
|
172
|
+
const mockFetch = mockGlobalFetch([])
|
|
173
|
+
const wire = new HTTPWalletWire(undefined, 'http://localhost:3301')
|
|
174
|
+
|
|
175
|
+
await wire.transmitToWallet(buildFrame('getVersion', '', payload))
|
|
176
|
+
|
|
177
|
+
const [, init] = mockFetch.mock.calls[0] as [string, RequestInit]
|
|
178
|
+
expect(init.body).toBeInstanceOf(Uint8Array)
|
|
179
|
+
const bodyBytes = Array.from(init.body as Uint8Array)
|
|
180
|
+
expect(bodyBytes).toEqual(payload)
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
it('sends an empty Uint8Array body when there is no payload', async () => {
|
|
184
|
+
const mockFetch = mockGlobalFetch([])
|
|
185
|
+
const wire = new HTTPWalletWire(undefined, 'http://localhost:3301')
|
|
186
|
+
|
|
187
|
+
await wire.transmitToWallet(buildFrame('getVersion', ''))
|
|
188
|
+
|
|
189
|
+
const [, init] = mockFetch.mock.calls[0] as [string, RequestInit]
|
|
190
|
+
expect(Array.from(init.body as Uint8Array)).toEqual([])
|
|
191
|
+
})
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
// ---------------------------------------------------------------------------
|
|
195
|
+
// transmitToWallet – response handling
|
|
196
|
+
// ---------------------------------------------------------------------------
|
|
197
|
+
|
|
198
|
+
describe('HTTPWalletWire – transmitToWallet response', () => {
|
|
199
|
+
it('returns the response body as a number array', async () => {
|
|
200
|
+
const responseBytes = [0xca, 0xfe, 0xba, 0xbe]
|
|
201
|
+
mockGlobalFetch(responseBytes)
|
|
202
|
+
const wire = new HTTPWalletWire(undefined, 'http://localhost:3301')
|
|
203
|
+
|
|
204
|
+
const result = await wire.transmitToWallet(buildFrame('getVersion'))
|
|
205
|
+
expect(result).toEqual(responseBytes)
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
it('returns an empty array when response body is empty', async () => {
|
|
209
|
+
mockGlobalFetch([])
|
|
210
|
+
const wire = new HTTPWalletWire(undefined, 'http://localhost:3301')
|
|
211
|
+
|
|
212
|
+
const result = await wire.transmitToWallet(buildFrame('getVersion'))
|
|
213
|
+
expect(result).toEqual([])
|
|
214
|
+
})
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
// ---------------------------------------------------------------------------
|
|
218
|
+
// transmitToWallet – network errors
|
|
219
|
+
// ---------------------------------------------------------------------------
|
|
220
|
+
|
|
221
|
+
describe('HTTPWalletWire – network errors', () => {
|
|
222
|
+
it('propagates a fetch rejection', async () => {
|
|
223
|
+
mockGlobalFetchWithNetworkError('Failed to connect')
|
|
224
|
+
const wire = new HTTPWalletWire(undefined, 'http://localhost:3301')
|
|
225
|
+
|
|
226
|
+
await expect(wire.transmitToWallet(buildFrame('getVersion'))).rejects.toThrow('Failed to connect')
|
|
227
|
+
})
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
// ---------------------------------------------------------------------------
|
|
231
|
+
// transmitToWallet – call-name routing smoke tests
|
|
232
|
+
// ---------------------------------------------------------------------------
|
|
233
|
+
|
|
234
|
+
describe('HTTPWalletWire – call-name routing', () => {
|
|
235
|
+
const callsToTest: Array<keyof typeof WalletWireCalls> = [
|
|
236
|
+
'createAction',
|
|
237
|
+
'signAction',
|
|
238
|
+
'abortAction',
|
|
239
|
+
'listActions',
|
|
240
|
+
'internalizeAction',
|
|
241
|
+
'listOutputs',
|
|
242
|
+
'relinquishOutput',
|
|
243
|
+
'getPublicKey',
|
|
244
|
+
'encrypt',
|
|
245
|
+
'decrypt',
|
|
246
|
+
'createHmac',
|
|
247
|
+
'verifyHmac',
|
|
248
|
+
'createSignature',
|
|
249
|
+
'verifySignature',
|
|
250
|
+
'acquireCertificate',
|
|
251
|
+
'listCertificates',
|
|
252
|
+
'proveCertificate',
|
|
253
|
+
'relinquishCertificate',
|
|
254
|
+
'discoverByIdentityKey',
|
|
255
|
+
'discoverByAttributes',
|
|
256
|
+
'isAuthenticated',
|
|
257
|
+
'waitForAuthentication',
|
|
258
|
+
'getHeight',
|
|
259
|
+
'getHeaderForHeight',
|
|
260
|
+
'getNetwork',
|
|
261
|
+
'getVersion',
|
|
262
|
+
]
|
|
263
|
+
|
|
264
|
+
it.each(callsToTest)('routes %s to the correct URL segment', async (callName) => {
|
|
265
|
+
const mockFetch = mockGlobalFetch([])
|
|
266
|
+
const wire = new HTTPWalletWire(undefined, 'http://localhost:3301')
|
|
267
|
+
|
|
268
|
+
await wire.transmitToWallet(buildFrame(callName))
|
|
269
|
+
|
|
270
|
+
const [url] = mockFetch.mock.calls[0] as [string]
|
|
271
|
+
expect(url).toBe(`http://localhost:3301/${callName}`)
|
|
272
|
+
})
|
|
273
|
+
})
|