feat(transaction-pay-controller): add HyperLiquid source quote support for Perps Withdraw#8285
feat(transaction-pay-controller): add HyperLiquid source quote support for Perps Withdraw#8285
Conversation
…t for Perps Withdraw Signed-off-by: dan437 <80175477+dan437@users.noreply.github.com>
Signed-off-by: dan437 <80175477+dan437@users.noreply.github.com>
| const { steps } = quote.original; | ||
| const params = steps.flatMap((step) => step.items).map((item) => item.data); | ||
| const txSteps = steps.filter( | ||
| (step): step is RelayTransactionStep => step.kind === 'transaction', |
There was a problem hiding this comment.
This was needed because with HyperLiquid withdraw the quote will come back as 2 different kinds:
authorize -> kind: 'signature'
deposit -> kind: 'transaction'
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
| const txSteps = steps.filter( | ||
| (step): step is RelayTransactionStep => step.kind === 'transaction', | ||
| ); | ||
| const params = txSteps.flatMap((step) => step.items).map((item) => item.data); |
There was a problem hiding this comment.
Invalid kind guard blocks HyperLiquid signature steps
High Severity
The txSteps filter on lines 314-316 correctly narrows to transaction steps, but the invalidKind guard still scans ALL steps and throws for any non-transaction kind. Since RelaySignatureStep (with kind: 'signature') was added to the steps union for HyperLiquid withdrawal support, any quote containing a signature step will cause submitTransactions to throw "Unsupported step kind: signature", completely blocking HyperLiquid withdrawal submission. There is no isHyperliquidSource check in relay-submit.ts to bypass this.
Additional Locations (1)
| export const POLYGON_USDCE_ADDRESS = | ||
| '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174' as Hex; | ||
|
|
||
| export const HYPERCORE_USDC_ADDRESS = '0x00000000000000000000000000000000'; |
There was a problem hiding this comment.
These are technically just Relay aliases but I see we already define the chain ID and stablecoin below.
| const firstTxStep = quote.original.steps.find( | ||
| (step) => step.kind === 'transaction', | ||
| ); | ||
| const firstStepData = firstTxStep?.items[0]?.data as |
There was a problem hiding this comment.
Minor, could we cast the above firstTxStep if we know the transaction type equates to a specific object?
| } | ||
|
|
||
| if (request.isHyperliquidSource) { | ||
| body.protocolVersion = 'v2'; |
There was a problem hiding this comment.
Is this needed? I thought the default was v2 now as Relay toggled it for our referrer.
| const tokenTransferData = nestedTransactions?.find((nestedTx) => | ||
| nestedTx.data?.startsWith(TOKEN_TRANSFER_FOUR_BYTE), | ||
| const tokenTransferData = nestedTransactions?.find( | ||
| (nestedTx: { data?: Hex }) => |
|
|
||
| // HyperLiquid withdrawal: source is HyperCore Perps USDC, not Arbitrum. | ||
| // Override source chain/token and set protocolVersion=v2 (required by Relay). | ||
| if (request.isHyperliquidSource) { |
There was a problem hiding this comment.
In future, we could inject this at the client level as a constructed payment token but it would be difficult to get the balance, and would only with Relay etc.
| export const HYPERCORE_USDC_ADDRESS = '0x00000000000000000000000000000000'; | ||
|
|
||
| // HyperCore Perps USDC uses 8 decimals vs standard USDC's 6. | ||
| export const HYPERCORE_USDC_DECIMAL_SHIFT = 2; |
There was a problem hiding this comment.
Minor, would it be more accurate to define the decimals so we can calculate the shift based on the tokens we're converting from?
This assumes it is always USDC.
| // For HyperLiquid source, the normalized chain/token (HyperCore + Perps USDC) | ||
| // won't have a fiat rate entry. Use Arbitrum USDC instead since Perps USDC | ||
| // is pegged 1:1. | ||
| const sourceChainId = request.isHyperliquidSource |
| }; | ||
|
|
||
| /** HyperLiquid deposit step (sendAsset to Relay solver). */ | ||
| export type RelayHyperliquidDepositStep = { |
There was a problem hiding this comment.
Minor, should this also be in the steps type above?
| }; | ||
| status: 'complete' | 'incomplete'; | ||
| }[]; | ||
| kind: 'transaction'; |
There was a problem hiding this comment.
Please tell me they don't have a different schema but leave the kind the same and not hyperliquid or something? 😅
| * When true, the Relay strategy uses the HyperLiquid 2-step withdrawal | ||
| * flow: (1) authorize nonce-mapping, (2) sendAsset to Relay solver. | ||
| */ | ||
| isHyperliquidSource?: boolean; |


Explanation
Adds HyperLiquid source quote support for Perps Withdraw. With this we will be able to show a quote for Perps Withdraw on a client.
References
Fixes https://consensyssoftware.atlassian.net/browse/CONF-1089
Checklist
Note
Medium Risk
Adds a new
isHyperliquidSourceflag that changes Relay quote request normalization, fee calculation (gasless), and request schema, which could affect quote correctness for post-quote flows if the override logic is wrong.Overview
Adds HyperLiquid-source (HyperCore) support to Transaction Pay’s Relay quoting path via a new
isHyperliquidSourceflag.When enabled, Relay quote requests are normalized to use HyperCore Perps USDC (including a decimal shift), include
protocolVersion: 'v2', use Arbitrum USDC for fiat-rate lookup, and treat source-network fees as gasless (zeroed). Types are expanded to handle non-transaction Relay steps and code paths are updated to only processtransactionsteps for gas estimation/submission.Plumbs
isHyperliquidSourcethrough controller config and quote-request building, adds HyperCore USDC constants, and extends tests to cover the new behavior.Written by Cursor Bugbot for commit c6e2d66. This will update automatically on new commits. Configure here.