@metamask-previews/transaction-pay-controller 24.0.3-preview-2fd14c0c3 → 24.0.3-preview-10d0bd75c

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.
Files changed (34) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/strategy/server/perps.cjs +18 -1
  3. package/dist/strategy/server/perps.cjs.map +1 -1
  4. package/dist/strategy/server/perps.d.cts +5 -1
  5. package/dist/strategy/server/perps.d.cts.map +1 -1
  6. package/dist/strategy/server/perps.d.mts +5 -1
  7. package/dist/strategy/server/perps.d.mts.map +1 -1
  8. package/dist/strategy/server/perps.mjs +18 -1
  9. package/dist/strategy/server/perps.mjs.map +1 -1
  10. package/dist/strategy/server/server-quotes.cjs +68 -19
  11. package/dist/strategy/server/server-quotes.cjs.map +1 -1
  12. package/dist/strategy/server/server-quotes.d.cts.map +1 -1
  13. package/dist/strategy/server/server-quotes.d.mts.map +1 -1
  14. package/dist/strategy/server/server-quotes.mjs +69 -20
  15. package/dist/strategy/server/server-quotes.mjs.map +1 -1
  16. package/dist/strategy/server/server-submit.cjs +389 -61
  17. package/dist/strategy/server/server-submit.cjs.map +1 -1
  18. package/dist/strategy/server/server-submit.d.cts.map +1 -1
  19. package/dist/strategy/server/server-submit.d.mts.map +1 -1
  20. package/dist/strategy/server/server-submit.mjs +390 -62
  21. package/dist/strategy/server/server-submit.mjs.map +1 -1
  22. package/dist/strategy/server/types.cjs.map +1 -1
  23. package/dist/strategy/server/types.d.cts +20 -4
  24. package/dist/strategy/server/types.d.cts.map +1 -1
  25. package/dist/strategy/server/types.d.mts +20 -4
  26. package/dist/strategy/server/types.d.mts.map +1 -1
  27. package/dist/strategy/server/types.mjs.map +1 -1
  28. package/dist/utils/transaction.cjs +4 -1
  29. package/dist/utils/transaction.cjs.map +1 -1
  30. package/dist/utils/transaction.d.cts.map +1 -1
  31. package/dist/utils/transaction.d.mts.map +1 -1
  32. package/dist/utils/transaction.mjs +4 -1
  33. package/dist/utils/transaction.mjs.map +1 -1
  34. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -7,6 +7,16 @@ 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
+ ### Changed
16
+
17
+ - Bump `@metamask/assets-controller` from `^10.2.1` to `^11.0.0` ([#9485](https://github.com/MetaMask/core/pull/9485))
18
+ - Bump `@metamask/ramps-controller` from `^16.0.0` to `^17.0.0` ([#9491](https://github.com/MetaMask/core/pull/9491))
19
+
10
20
  ## [24.0.3]
11
21
 
12
22
  ### Changed
@@ -42,11 +42,18 @@ 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
+ *
45
49
  * @param request - Quote request from the transaction-pay controller.
46
50
  * @param transaction - Parent transaction whose calldata is inspected.
47
- * @returns Normalized request, or the original request if not a perps deposit.
51
+ * @returns Normalized request, or the original request if not a perps flow.
48
52
  */
49
53
  function normalizeServerPerpsRequest(request, transaction) {
54
+ if (request.isHyperliquidSource) {
55
+ return normalizePerpsWithdrawRequest(request);
56
+ }
50
57
  if (!isServerPerpsDepositRequest(request, transaction)) {
51
58
  return request;
52
59
  }
@@ -60,6 +67,16 @@ function normalizeServerPerpsRequest(request, transaction) {
60
67
  };
61
68
  }
62
69
  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
+ }
63
80
  function transactionDataReferencesBridge(transaction) {
64
81
  const fragments = [
65
82
  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;;;;;;;;;;;;;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"]}
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;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAgB,2BAA2B,CACzC,OAAqB,EACrB,WAAqE;IAErE,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;QAChC,OAAO,6BAA6B,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC;IAED,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;AApBD,kEAoBC;AAED,SAAS,6BAA6B,CAAC,OAAqB;IAC1D,OAAO;QACL,GAAG,OAAO;QACV,aAAa,EAAE,8BAAkB;QACjC,kBAAkB,EAAE,2CAAmC;QACvD,iBAAiB,EAAE,IAAI,wBAAS,CAAC,OAAO,CAAC,iBAAiB,CAAC;aACxD,SAAS,CAAC,yBAAa,GAAG,mCAAuB,CAAC;aAClD,OAAO,CAAC,CAAC,CAAC;KACd,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 * Also handles the perps-withdraw direction: when `request.isHyperliquidSource`\n * is set the source is rewritten to the HyperCore sentinel and the amount is\n * shifted from 8 to 6 decimals.\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 flow.\n */\nexport function normalizeServerPerpsRequest(\n request: QuoteRequest,\n transaction: Pick<TransactionMeta, 'txParams' | 'nestedTransactions'>,\n): QuoteRequest {\n if (request.isHyperliquidSource) {\n return normalizePerpsWithdrawRequest(request);\n }\n\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 normalizePerpsWithdrawRequest(request: QuoteRequest): QuoteRequest {\n return {\n ...request,\n sourceChainId: CHAIN_ID_HYPERCORE,\n sourceTokenAddress: SERVER_HYPERCORE_USDC_PERPS_ADDRESS,\n sourceTokenAmount: new BigNumber(request.sourceTokenAmount)\n .shiftedBy(USDC_DECIMALS - HYPERCORE_USDC_DECIMALS)\n .toFixed(0),\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,9 +28,13 @@ 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
+ *
31
35
  * @param request - Quote request from the transaction-pay controller.
32
36
  * @param transaction - Parent transaction whose calldata is inspected.
33
- * @returns Normalized request, or the original request if not a perps deposit.
37
+ * @returns Normalized request, or the original request if not a perps flow.
34
38
  */
35
39
  export declare function normalizeServerPerpsRequest(request: QuoteRequest, transaction: Pick<TransactionMeta, 'txParams' | 'nestedTransactions'>): QuoteRequest;
36
40
  //# 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;;;;;;;;;;;;;GAaG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,oBAAoB,CAAC,GACpE,YAAY,CAad"}
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;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,oBAAoB,CAAC,GACpE,YAAY,CAiBd"}
@@ -28,9 +28,13 @@ 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
+ *
31
35
  * @param request - Quote request from the transaction-pay controller.
32
36
  * @param transaction - Parent transaction whose calldata is inspected.
33
- * @returns Normalized request, or the original request if not a perps deposit.
37
+ * @returns Normalized request, or the original request if not a perps flow.
34
38
  */
35
39
  export declare function normalizeServerPerpsRequest(request: QuoteRequest, transaction: Pick<TransactionMeta, 'txParams' | 'nestedTransactions'>): QuoteRequest;
36
40
  //# 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;;;;;;;;;;;;;GAaG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,oBAAoB,CAAC,GACpE,YAAY,CAad"}
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;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,oBAAoB,CAAC,GACpE,YAAY,CAiBd"}
@@ -38,11 +38,18 @@ 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
+ *
41
45
  * @param request - Quote request from the transaction-pay controller.
42
46
  * @param transaction - Parent transaction whose calldata is inspected.
43
- * @returns Normalized request, or the original request if not a perps deposit.
47
+ * @returns Normalized request, or the original request if not a perps flow.
44
48
  */
45
49
  export function normalizeServerPerpsRequest(request, transaction) {
50
+ if (request.isHyperliquidSource) {
51
+ return normalizePerpsWithdrawRequest(request);
52
+ }
46
53
  if (!isServerPerpsDepositRequest(request, transaction)) {
47
54
  return request;
48
55
  }
@@ -55,6 +62,16 @@ export function normalizeServerPerpsRequest(request, transaction) {
55
62
  targetTokenAddress: SERVER_HYPERCORE_USDC_PERPS_ADDRESS,
56
63
  };
57
64
  }
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
+ }
58
75
  function transactionDataReferencesBridge(transaction) {
59
76
  const fragments = [
60
77
  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;;;;;;;;;;;;;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"]}
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;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,2BAA2B,CACzC,OAAqB,EACrB,WAAqE;IAErE,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;QAChC,OAAO,6BAA6B,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC;IAED,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,6BAA6B,CAAC,OAAqB;IAC1D,OAAO;QACL,GAAG,OAAO;QACV,aAAa,EAAE,kBAAkB;QACjC,kBAAkB,EAAE,mCAAmC;QACvD,iBAAiB,EAAE,IAAI,SAAS,CAAC,OAAO,CAAC,iBAAiB,CAAC;aACxD,SAAS,CAAC,aAAa,GAAG,uBAAuB,CAAC;aAClD,OAAO,CAAC,CAAC,CAAC;KACd,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 * Also handles the perps-withdraw direction: when `request.isHyperliquidSource`\n * is set the source is rewritten to the HyperCore sentinel and the amount is\n * shifted from 8 to 6 decimals.\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 flow.\n */\nexport function normalizeServerPerpsRequest(\n request: QuoteRequest,\n transaction: Pick<TransactionMeta, 'txParams' | 'nestedTransactions'>,\n): QuoteRequest {\n if (request.isHyperliquidSource) {\n return normalizePerpsWithdrawRequest(request);\n }\n\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 normalizePerpsWithdrawRequest(request: QuoteRequest): QuoteRequest {\n return {\n ...request,\n sourceChainId: CHAIN_ID_HYPERCORE,\n sourceTokenAddress: SERVER_HYPERCORE_USDC_PERPS_ADDRESS,\n sourceTokenAmount: new BigNumber(request.sourceTokenAmount)\n .shiftedBy(USDC_DECIMALS - HYPERCORE_USDC_DECIMALS)\n .toFixed(0),\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,6 +23,9 @@ 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
+ }
26
29
  /**
27
30
  * Fetch server intents-api quotes and normalize them into Transaction Pay quotes.
28
31
  *
@@ -55,8 +58,10 @@ async function getQuotesForRequest(quoteRequest, fullRequest) {
55
58
  }
56
59
  async function buildServerQuoteRequest(quoteRequest, transaction, messenger, accountSupports7702) {
57
60
  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);
61
+ const { from, isMaxAmount, isPostQuote, paymentOverride, sourceChainId, sourceTokenAddress, sourceTokenAmount, targetAmountMinimum, targetChainId, targetTokenAddress, } = normalizedRequest;
62
+ const useExactInput = (isMaxAmount ?? false) ||
63
+ (isPostQuote ?? false) ||
64
+ Boolean(normalizedRequest.isHyperliquidSource);
60
65
  const singleData = getSingleTransactionData(transaction);
61
66
  const isHypercore = targetChainId === constants_1.CHAIN_ID_HYPERCORE;
62
67
  const isTokenTransfer = !isHypercore && Boolean(singleData?.startsWith(TOKEN_TRANSFER_FOUR_BYTE));
@@ -64,7 +69,10 @@ async function buildServerQuoteRequest(quoteRequest, transaction, messenger, acc
64
69
  if (isTokenTransfer && singleData) {
65
70
  recipient = decodeTransferRecipient(singleData);
66
71
  }
67
- const supportsGasless = accountSupports7702 && (0, feature_flags_1.isEIP7702Chain)(messenger, sourceChainId);
72
+ const isHypercoreSource = sourceChainId === constants_1.CHAIN_ID_HYPERCORE;
73
+ const supportsGasless = !isHypercoreSource &&
74
+ accountSupports7702 &&
75
+ (0, feature_flags_1.isEIP7702Chain)(messenger, sourceChainId);
68
76
  const body = {
69
77
  source: { chainId: Number(sourceChainId), token: sourceTokenAddress },
70
78
  target: { chainId: Number(targetChainId), token: targetTokenAddress },
@@ -81,9 +89,13 @@ async function buildServerQuoteRequest(quoteRequest, transaction, messenger, acc
81
89
  const skipDelegation = hasNoData ||
82
90
  isTokenTransfer ||
83
91
  isHypercore ||
92
+ isHypercoreSource ||
84
93
  (isPostQuote ?? false) ||
85
94
  (isMaxAmount ?? false);
86
- if (!skipDelegation) {
95
+ if (isPostQuote && paymentOverride === constants_1.PaymentOverride.MoneyAccount) {
96
+ await processMoneyAccountPostQuote(transaction, normalizedRequest, body, messenger);
97
+ }
98
+ else if (!skipDelegation) {
87
99
  const delegation = await messenger.call('TransactionPayController:getDelegationTransaction', { transaction });
88
100
  body.calls = [
89
101
  {
@@ -98,31 +110,72 @@ async function buildServerQuoteRequest(quoteRequest, transaction, messenger, acc
98
110
  },
99
111
  ];
100
112
  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
- }));
113
+ body.authorizationList = normalizeAuthorizationList(delegation.authorizationList);
109
114
  }
110
115
  }
111
116
  return body;
112
117
  }
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
+ }
113
163
  function shouldRequestQuote(quoteRequest) {
114
164
  return (quoteRequest.targetAmountMinimum !== '0' ||
115
165
  Boolean(quoteRequest.isPostQuote) ||
116
- Boolean(quoteRequest.isMaxAmount));
166
+ Boolean(quoteRequest.isMaxAmount) ||
167
+ Boolean(quoteRequest.isHyperliquidSource));
117
168
  }
118
169
  async function normalizeQuote(result, quoteRequest, messenger) {
119
170
  const { quote } = result;
120
171
  const { gasless } = quote;
172
+ const transactionSteps = quote.steps.filter(isTransactionStep);
173
+ const isSignatureOnly = transactionSteps.length === 0;
121
174
  const sourceNetwork = await calculateSourceNetworkCost({
122
- gasless,
175
+ gasless: gasless || isSignatureOnly,
123
176
  messenger,
124
177
  quoteRequest,
125
- steps: quote.steps,
178
+ steps: transactionSteps,
126
179
  });
127
180
  const sourceFiatRate = (0, token_1.getTokenFiatRate)(messenger, quoteRequest.sourceTokenAddress, quoteRequest.sourceChainId);
128
181
  const usdToFiatRate = sourceFiatRate
@@ -196,10 +249,6 @@ async function calculateSourceNetworkCost({ gasless, messenger, quoteRequest, st
196
249
  log('Zeroing source network fees for gasless quote');
197
250
  return noFees;
198
251
  }
199
- if (steps.length === 0) {
200
- log('No quote steps; zeroing source network fees');
201
- return noFees;
202
- }
203
252
  const { from, sourceChainId, sourceTokenAddress } = quoteRequest;
204
253
  const firstStep = steps[0];
205
254
  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 { 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
+ {"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 +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"}
1
+ {"version":3,"file":"server-quotes.d.cts","sourceRoot":"","sources":["../../../src/strategy/server/server-quotes.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EACV,2BAA2B,EAI3B,mBAAmB,EACpB,wBAAoB;AAqBrB,OAAO,KAAK,EACV,WAAW,EAIZ,oBAAgB;AAgCjB;;;;;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":"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
+ {"version":3,"file":"server-quotes.d.mts","sourceRoot":"","sources":["../../../src/strategy/server/server-quotes.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EACV,2BAA2B,EAI3B,mBAAmB,EACpB,wBAAoB;AAqBrB,OAAO,KAAK,EACV,WAAW,EAIZ,oBAAgB;AAgCjB;;;;;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, TransactionPayStrategy } from "../../constants.mjs";
5
+ import { CHAIN_ID_HYPERCORE, PaymentOverride, 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,6 +20,9 @@ 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
+ }
23
26
  /**
24
27
  * Fetch server intents-api quotes and normalize them into Transaction Pay quotes.
25
28
  *
@@ -51,8 +54,10 @@ async function getQuotesForRequest(quoteRequest, fullRequest) {
51
54
  }
52
55
  async function buildServerQuoteRequest(quoteRequest, transaction, messenger, accountSupports7702) {
53
56
  const normalizedRequest = normalizeServerPerpsRequest(quoteRequest, transaction);
54
- const { from, isMaxAmount, isPostQuote, sourceChainId, sourceTokenAddress, sourceTokenAmount, targetAmountMinimum, targetChainId, targetTokenAddress, } = normalizedRequest;
55
- const useExactInput = (isMaxAmount ?? false) || (isPostQuote ?? false);
57
+ const { from, isMaxAmount, isPostQuote, paymentOverride, sourceChainId, sourceTokenAddress, sourceTokenAmount, targetAmountMinimum, targetChainId, targetTokenAddress, } = normalizedRequest;
58
+ const useExactInput = (isMaxAmount ?? false) ||
59
+ (isPostQuote ?? false) ||
60
+ Boolean(normalizedRequest.isHyperliquidSource);
56
61
  const singleData = getSingleTransactionData(transaction);
57
62
  const isHypercore = targetChainId === CHAIN_ID_HYPERCORE;
58
63
  const isTokenTransfer = !isHypercore && Boolean(singleData?.startsWith(TOKEN_TRANSFER_FOUR_BYTE));
@@ -60,7 +65,10 @@ async function buildServerQuoteRequest(quoteRequest, transaction, messenger, acc
60
65
  if (isTokenTransfer && singleData) {
61
66
  recipient = decodeTransferRecipient(singleData);
62
67
  }
63
- const supportsGasless = accountSupports7702 && isEIP7702Chain(messenger, sourceChainId);
68
+ const isHypercoreSource = sourceChainId === CHAIN_ID_HYPERCORE;
69
+ const supportsGasless = !isHypercoreSource &&
70
+ accountSupports7702 &&
71
+ isEIP7702Chain(messenger, sourceChainId);
64
72
  const body = {
65
73
  source: { chainId: Number(sourceChainId), token: sourceTokenAddress },
66
74
  target: { chainId: Number(targetChainId), token: targetTokenAddress },
@@ -77,9 +85,13 @@ async function buildServerQuoteRequest(quoteRequest, transaction, messenger, acc
77
85
  const skipDelegation = hasNoData ||
78
86
  isTokenTransfer ||
79
87
  isHypercore ||
88
+ isHypercoreSource ||
80
89
  (isPostQuote ?? false) ||
81
90
  (isMaxAmount ?? false);
82
- if (!skipDelegation) {
91
+ if (isPostQuote && paymentOverride === PaymentOverride.MoneyAccount) {
92
+ await processMoneyAccountPostQuote(transaction, normalizedRequest, body, messenger);
93
+ }
94
+ else if (!skipDelegation) {
83
95
  const delegation = await messenger.call('TransactionPayController:getDelegationTransaction', { transaction });
84
96
  body.calls = [
85
97
  {
@@ -94,31 +106,72 @@ async function buildServerQuoteRequest(quoteRequest, transaction, messenger, acc
94
106
  },
95
107
  ];
96
108
  if (delegation.authorizationList?.length) {
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
- }));
109
+ body.authorizationList = normalizeAuthorizationList(delegation.authorizationList);
105
110
  }
106
111
  }
107
112
  return body;
108
113
  }
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
+ }
109
159
  function shouldRequestQuote(quoteRequest) {
110
160
  return (quoteRequest.targetAmountMinimum !== '0' ||
111
161
  Boolean(quoteRequest.isPostQuote) ||
112
- Boolean(quoteRequest.isMaxAmount));
162
+ Boolean(quoteRequest.isMaxAmount) ||
163
+ Boolean(quoteRequest.isHyperliquidSource));
113
164
  }
114
165
  async function normalizeQuote(result, quoteRequest, messenger) {
115
166
  const { quote } = result;
116
167
  const { gasless } = quote;
168
+ const transactionSteps = quote.steps.filter(isTransactionStep);
169
+ const isSignatureOnly = transactionSteps.length === 0;
117
170
  const sourceNetwork = await calculateSourceNetworkCost({
118
- gasless,
171
+ gasless: gasless || isSignatureOnly,
119
172
  messenger,
120
173
  quoteRequest,
121
- steps: quote.steps,
174
+ steps: transactionSteps,
122
175
  });
123
176
  const sourceFiatRate = getTokenFiatRate(messenger, quoteRequest.sourceTokenAddress, quoteRequest.sourceChainId);
124
177
  const usdToFiatRate = sourceFiatRate
@@ -192,10 +245,6 @@ async function calculateSourceNetworkCost({ gasless, messenger, quoteRequest, st
192
245
  log('Zeroing source network fees for gasless quote');
193
246
  return noFees;
194
247
  }
195
- if (steps.length === 0) {
196
- log('No quote steps; zeroing source network fees');
197
- return noFees;
198
- }
199
248
  const { from, sourceChainId, sourceTokenAddress } = quoteRequest;
200
249
  const firstStep = steps[0];
201
250
  const chainIdHex = toHex(firstStep.chainId);