@metamask-previews/transaction-pay-controller 24.0.3-preview-10d0bd75c → 24.0.3-preview-42cce76ad
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +0 -5
- package/dist/strategy/server/perps.cjs +1 -18
- package/dist/strategy/server/perps.cjs.map +1 -1
- package/dist/strategy/server/perps.d.cts +1 -5
- package/dist/strategy/server/perps.d.cts.map +1 -1
- package/dist/strategy/server/perps.d.mts +1 -5
- package/dist/strategy/server/perps.d.mts.map +1 -1
- package/dist/strategy/server/perps.mjs +1 -18
- package/dist/strategy/server/perps.mjs.map +1 -1
- package/dist/strategy/server/server-quotes.cjs +19 -68
- package/dist/strategy/server/server-quotes.cjs.map +1 -1
- package/dist/strategy/server/server-quotes.d.cts.map +1 -1
- package/dist/strategy/server/server-quotes.d.mts.map +1 -1
- package/dist/strategy/server/server-quotes.mjs +20 -69
- package/dist/strategy/server/server-quotes.mjs.map +1 -1
- package/dist/strategy/server/server-submit.cjs +61 -389
- package/dist/strategy/server/server-submit.cjs.map +1 -1
- package/dist/strategy/server/server-submit.d.cts.map +1 -1
- package/dist/strategy/server/server-submit.d.mts.map +1 -1
- package/dist/strategy/server/server-submit.mjs +62 -390
- package/dist/strategy/server/server-submit.mjs.map +1 -1
- package/dist/strategy/server/types.cjs.map +1 -1
- package/dist/strategy/server/types.d.cts +4 -20
- package/dist/strategy/server/types.d.cts.map +1 -1
- package/dist/strategy/server/types.d.mts +4 -20
- package/dist/strategy/server/types.d.mts.map +1 -1
- package/dist/strategy/server/types.mjs.map +1 -1
- package/dist/utils/transaction.cjs +1 -4
- package/dist/utils/transaction.cjs.map +1 -1
- package/dist/utils/transaction.d.cts.map +1 -1
- package/dist/utils/transaction.d.mts.map +1 -1
- package/dist/utils/transaction.mjs +1 -4
- package/dist/utils/transaction.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,11 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
-
### Added
|
|
11
|
-
|
|
12
|
-
- Add generic signature steps to the server pay strategy, supporting EIP-712 sign-then-POST flows ([#9051](https://github.com/MetaMask/core/pull/9051))
|
|
13
|
-
- Trigger quote refresh when `txParams.to` or `requiredAssets` changes on a transaction, in addition to the existing `txParams.data` trigger
|
|
14
|
-
|
|
15
10
|
### Changed
|
|
16
11
|
|
|
17
12
|
- Bump `@metamask/assets-controller` from `^10.2.1` to `^11.0.0` ([#9485](https://github.com/MetaMask/core/pull/9485))
|
|
@@ -42,18 +42,11 @@ exports.isServerPerpsDepositRequest = isServerPerpsDepositRequest;
|
|
|
42
42
|
* 6 decimals); HyperCore expects an 8-decimal amount, so the target amount is
|
|
43
43
|
* shifted accordingly.
|
|
44
44
|
*
|
|
45
|
-
* Also handles the perps-withdraw direction: when `request.isHyperliquidSource`
|
|
46
|
-
* is set the source is rewritten to the HyperCore sentinel and the amount is
|
|
47
|
-
* shifted from 8 to 6 decimals.
|
|
48
|
-
*
|
|
49
45
|
* @param request - Quote request from the transaction-pay controller.
|
|
50
46
|
* @param transaction - Parent transaction whose calldata is inspected.
|
|
51
|
-
* @returns Normalized request, or the original request if not a perps
|
|
47
|
+
* @returns Normalized request, or the original request if not a perps deposit.
|
|
52
48
|
*/
|
|
53
49
|
function normalizeServerPerpsRequest(request, transaction) {
|
|
54
|
-
if (request.isHyperliquidSource) {
|
|
55
|
-
return normalizePerpsWithdrawRequest(request);
|
|
56
|
-
}
|
|
57
50
|
if (!isServerPerpsDepositRequest(request, transaction)) {
|
|
58
51
|
return request;
|
|
59
52
|
}
|
|
@@ -67,16 +60,6 @@ function normalizeServerPerpsRequest(request, transaction) {
|
|
|
67
60
|
};
|
|
68
61
|
}
|
|
69
62
|
exports.normalizeServerPerpsRequest = normalizeServerPerpsRequest;
|
|
70
|
-
function normalizePerpsWithdrawRequest(request) {
|
|
71
|
-
return {
|
|
72
|
-
...request,
|
|
73
|
-
sourceChainId: constants_1.CHAIN_ID_HYPERCORE,
|
|
74
|
-
sourceTokenAddress: exports.SERVER_HYPERCORE_USDC_PERPS_ADDRESS,
|
|
75
|
-
sourceTokenAmount: new bignumber_js_1.BigNumber(request.sourceTokenAmount)
|
|
76
|
-
.shiftedBy(constants_1.USDC_DECIMALS - constants_1.HYPERCORE_USDC_DECIMALS)
|
|
77
|
-
.toFixed(0),
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
63
|
function transactionDataReferencesBridge(transaction) {
|
|
81
64
|
const fragments = [
|
|
82
65
|
transaction.txParams?.to,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"perps.cjs","sourceRoot":"","sources":["../../../src/strategy/server/perps.ts"],"names":[],"mappings":";;;AAEA,+CAAyC;AAEzC,mDAMyB;AAGzB;;;;;GAKG;AACU,QAAA,mCAAmC,GAC9C,4CAAmD,CAAC;AAEtD,MAAM,gCAAgC,GACpC,4CAA4C,CAAC;AAE/C,MAAM,oCAAoC,GACxC,gCAAgC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAE5C;;;;;;;;;GASG;AACH,SAAgB,2BAA2B,CACzC,OAGC,EACD,WAAqE;IAErE,IACE,OAAO,CAAC,WAAW,KAAK,IAAI;QAC5B,OAAO,CAAC,aAAa,KAAK,6BAAiB;QAC3C,OAAO,CAAC,kBAAkB,CAAC,WAAW,EAAE;YACtC,iCAAqB,CAAC,WAAW,EAAE,EACrC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,+BAA+B,CAAC,WAAW,CAAC,CAAC;AACtD,CAAC;AAjBD,kEAiBC;AAED
|
|
1
|
+
{"version":3,"file":"perps.cjs","sourceRoot":"","sources":["../../../src/strategy/server/perps.ts"],"names":[],"mappings":";;;AAEA,+CAAyC;AAEzC,mDAMyB;AAGzB;;;;;GAKG;AACU,QAAA,mCAAmC,GAC9C,4CAAmD,CAAC;AAEtD,MAAM,gCAAgC,GACpC,4CAA4C,CAAC;AAE/C,MAAM,oCAAoC,GACxC,gCAAgC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAE5C;;;;;;;;;GASG;AACH,SAAgB,2BAA2B,CACzC,OAGC,EACD,WAAqE;IAErE,IACE,OAAO,CAAC,WAAW,KAAK,IAAI;QAC5B,OAAO,CAAC,aAAa,KAAK,6BAAiB;QAC3C,OAAO,CAAC,kBAAkB,CAAC,WAAW,EAAE;YACtC,iCAAqB,CAAC,WAAW,EAAE,EACrC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,+BAA+B,CAAC,WAAW,CAAC,CAAC;AACtD,CAAC;AAjBD,kEAiBC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAgB,2BAA2B,CACzC,OAAqB,EACrB,WAAqE;IAErE,IAAI,CAAC,2BAA2B,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC;QACvD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO;QACL,GAAG,OAAO;QACV,mBAAmB,EAAE,IAAI,wBAAS,CAAC,OAAO,CAAC,mBAAmB,CAAC;aAC5D,SAAS,CAAC,mCAAuB,GAAG,yBAAa,CAAC;aAClD,OAAO,CAAC,CAAC,CAAC;QACb,aAAa,EAAE,8BAAkB;QACjC,kBAAkB,EAAE,2CAAmC;KACxD,CAAC;AACJ,CAAC;AAhBD,kEAgBC;AAED,SAAS,+BAA+B,CACtC,WAAqE;IAErE,MAAM,SAAS,GAA2B;QACxC,WAAW,CAAC,QAAQ,EAAE,EAAE;QACxB,GAAG,CAAC,WAAW,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;KAC7D,CAAC;IAEF,OAAO,SAAS,CAAC,IAAI,CACnB,CAAC,KAAK,EAAE,EAAE,CACR,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC,CACrE,CAAC;AACJ,CAAC","sourcesContent":["import type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport {\n ARBITRUM_USDC_ADDRESS,\n CHAIN_ID_ARBITRUM,\n CHAIN_ID_HYPERCORE,\n HYPERCORE_USDC_DECIMALS,\n USDC_DECIMALS,\n} from '../../constants';\nimport type { QuoteRequest } from '../../types';\n\n/**\n * Shared 20-byte sentinel address emitted by the server strategy to flag a\n * Hyperliquid perps deposit. Backend providers translate this to their own\n * on-chain destination (e.g. Relay's 16-byte HyperCore USDC sentinel, Across's\n * native USDC-PERPS token at the same address).\n */\nexport const SERVER_HYPERCORE_USDC_PERPS_ADDRESS =\n '0x2100000000000000000000000000000000000000' as Hex;\n\nconst HYPERLIQUID_BRIDGE_ADDRESS_LOWER =\n '0x2df1c51e09aecf9cacb7bc98cb1742757f163df7';\n\nconst HYPERLIQUID_BRIDGE_CALLDATA_FRAGMENT =\n HYPERLIQUID_BRIDGE_ADDRESS_LOWER.slice(2);\n\n/**\n * Detect whether a quote request represents a Hyperliquid perps deposit by\n * sniffing the parent transaction calldata for a reference to the Hyperliquid\n * bridge contract. Transaction type is intentionally NOT consulted so that any\n * caller funnelling a bridge deposit through Pay is supported.\n *\n * @param request - Quote request from the transaction-pay controller.\n * @param transaction - Parent transaction whose calldata is inspected.\n * @returns Whether the request matches a Hyperliquid bridge deposit.\n */\nexport function isServerPerpsDepositRequest(\n request: Pick<\n QuoteRequest,\n 'isPostQuote' | 'targetChainId' | 'targetTokenAddress'\n >,\n transaction: Pick<TransactionMeta, 'txParams' | 'nestedTransactions'>,\n): boolean {\n if (\n request.isPostQuote === true ||\n request.targetChainId !== CHAIN_ID_ARBITRUM ||\n request.targetTokenAddress.toLowerCase() !==\n ARBITRUM_USDC_ADDRESS.toLowerCase()\n ) {\n return false;\n }\n\n return transactionDataReferencesBridge(transaction);\n}\n\n/**\n * Translate a Hyperliquid perps-deposit quote request into the HyperCore\n * direct-deposit shape with a provider-agnostic sentinel destination. Backend\n * providers detect the sentinel and rewrite it to their respective on-chain\n * destinations.\n *\n * Transaction pay starts from the parent on-chain asset (Arbitrum USDC,\n * 6 decimals); HyperCore expects an 8-decimal amount, so the target amount is\n * shifted accordingly.\n *\n * @param request - Quote request from the transaction-pay controller.\n * @param transaction - Parent transaction whose calldata is inspected.\n * @returns Normalized request, or the original request if not a perps deposit.\n */\nexport function normalizeServerPerpsRequest(\n request: QuoteRequest,\n transaction: Pick<TransactionMeta, 'txParams' | 'nestedTransactions'>,\n): QuoteRequest {\n if (!isServerPerpsDepositRequest(request, transaction)) {\n return request;\n }\n\n return {\n ...request,\n targetAmountMinimum: new BigNumber(request.targetAmountMinimum)\n .shiftedBy(HYPERCORE_USDC_DECIMALS - USDC_DECIMALS)\n .toFixed(0),\n targetChainId: CHAIN_ID_HYPERCORE,\n targetTokenAddress: SERVER_HYPERCORE_USDC_PERPS_ADDRESS,\n };\n}\n\nfunction transactionDataReferencesBridge(\n transaction: Pick<TransactionMeta, 'txParams' | 'nestedTransactions'>,\n): boolean {\n const fragments: (string | undefined)[] = [\n transaction.txParams?.to,\n ...(transaction.nestedTransactions ?? []).map((tx) => tx.to),\n ];\n\n return fragments.some(\n (value) =>\n typeof value === 'string' &&\n value.toLowerCase().includes(HYPERLIQUID_BRIDGE_CALLDATA_FRAGMENT),\n );\n}\n"]}
|
|
@@ -28,13 +28,9 @@ export declare function isServerPerpsDepositRequest(request: Pick<QuoteRequest,
|
|
|
28
28
|
* 6 decimals); HyperCore expects an 8-decimal amount, so the target amount is
|
|
29
29
|
* shifted accordingly.
|
|
30
30
|
*
|
|
31
|
-
* Also handles the perps-withdraw direction: when `request.isHyperliquidSource`
|
|
32
|
-
* is set the source is rewritten to the HyperCore sentinel and the amount is
|
|
33
|
-
* shifted from 8 to 6 decimals.
|
|
34
|
-
*
|
|
35
31
|
* @param request - Quote request from the transaction-pay controller.
|
|
36
32
|
* @param transaction - Parent transaction whose calldata is inspected.
|
|
37
|
-
* @returns Normalized request, or the original request if not a perps
|
|
33
|
+
* @returns Normalized request, or the original request if not a perps deposit.
|
|
38
34
|
*/
|
|
39
35
|
export declare function normalizeServerPerpsRequest(request: QuoteRequest, transaction: Pick<TransactionMeta, 'txParams' | 'nestedTransactions'>): QuoteRequest;
|
|
40
36
|
//# sourceMappingURL=perps.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"perps.d.cts","sourceRoot":"","sources":["../../../src/strategy/server/perps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,yCAAyC;AAWxE,OAAO,KAAK,EAAE,YAAY,EAAE,wBAAoB;AAEhD;;;;;GAKG;AACH,eAAO,MAAM,mCAAmC,eACK,CAAC;AAQtD;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,IAAI,CACX,YAAY,EACZ,aAAa,GAAG,eAAe,GAAG,oBAAoB,CACvD,EACD,WAAW,EAAE,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,oBAAoB,CAAC,GACpE,OAAO,CAWT;AAED
|
|
1
|
+
{"version":3,"file":"perps.d.cts","sourceRoot":"","sources":["../../../src/strategy/server/perps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,yCAAyC;AAWxE,OAAO,KAAK,EAAE,YAAY,EAAE,wBAAoB;AAEhD;;;;;GAKG;AACH,eAAO,MAAM,mCAAmC,eACK,CAAC;AAQtD;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,IAAI,CACX,YAAY,EACZ,aAAa,GAAG,eAAe,GAAG,oBAAoB,CACvD,EACD,WAAW,EAAE,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,oBAAoB,CAAC,GACpE,OAAO,CAWT;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,oBAAoB,CAAC,GACpE,YAAY,CAad"}
|
|
@@ -28,13 +28,9 @@ export declare function isServerPerpsDepositRequest(request: Pick<QuoteRequest,
|
|
|
28
28
|
* 6 decimals); HyperCore expects an 8-decimal amount, so the target amount is
|
|
29
29
|
* shifted accordingly.
|
|
30
30
|
*
|
|
31
|
-
* Also handles the perps-withdraw direction: when `request.isHyperliquidSource`
|
|
32
|
-
* is set the source is rewritten to the HyperCore sentinel and the amount is
|
|
33
|
-
* shifted from 8 to 6 decimals.
|
|
34
|
-
*
|
|
35
31
|
* @param request - Quote request from the transaction-pay controller.
|
|
36
32
|
* @param transaction - Parent transaction whose calldata is inspected.
|
|
37
|
-
* @returns Normalized request, or the original request if not a perps
|
|
33
|
+
* @returns Normalized request, or the original request if not a perps deposit.
|
|
38
34
|
*/
|
|
39
35
|
export declare function normalizeServerPerpsRequest(request: QuoteRequest, transaction: Pick<TransactionMeta, 'txParams' | 'nestedTransactions'>): QuoteRequest;
|
|
40
36
|
//# sourceMappingURL=perps.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"perps.d.mts","sourceRoot":"","sources":["../../../src/strategy/server/perps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,yCAAyC;AAWxE,OAAO,KAAK,EAAE,YAAY,EAAE,wBAAoB;AAEhD;;;;;GAKG;AACH,eAAO,MAAM,mCAAmC,eACK,CAAC;AAQtD;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,IAAI,CACX,YAAY,EACZ,aAAa,GAAG,eAAe,GAAG,oBAAoB,CACvD,EACD,WAAW,EAAE,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,oBAAoB,CAAC,GACpE,OAAO,CAWT;AAED
|
|
1
|
+
{"version":3,"file":"perps.d.mts","sourceRoot":"","sources":["../../../src/strategy/server/perps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,yCAAyC;AAWxE,OAAO,KAAK,EAAE,YAAY,EAAE,wBAAoB;AAEhD;;;;;GAKG;AACH,eAAO,MAAM,mCAAmC,eACK,CAAC;AAQtD;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,IAAI,CACX,YAAY,EACZ,aAAa,GAAG,eAAe,GAAG,oBAAoB,CACvD,EACD,WAAW,EAAE,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,oBAAoB,CAAC,GACpE,OAAO,CAWT;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,oBAAoB,CAAC,GACpE,YAAY,CAad"}
|
|
@@ -38,18 +38,11 @@ export function isServerPerpsDepositRequest(request, transaction) {
|
|
|
38
38
|
* 6 decimals); HyperCore expects an 8-decimal amount, so the target amount is
|
|
39
39
|
* shifted accordingly.
|
|
40
40
|
*
|
|
41
|
-
* Also handles the perps-withdraw direction: when `request.isHyperliquidSource`
|
|
42
|
-
* is set the source is rewritten to the HyperCore sentinel and the amount is
|
|
43
|
-
* shifted from 8 to 6 decimals.
|
|
44
|
-
*
|
|
45
41
|
* @param request - Quote request from the transaction-pay controller.
|
|
46
42
|
* @param transaction - Parent transaction whose calldata is inspected.
|
|
47
|
-
* @returns Normalized request, or the original request if not a perps
|
|
43
|
+
* @returns Normalized request, or the original request if not a perps deposit.
|
|
48
44
|
*/
|
|
49
45
|
export function normalizeServerPerpsRequest(request, transaction) {
|
|
50
|
-
if (request.isHyperliquidSource) {
|
|
51
|
-
return normalizePerpsWithdrawRequest(request);
|
|
52
|
-
}
|
|
53
46
|
if (!isServerPerpsDepositRequest(request, transaction)) {
|
|
54
47
|
return request;
|
|
55
48
|
}
|
|
@@ -62,16 +55,6 @@ export function normalizeServerPerpsRequest(request, transaction) {
|
|
|
62
55
|
targetTokenAddress: SERVER_HYPERCORE_USDC_PERPS_ADDRESS,
|
|
63
56
|
};
|
|
64
57
|
}
|
|
65
|
-
function normalizePerpsWithdrawRequest(request) {
|
|
66
|
-
return {
|
|
67
|
-
...request,
|
|
68
|
-
sourceChainId: CHAIN_ID_HYPERCORE,
|
|
69
|
-
sourceTokenAddress: SERVER_HYPERCORE_USDC_PERPS_ADDRESS,
|
|
70
|
-
sourceTokenAmount: new BigNumber(request.sourceTokenAmount)
|
|
71
|
-
.shiftedBy(USDC_DECIMALS - HYPERCORE_USDC_DECIMALS)
|
|
72
|
-
.toFixed(0),
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
58
|
function transactionDataReferencesBridge(transaction) {
|
|
76
59
|
const fragments = [
|
|
77
60
|
transaction.txParams?.to,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"perps.mjs","sourceRoot":"","sources":["../../../src/strategy/server/perps.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,qBAAqB;AAEzC,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,EACvB,aAAa,EACd,4BAAwB;AAGzB;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAC9C,4CAAmD,CAAC;AAEtD,MAAM,gCAAgC,GACpC,4CAA4C,CAAC;AAE/C,MAAM,oCAAoC,GACxC,gCAAgC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAE5C;;;;;;;;;GASG;AACH,MAAM,UAAU,2BAA2B,CACzC,OAGC,EACD,WAAqE;IAErE,IACE,OAAO,CAAC,WAAW,KAAK,IAAI;QAC5B,OAAO,CAAC,aAAa,KAAK,iBAAiB;QAC3C,OAAO,CAAC,kBAAkB,CAAC,WAAW,EAAE;YACtC,qBAAqB,CAAC,WAAW,EAAE,EACrC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,+BAA+B,CAAC,WAAW,CAAC,CAAC;AACtD,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"perps.mjs","sourceRoot":"","sources":["../../../src/strategy/server/perps.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,qBAAqB;AAEzC,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,EACvB,aAAa,EACd,4BAAwB;AAGzB;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAC9C,4CAAmD,CAAC;AAEtD,MAAM,gCAAgC,GACpC,4CAA4C,CAAC;AAE/C,MAAM,oCAAoC,GACxC,gCAAgC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAE5C;;;;;;;;;GASG;AACH,MAAM,UAAU,2BAA2B,CACzC,OAGC,EACD,WAAqE;IAErE,IACE,OAAO,CAAC,WAAW,KAAK,IAAI;QAC5B,OAAO,CAAC,aAAa,KAAK,iBAAiB;QAC3C,OAAO,CAAC,kBAAkB,CAAC,WAAW,EAAE;YACtC,qBAAqB,CAAC,WAAW,EAAE,EACrC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,+BAA+B,CAAC,WAAW,CAAC,CAAC;AACtD,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,2BAA2B,CACzC,OAAqB,EACrB,WAAqE;IAErE,IAAI,CAAC,2BAA2B,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC;QACvD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO;QACL,GAAG,OAAO;QACV,mBAAmB,EAAE,IAAI,SAAS,CAAC,OAAO,CAAC,mBAAmB,CAAC;aAC5D,SAAS,CAAC,uBAAuB,GAAG,aAAa,CAAC;aAClD,OAAO,CAAC,CAAC,CAAC;QACb,aAAa,EAAE,kBAAkB;QACjC,kBAAkB,EAAE,mCAAmC;KACxD,CAAC;AACJ,CAAC;AAED,SAAS,+BAA+B,CACtC,WAAqE;IAErE,MAAM,SAAS,GAA2B;QACxC,WAAW,CAAC,QAAQ,EAAE,EAAE;QACxB,GAAG,CAAC,WAAW,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;KAC7D,CAAC;IAEF,OAAO,SAAS,CAAC,IAAI,CACnB,CAAC,KAAK,EAAE,EAAE,CACR,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC,CACrE,CAAC;AACJ,CAAC","sourcesContent":["import type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport {\n ARBITRUM_USDC_ADDRESS,\n CHAIN_ID_ARBITRUM,\n CHAIN_ID_HYPERCORE,\n HYPERCORE_USDC_DECIMALS,\n USDC_DECIMALS,\n} from '../../constants';\nimport type { QuoteRequest } from '../../types';\n\n/**\n * Shared 20-byte sentinel address emitted by the server strategy to flag a\n * Hyperliquid perps deposit. Backend providers translate this to their own\n * on-chain destination (e.g. Relay's 16-byte HyperCore USDC sentinel, Across's\n * native USDC-PERPS token at the same address).\n */\nexport const SERVER_HYPERCORE_USDC_PERPS_ADDRESS =\n '0x2100000000000000000000000000000000000000' as Hex;\n\nconst HYPERLIQUID_BRIDGE_ADDRESS_LOWER =\n '0x2df1c51e09aecf9cacb7bc98cb1742757f163df7';\n\nconst HYPERLIQUID_BRIDGE_CALLDATA_FRAGMENT =\n HYPERLIQUID_BRIDGE_ADDRESS_LOWER.slice(2);\n\n/**\n * Detect whether a quote request represents a Hyperliquid perps deposit by\n * sniffing the parent transaction calldata for a reference to the Hyperliquid\n * bridge contract. Transaction type is intentionally NOT consulted so that any\n * caller funnelling a bridge deposit through Pay is supported.\n *\n * @param request - Quote request from the transaction-pay controller.\n * @param transaction - Parent transaction whose calldata is inspected.\n * @returns Whether the request matches a Hyperliquid bridge deposit.\n */\nexport function isServerPerpsDepositRequest(\n request: Pick<\n QuoteRequest,\n 'isPostQuote' | 'targetChainId' | 'targetTokenAddress'\n >,\n transaction: Pick<TransactionMeta, 'txParams' | 'nestedTransactions'>,\n): boolean {\n if (\n request.isPostQuote === true ||\n request.targetChainId !== CHAIN_ID_ARBITRUM ||\n request.targetTokenAddress.toLowerCase() !==\n ARBITRUM_USDC_ADDRESS.toLowerCase()\n ) {\n return false;\n }\n\n return transactionDataReferencesBridge(transaction);\n}\n\n/**\n * Translate a Hyperliquid perps-deposit quote request into the HyperCore\n * direct-deposit shape with a provider-agnostic sentinel destination. Backend\n * providers detect the sentinel and rewrite it to their respective on-chain\n * destinations.\n *\n * Transaction pay starts from the parent on-chain asset (Arbitrum USDC,\n * 6 decimals); HyperCore expects an 8-decimal amount, so the target amount is\n * shifted accordingly.\n *\n * @param request - Quote request from the transaction-pay controller.\n * @param transaction - Parent transaction whose calldata is inspected.\n * @returns Normalized request, or the original request if not a perps deposit.\n */\nexport function normalizeServerPerpsRequest(\n request: QuoteRequest,\n transaction: Pick<TransactionMeta, 'txParams' | 'nestedTransactions'>,\n): QuoteRequest {\n if (!isServerPerpsDepositRequest(request, transaction)) {\n return request;\n }\n\n return {\n ...request,\n targetAmountMinimum: new BigNumber(request.targetAmountMinimum)\n .shiftedBy(HYPERCORE_USDC_DECIMALS - USDC_DECIMALS)\n .toFixed(0),\n targetChainId: CHAIN_ID_HYPERCORE,\n targetTokenAddress: SERVER_HYPERCORE_USDC_PERPS_ADDRESS,\n };\n}\n\nfunction transactionDataReferencesBridge(\n transaction: Pick<TransactionMeta, 'txParams' | 'nestedTransactions'>,\n): boolean {\n const fragments: (string | undefined)[] = [\n transaction.txParams?.to,\n ...(transaction.nestedTransactions ?? []).map((tx) => tx.to),\n ];\n\n return fragments.some(\n (value) =>\n typeof value === 'string' &&\n value.toLowerCase().includes(HYPERLIQUID_BRIDGE_CALLDATA_FRAGMENT),\n );\n}\n"]}
|
|
@@ -23,9 +23,6 @@ const TRANSFER_INTERFACE = new abi_1.Interface([
|
|
|
23
23
|
]);
|
|
24
24
|
const ZERO_AMOUNT = { fiat: '0', human: '0', raw: '0', usd: '0' };
|
|
25
25
|
const ZERO_FIAT_VALUE = { fiat: '0', usd: '0' };
|
|
26
|
-
function isTransactionStep(step) {
|
|
27
|
-
return step.type === 'transaction';
|
|
28
|
-
}
|
|
29
26
|
/**
|
|
30
27
|
* Fetch server intents-api quotes and normalize them into Transaction Pay quotes.
|
|
31
28
|
*
|
|
@@ -58,10 +55,8 @@ async function getQuotesForRequest(quoteRequest, fullRequest) {
|
|
|
58
55
|
}
|
|
59
56
|
async function buildServerQuoteRequest(quoteRequest, transaction, messenger, accountSupports7702) {
|
|
60
57
|
const normalizedRequest = (0, perps_1.normalizeServerPerpsRequest)(quoteRequest, transaction);
|
|
61
|
-
const { from, isMaxAmount, isPostQuote,
|
|
62
|
-
const useExactInput = (isMaxAmount ?? false) ||
|
|
63
|
-
(isPostQuote ?? false) ||
|
|
64
|
-
Boolean(normalizedRequest.isHyperliquidSource);
|
|
58
|
+
const { from, isMaxAmount, isPostQuote, sourceChainId, sourceTokenAddress, sourceTokenAmount, targetAmountMinimum, targetChainId, targetTokenAddress, } = normalizedRequest;
|
|
59
|
+
const useExactInput = (isMaxAmount ?? false) || (isPostQuote ?? false);
|
|
65
60
|
const singleData = getSingleTransactionData(transaction);
|
|
66
61
|
const isHypercore = targetChainId === constants_1.CHAIN_ID_HYPERCORE;
|
|
67
62
|
const isTokenTransfer = !isHypercore && Boolean(singleData?.startsWith(TOKEN_TRANSFER_FOUR_BYTE));
|
|
@@ -69,10 +64,7 @@ async function buildServerQuoteRequest(quoteRequest, transaction, messenger, acc
|
|
|
69
64
|
if (isTokenTransfer && singleData) {
|
|
70
65
|
recipient = decodeTransferRecipient(singleData);
|
|
71
66
|
}
|
|
72
|
-
const
|
|
73
|
-
const supportsGasless = !isHypercoreSource &&
|
|
74
|
-
accountSupports7702 &&
|
|
75
|
-
(0, feature_flags_1.isEIP7702Chain)(messenger, sourceChainId);
|
|
67
|
+
const supportsGasless = accountSupports7702 && (0, feature_flags_1.isEIP7702Chain)(messenger, sourceChainId);
|
|
76
68
|
const body = {
|
|
77
69
|
source: { chainId: Number(sourceChainId), token: sourceTokenAddress },
|
|
78
70
|
target: { chainId: Number(targetChainId), token: targetTokenAddress },
|
|
@@ -89,13 +81,9 @@ async function buildServerQuoteRequest(quoteRequest, transaction, messenger, acc
|
|
|
89
81
|
const skipDelegation = hasNoData ||
|
|
90
82
|
isTokenTransfer ||
|
|
91
83
|
isHypercore ||
|
|
92
|
-
isHypercoreSource ||
|
|
93
84
|
(isPostQuote ?? false) ||
|
|
94
85
|
(isMaxAmount ?? false);
|
|
95
|
-
if (
|
|
96
|
-
await processMoneyAccountPostQuote(transaction, normalizedRequest, body, messenger);
|
|
97
|
-
}
|
|
98
|
-
else if (!skipDelegation) {
|
|
86
|
+
if (!skipDelegation) {
|
|
99
87
|
const delegation = await messenger.call('TransactionPayController:getDelegationTransaction', { transaction });
|
|
100
88
|
body.calls = [
|
|
101
89
|
{
|
|
@@ -110,72 +98,31 @@ async function buildServerQuoteRequest(quoteRequest, transaction, messenger, acc
|
|
|
110
98
|
},
|
|
111
99
|
];
|
|
112
100
|
if (delegation.authorizationList?.length) {
|
|
113
|
-
body.authorizationList =
|
|
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
|
+
}));
|
|
114
109
|
}
|
|
115
110
|
}
|
|
116
111
|
return body;
|
|
117
112
|
}
|
|
118
|
-
function normalizeAuthorizationList(authorizationList) {
|
|
119
|
-
return authorizationList.map((entry) => ({
|
|
120
|
-
address: entry.address,
|
|
121
|
-
chainId: Number(entry.chainId),
|
|
122
|
-
nonce: Number(entry.nonce),
|
|
123
|
-
r: entry.r,
|
|
124
|
-
s: entry.s,
|
|
125
|
-
yParity: Number(entry.yParity),
|
|
126
|
-
}));
|
|
127
|
-
}
|
|
128
|
-
async function processMoneyAccountPostQuote(transaction, request, body, messenger) {
|
|
129
|
-
const { transactionData: transactionDataList } = messenger.call('TransactionPayController:getState');
|
|
130
|
-
const transactionData = transactionDataList[transaction.id];
|
|
131
|
-
const amountHuman = transactionData?.tokens?.[0]?.amountHuman ?? '0';
|
|
132
|
-
const { calls: overrideCalls, recipient, authorizationList, } = await messenger.call('TransactionPayController:getPaymentOverrideData', {
|
|
133
|
-
amount: amountHuman,
|
|
134
|
-
transaction,
|
|
135
|
-
transactionData,
|
|
136
|
-
});
|
|
137
|
-
if (!overrideCalls.length) {
|
|
138
|
-
log('No payment override calls for money account post-quote');
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
const fundingRecipient = recipient ?? request.from;
|
|
142
|
-
body.tradeType = types_1.ServerTradeType.ExactInput;
|
|
143
|
-
body.amount = request.sourceTokenAmount;
|
|
144
|
-
body.calls = [
|
|
145
|
-
{
|
|
146
|
-
data: buildTransferData(fundingRecipient, request.sourceTokenAmount),
|
|
147
|
-
to: request.targetTokenAddress,
|
|
148
|
-
value: '0x0',
|
|
149
|
-
},
|
|
150
|
-
...overrideCalls.map((call) => ({
|
|
151
|
-
data: call.data,
|
|
152
|
-
to: call.to,
|
|
153
|
-
value: call.value ?? '0x0',
|
|
154
|
-
})),
|
|
155
|
-
];
|
|
156
|
-
if (authorizationList?.length) {
|
|
157
|
-
body.authorizationList = normalizeAuthorizationList(authorizationList);
|
|
158
|
-
}
|
|
159
|
-
log('Added money account post-quote calls to server quote body', {
|
|
160
|
-
callCount: overrideCalls.length,
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
113
|
function shouldRequestQuote(quoteRequest) {
|
|
164
114
|
return (quoteRequest.targetAmountMinimum !== '0' ||
|
|
165
115
|
Boolean(quoteRequest.isPostQuote) ||
|
|
166
|
-
Boolean(quoteRequest.isMaxAmount)
|
|
167
|
-
Boolean(quoteRequest.isHyperliquidSource));
|
|
116
|
+
Boolean(quoteRequest.isMaxAmount));
|
|
168
117
|
}
|
|
169
118
|
async function normalizeQuote(result, quoteRequest, messenger) {
|
|
170
119
|
const { quote } = result;
|
|
171
120
|
const { gasless } = quote;
|
|
172
|
-
const transactionSteps = quote.steps.filter(isTransactionStep);
|
|
173
|
-
const isSignatureOnly = transactionSteps.length === 0;
|
|
174
121
|
const sourceNetwork = await calculateSourceNetworkCost({
|
|
175
|
-
gasless
|
|
122
|
+
gasless,
|
|
176
123
|
messenger,
|
|
177
124
|
quoteRequest,
|
|
178
|
-
steps:
|
|
125
|
+
steps: quote.steps,
|
|
179
126
|
});
|
|
180
127
|
const sourceFiatRate = (0, token_1.getTokenFiatRate)(messenger, quoteRequest.sourceTokenAddress, quoteRequest.sourceChainId);
|
|
181
128
|
const usdToFiatRate = sourceFiatRate
|
|
@@ -249,6 +196,10 @@ async function calculateSourceNetworkCost({ gasless, messenger, quoteRequest, st
|
|
|
249
196
|
log('Zeroing source network fees for gasless quote');
|
|
250
197
|
return noFees;
|
|
251
198
|
}
|
|
199
|
+
if (steps.length === 0) {
|
|
200
|
+
log('No quote steps; zeroing source network fees');
|
|
201
|
+
return noFees;
|
|
202
|
+
}
|
|
252
203
|
const { from, sourceChainId, sourceTokenAddress } = quoteRequest;
|
|
253
204
|
const firstStep = steps[0];
|
|
254
205
|
const chainIdHex = (0, controller_utils_1.toHex)(firstStep.chainId);
|
|
@@ -1 +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 {\n AuthorizationList,\n TransactionMeta,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport {\n CHAIN_ID_HYPERCORE,\n PaymentOverride,\n TransactionPayStrategy,\n} 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 ServerTransactionStep,\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\nfunction isTransactionStep(\n step: ServerQuote['steps'][number],\n): step is ServerTransactionStep {\n return step.type === 'transaction';\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 paymentOverride,\n sourceChainId,\n sourceTokenAddress,\n sourceTokenAmount,\n targetAmountMinimum,\n targetChainId,\n targetTokenAddress,\n } = normalizedRequest;\n\n const useExactInput =\n (isMaxAmount ?? false) ||\n (isPostQuote ?? false) ||\n Boolean(normalizedRequest.isHyperliquidSource);\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 isHypercoreSource = sourceChainId === CHAIN_ID_HYPERCORE;\n const supportsGasless =\n !isHypercoreSource &&\n accountSupports7702 &&\n 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 isHypercoreSource ||\n (isPostQuote ?? false) ||\n (isMaxAmount ?? false);\n\n if (isPostQuote && paymentOverride === PaymentOverride.MoneyAccount) {\n await processMoneyAccountPostQuote(\n transaction,\n normalizedRequest,\n body,\n messenger,\n );\n } else 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 = normalizeAuthorizationList(\n delegation.authorizationList,\n );\n }\n }\n\n return body;\n}\n\nfunction normalizeAuthorizationList(\n authorizationList: AuthorizationList,\n): NonNullable<ServerQuoteRequest['authorizationList']> {\n return 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\nasync function processMoneyAccountPostQuote(\n transaction: TransactionMeta,\n request: QuoteRequest,\n body: ServerQuoteRequest,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const { transactionData: transactionDataList } = messenger.call(\n 'TransactionPayController:getState',\n );\n\n const transactionData = transactionDataList[transaction.id];\n const amountHuman = transactionData?.tokens?.[0]?.amountHuman ?? '0';\n\n const {\n calls: overrideCalls,\n recipient,\n authorizationList,\n } = await messenger.call('TransactionPayController:getPaymentOverrideData', {\n amount: amountHuman,\n transaction,\n transactionData,\n });\n\n if (!overrideCalls.length) {\n log('No payment override calls for money account post-quote');\n return;\n }\n\n const fundingRecipient = recipient ?? request.from;\n\n body.tradeType = ServerTradeType.ExactInput;\n body.amount = request.sourceTokenAmount;\n\n body.calls = [\n {\n data: buildTransferData(fundingRecipient, request.sourceTokenAmount),\n to: request.targetTokenAddress,\n value: '0x0',\n },\n ...overrideCalls.map((call) => ({\n data: call.data as Hex,\n to: call.to as Hex,\n value: call.value ?? '0x0',\n })),\n ];\n\n if (authorizationList?.length) {\n body.authorizationList = normalizeAuthorizationList(authorizationList);\n }\n\n log('Added money account post-quote calls to server quote body', {\n callCount: overrideCalls.length,\n });\n}\n\nfunction shouldRequestQuote(quoteRequest: QuoteRequest): boolean {\n return (\n quoteRequest.targetAmountMinimum !== '0' ||\n Boolean(quoteRequest.isPostQuote) ||\n Boolean(quoteRequest.isMaxAmount) ||\n Boolean(quoteRequest.isHyperliquidSource)\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 transactionSteps = quote.steps.filter(isTransactionStep);\n const isSignatureOnly = transactionSteps.length === 0;\n const sourceNetwork = await calculateSourceNetworkCost({\n gasless: gasless || isSignatureOnly,\n messenger,\n quoteRequest,\n steps: transactionSteps,\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: ServerTransactionStep[];\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 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: ServerTransactionStep,\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"]}
|
|
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"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-quotes.d.cts","sourceRoot":"","sources":["../../../src/strategy/server/server-quotes.ts"],"names":[],"mappings":"
|
|
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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-quotes.d.mts","sourceRoot":"","sources":["../../../src/strategy/server/server-quotes.ts"],"names":[],"mappings":"
|
|
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"}
|
|
@@ -2,7 +2,7 @@ import { Interface } from "@ethersproject/abi";
|
|
|
2
2
|
import { toHex } from "@metamask/controller-utils";
|
|
3
3
|
import { createModuleLogger } from "@metamask/utils";
|
|
4
4
|
import { BigNumber } from "bignumber.js";
|
|
5
|
-
import { CHAIN_ID_HYPERCORE,
|
|
5
|
+
import { CHAIN_ID_HYPERCORE, TransactionPayStrategy } from "../../constants.mjs";
|
|
6
6
|
import { projectLogger } from "../../logger.mjs";
|
|
7
7
|
import { getFiatValueFromUsd } from "../../utils/amounts.mjs";
|
|
8
8
|
import { getFeatureFlags, getSlippage, isEIP7702Chain } from "../../utils/feature-flags.mjs";
|
|
@@ -20,9 +20,6 @@ const TRANSFER_INTERFACE = new Interface([
|
|
|
20
20
|
]);
|
|
21
21
|
const ZERO_AMOUNT = { fiat: '0', human: '0', raw: '0', usd: '0' };
|
|
22
22
|
const ZERO_FIAT_VALUE = { fiat: '0', usd: '0' };
|
|
23
|
-
function isTransactionStep(step) {
|
|
24
|
-
return step.type === 'transaction';
|
|
25
|
-
}
|
|
26
23
|
/**
|
|
27
24
|
* Fetch server intents-api quotes and normalize them into Transaction Pay quotes.
|
|
28
25
|
*
|
|
@@ -54,10 +51,8 @@ async function getQuotesForRequest(quoteRequest, fullRequest) {
|
|
|
54
51
|
}
|
|
55
52
|
async function buildServerQuoteRequest(quoteRequest, transaction, messenger, accountSupports7702) {
|
|
56
53
|
const normalizedRequest = normalizeServerPerpsRequest(quoteRequest, transaction);
|
|
57
|
-
const { from, isMaxAmount, isPostQuote,
|
|
58
|
-
const useExactInput = (isMaxAmount ?? false) ||
|
|
59
|
-
(isPostQuote ?? false) ||
|
|
60
|
-
Boolean(normalizedRequest.isHyperliquidSource);
|
|
54
|
+
const { from, isMaxAmount, isPostQuote, sourceChainId, sourceTokenAddress, sourceTokenAmount, targetAmountMinimum, targetChainId, targetTokenAddress, } = normalizedRequest;
|
|
55
|
+
const useExactInput = (isMaxAmount ?? false) || (isPostQuote ?? false);
|
|
61
56
|
const singleData = getSingleTransactionData(transaction);
|
|
62
57
|
const isHypercore = targetChainId === CHAIN_ID_HYPERCORE;
|
|
63
58
|
const isTokenTransfer = !isHypercore && Boolean(singleData?.startsWith(TOKEN_TRANSFER_FOUR_BYTE));
|
|
@@ -65,10 +60,7 @@ async function buildServerQuoteRequest(quoteRequest, transaction, messenger, acc
|
|
|
65
60
|
if (isTokenTransfer && singleData) {
|
|
66
61
|
recipient = decodeTransferRecipient(singleData);
|
|
67
62
|
}
|
|
68
|
-
const
|
|
69
|
-
const supportsGasless = !isHypercoreSource &&
|
|
70
|
-
accountSupports7702 &&
|
|
71
|
-
isEIP7702Chain(messenger, sourceChainId);
|
|
63
|
+
const supportsGasless = accountSupports7702 && isEIP7702Chain(messenger, sourceChainId);
|
|
72
64
|
const body = {
|
|
73
65
|
source: { chainId: Number(sourceChainId), token: sourceTokenAddress },
|
|
74
66
|
target: { chainId: Number(targetChainId), token: targetTokenAddress },
|
|
@@ -85,13 +77,9 @@ async function buildServerQuoteRequest(quoteRequest, transaction, messenger, acc
|
|
|
85
77
|
const skipDelegation = hasNoData ||
|
|
86
78
|
isTokenTransfer ||
|
|
87
79
|
isHypercore ||
|
|
88
|
-
isHypercoreSource ||
|
|
89
80
|
(isPostQuote ?? false) ||
|
|
90
81
|
(isMaxAmount ?? false);
|
|
91
|
-
if (
|
|
92
|
-
await processMoneyAccountPostQuote(transaction, normalizedRequest, body, messenger);
|
|
93
|
-
}
|
|
94
|
-
else if (!skipDelegation) {
|
|
82
|
+
if (!skipDelegation) {
|
|
95
83
|
const delegation = await messenger.call('TransactionPayController:getDelegationTransaction', { transaction });
|
|
96
84
|
body.calls = [
|
|
97
85
|
{
|
|
@@ -106,72 +94,31 @@ async function buildServerQuoteRequest(quoteRequest, transaction, messenger, acc
|
|
|
106
94
|
},
|
|
107
95
|
];
|
|
108
96
|
if (delegation.authorizationList?.length) {
|
|
109
|
-
body.authorizationList =
|
|
97
|
+
body.authorizationList = delegation.authorizationList.map((entry) => ({
|
|
98
|
+
address: entry.address,
|
|
99
|
+
chainId: Number(entry.chainId),
|
|
100
|
+
nonce: Number(entry.nonce),
|
|
101
|
+
r: entry.r,
|
|
102
|
+
s: entry.s,
|
|
103
|
+
yParity: Number(entry.yParity),
|
|
104
|
+
}));
|
|
110
105
|
}
|
|
111
106
|
}
|
|
112
107
|
return body;
|
|
113
108
|
}
|
|
114
|
-
function normalizeAuthorizationList(authorizationList) {
|
|
115
|
-
return authorizationList.map((entry) => ({
|
|
116
|
-
address: entry.address,
|
|
117
|
-
chainId: Number(entry.chainId),
|
|
118
|
-
nonce: Number(entry.nonce),
|
|
119
|
-
r: entry.r,
|
|
120
|
-
s: entry.s,
|
|
121
|
-
yParity: Number(entry.yParity),
|
|
122
|
-
}));
|
|
123
|
-
}
|
|
124
|
-
async function processMoneyAccountPostQuote(transaction, request, body, messenger) {
|
|
125
|
-
const { transactionData: transactionDataList } = messenger.call('TransactionPayController:getState');
|
|
126
|
-
const transactionData = transactionDataList[transaction.id];
|
|
127
|
-
const amountHuman = transactionData?.tokens?.[0]?.amountHuman ?? '0';
|
|
128
|
-
const { calls: overrideCalls, recipient, authorizationList, } = await messenger.call('TransactionPayController:getPaymentOverrideData', {
|
|
129
|
-
amount: amountHuman,
|
|
130
|
-
transaction,
|
|
131
|
-
transactionData,
|
|
132
|
-
});
|
|
133
|
-
if (!overrideCalls.length) {
|
|
134
|
-
log('No payment override calls for money account post-quote');
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
const fundingRecipient = recipient ?? request.from;
|
|
138
|
-
body.tradeType = ServerTradeType.ExactInput;
|
|
139
|
-
body.amount = request.sourceTokenAmount;
|
|
140
|
-
body.calls = [
|
|
141
|
-
{
|
|
142
|
-
data: buildTransferData(fundingRecipient, request.sourceTokenAmount),
|
|
143
|
-
to: request.targetTokenAddress,
|
|
144
|
-
value: '0x0',
|
|
145
|
-
},
|
|
146
|
-
...overrideCalls.map((call) => ({
|
|
147
|
-
data: call.data,
|
|
148
|
-
to: call.to,
|
|
149
|
-
value: call.value ?? '0x0',
|
|
150
|
-
})),
|
|
151
|
-
];
|
|
152
|
-
if (authorizationList?.length) {
|
|
153
|
-
body.authorizationList = normalizeAuthorizationList(authorizationList);
|
|
154
|
-
}
|
|
155
|
-
log('Added money account post-quote calls to server quote body', {
|
|
156
|
-
callCount: overrideCalls.length,
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
109
|
function shouldRequestQuote(quoteRequest) {
|
|
160
110
|
return (quoteRequest.targetAmountMinimum !== '0' ||
|
|
161
111
|
Boolean(quoteRequest.isPostQuote) ||
|
|
162
|
-
Boolean(quoteRequest.isMaxAmount)
|
|
163
|
-
Boolean(quoteRequest.isHyperliquidSource));
|
|
112
|
+
Boolean(quoteRequest.isMaxAmount));
|
|
164
113
|
}
|
|
165
114
|
async function normalizeQuote(result, quoteRequest, messenger) {
|
|
166
115
|
const { quote } = result;
|
|
167
116
|
const { gasless } = quote;
|
|
168
|
-
const transactionSteps = quote.steps.filter(isTransactionStep);
|
|
169
|
-
const isSignatureOnly = transactionSteps.length === 0;
|
|
170
117
|
const sourceNetwork = await calculateSourceNetworkCost({
|
|
171
|
-
gasless
|
|
118
|
+
gasless,
|
|
172
119
|
messenger,
|
|
173
120
|
quoteRequest,
|
|
174
|
-
steps:
|
|
121
|
+
steps: quote.steps,
|
|
175
122
|
});
|
|
176
123
|
const sourceFiatRate = getTokenFiatRate(messenger, quoteRequest.sourceTokenAddress, quoteRequest.sourceChainId);
|
|
177
124
|
const usdToFiatRate = sourceFiatRate
|
|
@@ -245,6 +192,10 @@ async function calculateSourceNetworkCost({ gasless, messenger, quoteRequest, st
|
|
|
245
192
|
log('Zeroing source network fees for gasless quote');
|
|
246
193
|
return noFees;
|
|
247
194
|
}
|
|
195
|
+
if (steps.length === 0) {
|
|
196
|
+
log('No quote steps; zeroing source network fees');
|
|
197
|
+
return noFees;
|
|
198
|
+
}
|
|
248
199
|
const { from, sourceChainId, sourceTokenAddress } = quoteRequest;
|
|
249
200
|
const firstStep = steps[0];
|
|
250
201
|
const chainIdHex = toHex(firstStep.chainId);
|