@metamask/transaction-pay-controller 16.4.1 → 17.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -1
- package/dist/strategy/across/across-quotes.cjs +42 -8
- package/dist/strategy/across/across-quotes.cjs.map +1 -1
- package/dist/strategy/across/across-quotes.d.cts.map +1 -1
- package/dist/strategy/across/across-quotes.d.mts.map +1 -1
- package/dist/strategy/across/across-quotes.mjs +42 -8
- package/dist/strategy/across/across-quotes.mjs.map +1 -1
- package/dist/strategy/relay/constants.cjs +15 -1
- package/dist/strategy/relay/constants.cjs.map +1 -1
- package/dist/strategy/relay/constants.d.cts +5 -0
- package/dist/strategy/relay/constants.d.cts.map +1 -1
- package/dist/strategy/relay/constants.d.mts +5 -0
- package/dist/strategy/relay/constants.d.mts.map +1 -1
- package/dist/strategy/relay/constants.mjs +14 -0
- package/dist/strategy/relay/constants.mjs.map +1 -1
- package/dist/strategy/relay/gas-station.cjs +1 -2
- package/dist/strategy/relay/gas-station.cjs.map +1 -1
- package/dist/strategy/relay/gas-station.d.cts.map +1 -1
- package/dist/strategy/relay/gas-station.d.mts.map +1 -1
- package/dist/strategy/relay/gas-station.mjs +2 -3
- package/dist/strategy/relay/gas-station.mjs.map +1 -1
- package/dist/strategy/relay/relay-api.cjs +55 -0
- package/dist/strategy/relay/relay-api.cjs.map +1 -0
- package/dist/strategy/relay/relay-api.d.cts +26 -0
- package/dist/strategy/relay/relay-api.d.cts.map +1 -0
- package/dist/strategy/relay/relay-api.d.mts +26 -0
- package/dist/strategy/relay/relay-api.d.mts.map +1 -0
- package/dist/strategy/relay/relay-api.mjs +49 -0
- package/dist/strategy/relay/relay-api.mjs.map +1 -0
- package/dist/strategy/relay/relay-quotes.cjs +123 -31
- package/dist/strategy/relay/relay-quotes.cjs.map +1 -1
- package/dist/strategy/relay/relay-quotes.d.cts.map +1 -1
- package/dist/strategy/relay/relay-quotes.d.mts.map +1 -1
- package/dist/strategy/relay/relay-quotes.mjs +125 -33
- package/dist/strategy/relay/relay-quotes.mjs.map +1 -1
- package/dist/strategy/relay/relay-submit.cjs +144 -19
- package/dist/strategy/relay/relay-submit.cjs.map +1 -1
- package/dist/strategy/relay/relay-submit.d.cts.map +1 -1
- package/dist/strategy/relay/relay-submit.d.mts.map +1 -1
- package/dist/strategy/relay/relay-submit.mjs +147 -22
- package/dist/strategy/relay/relay-submit.mjs.map +1 -1
- package/dist/strategy/relay/types.cjs.map +1 -1
- package/dist/strategy/relay/types.d.cts +29 -1
- package/dist/strategy/relay/types.d.cts.map +1 -1
- package/dist/strategy/relay/types.d.mts +29 -1
- package/dist/strategy/relay/types.d.mts.map +1 -1
- package/dist/strategy/relay/types.mjs.map +1 -1
- package/dist/tests/messenger-mock.cjs +3 -0
- package/dist/tests/messenger-mock.cjs.map +1 -1
- package/dist/tests/messenger-mock.d.cts +9 -1
- package/dist/tests/messenger-mock.d.cts.map +1 -1
- package/dist/tests/messenger-mock.d.mts +9 -1
- package/dist/tests/messenger-mock.d.mts.map +1 -1
- package/dist/tests/messenger-mock.mjs +3 -0
- package/dist/tests/messenger-mock.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +2 -1
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +2 -1
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/dist/utils/feature-flags.cjs +75 -7
- package/dist/utils/feature-flags.cjs.map +1 -1
- package/dist/utils/feature-flags.d.cts +49 -3
- package/dist/utils/feature-flags.d.cts.map +1 -1
- package/dist/utils/feature-flags.d.mts +49 -3
- package/dist/utils/feature-flags.d.mts.map +1 -1
- package/dist/utils/feature-flags.mjs +69 -6
- package/dist/utils/feature-flags.mjs.map +1 -1
- package/dist/utils/token.cjs +39 -40
- package/dist/utils/token.cjs.map +1 -1
- package/dist/utils/token.d.cts +0 -12
- package/dist/utils/token.d.cts.map +1 -1
- package/dist/utils/token.d.mts +0 -12
- package/dist/utils/token.d.mts.map +1 -1
- package/dist/utils/token.mjs +38 -39
- package/dist/utils/token.mjs.map +1 -1
- package/dist/utils/transaction.cjs +16 -1
- package/dist/utils/transaction.cjs.map +1 -1
- package/dist/utils/transaction.d.cts +10 -0
- package/dist/utils/transaction.d.cts.map +1 -1
- package/dist/utils/transaction.d.mts +10 -0
- package/dist/utils/transaction.d.mts.map +1 -1
- package/dist/utils/transaction.mjs +15 -1
- package/dist/utils/transaction.mjs.map +1 -1
- package/package.json +6 -5
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { TransactionType } from "@metamask/transaction-controller";
|
|
2
|
+
import type { RelayStatus } from "./types.mjs";
|
|
2
3
|
export declare const RELAY_URL_BASE = "https://api.relay.link";
|
|
4
|
+
export declare const RELAY_EXECUTE_URL = "https://api.relay.link/execute";
|
|
5
|
+
export declare const RELAY_QUOTE_URL = "https://api.relay.link/quote";
|
|
3
6
|
export declare const RELAY_STATUS_URL = "https://api.relay.link/intents/status/v3";
|
|
4
7
|
export declare const RELAY_POLLING_INTERVAL = 1000;
|
|
5
8
|
export declare const TOKEN_TRANSFER_FOUR_BYTE = "0xa9059cbb";
|
|
9
|
+
export declare const RELAY_FAILURE_STATUSES: RelayStatus[];
|
|
10
|
+
export declare const RELAY_PENDING_STATUSES: RelayStatus[];
|
|
6
11
|
export declare const RELAY_DEPOSIT_TYPES: Record<string, TransactionType>;
|
|
7
12
|
//# sourceMappingURL=constants.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.mts","sourceRoot":"","sources":["../../../src/strategy/relay/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,yCAAyC;AAEnE,eAAO,MAAM,cAAc,2BAA2B,CAAC;AACvD,eAAO,MAAM,gBAAgB,6CAAwC,CAAC;AACtE,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAC3C,eAAO,MAAM,wBAAwB,eAAe,CAAC;AAErD,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAG/D,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.d.mts","sourceRoot":"","sources":["../../../src/strategy/relay/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,yCAAyC;AAEnE,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAgB;AAE3C,eAAO,MAAM,cAAc,2BAA2B,CAAC;AACvD,eAAO,MAAM,iBAAiB,mCAA8B,CAAC;AAC7D,eAAO,MAAM,eAAe,iCAA4B,CAAC;AACzD,eAAO,MAAM,gBAAgB,6CAAwC,CAAC;AACtE,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAC3C,eAAO,MAAM,wBAAwB,eAAe,CAAC;AAErD,eAAO,MAAM,sBAAsB,EAAE,WAAW,EAI/C,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,WAAW,EAM/C,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAG/D,CAAC"}
|
|
@@ -1,8 +1,22 @@
|
|
|
1
1
|
import { TransactionType } from "@metamask/transaction-controller";
|
|
2
2
|
export const RELAY_URL_BASE = 'https://api.relay.link';
|
|
3
|
+
export const RELAY_EXECUTE_URL = `${RELAY_URL_BASE}/execute`;
|
|
4
|
+
export const RELAY_QUOTE_URL = `${RELAY_URL_BASE}/quote`;
|
|
3
5
|
export const RELAY_STATUS_URL = `${RELAY_URL_BASE}/intents/status/v3`;
|
|
4
6
|
export const RELAY_POLLING_INTERVAL = 1000; // 1 Second
|
|
5
7
|
export const TOKEN_TRANSFER_FOUR_BYTE = '0xa9059cbb';
|
|
8
|
+
export const RELAY_FAILURE_STATUSES = [
|
|
9
|
+
'failure',
|
|
10
|
+
'refund',
|
|
11
|
+
'refunded',
|
|
12
|
+
];
|
|
13
|
+
export const RELAY_PENDING_STATUSES = [
|
|
14
|
+
'delayed',
|
|
15
|
+
'depositing',
|
|
16
|
+
'pending',
|
|
17
|
+
'submitted',
|
|
18
|
+
'waiting',
|
|
19
|
+
];
|
|
6
20
|
export const RELAY_DEPOSIT_TYPES = {
|
|
7
21
|
[TransactionType.predictDeposit]: TransactionType.predictRelayDeposit,
|
|
8
22
|
[TransactionType.perpsDeposit]: TransactionType.perpsRelayDeposit,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.mjs","sourceRoot":"","sources":["../../../src/strategy/relay/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,yCAAyC;
|
|
1
|
+
{"version":3,"file":"constants.mjs","sourceRoot":"","sources":["../../../src/strategy/relay/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,yCAAyC;AAInE,MAAM,CAAC,MAAM,cAAc,GAAG,wBAAwB,CAAC;AACvD,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,cAAc,UAAU,CAAC;AAC7D,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,cAAc,QAAQ,CAAC;AACzD,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,cAAc,oBAAoB,CAAC;AACtE,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC,CAAC,WAAW;AACvD,MAAM,CAAC,MAAM,wBAAwB,GAAG,YAAY,CAAC;AAErD,MAAM,CAAC,MAAM,sBAAsB,GAAkB;IACnD,SAAS;IACT,QAAQ;IACR,UAAU;CACX,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAkB;IACnD,SAAS;IACT,YAAY;IACZ,SAAS;IACT,WAAW;IACX,SAAS;CACV,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAoC;IAClE,CAAC,eAAe,CAAC,cAAc,CAAC,EAAE,eAAe,CAAC,mBAAmB;IACrE,CAAC,eAAe,CAAC,YAAY,CAAC,EAAE,eAAe,CAAC,iBAAiB;CAClE,CAAC","sourcesContent":["import { TransactionType } from '@metamask/transaction-controller';\n\nimport type { RelayStatus } from './types';\n\nexport const RELAY_URL_BASE = 'https://api.relay.link';\nexport const RELAY_EXECUTE_URL = `${RELAY_URL_BASE}/execute`;\nexport const RELAY_QUOTE_URL = `${RELAY_URL_BASE}/quote`;\nexport const RELAY_STATUS_URL = `${RELAY_URL_BASE}/intents/status/v3`;\nexport const RELAY_POLLING_INTERVAL = 1000; // 1 Second\nexport const TOKEN_TRANSFER_FOUR_BYTE = '0xa9059cbb';\n\nexport const RELAY_FAILURE_STATUSES: RelayStatus[] = [\n 'failure',\n 'refund',\n 'refunded',\n];\n\nexport const RELAY_PENDING_STATUSES: RelayStatus[] = [\n 'delayed',\n 'depositing',\n 'pending',\n 'submitted',\n 'waiting',\n];\n\nexport const RELAY_DEPOSIT_TYPES: Record<string, TransactionType> = {\n [TransactionType.predictDeposit]: TransactionType.predictRelayDeposit,\n [TransactionType.perpsDeposit]: TransactionType.perpsRelayDeposit,\n};\n"]}
|
|
@@ -10,8 +10,7 @@ const gas_1 = require("../../utils/gas.cjs");
|
|
|
10
10
|
const log = (0, utils_1.createModuleLogger)(logger_1.projectLogger, 'relay-gas-station');
|
|
11
11
|
function getGasStationEligibility(messenger, sourceChainId) {
|
|
12
12
|
const { relayDisabledGasStationChains } = (0, feature_flags_1.getFeatureFlags)(messenger);
|
|
13
|
-
const
|
|
14
|
-
const chainSupportsGasStation = supportedChains.some((supportedChainId) => supportedChainId.toLowerCase() === sourceChainId.toLowerCase());
|
|
13
|
+
const chainSupportsGasStation = (0, feature_flags_1.isEIP7702Chain)(messenger, sourceChainId);
|
|
15
14
|
const isDisabledChain = relayDisabledGasStationChains.includes(sourceChainId);
|
|
16
15
|
return {
|
|
17
16
|
chainSupportsGasStation,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gas-station.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/gas-station.ts"],"names":[],"mappings":";;;AAAA,iEAAmD;AAGnD,2CAAqD;AACrD,+CAAyC;AAEzC,6CAA6C;AAM7C,
|
|
1
|
+
{"version":3,"file":"gas-station.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/gas-station.ts"],"names":[],"mappings":"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","sourcesContent":["import { toHex } from '@metamask/controller-utils';\nimport type { GasFeeToken } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { projectLogger } from '../../logger';\nimport type {\n Amount,\n QuoteRequest,\n TransactionPayControllerMessenger,\n} from '../../types';\nimport { getFeatureFlags, isEIP7702Chain } from '../../utils/feature-flags';\nimport { calculateGasFeeTokenCost } from '../../utils/gas';\n\nconst log = createModuleLogger(projectLogger, 'relay-gas-station');\n\ntype GasStationCostParams = {\n firstStepData: {\n data: Hex;\n to: Hex;\n value?: string;\n };\n messenger: TransactionPayControllerMessenger;\n request: Pick<QuoteRequest, 'from' | 'sourceChainId' | 'sourceTokenAddress'>;\n totalGasEstimate: number;\n totalItemCount: number;\n};\n\nexport type GasStationEligibility = {\n chainSupportsGasStation: boolean;\n isDisabledChain: boolean;\n isEligible: boolean;\n};\n\nexport function getGasStationEligibility(\n messenger: TransactionPayControllerMessenger,\n sourceChainId: QuoteRequest['sourceChainId'],\n): GasStationEligibility {\n const { relayDisabledGasStationChains } = getFeatureFlags(messenger);\n const chainSupportsGasStation = isEIP7702Chain(messenger, sourceChainId);\n\n const isDisabledChain = relayDisabledGasStationChains.includes(sourceChainId);\n\n return {\n chainSupportsGasStation,\n isDisabledChain,\n isEligible: !isDisabledChain && chainSupportsGasStation,\n };\n}\n\nexport async function getGasStationCostInSourceTokenRaw({\n firstStepData,\n messenger,\n request,\n totalGasEstimate,\n totalItemCount,\n}: GasStationCostParams): Promise<Amount | undefined> {\n const { data, to, value } = firstStepData;\n const { from, sourceChainId, sourceTokenAddress } = request;\n\n let gasFeeTokens: GasFeeToken[];\n\n try {\n gasFeeTokens = await messenger.call(\n 'TransactionController:getGasFeeTokens',\n {\n chainId: sourceChainId,\n data,\n from,\n to,\n value: toHex(value ?? '0'),\n },\n );\n } catch (error) {\n log('Failed to estimate gas fee tokens', {\n error,\n sourceChainId,\n });\n return undefined;\n }\n\n const gasFeeToken = gasFeeTokens.find(\n (singleGasFeeToken) =>\n singleGasFeeToken.tokenAddress.toLowerCase() ===\n sourceTokenAddress.toLowerCase(),\n );\n\n if (!gasFeeToken) {\n log('No matching source token in gas fee token estimate', {\n sourceTokenAddress,\n sourceChainId,\n });\n return undefined;\n }\n\n const gasFeeTokenWithNormalizedAmount = {\n ...gasFeeToken,\n amount: toHex(\n getNormalizedGasFeeTokenAmount({\n gasFeeToken,\n totalGasEstimate,\n totalItemCount,\n }),\n ),\n };\n\n const gasFeeTokenCost = calculateGasFeeTokenCost({\n chainId: sourceChainId,\n gasFeeToken: gasFeeTokenWithNormalizedAmount,\n messenger,\n });\n\n if (!gasFeeTokenCost) {\n log('Unable to calculate gas fee token cost using fiat rates', {\n sourceTokenAddress,\n sourceChainId,\n });\n return undefined;\n }\n\n log('Estimated gas station cost for source token', {\n amount: gasFeeTokenCost.raw,\n sourceTokenAddress,\n sourceChainId,\n });\n\n return gasFeeTokenCost;\n}\n\nfunction getNormalizedGasFeeTokenAmount({\n gasFeeToken,\n totalGasEstimate,\n totalItemCount,\n}: {\n gasFeeToken: GasFeeToken;\n totalGasEstimate: number;\n totalItemCount: number;\n}): string {\n let amount = new BigNumber(gasFeeToken.amount);\n\n if (totalItemCount > 1) {\n const gas = new BigNumber(gasFeeToken.gas);\n const gasFeeAmount = new BigNumber(gasFeeToken.amount);\n\n if (totalGasEstimate > 0 && gas.isGreaterThan(0)) {\n const gasRate = gasFeeAmount.dividedBy(gas);\n amount = gasRate.multipliedBy(totalGasEstimate);\n }\n }\n\n return amount.integerValue(BigNumber.ROUND_CEIL).toFixed(0);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gas-station.d.cts","sourceRoot":"","sources":["../../../src/strategy/relay/gas-station.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAK3C,OAAO,KAAK,EACV,MAAM,EACN,YAAY,EACZ,iCAAiC,EAClC,wBAAoB;
|
|
1
|
+
{"version":3,"file":"gas-station.d.cts","sourceRoot":"","sources":["../../../src/strategy/relay/gas-station.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAK3C,OAAO,KAAK,EACV,MAAM,EACN,YAAY,EACZ,iCAAiC,EAClC,wBAAoB;AAMrB,KAAK,oBAAoB,GAAG;IAC1B,aAAa,EAAE;QACb,IAAI,EAAE,GAAG,CAAC;QACV,EAAE,EAAE,GAAG,CAAC;QACR,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,SAAS,EAAE,iCAAiC,CAAC;IAC7C,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,eAAe,GAAG,oBAAoB,CAAC,CAAC;IAC7E,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,uBAAuB,EAAE,OAAO,CAAC;IACjC,eAAe,EAAE,OAAO,CAAC;IACzB,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,iCAAiC,EAC5C,aAAa,EAAE,YAAY,CAAC,eAAe,CAAC,GAC3C,qBAAqB,CAWvB;AAED,wBAAsB,iCAAiC,CAAC,EACtD,aAAa,EACb,SAAS,EACT,OAAO,EACP,gBAAgB,EAChB,cAAc,GACf,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAuEpD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gas-station.d.mts","sourceRoot":"","sources":["../../../src/strategy/relay/gas-station.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAK3C,OAAO,KAAK,EACV,MAAM,EACN,YAAY,EACZ,iCAAiC,EAClC,wBAAoB;
|
|
1
|
+
{"version":3,"file":"gas-station.d.mts","sourceRoot":"","sources":["../../../src/strategy/relay/gas-station.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAK3C,OAAO,KAAK,EACV,MAAM,EACN,YAAY,EACZ,iCAAiC,EAClC,wBAAoB;AAMrB,KAAK,oBAAoB,GAAG;IAC1B,aAAa,EAAE;QACb,IAAI,EAAE,GAAG,CAAC;QACV,EAAE,EAAE,GAAG,CAAC;QACR,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,SAAS,EAAE,iCAAiC,CAAC;IAC7C,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,eAAe,GAAG,oBAAoB,CAAC,CAAC;IAC7E,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,uBAAuB,EAAE,OAAO,CAAC;IACjC,eAAe,EAAE,OAAO,CAAC;IACzB,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,iCAAiC,EAC5C,aAAa,EAAE,YAAY,CAAC,eAAe,CAAC,GAC3C,qBAAqB,CAWvB;AAED,wBAAsB,iCAAiC,CAAC,EACtD,aAAa,EACb,SAAS,EACT,OAAO,EACP,gBAAgB,EAChB,cAAc,GACf,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAuEpD"}
|
|
@@ -2,13 +2,12 @@ import { toHex } from "@metamask/controller-utils";
|
|
|
2
2
|
import { createModuleLogger } from "@metamask/utils";
|
|
3
3
|
import { BigNumber } from "bignumber.js";
|
|
4
4
|
import { projectLogger } from "../../logger.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { getFeatureFlags, isEIP7702Chain } from "../../utils/feature-flags.mjs";
|
|
6
6
|
import { calculateGasFeeTokenCost } from "../../utils/gas.mjs";
|
|
7
7
|
const log = createModuleLogger(projectLogger, 'relay-gas-station');
|
|
8
8
|
export function getGasStationEligibility(messenger, sourceChainId) {
|
|
9
9
|
const { relayDisabledGasStationChains } = getFeatureFlags(messenger);
|
|
10
|
-
const
|
|
11
|
-
const chainSupportsGasStation = supportedChains.some((supportedChainId) => supportedChainId.toLowerCase() === sourceChainId.toLowerCase());
|
|
10
|
+
const chainSupportsGasStation = isEIP7702Chain(messenger, sourceChainId);
|
|
12
11
|
const isDisabledChain = relayDisabledGasStationChains.includes(sourceChainId);
|
|
13
12
|
return {
|
|
14
13
|
chainSupportsGasStation,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gas-station.mjs","sourceRoot":"","sources":["../../../src/strategy/relay/gas-station.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,mCAAmC;AAGnD,OAAO,EAAE,kBAAkB,EAAE,wBAAwB;AACrD,OAAO,EAAE,SAAS,EAAE,qBAAqB;AAEzC,OAAO,EAAE,aAAa,EAAE,yBAAqB;AAM7C,OAAO,
|
|
1
|
+
{"version":3,"file":"gas-station.mjs","sourceRoot":"","sources":["../../../src/strategy/relay/gas-station.ts"],"names":[],"mappings":"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","sourcesContent":["import { toHex } from '@metamask/controller-utils';\nimport type { GasFeeToken } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { projectLogger } from '../../logger';\nimport type {\n Amount,\n QuoteRequest,\n TransactionPayControllerMessenger,\n} from '../../types';\nimport { getFeatureFlags, isEIP7702Chain } from '../../utils/feature-flags';\nimport { calculateGasFeeTokenCost } from '../../utils/gas';\n\nconst log = createModuleLogger(projectLogger, 'relay-gas-station');\n\ntype GasStationCostParams = {\n firstStepData: {\n data: Hex;\n to: Hex;\n value?: string;\n };\n messenger: TransactionPayControllerMessenger;\n request: Pick<QuoteRequest, 'from' | 'sourceChainId' | 'sourceTokenAddress'>;\n totalGasEstimate: number;\n totalItemCount: number;\n};\n\nexport type GasStationEligibility = {\n chainSupportsGasStation: boolean;\n isDisabledChain: boolean;\n isEligible: boolean;\n};\n\nexport function getGasStationEligibility(\n messenger: TransactionPayControllerMessenger,\n sourceChainId: QuoteRequest['sourceChainId'],\n): GasStationEligibility {\n const { relayDisabledGasStationChains } = getFeatureFlags(messenger);\n const chainSupportsGasStation = isEIP7702Chain(messenger, sourceChainId);\n\n const isDisabledChain = relayDisabledGasStationChains.includes(sourceChainId);\n\n return {\n chainSupportsGasStation,\n isDisabledChain,\n isEligible: !isDisabledChain && chainSupportsGasStation,\n };\n}\n\nexport async function getGasStationCostInSourceTokenRaw({\n firstStepData,\n messenger,\n request,\n totalGasEstimate,\n totalItemCount,\n}: GasStationCostParams): Promise<Amount | undefined> {\n const { data, to, value } = firstStepData;\n const { from, sourceChainId, sourceTokenAddress } = request;\n\n let gasFeeTokens: GasFeeToken[];\n\n try {\n gasFeeTokens = await messenger.call(\n 'TransactionController:getGasFeeTokens',\n {\n chainId: sourceChainId,\n data,\n from,\n to,\n value: toHex(value ?? '0'),\n },\n );\n } catch (error) {\n log('Failed to estimate gas fee tokens', {\n error,\n sourceChainId,\n });\n return undefined;\n }\n\n const gasFeeToken = gasFeeTokens.find(\n (singleGasFeeToken) =>\n singleGasFeeToken.tokenAddress.toLowerCase() ===\n sourceTokenAddress.toLowerCase(),\n );\n\n if (!gasFeeToken) {\n log('No matching source token in gas fee token estimate', {\n sourceTokenAddress,\n sourceChainId,\n });\n return undefined;\n }\n\n const gasFeeTokenWithNormalizedAmount = {\n ...gasFeeToken,\n amount: toHex(\n getNormalizedGasFeeTokenAmount({\n gasFeeToken,\n totalGasEstimate,\n totalItemCount,\n }),\n ),\n };\n\n const gasFeeTokenCost = calculateGasFeeTokenCost({\n chainId: sourceChainId,\n gasFeeToken: gasFeeTokenWithNormalizedAmount,\n messenger,\n });\n\n if (!gasFeeTokenCost) {\n log('Unable to calculate gas fee token cost using fiat rates', {\n sourceTokenAddress,\n sourceChainId,\n });\n return undefined;\n }\n\n log('Estimated gas station cost for source token', {\n amount: gasFeeTokenCost.raw,\n sourceTokenAddress,\n sourceChainId,\n });\n\n return gasFeeTokenCost;\n}\n\nfunction getNormalizedGasFeeTokenAmount({\n gasFeeToken,\n totalGasEstimate,\n totalItemCount,\n}: {\n gasFeeToken: GasFeeToken;\n totalGasEstimate: number;\n totalItemCount: number;\n}): string {\n let amount = new BigNumber(gasFeeToken.amount);\n\n if (totalItemCount > 1) {\n const gas = new BigNumber(gasFeeToken.gas);\n const gasFeeAmount = new BigNumber(gasFeeToken.amount);\n\n if (totalGasEstimate > 0 && gas.isGreaterThan(0)) {\n const gasRate = gasFeeAmount.dividedBy(gas);\n amount = gasRate.multipliedBy(totalGasEstimate);\n }\n }\n\n return amount.integerValue(BigNumber.ROUND_CEIL).toFixed(0);\n}\n"]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getRelayStatus = exports.submitRelayExecute = exports.fetchRelayQuote = void 0;
|
|
4
|
+
const controller_utils_1 = require("@metamask/controller-utils");
|
|
5
|
+
const constants_1 = require("./constants.cjs");
|
|
6
|
+
const feature_flags_1 = require("../../utils/feature-flags.cjs");
|
|
7
|
+
/**
|
|
8
|
+
* Fetch a quote from the Relay API.
|
|
9
|
+
*
|
|
10
|
+
* @param messenger - Controller messenger.
|
|
11
|
+
* @param body - Quote request parameters.
|
|
12
|
+
* @returns The Relay quote with the request attached.
|
|
13
|
+
*/
|
|
14
|
+
async function fetchRelayQuote(messenger, body) {
|
|
15
|
+
const { relayQuoteUrl } = (0, feature_flags_1.getFeatureFlags)(messenger);
|
|
16
|
+
const response = await (0, controller_utils_1.successfulFetch)(relayQuoteUrl, {
|
|
17
|
+
method: 'POST',
|
|
18
|
+
headers: { 'Content-Type': 'application/json' },
|
|
19
|
+
body: JSON.stringify(body),
|
|
20
|
+
});
|
|
21
|
+
const quote = (await response.json());
|
|
22
|
+
quote.request = body;
|
|
23
|
+
return quote;
|
|
24
|
+
}
|
|
25
|
+
exports.fetchRelayQuote = fetchRelayQuote;
|
|
26
|
+
/**
|
|
27
|
+
* Submit a gasless transaction via the Relay /execute endpoint.
|
|
28
|
+
*
|
|
29
|
+
* @param messenger - Controller messenger.
|
|
30
|
+
* @param body - Execute request parameters.
|
|
31
|
+
* @returns The execute response containing the request ID.
|
|
32
|
+
*/
|
|
33
|
+
async function submitRelayExecute(messenger, body) {
|
|
34
|
+
const { relayExecuteUrl } = (0, feature_flags_1.getFeatureFlags)(messenger);
|
|
35
|
+
const response = await (0, controller_utils_1.successfulFetch)(relayExecuteUrl, {
|
|
36
|
+
method: 'POST',
|
|
37
|
+
headers: { 'Content-Type': 'application/json' },
|
|
38
|
+
body: JSON.stringify(body),
|
|
39
|
+
});
|
|
40
|
+
return (await response.json());
|
|
41
|
+
}
|
|
42
|
+
exports.submitRelayExecute = submitRelayExecute;
|
|
43
|
+
/**
|
|
44
|
+
* Poll the Relay status endpoint for a given request ID.
|
|
45
|
+
*
|
|
46
|
+
* @param requestId - The Relay request ID to check.
|
|
47
|
+
* @returns The current status of the request.
|
|
48
|
+
*/
|
|
49
|
+
async function getRelayStatus(requestId) {
|
|
50
|
+
const url = `${constants_1.RELAY_STATUS_URL}?requestId=${requestId}`;
|
|
51
|
+
const response = await (0, controller_utils_1.successfulFetch)(url, { method: 'GET' });
|
|
52
|
+
return (await response.json());
|
|
53
|
+
}
|
|
54
|
+
exports.getRelayStatus = getRelayStatus;
|
|
55
|
+
//# sourceMappingURL=relay-api.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relay-api.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-api.ts"],"names":[],"mappings":";;;AAAA,iEAA6D;AAE7D,+CAA+C;AAS/C,iEAA4D;AAE5D;;;;;;GAMG;AACI,KAAK,UAAU,eAAe,CACnC,SAA4C,EAC5C,IAAuB;IAEvB,MAAM,EAAE,aAAa,EAAE,GAAG,IAAA,+BAAe,EAAC,SAAS,CAAC,CAAC;IAErD,MAAM,QAAQ,GAAG,MAAM,IAAA,kCAAe,EAAC,aAAa,EAAE;QACpD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAe,CAAC;IACpD,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;IAErB,OAAO,KAAK,CAAC;AACf,CAAC;AAhBD,0CAgBC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,kBAAkB,CACtC,SAA4C,EAC5C,IAAyB;IAEzB,MAAM,EAAE,eAAe,EAAE,GAAG,IAAA,+BAAe,EAAC,SAAS,CAAC,CAAC;IAEvD,MAAM,QAAQ,GAAG,MAAM,IAAA,kCAAe,EAAC,eAAe,EAAE;QACtD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IAEH,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAyB,CAAC;AACzD,CAAC;AAbD,gDAaC;AAED;;;;;GAKG;AACI,KAAK,UAAU,cAAc,CAClC,SAAiB;IAEjB,MAAM,GAAG,GAAG,GAAG,4BAAgB,cAAc,SAAS,EAAE,CAAC;IAEzD,MAAM,QAAQ,GAAG,MAAM,IAAA,kCAAe,EAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAE/D,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAwB,CAAC;AACxD,CAAC;AARD,wCAQC","sourcesContent":["import { successfulFetch } from '@metamask/controller-utils';\n\nimport { RELAY_STATUS_URL } from './constants';\nimport type {\n RelayExecuteRequest,\n RelayExecuteResponse,\n RelayQuote,\n RelayQuoteRequest,\n RelayStatusResponse,\n} from './types';\nimport type { TransactionPayControllerMessenger } from '../../types';\nimport { getFeatureFlags } from '../../utils/feature-flags';\n\n/**\n * Fetch a quote from the Relay API.\n *\n * @param messenger - Controller messenger.\n * @param body - Quote request parameters.\n * @returns The Relay quote with the request attached.\n */\nexport async function fetchRelayQuote(\n messenger: TransactionPayControllerMessenger,\n body: RelayQuoteRequest,\n): Promise<RelayQuote> {\n const { relayQuoteUrl } = getFeatureFlags(messenger);\n\n const response = await successfulFetch(relayQuoteUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n const quote = (await response.json()) as RelayQuote;\n quote.request = body;\n\n return quote;\n}\n\n/**\n * Submit a gasless transaction via the Relay /execute endpoint.\n *\n * @param messenger - Controller messenger.\n * @param body - Execute request parameters.\n * @returns The execute response containing the request ID.\n */\nexport async function submitRelayExecute(\n messenger: TransactionPayControllerMessenger,\n body: RelayExecuteRequest,\n): Promise<RelayExecuteResponse> {\n const { relayExecuteUrl } = getFeatureFlags(messenger);\n\n const response = await successfulFetch(relayExecuteUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n return (await response.json()) as RelayExecuteResponse;\n}\n\n/**\n * Poll the Relay status endpoint for a given request ID.\n *\n * @param requestId - The Relay request ID to check.\n * @returns The current status of the request.\n */\nexport async function getRelayStatus(\n requestId: string,\n): Promise<RelayStatusResponse> {\n const url = `${RELAY_STATUS_URL}?requestId=${requestId}`;\n\n const response = await successfulFetch(url, { method: 'GET' });\n\n return (await response.json()) as RelayStatusResponse;\n}\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { RelayExecuteRequest, RelayExecuteResponse, RelayQuote, RelayQuoteRequest, RelayStatusResponse } from "./types.cjs";
|
|
2
|
+
import type { TransactionPayControllerMessenger } from "../../types.cjs";
|
|
3
|
+
/**
|
|
4
|
+
* Fetch a quote from the Relay API.
|
|
5
|
+
*
|
|
6
|
+
* @param messenger - Controller messenger.
|
|
7
|
+
* @param body - Quote request parameters.
|
|
8
|
+
* @returns The Relay quote with the request attached.
|
|
9
|
+
*/
|
|
10
|
+
export declare function fetchRelayQuote(messenger: TransactionPayControllerMessenger, body: RelayQuoteRequest): Promise<RelayQuote>;
|
|
11
|
+
/**
|
|
12
|
+
* Submit a gasless transaction via the Relay /execute endpoint.
|
|
13
|
+
*
|
|
14
|
+
* @param messenger - Controller messenger.
|
|
15
|
+
* @param body - Execute request parameters.
|
|
16
|
+
* @returns The execute response containing the request ID.
|
|
17
|
+
*/
|
|
18
|
+
export declare function submitRelayExecute(messenger: TransactionPayControllerMessenger, body: RelayExecuteRequest): Promise<RelayExecuteResponse>;
|
|
19
|
+
/**
|
|
20
|
+
* Poll the Relay status endpoint for a given request ID.
|
|
21
|
+
*
|
|
22
|
+
* @param requestId - The Relay request ID to check.
|
|
23
|
+
* @returns The current status of the request.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getRelayStatus(requestId: string): Promise<RelayStatusResponse>;
|
|
26
|
+
//# sourceMappingURL=relay-api.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relay-api.d.cts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-api.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACpB,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACpB,oBAAgB;AACjB,OAAO,KAAK,EAAE,iCAAiC,EAAE,wBAAoB;AAGrE;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,iCAAiC,EAC5C,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,UAAU,CAAC,CAarB;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,iCAAiC,EAC5C,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,oBAAoB,CAAC,CAU/B;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,mBAAmB,CAAC,CAM9B"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { RelayExecuteRequest, RelayExecuteResponse, RelayQuote, RelayQuoteRequest, RelayStatusResponse } from "./types.mjs";
|
|
2
|
+
import type { TransactionPayControllerMessenger } from "../../types.mjs";
|
|
3
|
+
/**
|
|
4
|
+
* Fetch a quote from the Relay API.
|
|
5
|
+
*
|
|
6
|
+
* @param messenger - Controller messenger.
|
|
7
|
+
* @param body - Quote request parameters.
|
|
8
|
+
* @returns The Relay quote with the request attached.
|
|
9
|
+
*/
|
|
10
|
+
export declare function fetchRelayQuote(messenger: TransactionPayControllerMessenger, body: RelayQuoteRequest): Promise<RelayQuote>;
|
|
11
|
+
/**
|
|
12
|
+
* Submit a gasless transaction via the Relay /execute endpoint.
|
|
13
|
+
*
|
|
14
|
+
* @param messenger - Controller messenger.
|
|
15
|
+
* @param body - Execute request parameters.
|
|
16
|
+
* @returns The execute response containing the request ID.
|
|
17
|
+
*/
|
|
18
|
+
export declare function submitRelayExecute(messenger: TransactionPayControllerMessenger, body: RelayExecuteRequest): Promise<RelayExecuteResponse>;
|
|
19
|
+
/**
|
|
20
|
+
* Poll the Relay status endpoint for a given request ID.
|
|
21
|
+
*
|
|
22
|
+
* @param requestId - The Relay request ID to check.
|
|
23
|
+
* @returns The current status of the request.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getRelayStatus(requestId: string): Promise<RelayStatusResponse>;
|
|
26
|
+
//# sourceMappingURL=relay-api.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relay-api.d.mts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-api.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACpB,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACpB,oBAAgB;AACjB,OAAO,KAAK,EAAE,iCAAiC,EAAE,wBAAoB;AAGrE;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,iCAAiC,EAC5C,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,UAAU,CAAC,CAarB;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,iCAAiC,EAC5C,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,oBAAoB,CAAC,CAU/B;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,mBAAmB,CAAC,CAM9B"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { successfulFetch } from "@metamask/controller-utils";
|
|
2
|
+
import { RELAY_STATUS_URL } from "./constants.mjs";
|
|
3
|
+
import { getFeatureFlags } from "../../utils/feature-flags.mjs";
|
|
4
|
+
/**
|
|
5
|
+
* Fetch a quote from the Relay API.
|
|
6
|
+
*
|
|
7
|
+
* @param messenger - Controller messenger.
|
|
8
|
+
* @param body - Quote request parameters.
|
|
9
|
+
* @returns The Relay quote with the request attached.
|
|
10
|
+
*/
|
|
11
|
+
export async function fetchRelayQuote(messenger, body) {
|
|
12
|
+
const { relayQuoteUrl } = getFeatureFlags(messenger);
|
|
13
|
+
const response = await successfulFetch(relayQuoteUrl, {
|
|
14
|
+
method: 'POST',
|
|
15
|
+
headers: { 'Content-Type': 'application/json' },
|
|
16
|
+
body: JSON.stringify(body),
|
|
17
|
+
});
|
|
18
|
+
const quote = (await response.json());
|
|
19
|
+
quote.request = body;
|
|
20
|
+
return quote;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Submit a gasless transaction via the Relay /execute endpoint.
|
|
24
|
+
*
|
|
25
|
+
* @param messenger - Controller messenger.
|
|
26
|
+
* @param body - Execute request parameters.
|
|
27
|
+
* @returns The execute response containing the request ID.
|
|
28
|
+
*/
|
|
29
|
+
export async function submitRelayExecute(messenger, body) {
|
|
30
|
+
const { relayExecuteUrl } = getFeatureFlags(messenger);
|
|
31
|
+
const response = await successfulFetch(relayExecuteUrl, {
|
|
32
|
+
method: 'POST',
|
|
33
|
+
headers: { 'Content-Type': 'application/json' },
|
|
34
|
+
body: JSON.stringify(body),
|
|
35
|
+
});
|
|
36
|
+
return (await response.json());
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Poll the Relay status endpoint for a given request ID.
|
|
40
|
+
*
|
|
41
|
+
* @param requestId - The Relay request ID to check.
|
|
42
|
+
* @returns The current status of the request.
|
|
43
|
+
*/
|
|
44
|
+
export async function getRelayStatus(requestId) {
|
|
45
|
+
const url = `${RELAY_STATUS_URL}?requestId=${requestId}`;
|
|
46
|
+
const response = await successfulFetch(url, { method: 'GET' });
|
|
47
|
+
return (await response.json());
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=relay-api.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relay-api.mjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,mCAAmC;AAE7D,OAAO,EAAE,gBAAgB,EAAE,wBAAoB;AAS/C,OAAO,EAAE,eAAe,EAAE,sCAAkC;AAE5D;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,SAA4C,EAC5C,IAAuB;IAEvB,MAAM,EAAE,aAAa,EAAE,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAErD,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,aAAa,EAAE;QACpD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAe,CAAC;IACpD,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;IAErB,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,SAA4C,EAC5C,IAAyB;IAEzB,MAAM,EAAE,eAAe,EAAE,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAEvD,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,eAAe,EAAE;QACtD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IAEH,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAyB,CAAC;AACzD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,SAAiB;IAEjB,MAAM,GAAG,GAAG,GAAG,gBAAgB,cAAc,SAAS,EAAE,CAAC;IAEzD,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAE/D,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAwB,CAAC;AACxD,CAAC","sourcesContent":["import { successfulFetch } from '@metamask/controller-utils';\n\nimport { RELAY_STATUS_URL } from './constants';\nimport type {\n RelayExecuteRequest,\n RelayExecuteResponse,\n RelayQuote,\n RelayQuoteRequest,\n RelayStatusResponse,\n} from './types';\nimport type { TransactionPayControllerMessenger } from '../../types';\nimport { getFeatureFlags } from '../../utils/feature-flags';\n\n/**\n * Fetch a quote from the Relay API.\n *\n * @param messenger - Controller messenger.\n * @param body - Quote request parameters.\n * @returns The Relay quote with the request attached.\n */\nexport async function fetchRelayQuote(\n messenger: TransactionPayControllerMessenger,\n body: RelayQuoteRequest,\n): Promise<RelayQuote> {\n const { relayQuoteUrl } = getFeatureFlags(messenger);\n\n const response = await successfulFetch(relayQuoteUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n const quote = (await response.json()) as RelayQuote;\n quote.request = body;\n\n return quote;\n}\n\n/**\n * Submit a gasless transaction via the Relay /execute endpoint.\n *\n * @param messenger - Controller messenger.\n * @param body - Execute request parameters.\n * @returns The execute response containing the request ID.\n */\nexport async function submitRelayExecute(\n messenger: TransactionPayControllerMessenger,\n body: RelayExecuteRequest,\n): Promise<RelayExecuteResponse> {\n const { relayExecuteUrl } = getFeatureFlags(messenger);\n\n const response = await successfulFetch(relayExecuteUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n return (await response.json()) as RelayExecuteResponse;\n}\n\n/**\n * Poll the Relay status endpoint for a given request ID.\n *\n * @param requestId - The Relay request ID to check.\n * @returns The current status of the request.\n */\nexport async function getRelayStatus(\n requestId: string,\n): Promise<RelayStatusResponse> {\n const url = `${RELAY_STATUS_URL}?requestId=${requestId}`;\n\n const response = await successfulFetch(url, { method: 'GET' });\n\n return (await response.json()) as RelayStatusResponse;\n}\n"]}
|
|
@@ -8,6 +8,7 @@ const utils_1 = require("@metamask/utils");
|
|
|
8
8
|
const bignumber_js_1 = require("bignumber.js");
|
|
9
9
|
const constants_1 = require("./constants.cjs");
|
|
10
10
|
const gas_station_1 = require("./gas-station.cjs");
|
|
11
|
+
const relay_api_1 = require("./relay-api.cjs");
|
|
11
12
|
const relay_max_gas_station_1 = require("./relay-max-gas-station.cjs");
|
|
12
13
|
const __1 = require("../../index.cjs");
|
|
13
14
|
const constants_2 = require("../../constants.cjs");
|
|
@@ -16,6 +17,7 @@ const amounts_1 = require("../../utils/amounts.cjs");
|
|
|
16
17
|
const feature_flags_1 = require("../../utils/feature-flags.cjs");
|
|
17
18
|
const gas_1 = require("../../utils/gas.cjs");
|
|
18
19
|
const token_1 = require("../../utils/token.cjs");
|
|
20
|
+
const transaction_1 = require("../../utils/transaction.cjs");
|
|
19
21
|
const log = (0, utils_1.createModuleLogger)(logger_1.projectLogger, 'relay-strategy');
|
|
20
22
|
/**
|
|
21
23
|
* Fetches Relay quotes.
|
|
@@ -45,10 +47,56 @@ exports.getRelayQuotes = getRelayQuotes;
|
|
|
45
47
|
async function getQuoteWithMaxAmountHandling(request, fullRequest) {
|
|
46
48
|
const { isMaxAmount } = request;
|
|
47
49
|
if (!isMaxAmount) {
|
|
48
|
-
return
|
|
50
|
+
return getQuoteWithPostQuoteGasHandling(request, fullRequest);
|
|
49
51
|
}
|
|
50
52
|
return (0, relay_max_gas_station_1.getRelayMaxGasStationQuote)(request, fullRequest, getSingleQuote);
|
|
51
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* For post-quote flows, fetch an initial quote to compute gas cost in source
|
|
56
|
+
* token, then re-quote with the source amount reduced by the gas cost.
|
|
57
|
+
* This ensures Relay reserves enough for the gas fee token payment.
|
|
58
|
+
*
|
|
59
|
+
* For non-post-quote flows, just returns a single quote.
|
|
60
|
+
*
|
|
61
|
+
* @param request - Quote request.
|
|
62
|
+
* @param fullRequest - Full request context.
|
|
63
|
+
* @returns The final quote (phase 2 for post-quote, or phase 1 for normal).
|
|
64
|
+
*/
|
|
65
|
+
async function getQuoteWithPostQuoteGasHandling(request, fullRequest) {
|
|
66
|
+
const phase1Quote = await getSingleQuote(request, fullRequest);
|
|
67
|
+
if (!request.isPostQuote || !phase1Quote.fees.isSourceGasFeeToken) {
|
|
68
|
+
return phase1Quote;
|
|
69
|
+
}
|
|
70
|
+
const gasCostRaw = phase1Quote.fees.sourceNetwork.max.raw;
|
|
71
|
+
const adjustedSourceAmount = new bignumber_js_1.BigNumber(request.sourceTokenAmount)
|
|
72
|
+
.minus(gasCostRaw)
|
|
73
|
+
.integerValue(bignumber_js_1.BigNumber.ROUND_DOWN);
|
|
74
|
+
log('Subtracting gas from source for post-quote two-call', {
|
|
75
|
+
originalSourceAmount: request.sourceTokenAmount,
|
|
76
|
+
gasCostRaw,
|
|
77
|
+
adjustedSourceAmount: adjustedSourceAmount.toString(10),
|
|
78
|
+
});
|
|
79
|
+
if (!adjustedSourceAmount.isGreaterThan(0)) {
|
|
80
|
+
log('Insufficient balance after gas subtraction for post-quote, using phase 1');
|
|
81
|
+
return phase1Quote;
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
const phase2Quote = await getSingleQuote({
|
|
85
|
+
...request,
|
|
86
|
+
sourceTokenAmount: adjustedSourceAmount.toFixed(0, bignumber_js_1.BigNumber.ROUND_DOWN),
|
|
87
|
+
}, fullRequest);
|
|
88
|
+
if (phase1Quote.fees.isSourceGasFeeToken &&
|
|
89
|
+
!phase2Quote.fees.isSourceGasFeeToken) {
|
|
90
|
+
log('Phase 2 lost gas fee token eligibility, falling back to phase 1');
|
|
91
|
+
return phase1Quote;
|
|
92
|
+
}
|
|
93
|
+
return phase2Quote;
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
log('Phase 2 quote failed, falling back to phase 1', { error });
|
|
97
|
+
return phase1Quote;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
52
100
|
/**
|
|
53
101
|
* Fetches a single Relay quote.
|
|
54
102
|
*
|
|
@@ -67,12 +115,17 @@ async function getSingleQuote(request, fullRequest) {
|
|
|
67
115
|
// For regular flows with a target amount, use EXPECTED_OUTPUT.
|
|
68
116
|
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
69
117
|
const useExactInput = isMaxAmount || request.isPostQuote;
|
|
118
|
+
const useExecute = (0, feature_flags_1.isRelayExecuteEnabled)(messenger) &&
|
|
119
|
+
(0, feature_flags_1.isEIP7702Chain)(messenger, sourceChainId);
|
|
70
120
|
const body = {
|
|
71
121
|
amount: useExactInput ? sourceTokenAmount : targetAmountMinimum,
|
|
72
122
|
destinationChainId: Number(targetChainId),
|
|
73
123
|
destinationCurrency: targetTokenAddress,
|
|
74
124
|
originChainId: Number(sourceChainId),
|
|
75
125
|
originCurrency: sourceTokenAddress,
|
|
126
|
+
...(useExecute
|
|
127
|
+
? { originGasOverhead: (0, feature_flags_1.getRelayOriginGasOverhead)(messenger) }
|
|
128
|
+
: {}),
|
|
76
129
|
recipient: from,
|
|
77
130
|
slippageTolerance,
|
|
78
131
|
tradeType: useExactInput ? 'EXACT_INPUT' : 'EXPECTED_OUTPUT',
|
|
@@ -89,15 +142,8 @@ async function getSingleQuote(request, fullRequest) {
|
|
|
89
142
|
// Safe proxy) rather than defaulting to the EOA.
|
|
90
143
|
body.refundTo = request.refundTo;
|
|
91
144
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const response = await (0, controller_utils_1.successfulFetch)(url, {
|
|
95
|
-
method: 'POST',
|
|
96
|
-
headers: { 'Content-Type': 'application/json' },
|
|
97
|
-
body: JSON.stringify(body),
|
|
98
|
-
});
|
|
99
|
-
const quote = (await response.json());
|
|
100
|
-
quote.request = body;
|
|
145
|
+
log('Request body', body);
|
|
146
|
+
const quote = await (0, relay_api_1.fetchRelayQuote)(messenger, body);
|
|
101
147
|
log('Fetched relay quote', quote);
|
|
102
148
|
return await normalizeQuote(quote, request, fullRequest);
|
|
103
149
|
}
|
|
@@ -239,6 +285,7 @@ async function normalizeQuote(quote, request, fullRequest) {
|
|
|
239
285
|
const targetAmountUsd = baseTargetAmountUsd.plus(additionalTargetAmountUsd);
|
|
240
286
|
const targetAmount = (0, amounts_1.getFiatValueFromUsd)(targetAmountUsd, usdToFiatRate);
|
|
241
287
|
const metamask = {
|
|
288
|
+
...quote.metamask,
|
|
242
289
|
gasLimits,
|
|
243
290
|
};
|
|
244
291
|
return {
|
|
@@ -305,6 +352,9 @@ function getFiatRates(messenger, request) {
|
|
|
305
352
|
* transaction's params so that gas estimation and gas-fee-token logic handle
|
|
306
353
|
* both transactions together.
|
|
307
354
|
*
|
|
355
|
+
* When the execute flow is active (indicated by `quote.metamask.isExecute`),
|
|
356
|
+
* network fees are zeroed because the relayer covers them.
|
|
357
|
+
*
|
|
308
358
|
* @param quote - Relay quote.
|
|
309
359
|
* @param messenger - Controller messenger.
|
|
310
360
|
* @param request - Quote request.
|
|
@@ -313,11 +363,21 @@ function getFiatRates(messenger, request) {
|
|
|
313
363
|
*/
|
|
314
364
|
async function calculateSourceNetworkCost(quote, messenger, request, transaction) {
|
|
315
365
|
const { from, sourceChainId, sourceTokenAddress } = request;
|
|
366
|
+
if (quote.metamask?.isExecute) {
|
|
367
|
+
log('Zeroing network fees for execute flow');
|
|
368
|
+
const zeroAmount = { fiat: '0', human: '0', raw: '0', usd: '0' };
|
|
369
|
+
return { estimate: zeroAmount, max: zeroAmount, gasLimits: [] };
|
|
370
|
+
}
|
|
316
371
|
const relayParams = quote.steps
|
|
317
372
|
.flatMap((step) => step.items)
|
|
318
373
|
.map((item) => item.data);
|
|
319
374
|
const { chainId, data, maxFeePerGas, maxPriorityFeePerGas, to, value } = relayParams[0];
|
|
320
|
-
const
|
|
375
|
+
const isPredictWithdraw = request.isPostQuote && (0, transaction_1.isPredictWithdrawTransaction)(transaction);
|
|
376
|
+
const fromOverride = isPredictWithdraw ? request.refundTo : undefined;
|
|
377
|
+
const relayOnlyGas = await calculateSourceNetworkGasLimit(relayParams, messenger, fromOverride);
|
|
378
|
+
const { totalGasEstimate, totalGasLimit, gasLimits } = request.isPostQuote
|
|
379
|
+
? combinePostQuoteGas(relayOnlyGas, transaction)
|
|
380
|
+
: relayOnlyGas;
|
|
321
381
|
log('Gas limit', {
|
|
322
382
|
totalGasEstimate,
|
|
323
383
|
totalGasLimit,
|
|
@@ -360,6 +420,40 @@ async function calculateSourceNetworkCost(quote, messenger, request, transaction
|
|
|
360
420
|
nativeBalance,
|
|
361
421
|
max: max.raw,
|
|
362
422
|
});
|
|
423
|
+
if (isPredictWithdraw && request.refundTo) {
|
|
424
|
+
log('Using proxy address for predict withdraw gas station simulation', {
|
|
425
|
+
proxyAddress: request.refundTo,
|
|
426
|
+
sourceTokenAddress,
|
|
427
|
+
totalGasEstimate,
|
|
428
|
+
});
|
|
429
|
+
const gasFeeTokenCost = await (0, gas_station_1.getGasStationCostInSourceTokenRaw)({
|
|
430
|
+
firstStepData: {
|
|
431
|
+
data,
|
|
432
|
+
to,
|
|
433
|
+
value,
|
|
434
|
+
},
|
|
435
|
+
messenger,
|
|
436
|
+
request: {
|
|
437
|
+
from: request.refundTo,
|
|
438
|
+
sourceChainId,
|
|
439
|
+
sourceTokenAddress,
|
|
440
|
+
},
|
|
441
|
+
totalGasEstimate,
|
|
442
|
+
totalItemCount: relayParams.length + 1,
|
|
443
|
+
});
|
|
444
|
+
if (gasFeeTokenCost) {
|
|
445
|
+
log('Using predict withdraw gas fee token for source network', {
|
|
446
|
+
gasFeeTokenCost,
|
|
447
|
+
});
|
|
448
|
+
return {
|
|
449
|
+
isGasFeeToken: true,
|
|
450
|
+
estimate: gasFeeTokenCost,
|
|
451
|
+
max: gasFeeTokenCost,
|
|
452
|
+
gasLimits,
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
return result;
|
|
456
|
+
}
|
|
363
457
|
const gasFeeTokenCost = await (0, gas_station_1.getGasStationCostInSourceTokenRaw)({
|
|
364
458
|
firstStepData: {
|
|
365
459
|
data,
|
|
@@ -391,24 +485,17 @@ async function calculateSourceNetworkCost(quote, messenger, request, transaction
|
|
|
391
485
|
/**
|
|
392
486
|
* Calculate the total gas limit for the source network.
|
|
393
487
|
*
|
|
394
|
-
* For post-quote flows (e.g. predict withdrawals), the original transaction's
|
|
395
|
-
* gas is combined with the relay gas so that source network cost accounts for
|
|
396
|
-
* both the user's transaction and the relay transactions.
|
|
397
|
-
*
|
|
398
488
|
* @param params - Array of relay transaction parameters.
|
|
399
489
|
* @param messenger - Controller messenger.
|
|
400
|
-
* @param
|
|
401
|
-
*
|
|
490
|
+
* @param fromOverride - Optional address to use as `from` in gas estimation
|
|
491
|
+
* instead of the address in the relay params. Used in predict withdraw flows
|
|
492
|
+
* to estimate with the proxy/Safe address that holds the source token balance.
|
|
402
493
|
* @returns Total gas estimates and per-transaction gas limits.
|
|
403
494
|
*/
|
|
404
|
-
async function calculateSourceNetworkGasLimit(params, messenger,
|
|
405
|
-
|
|
406
|
-
?
|
|
407
|
-
:
|
|
408
|
-
if (!postQuoteTransaction?.txParams.to) {
|
|
409
|
-
return relayGas;
|
|
410
|
-
}
|
|
411
|
-
return combinePostQuoteGas(relayGas, postQuoteTransaction);
|
|
495
|
+
async function calculateSourceNetworkGasLimit(params, messenger, fromOverride) {
|
|
496
|
+
return params.length === 1
|
|
497
|
+
? calculateSourceNetworkGasLimitSingle(params[0], messenger, fromOverride)
|
|
498
|
+
: calculateSourceNetworkGasLimitBatch(params, messenger, fromOverride);
|
|
412
499
|
}
|
|
413
500
|
/**
|
|
414
501
|
* Combine the original transaction's gas with relay gas for post-quote flows.
|
|
@@ -486,11 +573,11 @@ function getTransferRecipient(data) {
|
|
|
486
573
|
.decodeFunctionData('transfer', data)
|
|
487
574
|
.to.toLowerCase();
|
|
488
575
|
}
|
|
489
|
-
async function calculateSourceNetworkGasLimitSingle(params, messenger) {
|
|
576
|
+
async function calculateSourceNetworkGasLimitSingle(params, messenger, fromOverride) {
|
|
490
577
|
const paramGasLimit = params.gas
|
|
491
578
|
? new bignumber_js_1.BigNumber(params.gas).toNumber()
|
|
492
579
|
: undefined;
|
|
493
|
-
if (paramGasLimit) {
|
|
580
|
+
if (paramGasLimit && !fromOverride) {
|
|
494
581
|
log('Using single gas limit from params', { paramGasLimit });
|
|
495
582
|
return {
|
|
496
583
|
totalGasEstimate: paramGasLimit,
|
|
@@ -499,7 +586,8 @@ async function calculateSourceNetworkGasLimitSingle(params, messenger) {
|
|
|
499
586
|
};
|
|
500
587
|
}
|
|
501
588
|
try {
|
|
502
|
-
const { chainId: chainIdNumber, data, from, to, value: valueString, } = params;
|
|
589
|
+
const { chainId: chainIdNumber, data, from: paramsFrom, to, value: valueString, } = params;
|
|
590
|
+
const from = fromOverride ?? paramsFrom;
|
|
503
591
|
const chainId = (0, controller_utils_1.toHex)(chainIdNumber);
|
|
504
592
|
const value = (0, controller_utils_1.toHex)(valueString ?? '0');
|
|
505
593
|
const gasBuffer = (0, feature_flags_1.getGasBuffer)(messenger, chainId);
|
|
@@ -537,16 +625,20 @@ async function calculateSourceNetworkGasLimitSingle(params, messenger) {
|
|
|
537
625
|
*
|
|
538
626
|
* @param params - Array of transaction parameters.
|
|
539
627
|
* @param messenger - Controller messenger.
|
|
628
|
+
* @param fromOverride - Optional address to use as `from` in gas estimation.
|
|
540
629
|
* @returns - Gas limits.
|
|
541
630
|
*/
|
|
542
|
-
async function calculateSourceNetworkGasLimitBatch(params, messenger) {
|
|
631
|
+
async function calculateSourceNetworkGasLimitBatch(params, messenger, fromOverride) {
|
|
543
632
|
try {
|
|
544
|
-
const { chainId: chainIdNumber, from } = params[0];
|
|
633
|
+
const { chainId: chainIdNumber, from: paramsFrom } = params[0];
|
|
634
|
+
const from = fromOverride ?? paramsFrom;
|
|
545
635
|
const chainId = (0, controller_utils_1.toHex)(chainIdNumber);
|
|
546
636
|
const gasBuffer = (0, feature_flags_1.getGasBuffer)(messenger, chainId);
|
|
547
637
|
const transactions = params.map((singleParams) => ({
|
|
548
638
|
...singleParams,
|
|
549
|
-
gas:
|
|
639
|
+
gas: !fromOverride && singleParams.gas
|
|
640
|
+
? (0, controller_utils_1.toHex)(singleParams.gas)
|
|
641
|
+
: undefined,
|
|
550
642
|
maxFeePerGas: undefined,
|
|
551
643
|
maxPriorityFeePerGas: undefined,
|
|
552
644
|
value: (0, controller_utils_1.toHex)(singleParams.value ?? '0'),
|