@sidhujag/sysweb3-keyring 1.0.619 → 1.0.621
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.
- package/cjs/keyring-manager.js +1 -1
- package/cjs/keyring-manager.js.map +1 -1
- package/cjs/transactions/ethereum.js +145 -64
- package/cjs/transactions/ethereum.js.map +1 -1
- package/cjs/transactions/syscoin.js +25 -9
- package/cjs/transactions/syscoin.js.map +1 -1
- package/cjs/types.js.map +1 -1
- package/cjs/utils/excluded-utxos.js +59 -0
- package/cjs/utils/excluded-utxos.js.map +1 -0
- package/package.json +1 -1
- package/types/keyring-manager.d.ts +1 -1
- package/types/transactions/ethereum.d.ts +3 -1
- package/types/transactions/syscoin.d.ts +3 -1
- package/types/types.d.ts +6 -1
- package/types/utils/excluded-utxos.d.ts +13 -0
|
@@ -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
|
|
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
|
|
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
|
|
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
|
-
|
|
876
|
-
|
|
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
|
|
954
|
+
params.gasLimit = await provider.estimateGas(txForEstimation);
|
|
955
|
+
assertCurrent();
|
|
915
956
|
}
|
|
916
957
|
if (isLegacy) {
|
|
917
958
|
if (!params.gasPrice) {
|
|
918
|
-
params.gasPrice = await
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
971
|
-
const finalTx = await
|
|
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
|
-
|
|
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
|
-
|
|
1052
|
-
const finalTx = await
|
|
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)(
|
|
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 {
|
|
1479
|
-
const
|
|
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)(),
|
|
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
|
|
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
|
|
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)(
|
|
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
|
-
|
|
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)(),
|
|
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
|
-
|
|
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
|
-
|
|
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)(),
|
|
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
|
-
|
|
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 {
|
|
1690
|
-
const
|
|
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)(),
|
|
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
|
|
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
|
|
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)(
|
|
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
|
-
|
|
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)(),
|
|
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
|
-
|
|
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
|
-
|
|
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)(),
|
|
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
|
-
|
|
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 {
|
|
1903
|
-
const
|
|
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)(),
|
|
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
|
|
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
|
|
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)(
|
|
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
|
-
|
|
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)(),
|
|
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
|
-
|
|
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
|
-
|
|
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)(),
|
|
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
|
-
|
|
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() {
|