@metamask/transaction-pay-controller 19.0.3 → 19.1.1

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 (184) hide show
  1. package/CHANGELOG.md +28 -1
  2. package/dist/helpers/TransactionPayPublishHook.cjs +8 -0
  3. package/dist/helpers/TransactionPayPublishHook.cjs.map +1 -1
  4. package/dist/helpers/TransactionPayPublishHook.d.cts.map +1 -1
  5. package/dist/helpers/TransactionPayPublishHook.d.mts.map +1 -1
  6. package/dist/helpers/TransactionPayPublishHook.mjs +8 -0
  7. package/dist/helpers/TransactionPayPublishHook.mjs.map +1 -1
  8. package/dist/strategy/across/AcrossStrategy.cjs +4 -3
  9. package/dist/strategy/across/AcrossStrategy.cjs.map +1 -1
  10. package/dist/strategy/across/AcrossStrategy.d.cts +1 -1
  11. package/dist/strategy/across/AcrossStrategy.d.cts.map +1 -1
  12. package/dist/strategy/across/AcrossStrategy.d.mts +1 -1
  13. package/dist/strategy/across/AcrossStrategy.d.mts.map +1 -1
  14. package/dist/strategy/across/AcrossStrategy.mjs +4 -3
  15. package/dist/strategy/across/AcrossStrategy.mjs.map +1 -1
  16. package/dist/strategy/across/across-actions.cjs +7 -0
  17. package/dist/strategy/across/across-actions.cjs.map +1 -1
  18. package/dist/strategy/across/across-actions.d.cts +1 -1
  19. package/dist/strategy/across/across-actions.d.cts.map +1 -1
  20. package/dist/strategy/across/across-actions.d.mts +1 -1
  21. package/dist/strategy/across/across-actions.d.mts.map +1 -1
  22. package/dist/strategy/across/across-actions.mjs +7 -0
  23. package/dist/strategy/across/across-actions.mjs.map +1 -1
  24. package/dist/strategy/across/across-quotes.cjs +6 -4
  25. package/dist/strategy/across/across-quotes.cjs.map +1 -1
  26. package/dist/strategy/across/across-quotes.d.cts +1 -1
  27. package/dist/strategy/across/across-quotes.d.cts.map +1 -1
  28. package/dist/strategy/across/across-quotes.d.mts +1 -1
  29. package/dist/strategy/across/across-quotes.d.mts.map +1 -1
  30. package/dist/strategy/across/across-quotes.mjs +6 -4
  31. package/dist/strategy/across/across-quotes.mjs.map +1 -1
  32. package/dist/strategy/across/across-submit.cjs +1 -1
  33. package/dist/strategy/across/across-submit.cjs.map +1 -1
  34. package/dist/strategy/across/across-submit.d.cts +1 -1
  35. package/dist/strategy/across/across-submit.d.cts.map +1 -1
  36. package/dist/strategy/across/across-submit.d.mts +1 -1
  37. package/dist/strategy/across/across-submit.d.mts.map +1 -1
  38. package/dist/strategy/across/across-submit.mjs +1 -1
  39. package/dist/strategy/across/across-submit.mjs.map +1 -1
  40. package/dist/strategy/across/perps.cjs +56 -0
  41. package/dist/strategy/across/perps.cjs.map +1 -0
  42. package/dist/strategy/across/perps.d.cts +32 -0
  43. package/dist/strategy/across/perps.d.cts.map +1 -0
  44. package/dist/strategy/across/perps.d.mts +32 -0
  45. package/dist/strategy/across/perps.d.mts.map +1 -0
  46. package/dist/strategy/across/perps.mjs +51 -0
  47. package/dist/strategy/across/perps.mjs.map +1 -0
  48. package/dist/strategy/bridge/BridgeStrategy.cjs.map +1 -1
  49. package/dist/strategy/bridge/BridgeStrategy.d.cts +1 -1
  50. package/dist/strategy/bridge/BridgeStrategy.d.cts.map +1 -1
  51. package/dist/strategy/bridge/BridgeStrategy.d.mts +1 -1
  52. package/dist/strategy/bridge/BridgeStrategy.d.mts.map +1 -1
  53. package/dist/strategy/bridge/BridgeStrategy.mjs.map +1 -1
  54. package/dist/strategy/bridge/bridge-quotes.cjs.map +1 -1
  55. package/dist/strategy/bridge/bridge-quotes.d.cts +1 -1
  56. package/dist/strategy/bridge/bridge-quotes.d.cts.map +1 -1
  57. package/dist/strategy/bridge/bridge-quotes.d.mts +1 -1
  58. package/dist/strategy/bridge/bridge-quotes.d.mts.map +1 -1
  59. package/dist/strategy/bridge/bridge-quotes.mjs.map +1 -1
  60. package/dist/strategy/bridge/bridge-submit.cjs +1 -1
  61. package/dist/strategy/bridge/bridge-submit.cjs.map +1 -1
  62. package/dist/strategy/bridge/bridge-submit.d.cts +1 -1
  63. package/dist/strategy/bridge/bridge-submit.d.cts.map +1 -1
  64. package/dist/strategy/bridge/bridge-submit.d.mts +1 -1
  65. package/dist/strategy/bridge/bridge-submit.d.mts.map +1 -1
  66. package/dist/strategy/bridge/bridge-submit.mjs +1 -1
  67. package/dist/strategy/bridge/bridge-submit.mjs.map +1 -1
  68. package/dist/strategy/fiat/FiatStrategy.cjs.map +1 -1
  69. package/dist/strategy/fiat/FiatStrategy.d.cts +1 -1
  70. package/dist/strategy/fiat/FiatStrategy.d.cts.map +1 -1
  71. package/dist/strategy/fiat/FiatStrategy.d.mts +1 -1
  72. package/dist/strategy/fiat/FiatStrategy.d.mts.map +1 -1
  73. package/dist/strategy/fiat/FiatStrategy.mjs.map +1 -1
  74. package/dist/strategy/fiat/fiat-quotes.cjs +1 -1
  75. package/dist/strategy/fiat/fiat-quotes.cjs.map +1 -1
  76. package/dist/strategy/fiat/fiat-quotes.d.cts +1 -1
  77. package/dist/strategy/fiat/fiat-quotes.d.cts.map +1 -1
  78. package/dist/strategy/fiat/fiat-quotes.d.mts +1 -1
  79. package/dist/strategy/fiat/fiat-quotes.d.mts.map +1 -1
  80. package/dist/strategy/fiat/fiat-quotes.mjs +1 -1
  81. package/dist/strategy/fiat/fiat-quotes.mjs.map +1 -1
  82. package/dist/strategy/fiat/fiat-submit.cjs.map +1 -1
  83. package/dist/strategy/fiat/fiat-submit.d.cts +1 -1
  84. package/dist/strategy/fiat/fiat-submit.d.cts.map +1 -1
  85. package/dist/strategy/fiat/fiat-submit.d.mts +1 -1
  86. package/dist/strategy/fiat/fiat-submit.d.mts.map +1 -1
  87. package/dist/strategy/fiat/fiat-submit.mjs.map +1 -1
  88. package/dist/strategy/relay/RelayStrategy.cjs +1 -1
  89. package/dist/strategy/relay/RelayStrategy.cjs.map +1 -1
  90. package/dist/strategy/relay/RelayStrategy.d.cts +1 -1
  91. package/dist/strategy/relay/RelayStrategy.d.cts.map +1 -1
  92. package/dist/strategy/relay/RelayStrategy.d.mts +1 -1
  93. package/dist/strategy/relay/RelayStrategy.d.mts.map +1 -1
  94. package/dist/strategy/relay/RelayStrategy.mjs +1 -1
  95. package/dist/strategy/relay/RelayStrategy.mjs.map +1 -1
  96. package/dist/strategy/relay/hyperliquid-withdraw.cjs +5 -5
  97. package/dist/strategy/relay/hyperliquid-withdraw.cjs.map +1 -1
  98. package/dist/strategy/relay/hyperliquid-withdraw.d.cts +1 -1
  99. package/dist/strategy/relay/hyperliquid-withdraw.d.cts.map +1 -1
  100. package/dist/strategy/relay/hyperliquid-withdraw.d.mts +1 -1
  101. package/dist/strategy/relay/hyperliquid-withdraw.d.mts.map +1 -1
  102. package/dist/strategy/relay/hyperliquid-withdraw.mjs +1 -1
  103. package/dist/strategy/relay/hyperliquid-withdraw.mjs.map +1 -1
  104. package/dist/strategy/relay/relay-api.cjs +1 -1
  105. package/dist/strategy/relay/relay-api.cjs.map +1 -1
  106. package/dist/strategy/relay/relay-api.d.cts +1 -1
  107. package/dist/strategy/relay/relay-api.d.cts.map +1 -1
  108. package/dist/strategy/relay/relay-api.d.mts +1 -1
  109. package/dist/strategy/relay/relay-api.d.mts.map +1 -1
  110. package/dist/strategy/relay/relay-api.mjs +1 -1
  111. package/dist/strategy/relay/relay-api.mjs.map +1 -1
  112. package/dist/strategy/relay/relay-max-gas-station.cjs +1 -1
  113. package/dist/strategy/relay/relay-max-gas-station.cjs.map +1 -1
  114. package/dist/strategy/relay/relay-max-gas-station.d.cts +1 -1
  115. package/dist/strategy/relay/relay-max-gas-station.d.cts.map +1 -1
  116. package/dist/strategy/relay/relay-max-gas-station.d.mts +1 -1
  117. package/dist/strategy/relay/relay-max-gas-station.d.mts.map +1 -1
  118. package/dist/strategy/relay/relay-max-gas-station.mjs +1 -1
  119. package/dist/strategy/relay/relay-max-gas-station.mjs.map +1 -1
  120. package/dist/strategy/relay/relay-quotes.cjs +21 -21
  121. package/dist/strategy/relay/relay-quotes.cjs.map +1 -1
  122. package/dist/strategy/relay/relay-quotes.d.cts +1 -1
  123. package/dist/strategy/relay/relay-quotes.d.cts.map +1 -1
  124. package/dist/strategy/relay/relay-quotes.d.mts +1 -1
  125. package/dist/strategy/relay/relay-quotes.d.mts.map +1 -1
  126. package/dist/strategy/relay/relay-quotes.mjs +4 -4
  127. package/dist/strategy/relay/relay-quotes.mjs.map +1 -1
  128. package/dist/strategy/relay/relay-submit.cjs +3 -3
  129. package/dist/strategy/relay/relay-submit.cjs.map +1 -1
  130. package/dist/strategy/relay/relay-submit.d.cts +1 -1
  131. package/dist/strategy/relay/relay-submit.d.cts.map +1 -1
  132. package/dist/strategy/relay/relay-submit.d.mts +1 -1
  133. package/dist/strategy/relay/relay-submit.d.mts.map +1 -1
  134. package/dist/strategy/relay/relay-submit.mjs +3 -3
  135. package/dist/strategy/relay/relay-submit.mjs.map +1 -1
  136. package/dist/tests/messenger-mock.cjs.map +1 -1
  137. package/dist/tests/messenger-mock.d.cts.map +1 -1
  138. package/dist/tests/messenger-mock.d.mts.map +1 -1
  139. package/dist/tests/messenger-mock.mjs.map +1 -1
  140. package/dist/utils/gas.cjs +1 -1
  141. package/dist/utils/gas.cjs.map +1 -1
  142. package/dist/utils/gas.d.cts.map +1 -1
  143. package/dist/utils/gas.d.mts.map +1 -1
  144. package/dist/utils/gas.mjs +1 -1
  145. package/dist/utils/gas.mjs.map +1 -1
  146. package/dist/utils/quote-gas.cjs +1 -1
  147. package/dist/utils/quote-gas.cjs.map +1 -1
  148. package/dist/utils/quote-gas.d.cts.map +1 -1
  149. package/dist/utils/quote-gas.d.mts.map +1 -1
  150. package/dist/utils/quote-gas.mjs +1 -1
  151. package/dist/utils/quote-gas.mjs.map +1 -1
  152. package/dist/utils/quotes.cjs +2 -2
  153. package/dist/utils/quotes.cjs.map +1 -1
  154. package/dist/utils/quotes.d.cts.map +1 -1
  155. package/dist/utils/quotes.d.mts.map +1 -1
  156. package/dist/utils/quotes.mjs +2 -2
  157. package/dist/utils/quotes.mjs.map +1 -1
  158. package/dist/utils/required-tokens.cjs.map +1 -1
  159. package/dist/utils/required-tokens.d.cts.map +1 -1
  160. package/dist/utils/required-tokens.d.mts.map +1 -1
  161. package/dist/utils/required-tokens.mjs.map +1 -1
  162. package/dist/utils/source-amounts.cjs +25 -19
  163. package/dist/utils/source-amounts.cjs.map +1 -1
  164. package/dist/utils/source-amounts.d.cts.map +1 -1
  165. package/dist/utils/source-amounts.d.mts.map +1 -1
  166. package/dist/utils/source-amounts.mjs +25 -19
  167. package/dist/utils/source-amounts.mjs.map +1 -1
  168. package/dist/utils/token.cjs +1 -1
  169. package/dist/utils/token.cjs.map +1 -1
  170. package/dist/utils/token.d.cts.map +1 -1
  171. package/dist/utils/token.d.mts.map +1 -1
  172. package/dist/utils/token.mjs +1 -1
  173. package/dist/utils/token.mjs.map +1 -1
  174. package/dist/utils/totals.cjs.map +1 -1
  175. package/dist/utils/totals.d.cts.map +1 -1
  176. package/dist/utils/totals.d.mts.map +1 -1
  177. package/dist/utils/totals.mjs.map +1 -1
  178. package/dist/utils/transaction.cjs +1 -1
  179. package/dist/utils/transaction.cjs.map +1 -1
  180. package/dist/utils/transaction.d.cts.map +1 -1
  181. package/dist/utils/transaction.d.mts.map +1 -1
  182. package/dist/utils/transaction.mjs +1 -1
  183. package/dist/utils/transaction.mjs.map +1 -1
  184. package/package.json +19 -18
@@ -1 +1 @@
1
- {"version":3,"file":"hyperliquid-withdraw.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/hyperliquid-withdraw.ts"],"names":[],"mappings":";;;AAAA,iEAA6D;AAC7D,qEAAoE;AAEpE,2CAAqD;AAErD,+CAA4E;AAE5E,mDAAoD;AACpD,6CAA6C;AAM7C,MAAM,GAAG,GAAG,IAAA,0BAAkB,EAAC,sBAAa,EAAE,sBAAsB,CAAC,CAAC;AAItE,MAAM,gBAAgB,GAAsC;IAC1D,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE;IACtC,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE;IAC5C,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;IAC7C,iBAAiB,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,SAAS,EAAE;IACjE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE;CACxC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACI,KAAK,UAAU,yBAAyB,CAC7C,KAAsC,EACtC,IAAS,EACT,SAA4C;IAE5C,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC;IAEjC,GAAG,CAAC,iCAAiC,EAAE;QACrC,SAAS,EAAE,KAAK,CAAC,MAAM;QACvB,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;KACtC,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAC9B,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW,IAAI,IAAI,CAAC,EAAE,KAAK,WAAW,CAC7B,CAAC;IAEpC,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;IAEhE,IAAI,CAAC,aAAa,IAAI,CAAC,WAAW,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,yEAAyE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACtI,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,MAAM,oBAAoB,CAAC,aAAa,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAE3D,0EAA0E;IAC1E,MAAM,kBAAkB,CAAC,WAAW,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAEvD,GAAG,CAAC,+CAA+C,CAAC,CAAC;AACvD,CAAC;AA/BD,8DA+BC;AAED;;;;;;;GAOG;AACH,SAAS,sBAAsB,CAC7B,MAA+B;IAE/B,OAAO,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC;SACjC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,MAAM,CAAC;SAC9B,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,oBAAoB,CACjC,IAAwB,EACxB,IAAS,EACT,SAA4C;IAE5C,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CACb,0CAA0C,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAC9D,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC;IAEjC,MAAM,SAAS,GAAG;QAChB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE;YACL,GAAG,IAAI,CAAC,KAAK;YACb,YAAY,EAAE,sBAAsB,CAAC,IAAI,CAAC,MAAM,CAAC;SAClD;QACD,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,OAAO,EAAE,IAAI,CAAC,KAAK;KACpB,CAAC;IAEF,GAAG,CAAC,mCAAmC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAElE,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,IAAI,CACpC,oCAAoC,EACpC;QACE,IAAI;QACJ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;KAChC,EACD,yCAAoB,CAAC,EAAE,CACxB,CAAC;IAEF,GAAG,CAAC,sCAAsC,CAAC,CAAC;IAE5C,MAAM,YAAY,GAAG,GAAG,+BAAmB,cAAc,SAAS,EAAE,CAAC;IAErE,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,IAAA,kCAAe,EAAC,YAAY,EAAE;YACnD,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;SAChC,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAErC,GAAG,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,iCAAkC,KAAe,CAAC,OAAO,EAAE,CAC5D,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,KAAK,UAAU,kBAAkB,CAC/B,IAAyE,EACzE,IAAS,EACT,SAA4C;IAE5C,MAAM,KAAK,GAAG,IAAI,CAAC,KAA4C,CAAC;IAEhE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,wCAAwC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACtB,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;IAEtB,MAAM,MAAM,GAAG,IAAI,CAAC,MAGnB,CAAC;IACF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAe,CAAC;IACnC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAsC,CAAC;IAChE,MAAM,iBAAiB,GAAG,IAAI,CAAC,iBAA2B,CAAC;IAE3D,yEAAyE;IACzE,sEAAsE;IACtE,oEAAoE;IACpE,MAAM,OAAO,GAAG,MAAM,CAAC,6BAAiB,CAAC,CAAC;IAE1C,MAAM,MAAM,GAAG;QACb,IAAI,EAAE,4BAA4B;QAClC,OAAO,EAAE,GAAG;QACZ,OAAO;QACP,iBAAiB,EAAE,4CAA4C;KAChE,CAAC;IAEF,MAAM,aAAa,GAAG;QACpB,MAAM;QACN,KAAK,EAAE;YACL,GAAG,WAAW;YACd,YAAY,EAAE,sBAAsB,CAAC,MAAM,CAAC;SAC7C;QACD,WAAW,EAAE,iBAAiB;QAC9B,OAAO,EAAE;YACP,GAAG,MAAM,CAAC,UAAU;YACpB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,gBAAgB,EAAE,KAAK,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE;SAC9C;KACF,CAAC;IAEF,GAAG,CAAC,yCAAyC,EAAE;QAC7C,KAAK;QACL,MAAM,EAAE,MAAM,CAAC,IAAI;KACpB,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,IAAI,CACpC,oCAAoC,EACpC;QACE,IAAI;QACJ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC;KACpC,EACD,yCAAoB,CAAC,EAAE,CACxB,CAAC;IAEF,qCAAqC;IACrC,MAAM,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACjC,qCAAqC;IACrC,MAAM,CAAC,GAAG,KAAK,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC;IAC1C,qCAAqC;IACrC,MAAM,CAAC,GAAG,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;IAElD,GAAG,CAAC,yCAAyC,CAAC,CAAC;IAE/C,IAAI,MAAe,CAAC;IAEpB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,IAAA,kCAAe,EAAC,oCAAwB,EAAE;YAC/D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,MAAM,EAAE;oBACN,GAAG,MAAM,CAAC,UAAU;oBACpB,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,gBAAgB,EAAE,KAAK,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE;iBAC9C;gBACD,KAAK;gBACL,SAAS,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;aACvB,CAAC;SACH,CAAC,CAAC;QAEH,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,+BAAgC,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,IAAK,MAA8B,EAAE,MAAM,KAAK,IAAI,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,+BAA+B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED,GAAG,CAAC,8BAA8B,EAAE,MAAM,CAAC,CAAC;AAC9C,CAAC","sourcesContent":["import { successfulFetch } from '@metamask/controller-utils';\nimport { SignTypedDataVersion } from '@metamask/keyring-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { RELAY_AUTHORIZE_URL, HYPERLIQUID_EXCHANGE_URL } from './constants';\nimport type { RelayQuote, RelaySignatureStep } from './types';\nimport { CHAIN_ID_ARBITRUM } from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\n\nconst log = createModuleLogger(projectLogger, 'hyperliquid-withdraw');\n\ntype EIP712DomainField = { name: string; type: string };\n\nconst DOMAIN_FIELD_MAP: Record<string, EIP712DomainField> = {\n name: { name: 'name', type: 'string' },\n version: { name: 'version', type: 'string' },\n chainId: { name: 'chainId', type: 'uint256' },\n verifyingContract: { name: 'verifyingContract', type: 'address' },\n salt: { name: 'salt', type: 'bytes32' },\n};\n\n/**\n * Submit a HyperLiquid 2-step withdrawal via Relay.\n *\n * Step 1 (authorize): Sign an EIP-712 nonce-mapping message, POST to Relay /authorize.\n * Step 2 (deposit): Sign an EIP-712 HyperliquidSignTransaction, POST to HyperLiquid exchange.\n *\n * Both signatures are silent (no user confirmation). Both steps share the same nonce\n * from the Relay quote response.\n *\n * @param quote - Relay quote containing the 2-step flow.\n * @param from - User's account address.\n * @param messenger - Controller messenger (for KeyringController:signTypedMessage).\n */\nexport async function submitHyperliquidWithdraw(\n quote: TransactionPayQuote<RelayQuote>,\n from: Hex,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const { steps } = quote.original;\n\n log('Starting HyperLiquid withdrawal', {\n stepCount: steps.length,\n stepIds: steps.map((step) => step.id),\n });\n\n const authorizeStep = steps.find(\n (step) => step.kind === 'signature' && step.id === 'authorize',\n ) as RelaySignatureStep | undefined;\n\n const depositStep = steps.find((step) => step.id === 'deposit');\n\n if (!authorizeStep || !depositStep) {\n throw new Error(\n `Expected authorize and deposit steps for HyperLiquid withdrawal, got: ${steps.map((step) => `${step.id}(${step.kind})`).join(', ')}`,\n );\n }\n\n // Step 1: Authorize (nonce-mapping signature -> POST to Relay /authorize)\n await executeAuthorizeStep(authorizeStep, from, messenger);\n\n // Step 2: Deposit (HyperLiquid sendAsset -> POST to HyperLiquid exchange)\n await executeDepositStep(depositStep, from, messenger);\n\n log('HyperLiquid withdrawal submitted successfully');\n}\n\n/**\n * Derive the EIP712Domain type array from a domain object.\n * eth-sig-util defaults to EIP712Domain: [] when absent, breaking\n * the domain separator hash. This ensures it matches ethers.js behavior.\n *\n * @param domain - The EIP-712 domain object.\n * @returns The EIP712Domain type array in canonical order.\n */\nfunction deriveEIP712DomainType(\n domain: Record<string, unknown>,\n): EIP712DomainField[] {\n return Object.keys(DOMAIN_FIELD_MAP)\n .filter((key) => key in domain)\n .map((key) => DOMAIN_FIELD_MAP[key]);\n}\n\n/**\n * Execute the authorize step: sign EIP-712 nonce-mapping and POST to Relay.\n *\n * @param step - The authorize signature step from the Relay quote.\n * @param from - User's account address.\n * @param messenger - Controller messenger for signing.\n */\nasync function executeAuthorizeStep(\n step: RelaySignatureStep,\n from: Hex,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n if (step.items.length !== 1) {\n throw new Error(\n `Expected exactly 1 authorize item, got ${step.items.length}`,\n );\n }\n\n const item = step.items[0];\n if (!item) {\n throw new Error('Authorize step has no items');\n }\n\n const { sign, post } = item.data;\n\n const typedData = {\n domain: sign.domain,\n types: {\n ...sign.types,\n EIP712Domain: deriveEIP712DomainType(sign.domain),\n },\n primaryType: sign.primaryType,\n message: sign.value,\n };\n\n log('Signing authorize (nonce-mapping)', { domain: sign.domain });\n\n const signature = await messenger.call(\n 'KeyringController:signTypedMessage',\n {\n from,\n data: JSON.stringify(typedData),\n },\n SignTypedDataVersion.V4,\n );\n\n log('Posting authorize signature to Relay');\n\n const authorizeUrl = `${RELAY_AUTHORIZE_URL}?signature=${signature}`;\n\n try {\n const response = await successfulFetch(authorizeUrl, {\n method: post.method,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(post.body),\n });\n\n const result = await response.json();\n\n log('Authorize response', result);\n } catch (error) {\n throw new Error(\n `HyperLiquid authorize failed: ${(error as Error).message}`,\n );\n }\n}\n\n/**\n * Execute the deposit step: sign HyperLiquid sendAsset and POST to HL exchange.\n *\n * The signature data must be constructed from the step's eip712Types and action\n * parameters, following the Relay HyperLiquid integration spec.\n *\n * @param step - The deposit step from the Relay quote.\n * @param from - User's account address.\n * @param messenger - Controller messenger for signing.\n */\nasync function executeDepositStep(\n step: RelaySignatureStep | { id: string; kind: string; items: unknown[] },\n from: Hex,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const items = step.items as { data: Record<string, unknown> }[];\n\n if (items.length !== 1) {\n throw new Error(`Expected exactly 1 deposit item, got ${items.length}`);\n }\n\n const item = items[0];\n if (!item) {\n throw new Error('Deposit step has no items');\n }\n\n const { data } = item;\n\n const action = data.action as {\n type: string;\n parameters: Record<string, unknown>;\n };\n const nonce = data.nonce as number;\n const eip712Types = data.eip712Types as Record<string, unknown>;\n const eip712PrimaryType = data.eip712PrimaryType as string;\n\n // HyperLiquid's EIP-712 signing spec requires Arbitrum's chain ID in the\n // domain and message. This does not affect which chain the withdrawal\n // targets — the destination chain is determined by the Relay quote.\n const chainId = Number(CHAIN_ID_ARBITRUM);\n\n const domain = {\n name: 'HyperliquidSignTransaction',\n version: '1',\n chainId,\n verifyingContract: '0x0000000000000000000000000000000000000000',\n };\n\n const signatureData = {\n domain,\n types: {\n ...eip712Types,\n EIP712Domain: deriveEIP712DomainType(domain),\n },\n primaryType: eip712PrimaryType,\n message: {\n ...action.parameters,\n type: action.type,\n signatureChainId: `0x${chainId.toString(16)}`,\n },\n };\n\n log('Signing HyperLiquid deposit (sendAsset)', {\n nonce,\n action: action.type,\n });\n\n const signature = await messenger.call(\n 'KeyringController:signTypedMessage',\n {\n from,\n data: JSON.stringify(signatureData),\n },\n SignTypedDataVersion.V4,\n );\n\n // eslint-disable-next-line id-length\n const r = signature.slice(0, 66);\n // eslint-disable-next-line id-length\n const s = `0x${signature.slice(66, 130)}`;\n // eslint-disable-next-line id-length\n const v = parseInt(signature.slice(130, 132), 16);\n\n log('Posting deposit to HyperLiquid exchange');\n\n let result: unknown;\n\n try {\n const response = await successfulFetch(HYPERLIQUID_EXCHANGE_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n action: {\n ...action.parameters,\n type: action.type,\n signatureChainId: `0x${chainId.toString(16)}`,\n },\n nonce,\n signature: { r, s, v },\n }),\n });\n\n result = await response.json();\n } catch (error) {\n throw new Error(`HyperLiquid deposit failed: ${(error as Error).message}`);\n }\n\n if ((result as { status?: string })?.status !== 'ok') {\n throw new Error(`HyperLiquid deposit failed: ${JSON.stringify(result)}`);\n }\n\n log('HyperLiquid deposit response', result);\n}\n"]}
1
+ {"version":3,"file":"hyperliquid-withdraw.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/hyperliquid-withdraw.ts"],"names":[],"mappings":";;;AAAA,iEAA6D;AAC7D,qEAAoE;AAEpE,2CAAqD;AAErD,mDAAoD;AACpD,6CAA6C;AAK7C,+CAA4E;AAG5E,MAAM,GAAG,GAAG,IAAA,0BAAkB,EAAC,sBAAa,EAAE,sBAAsB,CAAC,CAAC;AAItE,MAAM,gBAAgB,GAAsC;IAC1D,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE;IACtC,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE;IAC5C,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;IAC7C,iBAAiB,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,SAAS,EAAE;IACjE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE;CACxC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACI,KAAK,UAAU,yBAAyB,CAC7C,KAAsC,EACtC,IAAS,EACT,SAA4C;IAE5C,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC;IAEjC,GAAG,CAAC,iCAAiC,EAAE;QACrC,SAAS,EAAE,KAAK,CAAC,MAAM;QACvB,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;KACtC,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAC9B,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW,IAAI,IAAI,CAAC,EAAE,KAAK,WAAW,CAC7B,CAAC;IAEpC,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;IAEhE,IAAI,CAAC,aAAa,IAAI,CAAC,WAAW,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,yEAAyE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACtI,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,MAAM,oBAAoB,CAAC,aAAa,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAE3D,0EAA0E;IAC1E,MAAM,kBAAkB,CAAC,WAAW,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAEvD,GAAG,CAAC,+CAA+C,CAAC,CAAC;AACvD,CAAC;AA/BD,8DA+BC;AAED;;;;;;;GAOG;AACH,SAAS,sBAAsB,CAC7B,MAA+B;IAE/B,OAAO,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC;SACjC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,MAAM,CAAC;SAC9B,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,oBAAoB,CACjC,IAAwB,EACxB,IAAS,EACT,SAA4C;IAE5C,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CACb,0CAA0C,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAC9D,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC;IAEjC,MAAM,SAAS,GAAG;QAChB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE;YACL,GAAG,IAAI,CAAC,KAAK;YACb,YAAY,EAAE,sBAAsB,CAAC,IAAI,CAAC,MAAM,CAAC;SAClD;QACD,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,OAAO,EAAE,IAAI,CAAC,KAAK;KACpB,CAAC;IAEF,GAAG,CAAC,mCAAmC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAElE,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,IAAI,CACpC,oCAAoC,EACpC;QACE,IAAI;QACJ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;KAChC,EACD,yCAAoB,CAAC,EAAE,CACxB,CAAC;IAEF,GAAG,CAAC,sCAAsC,CAAC,CAAC;IAE5C,MAAM,YAAY,GAAG,GAAG,+BAAmB,cAAc,SAAS,EAAE,CAAC;IAErE,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,IAAA,kCAAe,EAAC,YAAY,EAAE;YACnD,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;SAChC,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAErC,GAAG,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,iCAAkC,KAAe,CAAC,OAAO,EAAE,CAC5D,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,KAAK,UAAU,kBAAkB,CAC/B,IAAyE,EACzE,IAAS,EACT,SAA4C;IAE5C,MAAM,KAAK,GAAG,IAAI,CAAC,KAA4C,CAAC;IAEhE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,wCAAwC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACtB,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;IAEtB,MAAM,MAAM,GAAG,IAAI,CAAC,MAGnB,CAAC;IACF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAe,CAAC;IACnC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAsC,CAAC;IAChE,MAAM,iBAAiB,GAAG,IAAI,CAAC,iBAA2B,CAAC;IAE3D,yEAAyE;IACzE,sEAAsE;IACtE,oEAAoE;IACpE,MAAM,OAAO,GAAG,MAAM,CAAC,6BAAiB,CAAC,CAAC;IAE1C,MAAM,MAAM,GAAG;QACb,IAAI,EAAE,4BAA4B;QAClC,OAAO,EAAE,GAAG;QACZ,OAAO;QACP,iBAAiB,EAAE,4CAA4C;KAChE,CAAC;IAEF,MAAM,aAAa,GAAG;QACpB,MAAM;QACN,KAAK,EAAE;YACL,GAAG,WAAW;YACd,YAAY,EAAE,sBAAsB,CAAC,MAAM,CAAC;SAC7C;QACD,WAAW,EAAE,iBAAiB;QAC9B,OAAO,EAAE;YACP,GAAG,MAAM,CAAC,UAAU;YACpB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,gBAAgB,EAAE,KAAK,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE;SAC9C;KACF,CAAC;IAEF,GAAG,CAAC,yCAAyC,EAAE;QAC7C,KAAK;QACL,MAAM,EAAE,MAAM,CAAC,IAAI;KACpB,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,IAAI,CACpC,oCAAoC,EACpC;QACE,IAAI;QACJ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC;KACpC,EACD,yCAAoB,CAAC,EAAE,CACxB,CAAC;IAEF,qCAAqC;IACrC,MAAM,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACjC,qCAAqC;IACrC,MAAM,CAAC,GAAG,KAAK,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC;IAC1C,qCAAqC;IACrC,MAAM,CAAC,GAAG,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;IAElD,GAAG,CAAC,yCAAyC,CAAC,CAAC;IAE/C,IAAI,MAAe,CAAC;IAEpB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,IAAA,kCAAe,EAAC,oCAAwB,EAAE;YAC/D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,MAAM,EAAE;oBACN,GAAG,MAAM,CAAC,UAAU;oBACpB,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,gBAAgB,EAAE,KAAK,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE;iBAC9C;gBACD,KAAK;gBACL,SAAS,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;aACvB,CAAC;SACH,CAAC,CAAC;QAEH,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,+BAAgC,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,IAAK,MAA8B,EAAE,MAAM,KAAK,IAAI,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,+BAA+B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED,GAAG,CAAC,8BAA8B,EAAE,MAAM,CAAC,CAAC;AAC9C,CAAC","sourcesContent":["import { successfulFetch } from '@metamask/controller-utils';\nimport { SignTypedDataVersion } from '@metamask/keyring-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { CHAIN_ID_ARBITRUM } from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport { RELAY_AUTHORIZE_URL, HYPERLIQUID_EXCHANGE_URL } from './constants';\nimport type { RelayQuote, RelaySignatureStep } from './types';\n\nconst log = createModuleLogger(projectLogger, 'hyperliquid-withdraw');\n\ntype EIP712DomainField = { name: string; type: string };\n\nconst DOMAIN_FIELD_MAP: Record<string, EIP712DomainField> = {\n name: { name: 'name', type: 'string' },\n version: { name: 'version', type: 'string' },\n chainId: { name: 'chainId', type: 'uint256' },\n verifyingContract: { name: 'verifyingContract', type: 'address' },\n salt: { name: 'salt', type: 'bytes32' },\n};\n\n/**\n * Submit a HyperLiquid 2-step withdrawal via Relay.\n *\n * Step 1 (authorize): Sign an EIP-712 nonce-mapping message, POST to Relay /authorize.\n * Step 2 (deposit): Sign an EIP-712 HyperliquidSignTransaction, POST to HyperLiquid exchange.\n *\n * Both signatures are silent (no user confirmation). Both steps share the same nonce\n * from the Relay quote response.\n *\n * @param quote - Relay quote containing the 2-step flow.\n * @param from - User's account address.\n * @param messenger - Controller messenger (for KeyringController:signTypedMessage).\n */\nexport async function submitHyperliquidWithdraw(\n quote: TransactionPayQuote<RelayQuote>,\n from: Hex,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const { steps } = quote.original;\n\n log('Starting HyperLiquid withdrawal', {\n stepCount: steps.length,\n stepIds: steps.map((step) => step.id),\n });\n\n const authorizeStep = steps.find(\n (step) => step.kind === 'signature' && step.id === 'authorize',\n ) as RelaySignatureStep | undefined;\n\n const depositStep = steps.find((step) => step.id === 'deposit');\n\n if (!authorizeStep || !depositStep) {\n throw new Error(\n `Expected authorize and deposit steps for HyperLiquid withdrawal, got: ${steps.map((step) => `${step.id}(${step.kind})`).join(', ')}`,\n );\n }\n\n // Step 1: Authorize (nonce-mapping signature -> POST to Relay /authorize)\n await executeAuthorizeStep(authorizeStep, from, messenger);\n\n // Step 2: Deposit (HyperLiquid sendAsset -> POST to HyperLiquid exchange)\n await executeDepositStep(depositStep, from, messenger);\n\n log('HyperLiquid withdrawal submitted successfully');\n}\n\n/**\n * Derive the EIP712Domain type array from a domain object.\n * eth-sig-util defaults to EIP712Domain: [] when absent, breaking\n * the domain separator hash. This ensures it matches ethers.js behavior.\n *\n * @param domain - The EIP-712 domain object.\n * @returns The EIP712Domain type array in canonical order.\n */\nfunction deriveEIP712DomainType(\n domain: Record<string, unknown>,\n): EIP712DomainField[] {\n return Object.keys(DOMAIN_FIELD_MAP)\n .filter((key) => key in domain)\n .map((key) => DOMAIN_FIELD_MAP[key]);\n}\n\n/**\n * Execute the authorize step: sign EIP-712 nonce-mapping and POST to Relay.\n *\n * @param step - The authorize signature step from the Relay quote.\n * @param from - User's account address.\n * @param messenger - Controller messenger for signing.\n */\nasync function executeAuthorizeStep(\n step: RelaySignatureStep,\n from: Hex,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n if (step.items.length !== 1) {\n throw new Error(\n `Expected exactly 1 authorize item, got ${step.items.length}`,\n );\n }\n\n const item = step.items[0];\n if (!item) {\n throw new Error('Authorize step has no items');\n }\n\n const { sign, post } = item.data;\n\n const typedData = {\n domain: sign.domain,\n types: {\n ...sign.types,\n EIP712Domain: deriveEIP712DomainType(sign.domain),\n },\n primaryType: sign.primaryType,\n message: sign.value,\n };\n\n log('Signing authorize (nonce-mapping)', { domain: sign.domain });\n\n const signature = await messenger.call(\n 'KeyringController:signTypedMessage',\n {\n from,\n data: JSON.stringify(typedData),\n },\n SignTypedDataVersion.V4,\n );\n\n log('Posting authorize signature to Relay');\n\n const authorizeUrl = `${RELAY_AUTHORIZE_URL}?signature=${signature}`;\n\n try {\n const response = await successfulFetch(authorizeUrl, {\n method: post.method,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(post.body),\n });\n\n const result = await response.json();\n\n log('Authorize response', result);\n } catch (error) {\n throw new Error(\n `HyperLiquid authorize failed: ${(error as Error).message}`,\n );\n }\n}\n\n/**\n * Execute the deposit step: sign HyperLiquid sendAsset and POST to HL exchange.\n *\n * The signature data must be constructed from the step's eip712Types and action\n * parameters, following the Relay HyperLiquid integration spec.\n *\n * @param step - The deposit step from the Relay quote.\n * @param from - User's account address.\n * @param messenger - Controller messenger for signing.\n */\nasync function executeDepositStep(\n step: RelaySignatureStep | { id: string; kind: string; items: unknown[] },\n from: Hex,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const items = step.items as { data: Record<string, unknown> }[];\n\n if (items.length !== 1) {\n throw new Error(`Expected exactly 1 deposit item, got ${items.length}`);\n }\n\n const item = items[0];\n if (!item) {\n throw new Error('Deposit step has no items');\n }\n\n const { data } = item;\n\n const action = data.action as {\n type: string;\n parameters: Record<string, unknown>;\n };\n const nonce = data.nonce as number;\n const eip712Types = data.eip712Types as Record<string, unknown>;\n const eip712PrimaryType = data.eip712PrimaryType as string;\n\n // HyperLiquid's EIP-712 signing spec requires Arbitrum's chain ID in the\n // domain and message. This does not affect which chain the withdrawal\n // targets — the destination chain is determined by the Relay quote.\n const chainId = Number(CHAIN_ID_ARBITRUM);\n\n const domain = {\n name: 'HyperliquidSignTransaction',\n version: '1',\n chainId,\n verifyingContract: '0x0000000000000000000000000000000000000000',\n };\n\n const signatureData = {\n domain,\n types: {\n ...eip712Types,\n EIP712Domain: deriveEIP712DomainType(domain),\n },\n primaryType: eip712PrimaryType,\n message: {\n ...action.parameters,\n type: action.type,\n signatureChainId: `0x${chainId.toString(16)}`,\n },\n };\n\n log('Signing HyperLiquid deposit (sendAsset)', {\n nonce,\n action: action.type,\n });\n\n const signature = await messenger.call(\n 'KeyringController:signTypedMessage',\n {\n from,\n data: JSON.stringify(signatureData),\n },\n SignTypedDataVersion.V4,\n );\n\n // eslint-disable-next-line id-length\n const r = signature.slice(0, 66);\n // eslint-disable-next-line id-length\n const s = `0x${signature.slice(66, 130)}`;\n // eslint-disable-next-line id-length\n const v = parseInt(signature.slice(130, 132), 16);\n\n log('Posting deposit to HyperLiquid exchange');\n\n let result: unknown;\n\n try {\n const response = await successfulFetch(HYPERLIQUID_EXCHANGE_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n action: {\n ...action.parameters,\n type: action.type,\n signatureChainId: `0x${chainId.toString(16)}`,\n },\n nonce,\n signature: { r, s, v },\n }),\n });\n\n result = await response.json();\n } catch (error) {\n throw new Error(`HyperLiquid deposit failed: ${(error as Error).message}`);\n }\n\n if ((result as { status?: string })?.status !== 'ok') {\n throw new Error(`HyperLiquid deposit failed: ${JSON.stringify(result)}`);\n }\n\n log('HyperLiquid deposit response', result);\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import type { Hex } from "@metamask/utils";
2
- import type { RelayQuote } from "./types.cjs";
3
2
  import type { TransactionPayControllerMessenger, TransactionPayQuote } from "../../types.cjs";
3
+ import type { RelayQuote } from "./types.cjs";
4
4
  /**
5
5
  * Submit a HyperLiquid 2-step withdrawal via Relay.
6
6
  *
@@ -1 +1 @@
1
- {"version":3,"file":"hyperliquid-withdraw.d.cts","sourceRoot":"","sources":["../../../src/strategy/relay/hyperliquid-withdraw.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAI3C,OAAO,KAAK,EAAE,UAAU,EAAsB,oBAAgB;AAG9D,OAAO,KAAK,EACV,iCAAiC,EACjC,mBAAmB,EACpB,wBAAoB;AAcrB;;;;;;;;;;;;GAYG;AACH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,mBAAmB,CAAC,UAAU,CAAC,EACtC,IAAI,EAAE,GAAG,EACT,SAAS,EAAE,iCAAiC,GAC3C,OAAO,CAAC,IAAI,CAAC,CA2Bf"}
1
+ {"version":3,"file":"hyperliquid-withdraw.d.cts","sourceRoot":"","sources":["../../../src/strategy/relay/hyperliquid-withdraw.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAK3C,OAAO,KAAK,EACV,iCAAiC,EACjC,mBAAmB,EACpB,wBAAoB;AAErB,OAAO,KAAK,EAAE,UAAU,EAAsB,oBAAgB;AAc9D;;;;;;;;;;;;GAYG;AACH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,mBAAmB,CAAC,UAAU,CAAC,EACtC,IAAI,EAAE,GAAG,EACT,SAAS,EAAE,iCAAiC,GAC3C,OAAO,CAAC,IAAI,CAAC,CA2Bf"}
@@ -1,6 +1,6 @@
1
1
  import type { Hex } from "@metamask/utils";
2
- import type { RelayQuote } from "./types.mjs";
3
2
  import type { TransactionPayControllerMessenger, TransactionPayQuote } from "../../types.mjs";
3
+ import type { RelayQuote } from "./types.mjs";
4
4
  /**
5
5
  * Submit a HyperLiquid 2-step withdrawal via Relay.
6
6
  *
@@ -1 +1 @@
1
- {"version":3,"file":"hyperliquid-withdraw.d.mts","sourceRoot":"","sources":["../../../src/strategy/relay/hyperliquid-withdraw.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAI3C,OAAO,KAAK,EAAE,UAAU,EAAsB,oBAAgB;AAG9D,OAAO,KAAK,EACV,iCAAiC,EACjC,mBAAmB,EACpB,wBAAoB;AAcrB;;;;;;;;;;;;GAYG;AACH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,mBAAmB,CAAC,UAAU,CAAC,EACtC,IAAI,EAAE,GAAG,EACT,SAAS,EAAE,iCAAiC,GAC3C,OAAO,CAAC,IAAI,CAAC,CA2Bf"}
1
+ {"version":3,"file":"hyperliquid-withdraw.d.mts","sourceRoot":"","sources":["../../../src/strategy/relay/hyperliquid-withdraw.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAK3C,OAAO,KAAK,EACV,iCAAiC,EACjC,mBAAmB,EACpB,wBAAoB;AAErB,OAAO,KAAK,EAAE,UAAU,EAAsB,oBAAgB;AAc9D;;;;;;;;;;;;GAYG;AACH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,mBAAmB,CAAC,UAAU,CAAC,EACtC,IAAI,EAAE,GAAG,EACT,SAAS,EAAE,iCAAiC,GAC3C,OAAO,CAAC,IAAI,CAAC,CA2Bf"}
@@ -1,9 +1,9 @@
1
1
  import { successfulFetch } from "@metamask/controller-utils";
2
2
  import { SignTypedDataVersion } from "@metamask/keyring-controller";
3
3
  import { createModuleLogger } from "@metamask/utils";
4
- import { RELAY_AUTHORIZE_URL, HYPERLIQUID_EXCHANGE_URL } from "./constants.mjs";
5
4
  import { CHAIN_ID_ARBITRUM } from "../../constants.mjs";
6
5
  import { projectLogger } from "../../logger.mjs";
6
+ import { RELAY_AUTHORIZE_URL, HYPERLIQUID_EXCHANGE_URL } from "./constants.mjs";
7
7
  const log = createModuleLogger(projectLogger, 'hyperliquid-withdraw');
8
8
  const DOMAIN_FIELD_MAP = {
9
9
  name: { name: 'name', type: 'string' },
@@ -1 +1 @@
1
- {"version":3,"file":"hyperliquid-withdraw.mjs","sourceRoot":"","sources":["../../../src/strategy/relay/hyperliquid-withdraw.ts"],"names":[],"mappings":"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","sourcesContent":["import { successfulFetch } from '@metamask/controller-utils';\nimport { SignTypedDataVersion } from '@metamask/keyring-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { RELAY_AUTHORIZE_URL, HYPERLIQUID_EXCHANGE_URL } from './constants';\nimport type { RelayQuote, RelaySignatureStep } from './types';\nimport { CHAIN_ID_ARBITRUM } from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\n\nconst log = createModuleLogger(projectLogger, 'hyperliquid-withdraw');\n\ntype EIP712DomainField = { name: string; type: string };\n\nconst DOMAIN_FIELD_MAP: Record<string, EIP712DomainField> = {\n name: { name: 'name', type: 'string' },\n version: { name: 'version', type: 'string' },\n chainId: { name: 'chainId', type: 'uint256' },\n verifyingContract: { name: 'verifyingContract', type: 'address' },\n salt: { name: 'salt', type: 'bytes32' },\n};\n\n/**\n * Submit a HyperLiquid 2-step withdrawal via Relay.\n *\n * Step 1 (authorize): Sign an EIP-712 nonce-mapping message, POST to Relay /authorize.\n * Step 2 (deposit): Sign an EIP-712 HyperliquidSignTransaction, POST to HyperLiquid exchange.\n *\n * Both signatures are silent (no user confirmation). Both steps share the same nonce\n * from the Relay quote response.\n *\n * @param quote - Relay quote containing the 2-step flow.\n * @param from - User's account address.\n * @param messenger - Controller messenger (for KeyringController:signTypedMessage).\n */\nexport async function submitHyperliquidWithdraw(\n quote: TransactionPayQuote<RelayQuote>,\n from: Hex,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const { steps } = quote.original;\n\n log('Starting HyperLiquid withdrawal', {\n stepCount: steps.length,\n stepIds: steps.map((step) => step.id),\n });\n\n const authorizeStep = steps.find(\n (step) => step.kind === 'signature' && step.id === 'authorize',\n ) as RelaySignatureStep | undefined;\n\n const depositStep = steps.find((step) => step.id === 'deposit');\n\n if (!authorizeStep || !depositStep) {\n throw new Error(\n `Expected authorize and deposit steps for HyperLiquid withdrawal, got: ${steps.map((step) => `${step.id}(${step.kind})`).join(', ')}`,\n );\n }\n\n // Step 1: Authorize (nonce-mapping signature -> POST to Relay /authorize)\n await executeAuthorizeStep(authorizeStep, from, messenger);\n\n // Step 2: Deposit (HyperLiquid sendAsset -> POST to HyperLiquid exchange)\n await executeDepositStep(depositStep, from, messenger);\n\n log('HyperLiquid withdrawal submitted successfully');\n}\n\n/**\n * Derive the EIP712Domain type array from a domain object.\n * eth-sig-util defaults to EIP712Domain: [] when absent, breaking\n * the domain separator hash. This ensures it matches ethers.js behavior.\n *\n * @param domain - The EIP-712 domain object.\n * @returns The EIP712Domain type array in canonical order.\n */\nfunction deriveEIP712DomainType(\n domain: Record<string, unknown>,\n): EIP712DomainField[] {\n return Object.keys(DOMAIN_FIELD_MAP)\n .filter((key) => key in domain)\n .map((key) => DOMAIN_FIELD_MAP[key]);\n}\n\n/**\n * Execute the authorize step: sign EIP-712 nonce-mapping and POST to Relay.\n *\n * @param step - The authorize signature step from the Relay quote.\n * @param from - User's account address.\n * @param messenger - Controller messenger for signing.\n */\nasync function executeAuthorizeStep(\n step: RelaySignatureStep,\n from: Hex,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n if (step.items.length !== 1) {\n throw new Error(\n `Expected exactly 1 authorize item, got ${step.items.length}`,\n );\n }\n\n const item = step.items[0];\n if (!item) {\n throw new Error('Authorize step has no items');\n }\n\n const { sign, post } = item.data;\n\n const typedData = {\n domain: sign.domain,\n types: {\n ...sign.types,\n EIP712Domain: deriveEIP712DomainType(sign.domain),\n },\n primaryType: sign.primaryType,\n message: sign.value,\n };\n\n log('Signing authorize (nonce-mapping)', { domain: sign.domain });\n\n const signature = await messenger.call(\n 'KeyringController:signTypedMessage',\n {\n from,\n data: JSON.stringify(typedData),\n },\n SignTypedDataVersion.V4,\n );\n\n log('Posting authorize signature to Relay');\n\n const authorizeUrl = `${RELAY_AUTHORIZE_URL}?signature=${signature}`;\n\n try {\n const response = await successfulFetch(authorizeUrl, {\n method: post.method,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(post.body),\n });\n\n const result = await response.json();\n\n log('Authorize response', result);\n } catch (error) {\n throw new Error(\n `HyperLiquid authorize failed: ${(error as Error).message}`,\n );\n }\n}\n\n/**\n * Execute the deposit step: sign HyperLiquid sendAsset and POST to HL exchange.\n *\n * The signature data must be constructed from the step's eip712Types and action\n * parameters, following the Relay HyperLiquid integration spec.\n *\n * @param step - The deposit step from the Relay quote.\n * @param from - User's account address.\n * @param messenger - Controller messenger for signing.\n */\nasync function executeDepositStep(\n step: RelaySignatureStep | { id: string; kind: string; items: unknown[] },\n from: Hex,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const items = step.items as { data: Record<string, unknown> }[];\n\n if (items.length !== 1) {\n throw new Error(`Expected exactly 1 deposit item, got ${items.length}`);\n }\n\n const item = items[0];\n if (!item) {\n throw new Error('Deposit step has no items');\n }\n\n const { data } = item;\n\n const action = data.action as {\n type: string;\n parameters: Record<string, unknown>;\n };\n const nonce = data.nonce as number;\n const eip712Types = data.eip712Types as Record<string, unknown>;\n const eip712PrimaryType = data.eip712PrimaryType as string;\n\n // HyperLiquid's EIP-712 signing spec requires Arbitrum's chain ID in the\n // domain and message. This does not affect which chain the withdrawal\n // targets — the destination chain is determined by the Relay quote.\n const chainId = Number(CHAIN_ID_ARBITRUM);\n\n const domain = {\n name: 'HyperliquidSignTransaction',\n version: '1',\n chainId,\n verifyingContract: '0x0000000000000000000000000000000000000000',\n };\n\n const signatureData = {\n domain,\n types: {\n ...eip712Types,\n EIP712Domain: deriveEIP712DomainType(domain),\n },\n primaryType: eip712PrimaryType,\n message: {\n ...action.parameters,\n type: action.type,\n signatureChainId: `0x${chainId.toString(16)}`,\n },\n };\n\n log('Signing HyperLiquid deposit (sendAsset)', {\n nonce,\n action: action.type,\n });\n\n const signature = await messenger.call(\n 'KeyringController:signTypedMessage',\n {\n from,\n data: JSON.stringify(signatureData),\n },\n SignTypedDataVersion.V4,\n );\n\n // eslint-disable-next-line id-length\n const r = signature.slice(0, 66);\n // eslint-disable-next-line id-length\n const s = `0x${signature.slice(66, 130)}`;\n // eslint-disable-next-line id-length\n const v = parseInt(signature.slice(130, 132), 16);\n\n log('Posting deposit to HyperLiquid exchange');\n\n let result: unknown;\n\n try {\n const response = await successfulFetch(HYPERLIQUID_EXCHANGE_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n action: {\n ...action.parameters,\n type: action.type,\n signatureChainId: `0x${chainId.toString(16)}`,\n },\n nonce,\n signature: { r, s, v },\n }),\n });\n\n result = await response.json();\n } catch (error) {\n throw new Error(`HyperLiquid deposit failed: ${(error as Error).message}`);\n }\n\n if ((result as { status?: string })?.status !== 'ok') {\n throw new Error(`HyperLiquid deposit failed: ${JSON.stringify(result)}`);\n }\n\n log('HyperLiquid deposit response', result);\n}\n"]}
1
+ {"version":3,"file":"hyperliquid-withdraw.mjs","sourceRoot":"","sources":["../../../src/strategy/relay/hyperliquid-withdraw.ts"],"names":[],"mappings":"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","sourcesContent":["import { successfulFetch } from '@metamask/controller-utils';\nimport { SignTypedDataVersion } from '@metamask/keyring-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { CHAIN_ID_ARBITRUM } from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport { RELAY_AUTHORIZE_URL, HYPERLIQUID_EXCHANGE_URL } from './constants';\nimport type { RelayQuote, RelaySignatureStep } from './types';\n\nconst log = createModuleLogger(projectLogger, 'hyperliquid-withdraw');\n\ntype EIP712DomainField = { name: string; type: string };\n\nconst DOMAIN_FIELD_MAP: Record<string, EIP712DomainField> = {\n name: { name: 'name', type: 'string' },\n version: { name: 'version', type: 'string' },\n chainId: { name: 'chainId', type: 'uint256' },\n verifyingContract: { name: 'verifyingContract', type: 'address' },\n salt: { name: 'salt', type: 'bytes32' },\n};\n\n/**\n * Submit a HyperLiquid 2-step withdrawal via Relay.\n *\n * Step 1 (authorize): Sign an EIP-712 nonce-mapping message, POST to Relay /authorize.\n * Step 2 (deposit): Sign an EIP-712 HyperliquidSignTransaction, POST to HyperLiquid exchange.\n *\n * Both signatures are silent (no user confirmation). Both steps share the same nonce\n * from the Relay quote response.\n *\n * @param quote - Relay quote containing the 2-step flow.\n * @param from - User's account address.\n * @param messenger - Controller messenger (for KeyringController:signTypedMessage).\n */\nexport async function submitHyperliquidWithdraw(\n quote: TransactionPayQuote<RelayQuote>,\n from: Hex,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const { steps } = quote.original;\n\n log('Starting HyperLiquid withdrawal', {\n stepCount: steps.length,\n stepIds: steps.map((step) => step.id),\n });\n\n const authorizeStep = steps.find(\n (step) => step.kind === 'signature' && step.id === 'authorize',\n ) as RelaySignatureStep | undefined;\n\n const depositStep = steps.find((step) => step.id === 'deposit');\n\n if (!authorizeStep || !depositStep) {\n throw new Error(\n `Expected authorize and deposit steps for HyperLiquid withdrawal, got: ${steps.map((step) => `${step.id}(${step.kind})`).join(', ')}`,\n );\n }\n\n // Step 1: Authorize (nonce-mapping signature -> POST to Relay /authorize)\n await executeAuthorizeStep(authorizeStep, from, messenger);\n\n // Step 2: Deposit (HyperLiquid sendAsset -> POST to HyperLiquid exchange)\n await executeDepositStep(depositStep, from, messenger);\n\n log('HyperLiquid withdrawal submitted successfully');\n}\n\n/**\n * Derive the EIP712Domain type array from a domain object.\n * eth-sig-util defaults to EIP712Domain: [] when absent, breaking\n * the domain separator hash. This ensures it matches ethers.js behavior.\n *\n * @param domain - The EIP-712 domain object.\n * @returns The EIP712Domain type array in canonical order.\n */\nfunction deriveEIP712DomainType(\n domain: Record<string, unknown>,\n): EIP712DomainField[] {\n return Object.keys(DOMAIN_FIELD_MAP)\n .filter((key) => key in domain)\n .map((key) => DOMAIN_FIELD_MAP[key]);\n}\n\n/**\n * Execute the authorize step: sign EIP-712 nonce-mapping and POST to Relay.\n *\n * @param step - The authorize signature step from the Relay quote.\n * @param from - User's account address.\n * @param messenger - Controller messenger for signing.\n */\nasync function executeAuthorizeStep(\n step: RelaySignatureStep,\n from: Hex,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n if (step.items.length !== 1) {\n throw new Error(\n `Expected exactly 1 authorize item, got ${step.items.length}`,\n );\n }\n\n const item = step.items[0];\n if (!item) {\n throw new Error('Authorize step has no items');\n }\n\n const { sign, post } = item.data;\n\n const typedData = {\n domain: sign.domain,\n types: {\n ...sign.types,\n EIP712Domain: deriveEIP712DomainType(sign.domain),\n },\n primaryType: sign.primaryType,\n message: sign.value,\n };\n\n log('Signing authorize (nonce-mapping)', { domain: sign.domain });\n\n const signature = await messenger.call(\n 'KeyringController:signTypedMessage',\n {\n from,\n data: JSON.stringify(typedData),\n },\n SignTypedDataVersion.V4,\n );\n\n log('Posting authorize signature to Relay');\n\n const authorizeUrl = `${RELAY_AUTHORIZE_URL}?signature=${signature}`;\n\n try {\n const response = await successfulFetch(authorizeUrl, {\n method: post.method,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(post.body),\n });\n\n const result = await response.json();\n\n log('Authorize response', result);\n } catch (error) {\n throw new Error(\n `HyperLiquid authorize failed: ${(error as Error).message}`,\n );\n }\n}\n\n/**\n * Execute the deposit step: sign HyperLiquid sendAsset and POST to HL exchange.\n *\n * The signature data must be constructed from the step's eip712Types and action\n * parameters, following the Relay HyperLiquid integration spec.\n *\n * @param step - The deposit step from the Relay quote.\n * @param from - User's account address.\n * @param messenger - Controller messenger for signing.\n */\nasync function executeDepositStep(\n step: RelaySignatureStep | { id: string; kind: string; items: unknown[] },\n from: Hex,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const items = step.items as { data: Record<string, unknown> }[];\n\n if (items.length !== 1) {\n throw new Error(`Expected exactly 1 deposit item, got ${items.length}`);\n }\n\n const item = items[0];\n if (!item) {\n throw new Error('Deposit step has no items');\n }\n\n const { data } = item;\n\n const action = data.action as {\n type: string;\n parameters: Record<string, unknown>;\n };\n const nonce = data.nonce as number;\n const eip712Types = data.eip712Types as Record<string, unknown>;\n const eip712PrimaryType = data.eip712PrimaryType as string;\n\n // HyperLiquid's EIP-712 signing spec requires Arbitrum's chain ID in the\n // domain and message. This does not affect which chain the withdrawal\n // targets — the destination chain is determined by the Relay quote.\n const chainId = Number(CHAIN_ID_ARBITRUM);\n\n const domain = {\n name: 'HyperliquidSignTransaction',\n version: '1',\n chainId,\n verifyingContract: '0x0000000000000000000000000000000000000000',\n };\n\n const signatureData = {\n domain,\n types: {\n ...eip712Types,\n EIP712Domain: deriveEIP712DomainType(domain),\n },\n primaryType: eip712PrimaryType,\n message: {\n ...action.parameters,\n type: action.type,\n signatureChainId: `0x${chainId.toString(16)}`,\n },\n };\n\n log('Signing HyperLiquid deposit (sendAsset)', {\n nonce,\n action: action.type,\n });\n\n const signature = await messenger.call(\n 'KeyringController:signTypedMessage',\n {\n from,\n data: JSON.stringify(signatureData),\n },\n SignTypedDataVersion.V4,\n );\n\n // eslint-disable-next-line id-length\n const r = signature.slice(0, 66);\n // eslint-disable-next-line id-length\n const s = `0x${signature.slice(66, 130)}`;\n // eslint-disable-next-line id-length\n const v = parseInt(signature.slice(130, 132), 16);\n\n log('Posting deposit to HyperLiquid exchange');\n\n let result: unknown;\n\n try {\n const response = await successfulFetch(HYPERLIQUID_EXCHANGE_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n action: {\n ...action.parameters,\n type: action.type,\n signatureChainId: `0x${chainId.toString(16)}`,\n },\n nonce,\n signature: { r, s, v },\n }),\n });\n\n result = await response.json();\n } catch (error) {\n throw new Error(`HyperLiquid deposit failed: ${(error as Error).message}`);\n }\n\n if ((result as { status?: string })?.status !== 'ok') {\n throw new Error(`HyperLiquid deposit failed: ${JSON.stringify(result)}`);\n }\n\n log('HyperLiquid deposit response', result);\n}\n"]}
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getRelayStatus = exports.submitRelayExecute = exports.fetchRelayQuote = void 0;
4
4
  const controller_utils_1 = require("@metamask/controller-utils");
5
- const constants_1 = require("./constants.cjs");
6
5
  const feature_flags_1 = require("../../utils/feature-flags.cjs");
6
+ const constants_1 = require("./constants.cjs");
7
7
  /**
8
8
  * Fetch a quote from the Relay API.
9
9
  *
@@ -1 +1 @@
1
- {"version":3,"file":"relay-api.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-api.ts"],"names":[],"mappings":";;;AAAA,iEAA6D;AAE7D,+CAA+C;AAS/C,iEAA4D;AAE5D;;;;;;GAMG;AACI,KAAK,UAAU,eAAe,CACnC,SAA4C,EAC5C,IAAuB;IAEvB,MAAM,EAAE,aAAa,EAAE,GAAG,IAAA,+BAAe,EAAC,SAAS,CAAC,CAAC;IAErD,MAAM,QAAQ,GAAG,MAAM,IAAA,kCAAe,EAAC,aAAa,EAAE;QACpD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAe,CAAC;IACpD,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;IAErB,OAAO,KAAK,CAAC;AACf,CAAC;AAhBD,0CAgBC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,kBAAkB,CACtC,SAA4C,EAC5C,IAAyB;IAEzB,MAAM,EAAE,eAAe,EAAE,GAAG,IAAA,+BAAe,EAAC,SAAS,CAAC,CAAC;IAEvD,MAAM,QAAQ,GAAG,MAAM,IAAA,kCAAe,EAAC,eAAe,EAAE;QACtD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IAEH,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAyB,CAAC;AACzD,CAAC;AAbD,gDAaC;AAED;;;;;GAKG;AACI,KAAK,UAAU,cAAc,CAClC,SAAiB;IAEjB,MAAM,GAAG,GAAG,GAAG,4BAAgB,cAAc,SAAS,EAAE,CAAC;IAEzD,MAAM,QAAQ,GAAG,MAAM,IAAA,kCAAe,EAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAE/D,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAwB,CAAC;AACxD,CAAC;AARD,wCAQC","sourcesContent":["import { successfulFetch } from '@metamask/controller-utils';\n\nimport { RELAY_STATUS_URL } from './constants';\nimport type {\n RelayExecuteRequest,\n RelayExecuteResponse,\n RelayQuote,\n RelayQuoteRequest,\n RelayStatusResponse,\n} from './types';\nimport type { TransactionPayControllerMessenger } from '../../types';\nimport { getFeatureFlags } from '../../utils/feature-flags';\n\n/**\n * Fetch a quote from the Relay API.\n *\n * @param messenger - Controller messenger.\n * @param body - Quote request parameters.\n * @returns The Relay quote with the request attached.\n */\nexport async function fetchRelayQuote(\n messenger: TransactionPayControllerMessenger,\n body: RelayQuoteRequest,\n): Promise<RelayQuote> {\n const { relayQuoteUrl } = getFeatureFlags(messenger);\n\n const response = await successfulFetch(relayQuoteUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n const quote = (await response.json()) as RelayQuote;\n quote.request = body;\n\n return quote;\n}\n\n/**\n * Submit a gasless transaction via the Relay /execute endpoint.\n *\n * @param messenger - Controller messenger.\n * @param body - Execute request parameters.\n * @returns The execute response containing the request ID.\n */\nexport async function submitRelayExecute(\n messenger: TransactionPayControllerMessenger,\n body: RelayExecuteRequest,\n): Promise<RelayExecuteResponse> {\n const { relayExecuteUrl } = getFeatureFlags(messenger);\n\n const response = await successfulFetch(relayExecuteUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n return (await response.json()) as RelayExecuteResponse;\n}\n\n/**\n * Poll the Relay status endpoint for a given request ID.\n *\n * @param requestId - The Relay request ID to check.\n * @returns The current status of the request.\n */\nexport async function getRelayStatus(\n requestId: string,\n): Promise<RelayStatusResponse> {\n const url = `${RELAY_STATUS_URL}?requestId=${requestId}`;\n\n const response = await successfulFetch(url, { method: 'GET' });\n\n return (await response.json()) as RelayStatusResponse;\n}\n"]}
1
+ {"version":3,"file":"relay-api.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-api.ts"],"names":[],"mappings":";;;AAAA,iEAA6D;AAG7D,iEAA4D;AAC5D,+CAA+C;AAS/C;;;;;;GAMG;AACI,KAAK,UAAU,eAAe,CACnC,SAA4C,EAC5C,IAAuB;IAEvB,MAAM,EAAE,aAAa,EAAE,GAAG,IAAA,+BAAe,EAAC,SAAS,CAAC,CAAC;IAErD,MAAM,QAAQ,GAAG,MAAM,IAAA,kCAAe,EAAC,aAAa,EAAE;QACpD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAe,CAAC;IACpD,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;IAErB,OAAO,KAAK,CAAC;AACf,CAAC;AAhBD,0CAgBC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,kBAAkB,CACtC,SAA4C,EAC5C,IAAyB;IAEzB,MAAM,EAAE,eAAe,EAAE,GAAG,IAAA,+BAAe,EAAC,SAAS,CAAC,CAAC;IAEvD,MAAM,QAAQ,GAAG,MAAM,IAAA,kCAAe,EAAC,eAAe,EAAE;QACtD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IAEH,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAyB,CAAC;AACzD,CAAC;AAbD,gDAaC;AAED;;;;;GAKG;AACI,KAAK,UAAU,cAAc,CAClC,SAAiB;IAEjB,MAAM,GAAG,GAAG,GAAG,4BAAgB,cAAc,SAAS,EAAE,CAAC;IAEzD,MAAM,QAAQ,GAAG,MAAM,IAAA,kCAAe,EAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAE/D,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAwB,CAAC;AACxD,CAAC;AARD,wCAQC","sourcesContent":["import { successfulFetch } from '@metamask/controller-utils';\n\nimport type { TransactionPayControllerMessenger } from '../../types';\nimport { getFeatureFlags } from '../../utils/feature-flags';\nimport { RELAY_STATUS_URL } from './constants';\nimport type {\n RelayExecuteRequest,\n RelayExecuteResponse,\n RelayQuote,\n RelayQuoteRequest,\n RelayStatusResponse,\n} from './types';\n\n/**\n * Fetch a quote from the Relay API.\n *\n * @param messenger - Controller messenger.\n * @param body - Quote request parameters.\n * @returns The Relay quote with the request attached.\n */\nexport async function fetchRelayQuote(\n messenger: TransactionPayControllerMessenger,\n body: RelayQuoteRequest,\n): Promise<RelayQuote> {\n const { relayQuoteUrl } = getFeatureFlags(messenger);\n\n const response = await successfulFetch(relayQuoteUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n const quote = (await response.json()) as RelayQuote;\n quote.request = body;\n\n return quote;\n}\n\n/**\n * Submit a gasless transaction via the Relay /execute endpoint.\n *\n * @param messenger - Controller messenger.\n * @param body - Execute request parameters.\n * @returns The execute response containing the request ID.\n */\nexport async function submitRelayExecute(\n messenger: TransactionPayControllerMessenger,\n body: RelayExecuteRequest,\n): Promise<RelayExecuteResponse> {\n const { relayExecuteUrl } = getFeatureFlags(messenger);\n\n const response = await successfulFetch(relayExecuteUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n return (await response.json()) as RelayExecuteResponse;\n}\n\n/**\n * Poll the Relay status endpoint for a given request ID.\n *\n * @param requestId - The Relay request ID to check.\n * @returns The current status of the request.\n */\nexport async function getRelayStatus(\n requestId: string,\n): Promise<RelayStatusResponse> {\n const url = `${RELAY_STATUS_URL}?requestId=${requestId}`;\n\n const response = await successfulFetch(url, { method: 'GET' });\n\n return (await response.json()) as RelayStatusResponse;\n}\n"]}
@@ -1,5 +1,5 @@
1
- import type { RelayExecuteRequest, RelayExecuteResponse, RelayQuote, RelayQuoteRequest, RelayStatusResponse } from "./types.cjs";
2
1
  import type { TransactionPayControllerMessenger } from "../../types.cjs";
2
+ import type { RelayExecuteRequest, RelayExecuteResponse, RelayQuote, RelayQuoteRequest, RelayStatusResponse } from "./types.cjs";
3
3
  /**
4
4
  * Fetch a quote from the Relay API.
5
5
  *
@@ -1 +1 @@
1
- {"version":3,"file":"relay-api.d.cts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-api.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACpB,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACpB,oBAAgB;AACjB,OAAO,KAAK,EAAE,iCAAiC,EAAE,wBAAoB;AAGrE;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,iCAAiC,EAC5C,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,UAAU,CAAC,CAarB;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,iCAAiC,EAC5C,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,oBAAoB,CAAC,CAU/B;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,mBAAmB,CAAC,CAM9B"}
1
+ {"version":3,"file":"relay-api.d.cts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-api.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iCAAiC,EAAE,wBAAoB;AAGrE,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACpB,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACpB,oBAAgB;AAEjB;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,iCAAiC,EAC5C,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,UAAU,CAAC,CAarB;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,iCAAiC,EAC5C,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,oBAAoB,CAAC,CAU/B;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,mBAAmB,CAAC,CAM9B"}
@@ -1,5 +1,5 @@
1
- import type { RelayExecuteRequest, RelayExecuteResponse, RelayQuote, RelayQuoteRequest, RelayStatusResponse } from "./types.mjs";
2
1
  import type { TransactionPayControllerMessenger } from "../../types.mjs";
2
+ import type { RelayExecuteRequest, RelayExecuteResponse, RelayQuote, RelayQuoteRequest, RelayStatusResponse } from "./types.mjs";
3
3
  /**
4
4
  * Fetch a quote from the Relay API.
5
5
  *
@@ -1 +1 @@
1
- {"version":3,"file":"relay-api.d.mts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-api.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACpB,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACpB,oBAAgB;AACjB,OAAO,KAAK,EAAE,iCAAiC,EAAE,wBAAoB;AAGrE;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,iCAAiC,EAC5C,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,UAAU,CAAC,CAarB;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,iCAAiC,EAC5C,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,oBAAoB,CAAC,CAU/B;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,mBAAmB,CAAC,CAM9B"}
1
+ {"version":3,"file":"relay-api.d.mts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-api.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iCAAiC,EAAE,wBAAoB;AAGrE,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACpB,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACpB,oBAAgB;AAEjB;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,iCAAiC,EAC5C,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,UAAU,CAAC,CAarB;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,iCAAiC,EAC5C,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,oBAAoB,CAAC,CAU/B;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,mBAAmB,CAAC,CAM9B"}
@@ -1,6 +1,6 @@
1
1
  import { successfulFetch } from "@metamask/controller-utils";
2
- import { RELAY_STATUS_URL } from "./constants.mjs";
3
2
  import { getFeatureFlags } from "../../utils/feature-flags.mjs";
3
+ import { RELAY_STATUS_URL } from "./constants.mjs";
4
4
  /**
5
5
  * Fetch a quote from the Relay API.
6
6
  *
@@ -1 +1 @@
1
- {"version":3,"file":"relay-api.mjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,mCAAmC;AAE7D,OAAO,EAAE,gBAAgB,EAAE,wBAAoB;AAS/C,OAAO,EAAE,eAAe,EAAE,sCAAkC;AAE5D;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,SAA4C,EAC5C,IAAuB;IAEvB,MAAM,EAAE,aAAa,EAAE,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAErD,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,aAAa,EAAE;QACpD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAe,CAAC;IACpD,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;IAErB,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,SAA4C,EAC5C,IAAyB;IAEzB,MAAM,EAAE,eAAe,EAAE,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAEvD,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,eAAe,EAAE;QACtD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IAEH,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAyB,CAAC;AACzD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,SAAiB;IAEjB,MAAM,GAAG,GAAG,GAAG,gBAAgB,cAAc,SAAS,EAAE,CAAC;IAEzD,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAE/D,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAwB,CAAC;AACxD,CAAC","sourcesContent":["import { successfulFetch } from '@metamask/controller-utils';\n\nimport { RELAY_STATUS_URL } from './constants';\nimport type {\n RelayExecuteRequest,\n RelayExecuteResponse,\n RelayQuote,\n RelayQuoteRequest,\n RelayStatusResponse,\n} from './types';\nimport type { TransactionPayControllerMessenger } from '../../types';\nimport { getFeatureFlags } from '../../utils/feature-flags';\n\n/**\n * Fetch a quote from the Relay API.\n *\n * @param messenger - Controller messenger.\n * @param body - Quote request parameters.\n * @returns The Relay quote with the request attached.\n */\nexport async function fetchRelayQuote(\n messenger: TransactionPayControllerMessenger,\n body: RelayQuoteRequest,\n): Promise<RelayQuote> {\n const { relayQuoteUrl } = getFeatureFlags(messenger);\n\n const response = await successfulFetch(relayQuoteUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n const quote = (await response.json()) as RelayQuote;\n quote.request = body;\n\n return quote;\n}\n\n/**\n * Submit a gasless transaction via the Relay /execute endpoint.\n *\n * @param messenger - Controller messenger.\n * @param body - Execute request parameters.\n * @returns The execute response containing the request ID.\n */\nexport async function submitRelayExecute(\n messenger: TransactionPayControllerMessenger,\n body: RelayExecuteRequest,\n): Promise<RelayExecuteResponse> {\n const { relayExecuteUrl } = getFeatureFlags(messenger);\n\n const response = await successfulFetch(relayExecuteUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n return (await response.json()) as RelayExecuteResponse;\n}\n\n/**\n * Poll the Relay status endpoint for a given request ID.\n *\n * @param requestId - The Relay request ID to check.\n * @returns The current status of the request.\n */\nexport async function getRelayStatus(\n requestId: string,\n): Promise<RelayStatusResponse> {\n const url = `${RELAY_STATUS_URL}?requestId=${requestId}`;\n\n const response = await successfulFetch(url, { method: 'GET' });\n\n return (await response.json()) as RelayStatusResponse;\n}\n"]}
1
+ {"version":3,"file":"relay-api.mjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,mCAAmC;AAG7D,OAAO,EAAE,eAAe,EAAE,sCAAkC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,wBAAoB;AAS/C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,SAA4C,EAC5C,IAAuB;IAEvB,MAAM,EAAE,aAAa,EAAE,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAErD,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,aAAa,EAAE;QACpD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAe,CAAC;IACpD,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;IAErB,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,SAA4C,EAC5C,IAAyB;IAEzB,MAAM,EAAE,eAAe,EAAE,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAEvD,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,eAAe,EAAE;QACtD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IAEH,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAyB,CAAC;AACzD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,SAAiB;IAEjB,MAAM,GAAG,GAAG,GAAG,gBAAgB,cAAc,SAAS,EAAE,CAAC;IAEzD,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAE/D,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAwB,CAAC;AACxD,CAAC","sourcesContent":["import { successfulFetch } from '@metamask/controller-utils';\n\nimport type { TransactionPayControllerMessenger } from '../../types';\nimport { getFeatureFlags } from '../../utils/feature-flags';\nimport { RELAY_STATUS_URL } from './constants';\nimport type {\n RelayExecuteRequest,\n RelayExecuteResponse,\n RelayQuote,\n RelayQuoteRequest,\n RelayStatusResponse,\n} from './types';\n\n/**\n * Fetch a quote from the Relay API.\n *\n * @param messenger - Controller messenger.\n * @param body - Quote request parameters.\n * @returns The Relay quote with the request attached.\n */\nexport async function fetchRelayQuote(\n messenger: TransactionPayControllerMessenger,\n body: RelayQuoteRequest,\n): Promise<RelayQuote> {\n const { relayQuoteUrl } = getFeatureFlags(messenger);\n\n const response = await successfulFetch(relayQuoteUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n const quote = (await response.json()) as RelayQuote;\n quote.request = body;\n\n return quote;\n}\n\n/**\n * Submit a gasless transaction via the Relay /execute endpoint.\n *\n * @param messenger - Controller messenger.\n * @param body - Execute request parameters.\n * @returns The execute response containing the request ID.\n */\nexport async function submitRelayExecute(\n messenger: TransactionPayControllerMessenger,\n body: RelayExecuteRequest,\n): Promise<RelayExecuteResponse> {\n const { relayExecuteUrl } = getFeatureFlags(messenger);\n\n const response = await successfulFetch(relayExecuteUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n return (await response.json()) as RelayExecuteResponse;\n}\n\n/**\n * Poll the Relay status endpoint for a given request ID.\n *\n * @param requestId - The Relay request ID to check.\n * @returns The current status of the request.\n */\nexport async function getRelayStatus(\n requestId: string,\n): Promise<RelayStatusResponse> {\n const url = `${RELAY_STATUS_URL}?requestId=${requestId}`;\n\n const response = await successfulFetch(url, { method: 'GET' });\n\n return (await response.json()) as RelayStatusResponse;\n}\n"]}
@@ -3,9 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getRelayMaxGasStationQuote = void 0;
4
4
  const utils_1 = require("@metamask/utils");
5
5
  const bignumber_js_1 = require("bignumber.js");
6
- const gas_station_1 = require("./gas-station.cjs");
7
6
  const logger_1 = require("../../logger.cjs");
8
7
  const token_1 = require("../../utils/token.cjs");
8
+ const gas_station_1 = require("./gas-station.cjs");
9
9
  const log = (0, utils_1.createModuleLogger)(logger_1.projectLogger, 'relay-max-gas-station');
10
10
  const PROBE_AMOUNT_PERCENTAGE = 0.25;
11
11
  var GasCostEstimateSource;
@@ -1 +1 @@
1
- {"version":3,"file":"relay-max-gas-station.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-max-gas-station.ts"],"names":[],"mappings":"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","sourcesContent":["import { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport {\n getGasStationEligibility,\n getGasStationCostInSourceTokenRaw,\n} from './gas-station';\nimport type { RelayQuote, RelayTransactionStep } from './types';\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport {\n getNativeToken,\n getTokenBalance,\n getTokenInfo,\n} from '../../utils/token';\n\nconst log = createModuleLogger(projectLogger, 'relay-max-gas-station');\n\nconst PROBE_AMOUNT_PERCENTAGE = 0.25;\n\nenum GasCostEstimateSource {\n GasStation = 'gas-station',\n Probe = 'probe',\n Quote = 'quote',\n}\n\ntype GasCostEstimate = {\n amount: BigNumber;\n source: GasCostEstimateSource;\n};\n\ntype NativeBalanceCheckResult = {\n hasEnoughNativeBalance: boolean;\n nativeBalance?: string;\n nativeGasCostRaw?: string;\n};\n\ntype GetSingleQuoteFn = (\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n) => Promise<TransactionPayQuote<RelayQuote>>;\n\ntype MaxAmountQuoteContext = {\n fullRequest: PayStrategyGetQuotesRequest;\n getSingleQuote: GetSingleQuoteFn;\n messenger: TransactionPayControllerMessenger;\n request: QuoteRequest;\n};\n\n/**\n * Returns a Relay max-amount quote using a two-phase gas-station fallback.\n *\n * It first requests a standard max quote (phase 1), then when needed estimates\n * gas in source-token units (directly or via a probe quote), requests an\n * adjusted max quote (phase 2), and accepts phase 2 only if validation passes\n * (source gas fee token selected, gas-limit checks, affordability).\n *\n * If any step fails or validation is unsafe, it safely falls back to phase 1.\n * Successful phase-2 quotes are tagged with `metamask.isMaxGasStation = true`.\n *\n * @param request - Relay quote request for a max-amount flow.\n * @param fullRequest - Full quote request context including messenger and transaction.\n * @param getSingleQuote - Quote fetcher used for phase-1, phase-2, and probe quotes.\n * @returns The validated adjusted phase-2 quote, or the original phase-1 quote on fallback.\n */\nexport async function getRelayMaxGasStationQuote(\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n getSingleQuote: GetSingleQuoteFn,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const { messenger } = fullRequest;\n const { sourceChainId, sourceTokenAmount } = request;\n const context: MaxAmountQuoteContext = {\n fullRequest,\n getSingleQuote,\n messenger,\n request,\n };\n\n const phase1Quote = await getSingleQuote(request, fullRequest);\n\n const nativeBalanceCheck = checkEnoughNativeBalanceIfSourceGasFeeTokenNotUsed(\n phase1Quote,\n messenger,\n request,\n );\n\n if (nativeBalanceCheck.hasEnoughNativeBalance) {\n return fallbackToPhase1(\n phase1Quote,\n 'Native balance is sufficient for gas',\n {\n nativeBalance: nativeBalanceCheck.nativeBalance,\n nativeGasCost: nativeBalanceCheck.nativeGasCostRaw,\n },\n );\n }\n\n const gasStationEligibility = getGasStationEligibility(\n messenger,\n sourceChainId,\n );\n\n if (!gasStationEligibility.isEligible) {\n return fallbackToPhase1(\n phase1Quote,\n 'Gas station is disabled or unsupported',\n );\n }\n\n const sourceAmountBN = new BigNumber(sourceTokenAmount);\n const probeCost = await getProbeGasCostInSourceTokenRaw(context);\n\n if (!probeCost) {\n return fallbackToPhase1(\n phase1Quote,\n 'Unable to estimate gas-station source token cost',\n );\n }\n\n const initialGasEstimate: GasCostEstimate = {\n amount: probeCost,\n source: GasCostEstimateSource.Probe,\n };\n\n const adjustedSourceAmount = getAdjustedSourceAmount(\n sourceAmountBN,\n initialGasEstimate.amount,\n );\n\n if (!adjustedSourceAmount.isGreaterThan(0)) {\n return fallbackToPhase1(\n phase1Quote,\n 'Insufficient balance for gas station after max adjustment',\n );\n }\n\n const phase2Quote = await getAdjustedPhase2Quote(\n adjustedSourceAmount,\n initialGasEstimate,\n context,\n );\n\n if (!phase2Quote) {\n return fallbackToPhase1(\n phase1Quote,\n 'Adjusted phase-2 quote request failed',\n );\n }\n\n if (!phase2Quote.fees.isSourceGasFeeToken) {\n return fallbackToPhase1(\n phase1Quote,\n 'Adjusted quote did not return source gas fee token pricing',\n );\n }\n\n const phase1GasLimits = phase1Quote.original.metamask.gasLimits ?? [];\n const phase2GasLimits = phase2Quote.original.metamask.gasLimits ?? [];\n\n if (!hasMatchingGasLimitShape(phase1GasLimits, phase2GasLimits)) {\n return fallbackToPhase1(\n phase1Quote,\n 'Adjusted quote gas limit shape changed between phases',\n {\n phase1GasLimits,\n phase2GasLimits,\n },\n );\n }\n\n const phase1TotalGasLimit = getTotalGasLimit(phase1GasLimits);\n const phase2TotalGasLimit = getTotalGasLimit(phase2GasLimits);\n\n if (phase2TotalGasLimit > phase1TotalGasLimit) {\n return fallbackToPhase1(\n phase1Quote,\n 'Adjusted quote total gas limit increased between phases',\n {\n phase1TotalGasLimit,\n phase2TotalGasLimit,\n },\n );\n }\n\n const validationGasEstimate = new BigNumber(\n phase2Quote.fees.sourceNetwork.max.raw,\n );\n\n if (\n !isAdjustedAmountAffordable(\n adjustedSourceAmount,\n validationGasEstimate,\n sourceAmountBN,\n )\n ) {\n return fallbackToPhase1(\n phase1Quote,\n 'Adjusted quote fails affordability validation',\n {\n adjustedSourceAmount: adjustedSourceAmount.toString(10),\n validationGasCost: validationGasEstimate.toString(10),\n },\n );\n }\n\n markQuoteAsMaxGasStation(phase2Quote);\n\n return phase2Quote;\n}\n\nfunction checkEnoughNativeBalanceIfSourceGasFeeTokenNotUsed(\n quote: TransactionPayQuote<RelayQuote>,\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n): NativeBalanceCheckResult {\n if (quote.fees.isSourceGasFeeToken) {\n return { hasEnoughNativeBalance: false };\n }\n\n const nativeGasCostRaw = quote.fees.sourceNetwork.max.raw;\n const nativeBalance = getTokenBalance(\n messenger,\n request.from,\n request.sourceChainId,\n getNativeToken(request.sourceChainId),\n );\n\n return {\n hasEnoughNativeBalance: new BigNumber(nativeBalance).isGreaterThanOrEqualTo(\n nativeGasCostRaw,\n ),\n nativeBalance,\n nativeGasCostRaw,\n };\n}\n\nfunction getAdjustedSourceAmount(\n sourceAmount: BigNumber,\n estimatedGasCost: BigNumber,\n): BigNumber {\n return sourceAmount\n .minus(estimatedGasCost)\n .integerValue(BigNumber.ROUND_DOWN);\n}\n\nfunction isAdjustedAmountAffordable(\n adjustedSourceAmount: BigNumber,\n gasCost: BigNumber,\n originalSourceAmount: BigNumber,\n): boolean {\n return adjustedSourceAmount\n .plus(gasCost)\n .isLessThanOrEqualTo(originalSourceAmount);\n}\n\nasync function getAdjustedPhase2Quote(\n adjustedSourceAmount: BigNumber,\n initialGasEstimate: GasCostEstimate,\n context: MaxAmountQuoteContext,\n): Promise<TransactionPayQuote<RelayQuote> | undefined> {\n const { fullRequest, getSingleQuote, request } = context;\n\n log('Requesting adjusted max quote', {\n adjustedAmount: adjustedSourceAmount.toString(10),\n gasCostInSourceToken: initialGasEstimate.amount.toString(10),\n gasEstimateSource: initialGasEstimate.source,\n originalAmount: request.sourceTokenAmount,\n });\n\n try {\n return await getSingleQuote(\n {\n ...request,\n sourceTokenAmount: adjustedSourceAmount.toFixed(\n 0,\n BigNumber.ROUND_DOWN,\n ),\n },\n fullRequest,\n );\n } catch (error) {\n log('Adjusted quote request failed, falling back to phase-1 quote', {\n error,\n });\n return undefined;\n }\n}\n\nasync function getGasCostFromQuoteOrGasStation(\n quote: TransactionPayQuote<RelayQuote>,\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n): Promise<GasCostEstimate | undefined> {\n const gasCost = quote.fees.sourceNetwork.max;\n\n if (quote.fees.isSourceGasFeeToken) {\n log('Gas cost already in source token units', { raw: gasCost.raw });\n return {\n amount: new BigNumber(gasCost.raw),\n source: GasCostEstimateSource.Quote,\n };\n }\n\n const firstTxStep = quote.original.steps.find(\n (step): step is RelayTransactionStep => step.kind === 'transaction',\n );\n const firstStepData = firstTxStep?.items[0]?.data;\n\n if (!firstStepData) {\n return undefined;\n }\n\n const totalItemCount = quote.original.steps.reduce(\n (count, step) => count + step.items.length,\n 0,\n );\n\n const totalGasEstimate = (quote.original.metamask.gasLimits ?? []).reduce(\n (acc, gasLimit) => acc + gasLimit,\n 0,\n );\n\n const gasStationCost = await getGasStationCostInSourceTokenRaw({\n firstStepData,\n messenger,\n request: {\n from: request.from,\n sourceChainId: request.sourceChainId,\n sourceTokenAddress: request.sourceTokenAddress,\n },\n totalGasEstimate,\n totalItemCount,\n });\n\n if (!gasStationCost) {\n return undefined;\n }\n\n return {\n amount: new BigNumber(gasStationCost.raw),\n source: GasCostEstimateSource.GasStation,\n };\n}\n\nasync function getProbeGasCostInSourceTokenRaw(\n context: MaxAmountQuoteContext,\n): Promise<BigNumber | undefined> {\n const { fullRequest, getSingleQuote, messenger, request } = context;\n\n const sourceTokenInfo = getTokenInfo(\n messenger,\n request.sourceTokenAddress,\n request.sourceChainId,\n );\n\n if (!sourceTokenInfo) {\n return undefined;\n }\n\n const probeAmount = getProbeSourceAmountRaw(\n request.sourceTokenAmount,\n sourceTokenInfo.decimals,\n );\n\n if (!probeAmount || probeAmount === request.sourceTokenAmount) {\n return undefined;\n }\n\n log('Requesting probe quote for gas station estimation', {\n originalSourceAmount: request.sourceTokenAmount,\n probeAmount,\n });\n\n let probeQuote: TransactionPayQuote<RelayQuote> | undefined;\n\n try {\n probeQuote = await getSingleQuote(\n {\n ...request,\n sourceTokenAmount: probeAmount,\n },\n fullRequest,\n );\n } catch (error) {\n log('Probe quote request failed', { error });\n return undefined;\n }\n\n if (!probeQuote) {\n return undefined;\n }\n\n const probeEstimate = await getGasCostFromQuoteOrGasStation(\n probeQuote,\n messenger,\n request,\n );\n\n return probeEstimate?.amount;\n}\n\nfunction getProbeSourceAmountRaw(\n sourceAmountRaw: string,\n sourceDecimals: number,\n): string | undefined {\n const sourceAmount = new BigNumber(sourceAmountRaw);\n\n if (sourceAmount.isLessThanOrEqualTo(0)) {\n return undefined;\n }\n\n const probeRawAmount = sourceAmount\n .multipliedBy(PROBE_AMOUNT_PERCENTAGE)\n .integerValue(BigNumber.ROUND_FLOOR);\n\n // Minimum probe size: ~0.01 token for tokens with >=2 decimals,\n // otherwise one raw unit for low-decimal tokens.\n const minimumProbeRaw = new BigNumber(1).shiftedBy(\n Math.max(sourceDecimals - 2, 0),\n );\n\n const probeRaw = BigNumber.minimum(\n sourceAmount,\n BigNumber.maximum(probeRawAmount, minimumProbeRaw),\n ).integerValue(BigNumber.ROUND_FLOOR);\n\n if (probeRaw.isLessThanOrEqualTo(0)) {\n return undefined;\n }\n\n return probeRaw.toFixed(0);\n}\n\nfunction fallbackToPhase1(\n phase1Quote: TransactionPayQuote<RelayQuote>,\n message: string,\n paramsToLog?: Record<string, unknown>,\n): TransactionPayQuote<RelayQuote> {\n log(message, paramsToLog);\n return phase1Quote;\n}\n\nfunction hasMatchingGasLimitShape(phase1: number[], phase2: number[]): boolean {\n return phase1.length === phase2.length;\n}\n\nfunction getTotalGasLimit(gasLimits: number[]): number {\n return gasLimits.reduce((total, gasLimit) => total + gasLimit, 0);\n}\n\nfunction markQuoteAsMaxGasStation(\n quote: TransactionPayQuote<RelayQuote>,\n): void {\n quote.original.metamask = {\n ...quote.original.metamask,\n isMaxGasStation: true,\n };\n}\n"]}
1
+ {"version":3,"file":"relay-max-gas-station.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-max-gas-station.ts"],"names":[],"mappings":"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","sourcesContent":["import { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport {\n getNativeToken,\n getTokenBalance,\n getTokenInfo,\n} from '../../utils/token';\nimport {\n getGasStationEligibility,\n getGasStationCostInSourceTokenRaw,\n} from './gas-station';\nimport type { RelayQuote, RelayTransactionStep } from './types';\n\nconst log = createModuleLogger(projectLogger, 'relay-max-gas-station');\n\nconst PROBE_AMOUNT_PERCENTAGE = 0.25;\n\nenum GasCostEstimateSource {\n GasStation = 'gas-station',\n Probe = 'probe',\n Quote = 'quote',\n}\n\ntype GasCostEstimate = {\n amount: BigNumber;\n source: GasCostEstimateSource;\n};\n\ntype NativeBalanceCheckResult = {\n hasEnoughNativeBalance: boolean;\n nativeBalance?: string;\n nativeGasCostRaw?: string;\n};\n\ntype GetSingleQuoteFn = (\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n) => Promise<TransactionPayQuote<RelayQuote>>;\n\ntype MaxAmountQuoteContext = {\n fullRequest: PayStrategyGetQuotesRequest;\n getSingleQuote: GetSingleQuoteFn;\n messenger: TransactionPayControllerMessenger;\n request: QuoteRequest;\n};\n\n/**\n * Returns a Relay max-amount quote using a two-phase gas-station fallback.\n *\n * It first requests a standard max quote (phase 1), then when needed estimates\n * gas in source-token units (directly or via a probe quote), requests an\n * adjusted max quote (phase 2), and accepts phase 2 only if validation passes\n * (source gas fee token selected, gas-limit checks, affordability).\n *\n * If any step fails or validation is unsafe, it safely falls back to phase 1.\n * Successful phase-2 quotes are tagged with `metamask.isMaxGasStation = true`.\n *\n * @param request - Relay quote request for a max-amount flow.\n * @param fullRequest - Full quote request context including messenger and transaction.\n * @param getSingleQuote - Quote fetcher used for phase-1, phase-2, and probe quotes.\n * @returns The validated adjusted phase-2 quote, or the original phase-1 quote on fallback.\n */\nexport async function getRelayMaxGasStationQuote(\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n getSingleQuote: GetSingleQuoteFn,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const { messenger } = fullRequest;\n const { sourceChainId, sourceTokenAmount } = request;\n const context: MaxAmountQuoteContext = {\n fullRequest,\n getSingleQuote,\n messenger,\n request,\n };\n\n const phase1Quote = await getSingleQuote(request, fullRequest);\n\n const nativeBalanceCheck = checkEnoughNativeBalanceIfSourceGasFeeTokenNotUsed(\n phase1Quote,\n messenger,\n request,\n );\n\n if (nativeBalanceCheck.hasEnoughNativeBalance) {\n return fallbackToPhase1(\n phase1Quote,\n 'Native balance is sufficient for gas',\n {\n nativeBalance: nativeBalanceCheck.nativeBalance,\n nativeGasCost: nativeBalanceCheck.nativeGasCostRaw,\n },\n );\n }\n\n const gasStationEligibility = getGasStationEligibility(\n messenger,\n sourceChainId,\n );\n\n if (!gasStationEligibility.isEligible) {\n return fallbackToPhase1(\n phase1Quote,\n 'Gas station is disabled or unsupported',\n );\n }\n\n const sourceAmountBN = new BigNumber(sourceTokenAmount);\n const probeCost = await getProbeGasCostInSourceTokenRaw(context);\n\n if (!probeCost) {\n return fallbackToPhase1(\n phase1Quote,\n 'Unable to estimate gas-station source token cost',\n );\n }\n\n const initialGasEstimate: GasCostEstimate = {\n amount: probeCost,\n source: GasCostEstimateSource.Probe,\n };\n\n const adjustedSourceAmount = getAdjustedSourceAmount(\n sourceAmountBN,\n initialGasEstimate.amount,\n );\n\n if (!adjustedSourceAmount.isGreaterThan(0)) {\n return fallbackToPhase1(\n phase1Quote,\n 'Insufficient balance for gas station after max adjustment',\n );\n }\n\n const phase2Quote = await getAdjustedPhase2Quote(\n adjustedSourceAmount,\n initialGasEstimate,\n context,\n );\n\n if (!phase2Quote) {\n return fallbackToPhase1(\n phase1Quote,\n 'Adjusted phase-2 quote request failed',\n );\n }\n\n if (!phase2Quote.fees.isSourceGasFeeToken) {\n return fallbackToPhase1(\n phase1Quote,\n 'Adjusted quote did not return source gas fee token pricing',\n );\n }\n\n const phase1GasLimits = phase1Quote.original.metamask.gasLimits ?? [];\n const phase2GasLimits = phase2Quote.original.metamask.gasLimits ?? [];\n\n if (!hasMatchingGasLimitShape(phase1GasLimits, phase2GasLimits)) {\n return fallbackToPhase1(\n phase1Quote,\n 'Adjusted quote gas limit shape changed between phases',\n {\n phase1GasLimits,\n phase2GasLimits,\n },\n );\n }\n\n const phase1TotalGasLimit = getTotalGasLimit(phase1GasLimits);\n const phase2TotalGasLimit = getTotalGasLimit(phase2GasLimits);\n\n if (phase2TotalGasLimit > phase1TotalGasLimit) {\n return fallbackToPhase1(\n phase1Quote,\n 'Adjusted quote total gas limit increased between phases',\n {\n phase1TotalGasLimit,\n phase2TotalGasLimit,\n },\n );\n }\n\n const validationGasEstimate = new BigNumber(\n phase2Quote.fees.sourceNetwork.max.raw,\n );\n\n if (\n !isAdjustedAmountAffordable(\n adjustedSourceAmount,\n validationGasEstimate,\n sourceAmountBN,\n )\n ) {\n return fallbackToPhase1(\n phase1Quote,\n 'Adjusted quote fails affordability validation',\n {\n adjustedSourceAmount: adjustedSourceAmount.toString(10),\n validationGasCost: validationGasEstimate.toString(10),\n },\n );\n }\n\n markQuoteAsMaxGasStation(phase2Quote);\n\n return phase2Quote;\n}\n\nfunction checkEnoughNativeBalanceIfSourceGasFeeTokenNotUsed(\n quote: TransactionPayQuote<RelayQuote>,\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n): NativeBalanceCheckResult {\n if (quote.fees.isSourceGasFeeToken) {\n return { hasEnoughNativeBalance: false };\n }\n\n const nativeGasCostRaw = quote.fees.sourceNetwork.max.raw;\n const nativeBalance = getTokenBalance(\n messenger,\n request.from,\n request.sourceChainId,\n getNativeToken(request.sourceChainId),\n );\n\n return {\n hasEnoughNativeBalance: new BigNumber(nativeBalance).isGreaterThanOrEqualTo(\n nativeGasCostRaw,\n ),\n nativeBalance,\n nativeGasCostRaw,\n };\n}\n\nfunction getAdjustedSourceAmount(\n sourceAmount: BigNumber,\n estimatedGasCost: BigNumber,\n): BigNumber {\n return sourceAmount\n .minus(estimatedGasCost)\n .integerValue(BigNumber.ROUND_DOWN);\n}\n\nfunction isAdjustedAmountAffordable(\n adjustedSourceAmount: BigNumber,\n gasCost: BigNumber,\n originalSourceAmount: BigNumber,\n): boolean {\n return adjustedSourceAmount\n .plus(gasCost)\n .isLessThanOrEqualTo(originalSourceAmount);\n}\n\nasync function getAdjustedPhase2Quote(\n adjustedSourceAmount: BigNumber,\n initialGasEstimate: GasCostEstimate,\n context: MaxAmountQuoteContext,\n): Promise<TransactionPayQuote<RelayQuote> | undefined> {\n const { fullRequest, getSingleQuote, request } = context;\n\n log('Requesting adjusted max quote', {\n adjustedAmount: adjustedSourceAmount.toString(10),\n gasCostInSourceToken: initialGasEstimate.amount.toString(10),\n gasEstimateSource: initialGasEstimate.source,\n originalAmount: request.sourceTokenAmount,\n });\n\n try {\n return await getSingleQuote(\n {\n ...request,\n sourceTokenAmount: adjustedSourceAmount.toFixed(\n 0,\n BigNumber.ROUND_DOWN,\n ),\n },\n fullRequest,\n );\n } catch (error) {\n log('Adjusted quote request failed, falling back to phase-1 quote', {\n error,\n });\n return undefined;\n }\n}\n\nasync function getGasCostFromQuoteOrGasStation(\n quote: TransactionPayQuote<RelayQuote>,\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n): Promise<GasCostEstimate | undefined> {\n const gasCost = quote.fees.sourceNetwork.max;\n\n if (quote.fees.isSourceGasFeeToken) {\n log('Gas cost already in source token units', { raw: gasCost.raw });\n return {\n amount: new BigNumber(gasCost.raw),\n source: GasCostEstimateSource.Quote,\n };\n }\n\n const firstTxStep = quote.original.steps.find(\n (step): step is RelayTransactionStep => step.kind === 'transaction',\n );\n const firstStepData = firstTxStep?.items[0]?.data;\n\n if (!firstStepData) {\n return undefined;\n }\n\n const totalItemCount = quote.original.steps.reduce(\n (count, step) => count + step.items.length,\n 0,\n );\n\n const totalGasEstimate = (quote.original.metamask.gasLimits ?? []).reduce(\n (acc, gasLimit) => acc + gasLimit,\n 0,\n );\n\n const gasStationCost = await getGasStationCostInSourceTokenRaw({\n firstStepData,\n messenger,\n request: {\n from: request.from,\n sourceChainId: request.sourceChainId,\n sourceTokenAddress: request.sourceTokenAddress,\n },\n totalGasEstimate,\n totalItemCount,\n });\n\n if (!gasStationCost) {\n return undefined;\n }\n\n return {\n amount: new BigNumber(gasStationCost.raw),\n source: GasCostEstimateSource.GasStation,\n };\n}\n\nasync function getProbeGasCostInSourceTokenRaw(\n context: MaxAmountQuoteContext,\n): Promise<BigNumber | undefined> {\n const { fullRequest, getSingleQuote, messenger, request } = context;\n\n const sourceTokenInfo = getTokenInfo(\n messenger,\n request.sourceTokenAddress,\n request.sourceChainId,\n );\n\n if (!sourceTokenInfo) {\n return undefined;\n }\n\n const probeAmount = getProbeSourceAmountRaw(\n request.sourceTokenAmount,\n sourceTokenInfo.decimals,\n );\n\n if (!probeAmount || probeAmount === request.sourceTokenAmount) {\n return undefined;\n }\n\n log('Requesting probe quote for gas station estimation', {\n originalSourceAmount: request.sourceTokenAmount,\n probeAmount,\n });\n\n let probeQuote: TransactionPayQuote<RelayQuote> | undefined;\n\n try {\n probeQuote = await getSingleQuote(\n {\n ...request,\n sourceTokenAmount: probeAmount,\n },\n fullRequest,\n );\n } catch (error) {\n log('Probe quote request failed', { error });\n return undefined;\n }\n\n if (!probeQuote) {\n return undefined;\n }\n\n const probeEstimate = await getGasCostFromQuoteOrGasStation(\n probeQuote,\n messenger,\n request,\n );\n\n return probeEstimate?.amount;\n}\n\nfunction getProbeSourceAmountRaw(\n sourceAmountRaw: string,\n sourceDecimals: number,\n): string | undefined {\n const sourceAmount = new BigNumber(sourceAmountRaw);\n\n if (sourceAmount.isLessThanOrEqualTo(0)) {\n return undefined;\n }\n\n const probeRawAmount = sourceAmount\n .multipliedBy(PROBE_AMOUNT_PERCENTAGE)\n .integerValue(BigNumber.ROUND_FLOOR);\n\n // Minimum probe size: ~0.01 token for tokens with >=2 decimals,\n // otherwise one raw unit for low-decimal tokens.\n const minimumProbeRaw = new BigNumber(1).shiftedBy(\n Math.max(sourceDecimals - 2, 0),\n );\n\n const probeRaw = BigNumber.minimum(\n sourceAmount,\n BigNumber.maximum(probeRawAmount, minimumProbeRaw),\n ).integerValue(BigNumber.ROUND_FLOOR);\n\n if (probeRaw.isLessThanOrEqualTo(0)) {\n return undefined;\n }\n\n return probeRaw.toFixed(0);\n}\n\nfunction fallbackToPhase1(\n phase1Quote: TransactionPayQuote<RelayQuote>,\n message: string,\n paramsToLog?: Record<string, unknown>,\n): TransactionPayQuote<RelayQuote> {\n log(message, paramsToLog);\n return phase1Quote;\n}\n\nfunction hasMatchingGasLimitShape(phase1: number[], phase2: number[]): boolean {\n return phase1.length === phase2.length;\n}\n\nfunction getTotalGasLimit(gasLimits: number[]): number {\n return gasLimits.reduce((total, gasLimit) => total + gasLimit, 0);\n}\n\nfunction markQuoteAsMaxGasStation(\n quote: TransactionPayQuote<RelayQuote>,\n): void {\n quote.original.metamask = {\n ...quote.original.metamask,\n isMaxGasStation: true,\n };\n}\n"]}
@@ -1,5 +1,5 @@
1
- import type { RelayQuote } from "./types.cjs";
2
1
  import type { PayStrategyGetQuotesRequest, QuoteRequest, TransactionPayQuote } from "../../types.cjs";
2
+ import type { RelayQuote } from "./types.cjs";
3
3
  type GetSingleQuoteFn = (request: QuoteRequest, fullRequest: PayStrategyGetQuotesRequest) => Promise<TransactionPayQuote<RelayQuote>>;
4
4
  /**
5
5
  * Returns a Relay max-amount quote using a two-phase gas-station fallback.
@@ -1 +1 @@
1
- {"version":3,"file":"relay-max-gas-station.d.cts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-max-gas-station.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAwB,oBAAgB;AAEhE,OAAO,KAAK,EACV,2BAA2B,EAC3B,YAAY,EAEZ,mBAAmB,EACpB,wBAAoB;AA4BrB,KAAK,gBAAgB,GAAG,CACtB,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,2BAA2B,KACrC,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC,CAAC;AAS9C;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,2BAA2B,EACxC,cAAc,EAAE,gBAAgB,GAC/B,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC,CA4I1C"}
1
+ {"version":3,"file":"relay-max-gas-station.d.cts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-max-gas-station.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,2BAA2B,EAC3B,YAAY,EAEZ,mBAAmB,EACpB,wBAAoB;AAUrB,OAAO,KAAK,EAAE,UAAU,EAAwB,oBAAgB;AAuBhE,KAAK,gBAAgB,GAAG,CACtB,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,2BAA2B,KACrC,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC,CAAC;AAS9C;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,2BAA2B,EACxC,cAAc,EAAE,gBAAgB,GAC/B,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC,CA4I1C"}
@@ -1,5 +1,5 @@
1
- import type { RelayQuote } from "./types.mjs";
2
1
  import type { PayStrategyGetQuotesRequest, QuoteRequest, TransactionPayQuote } from "../../types.mjs";
2
+ import type { RelayQuote } from "./types.mjs";
3
3
  type GetSingleQuoteFn = (request: QuoteRequest, fullRequest: PayStrategyGetQuotesRequest) => Promise<TransactionPayQuote<RelayQuote>>;
4
4
  /**
5
5
  * Returns a Relay max-amount quote using a two-phase gas-station fallback.
@@ -1 +1 @@
1
- {"version":3,"file":"relay-max-gas-station.d.mts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-max-gas-station.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAwB,oBAAgB;AAEhE,OAAO,KAAK,EACV,2BAA2B,EAC3B,YAAY,EAEZ,mBAAmB,EACpB,wBAAoB;AA4BrB,KAAK,gBAAgB,GAAG,CACtB,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,2BAA2B,KACrC,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC,CAAC;AAS9C;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,2BAA2B,EACxC,cAAc,EAAE,gBAAgB,GAC/B,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC,CA4I1C"}
1
+ {"version":3,"file":"relay-max-gas-station.d.mts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-max-gas-station.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,2BAA2B,EAC3B,YAAY,EAEZ,mBAAmB,EACpB,wBAAoB;AAUrB,OAAO,KAAK,EAAE,UAAU,EAAwB,oBAAgB;AAuBhE,KAAK,gBAAgB,GAAG,CACtB,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,2BAA2B,KACrC,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC,CAAC;AAS9C;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,2BAA2B,EACxC,cAAc,EAAE,gBAAgB,GAC/B,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC,CA4I1C"}
@@ -1,8 +1,8 @@
1
1
  import { createModuleLogger } from "@metamask/utils";
2
2
  import { BigNumber } from "bignumber.js";
3
- import { getGasStationEligibility, getGasStationCostInSourceTokenRaw } from "./gas-station.mjs";
4
3
  import { projectLogger } from "../../logger.mjs";
5
4
  import { getNativeToken, getTokenBalance, getTokenInfo } from "../../utils/token.mjs";
5
+ import { getGasStationEligibility, getGasStationCostInSourceTokenRaw } from "./gas-station.mjs";
6
6
  const log = createModuleLogger(projectLogger, 'relay-max-gas-station');
7
7
  const PROBE_AMOUNT_PERCENTAGE = 0.25;
8
8
  var GasCostEstimateSource;
@@ -1 +1 @@
1
- {"version":3,"file":"relay-max-gas-station.mjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-max-gas-station.ts"],"names":[],"mappings":"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","sourcesContent":["import { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport {\n getGasStationEligibility,\n getGasStationCostInSourceTokenRaw,\n} from './gas-station';\nimport type { RelayQuote, RelayTransactionStep } from './types';\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport {\n getNativeToken,\n getTokenBalance,\n getTokenInfo,\n} from '../../utils/token';\n\nconst log = createModuleLogger(projectLogger, 'relay-max-gas-station');\n\nconst PROBE_AMOUNT_PERCENTAGE = 0.25;\n\nenum GasCostEstimateSource {\n GasStation = 'gas-station',\n Probe = 'probe',\n Quote = 'quote',\n}\n\ntype GasCostEstimate = {\n amount: BigNumber;\n source: GasCostEstimateSource;\n};\n\ntype NativeBalanceCheckResult = {\n hasEnoughNativeBalance: boolean;\n nativeBalance?: string;\n nativeGasCostRaw?: string;\n};\n\ntype GetSingleQuoteFn = (\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n) => Promise<TransactionPayQuote<RelayQuote>>;\n\ntype MaxAmountQuoteContext = {\n fullRequest: PayStrategyGetQuotesRequest;\n getSingleQuote: GetSingleQuoteFn;\n messenger: TransactionPayControllerMessenger;\n request: QuoteRequest;\n};\n\n/**\n * Returns a Relay max-amount quote using a two-phase gas-station fallback.\n *\n * It first requests a standard max quote (phase 1), then when needed estimates\n * gas in source-token units (directly or via a probe quote), requests an\n * adjusted max quote (phase 2), and accepts phase 2 only if validation passes\n * (source gas fee token selected, gas-limit checks, affordability).\n *\n * If any step fails or validation is unsafe, it safely falls back to phase 1.\n * Successful phase-2 quotes are tagged with `metamask.isMaxGasStation = true`.\n *\n * @param request - Relay quote request for a max-amount flow.\n * @param fullRequest - Full quote request context including messenger and transaction.\n * @param getSingleQuote - Quote fetcher used for phase-1, phase-2, and probe quotes.\n * @returns The validated adjusted phase-2 quote, or the original phase-1 quote on fallback.\n */\nexport async function getRelayMaxGasStationQuote(\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n getSingleQuote: GetSingleQuoteFn,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const { messenger } = fullRequest;\n const { sourceChainId, sourceTokenAmount } = request;\n const context: MaxAmountQuoteContext = {\n fullRequest,\n getSingleQuote,\n messenger,\n request,\n };\n\n const phase1Quote = await getSingleQuote(request, fullRequest);\n\n const nativeBalanceCheck = checkEnoughNativeBalanceIfSourceGasFeeTokenNotUsed(\n phase1Quote,\n messenger,\n request,\n );\n\n if (nativeBalanceCheck.hasEnoughNativeBalance) {\n return fallbackToPhase1(\n phase1Quote,\n 'Native balance is sufficient for gas',\n {\n nativeBalance: nativeBalanceCheck.nativeBalance,\n nativeGasCost: nativeBalanceCheck.nativeGasCostRaw,\n },\n );\n }\n\n const gasStationEligibility = getGasStationEligibility(\n messenger,\n sourceChainId,\n );\n\n if (!gasStationEligibility.isEligible) {\n return fallbackToPhase1(\n phase1Quote,\n 'Gas station is disabled or unsupported',\n );\n }\n\n const sourceAmountBN = new BigNumber(sourceTokenAmount);\n const probeCost = await getProbeGasCostInSourceTokenRaw(context);\n\n if (!probeCost) {\n return fallbackToPhase1(\n phase1Quote,\n 'Unable to estimate gas-station source token cost',\n );\n }\n\n const initialGasEstimate: GasCostEstimate = {\n amount: probeCost,\n source: GasCostEstimateSource.Probe,\n };\n\n const adjustedSourceAmount = getAdjustedSourceAmount(\n sourceAmountBN,\n initialGasEstimate.amount,\n );\n\n if (!adjustedSourceAmount.isGreaterThan(0)) {\n return fallbackToPhase1(\n phase1Quote,\n 'Insufficient balance for gas station after max adjustment',\n );\n }\n\n const phase2Quote = await getAdjustedPhase2Quote(\n adjustedSourceAmount,\n initialGasEstimate,\n context,\n );\n\n if (!phase2Quote) {\n return fallbackToPhase1(\n phase1Quote,\n 'Adjusted phase-2 quote request failed',\n );\n }\n\n if (!phase2Quote.fees.isSourceGasFeeToken) {\n return fallbackToPhase1(\n phase1Quote,\n 'Adjusted quote did not return source gas fee token pricing',\n );\n }\n\n const phase1GasLimits = phase1Quote.original.metamask.gasLimits ?? [];\n const phase2GasLimits = phase2Quote.original.metamask.gasLimits ?? [];\n\n if (!hasMatchingGasLimitShape(phase1GasLimits, phase2GasLimits)) {\n return fallbackToPhase1(\n phase1Quote,\n 'Adjusted quote gas limit shape changed between phases',\n {\n phase1GasLimits,\n phase2GasLimits,\n },\n );\n }\n\n const phase1TotalGasLimit = getTotalGasLimit(phase1GasLimits);\n const phase2TotalGasLimit = getTotalGasLimit(phase2GasLimits);\n\n if (phase2TotalGasLimit > phase1TotalGasLimit) {\n return fallbackToPhase1(\n phase1Quote,\n 'Adjusted quote total gas limit increased between phases',\n {\n phase1TotalGasLimit,\n phase2TotalGasLimit,\n },\n );\n }\n\n const validationGasEstimate = new BigNumber(\n phase2Quote.fees.sourceNetwork.max.raw,\n );\n\n if (\n !isAdjustedAmountAffordable(\n adjustedSourceAmount,\n validationGasEstimate,\n sourceAmountBN,\n )\n ) {\n return fallbackToPhase1(\n phase1Quote,\n 'Adjusted quote fails affordability validation',\n {\n adjustedSourceAmount: adjustedSourceAmount.toString(10),\n validationGasCost: validationGasEstimate.toString(10),\n },\n );\n }\n\n markQuoteAsMaxGasStation(phase2Quote);\n\n return phase2Quote;\n}\n\nfunction checkEnoughNativeBalanceIfSourceGasFeeTokenNotUsed(\n quote: TransactionPayQuote<RelayQuote>,\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n): NativeBalanceCheckResult {\n if (quote.fees.isSourceGasFeeToken) {\n return { hasEnoughNativeBalance: false };\n }\n\n const nativeGasCostRaw = quote.fees.sourceNetwork.max.raw;\n const nativeBalance = getTokenBalance(\n messenger,\n request.from,\n request.sourceChainId,\n getNativeToken(request.sourceChainId),\n );\n\n return {\n hasEnoughNativeBalance: new BigNumber(nativeBalance).isGreaterThanOrEqualTo(\n nativeGasCostRaw,\n ),\n nativeBalance,\n nativeGasCostRaw,\n };\n}\n\nfunction getAdjustedSourceAmount(\n sourceAmount: BigNumber,\n estimatedGasCost: BigNumber,\n): BigNumber {\n return sourceAmount\n .minus(estimatedGasCost)\n .integerValue(BigNumber.ROUND_DOWN);\n}\n\nfunction isAdjustedAmountAffordable(\n adjustedSourceAmount: BigNumber,\n gasCost: BigNumber,\n originalSourceAmount: BigNumber,\n): boolean {\n return adjustedSourceAmount\n .plus(gasCost)\n .isLessThanOrEqualTo(originalSourceAmount);\n}\n\nasync function getAdjustedPhase2Quote(\n adjustedSourceAmount: BigNumber,\n initialGasEstimate: GasCostEstimate,\n context: MaxAmountQuoteContext,\n): Promise<TransactionPayQuote<RelayQuote> | undefined> {\n const { fullRequest, getSingleQuote, request } = context;\n\n log('Requesting adjusted max quote', {\n adjustedAmount: adjustedSourceAmount.toString(10),\n gasCostInSourceToken: initialGasEstimate.amount.toString(10),\n gasEstimateSource: initialGasEstimate.source,\n originalAmount: request.sourceTokenAmount,\n });\n\n try {\n return await getSingleQuote(\n {\n ...request,\n sourceTokenAmount: adjustedSourceAmount.toFixed(\n 0,\n BigNumber.ROUND_DOWN,\n ),\n },\n fullRequest,\n );\n } catch (error) {\n log('Adjusted quote request failed, falling back to phase-1 quote', {\n error,\n });\n return undefined;\n }\n}\n\nasync function getGasCostFromQuoteOrGasStation(\n quote: TransactionPayQuote<RelayQuote>,\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n): Promise<GasCostEstimate | undefined> {\n const gasCost = quote.fees.sourceNetwork.max;\n\n if (quote.fees.isSourceGasFeeToken) {\n log('Gas cost already in source token units', { raw: gasCost.raw });\n return {\n amount: new BigNumber(gasCost.raw),\n source: GasCostEstimateSource.Quote,\n };\n }\n\n const firstTxStep = quote.original.steps.find(\n (step): step is RelayTransactionStep => step.kind === 'transaction',\n );\n const firstStepData = firstTxStep?.items[0]?.data;\n\n if (!firstStepData) {\n return undefined;\n }\n\n const totalItemCount = quote.original.steps.reduce(\n (count, step) => count + step.items.length,\n 0,\n );\n\n const totalGasEstimate = (quote.original.metamask.gasLimits ?? []).reduce(\n (acc, gasLimit) => acc + gasLimit,\n 0,\n );\n\n const gasStationCost = await getGasStationCostInSourceTokenRaw({\n firstStepData,\n messenger,\n request: {\n from: request.from,\n sourceChainId: request.sourceChainId,\n sourceTokenAddress: request.sourceTokenAddress,\n },\n totalGasEstimate,\n totalItemCount,\n });\n\n if (!gasStationCost) {\n return undefined;\n }\n\n return {\n amount: new BigNumber(gasStationCost.raw),\n source: GasCostEstimateSource.GasStation,\n };\n}\n\nasync function getProbeGasCostInSourceTokenRaw(\n context: MaxAmountQuoteContext,\n): Promise<BigNumber | undefined> {\n const { fullRequest, getSingleQuote, messenger, request } = context;\n\n const sourceTokenInfo = getTokenInfo(\n messenger,\n request.sourceTokenAddress,\n request.sourceChainId,\n );\n\n if (!sourceTokenInfo) {\n return undefined;\n }\n\n const probeAmount = getProbeSourceAmountRaw(\n request.sourceTokenAmount,\n sourceTokenInfo.decimals,\n );\n\n if (!probeAmount || probeAmount === request.sourceTokenAmount) {\n return undefined;\n }\n\n log('Requesting probe quote for gas station estimation', {\n originalSourceAmount: request.sourceTokenAmount,\n probeAmount,\n });\n\n let probeQuote: TransactionPayQuote<RelayQuote> | undefined;\n\n try {\n probeQuote = await getSingleQuote(\n {\n ...request,\n sourceTokenAmount: probeAmount,\n },\n fullRequest,\n );\n } catch (error) {\n log('Probe quote request failed', { error });\n return undefined;\n }\n\n if (!probeQuote) {\n return undefined;\n }\n\n const probeEstimate = await getGasCostFromQuoteOrGasStation(\n probeQuote,\n messenger,\n request,\n );\n\n return probeEstimate?.amount;\n}\n\nfunction getProbeSourceAmountRaw(\n sourceAmountRaw: string,\n sourceDecimals: number,\n): string | undefined {\n const sourceAmount = new BigNumber(sourceAmountRaw);\n\n if (sourceAmount.isLessThanOrEqualTo(0)) {\n return undefined;\n }\n\n const probeRawAmount = sourceAmount\n .multipliedBy(PROBE_AMOUNT_PERCENTAGE)\n .integerValue(BigNumber.ROUND_FLOOR);\n\n // Minimum probe size: ~0.01 token for tokens with >=2 decimals,\n // otherwise one raw unit for low-decimal tokens.\n const minimumProbeRaw = new BigNumber(1).shiftedBy(\n Math.max(sourceDecimals - 2, 0),\n );\n\n const probeRaw = BigNumber.minimum(\n sourceAmount,\n BigNumber.maximum(probeRawAmount, minimumProbeRaw),\n ).integerValue(BigNumber.ROUND_FLOOR);\n\n if (probeRaw.isLessThanOrEqualTo(0)) {\n return undefined;\n }\n\n return probeRaw.toFixed(0);\n}\n\nfunction fallbackToPhase1(\n phase1Quote: TransactionPayQuote<RelayQuote>,\n message: string,\n paramsToLog?: Record<string, unknown>,\n): TransactionPayQuote<RelayQuote> {\n log(message, paramsToLog);\n return phase1Quote;\n}\n\nfunction hasMatchingGasLimitShape(phase1: number[], phase2: number[]): boolean {\n return phase1.length === phase2.length;\n}\n\nfunction getTotalGasLimit(gasLimits: number[]): number {\n return gasLimits.reduce((total, gasLimit) => total + gasLimit, 0);\n}\n\nfunction markQuoteAsMaxGasStation(\n quote: TransactionPayQuote<RelayQuote>,\n): void {\n quote.original.metamask = {\n ...quote.original.metamask,\n isMaxGasStation: true,\n };\n}\n"]}
1
+ {"version":3,"file":"relay-max-gas-station.mjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-max-gas-station.ts"],"names":[],"mappings":"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","sourcesContent":["import { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport {\n getNativeToken,\n getTokenBalance,\n getTokenInfo,\n} from '../../utils/token';\nimport {\n getGasStationEligibility,\n getGasStationCostInSourceTokenRaw,\n} from './gas-station';\nimport type { RelayQuote, RelayTransactionStep } from './types';\n\nconst log = createModuleLogger(projectLogger, 'relay-max-gas-station');\n\nconst PROBE_AMOUNT_PERCENTAGE = 0.25;\n\nenum GasCostEstimateSource {\n GasStation = 'gas-station',\n Probe = 'probe',\n Quote = 'quote',\n}\n\ntype GasCostEstimate = {\n amount: BigNumber;\n source: GasCostEstimateSource;\n};\n\ntype NativeBalanceCheckResult = {\n hasEnoughNativeBalance: boolean;\n nativeBalance?: string;\n nativeGasCostRaw?: string;\n};\n\ntype GetSingleQuoteFn = (\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n) => Promise<TransactionPayQuote<RelayQuote>>;\n\ntype MaxAmountQuoteContext = {\n fullRequest: PayStrategyGetQuotesRequest;\n getSingleQuote: GetSingleQuoteFn;\n messenger: TransactionPayControllerMessenger;\n request: QuoteRequest;\n};\n\n/**\n * Returns a Relay max-amount quote using a two-phase gas-station fallback.\n *\n * It first requests a standard max quote (phase 1), then when needed estimates\n * gas in source-token units (directly or via a probe quote), requests an\n * adjusted max quote (phase 2), and accepts phase 2 only if validation passes\n * (source gas fee token selected, gas-limit checks, affordability).\n *\n * If any step fails or validation is unsafe, it safely falls back to phase 1.\n * Successful phase-2 quotes are tagged with `metamask.isMaxGasStation = true`.\n *\n * @param request - Relay quote request for a max-amount flow.\n * @param fullRequest - Full quote request context including messenger and transaction.\n * @param getSingleQuote - Quote fetcher used for phase-1, phase-2, and probe quotes.\n * @returns The validated adjusted phase-2 quote, or the original phase-1 quote on fallback.\n */\nexport async function getRelayMaxGasStationQuote(\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n getSingleQuote: GetSingleQuoteFn,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const { messenger } = fullRequest;\n const { sourceChainId, sourceTokenAmount } = request;\n const context: MaxAmountQuoteContext = {\n fullRequest,\n getSingleQuote,\n messenger,\n request,\n };\n\n const phase1Quote = await getSingleQuote(request, fullRequest);\n\n const nativeBalanceCheck = checkEnoughNativeBalanceIfSourceGasFeeTokenNotUsed(\n phase1Quote,\n messenger,\n request,\n );\n\n if (nativeBalanceCheck.hasEnoughNativeBalance) {\n return fallbackToPhase1(\n phase1Quote,\n 'Native balance is sufficient for gas',\n {\n nativeBalance: nativeBalanceCheck.nativeBalance,\n nativeGasCost: nativeBalanceCheck.nativeGasCostRaw,\n },\n );\n }\n\n const gasStationEligibility = getGasStationEligibility(\n messenger,\n sourceChainId,\n );\n\n if (!gasStationEligibility.isEligible) {\n return fallbackToPhase1(\n phase1Quote,\n 'Gas station is disabled or unsupported',\n );\n }\n\n const sourceAmountBN = new BigNumber(sourceTokenAmount);\n const probeCost = await getProbeGasCostInSourceTokenRaw(context);\n\n if (!probeCost) {\n return fallbackToPhase1(\n phase1Quote,\n 'Unable to estimate gas-station source token cost',\n );\n }\n\n const initialGasEstimate: GasCostEstimate = {\n amount: probeCost,\n source: GasCostEstimateSource.Probe,\n };\n\n const adjustedSourceAmount = getAdjustedSourceAmount(\n sourceAmountBN,\n initialGasEstimate.amount,\n );\n\n if (!adjustedSourceAmount.isGreaterThan(0)) {\n return fallbackToPhase1(\n phase1Quote,\n 'Insufficient balance for gas station after max adjustment',\n );\n }\n\n const phase2Quote = await getAdjustedPhase2Quote(\n adjustedSourceAmount,\n initialGasEstimate,\n context,\n );\n\n if (!phase2Quote) {\n return fallbackToPhase1(\n phase1Quote,\n 'Adjusted phase-2 quote request failed',\n );\n }\n\n if (!phase2Quote.fees.isSourceGasFeeToken) {\n return fallbackToPhase1(\n phase1Quote,\n 'Adjusted quote did not return source gas fee token pricing',\n );\n }\n\n const phase1GasLimits = phase1Quote.original.metamask.gasLimits ?? [];\n const phase2GasLimits = phase2Quote.original.metamask.gasLimits ?? [];\n\n if (!hasMatchingGasLimitShape(phase1GasLimits, phase2GasLimits)) {\n return fallbackToPhase1(\n phase1Quote,\n 'Adjusted quote gas limit shape changed between phases',\n {\n phase1GasLimits,\n phase2GasLimits,\n },\n );\n }\n\n const phase1TotalGasLimit = getTotalGasLimit(phase1GasLimits);\n const phase2TotalGasLimit = getTotalGasLimit(phase2GasLimits);\n\n if (phase2TotalGasLimit > phase1TotalGasLimit) {\n return fallbackToPhase1(\n phase1Quote,\n 'Adjusted quote total gas limit increased between phases',\n {\n phase1TotalGasLimit,\n phase2TotalGasLimit,\n },\n );\n }\n\n const validationGasEstimate = new BigNumber(\n phase2Quote.fees.sourceNetwork.max.raw,\n );\n\n if (\n !isAdjustedAmountAffordable(\n adjustedSourceAmount,\n validationGasEstimate,\n sourceAmountBN,\n )\n ) {\n return fallbackToPhase1(\n phase1Quote,\n 'Adjusted quote fails affordability validation',\n {\n adjustedSourceAmount: adjustedSourceAmount.toString(10),\n validationGasCost: validationGasEstimate.toString(10),\n },\n );\n }\n\n markQuoteAsMaxGasStation(phase2Quote);\n\n return phase2Quote;\n}\n\nfunction checkEnoughNativeBalanceIfSourceGasFeeTokenNotUsed(\n quote: TransactionPayQuote<RelayQuote>,\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n): NativeBalanceCheckResult {\n if (quote.fees.isSourceGasFeeToken) {\n return { hasEnoughNativeBalance: false };\n }\n\n const nativeGasCostRaw = quote.fees.sourceNetwork.max.raw;\n const nativeBalance = getTokenBalance(\n messenger,\n request.from,\n request.sourceChainId,\n getNativeToken(request.sourceChainId),\n );\n\n return {\n hasEnoughNativeBalance: new BigNumber(nativeBalance).isGreaterThanOrEqualTo(\n nativeGasCostRaw,\n ),\n nativeBalance,\n nativeGasCostRaw,\n };\n}\n\nfunction getAdjustedSourceAmount(\n sourceAmount: BigNumber,\n estimatedGasCost: BigNumber,\n): BigNumber {\n return sourceAmount\n .minus(estimatedGasCost)\n .integerValue(BigNumber.ROUND_DOWN);\n}\n\nfunction isAdjustedAmountAffordable(\n adjustedSourceAmount: BigNumber,\n gasCost: BigNumber,\n originalSourceAmount: BigNumber,\n): boolean {\n return adjustedSourceAmount\n .plus(gasCost)\n .isLessThanOrEqualTo(originalSourceAmount);\n}\n\nasync function getAdjustedPhase2Quote(\n adjustedSourceAmount: BigNumber,\n initialGasEstimate: GasCostEstimate,\n context: MaxAmountQuoteContext,\n): Promise<TransactionPayQuote<RelayQuote> | undefined> {\n const { fullRequest, getSingleQuote, request } = context;\n\n log('Requesting adjusted max quote', {\n adjustedAmount: adjustedSourceAmount.toString(10),\n gasCostInSourceToken: initialGasEstimate.amount.toString(10),\n gasEstimateSource: initialGasEstimate.source,\n originalAmount: request.sourceTokenAmount,\n });\n\n try {\n return await getSingleQuote(\n {\n ...request,\n sourceTokenAmount: adjustedSourceAmount.toFixed(\n 0,\n BigNumber.ROUND_DOWN,\n ),\n },\n fullRequest,\n );\n } catch (error) {\n log('Adjusted quote request failed, falling back to phase-1 quote', {\n error,\n });\n return undefined;\n }\n}\n\nasync function getGasCostFromQuoteOrGasStation(\n quote: TransactionPayQuote<RelayQuote>,\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n): Promise<GasCostEstimate | undefined> {\n const gasCost = quote.fees.sourceNetwork.max;\n\n if (quote.fees.isSourceGasFeeToken) {\n log('Gas cost already in source token units', { raw: gasCost.raw });\n return {\n amount: new BigNumber(gasCost.raw),\n source: GasCostEstimateSource.Quote,\n };\n }\n\n const firstTxStep = quote.original.steps.find(\n (step): step is RelayTransactionStep => step.kind === 'transaction',\n );\n const firstStepData = firstTxStep?.items[0]?.data;\n\n if (!firstStepData) {\n return undefined;\n }\n\n const totalItemCount = quote.original.steps.reduce(\n (count, step) => count + step.items.length,\n 0,\n );\n\n const totalGasEstimate = (quote.original.metamask.gasLimits ?? []).reduce(\n (acc, gasLimit) => acc + gasLimit,\n 0,\n );\n\n const gasStationCost = await getGasStationCostInSourceTokenRaw({\n firstStepData,\n messenger,\n request: {\n from: request.from,\n sourceChainId: request.sourceChainId,\n sourceTokenAddress: request.sourceTokenAddress,\n },\n totalGasEstimate,\n totalItemCount,\n });\n\n if (!gasStationCost) {\n return undefined;\n }\n\n return {\n amount: new BigNumber(gasStationCost.raw),\n source: GasCostEstimateSource.GasStation,\n };\n}\n\nasync function getProbeGasCostInSourceTokenRaw(\n context: MaxAmountQuoteContext,\n): Promise<BigNumber | undefined> {\n const { fullRequest, getSingleQuote, messenger, request } = context;\n\n const sourceTokenInfo = getTokenInfo(\n messenger,\n request.sourceTokenAddress,\n request.sourceChainId,\n );\n\n if (!sourceTokenInfo) {\n return undefined;\n }\n\n const probeAmount = getProbeSourceAmountRaw(\n request.sourceTokenAmount,\n sourceTokenInfo.decimals,\n );\n\n if (!probeAmount || probeAmount === request.sourceTokenAmount) {\n return undefined;\n }\n\n log('Requesting probe quote for gas station estimation', {\n originalSourceAmount: request.sourceTokenAmount,\n probeAmount,\n });\n\n let probeQuote: TransactionPayQuote<RelayQuote> | undefined;\n\n try {\n probeQuote = await getSingleQuote(\n {\n ...request,\n sourceTokenAmount: probeAmount,\n },\n fullRequest,\n );\n } catch (error) {\n log('Probe quote request failed', { error });\n return undefined;\n }\n\n if (!probeQuote) {\n return undefined;\n }\n\n const probeEstimate = await getGasCostFromQuoteOrGasStation(\n probeQuote,\n messenger,\n request,\n );\n\n return probeEstimate?.amount;\n}\n\nfunction getProbeSourceAmountRaw(\n sourceAmountRaw: string,\n sourceDecimals: number,\n): string | undefined {\n const sourceAmount = new BigNumber(sourceAmountRaw);\n\n if (sourceAmount.isLessThanOrEqualTo(0)) {\n return undefined;\n }\n\n const probeRawAmount = sourceAmount\n .multipliedBy(PROBE_AMOUNT_PERCENTAGE)\n .integerValue(BigNumber.ROUND_FLOOR);\n\n // Minimum probe size: ~0.01 token for tokens with >=2 decimals,\n // otherwise one raw unit for low-decimal tokens.\n const minimumProbeRaw = new BigNumber(1).shiftedBy(\n Math.max(sourceDecimals - 2, 0),\n );\n\n const probeRaw = BigNumber.minimum(\n sourceAmount,\n BigNumber.maximum(probeRawAmount, minimumProbeRaw),\n ).integerValue(BigNumber.ROUND_FLOOR);\n\n if (probeRaw.isLessThanOrEqualTo(0)) {\n return undefined;\n }\n\n return probeRaw.toFixed(0);\n}\n\nfunction fallbackToPhase1(\n phase1Quote: TransactionPayQuote<RelayQuote>,\n message: string,\n paramsToLog?: Record<string, unknown>,\n): TransactionPayQuote<RelayQuote> {\n log(message, paramsToLog);\n return phase1Quote;\n}\n\nfunction hasMatchingGasLimitShape(phase1: number[], phase2: number[]): boolean {\n return phase1.length === phase2.length;\n}\n\nfunction getTotalGasLimit(gasLimits: number[]): number {\n return gasLimits.reduce((total, gasLimit) => total + gasLimit, 0);\n}\n\nfunction markQuoteAsMaxGasStation(\n quote: TransactionPayQuote<RelayQuote>,\n): void {\n quote.original.metamask = {\n ...quote.original.metamask,\n isMaxGasStation: true,\n };\n}\n"]}