@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,996 +0,0 @@
1
- import { Wallet } from '@ethersproject/wallet';
2
- import { INetworkType } from '@sidhujag/sysweb3-network';
3
-
4
- import { KeyringManager, KeyringAccountType } from '../../../src';
5
- import { FAKE_PASSWORD, PEACE_SEED_PHRASE } from '../../helpers/constants';
6
- import { setupMocks } from '../../helpers/setup';
7
-
8
- describe('KeyringManager - Key Derivation', () => {
9
- let keyringManager: KeyringManager;
10
- let mockVaultStateGetter: jest.Mock;
11
- let currentVaultState: any;
12
-
13
- beforeEach(async () => {
14
- setupMocks();
15
- // Set up vault-keys that would normally be created by Pali's MainController
16
- await setupTestVault(FAKE_PASSWORD);
17
- });
18
-
19
- describe('EVM Key Derivation', () => {
20
- beforeEach(async () => {
21
- // Set up EVM vault state
22
- currentVaultState = createMockVaultState({
23
- activeAccountId: 0,
24
- activeAccountType: KeyringAccountType.HDAccount,
25
- networkType: INetworkType.Ethereum,
26
- chainId: 1,
27
- });
28
- mockVaultStateGetter = jest.fn(() => currentVaultState);
29
-
30
- keyringManager = await KeyringManager.createInitialized(
31
- PEACE_SEED_PHRASE,
32
- FAKE_PASSWORD,
33
- mockVaultStateGetter
34
- );
35
- });
36
-
37
- it('should derive deterministic EVM addresses', async () => {
38
- // Get the actual derived addresses for PEACE_SEED_PHRASE (standard test phrase)
39
- const account0 = keyringManager.getActiveAccount().activeAccount;
40
- const address0 = account0.address;
41
-
42
- // Add and check more accounts - verify they are deterministic
43
- const account1 = await keyringManager.addNewAccount();
44
- const address1 = account1.address;
45
-
46
- // Update vault state with new account
47
- currentVaultState.accounts[KeyringAccountType.HDAccount][1] = {
48
- id: 1,
49
- label: 'Account 2',
50
- address: account1.address,
51
- xpub: account1.xpub,
52
- xprv: '',
53
- isImported: false,
54
- isTrezorWallet: false,
55
- isLedgerWallet: false,
56
- balances: { syscoin: 0, ethereum: 0 },
57
- assets: { syscoin: [], ethereum: [] },
58
- };
59
-
60
- const account2 = await keyringManager.addNewAccount();
61
- const address2 = account2.address;
62
-
63
- // Update vault state with new account
64
- currentVaultState.accounts[KeyringAccountType.HDAccount][2] = {
65
- id: 2,
66
- label: 'Account 3',
67
- address: account2.address,
68
- xpub: account2.xpub,
69
- xprv: '',
70
- isImported: false,
71
- isTrezorWallet: false,
72
- isLedgerWallet: false,
73
- balances: { syscoin: 0, ethereum: 0 },
74
- assets: { syscoin: [], ethereum: [] },
75
- };
76
-
77
- // Verify addresses are valid Ethereum addresses
78
- expect(address0.startsWith('0x')).toBe(true);
79
- expect(address0).toHaveLength(42);
80
- expect(address1.startsWith('0x')).toBe(true);
81
- expect(address1).toHaveLength(42);
82
- expect(address2.startsWith('0x')).toBe(true);
83
- expect(address2).toHaveLength(42);
84
-
85
- // All addresses should be unique
86
- expect(address0).not.toBe(address1);
87
- expect(address1).not.toBe(address2);
88
- expect(address2).not.toBe(address0);
89
- });
90
-
91
- it('should derive correct private keys for EVM accounts', async () => {
92
- // The vault state now properly includes encrypted xprv values
93
- // No manual updates needed - just test the functionality
94
-
95
- // Get private key for account 0
96
- const privateKey0 = await keyringManager.getPrivateKeyByAccountId(
97
- 0,
98
- KeyringAccountType.HDAccount,
99
- FAKE_PASSWORD
100
- );
101
-
102
- // Verify it derives the correct address
103
- const wallet = new Wallet(privateKey0);
104
- const account = keyringManager.getActiveAccount().activeAccount;
105
- expect(wallet.address.toLowerCase()).toBe(account.address.toLowerCase());
106
- });
107
-
108
- it('should use standard EVM derivation path', async () => {
109
- // EVM uses m/44'/60'/0'/0/index
110
- // This is tested indirectly by verifying known addresses
111
- const account = keyringManager.getActiveAccount().activeAccount;
112
- expect(account.address).toBeDefined();
113
- expect(account.address.startsWith('0x')).toBe(true);
114
- expect(account.address).toHaveLength(42);
115
- });
116
-
117
- it('should handle multiple accounts with consistent derivation', async () => {
118
- // Add multiple accounts
119
- const accounts = [keyringManager.getActiveAccount().activeAccount];
120
- for (let i = 0; i < 5; i++) {
121
- const account = await keyringManager.addNewAccount();
122
- accounts.push(account);
123
-
124
- // Update vault state with new account
125
- currentVaultState.accounts[KeyringAccountType.HDAccount][account.id] = {
126
- id: account.id,
127
- label: `Account ${account.id + 1}`,
128
- address: account.address,
129
- xpub: account.xpub,
130
- xprv: '',
131
- isImported: false,
132
- isTrezorWallet: false,
133
- isLedgerWallet: false,
134
- balances: { syscoin: 0, ethereum: 0 },
135
- assets: { syscoin: [], ethereum: [] },
136
- };
137
- }
138
-
139
- // Verify all addresses are unique
140
- const addresses = accounts.map((a) => a.address);
141
- const uniqueAddresses = new Set(addresses);
142
- expect(uniqueAddresses.size).toBe(addresses.length);
143
-
144
- // Verify sequential IDs
145
- accounts.forEach((account, index) => {
146
- expect(account.id).toBe(index);
147
- });
148
- });
149
-
150
- it('should derive same addresses from same seed across instances', async () => {
151
- // Set up second EVM vault state
152
- const vault2State = createMockVaultState({
153
- activeAccountId: 0,
154
- activeAccountType: KeyringAccountType.HDAccount,
155
- networkType: INetworkType.Ethereum,
156
- chainId: 1,
157
- });
158
- const vault2StateGetter = jest.fn(() => vault2State);
159
-
160
- // Create second keyring with same seed
161
- const keyring2 = await KeyringManager.createInitialized(
162
- PEACE_SEED_PHRASE,
163
- FAKE_PASSWORD,
164
- vault2StateGetter
165
- );
166
-
167
- // Add accounts to both
168
- const accounts1 = [keyringManager.getActiveAccount().activeAccount];
169
- const accounts2 = [keyring2.getActiveAccount().activeAccount];
170
-
171
- for (let i = 0; i < 3; i++) {
172
- const account1 = await keyringManager.addNewAccount();
173
- const account2 = await keyring2.addNewAccount();
174
- accounts1.push(account1);
175
- accounts2.push(account2);
176
-
177
- // Update vault states with new accounts
178
- currentVaultState.accounts[KeyringAccountType.HDAccount][account1.id] =
179
- {
180
- id: account1.id,
181
- label: `Account ${account1.id + 1}`,
182
- address: account1.address,
183
- xpub: account1.xpub,
184
- xprv: '',
185
- isImported: false,
186
- isTrezorWallet: false,
187
- isLedgerWallet: false,
188
- balances: { syscoin: 0, ethereum: 0 },
189
- assets: { syscoin: [], ethereum: [] },
190
- };
191
- vault2State.accounts[KeyringAccountType.HDAccount][account2.id] = {
192
- id: account2.id,
193
- label: `Account ${account2.id + 1}`,
194
- address: account2.address,
195
- xpub: account2.xpub,
196
- xprv: '',
197
- isImported: false,
198
- isTrezorWallet: false,
199
- isLedgerWallet: false,
200
- balances: { syscoin: 0, ethereum: 0 },
201
- assets: { syscoin: [], ethereum: [] },
202
- };
203
- }
204
-
205
- // Verify addresses match
206
- for (let i = 0; i < accounts1.length; i++) {
207
- expect(accounts1[i].address).toBe(accounts2[i].address);
208
- }
209
- });
210
- });
211
-
212
- describe('UTXO Key Derivation', () => {
213
- beforeEach(async () => {
214
- // Set up UTXO vault state
215
- currentVaultState = createMockVaultState({
216
- activeAccountId: 0,
217
- activeAccountType: KeyringAccountType.HDAccount,
218
- networkType: INetworkType.Syscoin,
219
- chainId: 57,
220
- });
221
- mockVaultStateGetter = jest.fn(() => currentVaultState);
222
-
223
- keyringManager = await KeyringManager.createInitialized(
224
- PEACE_SEED_PHRASE,
225
- FAKE_PASSWORD,
226
- mockVaultStateGetter
227
- );
228
- });
229
-
230
- it('should derive deterministic UTXO addresses', async () => {
231
- // Check initial account has Syscoin address format
232
- const account0 = keyringManager.getActiveAccount().activeAccount;
233
- expect(account0.address.match(/^(sys1|tsys1)/)).toBeTruthy();
234
- });
235
-
236
- it('should use BIP84 derivation for UTXO', async () => {
237
- // The vault state now properly includes encrypted xprv values
238
- // No manual updates needed - just test the functionality
239
-
240
- const account = keyringManager.getActiveAccount().activeAccount;
241
- // BIP84 (native segwit) addresses start with 'sys1' or 'tsys1' for Syscoin
242
- expect(account.address.match(/^(sys1|tsys1)/)).toBeTruthy();
243
- expect(account.xpub).toBeDefined();
244
- expect(
245
- account.xpub.startsWith('zpub') || account.xpub.startsWith('xpub')
246
- ).toBe(true);
247
- });
248
-
249
- it('should derive different addresses for different account indices', async () => {
250
- const addresses = [
251
- keyringManager.getActiveAccount().activeAccount.address,
252
- ];
253
-
254
- // Add more accounts
255
- for (let i = 0; i < 3; i++) {
256
- const newAccount = await keyringManager.addNewAccount();
257
- addresses.push(newAccount.address);
258
-
259
- // Update vault state with new account
260
- currentVaultState.accounts[KeyringAccountType.HDAccount][
261
- newAccount.id
262
- ] = {
263
- id: newAccount.id,
264
- label: `Account ${newAccount.id + 1}`,
265
- address: newAccount.address,
266
- xpub: newAccount.xpub,
267
- xprv: '',
268
- isImported: false,
269
- isTrezorWallet: false,
270
- isLedgerWallet: false,
271
- balances: { syscoin: 0, ethereum: 0 },
272
- assets: { syscoin: [], ethereum: [] },
273
- };
274
- }
275
-
276
- // All addresses should be unique
277
- const uniqueAddresses = new Set(addresses);
278
- expect(uniqueAddresses.size).toBe(addresses.length);
279
- });
280
-
281
- it('should handle testnet derivation correctly', async () => {
282
- // Set up testnet vault state
283
- const testnetVaultState = createMockVaultState({
284
- activeAccountId: 0,
285
- activeAccountType: KeyringAccountType.HDAccount,
286
- networkType: INetworkType.Syscoin,
287
- chainId: 5700,
288
- });
289
- const testnetVaultStateGetter = jest.fn(() => testnetVaultState);
290
-
291
- // Create testnet keyring
292
- const testnetKeyring = await KeyringManager.createInitialized(
293
- PEACE_SEED_PHRASE,
294
- FAKE_PASSWORD,
295
- testnetVaultStateGetter
296
- );
297
-
298
- const account = testnetKeyring.getActiveAccount().activeAccount;
299
- // Testnet addresses should start with 'tsys1' or use default format
300
- expect(account.address.match(/^(sys1|tsys1)/)).toBeTruthy();
301
- });
302
- });
303
-
304
- describe('Cross-Chain Derivation Consistency', () => {
305
- it('should derive different addresses for EVM vs UTXO from same seed', async () => {
306
- // Set up EVM vault state
307
- const evmVaultState = createMockVaultState({
308
- activeAccountId: 0,
309
- activeAccountType: KeyringAccountType.HDAccount,
310
- networkType: INetworkType.Ethereum,
311
- chainId: 1,
312
- });
313
- const evmVaultStateGetter = jest.fn(() => evmVaultState);
314
-
315
- // EVM keyring
316
- const evmKeyring = await KeyringManager.createInitialized(
317
- PEACE_SEED_PHRASE,
318
- FAKE_PASSWORD,
319
- evmVaultStateGetter
320
- );
321
-
322
- // Set up UTXO vault state
323
- const utxoVaultState = createMockVaultState({
324
- activeAccountId: 0,
325
- activeAccountType: KeyringAccountType.HDAccount,
326
- networkType: INetworkType.Syscoin,
327
- chainId: 57,
328
- });
329
- const utxoVaultStateGetter = jest.fn(() => utxoVaultState);
330
-
331
- // UTXO keyring
332
- const utxoKeyring = await KeyringManager.createInitialized(
333
- PEACE_SEED_PHRASE,
334
- FAKE_PASSWORD,
335
- utxoVaultStateGetter
336
- );
337
-
338
- const evmAccount = evmKeyring.getActiveAccount().activeAccount;
339
- const utxoAccount = utxoKeyring.getActiveAccount().activeAccount;
340
-
341
- // Addresses should be completely different
342
- expect(evmAccount.address).not.toBe(utxoAccount.address);
343
- expect(evmAccount.address.startsWith('0x')).toBe(true);
344
- expect(utxoAccount.address.match(/^(sys1|tsys1)/)).toBeTruthy();
345
- });
346
-
347
- it('should maintain deterministic derivation after re-encryption', async () => {
348
- // Store original addresses
349
- const originalAddresses = [
350
- keyringManager.getActiveAccount().activeAccount.address,
351
- ];
352
- for (let i = 0; i < 2; i++) {
353
- const account = await keyringManager.addNewAccount();
354
- originalAddresses.push(account.address);
355
-
356
- // Update vault state with new account
357
- currentVaultState.accounts[KeyringAccountType.HDAccount][account.id] = {
358
- id: account.id,
359
- label: `Account ${account.id + 1}`,
360
- address: account.address,
361
- xpub: account.xpub,
362
- xprv: '',
363
- isImported: false,
364
- isTrezorWallet: false,
365
- isLedgerWallet: false,
366
- balances: { syscoin: 0, ethereum: 0 },
367
- assets: { syscoin: [], ethereum: [] },
368
- };
369
- }
370
-
371
- // Lock and unlock (simulating re-encryption scenario)
372
- keyringManager.lockWallet();
373
- await keyringManager.unlock(FAKE_PASSWORD);
374
-
375
- // Verify addresses remain the same
376
- const account0 = keyringManager.getAccountById(
377
- 0,
378
- KeyringAccountType.HDAccount
379
- );
380
- expect(account0.address).toBe(originalAddresses[0]);
381
-
382
- const account1 = keyringManager.getAccountById(
383
- 1,
384
- KeyringAccountType.HDAccount
385
- );
386
- expect(account1.address).toBe(originalAddresses[1]);
387
-
388
- const account2 = keyringManager.getAccountById(
389
- 2,
390
- KeyringAccountType.HDAccount
391
- );
392
- expect(account2.address).toBe(originalAddresses[2]);
393
- });
394
- });
395
-
396
- describe('Imported Key Handling', () => {
397
- it('should not derive keys for imported EVM accounts', async () => {
398
- // Set up EVM vault state
399
- currentVaultState = createMockVaultState({
400
- activeAccountId: 0,
401
- activeAccountType: KeyringAccountType.HDAccount,
402
- networkType: INetworkType.Ethereum,
403
- chainId: 1,
404
- });
405
- mockVaultStateGetter = jest.fn(() => currentVaultState);
406
-
407
- keyringManager = await KeyringManager.createInitialized(
408
- PEACE_SEED_PHRASE,
409
- FAKE_PASSWORD,
410
- mockVaultStateGetter
411
- );
412
-
413
- // Import a specific private key
414
- const privateKey =
415
- '0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318';
416
- const imported = await keyringManager.importAccount(privateKey);
417
-
418
- // Update vault state with imported account
419
- currentVaultState.accounts[KeyringAccountType.Imported][imported.id] = {
420
- id: imported.id,
421
- label: 'Imported 1',
422
- address: imported.address,
423
- xpub: imported.xpub,
424
- xprv: imported.xprv,
425
- isImported: true,
426
- isTrezorWallet: false,
427
- isLedgerWallet: false,
428
- balances: { syscoin: 0, ethereum: 0 },
429
- assets: { syscoin: [], ethereum: [] },
430
- };
431
-
432
- // Verify it uses the exact key, not derived
433
- const retrievedKey = await keyringManager.getPrivateKeyByAccountId(
434
- imported.id,
435
- KeyringAccountType.Imported,
436
- FAKE_PASSWORD
437
- );
438
- expect(retrievedKey).toBe(privateKey);
439
-
440
- // Verify address matches the private key
441
- const wallet = new Wallet(privateKey);
442
- expect(imported.address.toLowerCase()).toBe(wallet.address.toLowerCase());
443
- });
444
-
445
- it('should handle imported zprv for UTXO', async () => {
446
- // Set up UTXO vault state
447
- currentVaultState = createMockVaultState({
448
- activeAccountId: 0,
449
- activeAccountType: KeyringAccountType.HDAccount,
450
- networkType: INetworkType.Syscoin,
451
- chainId: 57,
452
- });
453
- mockVaultStateGetter = jest.fn(() => currentVaultState);
454
-
455
- keyringManager = await KeyringManager.createInitialized(
456
- PEACE_SEED_PHRASE,
457
- FAKE_PASSWORD,
458
- mockVaultStateGetter
459
- );
460
-
461
- // Import a zprv
462
- const zprv =
463
- 'zprvAdGDwa3WySqQoVwVSbYRMKxDhSXpK2wW6wDjekCMdm7TaQ3igf52xRRjYghTvnFurtMm6CMgQivEDJs5ixGSnTtv8usFmkAoTe6XCF5hnpR';
464
- const imported = await keyringManager.importAccount(zprv);
465
-
466
- // Update vault state with imported account
467
- currentVaultState.accounts[KeyringAccountType.Imported][imported.id] = {
468
- id: imported.id,
469
- label: 'Imported 1',
470
- address: imported.address,
471
- xpub: imported.xpub,
472
- xprv: imported.xprv,
473
- isImported: true,
474
- isTrezorWallet: false,
475
- isLedgerWallet: false,
476
- balances: { syscoin: 0, ethereum: 0 },
477
- assets: { syscoin: [], ethereum: [] },
478
- };
479
-
480
- // Verify it's treated as imported, not derived from main seed
481
- expect(imported.isImported).toBe(true);
482
-
483
- // Retrieve and verify the zprv
484
- const retrievedKey = await keyringManager.getPrivateKeyByAccountId(
485
- imported.id,
486
- KeyringAccountType.Imported,
487
- FAKE_PASSWORD
488
- );
489
- expect(retrievedKey).toBe(zprv);
490
- });
491
- });
492
-
493
- describe('Edge Cases', () => {
494
- it('should handle account creation when no HD signer exists', async () => {
495
- keyringManager = new KeyringManager();
496
-
497
- // Set up mock vault state getter for initializeWalletSecurely
498
- currentVaultState = createMockVaultState({
499
- activeAccountId: 0,
500
- activeAccountType: KeyringAccountType.HDAccount,
501
- networkType: INetworkType.Ethereum,
502
- chainId: 1,
503
- });
504
- mockVaultStateGetter = jest.fn(() => currentVaultState);
505
- keyringManager.setVaultStateGetter(mockVaultStateGetter);
506
-
507
- await keyringManager.initializeWalletSecurely(
508
- PEACE_SEED_PHRASE,
509
- FAKE_PASSWORD
510
- );
511
-
512
- // Should create HD signer on first account access
513
- const account = keyringManager.getActiveAccount().activeAccount;
514
- expect(account).toBeDefined();
515
- expect(account.address).toBeDefined();
516
- });
517
-
518
- it('should maintain key derivation consistency with special characters in labels', async () => {
519
- // Set up EVM vault state
520
- currentVaultState = createMockVaultState({
521
- activeAccountId: 0,
522
- activeAccountType: KeyringAccountType.HDAccount,
523
- networkType: INetworkType.Ethereum,
524
- chainId: 1,
525
- });
526
- mockVaultStateGetter = jest.fn(() => currentVaultState);
527
-
528
- keyringManager = await KeyringManager.createInitialized(
529
- PEACE_SEED_PHRASE,
530
- FAKE_PASSWORD,
531
- mockVaultStateGetter
532
- );
533
-
534
- // Labels should not affect derivation
535
- const account1 = await keyringManager.addNewAccount(
536
- 'Account with 特殊文字 and émojis 🚀'
537
- );
538
- const address1 = account1.address;
539
-
540
- // Update vault state
541
- currentVaultState.accounts[KeyringAccountType.HDAccount][account1.id] = {
542
- id: account1.id,
543
- label: 'Account with 特殊文字 and émojis 🚀',
544
- address: account1.address,
545
- xpub: account1.xpub,
546
- xprv: '',
547
- isImported: false,
548
- isTrezorWallet: false,
549
- isLedgerWallet: false,
550
- balances: { syscoin: 0, ethereum: 0 },
551
- assets: { syscoin: [], ethereum: [] },
552
- };
553
-
554
- // Set up second EVM vault state
555
- const vault2State = createMockVaultState({
556
- activeAccountId: 0,
557
- activeAccountType: KeyringAccountType.HDAccount,
558
- networkType: INetworkType.Ethereum,
559
- chainId: 1,
560
- });
561
- const vault2StateGetter = jest.fn(() => vault2State);
562
-
563
- // Create new keyring and add account with different label
564
- const keyring2 = await KeyringManager.createInitialized(
565
- PEACE_SEED_PHRASE,
566
- FAKE_PASSWORD,
567
- vault2StateGetter
568
- );
569
-
570
- const account2 = await keyring2.addNewAccount('Different Label');
571
-
572
- // Same index should give same address regardless of label
573
- expect(account2.address).toBe(address1);
574
- });
575
-
576
- it('should handle maximum safe integer account indices', () => {
577
- // This is more of a sanity check - we shouldn't realistically reach this
578
- const accounts = {};
579
- const maxSafeIndex = Number.MAX_SAFE_INTEGER;
580
-
581
- // Simulate account with the maximum safe index
582
- accounts[maxSafeIndex] = { id: maxSafeIndex };
583
-
584
- // getNextAccountId should handle this gracefully
585
- // (testing the concept, not the actual implementation)
586
- expect(() => {
587
- const nextId = maxSafeIndex + 1;
588
- if (nextId > Number.MAX_SAFE_INTEGER) {
589
- throw new Error('Account index overflow');
590
- }
591
- }).toThrow('Account index overflow');
592
- });
593
- });
594
-
595
- describe('Address Public Key and BIP32 Path Methods', () => {
596
- let mockFetchBackendAccount: jest.Mock;
597
-
598
- beforeEach(async () => {
599
- // Set up UTXO vault state for testing these methods
600
- currentVaultState = createMockVaultState({
601
- activeAccountId: 0,
602
- activeAccountType: KeyringAccountType.HDAccount,
603
- networkType: INetworkType.Syscoin,
604
- chainId: 57,
605
- });
606
- mockVaultStateGetter = jest.fn(() => currentVaultState);
607
-
608
- keyringManager = await KeyringManager.createInitialized(
609
- PEACE_SEED_PHRASE,
610
- FAKE_PASSWORD,
611
- mockVaultStateGetter
612
- );
613
-
614
- // Mock the fetchBackendAccount to return specific tokens with paths
615
- const syscoinjs = require('syscoinjs-lib');
616
- mockFetchBackendAccount = syscoinjs.utils
617
- .fetchBackendAccount as jest.Mock;
618
- });
619
-
620
- describe('getCurrentAddressPubkey', () => {
621
- it('should return public key for receiving address', async () => {
622
- // Mock backend response with tokens
623
- mockFetchBackendAccount.mockResolvedValue({
624
- balance: 100000000,
625
- tokens: [
626
- {
627
- path: "m/84'/57'/0'/0/0",
628
- transfers: '1',
629
- },
630
- {
631
- path: "m/84'/57'/0'/0/1",
632
- transfers: '1',
633
- },
634
- {
635
- path: "m/84'/57'/0'/1/0",
636
- transfers: '1',
637
- },
638
- ],
639
- });
640
-
641
- const account = keyringManager.getActiveAccount().activeAccount;
642
- const pubkey = await keyringManager.getCurrentAddressPubkey(
643
- account.xpub,
644
- false // receiving address
645
- );
646
-
647
- // Verify the public key is a valid hex string
648
- expect(pubkey).toMatch(/^[0-9a-fA-F]{66}$/); // 33 bytes = 66 hex chars
649
- expect(pubkey.length).toBe(66); // Compressed public key
650
-
651
- // Verify fetchBackendAccount was called with correct params
652
- expect(mockFetchBackendAccount).toHaveBeenCalledWith(
653
- expect.any(String), // blockbook URL
654
- account.xpub,
655
- 'tokens=used&details=tokens',
656
- true,
657
- undefined
658
- );
659
- });
660
-
661
- it('should return public key for change address', async () => {
662
- // Mock backend response with tokens
663
- mockFetchBackendAccount.mockResolvedValue({
664
- balance: 100000000,
665
- tokens: [
666
- {
667
- path: "m/84'/57'/0'/0/0",
668
- transfers: '1',
669
- },
670
- {
671
- path: "m/84'/57'/0'/1/0",
672
- transfers: '1',
673
- },
674
- {
675
- path: "m/84'/57'/0'/1/1",
676
- transfers: '1',
677
- },
678
- ],
679
- });
680
-
681
- const account = keyringManager.getActiveAccount().activeAccount;
682
- const pubkey = await keyringManager.getCurrentAddressPubkey(
683
- account.xpub,
684
- true // change address
685
- );
686
-
687
- // Verify the public key is a valid hex string
688
- expect(pubkey).toMatch(/^[0-9a-fA-F]{66}$/);
689
- expect(pubkey.length).toBe(66);
690
- });
691
-
692
- it('should use correct index based on token paths', async () => {
693
- // Mock backend response with specific token paths
694
- mockFetchBackendAccount.mockResolvedValue({
695
- balance: 100000000,
696
- tokens: [
697
- {
698
- path: "m/84'/57'/0'/0/5", // receiving index 5
699
- transfers: '1',
700
- },
701
- {
702
- path: "m/84'/57'/0'/1/3", // change index 3
703
- transfers: '1',
704
- },
705
- ],
706
- });
707
-
708
- const account = keyringManager.getActiveAccount().activeAccount;
709
-
710
- // Get public key for receiving address - should use index 6 (5 + 1)
711
- const receivingPubkey = await keyringManager.getCurrentAddressPubkey(
712
- account.xpub,
713
- false
714
- );
715
-
716
- // Get public key for change address - should use index 4 (3 + 1)
717
- const changePubkey = await keyringManager.getCurrentAddressPubkey(
718
- account.xpub,
719
- true
720
- );
721
-
722
- // They should be different
723
- expect(receivingPubkey).not.toBe(changePubkey);
724
- expect(receivingPubkey).toMatch(/^[0-9a-fA-F]{66}$/);
725
- expect(changePubkey).toMatch(/^[0-9a-fA-F]{66}$/);
726
- });
727
- });
728
-
729
- describe('getCurrentAddressBip32Path', () => {
730
- it('should return correct BIP32 path for receiving address', async () => {
731
- // Mock backend response with tokens
732
- mockFetchBackendAccount.mockResolvedValue({
733
- balance: 100000000,
734
- tokens: [
735
- {
736
- path: "m/84'/57'/0'/0/2",
737
- transfers: '1',
738
- },
739
- ],
740
- });
741
-
742
- const account = keyringManager.getActiveAccount().activeAccount;
743
- const path = await keyringManager.getCurrentAddressBip32Path(
744
- account.xpub,
745
- false // receiving address
746
- );
747
-
748
- // Should return path for index 3 (2 + 1)
749
- expect(path).toBe("m/84'/57'/0'/0/3");
750
- });
751
-
752
- it('should return correct BIP32 path for change address', async () => {
753
- // Mock backend response with tokens
754
- mockFetchBackendAccount.mockResolvedValue({
755
- balance: 100000000,
756
- tokens: [
757
- {
758
- path: "m/84'/57'/0'/1/4",
759
- transfers: '1',
760
- },
761
- ],
762
- });
763
-
764
- const account = keyringManager.getActiveAccount().activeAccount;
765
- const path = await keyringManager.getCurrentAddressBip32Path(
766
- account.xpub,
767
- true // change address
768
- );
769
-
770
- // Should return path for index 5 (4 + 1)
771
- expect(path).toBe("m/84'/57'/0'/1/5");
772
- });
773
-
774
- it('should use account ID from active account', async () => {
775
- // Add a new account
776
- const newAccount = await keyringManager.addNewAccount();
777
-
778
- // Update vault state with new account
779
- currentVaultState.accounts[KeyringAccountType.HDAccount][1] = {
780
- id: 1,
781
- label: 'Account 2',
782
- address: newAccount.address,
783
- xpub: newAccount.xpub,
784
- xprv: '',
785
- isImported: false,
786
- isTrezorWallet: false,
787
- isLedgerWallet: false,
788
- balances: { syscoin: 0, ethereum: 0 },
789
- assets: { syscoin: [], ethereum: [] },
790
- };
791
- currentVaultState.activeAccount = {
792
- id: 1,
793
- type: KeyringAccountType.HDAccount,
794
- };
795
-
796
- // Mock backend response
797
- mockFetchBackendAccount.mockResolvedValue({
798
- balance: 100000000,
799
- tokens: [],
800
- });
801
-
802
- const path = await keyringManager.getCurrentAddressBip32Path(
803
- newAccount.xpub,
804
- false
805
- );
806
-
807
- // Should use account ID 1
808
- expect(path).toBe("m/84'/57'/1'/0/0");
809
- });
810
-
811
- it('should handle empty token list', async () => {
812
- // Mock backend response with no tokens
813
- mockFetchBackendAccount.mockResolvedValue({
814
- balance: 0,
815
- tokens: [],
816
- });
817
-
818
- const account = keyringManager.getActiveAccount().activeAccount;
819
-
820
- // Should use index 0 for both
821
- const receivingPath = await keyringManager.getCurrentAddressBip32Path(
822
- account.xpub,
823
- false
824
- );
825
- const changePath = await keyringManager.getCurrentAddressBip32Path(
826
- account.xpub,
827
- true
828
- );
829
-
830
- expect(receivingPath).toBe("m/84'/57'/0'/0/0");
831
- expect(changePath).toBe("m/84'/57'/0'/1/0");
832
- });
833
-
834
- it('should handle Bitcoin network paths', async () => {
835
- // Set up Bitcoin vault state
836
- const btcVaultState = createMockVaultState({
837
- activeAccountId: 0,
838
- activeAccountType: KeyringAccountType.HDAccount,
839
- networkType: INetworkType.Syscoin, // UTXO type
840
- chainId: 57, // Use default Syscoin chainId for now
841
- });
842
-
843
- // Override the active network to be Bitcoin
844
- btcVaultState.activeNetwork = {
845
- chainId: 0,
846
- currency: 'BTC',
847
- label: 'Bitcoin',
848
- url: 'https://blockstream.info',
849
- kind: INetworkType.Syscoin,
850
- slip44: 0, // Bitcoin's slip44
851
- explorer: 'https://blockstream.info',
852
- };
853
-
854
- const btcVaultStateGetter = jest.fn(() => btcVaultState);
855
-
856
- // Create Bitcoin keyring
857
- const btcKeyring = await KeyringManager.createInitialized(
858
- PEACE_SEED_PHRASE,
859
- FAKE_PASSWORD,
860
- btcVaultStateGetter
861
- );
862
-
863
- // Mock backend response
864
- mockFetchBackendAccount.mockResolvedValue({
865
- balance: 100000000,
866
- tokens: [],
867
- });
868
-
869
- const account = btcKeyring.getActiveAccount().activeAccount;
870
- const path = await btcKeyring.getCurrentAddressBip32Path(
871
- account.xpub,
872
- false
873
- );
874
-
875
- // Should use Bitcoin's slip44 (0)
876
- expect(path).toBe("m/84'/0'/0'/0/0");
877
- });
878
- });
879
-
880
- describe('Integration between methods', () => {
881
- it('getCurrentAddressPubkey and getAddress should derive from same index', async () => {
882
- // Mock backend response
883
- mockFetchBackendAccount.mockResolvedValue({
884
- balance: 100000000,
885
- tokens: [
886
- {
887
- path: "m/84'/57'/0'/0/2",
888
- transfers: '1',
889
- },
890
- ],
891
- });
892
-
893
- const account = keyringManager.getActiveAccount().activeAccount;
894
-
895
- // Get address and public key
896
- const address = await keyringManager.getAddress(account.xpub, false);
897
- const pubkey = await keyringManager.getCurrentAddressPubkey(
898
- account.xpub,
899
- false
900
- );
901
-
902
- // Both should be valid and non-empty
903
- expect(address).toBeTruthy();
904
- expect(address).toMatch(/^(sys1|tsys1)/);
905
- expect(pubkey).toMatch(/^[0-9a-fA-F]{66}$/);
906
-
907
- // They should have been called with the same backend data
908
- expect(mockFetchBackendAccount).toHaveBeenCalledTimes(2);
909
- });
910
- });
911
- });
912
-
913
- describe('Hardware Wallet Support', () => {
914
- it('should work with all read-only methods', async () => {
915
- // Set up UTXO vault state with a regular HD account for testing
916
- // The key point is that our methods work with just xpub, regardless of account type
917
- currentVaultState = createMockVaultState({
918
- activeAccountId: 0,
919
- activeAccountType: KeyringAccountType.HDAccount,
920
- networkType: INetworkType.Syscoin,
921
- chainId: 57,
922
- });
923
-
924
- mockVaultStateGetter = jest.fn(() => currentVaultState);
925
-
926
- keyringManager = await KeyringManager.createInitialized(
927
- PEACE_SEED_PHRASE,
928
- FAKE_PASSWORD,
929
- mockVaultStateGetter
930
- );
931
-
932
- // Mock backend response
933
- const syscoinjs = require('syscoinjs-lib');
934
- const mockFetchBackendAccount = syscoinjs.utils
935
- .fetchBackendAccount as jest.Mock;
936
- mockFetchBackendAccount.mockResolvedValue({
937
- balance: 100000000,
938
- tokens: [
939
- {
940
- path: "m/84'/57'/0'/0/2",
941
- transfers: '1',
942
- },
943
- {
944
- path: "m/84'/57'/0'/1/1",
945
- transfers: '1',
946
- },
947
- ],
948
- });
949
-
950
- // Get the xpub from a regular account to test with
951
- const account = keyringManager.getActiveAccount().activeAccount;
952
- const xpub = account.xpub;
953
-
954
- // Test all read-only methods that hardware wallets can use
955
- // These methods only need xpub, not private keys
956
-
957
- // 1. Test getCurrentAddressPubkey
958
- const receivingPubkey = await keyringManager.getCurrentAddressPubkey(
959
- xpub,
960
- false
961
- );
962
- const changePubkey = await keyringManager.getCurrentAddressPubkey(
963
- xpub,
964
- true
965
- );
966
- expect(receivingPubkey).toMatch(/^[0-9a-fA-F]{66}$/);
967
- expect(changePubkey).toMatch(/^[0-9a-fA-F]{66}$/);
968
- expect(receivingPubkey).not.toBe(changePubkey);
969
-
970
- // 2. Test getBip32Path
971
- const receivingPath = await keyringManager.getCurrentAddressBip32Path(
972
- xpub,
973
- false
974
- );
975
- const changePath = await keyringManager.getCurrentAddressBip32Path(
976
- xpub,
977
- true
978
- );
979
- expect(receivingPath).toBe("m/84'/57'/0'/0/3"); // index 2 + 1
980
- expect(changePath).toBe("m/84'/57'/0'/1/2"); // index 1 + 1
981
-
982
- // 3. Test getAddress (used by getChangeAddress)
983
- const receivingAddress = await keyringManager.getAddress(xpub, false);
984
- const changeAddress = await keyringManager.getAddress(xpub, true);
985
- expect(receivingAddress).toMatch(/^(sys1|tsys1)/);
986
- expect(changeAddress).toMatch(/^(sys1|tsys1)/);
987
- expect(receivingAddress).not.toBe(changeAddress);
988
-
989
- // 4. Test getChangeAddress (calls getAddress internally)
990
- const changeAddr = await keyringManager.getChangeAddress(0);
991
- expect(changeAddr).toMatch(/^(sys1|tsys1)/);
992
-
993
- // All these methods work with just xpub, making them hardware wallet compatible
994
- });
995
- });
996
- });