@sidhujag/sysweb3-keyring 1.0.491

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 (104) hide show
  1. package/README.md +201 -0
  2. package/cjs/errorUtils.js +75 -0
  3. package/cjs/errorUtils.js.map +1 -0
  4. package/cjs/hardware-wallet-manager.js +462 -0
  5. package/cjs/hardware-wallet-manager.js.map +1 -0
  6. package/cjs/index.js +31 -0
  7. package/cjs/index.js.map +1 -0
  8. package/cjs/initial-state.js +105 -0
  9. package/cjs/initial-state.js.map +1 -0
  10. package/cjs/keyring-manager.js +1687 -0
  11. package/cjs/keyring-manager.js.map +1 -0
  12. package/cjs/ledger/bitcoin_client/index.js +47 -0
  13. package/cjs/ledger/bitcoin_client/index.js.map +1 -0
  14. package/cjs/ledger/bitcoin_client/lib/appClient.js +408 -0
  15. package/cjs/ledger/bitcoin_client/lib/appClient.js.map +1 -0
  16. package/cjs/ledger/bitcoin_client/lib/bip32.js +61 -0
  17. package/cjs/ledger/bitcoin_client/lib/bip32.js.map +1 -0
  18. package/cjs/ledger/bitcoin_client/lib/buffertools.js +126 -0
  19. package/cjs/ledger/bitcoin_client/lib/buffertools.js.map +1 -0
  20. package/cjs/ledger/bitcoin_client/lib/clientCommands.js +270 -0
  21. package/cjs/ledger/bitcoin_client/lib/clientCommands.js.map +1 -0
  22. package/cjs/ledger/bitcoin_client/lib/constants.js +16 -0
  23. package/cjs/ledger/bitcoin_client/lib/constants.js.map +1 -0
  24. package/cjs/ledger/bitcoin_client/lib/merkelizedPsbt.js +54 -0
  25. package/cjs/ledger/bitcoin_client/lib/merkelizedPsbt.js.map +1 -0
  26. package/cjs/ledger/bitcoin_client/lib/merkle.js +109 -0
  27. package/cjs/ledger/bitcoin_client/lib/merkle.js.map +1 -0
  28. package/cjs/ledger/bitcoin_client/lib/merkleMap.js +46 -0
  29. package/cjs/ledger/bitcoin_client/lib/merkleMap.js.map +1 -0
  30. package/cjs/ledger/bitcoin_client/lib/policy.js +66 -0
  31. package/cjs/ledger/bitcoin_client/lib/policy.js.map +1 -0
  32. package/cjs/ledger/bitcoin_client/lib/psbtv2.js +640 -0
  33. package/cjs/ledger/bitcoin_client/lib/psbtv2.js.map +1 -0
  34. package/cjs/ledger/bitcoin_client/lib/varint.js +113 -0
  35. package/cjs/ledger/bitcoin_client/lib/varint.js.map +1 -0
  36. package/cjs/ledger/consts.js +7 -0
  37. package/cjs/ledger/consts.js.map +1 -0
  38. package/cjs/ledger/index.js +319 -0
  39. package/cjs/ledger/index.js.map +1 -0
  40. package/cjs/ledger/types.js +3 -0
  41. package/cjs/ledger/types.js.map +1 -0
  42. package/cjs/network-utils.js +76 -0
  43. package/cjs/network-utils.js.map +1 -0
  44. package/cjs/providers.js +270 -0
  45. package/cjs/providers.js.map +1 -0
  46. package/cjs/signers.js +64 -0
  47. package/cjs/signers.js.map +1 -0
  48. package/cjs/storage.js +30 -0
  49. package/cjs/storage.js.map +1 -0
  50. package/cjs/transactions/__tests__/integration.test.js +237 -0
  51. package/cjs/transactions/__tests__/integration.test.js.map +1 -0
  52. package/cjs/transactions/__tests__/syscoin.test.js +361 -0
  53. package/cjs/transactions/__tests__/syscoin.test.js.map +1 -0
  54. package/cjs/transactions/ethereum.js +1577 -0
  55. package/cjs/transactions/ethereum.js.map +1 -0
  56. package/cjs/transactions/index.js +19 -0
  57. package/cjs/transactions/index.js.map +1 -0
  58. package/cjs/transactions/syscoin.js +328 -0
  59. package/cjs/transactions/syscoin.js.map +1 -0
  60. package/cjs/trezor/index.js +718 -0
  61. package/cjs/trezor/index.js.map +1 -0
  62. package/cjs/types.js +12 -0
  63. package/cjs/types.js.map +1 -0
  64. package/cjs/utils/derivation-paths.js +99 -0
  65. package/cjs/utils/derivation-paths.js.map +1 -0
  66. package/cjs/utils/psbt.js +60 -0
  67. package/cjs/utils/psbt.js.map +1 -0
  68. package/cjs/utils.js +130 -0
  69. package/cjs/utils.js.map +1 -0
  70. package/package.json +46 -0
  71. package/types/errorUtils.d.ts +1 -0
  72. package/types/hardware-wallet-manager.d.ts +110 -0
  73. package/types/index.d.ts +12 -0
  74. package/types/initial-state.d.ts +79 -0
  75. package/types/keyring-manager.d.ts +184 -0
  76. package/types/ledger/bitcoin_client/index.d.ts +5 -0
  77. package/types/ledger/bitcoin_client/lib/appClient.d.ts +106 -0
  78. package/types/ledger/bitcoin_client/lib/bip32.d.ts +11 -0
  79. package/types/ledger/bitcoin_client/lib/buffertools.d.ts +28 -0
  80. package/types/ledger/bitcoin_client/lib/clientCommands.d.ts +77 -0
  81. package/types/ledger/bitcoin_client/lib/constants.d.ts +12 -0
  82. package/types/ledger/bitcoin_client/lib/merkelizedPsbt.d.ts +24 -0
  83. package/types/ledger/bitcoin_client/lib/merkle.d.ts +32 -0
  84. package/types/ledger/bitcoin_client/lib/merkleMap.d.ts +23 -0
  85. package/types/ledger/bitcoin_client/lib/policy.d.ts +36 -0
  86. package/types/ledger/bitcoin_client/lib/psbtv2.d.ts +167 -0
  87. package/types/ledger/bitcoin_client/lib/varint.d.ts +23 -0
  88. package/types/ledger/consts.d.ts +3 -0
  89. package/types/ledger/index.d.ts +51 -0
  90. package/types/ledger/types.d.ts +48 -0
  91. package/types/network-utils.d.ts +14 -0
  92. package/types/providers.d.ts +47 -0
  93. package/types/signers.d.ts +95 -0
  94. package/types/storage.d.ts +2 -0
  95. package/types/transactions/__tests__/integration.test.d.ts +1 -0
  96. package/types/transactions/__tests__/syscoin.test.d.ts +1 -0
  97. package/types/transactions/ethereum.d.ts +80 -0
  98. package/types/transactions/index.d.ts +2 -0
  99. package/types/transactions/syscoin.d.ts +61 -0
  100. package/types/trezor/index.d.ts +170 -0
  101. package/types/types.d.ts +294 -0
  102. package/types/utils/derivation-paths.d.ts +35 -0
  103. package/types/utils/psbt.d.ts +17 -0
  104. package/types/utils.d.ts +4 -0
@@ -0,0 +1,718 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.TrezorKeyring = void 0;
40
+ /* eslint-disable camelcase */
41
+ const connect_webextension_1 = __importStar(require("@trezor/connect-webextension"));
42
+ const utxo_lib_1 = require("@trezor/utxo-lib");
43
+ const bitcoin_ops_1 = __importDefault(require("bitcoin-ops"));
44
+ const bitcoinjs_lib_1 = require("bitcoinjs-lib");
45
+ const buffer_1 = require("buffer");
46
+ const eth_sig_util_1 = require("eth-sig-util");
47
+ const ethereumjs_util_1 = require("ethereumjs-util");
48
+ const hardware_wallet_manager_1 = require("../hardware-wallet-manager");
49
+ const derivation_paths_1 = require("../utils/derivation-paths");
50
+ const { p2wsh } = bitcoinjs_lib_1.payments;
51
+ const { decompile } = bitcoinjs_lib_1.script;
52
+ const { fromBase58Check, fromBech32 } = utxo_lib_1.address;
53
+ const initialHDPath = `m/44'/60'/0'/0/0`;
54
+ const DELAY_BETWEEN_POPUPS = 2000; // Increased from 1000ms to 2000ms for more reliable operation
55
+ class TrezorKeyring {
56
+ constructor(getSyscoinSigner) {
57
+ this.hdPath = initialHDPath;
58
+ this.paths = {};
59
+ this.initialized = false;
60
+ this._transformTypedData = (data, metamask_v4_compat) => {
61
+ if (!metamask_v4_compat) {
62
+ throw new Error('Trezor: Only version 4 of typed data signing is supported');
63
+ }
64
+ const { types, primaryType, domain, message } = this._sanitizeData(data);
65
+ const domainSeparatorHash = eth_sig_util_1.TypedDataUtils.hashStruct('EIP712Domain', this._sanitizeData(domain), types, true).toString('hex');
66
+ let messageHash = null;
67
+ if (primaryType !== 'EIP712Domain') {
68
+ messageHash = eth_sig_util_1.TypedDataUtils.hashStruct(primaryType, this._sanitizeData(message), types, true).toString('hex');
69
+ }
70
+ return {
71
+ domain_separator_hash: domainSeparatorHash,
72
+ message_hash: messageHash,
73
+ ...data,
74
+ };
75
+ };
76
+ this.publicKey = buffer_1.Buffer.from('', 'hex');
77
+ this.chainCode = buffer_1.Buffer.from('', 'hex');
78
+ this.hdPath = '';
79
+ this.paths = {};
80
+ this.getSigner = getSyscoinSigner;
81
+ this.hardwareWalletManager = new hardware_wallet_manager_1.HardwareWalletManager();
82
+ // Set up event listeners
83
+ this.hardwareWalletManager.on('connected', ({ type }) => {
84
+ if (type === hardware_wallet_manager_1.HardwareWalletType.TREZOR) {
85
+ console.log('Trezor connected');
86
+ this.initialized = true;
87
+ }
88
+ });
89
+ this.hardwareWalletManager.on('disconnected', ({ type }) => {
90
+ if (type === hardware_wallet_manager_1.HardwareWalletType.TREZOR) {
91
+ console.log('Trezor disconnected');
92
+ this.initialized = false;
93
+ }
94
+ });
95
+ connect_webextension_1.default.on(connect_webextension_1.DEVICE_EVENT, (event) => {
96
+ if (event.payload.features) {
97
+ this.model = event.payload.features.model;
98
+ }
99
+ });
100
+ }
101
+ /**
102
+ * Initialize Trezor script.
103
+ */
104
+ async init() {
105
+ if (this.initialized) {
106
+ return true;
107
+ }
108
+ // Add a small delay to ensure Chrome extension context is ready
109
+ // This helps prevent "waiting for handshake" errors
110
+ await new Promise((resolve) => setTimeout(resolve, 100));
111
+ const result = await this.hardwareWalletManager.initializeTrezor();
112
+ if (result) {
113
+ this.initialized = true;
114
+ }
115
+ return result;
116
+ }
117
+ /**
118
+ * Execute operation with automatic retry
119
+ */
120
+ async executeWithRetry(operation, operationName) {
121
+ // Ensure initialization first
122
+ if (!this.initialized) {
123
+ const initResult = await this.init();
124
+ if (!initResult) {
125
+ throw new Error('Failed to initialize Trezor');
126
+ }
127
+ }
128
+ // For Trezor operations, use reduced retry config to prevent popup spam
129
+ const trezorRetryConfig = {
130
+ maxRetries: 1, // Only retry once
131
+ baseDelay: 1000,
132
+ maxDelay: 5000,
133
+ backoffMultiplier: 2,
134
+ };
135
+ // Use hardware wallet manager's retry mechanism with custom config
136
+ return this.hardwareWalletManager
137
+ .retryOperation(operation, operationName, trezorRetryConfig)
138
+ .catch((error) => {
139
+ // Clean up Trezor state on failure
140
+ if (error.message?.includes('Popup closed') ||
141
+ error.message?.includes('cancelled') ||
142
+ error.message?.includes('denied')) {
143
+ this.initialized = false;
144
+ // Dispose Trezor connection to clean up
145
+ try {
146
+ connect_webextension_1.default.dispose();
147
+ }
148
+ catch (disposeError) {
149
+ console.log('Failed to dispose Trezor on error:', disposeError);
150
+ }
151
+ }
152
+ throw error;
153
+ });
154
+ }
155
+ /**
156
+ * This return account info based in params provided.
157
+ *
158
+ * @param coin - network symbol. Example: eth, sys, btc
159
+ * @param slip44 - network slip44 number
160
+ * @param hdPath - path derivation. Example: m/84'/57'/0'
161
+ * @param index - index of account for path derivation
162
+ * @returns derivated account info or error
163
+ */
164
+ async getAccountInfo({ coin, slip44, hdPath, index, }) {
165
+ return this.executeWithRetry(async () => {
166
+ // Use dynamic path generation instead of hardcoded switch
167
+ this.setHdPath(coin, index || 0, slip44);
168
+ if (hdPath)
169
+ this.hdPath = hdPath;
170
+ // For EVM networks, getAccountInfo is not supported
171
+ // We need to use getAddress instead
172
+ if (slip44 === 60) {
173
+ const addressResponse = await connect_webextension_1.default.ethereumGetAddress({
174
+ path: this.hdPath,
175
+ showOnTrezor: false,
176
+ });
177
+ if (!addressResponse.success) {
178
+ throw new Error(addressResponse.payload.error || 'Failed to get EVM address');
179
+ }
180
+ // Return a compatible AccountInfo structure
181
+ return {
182
+ descriptor: addressResponse.payload.address,
183
+ balance: '0', // Balance is fetched separately for EVM
184
+ empty: true,
185
+ history: {
186
+ total: 0,
187
+ unconfirmed: 0,
188
+ },
189
+ };
190
+ }
191
+ // For UTXO networks, use the standard getAccountInfo
192
+ const response = await connect_webextension_1.default.getAccountInfo({
193
+ coin,
194
+ path: this.hdPath,
195
+ });
196
+ if (response.success) {
197
+ return response.payload;
198
+ }
199
+ throw new Error(response.payload.error);
200
+ }, 'getAccountInfo');
201
+ }
202
+ /**
203
+ * Gets the model, if known.
204
+ * This may be `undefined` if the model hasn't been loaded yet.
205
+ *
206
+ * @returns
207
+ */
208
+ getModel() {
209
+ return this.model;
210
+ }
211
+ /**
212
+ * This removes the Trezor Connect iframe from the DOM
213
+ *
214
+ * @returns void
215
+ */
216
+ dispose() {
217
+ try {
218
+ connect_webextension_1.default.dispose();
219
+ this.initialized = false;
220
+ // Clear any cached data
221
+ this.publicKey = buffer_1.Buffer.from('', 'hex');
222
+ this.chainCode = buffer_1.Buffer.from('', 'hex');
223
+ this.hdPath = '';
224
+ this.paths = {};
225
+ }
226
+ catch (error) {
227
+ console.log('Error disposing Trezor:', error);
228
+ }
229
+ }
230
+ /**
231
+ * This verify if message is valid or not.
232
+ *
233
+ * @param coin - network symbol. Example: eth, sys, btc
234
+ * @param address - account address that signed message
235
+ * @param message - message to be verified. Example: 'Test message'
236
+ * @param signature - signature received in sign method. Example: I6BrpivjCwZmScZ6BMAHWGQPo+JjX2kzKXU5LcGVfEgvFb2VfJuKo3g6eSQcykQZiILoWNUDn5rDHkwJg3EcvuY=
237
+ * @returns derivated account info or error
238
+ */
239
+ async verifyMessage({ coin, address, message, signature, }) {
240
+ return this.executeWithRetry(async () => {
241
+ let method = '';
242
+ switch (coin) {
243
+ case 'eth':
244
+ method = 'ethereumVerifyMessage';
245
+ break;
246
+ default:
247
+ method = 'verifyMessage';
248
+ }
249
+ // @ts-ignore
250
+ const { success, payload } = await connect_webextension_1.default[method]({
251
+ coin,
252
+ address,
253
+ message,
254
+ signature,
255
+ });
256
+ if (success) {
257
+ return { success, payload };
258
+ }
259
+ throw new Error(payload.error);
260
+ }, 'verifyMessage');
261
+ }
262
+ /**
263
+ * This return account public key.
264
+ *
265
+ * @param coin - network symbol. Example: eth, sys, btc
266
+ * @param slip44 - network slip44 number
267
+ * @param hdPath - path derivation. Example: m/44'/57'/0'/0/0
268
+ * @returns publicKey and chainCode
269
+ */
270
+ async getPublicKey({ coin, slip44, hdPath, index, }) {
271
+ this.setHdPath(coin, index || 0, slip44);
272
+ if (hdPath)
273
+ this.hdPath = hdPath;
274
+ await new Promise((resolve) => setTimeout(resolve, DELAY_BETWEEN_POPUPS));
275
+ try {
276
+ // For EVM networks, use ethereumGetPublicKey
277
+ if (slip44 === 60) {
278
+ const { success, payload } = await connect_webextension_1.default.ethereumGetPublicKey({
279
+ path: this.hdPath,
280
+ showOnTrezor: false,
281
+ });
282
+ if (success) {
283
+ const { publicKey } = payload;
284
+ // For Ethereum, we don't get chainCode from ethereumGetPublicKey
285
+ this.publicKey = buffer_1.Buffer.from(publicKey, 'hex');
286
+ return {
287
+ publicKey: `0x${publicKey}`,
288
+ chainCode: '', // Ethereum doesn't use chainCode in the same way
289
+ };
290
+ }
291
+ return { success: false, payload };
292
+ }
293
+ // For UTXO networks, use standard getPublicKey
294
+ const { success, payload } = await connect_webextension_1.default.getPublicKey({
295
+ coin: coin,
296
+ path: this.hdPath,
297
+ });
298
+ if (success) {
299
+ const { publicKey, chainCode } = payload;
300
+ this.publicKey = buffer_1.Buffer.from(publicKey, 'hex');
301
+ this.chainCode = buffer_1.Buffer.from(chainCode, 'hex');
302
+ return {
303
+ publicKey: `0x${this.publicKey.toString('hex')}`,
304
+ chainCode: `0x${this.chainCode.toString('hex')}`,
305
+ };
306
+ }
307
+ return { success: false, payload };
308
+ }
309
+ catch (error) {
310
+ return error;
311
+ }
312
+ }
313
+ range(n) {
314
+ return [...Array(n).keys()];
315
+ }
316
+ /**
317
+ * This sign UTXO tx.
318
+ *
319
+ * @param coin - network symbol. Example: eth, sys, btc
320
+ * @param inputs - utxo transaction inputs
321
+ * @param outputs - utxo transaction outputs
322
+ * @returns signature object
323
+ */
324
+ async signUtxoTransaction(utxoTransaction, psbt) {
325
+ return this.executeWithRetry(async () => {
326
+ const { payload, success } = await connect_webextension_1.default.signTransaction(utxoTransaction);
327
+ if (success) {
328
+ const tx = bitcoinjs_lib_1.Transaction.fromHex(payload.serializedTx);
329
+ for (const i of this.range(psbt.data.inputs.length)) {
330
+ if (tx.ins[i].witness == null) {
331
+ throw new Error('Please move your funds to a Segwit address: https://wiki.trezor.io/Account');
332
+ }
333
+ const partialSig = [
334
+ {
335
+ pubkey: tx.ins[i].witness[1],
336
+ signature: tx.ins[i].witness[0],
337
+ },
338
+ ];
339
+ psbt.updateInput(i, { partialSig });
340
+ }
341
+ try {
342
+ if (psbt.validateSignaturesOfAllInputs()) {
343
+ psbt.finalizeAllInputs();
344
+ }
345
+ }
346
+ catch (err) {
347
+ console.log(err);
348
+ }
349
+ return psbt;
350
+ }
351
+ else {
352
+ throw new Error('Trezor sign failed: ' + payload.error);
353
+ }
354
+ }, 'signUtxoTransaction');
355
+ }
356
+ setHdPath(coin, accountIndex, slip44) {
357
+ if ((0, derivation_paths_1.isEvmCoin)(coin, slip44)) {
358
+ // For EVM, the "accountIndex" parameter is actually used as the address index
359
+ // EVM typically uses account 0, and different addresses are at different address indices
360
+ this.hdPath = (0, derivation_paths_1.getAddressDerivationPath)(coin, slip44, 0, // account is always 0 for EVM
361
+ false, // not a change address
362
+ accountIndex // this is actually the address index for EVM
363
+ );
364
+ }
365
+ else {
366
+ // For UTXO, use account-level derivation path
367
+ this.hdPath = (0, derivation_paths_1.getAccountDerivationPath)(coin, slip44, accountIndex);
368
+ }
369
+ }
370
+ convertToAddressNFormat(path) {
371
+ const pathArray = path.replace(/'/g, '').split('/');
372
+ pathArray.shift();
373
+ const addressN = [];
374
+ for (const index in pathArray) {
375
+ if (Number(index) <= 2 && Number(index) >= 0) {
376
+ addressN[Number(index)] = Number(pathArray[index]) | 0x80000000;
377
+ }
378
+ else {
379
+ addressN[Number(index)] = Number(pathArray[index]);
380
+ }
381
+ }
382
+ return addressN;
383
+ }
384
+ isScriptHash(address, networkInfo) {
385
+ if (!this.isBech32(address)) {
386
+ const decoded = fromBase58Check(address);
387
+ if (decoded.version === networkInfo.pubKeyHash) {
388
+ return false;
389
+ }
390
+ if (decoded.version === networkInfo.scriptHash) {
391
+ return true;
392
+ }
393
+ }
394
+ else {
395
+ const decoded = fromBech32(address);
396
+ if (decoded.data.length === 20) {
397
+ return false;
398
+ }
399
+ if (decoded.data.length === 32) {
400
+ return true;
401
+ }
402
+ }
403
+ throw new Error('isScriptHash: Unknown address type');
404
+ }
405
+ isPaymentFactory(payment) {
406
+ return (script) => {
407
+ try {
408
+ payment({ output: script });
409
+ return true;
410
+ }
411
+ catch (err) {
412
+ return false;
413
+ }
414
+ };
415
+ }
416
+ isBech32(address) {
417
+ try {
418
+ fromBech32(address);
419
+ return true;
420
+ }
421
+ catch (e) {
422
+ return false;
423
+ }
424
+ }
425
+ isP2WSHScript(script) {
426
+ this.isPaymentFactory(p2wsh)(script);
427
+ return false;
428
+ }
429
+ convertToTrezorFormat({ psbt, pathIn, coin }) {
430
+ const { hd } = this.getSigner();
431
+ const trezortx = {};
432
+ trezortx.coin = coin;
433
+ trezortx.version = psbt.version;
434
+ trezortx.inputs = [];
435
+ trezortx.outputs = [];
436
+ for (let i = 0; i < psbt.txInputs.length; i++) {
437
+ const scriptTypes = psbt.getInputType(i);
438
+ const input = psbt.txInputs[i];
439
+ const inputItem = {};
440
+ inputItem.prev_index = input.index;
441
+ inputItem.prev_hash = input.hash.reverse().toString('hex');
442
+ if (input.sequence)
443
+ inputItem.sequence = input.sequence;
444
+ const dataInput = psbt.data.inputs[i];
445
+ let path = '';
446
+ if (pathIn ||
447
+ (dataInput.unknownKeyVals &&
448
+ dataInput.unknownKeyVals.length > 1 &&
449
+ dataInput.unknownKeyVals[1].key.equals(buffer_1.Buffer.from('path')) &&
450
+ (!dataInput.bip32Derivation ||
451
+ dataInput.bip32Derivation.length === 0))) {
452
+ path = pathIn || dataInput.unknownKeyVals[1].value.toString();
453
+ inputItem.address_n = this.convertToAddressNFormat(path);
454
+ }
455
+ switch (scriptTypes) {
456
+ case 'multisig':
457
+ inputItem.script_type = 'SPENDMULTISIG';
458
+ break;
459
+ case 'witnesspubkeyhash':
460
+ inputItem.script_type = 'SPENDWITNESS';
461
+ break;
462
+ default:
463
+ inputItem.script_type = this.isP2WSHScript(psbt.data.inputs[i].witnessUtxo.script
464
+ ? psbt.data.inputs[i].witnessUtxo.script
465
+ : '')
466
+ ? 'SPENDP2SHWITNESS'
467
+ : 'SPENDADDRESS';
468
+ break;
469
+ }
470
+ trezortx.inputs.push(inputItem);
471
+ }
472
+ for (let i = 0; i < psbt.txOutputs.length; i++) {
473
+ const output = psbt.txOutputs[i];
474
+ const outputItem = {};
475
+ const chunks = decompile(output.script);
476
+ outputItem.amount = output.value.toString();
477
+ if (chunks && chunks[0] === bitcoin_ops_1.default.OP_RETURN) {
478
+ outputItem.script_type = 'PAYTOOPRETURN';
479
+ // @ts-ignore
480
+ outputItem.op_return_data = chunks[1].toString('hex');
481
+ }
482
+ else {
483
+ if (output && this.isBech32(output.address)) {
484
+ if (output.script.length === 34 &&
485
+ output.script[0] === 0 &&
486
+ output.script[1] === 0x20) {
487
+ outputItem.script_type = 'PAYTOP2SHWITNESS';
488
+ }
489
+ else {
490
+ outputItem.script_type = 'PAYTOWITNESS';
491
+ }
492
+ }
493
+ else {
494
+ outputItem.script_type = this.isScriptHash(output.address, hd.Signer.network)
495
+ ? 'PAYTOSCRIPTHASH'
496
+ : 'PAYTOADDRESS';
497
+ }
498
+ if (output.address)
499
+ outputItem.address = output.address;
500
+ }
501
+ trezortx.outputs.push(outputItem);
502
+ }
503
+ return trezortx;
504
+ }
505
+ /**
506
+ * This sign EVM tx.
507
+ *
508
+ * @param index - index of account for path derivation
509
+ * @param tx - ethereum tx object
510
+ * @returns signature object
511
+ */
512
+ async signEthTransaction({ tx, index, coin, slip44, }) {
513
+ return this.executeWithRetry(async () => {
514
+ // Wait between popups
515
+ await new Promise((resolve) => setTimeout(resolve, DELAY_BETWEEN_POPUPS));
516
+ // Use dynamic path generation based on actual network parameters
517
+ this.setHdPath(coin, Number(index) || 0, slip44);
518
+ const response = await connect_webextension_1.default.ethereumSignTransaction({
519
+ path: this.hdPath,
520
+ transaction: tx,
521
+ });
522
+ if (response.success) {
523
+ return response;
524
+ }
525
+ throw new Error(response.payload.error);
526
+ }, 'signEthTransaction');
527
+ }
528
+ /**
529
+ * This sign message.
530
+ *
531
+ * @param coin - network symbol. Example: eth, sys, btc
532
+ * @param slip44 - network slip44 number
533
+ * @param message - message to be signed. Example: 'Test message'
534
+ * @param index - index of account for path derivation
535
+ * @returns signature object
536
+ */
537
+ async signMessage({ index, message, coin, slip44, address, }) {
538
+ return this.executeWithRetry(async () => {
539
+ // Wait between popups
540
+ await new Promise((resolve) => setTimeout(resolve, DELAY_BETWEEN_POPUPS));
541
+ if ((0, derivation_paths_1.isEvmCoin)(coin, slip44) && `${index ? index : 0}` && message) {
542
+ return this._signEthPersonalMessage(Number(index), message, address);
543
+ }
544
+ return this._signUtxoPersonalMessage({ coin, index, slip44, message });
545
+ }, 'signMessage');
546
+ }
547
+ async _signUtxoPersonalMessage({ coin, index, slip44, message, }) {
548
+ try {
549
+ // Use dynamic path generation instead of hardcoded switch
550
+ this.setHdPath(coin, index || 0, slip44);
551
+ const { success, payload } = await connect_webextension_1.default.signMessage({
552
+ path: this.hdPath,
553
+ coin: coin,
554
+ message: message,
555
+ });
556
+ if (success) {
557
+ return { success, payload };
558
+ }
559
+ return { success: false, payload };
560
+ }
561
+ catch (error) {
562
+ return { error };
563
+ }
564
+ }
565
+ // For personal_sign, we need to prefix the message:
566
+ async _signEthPersonalMessage(index, message, address) {
567
+ return new Promise((resolve, reject) => {
568
+ setTimeout(async () => {
569
+ try {
570
+ this.setHdPath('eth', index, 60);
571
+ connect_webextension_1.default.ethereumSignMessage({
572
+ path: this.hdPath,
573
+ message: (0, ethereumjs_util_1.stripHexPrefix)(message),
574
+ hex: true,
575
+ })
576
+ .then((response) => {
577
+ if (response.success) {
578
+ if (address &&
579
+ response.payload.address.toLowerCase() !==
580
+ address.toLowerCase()) {
581
+ reject(new Error('signature doesnt match the right address'));
582
+ }
583
+ const signature = `0x${response.payload.signature}`;
584
+ resolve({ signature, success: true });
585
+ }
586
+ else {
587
+ reject(
588
+ // @ts-ignore
589
+ new Error(response.payload.error || 'Unknown error'));
590
+ }
591
+ })
592
+ .catch((e) => {
593
+ reject(new Error(e.toString() || 'Unknown error'));
594
+ });
595
+ }
596
+ catch (error) {
597
+ reject(error);
598
+ }
599
+ // This is necessary to avoid popup collision
600
+ // between the unlock & sign trezor popups
601
+ }, DELAY_BETWEEN_POPUPS);
602
+ });
603
+ }
604
+ _sanitizeData(data) {
605
+ switch (Object.prototype.toString.call(data)) {
606
+ case '[object Object]': {
607
+ const entries = Object.keys(data).map((k) => [
608
+ k,
609
+ this._sanitizeData(data[k]),
610
+ ]);
611
+ return Object.fromEntries(entries);
612
+ }
613
+ case '[object Array]':
614
+ return data.map((v) => this._sanitizeData(v));
615
+ case '[object BigInt]':
616
+ return data.toString();
617
+ default:
618
+ return data;
619
+ }
620
+ }
621
+ /**
622
+ * EIP-712 Sign Typed Data
623
+ */
624
+ async signTypedData({ version, address, data, index, }) {
625
+ return this.executeWithRetry(async () => {
626
+ // Wait between popups
627
+ await new Promise((resolve) => setTimeout(resolve, DELAY_BETWEEN_POPUPS));
628
+ this.setHdPath('eth', index, 60);
629
+ // Use dynamic path generation for ETH (EVM) - typed data is only used for EVM
630
+ const dataWithHashes = this._transformTypedData(data, version === 'V4');
631
+ // set default values for signTypedData
632
+ // Trezor is stricter than @metamask/eth-sig-util in what it accepts
633
+ const { types, message = {}, domain = {}, primaryType,
634
+ // snake_case since Trezor uses Protobuf naming conventions here
635
+ domain_separator_hash, // eslint-disable-line camelcase
636
+ message_hash, // eslint-disable-line camelcase
637
+ } = dataWithHashes;
638
+ // This is necessary to avoid popup collision
639
+ // between the unlock & sign trezor popups
640
+ const response = await connect_webextension_1.default.ethereumSignTypedData({
641
+ path: this.hdPath,
642
+ data: {
643
+ types: {
644
+ ...types,
645
+ EIP712Domain: types.EIP712Domain ? types.EIP712Domain : [],
646
+ },
647
+ message,
648
+ domain,
649
+ primaryType: primaryType,
650
+ },
651
+ metamask_v4_compat: true,
652
+ // Trezor 1 only supports blindly signing hashes
653
+ domain_separator_hash,
654
+ message_hash: message_hash ? message_hash : '',
655
+ });
656
+ if (response.success) {
657
+ if (address !== response.payload.address) {
658
+ throw new Error('signature doesnt match the right address');
659
+ }
660
+ return response.payload.signature;
661
+ }
662
+ // @ts-ignore
663
+ throw new Error(response.payload.error || 'Unknown error');
664
+ }, 'signTypedData');
665
+ }
666
+ /**
667
+ * Verify UTXO address by displaying it on the Trezor device
668
+ * @param accountIndex - The account index
669
+ * @param currency - The currency (coin type)
670
+ * @param slip44 - The slip44 value for the network
671
+ * @returns The verified address
672
+ */
673
+ async verifyUtxoAddress(accountIndex, currency, slip44) {
674
+ return this.executeWithRetry(async () => {
675
+ const fullPath = (0, derivation_paths_1.getAddressDerivationPath)(currency, slip44, accountIndex, false, // Not a change address
676
+ 0);
677
+ try {
678
+ const { payload, success } = await connect_webextension_1.default.getAddress({
679
+ path: fullPath,
680
+ coin: currency,
681
+ showOnTrezor: true, // This displays the address on device for verification
682
+ });
683
+ if (success) {
684
+ return payload.address;
685
+ }
686
+ throw new Error('Address verification cancelled by user');
687
+ }
688
+ catch (error) {
689
+ throw error;
690
+ }
691
+ }, 'verifyUtxoAddress');
692
+ }
693
+ /**
694
+ * Check Trezor status
695
+ */
696
+ getStatus() {
697
+ return this.hardwareWalletManager
698
+ .getStatus()
699
+ .find((s) => s.type === hardware_wallet_manager_1.HardwareWalletType.TREZOR);
700
+ }
701
+ /**
702
+ * Clean up resources
703
+ */
704
+ async destroy() {
705
+ try {
706
+ // First dispose Trezor Connect
707
+ this.dispose();
708
+ // Then destroy hardware wallet manager
709
+ await this.hardwareWalletManager.destroy();
710
+ this.initialized = false;
711
+ }
712
+ catch (error) {
713
+ console.error('Error destroying Trezor keyring:', error);
714
+ }
715
+ }
716
+ }
717
+ exports.TrezorKeyring = TrezorKeyring;
718
+ //# sourceMappingURL=index.js.map