@onekeyfe/hd-core 1.2.2-alpha.100 → 1.2.2-alpha.102
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__/AllNetworkGetAddressBase.tracing.test.ts +20 -4
- package/__tests__/DeviceCommands.test.ts +13 -0
- package/__tests__/check-all-firmware-release-protocol-v2.test.ts +0 -2
- package/__tests__/check-firmware-release-protocol-v2.test.ts +0 -2
- package/__tests__/device-lifecycle-events.test.ts +102 -0
- package/__tests__/deviceUploadNft.test.ts +68 -0
- package/__tests__/evmSignTypedData.test.ts +42 -0
- package/__tests__/firmware-update/firmware-update-v4-install-poll.test.ts +825 -12
- package/__tests__/logBlockEvent.test.ts +45 -122
- package/__tests__/open-wallet-session.test.ts +781 -69
- package/__tests__/pro2HostAssetPackage.test.ts +165 -0
- package/__tests__/protocol-v2-resources.test.ts +7 -4
- package/__tests__/protocol-v2-unlock-policy.test.ts +35 -1
- package/__tests__/protocol-v2.test.ts +937 -74
- package/__tests__/protocolV2FileWrite.test.ts +40 -0
- package/__tests__/sol-sign-offchain-message.test.ts +64 -0
- package/dist/api/FirmwareUpdateV4.d.ts +5 -0
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/OpenWalletSession.d.ts.map +1 -1
- package/dist/api/UploadPortfolio.d.ts +1 -0
- package/dist/api/UploadPortfolio.d.ts.map +1 -1
- package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
- package/dist/api/evm/EVMSignTypedData.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +2 -2
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
- package/dist/api/firmware/getBinary.d.ts +2 -2
- package/dist/api/helpers/protocolV2FileWrite.d.ts +1 -0
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -1
- package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
- package/dist/api/solana/SolSignOffchainMessage.d.ts.map +1 -1
- package/dist/core/RequestQueue.d.ts +2 -0
- package/dist/core/RequestQueue.d.ts.map +1 -1
- package/dist/core/index.d.ts +4 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/uiPromiseRegistry.d.ts +1 -1
- package/dist/device/Device.d.ts +1 -1
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts +4 -4
- package/dist/device/DeviceConnector.d.ts +1 -1
- package/dist/device/DeviceConnector.d.ts.map +1 -1
- package/dist/events/logBlockEvent.d.ts.map +1 -1
- package/dist/events/ui-request.d.ts +3 -0
- package/dist/events/ui-request.d.ts.map +1 -1
- package/dist/index.d.ts +38 -16
- package/dist/index.js +2569 -1555
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +2 -0
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/walletSession.d.ts +3 -0
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +3 -4
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/api/solSignOffchainMessage.d.ts +1 -0
- package/dist/types/api/solSignOffchainMessage.d.ts.map +1 -1
- package/dist/types/settings.d.ts +2 -2
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesUtils.d.ts +3 -0
- package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
- package/dist/utils/patch.d.ts +1 -1
- package/dist/utils/patch.d.ts.map +1 -1
- package/dist/utils/pro2HostAssetPackage.d.ts +8 -0
- package/dist/utils/pro2HostAssetPackage.d.ts.map +1 -0
- package/package.json +4 -4
- package/src/api/FirmwareUpdateV4.ts +474 -83
- package/src/api/OpenWalletSession.ts +39 -12
- package/src/api/UploadPortfolio.ts +5 -4
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +5 -2
- package/src/api/evm/EVMSignTypedData.ts +1 -0
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +9 -3
- package/src/api/helpers/protocolV2FileWrite.ts +11 -5
- package/src/api/protocol-v2/DeviceGetFirmwareUpdateStatus.ts +7 -1
- package/src/api/protocol-v2/DeviceUploadNft.ts +31 -8
- package/src/api/protocol-v2/DeviceUploadWallpaper.ts +33 -8
- package/src/api/protocol-v2/helpers.ts +8 -0
- package/src/api/solana/SolSignOffchainMessage.ts +44 -4
- package/src/core/RequestQueue.ts +16 -1
- package/src/core/index.ts +179 -27
- package/src/data/messages/messages-protocol-v2.json +1591 -1382
- package/src/data/messages/messages.json +8 -5
- package/src/device/Device.ts +3 -1
- package/src/device/DeviceConnector.ts +7 -3
- package/src/events/logBlockEvent.ts +6 -75
- package/src/events/ui-request.ts +3 -0
- package/src/protocols/protocol-v2/resources.ts +9 -1
- package/src/protocols/protocol-v2/unlockPolicyRunner.ts +8 -1
- package/src/protocols/protocol-v2/walletSession.ts +223 -56
- package/src/types/api/protocolV2.ts +3 -4
- package/src/types/api/solSignOffchainMessage.ts +2 -0
- package/src/types/settings.ts +4 -2
- package/src/utils/deviceFeaturesUtils.ts +4 -0
- package/src/utils/pro2HostAssetPackage.ts +400 -0
|
@@ -95,7 +95,8 @@ describe('AllNetworkGetAddressBase tracing', () => {
|
|
|
95
95
|
'hidden-state',
|
|
96
96
|
false,
|
|
97
97
|
undefined,
|
|
98
|
-
|
|
98
|
+
undefined,
|
|
99
|
+
undefined
|
|
99
100
|
);
|
|
100
101
|
expect(calls).toEqual(['resume-hidden-session', 'run-chain-method']);
|
|
101
102
|
expect(typedCall).not.toHaveBeenCalled();
|
|
@@ -173,7 +174,13 @@ describe('AllNetworkGetAddressBase tracing', () => {
|
|
|
173
174
|
0
|
|
174
175
|
);
|
|
175
176
|
|
|
176
|
-
expect(checkPassphraseStateSafety).toHaveBeenCalledWith(
|
|
177
|
+
expect(checkPassphraseStateSafety).toHaveBeenCalledWith(
|
|
178
|
+
'hidden-state',
|
|
179
|
+
false,
|
|
180
|
+
undefined,
|
|
181
|
+
true,
|
|
182
|
+
undefined
|
|
183
|
+
);
|
|
177
184
|
expect(calls).toEqual(['resume-cardano-session', 'run-cardano-method']);
|
|
178
185
|
expect(typedCall).not.toHaveBeenCalled();
|
|
179
186
|
});
|
|
@@ -212,7 +219,10 @@ describe('AllNetworkGetAddressBase tracing', () => {
|
|
|
212
219
|
bundle: [],
|
|
213
220
|
},
|
|
214
221
|
});
|
|
215
|
-
method.protocolV2UnlockContext = {
|
|
222
|
+
method.protocolV2UnlockContext = {
|
|
223
|
+
preflightCompleted: true,
|
|
224
|
+
preflightMainPinSelected: true,
|
|
225
|
+
};
|
|
216
226
|
const typedCall = jest.fn();
|
|
217
227
|
method.device = {
|
|
218
228
|
checkPassphraseStateSafety,
|
|
@@ -250,7 +260,13 @@ describe('AllNetworkGetAddressBase tracing', () => {
|
|
|
250
260
|
0
|
|
251
261
|
);
|
|
252
262
|
|
|
253
|
-
expect(checkPassphraseStateSafety).toHaveBeenCalledWith(
|
|
263
|
+
expect(checkPassphraseStateSafety).toHaveBeenCalledWith(
|
|
264
|
+
undefined,
|
|
265
|
+
true,
|
|
266
|
+
undefined,
|
|
267
|
+
undefined,
|
|
268
|
+
true
|
|
269
|
+
);
|
|
254
270
|
expect(calls).toEqual(['resume-standard-session', 'run-chain-method']);
|
|
255
271
|
expect(typedCall).not.toHaveBeenCalled();
|
|
256
272
|
});
|
|
@@ -126,6 +126,19 @@ describe('DeviceCommands failure mapping', () => {
|
|
|
126
126
|
);
|
|
127
127
|
});
|
|
128
128
|
|
|
129
|
+
it('preserves the Protocol V2 peer-removed pairing error code', async () => {
|
|
130
|
+
const commands = createCommands();
|
|
131
|
+
const transportError = Object.assign(new Error('Peer removed pairing information'), {
|
|
132
|
+
errorCode: HardwareErrorCode.BlePeerRemovedPairingInformation,
|
|
133
|
+
});
|
|
134
|
+
commands.mainId = 'main-id';
|
|
135
|
+
commands.transport = {
|
|
136
|
+
call: jest.fn().mockRejectedValue(transportError),
|
|
137
|
+
} as any;
|
|
138
|
+
|
|
139
|
+
await expect(commands._commonCall('DeviceInfoGet', {})).rejects.toBe(transportError);
|
|
140
|
+
});
|
|
141
|
+
|
|
129
142
|
it('logs canonical DeviceStatus response fields without exposing the device ID', async () => {
|
|
130
143
|
const commands = createCommands();
|
|
131
144
|
const log = getLogger(LoggerNames.DeviceCommands);
|
|
@@ -33,8 +33,6 @@ const validComponentIntegrity = {
|
|
|
33
33
|
const release: IFirmwareReleaseInfo = {
|
|
34
34
|
required: true,
|
|
35
35
|
version: [2, 0, 0],
|
|
36
|
-
url: 'https://example.com/application-p1.bin',
|
|
37
|
-
fingerprint: 'release-fingerprint',
|
|
38
36
|
changelog: {
|
|
39
37
|
'zh-CN': '更新',
|
|
40
38
|
'en-US': 'Update',
|
|
@@ -16,8 +16,6 @@ jest.mock('../src/data/config', () => ({
|
|
|
16
16
|
const release: IFirmwareReleaseInfo = {
|
|
17
17
|
required: false,
|
|
18
18
|
version: [2, 0, 0],
|
|
19
|
-
url: 'https://example.com/application-p1.okpkg',
|
|
20
|
-
fingerprint: 'release-fingerprint',
|
|
21
19
|
changelog: {
|
|
22
20
|
'zh-CN': '更新',
|
|
23
21
|
'en-US': 'Update',
|
|
@@ -2,11 +2,15 @@ import { EDeviceType, ERRORS, HardwareErrorCode, createDeferred } from '@onekeyf
|
|
|
2
2
|
import { DeviceType, TRANSPORT_EVENT } from '@onekeyfe/hd-transport';
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
|
+
cancel,
|
|
5
6
|
initConnector,
|
|
6
7
|
initCore,
|
|
8
|
+
isDeviceIdentityMismatchError,
|
|
7
9
|
isMissingDetectedProtocolV2Error,
|
|
8
10
|
isRetryableBleConnectionError,
|
|
9
11
|
isRetryableBleProtocolV2ProbeError,
|
|
12
|
+
isTerminalBleStaleBondError,
|
|
13
|
+
resolveBleConnectProtocol,
|
|
10
14
|
} from '../src/core';
|
|
11
15
|
import { DataManager } from '../src/data-manager';
|
|
12
16
|
import TransportManager from '../src/data-manager/TransportManager';
|
|
@@ -70,6 +74,19 @@ describe('public device lifecycle events', () => {
|
|
|
70
74
|
jest.restoreAllMocks();
|
|
71
75
|
});
|
|
72
76
|
|
|
77
|
+
test('prefers Protocol V2 only when the method contract is explicitly V2-only', () => {
|
|
78
|
+
const createMethod = (protocols: readonly ('V1' | 'V2')[], connectProtocol?: 'V1' | 'V2') =>
|
|
79
|
+
({
|
|
80
|
+
payload: { connectProtocol },
|
|
81
|
+
getSupportedProtocols: () => protocols,
|
|
82
|
+
} as never);
|
|
83
|
+
|
|
84
|
+
expect(resolveBleConnectProtocol(createMethod(['V2']))).toBe('V2');
|
|
85
|
+
expect(resolveBleConnectProtocol(createMethod(['V1']))).toBeUndefined();
|
|
86
|
+
expect(resolveBleConnectProtocol(createMethod(['V1', 'V2']))).toBeUndefined();
|
|
87
|
+
expect(resolveBleConnectProtocol(createMethod(['V2'], 'V1'))).toBe('V1');
|
|
88
|
+
});
|
|
89
|
+
|
|
73
90
|
test('registers the shared device lifecycle listeners exactly once', async () => {
|
|
74
91
|
jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
|
|
75
92
|
core = initCore();
|
|
@@ -105,6 +122,58 @@ describe('public device lifecycle events', () => {
|
|
|
105
122
|
expect(context.getPrePendingCallPromise('device-a')).toBe(replacementCleanup.promise);
|
|
106
123
|
});
|
|
107
124
|
|
|
125
|
+
test('cancels only requests associated with the requested connect id', () => {
|
|
126
|
+
core = initCore();
|
|
127
|
+
const context = (core as any).getCoreContext();
|
|
128
|
+
const deviceA = {
|
|
129
|
+
mainId: 'transport-session-a',
|
|
130
|
+
getConnectId: jest.fn(() => 'serial-a'),
|
|
131
|
+
interruptionFromUser: jest.fn().mockResolvedValue(undefined),
|
|
132
|
+
};
|
|
133
|
+
const deviceB = {
|
|
134
|
+
mainId: 'device-b',
|
|
135
|
+
getConnectId: jest.fn(() => 'serial-b'),
|
|
136
|
+
interruptionFromUser: jest.fn().mockResolvedValue(undefined),
|
|
137
|
+
};
|
|
138
|
+
const taskA = context.requestQueue.createTask({
|
|
139
|
+
responseID: 101,
|
|
140
|
+
connectId: '',
|
|
141
|
+
device: deviceA,
|
|
142
|
+
} as never);
|
|
143
|
+
const taskB = context.requestQueue.createTask({
|
|
144
|
+
responseID: 102,
|
|
145
|
+
connectId: 'device-b',
|
|
146
|
+
device: deviceB,
|
|
147
|
+
} as never);
|
|
148
|
+
const signalA = taskA.abortController?.signal;
|
|
149
|
+
const signalB = taskB.abortController?.signal;
|
|
150
|
+
|
|
151
|
+
cancel(context, 'serial-a');
|
|
152
|
+
|
|
153
|
+
expect(signalA?.aborted).toBe(true);
|
|
154
|
+
expect(context.requestQueue.getTask(taskA.id)).toBeUndefined();
|
|
155
|
+
expect(signalB?.aborted).toBe(false);
|
|
156
|
+
expect(context.requestQueue.getTask(taskB.id)).toBe(taskB);
|
|
157
|
+
expect(deviceA.interruptionFromUser).toHaveBeenCalledTimes(1);
|
|
158
|
+
expect(deviceB.interruptionFromUser).not.toHaveBeenCalled();
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test('aborts every request before cancel-all rejects WebUSB tasks', () => {
|
|
162
|
+
jest.spyOn(DataManager, 'getSettings').mockReturnValue('webusb' as never);
|
|
163
|
+
core = initCore();
|
|
164
|
+
const context = (core as any).getCoreContext();
|
|
165
|
+
const task = context.requestQueue.createTask({
|
|
166
|
+
responseID: 103,
|
|
167
|
+
connectId: 'webusb-device',
|
|
168
|
+
} as never);
|
|
169
|
+
const signal = task.abortController?.signal;
|
|
170
|
+
|
|
171
|
+
cancel(context);
|
|
172
|
+
|
|
173
|
+
expect(signal?.aborted).toBe(true);
|
|
174
|
+
expect(context.requestQueue.getTask(task.id)).toBeUndefined();
|
|
175
|
+
});
|
|
176
|
+
|
|
108
177
|
test('keeps shared device lifecycle listeners across a device cache reset', () => {
|
|
109
178
|
jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
|
|
110
179
|
core = initCore();
|
|
@@ -278,6 +347,7 @@ describe('public device lifecycle events', () => {
|
|
|
278
347
|
test.each([
|
|
279
348
|
[HardwareErrorCode.RuntimeError, true],
|
|
280
349
|
[HardwareErrorCode.BleDeviceBondError, false],
|
|
350
|
+
[HardwareErrorCode.BlePeerRemovedPairingInformation, false],
|
|
281
351
|
] as const)(
|
|
282
352
|
'retries a Protocol V2 probe mismatch with error code %s: %s',
|
|
283
353
|
(errorCode, expected) => {
|
|
@@ -297,6 +367,8 @@ describe('public device lifecycle events', () => {
|
|
|
297
367
|
[HardwareErrorCode.BleTimeoutError, true],
|
|
298
368
|
[HardwareErrorCode.PollingTimeout, false],
|
|
299
369
|
[HardwareErrorCode.BleDeviceBondError, false],
|
|
370
|
+
[HardwareErrorCode.BlePeerRemovedPairingInformation, false],
|
|
371
|
+
[HardwareErrorCode.BleBondInvalid, false],
|
|
300
372
|
] as const)('retries a BLE connection error with error code %s: %s', (errorCode, expected) => {
|
|
301
373
|
const method = { payload: { connectProtocol: 'V2' } } as never;
|
|
302
374
|
const error = {
|
|
@@ -307,6 +379,36 @@ describe('public device lifecycle events', () => {
|
|
|
307
379
|
expect(isRetryableBleConnectionError(method, error)).toBe(expected);
|
|
308
380
|
});
|
|
309
381
|
|
|
382
|
+
test('does not retry the desktop acquire deadline fallback', () => {
|
|
383
|
+
const method = { payload: { connectProtocol: 'V2' } } as never;
|
|
384
|
+
const error = {
|
|
385
|
+
errorCode: HardwareErrorCode.BleTimeoutError,
|
|
386
|
+
params: { acquireDeadlineExceeded: true },
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
expect(isRetryableBleConnectionError(method, error)).toBe(false);
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
test.each([
|
|
393
|
+
[HardwareErrorCode.BleDeviceBondError, true],
|
|
394
|
+
[HardwareErrorCode.BlePeerRemovedPairingInformation, true],
|
|
395
|
+
[HardwareErrorCode.BleBondInvalid, true],
|
|
396
|
+
[HardwareErrorCode.DeviceNotFound, false],
|
|
397
|
+
] as const)('treats BLE stale-bond error code %s as terminal: %s', (errorCode, expected) => {
|
|
398
|
+
const error = {
|
|
399
|
+
errorCode,
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
expect(isTerminalBleStaleBondError(error)).toBe(expected);
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
test.each([
|
|
406
|
+
[HardwareErrorCode.DeviceCheckDeviceIdError, true],
|
|
407
|
+
[HardwareErrorCode.DeviceNotFound, false],
|
|
408
|
+
] as const)('treats device identity error code %s as a mismatch: %s', (errorCode, expected) => {
|
|
409
|
+
expect(isDeviceIdentityMismatchError({ errorCode })).toBe(expected);
|
|
410
|
+
});
|
|
411
|
+
|
|
310
412
|
test('converts an internal transport disconnect into a public KnownDevice snapshot', () => {
|
|
311
413
|
jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
|
|
312
414
|
core = initCore();
|
|
@@ -32,10 +32,12 @@ const createMethod = ({
|
|
|
32
32
|
typedCall,
|
|
33
33
|
supportedMessages = [60802, 60805, 60808, 61500],
|
|
34
34
|
useFullBundle = false,
|
|
35
|
+
firmwareVersion = '1.0.0',
|
|
35
36
|
}: {
|
|
36
37
|
typedCall: jest.Mock;
|
|
37
38
|
supportedMessages?: number[];
|
|
38
39
|
useFullBundle?: boolean;
|
|
40
|
+
firmwareVersion?: string;
|
|
39
41
|
}) => {
|
|
40
42
|
const method = new DeviceUploadNft({
|
|
41
43
|
id: 1,
|
|
@@ -52,6 +54,7 @@ const createMethod = ({
|
|
|
52
54
|
});
|
|
53
55
|
(method as any).device = {
|
|
54
56
|
commands: { typedCall },
|
|
57
|
+
state: { versions: { firmware: firmwareVersion } },
|
|
55
58
|
ensureProtocolV2RuntimeContext: jest.fn(() =>
|
|
56
59
|
Promise.resolve({
|
|
57
60
|
version: 2,
|
|
@@ -60,6 +63,7 @@ const createMethod = ({
|
|
|
60
63
|
})
|
|
61
64
|
),
|
|
62
65
|
getCurrentFirmwareType: jest.fn(),
|
|
66
|
+
getCurrentFirmwareVersionString: jest.fn(() => firmwareVersion),
|
|
63
67
|
};
|
|
64
68
|
method.postMessage = jest.fn();
|
|
65
69
|
|
|
@@ -202,6 +206,70 @@ describe('DeviceUploadNft', () => {
|
|
|
202
206
|
});
|
|
203
207
|
});
|
|
204
208
|
|
|
209
|
+
test('uploads one host asset package on firmware 1.0.1', async () => {
|
|
210
|
+
const typedCall = jest.fn((request: string, _response: string, params: any) => {
|
|
211
|
+
if (request === 'FilesystemFileWrite') return fileWriteSuccess(params);
|
|
212
|
+
if (request === 'NftUpdate') return { message: { message: 'NFT updated' } };
|
|
213
|
+
throw new Error(`Unexpected request: ${request}`);
|
|
214
|
+
});
|
|
215
|
+
const method = createMethod({
|
|
216
|
+
typedCall,
|
|
217
|
+
supportedMessages: [60805, 61500],
|
|
218
|
+
firmwareVersion: '1.0.1',
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
const result = await method.run();
|
|
222
|
+
|
|
223
|
+
const requests = typedCall.mock.calls.map(call => call[0]);
|
|
224
|
+
expect(requests).not.toContain('FilesystemPathInfoQuery');
|
|
225
|
+
expect(requests).not.toContain('FilesystemDirList');
|
|
226
|
+
const fileWrites = typedCall.mock.calls.filter(call => call[0] === 'FilesystemFileWrite');
|
|
227
|
+
expect(new Set(fileWrites.map(call => call[2].file.path))).toEqual(
|
|
228
|
+
new Set(['vol1:/nft/nft-deadbeef-1760000000000.okpkg'])
|
|
229
|
+
);
|
|
230
|
+
expect(fileWrites[0][2].file.data.subarray(0, 4)).toEqual(
|
|
231
|
+
new Uint8Array([0x4f, 0x4b, 0x50, 0x50])
|
|
232
|
+
);
|
|
233
|
+
expect(typedCall).toHaveBeenLastCalledWith(
|
|
234
|
+
'NftUpdate',
|
|
235
|
+
'Success',
|
|
236
|
+
{ file_name_no_ext: result.basename },
|
|
237
|
+
{ timeoutMs: 15_000 }
|
|
238
|
+
);
|
|
239
|
+
expect(result).toMatchObject({
|
|
240
|
+
imagePath: 'vol1:/nft/nft-deadbeef-1760000000000.bin',
|
|
241
|
+
thumbnailPath: 'vol1:/nft/nft-deadbeef-1760000000000_m.bin',
|
|
242
|
+
metadataPath: 'vol1:/nft/nft-deadbeef-1760000000000.json',
|
|
243
|
+
nftUpdated: true,
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
test('keeps the legacy upload flow on a 1.0.1 prerelease', async () => {
|
|
248
|
+
const typedCall = jest.fn((request: string, _response: string, params: any) => {
|
|
249
|
+
if (request === 'FilesystemPathInfoQuery') {
|
|
250
|
+
return { message: { exist: true, directory: true } };
|
|
251
|
+
}
|
|
252
|
+
if (request === 'FilesystemDirList') {
|
|
253
|
+
return { message: { path: 'vol1:/nft', child_files: '' } };
|
|
254
|
+
}
|
|
255
|
+
if (request === 'FilesystemFileWrite') return fileWriteSuccess(params);
|
|
256
|
+
if (request === 'NftUpdate') return { message: {} };
|
|
257
|
+
throw new Error(`Unexpected request: ${request}`);
|
|
258
|
+
});
|
|
259
|
+
const method = createMethod({ typedCall, firmwareVersion: '1.0.1-beta.1' });
|
|
260
|
+
|
|
261
|
+
await method.run();
|
|
262
|
+
|
|
263
|
+
const requests = typedCall.mock.calls.map(call => call[0]);
|
|
264
|
+
expect(requests).toContain('FilesystemPathInfoQuery');
|
|
265
|
+
expect(requests).toContain('FilesystemDirList');
|
|
266
|
+
const paths = typedCall.mock.calls
|
|
267
|
+
.filter(call => call[0] === 'FilesystemFileWrite')
|
|
268
|
+
.map(call => call[2].file.path as string);
|
|
269
|
+
expect(paths.some(path => path.endsWith('.okpkg'))).toBe(false);
|
|
270
|
+
expect(paths).toContain('vol1:/nft/nft-deadbeef-1760000000000.bin');
|
|
271
|
+
});
|
|
272
|
+
|
|
205
273
|
test('treats a missing NFT directory as empty before the first upload', async () => {
|
|
206
274
|
const typedCall = jest.fn((request: string, _response: string, params: any) => {
|
|
207
275
|
if (request === 'FilesystemPathInfoQuery') {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { EDeviceType } from '@onekeyfe/hd-shared';
|
|
2
|
+
|
|
1
3
|
import EVMSignTypedData from '../src/api/evm/EVMSignTypedData';
|
|
2
4
|
|
|
3
5
|
import type { EthereumSignTypedDataMessage, EthereumSignTypedDataTypes } from '../src/types';
|
|
@@ -577,3 +579,43 @@ describe('EVMSignTypedData — OneKey Pro Safe Protocol V1', () => {
|
|
|
577
579
|
});
|
|
578
580
|
});
|
|
579
581
|
});
|
|
582
|
+
|
|
583
|
+
describe('EVMSignTypedData — Protocol V2 data size routing', () => {
|
|
584
|
+
const buildSafeTxData = (
|
|
585
|
+
dataSize: number
|
|
586
|
+
): EthereumSignTypedDataMessage<EthereumSignTypedDataTypes> =>
|
|
587
|
+
({
|
|
588
|
+
types: {
|
|
589
|
+
EIP712Domain: [],
|
|
590
|
+
SafeTx: [{ name: 'data', type: 'bytes' }],
|
|
591
|
+
},
|
|
592
|
+
primaryType: 'SafeTx',
|
|
593
|
+
domain: {},
|
|
594
|
+
message: { data: `0x${'ab'.repeat(dataSize)}` },
|
|
595
|
+
} as EthereumSignTypedDataMessage<EthereumSignTypedDataTypes>);
|
|
596
|
+
|
|
597
|
+
test.each([EDeviceType.Pro2, EDeviceType.Neo])(
|
|
598
|
+
'keeps SafeTx data up to 1536 bytes on the structured route for %s',
|
|
599
|
+
deviceType => {
|
|
600
|
+
const data = buildSafeTxData(1316);
|
|
601
|
+
const method = createMethod(data);
|
|
602
|
+
method.device.getCurrentDeviceType = jest.fn(() => deviceType);
|
|
603
|
+
method.device.getCurrentFirmwareVersionString = jest.fn(() => '1.0.0');
|
|
604
|
+
|
|
605
|
+
expect(method.hasBiggerData(data)).toBe(false);
|
|
606
|
+
expect(method.hasBiggerData(buildSafeTxData(1536))).toBe(false);
|
|
607
|
+
}
|
|
608
|
+
);
|
|
609
|
+
|
|
610
|
+
test.each([EDeviceType.Pro2, EDeviceType.Neo])(
|
|
611
|
+
'falls back to the hash route above 1536 bytes for %s',
|
|
612
|
+
deviceType => {
|
|
613
|
+
const data = buildSafeTxData(1537);
|
|
614
|
+
const method = createMethod(data);
|
|
615
|
+
method.device.getCurrentDeviceType = jest.fn(() => deviceType);
|
|
616
|
+
method.device.getCurrentFirmwareVersionString = jest.fn(() => '1.0.0');
|
|
617
|
+
|
|
618
|
+
expect(method.hasBiggerData(data)).toBe(true);
|
|
619
|
+
}
|
|
620
|
+
);
|
|
621
|
+
});
|