@metamask-previews/transaction-controller 69.8.0-preview-efd9e28b2 → 69.8.0-preview-b123e43e2
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 +0 -4
- package/dist/utils/balance.cjs +2 -9
- package/dist/utils/balance.cjs.map +1 -1
- package/dist/utils/balance.d.cts.map +1 -1
- package/dist/utils/balance.d.mts.map +1 -1
- package/dist/utils/balance.mjs +2 -9
- package/dist/utils/balance.mjs.map +1 -1
- package/dist/utils/gas-fee-tokens.cjs +3 -8
- package/dist/utils/gas-fee-tokens.cjs.map +1 -1
- package/dist/utils/gas-fee-tokens.d.cts.map +1 -1
- package/dist/utils/gas-fee-tokens.d.mts.map +1 -1
- package/dist/utils/gas-fee-tokens.mjs +3 -8
- package/dist/utils/gas-fee-tokens.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,10 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
-
### Fixed
|
|
11
|
-
|
|
12
|
-
- Harden gas fee token preflight by not treating pending gas estimates as zero-cost native gas, and by resetting `isExternalSign` when preflight validation fails ([#10071](https://github.com/MetaMask/core/pull/10071))
|
|
13
|
-
|
|
14
10
|
## [69.8.0]
|
|
15
11
|
|
|
16
12
|
### Added
|
package/dist/utils/balance.cjs
CHANGED
|
@@ -35,15 +35,8 @@ exports.getNativeBalance = getNativeBalance;
|
|
|
35
35
|
* @returns True if the native balance is sufficient, false otherwise.
|
|
36
36
|
*/
|
|
37
37
|
async function isNativeBalanceSufficientForGas(transaction, messenger, networkClientId) {
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
// Gas estimates can still be in flight (e.g. skipInitialGasEstimate). Treating
|
|
41
|
-
// missing fee fields as zero makes every balance look sufficient and clears a
|
|
42
|
-
// selected gas fee token before publish.
|
|
43
|
-
if (!gas || !maxFeePerGasValue) {
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
const gasCostRawValue = new bignumber_js_1.BigNumber(gas).multipliedBy(maxFeePerGasValue);
|
|
38
|
+
const from = transaction.txParams.from;
|
|
39
|
+
const gasCostRawValue = new bignumber_js_1.BigNumber(transaction.txParams.gas ?? '0x0').multipliedBy(transaction.txParams.maxFeePerGas ?? transaction.txParams.gasPrice ?? '0x0');
|
|
47
40
|
const { balanceRaw } = await getNativeBalance(from, messenger, networkClientId);
|
|
48
41
|
return gasCostRawValue.isLessThanOrEqualTo(balanceRaw);
|
|
49
42
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"balance.cjs","sourceRoot":"","sources":["../../src/utils/balance.ts"],"names":[],"mappings":";;;AAEA,+CAAyC;AAIzC,gDAA2C;AAE3C;;;;;;;GAOG;AACI,KAAK,UAAU,gBAAgB,CACpC,OAAY,EACZ,SAAyC,EACzC,eAAgC;IAKhC,MAAM,aAAa,GAAG,CAAC,MAAM,IAAA,wBAAU,EAAC;QACtC,SAAS;QACT,eAAe;QACf,MAAM,EAAE,gBAAgB;QACxB,MAAM,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC;KAC5B,CAAC,CAAQ,CAAC;IAEX,MAAM,UAAU,GAAG,IAAI,wBAAS,CAAC,aAAa,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC7D,MAAM,YAAY,GAAG,IAAI,wBAAS,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAE3E,OAAO;QACL,YAAY;QACZ,UAAU;KACX,CAAC;AACJ,CAAC;AAtBD,4CAsBC;AAED;;;;;;;GAOG;AACI,KAAK,UAAU,+BAA+B,CACnD,WAA4B,EAC5B,SAAyC,EACzC,eAAgC;IAEhC,MAAM,
|
|
1
|
+
{"version":3,"file":"balance.cjs","sourceRoot":"","sources":["../../src/utils/balance.ts"],"names":[],"mappings":";;;AAEA,+CAAyC;AAIzC,gDAA2C;AAE3C;;;;;;;GAOG;AACI,KAAK,UAAU,gBAAgB,CACpC,OAAY,EACZ,SAAyC,EACzC,eAAgC;IAKhC,MAAM,aAAa,GAAG,CAAC,MAAM,IAAA,wBAAU,EAAC;QACtC,SAAS;QACT,eAAe;QACf,MAAM,EAAE,gBAAgB;QACxB,MAAM,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC;KAC5B,CAAC,CAAQ,CAAC;IAEX,MAAM,UAAU,GAAG,IAAI,wBAAS,CAAC,aAAa,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC7D,MAAM,YAAY,GAAG,IAAI,wBAAS,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAE3E,OAAO;QACL,YAAY;QACZ,UAAU;KACX,CAAC;AACJ,CAAC;AAtBD,4CAsBC;AAED;;;;;;;GAOG;AACI,KAAK,UAAU,+BAA+B,CACnD,WAA4B,EAC5B,SAAyC,EACzC,eAAgC;IAEhC,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAW,CAAC;IAE9C,MAAM,eAAe,GAAG,IAAI,wBAAS,CACnC,WAAW,CAAC,QAAQ,CAAC,GAAG,IAAI,KAAK,CAClC,CAAC,YAAY,CACZ,WAAW,CAAC,QAAQ,CAAC,YAAY,IAAI,WAAW,CAAC,QAAQ,CAAC,QAAQ,IAAI,KAAK,CAC5E,CAAC;IAEF,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,gBAAgB,CAC3C,IAAI,EACJ,SAAS,EACT,eAAe,CAChB,CAAC;IAEF,OAAO,eAAe,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;AACzD,CAAC;AApBD,0EAoBC","sourcesContent":["import type { NetworkClientId } from '@metamask/network-controller';\nimport type { Hex } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport type { TransactionMeta } from '../index.js';\nimport type { TransactionControllerMessenger } from '../TransactionController.js';\nimport { rpcRequest } from './provider.js';\n\n/**\n * Get the native balance for an address.\n *\n * @param address - Address to get the balance for.\n * @param messenger - The TransactionController messenger.\n * @param networkClientId - The network client ID.\n * @returns Balance in both human-readable and raw format.\n */\nexport async function getNativeBalance(\n address: Hex,\n messenger: TransactionControllerMessenger,\n networkClientId: NetworkClientId,\n): Promise<{\n balanceHuman: string;\n balanceRaw: string;\n}> {\n const balanceRawHex = (await rpcRequest({\n messenger,\n networkClientId,\n method: 'eth_getBalance',\n params: [address, 'latest'],\n })) as Hex;\n\n const balanceRaw = new BigNumber(balanceRawHex).toString(10);\n const balanceHuman = new BigNumber(balanceRaw).shiftedBy(-18).toString(10);\n\n return {\n balanceHuman,\n balanceRaw,\n };\n}\n\n/**\n * Determine if the native balance is sufficient to cover max gas cost.\n *\n * @param transaction - Transaction metadata.\n * @param messenger - The TransactionController messenger.\n * @param networkClientId - The network client ID.\n * @returns True if the native balance is sufficient, false otherwise.\n */\nexport async function isNativeBalanceSufficientForGas(\n transaction: TransactionMeta,\n messenger: TransactionControllerMessenger,\n networkClientId: NetworkClientId,\n): Promise<boolean> {\n const from = transaction.txParams.from as Hex;\n\n const gasCostRawValue = new BigNumber(\n transaction.txParams.gas ?? '0x0',\n ).multipliedBy(\n transaction.txParams.maxFeePerGas ?? transaction.txParams.gasPrice ?? '0x0',\n );\n\n const { balanceRaw } = await getNativeBalance(\n from,\n messenger,\n networkClientId,\n );\n\n return gasCostRawValue.isLessThanOrEqualTo(balanceRaw);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"balance.d.cts","sourceRoot":"","sources":["../../src/utils/balance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,qCAAqC;AACpE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAG3C,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAoB;AACnD,OAAO,KAAK,EAAE,8BAA8B,EAAE,qCAAoC;AAGlF;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,GAAG,EACZ,SAAS,EAAE,8BAA8B,EACzC,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC;IACT,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC,CAeD;AAED;;;;;;;GAOG;AACH,wBAAsB,+BAA+B,CACnD,WAAW,EAAE,eAAe,EAC5B,SAAS,EAAE,8BAA8B,EACzC,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"balance.d.cts","sourceRoot":"","sources":["../../src/utils/balance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,qCAAqC;AACpE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAG3C,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAoB;AACnD,OAAO,KAAK,EAAE,8BAA8B,EAAE,qCAAoC;AAGlF;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,GAAG,EACZ,SAAS,EAAE,8BAA8B,EACzC,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC;IACT,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC,CAeD;AAED;;;;;;;GAOG;AACH,wBAAsB,+BAA+B,CACnD,WAAW,EAAE,eAAe,EAC5B,SAAS,EAAE,8BAA8B,EACzC,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC,OAAO,CAAC,CAgBlB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"balance.d.mts","sourceRoot":"","sources":["../../src/utils/balance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,qCAAqC;AACpE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAG3C,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAoB;AACnD,OAAO,KAAK,EAAE,8BAA8B,EAAE,qCAAoC;AAGlF;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,GAAG,EACZ,SAAS,EAAE,8BAA8B,EACzC,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC;IACT,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC,CAeD;AAED;;;;;;;GAOG;AACH,wBAAsB,+BAA+B,CACnD,WAAW,EAAE,eAAe,EAC5B,SAAS,EAAE,8BAA8B,EACzC,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"balance.d.mts","sourceRoot":"","sources":["../../src/utils/balance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,qCAAqC;AACpE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAG3C,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAoB;AACnD,OAAO,KAAK,EAAE,8BAA8B,EAAE,qCAAoC;AAGlF;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,GAAG,EACZ,SAAS,EAAE,8BAA8B,EACzC,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC;IACT,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC,CAeD;AAED;;;;;;;GAOG;AACH,wBAAsB,+BAA+B,CACnD,WAAW,EAAE,eAAe,EAC5B,SAAS,EAAE,8BAA8B,EACzC,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC,OAAO,CAAC,CAgBlB"}
|
package/dist/utils/balance.mjs
CHANGED
|
@@ -31,15 +31,8 @@ export async function getNativeBalance(address, messenger, networkClientId) {
|
|
|
31
31
|
* @returns True if the native balance is sufficient, false otherwise.
|
|
32
32
|
*/
|
|
33
33
|
export async function isNativeBalanceSufficientForGas(transaction, messenger, networkClientId) {
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
// Gas estimates can still be in flight (e.g. skipInitialGasEstimate). Treating
|
|
37
|
-
// missing fee fields as zero makes every balance look sufficient and clears a
|
|
38
|
-
// selected gas fee token before publish.
|
|
39
|
-
if (!gas || !maxFeePerGasValue) {
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
const gasCostRawValue = new BigNumber(gas).multipliedBy(maxFeePerGasValue);
|
|
34
|
+
const from = transaction.txParams.from;
|
|
35
|
+
const gasCostRawValue = new BigNumber(transaction.txParams.gas ?? '0x0').multipliedBy(transaction.txParams.maxFeePerGas ?? transaction.txParams.gasPrice ?? '0x0');
|
|
43
36
|
const { balanceRaw } = await getNativeBalance(from, messenger, networkClientId);
|
|
44
37
|
return gasCostRawValue.isLessThanOrEqualTo(balanceRaw);
|
|
45
38
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"balance.mjs","sourceRoot":"","sources":["../../src/utils/balance.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,qBAAqB;AAIzC,OAAO,EAAE,UAAU,EAAE,uBAAsB;AAE3C;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAY,EACZ,SAAyC,EACzC,eAAgC;IAKhC,MAAM,aAAa,GAAG,CAAC,MAAM,UAAU,CAAC;QACtC,SAAS;QACT,eAAe;QACf,MAAM,EAAE,gBAAgB;QACxB,MAAM,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC;KAC5B,CAAC,CAAQ,CAAC;IAEX,MAAM,UAAU,GAAG,IAAI,SAAS,CAAC,aAAa,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC7D,MAAM,YAAY,GAAG,IAAI,SAAS,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAE3E,OAAO;QACL,YAAY;QACZ,UAAU;KACX,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACnD,WAA4B,EAC5B,SAAyC,EACzC,eAAgC;IAEhC,MAAM,
|
|
1
|
+
{"version":3,"file":"balance.mjs","sourceRoot":"","sources":["../../src/utils/balance.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,qBAAqB;AAIzC,OAAO,EAAE,UAAU,EAAE,uBAAsB;AAE3C;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAY,EACZ,SAAyC,EACzC,eAAgC;IAKhC,MAAM,aAAa,GAAG,CAAC,MAAM,UAAU,CAAC;QACtC,SAAS;QACT,eAAe;QACf,MAAM,EAAE,gBAAgB;QACxB,MAAM,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC;KAC5B,CAAC,CAAQ,CAAC;IAEX,MAAM,UAAU,GAAG,IAAI,SAAS,CAAC,aAAa,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC7D,MAAM,YAAY,GAAG,IAAI,SAAS,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAE3E,OAAO;QACL,YAAY;QACZ,UAAU;KACX,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACnD,WAA4B,EAC5B,SAAyC,EACzC,eAAgC;IAEhC,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAW,CAAC;IAE9C,MAAM,eAAe,GAAG,IAAI,SAAS,CACnC,WAAW,CAAC,QAAQ,CAAC,GAAG,IAAI,KAAK,CAClC,CAAC,YAAY,CACZ,WAAW,CAAC,QAAQ,CAAC,YAAY,IAAI,WAAW,CAAC,QAAQ,CAAC,QAAQ,IAAI,KAAK,CAC5E,CAAC;IAEF,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,gBAAgB,CAC3C,IAAI,EACJ,SAAS,EACT,eAAe,CAChB,CAAC;IAEF,OAAO,eAAe,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;AACzD,CAAC","sourcesContent":["import type { NetworkClientId } from '@metamask/network-controller';\nimport type { Hex } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport type { TransactionMeta } from '../index.js';\nimport type { TransactionControllerMessenger } from '../TransactionController.js';\nimport { rpcRequest } from './provider.js';\n\n/**\n * Get the native balance for an address.\n *\n * @param address - Address to get the balance for.\n * @param messenger - The TransactionController messenger.\n * @param networkClientId - The network client ID.\n * @returns Balance in both human-readable and raw format.\n */\nexport async function getNativeBalance(\n address: Hex,\n messenger: TransactionControllerMessenger,\n networkClientId: NetworkClientId,\n): Promise<{\n balanceHuman: string;\n balanceRaw: string;\n}> {\n const balanceRawHex = (await rpcRequest({\n messenger,\n networkClientId,\n method: 'eth_getBalance',\n params: [address, 'latest'],\n })) as Hex;\n\n const balanceRaw = new BigNumber(balanceRawHex).toString(10);\n const balanceHuman = new BigNumber(balanceRaw).shiftedBy(-18).toString(10);\n\n return {\n balanceHuman,\n balanceRaw,\n };\n}\n\n/**\n * Determine if the native balance is sufficient to cover max gas cost.\n *\n * @param transaction - Transaction metadata.\n * @param messenger - The TransactionController messenger.\n * @param networkClientId - The network client ID.\n * @returns True if the native balance is sufficient, false otherwise.\n */\nexport async function isNativeBalanceSufficientForGas(\n transaction: TransactionMeta,\n messenger: TransactionControllerMessenger,\n networkClientId: NetworkClientId,\n): Promise<boolean> {\n const from = transaction.txParams.from as Hex;\n\n const gasCostRawValue = new BigNumber(\n transaction.txParams.gas ?? '0x0',\n ).multipliedBy(\n transaction.txParams.maxFeePerGas ?? transaction.txParams.gasPrice ?? '0x0',\n );\n\n const { balanceRaw } = await getNativeBalance(\n from,\n messenger,\n networkClientId,\n );\n\n return gasCostRawValue.isLessThanOrEqualTo(balanceRaw);\n}\n"]}
|
|
@@ -105,20 +105,15 @@ async function checkGasFeeTokenBeforePublish({ messenger, networkClientId, fetch
|
|
|
105
105
|
...transaction,
|
|
106
106
|
isExternalSign: true,
|
|
107
107
|
});
|
|
108
|
-
const isSelectedGasFeeTokenAvailable = gasFeeTokens?.some((token) => token.tokenAddress.toLowerCase() === selectedGasFeeToken.toLowerCase());
|
|
109
|
-
if (!isSelectedGasFeeTokenAvailable) {
|
|
110
|
-
updateTransaction(transaction.id, (tx) => {
|
|
111
|
-
tx.gasFeeTokens = gasFeeTokens;
|
|
112
|
-
tx.isExternalSign = false;
|
|
113
|
-
});
|
|
114
|
-
throw new Error('Gas fee token not found and insufficient native balance');
|
|
115
|
-
}
|
|
116
108
|
updateTransaction(transaction.id, (tx) => {
|
|
117
109
|
tx.gasFeeTokens = gasFeeTokens;
|
|
118
110
|
tx.isExternalSign = true;
|
|
119
111
|
tx.txParams.nonce = undefined;
|
|
120
112
|
});
|
|
121
113
|
log('Updated gas fee tokens before publish', gasFeeTokens);
|
|
114
|
+
if (!gasFeeTokens?.some((token) => token.tokenAddress.toLowerCase() === selectedGasFeeToken.toLowerCase())) {
|
|
115
|
+
throw new Error('Gas fee token not found and insufficient native balance');
|
|
116
|
+
}
|
|
122
117
|
log('Publishing with selected gas fee token', { selectedGasFeeToken });
|
|
123
118
|
}
|
|
124
119
|
exports.checkGasFeeTokenBeforePublish = checkGasFeeTokenBeforePublish;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gas-fee-tokens.cjs","sourceRoot":"","sources":["../../src/utils/gas-fee-tokens.ts"],"names":[],"mappings":"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","sourcesContent":["import type { NetworkClientId } from '@metamask/network-controller';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { simulateTransactions } from '../api/simulation-api.js';\nimport type { SimulationRequestTransaction } from '../api/simulation-api.js';\nimport type {\n SimulationResponse,\n SimulationResponseTransaction,\n} from '../api/simulation-api.js';\nimport type {\n GasFeeToken,\n TransactionControllerMessenger,\n TransactionMeta,\n} from '../index.js';\nimport { projectLogger } from '../logger.js';\nimport type { GetSimulationConfig } from '../types.js';\nimport { isNativeBalanceSufficientForGas } from './balance.js';\nimport { ERROR_MESSAGE_NO_UPGRADE_CONTRACT } from './batch.js';\nimport { ERROR_MESSGE_PUBLIC_KEY, doesChainSupportEIP7702 } from './eip7702.js';\nimport { getEIP7702UpgradeContractAddress } from './feature-flags.js';\n\nconst log = createModuleLogger(projectLogger, 'gas-fee-tokens');\n\nexport type GetGasFeeTokensRequest = {\n chainId: Hex;\n isEIP7702GasFeeTokensEnabled: (\n transactionMeta: TransactionMeta,\n ) => Promise<boolean>;\n getSimulationConfig: GetSimulationConfig;\n messenger: TransactionControllerMessenger;\n publicKeyEIP7702?: Hex;\n transactionMeta: TransactionMeta;\n};\n\n/**\n * Get gas fee tokens for a transaction.\n *\n * @param request - The request object.\n * @param request.chainId - The chain ID of the transaction.\n * @param request.isEIP7702GasFeeTokensEnabled - Callback to check if EIP-7702 gas fee tokens are enabled.\n * @param request.messenger - The messenger instance.\n * @param request.publicKeyEIP7702 - Public key to validate EIP-7702 contract signatures.\n * @param request.transactionMeta - The transaction metadata.\n * @param request.getSimulationConfig - Optional transaction simulation parameters.\n * @returns An array of gas fee tokens.\n */\nexport async function getGasFeeTokens({\n chainId,\n isEIP7702GasFeeTokensEnabled,\n messenger,\n publicKeyEIP7702,\n transactionMeta,\n getSimulationConfig,\n}: GetGasFeeTokensRequest): Promise<{\n gasFeeTokens: GasFeeToken[];\n isGasFeeSponsored: boolean;\n}> {\n const { delegationAddress, txParams } = transactionMeta;\n const { authorizationList: authorizationListRequest } = txParams;\n const data = txParams.data as Hex;\n const from = txParams.from as Hex;\n const to = txParams.to as Hex;\n const value = txParams.value as Hex;\n\n log('Request', { chainId, txParams });\n\n const is7702GasFeeTokensEnabled =\n await isEIP7702GasFeeTokensEnabled(transactionMeta);\n\n const with7702 =\n is7702GasFeeTokensEnabled && doesChainSupportEIP7702(chainId, messenger);\n\n let authorizationList:\n | SimulationRequestTransaction['authorizationList']\n | undefined = authorizationListRequest?.map((authorization) => ({\n address: authorization.address,\n from,\n }));\n\n if (with7702 && !delegationAddress && !authorizationList) {\n authorizationList = buildAuthorizationList({\n chainId,\n from,\n messenger,\n publicKeyEIP7702,\n });\n }\n\n try {\n const response = await simulateTransactions(chainId, {\n getSimulationConfig,\n transactions: [\n {\n authorizationList,\n data,\n from,\n to,\n value,\n },\n ],\n suggestFees: {\n withTransfer: true,\n withFeeTransfer: true,\n with7702,\n },\n });\n\n log('Response', response);\n\n const result = parseGasFeeTokens(response);\n\n log('Gas fee tokens', result);\n\n return result;\n } catch (error) {\n log('Failed to gas fee tokens', error);\n return { gasFeeTokens: [], isGasFeeSponsored: false };\n }\n}\n\n/**\n * Check and update gas fee token selection before publishing a transaction.\n *\n * @param request - Request object.\n * @param request.messenger - The transaction controller messenger.\n * @param request.networkClientId - The network client ID.\n * @param request.fetchGasFeeTokens - Function to fetch gas fee tokens.\n * @param request.transaction - Transaction metadata.\n * @param request.updateTransaction - Function to update the transaction.\n */\nexport async function checkGasFeeTokenBeforePublish({\n messenger,\n networkClientId,\n fetchGasFeeTokens,\n transaction,\n updateTransaction,\n}: {\n messenger: TransactionControllerMessenger;\n networkClientId: NetworkClientId;\n fetchGasFeeTokens: (transaction: TransactionMeta) => Promise<GasFeeToken[]>;\n transaction: TransactionMeta;\n updateTransaction: (\n transactionId: string,\n fn: (tx: TransactionMeta) => void,\n ) => void;\n}): Promise<void> {\n const {\n excludeNativeTokenForFee,\n isGasFeeTokenIgnoredIfBalance,\n selectedGasFeeToken,\n } = transaction;\n\n if (\n !selectedGasFeeToken ||\n (!isGasFeeTokenIgnoredIfBalance && !excludeNativeTokenForFee)\n ) {\n return;\n }\n\n log('Checking gas fee token before publish', { selectedGasFeeToken });\n\n if (!excludeNativeTokenForFee) {\n const hasNativeBalance = await isNativeBalanceSufficientForGas(\n transaction,\n messenger,\n networkClientId,\n );\n\n if (hasNativeBalance) {\n log(\n 'Ignoring gas fee token before publish due to sufficient native balance',\n );\n\n updateTransaction(transaction.id, (tx) => {\n tx.isExternalSign = false;\n tx.selectedGasFeeToken = undefined;\n });\n\n return;\n }\n }\n\n const gasFeeTokens = await fetchGasFeeTokens({\n ...transaction,\n isExternalSign: true,\n });\n\n const isSelectedGasFeeTokenAvailable = gasFeeTokens?.some(\n (token) =>\n token.tokenAddress.toLowerCase() === selectedGasFeeToken.toLowerCase(),\n );\n\n if (!isSelectedGasFeeTokenAvailable) {\n updateTransaction(transaction.id, (tx) => {\n tx.gasFeeTokens = gasFeeTokens;\n tx.isExternalSign = false;\n });\n\n throw new Error('Gas fee token not found and insufficient native balance');\n }\n\n updateTransaction(transaction.id, (tx) => {\n tx.gasFeeTokens = gasFeeTokens;\n tx.isExternalSign = true;\n tx.txParams.nonce = undefined;\n });\n\n log('Updated gas fee tokens before publish', gasFeeTokens);\n log('Publishing with selected gas fee token', { selectedGasFeeToken });\n}\n\n/**\n * Extract gas fee tokens from a simulation response.\n *\n * @param response - The simulation response.\n * @returns gasFeeTokens: An array of gas fee tokens. isGasFeeSponsored: Whether the transaction is sponsored\n */\nfunction parseGasFeeTokens(response: SimulationResponse): {\n gasFeeTokens: GasFeeToken[];\n isGasFeeSponsored: boolean;\n} {\n const feeLevel = response.transactions?.[0]\n ?.fees?.[0] as Required<SimulationResponseTransaction>['fees'][0];\n\n const isGasFeeSponsored = response.sponsorship?.isSponsored ?? false;\n\n const tokenFees = feeLevel?.tokenFees ?? [];\n\n return {\n gasFeeTokens: tokenFees.map((tokenFee) => ({\n amount: tokenFee.balanceNeededToken,\n balance: tokenFee.currentBalanceToken,\n decimals: tokenFee.token.decimals,\n fee: tokenFee.serviceFee,\n gas: feeLevel.gas,\n gasTransfer: tokenFee.transferEstimate,\n maxFeePerGas: feeLevel.maxFeePerGas,\n maxPriorityFeePerGas: feeLevel.maxPriorityFeePerGas,\n rateWei: tokenFee.rateWei,\n recipient: tokenFee.feeRecipient,\n symbol: tokenFee.token.symbol,\n tokenAddress: tokenFee.token.address,\n })),\n isGasFeeSponsored,\n };\n}\n\n/**\n * Generate the authorization list for the request.\n *\n * @param request - The request object.\n * @param request.chainId - The chain ID.\n * @param request.from - The sender's address.\n * @param request.messenger - The messenger instance.\n * @param request.publicKeyEIP7702 - The public key for EIP-7702.\n * @returns The authorization list.\n */\nfunction buildAuthorizationList({\n chainId,\n from,\n messenger,\n publicKeyEIP7702,\n}: {\n chainId: Hex;\n from: Hex;\n messenger: TransactionControllerMessenger;\n publicKeyEIP7702?: Hex;\n}): SimulationRequestTransaction['authorizationList'] | undefined {\n if (!publicKeyEIP7702) {\n throw rpcErrors.internal(ERROR_MESSGE_PUBLIC_KEY);\n }\n\n const upgradeAddress = getEIP7702UpgradeContractAddress(\n chainId,\n messenger,\n publicKeyEIP7702,\n );\n\n if (!upgradeAddress) {\n throw rpcErrors.internal(ERROR_MESSAGE_NO_UPGRADE_CONTRACT);\n }\n\n return [\n {\n address: upgradeAddress,\n from,\n },\n ];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"gas-fee-tokens.cjs","sourceRoot":"","sources":["../../src/utils/gas-fee-tokens.ts"],"names":[],"mappings":"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","sourcesContent":["import type { NetworkClientId } from '@metamask/network-controller';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { simulateTransactions } from '../api/simulation-api.js';\nimport type { SimulationRequestTransaction } from '../api/simulation-api.js';\nimport type {\n SimulationResponse,\n SimulationResponseTransaction,\n} from '../api/simulation-api.js';\nimport type {\n GasFeeToken,\n TransactionControllerMessenger,\n TransactionMeta,\n} from '../index.js';\nimport { projectLogger } from '../logger.js';\nimport type { GetSimulationConfig } from '../types.js';\nimport { isNativeBalanceSufficientForGas } from './balance.js';\nimport { ERROR_MESSAGE_NO_UPGRADE_CONTRACT } from './batch.js';\nimport { ERROR_MESSGE_PUBLIC_KEY, doesChainSupportEIP7702 } from './eip7702.js';\nimport { getEIP7702UpgradeContractAddress } from './feature-flags.js';\n\nconst log = createModuleLogger(projectLogger, 'gas-fee-tokens');\n\nexport type GetGasFeeTokensRequest = {\n chainId: Hex;\n isEIP7702GasFeeTokensEnabled: (\n transactionMeta: TransactionMeta,\n ) => Promise<boolean>;\n getSimulationConfig: GetSimulationConfig;\n messenger: TransactionControllerMessenger;\n publicKeyEIP7702?: Hex;\n transactionMeta: TransactionMeta;\n};\n\n/**\n * Get gas fee tokens for a transaction.\n *\n * @param request - The request object.\n * @param request.chainId - The chain ID of the transaction.\n * @param request.isEIP7702GasFeeTokensEnabled - Callback to check if EIP-7702 gas fee tokens are enabled.\n * @param request.messenger - The messenger instance.\n * @param request.publicKeyEIP7702 - Public key to validate EIP-7702 contract signatures.\n * @param request.transactionMeta - The transaction metadata.\n * @param request.getSimulationConfig - Optional transaction simulation parameters.\n * @returns An array of gas fee tokens.\n */\nexport async function getGasFeeTokens({\n chainId,\n isEIP7702GasFeeTokensEnabled,\n messenger,\n publicKeyEIP7702,\n transactionMeta,\n getSimulationConfig,\n}: GetGasFeeTokensRequest): Promise<{\n gasFeeTokens: GasFeeToken[];\n isGasFeeSponsored: boolean;\n}> {\n const { delegationAddress, txParams } = transactionMeta;\n const { authorizationList: authorizationListRequest } = txParams;\n const data = txParams.data as Hex;\n const from = txParams.from as Hex;\n const to = txParams.to as Hex;\n const value = txParams.value as Hex;\n\n log('Request', { chainId, txParams });\n\n const is7702GasFeeTokensEnabled =\n await isEIP7702GasFeeTokensEnabled(transactionMeta);\n\n const with7702 =\n is7702GasFeeTokensEnabled && doesChainSupportEIP7702(chainId, messenger);\n\n let authorizationList:\n | SimulationRequestTransaction['authorizationList']\n | undefined = authorizationListRequest?.map((authorization) => ({\n address: authorization.address,\n from,\n }));\n\n if (with7702 && !delegationAddress && !authorizationList) {\n authorizationList = buildAuthorizationList({\n chainId,\n from,\n messenger,\n publicKeyEIP7702,\n });\n }\n\n try {\n const response = await simulateTransactions(chainId, {\n getSimulationConfig,\n transactions: [\n {\n authorizationList,\n data,\n from,\n to,\n value,\n },\n ],\n suggestFees: {\n withTransfer: true,\n withFeeTransfer: true,\n with7702,\n },\n });\n\n log('Response', response);\n\n const result = parseGasFeeTokens(response);\n\n log('Gas fee tokens', result);\n\n return result;\n } catch (error) {\n log('Failed to gas fee tokens', error);\n return { gasFeeTokens: [], isGasFeeSponsored: false };\n }\n}\n\n/**\n * Check and update gas fee token selection before publishing a transaction.\n *\n * @param request - Request object.\n * @param request.messenger - The transaction controller messenger.\n * @param request.networkClientId - The network client ID.\n * @param request.fetchGasFeeTokens - Function to fetch gas fee tokens.\n * @param request.transaction - Transaction metadata.\n * @param request.updateTransaction - Function to update the transaction.\n */\nexport async function checkGasFeeTokenBeforePublish({\n messenger,\n networkClientId,\n fetchGasFeeTokens,\n transaction,\n updateTransaction,\n}: {\n messenger: TransactionControllerMessenger;\n networkClientId: NetworkClientId;\n fetchGasFeeTokens: (transaction: TransactionMeta) => Promise<GasFeeToken[]>;\n transaction: TransactionMeta;\n updateTransaction: (\n transactionId: string,\n fn: (tx: TransactionMeta) => void,\n ) => void;\n}): Promise<void> {\n const {\n excludeNativeTokenForFee,\n isGasFeeTokenIgnoredIfBalance,\n selectedGasFeeToken,\n } = transaction;\n\n if (\n !selectedGasFeeToken ||\n (!isGasFeeTokenIgnoredIfBalance && !excludeNativeTokenForFee)\n ) {\n return;\n }\n\n log('Checking gas fee token before publish', { selectedGasFeeToken });\n\n if (!excludeNativeTokenForFee) {\n const hasNativeBalance = await isNativeBalanceSufficientForGas(\n transaction,\n messenger,\n networkClientId,\n );\n\n if (hasNativeBalance) {\n log(\n 'Ignoring gas fee token before publish due to sufficient native balance',\n );\n\n updateTransaction(transaction.id, (tx) => {\n tx.isExternalSign = false;\n tx.selectedGasFeeToken = undefined;\n });\n\n return;\n }\n }\n\n const gasFeeTokens = await fetchGasFeeTokens({\n ...transaction,\n isExternalSign: true,\n });\n\n updateTransaction(transaction.id, (tx) => {\n tx.gasFeeTokens = gasFeeTokens;\n tx.isExternalSign = true;\n tx.txParams.nonce = undefined;\n });\n\n log('Updated gas fee tokens before publish', gasFeeTokens);\n\n if (\n !gasFeeTokens?.some(\n (token) =>\n token.tokenAddress.toLowerCase() === selectedGasFeeToken.toLowerCase(),\n )\n ) {\n throw new Error('Gas fee token not found and insufficient native balance');\n }\n\n log('Publishing with selected gas fee token', { selectedGasFeeToken });\n}\n\n/**\n * Extract gas fee tokens from a simulation response.\n *\n * @param response - The simulation response.\n * @returns gasFeeTokens: An array of gas fee tokens. isGasFeeSponsored: Whether the transaction is sponsored\n */\nfunction parseGasFeeTokens(response: SimulationResponse): {\n gasFeeTokens: GasFeeToken[];\n isGasFeeSponsored: boolean;\n} {\n const feeLevel = response.transactions?.[0]\n ?.fees?.[0] as Required<SimulationResponseTransaction>['fees'][0];\n\n const isGasFeeSponsored = response.sponsorship?.isSponsored ?? false;\n\n const tokenFees = feeLevel?.tokenFees ?? [];\n\n return {\n gasFeeTokens: tokenFees.map((tokenFee) => ({\n amount: tokenFee.balanceNeededToken,\n balance: tokenFee.currentBalanceToken,\n decimals: tokenFee.token.decimals,\n fee: tokenFee.serviceFee,\n gas: feeLevel.gas,\n gasTransfer: tokenFee.transferEstimate,\n maxFeePerGas: feeLevel.maxFeePerGas,\n maxPriorityFeePerGas: feeLevel.maxPriorityFeePerGas,\n rateWei: tokenFee.rateWei,\n recipient: tokenFee.feeRecipient,\n symbol: tokenFee.token.symbol,\n tokenAddress: tokenFee.token.address,\n })),\n isGasFeeSponsored,\n };\n}\n\n/**\n * Generate the authorization list for the request.\n *\n * @param request - The request object.\n * @param request.chainId - The chain ID.\n * @param request.from - The sender's address.\n * @param request.messenger - The messenger instance.\n * @param request.publicKeyEIP7702 - The public key for EIP-7702.\n * @returns The authorization list.\n */\nfunction buildAuthorizationList({\n chainId,\n from,\n messenger,\n publicKeyEIP7702,\n}: {\n chainId: Hex;\n from: Hex;\n messenger: TransactionControllerMessenger;\n publicKeyEIP7702?: Hex;\n}): SimulationRequestTransaction['authorizationList'] | undefined {\n if (!publicKeyEIP7702) {\n throw rpcErrors.internal(ERROR_MESSGE_PUBLIC_KEY);\n }\n\n const upgradeAddress = getEIP7702UpgradeContractAddress(\n chainId,\n messenger,\n publicKeyEIP7702,\n );\n\n if (!upgradeAddress) {\n throw rpcErrors.internal(ERROR_MESSAGE_NO_UPGRADE_CONTRACT);\n }\n\n return [\n {\n address: upgradeAddress,\n from,\n },\n ];\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gas-fee-tokens.d.cts","sourceRoot":"","sources":["../../src/utils/gas-fee-tokens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,qCAAqC;AAEpE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAS3C,OAAO,KAAK,EACV,WAAW,EACX,8BAA8B,EAC9B,eAAe,EAChB,qBAAoB;AAErB,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAoB;AAQvD,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,GAAG,CAAC;IACb,4BAA4B,EAAE,CAC5B,eAAe,EAAE,eAAe,KAC7B,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,SAAS,EAAE,8BAA8B,CAAC;IAC1C,gBAAgB,CAAC,EAAE,GAAG,CAAC;IACvB,eAAe,EAAE,eAAe,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CAAC,EACpC,OAAO,EACP,4BAA4B,EAC5B,SAAS,EACT,gBAAgB,EAChB,eAAe,EACf,mBAAmB,GACpB,EAAE,sBAAsB,GAAG,OAAO,CAAC;IAClC,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,iBAAiB,EAAE,OAAO,CAAC;CAC5B,CAAC,CA8DD;AAED;;;;;;;;;GASG;AACH,wBAAsB,6BAA6B,CAAC,EAClD,SAAS,EACT,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,iBAAiB,GAClB,EAAE;IACD,SAAS,EAAE,8BAA8B,CAAC;IAC1C,eAAe,EAAE,eAAe,CAAC;IACjC,iBAAiB,EAAE,CAAC,WAAW,EAAE,eAAe,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5E,WAAW,EAAE,eAAe,CAAC;IAC7B,iBAAiB,EAAE,CACjB,aAAa,EAAE,MAAM,EACrB,EAAE,EAAE,CAAC,EAAE,EAAE,eAAe,KAAK,IAAI,KAC9B,IAAI,CAAC;CACX,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"gas-fee-tokens.d.cts","sourceRoot":"","sources":["../../src/utils/gas-fee-tokens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,qCAAqC;AAEpE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAS3C,OAAO,KAAK,EACV,WAAW,EACX,8BAA8B,EAC9B,eAAe,EAChB,qBAAoB;AAErB,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAoB;AAQvD,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,GAAG,CAAC;IACb,4BAA4B,EAAE,CAC5B,eAAe,EAAE,eAAe,KAC7B,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,SAAS,EAAE,8BAA8B,CAAC;IAC1C,gBAAgB,CAAC,EAAE,GAAG,CAAC;IACvB,eAAe,EAAE,eAAe,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CAAC,EACpC,OAAO,EACP,4BAA4B,EAC5B,SAAS,EACT,gBAAgB,EAChB,eAAe,EACf,mBAAmB,GACpB,EAAE,sBAAsB,GAAG,OAAO,CAAC;IAClC,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,iBAAiB,EAAE,OAAO,CAAC;CAC5B,CAAC,CA8DD;AAED;;;;;;;;;GASG;AACH,wBAAsB,6BAA6B,CAAC,EAClD,SAAS,EACT,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,iBAAiB,GAClB,EAAE;IACD,SAAS,EAAE,8BAA8B,CAAC;IAC1C,eAAe,EAAE,eAAe,CAAC;IACjC,iBAAiB,EAAE,CAAC,WAAW,EAAE,eAAe,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5E,WAAW,EAAE,eAAe,CAAC;IAC7B,iBAAiB,EAAE,CACjB,aAAa,EAAE,MAAM,EACrB,EAAE,EAAE,CAAC,EAAE,EAAE,eAAe,KAAK,IAAI,KAC9B,IAAI,CAAC;CACX,GAAG,OAAO,CAAC,IAAI,CAAC,CA4DhB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gas-fee-tokens.d.mts","sourceRoot":"","sources":["../../src/utils/gas-fee-tokens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,qCAAqC;AAEpE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAS3C,OAAO,KAAK,EACV,WAAW,EACX,8BAA8B,EAC9B,eAAe,EAChB,qBAAoB;AAErB,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAoB;AAQvD,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,GAAG,CAAC;IACb,4BAA4B,EAAE,CAC5B,eAAe,EAAE,eAAe,KAC7B,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,SAAS,EAAE,8BAA8B,CAAC;IAC1C,gBAAgB,CAAC,EAAE,GAAG,CAAC;IACvB,eAAe,EAAE,eAAe,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CAAC,EACpC,OAAO,EACP,4BAA4B,EAC5B,SAAS,EACT,gBAAgB,EAChB,eAAe,EACf,mBAAmB,GACpB,EAAE,sBAAsB,GAAG,OAAO,CAAC;IAClC,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,iBAAiB,EAAE,OAAO,CAAC;CAC5B,CAAC,CA8DD;AAED;;;;;;;;;GASG;AACH,wBAAsB,6BAA6B,CAAC,EAClD,SAAS,EACT,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,iBAAiB,GAClB,EAAE;IACD,SAAS,EAAE,8BAA8B,CAAC;IAC1C,eAAe,EAAE,eAAe,CAAC;IACjC,iBAAiB,EAAE,CAAC,WAAW,EAAE,eAAe,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5E,WAAW,EAAE,eAAe,CAAC;IAC7B,iBAAiB,EAAE,CACjB,aAAa,EAAE,MAAM,EACrB,EAAE,EAAE,CAAC,EAAE,EAAE,eAAe,KAAK,IAAI,KAC9B,IAAI,CAAC;CACX,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"gas-fee-tokens.d.mts","sourceRoot":"","sources":["../../src/utils/gas-fee-tokens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,qCAAqC;AAEpE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAS3C,OAAO,KAAK,EACV,WAAW,EACX,8BAA8B,EAC9B,eAAe,EAChB,qBAAoB;AAErB,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAoB;AAQvD,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,GAAG,CAAC;IACb,4BAA4B,EAAE,CAC5B,eAAe,EAAE,eAAe,KAC7B,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,SAAS,EAAE,8BAA8B,CAAC;IAC1C,gBAAgB,CAAC,EAAE,GAAG,CAAC;IACvB,eAAe,EAAE,eAAe,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CAAC,EACpC,OAAO,EACP,4BAA4B,EAC5B,SAAS,EACT,gBAAgB,EAChB,eAAe,EACf,mBAAmB,GACpB,EAAE,sBAAsB,GAAG,OAAO,CAAC;IAClC,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,iBAAiB,EAAE,OAAO,CAAC;CAC5B,CAAC,CA8DD;AAED;;;;;;;;;GASG;AACH,wBAAsB,6BAA6B,CAAC,EAClD,SAAS,EACT,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,iBAAiB,GAClB,EAAE;IACD,SAAS,EAAE,8BAA8B,CAAC;IAC1C,eAAe,EAAE,eAAe,CAAC;IACjC,iBAAiB,EAAE,CAAC,WAAW,EAAE,eAAe,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5E,WAAW,EAAE,eAAe,CAAC;IAC7B,iBAAiB,EAAE,CACjB,aAAa,EAAE,MAAM,EACrB,EAAE,EAAE,CAAC,EAAE,EAAE,eAAe,KAAK,IAAI,KAC9B,IAAI,CAAC;CACX,GAAG,OAAO,CAAC,IAAI,CAAC,CA4DhB"}
|
|
@@ -101,20 +101,15 @@ export async function checkGasFeeTokenBeforePublish({ messenger, networkClientId
|
|
|
101
101
|
...transaction,
|
|
102
102
|
isExternalSign: true,
|
|
103
103
|
});
|
|
104
|
-
const isSelectedGasFeeTokenAvailable = gasFeeTokens?.some((token) => token.tokenAddress.toLowerCase() === selectedGasFeeToken.toLowerCase());
|
|
105
|
-
if (!isSelectedGasFeeTokenAvailable) {
|
|
106
|
-
updateTransaction(transaction.id, (tx) => {
|
|
107
|
-
tx.gasFeeTokens = gasFeeTokens;
|
|
108
|
-
tx.isExternalSign = false;
|
|
109
|
-
});
|
|
110
|
-
throw new Error('Gas fee token not found and insufficient native balance');
|
|
111
|
-
}
|
|
112
104
|
updateTransaction(transaction.id, (tx) => {
|
|
113
105
|
tx.gasFeeTokens = gasFeeTokens;
|
|
114
106
|
tx.isExternalSign = true;
|
|
115
107
|
tx.txParams.nonce = undefined;
|
|
116
108
|
});
|
|
117
109
|
log('Updated gas fee tokens before publish', gasFeeTokens);
|
|
110
|
+
if (!gasFeeTokens?.some((token) => token.tokenAddress.toLowerCase() === selectedGasFeeToken.toLowerCase())) {
|
|
111
|
+
throw new Error('Gas fee token not found and insufficient native balance');
|
|
112
|
+
}
|
|
118
113
|
log('Publishing with selected gas fee token', { selectedGasFeeToken });
|
|
119
114
|
}
|
|
120
115
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gas-fee-tokens.mjs","sourceRoot":"","sources":["../../src/utils/gas-fee-tokens.ts"],"names":[],"mappings":"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","sourcesContent":["import type { NetworkClientId } from '@metamask/network-controller';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { simulateTransactions } from '../api/simulation-api.js';\nimport type { SimulationRequestTransaction } from '../api/simulation-api.js';\nimport type {\n SimulationResponse,\n SimulationResponseTransaction,\n} from '../api/simulation-api.js';\nimport type {\n GasFeeToken,\n TransactionControllerMessenger,\n TransactionMeta,\n} from '../index.js';\nimport { projectLogger } from '../logger.js';\nimport type { GetSimulationConfig } from '../types.js';\nimport { isNativeBalanceSufficientForGas } from './balance.js';\nimport { ERROR_MESSAGE_NO_UPGRADE_CONTRACT } from './batch.js';\nimport { ERROR_MESSGE_PUBLIC_KEY, doesChainSupportEIP7702 } from './eip7702.js';\nimport { getEIP7702UpgradeContractAddress } from './feature-flags.js';\n\nconst log = createModuleLogger(projectLogger, 'gas-fee-tokens');\n\nexport type GetGasFeeTokensRequest = {\n chainId: Hex;\n isEIP7702GasFeeTokensEnabled: (\n transactionMeta: TransactionMeta,\n ) => Promise<boolean>;\n getSimulationConfig: GetSimulationConfig;\n messenger: TransactionControllerMessenger;\n publicKeyEIP7702?: Hex;\n transactionMeta: TransactionMeta;\n};\n\n/**\n * Get gas fee tokens for a transaction.\n *\n * @param request - The request object.\n * @param request.chainId - The chain ID of the transaction.\n * @param request.isEIP7702GasFeeTokensEnabled - Callback to check if EIP-7702 gas fee tokens are enabled.\n * @param request.messenger - The messenger instance.\n * @param request.publicKeyEIP7702 - Public key to validate EIP-7702 contract signatures.\n * @param request.transactionMeta - The transaction metadata.\n * @param request.getSimulationConfig - Optional transaction simulation parameters.\n * @returns An array of gas fee tokens.\n */\nexport async function getGasFeeTokens({\n chainId,\n isEIP7702GasFeeTokensEnabled,\n messenger,\n publicKeyEIP7702,\n transactionMeta,\n getSimulationConfig,\n}: GetGasFeeTokensRequest): Promise<{\n gasFeeTokens: GasFeeToken[];\n isGasFeeSponsored: boolean;\n}> {\n const { delegationAddress, txParams } = transactionMeta;\n const { authorizationList: authorizationListRequest } = txParams;\n const data = txParams.data as Hex;\n const from = txParams.from as Hex;\n const to = txParams.to as Hex;\n const value = txParams.value as Hex;\n\n log('Request', { chainId, txParams });\n\n const is7702GasFeeTokensEnabled =\n await isEIP7702GasFeeTokensEnabled(transactionMeta);\n\n const with7702 =\n is7702GasFeeTokensEnabled && doesChainSupportEIP7702(chainId, messenger);\n\n let authorizationList:\n | SimulationRequestTransaction['authorizationList']\n | undefined = authorizationListRequest?.map((authorization) => ({\n address: authorization.address,\n from,\n }));\n\n if (with7702 && !delegationAddress && !authorizationList) {\n authorizationList = buildAuthorizationList({\n chainId,\n from,\n messenger,\n publicKeyEIP7702,\n });\n }\n\n try {\n const response = await simulateTransactions(chainId, {\n getSimulationConfig,\n transactions: [\n {\n authorizationList,\n data,\n from,\n to,\n value,\n },\n ],\n suggestFees: {\n withTransfer: true,\n withFeeTransfer: true,\n with7702,\n },\n });\n\n log('Response', response);\n\n const result = parseGasFeeTokens(response);\n\n log('Gas fee tokens', result);\n\n return result;\n } catch (error) {\n log('Failed to gas fee tokens', error);\n return { gasFeeTokens: [], isGasFeeSponsored: false };\n }\n}\n\n/**\n * Check and update gas fee token selection before publishing a transaction.\n *\n * @param request - Request object.\n * @param request.messenger - The transaction controller messenger.\n * @param request.networkClientId - The network client ID.\n * @param request.fetchGasFeeTokens - Function to fetch gas fee tokens.\n * @param request.transaction - Transaction metadata.\n * @param request.updateTransaction - Function to update the transaction.\n */\nexport async function checkGasFeeTokenBeforePublish({\n messenger,\n networkClientId,\n fetchGasFeeTokens,\n transaction,\n updateTransaction,\n}: {\n messenger: TransactionControllerMessenger;\n networkClientId: NetworkClientId;\n fetchGasFeeTokens: (transaction: TransactionMeta) => Promise<GasFeeToken[]>;\n transaction: TransactionMeta;\n updateTransaction: (\n transactionId: string,\n fn: (tx: TransactionMeta) => void,\n ) => void;\n}): Promise<void> {\n const {\n excludeNativeTokenForFee,\n isGasFeeTokenIgnoredIfBalance,\n selectedGasFeeToken,\n } = transaction;\n\n if (\n !selectedGasFeeToken ||\n (!isGasFeeTokenIgnoredIfBalance && !excludeNativeTokenForFee)\n ) {\n return;\n }\n\n log('Checking gas fee token before publish', { selectedGasFeeToken });\n\n if (!excludeNativeTokenForFee) {\n const hasNativeBalance = await isNativeBalanceSufficientForGas(\n transaction,\n messenger,\n networkClientId,\n );\n\n if (hasNativeBalance) {\n log(\n 'Ignoring gas fee token before publish due to sufficient native balance',\n );\n\n updateTransaction(transaction.id, (tx) => {\n tx.isExternalSign = false;\n tx.selectedGasFeeToken = undefined;\n });\n\n return;\n }\n }\n\n const gasFeeTokens = await fetchGasFeeTokens({\n ...transaction,\n isExternalSign: true,\n });\n\n const isSelectedGasFeeTokenAvailable = gasFeeTokens?.some(\n (token) =>\n token.tokenAddress.toLowerCase() === selectedGasFeeToken.toLowerCase(),\n );\n\n if (!isSelectedGasFeeTokenAvailable) {\n updateTransaction(transaction.id, (tx) => {\n tx.gasFeeTokens = gasFeeTokens;\n tx.isExternalSign = false;\n });\n\n throw new Error('Gas fee token not found and insufficient native balance');\n }\n\n updateTransaction(transaction.id, (tx) => {\n tx.gasFeeTokens = gasFeeTokens;\n tx.isExternalSign = true;\n tx.txParams.nonce = undefined;\n });\n\n log('Updated gas fee tokens before publish', gasFeeTokens);\n log('Publishing with selected gas fee token', { selectedGasFeeToken });\n}\n\n/**\n * Extract gas fee tokens from a simulation response.\n *\n * @param response - The simulation response.\n * @returns gasFeeTokens: An array of gas fee tokens. isGasFeeSponsored: Whether the transaction is sponsored\n */\nfunction parseGasFeeTokens(response: SimulationResponse): {\n gasFeeTokens: GasFeeToken[];\n isGasFeeSponsored: boolean;\n} {\n const feeLevel = response.transactions?.[0]\n ?.fees?.[0] as Required<SimulationResponseTransaction>['fees'][0];\n\n const isGasFeeSponsored = response.sponsorship?.isSponsored ?? false;\n\n const tokenFees = feeLevel?.tokenFees ?? [];\n\n return {\n gasFeeTokens: tokenFees.map((tokenFee) => ({\n amount: tokenFee.balanceNeededToken,\n balance: tokenFee.currentBalanceToken,\n decimals: tokenFee.token.decimals,\n fee: tokenFee.serviceFee,\n gas: feeLevel.gas,\n gasTransfer: tokenFee.transferEstimate,\n maxFeePerGas: feeLevel.maxFeePerGas,\n maxPriorityFeePerGas: feeLevel.maxPriorityFeePerGas,\n rateWei: tokenFee.rateWei,\n recipient: tokenFee.feeRecipient,\n symbol: tokenFee.token.symbol,\n tokenAddress: tokenFee.token.address,\n })),\n isGasFeeSponsored,\n };\n}\n\n/**\n * Generate the authorization list for the request.\n *\n * @param request - The request object.\n * @param request.chainId - The chain ID.\n * @param request.from - The sender's address.\n * @param request.messenger - The messenger instance.\n * @param request.publicKeyEIP7702 - The public key for EIP-7702.\n * @returns The authorization list.\n */\nfunction buildAuthorizationList({\n chainId,\n from,\n messenger,\n publicKeyEIP7702,\n}: {\n chainId: Hex;\n from: Hex;\n messenger: TransactionControllerMessenger;\n publicKeyEIP7702?: Hex;\n}): SimulationRequestTransaction['authorizationList'] | undefined {\n if (!publicKeyEIP7702) {\n throw rpcErrors.internal(ERROR_MESSGE_PUBLIC_KEY);\n }\n\n const upgradeAddress = getEIP7702UpgradeContractAddress(\n chainId,\n messenger,\n publicKeyEIP7702,\n );\n\n if (!upgradeAddress) {\n throw rpcErrors.internal(ERROR_MESSAGE_NO_UPGRADE_CONTRACT);\n }\n\n return [\n {\n address: upgradeAddress,\n from,\n },\n ];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"gas-fee-tokens.mjs","sourceRoot":"","sources":["../../src/utils/gas-fee-tokens.ts"],"names":[],"mappings":"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","sourcesContent":["import type { NetworkClientId } from '@metamask/network-controller';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { simulateTransactions } from '../api/simulation-api.js';\nimport type { SimulationRequestTransaction } from '../api/simulation-api.js';\nimport type {\n SimulationResponse,\n SimulationResponseTransaction,\n} from '../api/simulation-api.js';\nimport type {\n GasFeeToken,\n TransactionControllerMessenger,\n TransactionMeta,\n} from '../index.js';\nimport { projectLogger } from '../logger.js';\nimport type { GetSimulationConfig } from '../types.js';\nimport { isNativeBalanceSufficientForGas } from './balance.js';\nimport { ERROR_MESSAGE_NO_UPGRADE_CONTRACT } from './batch.js';\nimport { ERROR_MESSGE_PUBLIC_KEY, doesChainSupportEIP7702 } from './eip7702.js';\nimport { getEIP7702UpgradeContractAddress } from './feature-flags.js';\n\nconst log = createModuleLogger(projectLogger, 'gas-fee-tokens');\n\nexport type GetGasFeeTokensRequest = {\n chainId: Hex;\n isEIP7702GasFeeTokensEnabled: (\n transactionMeta: TransactionMeta,\n ) => Promise<boolean>;\n getSimulationConfig: GetSimulationConfig;\n messenger: TransactionControllerMessenger;\n publicKeyEIP7702?: Hex;\n transactionMeta: TransactionMeta;\n};\n\n/**\n * Get gas fee tokens for a transaction.\n *\n * @param request - The request object.\n * @param request.chainId - The chain ID of the transaction.\n * @param request.isEIP7702GasFeeTokensEnabled - Callback to check if EIP-7702 gas fee tokens are enabled.\n * @param request.messenger - The messenger instance.\n * @param request.publicKeyEIP7702 - Public key to validate EIP-7702 contract signatures.\n * @param request.transactionMeta - The transaction metadata.\n * @param request.getSimulationConfig - Optional transaction simulation parameters.\n * @returns An array of gas fee tokens.\n */\nexport async function getGasFeeTokens({\n chainId,\n isEIP7702GasFeeTokensEnabled,\n messenger,\n publicKeyEIP7702,\n transactionMeta,\n getSimulationConfig,\n}: GetGasFeeTokensRequest): Promise<{\n gasFeeTokens: GasFeeToken[];\n isGasFeeSponsored: boolean;\n}> {\n const { delegationAddress, txParams } = transactionMeta;\n const { authorizationList: authorizationListRequest } = txParams;\n const data = txParams.data as Hex;\n const from = txParams.from as Hex;\n const to = txParams.to as Hex;\n const value = txParams.value as Hex;\n\n log('Request', { chainId, txParams });\n\n const is7702GasFeeTokensEnabled =\n await isEIP7702GasFeeTokensEnabled(transactionMeta);\n\n const with7702 =\n is7702GasFeeTokensEnabled && doesChainSupportEIP7702(chainId, messenger);\n\n let authorizationList:\n | SimulationRequestTransaction['authorizationList']\n | undefined = authorizationListRequest?.map((authorization) => ({\n address: authorization.address,\n from,\n }));\n\n if (with7702 && !delegationAddress && !authorizationList) {\n authorizationList = buildAuthorizationList({\n chainId,\n from,\n messenger,\n publicKeyEIP7702,\n });\n }\n\n try {\n const response = await simulateTransactions(chainId, {\n getSimulationConfig,\n transactions: [\n {\n authorizationList,\n data,\n from,\n to,\n value,\n },\n ],\n suggestFees: {\n withTransfer: true,\n withFeeTransfer: true,\n with7702,\n },\n });\n\n log('Response', response);\n\n const result = parseGasFeeTokens(response);\n\n log('Gas fee tokens', result);\n\n return result;\n } catch (error) {\n log('Failed to gas fee tokens', error);\n return { gasFeeTokens: [], isGasFeeSponsored: false };\n }\n}\n\n/**\n * Check and update gas fee token selection before publishing a transaction.\n *\n * @param request - Request object.\n * @param request.messenger - The transaction controller messenger.\n * @param request.networkClientId - The network client ID.\n * @param request.fetchGasFeeTokens - Function to fetch gas fee tokens.\n * @param request.transaction - Transaction metadata.\n * @param request.updateTransaction - Function to update the transaction.\n */\nexport async function checkGasFeeTokenBeforePublish({\n messenger,\n networkClientId,\n fetchGasFeeTokens,\n transaction,\n updateTransaction,\n}: {\n messenger: TransactionControllerMessenger;\n networkClientId: NetworkClientId;\n fetchGasFeeTokens: (transaction: TransactionMeta) => Promise<GasFeeToken[]>;\n transaction: TransactionMeta;\n updateTransaction: (\n transactionId: string,\n fn: (tx: TransactionMeta) => void,\n ) => void;\n}): Promise<void> {\n const {\n excludeNativeTokenForFee,\n isGasFeeTokenIgnoredIfBalance,\n selectedGasFeeToken,\n } = transaction;\n\n if (\n !selectedGasFeeToken ||\n (!isGasFeeTokenIgnoredIfBalance && !excludeNativeTokenForFee)\n ) {\n return;\n }\n\n log('Checking gas fee token before publish', { selectedGasFeeToken });\n\n if (!excludeNativeTokenForFee) {\n const hasNativeBalance = await isNativeBalanceSufficientForGas(\n transaction,\n messenger,\n networkClientId,\n );\n\n if (hasNativeBalance) {\n log(\n 'Ignoring gas fee token before publish due to sufficient native balance',\n );\n\n updateTransaction(transaction.id, (tx) => {\n tx.isExternalSign = false;\n tx.selectedGasFeeToken = undefined;\n });\n\n return;\n }\n }\n\n const gasFeeTokens = await fetchGasFeeTokens({\n ...transaction,\n isExternalSign: true,\n });\n\n updateTransaction(transaction.id, (tx) => {\n tx.gasFeeTokens = gasFeeTokens;\n tx.isExternalSign = true;\n tx.txParams.nonce = undefined;\n });\n\n log('Updated gas fee tokens before publish', gasFeeTokens);\n\n if (\n !gasFeeTokens?.some(\n (token) =>\n token.tokenAddress.toLowerCase() === selectedGasFeeToken.toLowerCase(),\n )\n ) {\n throw new Error('Gas fee token not found and insufficient native balance');\n }\n\n log('Publishing with selected gas fee token', { selectedGasFeeToken });\n}\n\n/**\n * Extract gas fee tokens from a simulation response.\n *\n * @param response - The simulation response.\n * @returns gasFeeTokens: An array of gas fee tokens. isGasFeeSponsored: Whether the transaction is sponsored\n */\nfunction parseGasFeeTokens(response: SimulationResponse): {\n gasFeeTokens: GasFeeToken[];\n isGasFeeSponsored: boolean;\n} {\n const feeLevel = response.transactions?.[0]\n ?.fees?.[0] as Required<SimulationResponseTransaction>['fees'][0];\n\n const isGasFeeSponsored = response.sponsorship?.isSponsored ?? false;\n\n const tokenFees = feeLevel?.tokenFees ?? [];\n\n return {\n gasFeeTokens: tokenFees.map((tokenFee) => ({\n amount: tokenFee.balanceNeededToken,\n balance: tokenFee.currentBalanceToken,\n decimals: tokenFee.token.decimals,\n fee: tokenFee.serviceFee,\n gas: feeLevel.gas,\n gasTransfer: tokenFee.transferEstimate,\n maxFeePerGas: feeLevel.maxFeePerGas,\n maxPriorityFeePerGas: feeLevel.maxPriorityFeePerGas,\n rateWei: tokenFee.rateWei,\n recipient: tokenFee.feeRecipient,\n symbol: tokenFee.token.symbol,\n tokenAddress: tokenFee.token.address,\n })),\n isGasFeeSponsored,\n };\n}\n\n/**\n * Generate the authorization list for the request.\n *\n * @param request - The request object.\n * @param request.chainId - The chain ID.\n * @param request.from - The sender's address.\n * @param request.messenger - The messenger instance.\n * @param request.publicKeyEIP7702 - The public key for EIP-7702.\n * @returns The authorization list.\n */\nfunction buildAuthorizationList({\n chainId,\n from,\n messenger,\n publicKeyEIP7702,\n}: {\n chainId: Hex;\n from: Hex;\n messenger: TransactionControllerMessenger;\n publicKeyEIP7702?: Hex;\n}): SimulationRequestTransaction['authorizationList'] | undefined {\n if (!publicKeyEIP7702) {\n throw rpcErrors.internal(ERROR_MESSGE_PUBLIC_KEY);\n }\n\n const upgradeAddress = getEIP7702UpgradeContractAddress(\n chainId,\n messenger,\n publicKeyEIP7702,\n );\n\n if (!upgradeAddress) {\n throw rpcErrors.internal(ERROR_MESSAGE_NO_UPGRADE_CONTRACT);\n }\n\n return [\n {\n address: upgradeAddress,\n from,\n },\n ];\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamask-previews/transaction-controller",
|
|
3
|
-
"version": "69.8.0-preview-
|
|
3
|
+
"version": "69.8.0-preview-b123e43e2",
|
|
4
4
|
"description": "Stores transactions alongside their periodically updated statuses and manages interactions such as approval and cancellation",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Ethereum",
|