@sidhujag/sysweb3-keyring 1.0.547 → 1.0.548

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