@onekeyfe/hd-core 1.1.27-alpha.41 → 1.1.27-alpha.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/__tests__/DeviceCommands.test.ts +99 -0
  2. package/__tests__/evmLedgerLegacySafety.test.ts +261 -0
  3. package/__tests__/logBlockEvent.test.ts +37 -0
  4. package/__tests__/preInitialize.test.ts +22 -0
  5. package/__tests__/protocol-v2.test.ts +139 -27
  6. package/dist/api/BaseMethod.d.ts +7 -1
  7. package/dist/api/BaseMethod.d.ts.map +1 -1
  8. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  9. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  10. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  11. package/dist/api/alephium/AlephiumSignMessage.d.ts.map +1 -1
  12. package/dist/api/alephium/AlephiumSignTransaction.d.ts.map +1 -1
  13. package/dist/api/algo/AlgoSignTransaction.d.ts.map +1 -1
  14. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  15. package/dist/api/aptos/AptosSignInMessage.d.ts.map +1 -1
  16. package/dist/api/aptos/AptosSignMessage.d.ts.map +1 -1
  17. package/dist/api/aptos/AptosSignTransaction.d.ts.map +1 -1
  18. package/dist/api/benfen/BenfenSignMessage.d.ts.map +1 -1
  19. package/dist/api/benfen/BenfenSignTransaction.d.ts.map +1 -1
  20. package/dist/api/btc/BTCSignMessage.d.ts.map +1 -1
  21. package/dist/api/btc/BTCSignPsbt.d.ts.map +1 -1
  22. package/dist/api/btc/BTCSignTransaction.d.ts.map +1 -1
  23. package/dist/api/cardano/CardanoSignMessage.d.ts.map +1 -1
  24. package/dist/api/cardano/CardanoSignTransaction.d.ts.map +1 -1
  25. package/dist/api/conflux/ConfluxSignMessage.d.ts.map +1 -1
  26. package/dist/api/conflux/ConfluxSignMessageCIP23.d.ts.map +1 -1
  27. package/dist/api/conflux/ConfluxSignTransaction.d.ts.map +1 -1
  28. package/dist/api/cosmos/CosmosSignTransaction.d.ts.map +1 -1
  29. package/dist/api/device/DeviceLock.d.ts.map +1 -1
  30. package/dist/api/device/PreInitialize.d.ts +6 -0
  31. package/dist/api/device/PreInitialize.d.ts.map +1 -0
  32. package/dist/api/dynex/DnxSignTransaction.d.ts.map +1 -1
  33. package/dist/api/evm/EVMSignMessage.d.ts.map +1 -1
  34. package/dist/api/evm/EVMSignMessageEIP712.d.ts.map +1 -1
  35. package/dist/api/evm/EVMSignTransaction.d.ts.map +1 -1
  36. package/dist/api/evm/EVMSignTypedData.d.ts.map +1 -1
  37. package/dist/api/filecoin/FilecoinSignTransaction.d.ts.map +1 -1
  38. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +2 -10
  39. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  40. package/dist/api/index.d.ts +1 -0
  41. package/dist/api/index.d.ts.map +1 -1
  42. package/dist/api/kaspa/KaspaSignTransaction.d.ts.map +1 -1
  43. package/dist/api/near/NearSignTransaction.d.ts.map +1 -1
  44. package/dist/api/nem/NEMSignTransaction.d.ts.map +1 -1
  45. package/dist/api/neo/NeoSignTransaction.d.ts.map +1 -1
  46. package/dist/api/nervos/NervosSignTransaction.d.ts.map +1 -1
  47. package/dist/api/nexa/NexaSignTransaction.d.ts.map +1 -1
  48. package/dist/api/nostr/NostrSignEvent.d.ts.map +1 -1
  49. package/dist/api/nostr/NostrSignSchnorr.d.ts.map +1 -1
  50. package/dist/api/polkadot/PolkadotSignTransaction.d.ts.map +1 -1
  51. package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts +1 -1
  52. package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts.map +1 -1
  53. package/dist/api/protocol-v2/FilesystemDiskControl.d.ts +1 -1
  54. package/dist/api/scdo/ScdoSignMessage.d.ts.map +1 -1
  55. package/dist/api/scdo/ScdoSignTransaction.d.ts.map +1 -1
  56. package/dist/api/solana/SolSignMessage.d.ts.map +1 -1
  57. package/dist/api/solana/SolSignOffchainMessage.d.ts.map +1 -1
  58. package/dist/api/solana/SolSignTransaction.d.ts.map +1 -1
  59. package/dist/api/starcoin/StarcoinSignMessage.d.ts.map +1 -1
  60. package/dist/api/starcoin/StarcoinSignTransaction.d.ts.map +1 -1
  61. package/dist/api/stellar/StellarSignTransaction.d.ts.map +1 -1
  62. package/dist/api/sui/SuiGetAddress.d.ts +3 -0
  63. package/dist/api/sui/SuiGetAddress.d.ts.map +1 -1
  64. package/dist/api/sui/SuiGetPublicKey.d.ts +3 -0
  65. package/dist/api/sui/SuiGetPublicKey.d.ts.map +1 -1
  66. package/dist/api/sui/SuiSignMessage.d.ts +3 -0
  67. package/dist/api/sui/SuiSignMessage.d.ts.map +1 -1
  68. package/dist/api/sui/SuiSignTransaction.d.ts +3 -0
  69. package/dist/api/sui/SuiSignTransaction.d.ts.map +1 -1
  70. package/dist/api/ton/TonGetAddress.d.ts +3 -0
  71. package/dist/api/ton/TonGetAddress.d.ts.map +1 -1
  72. package/dist/api/ton/TonSignData.d.ts +5 -0
  73. package/dist/api/ton/TonSignData.d.ts.map +1 -1
  74. package/dist/api/ton/TonSignMessage.d.ts +3 -0
  75. package/dist/api/ton/TonSignMessage.d.ts.map +1 -1
  76. package/dist/api/ton/TonSignProof.d.ts +3 -0
  77. package/dist/api/ton/TonSignProof.d.ts.map +1 -1
  78. package/dist/api/tron/TronSignMessage.d.ts.map +1 -1
  79. package/dist/api/tron/TronSignTransaction.d.ts.map +1 -1
  80. package/dist/api/xrp/XrpSignTransaction.d.ts.map +1 -1
  81. package/dist/core/PollingStateManager.d.ts +8 -0
  82. package/dist/core/PollingStateManager.d.ts.map +1 -0
  83. package/dist/core/RequestQueue.d.ts +1 -1
  84. package/dist/core/RequestQueue.d.ts.map +1 -1
  85. package/dist/core/index.d.ts.map +1 -1
  86. package/dist/device/Device.d.ts +17 -2
  87. package/dist/device/Device.d.ts.map +1 -1
  88. package/dist/events/logBlockEvent.d.ts +1 -0
  89. package/dist/events/logBlockEvent.d.ts.map +1 -1
  90. package/dist/index.d.ts +25 -5
  91. package/dist/index.js +928 -407
  92. package/dist/types/api/index.d.ts +2 -0
  93. package/dist/types/api/index.d.ts.map +1 -1
  94. package/dist/types/api/preInitialize.d.ts +3 -0
  95. package/dist/types/api/preInitialize.d.ts.map +1 -0
  96. package/dist/types/api/protocolV2.d.ts +2 -2
  97. package/dist/types/api/protocolV2.d.ts.map +1 -1
  98. package/dist/types/params.d.ts +1 -0
  99. package/dist/types/params.d.ts.map +1 -1
  100. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  101. package/dist/utils/patch.d.ts +1 -1
  102. package/dist/utils/patch.d.ts.map +1 -1
  103. package/package.json +4 -4
  104. package/src/api/BaseMethod.ts +82 -2
  105. package/src/api/FirmwareUpdateV3.ts +0 -4
  106. package/src/api/FirmwareUpdateV4.ts +1 -19
  107. package/src/api/GetPassphraseState.ts +4 -3
  108. package/src/api/alephium/AlephiumSignMessage.ts +1 -0
  109. package/src/api/alephium/AlephiumSignTransaction.ts +1 -0
  110. package/src/api/algo/AlgoSignTransaction.ts +1 -0
  111. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +8 -0
  112. package/src/api/aptos/AptosSignInMessage.ts +1 -0
  113. package/src/api/aptos/AptosSignMessage.ts +1 -0
  114. package/src/api/aptos/AptosSignTransaction.ts +1 -0
  115. package/src/api/benfen/BenfenSignMessage.ts +1 -0
  116. package/src/api/benfen/BenfenSignTransaction.ts +1 -0
  117. package/src/api/btc/BTCSignMessage.ts +1 -0
  118. package/src/api/btc/BTCSignPsbt.ts +1 -0
  119. package/src/api/btc/BTCSignTransaction.ts +1 -0
  120. package/src/api/cardano/CardanoSignMessage.ts +1 -0
  121. package/src/api/cardano/CardanoSignTransaction.ts +1 -0
  122. package/src/api/conflux/ConfluxSignMessage.ts +1 -0
  123. package/src/api/conflux/ConfluxSignMessageCIP23.ts +1 -0
  124. package/src/api/conflux/ConfluxSignTransaction.ts +1 -0
  125. package/src/api/cosmos/CosmosSignTransaction.ts +1 -0
  126. package/src/api/device/DeviceLock.ts +1 -3
  127. package/src/api/device/PreInitialize.ts +41 -0
  128. package/src/api/dynex/DnxSignTransaction.ts +1 -0
  129. package/src/api/evm/EVMSignMessage.ts +2 -0
  130. package/src/api/evm/EVMSignMessageEIP712.ts +1 -0
  131. package/src/api/evm/EVMSignTransaction.ts +2 -0
  132. package/src/api/evm/EVMSignTypedData.ts +3 -1
  133. package/src/api/filecoin/FilecoinSignTransaction.ts +1 -0
  134. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +4 -27
  135. package/src/api/index.ts +1 -0
  136. package/src/api/kaspa/KaspaSignTransaction.ts +1 -0
  137. package/src/api/near/NearSignTransaction.ts +1 -0
  138. package/src/api/nem/NEMSignTransaction.ts +1 -0
  139. package/src/api/neo/NeoSignTransaction.ts +1 -0
  140. package/src/api/nervos/NervosSignTransaction.ts +1 -0
  141. package/src/api/nexa/NexaSignTransaction.ts +2 -0
  142. package/src/api/nostr/NostrSignEvent.ts +1 -0
  143. package/src/api/nostr/NostrSignSchnorr.ts +1 -0
  144. package/src/api/polkadot/PolkadotSignTransaction.ts +1 -0
  145. package/src/api/protocol-v2/DeviceGetOnboardingStatus.ts +1 -5
  146. package/src/api/scdo/ScdoSignMessage.ts +1 -0
  147. package/src/api/scdo/ScdoSignTransaction.ts +1 -0
  148. package/src/api/solana/SolSignMessage.ts +1 -0
  149. package/src/api/solana/SolSignOffchainMessage.ts +1 -0
  150. package/src/api/solana/SolSignTransaction.ts +1 -0
  151. package/src/api/starcoin/StarcoinSignMessage.ts +1 -0
  152. package/src/api/starcoin/StarcoinSignTransaction.ts +1 -0
  153. package/src/api/stellar/StellarSignTransaction.ts +1 -0
  154. package/src/api/sui/SuiGetAddress.ts +3 -0
  155. package/src/api/sui/SuiGetPublicKey.ts +3 -0
  156. package/src/api/sui/SuiSignMessage.ts +4 -0
  157. package/src/api/sui/SuiSignTransaction.ts +4 -0
  158. package/src/api/ton/TonGetAddress.ts +3 -0
  159. package/src/api/ton/TonSignData.ts +11 -3
  160. package/src/api/ton/TonSignMessage.ts +4 -0
  161. package/src/api/ton/TonSignProof.ts +4 -0
  162. package/src/api/tron/TronSignMessage.ts +1 -0
  163. package/src/api/tron/TronSignTransaction.ts +1 -0
  164. package/src/api/xrp/XrpSignTransaction.ts +1 -0
  165. package/src/core/PollingStateManager.ts +47 -0
  166. package/src/core/RequestQueue.ts +10 -3
  167. package/src/core/index.ts +153 -34
  168. package/src/data/messages/messages-protocol-v2.json +489 -268
  169. package/src/device/Device.ts +73 -16
  170. package/src/events/logBlockEvent.ts +23 -0
  171. package/src/inject.ts +1 -1
  172. package/src/types/api/index.ts +2 -0
  173. package/src/types/api/preInitialize.ts +3 -0
  174. package/src/types/api/protocolV2.ts +2 -2
  175. package/src/types/params.ts +5 -0
  176. package/src/utils/deviceFeaturesUtils.ts +8 -17
@@ -0,0 +1,99 @@
1
+ import { HardwareErrorCode } from '@onekeyfe/hd-shared';
2
+
3
+ import { DeviceCommands } from '../src/device/DeviceCommands';
4
+
5
+ jest.mock('../src/data/config', () => ({
6
+ getSDKVersion: jest.fn(() => '1.0.0'),
7
+ DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
8
+ }));
9
+
10
+ const createCommands = () => {
11
+ const commands = Object.create(DeviceCommands.prototype) as DeviceCommands;
12
+ commands.device = {
13
+ clearCancelableAction: jest.fn(),
14
+ } as any;
15
+ return commands;
16
+ };
17
+
18
+ describe('DeviceCommands failure mapping', () => {
19
+ it.each([
20
+ ['ButtonAck', 'Not in Ethereum signing mode'],
21
+ ['PinMatrixAck', 'Not in Conflux signing mode'],
22
+ ])('keeps %s unexpected message "%s" as firmware runtime error', async (callType, message) => {
23
+ const commands = createCommands();
24
+
25
+ await expect(
26
+ commands._filterCommonTypes(
27
+ {
28
+ type: 'Failure',
29
+ message: {
30
+ code: 'Failure_UnexpectedMessage',
31
+ message,
32
+ },
33
+ } as any,
34
+ callType as any
35
+ )
36
+ ).rejects.toMatchObject({
37
+ errorCode: HardwareErrorCode.RuntimeError,
38
+ message: `Failure_UnexpectedMessage,${message}`,
39
+ });
40
+ });
41
+
42
+ it('keeps the existing NotInSigningMode mapping', async () => {
43
+ const commands = createCommands();
44
+
45
+ await expect(
46
+ commands._filterCommonTypes(
47
+ {
48
+ type: 'Failure',
49
+ message: {
50
+ code: 'Failure_UnexpectedMessage',
51
+ message: 'Not in Signing mode',
52
+ },
53
+ } as any,
54
+ 'ButtonAck'
55
+ )
56
+ ).rejects.toMatchObject({
57
+ errorCode: HardwareErrorCode.NotInSigningMode,
58
+ });
59
+ });
60
+
61
+ it('keeps the existing unexpected passphrase mapping', async () => {
62
+ const commands = createCommands();
63
+
64
+ await expect(
65
+ commands._filterCommonTypes(
66
+ {
67
+ type: 'Failure',
68
+ message: {
69
+ code: 'Failure_UnexpectedMessage',
70
+ message: 'Unexpected message',
71
+ },
72
+ } as any,
73
+ 'PassphraseAck'
74
+ )
75
+ ).rejects.toMatchObject({
76
+ errorCode: HardwareErrorCode.UnexpectPassphrase,
77
+ });
78
+ });
79
+
80
+ it('keeps non signing unexpected messages as runtime errors', async () => {
81
+ const commands = createCommands();
82
+
83
+ await expect(
84
+ commands._filterCommonTypes(
85
+ {
86
+ type: 'Failure',
87
+ message: {
88
+ code: 'Failure_UnexpectedMessage',
89
+ message: 'Not in Reset mode',
90
+ },
91
+ } as any,
92
+ 'ButtonAck'
93
+ )
94
+ ).rejects.toMatchObject({
95
+ errorCode: HardwareErrorCode.RuntimeError,
96
+ message: 'Failure_UnexpectedMessage,Not in Reset mode',
97
+ });
98
+ });
99
+ });
@@ -0,0 +1,261 @@
1
+ import AllNetworkGetAddressBase from '../src/api/allnetwork/AllNetworkGetAddressBase';
2
+ import EvmGetAddress from '../src/api/evm/EVMGetAddress';
3
+ import EVMGetPublicKey from '../src/api/evm/EVMGetPublicKey';
4
+ import { findMethod } from '../src/api/utils';
5
+
6
+ jest.mock('../src/data/config', () => ({
7
+ getSDKVersion: jest.fn(() => '1.0.0'),
8
+ DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
9
+ }));
10
+
11
+ jest.mock('../src/api/utils', () => ({
12
+ findMethod: jest.fn(),
13
+ }));
14
+
15
+ const createDevice = (onekeyDeviceType: string) => {
16
+ const typedCall = jest.fn();
17
+ return {
18
+ typedCall,
19
+ device: {
20
+ features: {
21
+ onekey_device_type: onekeyDeviceType,
22
+ safety_checks: 'Strict',
23
+ },
24
+ commands: {
25
+ typedCall,
26
+ },
27
+ },
28
+ };
29
+ };
30
+
31
+ class TestAllNetworkMethod extends AllNetworkGetAddressBase {
32
+ async getAllNetworkAddress() {
33
+ return Promise.resolve([]);
34
+ }
35
+ }
36
+
37
+ describe('EVM Ledger legacy path safety checks', () => {
38
+ it.each([
39
+ ['evmGetAddress', EvmGetAddress],
40
+ ['evmGetPublicKey', EVMGetPublicKey],
41
+ ])(
42
+ 'temporarily relaxes safety checks for Pro %s on ledger legacy path index greater than 1',
43
+ async (methodName, Method) => {
44
+ const { device, typedCall } = createDevice('PRO');
45
+ const method = new Method({
46
+ id: 1,
47
+ payload: {
48
+ method: methodName,
49
+ path: "m/44'/60'/0'/2",
50
+ },
51
+ });
52
+ method.device = device as any;
53
+
54
+ await method.checkSafetyLevelOnTestNet();
55
+
56
+ expect(typedCall).toHaveBeenCalledWith('ApplySettings', 'Success', {
57
+ safety_checks: 'PromptTemporarily',
58
+ });
59
+ }
60
+ );
61
+
62
+ it('temporarily relaxes safety checks for Touch get public key on ledger legacy path index greater than 1', async () => {
63
+ const { device, typedCall } = createDevice('TOUCH');
64
+ const method = new EVMGetPublicKey({
65
+ id: 1,
66
+ payload: {
67
+ method: 'evmGetPublicKey',
68
+ path: "m/44'/60'/0'/2",
69
+ },
70
+ });
71
+ method.device = device as any;
72
+
73
+ await method.checkSafetyLevelOnTestNet();
74
+
75
+ expect(typedCall).toHaveBeenCalledWith('ApplySettings', 'Success', {
76
+ safety_checks: 'PromptTemporarily',
77
+ });
78
+ });
79
+
80
+ it('runs EVM safety checks when allNetwork dispatches to the inner get address method', async () => {
81
+ const { device, typedCall } = createDevice('PRO');
82
+ (findMethod as jest.Mock).mockImplementation(message => new EvmGetAddress(message));
83
+ const runSpy = jest.spyOn(EvmGetAddress.prototype, 'run').mockResolvedValue([
84
+ {
85
+ path: "m/44'/60'/0'/2",
86
+ address: '0x0000000000000000000000000000000000000000',
87
+ },
88
+ ]);
89
+ const method = new TestAllNetworkMethod({
90
+ id: 1,
91
+ payload: {
92
+ method: 'allNetworkGetAddress',
93
+ connectId: 'connect-id',
94
+ deviceId: 'device-id',
95
+ bundle: [],
96
+ },
97
+ });
98
+ method.device = {
99
+ ...device,
100
+ on: jest.fn(),
101
+ off: jest.fn(),
102
+ } as any;
103
+
104
+ await method.callMethod(
105
+ 'evmGetAddress',
106
+ {
107
+ bundle: [
108
+ {
109
+ path: "m/44'/60'/0'/2",
110
+ showOnOneKey: false,
111
+ chainId: 1,
112
+ _originRequestParams: {
113
+ network: 'evm',
114
+ path: "m/44'/60'/0'/2",
115
+ showOnOneKey: false,
116
+ chainName: '1',
117
+ },
118
+ },
119
+ ],
120
+ },
121
+ 0
122
+ );
123
+
124
+ expect(typedCall).toHaveBeenCalledWith('ApplySettings', 'Success', {
125
+ safety_checks: 'PromptTemporarily',
126
+ });
127
+
128
+ runSpy.mockRestore();
129
+ });
130
+
131
+ it('only applies temporary safety checks once during one allNetwork request even when features stay strict', async () => {
132
+ const { device, typedCall } = createDevice('PRO');
133
+ (findMethod as jest.Mock).mockImplementation(message => new EvmGetAddress(message));
134
+ const runSpy = jest
135
+ .spyOn(EvmGetAddress.prototype, 'run')
136
+ .mockResolvedValueOnce([
137
+ {
138
+ path: "m/44'/60'/0'/2",
139
+ address: '0x0000000000000000000000000000000000000002',
140
+ },
141
+ ])
142
+ .mockResolvedValueOnce([
143
+ {
144
+ path: "m/44'/60'/0'/3",
145
+ address: '0x0000000000000000000000000000000000000003',
146
+ },
147
+ ]);
148
+ const method = new TestAllNetworkMethod({
149
+ id: 1,
150
+ payload: {
151
+ method: 'allNetworkGetAddressByLoop',
152
+ connectId: 'connect-id',
153
+ deviceId: 'device-id',
154
+ bundle: [],
155
+ },
156
+ });
157
+ method.device = {
158
+ ...device,
159
+ on: jest.fn(),
160
+ off: jest.fn(),
161
+ } as any;
162
+
163
+ await method.callMethod(
164
+ 'evmGetAddress',
165
+ {
166
+ bundle: [
167
+ {
168
+ path: "m/44'/60'/0'/2",
169
+ showOnOneKey: false,
170
+ chainId: 1,
171
+ _originRequestParams: {
172
+ network: 'evm',
173
+ path: "m/44'/60'/0'/2",
174
+ showOnOneKey: false,
175
+ chainName: '1',
176
+ },
177
+ },
178
+ ],
179
+ },
180
+ 0
181
+ );
182
+
183
+ await method.callMethod(
184
+ 'evmGetAddress',
185
+ {
186
+ bundle: [
187
+ {
188
+ path: "m/44'/60'/0'/3",
189
+ showOnOneKey: false,
190
+ chainId: 1,
191
+ _originRequestParams: {
192
+ network: 'evm',
193
+ path: "m/44'/60'/0'/3",
194
+ showOnOneKey: false,
195
+ chainName: '1',
196
+ },
197
+ },
198
+ ],
199
+ },
200
+ 0
201
+ );
202
+
203
+ expect(typedCall).toHaveBeenCalledTimes(1);
204
+ expect(typedCall).toHaveBeenCalledWith('ApplySettings', 'Success', {
205
+ safety_checks: 'PromptTemporarily',
206
+ });
207
+
208
+ runSpy.mockRestore();
209
+ });
210
+
211
+ it.each(["m/44'/60'/0'/0", "m/44'/60'/0'/1"])(
212
+ 'keeps safety checks unchanged for legal ledger legacy path %s',
213
+ async path => {
214
+ const { device, typedCall } = createDevice('PRO');
215
+ const method = new EvmGetAddress({
216
+ id: 1,
217
+ payload: {
218
+ method: 'evmGetAddress',
219
+ path,
220
+ },
221
+ });
222
+ method.device = device as any;
223
+
224
+ await method.checkSafetyLevelOnTestNet();
225
+
226
+ expect(typedCall).not.toHaveBeenCalled();
227
+ }
228
+ );
229
+
230
+ it('keeps safety checks unchanged for standard 5-segment BIP44 paths', async () => {
231
+ const { device, typedCall } = createDevice('PRO');
232
+ const method = new EvmGetAddress({
233
+ id: 1,
234
+ payload: {
235
+ method: 'evmGetAddress',
236
+ path: "m/44'/60'/0'/0/2",
237
+ },
238
+ });
239
+ method.device = device as any;
240
+
241
+ await method.checkSafetyLevelOnTestNet();
242
+
243
+ expect(typedCall).not.toHaveBeenCalled();
244
+ });
245
+
246
+ it('keeps safety checks unchanged on non Pro/Touch devices', async () => {
247
+ const { device, typedCall } = createDevice('MINI');
248
+ const method = new EvmGetAddress({
249
+ id: 1,
250
+ payload: {
251
+ method: 'evmGetAddress',
252
+ path: "m/44'/60'/0'/2",
253
+ },
254
+ });
255
+ method.device = device as any;
256
+
257
+ await method.checkSafetyLevelOnTestNet();
258
+
259
+ expect(typedCall).not.toHaveBeenCalled();
260
+ });
261
+ });
@@ -0,0 +1,37 @@
1
+ import { UI_RESPONSE, getLogBlockLabel } from '../src/events';
2
+
3
+ describe('getLogBlockLabel', () => {
4
+ it('blocks evmSignTypedData params before logging large typed data', () => {
5
+ expect(
6
+ getLogBlockLabel({
7
+ method: 'evmSignTypedData',
8
+ data: {
9
+ message: {
10
+ data: `0x${'ab'.repeat(4096)}`,
11
+ },
12
+ },
13
+ })
14
+ ).toBe('evmSignTypedData');
15
+ });
16
+
17
+ it('blocks evmSignTypedData iframe call payload before bridge logging', () => {
18
+ expect(
19
+ getLogBlockLabel({
20
+ event: 'iframe-call',
21
+ type: 'iframe-call',
22
+ payload: {
23
+ method: 'evmSignTypedData',
24
+ data: {
25
+ message: {
26
+ data: `0x${'ab'.repeat(4096)}`,
27
+ },
28
+ },
29
+ },
30
+ })
31
+ ).toBe('evmSignTypedData');
32
+ });
33
+
34
+ it('keeps existing sensitive UI response blocking', () => {
35
+ expect(getLogBlockLabel({ type: UI_RESPONSE.RECEIVE_PIN })).toBe(UI_RESPONSE.RECEIVE_PIN);
36
+ });
37
+ });
@@ -0,0 +1,22 @@
1
+ import { Device } from '../src/device/Device';
2
+
3
+ jest.mock('../src/data/config', () => ({
4
+ getSDKVersion: jest.fn(() => '1.0.0'),
5
+ DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
6
+ }));
7
+
8
+ describe('preInitialize', () => {
9
+ it('matches pre-initialized state by passphraseState only', () => {
10
+ const device = Object.create(Device.prototype) as Device;
11
+
12
+ device.markPreInitialized({
13
+ passphraseState: 'passphrase-state',
14
+ });
15
+
16
+ expect(
17
+ device.isPreInitializeMetaMatch({
18
+ passphraseState: 'passphrase-state',
19
+ })
20
+ ).toBe(true);
21
+ });
22
+ });
@@ -17,8 +17,15 @@ import GetDeviceInfo from '../src/api/GetDeviceInfo';
17
17
  import GetPassphraseState from '../src/api/GetPassphraseState';
18
18
  import GetOnekeyFeatures from '../src/api/GetOnekeyFeatures';
19
19
  import { batchGetPublickeys } from '../src/api/helpers/batchGetPublickeys';
20
+ import SuiGetAddress from '../src/api/sui/SuiGetAddress';
21
+ import SuiGetPublicKey from '../src/api/sui/SuiGetPublicKey';
22
+ import SuiSignMessage from '../src/api/sui/SuiSignMessage';
20
23
  import SuiSignTransaction from '../src/api/sui/SuiSignTransaction';
21
24
  import SolGetAddress from '../src/api/solana/SolGetAddress';
25
+ import TonGetAddress from '../src/api/ton/TonGetAddress';
26
+ import TonSignData from '../src/api/ton/TonSignData';
27
+ import TonSignMessage from '../src/api/ton/TonSignMessage';
28
+ import TonSignProof from '../src/api/ton/TonSignProof';
22
29
  import TronGetAddress from '../src/api/tron/TronGetAddress';
23
30
  import TronSignMessage from '../src/api/tron/TronSignMessage';
24
31
  import XrpSignTransaction from '../src/api/xrp/XrpSignTransaction';
@@ -133,8 +140,9 @@ describe('Protocol V2 feature adapter', () => {
133
140
  expect(features.ble_enable).toBe(true);
134
141
  });
135
142
 
136
- test('uses GetPassphraseState payloads compatible with Pro1 passphrase flow', async () => {
143
+ test('uses GetPassphraseState payloads compatible with Pro series passphrase flow', async () => {
137
144
  const features = normalizeProtocolV2Features(descriptor as any);
145
+ features.onekey_firmware_version = '4.15.0';
138
146
  const typedCall = jest.fn().mockResolvedValue({
139
147
  type: 'PassphraseState',
140
148
  message: {
@@ -229,6 +237,8 @@ describe('Protocol V2 feature adapter', () => {
229
237
  ...descriptor,
230
238
  protocolType: 'V2',
231
239
  } as any);
240
+ (device as any).features.onekey_firmware_version = '4.15.0';
241
+ (device as any).features.passphrase_protection = true;
232
242
  (device as any).commands = { typedCall };
233
243
 
234
244
  await expect(getPassphraseStateWithRefreshDeviceInfo(device)).resolves.toMatchObject({
@@ -238,7 +248,7 @@ describe('Protocol V2 feature adapter', () => {
238
248
 
239
249
  expect(device.passphraseState).toBeUndefined();
240
250
  expect(device.features?.passphrase_protection).toBe(true);
241
- expect(device.features?.session_id).toBe('session-auto');
251
+ expect(device.features?.session_id).toBeNull();
242
252
  expect(device.getInternalState()).toBeUndefined();
243
253
  device.passphraseState = 'state-auto';
244
254
  expect(device.getInternalState()).toBe('session-auto');
@@ -268,6 +278,7 @@ describe('Protocol V2 feature adapter', () => {
268
278
  },
269
279
  }
270
280
  );
281
+ (device as any).features.onekey_firmware_version = '4.15.0';
271
282
  (device as any).commands = { typedCall };
272
283
 
273
284
  await expect(
@@ -278,7 +289,7 @@ describe('Protocol V2 feature adapter', () => {
278
289
  });
279
290
 
280
291
  expect(device.features?.passphrase_protection).toBe(false);
281
- expect(device.features?.session_id).toBe('main-pin-session');
292
+ expect(device.features?.session_id).toBeNull();
282
293
  expect(device.getInternalState()).toBeUndefined();
283
294
  expect(typedCall).toHaveBeenLastCalledWith('GetPassphraseState', 'PassphraseState', {
284
295
  _only_main_pin: true,
@@ -300,6 +311,8 @@ describe('Protocol V2 feature adapter', () => {
300
311
  ...descriptor,
301
312
  protocolType: 'V2',
302
313
  } as any);
314
+ (device as any).features.onekey_firmware_version = '4.15.0';
315
+ (device as any).features.passphrase_protection = true;
303
316
  (device as any).commands = { typedCall };
304
317
 
305
318
  await expect(device.checkPassphraseStateSafety('expected-state', false, true)).resolves.toBe(
@@ -307,7 +320,7 @@ describe('Protocol V2 feature adapter', () => {
307
320
  );
308
321
 
309
322
  expect(device.getInternalState()).toBeUndefined();
310
- expect(typedCall).toHaveBeenLastCalledWith('GetPassphraseState', 'PassphraseState', {
323
+ expect(typedCall).toHaveBeenNthCalledWith(1, 'GetPassphraseState', 'PassphraseState', {
311
324
  passphrase_state: 'expected-state',
312
325
  });
313
326
  });
@@ -676,7 +689,7 @@ describe('API compatibility handling', () => {
676
689
  );
677
690
  });
678
691
 
679
- test('does not mark Pro2 Tron and Solana address methods as unsupported', () => {
692
+ test('does not mark Pro2 Tron, Solana, TON and SUI methods as unsupported', () => {
680
693
  const features = {
681
694
  onekey_device_type: 'pro2',
682
695
  } as Features;
@@ -697,6 +710,66 @@ describe('API compatibility handling', () => {
697
710
  showOnOneKey: false,
698
711
  },
699
712
  });
713
+ const tonGetAddressMethod = new TonGetAddress({
714
+ id: 3,
715
+ payload: {
716
+ method: 'tonGetAddress',
717
+ path: "m/44'/607'/0'",
718
+ showOnOneKey: false,
719
+ },
720
+ });
721
+ const tonSignMessageMethod = new TonSignMessage({
722
+ id: 4,
723
+ payload: {
724
+ method: 'tonSignMessage',
725
+ path: "m/44'/607'/0'",
726
+ },
727
+ });
728
+ const tonSignProofMethod = new TonSignProof({
729
+ id: 5,
730
+ payload: {
731
+ method: 'tonSignProof',
732
+ path: "m/44'/607'/0'",
733
+ },
734
+ });
735
+ const tonSignDataMethod = new TonSignData({
736
+ id: 6,
737
+ payload: {
738
+ method: 'tonSignData',
739
+ path: "m/44'/607'/0'",
740
+ },
741
+ });
742
+ const suiGetAddressMethod = new SuiGetAddress({
743
+ id: 7,
744
+ payload: {
745
+ method: 'suiGetAddress',
746
+ path: "m/44'/784'/0'/0'/0'",
747
+ showOnOneKey: false,
748
+ },
749
+ });
750
+ const suiGetPublicKeyMethod = new SuiGetPublicKey({
751
+ id: 8,
752
+ payload: {
753
+ method: 'suiGetPublicKey',
754
+ path: "m/44'/784'/0'/0'/0'",
755
+ },
756
+ });
757
+ const suiSignMessageMethod = new SuiSignMessage({
758
+ id: 9,
759
+ payload: {
760
+ method: 'suiSignMessage',
761
+ path: "m/44'/784'/0'/0'/0'",
762
+ messageHex: '0x1234',
763
+ },
764
+ });
765
+ const suiSignTransactionMethod = new SuiSignTransaction({
766
+ id: 10,
767
+ payload: {
768
+ method: 'suiSignTransaction',
769
+ path: "m/44'/784'/0'/0'/0'",
770
+ rawTx: '0x1234',
771
+ },
772
+ });
700
773
 
701
774
  expect(
702
775
  isMethodVersionRangeUnsupported(
@@ -708,6 +781,48 @@ describe('API compatibility handling', () => {
708
781
  getMethodVersionRange(features, type => solMethod.getVersionRange()[type])
709
782
  )
710
783
  ).toBe(false);
784
+ expect(getMethodVersionRange(features, type => tonGetAddressMethod.getVersionRange()[type]))
785
+ .toEqual({
786
+ min: '0.0.0',
787
+ });
788
+ expect(getMethodVersionRange(features, type => tonSignMessageMethod.getVersionRange()[type]))
789
+ .toEqual({
790
+ min: '0.0.0',
791
+ });
792
+ expect(getMethodVersionRange(features, type => tonSignProofMethod.getVersionRange()[type]))
793
+ .toEqual({
794
+ min: '0.0.0',
795
+ });
796
+ expect(getMethodVersionRange(features, type => tonSignDataMethod.getVersionRange()[type]))
797
+ .toEqual({
798
+ min: '0.0.0',
799
+ });
800
+ expect(getMethodVersionRange(features, type => suiGetAddressMethod.getVersionRange()[type]))
801
+ .toEqual({
802
+ min: '0.0.0',
803
+ });
804
+ expect(getMethodVersionRange(features, type => suiGetPublicKeyMethod.getVersionRange()[type]))
805
+ .toEqual({
806
+ min: '0.0.0',
807
+ });
808
+ expect(getMethodVersionRange(features, type => suiSignMessageMethod.getVersionRange()[type]))
809
+ .toEqual({
810
+ min: '0.0.0',
811
+ });
812
+ expect(
813
+ getMethodVersionRange(features, type => suiSignTransactionMethod.getVersionRange()[type])
814
+ ).toEqual({
815
+ min: '0.0.0',
816
+ });
817
+ });
818
+
819
+ test('includes TON signData in the Protocol V2 protobuf schema', () => {
820
+ const protocolV2Messages = DataManager.getProtobufMessages('v2Schema') as any;
821
+
822
+ expect(protocolV2Messages.nested.TonSignData).toBeDefined();
823
+ expect(protocolV2Messages.nested.TonSignedData).toBeDefined();
824
+ expect(protocolV2Messages.nested.MessageType.values.MessageType_TonSignData).toBe(11908);
825
+ expect(protocolV2Messages.nested.MessageType.values.MessageType_TonSignedData).toBe(11909);
711
826
  });
712
827
 
713
828
  test('uses chunk transfer for large Sui transactions on Protocol V2', async () => {
@@ -1161,7 +1276,6 @@ describe('Protocol V2 firmware update targets', () => {
1161
1276
  filePath: 'vol1:firmware.bin',
1162
1277
  processedSize: 0,
1163
1278
  totalSize: 4097,
1164
- transferStartTime: Date.now() - 1000,
1165
1279
  });
1166
1280
 
1167
1281
  const writePayloads = typedCall.mock.calls.map(call => call[2]);
@@ -1169,16 +1283,6 @@ describe('Protocol V2 firmware update targets', () => {
1169
1283
  expect(writePayloads.map(payload => payload.file.data.byteLength)).toEqual([4096, 1]);
1170
1284
  expect(writePayloads.map(payload => payload.overwrite)).toEqual([true, false]);
1171
1285
  expect(writePayloads.every(payload => payload.append === false)).toBe(true);
1172
- expect(method.postProgressMessage).toHaveBeenLastCalledWith(
1173
- 99,
1174
- 'transferData',
1175
- expect.objectContaining({
1176
- transferredBytes: 4097,
1177
- totalBytes: 4097,
1178
- rateBytesPerSecond: expect.any(Number),
1179
- elapsedMs: expect.any(Number),
1180
- })
1181
- );
1182
1286
  });
1183
1287
 
1184
1288
  test('caps native BLE firmware upload chunks below the WebUSB limit', async () => {
@@ -1358,7 +1462,7 @@ describe('Protocol V2 firmware update method', () => {
1358
1462
  });
1359
1463
 
1360
1464
  describe('Protocol V2 onboarding status method', () => {
1361
- test('returns DeviceOnboardingStatus from low-level status query', async () => {
1465
+ test('returns OnboardingStatus from low-level status query', async () => {
1362
1466
  const method = new DeviceGetOnboardingStatus({
1363
1467
  id: 1,
1364
1468
  payload: {
@@ -1368,10 +1472,16 @@ describe('Protocol V2 onboarding status method', () => {
1368
1472
  method.init();
1369
1473
 
1370
1474
  const typedCall = jest.fn().mockResolvedValue({
1371
- type: 'DeviceOnboardingStatus',
1475
+ type: 'OnboardingStatus',
1372
1476
  message: {
1373
- step: 4,
1374
- page_name: 'Recovery Phrase',
1477
+ step: 3,
1478
+ setup: {
1479
+ restore: {
1480
+ mnemonic: true,
1481
+ },
1482
+ },
1483
+ detail_code: 7,
1484
+ detail_str: 'Recovery Phrase',
1375
1485
  },
1376
1486
  });
1377
1487
 
@@ -1380,14 +1490,16 @@ describe('Protocol V2 onboarding status method', () => {
1380
1490
  };
1381
1491
 
1382
1492
  await expect(method.run()).resolves.toEqual({
1383
- step: 4,
1384
- page_name: 'Recovery Phrase',
1493
+ step: 3,
1494
+ setup: {
1495
+ restore: {
1496
+ mnemonic: true,
1497
+ },
1498
+ },
1499
+ detail_code: 7,
1500
+ detail_str: 'Recovery Phrase',
1385
1501
  });
1386
- expect(typedCall).toHaveBeenCalledWith(
1387
- 'DeviceGetOnboardingStatus',
1388
- 'DeviceOnboardingStatus',
1389
- {}
1390
- );
1502
+ expect(typedCall).toHaveBeenCalledWith('GetOnboardingStatus', 'OnboardingStatus', {});
1391
1503
  });
1392
1504
  });
1393
1505