@sidhujag/sysweb3-keyring 1.0.547 → 1.0.548
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/package.json +2 -27
- package/coverage/clover.xml +0 -2875
- package/coverage/coverage-final.json +0 -29468
- package/coverage/lcov-report/base.css +0 -354
- package/coverage/lcov-report/block-navigation.js +0 -85
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -320
- package/coverage/lcov-report/prettify.css +0 -101
- package/coverage/lcov-report/prettify.js +0 -1008
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -191
- package/coverage/lcov-report/src/index.html +0 -276
- package/coverage/lcov-report/src/index.ts.html +0 -114
- package/coverage/lcov-report/src/initial-state.ts.html +0 -558
- package/coverage/lcov-report/src/keyring-manager.ts.html +0 -6279
- package/coverage/lcov-report/src/ledger/bitcoin_client/index.html +0 -178
- package/coverage/lcov-report/src/ledger/bitcoin_client/index.ts.html +0 -144
- package/coverage/lcov-report/src/ledger/bitcoin_client/lib/appClient.ts.html +0 -1560
- package/coverage/lcov-report/src/ledger/bitcoin_client/lib/bip32.ts.html +0 -276
- package/coverage/lcov-report/src/ledger/bitcoin_client/lib/buffertools.ts.html +0 -495
- package/coverage/lcov-report/src/ledger/bitcoin_client/lib/clientCommands.ts.html +0 -1138
- package/coverage/lcov-report/src/ledger/bitcoin_client/lib/index.html +0 -363
- package/coverage/lcov-report/src/ledger/bitcoin_client/lib/merkelizedPsbt.ts.html +0 -289
- package/coverage/lcov-report/src/ledger/bitcoin_client/lib/merkle.ts.html +0 -486
- package/coverage/lcov-report/src/ledger/bitcoin_client/lib/merkleMap.ts.html +0 -240
- package/coverage/lcov-report/src/ledger/bitcoin_client/lib/policy.ts.html +0 -342
- package/coverage/lcov-report/src/ledger/bitcoin_client/lib/psbtv2.ts.html +0 -2388
- package/coverage/lcov-report/src/ledger/bitcoin_client/lib/varint.ts.html +0 -453
- package/coverage/lcov-report/src/ledger/consts.ts.html +0 -177
- package/coverage/lcov-report/src/ledger/index.html +0 -216
- package/coverage/lcov-report/src/ledger/index.ts.html +0 -1371
- package/coverage/lcov-report/src/ledger/utils.ts.html +0 -102
- package/coverage/lcov-report/src/signers.ts.html +0 -591
- package/coverage/lcov-report/src/storage.ts.html +0 -198
- package/coverage/lcov-report/src/transactions/ethereum.ts.html +0 -5826
- package/coverage/lcov-report/src/transactions/index.html +0 -216
- package/coverage/lcov-report/src/transactions/index.ts.html +0 -93
- package/coverage/lcov-report/src/transactions/syscoin.ts.html +0 -1521
- package/coverage/lcov-report/src/trezor/index.html +0 -176
- package/coverage/lcov-report/src/trezor/index.ts.html +0 -2655
- package/coverage/lcov-report/src/types.ts.html +0 -1443
- package/coverage/lcov-report/src/utils/derivation-paths.ts.html +0 -486
- package/coverage/lcov-report/src/utils/index.html +0 -196
- package/coverage/lcov-report/src/utils/psbt.ts.html +0 -159
- package/coverage/lcov-report/test/helpers/constants.ts.html +0 -627
- package/coverage/lcov-report/test/helpers/index.html +0 -176
- package/coverage/lcov.info +0 -4832
- package/dist/package.json +0 -50
- package/examples/basic-usage.js +0 -140
- package/jest.config.js +0 -32
- package/readme.md +0 -201
- package/src/declare.d.ts +0 -7
- package/src/errorUtils.ts +0 -83
- package/src/hardware-wallet-manager.ts +0 -655
- package/src/index.ts +0 -12
- package/src/initial-state.ts +0 -108
- package/src/keyring-manager.ts +0 -2698
- package/src/ledger/bitcoin_client/index.ts +0 -19
- package/src/ledger/bitcoin_client/lib/appClient.ts +0 -405
- package/src/ledger/bitcoin_client/lib/bip32.ts +0 -61
- package/src/ledger/bitcoin_client/lib/buffertools.ts +0 -134
- package/src/ledger/bitcoin_client/lib/clientCommands.ts +0 -356
- package/src/ledger/bitcoin_client/lib/constants.ts +0 -12
- package/src/ledger/bitcoin_client/lib/merkelizedPsbt.ts +0 -65
- package/src/ledger/bitcoin_client/lib/merkle.ts +0 -136
- package/src/ledger/bitcoin_client/lib/merkleMap.ts +0 -49
- package/src/ledger/bitcoin_client/lib/policy.ts +0 -91
- package/src/ledger/bitcoin_client/lib/psbtv2.ts +0 -768
- package/src/ledger/bitcoin_client/lib/varint.ts +0 -120
- package/src/ledger/consts.ts +0 -3
- package/src/ledger/index.ts +0 -685
- package/src/ledger/types.ts +0 -74
- package/src/network-utils.ts +0 -99
- package/src/providers.ts +0 -345
- package/src/signers.ts +0 -158
- package/src/storage.ts +0 -63
- package/src/transactions/__tests__/integration.test.ts +0 -303
- package/src/transactions/__tests__/syscoin.test.ts +0 -409
- package/src/transactions/ethereum.ts +0 -2503
- package/src/transactions/index.ts +0 -2
- package/src/transactions/syscoin.ts +0 -542
- package/src/trezor/index.ts +0 -1050
- package/src/types.ts +0 -366
- package/src/utils/derivation-paths.ts +0 -133
- package/src/utils/psbt.ts +0 -24
- package/src/utils.ts +0 -191
- package/test/README.md +0 -158
- package/test/__mocks__/ledger-mock.js +0 -20
- package/test/__mocks__/trezor-mock.js +0 -75
- package/test/cleanup-summary.md +0 -167
- package/test/helpers/README.md +0 -78
- package/test/helpers/constants.ts +0 -79
- package/test/helpers/setup.ts +0 -714
- package/test/integration/import-validation.spec.ts +0 -588
- package/test/unit/hardware/ledger.spec.ts +0 -869
- package/test/unit/hardware/trezor.spec.ts +0 -828
- package/test/unit/keyring-manager/account-management.spec.ts +0 -970
- package/test/unit/keyring-manager/import-watchonly.spec.ts +0 -181
- package/test/unit/keyring-manager/import-wif.spec.ts +0 -126
- package/test/unit/keyring-manager/initialization.spec.ts +0 -782
- package/test/unit/keyring-manager/key-derivation.spec.ts +0 -996
- package/test/unit/keyring-manager/security.spec.ts +0 -505
- package/test/unit/keyring-manager/state-management.spec.ts +0 -375
- package/test/unit/network/network-management.spec.ts +0 -372
- package/test/unit/transactions/ethereum-transactions.spec.ts +0 -382
- package/test/unit/transactions/syscoin-transactions.spec.ts +0 -615
- package/tsconfig.json +0 -14
- /package/{dist/README.md → README.md} +0 -0
- /package/{dist/cjs → cjs}/errorUtils.js +0 -0
- /package/{dist/cjs → cjs}/errorUtils.js.map +0 -0
- /package/{dist/cjs → cjs}/hardware-wallet-manager.js +0 -0
- /package/{dist/cjs → cjs}/hardware-wallet-manager.js.map +0 -0
- /package/{dist/cjs → cjs}/index.js +0 -0
- /package/{dist/cjs → cjs}/index.js.map +0 -0
- /package/{dist/cjs → cjs}/initial-state.js +0 -0
- /package/{dist/cjs → cjs}/initial-state.js.map +0 -0
- /package/{dist/cjs → cjs}/keyring-manager.js +0 -0
- /package/{dist/cjs → cjs}/keyring-manager.js.map +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/index.js +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/index.js.map +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/appClient.js +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/appClient.js.map +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/bip32.js +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/bip32.js.map +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/buffertools.js +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/buffertools.js.map +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/clientCommands.js +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/clientCommands.js.map +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/constants.js +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/constants.js.map +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/merkelizedPsbt.js +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/merkelizedPsbt.js.map +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/merkle.js +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/merkle.js.map +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/merkleMap.js +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/merkleMap.js.map +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/policy.js +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/policy.js.map +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/psbtv2.js +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/psbtv2.js.map +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/varint.js +0 -0
- /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/varint.js.map +0 -0
- /package/{dist/cjs → cjs}/ledger/consts.js +0 -0
- /package/{dist/cjs → cjs}/ledger/consts.js.map +0 -0
- /package/{dist/cjs → cjs}/ledger/index.js +0 -0
- /package/{dist/cjs → cjs}/ledger/index.js.map +0 -0
- /package/{dist/cjs → cjs}/ledger/types.js +0 -0
- /package/{dist/cjs → cjs}/ledger/types.js.map +0 -0
- /package/{dist/cjs → cjs}/network-utils.js +0 -0
- /package/{dist/cjs → cjs}/network-utils.js.map +0 -0
- /package/{dist/cjs → cjs}/providers.js +0 -0
- /package/{dist/cjs → cjs}/providers.js.map +0 -0
- /package/{dist/cjs → cjs}/signers.js +0 -0
- /package/{dist/cjs → cjs}/signers.js.map +0 -0
- /package/{dist/cjs → cjs}/storage.js +0 -0
- /package/{dist/cjs → cjs}/storage.js.map +0 -0
- /package/{dist/cjs → cjs}/transactions/__tests__/integration.test.js +0 -0
- /package/{dist/cjs → cjs}/transactions/__tests__/integration.test.js.map +0 -0
- /package/{dist/cjs → cjs}/transactions/__tests__/syscoin.test.js +0 -0
- /package/{dist/cjs → cjs}/transactions/__tests__/syscoin.test.js.map +0 -0
- /package/{dist/cjs → cjs}/transactions/ethereum.js +0 -0
- /package/{dist/cjs → cjs}/transactions/ethereum.js.map +0 -0
- /package/{dist/cjs → cjs}/transactions/index.js +0 -0
- /package/{dist/cjs → cjs}/transactions/index.js.map +0 -0
- /package/{dist/cjs → cjs}/transactions/syscoin.js +0 -0
- /package/{dist/cjs → cjs}/transactions/syscoin.js.map +0 -0
- /package/{dist/cjs → cjs}/trezor/index.js +0 -0
- /package/{dist/cjs → cjs}/trezor/index.js.map +0 -0
- /package/{dist/cjs → cjs}/types.js +0 -0
- /package/{dist/cjs → cjs}/types.js.map +0 -0
- /package/{dist/cjs → cjs}/utils/derivation-paths.js +0 -0
- /package/{dist/cjs → cjs}/utils/derivation-paths.js.map +0 -0
- /package/{dist/cjs → cjs}/utils/psbt.js +0 -0
- /package/{dist/cjs → cjs}/utils/psbt.js.map +0 -0
- /package/{dist/cjs → cjs}/utils.js +0 -0
- /package/{dist/cjs → cjs}/utils.js.map +0 -0
- /package/{dist/types → types}/errorUtils.d.ts +0 -0
- /package/{dist/types → types}/hardware-wallet-manager.d.ts +0 -0
- /package/{dist/types → types}/index.d.ts +0 -0
- /package/{dist/types → types}/initial-state.d.ts +0 -0
- /package/{dist/types → types}/keyring-manager.d.ts +0 -0
- /package/{dist/types → types}/ledger/bitcoin_client/index.d.ts +0 -0
- /package/{dist/types → types}/ledger/bitcoin_client/lib/appClient.d.ts +0 -0
- /package/{dist/types → types}/ledger/bitcoin_client/lib/bip32.d.ts +0 -0
- /package/{dist/types → types}/ledger/bitcoin_client/lib/buffertools.d.ts +0 -0
- /package/{dist/types → types}/ledger/bitcoin_client/lib/clientCommands.d.ts +0 -0
- /package/{dist/types → types}/ledger/bitcoin_client/lib/constants.d.ts +0 -0
- /package/{dist/types → types}/ledger/bitcoin_client/lib/merkelizedPsbt.d.ts +0 -0
- /package/{dist/types → types}/ledger/bitcoin_client/lib/merkle.d.ts +0 -0
- /package/{dist/types → types}/ledger/bitcoin_client/lib/merkleMap.d.ts +0 -0
- /package/{dist/types → types}/ledger/bitcoin_client/lib/policy.d.ts +0 -0
- /package/{dist/types → types}/ledger/bitcoin_client/lib/psbtv2.d.ts +0 -0
- /package/{dist/types → types}/ledger/bitcoin_client/lib/varint.d.ts +0 -0
- /package/{dist/types → types}/ledger/consts.d.ts +0 -0
- /package/{dist/types → types}/ledger/index.d.ts +0 -0
- /package/{dist/types → types}/ledger/types.d.ts +0 -0
- /package/{dist/types → types}/network-utils.d.ts +0 -0
- /package/{dist/types → types}/providers.d.ts +0 -0
- /package/{dist/types → types}/signers.d.ts +0 -0
- /package/{dist/types → types}/storage.d.ts +0 -0
- /package/{dist/types → types}/transactions/__tests__/integration.test.d.ts +0 -0
- /package/{dist/types → types}/transactions/__tests__/syscoin.test.d.ts +0 -0
- /package/{dist/types → types}/transactions/ethereum.d.ts +0 -0
- /package/{dist/types → types}/transactions/index.d.ts +0 -0
- /package/{dist/types → types}/transactions/syscoin.d.ts +0 -0
- /package/{dist/types → types}/trezor/index.d.ts +0 -0
- /package/{dist/types → types}/types.d.ts +0 -0
- /package/{dist/types → types}/utils/derivation-paths.d.ts +0 -0
- /package/{dist/types → types}/utils/psbt.d.ts +0 -0
- /package/{dist/types → types}/utils.d.ts +0 -0
|
@@ -1,970 +0,0 @@
|
|
|
1
|
-
import { INetworkType } from '@sidhujag/sysweb3-network';
|
|
2
|
-
|
|
3
|
-
import { KeyringManager, KeyringAccountType } from '../../../src';
|
|
4
|
-
import { FAKE_PASSWORD, PEACE_SEED_PHRASE } from '../../helpers/constants';
|
|
5
|
-
import { setupMocks } from '../../helpers/setup';
|
|
6
|
-
|
|
7
|
-
describe('KeyringManager - Account Management', () => {
|
|
8
|
-
let keyringManager: KeyringManager;
|
|
9
|
-
let mockVaultStateGetter: jest.Mock;
|
|
10
|
-
let currentVaultState: any;
|
|
11
|
-
|
|
12
|
-
beforeEach(async () => {
|
|
13
|
-
setupMocks();
|
|
14
|
-
|
|
15
|
-
// Set up mock vault state for testing
|
|
16
|
-
currentVaultState = createMockVaultState({
|
|
17
|
-
activeAccountId: 0,
|
|
18
|
-
activeAccountType: KeyringAccountType.HDAccount,
|
|
19
|
-
networkType: INetworkType.Ethereum,
|
|
20
|
-
chainId: 1,
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
// Set up vault-keys that would normally be created by Pali's MainController
|
|
24
|
-
await setupTestVault(FAKE_PASSWORD);
|
|
25
|
-
|
|
26
|
-
// Create mock vault getter that returns the current state
|
|
27
|
-
mockVaultStateGetter = jest.fn(() => currentVaultState);
|
|
28
|
-
|
|
29
|
-
// Create keyring manager with vault getter
|
|
30
|
-
keyringManager = await KeyringManager.createInitialized(
|
|
31
|
-
PEACE_SEED_PHRASE,
|
|
32
|
-
FAKE_PASSWORD,
|
|
33
|
-
mockVaultStateGetter
|
|
34
|
-
);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
describe('HD Account Management', () => {
|
|
38
|
-
it('should add new HD accounts with sequential IDs', async () => {
|
|
39
|
-
// Initial account should be 0
|
|
40
|
-
const initialAccount = keyringManager.getActiveAccount().activeAccount;
|
|
41
|
-
expect(initialAccount.id).toBe(0);
|
|
42
|
-
expect(initialAccount.label).toBe('Account 1');
|
|
43
|
-
|
|
44
|
-
// Add second account
|
|
45
|
-
const account2 = await keyringManager.addNewAccount();
|
|
46
|
-
expect(account2.id).toBe(1);
|
|
47
|
-
expect(account2.label).toBe('Account 2');
|
|
48
|
-
expect(account2.isImported).toBe(false);
|
|
49
|
-
|
|
50
|
-
// Update vault state to include the new account
|
|
51
|
-
currentVaultState.accounts[KeyringAccountType.HDAccount][1] = {
|
|
52
|
-
id: 1,
|
|
53
|
-
label: 'Account 2',
|
|
54
|
-
address: account2.address,
|
|
55
|
-
xpub: account2.xpub,
|
|
56
|
-
xprv: account2.xprv,
|
|
57
|
-
isImported: false,
|
|
58
|
-
isTrezorWallet: false,
|
|
59
|
-
isLedgerWallet: false,
|
|
60
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
61
|
-
assets: { syscoin: [], ethereum: [] },
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
// Add third account with custom label
|
|
65
|
-
const account3 = await keyringManager.addNewAccount('My Custom Account');
|
|
66
|
-
expect(account3.id).toBe(2);
|
|
67
|
-
expect(account3.label).toBe('My Custom Account');
|
|
68
|
-
|
|
69
|
-
// Update vault state for account 3
|
|
70
|
-
currentVaultState.accounts[KeyringAccountType.HDAccount][2] = {
|
|
71
|
-
id: 2,
|
|
72
|
-
label: 'My Custom Account',
|
|
73
|
-
address: account3.address,
|
|
74
|
-
xpub: account3.xpub,
|
|
75
|
-
xprv: account3.xprv,
|
|
76
|
-
isImported: false,
|
|
77
|
-
isTrezorWallet: false,
|
|
78
|
-
isLedgerWallet: false,
|
|
79
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
80
|
-
assets: { syscoin: [], ethereum: [] },
|
|
81
|
-
};
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it('should switch between HD accounts', async () => {
|
|
85
|
-
// First create the accounts and update vault state
|
|
86
|
-
const account2 = await keyringManager.addNewAccount();
|
|
87
|
-
const account3 = await keyringManager.addNewAccount();
|
|
88
|
-
|
|
89
|
-
// Update vault state to include all accounts
|
|
90
|
-
currentVaultState.accounts[KeyringAccountType.HDAccount][1] = {
|
|
91
|
-
id: 1,
|
|
92
|
-
label: 'Account 2',
|
|
93
|
-
address: account2.address,
|
|
94
|
-
xpub: account2.xpub,
|
|
95
|
-
xprv: '',
|
|
96
|
-
isImported: false,
|
|
97
|
-
isTrezorWallet: false,
|
|
98
|
-
isLedgerWallet: false,
|
|
99
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
100
|
-
assets: { syscoin: [], ethereum: [] },
|
|
101
|
-
};
|
|
102
|
-
currentVaultState.accounts[KeyringAccountType.HDAccount][2] = {
|
|
103
|
-
id: 2,
|
|
104
|
-
label: 'Account 3',
|
|
105
|
-
address: account3.address,
|
|
106
|
-
xpub: account3.xpub,
|
|
107
|
-
xprv: '',
|
|
108
|
-
isImported: false,
|
|
109
|
-
isTrezorWallet: false,
|
|
110
|
-
isLedgerWallet: false,
|
|
111
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
112
|
-
assets: { syscoin: [], ethereum: [] },
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
// Switch to account 1 (only update vault state - no setActiveAccount needed)
|
|
116
|
-
currentVaultState.activeAccount = {
|
|
117
|
-
id: 1,
|
|
118
|
-
type: KeyringAccountType.HDAccount,
|
|
119
|
-
};
|
|
120
|
-
let active = keyringManager.getActiveAccount();
|
|
121
|
-
expect(active.activeAccount.id).toBe(1);
|
|
122
|
-
expect(active.activeAccountType).toBe(KeyringAccountType.HDAccount);
|
|
123
|
-
|
|
124
|
-
// Switch to account 2 (only update vault state)
|
|
125
|
-
currentVaultState.activeAccount = {
|
|
126
|
-
id: 2,
|
|
127
|
-
type: KeyringAccountType.HDAccount,
|
|
128
|
-
};
|
|
129
|
-
active = keyringManager.getActiveAccount();
|
|
130
|
-
expect(active.activeAccount.id).toBe(2);
|
|
131
|
-
|
|
132
|
-
// Switch back to account 0 (only update vault state)
|
|
133
|
-
currentVaultState.activeAccount = {
|
|
134
|
-
id: 0,
|
|
135
|
-
type: KeyringAccountType.HDAccount,
|
|
136
|
-
};
|
|
137
|
-
active = keyringManager.getActiveAccount();
|
|
138
|
-
expect(active.activeAccount.id).toBe(0);
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
it('should get account by ID', async () => {
|
|
142
|
-
// Add account and update vault state
|
|
143
|
-
const newAccount = await keyringManager.addNewAccount('Test Account');
|
|
144
|
-
currentVaultState.accounts[KeyringAccountType.HDAccount][1] = {
|
|
145
|
-
id: 1,
|
|
146
|
-
label: 'Test Account',
|
|
147
|
-
address: newAccount.address,
|
|
148
|
-
xpub: newAccount.xpub,
|
|
149
|
-
xprv: '',
|
|
150
|
-
isImported: false,
|
|
151
|
-
isTrezorWallet: false,
|
|
152
|
-
isLedgerWallet: false,
|
|
153
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
154
|
-
assets: { syscoin: [], ethereum: [] },
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
const account0 = keyringManager.getAccountById(
|
|
158
|
-
0,
|
|
159
|
-
KeyringAccountType.HDAccount
|
|
160
|
-
);
|
|
161
|
-
expect(account0.id).toBe(0);
|
|
162
|
-
expect(account0.label).toBe('Account 1');
|
|
163
|
-
|
|
164
|
-
const account1 = keyringManager.getAccountById(
|
|
165
|
-
1,
|
|
166
|
-
KeyringAccountType.HDAccount
|
|
167
|
-
);
|
|
168
|
-
expect(account1.id).toBe(1);
|
|
169
|
-
expect(account1.label).toBe('Test Account');
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
it('should throw when getting non-existent account', () => {
|
|
173
|
-
expect(() =>
|
|
174
|
-
keyringManager.getAccountById(999, KeyringAccountType.HDAccount)
|
|
175
|
-
).toThrow('Account not found');
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
it('should generate correct network-specific addresses when switching between different slip44 networks', async () => {
|
|
179
|
-
// This test verifies the fix for the bug where cached accounts
|
|
180
|
-
// retained stale addresses from previous networks
|
|
181
|
-
|
|
182
|
-
// Step 1: Create keyring for Syscoin mainnet (slip44=57)
|
|
183
|
-
const mainnetVaultState = createMockVaultState({
|
|
184
|
-
activeAccountId: 0,
|
|
185
|
-
activeAccountType: KeyringAccountType.HDAccount,
|
|
186
|
-
networkType: INetworkType.Syscoin,
|
|
187
|
-
chainId: 57, // Syscoin mainnet
|
|
188
|
-
});
|
|
189
|
-
const mainnetVaultStateGetter = jest.fn(() => mainnetVaultState);
|
|
190
|
-
|
|
191
|
-
const mainnetKeyring = await KeyringManager.createInitialized(
|
|
192
|
-
PEACE_SEED_PHRASE,
|
|
193
|
-
FAKE_PASSWORD,
|
|
194
|
-
mainnetVaultStateGetter
|
|
195
|
-
);
|
|
196
|
-
|
|
197
|
-
// Get mainnet account with sys1... address
|
|
198
|
-
const mainnetAccount = mainnetKeyring.getActiveAccount().activeAccount;
|
|
199
|
-
expect(mainnetAccount.address.startsWith('sys1')).toBe(true);
|
|
200
|
-
|
|
201
|
-
// Step 2: Simulate caching this account in vault state
|
|
202
|
-
// This represents what happens when we cache vault state
|
|
203
|
-
mainnetVaultState.accounts[KeyringAccountType.HDAccount][0] = {
|
|
204
|
-
...mainnetAccount,
|
|
205
|
-
address: mainnetAccount.address, // This will be sys1... address
|
|
206
|
-
xpub: mainnetAccount.xpub,
|
|
207
|
-
balances: { syscoin: 10, ethereum: 0 }, // Some mainnet balance
|
|
208
|
-
} as any;
|
|
209
|
-
|
|
210
|
-
// Step 3: Create keyring for Syscoin testnet (slip44=1) with SAME vault state
|
|
211
|
-
// This simulates loading cached vault state that has stale mainnet addresses
|
|
212
|
-
const testnetVaultState = createMockVaultState({
|
|
213
|
-
activeAccountId: 0,
|
|
214
|
-
activeAccountType: KeyringAccountType.HDAccount,
|
|
215
|
-
networkType: INetworkType.Syscoin,
|
|
216
|
-
chainId: 5700, // Syscoin testnet
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
// CRITICAL: Inject the stale mainnet account into testnet vault state
|
|
220
|
-
// This represents the bug scenario where cached vault has wrong addresses
|
|
221
|
-
testnetVaultState.accounts[KeyringAccountType.HDAccount][0] = {
|
|
222
|
-
...mainnetVaultState.accounts[KeyringAccountType.HDAccount][0],
|
|
223
|
-
// This account still has sys1... address but we're now on testnet
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
const testnetVaultStateGetter = jest.fn(() => testnetVaultState);
|
|
227
|
-
|
|
228
|
-
const testnetKeyring = await KeyringManager.createInitialized(
|
|
229
|
-
PEACE_SEED_PHRASE,
|
|
230
|
-
FAKE_PASSWORD,
|
|
231
|
-
testnetVaultStateGetter
|
|
232
|
-
);
|
|
233
|
-
|
|
234
|
-
// Step 4: Create/load account on testnet - this should generate fresh tsys1... address
|
|
235
|
-
// With the bug: would reuse cached sys1... address
|
|
236
|
-
// With the fix: should derive fresh tsys1... address
|
|
237
|
-
const testnetAccount = await testnetKeyring.createFirstAccount(
|
|
238
|
-
'Test Account'
|
|
239
|
-
);
|
|
240
|
-
|
|
241
|
-
// Step 5: Verify addresses are network-specific
|
|
242
|
-
expect(mainnetAccount.address.startsWith('sys1')).toBe(true);
|
|
243
|
-
expect(testnetAccount.address.startsWith('tsys1')).toBe(true);
|
|
244
|
-
|
|
245
|
-
// Step 6: Addresses should be different (different networks)
|
|
246
|
-
expect(mainnetAccount.address).not.toBe(testnetAccount.address);
|
|
247
|
-
|
|
248
|
-
// Step 7: xpub formats should also be different
|
|
249
|
-
expect(mainnetAccount.xpub.startsWith('zpub')).toBe(true); // Mainnet format
|
|
250
|
-
expect(testnetAccount.xpub.startsWith('vpub')).toBe(true); // Testnet format
|
|
251
|
-
|
|
252
|
-
// Step 8: Verify testnet account has fresh balance, not cached mainnet balance
|
|
253
|
-
expect(testnetAccount.balances.syscoin).toBe(0); // Fresh account
|
|
254
|
-
expect(testnetAccount.balances.ethereum).toBe(0);
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
it('should handle address generation consistently across multiple account operations', async () => {
|
|
258
|
-
// Test that all account operations use fresh derived addresses
|
|
259
|
-
|
|
260
|
-
const testnetVaultState = createMockVaultState({
|
|
261
|
-
activeAccountId: 0,
|
|
262
|
-
activeAccountType: KeyringAccountType.HDAccount,
|
|
263
|
-
networkType: INetworkType.Syscoin,
|
|
264
|
-
chainId: 5700,
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
// Inject stale mainnet address to simulate the bug condition
|
|
268
|
-
testnetVaultState.accounts[KeyringAccountType.HDAccount][0] = {
|
|
269
|
-
id: 0,
|
|
270
|
-
label: 'Account 1',
|
|
271
|
-
address: 'sys1qbuggyaddressfromcachedmainnetstate', // Wrong network address
|
|
272
|
-
xpub: 'zpub6rSLPXDUvvuy5VEPMUTkiTYfpr7vYACJKsySDMgng1rwEU', // Wrong format
|
|
273
|
-
xprv: 'encrypted_xprv',
|
|
274
|
-
balances: { syscoin: 5, ethereum: 0 }, // Stale balance
|
|
275
|
-
isImported: false,
|
|
276
|
-
isTrezorWallet: false,
|
|
277
|
-
isLedgerWallet: false,
|
|
278
|
-
} as any;
|
|
279
|
-
|
|
280
|
-
const vaultStateGetter = jest.fn(() => testnetVaultState);
|
|
281
|
-
|
|
282
|
-
const keyringManager = await KeyringManager.createInitialized(
|
|
283
|
-
PEACE_SEED_PHRASE,
|
|
284
|
-
FAKE_PASSWORD,
|
|
285
|
-
vaultStateGetter
|
|
286
|
-
);
|
|
287
|
-
|
|
288
|
-
// All these operations should use correctly derived testnet addresses
|
|
289
|
-
const firstAccount = await keyringManager.createFirstAccount();
|
|
290
|
-
|
|
291
|
-
// Update the vault state to reflect the correctly generated first account
|
|
292
|
-
// This simulates what would happen in real usage where the vault state gets updated
|
|
293
|
-
testnetVaultState.accounts[KeyringAccountType.HDAccount][0] = {
|
|
294
|
-
id: 0,
|
|
295
|
-
label: 'Account 1',
|
|
296
|
-
address: firstAccount.address, // Now has correct tsys1... address
|
|
297
|
-
xpub: firstAccount.xpub,
|
|
298
|
-
xprv: 'encrypted_xprv',
|
|
299
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
300
|
-
isImported: false,
|
|
301
|
-
isTrezorWallet: false,
|
|
302
|
-
isLedgerWallet: false,
|
|
303
|
-
} as any;
|
|
304
|
-
|
|
305
|
-
const newAccount = await keyringManager.addNewAccount('Account 2');
|
|
306
|
-
const activeAccount = keyringManager.getActiveAccount().activeAccount;
|
|
307
|
-
|
|
308
|
-
// All should have correct testnet addresses
|
|
309
|
-
expect(firstAccount.address.startsWith('tsys1')).toBe(true);
|
|
310
|
-
expect(newAccount.address.startsWith('tsys1')).toBe(true);
|
|
311
|
-
expect(activeAccount.address.startsWith('tsys1')).toBe(true);
|
|
312
|
-
|
|
313
|
-
// Should not have the buggy cached address
|
|
314
|
-
expect(firstAccount.address).not.toBe(
|
|
315
|
-
'sys1qbuggyaddressfromcachedmainnetstate'
|
|
316
|
-
);
|
|
317
|
-
expect(activeAccount.address).not.toBe(
|
|
318
|
-
'sys1qbuggyaddressfromcachedmainnetstate'
|
|
319
|
-
);
|
|
320
|
-
});
|
|
321
|
-
});
|
|
322
|
-
|
|
323
|
-
describe('Imported Account Management', () => {
|
|
324
|
-
describe('EVM Import', () => {
|
|
325
|
-
it('should import account from private key', async () => {
|
|
326
|
-
const privateKey =
|
|
327
|
-
'0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318';
|
|
328
|
-
const expectedAddress = '0x2c7536E3605D9C16a7a3D7b1898e529396a65c23';
|
|
329
|
-
|
|
330
|
-
const imported = await keyringManager.importAccount(privateKey);
|
|
331
|
-
|
|
332
|
-
// Update vault state to reflect import
|
|
333
|
-
currentVaultState.accounts[KeyringAccountType.Imported][0] = {
|
|
334
|
-
id: 0,
|
|
335
|
-
label: 'Imported 1',
|
|
336
|
-
address: imported.address,
|
|
337
|
-
xpub: imported.xpub,
|
|
338
|
-
xprv: imported.xprv,
|
|
339
|
-
isImported: true,
|
|
340
|
-
isTrezorWallet: false,
|
|
341
|
-
isLedgerWallet: false,
|
|
342
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
343
|
-
assets: { syscoin: [], ethereum: [] },
|
|
344
|
-
};
|
|
345
|
-
|
|
346
|
-
expect(imported.isImported).toBe(true);
|
|
347
|
-
expect(imported.address.toLowerCase()).toBe(
|
|
348
|
-
expectedAddress.toLowerCase()
|
|
349
|
-
);
|
|
350
|
-
expect(imported.id).toBe(0);
|
|
351
|
-
expect(imported.label).toBe('Imported 1');
|
|
352
|
-
});
|
|
353
|
-
|
|
354
|
-
it('should import account with custom label', async () => {
|
|
355
|
-
const privateKey =
|
|
356
|
-
'0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318';
|
|
357
|
-
const imported = await keyringManager.importAccount(
|
|
358
|
-
privateKey,
|
|
359
|
-
'My Hardware Wallet'
|
|
360
|
-
);
|
|
361
|
-
expect(imported.label).toBe('My Hardware Wallet');
|
|
362
|
-
});
|
|
363
|
-
|
|
364
|
-
it('should handle multiple imported accounts', async () => {
|
|
365
|
-
const privateKey1 =
|
|
366
|
-
'0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318';
|
|
367
|
-
const privateKey2 =
|
|
368
|
-
'0x1234567890123456789012345678901234567890123456789012345678901234';
|
|
369
|
-
|
|
370
|
-
const imported1 = await keyringManager.importAccount(privateKey1);
|
|
371
|
-
|
|
372
|
-
// Update vault state for first import
|
|
373
|
-
currentVaultState.accounts[KeyringAccountType.Imported][0] = {
|
|
374
|
-
id: 0,
|
|
375
|
-
label: 'Imported 1',
|
|
376
|
-
address: imported1.address,
|
|
377
|
-
xpub: imported1.xpub,
|
|
378
|
-
xprv: imported1.xprv,
|
|
379
|
-
isImported: true,
|
|
380
|
-
isTrezorWallet: false,
|
|
381
|
-
isLedgerWallet: false,
|
|
382
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
383
|
-
assets: { syscoin: [], ethereum: [] },
|
|
384
|
-
};
|
|
385
|
-
|
|
386
|
-
const imported2 = await keyringManager.importAccount(privateKey2);
|
|
387
|
-
|
|
388
|
-
// Update vault state for second import
|
|
389
|
-
currentVaultState.accounts[KeyringAccountType.Imported][1] = {
|
|
390
|
-
id: 1,
|
|
391
|
-
label: 'Imported 2',
|
|
392
|
-
address: imported2.address,
|
|
393
|
-
xpub: imported2.xpub,
|
|
394
|
-
xprv: imported2.xprv,
|
|
395
|
-
isImported: true,
|
|
396
|
-
isTrezorWallet: false,
|
|
397
|
-
isLedgerWallet: false,
|
|
398
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
399
|
-
assets: { syscoin: [], ethereum: [] },
|
|
400
|
-
};
|
|
401
|
-
|
|
402
|
-
expect(imported1.id).toBe(0);
|
|
403
|
-
expect(imported2.id).toBe(1);
|
|
404
|
-
expect(imported2.label).toBe('Imported 2');
|
|
405
|
-
});
|
|
406
|
-
|
|
407
|
-
it('should get private key for imported account', async () => {
|
|
408
|
-
const privateKey =
|
|
409
|
-
'0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318';
|
|
410
|
-
const imported = await keyringManager.importAccount(privateKey);
|
|
411
|
-
|
|
412
|
-
// Update vault state
|
|
413
|
-
currentVaultState.accounts[KeyringAccountType.Imported][imported.id] = {
|
|
414
|
-
id: imported.id,
|
|
415
|
-
label: imported.label,
|
|
416
|
-
address: imported.address,
|
|
417
|
-
xpub: imported.xpub,
|
|
418
|
-
xprv: imported.xprv,
|
|
419
|
-
isImported: true,
|
|
420
|
-
isTrezorWallet: false,
|
|
421
|
-
isLedgerWallet: false,
|
|
422
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
423
|
-
assets: { syscoin: [], ethereum: [] },
|
|
424
|
-
};
|
|
425
|
-
|
|
426
|
-
const retrievedKey = await keyringManager.getPrivateKeyByAccountId(
|
|
427
|
-
imported.id,
|
|
428
|
-
KeyringAccountType.Imported,
|
|
429
|
-
FAKE_PASSWORD
|
|
430
|
-
);
|
|
431
|
-
|
|
432
|
-
expect(retrievedKey).toBe(privateKey);
|
|
433
|
-
});
|
|
434
|
-
|
|
435
|
-
it('should reject private key retrieval with wrong password', async () => {
|
|
436
|
-
const privateKey =
|
|
437
|
-
'0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318';
|
|
438
|
-
const imported = await keyringManager.importAccount(privateKey);
|
|
439
|
-
|
|
440
|
-
// Update vault state
|
|
441
|
-
currentVaultState.accounts[KeyringAccountType.Imported][imported.id] = {
|
|
442
|
-
id: imported.id,
|
|
443
|
-
label: imported.label,
|
|
444
|
-
address: imported.address,
|
|
445
|
-
xpub: imported.xpub,
|
|
446
|
-
xprv: imported.xprv,
|
|
447
|
-
isImported: true,
|
|
448
|
-
isTrezorWallet: false,
|
|
449
|
-
isLedgerWallet: false,
|
|
450
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
451
|
-
assets: { syscoin: [], ethereum: [] },
|
|
452
|
-
};
|
|
453
|
-
|
|
454
|
-
await expect(
|
|
455
|
-
keyringManager.getPrivateKeyByAccountId(
|
|
456
|
-
imported.id,
|
|
457
|
-
KeyringAccountType.Imported,
|
|
458
|
-
'wrong_password'
|
|
459
|
-
)
|
|
460
|
-
).rejects.toThrow('Invalid password');
|
|
461
|
-
});
|
|
462
|
-
});
|
|
463
|
-
|
|
464
|
-
describe('UTXO Import', () => {
|
|
465
|
-
beforeEach(() => {
|
|
466
|
-
// Set up UTXO network state
|
|
467
|
-
currentVaultState = createMockVaultState({
|
|
468
|
-
activeAccountId: 0,
|
|
469
|
-
activeAccountType: KeyringAccountType.HDAccount,
|
|
470
|
-
networkType: INetworkType.Syscoin,
|
|
471
|
-
chainId: 57,
|
|
472
|
-
});
|
|
473
|
-
mockVaultStateGetter.mockReturnValue(currentVaultState);
|
|
474
|
-
});
|
|
475
|
-
|
|
476
|
-
it('should import UTXO account from mainnet zprv', async () => {
|
|
477
|
-
const mainnetZprv =
|
|
478
|
-
'zprvAdGDwa3WySqQoVwVSbYRMKxDhSXpK2wW6wDjekCMdm7TaQ3igf52xRRjYghTvnFurtMm6CMgQivEDJs5ixGSnTtv8usFmkAoTe6XCF5hnpR';
|
|
479
|
-
const imported = await keyringManager.importAccount(mainnetZprv);
|
|
480
|
-
|
|
481
|
-
expect(imported.isImported).toBe(true);
|
|
482
|
-
expect(imported.address.startsWith('sys1')).toBe(true);
|
|
483
|
-
expect(imported.id).toBe(0);
|
|
484
|
-
expect(imported.label).toBe('Imported 1');
|
|
485
|
-
});
|
|
486
|
-
|
|
487
|
-
it('should validate zprv before import', async () => {
|
|
488
|
-
const invalidZprv = 'invalid_zprv_string';
|
|
489
|
-
await expect(
|
|
490
|
-
keyringManager.importAccount(invalidZprv)
|
|
491
|
-
).rejects.toThrow();
|
|
492
|
-
});
|
|
493
|
-
|
|
494
|
-
it('should switch between HD and imported UTXO accounts', async () => {
|
|
495
|
-
const mainnetZprv =
|
|
496
|
-
'zprvAdGDwa3WySqQoVwVSbYRMKxDhSXpK2wW6wDjekCMdm7TaQ3igf52xRRjYghTvnFurtMm6CMgQivEDJs5ixGSnTtv8usFmkAoTe6XCF5hnpR';
|
|
497
|
-
const imported = await keyringManager.importAccount(mainnetZprv);
|
|
498
|
-
|
|
499
|
-
// Update vault state with imported account
|
|
500
|
-
currentVaultState.accounts[KeyringAccountType.Imported][imported.id] = {
|
|
501
|
-
id: imported.id,
|
|
502
|
-
label: imported.label,
|
|
503
|
-
address: imported.address,
|
|
504
|
-
xpub: imported.xpub,
|
|
505
|
-
xprv: imported.xprv,
|
|
506
|
-
isImported: true,
|
|
507
|
-
isTrezorWallet: false,
|
|
508
|
-
isLedgerWallet: false,
|
|
509
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
510
|
-
assets: { syscoin: [], ethereum: [] },
|
|
511
|
-
};
|
|
512
|
-
|
|
513
|
-
// Switch to imported account (only update vault state)
|
|
514
|
-
currentVaultState.activeAccount = {
|
|
515
|
-
id: imported.id,
|
|
516
|
-
type: KeyringAccountType.Imported,
|
|
517
|
-
};
|
|
518
|
-
let active = keyringManager.getActiveAccount();
|
|
519
|
-
expect(active.activeAccount.id).toBe(imported.id);
|
|
520
|
-
expect(active.activeAccountType).toBe(KeyringAccountType.Imported);
|
|
521
|
-
expect(active.activeAccount.address).toBe(imported.address);
|
|
522
|
-
|
|
523
|
-
// Switch back to HD account (only update vault state)
|
|
524
|
-
currentVaultState.activeAccount = {
|
|
525
|
-
id: 0,
|
|
526
|
-
type: KeyringAccountType.HDAccount,
|
|
527
|
-
};
|
|
528
|
-
active = keyringManager.getActiveAccount();
|
|
529
|
-
expect(active.activeAccount.id).toBe(0);
|
|
530
|
-
expect(active.activeAccountType).toBe(KeyringAccountType.HDAccount);
|
|
531
|
-
});
|
|
532
|
-
});
|
|
533
|
-
});
|
|
534
|
-
|
|
535
|
-
describe('Mixed Account Types', () => {
|
|
536
|
-
it('should handle switching between different account types', async () => {
|
|
537
|
-
// Add HD accounts
|
|
538
|
-
const hdAccount2 = await keyringManager.addNewAccount('HD Account 2');
|
|
539
|
-
|
|
540
|
-
// Import account
|
|
541
|
-
const privateKey =
|
|
542
|
-
'0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318';
|
|
543
|
-
const imported = await keyringManager.importAccount(
|
|
544
|
-
privateKey,
|
|
545
|
-
'Imported Account'
|
|
546
|
-
);
|
|
547
|
-
|
|
548
|
-
// Update vault state with all accounts
|
|
549
|
-
currentVaultState.accounts[KeyringAccountType.HDAccount][1] = {
|
|
550
|
-
id: 1,
|
|
551
|
-
label: 'HD Account 2',
|
|
552
|
-
address: hdAccount2.address,
|
|
553
|
-
xpub: hdAccount2.xpub,
|
|
554
|
-
xprv: '',
|
|
555
|
-
isImported: false,
|
|
556
|
-
isTrezorWallet: false,
|
|
557
|
-
isLedgerWallet: false,
|
|
558
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
559
|
-
assets: { syscoin: [], ethereum: [] },
|
|
560
|
-
};
|
|
561
|
-
currentVaultState.accounts[KeyringAccountType.Imported][imported.id] = {
|
|
562
|
-
id: imported.id,
|
|
563
|
-
label: 'Imported Account',
|
|
564
|
-
address: imported.address,
|
|
565
|
-
xpub: imported.xpub,
|
|
566
|
-
xprv: imported.xprv,
|
|
567
|
-
isImported: true,
|
|
568
|
-
isTrezorWallet: false,
|
|
569
|
-
isLedgerWallet: false,
|
|
570
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
571
|
-
assets: { syscoin: [], ethereum: [] },
|
|
572
|
-
};
|
|
573
|
-
|
|
574
|
-
// Test switching between all accounts
|
|
575
|
-
const switches = [
|
|
576
|
-
{ id: 0, type: KeyringAccountType.HDAccount, label: 'Account 1' },
|
|
577
|
-
{ id: 1, type: KeyringAccountType.HDAccount, label: 'HD Account 2' },
|
|
578
|
-
{
|
|
579
|
-
id: imported.id,
|
|
580
|
-
type: KeyringAccountType.Imported,
|
|
581
|
-
label: 'Imported Account',
|
|
582
|
-
},
|
|
583
|
-
];
|
|
584
|
-
|
|
585
|
-
for (const { id, type, label } of switches) {
|
|
586
|
-
currentVaultState.activeAccount = { id, type };
|
|
587
|
-
const active = keyringManager.getActiveAccount();
|
|
588
|
-
expect(active.activeAccount.id).toBe(id);
|
|
589
|
-
expect(active.activeAccountType).toBe(type);
|
|
590
|
-
expect(active.activeAccount.label).toBe(label);
|
|
591
|
-
}
|
|
592
|
-
});
|
|
593
|
-
|
|
594
|
-
it('should maintain separate ID sequences for each account type', async () => {
|
|
595
|
-
// Add HD accounts
|
|
596
|
-
const hd1 = await keyringManager.addNewAccount();
|
|
597
|
-
|
|
598
|
-
// Update vault state to include hd1 so hd2 gets the right ID
|
|
599
|
-
currentVaultState.accounts[KeyringAccountType.HDAccount][1] = {
|
|
600
|
-
id: 1,
|
|
601
|
-
label: 'Account 2',
|
|
602
|
-
address: hd1.address,
|
|
603
|
-
xpub: hd1.xpub,
|
|
604
|
-
xprv: '',
|
|
605
|
-
isImported: false,
|
|
606
|
-
isTrezorWallet: false,
|
|
607
|
-
isLedgerWallet: false,
|
|
608
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
609
|
-
assets: { syscoin: [], ethereum: [] },
|
|
610
|
-
};
|
|
611
|
-
|
|
612
|
-
const hd2 = await keyringManager.addNewAccount();
|
|
613
|
-
|
|
614
|
-
// Import accounts
|
|
615
|
-
const imported1 = await keyringManager.importAccount(
|
|
616
|
-
'0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318'
|
|
617
|
-
);
|
|
618
|
-
|
|
619
|
-
// Update vault state to include imported1 so imported2 gets the right ID
|
|
620
|
-
currentVaultState.accounts[KeyringAccountType.Imported][0] = {
|
|
621
|
-
id: 0,
|
|
622
|
-
label: 'Imported 1',
|
|
623
|
-
address: imported1.address,
|
|
624
|
-
xpub: imported1.xpub,
|
|
625
|
-
xprv: imported1.xprv,
|
|
626
|
-
isImported: true,
|
|
627
|
-
isTrezorWallet: false,
|
|
628
|
-
isLedgerWallet: false,
|
|
629
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
630
|
-
assets: { syscoin: [], ethereum: [] },
|
|
631
|
-
};
|
|
632
|
-
|
|
633
|
-
const imported2 = await keyringManager.importAccount(
|
|
634
|
-
'0x1234567890123456789012345678901234567890123456789012345678901234'
|
|
635
|
-
);
|
|
636
|
-
|
|
637
|
-
// HD accounts should have sequential IDs starting from 0
|
|
638
|
-
expect(hd1.id).toBe(1);
|
|
639
|
-
expect(hd2.id).toBe(2);
|
|
640
|
-
|
|
641
|
-
// Imported accounts should have their own ID sequence starting from 0
|
|
642
|
-
expect(imported1.id).toBe(0);
|
|
643
|
-
expect(imported2.id).toBe(1);
|
|
644
|
-
});
|
|
645
|
-
});
|
|
646
|
-
|
|
647
|
-
describe('Account State Management', () => {
|
|
648
|
-
it('should preserve account state across lock/unlock', async () => {
|
|
649
|
-
// Add accounts
|
|
650
|
-
const hdAccount = await keyringManager.addNewAccount('Test Account');
|
|
651
|
-
const imported = await keyringManager.importAccount(
|
|
652
|
-
'0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318',
|
|
653
|
-
'Imported Test'
|
|
654
|
-
);
|
|
655
|
-
|
|
656
|
-
// Update vault state
|
|
657
|
-
currentVaultState.accounts[KeyringAccountType.HDAccount][1] = {
|
|
658
|
-
id: 1,
|
|
659
|
-
label: 'Test Account',
|
|
660
|
-
address: hdAccount.address,
|
|
661
|
-
xpub: hdAccount.xpub,
|
|
662
|
-
xprv: '',
|
|
663
|
-
isImported: false,
|
|
664
|
-
isTrezorWallet: false,
|
|
665
|
-
isLedgerWallet: false,
|
|
666
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
667
|
-
assets: { syscoin: [], ethereum: [] },
|
|
668
|
-
};
|
|
669
|
-
currentVaultState.accounts[KeyringAccountType.Imported][imported.id] = {
|
|
670
|
-
id: imported.id,
|
|
671
|
-
label: 'Imported Test',
|
|
672
|
-
address: imported.address,
|
|
673
|
-
xpub: imported.xpub,
|
|
674
|
-
xprv: imported.xprv,
|
|
675
|
-
isImported: true,
|
|
676
|
-
isTrezorWallet: false,
|
|
677
|
-
isLedgerWallet: false,
|
|
678
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
679
|
-
assets: { syscoin: [], ethereum: [] },
|
|
680
|
-
};
|
|
681
|
-
|
|
682
|
-
// Switch to imported account (only update vault state)
|
|
683
|
-
currentVaultState.activeAccount = {
|
|
684
|
-
id: imported.id,
|
|
685
|
-
type: KeyringAccountType.Imported,
|
|
686
|
-
};
|
|
687
|
-
|
|
688
|
-
// Lock and unlock
|
|
689
|
-
keyringManager.lockWallet();
|
|
690
|
-
await keyringManager.unlock(FAKE_PASSWORD);
|
|
691
|
-
|
|
692
|
-
// Active account should still be the imported one
|
|
693
|
-
const active = keyringManager.getActiveAccount();
|
|
694
|
-
expect(active.activeAccount.id).toBe(imported.id);
|
|
695
|
-
expect(active.activeAccountType).toBe(KeyringAccountType.Imported);
|
|
696
|
-
expect(active.activeAccount.label).toBe('Imported Test');
|
|
697
|
-
});
|
|
698
|
-
|
|
699
|
-
it('should get account xpub', async () => {
|
|
700
|
-
const xpub = keyringManager.getAccountXpub();
|
|
701
|
-
expect(xpub).toBeDefined();
|
|
702
|
-
expect(typeof xpub).toBe('string');
|
|
703
|
-
});
|
|
704
|
-
|
|
705
|
-
it('should not expose private key in account data', async () => {
|
|
706
|
-
const account = keyringManager.getActiveAccount().activeAccount;
|
|
707
|
-
expect(account).not.toHaveProperty('xprv');
|
|
708
|
-
expect(account).toHaveProperty('xpub');
|
|
709
|
-
});
|
|
710
|
-
});
|
|
711
|
-
|
|
712
|
-
describe('Edge Cases', () => {
|
|
713
|
-
it('should handle invalid account type when getting account', async () => {
|
|
714
|
-
expect(() =>
|
|
715
|
-
keyringManager.getAccountById(0, 'INVALID_TYPE' as any)
|
|
716
|
-
).toThrow();
|
|
717
|
-
});
|
|
718
|
-
|
|
719
|
-
it('should handle getting non-existent account', async () => {
|
|
720
|
-
expect(() =>
|
|
721
|
-
keyringManager.getAccountById(999, KeyringAccountType.HDAccount)
|
|
722
|
-
).toThrow('Account not found');
|
|
723
|
-
});
|
|
724
|
-
|
|
725
|
-
it('should reject import of invalid private key', async () => {
|
|
726
|
-
await expect(
|
|
727
|
-
keyringManager.importAccount('not_a_valid_key')
|
|
728
|
-
).rejects.toThrow();
|
|
729
|
-
});
|
|
730
|
-
|
|
731
|
-
it('should handle getNextAccountId with empty accounts', () => {
|
|
732
|
-
// This is a private method, but we can test it indirectly
|
|
733
|
-
// by checking that first account gets ID 0
|
|
734
|
-
const account = keyringManager.getActiveAccount().activeAccount;
|
|
735
|
-
expect(account.id).toBe(0);
|
|
736
|
-
});
|
|
737
|
-
|
|
738
|
-
it('should fill gaps in account IDs when accounts are removed', async () => {
|
|
739
|
-
// Create multiple accounts to simulate a scenario where some are removed
|
|
740
|
-
const account1 = await keyringManager.addNewAccount('Account 1');
|
|
741
|
-
expect(account1.id).toBe(1);
|
|
742
|
-
|
|
743
|
-
// Update vault state to include account1
|
|
744
|
-
currentVaultState.accounts[KeyringAccountType.HDAccount][1] = {
|
|
745
|
-
id: 1,
|
|
746
|
-
label: 'Account 1',
|
|
747
|
-
address: account1.address,
|
|
748
|
-
xpub: account1.xpub,
|
|
749
|
-
xprv: '',
|
|
750
|
-
isImported: false,
|
|
751
|
-
isTrezorWallet: false,
|
|
752
|
-
isLedgerWallet: false,
|
|
753
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
754
|
-
assets: { syscoin: [], ethereum: [] },
|
|
755
|
-
};
|
|
756
|
-
|
|
757
|
-
const account2 = await keyringManager.addNewAccount('Account 2');
|
|
758
|
-
expect(account2.id).toBe(2);
|
|
759
|
-
|
|
760
|
-
// Update vault state to include account2
|
|
761
|
-
currentVaultState.accounts[KeyringAccountType.HDAccount][2] = {
|
|
762
|
-
id: 2,
|
|
763
|
-
label: 'Account 2',
|
|
764
|
-
address: account2.address,
|
|
765
|
-
xpub: account2.xpub,
|
|
766
|
-
xprv: '',
|
|
767
|
-
isImported: false,
|
|
768
|
-
isTrezorWallet: false,
|
|
769
|
-
isLedgerWallet: false,
|
|
770
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
771
|
-
assets: { syscoin: [], ethereum: [] },
|
|
772
|
-
};
|
|
773
|
-
|
|
774
|
-
const account3 = await keyringManager.addNewAccount('Account 3');
|
|
775
|
-
expect(account3.id).toBe(3);
|
|
776
|
-
|
|
777
|
-
// Update vault state to include account3
|
|
778
|
-
currentVaultState.accounts[KeyringAccountType.HDAccount][3] = {
|
|
779
|
-
id: 3,
|
|
780
|
-
label: 'Account 3',
|
|
781
|
-
address: account3.address,
|
|
782
|
-
xpub: account3.xpub,
|
|
783
|
-
xprv: '',
|
|
784
|
-
isImported: false,
|
|
785
|
-
isTrezorWallet: false,
|
|
786
|
-
isLedgerWallet: false,
|
|
787
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
788
|
-
assets: { syscoin: [], ethereum: [] },
|
|
789
|
-
};
|
|
790
|
-
|
|
791
|
-
// Simulate account deletion by removing account with ID 1 from vault state
|
|
792
|
-
// (In real usage, this would be done by the removeAccount controller method)
|
|
793
|
-
delete currentVaultState.accounts[KeyringAccountType.HDAccount][1];
|
|
794
|
-
|
|
795
|
-
// Now when we create a new account, it should fill the gap at ID 1
|
|
796
|
-
const newAccount = await keyringManager.addNewAccount('New Account');
|
|
797
|
-
expect(newAccount.id).toBe(1); // Should reuse the deleted account's ID
|
|
798
|
-
|
|
799
|
-
// Update vault state to include the new account
|
|
800
|
-
currentVaultState.accounts[KeyringAccountType.HDAccount][1] = {
|
|
801
|
-
id: 1,
|
|
802
|
-
label: 'New Account',
|
|
803
|
-
address: newAccount.address,
|
|
804
|
-
xpub: newAccount.xpub,
|
|
805
|
-
xprv: '',
|
|
806
|
-
isImported: false,
|
|
807
|
-
isTrezorWallet: false,
|
|
808
|
-
isLedgerWallet: false,
|
|
809
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
810
|
-
assets: { syscoin: [], ethereum: [] },
|
|
811
|
-
};
|
|
812
|
-
|
|
813
|
-
// At this point we have accounts: [0, 1, 2, 3] - no gaps
|
|
814
|
-
// Next account should get the next sequential ID
|
|
815
|
-
const anotherAccount = await keyringManager.addNewAccount(
|
|
816
|
-
'Another Account'
|
|
817
|
-
);
|
|
818
|
-
expect(anotherAccount.id).toBe(4); // Should continue sequence after 3
|
|
819
|
-
|
|
820
|
-
// Update vault state to include anotherAccount
|
|
821
|
-
currentVaultState.accounts[KeyringAccountType.HDAccount][4] = {
|
|
822
|
-
id: 4,
|
|
823
|
-
label: 'Another Account',
|
|
824
|
-
address: anotherAccount.address,
|
|
825
|
-
xpub: anotherAccount.xpub,
|
|
826
|
-
xprv: '',
|
|
827
|
-
isImported: false,
|
|
828
|
-
isTrezorWallet: false,
|
|
829
|
-
isLedgerWallet: false,
|
|
830
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
831
|
-
assets: { syscoin: [], ethereum: [] },
|
|
832
|
-
};
|
|
833
|
-
|
|
834
|
-
// Simulate removing the middle account (ID 2)
|
|
835
|
-
delete currentVaultState.accounts[KeyringAccountType.HDAccount][2];
|
|
836
|
-
|
|
837
|
-
// Now we have accounts: [0, 1, 3, 4] - gap at ID 2
|
|
838
|
-
// Next account should fill that gap
|
|
839
|
-
const gapFillerAccount = await keyringManager.addNewAccount('Gap Filler');
|
|
840
|
-
expect(gapFillerAccount.id).toBe(2); // Should reuse ID 2
|
|
841
|
-
});
|
|
842
|
-
});
|
|
843
|
-
|
|
844
|
-
describe('Account Label Consistency', () => {
|
|
845
|
-
it('should create EVM accounts with generic labels regardless of network', async () => {
|
|
846
|
-
// Test that EVM accounts always get generic "Account N" labels
|
|
847
|
-
// regardless of which specific EVM network they're created on
|
|
848
|
-
|
|
849
|
-
// Set up NEVM Testnet vault state
|
|
850
|
-
const nevmTestnetVaultState = createMockVaultState({
|
|
851
|
-
activeAccountId: 0,
|
|
852
|
-
activeAccountType: KeyringAccountType.HDAccount,
|
|
853
|
-
networkType: INetworkType.Ethereum,
|
|
854
|
-
chainId: 5700, // Syscoin NEVM Testnet
|
|
855
|
-
});
|
|
856
|
-
const nevmTestnetVaultGetter = jest.fn(() => nevmTestnetVaultState);
|
|
857
|
-
|
|
858
|
-
// Create keyring on NEVM Testnet
|
|
859
|
-
const nevmKeyring = await KeyringManager.createInitialized(
|
|
860
|
-
PEACE_SEED_PHRASE,
|
|
861
|
-
FAKE_PASSWORD,
|
|
862
|
-
nevmTestnetVaultGetter
|
|
863
|
-
);
|
|
864
|
-
|
|
865
|
-
// Create accounts on NEVM Testnet
|
|
866
|
-
const account1 = nevmKeyring.getActiveAccount().activeAccount;
|
|
867
|
-
const account2 = await nevmKeyring.addNewAccount();
|
|
868
|
-
|
|
869
|
-
// Update vault state to include account2 BEFORE creating account3
|
|
870
|
-
nevmTestnetVaultState.accounts[KeyringAccountType.HDAccount][1] = {
|
|
871
|
-
id: 1,
|
|
872
|
-
label: account2.label,
|
|
873
|
-
address: account2.address,
|
|
874
|
-
xpub: account2.xpub,
|
|
875
|
-
xprv: '',
|
|
876
|
-
isImported: false,
|
|
877
|
-
isTrezorWallet: false,
|
|
878
|
-
isLedgerWallet: false,
|
|
879
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
880
|
-
assets: { syscoin: [], ethereum: [] },
|
|
881
|
-
};
|
|
882
|
-
|
|
883
|
-
const account3 = await nevmKeyring.addNewAccount();
|
|
884
|
-
|
|
885
|
-
// Update vault state to include account3
|
|
886
|
-
nevmTestnetVaultState.accounts[KeyringAccountType.HDAccount][2] = {
|
|
887
|
-
id: 2,
|
|
888
|
-
label: account3.label,
|
|
889
|
-
address: account3.address,
|
|
890
|
-
xpub: account3.xpub,
|
|
891
|
-
xprv: '',
|
|
892
|
-
isImported: false,
|
|
893
|
-
isTrezorWallet: false,
|
|
894
|
-
isLedgerWallet: false,
|
|
895
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
896
|
-
assets: { syscoin: [], ethereum: [] },
|
|
897
|
-
};
|
|
898
|
-
|
|
899
|
-
// BUG TEST: EVM accounts should have generic labels, not network-specific ones
|
|
900
|
-
expect(account1.label).toBe('Account 1'); // Should be generic
|
|
901
|
-
expect(account2.label).toBe('Account 2'); // Should be generic
|
|
902
|
-
expect(account3.label).toBe('Account 3'); // Should be generic
|
|
903
|
-
|
|
904
|
-
// These should NOT happen (network-specific labels for EVM accounts)
|
|
905
|
-
expect(account1.label).not.toContain('NEVM');
|
|
906
|
-
expect(account1.label).not.toContain('Testnet');
|
|
907
|
-
expect(account2.label).not.toContain('NEVM');
|
|
908
|
-
expect(account2.label).not.toContain('Testnet');
|
|
909
|
-
expect(account3.label).not.toContain('NEVM');
|
|
910
|
-
expect(account3.label).not.toContain('Testnet');
|
|
911
|
-
|
|
912
|
-
// Verify accounts work across EVM networks (same slip44=60)
|
|
913
|
-
expect(account1.address.startsWith('0x')).toBe(true);
|
|
914
|
-
expect(account2.address.startsWith('0x')).toBe(true);
|
|
915
|
-
expect(account3.address.startsWith('0x')).toBe(true);
|
|
916
|
-
});
|
|
917
|
-
|
|
918
|
-
it('should create UTXO accounts with network-specific labels', async () => {
|
|
919
|
-
// Test the keyring manager's actual label generation logic
|
|
920
|
-
|
|
921
|
-
// Set up empty Syscoin Testnet vault state (no pre-existing accounts)
|
|
922
|
-
const sysTestnetVaultState = createMockVaultState({
|
|
923
|
-
activeAccountId: 0,
|
|
924
|
-
activeAccountType: KeyringAccountType.HDAccount,
|
|
925
|
-
networkType: INetworkType.Syscoin,
|
|
926
|
-
chainId: 5700, // Syscoin UTXO Testnet
|
|
927
|
-
});
|
|
928
|
-
|
|
929
|
-
// Clear pre-existing accounts to let keyring manager create them
|
|
930
|
-
sysTestnetVaultState.accounts[KeyringAccountType.HDAccount] = {};
|
|
931
|
-
|
|
932
|
-
const sysTestnetVaultGetter = jest.fn(() => sysTestnetVaultState);
|
|
933
|
-
|
|
934
|
-
// Create keyring - this should call createFirstAccount internally
|
|
935
|
-
const sysKeyring = await KeyringManager.createInitialized(
|
|
936
|
-
PEACE_SEED_PHRASE,
|
|
937
|
-
FAKE_PASSWORD,
|
|
938
|
-
sysTestnetVaultGetter
|
|
939
|
-
);
|
|
940
|
-
|
|
941
|
-
// The first account should be created by keyring manager's createFirstAccount method
|
|
942
|
-
const firstAccount = await sysKeyring.createFirstAccount();
|
|
943
|
-
|
|
944
|
-
// Add to vault state so addNewAccount can find existing accounts for ID calculation
|
|
945
|
-
sysTestnetVaultState.accounts[KeyringAccountType.HDAccount][0] = {
|
|
946
|
-
id: 0,
|
|
947
|
-
label: firstAccount.label,
|
|
948
|
-
address: firstAccount.address,
|
|
949
|
-
xpub: firstAccount.xpub,
|
|
950
|
-
xprv: '',
|
|
951
|
-
isImported: false,
|
|
952
|
-
isTrezorWallet: false,
|
|
953
|
-
isLedgerWallet: false,
|
|
954
|
-
balances: { syscoin: 0, ethereum: 0 },
|
|
955
|
-
assets: { syscoin: [], ethereum: [] },
|
|
956
|
-
};
|
|
957
|
-
|
|
958
|
-
// Create second account using addNewAccount
|
|
959
|
-
const secondAccount = await sysKeyring.addNewAccount();
|
|
960
|
-
|
|
961
|
-
// Test that the keyring manager generates network-specific labels for UTXO accounts
|
|
962
|
-
expect(firstAccount.label).toContain('SYS'); // Should be "SYS-T 1" for testnet
|
|
963
|
-
expect(secondAccount.label).toContain('SYS'); // Should be "SYS-T 2" for testnet
|
|
964
|
-
|
|
965
|
-
// Verify accounts are UTXO format
|
|
966
|
-
expect(firstAccount.address.startsWith('tsys1')).toBe(true); // Testnet format
|
|
967
|
-
expect(secondAccount.address.startsWith('tsys1')).toBe(true); // Testnet format
|
|
968
|
-
});
|
|
969
|
-
});
|
|
970
|
-
});
|