@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,869 +0,0 @@
1
- import { INetworkType } from '@sidhujag/sysweb3-network';
2
-
3
- import { KeyringManager, KeyringAccountType } from '../../../src';
4
- import { FAKE_PASSWORD, PEACE_SEED_PHRASE } from '../../helpers/constants';
5
- import { setupMocks } from '../../helpers/setup';
6
-
7
- // Use global createMockVaultState
8
- const createMockVaultState = (global as any).createMockVaultState;
9
-
10
- describe('Ledger Hardware Wallet', () => {
11
- let keyringManager: KeyringManager;
12
- let mockVaultStateGetter: jest.Mock;
13
- let currentVaultState: any;
14
-
15
- beforeEach(async () => {
16
- setupMocks();
17
- await global.setupTestVault(FAKE_PASSWORD);
18
-
19
- // Set up UTXO vault state
20
- currentVaultState = createMockVaultState({
21
- activeAccountId: 0,
22
- activeAccountType: KeyringAccountType.HDAccount,
23
- networkType: INetworkType.Syscoin,
24
- chainId: 57,
25
- });
26
- mockVaultStateGetter = jest.fn(() => currentVaultState);
27
-
28
- keyringManager = await KeyringManager.createInitialized(
29
- PEACE_SEED_PHRASE,
30
- FAKE_PASSWORD,
31
- mockVaultStateGetter
32
- );
33
-
34
- // Mock HardwareWalletManager ensureConnection
35
- keyringManager.ledgerSigner.ensureConnection = jest
36
- .fn()
37
- .mockResolvedValue(undefined);
38
-
39
- // Mock transport property
40
- keyringManager.ledgerSigner.transport = {} as any;
41
-
42
- // Mock ledgerUtxoClient for getMasterFingerprint calls
43
- keyringManager.ledgerSigner.ledgerUtxoClient = {
44
- getMasterFingerprint: jest.fn().mockResolvedValue('12345678'),
45
- signPsbt: jest.fn(),
46
- } as any;
47
-
48
- // Mock getAddress to return our mocked addresses
49
- keyringManager.getAddress = jest
50
- .fn()
51
- .mockResolvedValue('sys1qmock_ledger_address');
52
- });
53
-
54
- afterEach(async () => {
55
- // Clean up hardware wallet connections
56
- if (keyringManager) {
57
- await keyringManager.destroy();
58
- }
59
- });
60
-
61
- describe('Account Import', () => {
62
- it('should import Ledger account when connected', async () => {
63
- // Mock complete UTXO interface
64
- keyringManager.ledgerSigner.utxo = {
65
- getXpub: jest
66
- .fn()
67
- .mockResolvedValue(
68
- 'zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs'
69
- ),
70
- getUtxoAddress: jest.fn().mockResolvedValue('sys1qmock_ledger_address'),
71
- verifyUtxoAddress: jest
72
- .fn()
73
- .mockResolvedValue('sys1qmock_ledger_address'),
74
- };
75
-
76
- const account = await keyringManager.importLedgerAccount('My Ledger');
77
-
78
- expect(account).toBeDefined();
79
- if (account) {
80
- expect(account.id).toBe(0); // First imported Ledger account gets ID 0
81
- expect(account.label).toBe('My Ledger');
82
- expect(account.isLedgerWallet).toBe(true);
83
- expect(account.isTrezorWallet).toBe(false);
84
- expect(account.isImported).toBe(false);
85
- expect(account.xprv).toBe(''); // Hardware wallets don't expose private keys
86
- expect(account.address).toBe('sys1qmock_ledger_address');
87
- }
88
- });
89
-
90
- it('should fail if Ledger connection fails', async () => {
91
- // Mock connection failure in ensureConnection
92
- keyringManager.ledgerSigner.ensureConnection = jest
93
- .fn()
94
- .mockRejectedValue(new Error('Failed to connect to device'));
95
-
96
- await expect(keyringManager.importLedgerAccount()).rejects.toThrow(
97
- 'Failed to connect to device'
98
- );
99
- });
100
-
101
- it('should handle Ledger import for EVM networks', async () => {
102
- // Set up EVM vault state
103
- const evmVaultState = createMockVaultState({
104
- activeAccountId: 0,
105
- activeAccountType: KeyringAccountType.HDAccount,
106
- networkType: INetworkType.Ethereum,
107
- chainId: 1,
108
- });
109
- const evmVaultStateGetter = jest.fn(() => evmVaultState);
110
-
111
- // Create EVM keyring
112
- const evmKeyring = await KeyringManager.createInitialized(
113
- PEACE_SEED_PHRASE,
114
- FAKE_PASSWORD,
115
- evmVaultStateGetter
116
- );
117
-
118
- // Mock ensureConnection for EVM keyring
119
- evmKeyring.ledgerSigner.ensureConnection = jest
120
- .fn()
121
- .mockResolvedValue(undefined);
122
-
123
- // Mock complete EVM interface
124
- evmKeyring.ledgerSigner.evm = {
125
- getEvmAddressAndPubKey: jest.fn().mockResolvedValue({
126
- address: '0x742d35Cc6634C0532925a3b844Bc9e7595f2bd9F',
127
- publicKey: '0x04...',
128
- }),
129
- signEVMTransaction: jest.fn().mockResolvedValue({
130
- r: '123456789abcdef123456789abcdef123456789abcdef123456789abcdef12345678',
131
- s: '987654321fedcba987654321fedcba987654321fedcba987654321fedcba987654',
132
- v: '1c',
133
- }),
134
- signPersonalMessage: jest.fn().mockResolvedValue('0xmocked_signature'),
135
- signTypedData: jest.fn().mockResolvedValue('0xmocked_typed_signature'),
136
- };
137
-
138
- const account = await evmKeyring.importLedgerAccount('Ledger ETH');
139
-
140
- expect(account).toBeDefined();
141
- if (account) {
142
- expect(account.address.startsWith('0x')).toBe(true);
143
- expect(account.isLedgerWallet).toBe(true);
144
- }
145
- });
146
-
147
- it('should reject duplicate Ledger addresses', async () => {
148
- // Mock getAddress to return the expected addresses
149
- keyringManager.getAddress = jest
150
- .fn()
151
- .mockResolvedValue('sys1q_first_address');
152
-
153
- // First import with unique address
154
- keyringManager.ledgerSigner.utxo = {
155
- getXpub: jest
156
- .fn()
157
- .mockResolvedValue(
158
- 'zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs'
159
- ),
160
- getUtxoAddress: jest.fn().mockResolvedValue('sys1q_first_address'),
161
- verifyUtxoAddress: jest.fn().mockResolvedValue('sys1q_first_address'),
162
- };
163
-
164
- const firstAccount = await keyringManager.importLedgerAccount();
165
-
166
- // Update vault state with first account
167
- if (firstAccount) {
168
- currentVaultState.accounts[KeyringAccountType.Ledger][firstAccount.id] =
169
- {
170
- id: firstAccount.id,
171
- label: firstAccount.label,
172
- address: firstAccount.address,
173
- xpub: firstAccount.xpub,
174
- xprv: '',
175
- isImported: false,
176
- isTrezorWallet: false,
177
- isLedgerWallet: true,
178
- balances: { syscoin: 0, ethereum: 0 },
179
- assets: { syscoin: [], ethereum: [] },
180
- };
181
- }
182
-
183
- // Mock Ledger returning same address for next account (simulate duplicate)
184
- keyringManager.ledgerSigner.utxo = {
185
- getXpub: jest
186
- .fn()
187
- .mockResolvedValue(
188
- 'zpub6s8HtEQtcu3AmBn9sniSqCAVhx2nJAhb2sd5NDYeYZ1ZJaZx7MAVZZnG1PdCUNJcVJXGbVpGfSYZLgkPSUjLYnJg8UdYvdkfaygcXZKPLy6'
189
- ),
190
- getUtxoAddress: jest.fn().mockResolvedValue('sys1q_first_address'), // Same as first!
191
- verifyUtxoAddress: jest.fn().mockResolvedValue('sys1q_first_address'),
192
- };
193
-
194
- // Should reject duplicate - this tests the actual business logic
195
- await expect(keyringManager.importLedgerAccount()).rejects.toThrow(
196
- 'Account already exists'
197
- );
198
- });
199
- });
200
-
201
- describe('Account Management', () => {
202
- beforeEach(async () => {
203
- // Mock complete Ledger methods
204
- keyringManager.ledgerSigner.utxo = {
205
- getXpub: jest
206
- .fn()
207
- .mockResolvedValue(
208
- 'zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs'
209
- ),
210
- getUtxoAddress: jest.fn().mockResolvedValue('sys1qmock_ledger_address'),
211
- verifyUtxoAddress: jest
212
- .fn()
213
- .mockResolvedValue('sys1qmock_ledger_address'),
214
- };
215
-
216
- // Import a Ledger account
217
- const account = await keyringManager.importLedgerAccount('Test Ledger');
218
-
219
- // Update vault state with imported account
220
- if (account) {
221
- currentVaultState.accounts[KeyringAccountType.Ledger][account.id] = {
222
- id: account.id,
223
- label: account.label,
224
- address: account.address,
225
- xpub: account.xpub,
226
- xprv: '',
227
- isImported: false,
228
- isTrezorWallet: false,
229
- isLedgerWallet: true,
230
- balances: { syscoin: 0, ethereum: 0 },
231
- assets: { syscoin: [], ethereum: [] },
232
- };
233
- }
234
- });
235
-
236
- it('should switch to Ledger account', async () => {
237
- // Update vault state to set Ledger as active
238
- currentVaultState.activeAccount = {
239
- id: 0,
240
- type: KeyringAccountType.Ledger,
241
- };
242
-
243
- // Account switch is handled by vault state update
244
-
245
- const { activeAccount, activeAccountType } =
246
- keyringManager.getActiveAccount();
247
- expect(activeAccountType).toBe(KeyringAccountType.Ledger);
248
- expect(activeAccount.isLedgerWallet).toBe(true);
249
- expect(activeAccount.label).toBe('Test Ledger');
250
- });
251
-
252
- it('should get Ledger account xpub', async () => {
253
- // Update vault state to set Ledger as active
254
- currentVaultState.activeAccount = {
255
- id: 0,
256
- type: KeyringAccountType.Ledger,
257
- };
258
-
259
- // Account switch is handled by vault state update
260
-
261
- const xpub = keyringManager.getAccountXpub();
262
- expect(xpub).toBeDefined();
263
- expect(xpub).toBe(
264
- 'zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs'
265
- );
266
- });
267
-
268
- it('should handle mixed account types with Ledger', async () => {
269
- // Add HD account
270
- const hdAccount = await keyringManager.addNewAccount('HD Account 2');
271
-
272
- // Update vault state with HD account
273
- currentVaultState.accounts[KeyringAccountType.HDAccount][hdAccount.id] = {
274
- id: hdAccount.id,
275
- label: hdAccount.label,
276
- address: hdAccount.address,
277
- xpub: hdAccount.xpub,
278
- xprv: '',
279
- isImported: false,
280
- isTrezorWallet: false,
281
- isLedgerWallet: false,
282
- balances: { syscoin: 0, ethereum: 0 },
283
- assets: { syscoin: [], ethereum: [] },
284
- };
285
-
286
- // Switch between them using actual account IDs
287
- currentVaultState.activeAccount = {
288
- id: 0,
289
- type: KeyringAccountType.HDAccount,
290
- };
291
- // Account switch is handled by vault state update
292
- expect(keyringManager.getActiveAccount().activeAccountType).toBe(
293
- KeyringAccountType.HDAccount
294
- );
295
-
296
- // Switch to Ledger account
297
- currentVaultState.activeAccount = {
298
- id: 0,
299
- type: KeyringAccountType.Ledger,
300
- };
301
- // Account switch is handled by vault state update
302
- expect(keyringManager.getActiveAccount().activeAccountType).toBe(
303
- KeyringAccountType.Ledger
304
- );
305
- });
306
- });
307
-
308
- describe('Transaction Signing', () => {
309
- beforeEach(async () => {
310
- // Complete mock setup for transaction signing tests
311
- keyringManager.ledgerSigner.utxo = {
312
- getXpub: jest
313
- .fn()
314
- .mockResolvedValue(
315
- 'zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs'
316
- ),
317
- getUtxoAddress: jest.fn().mockResolvedValue('sys1qmock_ledger_address'),
318
- verifyUtxoAddress: jest
319
- .fn()
320
- .mockResolvedValue('sys1qmock_ledger_address'),
321
- };
322
-
323
- const account = await keyringManager.importLedgerAccount('Signing Test');
324
- if (account) {
325
- // Update vault state to set Ledger as active
326
- currentVaultState.accounts[KeyringAccountType.Ledger][account.id] = {
327
- id: account.id,
328
- label: account.label,
329
- address: account.address,
330
- xpub: account.xpub,
331
- xprv: '',
332
- isImported: false,
333
- isTrezorWallet: false,
334
- isLedgerWallet: true,
335
- balances: { syscoin: 0, ethereum: 0 },
336
- assets: { syscoin: [], ethereum: [] },
337
- };
338
- currentVaultState.activeAccount = {
339
- id: account.id,
340
- type: KeyringAccountType.Ledger,
341
- };
342
-
343
- // Account switch is handled by vault state update
344
- }
345
-
346
- // Mock getAddress to return our mocked addresses
347
- keyringManager.getAddress = jest
348
- .fn()
349
- .mockResolvedValue('sys1qmock_ledger_address');
350
-
351
- // Mock Ledger UTXO client for transaction signing
352
- keyringManager.ledgerSigner.ledgerUtxoClient = {
353
- getMasterFingerprint: jest.fn().mockResolvedValue('12345678'),
354
- signPsbt: jest.fn().mockResolvedValue([
355
- [
356
- 0,
357
- {
358
- pubkey: Buffer.from('mock_pubkey'),
359
- signature: Buffer.from('mock_signature'),
360
- },
361
- ],
362
- ]),
363
- // Add minimal required properties to satisfy interface
364
- transport: {} as any,
365
- makeRequest: jest.fn(),
366
- getAppAndVersion: jest.fn(),
367
- getExtendedPubkey: jest.fn(),
368
- registerWallet: jest.fn(),
369
- getWalletAddress: jest.fn(),
370
- signMessage: jest.fn(),
371
- } as any;
372
-
373
- // Mock convertToLedgerFormat to return a proper PSBT mock with toBase64 method
374
- keyringManager.ledgerSigner.convertToLedgerFormat = jest
375
- .fn()
376
- .mockResolvedValue({
377
- toBase64: jest
378
- .fn()
379
- .mockReturnValue(
380
- 'cHNidP8BAHECAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=='
381
- ),
382
- extractTransaction: jest.fn().mockReturnValue({
383
- getId: jest.fn().mockReturnValue('mock_transaction_id'),
384
- }),
385
- updateInput: jest.fn(),
386
- finalizeAllInputs: jest.fn(),
387
- });
388
- });
389
-
390
- it('should prepare PSBT for Ledger signing', async () => {
391
- // Mock the PSBT parsing to avoid base64 validation issues
392
- const mockSyscoinjs = require('syscoinjs-lib');
393
- const originalImportPsbtFromJson = mockSyscoinjs.utils.importPsbtFromJson;
394
- mockSyscoinjs.utils.importPsbtFromJson = jest.fn().mockReturnValue({
395
- psbt: {
396
- toBase64: jest
397
- .fn()
398
- .mockReturnValue(
399
- 'cHNidP8BAHECAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=='
400
- ),
401
- extractTransaction: jest.fn().mockReturnValue({
402
- getId: jest.fn().mockReturnValue('mock_transaction_id'),
403
- }),
404
- updateInput: jest.fn(),
405
- finalizeAllInputs: jest.fn(),
406
- },
407
- });
408
-
409
- const psbtData = {
410
- psbt: 'valid_psbt_data',
411
- assets: [],
412
- };
413
-
414
- const result = await keyringManager.syscoinTransaction.signPSBT({
415
- psbt: psbtData,
416
- isTrezor: false,
417
- isLedger: true,
418
- });
419
-
420
- expect(result).toBeDefined();
421
- // Verify Ledger-specific handling was applied
422
- // Restore original function
423
- mockSyscoinjs.utils.importPsbtFromJson = originalImportPsbtFromJson;
424
- });
425
-
426
- it('should reconnect to Ledger when connection is lost during EVM transaction signing', async () => {
427
- // Set up EVM vault state
428
- const evmVaultState = createMockVaultState({
429
- activeAccountId: 0,
430
- activeAccountType: KeyringAccountType.Ledger,
431
- networkType: INetworkType.Ethereum,
432
- chainId: 1,
433
- });
434
- const evmVaultStateGetter = jest.fn(() => evmVaultState);
435
-
436
- // Create EVM keyring with Ledger
437
- const evmKeyring = await KeyringManager.createInitialized(
438
- PEACE_SEED_PHRASE,
439
- FAKE_PASSWORD,
440
- evmVaultStateGetter
441
- );
442
-
443
- // Mock Ledger as disconnected
444
- evmKeyring.ledgerSigner.transport = null;
445
- evmKeyring.ledgerSigner.ledgerUtxoClient = null as any;
446
- evmKeyring.ledgerSigner.ledgerEVMClient = null as any;
447
-
448
- // Mock transport for reconnection
449
- const mockTransport = { close: jest.fn() } as any;
450
-
451
- // Mock ensureConnection to simulate successful reconnection
452
- evmKeyring.ledgerSigner.ensureConnection = jest
453
- .fn()
454
- .mockImplementation(async () => {
455
- // Simulate successful reconnection
456
- evmKeyring.ledgerSigner.transport = mockTransport;
457
- evmKeyring.ledgerSigner.ledgerUtxoClient = {
458
- getMasterFingerprint: jest.fn().mockResolvedValue('12345678'),
459
- } as any;
460
- evmKeyring.ledgerSigner.ledgerEVMClient = {
461
- signTransaction: jest.fn().mockResolvedValue({
462
- r: '123456789abcdef',
463
- s: '987654321fedcba',
464
- v: '00',
465
- }),
466
- getAddress: jest.fn().mockResolvedValue({
467
- address: '0x742D35Cc6634C0532925a3b844bc9e7595f2bd9f',
468
- publicKey: '0x04...',
469
- }),
470
- signPersonalMessage: jest
471
- .fn()
472
- .mockResolvedValue('0xmocked_signature'),
473
- signEIP712HashedMessage: jest
474
- .fn()
475
- .mockResolvedValue('0xmocked_typed_signature'),
476
- } as any;
477
- });
478
-
479
- // Import Ledger account
480
- const evmAccount = {
481
- id: 0,
482
- label: 'Ledger 1',
483
- address: '0x742D35Cc6634C0532925a3b844bc9e7595f2bd9f',
484
- xpub: 'xpub...',
485
- };
486
-
487
- evmVaultState.accounts[KeyringAccountType.Ledger][0] = {
488
- id: evmAccount.id,
489
- label: evmAccount.label,
490
- address: evmAccount.address,
491
- xpub: evmAccount.xpub,
492
- xprv: '',
493
- isImported: false,
494
- isTrezorWallet: false,
495
- isLedgerWallet: true,
496
- balances: { syscoin: 0, ethereum: 0 },
497
- assets: { syscoin: [], ethereum: [] },
498
- };
499
-
500
- // Test that Ledger reconnects and signs successfully
501
- const result = await evmKeyring.ledgerSigner.evm.signEVMTransaction({
502
- rawTx: '0x1234567890',
503
- accountIndex: 0,
504
- });
505
-
506
- // Verify reconnection happened
507
- expect(evmKeyring.ledgerSigner.ensureConnection).toHaveBeenCalledTimes(1);
508
-
509
- // Verify the signature was returned
510
- expect(result).toEqual({
511
- r: '123456789abcdef',
512
- s: '987654321fedcba',
513
- v: '00',
514
- });
515
-
516
- // Verify Ledger is now connected
517
- expect(evmKeyring.ledgerSigner.transport).toBeTruthy();
518
- });
519
-
520
- it('should handle EVM transaction signing for Ledger', async () => {
521
- // Set up EVM vault state
522
- const evmVaultState = createMockVaultState({
523
- activeAccountId: 0,
524
- activeAccountType: KeyringAccountType.HDAccount,
525
- networkType: INetworkType.Ethereum,
526
- chainId: 1,
527
- });
528
- const evmVaultStateGetter = jest.fn(() => evmVaultState);
529
-
530
- // Create EVM keyring with Ledger
531
- const evmKeyring = await KeyringManager.createInitialized(
532
- PEACE_SEED_PHRASE,
533
- FAKE_PASSWORD,
534
- evmVaultStateGetter
535
- );
536
-
537
- // Mock ensureConnection
538
- evmKeyring.ledgerSigner.ensureConnection = jest
539
- .fn()
540
- .mockResolvedValue(undefined);
541
-
542
- // Mock Ledger EVM signer
543
- const mockSignEVMTransaction = jest.fn().mockResolvedValue({
544
- r: '123456789abcdef123456789abcdef123456789abcdef123456789abcdef12345678',
545
- s: '987654321fedcba987654321fedcba987654321fedcba987654321fedcba987654',
546
- v: '00',
547
- });
548
-
549
- evmKeyring.ledgerSigner.evm = {
550
- getEvmAddressAndPubKey: jest.fn().mockResolvedValue({
551
- address: '0x742D35Cc6634C0532925a3b844bc9e7595f2bd9f',
552
- publicKey: '0x04...',
553
- }),
554
- signEVMTransaction: mockSignEVMTransaction,
555
- signPersonalMessage: jest.fn().mockResolvedValue('0xmocked_signature'),
556
- signTypedData: jest.fn().mockResolvedValue('0xmocked_typed_signature'),
557
- };
558
-
559
- // Import Ledger account
560
- const evmAccount = await evmKeyring.importLedgerAccount('EVM Ledger');
561
- if (evmAccount) {
562
- // Update vault state to set Ledger as active
563
- evmVaultState.accounts[KeyringAccountType.Ledger][evmAccount.id] = {
564
- id: evmAccount.id,
565
- label: evmAccount.label,
566
- address: evmAccount.address,
567
- xpub: evmAccount.xpub,
568
- xprv: '',
569
- isImported: false,
570
- isTrezorWallet: false,
571
- isLedgerWallet: true,
572
- balances: { syscoin: 0, ethereum: 0 },
573
- assets: { syscoin: [], ethereum: [] },
574
- };
575
- evmVaultState.activeAccount = {
576
- id: evmAccount.id,
577
- type: KeyringAccountType.Ledger,
578
- };
579
-
580
- // Account switch is handled by vault state update
581
- }
582
-
583
- // Test that Ledger signing is called - expect it to fail at serialization but verify Ledger was called
584
- try {
585
- await evmKeyring.ethereumTransaction.sendFormattedTransaction({
586
- to: '0x742D35Cc6634C0532925a3b844bc9e7595f2bd9f',
587
- value: '0x0',
588
- data: '0x',
589
- gasLimit: '0x5208',
590
- maxFeePerGas: '0x3b9aca00',
591
- maxPriorityFeePerGas: '0x1dcd6500',
592
- chainId: 1,
593
- from: '0x742D35Cc6634C0532925a3b844bc9e7595f2bd9f',
594
- });
595
- // If it doesn't throw, that's fine too
596
- } catch (error) {
597
- // Expected to fail at signature serialization, but we should have called the Ledger signer
598
- expect(error.message).toContain('value out of range');
599
- }
600
-
601
- // The important part: verify that Ledger signing was attempted with correct parameters
602
- expect(mockSignEVMTransaction).toHaveBeenCalled();
603
- expect(mockSignEVMTransaction).toHaveBeenCalledWith({
604
- rawTx: expect.any(String), // Should be a hex string of the unsigned transaction
605
- accountIndex: expect.any(Number), // Should be the account index
606
- });
607
- });
608
- });
609
-
610
- describe('Network Support', () => {
611
- it('should support Ledger on different UTXO networks', async () => {
612
- // Set up testnet vault state
613
- const testnetVaultState = createMockVaultState({
614
- activeAccountId: 0,
615
- activeAccountType: KeyringAccountType.HDAccount,
616
- networkType: INetworkType.Syscoin,
617
- chainId: 5700,
618
- });
619
- const testnetVaultStateGetter = jest.fn(() => testnetVaultState);
620
-
621
- // Test on testnet
622
- const testnetKeyring = await KeyringManager.createInitialized(
623
- PEACE_SEED_PHRASE,
624
- FAKE_PASSWORD,
625
- testnetVaultStateGetter
626
- );
627
-
628
- // Mock getAddress to return testnet address
629
- testnetKeyring.getAddress = jest
630
- .fn()
631
- .mockResolvedValue('tsys1q_testnet_ledger');
632
-
633
- // Mock ensureConnection for testnet
634
- testnetKeyring.ledgerSigner.ensureConnection = jest
635
- .fn()
636
- .mockResolvedValue(undefined);
637
-
638
- // Mock testnet Ledger
639
- testnetKeyring.ledgerSigner.utxo = {
640
- getXpub: jest
641
- .fn()
642
- .mockResolvedValue(
643
- 'vpub5YMNvjHGu8MhNvgxNrGV8qZGkb3SVTiCAzqyCV8TbCZrEXrJqsCTMJjEJXBLfmjfFCDPRpGPW59THQMvPDuQejY5cSpfNYVZYcgJaMVZJCG'
644
- ),
645
- getUtxoAddress: jest.fn().mockResolvedValue('tsys1q_testnet_ledger'),
646
- verifyUtxoAddress: jest.fn().mockResolvedValue('tsys1q_testnet_ledger'),
647
- };
648
-
649
- const account = await testnetKeyring.importLedgerAccount(
650
- 'Testnet Ledger'
651
- );
652
- if (account) {
653
- expect(account.address.match(/^(sys1|tsys1)/)).toBeTruthy();
654
- }
655
- });
656
-
657
- it('should maintain separate Ledger accounts per network', async () => {
658
- // Mock getAddress for mainnet
659
- keyringManager.getAddress = jest
660
- .fn()
661
- .mockResolvedValue('sys1q_mainnet_ledger');
662
-
663
- // Mock mainnet Ledger
664
- keyringManager.ledgerSigner.utxo = {
665
- getXpub: jest
666
- .fn()
667
- .mockResolvedValue(
668
- 'zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs'
669
- ),
670
- getUtxoAddress: jest.fn().mockResolvedValue('sys1q_mainnet_ledger'),
671
- verifyUtxoAddress: jest.fn().mockResolvedValue('sys1q_mainnet_ledger'),
672
- };
673
-
674
- // Import on mainnet
675
- const mainnetAccount = await keyringManager.importLedgerAccount(
676
- 'Mainnet Ledger'
677
- );
678
-
679
- // Set up testnet vault state
680
- const testnetVaultState = createMockVaultState({
681
- activeAccountId: 0,
682
- activeAccountType: KeyringAccountType.HDAccount,
683
- networkType: INetworkType.Syscoin,
684
- chainId: 5700,
685
- });
686
- const testnetVaultStateGetter = jest.fn(() => testnetVaultState);
687
-
688
- // Create testnet keyring
689
- const testnetKeyring = await KeyringManager.createInitialized(
690
- PEACE_SEED_PHRASE,
691
- FAKE_PASSWORD,
692
- testnetVaultStateGetter
693
- );
694
-
695
- // Mock getAddress for testnet
696
- testnetKeyring.getAddress = jest
697
- .fn()
698
- .mockResolvedValue('tsys1q_testnet_ledger');
699
-
700
- // Mock ensureConnection for testnet
701
- testnetKeyring.ledgerSigner.ensureConnection = jest
702
- .fn()
703
- .mockResolvedValue(undefined);
704
-
705
- // Mock testnet Ledger
706
- testnetKeyring.ledgerSigner.utxo = {
707
- getXpub: jest
708
- .fn()
709
- .mockResolvedValue(
710
- 'vpub5YMNvjHGu8MhNvgxNrGV8qZGkb3SVTiCAzqyCV8TbCZrEXrJqsCTMJjEJXBLfmjfFCDPRpGPW59THQMvPDuQejY5cSpfNYVZYcgJaMVZJCG'
711
- ),
712
- getUtxoAddress: jest.fn().mockResolvedValue('tsys1q_testnet_ledger'),
713
- verifyUtxoAddress: jest.fn().mockResolvedValue('tsys1q_testnet_ledger'),
714
- };
715
-
716
- // Import on testnet
717
- const testnetAccount = await testnetKeyring.importLedgerAccount(
718
- 'Testnet Ledger'
719
- );
720
-
721
- // Accounts should be independent
722
- if (mainnetAccount && testnetAccount) {
723
- expect(mainnetAccount.address).not.toBe(testnetAccount.address);
724
- expect(mainnetAccount.address.match(/^(sys1|tsys1)/)).toBeTruthy();
725
- expect(testnetAccount.address.match(/^(sys1|tsys1)/)).toBeTruthy();
726
- }
727
- });
728
- });
729
-
730
- describe('Error Handling', () => {
731
- it('should handle Ledger communication errors', async () => {
732
- // Mock communication error
733
- keyringManager.ledgerSigner.utxo = {
734
- getXpub: jest
735
- .fn()
736
- .mockRejectedValue(new Error('Ledger device communication error')),
737
- getUtxoAddress: jest.fn(),
738
- verifyUtxoAddress: jest.fn(),
739
- };
740
-
741
- await expect(keyringManager.importLedgerAccount()).rejects.toThrow(
742
- 'Ledger device communication error'
743
- );
744
- });
745
-
746
- it('should handle invalid Ledger responses', async () => {
747
- // Mock invalid response
748
- keyringManager.ledgerSigner.utxo = {
749
- getXpub: jest.fn().mockResolvedValue(null),
750
- getUtxoAddress: jest.fn().mockResolvedValue(null),
751
- verifyUtxoAddress: jest.fn(),
752
- };
753
-
754
- await expect(keyringManager.importLedgerAccount()).rejects.toThrow(
755
- 'Something wrong happened'
756
- );
757
- });
758
-
759
- it('should handle Ledger app not open', async () => {
760
- keyringManager.ledgerSigner.utxo = {
761
- getXpub: jest
762
- .fn()
763
- .mockRejectedValue(new Error('Please open Syscoin app on Ledger')),
764
- getUtxoAddress: jest.fn(),
765
- verifyUtxoAddress: jest.fn(),
766
- };
767
-
768
- await expect(keyringManager.importLedgerAccount()).rejects.toThrow(
769
- 'Please open Syscoin app on Ledger'
770
- );
771
- });
772
- });
773
-
774
- describe('Security', () => {
775
- it('should not expose private keys for hardware wallets', async () => {
776
- // Mock getAddress
777
- keyringManager.getAddress = jest
778
- .fn()
779
- .mockResolvedValue('sys1q_test_address');
780
-
781
- keyringManager.ledgerSigner.utxo = {
782
- getXpub: jest
783
- .fn()
784
- .mockResolvedValue(
785
- 'zpub6s8HtEQtcu3AmBn9sniSqCAVhx2nJAhb2sd5NDYeYZ1ZJaZx7MAVZZnG1PdCUNJcVJXGbVpGfSYZLgkPSUjLYnJg8UdYvdkfaygcXZKPLy6'
786
- ),
787
- getUtxoAddress: jest.fn().mockResolvedValue('sys1q_test_address'),
788
- verifyUtxoAddress: jest.fn().mockResolvedValue('sys1q_test_address'),
789
- };
790
-
791
- const account = await keyringManager.importLedgerAccount('Security Test');
792
-
793
- expect(account).toBeDefined();
794
- if (account) {
795
- expect(account.xprv).toBe(''); // Should be empty for hardware wallets
796
- expect(account.isLedgerWallet).toBe(true);
797
-
798
- // Should not be able to get private key for hardware wallet
799
- await expect(
800
- keyringManager.getPrivateKeyByAccountId(
801
- account.id,
802
- KeyringAccountType.Ledger,
803
- FAKE_PASSWORD
804
- )
805
- ).rejects.toThrow();
806
- }
807
- });
808
-
809
- it('should maintain hardware wallet isolation', async () => {
810
- // Mock getAddress
811
- keyringManager.getAddress = jest
812
- .fn()
813
- .mockResolvedValue('sys1q_isolation_address');
814
-
815
- // Mock and import Ledger account
816
- keyringManager.ledgerSigner.utxo = {
817
- getXpub: jest
818
- .fn()
819
- .mockResolvedValue(
820
- 'zpub6s8HtEQtcu3AmBn9sniSqCAVhx2nJAhb2sd5NDYeYZ1ZJaZx7MAVZZnG1PdCUNJcVJXGbVpGfSYZLgkPSUjLYnJg8UdYvdkfaygcXZKPLy6'
821
- ),
822
- getUtxoAddress: jest.fn().mockResolvedValue('sys1q_isolation_address'),
823
- verifyUtxoAddress: jest
824
- .fn()
825
- .mockResolvedValue('sys1q_isolation_address'),
826
- };
827
-
828
- const ledgerAccount = await keyringManager.importLedgerAccount(
829
- 'Isolation Test'
830
- );
831
-
832
- if (ledgerAccount) {
833
- // Update vault state
834
- currentVaultState.accounts[KeyringAccountType.Ledger][
835
- ledgerAccount.id
836
- ] = {
837
- id: ledgerAccount.id,
838
- label: ledgerAccount.label,
839
- address: ledgerAccount.address,
840
- xpub: ledgerAccount.xpub,
841
- xprv: '',
842
- isImported: false,
843
- isTrezorWallet: false,
844
- isLedgerWallet: true,
845
- balances: { syscoin: 0, ethereum: 0 },
846
- assets: { syscoin: [], ethereum: [] },
847
- };
848
-
849
- // Verify Ledger accounts are completely separate from HD accounts
850
- const hdAccounts =
851
- currentVaultState.accounts[KeyringAccountType.HDAccount];
852
- const ledgerAccounts =
853
- currentVaultState.accounts[KeyringAccountType.Ledger];
854
-
855
- expect(Object.keys(hdAccounts)).toHaveLength(1); // Initial HD account
856
- expect(Object.keys(ledgerAccounts)).toHaveLength(1); // One imported Ledger account
857
-
858
- // Verify no cross-contamination of account types
859
- Object.values(hdAccounts).forEach((account: any) => {
860
- expect(account.isLedgerWallet).toBe(false);
861
- });
862
-
863
- Object.values(ledgerAccounts).forEach((account: any) => {
864
- expect(account.isLedgerWallet).toBe(true);
865
- });
866
- }
867
- });
868
- });
869
- });