@metamask/transaction-pay-controller 22.6.3 → 22.8.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 +27 -1
- package/dist/TransactionPayController-method-action-types.cjs.map +1 -1
- package/dist/TransactionPayController-method-action-types.d.cts +15 -1
- package/dist/TransactionPayController-method-action-types.d.cts.map +1 -1
- package/dist/TransactionPayController-method-action-types.d.mts +15 -1
- package/dist/TransactionPayController-method-action-types.d.mts.map +1 -1
- package/dist/TransactionPayController-method-action-types.mjs.map +1 -1
- package/dist/TransactionPayController.cjs +21 -3
- package/dist/TransactionPayController.cjs.map +1 -1
- package/dist/TransactionPayController.d.cts +13 -2
- package/dist/TransactionPayController.d.cts.map +1 -1
- package/dist/TransactionPayController.d.mts +13 -2
- package/dist/TransactionPayController.d.mts.map +1 -1
- package/dist/TransactionPayController.mjs +21 -3
- package/dist/TransactionPayController.mjs.map +1 -1
- package/dist/constants.cjs +8 -1
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +6 -0
- package/dist/constants.d.cts.map +1 -1
- package/dist/constants.d.mts +6 -0
- package/dist/constants.d.mts.map +1 -1
- package/dist/constants.mjs +7 -0
- package/dist/constants.mjs.map +1 -1
- package/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/strategy/relay/relay-quotes.cjs +20 -3
- 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 +20 -3
- package/dist/strategy/relay/relay-quotes.mjs.map +1 -1
- package/dist/strategy/relay/relay-submit.cjs +24 -11
- package/dist/strategy/relay/relay-submit.cjs.map +1 -1
- package/dist/strategy/relay/relay-submit.mjs +24 -11
- package/dist/strategy/relay/relay-submit.mjs.map +1 -1
- package/dist/strategy/server/ServerStrategy.cjs +35 -0
- package/dist/strategy/server/ServerStrategy.cjs.map +1 -0
- package/dist/strategy/server/ServerStrategy.d.cts +15 -0
- package/dist/strategy/server/ServerStrategy.d.cts.map +1 -0
- package/dist/strategy/server/ServerStrategy.d.mts +15 -0
- package/dist/strategy/server/ServerStrategy.d.mts.map +1 -0
- package/dist/strategy/server/ServerStrategy.mjs +31 -0
- package/dist/strategy/server/ServerStrategy.mjs.map +1 -0
- package/dist/strategy/server/constants.cjs +11 -0
- package/dist/strategy/server/constants.cjs.map +1 -0
- package/dist/strategy/server/constants.d.cts +8 -0
- package/dist/strategy/server/constants.d.cts.map +1 -0
- package/dist/strategy/server/constants.d.mts +8 -0
- package/dist/strategy/server/constants.d.mts.map +1 -0
- package/dist/strategy/server/constants.mjs +8 -0
- package/dist/strategy/server/constants.mjs.map +1 -0
- package/dist/strategy/server/perps.cjs +71 -0
- package/dist/strategy/server/perps.cjs.map +1 -0
- package/dist/strategy/server/perps.d.cts +36 -0
- package/dist/strategy/server/perps.d.cts.map +1 -0
- package/dist/strategy/server/perps.d.mts +36 -0
- package/dist/strategy/server/perps.d.mts.map +1 -0
- package/dist/strategy/server/perps.mjs +66 -0
- package/dist/strategy/server/perps.mjs.map +1 -0
- package/dist/strategy/server/server-api.cjs +98 -0
- package/dist/strategy/server/server-api.cjs.map +1 -0
- package/dist/strategy/server/server-api.d.cts +35 -0
- package/dist/strategy/server/server-api.d.cts.map +1 -0
- package/dist/strategy/server/server-api.d.mts +35 -0
- package/dist/strategy/server/server-api.d.mts.map +1 -0
- package/dist/strategy/server/server-api.mjs +92 -0
- package/dist/strategy/server/server-api.mjs.map +1 -0
- package/dist/strategy/server/server-quotes.cjs +315 -0
- package/dist/strategy/server/server-quotes.cjs.map +1 -0
- package/dist/strategy/server/server-quotes.d.cts +10 -0
- package/dist/strategy/server/server-quotes.d.cts.map +1 -0
- package/dist/strategy/server/server-quotes.d.mts +10 -0
- package/dist/strategy/server/server-quotes.d.mts.map +1 -0
- package/dist/strategy/server/server-quotes.mjs +311 -0
- package/dist/strategy/server/server-quotes.mjs.map +1 -0
- package/dist/strategy/server/server-submit.cjs +296 -0
- package/dist/strategy/server/server-submit.cjs.map +1 -0
- package/dist/strategy/server/server-submit.d.cts +13 -0
- package/dist/strategy/server/server-submit.d.cts.map +1 -0
- package/dist/strategy/server/server-submit.d.mts +13 -0
- package/dist/strategy/server/server-submit.d.mts.map +1 -0
- package/dist/strategy/server/server-submit.mjs +292 -0
- package/dist/strategy/server/server-submit.mjs.map +1 -0
- package/dist/strategy/server/types.cjs +26 -0
- package/dist/strategy/server/types.cjs.map +1 -0
- package/dist/strategy/server/types.d.cts +153 -0
- package/dist/strategy/server/types.d.cts.map +1 -0
- package/dist/strategy/server/types.d.mts +153 -0
- package/dist/strategy/server/types.d.mts.map +1 -0
- package/dist/strategy/server/types.mjs +23 -0
- package/dist/strategy/server/types.mjs.map +1 -0
- package/dist/tests/messenger-mock.cjs +3 -0
- package/dist/tests/messenger-mock.cjs.map +1 -1
- package/dist/tests/messenger-mock.d.cts +255 -3
- package/dist/tests/messenger-mock.d.cts.map +1 -1
- package/dist/tests/messenger-mock.d.mts +255 -3
- 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 +44 -14
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +44 -14
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/dist/utils/feature-flags.cjs +43 -3
- package/dist/utils/feature-flags.cjs.map +1 -1
- package/dist/utils/feature-flags.d.cts +21 -0
- package/dist/utils/feature-flags.d.cts.map +1 -1
- package/dist/utils/feature-flags.d.mts +21 -0
- package/dist/utils/feature-flags.d.mts.map +1 -1
- package/dist/utils/feature-flags.mjs +40 -2
- package/dist/utils/feature-flags.mjs.map +1 -1
- package/dist/utils/gas.cjs +11 -10
- package/dist/utils/gas.cjs.map +1 -1
- package/dist/utils/gas.d.cts +12 -0
- package/dist/utils/gas.d.cts.map +1 -1
- package/dist/utils/gas.d.mts +12 -0
- package/dist/utils/gas.d.mts.map +1 -1
- package/dist/utils/gas.mjs +10 -10
- package/dist/utils/gas.mjs.map +1 -1
- package/dist/utils/quotes.cjs +9 -3
- package/dist/utils/quotes.cjs.map +1 -1
- package/dist/utils/quotes.d.cts.map +1 -1
- package/dist/utils/quotes.d.mts.map +1 -1
- package/dist/utils/quotes.mjs +10 -4
- package/dist/utils/quotes.mjs.map +1 -1
- package/dist/utils/strategy.cjs +3 -0
- package/dist/utils/strategy.cjs.map +1 -1
- package/dist/utils/strategy.d.cts.map +1 -1
- package/dist/utils/strategy.d.mts.map +1 -1
- package/dist/utils/strategy.mjs +3 -0
- package/dist/utils/strategy.mjs.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { createModuleLogger } from "@metamask/utils";
|
|
2
|
+
import { projectLogger } from "../../logger.mjs";
|
|
3
|
+
import { getPayStrategiesConfig } from "../../utils/feature-flags.mjs";
|
|
4
|
+
const log = createModuleLogger(projectLogger, 'server-api');
|
|
5
|
+
/**
|
|
6
|
+
* Fetch a quote from the server intents API.
|
|
7
|
+
*
|
|
8
|
+
* @param messenger - Controller messenger.
|
|
9
|
+
* @param body - Quote request parameters.
|
|
10
|
+
* @param signal - Optional abort signal that cancels the underlying fetch.
|
|
11
|
+
* @returns The server quote response.
|
|
12
|
+
*/
|
|
13
|
+
export async function fetchServerQuote(messenger, body, signal) {
|
|
14
|
+
const { server } = getPayStrategiesConfig(messenger);
|
|
15
|
+
const quoteUrl = `${server.baseUrl}/quote`;
|
|
16
|
+
log('Fetching quote', { url: quoteUrl });
|
|
17
|
+
const response = await serverFetch(quoteUrl, {
|
|
18
|
+
method: 'POST',
|
|
19
|
+
headers: { 'Content-Type': 'application/json' },
|
|
20
|
+
body: JSON.stringify(body),
|
|
21
|
+
signal,
|
|
22
|
+
});
|
|
23
|
+
return (await response.json());
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Submit a gasless intent via the server intents API.
|
|
27
|
+
*
|
|
28
|
+
* @param messenger - Controller messenger.
|
|
29
|
+
* @param body - Submit request parameters.
|
|
30
|
+
* @returns The submit response.
|
|
31
|
+
*/
|
|
32
|
+
export async function submitServerIntent(messenger, body) {
|
|
33
|
+
const { server } = getPayStrategiesConfig(messenger);
|
|
34
|
+
const submitUrl = `${server.baseUrl}/submit`;
|
|
35
|
+
log('Submitting intent', { url: submitUrl });
|
|
36
|
+
const response = await serverFetch(submitUrl, {
|
|
37
|
+
method: 'POST',
|
|
38
|
+
headers: { 'Content-Type': 'application/json' },
|
|
39
|
+
body: JSON.stringify(body),
|
|
40
|
+
});
|
|
41
|
+
return (await response.json());
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Fetch the status of a server intent.
|
|
45
|
+
*
|
|
46
|
+
* @param messenger - Controller messenger.
|
|
47
|
+
* @param params - Status query parameters.
|
|
48
|
+
* @param params.provider - The provider that the intent was submitted to.
|
|
49
|
+
* @param params.id - The intent ID.
|
|
50
|
+
* @param params.hash - Optional transaction hash to include in the status query.
|
|
51
|
+
* @returns The current status of the intent.
|
|
52
|
+
*/
|
|
53
|
+
export async function getServerStatus(messenger, params) {
|
|
54
|
+
const { server } = getPayStrategiesConfig(messenger);
|
|
55
|
+
const query = new URLSearchParams({
|
|
56
|
+
provider: params.provider,
|
|
57
|
+
id: params.id,
|
|
58
|
+
});
|
|
59
|
+
if (params.hash) {
|
|
60
|
+
query.set('hash', params.hash);
|
|
61
|
+
}
|
|
62
|
+
const url = `${server.baseUrl}/status?${query.toString()}`;
|
|
63
|
+
log('Fetching status', { url });
|
|
64
|
+
const response = await serverFetch(url, { method: 'GET' });
|
|
65
|
+
return (await response.json());
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Fetch a server intents-api endpoint, throwing an error containing the
|
|
69
|
+
* response body's `message` or `error` field (or status code) on non-OK
|
|
70
|
+
* responses so the server's actual reason is preserved without leaking the
|
|
71
|
+
* request URL.
|
|
72
|
+
*
|
|
73
|
+
* @param url - The endpoint to fetch.
|
|
74
|
+
* @param init - Fetch init options.
|
|
75
|
+
* @returns The successful response.
|
|
76
|
+
*/
|
|
77
|
+
async function serverFetch(url, init) {
|
|
78
|
+
const response = await fetch(url, init);
|
|
79
|
+
if (!response.ok) {
|
|
80
|
+
let detail;
|
|
81
|
+
try {
|
|
82
|
+
const body = (await response.json());
|
|
83
|
+
detail = body.message ?? body.error;
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// Body wasn't JSON; fall through to status-only error.
|
|
87
|
+
}
|
|
88
|
+
throw new Error(detail ? `${response.status} - ${detail}` : String(response.status));
|
|
89
|
+
}
|
|
90
|
+
return response;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=server-api.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-api.mjs","sourceRoot":"","sources":["../../../src/strategy/server/server-api.ts"],"names":[],"mappings":"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","sourcesContent":["import { createModuleLogger } from '@metamask/utils';\n\nimport { projectLogger } from '../../logger';\nimport type { TransactionPayControllerMessenger } from '../../types';\nimport { getPayStrategiesConfig } from '../../utils/feature-flags';\nimport type {\n ServerProviderName,\n ServerQuoteRequest,\n ServerQuoteResponse,\n ServerStatusResponse,\n ServerSubmitRequest,\n ServerSubmitResponse,\n} from './types';\n\nconst log = createModuleLogger(projectLogger, 'server-api');\n\n/**\n * Fetch a quote from the server intents API.\n *\n * @param messenger - Controller messenger.\n * @param body - Quote request parameters.\n * @param signal - Optional abort signal that cancels the underlying fetch.\n * @returns The server quote response.\n */\nexport async function fetchServerQuote(\n messenger: TransactionPayControllerMessenger,\n body: ServerQuoteRequest,\n signal?: AbortSignal,\n): Promise<ServerQuoteResponse> {\n const { server } = getPayStrategiesConfig(messenger);\n const quoteUrl = `${server.baseUrl}/quote`;\n\n log('Fetching quote', { url: quoteUrl });\n\n const response = await serverFetch(quoteUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal,\n });\n\n return (await response.json()) as ServerQuoteResponse;\n}\n\n/**\n * Submit a gasless intent via the server intents API.\n *\n * @param messenger - Controller messenger.\n * @param body - Submit request parameters.\n * @returns The submit response.\n */\nexport async function submitServerIntent(\n messenger: TransactionPayControllerMessenger,\n body: ServerSubmitRequest,\n): Promise<ServerSubmitResponse> {\n const { server } = getPayStrategiesConfig(messenger);\n const submitUrl = `${server.baseUrl}/submit`;\n\n log('Submitting intent', { url: submitUrl });\n\n const response = await serverFetch(submitUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n return (await response.json()) as ServerSubmitResponse;\n}\n\n/**\n * Fetch the status of a server intent.\n *\n * @param messenger - Controller messenger.\n * @param params - Status query parameters.\n * @param params.provider - The provider that the intent was submitted to.\n * @param params.id - The intent ID.\n * @param params.hash - Optional transaction hash to include in the status query.\n * @returns The current status of the intent.\n */\nexport async function getServerStatus(\n messenger: TransactionPayControllerMessenger,\n params: { provider: ServerProviderName; id: string; hash?: string },\n): Promise<ServerStatusResponse> {\n const { server } = getPayStrategiesConfig(messenger);\n const query = new URLSearchParams({\n provider: params.provider,\n id: params.id,\n });\n if (params.hash) {\n query.set('hash', params.hash);\n }\n const url = `${server.baseUrl}/status?${query.toString()}`;\n\n log('Fetching status', { url });\n\n const response = await serverFetch(url, { method: 'GET' });\n\n return (await response.json()) as ServerStatusResponse;\n}\n\n/**\n * Fetch a server intents-api endpoint, throwing an error containing the\n * response body's `message` or `error` field (or status code) on non-OK\n * responses so the server's actual reason is preserved without leaking the\n * request URL.\n *\n * @param url - The endpoint to fetch.\n * @param init - Fetch init options.\n * @returns The successful response.\n */\nasync function serverFetch(url: string, init?: RequestInit): Promise<Response> {\n const response = await fetch(url, init);\n\n if (!response.ok) {\n let detail: string | undefined;\n try {\n const body = (await response.json()) as {\n message?: string;\n error?: string;\n };\n detail = body.message ?? body.error;\n } catch {\n // Body wasn't JSON; fall through to status-only error.\n }\n throw new Error(\n detail ? `${response.status} - ${detail}` : String(response.status),\n );\n }\n\n return response;\n}\n"]}
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getServerQuotes = void 0;
|
|
4
|
+
const abi_1 = require("@ethersproject/abi");
|
|
5
|
+
const controller_utils_1 = require("@metamask/controller-utils");
|
|
6
|
+
const utils_1 = require("@metamask/utils");
|
|
7
|
+
const bignumber_js_1 = require("bignumber.js");
|
|
8
|
+
const constants_1 = require("../../constants.cjs");
|
|
9
|
+
const logger_1 = require("../../logger.cjs");
|
|
10
|
+
const amounts_1 = require("../../utils/amounts.cjs");
|
|
11
|
+
const feature_flags_1 = require("../../utils/feature-flags.cjs");
|
|
12
|
+
const gas_1 = require("../../utils/gas.cjs");
|
|
13
|
+
const gas_station_1 = require("../../utils/gas-station.cjs");
|
|
14
|
+
const quote_gas_1 = require("../../utils/quote-gas.cjs");
|
|
15
|
+
const token_1 = require("../../utils/token.cjs");
|
|
16
|
+
const perps_1 = require("./perps.cjs");
|
|
17
|
+
const server_api_1 = require("./server-api.cjs");
|
|
18
|
+
const types_1 = require("./types.cjs");
|
|
19
|
+
const log = (0, utils_1.createModuleLogger)(logger_1.projectLogger, 'server-quotes');
|
|
20
|
+
const TOKEN_TRANSFER_FOUR_BYTE = '0xa9059cbb';
|
|
21
|
+
const TRANSFER_INTERFACE = new abi_1.Interface([
|
|
22
|
+
'function transfer(address to, uint256 amount)',
|
|
23
|
+
]);
|
|
24
|
+
const ZERO_AMOUNT = { fiat: '0', human: '0', raw: '0', usd: '0' };
|
|
25
|
+
const ZERO_FIAT_VALUE = { fiat: '0', usd: '0' };
|
|
26
|
+
/**
|
|
27
|
+
* Fetch server intents-api quotes and normalize them into Transaction Pay quotes.
|
|
28
|
+
*
|
|
29
|
+
* @param request - Quote request context.
|
|
30
|
+
* @returns Normalized server strategy quotes.
|
|
31
|
+
*/
|
|
32
|
+
async function getServerQuotes(request) {
|
|
33
|
+
const quoteRequests = request.requests.filter(shouldRequestQuote);
|
|
34
|
+
log('Fetching quotes', { quoteRequests });
|
|
35
|
+
const quotes = await Promise.all(quoteRequests.map((quoteRequest) => getQuotesForRequest(quoteRequest, request)));
|
|
36
|
+
return quotes.flat();
|
|
37
|
+
}
|
|
38
|
+
exports.getServerQuotes = getServerQuotes;
|
|
39
|
+
async function getQuotesForRequest(quoteRequest, fullRequest) {
|
|
40
|
+
const { accountSupports7702, messenger, signal, transaction } = fullRequest;
|
|
41
|
+
const body = await buildServerQuoteRequest(quoteRequest, transaction, messenger, accountSupports7702);
|
|
42
|
+
try {
|
|
43
|
+
log('Request body', body);
|
|
44
|
+
const response = await (0, server_api_1.fetchServerQuote)(messenger, body, signal);
|
|
45
|
+
log('Raw quote response', response);
|
|
46
|
+
const fulfilledResults = response.results.filter(isFulfilledResult);
|
|
47
|
+
const normalized = await Promise.all(fulfilledResults.map((result) => normalizeQuote(result, quoteRequest, messenger)));
|
|
48
|
+
log('Normalized quotes', normalized);
|
|
49
|
+
return normalized;
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
log('Error fetching quotes', { error });
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async function buildServerQuoteRequest(quoteRequest, transaction, messenger, accountSupports7702) {
|
|
57
|
+
const normalizedRequest = (0, perps_1.normalizeServerPerpsRequest)(quoteRequest, transaction);
|
|
58
|
+
const { from, isMaxAmount, isPostQuote, sourceChainId, sourceTokenAddress, sourceTokenAmount, targetAmountMinimum, targetChainId, targetTokenAddress, } = normalizedRequest;
|
|
59
|
+
const useExactInput = (isMaxAmount ?? false) || (isPostQuote ?? false);
|
|
60
|
+
const singleData = getSingleTransactionData(transaction);
|
|
61
|
+
const isHypercore = targetChainId === constants_1.CHAIN_ID_HYPERCORE;
|
|
62
|
+
const isTokenTransfer = !isHypercore && Boolean(singleData?.startsWith(TOKEN_TRANSFER_FOUR_BYTE));
|
|
63
|
+
let recipient = from;
|
|
64
|
+
if (isTokenTransfer && singleData) {
|
|
65
|
+
recipient = decodeTransferRecipient(singleData);
|
|
66
|
+
}
|
|
67
|
+
const supportsGasless = accountSupports7702 && (0, feature_flags_1.isEIP7702Chain)(messenger, sourceChainId);
|
|
68
|
+
const body = {
|
|
69
|
+
source: { chainId: Number(sourceChainId), token: sourceTokenAddress },
|
|
70
|
+
target: { chainId: Number(targetChainId), token: targetTokenAddress },
|
|
71
|
+
amount: useExactInput ? sourceTokenAmount : targetAmountMinimum,
|
|
72
|
+
tradeType: useExactInput
|
|
73
|
+
? types_1.ServerTradeType.ExactInput
|
|
74
|
+
: types_1.ServerTradeType.ExpectedOutput,
|
|
75
|
+
sender: from,
|
|
76
|
+
recipient,
|
|
77
|
+
slippage: Math.round((0, feature_flags_1.getSlippage)(messenger, sourceChainId, sourceTokenAddress) * 10000),
|
|
78
|
+
supportsGasless,
|
|
79
|
+
};
|
|
80
|
+
const hasNoData = singleData === undefined || singleData === '0x';
|
|
81
|
+
const skipDelegation = hasNoData ||
|
|
82
|
+
isTokenTransfer ||
|
|
83
|
+
isHypercore ||
|
|
84
|
+
(isPostQuote ?? false) ||
|
|
85
|
+
(isMaxAmount ?? false);
|
|
86
|
+
if (!skipDelegation) {
|
|
87
|
+
const delegation = await messenger.call('TransactionPayController:getDelegationTransaction', { transaction });
|
|
88
|
+
body.calls = [
|
|
89
|
+
{
|
|
90
|
+
data: buildTransferData(from, targetAmountMinimum),
|
|
91
|
+
to: targetTokenAddress,
|
|
92
|
+
value: '0x0',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
data: delegation.data,
|
|
96
|
+
to: delegation.to,
|
|
97
|
+
value: delegation.value,
|
|
98
|
+
},
|
|
99
|
+
];
|
|
100
|
+
if (delegation.authorizationList?.length) {
|
|
101
|
+
body.authorizationList = delegation.authorizationList.map((entry) => ({
|
|
102
|
+
address: entry.address,
|
|
103
|
+
chainId: Number(entry.chainId),
|
|
104
|
+
nonce: Number(entry.nonce),
|
|
105
|
+
r: entry.r,
|
|
106
|
+
s: entry.s,
|
|
107
|
+
yParity: Number(entry.yParity),
|
|
108
|
+
}));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return body;
|
|
112
|
+
}
|
|
113
|
+
function shouldRequestQuote(quoteRequest) {
|
|
114
|
+
return (quoteRequest.targetAmountMinimum !== '0' ||
|
|
115
|
+
Boolean(quoteRequest.isPostQuote) ||
|
|
116
|
+
Boolean(quoteRequest.isMaxAmount));
|
|
117
|
+
}
|
|
118
|
+
async function normalizeQuote(result, quoteRequest, messenger) {
|
|
119
|
+
const { quote } = result;
|
|
120
|
+
const { gasless } = quote;
|
|
121
|
+
const sourceNetwork = await calculateSourceNetworkCost({
|
|
122
|
+
gasless,
|
|
123
|
+
messenger,
|
|
124
|
+
quoteRequest,
|
|
125
|
+
steps: quote.steps,
|
|
126
|
+
});
|
|
127
|
+
const sourceFiatRate = (0, token_1.getTokenFiatRate)(messenger, quoteRequest.sourceTokenAddress, quoteRequest.sourceChainId);
|
|
128
|
+
const usdToFiatRate = sourceFiatRate
|
|
129
|
+
? new bignumber_js_1.BigNumber(sourceFiatRate.fiatRate).dividedBy(sourceFiatRate.usdRate)
|
|
130
|
+
: new bignumber_js_1.BigNumber(1);
|
|
131
|
+
const metaMask = (0, amounts_1.getFiatValueFromUsd)(new bignumber_js_1.BigNumber(quote.fees.metamask), usdToFiatRate);
|
|
132
|
+
const provider = (0, amounts_1.getFiatValueFromUsd)(new bignumber_js_1.BigNumber(quote.fees.provider), usdToFiatRate);
|
|
133
|
+
return {
|
|
134
|
+
dust: ZERO_FIAT_VALUE,
|
|
135
|
+
estimatedDuration: quote.duration,
|
|
136
|
+
fees: {
|
|
137
|
+
...(sourceNetwork.isSourceGasFeeToken
|
|
138
|
+
? { isSourceGasFeeToken: true }
|
|
139
|
+
: {}),
|
|
140
|
+
metaMask,
|
|
141
|
+
provider,
|
|
142
|
+
sourceNetwork: {
|
|
143
|
+
estimate: sourceNetwork.estimate,
|
|
144
|
+
max: sourceNetwork.max,
|
|
145
|
+
},
|
|
146
|
+
targetNetwork: ZERO_FIAT_VALUE,
|
|
147
|
+
},
|
|
148
|
+
original: {
|
|
149
|
+
client: {
|
|
150
|
+
gasLimits: sourceNetwork.gasLimits,
|
|
151
|
+
is7702: sourceNetwork.is7702,
|
|
152
|
+
maxFeePerGas: sourceNetwork.maxFeePerGas,
|
|
153
|
+
maxPriorityFeePerGas: sourceNetwork.maxPriorityFeePerGas,
|
|
154
|
+
},
|
|
155
|
+
duration: quote.duration,
|
|
156
|
+
fees: quote.fees,
|
|
157
|
+
gasless,
|
|
158
|
+
id: quote.id,
|
|
159
|
+
input: quote.input,
|
|
160
|
+
output: quote.output,
|
|
161
|
+
provider: result.provider,
|
|
162
|
+
steps: quote.steps,
|
|
163
|
+
},
|
|
164
|
+
request: quoteRequest,
|
|
165
|
+
sourceAmount: {
|
|
166
|
+
fiat: sourceFiatRate
|
|
167
|
+
? new bignumber_js_1.BigNumber(quote.input.formatted)
|
|
168
|
+
.multipliedBy(sourceFiatRate.fiatRate)
|
|
169
|
+
.toString(10)
|
|
170
|
+
: '0',
|
|
171
|
+
human: quote.input.formatted,
|
|
172
|
+
raw: quote.input.raw,
|
|
173
|
+
usd: sourceFiatRate
|
|
174
|
+
? new bignumber_js_1.BigNumber(quote.input.formatted)
|
|
175
|
+
.multipliedBy(sourceFiatRate.usdRate)
|
|
176
|
+
.toString(10)
|
|
177
|
+
: '0',
|
|
178
|
+
},
|
|
179
|
+
strategy: constants_1.TransactionPayStrategy.Server,
|
|
180
|
+
targetAmount: {
|
|
181
|
+
fiat: '0',
|
|
182
|
+
usd: '0',
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
async function calculateSourceNetworkCost({ gasless, messenger, quoteRequest, steps, }) {
|
|
187
|
+
const noFees = {
|
|
188
|
+
estimate: ZERO_AMOUNT,
|
|
189
|
+
gasLimits: [],
|
|
190
|
+
is7702: false,
|
|
191
|
+
max: ZERO_AMOUNT,
|
|
192
|
+
maxFeePerGas: undefined,
|
|
193
|
+
maxPriorityFeePerGas: undefined,
|
|
194
|
+
};
|
|
195
|
+
if (gasless) {
|
|
196
|
+
log('Zeroing source network fees for gasless quote');
|
|
197
|
+
return noFees;
|
|
198
|
+
}
|
|
199
|
+
if (steps.length === 0) {
|
|
200
|
+
log('No quote steps; zeroing source network fees');
|
|
201
|
+
return noFees;
|
|
202
|
+
}
|
|
203
|
+
const { from, sourceChainId, sourceTokenAddress } = quoteRequest;
|
|
204
|
+
const firstStep = steps[0];
|
|
205
|
+
const chainIdHex = (0, controller_utils_1.toHex)(firstStep.chainId);
|
|
206
|
+
const needsGasFeeEstimate = !firstStep.maxFeePerGas && !firstStep.maxPriorityFeePerGas;
|
|
207
|
+
const gasFeeEstimate = needsGasFeeEstimate
|
|
208
|
+
? (0, gas_1.getGasFee)(chainIdHex, messenger)
|
|
209
|
+
: { maxFeePerGas: undefined, maxPriorityFeePerGas: undefined };
|
|
210
|
+
const maxFeePerGas = firstStep.maxFeePerGas ?? gasFeeEstimate.maxFeePerGas;
|
|
211
|
+
const maxPriorityFeePerGas = firstStep.maxPriorityFeePerGas ?? gasFeeEstimate.maxPriorityFeePerGas;
|
|
212
|
+
const gasTransactions = steps.map((step) => stepToGasTransaction(step, from));
|
|
213
|
+
const gasResult = await (0, quote_gas_1.estimateQuoteGasLimits)({
|
|
214
|
+
fallbackGas: (0, feature_flags_1.getFeatureFlags)(messenger).relayFallbackGas,
|
|
215
|
+
fallbackOnSimulationFailure: true,
|
|
216
|
+
messenger,
|
|
217
|
+
transactions: gasTransactions,
|
|
218
|
+
});
|
|
219
|
+
const { is7702 } = gasResult;
|
|
220
|
+
const gasLimits = is7702
|
|
221
|
+
? [gasResult.gasLimits[0].max]
|
|
222
|
+
: gasResult.gasLimits.map((gasLimit) => gasLimit.max);
|
|
223
|
+
const estimate = (0, gas_1.calculateGasCost)({
|
|
224
|
+
chainId: chainIdHex,
|
|
225
|
+
gas: gasResult.totalGasEstimate,
|
|
226
|
+
maxFeePerGas: maxFeePerGas ?? '0',
|
|
227
|
+
maxPriorityFeePerGas: maxPriorityFeePerGas ?? '0',
|
|
228
|
+
messenger,
|
|
229
|
+
});
|
|
230
|
+
const max = (0, gas_1.calculateGasCost)({
|
|
231
|
+
chainId: chainIdHex,
|
|
232
|
+
gas: gasResult.totalGasLimit,
|
|
233
|
+
isMax: true,
|
|
234
|
+
maxFeePerGas: maxFeePerGas ?? '0',
|
|
235
|
+
maxPriorityFeePerGas: maxPriorityFeePerGas ?? '0',
|
|
236
|
+
messenger,
|
|
237
|
+
});
|
|
238
|
+
const nativeBalance = (0, token_1.getTokenBalance)(messenger, from, sourceChainId, (0, token_1.getNativeToken)(sourceChainId));
|
|
239
|
+
const fees = { maxFeePerGas, maxPriorityFeePerGas };
|
|
240
|
+
if (new bignumber_js_1.BigNumber(nativeBalance).isGreaterThanOrEqualTo(max.raw)) {
|
|
241
|
+
return { estimate, gasLimits, is7702, max, ...fees };
|
|
242
|
+
}
|
|
243
|
+
const eligibility = (0, gas_station_1.getGasStationEligibility)(messenger, sourceChainId);
|
|
244
|
+
if (eligibility.isDisabledChain || !eligibility.chainSupportsGasStation) {
|
|
245
|
+
log('Skipping gas station for source network', {
|
|
246
|
+
isDisabledChain: eligibility.isDisabledChain,
|
|
247
|
+
sourceChainId,
|
|
248
|
+
supportsGasStation: eligibility.chainSupportsGasStation,
|
|
249
|
+
});
|
|
250
|
+
return { estimate, gasLimits, is7702, max, ...fees };
|
|
251
|
+
}
|
|
252
|
+
log('Checking gas fee tokens due to insufficient native balance', {
|
|
253
|
+
max: max.raw,
|
|
254
|
+
nativeBalance,
|
|
255
|
+
});
|
|
256
|
+
const gasFeeTokenCost = await (0, gas_station_1.getGasStationCostInSourceTokenRaw)({
|
|
257
|
+
firstStepData: {
|
|
258
|
+
data: firstStep.data,
|
|
259
|
+
to: firstStep.to,
|
|
260
|
+
value: firstStep.value,
|
|
261
|
+
},
|
|
262
|
+
messenger,
|
|
263
|
+
request: {
|
|
264
|
+
from,
|
|
265
|
+
sourceChainId,
|
|
266
|
+
sourceTokenAddress,
|
|
267
|
+
},
|
|
268
|
+
totalGasEstimate: gasResult.totalGasEstimate,
|
|
269
|
+
totalItemCount: steps.length,
|
|
270
|
+
});
|
|
271
|
+
if (!gasFeeTokenCost) {
|
|
272
|
+
return { estimate, gasLimits, is7702, max, ...fees };
|
|
273
|
+
}
|
|
274
|
+
log('Using gas fee token for source network', { gasFeeTokenCost });
|
|
275
|
+
return {
|
|
276
|
+
estimate: gasFeeTokenCost,
|
|
277
|
+
gasLimits,
|
|
278
|
+
is7702,
|
|
279
|
+
isSourceGasFeeToken: true,
|
|
280
|
+
max: gasFeeTokenCost,
|
|
281
|
+
...fees,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
function stepToGasTransaction(step, from) {
|
|
285
|
+
return {
|
|
286
|
+
chainId: (0, controller_utils_1.toHex)(step.chainId),
|
|
287
|
+
data: step.data,
|
|
288
|
+
from,
|
|
289
|
+
to: step.to,
|
|
290
|
+
value: step.value,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
function getSingleTransactionData(transaction) {
|
|
294
|
+
for (const nested of transaction.nestedTransactions ?? []) {
|
|
295
|
+
if (nested.data && nested.data !== '0x') {
|
|
296
|
+
return nested.data;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return transaction.txParams?.data;
|
|
300
|
+
}
|
|
301
|
+
function isFulfilledResult(result) {
|
|
302
|
+
return (result.quote?.id !== undefined &&
|
|
303
|
+
result.quote.input !== undefined &&
|
|
304
|
+
result.quote.output !== undefined);
|
|
305
|
+
}
|
|
306
|
+
function decodeTransferRecipient(data) {
|
|
307
|
+
return TRANSFER_INTERFACE.decodeFunctionData('transfer', data).to.toLowerCase();
|
|
308
|
+
}
|
|
309
|
+
function buildTransferData(recipient, amountRaw) {
|
|
310
|
+
return TRANSFER_INTERFACE.encodeFunctionData('transfer', [
|
|
311
|
+
recipient,
|
|
312
|
+
amountRaw,
|
|
313
|
+
]);
|
|
314
|
+
}
|
|
315
|
+
//# sourceMappingURL=server-quotes.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-quotes.cjs","sourceRoot":"","sources":["../../../src/strategy/server/server-quotes.ts"],"names":[],"mappings":"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","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport { toHex } from '@metamask/controller-utils';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { CHAIN_ID_HYPERCORE, TransactionPayStrategy } from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionPayControllerMessenger,\n TransactionPayFees,\n TransactionPayQuote,\n} from '../../types';\nimport { getFiatValueFromUsd } from '../../utils/amounts';\nimport {\n getFeatureFlags,\n getSlippage,\n isEIP7702Chain,\n} from '../../utils/feature-flags';\nimport { calculateGasCost, getGasFee } from '../../utils/gas';\nimport {\n getGasStationCostInSourceTokenRaw,\n getGasStationEligibility,\n} from '../../utils/gas-station';\nimport { estimateQuoteGasLimits } from '../../utils/quote-gas';\nimport type { QuoteGasTransaction } from '../../utils/quote-gas';\nimport {\n getNativeToken,\n getTokenBalance,\n getTokenFiatRate,\n} from '../../utils/token';\nimport { normalizeServerPerpsRequest } from './perps';\nimport { fetchServerQuote } from './server-api';\nimport type {\n ServerQuote,\n ServerQuoteRequest,\n ServerQuoteResult,\n ServerQuoteStep,\n} from './types';\nimport { ServerTradeType } from './types';\n\nconst log = createModuleLogger(projectLogger, 'server-quotes');\nconst TOKEN_TRANSFER_FOUR_BYTE = '0xa9059cbb';\nconst TRANSFER_INTERFACE = new Interface([\n 'function transfer(address to, uint256 amount)',\n]);\nconst ZERO_AMOUNT = { fiat: '0', human: '0', raw: '0', usd: '0' };\nconst ZERO_FIAT_VALUE = { fiat: '0', usd: '0' };\n\ntype FulfilledServerQuoteResult = ServerQuoteResult & {\n quote: NonNullable<ServerQuoteResult['quote']>;\n};\n\ntype SourceNetworkCost = Pick<\n TransactionPayFees['sourceNetwork'],\n 'estimate' | 'max'\n> & {\n gasLimits: number[];\n is7702: boolean;\n isSourceGasFeeToken?: boolean;\n maxFeePerGas: string | undefined;\n maxPriorityFeePerGas: string | undefined;\n};\n\n/**\n * Fetch server intents-api quotes and normalize them into Transaction Pay quotes.\n *\n * @param request - Quote request context.\n * @returns Normalized server strategy quotes.\n */\nexport async function getServerQuotes(\n request: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<ServerQuote>[]> {\n const quoteRequests = request.requests.filter(shouldRequestQuote);\n\n log('Fetching quotes', { quoteRequests });\n\n const quotes = await Promise.all(\n quoteRequests.map((quoteRequest) =>\n getQuotesForRequest(quoteRequest, request),\n ),\n );\n\n return quotes.flat();\n}\n\nasync function getQuotesForRequest(\n quoteRequest: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<ServerQuote>[]> {\n const { accountSupports7702, messenger, signal, transaction } = fullRequest;\n\n const body = await buildServerQuoteRequest(\n quoteRequest,\n transaction,\n messenger,\n accountSupports7702,\n );\n\n try {\n log('Request body', body);\n\n const response = await fetchServerQuote(messenger, body, signal);\n\n log('Raw quote response', response);\n\n const fulfilledResults = response.results.filter(isFulfilledResult);\n\n const normalized = await Promise.all(\n fulfilledResults.map((result) =>\n normalizeQuote(result, quoteRequest, messenger),\n ),\n );\n\n log('Normalized quotes', normalized);\n\n return normalized;\n } catch (error) {\n log('Error fetching quotes', { error });\n return [];\n }\n}\n\nasync function buildServerQuoteRequest(\n quoteRequest: QuoteRequest,\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n accountSupports7702: boolean,\n): Promise<ServerQuoteRequest> {\n const normalizedRequest = normalizeServerPerpsRequest(\n quoteRequest,\n transaction,\n );\n const {\n from,\n isMaxAmount,\n isPostQuote,\n sourceChainId,\n sourceTokenAddress,\n sourceTokenAmount,\n targetAmountMinimum,\n targetChainId,\n targetTokenAddress,\n } = normalizedRequest;\n\n const useExactInput = (isMaxAmount ?? false) || (isPostQuote ?? false);\n const singleData = getSingleTransactionData(transaction);\n const isHypercore = targetChainId === CHAIN_ID_HYPERCORE;\n const isTokenTransfer =\n !isHypercore && Boolean(singleData?.startsWith(TOKEN_TRANSFER_FOUR_BYTE));\n\n let recipient = from;\n\n if (isTokenTransfer && singleData) {\n recipient = decodeTransferRecipient(singleData);\n }\n\n const supportsGasless =\n accountSupports7702 && isEIP7702Chain(messenger, sourceChainId);\n\n const body: ServerQuoteRequest = {\n source: { chainId: Number(sourceChainId), token: sourceTokenAddress },\n target: { chainId: Number(targetChainId), token: targetTokenAddress },\n amount: useExactInput ? sourceTokenAmount : targetAmountMinimum,\n tradeType: useExactInput\n ? ServerTradeType.ExactInput\n : ServerTradeType.ExpectedOutput,\n sender: from,\n recipient,\n slippage: Math.round(\n getSlippage(messenger, sourceChainId, sourceTokenAddress) * 10000,\n ),\n supportsGasless,\n };\n\n const hasNoData = singleData === undefined || singleData === '0x';\n const skipDelegation =\n hasNoData ||\n isTokenTransfer ||\n isHypercore ||\n (isPostQuote ?? false) ||\n (isMaxAmount ?? false);\n\n if (!skipDelegation) {\n const delegation = await messenger.call(\n 'TransactionPayController:getDelegationTransaction',\n { transaction },\n );\n\n body.calls = [\n {\n data: buildTransferData(from, targetAmountMinimum),\n to: targetTokenAddress,\n value: '0x0',\n },\n {\n data: delegation.data,\n to: delegation.to,\n value: delegation.value,\n },\n ];\n\n if (delegation.authorizationList?.length) {\n body.authorizationList = delegation.authorizationList.map((entry) => ({\n address: entry.address,\n chainId: Number(entry.chainId),\n nonce: Number(entry.nonce),\n r: entry.r as Hex,\n s: entry.s as Hex,\n yParity: Number(entry.yParity),\n }));\n }\n }\n\n return body;\n}\n\nfunction shouldRequestQuote(quoteRequest: QuoteRequest): boolean {\n return (\n quoteRequest.targetAmountMinimum !== '0' ||\n Boolean(quoteRequest.isPostQuote) ||\n Boolean(quoteRequest.isMaxAmount)\n );\n}\n\nasync function normalizeQuote(\n result: FulfilledServerQuoteResult,\n quoteRequest: QuoteRequest,\n messenger: TransactionPayControllerMessenger,\n): Promise<TransactionPayQuote<ServerQuote>> {\n const { quote } = result;\n const { gasless } = quote;\n const sourceNetwork = await calculateSourceNetworkCost({\n gasless,\n messenger,\n quoteRequest,\n steps: quote.steps,\n });\n\n const sourceFiatRate = getTokenFiatRate(\n messenger,\n quoteRequest.sourceTokenAddress,\n quoteRequest.sourceChainId,\n );\n\n const usdToFiatRate = sourceFiatRate\n ? new BigNumber(sourceFiatRate.fiatRate).dividedBy(sourceFiatRate.usdRate)\n : new BigNumber(1);\n\n const metaMask = getFiatValueFromUsd(\n new BigNumber(quote.fees.metamask),\n usdToFiatRate,\n );\n\n const provider = getFiatValueFromUsd(\n new BigNumber(quote.fees.provider),\n usdToFiatRate,\n );\n\n return {\n dust: ZERO_FIAT_VALUE,\n estimatedDuration: quote.duration,\n fees: {\n ...(sourceNetwork.isSourceGasFeeToken\n ? { isSourceGasFeeToken: true }\n : {}),\n metaMask,\n provider,\n sourceNetwork: {\n estimate: sourceNetwork.estimate,\n max: sourceNetwork.max,\n },\n targetNetwork: ZERO_FIAT_VALUE,\n },\n original: {\n client: {\n gasLimits: sourceNetwork.gasLimits,\n is7702: sourceNetwork.is7702,\n maxFeePerGas: sourceNetwork.maxFeePerGas,\n maxPriorityFeePerGas: sourceNetwork.maxPriorityFeePerGas,\n },\n duration: quote.duration,\n fees: quote.fees,\n gasless,\n id: quote.id,\n input: quote.input,\n output: quote.output,\n provider: result.provider,\n steps: quote.steps,\n },\n request: quoteRequest,\n sourceAmount: {\n fiat: sourceFiatRate\n ? new BigNumber(quote.input.formatted)\n .multipliedBy(sourceFiatRate.fiatRate)\n .toString(10)\n : '0',\n human: quote.input.formatted,\n raw: quote.input.raw,\n usd: sourceFiatRate\n ? new BigNumber(quote.input.formatted)\n .multipliedBy(sourceFiatRate.usdRate)\n .toString(10)\n : '0',\n },\n strategy: TransactionPayStrategy.Server,\n targetAmount: {\n fiat: '0',\n usd: '0',\n },\n };\n}\n\nasync function calculateSourceNetworkCost({\n gasless,\n messenger,\n quoteRequest,\n steps,\n}: {\n gasless: boolean;\n messenger: TransactionPayControllerMessenger;\n quoteRequest: QuoteRequest;\n steps: ServerQuoteStep[];\n}): Promise<SourceNetworkCost> {\n const noFees = {\n estimate: ZERO_AMOUNT,\n gasLimits: [],\n is7702: false,\n max: ZERO_AMOUNT,\n maxFeePerGas: undefined,\n maxPriorityFeePerGas: undefined,\n };\n\n if (gasless) {\n log('Zeroing source network fees for gasless quote');\n return noFees;\n }\n\n if (steps.length === 0) {\n log('No quote steps; zeroing source network fees');\n return noFees;\n }\n\n const { from, sourceChainId, sourceTokenAddress } = quoteRequest;\n const firstStep = steps[0];\n const chainIdHex = toHex(firstStep.chainId);\n\n const needsGasFeeEstimate =\n !firstStep.maxFeePerGas && !firstStep.maxPriorityFeePerGas;\n\n const gasFeeEstimate = needsGasFeeEstimate\n ? getGasFee(chainIdHex, messenger)\n : { maxFeePerGas: undefined, maxPriorityFeePerGas: undefined };\n\n const maxFeePerGas = firstStep.maxFeePerGas ?? gasFeeEstimate.maxFeePerGas;\n const maxPriorityFeePerGas =\n firstStep.maxPriorityFeePerGas ?? gasFeeEstimate.maxPriorityFeePerGas;\n\n const gasTransactions = steps.map((step) => stepToGasTransaction(step, from));\n\n const gasResult = await estimateQuoteGasLimits({\n fallbackGas: getFeatureFlags(messenger).relayFallbackGas,\n fallbackOnSimulationFailure: true,\n messenger,\n transactions: gasTransactions,\n });\n\n const { is7702 } = gasResult;\n const gasLimits = is7702\n ? [gasResult.gasLimits[0].max]\n : gasResult.gasLimits.map((gasLimit) => gasLimit.max);\n\n const estimate = calculateGasCost({\n chainId: chainIdHex,\n gas: gasResult.totalGasEstimate,\n maxFeePerGas: maxFeePerGas ?? '0',\n maxPriorityFeePerGas: maxPriorityFeePerGas ?? '0',\n messenger,\n });\n\n const max = calculateGasCost({\n chainId: chainIdHex,\n gas: gasResult.totalGasLimit,\n isMax: true,\n maxFeePerGas: maxFeePerGas ?? '0',\n maxPriorityFeePerGas: maxPriorityFeePerGas ?? '0',\n messenger,\n });\n\n const nativeBalance = getTokenBalance(\n messenger,\n from,\n sourceChainId,\n getNativeToken(sourceChainId),\n );\n\n const fees = { maxFeePerGas, maxPriorityFeePerGas };\n\n if (new BigNumber(nativeBalance).isGreaterThanOrEqualTo(max.raw)) {\n return { estimate, gasLimits, is7702, max, ...fees };\n }\n\n const eligibility = getGasStationEligibility(messenger, sourceChainId);\n\n if (eligibility.isDisabledChain || !eligibility.chainSupportsGasStation) {\n log('Skipping gas station for source network', {\n isDisabledChain: eligibility.isDisabledChain,\n sourceChainId,\n supportsGasStation: eligibility.chainSupportsGasStation,\n });\n return { estimate, gasLimits, is7702, max, ...fees };\n }\n\n log('Checking gas fee tokens due to insufficient native balance', {\n max: max.raw,\n nativeBalance,\n });\n\n const gasFeeTokenCost = await getGasStationCostInSourceTokenRaw({\n firstStepData: {\n data: firstStep.data,\n to: firstStep.to,\n value: firstStep.value as Hex,\n },\n messenger,\n request: {\n from,\n sourceChainId,\n sourceTokenAddress,\n },\n totalGasEstimate: gasResult.totalGasEstimate,\n totalItemCount: steps.length,\n });\n\n if (!gasFeeTokenCost) {\n return { estimate, gasLimits, is7702, max, ...fees };\n }\n\n log('Using gas fee token for source network', { gasFeeTokenCost });\n\n return {\n estimate: gasFeeTokenCost,\n gasLimits,\n is7702,\n isSourceGasFeeToken: true,\n max: gasFeeTokenCost,\n ...fees,\n };\n}\n\nfunction stepToGasTransaction(\n step: ServerQuoteStep,\n from: Hex,\n): QuoteGasTransaction {\n return {\n chainId: toHex(step.chainId),\n data: step.data,\n from,\n to: step.to,\n value: step.value,\n };\n}\n\nfunction getSingleTransactionData(\n transaction: TransactionMeta,\n): Hex | undefined {\n for (const nested of transaction.nestedTransactions ?? []) {\n if (nested.data && nested.data !== '0x') {\n return nested.data;\n }\n }\n\n return transaction.txParams?.data as Hex | undefined;\n}\n\nfunction isFulfilledResult(\n result: ServerQuoteResult,\n): result is FulfilledServerQuoteResult {\n return (\n result.quote?.id !== undefined &&\n result.quote.input !== undefined &&\n result.quote.output !== undefined\n );\n}\n\nfunction decodeTransferRecipient(data: Hex): Hex {\n return TRANSFER_INTERFACE.decodeFunctionData(\n 'transfer',\n data,\n ).to.toLowerCase() as Hex;\n}\n\nfunction buildTransferData(recipient: Hex, amountRaw: string): Hex {\n return TRANSFER_INTERFACE.encodeFunctionData('transfer', [\n recipient,\n amountRaw,\n ]) as Hex;\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { PayStrategyGetQuotesRequest, TransactionPayQuote } from "../../types.cjs";
|
|
2
|
+
import type { ServerQuote } from "./types.cjs";
|
|
3
|
+
/**
|
|
4
|
+
* Fetch server intents-api quotes and normalize them into Transaction Pay quotes.
|
|
5
|
+
*
|
|
6
|
+
* @param request - Quote request context.
|
|
7
|
+
* @returns Normalized server strategy quotes.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getServerQuotes(request: PayStrategyGetQuotesRequest): Promise<TransactionPayQuote<ServerQuote>[]>;
|
|
10
|
+
//# sourceMappingURL=server-quotes.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-quotes.d.cts","sourceRoot":"","sources":["../../../src/strategy/server/server-quotes.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,2BAA2B,EAI3B,mBAAmB,EACpB,wBAAoB;AAqBrB,OAAO,KAAK,EACV,WAAW,EAIZ,oBAAgB;AA0BjB;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,WAAW,CAAC,EAAE,CAAC,CAY7C"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { PayStrategyGetQuotesRequest, TransactionPayQuote } from "../../types.mjs";
|
|
2
|
+
import type { ServerQuote } from "./types.mjs";
|
|
3
|
+
/**
|
|
4
|
+
* Fetch server intents-api quotes and normalize them into Transaction Pay quotes.
|
|
5
|
+
*
|
|
6
|
+
* @param request - Quote request context.
|
|
7
|
+
* @returns Normalized server strategy quotes.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getServerQuotes(request: PayStrategyGetQuotesRequest): Promise<TransactionPayQuote<ServerQuote>[]>;
|
|
10
|
+
//# sourceMappingURL=server-quotes.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-quotes.d.mts","sourceRoot":"","sources":["../../../src/strategy/server/server-quotes.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,2BAA2B,EAI3B,mBAAmB,EACpB,wBAAoB;AAqBrB,OAAO,KAAK,EACV,WAAW,EAIZ,oBAAgB;AA0BjB;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,WAAW,CAAC,EAAE,CAAC,CAY7C"}
|