@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,409 @@
1
+ import { INetworkType } from '@sidhujag/sysweb3-network';
2
+ import { getAsset } from '@sidhujag/sysweb3-utils';
3
+ import * as syscoinjs from 'syscoinjs-lib';
4
+
5
+ import { KeyringAccountType } from '../../types';
6
+ import { SyscoinTransactions } from '../syscoin';
7
+
8
+ // Mock dependencies
9
+ jest.mock('@sidhujag/sysweb3-utils', () => ({
10
+ getAsset: jest.fn(),
11
+ isBase64: jest.fn().mockReturnValue(true),
12
+ countDecimals: jest.fn().mockReturnValue(8),
13
+ }));
14
+
15
+ jest.mock('syscoinjs-lib', () => ({
16
+ utils: {
17
+ BN: jest.fn().mockImplementation((value) => ({
18
+ toNumber: () => value,
19
+ add: jest.fn().mockReturnThis(),
20
+ sub: jest.fn().mockReturnThis(),
21
+ mul: jest.fn().mockReturnThis(),
22
+ })),
23
+ fetchBackendUTXOS: jest.fn().mockResolvedValue([]),
24
+ sanitizeBlockbookUTXOs: jest.fn().mockReturnValue([]),
25
+ fetchEstimateFee: jest.fn().mockResolvedValue(10000),
26
+ importPsbtFromJson: jest.fn().mockReturnValue({
27
+ extractTransaction: () => ({
28
+ getId: () => 'mock-txid',
29
+ outs: [],
30
+ }),
31
+ inputs: [],
32
+ updateInput: jest.fn(),
33
+ finalizeAllInputs: jest.fn(),
34
+ toBase64: jest.fn().mockReturnValue('mock-signed-psbt'),
35
+ }),
36
+ exportPsbtToJson: jest.fn().mockReturnValue('mock-psbt-json'),
37
+ },
38
+ Psbt: {
39
+ fromBase64: jest.fn().mockReturnValue({
40
+ extractTransaction: () => ({
41
+ getId: () => 'mock-txid',
42
+ outs: [],
43
+ }),
44
+ inputs: [],
45
+ updateInput: jest.fn(),
46
+ finalizeAllInputs: jest.fn(),
47
+ toBase64: jest.fn().mockReturnValue('mock-signed-psbt'),
48
+ }),
49
+ },
50
+ }));
51
+
52
+ jest.mock('syscointx-js', () => ({
53
+ createTransaction: jest.fn().mockResolvedValue({
54
+ inputs: [],
55
+ outputs: [],
56
+ }),
57
+ assetAllocationSend: jest.fn().mockResolvedValue({
58
+ extractTransaction: () => ({
59
+ getId: () => 'mock-token-txid',
60
+ }),
61
+ }),
62
+ }));
63
+
64
+ jest.mock('coinselectsyscoin', () => ({
65
+ utils: {
66
+ transactionBytes: jest.fn().mockReturnValue(250),
67
+ },
68
+ }));
69
+
70
+ describe('SyscoinTransactions', () => {
71
+ let syscoinTransactions: SyscoinTransactions;
72
+ let mockGetSigner: jest.Mock;
73
+ let mockGetState: jest.Mock;
74
+ let mockGetAddress: jest.Mock;
75
+ let mockLedger: any;
76
+ let mockTrezor: any;
77
+
78
+ beforeEach(() => {
79
+ // Reset all mocks
80
+ jest.clearAllMocks();
81
+
82
+ // Mock signers
83
+ mockGetSigner = jest.fn().mockReturnValue({
84
+ hd: {
85
+ Signer: {
86
+ network: 'mainnet',
87
+ },
88
+ },
89
+ main: {
90
+ blockbookURL: 'https://blockbook.test',
91
+ createPSBTFromRes: jest.fn().mockResolvedValue('mock-unsigned-psbt'),
92
+ assetAllocationSend: jest.fn().mockResolvedValue({
93
+ psbt: 'mock-token-psbt',
94
+ }),
95
+ send: jest.fn().mockResolvedValue({
96
+ extractTransaction: () => ({
97
+ getId: () => 'broadcast-txid',
98
+ }),
99
+ }),
100
+ },
101
+ });
102
+
103
+ // Mock state
104
+ mockGetState = jest.fn().mockReturnValue({
105
+ activeAccountId: 0,
106
+ activeAccountType: KeyringAccountType.HDAccount,
107
+ accounts: {
108
+ [KeyringAccountType.HDAccount]: {
109
+ 0: {
110
+ xpub: 'mock-xpub',
111
+ id: 0,
112
+ isTrezorWallet: false,
113
+ isLedgerWallet: false,
114
+ },
115
+ },
116
+ },
117
+ activeNetwork: {
118
+ currency: 'sys',
119
+ chainId: 57,
120
+ kind: INetworkType.Syscoin,
121
+ url: 'https://blockbook.test',
122
+ slip44: 57,
123
+ label: 'Syscoin Mainnet',
124
+ },
125
+ });
126
+
127
+ // Mock address getter
128
+ mockGetAddress = jest.fn().mockResolvedValue('mock-change-address');
129
+
130
+ // Mock Trezor
131
+ mockTrezor = {
132
+ init: jest.fn(),
133
+ convertToTrezorFormat: jest.fn().mockReturnValue('mock-trezor-tx'),
134
+ signUtxoTransaction: jest
135
+ .fn()
136
+ .mockResolvedValue('mock-trezor-signed-psbt'),
137
+ };
138
+
139
+ // Mock Ledger
140
+ mockLedger = {
141
+ ledgerTransport: true,
142
+ ledgerUtxoClient: {
143
+ getMasterFingerprint: jest.fn().mockResolvedValue('1234abcd'),
144
+ signPsbt: jest
145
+ .fn()
146
+ .mockResolvedValue([
147
+ [0, { pubkey: Buffer.from(''), signature: Buffer.from('') }],
148
+ ]),
149
+ },
150
+ connectToLedgerDevice: jest.fn(),
151
+ };
152
+
153
+ // Create instance
154
+ syscoinTransactions = new SyscoinTransactions(
155
+ mockGetSigner,
156
+ mockGetSigner,
157
+ mockGetState,
158
+ mockGetAddress,
159
+ mockLedger,
160
+ mockTrezor
161
+ );
162
+ });
163
+
164
+ describe('getEstimateSysTransactionFee', () => {
165
+ it('should create and sign a native transaction for HD wallet', async () => {
166
+ const result = await syscoinTransactions.getEstimateSysTransactionFee({
167
+ amount: 1,
168
+ receivingAddress: 'sys1qtest',
169
+ feeRate: 0.00001,
170
+ txOptions: { rbf: true },
171
+ });
172
+
173
+ expect(result).toEqual({
174
+ fee: expect.any(Number),
175
+ psbt: expect.any(String),
176
+ });
177
+
178
+ expect(mockGetSigner().main.createPSBTFromRes).toHaveBeenCalled();
179
+ });
180
+
181
+ it('should create and sign a token transaction', async () => {
182
+ (getAsset as jest.Mock).mockResolvedValue({
183
+ assetGuid: '123456',
184
+ decimals: 8,
185
+ });
186
+
187
+ const result = await syscoinTransactions.getEstimateSysTransactionFee({
188
+ amount: 100,
189
+ receivingAddress: 'sys1qtest',
190
+ feeRate: 0.00001,
191
+ token: { guid: '123456', symbol: 'TEST' },
192
+ });
193
+
194
+ expect(result).toEqual({
195
+ fee: expect.any(Number),
196
+ psbt: expect.any(String),
197
+ });
198
+
199
+ expect(mockGetSigner().main.assetAllocationSend).toHaveBeenCalledWith(
200
+ { rbf: true },
201
+ expect.any(Map),
202
+ 'mock-change-address',
203
+ expect.any(Object),
204
+ 'mock-xpub'
205
+ );
206
+ });
207
+
208
+ it('should handle Trezor signing separately', async () => {
209
+ // First get fee estimate (unsigned PSBT)
210
+ const feeResult = await syscoinTransactions.getEstimateSysTransactionFee({
211
+ amount: 1,
212
+ receivingAddress: 'sys1qtest',
213
+ });
214
+
215
+ expect(feeResult.psbt).toBeDefined();
216
+ expect(feeResult.fee).toBeGreaterThan(0);
217
+
218
+ // Then sign separately
219
+ const signedPsbt = await syscoinTransactions.signPSBT({
220
+ psbt: feeResult.psbt,
221
+ isTrezor: true,
222
+ });
223
+
224
+ expect(mockTrezor.init).toHaveBeenCalled();
225
+ expect(mockTrezor.signUtxoTransaction).toHaveBeenCalled();
226
+ expect(signedPsbt).toBe('mock-trezor-signed-psbt');
227
+ });
228
+
229
+ it('should handle Ledger signing separately', async () => {
230
+ mockGetState.mockReturnValue({
231
+ ...mockGetState(),
232
+ accounts: {
233
+ [KeyringAccountType.Ledger]: {
234
+ 0: {
235
+ xpub: 'mock-xpub',
236
+ id: 0,
237
+ isLedgerWallet: true,
238
+ },
239
+ },
240
+ },
241
+ activeAccountType: KeyringAccountType.Ledger,
242
+ });
243
+
244
+ // First get fee estimate (unsigned PSBT)
245
+ const feeResult = await syscoinTransactions.getEstimateSysTransactionFee({
246
+ amount: 1,
247
+ receivingAddress: 'sys1qtest',
248
+ });
249
+
250
+ expect(feeResult.psbt).toBeDefined();
251
+ expect(feeResult.fee).toBeGreaterThan(0);
252
+
253
+ // Then sign separately
254
+ const signedPsbt = await syscoinTransactions.signPSBT({
255
+ psbt: feeResult.psbt,
256
+ isLedger: true,
257
+ });
258
+
259
+ expect(mockLedger.ledgerUtxoClient.signPsbt).toHaveBeenCalled();
260
+ expect(signedPsbt).toBe('mock-signed-psbt');
261
+ });
262
+
263
+ it('should throw error when token is not found', async () => {
264
+ (getAsset as jest.Mock).mockResolvedValue(null);
265
+
266
+ await expect(
267
+ syscoinTransactions.getEstimateSysTransactionFee({
268
+ amount: 100,
269
+ receivingAddress: 'sys1qtest',
270
+ token: { guid: 'invalid', symbol: 'INVALID' },
271
+ })
272
+ ).rejects.toThrow('Failed to create transaction: Token not found');
273
+ });
274
+
275
+ it('should use recommended fee when feeRate not provided', async () => {
276
+ await syscoinTransactions.getEstimateSysTransactionFee({
277
+ amount: 1,
278
+ receivingAddress: 'sys1qtest',
279
+ });
280
+
281
+ expect(syscoinjs.utils.fetchEstimateFee).toHaveBeenCalled();
282
+ });
283
+ });
284
+
285
+ describe('sendTransaction', () => {
286
+ it('should require pre-signed PSBT', async () => {
287
+ await expect(syscoinTransactions.sendTransaction('')).rejects.toThrow(
288
+ 'Pre-signed PSBT is required'
289
+ );
290
+ });
291
+
292
+ it('should send pre-signed PSBT', async () => {
293
+ await syscoinTransactions.sendTransaction('mock-signed-psbt');
294
+
295
+ // Verify the PSBT was sent correctly
296
+ expect(mockGetSigner().main.send).toHaveBeenCalledWith(
297
+ 'mock-signed-psbt'
298
+ );
299
+ });
300
+
301
+ it('should handle JSON PSBTs', async () => {
302
+ const jsonPsbt = JSON.stringify({ test: 'psbt' });
303
+ await syscoinTransactions.sendTransaction(jsonPsbt);
304
+
305
+ expect(mockGetSigner().main.send).toHaveBeenCalledWith({ test: 'psbt' });
306
+ });
307
+ });
308
+
309
+ describe('deprecated methods', () => {
310
+ it('should throw error for confirmCustomTokenSend', async () => {
311
+ await expect(
312
+ (syscoinTransactions as any).confirmCustomTokenSend({})
313
+ ).rejects.toThrow('This method is deprecated');
314
+ });
315
+
316
+ it('should throw error for confirmNativeTokenSend', async () => {
317
+ await expect(
318
+ (syscoinTransactions as any).confirmNativeTokenSend({})
319
+ ).rejects.toThrow('This method is deprecated');
320
+ });
321
+ });
322
+
323
+ describe('edge cases', () => {
324
+ it('should handle signing errors gracefully', async () => {
325
+ const mockError = new Error('Device disconnected');
326
+ mockGetSigner.mockReturnValue({
327
+ ...mockGetSigner(),
328
+ hd: {
329
+ sign: jest.fn().mockRejectedValue(mockError),
330
+ },
331
+ });
332
+
333
+ await expect(
334
+ syscoinTransactions.getEstimateSysTransactionFee({
335
+ amount: 1,
336
+ receivingAddress: 'sys1qtest',
337
+ })
338
+ ).rejects.toThrow('Failed to sign transaction');
339
+ });
340
+
341
+ it('should handle network errors', async () => {
342
+ syscoinjs.utils.fetchBackendUTXOS = jest
343
+ .fn()
344
+ .mockRejectedValue(new Error('Network error'));
345
+
346
+ await expect(
347
+ syscoinTransactions.getEstimateSysTransactionFee({
348
+ amount: 1,
349
+ receivingAddress: 'sys1qtest',
350
+ })
351
+ ).rejects.toThrow('Failed to create transaction');
352
+ });
353
+
354
+ it('should handle Ledger not connected', async () => {
355
+ mockLedger.ledgerTransport = null;
356
+
357
+ const { psbt } = await syscoinTransactions.getEstimateSysTransactionFee({
358
+ amount: 1,
359
+ receivingAddress: 'sys1qtest',
360
+ });
361
+
362
+ // Test signing which would trigger Ledger connection
363
+ await syscoinTransactions.signPSBT({
364
+ psbt,
365
+ isLedger: true,
366
+ });
367
+
368
+ expect(mockLedger.connectToLedgerDevice).toHaveBeenCalled();
369
+ });
370
+ });
371
+
372
+ describe('PSBT flow integration', () => {
373
+ it('should maintain PSBT integrity through sign and send', async () => {
374
+ // Create and sign
375
+ const { psbt } = await syscoinTransactions.getEstimateSysTransactionFee({
376
+ amount: 1,
377
+ receivingAddress: 'sys1qtest',
378
+ feeRate: 0.00001,
379
+ });
380
+
381
+ // Send
382
+ const result = await syscoinTransactions.sendTransaction(psbt);
383
+
384
+ expect(result.txid).toBe('broadcast-txid');
385
+ });
386
+
387
+ it('should handle token transactions end-to-end', async () => {
388
+ (getAsset as jest.Mock).mockResolvedValue({
389
+ assetGuid: '123456',
390
+ decimals: 8,
391
+ });
392
+
393
+ // Create and sign token transaction
394
+ const { psbt, fee } =
395
+ await syscoinTransactions.getEstimateSysTransactionFee({
396
+ amount: 100,
397
+ receivingAddress: 'sys1qtest',
398
+ token: { guid: '123456', symbol: 'TEST' },
399
+ });
400
+
401
+ expect(fee).toBeGreaterThan(0);
402
+
403
+ // Send token transaction
404
+ const result = await syscoinTransactions.sendTransaction(psbt);
405
+
406
+ expect(result.txid).toBe('broadcast-txid');
407
+ });
408
+ });
409
+ });