@sidhujag/sysweb3-keyring 1.0.547 → 1.0.549

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 (212) hide show
  1. package/{dist/cjs → cjs}/providers.js +1 -64
  2. package/cjs/providers.js.map +1 -0
  3. package/{dist/cjs → cjs}/transactions/ethereum.js +1 -16
  4. package/cjs/transactions/ethereum.js.map +1 -0
  5. package/package.json +2 -30
  6. package/{dist/types → types}/providers.d.ts +0 -8
  7. package/{dist/types → types}/transactions/ethereum.d.ts +2 -2
  8. package/{dist/types → types}/types.d.ts +2 -2
  9. package/coverage/clover.xml +0 -2875
  10. package/coverage/coverage-final.json +0 -29468
  11. package/coverage/lcov-report/base.css +0 -354
  12. package/coverage/lcov-report/block-navigation.js +0 -85
  13. package/coverage/lcov-report/favicon.png +0 -0
  14. package/coverage/lcov-report/index.html +0 -320
  15. package/coverage/lcov-report/prettify.css +0 -101
  16. package/coverage/lcov-report/prettify.js +0 -1008
  17. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  18. package/coverage/lcov-report/sorter.js +0 -191
  19. package/coverage/lcov-report/src/index.html +0 -276
  20. package/coverage/lcov-report/src/index.ts.html +0 -114
  21. package/coverage/lcov-report/src/initial-state.ts.html +0 -558
  22. package/coverage/lcov-report/src/keyring-manager.ts.html +0 -6279
  23. package/coverage/lcov-report/src/ledger/bitcoin_client/index.html +0 -178
  24. package/coverage/lcov-report/src/ledger/bitcoin_client/index.ts.html +0 -144
  25. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/appClient.ts.html +0 -1560
  26. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/bip32.ts.html +0 -276
  27. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/buffertools.ts.html +0 -495
  28. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/clientCommands.ts.html +0 -1138
  29. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/index.html +0 -363
  30. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/merkelizedPsbt.ts.html +0 -289
  31. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/merkle.ts.html +0 -486
  32. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/merkleMap.ts.html +0 -240
  33. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/policy.ts.html +0 -342
  34. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/psbtv2.ts.html +0 -2388
  35. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/varint.ts.html +0 -453
  36. package/coverage/lcov-report/src/ledger/consts.ts.html +0 -177
  37. package/coverage/lcov-report/src/ledger/index.html +0 -216
  38. package/coverage/lcov-report/src/ledger/index.ts.html +0 -1371
  39. package/coverage/lcov-report/src/ledger/utils.ts.html +0 -102
  40. package/coverage/lcov-report/src/signers.ts.html +0 -591
  41. package/coverage/lcov-report/src/storage.ts.html +0 -198
  42. package/coverage/lcov-report/src/transactions/ethereum.ts.html +0 -5826
  43. package/coverage/lcov-report/src/transactions/index.html +0 -216
  44. package/coverage/lcov-report/src/transactions/index.ts.html +0 -93
  45. package/coverage/lcov-report/src/transactions/syscoin.ts.html +0 -1521
  46. package/coverage/lcov-report/src/trezor/index.html +0 -176
  47. package/coverage/lcov-report/src/trezor/index.ts.html +0 -2655
  48. package/coverage/lcov-report/src/types.ts.html +0 -1443
  49. package/coverage/lcov-report/src/utils/derivation-paths.ts.html +0 -486
  50. package/coverage/lcov-report/src/utils/index.html +0 -196
  51. package/coverage/lcov-report/src/utils/psbt.ts.html +0 -159
  52. package/coverage/lcov-report/test/helpers/constants.ts.html +0 -627
  53. package/coverage/lcov-report/test/helpers/index.html +0 -176
  54. package/coverage/lcov.info +0 -4832
  55. package/dist/cjs/providers.js.map +0 -1
  56. package/dist/cjs/transactions/ethereum.js.map +0 -1
  57. package/dist/package.json +0 -50
  58. package/examples/basic-usage.js +0 -140
  59. package/jest.config.js +0 -32
  60. package/readme.md +0 -201
  61. package/src/declare.d.ts +0 -7
  62. package/src/errorUtils.ts +0 -83
  63. package/src/hardware-wallet-manager.ts +0 -655
  64. package/src/index.ts +0 -12
  65. package/src/initial-state.ts +0 -108
  66. package/src/keyring-manager.ts +0 -2698
  67. package/src/ledger/bitcoin_client/index.ts +0 -19
  68. package/src/ledger/bitcoin_client/lib/appClient.ts +0 -405
  69. package/src/ledger/bitcoin_client/lib/bip32.ts +0 -61
  70. package/src/ledger/bitcoin_client/lib/buffertools.ts +0 -134
  71. package/src/ledger/bitcoin_client/lib/clientCommands.ts +0 -356
  72. package/src/ledger/bitcoin_client/lib/constants.ts +0 -12
  73. package/src/ledger/bitcoin_client/lib/merkelizedPsbt.ts +0 -65
  74. package/src/ledger/bitcoin_client/lib/merkle.ts +0 -136
  75. package/src/ledger/bitcoin_client/lib/merkleMap.ts +0 -49
  76. package/src/ledger/bitcoin_client/lib/policy.ts +0 -91
  77. package/src/ledger/bitcoin_client/lib/psbtv2.ts +0 -768
  78. package/src/ledger/bitcoin_client/lib/varint.ts +0 -120
  79. package/src/ledger/consts.ts +0 -3
  80. package/src/ledger/index.ts +0 -685
  81. package/src/ledger/types.ts +0 -74
  82. package/src/network-utils.ts +0 -99
  83. package/src/providers.ts +0 -345
  84. package/src/signers.ts +0 -158
  85. package/src/storage.ts +0 -63
  86. package/src/transactions/__tests__/integration.test.ts +0 -303
  87. package/src/transactions/__tests__/syscoin.test.ts +0 -409
  88. package/src/transactions/ethereum.ts +0 -2503
  89. package/src/transactions/index.ts +0 -2
  90. package/src/transactions/syscoin.ts +0 -542
  91. package/src/trezor/index.ts +0 -1050
  92. package/src/types.ts +0 -366
  93. package/src/utils/derivation-paths.ts +0 -133
  94. package/src/utils/psbt.ts +0 -24
  95. package/src/utils.ts +0 -191
  96. package/test/README.md +0 -158
  97. package/test/__mocks__/ledger-mock.js +0 -20
  98. package/test/__mocks__/trezor-mock.js +0 -75
  99. package/test/cleanup-summary.md +0 -167
  100. package/test/helpers/README.md +0 -78
  101. package/test/helpers/constants.ts +0 -79
  102. package/test/helpers/setup.ts +0 -714
  103. package/test/integration/import-validation.spec.ts +0 -588
  104. package/test/unit/hardware/ledger.spec.ts +0 -869
  105. package/test/unit/hardware/trezor.spec.ts +0 -828
  106. package/test/unit/keyring-manager/account-management.spec.ts +0 -970
  107. package/test/unit/keyring-manager/import-watchonly.spec.ts +0 -181
  108. package/test/unit/keyring-manager/import-wif.spec.ts +0 -126
  109. package/test/unit/keyring-manager/initialization.spec.ts +0 -782
  110. package/test/unit/keyring-manager/key-derivation.spec.ts +0 -996
  111. package/test/unit/keyring-manager/security.spec.ts +0 -505
  112. package/test/unit/keyring-manager/state-management.spec.ts +0 -375
  113. package/test/unit/network/network-management.spec.ts +0 -372
  114. package/test/unit/transactions/ethereum-transactions.spec.ts +0 -382
  115. package/test/unit/transactions/syscoin-transactions.spec.ts +0 -615
  116. package/tsconfig.json +0 -14
  117. /package/{dist/README.md → README.md} +0 -0
  118. /package/{dist/cjs → cjs}/errorUtils.js +0 -0
  119. /package/{dist/cjs → cjs}/errorUtils.js.map +0 -0
  120. /package/{dist/cjs → cjs}/hardware-wallet-manager.js +0 -0
  121. /package/{dist/cjs → cjs}/hardware-wallet-manager.js.map +0 -0
  122. /package/{dist/cjs → cjs}/index.js +0 -0
  123. /package/{dist/cjs → cjs}/index.js.map +0 -0
  124. /package/{dist/cjs → cjs}/initial-state.js +0 -0
  125. /package/{dist/cjs → cjs}/initial-state.js.map +0 -0
  126. /package/{dist/cjs → cjs}/keyring-manager.js +0 -0
  127. /package/{dist/cjs → cjs}/keyring-manager.js.map +0 -0
  128. /package/{dist/cjs → cjs}/ledger/bitcoin_client/index.js +0 -0
  129. /package/{dist/cjs → cjs}/ledger/bitcoin_client/index.js.map +0 -0
  130. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/appClient.js +0 -0
  131. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/appClient.js.map +0 -0
  132. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/bip32.js +0 -0
  133. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/bip32.js.map +0 -0
  134. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/buffertools.js +0 -0
  135. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/buffertools.js.map +0 -0
  136. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/clientCommands.js +0 -0
  137. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/clientCommands.js.map +0 -0
  138. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/constants.js +0 -0
  139. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/constants.js.map +0 -0
  140. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/merkelizedPsbt.js +0 -0
  141. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/merkelizedPsbt.js.map +0 -0
  142. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/merkle.js +0 -0
  143. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/merkle.js.map +0 -0
  144. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/merkleMap.js +0 -0
  145. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/merkleMap.js.map +0 -0
  146. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/policy.js +0 -0
  147. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/policy.js.map +0 -0
  148. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/psbtv2.js +0 -0
  149. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/psbtv2.js.map +0 -0
  150. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/varint.js +0 -0
  151. /package/{dist/cjs → cjs}/ledger/bitcoin_client/lib/varint.js.map +0 -0
  152. /package/{dist/cjs → cjs}/ledger/consts.js +0 -0
  153. /package/{dist/cjs → cjs}/ledger/consts.js.map +0 -0
  154. /package/{dist/cjs → cjs}/ledger/index.js +0 -0
  155. /package/{dist/cjs → cjs}/ledger/index.js.map +0 -0
  156. /package/{dist/cjs → cjs}/ledger/types.js +0 -0
  157. /package/{dist/cjs → cjs}/ledger/types.js.map +0 -0
  158. /package/{dist/cjs → cjs}/network-utils.js +0 -0
  159. /package/{dist/cjs → cjs}/network-utils.js.map +0 -0
  160. /package/{dist/cjs → cjs}/signers.js +0 -0
  161. /package/{dist/cjs → cjs}/signers.js.map +0 -0
  162. /package/{dist/cjs → cjs}/storage.js +0 -0
  163. /package/{dist/cjs → cjs}/storage.js.map +0 -0
  164. /package/{dist/cjs → cjs}/transactions/__tests__/integration.test.js +0 -0
  165. /package/{dist/cjs → cjs}/transactions/__tests__/integration.test.js.map +0 -0
  166. /package/{dist/cjs → cjs}/transactions/__tests__/syscoin.test.js +0 -0
  167. /package/{dist/cjs → cjs}/transactions/__tests__/syscoin.test.js.map +0 -0
  168. /package/{dist/cjs → cjs}/transactions/index.js +0 -0
  169. /package/{dist/cjs → cjs}/transactions/index.js.map +0 -0
  170. /package/{dist/cjs → cjs}/transactions/syscoin.js +0 -0
  171. /package/{dist/cjs → cjs}/transactions/syscoin.js.map +0 -0
  172. /package/{dist/cjs → cjs}/trezor/index.js +0 -0
  173. /package/{dist/cjs → cjs}/trezor/index.js.map +0 -0
  174. /package/{dist/cjs → cjs}/types.js +0 -0
  175. /package/{dist/cjs → cjs}/types.js.map +0 -0
  176. /package/{dist/cjs → cjs}/utils/derivation-paths.js +0 -0
  177. /package/{dist/cjs → cjs}/utils/derivation-paths.js.map +0 -0
  178. /package/{dist/cjs → cjs}/utils/psbt.js +0 -0
  179. /package/{dist/cjs → cjs}/utils/psbt.js.map +0 -0
  180. /package/{dist/cjs → cjs}/utils.js +0 -0
  181. /package/{dist/cjs → cjs}/utils.js.map +0 -0
  182. /package/{dist/types → types}/errorUtils.d.ts +0 -0
  183. /package/{dist/types → types}/hardware-wallet-manager.d.ts +0 -0
  184. /package/{dist/types → types}/index.d.ts +0 -0
  185. /package/{dist/types → types}/initial-state.d.ts +0 -0
  186. /package/{dist/types → types}/keyring-manager.d.ts +0 -0
  187. /package/{dist/types → types}/ledger/bitcoin_client/index.d.ts +0 -0
  188. /package/{dist/types → types}/ledger/bitcoin_client/lib/appClient.d.ts +0 -0
  189. /package/{dist/types → types}/ledger/bitcoin_client/lib/bip32.d.ts +0 -0
  190. /package/{dist/types → types}/ledger/bitcoin_client/lib/buffertools.d.ts +0 -0
  191. /package/{dist/types → types}/ledger/bitcoin_client/lib/clientCommands.d.ts +0 -0
  192. /package/{dist/types → types}/ledger/bitcoin_client/lib/constants.d.ts +0 -0
  193. /package/{dist/types → types}/ledger/bitcoin_client/lib/merkelizedPsbt.d.ts +0 -0
  194. /package/{dist/types → types}/ledger/bitcoin_client/lib/merkle.d.ts +0 -0
  195. /package/{dist/types → types}/ledger/bitcoin_client/lib/merkleMap.d.ts +0 -0
  196. /package/{dist/types → types}/ledger/bitcoin_client/lib/policy.d.ts +0 -0
  197. /package/{dist/types → types}/ledger/bitcoin_client/lib/psbtv2.d.ts +0 -0
  198. /package/{dist/types → types}/ledger/bitcoin_client/lib/varint.d.ts +0 -0
  199. /package/{dist/types → types}/ledger/consts.d.ts +0 -0
  200. /package/{dist/types → types}/ledger/index.d.ts +0 -0
  201. /package/{dist/types → types}/ledger/types.d.ts +0 -0
  202. /package/{dist/types → types}/network-utils.d.ts +0 -0
  203. /package/{dist/types → types}/signers.d.ts +0 -0
  204. /package/{dist/types → types}/storage.d.ts +0 -0
  205. /package/{dist/types → types}/transactions/__tests__/integration.test.d.ts +0 -0
  206. /package/{dist/types → types}/transactions/__tests__/syscoin.test.d.ts +0 -0
  207. /package/{dist/types → types}/transactions/index.d.ts +0 -0
  208. /package/{dist/types → types}/transactions/syscoin.d.ts +0 -0
  209. /package/{dist/types → types}/trezor/index.d.ts +0 -0
  210. /package/{dist/types → types}/utils/derivation-paths.d.ts +0 -0
  211. /package/{dist/types → types}/utils/psbt.d.ts +0 -0
  212. /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
- });