@metamask-previews/transaction-pay-controller 16.4.1-preview-e0ce55a8c → 16.5.0-preview-1f5463f7b

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 (66) hide show
  1. package/CHANGELOG.md +16 -5
  2. package/dist/strategy/relay/constants.cjs +1 -13
  3. package/dist/strategy/relay/constants.cjs.map +1 -1
  4. package/dist/strategy/relay/constants.d.cts +0 -3
  5. package/dist/strategy/relay/constants.d.cts.map +1 -1
  6. package/dist/strategy/relay/constants.d.mts +0 -3
  7. package/dist/strategy/relay/constants.d.mts.map +1 -1
  8. package/dist/strategy/relay/constants.mjs +0 -12
  9. package/dist/strategy/relay/constants.mjs.map +1 -1
  10. package/dist/strategy/relay/relay-quotes.cjs +106 -22
  11. package/dist/strategy/relay/relay-quotes.cjs.map +1 -1
  12. package/dist/strategy/relay/relay-quotes.d.cts.map +1 -1
  13. package/dist/strategy/relay/relay-quotes.d.mts.map +1 -1
  14. package/dist/strategy/relay/relay-quotes.mjs +106 -22
  15. package/dist/strategy/relay/relay-quotes.mjs.map +1 -1
  16. package/dist/strategy/relay/relay-submit.cjs +31 -32
  17. package/dist/strategy/relay/relay-submit.cjs.map +1 -1
  18. package/dist/strategy/relay/relay-submit.d.cts.map +1 -1
  19. package/dist/strategy/relay/relay-submit.d.mts.map +1 -1
  20. package/dist/strategy/relay/relay-submit.mjs +33 -34
  21. package/dist/strategy/relay/relay-submit.mjs.map +1 -1
  22. package/dist/strategy/relay/types.cjs.map +1 -1
  23. package/dist/strategy/relay/types.d.cts +1 -1
  24. package/dist/strategy/relay/types.d.cts.map +1 -1
  25. package/dist/strategy/relay/types.d.mts +1 -1
  26. package/dist/strategy/relay/types.d.mts.map +1 -1
  27. package/dist/strategy/relay/types.mjs.map +1 -1
  28. package/dist/tests/messenger-mock.cjs +3 -0
  29. package/dist/tests/messenger-mock.cjs.map +1 -1
  30. package/dist/tests/messenger-mock.d.cts +1 -0
  31. package/dist/tests/messenger-mock.d.cts.map +1 -1
  32. package/dist/tests/messenger-mock.d.mts +1 -0
  33. package/dist/tests/messenger-mock.d.mts.map +1 -1
  34. package/dist/tests/messenger-mock.mjs +3 -0
  35. package/dist/tests/messenger-mock.mjs.map +1 -1
  36. package/dist/types.cjs.map +1 -1
  37. package/dist/types.d.cts +2 -1
  38. package/dist/types.d.cts.map +1 -1
  39. package/dist/types.d.mts +2 -1
  40. package/dist/types.d.mts.map +1 -1
  41. package/dist/types.mjs.map +1 -1
  42. package/dist/utils/feature-flags.cjs +15 -25
  43. package/dist/utils/feature-flags.cjs.map +1 -1
  44. package/dist/utils/feature-flags.d.cts +7 -18
  45. package/dist/utils/feature-flags.d.cts.map +1 -1
  46. package/dist/utils/feature-flags.d.mts +7 -18
  47. package/dist/utils/feature-flags.d.mts.map +1 -1
  48. package/dist/utils/feature-flags.mjs +14 -23
  49. package/dist/utils/feature-flags.mjs.map +1 -1
  50. package/dist/utils/token.cjs +39 -40
  51. package/dist/utils/token.cjs.map +1 -1
  52. package/dist/utils/token.d.cts +0 -12
  53. package/dist/utils/token.d.cts.map +1 -1
  54. package/dist/utils/token.d.mts +0 -12
  55. package/dist/utils/token.d.mts.map +1 -1
  56. package/dist/utils/token.mjs +38 -39
  57. package/dist/utils/token.mjs.map +1 -1
  58. package/dist/utils/transaction.cjs +16 -1
  59. package/dist/utils/transaction.cjs.map +1 -1
  60. package/dist/utils/transaction.d.cts +10 -0
  61. package/dist/utils/transaction.d.cts.map +1 -1
  62. package/dist/utils/transaction.d.mts +10 -0
  63. package/dist/utils/transaction.d.mts.map +1 -1
  64. package/dist/utils/transaction.mjs +15 -1
  65. package/dist/utils/transaction.mjs.map +1 -1
  66. package/package.json +2 -1
package/CHANGELOG.md CHANGED
@@ -9,19 +9,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  ### Added
11
11
 
12
+ - **BREAKING:** Add `AssetsControllerGetStateForTransactionPayAction` to the `AllowedActions` messenger type ([#8163](https://github.com/MetaMask/core/pull/8163))
13
+
14
+ ### Changed
15
+
16
+ - `getTokenBalance`, `getTokenInfo`, and `getTokenFiatRate` now source token metadata, balances, and pricing from `AssetsControllerGetStateForTransactionPayAction` when the `assetsUnifyState` remote feature flag is enabled, falling back to individual controller state calls otherwise ([#8163](https://github.com/MetaMask/core/pull/8163))
17
+
18
+ ## [16.5.0]
19
+
20
+ ### Added
21
+
12
22
  - Support gasless Relay deposits via `execute` endpoint ([#8133](https://github.com/MetaMask/core/pull/8133))
13
23
  - Build Across post-swap transfer actions for `predictDeposit` quotes so Predict deposits can bridge swapped output into the destination proxy wallet ([#8159](https://github.com/MetaMask/core/pull/8159))
14
24
 
15
25
  ### Changed
16
26
 
17
- - Harden relay status polling ([#8189](https://github.com/MetaMask/core/pull/8189))
18
- - Throw if status not recognised.
19
- - Support feature flags for polling interval and timeout.
20
- - Ignore transient network errors.
21
27
  - Bump `@metamask/assets-controllers` from `^100.2.0` to `^100.2.1` ([#8162](https://github.com/MetaMask/core/pull/8162))
22
28
  - Bump `@metamask/bridge-controller` from `^69.0.0` to `^69.1.0` ([#8162](https://github.com/MetaMask/core/pull/8162), [#8168](https://github.com/MetaMask/core/pull/8168))
23
29
  - Bump `@metamask/bridge-status-controller` from `^68.0.1` to `^68.1.0` ([#8162](https://github.com/MetaMask/core/pull/8162), [#8168](https://github.com/MetaMask/core/pull/8168))
24
30
 
31
+ ### Fixed
32
+
33
+ - Support gasless withdraw for post-quote flows (e.g. Predict Withdraw) when transaction would provide sufficient token balance for gas fee token ([#8146](https://github.com/MetaMask/core/pull/8146))
34
+
25
35
  ## [16.4.1]
26
36
 
27
37
  ### Changed
@@ -508,7 +518,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
508
518
 
509
519
  - Initial release ([#6820](https://github.com/MetaMask/core/pull/6820))
510
520
 
511
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@16.4.1...HEAD
521
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@16.5.0...HEAD
522
+ [16.5.0]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@16.4.1...@metamask/transaction-pay-controller@16.5.0
512
523
  [16.4.1]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@16.4.0...@metamask/transaction-pay-controller@16.4.1
513
524
  [16.4.0]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@16.3.0...@metamask/transaction-pay-controller@16.4.0
514
525
  [16.3.0]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@16.2.0...@metamask/transaction-pay-controller@16.3.0
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RELAY_DEPOSIT_TYPES = exports.RELAY_PENDING_STATUSES = exports.RELAY_FAILURE_STATUSES = exports.TOKEN_TRANSFER_FOUR_BYTE = exports.RELAY_POLLING_INTERVAL = exports.RELAY_STATUS_URL = exports.RELAY_QUOTE_URL = exports.RELAY_EXECUTE_URL = exports.RELAY_URL_BASE = void 0;
3
+ exports.RELAY_DEPOSIT_TYPES = exports.TOKEN_TRANSFER_FOUR_BYTE = exports.RELAY_POLLING_INTERVAL = exports.RELAY_STATUS_URL = exports.RELAY_QUOTE_URL = exports.RELAY_EXECUTE_URL = exports.RELAY_URL_BASE = void 0;
4
4
  const transaction_controller_1 = require("@metamask/transaction-controller");
5
5
  exports.RELAY_URL_BASE = 'https://api.relay.link';
6
6
  exports.RELAY_EXECUTE_URL = `${exports.RELAY_URL_BASE}/execute`;
@@ -8,18 +8,6 @@ exports.RELAY_QUOTE_URL = `${exports.RELAY_URL_BASE}/quote`;
8
8
  exports.RELAY_STATUS_URL = `${exports.RELAY_URL_BASE}/intents/status/v3`;
9
9
  exports.RELAY_POLLING_INTERVAL = 1000; // 1 Second
10
10
  exports.TOKEN_TRANSFER_FOUR_BYTE = '0xa9059cbb';
11
- exports.RELAY_FAILURE_STATUSES = [
12
- 'failure',
13
- 'refund',
14
- 'refunded',
15
- ];
16
- exports.RELAY_PENDING_STATUSES = [
17
- 'delayed',
18
- 'depositing',
19
- 'pending',
20
- 'submitted',
21
- 'waiting',
22
- ];
23
11
  exports.RELAY_DEPOSIT_TYPES = {
24
12
  [transaction_controller_1.TransactionType.predictDeposit]: transaction_controller_1.TransactionType.predictRelayDeposit,
25
13
  [transaction_controller_1.TransactionType.perpsDeposit]: transaction_controller_1.TransactionType.perpsRelayDeposit,
@@ -1 +1 @@
1
- {"version":3,"file":"constants.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/constants.ts"],"names":[],"mappings":";;;AAAA,6EAAmE;AAItD,QAAA,cAAc,GAAG,wBAAwB,CAAC;AAC1C,QAAA,iBAAiB,GAAG,GAAG,sBAAc,UAAU,CAAC;AAChD,QAAA,eAAe,GAAG,GAAG,sBAAc,QAAQ,CAAC;AAC5C,QAAA,gBAAgB,GAAG,GAAG,sBAAc,oBAAoB,CAAC;AACzD,QAAA,sBAAsB,GAAG,IAAI,CAAC,CAAC,WAAW;AAC1C,QAAA,wBAAwB,GAAG,YAAY,CAAC;AAExC,QAAA,sBAAsB,GAAkB;IACnD,SAAS;IACT,QAAQ;IACR,UAAU;CACX,CAAC;AAEW,QAAA,sBAAsB,GAAkB;IACnD,SAAS;IACT,YAAY;IACZ,SAAS;IACT,WAAW;IACX,SAAS;CACV,CAAC;AAEW,QAAA,mBAAmB,GAAoC;IAClE,CAAC,wCAAe,CAAC,cAAc,CAAC,EAAE,wCAAe,CAAC,mBAAmB;IACrE,CAAC,wCAAe,CAAC,YAAY,CAAC,EAAE,wCAAe,CAAC,iBAAiB;CAClE,CAAC","sourcesContent":["import { TransactionType } from '@metamask/transaction-controller';\n\nimport type { RelayStatus } from './types';\n\nexport const RELAY_URL_BASE = 'https://api.relay.link';\nexport const RELAY_EXECUTE_URL = `${RELAY_URL_BASE}/execute`;\nexport const RELAY_QUOTE_URL = `${RELAY_URL_BASE}/quote`;\nexport const RELAY_STATUS_URL = `${RELAY_URL_BASE}/intents/status/v3`;\nexport const RELAY_POLLING_INTERVAL = 1000; // 1 Second\nexport const TOKEN_TRANSFER_FOUR_BYTE = '0xa9059cbb';\n\nexport const RELAY_FAILURE_STATUSES: RelayStatus[] = [\n 'failure',\n 'refund',\n 'refunded',\n];\n\nexport const RELAY_PENDING_STATUSES: RelayStatus[] = [\n 'delayed',\n 'depositing',\n 'pending',\n 'submitted',\n 'waiting',\n];\n\nexport const RELAY_DEPOSIT_TYPES: Record<string, TransactionType> = {\n [TransactionType.predictDeposit]: TransactionType.predictRelayDeposit,\n [TransactionType.perpsDeposit]: TransactionType.perpsRelayDeposit,\n};\n"]}
1
+ {"version":3,"file":"constants.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/constants.ts"],"names":[],"mappings":";;;AAAA,6EAAmE;AAEtD,QAAA,cAAc,GAAG,wBAAwB,CAAC;AAC1C,QAAA,iBAAiB,GAAG,GAAG,sBAAc,UAAU,CAAC;AAChD,QAAA,eAAe,GAAG,GAAG,sBAAc,QAAQ,CAAC;AAC5C,QAAA,gBAAgB,GAAG,GAAG,sBAAc,oBAAoB,CAAC;AACzD,QAAA,sBAAsB,GAAG,IAAI,CAAC,CAAC,WAAW;AAC1C,QAAA,wBAAwB,GAAG,YAAY,CAAC;AAExC,QAAA,mBAAmB,GAAoC;IAClE,CAAC,wCAAe,CAAC,cAAc,CAAC,EAAE,wCAAe,CAAC,mBAAmB;IACrE,CAAC,wCAAe,CAAC,YAAY,CAAC,EAAE,wCAAe,CAAC,iBAAiB;CAClE,CAAC","sourcesContent":["import { TransactionType } from '@metamask/transaction-controller';\n\nexport const RELAY_URL_BASE = 'https://api.relay.link';\nexport const RELAY_EXECUTE_URL = `${RELAY_URL_BASE}/execute`;\nexport const RELAY_QUOTE_URL = `${RELAY_URL_BASE}/quote`;\nexport const RELAY_STATUS_URL = `${RELAY_URL_BASE}/intents/status/v3`;\nexport const RELAY_POLLING_INTERVAL = 1000; // 1 Second\nexport const TOKEN_TRANSFER_FOUR_BYTE = '0xa9059cbb';\n\nexport const RELAY_DEPOSIT_TYPES: Record<string, TransactionType> = {\n [TransactionType.predictDeposit]: TransactionType.predictRelayDeposit,\n [TransactionType.perpsDeposit]: TransactionType.perpsRelayDeposit,\n};\n"]}
@@ -1,12 +1,9 @@
1
1
  import { TransactionType } from "@metamask/transaction-controller";
2
- import type { RelayStatus } from "./types.cjs";
3
2
  export declare const RELAY_URL_BASE = "https://api.relay.link";
4
3
  export declare const RELAY_EXECUTE_URL = "https://api.relay.link/execute";
5
4
  export declare const RELAY_QUOTE_URL = "https://api.relay.link/quote";
6
5
  export declare const RELAY_STATUS_URL = "https://api.relay.link/intents/status/v3";
7
6
  export declare const RELAY_POLLING_INTERVAL = 1000;
8
7
  export declare const TOKEN_TRANSFER_FOUR_BYTE = "0xa9059cbb";
9
- export declare const RELAY_FAILURE_STATUSES: RelayStatus[];
10
- export declare const RELAY_PENDING_STATUSES: RelayStatus[];
11
8
  export declare const RELAY_DEPOSIT_TYPES: Record<string, TransactionType>;
12
9
  //# sourceMappingURL=constants.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.cts","sourceRoot":"","sources":["../../../src/strategy/relay/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,yCAAyC;AAEnE,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAgB;AAE3C,eAAO,MAAM,cAAc,2BAA2B,CAAC;AACvD,eAAO,MAAM,iBAAiB,mCAA8B,CAAC;AAC7D,eAAO,MAAM,eAAe,iCAA4B,CAAC;AACzD,eAAO,MAAM,gBAAgB,6CAAwC,CAAC;AACtE,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAC3C,eAAO,MAAM,wBAAwB,eAAe,CAAC;AAErD,eAAO,MAAM,sBAAsB,EAAE,WAAW,EAI/C,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,WAAW,EAM/C,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAG/D,CAAC"}
1
+ {"version":3,"file":"constants.d.cts","sourceRoot":"","sources":["../../../src/strategy/relay/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,yCAAyC;AAEnE,eAAO,MAAM,cAAc,2BAA2B,CAAC;AACvD,eAAO,MAAM,iBAAiB,mCAA8B,CAAC;AAC7D,eAAO,MAAM,eAAe,iCAA4B,CAAC;AACzD,eAAO,MAAM,gBAAgB,6CAAwC,CAAC;AACtE,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAC3C,eAAO,MAAM,wBAAwB,eAAe,CAAC;AAErD,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAG/D,CAAC"}
@@ -1,12 +1,9 @@
1
1
  import { TransactionType } from "@metamask/transaction-controller";
2
- import type { RelayStatus } from "./types.mjs";
3
2
  export declare const RELAY_URL_BASE = "https://api.relay.link";
4
3
  export declare const RELAY_EXECUTE_URL = "https://api.relay.link/execute";
5
4
  export declare const RELAY_QUOTE_URL = "https://api.relay.link/quote";
6
5
  export declare const RELAY_STATUS_URL = "https://api.relay.link/intents/status/v3";
7
6
  export declare const RELAY_POLLING_INTERVAL = 1000;
8
7
  export declare const TOKEN_TRANSFER_FOUR_BYTE = "0xa9059cbb";
9
- export declare const RELAY_FAILURE_STATUSES: RelayStatus[];
10
- export declare const RELAY_PENDING_STATUSES: RelayStatus[];
11
8
  export declare const RELAY_DEPOSIT_TYPES: Record<string, TransactionType>;
12
9
  //# sourceMappingURL=constants.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.mts","sourceRoot":"","sources":["../../../src/strategy/relay/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,yCAAyC;AAEnE,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAgB;AAE3C,eAAO,MAAM,cAAc,2BAA2B,CAAC;AACvD,eAAO,MAAM,iBAAiB,mCAA8B,CAAC;AAC7D,eAAO,MAAM,eAAe,iCAA4B,CAAC;AACzD,eAAO,MAAM,gBAAgB,6CAAwC,CAAC;AACtE,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAC3C,eAAO,MAAM,wBAAwB,eAAe,CAAC;AAErD,eAAO,MAAM,sBAAsB,EAAE,WAAW,EAI/C,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,WAAW,EAM/C,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAG/D,CAAC"}
1
+ {"version":3,"file":"constants.d.mts","sourceRoot":"","sources":["../../../src/strategy/relay/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,yCAAyC;AAEnE,eAAO,MAAM,cAAc,2BAA2B,CAAC;AACvD,eAAO,MAAM,iBAAiB,mCAA8B,CAAC;AAC7D,eAAO,MAAM,eAAe,iCAA4B,CAAC;AACzD,eAAO,MAAM,gBAAgB,6CAAwC,CAAC;AACtE,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAC3C,eAAO,MAAM,wBAAwB,eAAe,CAAC;AAErD,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAG/D,CAAC"}
@@ -5,18 +5,6 @@ export const RELAY_QUOTE_URL = `${RELAY_URL_BASE}/quote`;
5
5
  export const RELAY_STATUS_URL = `${RELAY_URL_BASE}/intents/status/v3`;
6
6
  export const RELAY_POLLING_INTERVAL = 1000; // 1 Second
7
7
  export const TOKEN_TRANSFER_FOUR_BYTE = '0xa9059cbb';
8
- export const RELAY_FAILURE_STATUSES = [
9
- 'failure',
10
- 'refund',
11
- 'refunded',
12
- ];
13
- export const RELAY_PENDING_STATUSES = [
14
- 'delayed',
15
- 'depositing',
16
- 'pending',
17
- 'submitted',
18
- 'waiting',
19
- ];
20
8
  export const RELAY_DEPOSIT_TYPES = {
21
9
  [TransactionType.predictDeposit]: TransactionType.predictRelayDeposit,
22
10
  [TransactionType.perpsDeposit]: TransactionType.perpsRelayDeposit,
@@ -1 +1 @@
1
- {"version":3,"file":"constants.mjs","sourceRoot":"","sources":["../../../src/strategy/relay/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,yCAAyC;AAInE,MAAM,CAAC,MAAM,cAAc,GAAG,wBAAwB,CAAC;AACvD,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,cAAc,UAAU,CAAC;AAC7D,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,cAAc,QAAQ,CAAC;AACzD,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,cAAc,oBAAoB,CAAC;AACtE,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC,CAAC,WAAW;AACvD,MAAM,CAAC,MAAM,wBAAwB,GAAG,YAAY,CAAC;AAErD,MAAM,CAAC,MAAM,sBAAsB,GAAkB;IACnD,SAAS;IACT,QAAQ;IACR,UAAU;CACX,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAkB;IACnD,SAAS;IACT,YAAY;IACZ,SAAS;IACT,WAAW;IACX,SAAS;CACV,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAoC;IAClE,CAAC,eAAe,CAAC,cAAc,CAAC,EAAE,eAAe,CAAC,mBAAmB;IACrE,CAAC,eAAe,CAAC,YAAY,CAAC,EAAE,eAAe,CAAC,iBAAiB;CAClE,CAAC","sourcesContent":["import { TransactionType } from '@metamask/transaction-controller';\n\nimport type { RelayStatus } from './types';\n\nexport const RELAY_URL_BASE = 'https://api.relay.link';\nexport const RELAY_EXECUTE_URL = `${RELAY_URL_BASE}/execute`;\nexport const RELAY_QUOTE_URL = `${RELAY_URL_BASE}/quote`;\nexport const RELAY_STATUS_URL = `${RELAY_URL_BASE}/intents/status/v3`;\nexport const RELAY_POLLING_INTERVAL = 1000; // 1 Second\nexport const TOKEN_TRANSFER_FOUR_BYTE = '0xa9059cbb';\n\nexport const RELAY_FAILURE_STATUSES: RelayStatus[] = [\n 'failure',\n 'refund',\n 'refunded',\n];\n\nexport const RELAY_PENDING_STATUSES: RelayStatus[] = [\n 'delayed',\n 'depositing',\n 'pending',\n 'submitted',\n 'waiting',\n];\n\nexport const RELAY_DEPOSIT_TYPES: Record<string, TransactionType> = {\n [TransactionType.predictDeposit]: TransactionType.predictRelayDeposit,\n [TransactionType.perpsDeposit]: TransactionType.perpsRelayDeposit,\n};\n"]}
1
+ {"version":3,"file":"constants.mjs","sourceRoot":"","sources":["../../../src/strategy/relay/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,yCAAyC;AAEnE,MAAM,CAAC,MAAM,cAAc,GAAG,wBAAwB,CAAC;AACvD,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,cAAc,UAAU,CAAC;AAC7D,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,cAAc,QAAQ,CAAC;AACzD,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,cAAc,oBAAoB,CAAC;AACtE,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC,CAAC,WAAW;AACvD,MAAM,CAAC,MAAM,wBAAwB,GAAG,YAAY,CAAC;AAErD,MAAM,CAAC,MAAM,mBAAmB,GAAoC;IAClE,CAAC,eAAe,CAAC,cAAc,CAAC,EAAE,eAAe,CAAC,mBAAmB;IACrE,CAAC,eAAe,CAAC,YAAY,CAAC,EAAE,eAAe,CAAC,iBAAiB;CAClE,CAAC","sourcesContent":["import { TransactionType } from '@metamask/transaction-controller';\n\nexport const RELAY_URL_BASE = 'https://api.relay.link';\nexport const RELAY_EXECUTE_URL = `${RELAY_URL_BASE}/execute`;\nexport const RELAY_QUOTE_URL = `${RELAY_URL_BASE}/quote`;\nexport const RELAY_STATUS_URL = `${RELAY_URL_BASE}/intents/status/v3`;\nexport const RELAY_POLLING_INTERVAL = 1000; // 1 Second\nexport const TOKEN_TRANSFER_FOUR_BYTE = '0xa9059cbb';\n\nexport const RELAY_DEPOSIT_TYPES: Record<string, TransactionType> = {\n [TransactionType.predictDeposit]: TransactionType.predictRelayDeposit,\n [TransactionType.perpsDeposit]: TransactionType.perpsRelayDeposit,\n};\n"]}
@@ -17,6 +17,7 @@ const amounts_1 = require("../../utils/amounts.cjs");
17
17
  const feature_flags_1 = require("../../utils/feature-flags.cjs");
18
18
  const gas_1 = require("../../utils/gas.cjs");
19
19
  const token_1 = require("../../utils/token.cjs");
20
+ const transaction_1 = require("../../utils/transaction.cjs");
20
21
  const log = (0, utils_1.createModuleLogger)(logger_1.projectLogger, 'relay-strategy');
21
22
  /**
22
23
  * Fetches Relay quotes.
@@ -46,10 +47,56 @@ exports.getRelayQuotes = getRelayQuotes;
46
47
  async function getQuoteWithMaxAmountHandling(request, fullRequest) {
47
48
  const { isMaxAmount } = request;
48
49
  if (!isMaxAmount) {
49
- return getSingleQuote(request, fullRequest);
50
+ return getQuoteWithPostQuoteGasHandling(request, fullRequest);
50
51
  }
51
52
  return (0, relay_max_gas_station_1.getRelayMaxGasStationQuote)(request, fullRequest, getSingleQuote);
52
53
  }
54
+ /**
55
+ * For post-quote flows, fetch an initial quote to compute gas cost in source
56
+ * token, then re-quote with the source amount reduced by the gas cost.
57
+ * This ensures Relay reserves enough for the gas fee token payment.
58
+ *
59
+ * For non-post-quote flows, just returns a single quote.
60
+ *
61
+ * @param request - Quote request.
62
+ * @param fullRequest - Full request context.
63
+ * @returns The final quote (phase 2 for post-quote, or phase 1 for normal).
64
+ */
65
+ async function getQuoteWithPostQuoteGasHandling(request, fullRequest) {
66
+ const phase1Quote = await getSingleQuote(request, fullRequest);
67
+ if (!request.isPostQuote || !phase1Quote.fees.isSourceGasFeeToken) {
68
+ return phase1Quote;
69
+ }
70
+ const gasCostRaw = phase1Quote.fees.sourceNetwork.max.raw;
71
+ const adjustedSourceAmount = new bignumber_js_1.BigNumber(request.sourceTokenAmount)
72
+ .minus(gasCostRaw)
73
+ .integerValue(bignumber_js_1.BigNumber.ROUND_DOWN);
74
+ log('Subtracting gas from source for post-quote two-call', {
75
+ originalSourceAmount: request.sourceTokenAmount,
76
+ gasCostRaw,
77
+ adjustedSourceAmount: adjustedSourceAmount.toString(10),
78
+ });
79
+ if (!adjustedSourceAmount.isGreaterThan(0)) {
80
+ log('Insufficient balance after gas subtraction for post-quote, using phase 1');
81
+ return phase1Quote;
82
+ }
83
+ try {
84
+ const phase2Quote = await getSingleQuote({
85
+ ...request,
86
+ sourceTokenAmount: adjustedSourceAmount.toFixed(0, bignumber_js_1.BigNumber.ROUND_DOWN),
87
+ }, fullRequest);
88
+ if (phase1Quote.fees.isSourceGasFeeToken &&
89
+ !phase2Quote.fees.isSourceGasFeeToken) {
90
+ log('Phase 2 lost gas fee token eligibility, falling back to phase 1');
91
+ return phase1Quote;
92
+ }
93
+ return phase2Quote;
94
+ }
95
+ catch (error) {
96
+ log('Phase 2 quote failed, falling back to phase 1', { error });
97
+ return phase1Quote;
98
+ }
99
+ }
53
100
  /**
54
101
  * Fetches a single Relay quote.
55
102
  *
@@ -316,7 +363,12 @@ async function calculateSourceNetworkCost(quote, messenger, request, transaction
316
363
  .flatMap((step) => step.items)
317
364
  .map((item) => item.data);
318
365
  const { chainId, data, maxFeePerGas, maxPriorityFeePerGas, to, value } = relayParams[0];
319
- const { totalGasEstimate, totalGasLimit, gasLimits } = await calculateSourceNetworkGasLimit(relayParams, messenger, request.isPostQuote ? transaction : undefined);
366
+ const isPredictWithdraw = request.isPostQuote && (0, transaction_1.isPredictWithdrawTransaction)(transaction);
367
+ const fromOverride = isPredictWithdraw ? request.refundTo : undefined;
368
+ const relayOnlyGas = await calculateSourceNetworkGasLimit(relayParams, messenger, fromOverride);
369
+ const { totalGasEstimate, totalGasLimit, gasLimits } = request.isPostQuote
370
+ ? combinePostQuoteGas(relayOnlyGas, transaction)
371
+ : relayOnlyGas;
320
372
  log('Gas limit', {
321
373
  totalGasEstimate,
322
374
  totalGasLimit,
@@ -359,6 +411,40 @@ async function calculateSourceNetworkCost(quote, messenger, request, transaction
359
411
  nativeBalance,
360
412
  max: max.raw,
361
413
  });
414
+ if (isPredictWithdraw && request.refundTo) {
415
+ log('Using proxy address for predict withdraw gas station simulation', {
416
+ proxyAddress: request.refundTo,
417
+ sourceTokenAddress,
418
+ totalGasEstimate,
419
+ });
420
+ const gasFeeTokenCost = await (0, gas_station_1.getGasStationCostInSourceTokenRaw)({
421
+ firstStepData: {
422
+ data,
423
+ to,
424
+ value,
425
+ },
426
+ messenger,
427
+ request: {
428
+ from: request.refundTo,
429
+ sourceChainId,
430
+ sourceTokenAddress,
431
+ },
432
+ totalGasEstimate,
433
+ totalItemCount: relayParams.length + 1,
434
+ });
435
+ if (gasFeeTokenCost) {
436
+ log('Using predict withdraw gas fee token for source network', {
437
+ gasFeeTokenCost,
438
+ });
439
+ return {
440
+ isGasFeeToken: true,
441
+ estimate: gasFeeTokenCost,
442
+ max: gasFeeTokenCost,
443
+ gasLimits,
444
+ };
445
+ }
446
+ return result;
447
+ }
362
448
  const gasFeeTokenCost = await (0, gas_station_1.getGasStationCostInSourceTokenRaw)({
363
449
  firstStepData: {
364
450
  data,
@@ -390,24 +476,17 @@ async function calculateSourceNetworkCost(quote, messenger, request, transaction
390
476
  /**
391
477
  * Calculate the total gas limit for the source network.
392
478
  *
393
- * For post-quote flows (e.g. predict withdrawals), the original transaction's
394
- * gas is combined with the relay gas so that source network cost accounts for
395
- * both the user's transaction and the relay transactions.
396
- *
397
479
  * @param params - Array of relay transaction parameters.
398
480
  * @param messenger - Controller messenger.
399
- * @param postQuoteTransaction - Original transaction for post-quote flows.
400
- * When provided, its gas is included in the returned totals.
481
+ * @param fromOverride - Optional address to use as `from` in gas estimation
482
+ * instead of the address in the relay params. Used in predict withdraw flows
483
+ * to estimate with the proxy/Safe address that holds the source token balance.
401
484
  * @returns Total gas estimates and per-transaction gas limits.
402
485
  */
403
- async function calculateSourceNetworkGasLimit(params, messenger, postQuoteTransaction) {
404
- const relayGas = params.length === 1
405
- ? await calculateSourceNetworkGasLimitSingle(params[0], messenger)
406
- : await calculateSourceNetworkGasLimitBatch(params, messenger);
407
- if (!postQuoteTransaction?.txParams.to) {
408
- return relayGas;
409
- }
410
- return combinePostQuoteGas(relayGas, postQuoteTransaction);
486
+ async function calculateSourceNetworkGasLimit(params, messenger, fromOverride) {
487
+ return params.length === 1
488
+ ? calculateSourceNetworkGasLimitSingle(params[0], messenger, fromOverride)
489
+ : calculateSourceNetworkGasLimitBatch(params, messenger, fromOverride);
411
490
  }
412
491
  /**
413
492
  * Combine the original transaction's gas with relay gas for post-quote flows.
@@ -485,11 +564,11 @@ function getTransferRecipient(data) {
485
564
  .decodeFunctionData('transfer', data)
486
565
  .to.toLowerCase();
487
566
  }
488
- async function calculateSourceNetworkGasLimitSingle(params, messenger) {
567
+ async function calculateSourceNetworkGasLimitSingle(params, messenger, fromOverride) {
489
568
  const paramGasLimit = params.gas
490
569
  ? new bignumber_js_1.BigNumber(params.gas).toNumber()
491
570
  : undefined;
492
- if (paramGasLimit) {
571
+ if (paramGasLimit && !fromOverride) {
493
572
  log('Using single gas limit from params', { paramGasLimit });
494
573
  return {
495
574
  totalGasEstimate: paramGasLimit,
@@ -498,7 +577,8 @@ async function calculateSourceNetworkGasLimitSingle(params, messenger) {
498
577
  };
499
578
  }
500
579
  try {
501
- const { chainId: chainIdNumber, data, from, to, value: valueString, } = params;
580
+ const { chainId: chainIdNumber, data, from: paramsFrom, to, value: valueString, } = params;
581
+ const from = fromOverride ?? paramsFrom;
502
582
  const chainId = (0, controller_utils_1.toHex)(chainIdNumber);
503
583
  const value = (0, controller_utils_1.toHex)(valueString ?? '0');
504
584
  const gasBuffer = (0, feature_flags_1.getGasBuffer)(messenger, chainId);
@@ -536,16 +616,20 @@ async function calculateSourceNetworkGasLimitSingle(params, messenger) {
536
616
  *
537
617
  * @param params - Array of transaction parameters.
538
618
  * @param messenger - Controller messenger.
619
+ * @param fromOverride - Optional address to use as `from` in gas estimation.
539
620
  * @returns - Gas limits.
540
621
  */
541
- async function calculateSourceNetworkGasLimitBatch(params, messenger) {
622
+ async function calculateSourceNetworkGasLimitBatch(params, messenger, fromOverride) {
542
623
  try {
543
- const { chainId: chainIdNumber, from } = params[0];
624
+ const { chainId: chainIdNumber, from: paramsFrom } = params[0];
625
+ const from = fromOverride ?? paramsFrom;
544
626
  const chainId = (0, controller_utils_1.toHex)(chainIdNumber);
545
627
  const gasBuffer = (0, feature_flags_1.getGasBuffer)(messenger, chainId);
546
628
  const transactions = params.map((singleParams) => ({
547
629
  ...singleParams,
548
- gas: singleParams.gas ? (0, controller_utils_1.toHex)(singleParams.gas) : undefined,
630
+ gas: !fromOverride && singleParams.gas
631
+ ? (0, controller_utils_1.toHex)(singleParams.gas)
632
+ : undefined,
549
633
  maxFeePerGas: undefined,
550
634
  maxPriorityFeePerGas: undefined,
551
635
  value: (0, controller_utils_1.toHex)(singleParams.value ?? '0'),
@@ -1 +1 @@
1
- {"version":3,"file":"relay-quotes.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-quotes.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable require-atomic-updates */\n\nimport { Interface } from '@ethersproject/abi';\nimport { toHex } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { TOKEN_TRANSFER_FOUR_BYTE } from './constants';\nimport {\n getGasStationEligibility,\n getGasStationCostInSourceTokenRaw,\n} from './gas-station';\nimport { fetchRelayQuote } from './relay-api';\nimport { getRelayMaxGasStationQuote } from './relay-max-gas-station';\nimport type { RelayQuote, RelayQuoteRequest } from './types';\nimport { TransactionPayStrategy } from '../..';\nimport type {\n BatchTransactionParams,\n TransactionMeta,\n} from '../../../../transaction-controller/src';\nimport {\n ARBITRUM_USDC_ADDRESS,\n CHAIN_ID_ARBITRUM,\n CHAIN_ID_HYPERCORE,\n CHAIN_ID_POLYGON,\n NATIVE_TOKEN_ADDRESS,\n STABLECOINS,\n} from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n Amount,\n FiatRates,\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport { getFiatValueFromUsd } from '../../utils/amounts';\nimport {\n isEIP7702Chain,\n isRelayExecuteEnabled,\n getFeatureFlags,\n getGasBuffer,\n getRelayOriginGasOverhead,\n getSlippage,\n} from '../../utils/feature-flags';\nimport { calculateGasCost } from '../../utils/gas';\nimport {\n getNativeToken,\n getTokenBalance,\n getTokenFiatRate,\n normalizeTokenAddress,\n TokenAddressTarget,\n} from '../../utils/token';\n\nconst log = createModuleLogger(projectLogger, 'relay-strategy');\n\n/**\n * Fetches Relay quotes.\n *\n * @param request - Request object.\n * @returns Array of quotes.\n */\nexport async function getRelayQuotes(\n request: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>[]> {\n const { requests } = request;\n\n log('Fetching quotes', requests);\n\n try {\n const normalizedRequests = requests\n // Ignore gas fee token requests (which have both target=0 and source=0)\n // but keep post-quote requests (identified by isPostQuote flag)\n .filter(\n (singleRequest) =>\n singleRequest.targetAmountMinimum !== '0' ||\n singleRequest.isPostQuote,\n )\n .map((singleRequest) => normalizeRequest(singleRequest));\n\n log('Normalized requests', normalizedRequests);\n\n return await Promise.all(\n normalizedRequests.map((singleRequest) =>\n getQuoteWithMaxAmountHandling(singleRequest, request),\n ),\n );\n } catch (error) {\n log('Error fetching quotes', { error });\n throw new Error(`Failed to fetch Relay quotes: ${String(error)}`);\n }\n}\n\nasync function getQuoteWithMaxAmountHandling(\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const { isMaxAmount } = request;\n\n if (!isMaxAmount) {\n return getSingleQuote(request, fullRequest);\n }\n\n return getRelayMaxGasStationQuote(request, fullRequest, getSingleQuote);\n}\n\n/**\n * Fetches a single Relay quote.\n *\n * @param request - Quote request.\n * @param fullRequest - Full quotes request.\n * @returns Single quote.\n */\nasync function getSingleQuote(\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const { messenger, transaction } = fullRequest;\n\n const {\n from,\n isMaxAmount,\n sourceChainId,\n sourceTokenAddress,\n sourceTokenAmount,\n targetAmountMinimum,\n targetChainId,\n targetTokenAddress,\n } = request;\n\n const slippageDecimal = getSlippage(\n messenger,\n sourceChainId,\n sourceTokenAddress,\n );\n\n const slippageTolerance = new BigNumber(slippageDecimal * 100 * 100).toFixed(\n 0,\n );\n\n try {\n // For post-quote or max amount flows, use EXACT_INPUT - user specifies how much to send,\n // and we show them how much they'll receive after fees.\n // For regular flows with a target amount, use EXPECTED_OUTPUT.\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n const useExactInput = isMaxAmount || request.isPostQuote;\n\n const useExecute =\n isRelayExecuteEnabled(messenger) &&\n isEIP7702Chain(messenger, sourceChainId);\n\n const body: RelayQuoteRequest = {\n amount: useExactInput ? sourceTokenAmount : targetAmountMinimum,\n destinationChainId: Number(targetChainId),\n destinationCurrency: targetTokenAddress,\n originChainId: Number(sourceChainId),\n originCurrency: sourceTokenAddress,\n ...(useExecute\n ? { originGasOverhead: getRelayOriginGasOverhead(messenger) }\n : {}),\n recipient: from,\n slippageTolerance,\n tradeType: useExactInput ? 'EXACT_INPUT' : 'EXPECTED_OUTPUT',\n user: from,\n };\n\n // Skip transaction processing for post-quote flows - the original transaction\n // will be included in the batch separately, not as part of the quote\n if (!request.isPostQuote) {\n await processTransactions(transaction, request, body, messenger);\n } else if (request.refundTo) {\n // For post-quote flows, honour the caller-specified refund address so that\n // failed Relay transactions refund to the correct account (e.g. the Predict\n // Safe proxy) rather than defaulting to the EOA.\n body.refundTo = request.refundTo;\n }\n\n log('Request body', body);\n\n const quote = await fetchRelayQuote(messenger, body);\n\n log('Fetched relay quote', quote);\n\n return await normalizeQuote(quote, request, fullRequest);\n } catch (error) {\n log('Error fetching relay quote', error);\n throw error;\n }\n}\n\n/**\n * Add tranasction data to request body if needed.\n *\n * @param transaction - Transaction metadata.\n * @param request - Quote request.\n * @param requestBody - Request body to populate.\n * @param messenger - Controller messenger.\n */\nasync function processTransactions(\n transaction: TransactionMeta,\n request: QuoteRequest,\n requestBody: RelayQuoteRequest,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const { nestedTransactions, txParams } = transaction;\n const { isMaxAmount, targetChainId } = request;\n const data = txParams?.data as Hex | undefined;\n\n const singleData =\n nestedTransactions?.length === 1 ? nestedTransactions[0].data : data;\n\n const isHypercore = targetChainId === CHAIN_ID_HYPERCORE;\n\n const isTokenTransfer =\n !isHypercore && Boolean(singleData?.startsWith(TOKEN_TRANSFER_FOUR_BYTE));\n\n if (isTokenTransfer) {\n requestBody.recipient = getTransferRecipient(singleData as Hex);\n\n log('Updating recipient as token transfer', requestBody.recipient);\n }\n\n const hasNoData = singleData === undefined || singleData === '0x';\n const skipDelegation = hasNoData || isTokenTransfer || isHypercore;\n\n if (skipDelegation) {\n log('Skipping delegation as token transfer or Hypercore deposit');\n return;\n }\n\n if (isMaxAmount) {\n throw new Error('Max amount quotes do not support included transactions');\n }\n\n const delegation = await messenger.call(\n 'TransactionPayController:getDelegationTransaction',\n { transaction },\n );\n\n const normalizedAuthorizationList = delegation.authorizationList?.map(\n (a) => ({\n ...a,\n chainId: Number(a.chainId),\n nonce: Number(a.nonce),\n r: a.r as Hex,\n s: a.s as Hex,\n yParity: Number(a.yParity),\n }),\n );\n\n requestBody.authorizationList = normalizedAuthorizationList;\n requestBody.tradeType = 'EXACT_OUTPUT';\n\n const tokenTransferData = nestedTransactions?.find((nestedTx) =>\n nestedTx.data?.startsWith(TOKEN_TRANSFER_FOUR_BYTE),\n )?.data;\n\n // If the transactions include a token transfer, change the recipient\n // so any extra dust is also sent to the same address, rather than back to the user.\n if (tokenTransferData) {\n requestBody.recipient = getTransferRecipient(tokenTransferData);\n requestBody.refundTo = request.from;\n }\n\n requestBody.txs = [\n {\n to: request.targetTokenAddress,\n data: buildTokenTransferData(request.from, request.targetAmountMinimum),\n value: '0x0',\n },\n {\n to: delegation.to,\n data: delegation.data,\n value: delegation.value,\n },\n ];\n}\n\n/**\n * Normalizes requests for Relay.\n *\n * @param request - Quote request to normalize.\n * @returns Normalized request.\n */\nfunction normalizeRequest(request: QuoteRequest): QuoteRequest {\n const newRequest = {\n ...request,\n };\n\n const isHyperliquidDeposit =\n !request.isPostQuote &&\n request.targetChainId === CHAIN_ID_ARBITRUM &&\n request.targetTokenAddress.toLowerCase() ===\n ARBITRUM_USDC_ADDRESS.toLowerCase();\n\n newRequest.sourceTokenAddress = normalizeTokenAddress(\n newRequest.sourceTokenAddress,\n newRequest.sourceChainId,\n TokenAddressTarget.Relay,\n );\n newRequest.targetTokenAddress = normalizeTokenAddress(\n newRequest.targetTokenAddress,\n newRequest.targetChainId,\n TokenAddressTarget.Relay,\n );\n\n if (isHyperliquidDeposit) {\n newRequest.targetChainId = CHAIN_ID_HYPERCORE;\n newRequest.targetTokenAddress = '0x00000000000000000000000000000000';\n newRequest.targetAmountMinimum = new BigNumber(request.targetAmountMinimum)\n .shiftedBy(2)\n .toString(10);\n\n log('Converting Arbitrum Hyperliquid deposit to direct deposit', {\n originalRequest: request,\n normalizedRequest: newRequest,\n });\n }\n\n return newRequest;\n}\n\n/**\n * Normalizes a Relay quote into a TransactionPayQuote.\n *\n * @param quote - Relay quote.\n * @param request - Original quote request.\n * @param fullRequest - Full quotes request.\n * @returns Normalized quote.\n */\nasync function normalizeQuote(\n quote: RelayQuote,\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const { messenger } = fullRequest;\n const { details } = quote;\n const { currencyIn, currencyOut } = details;\n\n const { usdToFiatRate } = getFiatRates(messenger, request);\n\n const dust = getFiatValueFromUsd(\n calculateDustUsd(quote, request),\n usdToFiatRate,\n );\n\n const subsidizedFeeUsd = getSubsidizedFeeAmountUsd(quote);\n\n const appFeeUsd = new BigNumber(quote.fees?.app?.amountUsd ?? '0');\n const metaMaskFee = getFiatValueFromUsd(appFeeUsd, usdToFiatRate);\n\n // Subtract app fee from provider fee since totalImpact.usd already includes it\n const providerFeeUsd = calculateProviderFee(quote).minus(appFeeUsd);\n const provider = subsidizedFeeUsd.gt(0)\n ? { usd: '0', fiat: '0' }\n : getFiatValueFromUsd(providerFeeUsd, usdToFiatRate);\n\n const {\n gasLimits,\n isGasFeeToken: isSourceGasFeeToken,\n ...sourceNetwork\n } = await calculateSourceNetworkCost(\n quote,\n messenger,\n request,\n fullRequest.transaction,\n );\n\n const targetNetwork = {\n usd: '0',\n fiat: '0',\n };\n\n const sourceAmount: Amount = {\n human: currencyIn.amountFormatted,\n raw: currencyIn.amount,\n ...getFiatValueFromUsd(new BigNumber(currencyIn.amountUsd), usdToFiatRate),\n };\n\n const isTargetStablecoin = isStablecoin(\n request.targetChainId,\n request.targetTokenAddress,\n );\n\n const additionalTargetAmountUsd =\n quote.request.tradeType === 'EXACT_INPUT'\n ? subsidizedFeeUsd\n : new BigNumber(0);\n\n if (additionalTargetAmountUsd.gt(0)) {\n log(\n 'Including subsidized fee in target amount',\n additionalTargetAmountUsd.toString(10),\n );\n }\n\n const baseTargetAmountUsd = isTargetStablecoin\n ? new BigNumber(currencyOut.amountFormatted)\n : new BigNumber(currencyOut.amountUsd);\n\n const targetAmountUsd = baseTargetAmountUsd.plus(additionalTargetAmountUsd);\n\n const targetAmount = getFiatValueFromUsd(targetAmountUsd, usdToFiatRate);\n\n const metamask = {\n gasLimits,\n };\n\n return {\n dust,\n estimatedDuration: details.timeEstimate,\n fees: {\n isSourceGasFeeToken,\n metaMask: metaMaskFee,\n provider,\n sourceNetwork,\n targetNetwork,\n },\n original: {\n ...quote,\n metamask,\n },\n request,\n sourceAmount,\n targetAmount,\n strategy: TransactionPayStrategy.Relay,\n };\n}\n\n/**\n * Calculate dust USD value.\n *\n * @param quote - Relay quote.\n * @param request - Quote request.\n * @returns Dust value in USD and fiat.\n */\nfunction calculateDustUsd(quote: RelayQuote, request: QuoteRequest): BigNumber {\n const { currencyOut } = quote.details;\n const { amountUsd, amountFormatted, minimumAmount } = currencyOut;\n const { decimals: targetDecimals } = currencyOut.currency;\n\n const targetUsdRate = new BigNumber(amountUsd).dividedBy(amountFormatted);\n\n const dustRaw = new BigNumber(minimumAmount).minus(\n request.targetAmountMinimum,\n );\n\n return dustRaw.shiftedBy(-targetDecimals).multipliedBy(targetUsdRate);\n}\n\n/**\n * Calculates USD to fiat rate.\n *\n * @param messenger - Controller messenger.\n * @param request - Quote request.\n * @returns USD to fiat rate.\n */\nfunction getFiatRates(\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n): {\n sourceFiatRate: FiatRates;\n usdToFiatRate: BigNumber;\n} {\n const { sourceChainId, sourceTokenAddress } = request;\n\n const finalSourceTokenAddress =\n sourceChainId === CHAIN_ID_POLYGON &&\n sourceTokenAddress === NATIVE_TOKEN_ADDRESS\n ? getNativeToken(sourceChainId)\n : sourceTokenAddress;\n\n const sourceFiatRate = getTokenFiatRate(\n messenger,\n finalSourceTokenAddress,\n sourceChainId,\n );\n\n if (!sourceFiatRate) {\n throw new Error('Source token fiat rate not found');\n }\n\n const usdToFiatRate = new BigNumber(sourceFiatRate.fiatRate).dividedBy(\n sourceFiatRate.usdRate,\n );\n\n return { sourceFiatRate, usdToFiatRate };\n}\n\n/**\n * Calculates source network cost from a Relay quote.\n *\n * For post-quote flows (e.g. predictWithdraw), the cost also includes the\n * original transaction's gas (the user's Polygon USDC.e transfer) in addition\n * to the Relay deposit transaction gas, by appending the original\n * transaction's params so that gas estimation and gas-fee-token logic handle\n * both transactions together.\n *\n * @param quote - Relay quote.\n * @param messenger - Controller messenger.\n * @param request - Quote request.\n * @param transaction - Original transaction metadata.\n * @returns Total source network cost in USD and fiat.\n */\nasync function calculateSourceNetworkCost(\n quote: RelayQuote,\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n transaction: TransactionMeta,\n): Promise<\n TransactionPayQuote<RelayQuote>['fees']['sourceNetwork'] & {\n gasLimits: number[];\n isGasFeeToken?: boolean;\n }\n> {\n const { from, sourceChainId, sourceTokenAddress } = request;\n\n const relayParams = quote.steps\n .flatMap((step) => step.items)\n .map((item) => item.data);\n\n const { chainId, data, maxFeePerGas, maxPriorityFeePerGas, to, value } =\n relayParams[0];\n\n const { totalGasEstimate, totalGasLimit, gasLimits } =\n await calculateSourceNetworkGasLimit(\n relayParams,\n messenger,\n request.isPostQuote ? transaction : undefined,\n );\n\n log('Gas limit', {\n totalGasEstimate,\n totalGasLimit,\n gasLimits,\n });\n\n const estimate = calculateGasCost({\n chainId,\n gas: totalGasEstimate,\n maxFeePerGas,\n maxPriorityFeePerGas,\n messenger,\n });\n\n const max = calculateGasCost({\n chainId,\n gas: totalGasLimit,\n maxFeePerGas,\n maxPriorityFeePerGas,\n messenger,\n isMax: true,\n });\n\n const nativeBalance = getTokenBalance(\n messenger,\n from,\n sourceChainId,\n getNativeToken(sourceChainId),\n );\n\n const result = { estimate, max, gasLimits };\n\n if (new BigNumber(nativeBalance).isGreaterThanOrEqualTo(max.raw)) {\n return result;\n }\n\n const gasStationEligibility = getGasStationEligibility(\n messenger,\n sourceChainId,\n );\n\n if (gasStationEligibility.isDisabledChain) {\n log('Skipping gas station as disabled chain', {\n sourceChainId,\n });\n\n return result;\n }\n\n if (!gasStationEligibility.chainSupportsGasStation) {\n log('Skipping gas station as chain does not support EIP-7702', {\n sourceChainId,\n });\n\n return result;\n }\n\n log('Checking gas fee tokens as insufficient native balance', {\n nativeBalance,\n max: max.raw,\n });\n\n const gasFeeTokenCost = await getGasStationCostInSourceTokenRaw({\n firstStepData: {\n data,\n to,\n value,\n },\n messenger,\n request: {\n from,\n sourceChainId,\n sourceTokenAddress,\n },\n totalGasEstimate,\n totalItemCount: Math.max(relayParams.length, gasLimits.length),\n });\n\n if (!gasFeeTokenCost) {\n return result;\n }\n\n log('Using gas fee token for source network', {\n gasFeeTokenCost,\n });\n\n return {\n isGasFeeToken: true,\n estimate: gasFeeTokenCost,\n max: gasFeeTokenCost,\n gasLimits,\n };\n}\n\n/**\n * Calculate the total gas limit for the source network.\n *\n * For post-quote flows (e.g. predict withdrawals), the original transaction's\n * gas is combined with the relay gas so that source network cost accounts for\n * both the user's transaction and the relay transactions.\n *\n * @param params - Array of relay transaction parameters.\n * @param messenger - Controller messenger.\n * @param postQuoteTransaction - Original transaction for post-quote flows.\n * When provided, its gas is included in the returned totals.\n * @returns Total gas estimates and per-transaction gas limits.\n */\nasync function calculateSourceNetworkGasLimit(\n params: RelayQuote['steps'][0]['items'][0]['data'][],\n messenger: TransactionPayControllerMessenger,\n postQuoteTransaction?: TransactionMeta,\n): Promise<{\n totalGasEstimate: number;\n totalGasLimit: number;\n gasLimits: number[];\n}> {\n const relayGas =\n params.length === 1\n ? await calculateSourceNetworkGasLimitSingle(params[0], messenger)\n : await calculateSourceNetworkGasLimitBatch(params, messenger);\n\n if (!postQuoteTransaction?.txParams.to) {\n return relayGas;\n }\n\n return combinePostQuoteGas(relayGas, postQuoteTransaction);\n}\n\n/**\n * Combine the original transaction's gas with relay gas for post-quote flows.\n *\n * Prefers gas from `nestedTransactions` (preserves the caller-provided value)\n * since TransactionController may re-estimate `txParams.gas` during batch\n * creation.\n *\n * @param relayGas - Gas estimates from relay transactions.\n * @param relayGas.totalGasEstimate - Estimated gas total.\n * @param relayGas.totalGasLimit - Maximum gas total.\n * @param relayGas.gasLimits - Per-transaction gas limits.\n * @param transaction - Original transaction metadata.\n * @returns Combined gas estimates including the original transaction.\n */\nfunction combinePostQuoteGas(\n relayGas: {\n totalGasEstimate: number;\n totalGasLimit: number;\n gasLimits: number[];\n },\n transaction: TransactionMeta,\n): { totalGasEstimate: number; totalGasLimit: number; gasLimits: number[] } {\n const nestedGas = transaction.nestedTransactions?.find((tx) => tx.gas)?.gas;\n const rawGas = nestedGas ?? transaction.txParams.gas;\n const originalTxGas = rawGas ? new BigNumber(rawGas).toNumber() : undefined;\n\n if (originalTxGas === undefined) {\n return relayGas;\n }\n\n let { gasLimits } = relayGas;\n // TODO: Test EIP-7702 support on the chain as well before assuming single gas limit.\n const isEIP7702 = gasLimits.length === 1;\n\n if (isEIP7702) {\n // Single gas limit (either one relay param or 7702 combined) —\n // add the original tx gas so the batch uses a single 7702 limit.\n gasLimits = [gasLimits[0] + originalTxGas];\n } else {\n // Multiple individual gas limits — prepend the original tx gas\n // so the list order matches relay-submit's transaction order.\n gasLimits = [originalTxGas, ...gasLimits];\n }\n\n const totalGasEstimate = relayGas.totalGasEstimate + originalTxGas;\n const totalGasLimit = relayGas.totalGasLimit + originalTxGas;\n\n log('Combined original tx gas with relay gas', {\n originalTxGas,\n isEIP7702,\n gasLimits,\n totalGasLimit,\n });\n\n return { totalGasEstimate, totalGasLimit, gasLimits };\n}\n\n/**\n * Calculate the provider fee for a Relay quote.\n *\n * @param quote - Relay quote.\n * @returns - Provider fee in USD.\n */\nfunction calculateProviderFee(quote: RelayQuote): BigNumber {\n return new BigNumber(quote.details.totalImpact.usd).abs();\n}\n\n/**\n * Build token transfer data.\n *\n * @param recipient - Recipient address.\n * @param amountRaw - Amount in raw format.\n * @returns Token transfer data.\n */\nfunction buildTokenTransferData(recipient: Hex, amountRaw: string): Hex {\n return new Interface([\n 'function transfer(address to, uint256 amount)',\n ]).encodeFunctionData('transfer', [recipient, amountRaw]) as Hex;\n}\n\n/**\n * Get transfer recipient from token transfer data.\n *\n * @param data - Token transfer data.\n * @returns Transfer recipient.\n */\nfunction getTransferRecipient(data: Hex): Hex {\n return new Interface(['function transfer(address to, uint256 amount)'])\n .decodeFunctionData('transfer', data)\n .to.toLowerCase();\n}\n\nasync function calculateSourceNetworkGasLimitSingle(\n params: RelayQuote['steps'][0]['items'][0]['data'],\n messenger: TransactionPayControllerMessenger,\n): Promise<{\n totalGasEstimate: number;\n totalGasLimit: number;\n gasLimits: number[];\n}> {\n const paramGasLimit = params.gas\n ? new BigNumber(params.gas).toNumber()\n : undefined;\n\n if (paramGasLimit) {\n log('Using single gas limit from params', { paramGasLimit });\n\n return {\n totalGasEstimate: paramGasLimit,\n totalGasLimit: paramGasLimit,\n gasLimits: [paramGasLimit],\n };\n }\n\n try {\n const {\n chainId: chainIdNumber,\n data,\n from,\n to,\n value: valueString,\n } = params;\n\n const chainId = toHex(chainIdNumber);\n const value = toHex(valueString ?? '0');\n const gasBuffer = getGasBuffer(messenger, chainId);\n\n const networkClientId = messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n chainId,\n );\n\n const { gas: gasHex, simulationFails } = await messenger.call(\n 'TransactionController:estimateGas',\n { from, data, to, value },\n networkClientId,\n );\n\n const estimatedGas = new BigNumber(gasHex).toNumber();\n const bufferedGas = Math.ceil(estimatedGas * gasBuffer);\n\n if (!simulationFails) {\n log('Estimated gas limit for single transaction', {\n chainId,\n estimatedGas,\n bufferedGas,\n gasBuffer,\n });\n\n return {\n totalGasEstimate: bufferedGas,\n totalGasLimit: bufferedGas,\n gasLimits: [bufferedGas],\n };\n }\n } catch (error) {\n log('Failed to estimate gas limit for single transaction', error);\n }\n\n const fallbackGas = getFeatureFlags(messenger).relayFallbackGas;\n\n log('Using fallback gas for single transaction', { fallbackGas });\n\n return {\n totalGasEstimate: fallbackGas.estimate,\n totalGasLimit: fallbackGas.max,\n gasLimits: [fallbackGas.max],\n };\n}\n\n/**\n * Calculate the gas limits for a batch of transactions.\n *\n * @param params - Array of transaction parameters.\n * @param messenger - Controller messenger.\n * @returns - Gas limits.\n */\nasync function calculateSourceNetworkGasLimitBatch(\n params: RelayQuote['steps'][0]['items'][0]['data'][],\n messenger: TransactionPayControllerMessenger,\n): Promise<{\n totalGasEstimate: number;\n totalGasLimit: number;\n gasLimits: number[];\n}> {\n try {\n const { chainId: chainIdNumber, from } = params[0];\n const chainId = toHex(chainIdNumber);\n const gasBuffer = getGasBuffer(messenger, chainId);\n\n const transactions: BatchTransactionParams[] = params.map(\n (singleParams) => ({\n ...singleParams,\n gas: singleParams.gas ? toHex(singleParams.gas) : undefined,\n maxFeePerGas: undefined,\n maxPriorityFeePerGas: undefined,\n value: toHex(singleParams.value ?? '0'),\n }),\n );\n\n const paramGasLimits = params.map((singleParams) =>\n singleParams.gas ? new BigNumber(singleParams.gas).toNumber() : undefined,\n );\n\n const { totalGasLimit, gasLimits } = await messenger.call(\n 'TransactionController:estimateGasBatch',\n {\n chainId,\n from,\n transactions,\n },\n );\n\n const bufferedGasLimits = gasLimits.map((limit, index) => {\n const useBuffer =\n gasLimits.length === 1 || paramGasLimits[index] !== gasLimits[index];\n\n const buffer = useBuffer ? gasBuffer : 1;\n\n return Math.ceil(limit * buffer);\n });\n\n const bufferedTotalGasLimit = bufferedGasLimits.reduce(\n (acc, limit) => acc + limit,\n 0,\n );\n\n log('Estimated gas limit for batch', {\n chainId,\n totalGasLimit,\n gasLimits,\n bufferedTotalGasLimit,\n bufferedGasLimits,\n gasBuffer,\n });\n\n return {\n totalGasEstimate: bufferedTotalGasLimit,\n totalGasLimit: bufferedTotalGasLimit,\n gasLimits: bufferedGasLimits,\n };\n } catch (error) {\n log('Failed to estimate gas limit for batch', error);\n }\n\n const fallbackGas = getFeatureFlags(messenger).relayFallbackGas;\n\n const totalGasEstimate = params.reduce((acc, singleParams) => {\n const gas = singleParams.gas ?? fallbackGas.estimate;\n return acc + new BigNumber(gas).toNumber();\n }, 0);\n\n const gasLimits = params.map((singleParams) => {\n const gas = singleParams.gas ?? fallbackGas.max;\n return new BigNumber(gas).toNumber();\n });\n\n const totalGasLimit = gasLimits.reduce(\n (acc, singleGasLimit) => acc + singleGasLimit,\n 0,\n );\n\n log('Using fallback gas for batch', {\n totalGasEstimate,\n totalGasLimit,\n gasLimits,\n });\n\n return {\n totalGasEstimate,\n totalGasLimit,\n gasLimits,\n };\n}\n\nfunction getSubsidizedFeeAmountUsd(quote: RelayQuote): BigNumber {\n const subsidizedFee = quote.fees?.subsidized;\n const amountUsd = new BigNumber(subsidizedFee?.amountUsd ?? '0');\n const amountFormatted = new BigNumber(subsidizedFee?.amountFormatted ?? '0');\n\n if (!subsidizedFee || amountUsd.isZero()) {\n return new BigNumber(0);\n }\n\n const isSubsidizedStablecoin = isStablecoin(\n toHex(subsidizedFee.currency.chainId),\n subsidizedFee.currency.address,\n );\n\n return isSubsidizedStablecoin ? amountFormatted : amountUsd;\n}\n\nfunction isStablecoin(chainId: string, tokenAddress: string): boolean {\n return Boolean(\n STABLECOINS[chainId as Hex]?.includes(tokenAddress.toLowerCase() as Hex),\n );\n}\n"]}
1
+ {"version":3,"file":"relay-quotes.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-quotes.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable require-atomic-updates */\n\nimport { Interface } from '@ethersproject/abi';\nimport { toHex } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { TOKEN_TRANSFER_FOUR_BYTE } from './constants';\nimport {\n getGasStationEligibility,\n getGasStationCostInSourceTokenRaw,\n} from './gas-station';\nimport { fetchRelayQuote } from './relay-api';\nimport { getRelayMaxGasStationQuote } from './relay-max-gas-station';\nimport type { RelayQuote, RelayQuoteRequest } from './types';\nimport { TransactionPayStrategy } from '../..';\nimport type {\n BatchTransactionParams,\n TransactionMeta,\n} from '../../../../transaction-controller/src';\nimport {\n ARBITRUM_USDC_ADDRESS,\n CHAIN_ID_ARBITRUM,\n CHAIN_ID_HYPERCORE,\n CHAIN_ID_POLYGON,\n NATIVE_TOKEN_ADDRESS,\n STABLECOINS,\n} from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n Amount,\n FiatRates,\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport { getFiatValueFromUsd } from '../../utils/amounts';\nimport {\n isEIP7702Chain,\n isRelayExecuteEnabled,\n getFeatureFlags,\n getGasBuffer,\n getRelayOriginGasOverhead,\n getSlippage,\n} from '../../utils/feature-flags';\nimport { calculateGasCost } from '../../utils/gas';\nimport {\n getNativeToken,\n getTokenBalance,\n getTokenFiatRate,\n normalizeTokenAddress,\n TokenAddressTarget,\n} from '../../utils/token';\nimport { isPredictWithdrawTransaction } from '../../utils/transaction';\n\nconst log = createModuleLogger(projectLogger, 'relay-strategy');\n\n/**\n * Fetches Relay quotes.\n *\n * @param request - Request object.\n * @returns Array of quotes.\n */\nexport async function getRelayQuotes(\n request: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>[]> {\n const { requests } = request;\n\n log('Fetching quotes', requests);\n\n try {\n const normalizedRequests = requests\n // Ignore gas fee token requests (which have both target=0 and source=0)\n // but keep post-quote requests (identified by isPostQuote flag)\n .filter(\n (singleRequest) =>\n singleRequest.targetAmountMinimum !== '0' ||\n singleRequest.isPostQuote,\n )\n .map((singleRequest) => normalizeRequest(singleRequest));\n\n log('Normalized requests', normalizedRequests);\n\n return await Promise.all(\n normalizedRequests.map((singleRequest) =>\n getQuoteWithMaxAmountHandling(singleRequest, request),\n ),\n );\n } catch (error) {\n log('Error fetching quotes', { error });\n throw new Error(`Failed to fetch Relay quotes: ${String(error)}`);\n }\n}\n\nasync function getQuoteWithMaxAmountHandling(\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const { isMaxAmount } = request;\n\n if (!isMaxAmount) {\n return getQuoteWithPostQuoteGasHandling(request, fullRequest);\n }\n\n return getRelayMaxGasStationQuote(request, fullRequest, getSingleQuote);\n}\n\n/**\n * For post-quote flows, fetch an initial quote to compute gas cost in source\n * token, then re-quote with the source amount reduced by the gas cost.\n * This ensures Relay reserves enough for the gas fee token payment.\n *\n * For non-post-quote flows, just returns a single quote.\n *\n * @param request - Quote request.\n * @param fullRequest - Full request context.\n * @returns The final quote (phase 2 for post-quote, or phase 1 for normal).\n */\nasync function getQuoteWithPostQuoteGasHandling(\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const phase1Quote = await getSingleQuote(request, fullRequest);\n\n if (!request.isPostQuote || !phase1Quote.fees.isSourceGasFeeToken) {\n return phase1Quote;\n }\n\n const gasCostRaw = phase1Quote.fees.sourceNetwork.max.raw;\n\n const adjustedSourceAmount = new BigNumber(request.sourceTokenAmount)\n .minus(gasCostRaw)\n .integerValue(BigNumber.ROUND_DOWN);\n\n log('Subtracting gas from source for post-quote two-call', {\n originalSourceAmount: request.sourceTokenAmount,\n gasCostRaw,\n adjustedSourceAmount: adjustedSourceAmount.toString(10),\n });\n\n if (!adjustedSourceAmount.isGreaterThan(0)) {\n log(\n 'Insufficient balance after gas subtraction for post-quote, using phase 1',\n );\n return phase1Quote;\n }\n\n try {\n const phase2Quote = await getSingleQuote(\n {\n ...request,\n sourceTokenAmount: adjustedSourceAmount.toFixed(\n 0,\n BigNumber.ROUND_DOWN,\n ),\n },\n fullRequest,\n );\n\n if (\n phase1Quote.fees.isSourceGasFeeToken &&\n !phase2Quote.fees.isSourceGasFeeToken\n ) {\n log('Phase 2 lost gas fee token eligibility, falling back to phase 1');\n return phase1Quote;\n }\n\n return phase2Quote;\n } catch (error) {\n log('Phase 2 quote failed, falling back to phase 1', { error });\n return phase1Quote;\n }\n}\n\n/**\n * Fetches a single Relay quote.\n *\n * @param request - Quote request.\n * @param fullRequest - Full quotes request.\n * @returns Single quote.\n */\nasync function getSingleQuote(\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const { messenger, transaction } = fullRequest;\n\n const {\n from,\n isMaxAmount,\n sourceChainId,\n sourceTokenAddress,\n sourceTokenAmount,\n targetAmountMinimum,\n targetChainId,\n targetTokenAddress,\n } = request;\n\n const slippageDecimal = getSlippage(\n messenger,\n sourceChainId,\n sourceTokenAddress,\n );\n\n const slippageTolerance = new BigNumber(slippageDecimal * 100 * 100).toFixed(\n 0,\n );\n\n try {\n // For post-quote or max amount flows, use EXACT_INPUT - user specifies how much to send,\n // and we show them how much they'll receive after fees.\n // For regular flows with a target amount, use EXPECTED_OUTPUT.\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n const useExactInput = isMaxAmount || request.isPostQuote;\n\n const useExecute =\n isRelayExecuteEnabled(messenger) &&\n isEIP7702Chain(messenger, sourceChainId);\n\n const body: RelayQuoteRequest = {\n amount: useExactInput ? sourceTokenAmount : targetAmountMinimum,\n destinationChainId: Number(targetChainId),\n destinationCurrency: targetTokenAddress,\n originChainId: Number(sourceChainId),\n originCurrency: sourceTokenAddress,\n ...(useExecute\n ? { originGasOverhead: getRelayOriginGasOverhead(messenger) }\n : {}),\n recipient: from,\n slippageTolerance,\n tradeType: useExactInput ? 'EXACT_INPUT' : 'EXPECTED_OUTPUT',\n user: from,\n };\n\n // Skip transaction processing for post-quote flows - the original transaction\n // will be included in the batch separately, not as part of the quote\n if (!request.isPostQuote) {\n await processTransactions(transaction, request, body, messenger);\n } else if (request.refundTo) {\n // For post-quote flows, honour the caller-specified refund address so that\n // failed Relay transactions refund to the correct account (e.g. the Predict\n // Safe proxy) rather than defaulting to the EOA.\n body.refundTo = request.refundTo;\n }\n\n log('Request body', body);\n\n const quote = await fetchRelayQuote(messenger, body);\n\n log('Fetched relay quote', quote);\n\n return await normalizeQuote(quote, request, fullRequest);\n } catch (error) {\n log('Error fetching relay quote', error);\n throw error;\n }\n}\n\n/**\n * Add tranasction data to request body if needed.\n *\n * @param transaction - Transaction metadata.\n * @param request - Quote request.\n * @param requestBody - Request body to populate.\n * @param messenger - Controller messenger.\n */\nasync function processTransactions(\n transaction: TransactionMeta,\n request: QuoteRequest,\n requestBody: RelayQuoteRequest,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const { nestedTransactions, txParams } = transaction;\n const { isMaxAmount, targetChainId } = request;\n const data = txParams?.data as Hex | undefined;\n\n const singleData =\n nestedTransactions?.length === 1 ? nestedTransactions[0].data : data;\n\n const isHypercore = targetChainId === CHAIN_ID_HYPERCORE;\n\n const isTokenTransfer =\n !isHypercore && Boolean(singleData?.startsWith(TOKEN_TRANSFER_FOUR_BYTE));\n\n if (isTokenTransfer) {\n requestBody.recipient = getTransferRecipient(singleData as Hex);\n\n log('Updating recipient as token transfer', requestBody.recipient);\n }\n\n const hasNoData = singleData === undefined || singleData === '0x';\n const skipDelegation = hasNoData || isTokenTransfer || isHypercore;\n\n if (skipDelegation) {\n log('Skipping delegation as token transfer or Hypercore deposit');\n return;\n }\n\n if (isMaxAmount) {\n throw new Error('Max amount quotes do not support included transactions');\n }\n\n const delegation = await messenger.call(\n 'TransactionPayController:getDelegationTransaction',\n { transaction },\n );\n\n const normalizedAuthorizationList = delegation.authorizationList?.map(\n (a) => ({\n ...a,\n chainId: Number(a.chainId),\n nonce: Number(a.nonce),\n r: a.r as Hex,\n s: a.s as Hex,\n yParity: Number(a.yParity),\n }),\n );\n\n requestBody.authorizationList = normalizedAuthorizationList;\n requestBody.tradeType = 'EXACT_OUTPUT';\n\n const tokenTransferData = nestedTransactions?.find((nestedTx) =>\n nestedTx.data?.startsWith(TOKEN_TRANSFER_FOUR_BYTE),\n )?.data;\n\n // If the transactions include a token transfer, change the recipient\n // so any extra dust is also sent to the same address, rather than back to the user.\n if (tokenTransferData) {\n requestBody.recipient = getTransferRecipient(tokenTransferData);\n requestBody.refundTo = request.from;\n }\n\n requestBody.txs = [\n {\n to: request.targetTokenAddress,\n data: buildTokenTransferData(request.from, request.targetAmountMinimum),\n value: '0x0',\n },\n {\n to: delegation.to,\n data: delegation.data,\n value: delegation.value,\n },\n ];\n}\n\n/**\n * Normalizes requests for Relay.\n *\n * @param request - Quote request to normalize.\n * @returns Normalized request.\n */\nfunction normalizeRequest(request: QuoteRequest): QuoteRequest {\n const newRequest = {\n ...request,\n };\n\n const isHyperliquidDeposit =\n !request.isPostQuote &&\n request.targetChainId === CHAIN_ID_ARBITRUM &&\n request.targetTokenAddress.toLowerCase() ===\n ARBITRUM_USDC_ADDRESS.toLowerCase();\n\n newRequest.sourceTokenAddress = normalizeTokenAddress(\n newRequest.sourceTokenAddress,\n newRequest.sourceChainId,\n TokenAddressTarget.Relay,\n );\n newRequest.targetTokenAddress = normalizeTokenAddress(\n newRequest.targetTokenAddress,\n newRequest.targetChainId,\n TokenAddressTarget.Relay,\n );\n\n if (isHyperliquidDeposit) {\n newRequest.targetChainId = CHAIN_ID_HYPERCORE;\n newRequest.targetTokenAddress = '0x00000000000000000000000000000000';\n newRequest.targetAmountMinimum = new BigNumber(request.targetAmountMinimum)\n .shiftedBy(2)\n .toString(10);\n\n log('Converting Arbitrum Hyperliquid deposit to direct deposit', {\n originalRequest: request,\n normalizedRequest: newRequest,\n });\n }\n\n return newRequest;\n}\n\n/**\n * Normalizes a Relay quote into a TransactionPayQuote.\n *\n * @param quote - Relay quote.\n * @param request - Original quote request.\n * @param fullRequest - Full quotes request.\n * @returns Normalized quote.\n */\nasync function normalizeQuote(\n quote: RelayQuote,\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const { messenger } = fullRequest;\n const { details } = quote;\n const { currencyIn, currencyOut } = details;\n\n const { usdToFiatRate } = getFiatRates(messenger, request);\n\n const dust = getFiatValueFromUsd(\n calculateDustUsd(quote, request),\n usdToFiatRate,\n );\n\n const subsidizedFeeUsd = getSubsidizedFeeAmountUsd(quote);\n\n const appFeeUsd = new BigNumber(quote.fees?.app?.amountUsd ?? '0');\n const metaMaskFee = getFiatValueFromUsd(appFeeUsd, usdToFiatRate);\n\n // Subtract app fee from provider fee since totalImpact.usd already includes it\n const providerFeeUsd = calculateProviderFee(quote).minus(appFeeUsd);\n const provider = subsidizedFeeUsd.gt(0)\n ? { usd: '0', fiat: '0' }\n : getFiatValueFromUsd(providerFeeUsd, usdToFiatRate);\n\n const {\n gasLimits,\n isGasFeeToken: isSourceGasFeeToken,\n ...sourceNetwork\n } = await calculateSourceNetworkCost(\n quote,\n messenger,\n request,\n fullRequest.transaction,\n );\n\n const targetNetwork = {\n usd: '0',\n fiat: '0',\n };\n\n const sourceAmount: Amount = {\n human: currencyIn.amountFormatted,\n raw: currencyIn.amount,\n ...getFiatValueFromUsd(new BigNumber(currencyIn.amountUsd), usdToFiatRate),\n };\n\n const isTargetStablecoin = isStablecoin(\n request.targetChainId,\n request.targetTokenAddress,\n );\n\n const additionalTargetAmountUsd =\n quote.request.tradeType === 'EXACT_INPUT'\n ? subsidizedFeeUsd\n : new BigNumber(0);\n\n if (additionalTargetAmountUsd.gt(0)) {\n log(\n 'Including subsidized fee in target amount',\n additionalTargetAmountUsd.toString(10),\n );\n }\n\n const baseTargetAmountUsd = isTargetStablecoin\n ? new BigNumber(currencyOut.amountFormatted)\n : new BigNumber(currencyOut.amountUsd);\n\n const targetAmountUsd = baseTargetAmountUsd.plus(additionalTargetAmountUsd);\n\n const targetAmount = getFiatValueFromUsd(targetAmountUsd, usdToFiatRate);\n\n const metamask = {\n gasLimits,\n };\n\n return {\n dust,\n estimatedDuration: details.timeEstimate,\n fees: {\n isSourceGasFeeToken,\n metaMask: metaMaskFee,\n provider,\n sourceNetwork,\n targetNetwork,\n },\n original: {\n ...quote,\n metamask,\n },\n request,\n sourceAmount,\n targetAmount,\n strategy: TransactionPayStrategy.Relay,\n };\n}\n\n/**\n * Calculate dust USD value.\n *\n * @param quote - Relay quote.\n * @param request - Quote request.\n * @returns Dust value in USD and fiat.\n */\nfunction calculateDustUsd(quote: RelayQuote, request: QuoteRequest): BigNumber {\n const { currencyOut } = quote.details;\n const { amountUsd, amountFormatted, minimumAmount } = currencyOut;\n const { decimals: targetDecimals } = currencyOut.currency;\n\n const targetUsdRate = new BigNumber(amountUsd).dividedBy(amountFormatted);\n\n const dustRaw = new BigNumber(minimumAmount).minus(\n request.targetAmountMinimum,\n );\n\n return dustRaw.shiftedBy(-targetDecimals).multipliedBy(targetUsdRate);\n}\n\n/**\n * Calculates USD to fiat rate.\n *\n * @param messenger - Controller messenger.\n * @param request - Quote request.\n * @returns USD to fiat rate.\n */\nfunction getFiatRates(\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n): {\n sourceFiatRate: FiatRates;\n usdToFiatRate: BigNumber;\n} {\n const { sourceChainId, sourceTokenAddress } = request;\n\n const finalSourceTokenAddress =\n sourceChainId === CHAIN_ID_POLYGON &&\n sourceTokenAddress === NATIVE_TOKEN_ADDRESS\n ? getNativeToken(sourceChainId)\n : sourceTokenAddress;\n\n const sourceFiatRate = getTokenFiatRate(\n messenger,\n finalSourceTokenAddress,\n sourceChainId,\n );\n\n if (!sourceFiatRate) {\n throw new Error('Source token fiat rate not found');\n }\n\n const usdToFiatRate = new BigNumber(sourceFiatRate.fiatRate).dividedBy(\n sourceFiatRate.usdRate,\n );\n\n return { sourceFiatRate, usdToFiatRate };\n}\n\n/**\n * Calculates source network cost from a Relay quote.\n *\n * For post-quote flows (e.g. predictWithdraw), the cost also includes the\n * original transaction's gas (the user's Polygon USDC.e transfer) in addition\n * to the Relay deposit transaction gas, by appending the original\n * transaction's params so that gas estimation and gas-fee-token logic handle\n * both transactions together.\n *\n * @param quote - Relay quote.\n * @param messenger - Controller messenger.\n * @param request - Quote request.\n * @param transaction - Original transaction metadata.\n * @returns Total source network cost in USD and fiat.\n */\nasync function calculateSourceNetworkCost(\n quote: RelayQuote,\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n transaction: TransactionMeta,\n): Promise<\n TransactionPayQuote<RelayQuote>['fees']['sourceNetwork'] & {\n gasLimits: number[];\n isGasFeeToken?: boolean;\n }\n> {\n const { from, sourceChainId, sourceTokenAddress } = request;\n\n const relayParams = quote.steps\n .flatMap((step) => step.items)\n .map((item) => item.data);\n\n const { chainId, data, maxFeePerGas, maxPriorityFeePerGas, to, value } =\n relayParams[0];\n\n const isPredictWithdraw =\n request.isPostQuote && isPredictWithdrawTransaction(transaction);\n\n const fromOverride = isPredictWithdraw ? request.refundTo : undefined;\n\n const relayOnlyGas = await calculateSourceNetworkGasLimit(\n relayParams,\n messenger,\n fromOverride,\n );\n\n const { totalGasEstimate, totalGasLimit, gasLimits } = request.isPostQuote\n ? combinePostQuoteGas(relayOnlyGas, transaction)\n : relayOnlyGas;\n\n log('Gas limit', {\n totalGasEstimate,\n totalGasLimit,\n gasLimits,\n });\n\n const estimate = calculateGasCost({\n chainId,\n gas: totalGasEstimate,\n maxFeePerGas,\n maxPriorityFeePerGas,\n messenger,\n });\n\n const max = calculateGasCost({\n chainId,\n gas: totalGasLimit,\n maxFeePerGas,\n maxPriorityFeePerGas,\n messenger,\n isMax: true,\n });\n\n const nativeBalance = getTokenBalance(\n messenger,\n from,\n sourceChainId,\n getNativeToken(sourceChainId),\n );\n\n const result = { estimate, max, gasLimits };\n\n if (new BigNumber(nativeBalance).isGreaterThanOrEqualTo(max.raw)) {\n return result;\n }\n\n const gasStationEligibility = getGasStationEligibility(\n messenger,\n sourceChainId,\n );\n\n if (gasStationEligibility.isDisabledChain) {\n log('Skipping gas station as disabled chain', {\n sourceChainId,\n });\n\n return result;\n }\n\n if (!gasStationEligibility.chainSupportsGasStation) {\n log('Skipping gas station as chain does not support EIP-7702', {\n sourceChainId,\n });\n\n return result;\n }\n\n log('Checking gas fee tokens as insufficient native balance', {\n nativeBalance,\n max: max.raw,\n });\n\n if (isPredictWithdraw && request.refundTo) {\n log('Using proxy address for predict withdraw gas station simulation', {\n proxyAddress: request.refundTo,\n sourceTokenAddress,\n totalGasEstimate,\n });\n\n const gasFeeTokenCost = await getGasStationCostInSourceTokenRaw({\n firstStepData: {\n data,\n to,\n value,\n },\n messenger,\n request: {\n from: request.refundTo,\n sourceChainId,\n sourceTokenAddress,\n },\n totalGasEstimate,\n totalItemCount: relayParams.length + 1,\n });\n\n if (gasFeeTokenCost) {\n log('Using predict withdraw gas fee token for source network', {\n gasFeeTokenCost,\n });\n\n return {\n isGasFeeToken: true,\n estimate: gasFeeTokenCost,\n max: gasFeeTokenCost,\n gasLimits,\n };\n }\n\n return result;\n }\n\n const gasFeeTokenCost = await getGasStationCostInSourceTokenRaw({\n firstStepData: {\n data,\n to,\n value,\n },\n messenger,\n request: {\n from,\n sourceChainId,\n sourceTokenAddress,\n },\n totalGasEstimate,\n totalItemCount: Math.max(relayParams.length, gasLimits.length),\n });\n\n if (!gasFeeTokenCost) {\n return result;\n }\n\n log('Using gas fee token for source network', {\n gasFeeTokenCost,\n });\n\n return {\n isGasFeeToken: true,\n estimate: gasFeeTokenCost,\n max: gasFeeTokenCost,\n gasLimits,\n };\n}\n\n/**\n * Calculate the total gas limit for the source network.\n *\n * @param params - Array of relay transaction parameters.\n * @param messenger - Controller messenger.\n * @param fromOverride - Optional address to use as `from` in gas estimation\n * instead of the address in the relay params. Used in predict withdraw flows\n * to estimate with the proxy/Safe address that holds the source token balance.\n * @returns Total gas estimates and per-transaction gas limits.\n */\nasync function calculateSourceNetworkGasLimit(\n params: RelayQuote['steps'][0]['items'][0]['data'][],\n messenger: TransactionPayControllerMessenger,\n fromOverride?: Hex,\n): Promise<{\n totalGasEstimate: number;\n totalGasLimit: number;\n gasLimits: number[];\n}> {\n return params.length === 1\n ? calculateSourceNetworkGasLimitSingle(params[0], messenger, fromOverride)\n : calculateSourceNetworkGasLimitBatch(params, messenger, fromOverride);\n}\n\n/**\n * Combine the original transaction's gas with relay gas for post-quote flows.\n *\n * Prefers gas from `nestedTransactions` (preserves the caller-provided value)\n * since TransactionController may re-estimate `txParams.gas` during batch\n * creation.\n *\n * @param relayGas - Gas estimates from relay transactions.\n * @param relayGas.totalGasEstimate - Estimated gas total.\n * @param relayGas.totalGasLimit - Maximum gas total.\n * @param relayGas.gasLimits - Per-transaction gas limits.\n * @param transaction - Original transaction metadata.\n * @returns Combined gas estimates including the original transaction.\n */\nfunction combinePostQuoteGas(\n relayGas: {\n totalGasEstimate: number;\n totalGasLimit: number;\n gasLimits: number[];\n },\n transaction: TransactionMeta,\n): { totalGasEstimate: number; totalGasLimit: number; gasLimits: number[] } {\n const nestedGas = transaction.nestedTransactions?.find((tx) => tx.gas)?.gas;\n const rawGas = nestedGas ?? transaction.txParams.gas;\n const originalTxGas = rawGas ? new BigNumber(rawGas).toNumber() : undefined;\n\n if (originalTxGas === undefined) {\n return relayGas;\n }\n\n let { gasLimits } = relayGas;\n // TODO: Test EIP-7702 support on the chain as well before assuming single gas limit.\n const isEIP7702 = gasLimits.length === 1;\n\n if (isEIP7702) {\n // Single gas limit (either one relay param or 7702 combined) —\n // add the original tx gas so the batch uses a single 7702 limit.\n gasLimits = [gasLimits[0] + originalTxGas];\n } else {\n // Multiple individual gas limits — prepend the original tx gas\n // so the list order matches relay-submit's transaction order.\n gasLimits = [originalTxGas, ...gasLimits];\n }\n\n const totalGasEstimate = relayGas.totalGasEstimate + originalTxGas;\n const totalGasLimit = relayGas.totalGasLimit + originalTxGas;\n\n log('Combined original tx gas with relay gas', {\n originalTxGas,\n isEIP7702,\n gasLimits,\n totalGasLimit,\n });\n\n return { totalGasEstimate, totalGasLimit, gasLimits };\n}\n\n/**\n * Calculate the provider fee for a Relay quote.\n *\n * @param quote - Relay quote.\n * @returns - Provider fee in USD.\n */\nfunction calculateProviderFee(quote: RelayQuote): BigNumber {\n return new BigNumber(quote.details.totalImpact.usd).abs();\n}\n\n/**\n * Build token transfer data.\n *\n * @param recipient - Recipient address.\n * @param amountRaw - Amount in raw format.\n * @returns Token transfer data.\n */\nfunction buildTokenTransferData(recipient: Hex, amountRaw: string): Hex {\n return new Interface([\n 'function transfer(address to, uint256 amount)',\n ]).encodeFunctionData('transfer', [recipient, amountRaw]) as Hex;\n}\n\n/**\n * Get transfer recipient from token transfer data.\n *\n * @param data - Token transfer data.\n * @returns Transfer recipient.\n */\nfunction getTransferRecipient(data: Hex): Hex {\n return new Interface(['function transfer(address to, uint256 amount)'])\n .decodeFunctionData('transfer', data)\n .to.toLowerCase();\n}\n\nasync function calculateSourceNetworkGasLimitSingle(\n params: RelayQuote['steps'][0]['items'][0]['data'],\n messenger: TransactionPayControllerMessenger,\n fromOverride?: Hex,\n): Promise<{\n totalGasEstimate: number;\n totalGasLimit: number;\n gasLimits: number[];\n}> {\n const paramGasLimit = params.gas\n ? new BigNumber(params.gas).toNumber()\n : undefined;\n\n if (paramGasLimit && !fromOverride) {\n log('Using single gas limit from params', { paramGasLimit });\n\n return {\n totalGasEstimate: paramGasLimit,\n totalGasLimit: paramGasLimit,\n gasLimits: [paramGasLimit],\n };\n }\n\n try {\n const {\n chainId: chainIdNumber,\n data,\n from: paramsFrom,\n to,\n value: valueString,\n } = params;\n\n const from = fromOverride ?? paramsFrom;\n const chainId = toHex(chainIdNumber);\n const value = toHex(valueString ?? '0');\n const gasBuffer = getGasBuffer(messenger, chainId);\n\n const networkClientId = messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n chainId,\n );\n\n const { gas: gasHex, simulationFails } = await messenger.call(\n 'TransactionController:estimateGas',\n { from, data, to, value },\n networkClientId,\n );\n\n const estimatedGas = new BigNumber(gasHex).toNumber();\n const bufferedGas = Math.ceil(estimatedGas * gasBuffer);\n\n if (!simulationFails) {\n log('Estimated gas limit for single transaction', {\n chainId,\n estimatedGas,\n bufferedGas,\n gasBuffer,\n });\n\n return {\n totalGasEstimate: bufferedGas,\n totalGasLimit: bufferedGas,\n gasLimits: [bufferedGas],\n };\n }\n } catch (error) {\n log('Failed to estimate gas limit for single transaction', error);\n }\n\n const fallbackGas = getFeatureFlags(messenger).relayFallbackGas;\n\n log('Using fallback gas for single transaction', { fallbackGas });\n\n return {\n totalGasEstimate: fallbackGas.estimate,\n totalGasLimit: fallbackGas.max,\n gasLimits: [fallbackGas.max],\n };\n}\n\n/**\n * Calculate the gas limits for a batch of transactions.\n *\n * @param params - Array of transaction parameters.\n * @param messenger - Controller messenger.\n * @param fromOverride - Optional address to use as `from` in gas estimation.\n * @returns - Gas limits.\n */\nasync function calculateSourceNetworkGasLimitBatch(\n params: RelayQuote['steps'][0]['items'][0]['data'][],\n messenger: TransactionPayControllerMessenger,\n fromOverride?: Hex,\n): Promise<{\n totalGasEstimate: number;\n totalGasLimit: number;\n gasLimits: number[];\n}> {\n try {\n const { chainId: chainIdNumber, from: paramsFrom } = params[0];\n const from = fromOverride ?? paramsFrom;\n const chainId = toHex(chainIdNumber);\n const gasBuffer = getGasBuffer(messenger, chainId);\n\n const transactions: BatchTransactionParams[] = params.map(\n (singleParams) => ({\n ...singleParams,\n gas:\n !fromOverride && singleParams.gas\n ? toHex(singleParams.gas)\n : undefined,\n maxFeePerGas: undefined,\n maxPriorityFeePerGas: undefined,\n value: toHex(singleParams.value ?? '0'),\n }),\n );\n\n const paramGasLimits = params.map((singleParams) =>\n singleParams.gas ? new BigNumber(singleParams.gas).toNumber() : undefined,\n );\n\n const { totalGasLimit, gasLimits } = await messenger.call(\n 'TransactionController:estimateGasBatch',\n {\n chainId,\n from,\n transactions,\n },\n );\n\n const bufferedGasLimits = gasLimits.map((limit, index) => {\n const useBuffer =\n gasLimits.length === 1 || paramGasLimits[index] !== gasLimits[index];\n\n const buffer = useBuffer ? gasBuffer : 1;\n\n return Math.ceil(limit * buffer);\n });\n\n const bufferedTotalGasLimit = bufferedGasLimits.reduce(\n (acc, limit) => acc + limit,\n 0,\n );\n\n log('Estimated gas limit for batch', {\n chainId,\n totalGasLimit,\n gasLimits,\n bufferedTotalGasLimit,\n bufferedGasLimits,\n gasBuffer,\n });\n\n return {\n totalGasEstimate: bufferedTotalGasLimit,\n totalGasLimit: bufferedTotalGasLimit,\n gasLimits: bufferedGasLimits,\n };\n } catch (error) {\n log('Failed to estimate gas limit for batch', error);\n }\n\n const fallbackGas = getFeatureFlags(messenger).relayFallbackGas;\n\n const totalGasEstimate = params.reduce((acc, singleParams) => {\n const gas = singleParams.gas ?? fallbackGas.estimate;\n return acc + new BigNumber(gas).toNumber();\n }, 0);\n\n const gasLimits = params.map((singleParams) => {\n const gas = singleParams.gas ?? fallbackGas.max;\n return new BigNumber(gas).toNumber();\n });\n\n const totalGasLimit = gasLimits.reduce(\n (acc, singleGasLimit) => acc + singleGasLimit,\n 0,\n );\n\n log('Using fallback gas for batch', {\n totalGasEstimate,\n totalGasLimit,\n gasLimits,\n });\n\n return {\n totalGasEstimate,\n totalGasLimit,\n gasLimits,\n };\n}\n\nfunction getSubsidizedFeeAmountUsd(quote: RelayQuote): BigNumber {\n const subsidizedFee = quote.fees?.subsidized;\n const amountUsd = new BigNumber(subsidizedFee?.amountUsd ?? '0');\n const amountFormatted = new BigNumber(subsidizedFee?.amountFormatted ?? '0');\n\n if (!subsidizedFee || amountUsd.isZero()) {\n return new BigNumber(0);\n }\n\n const isSubsidizedStablecoin = isStablecoin(\n toHex(subsidizedFee.currency.chainId),\n subsidizedFee.currency.address,\n );\n\n return isSubsidizedStablecoin ? amountFormatted : amountUsd;\n}\n\nfunction isStablecoin(chainId: string, tokenAddress: string): boolean {\n return Boolean(\n STABLECOINS[chainId as Hex]?.includes(tokenAddress.toLowerCase() as Hex),\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"relay-quotes.d.cts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-quotes.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,UAAU,EAAqB,oBAAgB;AAe7D,OAAO,KAAK,EAGV,2BAA2B,EAG3B,mBAAmB,EACpB,wBAAoB;AAqBrB;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE,CAAC,CA2B5C"}
1
+ {"version":3,"file":"relay-quotes.d.cts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-quotes.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,UAAU,EAAqB,oBAAgB;AAe7D,OAAO,KAAK,EAGV,2BAA2B,EAG3B,mBAAmB,EACpB,wBAAoB;AAsBrB;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE,CAAC,CA2B5C"}
@@ -1 +1 @@
1
- {"version":3,"file":"relay-quotes.d.mts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-quotes.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,UAAU,EAAqB,oBAAgB;AAe7D,OAAO,KAAK,EAGV,2BAA2B,EAG3B,mBAAmB,EACpB,wBAAoB;AAqBrB;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE,CAAC,CA2B5C"}
1
+ {"version":3,"file":"relay-quotes.d.mts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-quotes.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,UAAU,EAAqB,oBAAgB;AAe7D,OAAO,KAAK,EAGV,2BAA2B,EAG3B,mBAAmB,EACpB,wBAAoB;AAsBrB;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE,CAAC,CA2B5C"}