@sidhujag/sysweb3-keyring 1.0.545 → 1.0.547

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/coverage/clover.xml +2875 -0
  2. package/coverage/coverage-final.json +29468 -0
  3. package/coverage/lcov-report/base.css +354 -0
  4. package/coverage/lcov-report/block-navigation.js +85 -0
  5. package/coverage/lcov-report/favicon.png +0 -0
  6. package/coverage/lcov-report/index.html +320 -0
  7. package/coverage/lcov-report/prettify.css +101 -0
  8. package/coverage/lcov-report/prettify.js +1008 -0
  9. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  10. package/coverage/lcov-report/sorter.js +191 -0
  11. package/coverage/lcov-report/src/index.html +276 -0
  12. package/coverage/lcov-report/src/index.ts.html +114 -0
  13. package/coverage/lcov-report/src/initial-state.ts.html +558 -0
  14. package/coverage/lcov-report/src/keyring-manager.ts.html +6279 -0
  15. package/coverage/lcov-report/src/ledger/bitcoin_client/index.html +178 -0
  16. package/coverage/lcov-report/src/ledger/bitcoin_client/index.ts.html +144 -0
  17. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/appClient.ts.html +1560 -0
  18. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/bip32.ts.html +276 -0
  19. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/buffertools.ts.html +495 -0
  20. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/clientCommands.ts.html +1138 -0
  21. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/index.html +363 -0
  22. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/merkelizedPsbt.ts.html +289 -0
  23. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/merkle.ts.html +486 -0
  24. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/merkleMap.ts.html +240 -0
  25. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/policy.ts.html +342 -0
  26. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/psbtv2.ts.html +2388 -0
  27. package/coverage/lcov-report/src/ledger/bitcoin_client/lib/varint.ts.html +453 -0
  28. package/coverage/lcov-report/src/ledger/consts.ts.html +177 -0
  29. package/coverage/lcov-report/src/ledger/index.html +216 -0
  30. package/coverage/lcov-report/src/ledger/index.ts.html +1371 -0
  31. package/coverage/lcov-report/src/ledger/utils.ts.html +102 -0
  32. package/coverage/lcov-report/src/signers.ts.html +591 -0
  33. package/coverage/lcov-report/src/storage.ts.html +198 -0
  34. package/coverage/lcov-report/src/transactions/ethereum.ts.html +5826 -0
  35. package/coverage/lcov-report/src/transactions/index.html +216 -0
  36. package/coverage/lcov-report/src/transactions/index.ts.html +93 -0
  37. package/coverage/lcov-report/src/transactions/syscoin.ts.html +1521 -0
  38. package/coverage/lcov-report/src/trezor/index.html +176 -0
  39. package/coverage/lcov-report/src/trezor/index.ts.html +2655 -0
  40. package/coverage/lcov-report/src/types.ts.html +1443 -0
  41. package/coverage/lcov-report/src/utils/derivation-paths.ts.html +486 -0
  42. package/coverage/lcov-report/src/utils/index.html +196 -0
  43. package/coverage/lcov-report/src/utils/psbt.ts.html +159 -0
  44. package/coverage/lcov-report/test/helpers/constants.ts.html +627 -0
  45. package/coverage/lcov-report/test/helpers/index.html +176 -0
  46. package/coverage/lcov.info +4832 -0
  47. package/{cjs → dist/cjs}/ledger/bitcoin_client/lib/appClient.js +1 -124
  48. package/dist/cjs/ledger/bitcoin_client/lib/appClient.js.map +1 -0
  49. package/{cjs → dist/cjs}/transactions/ethereum.js +6 -2
  50. package/dist/cjs/transactions/ethereum.js.map +1 -0
  51. package/dist/package.json +50 -0
  52. package/{types → dist/types}/ledger/bitcoin_client/lib/appClient.d.ts +0 -6
  53. package/examples/basic-usage.js +140 -0
  54. package/jest.config.js +32 -0
  55. package/package.json +31 -13
  56. package/readme.md +201 -0
  57. package/src/declare.d.ts +7 -0
  58. package/src/errorUtils.ts +83 -0
  59. package/src/hardware-wallet-manager.ts +655 -0
  60. package/src/index.ts +12 -0
  61. package/src/initial-state.ts +108 -0
  62. package/src/keyring-manager.ts +2698 -0
  63. package/src/ledger/bitcoin_client/index.ts +19 -0
  64. package/src/ledger/bitcoin_client/lib/appClient.ts +405 -0
  65. package/src/ledger/bitcoin_client/lib/bip32.ts +61 -0
  66. package/src/ledger/bitcoin_client/lib/buffertools.ts +134 -0
  67. package/src/ledger/bitcoin_client/lib/clientCommands.ts +356 -0
  68. package/src/ledger/bitcoin_client/lib/constants.ts +12 -0
  69. package/src/ledger/bitcoin_client/lib/merkelizedPsbt.ts +65 -0
  70. package/src/ledger/bitcoin_client/lib/merkle.ts +136 -0
  71. package/src/ledger/bitcoin_client/lib/merkleMap.ts +49 -0
  72. package/src/ledger/bitcoin_client/lib/policy.ts +91 -0
  73. package/src/ledger/bitcoin_client/lib/psbtv2.ts +768 -0
  74. package/src/ledger/bitcoin_client/lib/varint.ts +120 -0
  75. package/src/ledger/consts.ts +3 -0
  76. package/src/ledger/index.ts +685 -0
  77. package/src/ledger/types.ts +74 -0
  78. package/src/network-utils.ts +99 -0
  79. package/src/providers.ts +345 -0
  80. package/src/signers.ts +158 -0
  81. package/src/storage.ts +63 -0
  82. package/src/transactions/__tests__/integration.test.ts +303 -0
  83. package/src/transactions/__tests__/syscoin.test.ts +409 -0
  84. package/src/transactions/ethereum.ts +2503 -0
  85. package/src/transactions/index.ts +2 -0
  86. package/src/transactions/syscoin.ts +542 -0
  87. package/src/trezor/index.ts +1050 -0
  88. package/src/types.ts +366 -0
  89. package/src/utils/derivation-paths.ts +133 -0
  90. package/src/utils/psbt.ts +24 -0
  91. package/src/utils.ts +191 -0
  92. package/test/README.md +158 -0
  93. package/test/__mocks__/ledger-mock.js +20 -0
  94. package/test/__mocks__/trezor-mock.js +75 -0
  95. package/test/cleanup-summary.md +167 -0
  96. package/test/helpers/README.md +78 -0
  97. package/test/helpers/constants.ts +79 -0
  98. package/test/helpers/setup.ts +714 -0
  99. package/test/integration/import-validation.spec.ts +588 -0
  100. package/test/unit/hardware/ledger.spec.ts +869 -0
  101. package/test/unit/hardware/trezor.spec.ts +828 -0
  102. package/test/unit/keyring-manager/account-management.spec.ts +970 -0
  103. package/test/unit/keyring-manager/import-watchonly.spec.ts +181 -0
  104. package/test/unit/keyring-manager/import-wif.spec.ts +126 -0
  105. package/test/unit/keyring-manager/initialization.spec.ts +782 -0
  106. package/test/unit/keyring-manager/key-derivation.spec.ts +996 -0
  107. package/test/unit/keyring-manager/security.spec.ts +505 -0
  108. package/test/unit/keyring-manager/state-management.spec.ts +375 -0
  109. package/test/unit/network/network-management.spec.ts +372 -0
  110. package/test/unit/transactions/ethereum-transactions.spec.ts +382 -0
  111. package/test/unit/transactions/syscoin-transactions.spec.ts +615 -0
  112. package/tsconfig.json +14 -0
  113. package/cjs/ledger/bitcoin_client/lib/appClient.js.map +0 -1
  114. package/cjs/transactions/ethereum.js.map +0 -1
  115. /package/{README.md → dist/README.md} +0 -0
  116. /package/{cjs → dist/cjs}/errorUtils.js +0 -0
  117. /package/{cjs → dist/cjs}/errorUtils.js.map +0 -0
  118. /package/{cjs → dist/cjs}/hardware-wallet-manager.js +0 -0
  119. /package/{cjs → dist/cjs}/hardware-wallet-manager.js.map +0 -0
  120. /package/{cjs → dist/cjs}/index.js +0 -0
  121. /package/{cjs → dist/cjs}/index.js.map +0 -0
  122. /package/{cjs → dist/cjs}/initial-state.js +0 -0
  123. /package/{cjs → dist/cjs}/initial-state.js.map +0 -0
  124. /package/{cjs → dist/cjs}/keyring-manager.js +0 -0
  125. /package/{cjs → dist/cjs}/keyring-manager.js.map +0 -0
  126. /package/{cjs → dist/cjs}/ledger/bitcoin_client/index.js +0 -0
  127. /package/{cjs → dist/cjs}/ledger/bitcoin_client/index.js.map +0 -0
  128. /package/{cjs → dist/cjs}/ledger/bitcoin_client/lib/bip32.js +0 -0
  129. /package/{cjs → dist/cjs}/ledger/bitcoin_client/lib/bip32.js.map +0 -0
  130. /package/{cjs → dist/cjs}/ledger/bitcoin_client/lib/buffertools.js +0 -0
  131. /package/{cjs → dist/cjs}/ledger/bitcoin_client/lib/buffertools.js.map +0 -0
  132. /package/{cjs → dist/cjs}/ledger/bitcoin_client/lib/clientCommands.js +0 -0
  133. /package/{cjs → dist/cjs}/ledger/bitcoin_client/lib/clientCommands.js.map +0 -0
  134. /package/{cjs → dist/cjs}/ledger/bitcoin_client/lib/constants.js +0 -0
  135. /package/{cjs → dist/cjs}/ledger/bitcoin_client/lib/constants.js.map +0 -0
  136. /package/{cjs → dist/cjs}/ledger/bitcoin_client/lib/merkelizedPsbt.js +0 -0
  137. /package/{cjs → dist/cjs}/ledger/bitcoin_client/lib/merkelizedPsbt.js.map +0 -0
  138. /package/{cjs → dist/cjs}/ledger/bitcoin_client/lib/merkle.js +0 -0
  139. /package/{cjs → dist/cjs}/ledger/bitcoin_client/lib/merkle.js.map +0 -0
  140. /package/{cjs → dist/cjs}/ledger/bitcoin_client/lib/merkleMap.js +0 -0
  141. /package/{cjs → dist/cjs}/ledger/bitcoin_client/lib/merkleMap.js.map +0 -0
  142. /package/{cjs → dist/cjs}/ledger/bitcoin_client/lib/policy.js +0 -0
  143. /package/{cjs → dist/cjs}/ledger/bitcoin_client/lib/policy.js.map +0 -0
  144. /package/{cjs → dist/cjs}/ledger/bitcoin_client/lib/psbtv2.js +0 -0
  145. /package/{cjs → dist/cjs}/ledger/bitcoin_client/lib/psbtv2.js.map +0 -0
  146. /package/{cjs → dist/cjs}/ledger/bitcoin_client/lib/varint.js +0 -0
  147. /package/{cjs → dist/cjs}/ledger/bitcoin_client/lib/varint.js.map +0 -0
  148. /package/{cjs → dist/cjs}/ledger/consts.js +0 -0
  149. /package/{cjs → dist/cjs}/ledger/consts.js.map +0 -0
  150. /package/{cjs → dist/cjs}/ledger/index.js +0 -0
  151. /package/{cjs → dist/cjs}/ledger/index.js.map +0 -0
  152. /package/{cjs → dist/cjs}/ledger/types.js +0 -0
  153. /package/{cjs → dist/cjs}/ledger/types.js.map +0 -0
  154. /package/{cjs → dist/cjs}/network-utils.js +0 -0
  155. /package/{cjs → dist/cjs}/network-utils.js.map +0 -0
  156. /package/{cjs → dist/cjs}/providers.js +0 -0
  157. /package/{cjs → dist/cjs}/providers.js.map +0 -0
  158. /package/{cjs → dist/cjs}/signers.js +0 -0
  159. /package/{cjs → dist/cjs}/signers.js.map +0 -0
  160. /package/{cjs → dist/cjs}/storage.js +0 -0
  161. /package/{cjs → dist/cjs}/storage.js.map +0 -0
  162. /package/{cjs → dist/cjs}/transactions/__tests__/integration.test.js +0 -0
  163. /package/{cjs → dist/cjs}/transactions/__tests__/integration.test.js.map +0 -0
  164. /package/{cjs → dist/cjs}/transactions/__tests__/syscoin.test.js +0 -0
  165. /package/{cjs → dist/cjs}/transactions/__tests__/syscoin.test.js.map +0 -0
  166. /package/{cjs → dist/cjs}/transactions/index.js +0 -0
  167. /package/{cjs → dist/cjs}/transactions/index.js.map +0 -0
  168. /package/{cjs → dist/cjs}/transactions/syscoin.js +0 -0
  169. /package/{cjs → dist/cjs}/transactions/syscoin.js.map +0 -0
  170. /package/{cjs → dist/cjs}/trezor/index.js +0 -0
  171. /package/{cjs → dist/cjs}/trezor/index.js.map +0 -0
  172. /package/{cjs → dist/cjs}/types.js +0 -0
  173. /package/{cjs → dist/cjs}/types.js.map +0 -0
  174. /package/{cjs → dist/cjs}/utils/derivation-paths.js +0 -0
  175. /package/{cjs → dist/cjs}/utils/derivation-paths.js.map +0 -0
  176. /package/{cjs → dist/cjs}/utils/psbt.js +0 -0
  177. /package/{cjs → dist/cjs}/utils/psbt.js.map +0 -0
  178. /package/{cjs → dist/cjs}/utils.js +0 -0
  179. /package/{cjs → dist/cjs}/utils.js.map +0 -0
  180. /package/{types → dist/types}/errorUtils.d.ts +0 -0
  181. /package/{types → dist/types}/hardware-wallet-manager.d.ts +0 -0
  182. /package/{types → dist/types}/index.d.ts +0 -0
  183. /package/{types → dist/types}/initial-state.d.ts +0 -0
  184. /package/{types → dist/types}/keyring-manager.d.ts +0 -0
  185. /package/{types → dist/types}/ledger/bitcoin_client/index.d.ts +0 -0
  186. /package/{types → dist/types}/ledger/bitcoin_client/lib/bip32.d.ts +0 -0
  187. /package/{types → dist/types}/ledger/bitcoin_client/lib/buffertools.d.ts +0 -0
  188. /package/{types → dist/types}/ledger/bitcoin_client/lib/clientCommands.d.ts +0 -0
  189. /package/{types → dist/types}/ledger/bitcoin_client/lib/constants.d.ts +0 -0
  190. /package/{types → dist/types}/ledger/bitcoin_client/lib/merkelizedPsbt.d.ts +0 -0
  191. /package/{types → dist/types}/ledger/bitcoin_client/lib/merkle.d.ts +0 -0
  192. /package/{types → dist/types}/ledger/bitcoin_client/lib/merkleMap.d.ts +0 -0
  193. /package/{types → dist/types}/ledger/bitcoin_client/lib/policy.d.ts +0 -0
  194. /package/{types → dist/types}/ledger/bitcoin_client/lib/psbtv2.d.ts +0 -0
  195. /package/{types → dist/types}/ledger/bitcoin_client/lib/varint.d.ts +0 -0
  196. /package/{types → dist/types}/ledger/consts.d.ts +0 -0
  197. /package/{types → dist/types}/ledger/index.d.ts +0 -0
  198. /package/{types → dist/types}/ledger/types.d.ts +0 -0
  199. /package/{types → dist/types}/network-utils.d.ts +0 -0
  200. /package/{types → dist/types}/providers.d.ts +0 -0
  201. /package/{types → dist/types}/signers.d.ts +0 -0
  202. /package/{types → dist/types}/storage.d.ts +0 -0
  203. /package/{types → dist/types}/transactions/__tests__/integration.test.d.ts +0 -0
  204. /package/{types → dist/types}/transactions/__tests__/syscoin.test.d.ts +0 -0
  205. /package/{types → dist/types}/transactions/ethereum.d.ts +0 -0
  206. /package/{types → dist/types}/transactions/index.d.ts +0 -0
  207. /package/{types → dist/types}/transactions/syscoin.d.ts +0 -0
  208. /package/{types → dist/types}/trezor/index.d.ts +0 -0
  209. /package/{types → dist/types}/types.d.ts +0 -0
  210. /package/{types → dist/types}/utils/derivation-paths.d.ts +0 -0
  211. /package/{types → dist/types}/utils/psbt.d.ts +0 -0
  212. /package/{types → dist/types}/utils.d.ts +0 -0
@@ -0,0 +1,714 @@
1
+ // Test setup file
2
+ import { INetworkType } from '@sidhujag/sysweb3-network';
3
+ import { randomBytes, createHmac } from 'crypto';
4
+ import { TextEncoder, TextDecoder } from 'util';
5
+
6
+ import { KeyringAccountType } from '../../src';
7
+
8
+ // Extend global type to include setupTestVault and mockVaultState utilities
9
+ declare global {
10
+ function setupTestVault(password?: string): Promise<void>;
11
+ function createMockVaultState(options?: {
12
+ activeAccountId?: number;
13
+ activeAccountType?: KeyringAccountType;
14
+ networkType?: INetworkType;
15
+ chainId?: number;
16
+ }): any;
17
+ const mockVaultState: any;
18
+ }
19
+
20
+ // Polyfill for TextEncoder/TextDecoder in Node.js environment
21
+ global.TextEncoder = TextEncoder;
22
+ global.TextDecoder = TextDecoder as any;
23
+
24
+ // Polyfill crypto.getRandomValues for Node.js
25
+ global.crypto = {
26
+ getRandomValues: (arr: Uint8Array) => {
27
+ const bytes = randomBytes(arr.length);
28
+ arr.set(bytes);
29
+ return arr;
30
+ },
31
+ } as any;
32
+
33
+ // Mock browser globals that Trezor expects
34
+ global.self = global as any;
35
+ (global as any).window = global;
36
+ (global as any).document = {
37
+ createElement: () => ({}),
38
+ body: {
39
+ appendChild: () => {
40
+ // Empty implementation for mock DOM element appendChild
41
+ },
42
+ },
43
+ };
44
+
45
+ // Mock ledgerService from @ledgerhq/hw-app-eth
46
+ jest.mock('@ledgerhq/hw-app-eth', () => ({
47
+ __esModule: true,
48
+ default: jest.fn().mockImplementation(() => ({
49
+ getAddress: jest.fn(),
50
+ signTransaction: jest.fn(),
51
+ signPersonalMessage: jest.fn(),
52
+ signEIP712HashedMessage: jest.fn(),
53
+ })),
54
+ ledgerService: {
55
+ resolveTransaction: jest.fn().mockResolvedValue({}),
56
+ },
57
+ }));
58
+
59
+ // Mock environment variables if needed
60
+ process.env.SEED_PEACE_GLOBE =
61
+ process.env.SEED_PEACE_GLOBE ||
62
+ 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
63
+ process.env.PRIVATE_KEY_ACCOUNT =
64
+ process.env.PRIVATE_KEY_ACCOUNT ||
65
+ '0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
66
+ process.env.PRIVATE_KEY_ACCOUNT_ADDRESS =
67
+ process.env.PRIVATE_KEY_ACCOUNT_ADDRESS ||
68
+ '0x1234567890123456789012345678901234567890';
69
+ process.env.SEED_ACCOUNT_ADDRESS_AT_EVM =
70
+ process.env.SEED_ACCOUNT_ADDRESS_AT_EVM ||
71
+ '0x1234567890123456789012345678901234567890';
72
+ process.env.SEED_ACCOUNT_ADDRESS_AT_UTX0 =
73
+ process.env.SEED_ACCOUNT_ADDRESS_AT_UTX0 ||
74
+ 'tsys1q4v8sagt0znwaxdscrzhvu8t33n7vj8j45czpv4';
75
+ process.env.SEED_SWALLOW_HEALTH =
76
+ process.env.SEED_SWALLOW_HEALTH ||
77
+ 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon';
78
+
79
+ // Mock the providers module
80
+ jest.mock('../../src/providers', () => ({
81
+ CustomJsonRpcProvider: jest.fn().mockImplementation((_signal, _url) => {
82
+ const { BigNumber } = jest.requireActual('@ethersproject/bignumber');
83
+
84
+ // Determine chainId based on URL
85
+ let chainId = 57; // Default Syscoin mainnet
86
+ let name = 'syscoin';
87
+
88
+ if (_url) {
89
+ if (_url.includes('rpc.ankr.com/eth') || _url.includes('mainnet')) {
90
+ chainId = 1;
91
+ name = 'mainnet';
92
+ } else if (
93
+ _url.includes('tanenbaum') ||
94
+ _url.includes('test') ||
95
+ _url.includes('5700')
96
+ ) {
97
+ chainId = 5700;
98
+ name = 'syscoin-testnet';
99
+ } else if (_url.includes('mumbai') || _url.includes('80001')) {
100
+ chainId = 80001;
101
+ name = 'mumbai';
102
+ } else if (_url.includes('polygon') && !_url.includes('mumbai')) {
103
+ chainId = 137;
104
+ name = 'polygon';
105
+ }
106
+ }
107
+
108
+ // Create signer first
109
+ const signer = {
110
+ getAddress: jest
111
+ .fn()
112
+ .mockResolvedValue('0x1234567890123456789012345678901234567890'),
113
+ sendTransaction: jest.fn().mockResolvedValue({
114
+ hash: '0x1234567890123456789012345678901234567890123456789012345678901234',
115
+ wait: jest.fn().mockResolvedValue({ status: 1 }),
116
+ }),
117
+ connect: jest.fn().mockReturnThis(),
118
+ provider: null as any, // Will be set below
119
+ };
120
+
121
+ const provider = {
122
+ getNetwork: jest.fn().mockResolvedValue({ chainId, name }),
123
+ getBalance: jest
124
+ .fn()
125
+ .mockResolvedValue(BigNumber.from('1000000000000000000')),
126
+ getCode: jest.fn().mockResolvedValue('0x'),
127
+ estimateGas: jest.fn().mockResolvedValue(BigNumber.from('21000')),
128
+ getGasPrice: jest.fn().mockResolvedValue(BigNumber.from('20000000000')),
129
+ getTransactionCount: jest.fn().mockResolvedValue(0),
130
+ sendTransaction: jest.fn().mockResolvedValue({
131
+ hash: '0x1234567890123456789012345678901234567890123456789012345678901234',
132
+ wait: jest.fn().mockResolvedValue({ status: 1 }),
133
+ }),
134
+ call: jest
135
+ .fn()
136
+ .mockResolvedValue(
137
+ '0x0000000000000000000000000000000000000000000000000000000000000001'
138
+ ),
139
+ getBlock: jest.fn().mockResolvedValue({
140
+ number: 12345,
141
+ timestamp: Math.floor(Date.now() / 1000),
142
+ baseFeePerGas: BigNumber.from('20000000000'),
143
+ gasLimit: BigNumber.from('30000000'),
144
+ gasUsed: BigNumber.from('21000'),
145
+ transactions: [],
146
+ hash: '0x1234567890123456789012345678901234567890123456789012345678901234',
147
+ }),
148
+ send: jest.fn().mockImplementation((method: string) => {
149
+ if (method === 'eth_maxPriorityFeePerGas') {
150
+ return Promise.resolve('0x5f5e100'); // 1 gwei
151
+ }
152
+ return Promise.resolve('0x0');
153
+ }),
154
+ getTransaction: jest.fn().mockResolvedValue({
155
+ hash: '0x1234567890123456789012345678901234567890123456789012345678901234',
156
+ from: '0x1234567890123456789012345678901234567890',
157
+ to: '0x0987654321098765432109876543210987654321',
158
+ nonce: 0,
159
+ gasLimit: BigNumber.from('21000'),
160
+ gasPrice: BigNumber.from('20000000000'),
161
+ maxFeePerGas: BigNumber.from('40000000000'),
162
+ maxPriorityFeePerGas: BigNumber.from('2000000000'),
163
+ value: BigNumber.from('0'),
164
+ chainId: 1,
165
+ wait: jest.fn().mockResolvedValue({ status: 1 }),
166
+ }),
167
+ getSigner: jest.fn().mockReturnValue(signer),
168
+ // Add missing methods that ethers.js expects
169
+ resolveName: jest.fn().mockImplementation((nameOrAddress) => {
170
+ // If it's already an address, return it; otherwise return null (no ENS resolution)
171
+ if (
172
+ nameOrAddress &&
173
+ nameOrAddress.startsWith('0x') &&
174
+ nameOrAddress.length === 42
175
+ ) {
176
+ return Promise.resolve(nameOrAddress);
177
+ }
178
+ return Promise.resolve(null);
179
+ }),
180
+ lookupAddress: jest.fn().mockResolvedValue(null),
181
+ waitForTransaction: jest.fn().mockImplementation((hash) => {
182
+ return Promise.resolve({
183
+ hash,
184
+ status: 1,
185
+ confirmations: 1,
186
+ blockNumber: 12345,
187
+ blockHash:
188
+ '0x1234567890123456789012345678901234567890123456789012345678901234',
189
+ gasUsed: BigNumber.from('21000'),
190
+ });
191
+ }),
192
+ getResolver: jest.fn().mockResolvedValue(null),
193
+ getAvatar: jest.fn().mockResolvedValue(null),
194
+ network: { chainId },
195
+ _isProvider: true,
196
+ };
197
+
198
+ // Set circular reference
199
+ signer.provider = provider;
200
+
201
+ return provider;
202
+ }),
203
+ CustomL2JsonRpcProvider: jest.fn().mockImplementation((_signal, _url) => {
204
+ // Return the same mock as CustomJsonRpcProvider for simplicity
205
+ const CustomJsonRpcProviderMock = jest.requireMock(
206
+ '../../src/providers'
207
+ ).CustomJsonRpcProvider;
208
+ return new CustomJsonRpcProviderMock(_signal, _url);
209
+ }),
210
+ }));
211
+
212
+ // Mock storage for sysweb3-core
213
+ const mockStorage = new Map();
214
+
215
+ // Mock sysweb3-core storage
216
+ jest.mock('@sidhujag/sysweb3-core', () => ({
217
+ sysweb3Di: {
218
+ getStateStorageDb: () => ({
219
+ get: jest.fn(async (key: string) => {
220
+ return mockStorage.get(key) || null;
221
+ }),
222
+ set: jest.fn((key: string, value: any) => {
223
+ mockStorage.set(key, value);
224
+ return Promise.resolve();
225
+ }),
226
+ deleteItem: jest.fn((key: string) => {
227
+ mockStorage.delete(key);
228
+ return Promise.resolve();
229
+ }),
230
+ clear: jest.fn(() => {
231
+ mockStorage.clear();
232
+ return Promise.resolve();
233
+ }),
234
+ setClient: jest.fn(),
235
+ }),
236
+ },
237
+ }));
238
+
239
+ // Mock sysweb3-utils to support token operations
240
+ jest.mock('@sidhujag/sysweb3-utils', () => {
241
+ const actualUtils = jest.requireActual('@sidhujag/sysweb3-utils');
242
+ return {
243
+ ...actualUtils,
244
+ getAsset: jest.fn().mockResolvedValue({
245
+ assetGuid: '123456789',
246
+ symbol: 'TEST',
247
+ decimals: 8,
248
+ maxSupply: 1000000,
249
+ totalSupply: 500000,
250
+ }),
251
+ };
252
+ });
253
+
254
+ // Mock syscoinjs utilities - only network calls, use real HDSigner for deterministic crypto
255
+ jest.mock('syscoinjs-lib', () => {
256
+ const actualSyscoinjs = jest.requireActual('syscoinjs-lib');
257
+
258
+ // Create a mock HDSigner class that extends the real one
259
+ class MockHDSigner extends actualSyscoinjs.utils.HDSigner {
260
+ // Override sign method to avoid real PSBT signing
261
+ async sign(psbt) {
262
+ // If psbt is a string (from mock), just return it
263
+ if (typeof psbt === 'string') {
264
+ return psbt;
265
+ }
266
+
267
+ // If it's a mock PSBT object, return a properly signed mock
268
+ if (psbt && psbt.data && psbt.data.inputs) {
269
+ // Mock the signing process
270
+ return {
271
+ ...psbt,
272
+ signed: true,
273
+ extractTransaction: jest.fn().mockReturnValue({
274
+ getId: jest.fn().mockReturnValue('mock_txid'),
275
+ toHex: jest.fn().mockReturnValue('mock_hex'),
276
+ }),
277
+ finalizeAllInputs: jest.fn(),
278
+ validateSignaturesOfAllInputs: jest.fn().mockReturnValue(true),
279
+ };
280
+ }
281
+
282
+ // Otherwise return the psbt as-is
283
+ return psbt;
284
+ }
285
+ }
286
+
287
+ return {
288
+ ...actualSyscoinjs,
289
+ utils: {
290
+ ...actualSyscoinjs.utils,
291
+ // Replace HDSigner with our mock version
292
+ HDSigner: MockHDSigner,
293
+ // Only mock network-dependent functions
294
+ fetchBackendAccount: jest.fn().mockResolvedValue({
295
+ balance: 100000000, // 1 SYS in satoshis
296
+ tokens: [],
297
+ address: 'tsys1q4v8sagt0znwaxdscrzhvu8t33n7vj8j45czpv4',
298
+ }),
299
+ fetchEstimateFee: jest.fn().mockResolvedValue(10), // Return reasonable fee rate (10 satoshis per 1024 bytes)
300
+ fetchBackendRawTx: jest.fn().mockResolvedValue('mockedRawTx'),
301
+ fetchBackendUTXOS: jest.fn().mockResolvedValue([]),
302
+ sanitizeBlockbookUTXOs: jest.fn().mockReturnValue([]),
303
+ getMemoFromOpReturn: jest.fn(),
304
+ createTransaction: jest.fn().mockResolvedValue({
305
+ psbt: 'mocked_psbt',
306
+ assets: [],
307
+ }),
308
+ syscoinNetworks: {
309
+ mainnet: {},
310
+ testnet: {},
311
+ },
312
+ },
313
+ createPSBTFromRes: jest.fn().mockReturnValue({
314
+ psbt: 'mocked_psbt',
315
+ assets: [],
316
+ }),
317
+ signTransaction: jest.fn().mockResolvedValue('signed_tx'),
318
+ sendTransaction: jest.fn().mockResolvedValue({ txid: 'mocked_txid' }),
319
+ SyscoinJSLib: jest.fn().mockImplementation((hd, url) => ({
320
+ blockbookURL: url || 'https://blockbook-dev.elint.services/',
321
+ Signer: hd,
322
+ createTransaction: jest.fn().mockResolvedValue({
323
+ psbt: 'mocked_psbt_object',
324
+ fee: 0.0001, // 0.0001 SYS fee
325
+ }),
326
+ decodeRawTransaction: jest.fn().mockReturnValue({
327
+ txid: 'mocked_txid',
328
+ version: 1,
329
+ locktime: 0,
330
+ vin: [],
331
+ vout: [],
332
+ }),
333
+ assetAllocationSend: jest.fn().mockResolvedValue({
334
+ psbt: 'mocked_spt_psbt',
335
+ fee: 0.0001,
336
+ }),
337
+ send: jest.fn().mockResolvedValue({
338
+ extractTransaction: jest.fn().mockReturnValue({
339
+ getId: jest.fn().mockReturnValue('mock_transaction_id'),
340
+ }),
341
+ }),
342
+ })),
343
+ };
344
+ });
345
+
346
+ // Mock fetch to avoid network requests
347
+ global.fetch = jest.fn((url) => {
348
+ if (url.includes('/api/v2') && !url.includes('xpub')) {
349
+ // Determine coin name based on URL
350
+ let coinName = 'Syscoin'; // Default to mainnet
351
+ let chainType = 'main';
352
+
353
+ // Check if it's a testnet URL
354
+ if (
355
+ url.includes('dev') ||
356
+ url.includes('test') ||
357
+ url.includes('tanenbaum')
358
+ ) {
359
+ coinName = 'Syscoin Testnet';
360
+ chainType = 'test';
361
+ }
362
+
363
+ return Promise.resolve({
364
+ ok: true,
365
+ json: () =>
366
+ Promise.resolve({
367
+ blockbook: { coin: coinName },
368
+ backend: { chain: chainType },
369
+ }),
370
+ } as any);
371
+ }
372
+ if (url.includes('xpub') || url.includes('fetchBackendAccount')) {
373
+ return Promise.resolve({
374
+ ok: true,
375
+ json: () =>
376
+ Promise.resolve({
377
+ balance: 100000000,
378
+ tokens: [],
379
+ address: 'tsys1q4v8sagt0znwaxdscrzhvu8t33n7vj8j45czpv4',
380
+ }),
381
+ } as any);
382
+ }
383
+ if (url.includes('fetchEstimateFee')) {
384
+ return Promise.resolve({
385
+ ok: true,
386
+ json: () => Promise.resolve({ result: 10000 }),
387
+ } as any);
388
+ }
389
+ // Default Ethereum RPC response
390
+ return Promise.resolve({
391
+ ok: true,
392
+ json: () =>
393
+ Promise.resolve({
394
+ jsonrpc: '2.0',
395
+ id: 1,
396
+ result: '0x1',
397
+ }),
398
+ } as any);
399
+ }) as any;
400
+
401
+ // Clear storage before each test to ensure clean state
402
+ beforeEach(() => {
403
+ mockStorage.clear();
404
+ });
405
+
406
+ // Also clear after each test to prevent cross-test pollution
407
+ afterEach(() => {
408
+ mockStorage.clear();
409
+ });
410
+
411
+ // Helper function to set up a basic vault for tests
412
+ global.setupTestVault = async (password = 'Asdqwe123!') => {
413
+ const { sysweb3Di } = jest.requireMock('@sidhujag/sysweb3-core');
414
+ const storage = sysweb3Di.getStateStorageDb();
415
+
416
+ // Check if vault-keys already exist - if so, don't recreate them (idempotent)
417
+ const existingVaultKeys = await storage.get('vault-keys');
418
+ if (existingVaultKeys && existingVaultKeys.salt && existingVaultKeys.hash) {
419
+ // Vault already set up, verify password matches
420
+ const expectedHash = createHmac('sha512', existingVaultKeys.salt)
421
+ .update(password)
422
+ .digest('hex');
423
+ if (expectedHash === existingVaultKeys.hash) {
424
+ // Same password, vault is already correctly set up
425
+ return;
426
+ }
427
+ // Different password - need to recreate
428
+ }
429
+
430
+ // Create a vault with plain mnemonic (it will be encrypted by storage)
431
+ const CryptoJS = jest.requireActual('crypto-js');
432
+ const mnemonic =
433
+ 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
434
+
435
+ // Vault should contain plain mnemonic - the storage layer handles encryption
436
+ const vault = { mnemonic: mnemonic };
437
+ const encryptedVault = CryptoJS.AES.encrypt(
438
+ JSON.stringify(vault),
439
+ password
440
+ ).toString();
441
+
442
+ await storage.set('vault', encryptedVault);
443
+
444
+ // Use CONSISTENT salts for testing (not random) to prevent password validation mismatches
445
+ const salt = 'test-salt-12345678901234567890123456789012'; // Fixed 32-char salt
446
+ const hash = createHmac('sha512', salt).update(password).digest('hex');
447
+
448
+ await storage.set('vault-keys', {
449
+ hash,
450
+ salt,
451
+ });
452
+ };
453
+
454
+ // Create mock vault state utility function
455
+ global.createMockVaultState = (options = {}) => {
456
+ const {
457
+ activeAccountId = 0,
458
+ activeAccountType = KeyringAccountType.HDAccount,
459
+ networkType = INetworkType.Syscoin,
460
+ chainId,
461
+ } = options;
462
+
463
+ // Derive real addresses from the test seed phrase for consistency
464
+ const testSeedPhrase =
465
+ 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
466
+ const testPassword = 'Asdqwe123!'; // Must match FAKE_PASSWORD from constants
467
+
468
+ let address, xpub, xprv;
469
+ if (networkType === INetworkType.Ethereum) {
470
+ // Derive real EVM address from test seed
471
+ const { HDNode } = jest.requireActual('@ethersproject/hdnode');
472
+ const { getAddressDerivationPath } = jest.requireActual(
473
+ '../../src/utils/derivation-paths'
474
+ );
475
+
476
+ const hdNode = HDNode.fromMnemonic(testSeedPhrase);
477
+ const ethDerivationPath = getAddressDerivationPath(
478
+ 'eth',
479
+ 60,
480
+ 0,
481
+ false,
482
+ activeAccountId
483
+ );
484
+ const derivedAccount = hdNode.derivePath(ethDerivationPath);
485
+
486
+ address = derivedAccount.address;
487
+ xpub = derivedAccount.publicKey;
488
+
489
+ // Encrypt the private key like the real vault does
490
+ const CryptoJS = jest.requireActual('crypto-js');
491
+ const crypto = jest.requireActual('crypto');
492
+ const salt = 'test-salt-12345678901234567890123456789012';
493
+ const sessionPassword = crypto
494
+ .createHmac('sha512', salt)
495
+ .update(testPassword)
496
+ .digest('hex');
497
+ xprv = CryptoJS.AES.encrypt(
498
+ derivedAccount.privateKey,
499
+ sessionPassword
500
+ ).toString();
501
+ } else {
502
+ // For UTXO, use syscoinjs to derive real xpub and address from test seed
503
+ const { getSyscoinSigners } = jest.requireActual('../../src/signers');
504
+ const { getNetworkConfig } = jest.requireActual(
505
+ '@sidhujag/sysweb3-network'
506
+ );
507
+ const CryptoJS = jest.requireActual('crypto-js');
508
+ const crypto = jest.requireActual('crypto');
509
+
510
+ try {
511
+ // Determine slip44 and coin name based on chainId
512
+ const slip44 = chainId === 57 ? 57 : 1; // mainnet = 57, testnet = 1
513
+ const currency = chainId === 57 ? 'SYS' : 'TSYS';
514
+ const coinName = chainId === 57 ? 'Syscoin' : 'Syscoin Testnet'; // Use full coin names from coins.ts
515
+
516
+ // Get network config for proper syscoin parameters
517
+ const networkConfig = getNetworkConfig(slip44, coinName);
518
+
519
+ // Create mock RPC config for syscoinjs
520
+ const mockRpc = {
521
+ formattedNetwork: {
522
+ url:
523
+ chainId === 57
524
+ ? 'https://blockbook.elint.services/'
525
+ : 'https://blockbook-dev.elint.services/',
526
+ slip44,
527
+ currency,
528
+ chainId,
529
+ },
530
+ networkConfig,
531
+ };
532
+
533
+ // Use syscoinjs to create HD signer with proper network parameters
534
+ const { hd } = getSyscoinSigners({
535
+ mnemonic: testSeedPhrase,
536
+ rpc: mockRpc,
537
+ });
538
+
539
+ // Create account at the specified index (synchronous)
540
+ hd.createAccount(84);
541
+ hd.setAccountIndex(activeAccountId);
542
+
543
+ // Get the real xpub and address from syscoinjs
544
+ xpub = hd.getAccountXpub();
545
+ address = hd.createAddress(0, false, 84); // receiving address at index 0
546
+ } catch (error) {
547
+ // Fallback to known working addresses if syscoinjs derivation fails
548
+ console.warn(
549
+ 'Syscoinjs derivation failed, using fallback addresses:',
550
+ error.message
551
+ );
552
+ if (chainId === 57) {
553
+ // Use a known mainnet address format
554
+ address = 'sys1q4kk5wqjwdzxh6zt7hpfj3zwrhv5v5v5ht8fqv8';
555
+ xpub =
556
+ 'zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wgmUn9Q5Vgg2KHJD5YQJpFHxhtQQh3yJiRMLrYjfF5VGN1yPYxkQWxgd6YWBvYcB';
557
+ } else {
558
+ // Use a known testnet address format
559
+ address = 'tsys1qhkd3x4r8p5w2e5n9v3h8j2m4b6c9z7f5g3h2k7';
560
+ xpub =
561
+ 'tpubDDJC8T2bGJkQs6Qu7xRELGF9KNKpfF8nTy6tGNT7BudJw32VhJ7HkF7yGG7LfQ6SFGgM4V4MYWGCE7h4K7JbE7QGJFSD9P5a6f1vNMrDbqZ';
562
+ }
563
+ }
564
+
565
+ // Encrypt a mock private key
566
+ const salt = 'test-salt-12345678901234567890123456789012';
567
+ const sessionPassword = crypto
568
+ .createHmac('sha512', salt)
569
+ .update(testPassword)
570
+ .digest('hex');
571
+ const mockPrivateKey =
572
+ 'L1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef';
573
+ xprv = CryptoJS.AES.encrypt(mockPrivateKey, sessionPassword).toString();
574
+ }
575
+
576
+ // Create mock networks structure
577
+ const networks = {
578
+ syscoin: {
579
+ 57: {
580
+ chainId: 57,
581
+ currency: 'SYS',
582
+ label: 'Syscoin Mainnet',
583
+ url: 'https://blockbook.elint.services/',
584
+ kind: INetworkType.Syscoin,
585
+ explorer: 'https://explorer.syscoin.org/',
586
+ slip44: 57,
587
+ },
588
+ 5700: {
589
+ chainId: 5700,
590
+ currency: 'TSYS',
591
+ label: 'Syscoin Testnet',
592
+ url: 'https://blockbook-dev.elint.services/',
593
+ kind: INetworkType.Syscoin,
594
+ explorer: 'https://explorer-testnet.syscoin.org/',
595
+ slip44: 1,
596
+ },
597
+ },
598
+ ethereum: {
599
+ 1: {
600
+ chainId: 1,
601
+ currency: 'ETH',
602
+ label: 'Ethereum Mainnet',
603
+ url: 'https://rpc.ankr.com/eth',
604
+ kind: INetworkType.Ethereum,
605
+ explorer: 'https://etherscan.io/',
606
+ slip44: 60,
607
+ },
608
+ 57: {
609
+ chainId: 57,
610
+ currency: 'SYS',
611
+ label: 'Syscoin NEVM',
612
+ url: 'https://rpc.syscoin.org',
613
+ kind: INetworkType.Ethereum,
614
+ explorer: 'https://explorer.syscoin.org/',
615
+ slip44: 60,
616
+ },
617
+ 5700: {
618
+ chainId: 5700,
619
+ currency: 'TSYS',
620
+ label: 'Syscoin NEVM Testnet',
621
+ url: 'https://rpc.tanenbaum.io',
622
+ kind: INetworkType.Ethereum,
623
+ explorer: 'https://explorer.tanenbaum.io/',
624
+ slip44: 60,
625
+ },
626
+ 137: {
627
+ chainId: 137,
628
+ currency: 'MATIC',
629
+ label: 'Polygon',
630
+ url: 'https://polygon-rpc.com',
631
+ kind: INetworkType.Ethereum,
632
+ explorer: 'https://polygonscan.com/',
633
+ slip44: 60,
634
+ },
635
+ 80001: {
636
+ chainId: 80001,
637
+ currency: 'MATIC',
638
+ label: 'Mumbai',
639
+ url: 'https://rpc-mumbai.maticvigil.com',
640
+ kind: INetworkType.Ethereum,
641
+ explorer: 'https://mumbai.polygonscan.com/',
642
+ slip44: 60,
643
+ },
644
+ },
645
+ };
646
+
647
+ // Determine the network based on type and chainId
648
+ let activeNetwork;
649
+ if (networkType === INetworkType.Syscoin) {
650
+ const syscoinChainId = chainId || 57; // Default to mainnet
651
+ activeNetwork = networks.syscoin[syscoinChainId];
652
+ } else if (networkType === INetworkType.Ethereum) {
653
+ const ethChainId = chainId || 1; // Default to Ethereum mainnet
654
+ activeNetwork = networks.ethereum[ethChainId];
655
+ } else {
656
+ throw new Error(`Unsupported network type: ${networkType}`);
657
+ }
658
+
659
+ if (!activeNetwork) {
660
+ throw new Error(
661
+ `Network not found for type ${networkType} and chainId ${chainId}`
662
+ );
663
+ }
664
+
665
+ // Create mock accounts structure with generic labels - tests should verify what keyring manager actually produces
666
+ const accounts = {
667
+ [KeyringAccountType.HDAccount]: {
668
+ 0: {
669
+ id: 0,
670
+ address,
671
+ xpub,
672
+ xprv, // Now includes encrypted private key like real vault
673
+ label: `Account 1`, // Generic label - tests should expect what keyring manager actually creates
674
+ balances: { syscoin: 0, ethereum: 0 },
675
+ isImported: false,
676
+ isTrezorWallet: false,
677
+ isLedgerWallet: false,
678
+ assets: { syscoin: [], ethereum: [] },
679
+ },
680
+ },
681
+ [KeyringAccountType.Imported]: {},
682
+ [KeyringAccountType.Trezor]: {},
683
+ [KeyringAccountType.Ledger]: {},
684
+ };
685
+
686
+ return {
687
+ activeAccount: { id: activeAccountId, type: activeAccountType },
688
+ accounts,
689
+ activeNetwork,
690
+ networks,
691
+ isUnlocked: false,
692
+ lastLogin: null,
693
+ };
694
+ };
695
+
696
+ // Default mock vault state (for backward compatibility) - Ethereum mainnet by default
697
+ (global as any).mockVaultState = global.createMockVaultState({
698
+ networkType: INetworkType.Ethereum,
699
+ chainId: 1,
700
+ });
701
+
702
+ // Export setupMocks function for use in test files
703
+ export const setupMocks = () => {
704
+ // Reset any global state
705
+ jest.clearAllMocks();
706
+
707
+ // Don't clear storage here - let the beforeEach/afterEach hooks handle it
708
+ // This prevents clearing vault-keys between keyring creation and password validation
709
+
710
+ // Reset vault data if it exists
711
+ if ((global as any).storedVaultData) {
712
+ (global as any).storedVaultData = null;
713
+ }
714
+ };