@sidhujag/sysweb3-keyring 1.0.628 → 2.1.0

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 (131) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +174 -0
  3. package/cjs/bip84-native.js +8 -0
  4. package/cjs/bip84-native.js.map +1 -0
  5. package/cjs/hardware-wallet-manager.js +302 -128
  6. package/cjs/hardware-wallet-manager.js.map +1 -1
  7. package/cjs/keyring-core.js +319 -0
  8. package/cjs/keyring-core.js.map +1 -1
  9. package/cjs/keyring-manager.js +9 -3
  10. package/cjs/keyring-manager.js.map +1 -1
  11. package/cjs/ledger/bitcoin_client/lib/appClient.js.map +1 -1
  12. package/cjs/ledger/host-types.js +10 -0
  13. package/cjs/ledger/host-types.js.map +1 -0
  14. package/cjs/ledger/index.js +243 -447
  15. package/cjs/ledger/index.js.map +1 -1
  16. package/cjs/ledger/prepare-psbt.js +177 -0
  17. package/cjs/ledger/prepare-psbt.js.map +1 -0
  18. package/cjs/public-bip84.js +157 -0
  19. package/cjs/public-bip84.js.map +1 -0
  20. package/cjs/software-hd-account.js +23 -0
  21. package/cjs/software-hd-account.js.map +1 -0
  22. package/cjs/software-utxo-account.js +12 -0
  23. package/cjs/software-utxo-account.js.map +1 -0
  24. package/cjs/software.js +24 -0
  25. package/cjs/software.js.map +1 -1
  26. package/cjs/transactions/bip84-native-plan.js +481 -0
  27. package/cjs/transactions/bip84-native-plan.js.map +1 -0
  28. package/cjs/transactions/ethereum.js +55 -10
  29. package/cjs/transactions/ethereum.js.map +1 -1
  30. package/cjs/transactions/hardware-psbt.js +36 -44
  31. package/cjs/transactions/hardware-psbt.js.map +1 -1
  32. package/cjs/transactions/prepared-bip84.js +214 -0
  33. package/cjs/transactions/prepared-bip84.js.map +1 -0
  34. package/cjs/transactions/prepared-evm.js +197 -0
  35. package/cjs/transactions/prepared-evm.js.map +1 -0
  36. package/cjs/trezor/connect.js +243 -0
  37. package/cjs/trezor/connect.js.map +1 -0
  38. package/cjs/trezor/index.js +96 -58
  39. package/cjs/trezor/index.js.map +1 -1
  40. package/cjs/trezor/witness.js +25 -0
  41. package/cjs/trezor/witness.js.map +1 -0
  42. package/cjs/utils/psbt-account-scope.js +5 -3
  43. package/cjs/utils/psbt-account-scope.js.map +1 -1
  44. package/esm/errorUtils.js +72 -0
  45. package/esm/errorUtils.js.map +1 -0
  46. package/esm/ethers-v6.js +207 -0
  47. package/esm/ethers-v6.js.map +1 -0
  48. package/esm/hardware-wallet-manager.js +643 -0
  49. package/esm/hardware-wallet-manager.js.map +1 -0
  50. package/esm/ledger/bitcoin_client/lib/appClient.js +279 -0
  51. package/esm/ledger/bitcoin_client/lib/appClient.js.map +1 -0
  52. package/esm/ledger/bitcoin_client/lib/bip32.js +49 -0
  53. package/esm/ledger/bitcoin_client/lib/bip32.js.map +1 -0
  54. package/esm/ledger/bitcoin_client/lib/buffertools.js +119 -0
  55. package/esm/ledger/bitcoin_client/lib/buffertools.js.map +1 -0
  56. package/esm/ledger/bitcoin_client/lib/clientCommands.js +269 -0
  57. package/esm/ledger/bitcoin_client/lib/clientCommands.js.map +1 -0
  58. package/esm/ledger/bitcoin_client/lib/merkelizedPsbt.js +50 -0
  59. package/esm/ledger/bitcoin_client/lib/merkelizedPsbt.js.map +1 -0
  60. package/esm/ledger/bitcoin_client/lib/merkle.js +111 -0
  61. package/esm/ledger/bitcoin_client/lib/merkle.js.map +1 -0
  62. package/esm/ledger/bitcoin_client/lib/merkleMap.js +42 -0
  63. package/esm/ledger/bitcoin_client/lib/merkleMap.js.map +1 -0
  64. package/esm/ledger/bitcoin_client/lib/policy.js +68 -0
  65. package/esm/ledger/bitcoin_client/lib/policy.js.map +1 -0
  66. package/esm/ledger/bitcoin_client/lib/psbtv2.js +645 -0
  67. package/esm/ledger/bitcoin_client/lib/psbtv2.js.map +1 -0
  68. package/esm/ledger/bitcoin_client/lib/varint.js +108 -0
  69. package/esm/ledger/bitcoin_client/lib/varint.js.map +1 -0
  70. package/esm/ledger/consts.js +4 -0
  71. package/esm/ledger/consts.js.map +1 -0
  72. package/esm/ledger/dmk-evm.js +258 -0
  73. package/esm/ledger/dmk-evm.js.map +1 -0
  74. package/esm/ledger/dmk-session.js +264 -0
  75. package/esm/ledger/dmk-session.js.map +1 -0
  76. package/esm/ledger/dmk-utxo.js +279 -0
  77. package/esm/ledger/dmk-utxo.js.map +1 -0
  78. package/esm/ledger/host-types.js +5 -0
  79. package/esm/ledger/host-types.js.map +1 -0
  80. package/esm/ledger/index.js +268 -0
  81. package/esm/ledger/index.js.map +1 -0
  82. package/esm/ledger/prepare-psbt.js +141 -0
  83. package/esm/ledger/prepare-psbt.js.map +1 -0
  84. package/esm/ledger/types.js +2 -0
  85. package/esm/ledger/types.js.map +1 -0
  86. package/esm/ledger-host.js +36 -0
  87. package/esm/ledger-host.js.map +1 -0
  88. package/esm/private-records.js +153 -0
  89. package/esm/private-records.js.map +1 -0
  90. package/esm/providers.js +588 -0
  91. package/esm/providers.js.map +1 -0
  92. package/esm/signers.js +28 -0
  93. package/esm/signers.js.map +1 -0
  94. package/esm/trezor/connect.js +206 -0
  95. package/esm/trezor/connect.js.map +1 -0
  96. package/esm/trezor/index.js +876 -0
  97. package/esm/trezor/index.js.map +1 -0
  98. package/esm/trezor/witness.js +21 -0
  99. package/esm/trezor/witness.js.map +1 -0
  100. package/esm/types.js +17 -0
  101. package/esm/types.js.map +1 -0
  102. package/esm/utils/derivation-paths.js +109 -0
  103. package/esm/utils/derivation-paths.js.map +1 -0
  104. package/esm/utils/psbt-account-scope.js +310 -0
  105. package/esm/utils/psbt-account-scope.js.map +1 -0
  106. package/package.json +34 -9
  107. package/types/bip84-native.d.ts +3 -0
  108. package/types/hardware-wallet-manager.d.ts +12 -19
  109. package/types/keyring-core.d.ts +14 -0
  110. package/types/keyring-manager.d.ts +2 -1
  111. package/types/ledger/bitcoin_client/lib/appClient.d.ts +6 -3
  112. package/types/ledger/dmk-evm.d.ts +8 -0
  113. package/types/ledger/dmk-session.d.ts +60 -0
  114. package/types/ledger/dmk-utxo.d.ts +26 -0
  115. package/types/ledger/host-types.d.ts +131 -0
  116. package/types/ledger/index.d.ts +21 -58
  117. package/types/ledger/prepare-psbt.d.ts +3 -0
  118. package/types/ledger/types.d.ts +3 -0
  119. package/types/ledger-host.d.ts +7 -0
  120. package/types/public-bip84.d.ts +39 -0
  121. package/types/software-hd-account.d.ts +16 -0
  122. package/types/software-utxo-account.d.ts +13 -0
  123. package/types/software.d.ts +26 -0
  124. package/types/transactions/bip84-native-plan.d.ts +83 -0
  125. package/types/transactions/ethereum.d.ts +1 -1
  126. package/types/transactions/prepared-bip84.d.ts +27 -0
  127. package/types/transactions/prepared-evm.d.ts +53 -0
  128. package/types/trezor/connect.d.ts +42 -0
  129. package/types/trezor/index.d.ts +22 -4
  130. package/types/trezor/witness.d.ts +3 -0
  131. package/types/utils/psbt-account-scope.d.ts +1 -0
@@ -0,0 +1,243 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.trezorResponseError = exports.subscribeTrezorEvents = void 0;
37
+ const methods = [
38
+ 'getFeatures',
39
+ 'getAccountInfo',
40
+ 'ethereumGetAddress',
41
+ 'ethereumGetPublicKey',
42
+ 'getPublicKey',
43
+ 'getAddress',
44
+ 'signTransaction',
45
+ 'ethereumSignTransaction',
46
+ 'signMessage',
47
+ 'ethereumSignMessage',
48
+ 'ethereumSignTypedData',
49
+ 'verifyMessage',
50
+ 'ethereumVerifyMessage',
51
+ ];
52
+ const listeners = new Set();
53
+ let clientPromise;
54
+ let generation = 0;
55
+ let initialized = false;
56
+ let cleanupPromise = Promise.resolve();
57
+ let cleanupPending = false;
58
+ const inFlight = new Set();
59
+ const pending = new Set();
60
+ const interrupted = () => Object.assign(new Error('Trezor operation cancelled'), {
61
+ code: 'Method_Interrupted',
62
+ });
63
+ const invalidate = () => {
64
+ generation++;
65
+ initialized = false;
66
+ const error = interrupted();
67
+ for (const reject of pending)
68
+ reject(error);
69
+ pending.clear();
70
+ emit({ type: 'disconnected' });
71
+ };
72
+ const subscribeTrezorEvents = (listener) => {
73
+ listeners.add(listener);
74
+ return () => listeners.delete(listener);
75
+ };
76
+ exports.subscribeTrezorEvents = subscribeTrezorEvents;
77
+ const emit = (event) => {
78
+ for (const listener of listeners) {
79
+ try {
80
+ listener(event);
81
+ }
82
+ catch {
83
+ // Status observers must not turn a completed device call into a retry.
84
+ }
85
+ }
86
+ };
87
+ /** Connect 10's webextension module registers Chrome listeners on import. */
88
+ const requireExtensionHost = () => {
89
+ const chrome = globalThis.chrome;
90
+ if (!chrome?.runtime?.id ||
91
+ chrome.runtime.getManifest?.()?.manifest_version !== 3 ||
92
+ typeof chrome.runtime.onConnect?.addListener !== 'function' ||
93
+ typeof chrome.runtime.onMessageExternal?.addListener !== 'function' ||
94
+ typeof chrome.tabs?.get !== 'function' ||
95
+ typeof chrome.tabs?.create !== 'function' ||
96
+ typeof chrome.tabs?.update !== 'function' ||
97
+ typeof chrome.windows?.getCurrent !== 'function') {
98
+ throw Object.assign(new Error('Trezor requires a supported MV3 extension host'), { code: 'HARDWARE_SIGNER_UNAVAILABLE' });
99
+ }
100
+ };
101
+ const getClient = () => {
102
+ requireExtensionHost();
103
+ if (!clientPromise) {
104
+ clientPromise = Promise.resolve().then(() => __importStar(require('@trezor/connect-webextension'))).then((module) => module.default)
105
+ .catch((error) => {
106
+ clientPromise = undefined;
107
+ throw error;
108
+ });
109
+ }
110
+ return clientPromise;
111
+ };
112
+ /** Keep the SDK's established failure payload while preserving Connect 10 codes. */
113
+ const normalize = (response, method) => {
114
+ if (response?.success === false) {
115
+ const error = response.error;
116
+ const code = typeof error?.code === 'string' ? error.code : undefined;
117
+ if (code === 'Device_Disconnected' ||
118
+ code === 'Device_NotFound' ||
119
+ code === 'Desktop_ConnectionMissing' ||
120
+ code === 'Transport_Missing') {
121
+ invalidate();
122
+ }
123
+ return {
124
+ ...response,
125
+ payload: {
126
+ error: typeof error?.message === 'string'
127
+ ? error.message
128
+ : 'Trezor request failed',
129
+ code,
130
+ },
131
+ };
132
+ }
133
+ const model = response?.device?.features?.model ??
134
+ (method === 'getFeatures' ? response?.payload?.model : undefined);
135
+ if (response?.success === true && typeof model === 'string') {
136
+ emit({ type: 'model', model });
137
+ }
138
+ return response;
139
+ };
140
+ const withClient = async (operation, requireInitialized = true) => {
141
+ const captured = generation;
142
+ const assertCurrent = () => {
143
+ if (captured !== generation)
144
+ throw interrupted();
145
+ if (requireInitialized && !initialized) {
146
+ throw Object.assign(new Error('TrezorConnect not initialized'), {
147
+ code: 'Init_NotInitialized',
148
+ });
149
+ }
150
+ };
151
+ assertCurrent();
152
+ let rejectPending;
153
+ const cancelled = new Promise((_resolve, reject) => {
154
+ rejectPending = reject;
155
+ });
156
+ pending.add(rejectPending);
157
+ try {
158
+ const result = await Promise.race([
159
+ (async () => {
160
+ await cleanupPromise;
161
+ assertCurrent();
162
+ const client = await getClient();
163
+ assertCurrent();
164
+ const request = Promise.resolve(operation(client));
165
+ inFlight.add(request);
166
+ try {
167
+ return await request;
168
+ }
169
+ finally {
170
+ inFlight.delete(request);
171
+ }
172
+ })(),
173
+ cancelled,
174
+ ]);
175
+ // A late response must not restore a model/status or return a signature.
176
+ assertCurrent();
177
+ return result;
178
+ }
179
+ finally {
180
+ pending.delete(rejectPending);
181
+ }
182
+ };
183
+ const calls = Object.fromEntries(methods.map((method) => [
184
+ method,
185
+ async (...args) => {
186
+ const captured = generation;
187
+ const response = await withClient((client) => client[method](...args));
188
+ if (captured !== generation)
189
+ throw interrupted();
190
+ return normalize(response, method);
191
+ },
192
+ ]));
193
+ const TrezorConnect = {
194
+ ...calls,
195
+ async init(settings) {
196
+ if (cleanupPending) {
197
+ throw Object.assign(new Error('Previous Trezor request is still pending'), {
198
+ code: 'HARDWARE_SIGNER_BUSY',
199
+ });
200
+ }
201
+ invalidate();
202
+ const captured = generation;
203
+ await withClient((client) => client.init({ ...settings, env: 'webextension' }), false);
204
+ if (captured !== generation)
205
+ throw interrupted();
206
+ initialized = true;
207
+ },
208
+ dispose() {
209
+ // Invalidate synchronously, before waiting for import or remote cleanup.
210
+ // Suite Web's upstream dispose is a no-op; local invalidation is required.
211
+ invalidate();
212
+ if (cleanupPending) {
213
+ return inFlight.size ? Promise.resolve() : cleanupPromise;
214
+ }
215
+ const loaded = clientPromise;
216
+ if (!loaded)
217
+ return Promise.resolve();
218
+ const outstanding = [...inFlight];
219
+ cleanupPending = true;
220
+ cleanupPromise = cleanupPromise
221
+ .catch(() => undefined)
222
+ .then(async () => {
223
+ // Closing Desktop's socket during a raw call makes Connect auto-open
224
+ // Suite Web. Let that raw call settle while its result stays fenced.
225
+ await Promise.allSettled(outstanding);
226
+ const client = await loaded;
227
+ // Desktop cancel() discards an internal Promise in Connect 10.0.1;
228
+ // do not invoke it or claim that Suite Web's no-op dispose closes UI.
229
+ await client.dispose();
230
+ })
231
+ .finally(() => {
232
+ cleanupPending = false;
233
+ });
234
+ // Deferred cleanup may outlive the caller; preserve its failure for future
235
+ // init while preventing an unhandled rejection when the host is locking.
236
+ void cleanupPromise.catch(() => undefined);
237
+ return outstanding.length ? Promise.resolve() : cleanupPromise;
238
+ },
239
+ };
240
+ const trezorResponseError = (response, prefix = '') => Object.assign(new Error(prefix + (response.payload?.error || 'Trezor request failed')), { code: response.payload?.code });
241
+ exports.trezorResponseError = trezorResponseError;
242
+ exports.default = TrezorConnect;
243
+ //# sourceMappingURL=connect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect.js","sourceRoot":"","sources":["../../../src/trezor/connect.ts"],"names":[],"mappings":"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"}
@@ -39,28 +39,38 @@ Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.TrezorKeyring = void 0;
40
40
  /* eslint-disable camelcase */
41
41
  const eth_sig_util_1 = require("@metamask/eth-sig-util");
42
- const connect_webextension_1 = __importStar(require("@trezor/connect-webextension"));
43
- const utxo_lib_1 = require("@trezor/utxo-lib");
44
42
  const bitcoin_ops_1 = __importDefault(require("bitcoin-ops"));
43
+ const bs58check_1 = __importDefault(require("bs58check"));
45
44
  const buffer_1 = require("buffer");
46
45
  const syscoinjs = __importStar(require("syscoinjs-lib"));
46
+ const connect_1 = __importStar(require("./connect"));
47
+ const witness_1 = require("./witness");
47
48
  const hardware_wallet_manager_1 = require("../hardware-wallet-manager");
48
49
  const derivation_paths_1 = require("../utils/derivation-paths");
49
50
  const bitcoinjs = syscoinjs.utils.bitcoinjs;
50
51
  const { p2wsh } = bitcoinjs.payments;
51
52
  const { decompile } = bitcoinjs.script;
52
- const { fromBase58Check, fromBech32 } = utxo_lib_1.address;
53
+ const { fromBech32 } = bitcoinjs.address;
54
+ const fromBase58Check = (value) => {
55
+ try {
56
+ return bitcoinjs.address.fromBase58Check(value);
57
+ }
58
+ catch (error) {
59
+ // The former decoder also accepted a two-byte network version. Preserve
60
+ // exactly that checksum-verified format without loading the legacy fork.
61
+ const payload = bs58check_1.default.decode(value);
62
+ if (payload.length === 22) {
63
+ return {
64
+ version: (payload[0] << 8) | payload[1],
65
+ hash: payload.subarray(2),
66
+ };
67
+ }
68
+ throw error;
69
+ }
70
+ };
53
71
  const initialHDPath = `m/44'/60'/0'/0/0`;
54
72
  const DELAY_BETWEEN_POPUPS = 2000; // Increased from 1000ms to 2000ms for more reliable operation
55
73
  const stripHexPrefix = (value) => value.startsWith('0x') || value.startsWith('0X') ? value.slice(2) : value;
56
- const serializeWitness = (witness) => {
57
- const stack = witness.map((item) => buffer_1.Buffer.from(item));
58
- const size = utxo_lib_1.bufferutils.varIntSize(stack.length) +
59
- stack.reduce((total, item) => total + utxo_lib_1.bufferutils.varIntSize(item.length) + item.length, 0);
60
- const writer = new utxo_lib_1.bufferutils.BufferWriter(buffer_1.Buffer.alloc(size));
61
- writer.writeVector(stack);
62
- return writer.buffer;
63
- };
64
74
  const finalizedFields = (input) => {
65
75
  if (!input.finalScriptSig && !input.finalScriptWitness)
66
76
  return null;
@@ -76,6 +86,19 @@ class TrezorKeyring {
76
86
  this.hdPath = initialHDPath;
77
87
  this.paths = {};
78
88
  this.initialized = false;
89
+ this.lifecycleGeneration = 0;
90
+ this.onTrezorConnected = ({ type, }) => {
91
+ if (type === hardware_wallet_manager_1.HardwareWalletType.TREZOR) {
92
+ console.log('Trezor connected');
93
+ this.initialized = true;
94
+ }
95
+ };
96
+ this.onTrezorDisconnected = ({ type, }) => {
97
+ if (type === hardware_wallet_manager_1.HardwareWalletType.TREZOR) {
98
+ console.log('Trezor disconnected');
99
+ this.initialized = false;
100
+ }
101
+ };
79
102
  this._transformTypedData = (data, version) => {
80
103
  const { types, primaryType, domain, message } = this._sanitizeData(data);
81
104
  const domainSeparatorHash = eth_sig_util_1.TypedDataUtils.hashStruct('EIP712Domain', this._sanitizeData(domain), types, version).toString('hex');
@@ -94,36 +117,42 @@ class TrezorKeyring {
94
117
  this.hdPath = '';
95
118
  this.paths = {};
96
119
  this.hardwareWalletManager = new hardware_wallet_manager_1.HardwareWalletManager();
97
- // Set up event listeners
98
- this.hardwareWalletManager.on('connected', ({ type }) => {
99
- if (type === hardware_wallet_manager_1.HardwareWalletType.TREZOR) {
100
- console.log('Trezor connected');
101
- this.initialized = true;
102
- }
103
- });
104
- this.hardwareWalletManager.on('disconnected', ({ type }) => {
105
- if (type === hardware_wallet_manager_1.HardwareWalletType.TREZOR) {
106
- console.log('Trezor disconnected');
107
- this.initialized = false;
108
- }
109
- });
110
- connect_webextension_1.default.on(connect_webextension_1.DEVICE_EVENT, (event) => {
111
- if (event.payload.features) {
112
- this.model = event.payload.features.model;
113
- }
114
- });
120
+ this.observeTrezor();
121
+ }
122
+ observeTrezor() {
123
+ // Manager destruction removes its listeners. Reusing an unlocked keyring
124
+ // must restore these same callbacks without multiplying them on each init.
125
+ if (!this.hardwareWalletManager
126
+ .listeners('connected')
127
+ .includes(this.onTrezorConnected))
128
+ this.hardwareWalletManager.on('connected', this.onTrezorConnected);
129
+ if (!this.hardwareWalletManager
130
+ .listeners('disconnected')
131
+ .includes(this.onTrezorDisconnected))
132
+ this.hardwareWalletManager.on('disconnected', this.onTrezorDisconnected);
133
+ if (!this.unsubscribeTrezor)
134
+ this.unsubscribeTrezor = (0, connect_1.subscribeTrezorEvents)((event) => {
135
+ if (event.type === 'model')
136
+ this.model = event.model;
137
+ });
115
138
  }
116
139
  /**
117
140
  * Initialize Trezor script.
118
141
  */
119
142
  async init() {
143
+ const generation = this.lifecycleGeneration;
144
+ this.observeTrezor();
120
145
  if (this.initialized) {
121
146
  return true;
122
147
  }
123
148
  // Add a small delay to ensure Chrome extension context is ready
124
149
  // This helps prevent "waiting for handshake" errors
125
150
  await new Promise((resolve) => setTimeout(resolve, 100));
151
+ if (generation !== this.lifecycleGeneration)
152
+ return false;
126
153
  const result = await this.hardwareWalletManager.initializeTrezor();
154
+ if (generation !== this.lifecycleGeneration)
155
+ return false;
127
156
  if (result) {
128
157
  this.initialized = true;
129
158
  }
@@ -150,15 +179,17 @@ class TrezorKeyring {
150
179
  // Use hardware wallet manager's retry mechanism with custom config
151
180
  return this.hardwareWalletManager
152
181
  .retryOperation(operation, operationName, trezorRetryConfig)
153
- .catch((error) => {
182
+ .catch(async (error) => {
154
183
  // Clean up Trezor state on failure
155
- if (error.message?.includes('Popup closed') ||
156
- error.message?.includes('cancelled') ||
157
- error.message?.includes('denied')) {
184
+ const message = String(error.message || '').toLowerCase();
185
+ if (message.includes('popup closed') ||
186
+ message.includes('cancelled') ||
187
+ message.includes('canceled') ||
188
+ message.includes('denied')) {
158
189
  this.initialized = false;
159
190
  // Dispose Trezor connection to clean up
160
191
  try {
161
- connect_webextension_1.default.dispose();
192
+ await connect_1.default.dispose();
162
193
  }
163
194
  catch (disposeError) {
164
195
  console.log('Failed to dispose Trezor on error:', disposeError);
@@ -185,12 +216,12 @@ class TrezorKeyring {
185
216
  // For EVM networks, getAccountInfo is not supported
186
217
  // We need to use getAddress instead
187
218
  if (slip44 === 60) {
188
- const addressResponse = await connect_webextension_1.default.ethereumGetAddress({
219
+ const addressResponse = await connect_1.default.ethereumGetAddress({
189
220
  path: this.hdPath,
190
221
  showOnTrezor: false,
191
222
  });
192
223
  if (!addressResponse.success) {
193
- throw new Error(addressResponse.payload.error || 'Failed to get EVM address');
224
+ throw (0, connect_1.trezorResponseError)(addressResponse);
194
225
  }
195
226
  // Return a compatible AccountInfo structure
196
227
  return {
@@ -204,14 +235,14 @@ class TrezorKeyring {
204
235
  };
205
236
  }
206
237
  // For UTXO networks, use the standard getAccountInfo
207
- const response = await connect_webextension_1.default.getAccountInfo({
208
- coin,
238
+ const response = await connect_1.default.getAccountInfo({
239
+ coin: coin,
209
240
  path: this.hdPath,
210
241
  });
211
242
  if (response.success) {
212
243
  return response.payload;
213
244
  }
214
- throw new Error(response.payload.error);
245
+ throw (0, connect_1.trezorResponseError)(response);
215
246
  }, 'getAccountInfo');
216
247
  }
217
248
  /**
@@ -224,13 +255,16 @@ class TrezorKeyring {
224
255
  return this.model;
225
256
  }
226
257
  /**
227
- * This removes the Trezor Connect iframe from the DOM
258
+ * This disposes the active Trezor Suite connection
228
259
  *
229
260
  * @returns void
230
261
  */
231
262
  dispose() {
263
+ this.lifecycleGeneration++;
232
264
  try {
233
- connect_webextension_1.default.dispose();
265
+ void connect_1.default.dispose().catch((error) => {
266
+ console.log('Error disposing Trezor:', error);
267
+ });
234
268
  this.initialized = false;
235
269
  // Clear any cached data
236
270
  this.publicKey = buffer_1.Buffer.from('', 'hex');
@@ -262,7 +296,7 @@ class TrezorKeyring {
262
296
  method = 'verifyMessage';
263
297
  }
264
298
  // @ts-ignore
265
- const { success, payload } = await connect_webextension_1.default[method]({
299
+ const { success, payload } = await connect_1.default[method]({
266
300
  coin,
267
301
  address,
268
302
  message,
@@ -271,7 +305,7 @@ class TrezorKeyring {
271
305
  if (success) {
272
306
  return { success, payload };
273
307
  }
274
- throw new Error(payload.error);
308
+ throw (0, connect_1.trezorResponseError)({ payload });
275
309
  }, 'verifyMessage');
276
310
  }
277
311
  /**
@@ -290,7 +324,7 @@ class TrezorKeyring {
290
324
  try {
291
325
  // For EVM networks, use ethereumGetPublicKey
292
326
  if (slip44 === 60) {
293
- const { success, payload } = await connect_webextension_1.default.ethereumGetPublicKey({
327
+ const { success, payload } = await connect_1.default.ethereumGetPublicKey({
294
328
  path: this.hdPath,
295
329
  showOnTrezor: false,
296
330
  });
@@ -306,7 +340,7 @@ class TrezorKeyring {
306
340
  return { success: false, payload };
307
341
  }
308
342
  // For UTXO networks, use standard getPublicKey
309
- const { success, payload } = await connect_webextension_1.default.getPublicKey({
343
+ const { success, payload } = await connect_1.default.getPublicKey({
310
344
  coin: coin,
311
345
  path: this.hdPath,
312
346
  });
@@ -355,9 +389,9 @@ class TrezorKeyring {
355
389
  const approvedTransaction = unsignedSnapshot(psbt);
356
390
  const approvedFinalInputs = psbt.data.inputs.map(finalizedFields);
357
391
  const payload = await this.executeWithRetry(async () => {
358
- const response = await connect_webextension_1.default.signTransaction(utxoTransaction);
392
+ const response = await connect_1.default.signTransaction(utxoTransaction);
359
393
  if (!response.success) {
360
- throw new Error('Trezor sign failed: ' + response.payload.error);
394
+ throw (0, connect_1.trezorResponseError)(response, 'Trezor sign failed: ');
361
395
  }
362
396
  return response.payload;
363
397
  }, 'signUtxoTransaction');
@@ -377,7 +411,7 @@ class TrezorKeyring {
377
411
  current.witness !== approved.witness ||
378
412
  buffer_1.Buffer.from(tx.ins[index].script).toString('hex') !==
379
413
  approved.scriptSig ||
380
- serializeWitness(tx.ins[index].witness || []).toString('hex') !==
414
+ (0, witness_1.serializeWitness)(tx.ins[index].witness || []).toString('hex') !==
381
415
  approved.witness);
382
416
  })) {
383
417
  throw new Error('Trezor changed an already-finalized input');
@@ -671,14 +705,14 @@ class TrezorKeyring {
671
705
  await new Promise((resolve) => setTimeout(resolve, DELAY_BETWEEN_POPUPS));
672
706
  // Use dynamic path generation based on actual network parameters
673
707
  this.setHdPath(coin, Number(index) || 0, slip44);
674
- const response = await connect_webextension_1.default.ethereumSignTransaction({
708
+ const response = await connect_1.default.ethereumSignTransaction({
675
709
  path: this.hdPath,
676
710
  transaction: tx,
677
711
  });
678
712
  if (response.success) {
679
713
  return response;
680
714
  }
681
- throw new Error(response.payload.error);
715
+ throw (0, connect_1.trezorResponseError)(response);
682
716
  }, 'signEthTransaction');
683
717
  }
684
718
  /**
@@ -702,12 +736,14 @@ class TrezorKeyring {
702
736
  }
703
737
  async _signUtxoPersonalMessage({ coin, index, slip44, message, }) {
704
738
  try {
739
+ if (typeof message !== 'string')
740
+ throw new Error('Message must be a string');
705
741
  // Use dynamic path generation instead of hardcoded switch
706
742
  this.setHdPath(coin, index || 0, slip44);
707
- const { success, payload } = await connect_webextension_1.default.signMessage({
743
+ const { success, payload } = await connect_1.default.signMessage({
708
744
  path: this.hdPath,
709
745
  coin: coin,
710
- message: message,
746
+ message,
711
747
  });
712
748
  if (success) {
713
749
  return { success, payload };
@@ -724,7 +760,7 @@ class TrezorKeyring {
724
760
  setTimeout(async () => {
725
761
  try {
726
762
  this.setHdPath('eth', index, 60);
727
- connect_webextension_1.default.ethereumSignMessage({
763
+ connect_1.default.ethereumSignMessage({
728
764
  path: this.hdPath,
729
765
  message: stripHexPrefix(message),
730
766
  hex: true,
@@ -742,11 +778,11 @@ class TrezorKeyring {
742
778
  else {
743
779
  reject(
744
780
  // @ts-ignore
745
- new Error(response.payload.error || 'Unknown error'));
781
+ (0, connect_1.trezorResponseError)(response));
746
782
  }
747
783
  })
748
784
  .catch((e) => {
749
- reject(new Error(e.toString() || 'Unknown error'));
785
+ reject(e instanceof Error ? e : new Error(String(e)));
750
786
  });
751
787
  }
752
788
  catch (error) {
@@ -797,7 +833,7 @@ class TrezorKeyring {
797
833
  } = dataWithHashes;
798
834
  // This is necessary to avoid popup collision
799
835
  // between the unlock & sign trezor popups
800
- const response = await connect_webextension_1.default.ethereumSignTypedData({
836
+ const response = await connect_1.default.ethereumSignTypedData({
801
837
  path: this.hdPath,
802
838
  data: {
803
839
  types: {
@@ -820,7 +856,7 @@ class TrezorKeyring {
820
856
  return response.payload.signature;
821
857
  }
822
858
  // @ts-ignore
823
- throw new Error(response.payload.error || 'Unknown error');
859
+ throw (0, connect_1.trezorResponseError)(response);
824
860
  }, 'signTypedData');
825
861
  }
826
862
  /**
@@ -835,7 +871,7 @@ class TrezorKeyring {
835
871
  const fullPath = (0, derivation_paths_1.getAddressDerivationPath)(currency, slip44, accountIndex, false, // Not a change address
836
872
  0);
837
873
  try {
838
- const { payload, success } = await connect_webextension_1.default.getAddress({
874
+ const { payload, success } = await connect_1.default.getAddress({
839
875
  path: fullPath,
840
876
  coin: currency,
841
877
  showOnTrezor: true, // This displays the address on device for verification
@@ -862,6 +898,8 @@ class TrezorKeyring {
862
898
  * Clean up resources
863
899
  */
864
900
  async destroy() {
901
+ this.unsubscribeTrezor?.();
902
+ this.unsubscribeTrezor = undefined;
865
903
  try {
866
904
  // First dispose Trezor Connect
867
905
  this.dispose();