@sidhujag/sysweb3-keyring 2.1.1 → 2.1.3
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/CHANGELOG.md +5 -2
- package/README.md +8 -0
- package/cjs/current-vault-refusal.js +6 -0
- package/cjs/current-vault-refusal.js.map +1 -0
- package/cjs/evm-fees.js +29 -1
- package/cjs/evm-fees.js.map +1 -1
- package/cjs/keyring-core.js +349 -84
- package/cjs/keyring-core.js.map +1 -1
- package/cjs/keyring-manager.js +100 -4
- package/cjs/keyring-manager.js.map +1 -1
- package/cjs/software.js +14 -1
- package/cjs/software.js.map +1 -1
- package/cjs/storage-core.js +44 -4
- package/cjs/storage-core.js.map +1 -1
- package/cjs/transactions/ethereum.js +138 -82
- package/cjs/transactions/ethereum.js.map +1 -1
- package/cjs/transactions/evm-cancellation.js +43 -0
- package/cjs/transactions/evm-cancellation.js.map +1 -0
- package/cjs/transactions/evm-local-signer.js +4 -2
- package/cjs/transactions/evm-local-signer.js.map +1 -1
- package/cjs/transactions/evm-submission.js +23 -2
- package/cjs/transactions/evm-submission.js.map +1 -1
- package/cjs/transactions/prepared-evm.js +3 -6
- package/cjs/transactions/prepared-evm.js.map +1 -1
- package/esm/ledger/dmk-host.js +31 -0
- package/esm/ledger/dmk-host.js.map +1 -0
- package/esm/ledger/dmk-selected-host.js +6 -0
- package/esm/ledger/dmk-selected-host.js.map +1 -0
- package/esm/ledger/dmk-session.js +153 -34
- package/esm/ledger/dmk-session.js.map +1 -1
- package/esm/ledger-host.js +3 -27
- package/esm/ledger-host.js.map +1 -1
- package/package.json +13 -1
- package/types/current-vault-refusal.d.ts +2 -0
- package/types/evm-fees.d.ts +25 -0
- package/types/keyring-core.d.ts +36 -3
- package/types/keyring-manager.d.ts +15 -3
- package/types/ledger/dmk-host.d.ts +7 -0
- package/types/ledger/dmk-selected-host.d.ts +7 -0
- package/types/ledger/dmk-session.d.ts +10 -2
- package/types/ledger-host.d.ts +6 -2
- package/types/software.d.ts +4 -3
- package/types/storage-core.d.ts +3 -1
- package/types/storage.d.ts +1 -1
- package/types/transactions/evm-cancellation.d.ts +10 -0
- package/types/transactions/evm-submission.d.ts +4 -1
package/cjs/software.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"software.js","sourceRoot":"","sources":["../../src/software.ts"],"names":[],"mappings":";;;AAAA,oFAAoF;AACpF,iDAA6C;AAC7C,iDAAwD;
|
|
1
|
+
{"version":3,"file":"software.js","sourceRoot":"","sources":["../../src/software.ts"],"names":[],"mappings":"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"}
|
package/cjs/storage-core.js
CHANGED
|
@@ -3,8 +3,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.createVaultPersistence = exports.VaultAuthenticationError = void 0;
|
|
6
|
+
exports.createVaultPersistence = exports.decryptCurrentVault = exports.VaultAuthenticationError = void 0;
|
|
7
7
|
const crypto_js_1 = __importDefault(require("crypto-js"));
|
|
8
|
+
const current_vault_refusal_1 = require("./current-vault-refusal");
|
|
8
9
|
// Simple async mutex implementation to prevent concurrent vault operations
|
|
9
10
|
class AsyncMutex {
|
|
10
11
|
constructor() {
|
|
@@ -65,6 +66,12 @@ const maybeParseGcmEnvelope = (raw) => {
|
|
|
65
66
|
return null;
|
|
66
67
|
}
|
|
67
68
|
};
|
|
69
|
+
const isCurrentGcmEnvelope = (envelope) => !!envelope &&
|
|
70
|
+
Object.keys(envelope).length === 4 &&
|
|
71
|
+
/^[0-9a-f]{24}$/i.test(envelope.iv) &&
|
|
72
|
+
envelope.ct.length >= 32 &&
|
|
73
|
+
envelope.ct.length % 2 === 0 &&
|
|
74
|
+
isHex(envelope.ct);
|
|
68
75
|
const encryptVaultWebCrypto = async (plaintextJson, keyHex) => {
|
|
69
76
|
const subtle = globalThis.crypto.subtle;
|
|
70
77
|
const iv = new Uint8Array(12);
|
|
@@ -101,7 +108,13 @@ const decryptVaultWebCrypto = async (envelope, keyHex) => {
|
|
|
101
108
|
if (keyBytes.length !== 32) {
|
|
102
109
|
throw new Error('Vault key must be 32 bytes (hex length 64)');
|
|
103
110
|
}
|
|
104
|
-
|
|
111
|
+
let key;
|
|
112
|
+
try {
|
|
113
|
+
key = await subtle.importKey('raw', keyBytes, { name: 'AES-GCM' }, false, ['decrypt']);
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
keyBytes.fill(0);
|
|
117
|
+
}
|
|
105
118
|
const ivBytes = hexToBytes(envelope.iv);
|
|
106
119
|
const ctBytes = hexToBytes(envelope.ct);
|
|
107
120
|
if (ivBytes.length !== 12 || ctBytes.length < 16) {
|
|
@@ -121,6 +134,21 @@ const decryptVaultWebCrypto = async (envelope, keyHex) => {
|
|
|
121
134
|
}
|
|
122
135
|
return new TextDecoder().decode(pt);
|
|
123
136
|
};
|
|
137
|
+
/** Authenticate a captured current-format vault. This path has no CBC fallback. */
|
|
138
|
+
const decryptCurrentVault = async (vault, key) => {
|
|
139
|
+
const envelope = maybeParseGcmEnvelope(vault);
|
|
140
|
+
if (!isCurrentGcmEnvelope(envelope)) {
|
|
141
|
+
throw new Error('Invalid encrypted vault format');
|
|
142
|
+
}
|
|
143
|
+
const plaintext = await decryptVaultWebCrypto(envelope, key);
|
|
144
|
+
try {
|
|
145
|
+
return JSON.parse(plaintext);
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
throw new Error('Invalid device unlock vault payload');
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
exports.decryptCurrentVault = decryptCurrentVault;
|
|
124
152
|
/**
|
|
125
153
|
* Create once per wallet authority and share across its network keyrings.
|
|
126
154
|
* The host owns storage durability and cross-context atomic creation.
|
|
@@ -134,8 +162,9 @@ const createVaultPersistence = (storage) => {
|
|
|
134
162
|
}
|
|
135
163
|
const vaultMutex = new AsyncMutex();
|
|
136
164
|
// Single vault for all networks; derivation remains the keyring's concern.
|
|
137
|
-
const setEncryptedVault = async (decryptedVault, pwd, freshVaultKeys) => {
|
|
165
|
+
const setEncryptedVault = async (decryptedVault, pwd, freshVaultKeys, assertCurrent) => {
|
|
138
166
|
return vaultMutex.runExclusive(async () => {
|
|
167
|
+
assertCurrent?.();
|
|
139
168
|
const plaintext = JSON.stringify(decryptedVault);
|
|
140
169
|
// Writes never downgrade to unauthenticated passphrase AES. Legacy CBC
|
|
141
170
|
// remains readable below, but missing WebCrypto is an operational failure.
|
|
@@ -149,6 +178,7 @@ const createVaultPersistence = (storage) => {
|
|
|
149
178
|
}
|
|
150
179
|
const envelope = await encryptVaultWebCrypto(plaintext, pwd);
|
|
151
180
|
const toStore = JSON.stringify(envelope);
|
|
181
|
+
assertCurrent?.();
|
|
152
182
|
if (freshVaultKeys) {
|
|
153
183
|
// The host primitive covers the absence check and batch commit
|
|
154
184
|
// across all clients that can initialize the same persisted authority.
|
|
@@ -185,7 +215,17 @@ const createVaultPersistence = (storage) => {
|
|
|
185
215
|
}
|
|
186
216
|
let decryptedVault;
|
|
187
217
|
if (maybeEnvelope) {
|
|
188
|
-
|
|
218
|
+
try {
|
|
219
|
+
decryptedVault = await decryptVaultWebCrypto(maybeEnvelope, pwd);
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
if (error instanceof VaultAuthenticationError &&
|
|
223
|
+
typeof vault === 'string' &&
|
|
224
|
+
isCurrentGcmEnvelope(maybeEnvelope)) {
|
|
225
|
+
current_vault_refusal_1.currentVaultRefusals.set(error, (candidate) => candidate === vault);
|
|
226
|
+
}
|
|
227
|
+
throw error;
|
|
228
|
+
}
|
|
189
229
|
}
|
|
190
230
|
else {
|
|
191
231
|
// Legacy CryptoJS passphrase-AES vault (v3 and older v4 canary).
|
package/cjs/storage-core.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-core.js","sourceRoot":"","sources":["../../src/storage-core.ts"],"names":[],"mappings":";;;;;;AAAA,0DAAiC;
|
|
1
|
+
{"version":3,"file":"storage-core.js","sourceRoot":"","sources":["../../src/storage-core.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,11 +8,13 @@ const eth_sig_util_1 = require("@metamask/eth-sig-util");
|
|
|
8
8
|
const sysweb3_network_1 = require("@sidhujag/sysweb3-network");
|
|
9
9
|
const sysweb3_utils_1 = require("@sidhujag/sysweb3-utils");
|
|
10
10
|
const transaction_1 = require("ethers/transaction");
|
|
11
|
+
const utils_1 = require("ethers/utils");
|
|
11
12
|
const omit_1 = __importDefault(require("lodash/omit"));
|
|
12
13
|
const ethers_v6_1 = require("../ethers-v6");
|
|
13
14
|
const evm_fees_1 = require("../evm-fees");
|
|
14
15
|
const providers_1 = require("../providers");
|
|
15
16
|
const types_1 = require("../types");
|
|
17
|
+
const evm_cancellation_1 = require("./evm-cancellation");
|
|
16
18
|
const evm_local_signer_1 = require("./evm-local-signer");
|
|
17
19
|
const evm_submission_1 = require("./evm-submission");
|
|
18
20
|
const derivation_paths_1 = require("../utils/derivation-paths");
|
|
@@ -737,6 +739,17 @@ class EthereumTransactions {
|
|
|
737
739
|
let tx = response === null
|
|
738
740
|
? null
|
|
739
741
|
: authenticateReplacementOriginal(response, txHash.toLowerCase(), activeAccount.address.toLowerCase(), activeNetwork.chainId);
|
|
742
|
+
const software = activeAccountType !== types_1.KeyringAccountType.Ledger &&
|
|
743
|
+
activeAccountType !== types_1.KeyringAccountType.Trezor;
|
|
744
|
+
const softwareNonce = software ? tx?.nonce ?? fallbackNonce : undefined;
|
|
745
|
+
// The host validator may retain the wrapped response and its fee objects.
|
|
746
|
+
const softwareOriginalFees = software && tx
|
|
747
|
+
? {
|
|
748
|
+
gasPrice: tx.gasPrice.toBigInt(),
|
|
749
|
+
maxFeePerGas: tx.maxFeePerGas.toBigInt(),
|
|
750
|
+
maxPriorityFeePerGas: tx.maxPriorityFeePerGas.toBigInt(),
|
|
751
|
+
}
|
|
752
|
+
: undefined;
|
|
740
753
|
assertSynchronousOriginalValidation(options.validateOriginal(tx));
|
|
741
754
|
assertCurrent();
|
|
742
755
|
// If transaction not found, create a minimal tx object with current gas prices
|
|
@@ -752,7 +765,6 @@ class EthereumTransactions {
|
|
|
752
765
|
value: ethers_v6_1.Zero,
|
|
753
766
|
nonce: fallbackNonce,
|
|
754
767
|
gasPrice: currentGasPrice,
|
|
755
|
-
gasLimit: ethers_v6_1.BigNumber.from(42000),
|
|
756
768
|
data: '0x',
|
|
757
769
|
};
|
|
758
770
|
}
|
|
@@ -765,7 +777,6 @@ class EthereumTransactions {
|
|
|
765
777
|
nonce: fallbackNonce,
|
|
766
778
|
maxFeePerGas: feeData.maxFeePerGas,
|
|
767
779
|
maxPriorityFeePerGas: feeData.maxPriorityFeePerGas,
|
|
768
|
-
gasLimit: ethers_v6_1.BigNumber.from(42000),
|
|
769
780
|
data: '0x',
|
|
770
781
|
};
|
|
771
782
|
}
|
|
@@ -777,65 +788,34 @@ class EthereumTransactions {
|
|
|
777
788
|
error: true,
|
|
778
789
|
};
|
|
779
790
|
}
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
maxFeePerGas: tx.maxFeePerGas,
|
|
783
|
-
maxPriorityFeePerGas: tx.maxPriorityFeePerGas,
|
|
784
|
-
gasPrice: tx.gasPrice,
|
|
785
|
-
gasLimit: tx.gasLimit,
|
|
786
|
-
};
|
|
791
|
+
const { gasPrice: originalGasPrice, maxFeePerGas: originalMaxFeePerGas, maxPriorityFeePerGas: originalMaxPriorityFeePerGas, } = softwareOriginalFees ?? tx;
|
|
792
|
+
let feePlan;
|
|
787
793
|
if (isLegacy) {
|
|
788
|
-
const currentGasPrice =
|
|
794
|
+
const currentGasPrice = (0, evm_fees_1.parseEvmFeeQuantity)(await provider.getGasPrice(), 'cancellation gas price');
|
|
789
795
|
assertCurrent();
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
}
|
|
796
|
+
feePlan = (0, evm_fees_1.planEvmCancellationFees)({
|
|
797
|
+
type: 0,
|
|
798
|
+
currentGasPrice,
|
|
799
|
+
originalGasPrice: originalGasPrice == null
|
|
800
|
+
? undefined
|
|
801
|
+
: (0, evm_fees_1.parseEvmFeeQuantity)(originalGasPrice, 'original gas price'),
|
|
802
|
+
});
|
|
798
803
|
}
|
|
799
804
|
else {
|
|
800
|
-
const
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
oldTxsGasValues.maxPriorityFeePerGas = currentMaxPriorityFeePerGas;
|
|
815
|
-
}
|
|
816
|
-
if (oldTxsGasValues.maxFeePerGas.lt(oldTxsGasValues.maxPriorityFeePerGas)) {
|
|
817
|
-
oldTxsGasValues.maxFeePerGas = oldTxsGasValues.maxPriorityFeePerGas;
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
// Preserve the existing 20% replacement policy with exact integer math.
|
|
821
|
-
// Nodes also require a strictly larger cap and tip than an old pending
|
|
822
|
-
// transaction; zero/small fees therefore need at least a one-wei bump.
|
|
823
|
-
// This is a replacement bump, not a fabricated network priority floor.
|
|
824
|
-
const bumpCancelFee = (fee) => {
|
|
825
|
-
const percentageBump = fee.mul(120).div(100);
|
|
826
|
-
const strictBump = fee.add(1);
|
|
827
|
-
return percentageBump.gt(strictBump) ? percentageBump : strictBump;
|
|
828
|
-
};
|
|
829
|
-
const newGasValues = {
|
|
830
|
-
gasLimit: ethers_v6_1.BigNumber.from(42000),
|
|
831
|
-
...(isLegacy
|
|
832
|
-
? { gasPrice: bumpCancelFee(oldTxsGasValues.gasPrice) }
|
|
833
|
-
: {
|
|
834
|
-
maxFeePerGas: bumpCancelFee(oldTxsGasValues.maxFeePerGas),
|
|
835
|
-
maxPriorityFeePerGas: bumpCancelFee(oldTxsGasValues.maxPriorityFeePerGas),
|
|
836
|
-
}),
|
|
837
|
-
};
|
|
838
|
-
const maximumFee = newGasValues.gasLimit.mul(isLegacy ? newGasValues.gasPrice : newGasValues.maxFeePerGas);
|
|
805
|
+
const currentFees = await currentEip1559Fees();
|
|
806
|
+
feePlan = (0, evm_fees_1.planEvmCancellationFees)({
|
|
807
|
+
type: 2,
|
|
808
|
+
currentMaxFeePerGas: currentFees.maxFeePerGas.toBigInt(),
|
|
809
|
+
currentMaxPriorityFeePerGas: currentFees.maxPriorityFeePerGas.toBigInt(),
|
|
810
|
+
originalMaxFeePerGas: originalMaxFeePerGas == null
|
|
811
|
+
? undefined
|
|
812
|
+
: (0, evm_fees_1.parseEvmFeeQuantity)(originalMaxFeePerGas, 'original maximum fee'),
|
|
813
|
+
originalMaxPriorityFeePerGas: originalMaxPriorityFeePerGas == null
|
|
814
|
+
? undefined
|
|
815
|
+
: (0, evm_fees_1.parseEvmFeeQuantity)(originalMaxPriorityFeePerGas, 'original priority fee'),
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
const maximumFee = ethers_v6_1.BigNumber.from(feePlan.maximumFee);
|
|
839
819
|
assertCurrent();
|
|
840
820
|
if (previewOnly)
|
|
841
821
|
return {
|
|
@@ -848,27 +828,27 @@ class EthereumTransactions {
|
|
|
848
828
|
const assertApprovedEnvelope = (transaction) => {
|
|
849
829
|
const gas = nonNegativeFeeQuantity(transaction.gasLimit, 'cancellation gas limit');
|
|
850
830
|
const cap = nonNegativeFeeQuantity(isLegacy ? transaction.gasPrice : transaction.maxFeePerGas, 'cancellation maximum fee');
|
|
851
|
-
if (!gas.eq(
|
|
831
|
+
if (!gas.eq(feePlan.gasLimit) || gas.mul(cap).gt(approvedMaximumFee))
|
|
852
832
|
throw new Error('Cancellation fee exceeds approval');
|
|
853
833
|
};
|
|
854
834
|
// Base cancel transaction parameters (same for all wallet types)
|
|
855
835
|
const baseCancelTx = {
|
|
856
|
-
nonce: tx.nonce,
|
|
836
|
+
nonce: software ? softwareNonce : tx.nonce,
|
|
857
837
|
from: activeAccount.address,
|
|
858
838
|
to: activeAccount.address,
|
|
859
839
|
value: ethers_v6_1.Zero,
|
|
860
|
-
gasLimit:
|
|
840
|
+
gasLimit: ethers_v6_1.BigNumber.from(feePlan.gasLimit),
|
|
861
841
|
};
|
|
862
|
-
const changedTxToCancel =
|
|
842
|
+
const changedTxToCancel = feePlan.type === 0
|
|
863
843
|
? {
|
|
864
844
|
...baseCancelTx,
|
|
865
|
-
gasPrice:
|
|
845
|
+
gasPrice: ethers_v6_1.BigNumber.from(feePlan.gasPrice),
|
|
866
846
|
type: 0, // Force Type 0 for legacy cancel
|
|
867
847
|
}
|
|
868
848
|
: {
|
|
869
849
|
...baseCancelTx,
|
|
870
|
-
maxFeePerGas:
|
|
871
|
-
maxPriorityFeePerGas:
|
|
850
|
+
maxFeePerGas: ethers_v6_1.BigNumber.from(feePlan.maxFeePerGas),
|
|
851
|
+
maxPriorityFeePerGas: ethers_v6_1.BigNumber.from(feePlan.maxPriorityFeePerGas),
|
|
872
852
|
// Don't set type - let ethers auto-detect
|
|
873
853
|
};
|
|
874
854
|
// Ledger cancel handler
|
|
@@ -911,7 +891,7 @@ class EthereumTransactions {
|
|
|
911
891
|
const signedTx = serializeTransaction(txFormattedForEthers, formattedSignature);
|
|
912
892
|
assertCurrent();
|
|
913
893
|
assertHardwareTransactionSender(signedTx, activeAccount.address);
|
|
914
|
-
const transactionResponse = await (0, evm_submission_1.submitSignedEvmTransaction)(signedTx, (raw) => provider.sendTransaction(raw), submission);
|
|
894
|
+
const transactionResponse = await (0, evm_submission_1.submitSignedEvmTransaction)(signedTx, (raw) => provider.sendTransaction(raw), submission, undefined, rawTx);
|
|
915
895
|
return {
|
|
916
896
|
isCanceled: true,
|
|
917
897
|
transaction: transactionResponse,
|
|
@@ -967,6 +947,7 @@ class EthereumTransactions {
|
|
|
967
947
|
}
|
|
968
948
|
assertApprovedEnvelope(txFormattedForTrezor);
|
|
969
949
|
assertTransactionGasLimit(txFormattedForTrezor);
|
|
950
|
+
const expectedUnsignedTransaction = serializeTransaction(txFormattedForTrezor);
|
|
970
951
|
const signature = await this.requireTrezorSigner().signEthTransaction({
|
|
971
952
|
coin: trezorCoin,
|
|
972
953
|
tx: txFormattedForTrezor,
|
|
@@ -978,7 +959,7 @@ class EthereumTransactions {
|
|
|
978
959
|
const signedTx = serializeTransaction(txFormattedForTrezor, trezorSignature(signature.payload));
|
|
979
960
|
assertCurrent();
|
|
980
961
|
assertHardwareTransactionSender(signedTx, activeAccount.address);
|
|
981
|
-
const transactionResponse = await (0, evm_submission_1.submitSignedEvmTransaction)(signedTx, (raw) => provider.sendTransaction(raw), submission);
|
|
962
|
+
const transactionResponse = await (0, evm_submission_1.submitSignedEvmTransaction)(signedTx, (raw) => provider.sendTransaction(raw), submission, undefined, expectedUnsignedTransaction);
|
|
982
963
|
return {
|
|
983
964
|
isCanceled: true,
|
|
984
965
|
transaction: transactionResponse,
|
|
@@ -1007,7 +988,15 @@ class EthereumTransactions {
|
|
|
1007
988
|
if (address?.toLowerCase() !== activeAccount.address.toLowerCase()) {
|
|
1008
989
|
throw new Error('Wallet signing context changed');
|
|
1009
990
|
}
|
|
1010
|
-
const transactionResponse = await (0, evm_local_signer_1.sendLocalEvmTransaction)(provider, decryptedPrivateKey, changedTxToCancel, assertCurrent, assertCurrent,
|
|
991
|
+
const transactionResponse = await (0, evm_local_signer_1.sendLocalEvmTransaction)(provider, decryptedPrivateKey, changedTxToCancel, assertCurrent, assertCurrent, (transaction) => {
|
|
992
|
+
assertApprovedEnvelope(transaction);
|
|
993
|
+
(0, evm_cancellation_1.assertEvmCancellationEnvelope)(serializeTransaction(transaction), {
|
|
994
|
+
payer: activeAccount.address,
|
|
995
|
+
chainId: activeNetwork.chainId,
|
|
996
|
+
nonce: softwareNonce,
|
|
997
|
+
feePlan,
|
|
998
|
+
});
|
|
999
|
+
}, submission);
|
|
1011
1000
|
if (transactionResponse) {
|
|
1012
1001
|
return {
|
|
1013
1002
|
isCanceled: true,
|
|
@@ -1088,6 +1077,53 @@ class EthereumTransactions {
|
|
|
1088
1077
|
};
|
|
1089
1078
|
assertCurrent();
|
|
1090
1079
|
const submission = this.captureSubmission('send', activeAccount, activeAccountType, activeAccountId, activeNetwork, assertCurrent);
|
|
1080
|
+
// Detach supplied values before any RPC/device await. Autofill updates only
|
|
1081
|
+
// this invocation; caller mutations cannot replace already supplied fields.
|
|
1082
|
+
if (!params || typeof params !== 'object' || Array.isArray(params))
|
|
1083
|
+
throw new TypeError('Invalid EVM transaction request');
|
|
1084
|
+
const supplied = { ...params };
|
|
1085
|
+
// Validate original scalar spellings before conversion. Normalization's
|
|
1086
|
+
// permissive zero coercion must not bypass the bounded wire parser.
|
|
1087
|
+
for (const field of [
|
|
1088
|
+
'chainId',
|
|
1089
|
+
'nonce',
|
|
1090
|
+
'gasLimit',
|
|
1091
|
+
'gasPrice',
|
|
1092
|
+
'maxFeePerGas',
|
|
1093
|
+
'maxPriorityFeePerGas',
|
|
1094
|
+
'value',
|
|
1095
|
+
'type',
|
|
1096
|
+
]) {
|
|
1097
|
+
if (supplied[field] != null) {
|
|
1098
|
+
const value = (0, evm_fees_1.parseEvmFeeQuantity)(supplied[field], field);
|
|
1099
|
+
if (field === 'nonce' || field === 'type') {
|
|
1100
|
+
if (value > BigInt(Number.MAX_SAFE_INTEGER))
|
|
1101
|
+
throw new Error(`Invalid transaction ${field}`);
|
|
1102
|
+
supplied[field] = Number(value);
|
|
1103
|
+
}
|
|
1104
|
+
else
|
|
1105
|
+
supplied[field] = value;
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
if (supplied.data != null)
|
|
1109
|
+
supplied.data = (0, utils_1.hexlify)(supplied.data);
|
|
1110
|
+
if (supplied.accessList != null)
|
|
1111
|
+
supplied.accessList = (0, transaction_1.accessListify)(supplied.accessList);
|
|
1112
|
+
params = supplied;
|
|
1113
|
+
assertCurrent();
|
|
1114
|
+
// Capture the reviewed nonce before any fee/RPC await. Hardware and the
|
|
1115
|
+
// final serializer must use the same immutable integer, including zero.
|
|
1116
|
+
let explicitHardwareNonce;
|
|
1117
|
+
if (activeAccountType === types_1.KeyringAccountType.Ledger ||
|
|
1118
|
+
activeAccountType === types_1.KeyringAccountType.Trezor) {
|
|
1119
|
+
const suppliedNonce = params.nonce;
|
|
1120
|
+
if (suppliedNonce != null) {
|
|
1121
|
+
const nonce = (0, evm_fees_1.parseEvmFeeQuantity)(suppliedNonce, 'transaction nonce');
|
|
1122
|
+
if (nonce > BigInt(Number.MAX_SAFE_INTEGER))
|
|
1123
|
+
throw new Error('Invalid transaction nonce');
|
|
1124
|
+
explicitHardwareNonce = Number(nonce);
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1091
1127
|
const explicitEip1559 = params.type != null && ethers_v6_1.BigNumber.from(params.type).eq(2);
|
|
1092
1128
|
const requestedEip1559 = explicitEip1559 ||
|
|
1093
1129
|
params.maxFeePerGas != null ||
|
|
@@ -1108,7 +1144,7 @@ class EthereumTransactions {
|
|
|
1108
1144
|
validateEip1559Fees();
|
|
1109
1145
|
// Only apply a minimum gas limit when a network-specific override is set.
|
|
1110
1146
|
// Otherwise keep the user/dapp-approved gas limit unchanged.
|
|
1111
|
-
if (params.gasLimit && this.gasOverrides.minGasLimit) {
|
|
1147
|
+
if (params.gasLimit != null && this.gasOverrides.minGasLimit) {
|
|
1112
1148
|
const minGasLimit = this.gasOverrides.minGasLimit;
|
|
1113
1149
|
const currentGasLimit = ethers_v6_1.BigNumber.from(params.gasLimit);
|
|
1114
1150
|
if (currentGasLimit.lt(minGasLimit)) {
|
|
@@ -1124,7 +1160,7 @@ class EthereumTransactions {
|
|
|
1124
1160
|
...params,
|
|
1125
1161
|
from: params.from || activeAccount.address,
|
|
1126
1162
|
}, ['gasPrice']);
|
|
1127
|
-
if (
|
|
1163
|
+
if (params.gasLimit == null) {
|
|
1128
1164
|
params.gasLimit = await provider.estimateGas(txForEstimation);
|
|
1129
1165
|
assertCurrent();
|
|
1130
1166
|
}
|
|
@@ -1133,7 +1169,7 @@ class EthereumTransactions {
|
|
|
1133
1169
|
chainId: activeNetwork.chainId,
|
|
1134
1170
|
});
|
|
1135
1171
|
if (isLegacy) {
|
|
1136
|
-
if (
|
|
1172
|
+
if (params.gasPrice == null) {
|
|
1137
1173
|
params.gasPrice = await provider.getGasPrice();
|
|
1138
1174
|
assertCurrent();
|
|
1139
1175
|
}
|
|
@@ -1159,7 +1195,8 @@ class EthereumTransactions {
|
|
|
1159
1195
|
validateEip1559Fees();
|
|
1160
1196
|
const sendEVMLedgerTransaction = async () => {
|
|
1161
1197
|
assertCurrent();
|
|
1162
|
-
const transactionNonce =
|
|
1198
|
+
const transactionNonce = explicitHardwareNonce ??
|
|
1199
|
+
(await provider.getTransactionCount(activeAccount.address, 'pending'));
|
|
1163
1200
|
assertCurrent();
|
|
1164
1201
|
const formatParams = isLegacy
|
|
1165
1202
|
? (0, omit_1.default)(params, 'from')
|
|
@@ -1193,7 +1230,7 @@ class EthereumTransactions {
|
|
|
1193
1230
|
try {
|
|
1194
1231
|
const signedTx = serializeTransaction(txFormattedForEthers, formattedSignature);
|
|
1195
1232
|
assertHardwareTransactionSender(signedTx, activeAccount.address);
|
|
1196
|
-
const finalTx = await (0, evm_submission_1.submitSignedEvmTransaction)(signedTx, (raw) => provider.sendTransaction(raw), submission, assertBeforeBroadcast);
|
|
1233
|
+
const finalTx = await (0, evm_submission_1.submitSignedEvmTransaction)(signedTx, (raw) => provider.sendTransaction(raw), submission, assertBeforeBroadcast, rawTx);
|
|
1197
1234
|
return finalTx;
|
|
1198
1235
|
}
|
|
1199
1236
|
catch (error) {
|
|
@@ -1206,7 +1243,8 @@ class EthereumTransactions {
|
|
|
1206
1243
|
};
|
|
1207
1244
|
const sendEVMTrezorTransaction = async () => {
|
|
1208
1245
|
assertCurrent();
|
|
1209
|
-
const transactionNonce =
|
|
1246
|
+
const transactionNonce = explicitHardwareNonce ??
|
|
1247
|
+
(await provider.getTransactionCount(activeAccount.address, 'pending'));
|
|
1210
1248
|
assertCurrent();
|
|
1211
1249
|
let txFormattedForTrezor = {};
|
|
1212
1250
|
const formatParams = isLegacy
|
|
@@ -1216,6 +1254,7 @@ class EthereumTransactions {
|
|
|
1216
1254
|
case true:
|
|
1217
1255
|
txFormattedForTrezor = {
|
|
1218
1256
|
...formatParams,
|
|
1257
|
+
gasPrice: this.toHex0x(params.gasPrice, 'gasPrice'),
|
|
1219
1258
|
gasLimit: this.toHex0x(formatParams.gasLimit ?? params.gasLimit, 'gasLimit'),
|
|
1220
1259
|
value: this.toHex0x(formatParams.value ?? params.value, 'value'),
|
|
1221
1260
|
nonce: this.toBigNumber(transactionNonce)._hex,
|
|
@@ -1253,6 +1292,10 @@ class EthereumTransactions {
|
|
|
1253
1292
|
break;
|
|
1254
1293
|
}
|
|
1255
1294
|
assertTransactionGasLimit(txFormattedForTrezor);
|
|
1295
|
+
const expectedUnsignedTransaction = serializeTransaction({
|
|
1296
|
+
...txFormattedForTrezor,
|
|
1297
|
+
type: isLegacy ? 0 : 2,
|
|
1298
|
+
});
|
|
1256
1299
|
const signature = await this.requireTrezorSigner().signEthTransaction({
|
|
1257
1300
|
index: `${activeAccountId}`,
|
|
1258
1301
|
tx: txFormattedForTrezor,
|
|
@@ -1277,7 +1320,7 @@ class EthereumTransactions {
|
|
|
1277
1320
|
};
|
|
1278
1321
|
const signedTx = serializeTransaction(txFormattedForEthers, trezorSignature(signature.payload));
|
|
1279
1322
|
assertHardwareTransactionSender(signedTx, activeAccount.address);
|
|
1280
|
-
const finalTx = await (0, evm_submission_1.submitSignedEvmTransaction)(signedTx, (raw) => provider.sendTransaction(raw), submission, assertBeforeBroadcast);
|
|
1323
|
+
const finalTx = await (0, evm_submission_1.submitSignedEvmTransaction)(signedTx, (raw) => provider.sendTransaction(raw), submission, assertBeforeBroadcast, expectedUnsignedTransaction);
|
|
1281
1324
|
return finalTx;
|
|
1282
1325
|
}
|
|
1283
1326
|
catch (error) {
|
|
@@ -1526,7 +1569,7 @@ class EthereumTransactions {
|
|
|
1526
1569
|
const signedTx = serializeTransaction(txFormattedForEthers, formattedSignature);
|
|
1527
1570
|
assertSignedSender(signedTx);
|
|
1528
1571
|
assertHardwareTransactionSender(signedTx, activeAccount.address);
|
|
1529
|
-
const transactionResponse = await (0, evm_submission_1.submitSignedEvmTransaction)(signedTx, (raw) => provider.sendTransaction(raw), submission, assertBeforeBroadcast);
|
|
1572
|
+
const transactionResponse = await (0, evm_submission_1.submitSignedEvmTransaction)(signedTx, (raw) => provider.sendTransaction(raw), submission, assertBeforeBroadcast, rawTx);
|
|
1530
1573
|
return {
|
|
1531
1574
|
isSpeedUp: true,
|
|
1532
1575
|
transaction: transactionResponse,
|
|
@@ -1596,6 +1639,7 @@ class EthereumTransactions {
|
|
|
1596
1639
|
}
|
|
1597
1640
|
assertCurrent();
|
|
1598
1641
|
assertTransactionGasLimit(txFormattedForTrezor);
|
|
1642
|
+
const expectedUnsignedTransaction = serializeTransaction(txFormattedForTrezor);
|
|
1599
1643
|
const signature = await this.requireTrezorSigner().signEthTransaction({
|
|
1600
1644
|
coin: trezorCoin,
|
|
1601
1645
|
tx: txFormattedForTrezor,
|
|
@@ -1606,7 +1650,7 @@ class EthereumTransactions {
|
|
|
1606
1650
|
const signedTx = serializeTransaction(txFormattedForTrezor, trezorSignature(signature.payload));
|
|
1607
1651
|
assertSignedSender(signedTx);
|
|
1608
1652
|
assertHardwareTransactionSender(signedTx, activeAccount.address);
|
|
1609
|
-
const transactionResponse = await (0, evm_submission_1.submitSignedEvmTransaction)(signedTx, (raw) => provider.sendTransaction(raw), submission, assertBeforeBroadcast);
|
|
1653
|
+
const transactionResponse = await (0, evm_submission_1.submitSignedEvmTransaction)(signedTx, (raw) => provider.sendTransaction(raw), submission, assertBeforeBroadcast, expectedUnsignedTransaction);
|
|
1610
1654
|
return {
|
|
1611
1655
|
isSpeedUp: true,
|
|
1612
1656
|
transaction: transactionResponse,
|
|
@@ -1802,7 +1846,7 @@ class EthereumTransactions {
|
|
|
1802
1846
|
const response = await provider.sendTransaction(raw);
|
|
1803
1847
|
saveTrezorTx && saveTrezorTx(response);
|
|
1804
1848
|
return response;
|
|
1805
|
-
}, submission);
|
|
1849
|
+
}, submission, undefined, rawTx);
|
|
1806
1850
|
return finalTx;
|
|
1807
1851
|
}
|
|
1808
1852
|
catch (error) {
|
|
@@ -1856,6 +1900,10 @@ class EthereumTransactions {
|
|
|
1856
1900
|
};
|
|
1857
1901
|
}
|
|
1858
1902
|
assertTransactionGasLimit(txToBeSignedByTrezor);
|
|
1903
|
+
const expectedUnsignedTransaction = serializeTransaction({
|
|
1904
|
+
...txToBeSignedByTrezor,
|
|
1905
|
+
type: isLegacy ? 0 : 2,
|
|
1906
|
+
});
|
|
1859
1907
|
const signature = await this.requireTrezorSigner().signEthTransaction({
|
|
1860
1908
|
index: `${activeAccountId}`,
|
|
1861
1909
|
tx: txToBeSignedByTrezor,
|
|
@@ -1898,7 +1946,7 @@ class EthereumTransactions {
|
|
|
1898
1946
|
const response = await provider.sendTransaction(raw);
|
|
1899
1947
|
saveTrezorTx && saveTrezorTx(response);
|
|
1900
1948
|
return response;
|
|
1901
|
-
}, submission);
|
|
1949
|
+
}, submission, undefined, expectedUnsignedTransaction);
|
|
1902
1950
|
return finalTx;
|
|
1903
1951
|
}
|
|
1904
1952
|
catch (error) {
|
|
@@ -2029,7 +2077,7 @@ class EthereumTransactions {
|
|
|
2029
2077
|
const signedTx = serializeTransaction(txFormattedForEthers, formattedSignature);
|
|
2030
2078
|
assertCurrent();
|
|
2031
2079
|
assertHardwareTransactionSender(signedTx, activeAccount.address);
|
|
2032
|
-
const finalTx = await (0, evm_submission_1.submitSignedEvmTransaction)(signedTx, (raw) => provider.sendTransaction(raw), submission);
|
|
2080
|
+
const finalTx = await (0, evm_submission_1.submitSignedEvmTransaction)(signedTx, (raw) => provider.sendTransaction(raw), submission, undefined, rawTx);
|
|
2033
2081
|
return finalTx;
|
|
2034
2082
|
}
|
|
2035
2083
|
catch (error) {
|
|
@@ -2085,6 +2133,10 @@ class EthereumTransactions {
|
|
|
2085
2133
|
// For EVM networks, Trezor expects 'eth' regardless of the network's currency
|
|
2086
2134
|
const trezorCoin = activeNetwork.slip44 === 60 ? 'eth' : activeNetwork.currency;
|
|
2087
2135
|
assertTransactionGasLimit(txToBeSignedByTrezor);
|
|
2136
|
+
const expectedUnsignedTransaction = serializeTransaction({
|
|
2137
|
+
...txToBeSignedByTrezor,
|
|
2138
|
+
type: isLegacy ? 0 : 2,
|
|
2139
|
+
});
|
|
2088
2140
|
const signature = await this.requireTrezorSigner().signEthTransaction({
|
|
2089
2141
|
index: `${activeAccountId}`,
|
|
2090
2142
|
tx: txToBeSignedByTrezor,
|
|
@@ -2123,7 +2175,7 @@ class EthereumTransactions {
|
|
|
2123
2175
|
const signedTx = serializeTransaction(txFormattedForEthers, trezorSignature(signature.payload));
|
|
2124
2176
|
assertCurrent();
|
|
2125
2177
|
assertHardwareTransactionSender(signedTx, activeAccount.address);
|
|
2126
|
-
const finalTx = await (0, evm_submission_1.submitSignedEvmTransaction)(signedTx, (raw) => provider.sendTransaction(raw), submission);
|
|
2178
|
+
const finalTx = await (0, evm_submission_1.submitSignedEvmTransaction)(signedTx, (raw) => provider.sendTransaction(raw), submission, undefined, expectedUnsignedTransaction);
|
|
2127
2179
|
return finalTx;
|
|
2128
2180
|
}
|
|
2129
2181
|
catch (error) {
|
|
@@ -2251,7 +2303,7 @@ class EthereumTransactions {
|
|
|
2251
2303
|
const signedTx = serializeTransaction(txFormattedForEthers, formattedSignature);
|
|
2252
2304
|
assertCurrent();
|
|
2253
2305
|
assertHardwareTransactionSender(signedTx, activeAccount.address);
|
|
2254
|
-
const finalTx = await (0, evm_submission_1.submitSignedEvmTransaction)(signedTx, (raw) => provider.sendTransaction(raw), submission);
|
|
2306
|
+
const finalTx = await (0, evm_submission_1.submitSignedEvmTransaction)(signedTx, (raw) => provider.sendTransaction(raw), submission, undefined, rawTx);
|
|
2255
2307
|
return finalTx;
|
|
2256
2308
|
}
|
|
2257
2309
|
catch (error) {
|
|
@@ -2301,6 +2353,10 @@ class EthereumTransactions {
|
|
|
2301
2353
|
};
|
|
2302
2354
|
}
|
|
2303
2355
|
assertTransactionGasLimit(txToBeSignedByTrezor);
|
|
2356
|
+
const expectedUnsignedTransaction = serializeTransaction({
|
|
2357
|
+
...txToBeSignedByTrezor,
|
|
2358
|
+
type: isLegacy ? 0 : 2,
|
|
2359
|
+
});
|
|
2304
2360
|
const signature = await this.requireTrezorSigner().signEthTransaction({
|
|
2305
2361
|
index: `${activeAccountId}`,
|
|
2306
2362
|
tx: txToBeSignedByTrezor,
|
|
@@ -2339,7 +2395,7 @@ class EthereumTransactions {
|
|
|
2339
2395
|
const signedTx = serializeTransaction(txFormattedForEthers, trezorSignature(signature.payload));
|
|
2340
2396
|
assertCurrent();
|
|
2341
2397
|
assertHardwareTransactionSender(signedTx, activeAccount.address);
|
|
2342
|
-
const finalTx = await (0, evm_submission_1.submitSignedEvmTransaction)(signedTx, (raw) => provider.sendTransaction(raw), submission);
|
|
2398
|
+
const finalTx = await (0, evm_submission_1.submitSignedEvmTransaction)(signedTx, (raw) => provider.sendTransaction(raw), submission, undefined, expectedUnsignedTransaction);
|
|
2343
2399
|
return finalTx;
|
|
2344
2400
|
}
|
|
2345
2401
|
catch (error) {
|