@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.
- package/__tests__/DeviceCommands.test.ts +99 -0
- package/__tests__/evmLedgerLegacySafety.test.ts +261 -0
- package/__tests__/logBlockEvent.test.ts +37 -0
- package/__tests__/preInitialize.test.ts +22 -0
- package/__tests__/protocol-v2.test.ts +139 -27
- package/dist/api/BaseMethod.d.ts +7 -1
- package/dist/api/BaseMethod.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/GetPassphraseState.d.ts.map +1 -1
- package/dist/api/alephium/AlephiumSignMessage.d.ts.map +1 -1
- package/dist/api/alephium/AlephiumSignTransaction.d.ts.map +1 -1
- package/dist/api/algo/AlgoSignTransaction.d.ts.map +1 -1
- package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
- package/dist/api/aptos/AptosSignInMessage.d.ts.map +1 -1
- package/dist/api/aptos/AptosSignMessage.d.ts.map +1 -1
- package/dist/api/aptos/AptosSignTransaction.d.ts.map +1 -1
- package/dist/api/benfen/BenfenSignMessage.d.ts.map +1 -1
- package/dist/api/benfen/BenfenSignTransaction.d.ts.map +1 -1
- package/dist/api/btc/BTCSignMessage.d.ts.map +1 -1
- package/dist/api/btc/BTCSignPsbt.d.ts.map +1 -1
- package/dist/api/btc/BTCSignTransaction.d.ts.map +1 -1
- package/dist/api/cardano/CardanoSignMessage.d.ts.map +1 -1
- package/dist/api/cardano/CardanoSignTransaction.d.ts.map +1 -1
- package/dist/api/conflux/ConfluxSignMessage.d.ts.map +1 -1
- package/dist/api/conflux/ConfluxSignMessageCIP23.d.ts.map +1 -1
- package/dist/api/conflux/ConfluxSignTransaction.d.ts.map +1 -1
- package/dist/api/cosmos/CosmosSignTransaction.d.ts.map +1 -1
- package/dist/api/device/DeviceLock.d.ts.map +1 -1
- package/dist/api/device/PreInitialize.d.ts +6 -0
- package/dist/api/device/PreInitialize.d.ts.map +1 -0
- package/dist/api/dynex/DnxSignTransaction.d.ts.map +1 -1
- package/dist/api/evm/EVMSignMessage.d.ts.map +1 -1
- package/dist/api/evm/EVMSignMessageEIP712.d.ts.map +1 -1
- package/dist/api/evm/EVMSignTransaction.d.ts.map +1 -1
- package/dist/api/evm/EVMSignTypedData.d.ts.map +1 -1
- package/dist/api/filecoin/FilecoinSignTransaction.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +2 -10
- package/dist/api/firmware/FirmwareUpdateBaseMethod.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/kaspa/KaspaSignTransaction.d.ts.map +1 -1
- package/dist/api/near/NearSignTransaction.d.ts.map +1 -1
- package/dist/api/nem/NEMSignTransaction.d.ts.map +1 -1
- package/dist/api/neo/NeoSignTransaction.d.ts.map +1 -1
- package/dist/api/nervos/NervosSignTransaction.d.ts.map +1 -1
- package/dist/api/nexa/NexaSignTransaction.d.ts.map +1 -1
- package/dist/api/nostr/NostrSignEvent.d.ts.map +1 -1
- package/dist/api/nostr/NostrSignSchnorr.d.ts.map +1 -1
- package/dist/api/polkadot/PolkadotSignTransaction.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts +1 -1
- package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts.map +1 -1
- package/dist/api/protocol-v2/FilesystemDiskControl.d.ts +1 -1
- package/dist/api/scdo/ScdoSignMessage.d.ts.map +1 -1
- package/dist/api/scdo/ScdoSignTransaction.d.ts.map +1 -1
- package/dist/api/solana/SolSignMessage.d.ts.map +1 -1
- package/dist/api/solana/SolSignOffchainMessage.d.ts.map +1 -1
- package/dist/api/solana/SolSignTransaction.d.ts.map +1 -1
- package/dist/api/starcoin/StarcoinSignMessage.d.ts.map +1 -1
- package/dist/api/starcoin/StarcoinSignTransaction.d.ts.map +1 -1
- package/dist/api/stellar/StellarSignTransaction.d.ts.map +1 -1
- package/dist/api/sui/SuiGetAddress.d.ts +3 -0
- package/dist/api/sui/SuiGetAddress.d.ts.map +1 -1
- package/dist/api/sui/SuiGetPublicKey.d.ts +3 -0
- package/dist/api/sui/SuiGetPublicKey.d.ts.map +1 -1
- package/dist/api/sui/SuiSignMessage.d.ts +3 -0
- package/dist/api/sui/SuiSignMessage.d.ts.map +1 -1
- package/dist/api/sui/SuiSignTransaction.d.ts +3 -0
- package/dist/api/sui/SuiSignTransaction.d.ts.map +1 -1
- package/dist/api/ton/TonGetAddress.d.ts +3 -0
- package/dist/api/ton/TonGetAddress.d.ts.map +1 -1
- package/dist/api/ton/TonSignData.d.ts +5 -0
- package/dist/api/ton/TonSignData.d.ts.map +1 -1
- package/dist/api/ton/TonSignMessage.d.ts +3 -0
- package/dist/api/ton/TonSignMessage.d.ts.map +1 -1
- package/dist/api/ton/TonSignProof.d.ts +3 -0
- package/dist/api/ton/TonSignProof.d.ts.map +1 -1
- package/dist/api/tron/TronSignMessage.d.ts.map +1 -1
- package/dist/api/tron/TronSignTransaction.d.ts.map +1 -1
- package/dist/api/xrp/XrpSignTransaction.d.ts.map +1 -1
- package/dist/core/PollingStateManager.d.ts +8 -0
- package/dist/core/PollingStateManager.d.ts.map +1 -0
- package/dist/core/RequestQueue.d.ts +1 -1
- package/dist/core/RequestQueue.d.ts.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/device/Device.d.ts +17 -2
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/events/logBlockEvent.d.ts +1 -0
- package/dist/events/logBlockEvent.d.ts.map +1 -1
- package/dist/index.d.ts +25 -5
- package/dist/index.js +928 -407
- package/dist/types/api/index.d.ts +2 -0
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/preInitialize.d.ts +3 -0
- package/dist/types/api/preInitialize.d.ts.map +1 -0
- package/dist/types/api/protocolV2.d.ts +2 -2
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/params.d.ts +1 -0
- package/dist/types/params.d.ts.map +1 -1
- 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/package.json +4 -4
- package/src/api/BaseMethod.ts +82 -2
- package/src/api/FirmwareUpdateV3.ts +0 -4
- package/src/api/FirmwareUpdateV4.ts +1 -19
- package/src/api/GetPassphraseState.ts +4 -3
- package/src/api/alephium/AlephiumSignMessage.ts +1 -0
- package/src/api/alephium/AlephiumSignTransaction.ts +1 -0
- package/src/api/algo/AlgoSignTransaction.ts +1 -0
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +8 -0
- package/src/api/aptos/AptosSignInMessage.ts +1 -0
- package/src/api/aptos/AptosSignMessage.ts +1 -0
- package/src/api/aptos/AptosSignTransaction.ts +1 -0
- package/src/api/benfen/BenfenSignMessage.ts +1 -0
- package/src/api/benfen/BenfenSignTransaction.ts +1 -0
- package/src/api/btc/BTCSignMessage.ts +1 -0
- package/src/api/btc/BTCSignPsbt.ts +1 -0
- package/src/api/btc/BTCSignTransaction.ts +1 -0
- package/src/api/cardano/CardanoSignMessage.ts +1 -0
- package/src/api/cardano/CardanoSignTransaction.ts +1 -0
- package/src/api/conflux/ConfluxSignMessage.ts +1 -0
- package/src/api/conflux/ConfluxSignMessageCIP23.ts +1 -0
- package/src/api/conflux/ConfluxSignTransaction.ts +1 -0
- package/src/api/cosmos/CosmosSignTransaction.ts +1 -0
- package/src/api/device/DeviceLock.ts +1 -3
- package/src/api/device/PreInitialize.ts +41 -0
- package/src/api/dynex/DnxSignTransaction.ts +1 -0
- package/src/api/evm/EVMSignMessage.ts +2 -0
- package/src/api/evm/EVMSignMessageEIP712.ts +1 -0
- package/src/api/evm/EVMSignTransaction.ts +2 -0
- package/src/api/evm/EVMSignTypedData.ts +3 -1
- package/src/api/filecoin/FilecoinSignTransaction.ts +1 -0
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +4 -27
- package/src/api/index.ts +1 -0
- package/src/api/kaspa/KaspaSignTransaction.ts +1 -0
- package/src/api/near/NearSignTransaction.ts +1 -0
- package/src/api/nem/NEMSignTransaction.ts +1 -0
- package/src/api/neo/NeoSignTransaction.ts +1 -0
- package/src/api/nervos/NervosSignTransaction.ts +1 -0
- package/src/api/nexa/NexaSignTransaction.ts +2 -0
- package/src/api/nostr/NostrSignEvent.ts +1 -0
- package/src/api/nostr/NostrSignSchnorr.ts +1 -0
- package/src/api/polkadot/PolkadotSignTransaction.ts +1 -0
- package/src/api/protocol-v2/DeviceGetOnboardingStatus.ts +1 -5
- package/src/api/scdo/ScdoSignMessage.ts +1 -0
- package/src/api/scdo/ScdoSignTransaction.ts +1 -0
- package/src/api/solana/SolSignMessage.ts +1 -0
- package/src/api/solana/SolSignOffchainMessage.ts +1 -0
- package/src/api/solana/SolSignTransaction.ts +1 -0
- package/src/api/starcoin/StarcoinSignMessage.ts +1 -0
- package/src/api/starcoin/StarcoinSignTransaction.ts +1 -0
- package/src/api/stellar/StellarSignTransaction.ts +1 -0
- package/src/api/sui/SuiGetAddress.ts +3 -0
- package/src/api/sui/SuiGetPublicKey.ts +3 -0
- package/src/api/sui/SuiSignMessage.ts +4 -0
- package/src/api/sui/SuiSignTransaction.ts +4 -0
- package/src/api/ton/TonGetAddress.ts +3 -0
- package/src/api/ton/TonSignData.ts +11 -3
- package/src/api/ton/TonSignMessage.ts +4 -0
- package/src/api/ton/TonSignProof.ts +4 -0
- package/src/api/tron/TronSignMessage.ts +1 -0
- package/src/api/tron/TronSignTransaction.ts +1 -0
- package/src/api/xrp/XrpSignTransaction.ts +1 -0
- package/src/core/PollingStateManager.ts +47 -0
- package/src/core/RequestQueue.ts +10 -3
- package/src/core/index.ts +153 -34
- package/src/data/messages/messages-protocol-v2.json +489 -268
- package/src/device/Device.ts +73 -16
- package/src/events/logBlockEvent.ts +23 -0
- package/src/inject.ts +1 -1
- package/src/types/api/index.ts +2 -0
- package/src/types/api/preInitialize.ts +3 -0
- package/src/types/api/protocolV2.ts +2 -2
- package/src/types/params.ts +5 -0
- 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
|
|
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).
|
|
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).
|
|
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).
|
|
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
|
|
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
|
|
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: '
|
|
1475
|
+
type: 'OnboardingStatus',
|
|
1372
1476
|
message: {
|
|
1373
|
-
step:
|
|
1374
|
-
|
|
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:
|
|
1384
|
-
|
|
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
|
|