@sidhujag/sysweb3-keyring 1.0.627 → 2.0.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 (140) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/README.md +66 -0
  3. package/cjs/hardware-wallet-manager.js +302 -128
  4. package/cjs/hardware-wallet-manager.js.map +1 -1
  5. package/cjs/keyring-core.js +2605 -0
  6. package/cjs/keyring-core.js.map +1 -0
  7. package/cjs/keyring-manager.js +31 -2439
  8. package/cjs/keyring-manager.js.map +1 -1
  9. package/cjs/ledger/bitcoin_client/lib/appClient.js.map +1 -1
  10. package/cjs/ledger/host-types.js +10 -0
  11. package/cjs/ledger/host-types.js.map +1 -0
  12. package/cjs/ledger/index.js +243 -447
  13. package/cjs/ledger/index.js.map +1 -1
  14. package/cjs/ledger/prepare-psbt.js +177 -0
  15. package/cjs/ledger/prepare-psbt.js.map +1 -0
  16. package/cjs/software-hd-account.js +23 -0
  17. package/cjs/software-hd-account.js.map +1 -0
  18. package/cjs/software.js +74 -0
  19. package/cjs/software.js.map +1 -0
  20. package/cjs/storage-core.js +227 -0
  21. package/cjs/storage-core.js.map +1 -0
  22. package/cjs/storage.js +15 -210
  23. package/cjs/storage.js.map +1 -1
  24. package/cjs/transactions/ethereum.js +176 -39
  25. package/cjs/transactions/ethereum.js.map +1 -1
  26. package/cjs/transactions/evm-local-signer.js +11 -1
  27. package/cjs/transactions/evm-local-signer.js.map +1 -1
  28. package/cjs/transactions/hardware-psbt.js +159 -0
  29. package/cjs/transactions/hardware-psbt.js.map +1 -0
  30. package/cjs/transactions/prepared-evm.js +196 -0
  31. package/cjs/transactions/prepared-evm.js.map +1 -0
  32. package/cjs/transactions/syscoin-core.js +651 -0
  33. package/cjs/transactions/syscoin-core.js.map +1 -0
  34. package/cjs/transactions/syscoin.js +8 -768
  35. package/cjs/transactions/syscoin.js.map +1 -1
  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/types.js.map +1 -1
  43. package/cjs/utils/psbt-account-scope.js +5 -3
  44. package/cjs/utils/psbt-account-scope.js.map +1 -1
  45. package/esm/errorUtils.js +72 -0
  46. package/esm/errorUtils.js.map +1 -0
  47. package/esm/ethers-v6.js +207 -0
  48. package/esm/ethers-v6.js.map +1 -0
  49. package/esm/hardware-wallet-manager.js +643 -0
  50. package/esm/hardware-wallet-manager.js.map +1 -0
  51. package/esm/ledger/bitcoin_client/lib/appClient.js +279 -0
  52. package/esm/ledger/bitcoin_client/lib/appClient.js.map +1 -0
  53. package/esm/ledger/bitcoin_client/lib/bip32.js +49 -0
  54. package/esm/ledger/bitcoin_client/lib/bip32.js.map +1 -0
  55. package/esm/ledger/bitcoin_client/lib/buffertools.js +119 -0
  56. package/esm/ledger/bitcoin_client/lib/buffertools.js.map +1 -0
  57. package/esm/ledger/bitcoin_client/lib/clientCommands.js +269 -0
  58. package/esm/ledger/bitcoin_client/lib/clientCommands.js.map +1 -0
  59. package/esm/ledger/bitcoin_client/lib/merkelizedPsbt.js +50 -0
  60. package/esm/ledger/bitcoin_client/lib/merkelizedPsbt.js.map +1 -0
  61. package/esm/ledger/bitcoin_client/lib/merkle.js +111 -0
  62. package/esm/ledger/bitcoin_client/lib/merkle.js.map +1 -0
  63. package/esm/ledger/bitcoin_client/lib/merkleMap.js +42 -0
  64. package/esm/ledger/bitcoin_client/lib/merkleMap.js.map +1 -0
  65. package/esm/ledger/bitcoin_client/lib/policy.js +68 -0
  66. package/esm/ledger/bitcoin_client/lib/policy.js.map +1 -0
  67. package/esm/ledger/bitcoin_client/lib/psbtv2.js +645 -0
  68. package/esm/ledger/bitcoin_client/lib/psbtv2.js.map +1 -0
  69. package/esm/ledger/bitcoin_client/lib/varint.js +108 -0
  70. package/esm/ledger/bitcoin_client/lib/varint.js.map +1 -0
  71. package/esm/ledger/consts.js +4 -0
  72. package/esm/ledger/consts.js.map +1 -0
  73. package/esm/ledger/dmk-evm.js +258 -0
  74. package/esm/ledger/dmk-evm.js.map +1 -0
  75. package/esm/ledger/dmk-session.js +264 -0
  76. package/esm/ledger/dmk-session.js.map +1 -0
  77. package/esm/ledger/dmk-utxo.js +279 -0
  78. package/esm/ledger/dmk-utxo.js.map +1 -0
  79. package/esm/ledger/host-types.js +5 -0
  80. package/esm/ledger/host-types.js.map +1 -0
  81. package/esm/ledger/index.js +268 -0
  82. package/esm/ledger/index.js.map +1 -0
  83. package/esm/ledger/prepare-psbt.js +141 -0
  84. package/esm/ledger/prepare-psbt.js.map +1 -0
  85. package/esm/ledger/types.js +2 -0
  86. package/esm/ledger/types.js.map +1 -0
  87. package/esm/ledger-host.js +36 -0
  88. package/esm/ledger-host.js.map +1 -0
  89. package/esm/private-records.js +153 -0
  90. package/esm/private-records.js.map +1 -0
  91. package/esm/providers.js +588 -0
  92. package/esm/providers.js.map +1 -0
  93. package/esm/signers.js +28 -0
  94. package/esm/signers.js.map +1 -0
  95. package/esm/trezor/connect.js +206 -0
  96. package/esm/trezor/connect.js.map +1 -0
  97. package/esm/trezor/index.js +876 -0
  98. package/esm/trezor/index.js.map +1 -0
  99. package/esm/trezor/witness.js +21 -0
  100. package/esm/trezor/witness.js.map +1 -0
  101. package/esm/types.js +17 -0
  102. package/esm/types.js.map +1 -0
  103. package/esm/utils/derivation-paths.js +109 -0
  104. package/esm/utils/derivation-paths.js.map +1 -0
  105. package/esm/utils/psbt-account-scope.js +310 -0
  106. package/esm/utils/psbt-account-scope.js.map +1 -0
  107. package/package.json +55 -8
  108. package/types/hardware-wallet-manager.d.ts +12 -19
  109. package/types/keyring-core.d.ts +263 -0
  110. package/types/keyring-manager.d.ts +7 -224
  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/software-hd-account.d.ts +16 -0
  121. package/types/software.d.ts +39 -0
  122. package/types/storage-core.d.ts +22 -0
  123. package/types/storage.d.ts +1 -4
  124. package/types/transactions/ethereum.d.ts +17 -7
  125. package/types/transactions/evm-local-signer.d.ts +3 -1
  126. package/types/transactions/hardware-psbt.d.ts +7 -0
  127. package/types/transactions/prepared-evm.d.ts +53 -0
  128. package/types/transactions/syscoin-core.d.ts +92 -0
  129. package/types/transactions/syscoin.d.ts +8 -67
  130. package/types/trezor/connect.d.ts +42 -0
  131. package/types/trezor/index.d.ts +22 -4
  132. package/types/trezor/witness.d.ts +3 -0
  133. package/types/types.d.ts +10 -0
  134. package/types/utils/psbt-account-scope.d.ts +1 -0
  135. package/cjs/transactions/__tests__/integration.test.js +0 -237
  136. package/cjs/transactions/__tests__/integration.test.js.map +0 -1
  137. package/cjs/transactions/__tests__/syscoin.test.js +0 -361
  138. package/cjs/transactions/__tests__/syscoin.test.js.map +0 -1
  139. package/types/transactions/__tests__/integration.test.d.ts +0 -1
  140. package/types/transactions/__tests__/syscoin.test.d.ts +0 -1
@@ -14,7 +14,38 @@ const providers_1 = require("../providers");
14
14
  const types_1 = require("../types");
15
15
  const evm_local_signer_1 = require("./evm-local-signer");
16
16
  const derivation_paths_1 = require("../utils/derivation-paths");
17
+ const hardwareSignerUnavailable = (hardware) => Object.assign(new Error(`${hardware} signer is unavailable in this host`), {
18
+ code: 'HARDWARE_SIGNER_UNAVAILABLE',
19
+ });
20
+ const assertHardwareTransactionSender = (signedTx, expectedAddress) => {
21
+ if (transaction_1.Transaction.from(signedTx).from?.toLowerCase() !==
22
+ expectedAddress.toLowerCase()) {
23
+ throw Object.assign(new Error('Hardware signature does not match the approved account'), {
24
+ code: 'HARDWARE_ACCOUNT_MISMATCH',
25
+ });
26
+ }
27
+ };
17
28
  const stripHexPrefix = (value) => value.startsWith('0x') || value.startsWith('0X') ? value.slice(2) : value;
29
+ // Connect returns hexadecimal signature fields; normalize their encoding
30
+ // without mutating the response or reparsing an already numeric recovery v.
31
+ const trezorSignature = (signature) => {
32
+ const { r, s, v } = signature;
33
+ if (![r, s].every((value) => /^(?:0x)?[0-9a-f]{64}$/i.test(value))) {
34
+ throw new Error('Invalid Trezor signature scalar encoding');
35
+ }
36
+ if (typeof v === 'string' && !/^(?:0x)?[0-9a-f]+$/i.test(v)) {
37
+ throw new Error('Invalid Trezor signature recovery value');
38
+ }
39
+ const recovery = typeof v === 'number' ? v : Number.parseInt(v, 16);
40
+ if (!Number.isSafeInteger(recovery) || recovery < 0) {
41
+ throw new Error('Invalid Trezor signature recovery value');
42
+ }
43
+ return {
44
+ r: `0x${stripHexPrefix(r)}`,
45
+ s: `0x${stripHexPrefix(s)}`,
46
+ v: recovery,
47
+ };
48
+ };
18
49
  const normalizeEthersOverrideValue = (value) => (0, ethers_v6_1.normalizeTxValue)(value);
19
50
  const nonNegativeFeeQuantity = (value, label) => {
20
51
  // Match the exported BigNumberish object contract without trusting a
@@ -131,7 +162,28 @@ class EthereumTransactions {
131
162
  constructor(getNetwork, getDecryptedPrivateKey, getState, ledgerSigner, trezorSigner, captureSigningContext) {
132
163
  // Allow manual override of gas parameters when automatic estimation fails
133
164
  this.gasOverrides = {};
165
+ this.requireLedgerSigner = () => {
166
+ if (!this.ledgerSigner)
167
+ throw hardwareSignerUnavailable('Ledger');
168
+ return this.ledgerSigner;
169
+ };
170
+ this.requireTrezorSigner = () => {
171
+ if (!this.trezorSigner)
172
+ throw hardwareSignerUnavailable('Trezor');
173
+ return this.trezorSigner;
174
+ };
175
+ this.assertHardwareSignerAvailable = (targetAccount) => {
176
+ const state = this.getState();
177
+ const type = targetAccount?.type ?? state.activeAccountType;
178
+ const id = targetAccount?.id ?? state.activeAccountId;
179
+ const account = state.accounts[type]?.[id];
180
+ if (type === types_1.KeyringAccountType.Ledger || account?.isLedgerWallet)
181
+ this.requireLedgerSigner();
182
+ if (type === types_1.KeyringAccountType.Trezor || account?.isTrezorWallet)
183
+ this.requireTrezorSigner();
184
+ };
134
185
  this.captureEvmSigningContext = () => {
186
+ this.assertHardwareSignerAvailable();
135
187
  const { activeAccountType, activeAccountId, accounts, activeNetwork } = this.getState();
136
188
  const selectedAccount = accounts[activeAccountType]?.[activeAccountId];
137
189
  if (!selectedAccount)
@@ -192,9 +244,10 @@ class EthereumTransactions {
192
244
  throw {
193
245
  message: 'Decrypting for wrong address, change activeAccount maybe',
194
246
  };
195
- return await this.ledgerSigner.evm.signTypedData({
247
+ return await this.requireLedgerSigner().evm.signTypedData({
196
248
  version,
197
249
  accountIndex: activeAccountId,
250
+ expectedAddress: activeAccount.address,
198
251
  data: typedData,
199
252
  });
200
253
  };
@@ -203,7 +256,7 @@ class EthereumTransactions {
203
256
  throw {
204
257
  message: 'Decrypting for wrong address, change activeAccount maybe',
205
258
  };
206
- return await this.trezorSigner.signTypedData({
259
+ return await this.requireTrezorSigner().signTypedData({
207
260
  version,
208
261
  address: addr,
209
262
  data: typedData,
@@ -225,9 +278,9 @@ class EthereumTransactions {
225
278
  const { activeAccountType } = this.getState();
226
279
  switch (activeAccountType) {
227
280
  case types_1.KeyringAccountType.Ledger:
228
- return await this.ledgerSigner.verifyUtxoAddress(accountIndex, currency, slip44);
281
+ return await this.requireLedgerSigner().verifyUtxoAddress(accountIndex, currency, slip44);
229
282
  case types_1.KeyringAccountType.Trezor:
230
- return await this.trezorSigner.verifyUtxoAddress(accountIndex, currency, slip44);
283
+ return await this.requireTrezorSigner().verifyUtxoAddress(accountIndex, currency, slip44);
231
284
  default:
232
285
  throw new Error('verifyUtxoAddress is only available for hardware wallet accounts');
233
286
  }
@@ -284,8 +337,9 @@ class EthereumTransactions {
284
337
  };
285
338
  const signWithLedger = async () => {
286
339
  try {
287
- const response = await this.ledgerSigner.evm.signPersonalMessage({
340
+ const response = await this.requireLedgerSigner().evm.signPersonalMessage({
288
341
  accountIndex: activeAccountId,
342
+ expectedAddress: activeAccount.address,
289
343
  message: msg,
290
344
  });
291
345
  return response;
@@ -298,7 +352,7 @@ class EthereumTransactions {
298
352
  try {
299
353
  // For EVM networks, Trezor expects 'eth' regardless of the network's currency
300
354
  const trezorCoin = activeNetwork.slip44 === 60 ? 'eth' : activeNetwork.currency;
301
- const response = await this.trezorSigner.signMessage({
355
+ const response = await this.requireTrezorSigner().signMessage({
302
356
  coin: trezorCoin,
303
357
  address: activeAccount.address,
304
358
  index: activeAccountId,
@@ -377,8 +431,9 @@ class EthereumTransactions {
377
431
  // Message is plain text, convert to hex
378
432
  messageForLedger = Buffer.from(msg, 'utf8').toString('hex');
379
433
  }
380
- const response = await this.ledgerSigner.evm.signPersonalMessage({
434
+ const response = await this.requireLedgerSigner().evm.signPersonalMessage({
381
435
  accountIndex: activeAccountId,
436
+ expectedAddress: activeAccount.address,
382
437
  message: messageForLedger,
383
438
  });
384
439
  return response;
@@ -401,7 +456,7 @@ class EthereumTransactions {
401
456
  }
402
457
  // For EVM networks, Trezor expects 'eth' regardless of the network's currency
403
458
  const trezorCoin = activeNetwork.slip44 === 60 ? 'eth' : activeNetwork.currency;
404
- const response = await this.trezorSigner.signMessage({
459
+ const response = await this.requireTrezorSigner().signMessage({
405
460
  coin: trezorCoin,
406
461
  address: activeAccount.address,
407
462
  index: activeAccountId,
@@ -674,9 +729,52 @@ class EthereumTransactions {
674
729
  (!Number.isSafeInteger(fallbackNonce) || fallbackNonce < 0)) {
675
730
  throw new Error('Invalid cancellation fallback nonce');
676
731
  }
732
+ const previewOnly = options.previewOnly === true;
733
+ const approvedMaximumFee = options.approvedMaximumFee;
734
+ if (!previewOnly &&
735
+ (typeof approvedMaximumFee !== 'string' ||
736
+ !/^(0|[1-9][0-9]{0,77})$/.test(approvedMaximumFee))) {
737
+ throw new Error('Cancellation fee approval required');
738
+ }
677
739
  const assertHostContext = options.assertCurrentContext;
678
740
  assertHostContext();
679
- const { activeAccount, activeAccountType, activeAccountId, activeNetwork, provider, assertCurrent: assertKeyringContext, } = this.captureEvmSigningContext();
741
+ const state = this.getState();
742
+ const selectedType = state.activeAccountType;
743
+ const selectedId = state.activeAccountId;
744
+ const selectedAddress = state.accounts?.[selectedType]?.[selectedId]?.address;
745
+ const activeAccountType = options.targetAccount?.type ?? selectedType;
746
+ const activeAccountId = options.targetAccount?.id ?? selectedId;
747
+ const targetAccount = options.targetAccount
748
+ ? { type: activeAccountType, id: activeAccountId }
749
+ : undefined;
750
+ const activeAccount = {
751
+ ...state.accounts?.[activeAccountType]?.[activeAccountId],
752
+ };
753
+ const activeNetwork = { ...state.activeNetwork };
754
+ if (!selectedAddress ||
755
+ !activeAccount.address ||
756
+ (targetAccount && activeAccountType === types_1.KeyringAccountType.SmartAccount)) {
757
+ throw new Error('Cancellation signing account is unavailable');
758
+ }
759
+ if (!previewOnly)
760
+ this.assertHardwareSignerAvailable(targetAccount);
761
+ const provider = this.web3Provider;
762
+ const assertSession = this.captureSigningContext?.();
763
+ const assertKeyringContext = () => {
764
+ assertSession?.();
765
+ const current = this.getState();
766
+ if (current.activeAccountType !== selectedType ||
767
+ current.activeAccountId !== selectedId ||
768
+ current.accounts?.[selectedType]?.[selectedId]?.address?.toLowerCase() !== selectedAddress.toLowerCase() ||
769
+ current.accounts?.[activeAccountType]?.[activeAccountId]?.address?.toLowerCase() !== activeAccount.address.toLowerCase() ||
770
+ [current.activeNetwork, this.getNetwork()].some((selected) => selected.kind !== activeNetwork.kind ||
771
+ selected.chainId !== activeNetwork.chainId ||
772
+ selected.slip44 !== activeNetwork.slip44 ||
773
+ selected.url !== activeNetwork.url) ||
774
+ this.web3Provider !== provider) {
775
+ throw new Error('Wallet signing context changed');
776
+ }
777
+ };
680
778
  const assertCurrent = () => {
681
779
  assertHostContext();
682
780
  assertKeyringContext();
@@ -798,6 +896,22 @@ class EthereumTransactions {
798
896
  maxPriorityFeePerGas: bumpCancelFee(oldTxsGasValues.maxPriorityFeePerGas),
799
897
  }),
800
898
  };
899
+ const maximumFee = newGasValues.gasLimit.mul(isLegacy ? newGasValues.gasPrice : newGasValues.maxFeePerGas);
900
+ assertCurrent();
901
+ if (previewOnly)
902
+ return {
903
+ isCanceled: false,
904
+ error: false,
905
+ maximumFee: maximumFee.toString(),
906
+ };
907
+ if (maximumFee.gt(approvedMaximumFee))
908
+ throw new Error('Cancellation fee exceeds approval');
909
+ const assertApprovedEnvelope = (transaction) => {
910
+ const gas = nonNegativeFeeQuantity(transaction.gasLimit, 'cancellation gas limit');
911
+ const cap = nonNegativeFeeQuantity(isLegacy ? transaction.gasPrice : transaction.maxFeePerGas, 'cancellation maximum fee');
912
+ if (!gas.eq(42000) || gas.mul(cap).gt(approvedMaximumFee))
913
+ throw new Error('Cancellation fee exceeds approval');
914
+ };
801
915
  // Base cancel transaction parameters (same for all wallet types)
802
916
  const baseCancelTx = {
803
917
  nonce: tx.nonce,
@@ -841,10 +955,12 @@ class EthereumTransactions {
841
955
  chainId: activeNetwork.chainId,
842
956
  type: 2, // Need explicit type for hardware wallet serialization
843
957
  };
958
+ assertApprovedEnvelope(txFormattedForEthers);
844
959
  const rawTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers);
845
- const signature = await this.ledgerSigner.evm.signEVMTransaction({
960
+ const signature = await this.requireLedgerSigner().evm.signEVMTransaction({
846
961
  rawTx: rawTx.replace('0x', ''),
847
962
  accountIndex: activeAccountId,
963
+ expectedAddress: activeAccount.address,
848
964
  });
849
965
  assertCurrent();
850
966
  const formattedSignature = {
@@ -855,6 +971,7 @@ class EthereumTransactions {
855
971
  if (signature) {
856
972
  const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, formattedSignature);
857
973
  assertCurrent();
974
+ assertHardwareTransactionSender(signedTx, activeAccount.address);
858
975
  const transactionResponse = await provider.sendTransaction(signedTx);
859
976
  return {
860
977
  isCanceled: true,
@@ -908,7 +1025,8 @@ class EthereumTransactions {
908
1025
  ? formattedTx.maxPriorityFeePerGas
909
1026
  : this.toHex0x(formattedTx.maxPriorityFeePerGas, 'maxPriorityFeePerGas');
910
1027
  }
911
- const signature = await this.trezorSigner.signEthTransaction({
1028
+ assertApprovedEnvelope(txFormattedForTrezor);
1029
+ const signature = await this.requireTrezorSigner().signEthTransaction({
912
1030
  coin: trezorCoin,
913
1031
  tx: txFormattedForTrezor,
914
1032
  index: activeAccountId.toString(),
@@ -916,8 +1034,9 @@ class EthereumTransactions {
916
1034
  });
917
1035
  assertCurrent();
918
1036
  if (signature.success) {
919
- const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForTrezor, signature.payload);
1037
+ const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForTrezor, trezorSignature(signature.payload));
920
1038
  assertCurrent();
1039
+ assertHardwareTransactionSender(signedTx, activeAccount.address);
921
1040
  const transactionResponse = await provider.sendTransaction(signedTx);
922
1041
  return {
923
1042
  isCanceled: true,
@@ -942,11 +1061,11 @@ class EthereumTransactions {
942
1061
  const cancelWithPrivateKey = async () => {
943
1062
  try {
944
1063
  assertCurrent();
945
- const { address, decryptedPrivateKey } = this.getDecryptedPrivateKey();
1064
+ const { address, decryptedPrivateKey } = this.getDecryptedPrivateKey(targetAccount);
946
1065
  if (address?.toLowerCase() !== activeAccount.address.toLowerCase()) {
947
1066
  throw new Error('Wallet signing context changed');
948
1067
  }
949
- const transactionResponse = await (0, evm_local_signer_1.sendLocalEvmTransaction)(provider, decryptedPrivateKey, changedTxToCancel, assertCurrent, assertCurrent);
1068
+ const transactionResponse = await (0, evm_local_signer_1.sendLocalEvmTransaction)(provider, decryptedPrivateKey, changedTxToCancel, assertCurrent, assertCurrent, assertApprovedEnvelope);
950
1069
  if (transactionResponse) {
951
1070
  return {
952
1071
  isCanceled: true,
@@ -1107,9 +1226,10 @@ class EthereumTransactions {
1107
1226
  type: 2, // Need explicit type for hardware wallet serialization
1108
1227
  };
1109
1228
  const rawTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers);
1110
- const signature = await this.ledgerSigner.evm.signEVMTransaction({
1229
+ const signature = await this.requireLedgerSigner().evm.signEVMTransaction({
1111
1230
  rawTx: rawTx.replace('0x', ''),
1112
1231
  accountIndex: activeAccountId,
1232
+ expectedAddress: activeAccount.address,
1113
1233
  });
1114
1234
  assertCurrent();
1115
1235
  const formattedSignature = {
@@ -1120,6 +1240,7 @@ class EthereumTransactions {
1120
1240
  if (signature) {
1121
1241
  try {
1122
1242
  const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, formattedSignature);
1243
+ assertHardwareTransactionSender(signedTx, activeAccount.address);
1123
1244
  assertBeforeBroadcast();
1124
1245
  const finalTx = await provider.sendTransaction(signedTx);
1125
1246
  return finalTx;
@@ -1180,7 +1301,7 @@ class EthereumTransactions {
1180
1301
  };
1181
1302
  break;
1182
1303
  }
1183
- const signature = await this.trezorSigner.signEthTransaction({
1304
+ const signature = await this.requireTrezorSigner().signEthTransaction({
1184
1305
  index: `${activeAccountId}`,
1185
1306
  tx: txFormattedForTrezor,
1186
1307
  coin: activeNetwork.currency,
@@ -1202,8 +1323,8 @@ class EthereumTransactions {
1202
1323
  chainId: activeNetwork.chainId,
1203
1324
  type: 2, // Need explicit type for hardware wallet serialization
1204
1325
  };
1205
- signature.payload.v = parseInt(signature.payload.v, 16); //v parameter must be a number by ethers standards
1206
- const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, signature.payload);
1326
+ const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, trezorSignature(signature.payload));
1327
+ assertHardwareTransactionSender(signedTx, activeAccount.address);
1207
1328
  assertBeforeBroadcast();
1208
1329
  const finalTx = await provider.sendTransaction(signedTx);
1209
1330
  return finalTx;
@@ -1252,6 +1373,8 @@ class EthereumTransactions {
1252
1373
  this.sendTransactionWithEditedFee = async (txHash, isLegacy = false, options = {}) => {
1253
1374
  const { assertCurrentContext, validateOriginal, beforeBroadcast, approvedMaximumFee, } = options;
1254
1375
  const previewOnly = options.previewOnly === true;
1376
+ if (!previewOnly)
1377
+ this.assertHardwareSignerAvailable(options.targetAccount);
1255
1378
  if (!previewOnly &&
1256
1379
  (typeof approvedMaximumFee !== 'string' ||
1257
1380
  !/^\d{1,78}$/.test(approvedMaximumFee))) {
@@ -1366,7 +1489,6 @@ class EthereumTransactions {
1366
1489
  newGasValues.maxPriorityFeePerGas.gt(newGasValues.maxFeePerGas))
1367
1490
  throw new Error('Invalid replacement fee');
1368
1491
  const maximumFee = newGasValues.gasLimit.mul(isLegacy ? newGasValues.gasPrice : newGasValues.maxFeePerGas);
1369
- let adjustedValue = txValue;
1370
1492
  if (isLikelyMaxSend && txValue.add(maximumFee).gt(currentBalance)) {
1371
1493
  if (isContractCall) {
1372
1494
  console.error('[SpeedUp] Cannot adjust value for contract call - rejecting speedup');
@@ -1377,16 +1499,19 @@ class EthereumTransactions {
1377
1499
  message: 'Cannot speed up a likely max-send contract call; value cannot be adjusted to fit new gas',
1378
1500
  };
1379
1501
  }
1380
- adjustedValue = currentBalance.gt(maximumFee)
1381
- ? currentBalance.sub(maximumFee)
1382
- : ethers_v6_1.Zero;
1502
+ return {
1503
+ isSpeedUp: false,
1504
+ error: true,
1505
+ code: 'REPLACEMENT_VALUE_WOULD_CHANGE',
1506
+ message: 'Add funds before speeding up this transaction; the original amount will not be changed',
1507
+ };
1383
1508
  }
1384
1509
  const txWithEditedFee = {
1385
1510
  chainId: activeNetwork.chainId,
1386
1511
  from: tx.from,
1387
1512
  to: tx.to,
1388
1513
  nonce: tx.nonce,
1389
- value: adjustedValue,
1514
+ value: txValue,
1390
1515
  data: txData,
1391
1516
  gasLimit: newGasValues.gasLimit,
1392
1517
  ...(tx.accessList != null ? { accessList: tx.accessList } : {}),
@@ -1424,9 +1549,10 @@ class EthereumTransactions {
1424
1549
  };
1425
1550
  const rawTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers);
1426
1551
  assertCurrent();
1427
- const signature = await this.ledgerSigner.evm.signEVMTransaction({
1552
+ const signature = await this.requireLedgerSigner().evm.signEVMTransaction({
1428
1553
  rawTx: rawTx.replace('0x', ''),
1429
1554
  accountIndex: activeAccountId,
1555
+ expectedAddress: activeAccount.address,
1430
1556
  });
1431
1557
  const formattedSignature = {
1432
1558
  r: `0x${signature.r}`,
@@ -1436,6 +1562,7 @@ class EthereumTransactions {
1436
1562
  if (signature) {
1437
1563
  const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, formattedSignature);
1438
1564
  assertSignedSender(signedTx);
1565
+ assertHardwareTransactionSender(signedTx, activeAccount.address);
1439
1566
  assertBeforeBroadcast();
1440
1567
  const transactionResponse = await provider.sendTransaction(signedTx);
1441
1568
  return {
@@ -1505,15 +1632,16 @@ class EthereumTransactions {
1505
1632
  : this.toHex0x(formattedTx.maxPriorityFeePerGas, 'maxPriorityFeePerGas');
1506
1633
  }
1507
1634
  assertCurrent();
1508
- const signature = await this.trezorSigner.signEthTransaction({
1635
+ const signature = await this.requireTrezorSigner().signEthTransaction({
1509
1636
  coin: trezorCoin,
1510
1637
  tx: txFormattedForTrezor,
1511
1638
  index: activeAccountId.toString(),
1512
1639
  slip44: activeNetwork.slip44,
1513
1640
  });
1514
1641
  if (signature.success) {
1515
- const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForTrezor, signature.payload);
1642
+ const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForTrezor, trezorSignature(signature.payload));
1516
1643
  assertSignedSender(signedTx);
1644
+ assertHardwareTransactionSender(signedTx, activeAccount.address);
1517
1645
  assertBeforeBroadcast();
1518
1646
  const transactionResponse = await provider.sendTransaction(signedTx);
1519
1647
  return {
@@ -1688,9 +1816,10 @@ class EthereumTransactions {
1688
1816
  };
1689
1817
  }
1690
1818
  const rawTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers);
1691
- const signature = await this.ledgerSigner.evm.signEVMTransaction({
1819
+ const signature = await this.requireLedgerSigner().evm.signEVMTransaction({
1692
1820
  rawTx: rawTx.replace('0x', ''),
1693
1821
  accountIndex: activeAccountId,
1822
+ expectedAddress: activeAccount.address,
1694
1823
  });
1695
1824
  assertCurrent();
1696
1825
  const formattedSignature = {
@@ -1702,6 +1831,7 @@ class EthereumTransactions {
1702
1831
  try {
1703
1832
  const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, formattedSignature);
1704
1833
  assertCurrent();
1834
+ assertHardwareTransactionSender(signedTx, activeAccount.address);
1705
1835
  const finalTx = await provider.sendTransaction(signedTx);
1706
1836
  saveTrezorTx && saveTrezorTx(finalTx);
1707
1837
  return finalTx;
@@ -1756,7 +1886,7 @@ class EthereumTransactions {
1756
1886
  data: txData,
1757
1887
  };
1758
1888
  }
1759
- const signature = await this.trezorSigner.signEthTransaction({
1889
+ const signature = await this.requireTrezorSigner().signEthTransaction({
1760
1890
  index: `${activeAccountId}`,
1761
1891
  tx: txToBeSignedByTrezor,
1762
1892
  coin: activeNetwork.currency,
@@ -1791,9 +1921,9 @@ class EthereumTransactions {
1791
1921
  type: 2, // Need explicit type for hardware wallet serialization
1792
1922
  };
1793
1923
  }
1794
- signature.payload.v = parseInt(signature.payload.v, 16); //v parameter must be a number by ethers standards
1795
- const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, signature.payload);
1924
+ const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, trezorSignature(signature.payload));
1796
1925
  assertCurrent();
1926
+ assertHardwareTransactionSender(signedTx, activeAccount.address);
1797
1927
  const finalTx = await provider.sendTransaction(signedTx);
1798
1928
  saveTrezorTx && saveTrezorTx(finalTx);
1799
1929
  return finalTx;
@@ -1909,9 +2039,10 @@ class EthereumTransactions {
1909
2039
  };
1910
2040
  }
1911
2041
  const rawTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers);
1912
- const signature = await this.ledgerSigner.evm.signEVMTransaction({
2042
+ const signature = await this.requireLedgerSigner().evm.signEVMTransaction({
1913
2043
  rawTx: rawTx.replace('0x', ''),
1914
2044
  accountIndex: activeAccountId,
2045
+ expectedAddress: activeAccount.address,
1915
2046
  });
1916
2047
  assertCurrent();
1917
2048
  const formattedSignature = {
@@ -1923,6 +2054,7 @@ class EthereumTransactions {
1923
2054
  try {
1924
2055
  const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, formattedSignature);
1925
2056
  assertCurrent();
2057
+ assertHardwareTransactionSender(signedTx, activeAccount.address);
1926
2058
  const finalTx = await provider.sendTransaction(signedTx);
1927
2059
  return finalTx;
1928
2060
  }
@@ -1978,7 +2110,7 @@ class EthereumTransactions {
1978
2110
  }
1979
2111
  // For EVM networks, Trezor expects 'eth' regardless of the network's currency
1980
2112
  const trezorCoin = activeNetwork.slip44 === 60 ? 'eth' : activeNetwork.currency;
1981
- const signature = await this.trezorSigner.signEthTransaction({
2113
+ const signature = await this.requireTrezorSigner().signEthTransaction({
1982
2114
  index: `${activeAccountId}`,
1983
2115
  tx: txToBeSignedByTrezor,
1984
2116
  coin: trezorCoin,
@@ -2013,9 +2145,9 @@ class EthereumTransactions {
2013
2145
  type: 2, // Need explicit type for hardware wallet serialization
2014
2146
  };
2015
2147
  }
2016
- signature.payload.v = parseInt(signature.payload.v, 16); //v parameter must be a number by ethers standards
2017
- const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, signature.payload);
2148
+ const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, trezorSignature(signature.payload));
2018
2149
  assertCurrent();
2150
+ assertHardwareTransactionSender(signedTx, activeAccount.address);
2019
2151
  const finalTx = await provider.sendTransaction(signedTx);
2020
2152
  return finalTx;
2021
2153
  }
@@ -2127,9 +2259,10 @@ class EthereumTransactions {
2127
2259
  };
2128
2260
  }
2129
2261
  const rawTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers);
2130
- const signature = await this.ledgerSigner.evm.signEVMTransaction({
2262
+ const signature = await this.requireLedgerSigner().evm.signEVMTransaction({
2131
2263
  rawTx: rawTx.replace('0x', ''),
2132
2264
  accountIndex: activeAccountId,
2265
+ expectedAddress: activeAccount.address,
2133
2266
  });
2134
2267
  assertCurrent();
2135
2268
  const formattedSignature = {
@@ -2141,6 +2274,7 @@ class EthereumTransactions {
2141
2274
  try {
2142
2275
  const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, formattedSignature);
2143
2276
  assertCurrent();
2277
+ assertHardwareTransactionSender(signedTx, activeAccount.address);
2144
2278
  const finalTx = await provider.sendTransaction(signedTx);
2145
2279
  return finalTx;
2146
2280
  }
@@ -2190,7 +2324,7 @@ class EthereumTransactions {
2190
2324
  data: txData,
2191
2325
  };
2192
2326
  }
2193
- const signature = await this.trezorSigner.signEthTransaction({
2327
+ const signature = await this.requireTrezorSigner().signEthTransaction({
2194
2328
  index: `${activeAccountId}`,
2195
2329
  tx: txToBeSignedByTrezor,
2196
2330
  coin: activeNetwork.currency,
@@ -2225,9 +2359,9 @@ class EthereumTransactions {
2225
2359
  type: 2, // Need explicit type for hardware wallet serialization
2226
2360
  };
2227
2361
  }
2228
- signature.payload.v = parseInt(signature.payload.v, 16); //v parameter must be a number by ethers standards
2229
- const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, signature.payload);
2362
+ const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, trezorSignature(signature.payload));
2230
2363
  assertCurrent();
2364
+ assertHardwareTransactionSender(signedTx, activeAccount.address);
2231
2365
  const finalTx = await provider.sendTransaction(signedTx);
2232
2366
  return finalTx;
2233
2367
  }
@@ -2403,7 +2537,10 @@ class EthereumTransactions {
2403
2537
  };
2404
2538
  };
2405
2539
  this.getNetwork = getNetwork;
2406
- this.getDecryptedPrivateKey = getDecryptedPrivateKey;
2540
+ this.getDecryptedPrivateKey = (targetAccount) => {
2541
+ this.assertHardwareSignerAvailable(targetAccount);
2542
+ return getDecryptedPrivateKey(targetAccount);
2543
+ };
2407
2544
  this.abortController = new AbortController();
2408
2545
  // NOTE: Defer network access until vault state getter is initialized
2409
2546
  // The web3Provider will be created lazily when first accessed via getters