@onekeyfe/hd-core 1.2.0-alpha.23 → 1.2.0-alpha.24
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/__tests__/DeviceCommands.test.ts +35 -0
- package/__tests__/connectSettings.test.ts +5 -47
- package/__tests__/device-lifecycle-events.test.ts +59 -0
- package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +30 -39
- package/__tests__/open-wallet-session.test.ts +192 -129
- package/__tests__/protocol-v2-ping.test.ts +28 -0
- package/__tests__/protocol-v2.test.ts +338 -376
- package/__tests__/public-pro2-api-boundary.test.ts +22 -0
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV2.d.ts +0 -11
- package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV3.d.ts +3 -7
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +5 -21
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/OpenWalletSession.d.ts +1 -8
- package/dist/api/OpenWalletSession.d.ts.map +1 -1
- package/dist/api/device/DeviceUpdateBootloader.d.ts +1 -5
- package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +0 -7
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
- package/dist/api/firmware/getBinary.d.ts +0 -7
- package/dist/api/firmware/getBinary.d.ts.map +1 -1
- package/dist/api/firmware/updateBootloader.d.ts +0 -2
- package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
- package/dist/api/firmware/uploadFirmware.d.ts +1 -9
- package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/protocol-v2/Ping.d.ts +2 -0
- package/dist/api/protocol-v2/Ping.d.ts.map +1 -1
- package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/data-manager/DataManager.d.ts +0 -1
- package/dist/data-manager/DataManager.d.ts.map +1 -1
- package/dist/data-manager/connectSettings.d.ts.map +1 -1
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts.map +1 -1
- package/dist/index.d.ts +89 -273
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +783 -2443
- package/dist/inject.d.ts.map +1 -1
- package/dist/lowLevelInject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockRetry.d.ts +2 -3
- package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/walletSession.d.ts +12 -0
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
- package/dist/topLevelInject.d.ts.map +1 -1
- package/dist/types/api/checkAllFirmwareRelease.d.ts +0 -3
- package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/deviceUpdateBootloader.d.ts +0 -6
- package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
- package/dist/types/api/export.d.ts +1 -4
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdate.d.ts +0 -69
- package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +4 -10
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/openWalletSession.d.ts +0 -12
- package/dist/types/api/openWalletSession.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +4 -0
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/settings.d.ts +0 -13
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
- package/dist/utils/patch.d.ts +1 -1
- package/dist/utils/patch.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/CheckAllFirmwareRelease.ts +3 -23
- package/src/api/FirmwareUpdateV2.ts +120 -292
- package/src/api/FirmwareUpdateV3.ts +55 -256
- package/src/api/FirmwareUpdateV4.ts +297 -757
- package/src/api/OpenWalletSession.ts +23 -86
- package/src/api/device/DeviceUpdateBootloader.ts +6 -122
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +0 -50
- package/src/api/firmware/updateBootloader.ts +4 -19
- package/src/api/firmware/uploadFirmware.ts +22 -140
- package/src/api/index.ts +1 -0
- package/src/api/protocol-v2/Ping.ts +32 -1
- package/src/core/index.ts +39 -7
- package/src/data/messages/messages-protocol-v2.json +33 -1
- package/src/data-manager/DataManager.ts +33 -33
- package/src/data-manager/connectSettings.ts +0 -11
- package/src/device/Device.ts +7 -9
- package/src/device/DeviceCommands.ts +19 -0
- package/src/index.ts +0 -5
- package/src/inject.ts +4 -22
- package/src/lowLevelInject.ts +1 -5
- package/src/protocols/protocol-v2/unlockRetry.ts +20 -3
- package/src/protocols/protocol-v2/walletSession.ts +26 -8
- package/src/topLevelInject.ts +1 -5
- package/src/types/api/checkAllFirmwareRelease.ts +0 -3
- package/src/types/api/deviceUpdateBootloader.ts +0 -6
- package/src/types/api/export.ts +0 -18
- package/src/types/api/firmwareUpdate.ts +0 -76
- package/src/types/api/index.ts +3 -14
- package/src/types/api/openWalletSession.ts +0 -19
- package/src/types/api/protocolV2.ts +10 -0
- package/src/types/settings.ts +0 -13
- package/src/utils/deviceInfoUtils.ts +15 -3
- package/__tests__/firmware-update/check-all-firmware-release.test.ts +0 -86
- package/__tests__/firmware-update/firmware-artifact-source.test.ts +0 -119
- package/__tests__/firmware-update/firmware-host-binding.test.ts +0 -70
- package/__tests__/firmware-update/firmware-update-capabilities.test.ts +0 -13
- package/__tests__/firmware-update/firmware-update-plan.test.ts +0 -326
- package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +0 -213
- package/__tests__/firmware-update/firmware-upload-source.test.ts +0 -70
- package/dist/api/firmware/FirmwareArtifactSource.d.ts +0 -25
- package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +0 -1
- package/dist/api/firmware/FirmwareHostBinding.d.ts +0 -6
- package/dist/api/firmware/FirmwareHostBinding.d.ts.map +0 -1
- package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +0 -3
- package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +0 -1
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts +0 -23
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +0 -1
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +0 -30
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +0 -1
- package/dist/types/api/firmwareUpdateCapabilities.d.ts +0 -9
- package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +0 -1
- package/dist/types/api/firmwareUpdatePlan.d.ts +0 -27
- package/dist/types/api/firmwareUpdatePlan.d.ts.map +0 -1
- package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +0 -42
- package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +0 -1
- package/src/api/firmware/FirmwareArtifactSource.ts +0 -278
- package/src/api/firmware/FirmwareHostBinding.ts +0 -100
- package/src/api/firmware/FirmwareUpdateCapabilities.ts +0 -9
- package/src/api/firmware/FirmwareUpdatePlan.ts +0 -621
- package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +0 -392
- package/src/types/api/firmwareUpdateCapabilities.ts +0 -9
- package/src/types/api/firmwareUpdatePlan.ts +0 -36
- package/src/types/api/firmwareUpdatePreparedPlan.ts +0 -53
|
@@ -60,10 +60,25 @@ describe('openWalletSession', () => {
|
|
|
60
60
|
deviceWalletSessionStore.clear();
|
|
61
61
|
});
|
|
62
62
|
|
|
63
|
+
test.each([{ useEmptyPassphrase: true }, { initSession: true }, {}])(
|
|
64
|
+
'requires the explicit mode in the new public API: %p',
|
|
65
|
+
legacyParams => {
|
|
66
|
+
const method = new OpenWalletSession({
|
|
67
|
+
payload: {
|
|
68
|
+
method: 'openWalletSession',
|
|
69
|
+
connectId: 'connect-id',
|
|
70
|
+
...legacyParams,
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
expect(() => method.init()).toThrow('Parameter [mode] is required');
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
|
|
63
78
|
test('keeps the legacy getPassphraseState App flow working on Protocol V2', async () => {
|
|
64
79
|
const typedCall = jest
|
|
65
80
|
.fn()
|
|
66
|
-
.mockResolvedValueOnce({ message: {
|
|
81
|
+
.mockResolvedValueOnce({ message: { version: 2 } })
|
|
67
82
|
.mockResolvedValueOnce({ message: { message: 'passphrase prepared' } })
|
|
68
83
|
.mockResolvedValueOnce({
|
|
69
84
|
message: {
|
|
@@ -71,7 +86,7 @@ describe('openWalletSession', () => {
|
|
|
71
86
|
session_id: 'pro2-wallet-session',
|
|
72
87
|
},
|
|
73
88
|
});
|
|
74
|
-
const promptPassphrase = jest.fn().mockResolvedValue({
|
|
89
|
+
const promptPassphrase = jest.fn().mockResolvedValue({ passphraseOnDevice: true });
|
|
75
90
|
const method = new GetPassphraseState({
|
|
76
91
|
payload: {
|
|
77
92
|
method: 'getPassphraseState',
|
|
@@ -84,18 +99,15 @@ describe('openWalletSession', () => {
|
|
|
84
99
|
|
|
85
100
|
await expect(method.run()).resolves.toBe('pro2-wallet-state');
|
|
86
101
|
expect(promptPassphrase).toHaveBeenCalledWith(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
'Success',
|
|
94
|
-
{},
|
|
95
|
-
{ timeoutMs: 120_000 }
|
|
102
|
+
{
|
|
103
|
+
existsAttachPinUser: false,
|
|
104
|
+
source: 'wallet-session-coordinator',
|
|
105
|
+
reason: 'open-wallet',
|
|
106
|
+
},
|
|
107
|
+
{ cancelDeviceOnReject: false }
|
|
96
108
|
);
|
|
109
|
+
expect(typedCall).toHaveBeenNthCalledWith(2, 'DeviceSessionAskPassphrase', 'Success', {});
|
|
97
110
|
expect(typedCall).toHaveBeenNthCalledWith(3, 'DeviceSessionGet', 'DeviceSession', {});
|
|
98
|
-
expect(JSON.stringify(typedCall.mock.calls)).not.toContain('legacy app secret');
|
|
99
111
|
});
|
|
100
112
|
|
|
101
113
|
test('keeps Legacy Protocol V1 getPassphraseState parameterless', async () => {
|
|
@@ -150,9 +162,7 @@ describe('openWalletSession', () => {
|
|
|
150
162
|
payload: {
|
|
151
163
|
method: 'openWalletSession',
|
|
152
164
|
connectId: 'connect-id',
|
|
153
|
-
|
|
154
|
-
initSession: true,
|
|
155
|
-
passphraseState: 'stale-hidden-state',
|
|
165
|
+
mode: 'standard',
|
|
156
166
|
},
|
|
157
167
|
});
|
|
158
168
|
method.init();
|
|
@@ -181,19 +191,27 @@ describe('openWalletSession', () => {
|
|
|
181
191
|
expect(typedCall).toHaveBeenCalledWith('GetPassphraseState', 'PassphraseState', {
|
|
182
192
|
passphrase_state: undefined,
|
|
183
193
|
});
|
|
184
|
-
expect(device.clearInternalState).toHaveBeenCalled();
|
|
194
|
+
expect(device.clearInternalState).not.toHaveBeenCalled();
|
|
185
195
|
});
|
|
186
196
|
|
|
187
|
-
test('uses the
|
|
188
|
-
const typedCall = jest
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
197
|
+
test('uses the explicit mode to select a hidden wallet on Protocol V2', async () => {
|
|
198
|
+
const typedCall = jest
|
|
199
|
+
.fn()
|
|
200
|
+
.mockResolvedValueOnce({ message: { version: 2 } })
|
|
201
|
+
.mockResolvedValueOnce({ message: { message: 'passphrase prepared' } })
|
|
202
|
+
.mockResolvedValueOnce({
|
|
203
|
+
message: {
|
|
204
|
+
btc_test_address: 'hidden-state',
|
|
205
|
+
session_id: 'hidden-session',
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
const promptPassphrase = jest.fn().mockResolvedValue({ passphraseOnDevice: true });
|
|
195
209
|
const method = new OpenWalletSession({
|
|
196
|
-
payload: {
|
|
210
|
+
payload: {
|
|
211
|
+
method: 'openWalletSession',
|
|
212
|
+
connectId: 'connect-id',
|
|
213
|
+
mode: 'select-hidden',
|
|
214
|
+
},
|
|
197
215
|
});
|
|
198
216
|
method.init();
|
|
199
217
|
method.device = createDevice({ typedCall, promptPassphrase }) as any;
|
|
@@ -203,19 +221,9 @@ describe('openWalletSession', () => {
|
|
|
203
221
|
walletType: 'hidden',
|
|
204
222
|
passphraseState: 'hidden-state',
|
|
205
223
|
});
|
|
206
|
-
expect(promptPassphrase).
|
|
207
|
-
|
|
208
|
-
expect.anything()
|
|
209
|
-
);
|
|
210
|
-
expect(typedCall).toHaveBeenNthCalledWith(
|
|
211
|
-
2,
|
|
212
|
-
'DeviceSessionAskPassphrase',
|
|
213
|
-
'Success',
|
|
214
|
-
{},
|
|
215
|
-
{ timeoutMs: 120_000 }
|
|
216
|
-
);
|
|
224
|
+
expect(promptPassphrase).toHaveBeenCalled();
|
|
225
|
+
expect(typedCall).toHaveBeenNthCalledWith(2, 'DeviceSessionAskPassphrase', 'Success', {});
|
|
217
226
|
expect(typedCall).toHaveBeenNthCalledWith(3, 'DeviceSessionGet', 'DeviceSession', {});
|
|
218
|
-
expect(JSON.stringify(typedCall.mock.calls)).not.toContain('hidden secret');
|
|
219
227
|
});
|
|
220
228
|
|
|
221
229
|
test('classifies the selected Pro2 wallet from the post-unlock device state', async () => {
|
|
@@ -229,12 +237,16 @@ describe('openWalletSession', () => {
|
|
|
229
237
|
session_id: 'hidden-session-after-unlock',
|
|
230
238
|
},
|
|
231
239
|
});
|
|
232
|
-
const promptPassphrase = jest.fn().mockResolvedValue({
|
|
240
|
+
const promptPassphrase = jest.fn().mockResolvedValue({ passphraseOnDevice: true });
|
|
233
241
|
const method = new OpenWalletSession({
|
|
234
242
|
payload: { method: 'openWalletSession', connectId: 'connect-id', mode: 'select-hidden' },
|
|
235
243
|
});
|
|
236
244
|
method.init();
|
|
237
|
-
const device = createDevice({
|
|
245
|
+
const device = createDevice({
|
|
246
|
+
passphraseProtection: false,
|
|
247
|
+
typedCall,
|
|
248
|
+
promptPassphrase,
|
|
249
|
+
});
|
|
238
250
|
device.features.unlocked = false;
|
|
239
251
|
device.getCurrentPassphraseProtection = () => device.features.passphraseProtection;
|
|
240
252
|
device.unlockDevice = jest.fn().mockImplementation(() => {
|
|
@@ -256,25 +268,26 @@ describe('openWalletSession', () => {
|
|
|
256
268
|
expect(promptPassphrase).toHaveBeenCalledTimes(1);
|
|
257
269
|
});
|
|
258
270
|
|
|
259
|
-
test('
|
|
260
|
-
const typedCall = jest
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
271
|
+
test('select-hidden starts a fresh hidden-wallet session on Protocol V2', async () => {
|
|
272
|
+
const typedCall = jest
|
|
273
|
+
.fn()
|
|
274
|
+
.mockResolvedValueOnce({ message: { version: 2 } })
|
|
275
|
+
.mockResolvedValueOnce({ message: { message: 'passphrase prepared' } })
|
|
276
|
+
.mockResolvedValueOnce({
|
|
277
|
+
message: {
|
|
278
|
+
btc_test_address: 'new-hidden-state',
|
|
279
|
+
session_id: 'new-hidden-session',
|
|
280
|
+
},
|
|
281
|
+
});
|
|
282
|
+
const promptPassphrase = jest.fn().mockResolvedValue({ passphraseOnDevice: true });
|
|
267
283
|
const method = new OpenWalletSession({
|
|
268
284
|
payload: {
|
|
269
285
|
method: 'openWalletSession',
|
|
270
286
|
connectId: 'connect-id',
|
|
271
|
-
|
|
272
|
-
deviceId: 'device-1',
|
|
273
|
-
passphraseState: 'stale-hidden-state',
|
|
287
|
+
mode: 'select-hidden',
|
|
274
288
|
},
|
|
275
289
|
});
|
|
276
290
|
method.init();
|
|
277
|
-
deviceWalletSessionStore.set('device-1', 'stale-hidden-state', 'stale-hidden-session');
|
|
278
291
|
method.device = createDevice({ typedCall, promptPassphrase }) as any;
|
|
279
292
|
|
|
280
293
|
await expect(method.run()).resolves.toEqual({
|
|
@@ -288,35 +301,29 @@ describe('openWalletSession', () => {
|
|
|
288
301
|
expect(typedCall).toHaveBeenCalledWith('ProtocolInfoRequest', 'ProtocolInfo', {
|
|
289
302
|
eventless_wallet_session: true,
|
|
290
303
|
});
|
|
291
|
-
expect(typedCall).toHaveBeenCalledWith(
|
|
292
|
-
'DeviceSessionAskPassphrase',
|
|
293
|
-
'Success',
|
|
294
|
-
{},
|
|
295
|
-
{
|
|
296
|
-
timeoutMs: 120_000,
|
|
297
|
-
}
|
|
298
|
-
);
|
|
304
|
+
expect(typedCall).toHaveBeenCalledWith('DeviceSessionAskPassphrase', 'Success', {});
|
|
299
305
|
expect(typedCall).toHaveBeenCalledWith('DeviceSessionGet', 'DeviceSession', {});
|
|
300
306
|
expect(promptPassphrase).toHaveBeenCalled();
|
|
301
|
-
expect(deviceWalletSessionStore.get('device-1', 'stale-hidden-state')).toBeUndefined();
|
|
302
307
|
expect(deviceWalletSessionStore.get('device-1', 'new-hidden-state')).toBe('new-hidden-session');
|
|
303
308
|
});
|
|
304
309
|
|
|
305
|
-
test('does not clear another device wallet
|
|
306
|
-
const typedCall = jest
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
310
|
+
test('select-hidden does not clear another device wallet', async () => {
|
|
311
|
+
const typedCall = jest
|
|
312
|
+
.fn()
|
|
313
|
+
.mockResolvedValueOnce({ message: { version: 2 } })
|
|
314
|
+
.mockResolvedValueOnce({ message: { message: 'passphrase prepared' } })
|
|
315
|
+
.mockResolvedValueOnce({
|
|
316
|
+
message: {
|
|
317
|
+
btc_test_address: 'current-device-state',
|
|
318
|
+
session_id: 'current-device-session',
|
|
319
|
+
},
|
|
320
|
+
});
|
|
321
|
+
const promptPassphrase = jest.fn().mockResolvedValue({ passphraseOnDevice: true });
|
|
313
322
|
const method = new OpenWalletSession({
|
|
314
323
|
payload: {
|
|
315
324
|
method: 'openWalletSession',
|
|
316
325
|
connectId: 'connect-id',
|
|
317
|
-
|
|
318
|
-
deviceId: 'other-device',
|
|
319
|
-
passphraseState: 'other-device-state',
|
|
326
|
+
mode: 'select-hidden',
|
|
320
327
|
},
|
|
321
328
|
});
|
|
322
329
|
method.init();
|
|
@@ -333,19 +340,22 @@ describe('openWalletSession', () => {
|
|
|
333
340
|
);
|
|
334
341
|
});
|
|
335
342
|
|
|
336
|
-
test('uses
|
|
337
|
-
const typedCall = jest
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
+
test('uses an explicit wallet binding to resume on Protocol V2', async () => {
|
|
344
|
+
const typedCall = jest
|
|
345
|
+
.fn()
|
|
346
|
+
.mockResolvedValueOnce({ message: { version: 2 } })
|
|
347
|
+
.mockResolvedValueOnce({
|
|
348
|
+
message: {
|
|
349
|
+
btc_test_address: 'hidden-state',
|
|
350
|
+
session_id: 'renewed-session',
|
|
351
|
+
},
|
|
352
|
+
});
|
|
343
353
|
const promptPassphrase = jest.fn();
|
|
344
354
|
const method = new OpenWalletSession({
|
|
345
355
|
payload: {
|
|
346
356
|
method: 'openWalletSession',
|
|
347
357
|
connectId: 'connect-id',
|
|
348
|
-
|
|
358
|
+
mode: 'resume-hidden',
|
|
349
359
|
deviceId: 'device-1',
|
|
350
360
|
passphraseState: 'hidden-state',
|
|
351
361
|
},
|
|
@@ -405,7 +415,7 @@ describe('openWalletSession', () => {
|
|
|
405
415
|
});
|
|
406
416
|
|
|
407
417
|
test.each([{ initSession: 'true' }, { useEmptyPassphrase: 'false' }])(
|
|
408
|
-
'rejects
|
|
418
|
+
'rejects legacy flags without an explicit mode: %o',
|
|
409
419
|
params => {
|
|
410
420
|
const method = new OpenWalletSession({
|
|
411
421
|
payload: {
|
|
@@ -533,12 +543,15 @@ describe('openWalletSession', () => {
|
|
|
533
543
|
});
|
|
534
544
|
|
|
535
545
|
test('rejects a standard-wallet request when Protocol V2 is unlocked by Attach PIN', async () => {
|
|
536
|
-
const typedCall = jest
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
546
|
+
const typedCall = jest
|
|
547
|
+
.fn()
|
|
548
|
+
.mockResolvedValueOnce({ message: { version: 2 } })
|
|
549
|
+
.mockResolvedValueOnce({
|
|
550
|
+
message: {
|
|
551
|
+
btc_test_address: 'attach-wallet-state',
|
|
552
|
+
session_id: 'attach-wallet-session',
|
|
553
|
+
},
|
|
554
|
+
});
|
|
542
555
|
const method = new OpenWalletSession({
|
|
543
556
|
payload: { method: 'openWalletSession', connectId: 'connect-id', mode: 'standard' },
|
|
544
557
|
});
|
|
@@ -555,13 +568,17 @@ describe('openWalletSession', () => {
|
|
|
555
568
|
});
|
|
556
569
|
|
|
557
570
|
test('selects a hidden wallet and returns the CLI compatibility session', async () => {
|
|
558
|
-
const typedCall = jest
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
571
|
+
const typedCall = jest
|
|
572
|
+
.fn()
|
|
573
|
+
.mockResolvedValueOnce({ message: { version: 2 } })
|
|
574
|
+
.mockResolvedValueOnce({ message: { message: 'passphrase prepared' } })
|
|
575
|
+
.mockResolvedValueOnce({
|
|
576
|
+
message: {
|
|
577
|
+
btc_test_address: 'hidden-state',
|
|
578
|
+
session_id: 'hidden-session',
|
|
579
|
+
},
|
|
580
|
+
});
|
|
581
|
+
const promptPassphrase = jest.fn().mockResolvedValue({ passphraseOnDevice: true });
|
|
565
582
|
const method = new OpenWalletSession({
|
|
566
583
|
payload: { method: 'openWalletSession', connectId: 'connect-id', mode: 'select-hidden' },
|
|
567
584
|
});
|
|
@@ -578,14 +595,7 @@ describe('openWalletSession', () => {
|
|
|
578
595
|
sessionId: 'hidden-session',
|
|
579
596
|
resumed: false,
|
|
580
597
|
});
|
|
581
|
-
expect(typedCall).toHaveBeenCalledWith(
|
|
582
|
-
'DeviceSessionAskPassphrase',
|
|
583
|
-
'Success',
|
|
584
|
-
{},
|
|
585
|
-
{
|
|
586
|
-
timeoutMs: 120_000,
|
|
587
|
-
}
|
|
588
|
-
);
|
|
598
|
+
expect(typedCall).toHaveBeenCalledWith('DeviceSessionAskPassphrase', 'Success', {});
|
|
589
599
|
expect(typedCall).toHaveBeenCalledWith('DeviceSessionGet', 'DeviceSession', {});
|
|
590
600
|
expect(promptPassphrase).toHaveBeenCalled();
|
|
591
601
|
expect(device.passphraseState).toBeUndefined();
|
|
@@ -593,9 +603,13 @@ describe('openWalletSession', () => {
|
|
|
593
603
|
});
|
|
594
604
|
|
|
595
605
|
test('selects on-device passphrase entry before getting the prepared session', async () => {
|
|
596
|
-
const typedCall = jest
|
|
597
|
-
|
|
598
|
-
|
|
606
|
+
const typedCall = jest
|
|
607
|
+
.fn()
|
|
608
|
+
.mockResolvedValueOnce({ message: { version: 2 } })
|
|
609
|
+
.mockResolvedValueOnce({ message: { message: 'passphrase prepared' } })
|
|
610
|
+
.mockResolvedValueOnce({
|
|
611
|
+
message: { btc_test_address: 'device-state', session_id: 'device-session' },
|
|
612
|
+
});
|
|
599
613
|
const promptPassphrase = jest.fn().mockResolvedValue({ passphraseOnDevice: true });
|
|
600
614
|
const method = new OpenWalletSession({
|
|
601
615
|
payload: { method: 'openWalletSession', connectId: 'connect-id', mode: 'select-hidden' },
|
|
@@ -607,21 +621,56 @@ describe('openWalletSession', () => {
|
|
|
607
621
|
walletType: 'hidden',
|
|
608
622
|
passphraseState: 'device-state',
|
|
609
623
|
});
|
|
610
|
-
expect(typedCall).toHaveBeenCalledWith(
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
624
|
+
expect(typedCall).toHaveBeenCalledWith('DeviceSessionAskPassphrase', 'Success', {});
|
|
625
|
+
expect(typedCall).toHaveBeenCalledWith('DeviceSessionGet', 'DeviceSession', {});
|
|
626
|
+
});
|
|
627
|
+
|
|
628
|
+
test('forwards a host passphrase to Pro2 firmware', async () => {
|
|
629
|
+
const typedCall = jest
|
|
630
|
+
.fn()
|
|
631
|
+
.mockResolvedValueOnce({ message: { version: 2 } })
|
|
632
|
+
.mockResolvedValueOnce({ message: { message: 'passphrase prepared' } })
|
|
633
|
+
.mockResolvedValueOnce({
|
|
634
|
+
message: { btc_test_address: 'host-state', session_id: 'host-session' },
|
|
635
|
+
});
|
|
636
|
+
const promptPassphrase = jest.fn().mockResolvedValue({ passphrase: 'host hidden wallet' });
|
|
637
|
+
const method = new OpenWalletSession({
|
|
638
|
+
payload: {
|
|
639
|
+
method: 'openWalletSession',
|
|
640
|
+
connectId: 'connect-id',
|
|
641
|
+
mode: 'select-hidden',
|
|
642
|
+
},
|
|
643
|
+
});
|
|
644
|
+
method.init();
|
|
645
|
+
method.device = createDevice({
|
|
646
|
+
typedCall,
|
|
647
|
+
promptPassphrase,
|
|
648
|
+
}) as any;
|
|
649
|
+
|
|
650
|
+
await expect(method.run()).resolves.toMatchObject({
|
|
651
|
+
walletType: 'hidden',
|
|
652
|
+
passphraseState: 'host-state',
|
|
653
|
+
});
|
|
654
|
+
expect(promptPassphrase).toHaveBeenCalledWith(
|
|
614
655
|
{
|
|
615
|
-
|
|
616
|
-
|
|
656
|
+
existsAttachPinUser: false,
|
|
657
|
+
source: 'wallet-session-coordinator',
|
|
658
|
+
reason: 'open-wallet',
|
|
659
|
+
},
|
|
660
|
+
{ cancelDeviceOnReject: false }
|
|
617
661
|
);
|
|
618
|
-
expect(typedCall).
|
|
662
|
+
expect(typedCall).toHaveBeenNthCalledWith(2, 'DeviceSessionAskPassphrase', 'Success', {
|
|
663
|
+
passphrase: 'host hidden wallet',
|
|
664
|
+
});
|
|
619
665
|
});
|
|
620
666
|
|
|
621
667
|
test('selects Attach PIN only when the device reports an existing binding', async () => {
|
|
622
|
-
const typedCall = jest
|
|
623
|
-
|
|
624
|
-
|
|
668
|
+
const typedCall = jest
|
|
669
|
+
.fn()
|
|
670
|
+
.mockResolvedValueOnce({ message: { version: 2 } })
|
|
671
|
+
.mockResolvedValueOnce({
|
|
672
|
+
message: { btc_test_address: 'attach-state', session_id: 'attach-session' },
|
|
673
|
+
});
|
|
625
674
|
const promptPassphrase = jest.fn().mockResolvedValue({ attachPinOnDevice: true });
|
|
626
675
|
const method = new OpenWalletSession({
|
|
627
676
|
payload: { method: 'openWalletSession', connectId: 'connect-id', mode: 'select-hidden' },
|
|
@@ -636,7 +685,11 @@ describe('openWalletSession', () => {
|
|
|
636
685
|
passphraseState: 'attach-state',
|
|
637
686
|
});
|
|
638
687
|
expect(promptPassphrase).toHaveBeenCalledWith(
|
|
639
|
-
|
|
688
|
+
{
|
|
689
|
+
existsAttachPinUser: true,
|
|
690
|
+
source: 'wallet-session-coordinator',
|
|
691
|
+
reason: 'open-wallet',
|
|
692
|
+
},
|
|
640
693
|
{ cancelDeviceOnReject: false }
|
|
641
694
|
);
|
|
642
695
|
expect(device.unlockDevice).toHaveBeenCalledWith(DeviceSessionPinType.AttachToPin);
|
|
@@ -655,8 +708,12 @@ describe('openWalletSession', () => {
|
|
|
655
708
|
])(
|
|
656
709
|
'rejects an incomplete Protocol V2 hidden-wallet response missing $missingField',
|
|
657
710
|
async ({ message }) => {
|
|
658
|
-
const typedCall = jest
|
|
659
|
-
|
|
711
|
+
const typedCall = jest
|
|
712
|
+
.fn()
|
|
713
|
+
.mockResolvedValueOnce({ message: { version: 2 } })
|
|
714
|
+
.mockResolvedValueOnce({ message: { message: 'passphrase prepared' } })
|
|
715
|
+
.mockResolvedValueOnce({ message });
|
|
716
|
+
const promptPassphrase = jest.fn().mockResolvedValue({ passphraseOnDevice: true });
|
|
660
717
|
const method = new OpenWalletSession({
|
|
661
718
|
payload: { method: 'openWalletSession', connectId: 'connect-id', mode: 'select-hidden' },
|
|
662
719
|
});
|
|
@@ -674,12 +731,15 @@ describe('openWalletSession', () => {
|
|
|
674
731
|
);
|
|
675
732
|
|
|
676
733
|
test('resumes a known hidden wallet without prompting or device selection', async () => {
|
|
677
|
-
const typedCall = jest
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
734
|
+
const typedCall = jest
|
|
735
|
+
.fn()
|
|
736
|
+
.mockResolvedValueOnce({ message: { version: 2 } })
|
|
737
|
+
.mockResolvedValueOnce({
|
|
738
|
+
message: {
|
|
739
|
+
btc_test_address: 'hidden-state',
|
|
740
|
+
session_id: 'renewed-session',
|
|
741
|
+
},
|
|
742
|
+
});
|
|
683
743
|
const promptPassphrase = jest.fn();
|
|
684
744
|
const method = new OpenWalletSession({
|
|
685
745
|
payload: {
|
|
@@ -709,12 +769,15 @@ describe('openWalletSession', () => {
|
|
|
709
769
|
});
|
|
710
770
|
|
|
711
771
|
test('validates a locked Protocol V2 resume binding after deviceId refresh', async () => {
|
|
712
|
-
const typedCall = jest
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
772
|
+
const typedCall = jest
|
|
773
|
+
.fn()
|
|
774
|
+
.mockResolvedValueOnce({ message: { version: 2 } })
|
|
775
|
+
.mockResolvedValueOnce({
|
|
776
|
+
message: {
|
|
777
|
+
btc_test_address: 'hidden-state',
|
|
778
|
+
session_id: 'renewed-session',
|
|
779
|
+
},
|
|
780
|
+
});
|
|
718
781
|
const method = new OpenWalletSession({
|
|
719
782
|
payload: {
|
|
720
783
|
method: 'openWalletSession',
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { validateProtocolV2PingMessage } from '../src/api/protocol-v2/Ping';
|
|
2
|
+
|
|
3
|
+
jest.mock('../src/data/config', () => ({
|
|
4
|
+
DEFAULT_DOMAIN: 'https://example.com/',
|
|
5
|
+
getSDKVersion: () => '0.0.0-test',
|
|
6
|
+
}));
|
|
7
|
+
|
|
8
|
+
describe('Protocol V2 diagnostic Ping validation', () => {
|
|
9
|
+
test('accepts messages up to the firmware UTF-8 byte limit', () => {
|
|
10
|
+
expect(validateProtocolV2PingMessage('x'.repeat(63))).toBe('x'.repeat(63));
|
|
11
|
+
expect(validateProtocolV2PingMessage('测'.repeat(21))).toBe('测'.repeat(21));
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test('rejects messages larger than the firmware UTF-8 byte limit', () => {
|
|
15
|
+
expect(() => validateProtocolV2PingMessage('x'.repeat(64))).toThrow(
|
|
16
|
+
'Protocol V2 Ping message must not exceed 63 UTF-8 bytes.'
|
|
17
|
+
);
|
|
18
|
+
expect(() => validateProtocolV2PingMessage('测'.repeat(22))).toThrow(
|
|
19
|
+
'Protocol V2 Ping message must not exceed 63 UTF-8 bytes.'
|
|
20
|
+
);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('rejects non-string messages at the runtime API boundary', () => {
|
|
24
|
+
expect(() => validateProtocolV2PingMessage(64)).toThrow(
|
|
25
|
+
'Protocol V2 Ping message must be a string.'
|
|
26
|
+
);
|
|
27
|
+
});
|
|
28
|
+
});
|