@sidhujag/sysweb3-keyring 1.0.618 → 1.0.620

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.
@@ -80,9 +80,43 @@ const normalizeEthersOverrides = (overrides) => {
80
80
  return normalized;
81
81
  };
82
82
  class EthereumTransactions {
83
- constructor(getNetwork, getDecryptedPrivateKey, getState, ledgerSigner, trezorSigner) {
83
+ constructor(getNetwork, getDecryptedPrivateKey, getState, ledgerSigner, trezorSigner, captureSigningContext) {
84
84
  // Allow manual override of gas parameters when automatic estimation fails
85
85
  this.gasOverrides = {};
86
+ this.captureEvmSigningContext = () => {
87
+ const { activeAccountType, activeAccountId, accounts, activeNetwork } = this.getState();
88
+ const selectedAccount = accounts[activeAccountType]?.[activeAccountId];
89
+ if (!selectedAccount)
90
+ throw new Error('Active account not found');
91
+ const account = { address: selectedAccount.address };
92
+ const network = { ...activeNetwork };
93
+ const assertSession = this.captureSigningContext?.();
94
+ const provider = this.web3Provider;
95
+ const assertCurrent = () => {
96
+ assertSession?.();
97
+ const current = this.getState();
98
+ const currentAccount = current.accounts[current.activeAccountType]?.[current.activeAccountId];
99
+ if (current.activeAccountId !== activeAccountId ||
100
+ current.activeAccountType !== activeAccountType ||
101
+ currentAccount?.address?.toLowerCase() !==
102
+ account.address.toLowerCase() ||
103
+ [current.activeNetwork, this.getNetwork()].some((selected) => selected.kind !== network.kind ||
104
+ selected.chainId !== network.chainId ||
105
+ selected.slip44 !== network.slip44 ||
106
+ selected.url !== network.url) ||
107
+ this.web3Provider !== provider)
108
+ throw new Error('Wallet signing context changed');
109
+ };
110
+ assertCurrent();
111
+ return {
112
+ activeAccount: account,
113
+ activeAccountType,
114
+ activeAccountId,
115
+ activeNetwork: network,
116
+ provider,
117
+ assertCurrent,
118
+ };
119
+ };
86
120
  this.signTypedData = async (addr, typedData, version) => {
87
121
  const { address, decryptedPrivateKey } = this.getDecryptedPrivateKey();
88
122
  const { activeAccountType, accounts, activeAccountId } = this.getState();
@@ -433,23 +467,23 @@ class EthereumTransactions {
433
467
  throw new Error(`Invalid numeric field "${fieldName}" for EVM tx: ${String(value)}`);
434
468
  }
435
469
  };
436
- this.resolveEvmFeeParams = async ({ gasPrice, isLegacy = false, maxFeePerGas, maxPriorityFeePerGas, }) => {
470
+ this.resolveEvmFeeParams = async ({ gasPrice, isLegacy = false, maxFeePerGas, maxPriorityFeePerGas, }, provider = this.web3Provider) => {
437
471
  if (isLegacy) {
438
472
  return {
439
- gasPrice: gasPrice || (await this.web3Provider.getGasPrice()),
473
+ gasPrice: gasPrice || (await provider.getGasPrice()),
440
474
  isLegacy: true,
441
475
  maxFeePerGas: undefined,
442
476
  maxPriorityFeePerGas: undefined,
443
477
  };
444
478
  }
445
479
  if (!maxFeePerGas || maxPriorityFeePerGas == null) {
446
- const feeData = await this.web3Provider.getFeeData();
480
+ const feeData = await provider.getFeeData();
447
481
  maxFeePerGas = maxFeePerGas || feeData.maxFeePerGas || feeData.gasPrice;
448
482
  maxPriorityFeePerGas =
449
483
  maxPriorityFeePerGas ?? feeData.maxPriorityFeePerGas;
450
484
  if (!maxFeePerGas || maxPriorityFeePerGas == null) {
451
485
  return {
452
- gasPrice: feeData.gasPrice || (await this.web3Provider.getGasPrice()),
486
+ gasPrice: feeData.gasPrice || (await provider.getGasPrice()),
453
487
  isLegacy: true,
454
488
  maxFeePerGas: undefined,
455
489
  maxPriorityFeePerGas: undefined,
@@ -872,8 +906,14 @@ class EthereumTransactions {
872
906
  }
873
907
  };
874
908
  this.sendFormattedTransactionInternal = async (params, isLegacy, beforeBroadcast) => {
875
- const { activeAccountType, activeAccountId, accounts, activeNetwork } = this.getState();
876
- const activeAccount = accounts[activeAccountType][activeAccountId];
909
+ // Hardware approval may outlive the selected account, network or unlocked
910
+ // session. Keep immutable identities and one provider for this invocation.
911
+ const { activeAccount, activeAccountType, activeAccountId, activeNetwork, provider, assertCurrent, } = this.captureEvmSigningContext();
912
+ const assertBeforeBroadcast = () => {
913
+ assertCurrent();
914
+ beforeBroadcast();
915
+ };
916
+ assertCurrent();
877
917
  const explicitEip1559 = params.type != null && ethers_v6_1.BigNumber.from(params.type).eq(2);
878
918
  const requestedEip1559 = explicitEip1559 ||
879
919
  params.maxFeePerGas != null ||
@@ -911,16 +951,19 @@ class EthereumTransactions {
911
951
  from: params.from || activeAccount.address,
912
952
  }, ['gasPrice']);
913
953
  if (!params.gasLimit) {
914
- params.gasLimit = await this.web3Provider.estimateGas(txForEstimation);
954
+ params.gasLimit = await provider.estimateGas(txForEstimation);
955
+ assertCurrent();
915
956
  }
916
957
  if (isLegacy) {
917
958
  if (!params.gasPrice) {
918
- params.gasPrice = await this.web3Provider.getGasPrice();
959
+ params.gasPrice = await provider.getGasPrice();
960
+ assertCurrent();
919
961
  }
920
962
  }
921
963
  else if (params.maxFeePerGas == null ||
922
964
  params.maxPriorityFeePerGas == null) {
923
- const feeData = await this.web3Provider.getFeeData();
965
+ const feeData = await provider.getFeeData();
966
+ assertCurrent();
924
967
  params.maxFeePerGas = params.maxFeePerGas ?? feeData.maxFeePerGas;
925
968
  params.maxPriorityFeePerGas =
926
969
  params.maxPriorityFeePerGas ?? feeData.maxPriorityFeePerGas;
@@ -928,8 +971,8 @@ class EthereumTransactions {
928
971
  if (requestedEip1559)
929
972
  throw new Error('EIP-1559 fee data unavailable');
930
973
  isLegacy = true;
931
- params.gasPrice =
932
- feeData.gasPrice ?? (await this.web3Provider.getGasPrice());
974
+ params.gasPrice = feeData.gasPrice ?? (await provider.getGasPrice());
975
+ assertCurrent();
933
976
  delete params.maxFeePerGas;
934
977
  delete params.maxPriorityFeePerGas;
935
978
  }
@@ -937,7 +980,9 @@ class EthereumTransactions {
937
980
  if (!isLegacy)
938
981
  validateEip1559Fees();
939
982
  const sendEVMLedgerTransaction = async () => {
940
- const transactionNonce = await this.getRecommendedNonce(activeAccount.address);
983
+ assertCurrent();
984
+ const transactionNonce = await provider.getTransactionCount(activeAccount.address, 'pending');
985
+ assertCurrent();
941
986
  const formatParams = isLegacy
942
987
  ? (0, omit_1.default)(params, 'from')
943
988
  : (0, omit_1.default)(params, ['from', 'gasPrice']); // Strip gasPrice for EIP-1559
@@ -959,6 +1004,7 @@ class EthereumTransactions {
959
1004
  rawTx: rawTx.replace('0x', ''),
960
1005
  accountIndex: activeAccountId,
961
1006
  });
1007
+ assertCurrent();
962
1008
  const formattedSignature = {
963
1009
  r: `0x${signature.r}`,
964
1010
  s: `0x${signature.s}`,
@@ -967,8 +1013,8 @@ class EthereumTransactions {
967
1013
  if (signature) {
968
1014
  try {
969
1015
  const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, formattedSignature);
970
- beforeBroadcast();
971
- const finalTx = await this.web3Provider.sendTransaction(signedTx);
1016
+ assertBeforeBroadcast();
1017
+ const finalTx = await provider.sendTransaction(signedTx);
972
1018
  return finalTx;
973
1019
  }
974
1020
  catch (error) {
@@ -980,7 +1026,9 @@ class EthereumTransactions {
980
1026
  }
981
1027
  };
982
1028
  const sendEVMTrezorTransaction = async () => {
983
- const transactionNonce = await this.getRecommendedNonce(activeAccount.address);
1029
+ assertCurrent();
1030
+ const transactionNonce = await provider.getTransactionCount(activeAccount.address, 'pending');
1031
+ assertCurrent();
984
1032
  let txFormattedForTrezor = {};
985
1033
  const formatParams = isLegacy
986
1034
  ? (0, omit_1.default)(params, 'from')
@@ -1031,6 +1079,7 @@ class EthereumTransactions {
1031
1079
  coin: activeNetwork.currency,
1032
1080
  slip44: activeNetwork.slip44,
1033
1081
  });
1082
+ assertCurrent();
1034
1083
  if (signature.success) {
1035
1084
  try {
1036
1085
  const txFormattedForEthers = isLegacy
@@ -1048,8 +1097,8 @@ class EthereumTransactions {
1048
1097
  };
1049
1098
  signature.payload.v = parseInt(signature.payload.v, 16); //v parameter must be a number by ethers standards
1050
1099
  const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, signature.payload);
1051
- beforeBroadcast();
1052
- const finalTx = await this.web3Provider.sendTransaction(signedTx);
1100
+ assertBeforeBroadcast();
1101
+ const finalTx = await provider.sendTransaction(signedTx);
1053
1102
  return finalTx;
1054
1103
  }
1055
1104
  catch (error) {
@@ -1061,6 +1110,7 @@ class EthereumTransactions {
1061
1110
  }
1062
1111
  };
1063
1112
  const sendEVMTransaction = async () => {
1113
+ assertCurrent();
1064
1114
  const { address, decryptedPrivateKey } = this.getDecryptedPrivateKey();
1065
1115
  // Validate that we have the correct private key for the active account to prevent race conditions
1066
1116
  // This is critical for transaction security during account switches
@@ -1073,7 +1123,7 @@ class EthereumTransactions {
1073
1123
  ? { ...params, type: 0 } // Force Type 0 for legacy transactions
1074
1124
  : (0, omit_1.default)(params, ['gasPrice']); // Strip gasPrice for EIP-1559
1075
1125
  try {
1076
- const transaction = await (0, evm_local_signer_1.sendLocalEvmTransaction)(this.web3Provider, decryptedPrivateKey, tx, beforeBroadcast);
1126
+ const transaction = await (0, evm_local_signer_1.sendLocalEvmTransaction)(provider, decryptedPrivateKey, tx, assertBeforeBroadcast, assertCurrent);
1077
1127
  // The broadcast response already has the hash. Pending transactions
1078
1128
  // have no block number, so a block lookup can fail after a successful
1079
1129
  // broadcast and incorrectly report the send as failed.
@@ -1475,26 +1525,28 @@ class EthereumTransactions {
1475
1525
  }
1476
1526
  };
1477
1527
  this.sendSignedErc20Transaction = async ({ receiver, tokenAddress, tokenAmount, isLegacy = false, maxPriorityFeePerGas, maxFeePerGas, gasPrice, decimals, gasLimit, saveTrezorTx, }) => {
1478
- const { decryptedPrivateKey } = this.getDecryptedPrivateKey();
1479
- const { accounts, activeAccountType, activeAccountId, activeNetwork } = this.getState();
1480
- const { address: activeAccountAddress } = accounts[activeAccountType][activeAccountId];
1528
+ const { activeAccount, activeAccountType, activeAccountId, activeNetwork, provider, assertCurrent, } = this.captureEvmSigningContext();
1529
+ const activeAccountAddress = activeAccount.address;
1481
1530
  ({ gasPrice, isLegacy, maxFeePerGas, maxPriorityFeePerGas } =
1482
1531
  await this.resolveEvmFeeParams({
1483
1532
  gasPrice,
1484
1533
  isLegacy,
1485
1534
  maxFeePerGas,
1486
1535
  maxPriorityFeePerGas,
1487
- }));
1536
+ }, provider));
1537
+ assertCurrent();
1488
1538
  const sendERC20Token = async () => {
1539
+ assertCurrent();
1540
+ const { decryptedPrivateKey } = this.getDecryptedPrivateKey();
1489
1541
  try {
1490
- const _contract = new ethers_v6_1.Contract(tokenAddress, (0, sysweb3_utils_1.getErc20Abi)(), this.web3Provider);
1542
+ const _contract = new ethers_v6_1.Contract(tokenAddress, (0, sysweb3_utils_1.getErc20Abi)(), provider);
1491
1543
  // Preserve zero-decimal tokens: use provided decimals when defined (including 0).
1492
1544
  const resolvedDecimals = decimals === undefined || decimals === null ? 18 : Number(decimals);
1493
1545
  const calculatedTokenAmount = (0, ethers_v6_1.parseUnits)(tokenAmount, resolvedDecimals).toBigInt();
1494
1546
  let transferMethod;
1495
1547
  if (isLegacy) {
1496
1548
  const overrides = {
1497
- nonce: await this.web3Provider.getTransactionCount(activeAccountAddress, 'pending'),
1549
+ nonce: await provider.getTransactionCount(activeAccountAddress, 'pending'),
1498
1550
  gasPrice,
1499
1551
  ...(gasLimit && { gasLimit }),
1500
1552
  type: 0, // Explicitly set Type 0 for legacy token transfers
@@ -1503,28 +1555,30 @@ class EthereumTransactions {
1503
1555
  }
1504
1556
  else {
1505
1557
  const overrides = {
1506
- nonce: await this.web3Provider.getTransactionCount(activeAccountAddress, 'pending'),
1558
+ nonce: await provider.getTransactionCount(activeAccountAddress, 'pending'),
1507
1559
  maxPriorityFeePerGas,
1508
1560
  maxFeePerGas,
1509
1561
  ...(gasLimit && { gasLimit }),
1510
1562
  };
1511
1563
  transferMethod = await _contract.transfer.populateTransaction(receiver, calculatedTokenAmount, normalizeEthersOverrides(overrides));
1512
1564
  }
1513
- return await (0, evm_local_signer_1.sendLocalEvmTransaction)(this.web3Provider, decryptedPrivateKey, {
1565
+ return await (0, evm_local_signer_1.sendLocalEvmTransaction)(provider, decryptedPrivateKey, {
1514
1566
  ...transferMethod,
1515
1567
  chainId: activeNetwork.chainId,
1516
1568
  from: activeAccountAddress,
1517
1569
  value: '0x0',
1518
- });
1570
+ }, assertCurrent, assertCurrent);
1519
1571
  }
1520
1572
  catch (error) {
1521
1573
  throw error;
1522
1574
  }
1523
1575
  };
1524
1576
  const sendERC20TokenOnLedger = async () => {
1525
- const transactionNonce = await this.getRecommendedNonce(activeAccountAddress);
1577
+ assertCurrent();
1578
+ const transactionNonce = await provider.getTransactionCount(activeAccountAddress, 'pending');
1579
+ assertCurrent();
1526
1580
  try {
1527
- const _contract = new ethers_v6_1.Contract(tokenAddress, (0, sysweb3_utils_1.getErc20Abi)(), this.web3Provider);
1581
+ const _contract = new ethers_v6_1.Contract(tokenAddress, (0, sysweb3_utils_1.getErc20Abi)(), provider);
1528
1582
  const resolvedDecimals = decimals === undefined || decimals === null ? 18 : Number(decimals);
1529
1583
  const calculatedTokenAmount = (0, ethers_v6_1.parseUnits)(tokenAmount, resolvedDecimals).toBigInt();
1530
1584
  const txData = _contract.interface.encodeFunctionData('transfer', [
@@ -1564,6 +1618,7 @@ class EthereumTransactions {
1564
1618
  rawTx: rawTx.replace('0x', ''),
1565
1619
  accountIndex: activeAccountId,
1566
1620
  });
1621
+ assertCurrent();
1567
1622
  const formattedSignature = {
1568
1623
  r: `0x${signature.r}`,
1569
1624
  s: `0x${signature.s}`,
@@ -1572,7 +1627,8 @@ class EthereumTransactions {
1572
1627
  if (signature) {
1573
1628
  try {
1574
1629
  const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, formattedSignature);
1575
- const finalTx = await this.web3Provider.sendTransaction(signedTx);
1630
+ assertCurrent();
1631
+ const finalTx = await provider.sendTransaction(signedTx);
1576
1632
  saveTrezorTx && saveTrezorTx(finalTx);
1577
1633
  return finalTx;
1578
1634
  }
@@ -1589,9 +1645,11 @@ class EthereumTransactions {
1589
1645
  }
1590
1646
  };
1591
1647
  const sendERC20TokenOnTrezor = async () => {
1592
- const transactionNonce = await this.getRecommendedNonce(activeAccountAddress);
1648
+ assertCurrent();
1649
+ const transactionNonce = await provider.getTransactionCount(activeAccountAddress, 'pending');
1650
+ assertCurrent();
1593
1651
  try {
1594
- const _contract = new ethers_v6_1.Contract(tokenAddress, (0, sysweb3_utils_1.getErc20Abi)(), this.web3Provider);
1652
+ const _contract = new ethers_v6_1.Contract(tokenAddress, (0, sysweb3_utils_1.getErc20Abi)(), provider);
1595
1653
  const resolvedDecimals = decimals === undefined || decimals === null ? 18 : Number(decimals);
1596
1654
  const calculatedTokenAmount = (0, ethers_v6_1.parseUnits)(tokenAmount, resolvedDecimals).toBigInt();
1597
1655
  const txData = _contract.interface.encodeFunctionData('transfer', [
@@ -1630,6 +1688,7 @@ class EthereumTransactions {
1630
1688
  coin: activeNetwork.currency,
1631
1689
  slip44: activeNetwork.slip44,
1632
1690
  });
1691
+ assertCurrent();
1633
1692
  if (signature.success) {
1634
1693
  try {
1635
1694
  let txFormattedForEthers;
@@ -1660,7 +1719,8 @@ class EthereumTransactions {
1660
1719
  }
1661
1720
  signature.payload.v = parseInt(signature.payload.v, 16); //v parameter must be a number by ethers standards
1662
1721
  const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, signature.payload);
1663
- const finalTx = await this.web3Provider.sendTransaction(signedTx);
1722
+ assertCurrent();
1723
+ const finalTx = await provider.sendTransaction(signedTx);
1664
1724
  saveTrezorTx && saveTrezorTx(finalTx);
1665
1725
  return finalTx;
1666
1726
  }
@@ -1686,9 +1746,8 @@ class EthereumTransactions {
1686
1746
  }
1687
1747
  };
1688
1748
  this.sendSignedErc721Transaction = async ({ receiver, tokenAddress, tokenId, isLegacy, maxPriorityFeePerGas, maxFeePerGas, gasPrice, gasLimit, }) => {
1689
- const { decryptedPrivateKey } = this.getDecryptedPrivateKey();
1690
- const { accounts, activeAccountType, activeAccountId, activeNetwork } = this.getState();
1691
- const { address: activeAccountAddress } = accounts[activeAccountType][activeAccountId];
1749
+ const { activeAccount, activeAccountType, activeAccountId, activeNetwork, provider, assertCurrent, } = this.captureEvmSigningContext();
1750
+ const activeAccountAddress = activeAccount.address;
1692
1751
  if (tokenId === undefined || tokenId === null) {
1693
1752
  throw new Error('ERC721 tokenId is required');
1694
1753
  }
@@ -1698,15 +1757,18 @@ class EthereumTransactions {
1698
1757
  isLegacy,
1699
1758
  maxFeePerGas,
1700
1759
  maxPriorityFeePerGas,
1701
- }));
1760
+ }, provider));
1761
+ assertCurrent();
1702
1762
  const normalizedTokenId = ethers_v6_1.BigNumber.from(tokenId).toBigInt();
1703
1763
  const sendERC721Token = async () => {
1764
+ assertCurrent();
1765
+ const { decryptedPrivateKey } = this.getDecryptedPrivateKey();
1704
1766
  let transferMethod;
1705
1767
  try {
1706
- const _contract = new ethers_v6_1.Contract(tokenAddress, (0, sysweb3_utils_1.getErc21Abi)(), this.web3Provider);
1768
+ const _contract = new ethers_v6_1.Contract(tokenAddress, (0, sysweb3_utils_1.getErc21Abi)(), provider);
1707
1769
  if (isLegacy) {
1708
1770
  const overrides = {
1709
- nonce: await this.web3Provider.getTransactionCount(activeAccountAddress, 'pending'),
1771
+ nonce: await provider.getTransactionCount(activeAccountAddress, 'pending'),
1710
1772
  gasPrice,
1711
1773
  ...(gasLimit && { gasLimit }),
1712
1774
  type: 0, // Explicitly set Type 0 for legacy NFT transfers
@@ -1715,28 +1777,30 @@ class EthereumTransactions {
1715
1777
  }
1716
1778
  else {
1717
1779
  const overrides = {
1718
- nonce: await this.web3Provider.getTransactionCount(activeAccountAddress, 'pending'),
1780
+ nonce: await provider.getTransactionCount(activeAccountAddress, 'pending'),
1719
1781
  maxPriorityFeePerGas,
1720
1782
  maxFeePerGas,
1721
1783
  ...(gasLimit && { gasLimit }),
1722
1784
  };
1723
1785
  transferMethod = await _contract.transferFrom.populateTransaction(activeAccountAddress, receiver, normalizedTokenId, normalizeEthersOverrides(overrides));
1724
1786
  }
1725
- return await (0, evm_local_signer_1.sendLocalEvmTransaction)(this.web3Provider, decryptedPrivateKey, {
1787
+ return await (0, evm_local_signer_1.sendLocalEvmTransaction)(provider, decryptedPrivateKey, {
1726
1788
  ...transferMethod,
1727
1789
  chainId: activeNetwork.chainId,
1728
1790
  from: activeAccountAddress,
1729
1791
  value: '0x0',
1730
- });
1792
+ }, assertCurrent, assertCurrent);
1731
1793
  }
1732
1794
  catch (error) {
1733
1795
  throw error;
1734
1796
  }
1735
1797
  };
1736
1798
  const sendERC721TokenOnLedger = async () => {
1737
- const transactionNonce = await this.getRecommendedNonce(activeAccountAddress);
1799
+ assertCurrent();
1800
+ const transactionNonce = await provider.getTransactionCount(activeAccountAddress, 'pending');
1801
+ assertCurrent();
1738
1802
  try {
1739
- const _contract = new ethers_v6_1.Contract(tokenAddress, (0, sysweb3_utils_1.getErc21Abi)(), this.web3Provider);
1803
+ const _contract = new ethers_v6_1.Contract(tokenAddress, (0, sysweb3_utils_1.getErc21Abi)(), provider);
1740
1804
  const txData = _contract.interface.encodeFunctionData('transferFrom', [
1741
1805
  activeAccountAddress,
1742
1806
  receiver,
@@ -1775,6 +1839,7 @@ class EthereumTransactions {
1775
1839
  rawTx: rawTx.replace('0x', ''),
1776
1840
  accountIndex: activeAccountId,
1777
1841
  });
1842
+ assertCurrent();
1778
1843
  const formattedSignature = {
1779
1844
  r: `0x${signature.r}`,
1780
1845
  s: `0x${signature.s}`,
@@ -1783,7 +1848,8 @@ class EthereumTransactions {
1783
1848
  if (signature) {
1784
1849
  try {
1785
1850
  const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, formattedSignature);
1786
- const finalTx = await this.web3Provider.sendTransaction(signedTx);
1851
+ assertCurrent();
1852
+ const finalTx = await provider.sendTransaction(signedTx);
1787
1853
  return finalTx;
1788
1854
  }
1789
1855
  catch (error) {
@@ -1799,9 +1865,11 @@ class EthereumTransactions {
1799
1865
  }
1800
1866
  };
1801
1867
  const sendERC721TokenOnTrezor = async () => {
1802
- const transactionNonce = await this.getRecommendedNonce(activeAccountAddress);
1868
+ assertCurrent();
1869
+ const transactionNonce = await provider.getTransactionCount(activeAccountAddress, 'pending');
1870
+ assertCurrent();
1803
1871
  try {
1804
- const _contract = new ethers_v6_1.Contract(tokenAddress, (0, sysweb3_utils_1.getErc21Abi)(), this.web3Provider);
1872
+ const _contract = new ethers_v6_1.Contract(tokenAddress, (0, sysweb3_utils_1.getErc21Abi)(), provider);
1805
1873
  const txData = _contract.interface.encodeFunctionData('transferFrom', [
1806
1874
  activeAccountAddress,
1807
1875
  receiver,
@@ -1842,6 +1910,7 @@ class EthereumTransactions {
1842
1910
  coin: trezorCoin,
1843
1911
  slip44: activeNetwork.slip44,
1844
1912
  });
1913
+ assertCurrent();
1845
1914
  if (signature.success) {
1846
1915
  try {
1847
1916
  let txFormattedForEthers;
@@ -1872,7 +1941,8 @@ class EthereumTransactions {
1872
1941
  }
1873
1942
  signature.payload.v = parseInt(signature.payload.v, 16); //v parameter must be a number by ethers standards
1874
1943
  const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, signature.payload);
1875
- const finalTx = await this.web3Provider.sendTransaction(signedTx);
1944
+ assertCurrent();
1945
+ const finalTx = await provider.sendTransaction(signedTx);
1876
1946
  return finalTx;
1877
1947
  }
1878
1948
  catch (error) {
@@ -1899,26 +1969,28 @@ class EthereumTransactions {
1899
1969
  }
1900
1970
  };
1901
1971
  this.sendSignedErc1155Transaction = async ({ receiver, tokenAddress, tokenId, tokenAmount, isLegacy, maxPriorityFeePerGas, maxFeePerGas, gasPrice, gasLimit, }) => {
1902
- const { decryptedPrivateKey } = this.getDecryptedPrivateKey();
1903
- const { accounts, activeAccountType, activeAccountId, activeNetwork } = this.getState();
1904
- const { address: activeAccountAddress } = accounts[activeAccountType][activeAccountId];
1972
+ const { activeAccount, activeAccountType, activeAccountId, activeNetwork, provider, assertCurrent, } = this.captureEvmSigningContext();
1973
+ const activeAccountAddress = activeAccount.address;
1905
1974
  ({ gasPrice, isLegacy, maxFeePerGas, maxPriorityFeePerGas } =
1906
1975
  await this.resolveEvmFeeParams({
1907
1976
  gasPrice,
1908
1977
  isLegacy,
1909
1978
  maxFeePerGas,
1910
1979
  maxPriorityFeePerGas,
1911
- }));
1980
+ }, provider));
1981
+ assertCurrent();
1912
1982
  const sendERC1155Token = async () => {
1983
+ assertCurrent();
1984
+ const { decryptedPrivateKey } = this.getDecryptedPrivateKey();
1913
1985
  let transferMethod;
1914
1986
  try {
1915
- const _contract = new ethers_v6_1.Contract(tokenAddress, (0, sysweb3_utils_1.getErc55Abi)(), this.web3Provider);
1987
+ const _contract = new ethers_v6_1.Contract(tokenAddress, (0, sysweb3_utils_1.getErc55Abi)(), provider);
1916
1988
  // Use BigNumber to avoid JS number overflow/precision loss
1917
1989
  const amount = ethers_v6_1.BigNumber.from(tokenAmount ?? '1');
1918
1990
  let overrides;
1919
1991
  if (isLegacy) {
1920
1992
  overrides = {
1921
- nonce: await this.web3Provider.getTransactionCount(activeAccountAddress, 'pending'),
1993
+ nonce: await provider.getTransactionCount(activeAccountAddress, 'pending'),
1922
1994
  gasPrice,
1923
1995
  ...(gasLimit && { gasLimit }),
1924
1996
  type: 0, // Explicitly set Type 0 for legacy ERC1155 transfers
@@ -1926,28 +1998,30 @@ class EthereumTransactions {
1926
1998
  }
1927
1999
  else {
1928
2000
  overrides = {
1929
- nonce: await this.web3Provider.getTransactionCount(activeAccountAddress, 'pending'),
2001
+ nonce: await provider.getTransactionCount(activeAccountAddress, 'pending'),
1930
2002
  maxPriorityFeePerGas,
1931
2003
  maxFeePerGas,
1932
2004
  ...(gasLimit && { gasLimit }),
1933
2005
  };
1934
2006
  }
1935
2007
  transferMethod = await _contract.safeTransferFrom.populateTransaction(activeAccountAddress, receiver, tokenId, amount.toBigInt(), '0x', normalizeEthersOverrides(overrides));
1936
- return await (0, evm_local_signer_1.sendLocalEvmTransaction)(this.web3Provider, decryptedPrivateKey, {
2008
+ return await (0, evm_local_signer_1.sendLocalEvmTransaction)(provider, decryptedPrivateKey, {
1937
2009
  ...transferMethod,
1938
2010
  chainId: activeNetwork.chainId,
1939
2011
  from: activeAccountAddress,
1940
2012
  value: '0x0',
1941
- });
2013
+ }, assertCurrent, assertCurrent);
1942
2014
  }
1943
2015
  catch (error) {
1944
2016
  throw error;
1945
2017
  }
1946
2018
  };
1947
2019
  const sendERC1155TokenOnLedger = async () => {
1948
- const transactionNonce = await this.getRecommendedNonce(activeAccountAddress);
2020
+ assertCurrent();
2021
+ const transactionNonce = await provider.getTransactionCount(activeAccountAddress, 'pending');
2022
+ assertCurrent();
1949
2023
  try {
1950
- const _contract = new ethers_v6_1.Contract(tokenAddress, (0, sysweb3_utils_1.getErc55Abi)(), this.web3Provider);
2024
+ const _contract = new ethers_v6_1.Contract(tokenAddress, (0, sysweb3_utils_1.getErc55Abi)(), provider);
1951
2025
  const amount = ethers_v6_1.BigNumber.from(tokenAmount ?? '1');
1952
2026
  const txData = _contract.interface.encodeFunctionData('safeTransferFrom', [activeAccountAddress, receiver, tokenId, amount.toBigInt(), '0x']);
1953
2027
  // Use fallback gas limit if not provided (for auto-estimation)
@@ -1983,6 +2057,7 @@ class EthereumTransactions {
1983
2057
  rawTx: rawTx.replace('0x', ''),
1984
2058
  accountIndex: activeAccountId,
1985
2059
  });
2060
+ assertCurrent();
1986
2061
  const formattedSignature = {
1987
2062
  r: `0x${signature.r}`,
1988
2063
  s: `0x${signature.s}`,
@@ -1991,7 +2066,8 @@ class EthereumTransactions {
1991
2066
  if (signature) {
1992
2067
  try {
1993
2068
  const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, formattedSignature);
1994
- const finalTx = await this.web3Provider.sendTransaction(signedTx);
2069
+ assertCurrent();
2070
+ const finalTx = await provider.sendTransaction(signedTx);
1995
2071
  return finalTx;
1996
2072
  }
1997
2073
  catch (error) {
@@ -2007,9 +2083,11 @@ class EthereumTransactions {
2007
2083
  }
2008
2084
  };
2009
2085
  const sendERC1155TokenOnTrezor = async () => {
2010
- const transactionNonce = await this.getRecommendedNonce(activeAccountAddress);
2086
+ assertCurrent();
2087
+ const transactionNonce = await provider.getTransactionCount(activeAccountAddress, 'pending');
2088
+ assertCurrent();
2011
2089
  try {
2012
- const _contract = new ethers_v6_1.Contract(tokenAddress, (0, sysweb3_utils_1.getErc55Abi)(), this.web3Provider);
2090
+ const _contract = new ethers_v6_1.Contract(tokenAddress, (0, sysweb3_utils_1.getErc55Abi)(), provider);
2013
2091
  const amount = ethers_v6_1.BigNumber.from(tokenAmount ?? '1');
2014
2092
  const txData = _contract.interface.encodeFunctionData('safeTransferFrom', [activeAccountAddress, receiver, tokenId, amount.toBigInt(), '0x']);
2015
2093
  // Use fallback gas limit if not provided (for auto-estimation)
@@ -2044,6 +2122,7 @@ class EthereumTransactions {
2044
2122
  coin: activeNetwork.currency,
2045
2123
  slip44: activeNetwork.slip44,
2046
2124
  });
2125
+ assertCurrent();
2047
2126
  if (signature.success) {
2048
2127
  try {
2049
2128
  let txFormattedForEthers;
@@ -2074,7 +2153,8 @@ class EthereumTransactions {
2074
2153
  }
2075
2154
  signature.payload.v = parseInt(signature.payload.v, 16); //v parameter must be a number by ethers standards
2076
2155
  const signedTx = (0, ethers_v6_1.serializeTransaction)(txFormattedForEthers, signature.payload);
2077
- const finalTx = await this.web3Provider.sendTransaction(signedTx);
2156
+ assertCurrent();
2157
+ const finalTx = await provider.sendTransaction(signedTx);
2078
2158
  return finalTx;
2079
2159
  }
2080
2160
  catch (error) {
@@ -2256,6 +2336,7 @@ class EthereumTransactions {
2256
2336
  this.getState = getState;
2257
2337
  this.trezorSigner = trezorSigner;
2258
2338
  this.ledgerSigner = ledgerSigner;
2339
+ this.captureSigningContext = captureSigningContext;
2259
2340
  }
2260
2341
  // Getter that automatically ensures providers are initialized when accessed
2261
2342
  get web3Provider() {