Skip to content Skip to documentation navigation
Haptic Docs Open the terminal

Start here

The two signatures

Two wallet popups. Neither is a transaction and neither spends gas, and one of them hands out a key worth understanding first.

Pre-launch. Market data is live Hyperliquid mainnet. Order placement is not wired: the fills, position, PnL and volume shown here are simulated against the real price. Amber outline means simulated. What is built, in full.

You will not meet these prompts yet

The wallet layer described here is built and tested and is not connected to the build you can open, which runs a simulated connect flow that contacts no wallet and signs nothing. It is written now because this is what people want to read before they arrive at it, and because none of it changes when it is switched on.

What the two prompts are not

Connecting asks for two signatures from your main wallet, back to back, off one click. Neither is a blockchain transaction. Both are typed-data signatures, the same mechanism a site uses to ask you to prove you own an address, and they go to Hyperliquid as a signed message. Nothing is broadcast to a chain.

What each of the two signatures authorizesBoth come from your main wallet and neither is a transaction. The first registers a trading key that can place, cancel and modify orders and set leverage, and cannot withdraw. The second approves a builder fee of 0.045% per perpetual fill against a venue cap of 0.1% and authorizes no transfer. Neither spends gas. A key that can trade can still lose the money.YOUR MAIN WALLET, TWICE1 THE TRADING KEY2 THE BUILDER FEEapproveAgentPlaces ordersCancels, modifiesSets leverageCannot withdrawapproveBuilderFee0.045% per perp fillVenue cap 0.1%A rate. That is allNot a transfer0 TRANSACTIONS / 0 GAS / 0 TRANSFERSA KEY THAT CAN TRADE CAN LOSE THE MONEY
Cannot withdraw is structural and is worth what it is worth. What the key can and cannot do is the part to read slowly.

The second prompt will look more serious than the first. It is not.

Wallets render an unfamiliar typed-data structure with more ceremony than a plain message, and all this one carries is a number.

The first one: a trading key

approveAgent. It registers a key the terminal generates in your browser as an agent wallet on your Hyperliquid account, so that placing an order afterwards does not need a wallet popup of its own.

The key comes from your browser's cryptographic random number generator and is never derived from anything your main wallet also derives, so a leak of one cannot compromise the other. It is stored as AES-GCM-256 ciphertext in IndexedDB, wrapped by a key the browser marks non-extractable, with your account address, the network and the expiry bound into the encryption. Edit any of those and the decryption fails instead of quietly succeeding. If your browser does not support that, the key lives in memory for the session. There is no plaintext fallback, ever.

The exchange enforces the expiry

The agent name registered with Hyperliquid carries its own expiry suffix, which Hyperliquid honors. So the expiry is not a promise that the terminal will stop using the key. It is the venue refusing it. An attacker who steals the key and controls your browser cannot extend it. Only a fresh main-wallet signature can.

Local lifetime
7 days
Protocol ceiling
180 days
Which wins
the shorter
Stored as
AES-GCM-256

Revoking it is real, not cosmetic

Wiping the key out of your browser would leave the stolen copy authorized at the venue, so revoke does both. It deletes the local copy and displaces the approval on Hyperliquid by re-approving the same agent name against a throwaway address. Hyperliquid deregisters an existing named agent when a new approval arrives under a matching name, and that is what makes it a genuine revoke. It costs one main-wallet signature.

A plain disconnect clears the key locally only. Prompting your wallet during a logout you just asked for is hostile, so the on-chain displacement is the explicit, user-initiated version. Switching accounts also wipes it: an agent record for one address is never loaded for another.

What the key can and cannot do

Read this part slowly. The honest version is narrower than the version you will hear elsewhere.

It cannot withdraw and it cannot send to anybody else. That is structural, not a permission setting. Hyperliquid's withdraw and send actions carry no "from" field, so the account debited is whichever key signed. This key signing a withdrawal withdraws from its own empty account. Not a rule we chose, and not one we can change.

Do not read that as "safe"

"Agent keys can only trade" is the common phrasing and it is too generous. An agent key can also move your collateral inside your own account tree, including into a Hyperliquid vault, where a hostile vault operator could trade it away. And it can trade, which means it can open maximum-leverage positions and liquidate them deliberately.

So the accurate boundary: an agent key cannot move funds out of your control directly, but it can move them somewhere they can be destroyed, and it can destroy them in place. What the restriction buys is that any such attack is loud, slow, visible on chain, needs market access, and cannot be one silent transfer. We are not going to tell you the funds are safe.

If you would rather not hold a key in a browser at all, declining this first signature is a supported outcome. You stay connected and every order costs a main-wallet signature instead. Declining it never strands you short of the second prompt.

The second one: the builder fee

approveBuilderFee. It approves a maximum fee rate of 0.045% that Hyperliquid will charge on each of your perp fills and route to us. It authorizes a rate. It does not authorize a transfer, a withdrawal, or any other action.

Hyperliquid caps perp builder fees at 0.1%. We ask for 0.045%, which is 45% of the cap, and the exchange rejects anything above it whatever we ask for. Fees has the arithmetic and the units. The units are a real trap and worth reading if you plan to check the number yourself.

Why it has to be your main wallet

Hyperliquid requires it. From the venue's own builder-code documentation, verbatim: "This action must be signed by the user's main wallet, not an agent/API wallet." The terminal cannot route it any other way, and it is built so that it cannot: user-signed actions have exactly one signer available to them, and it is the wallet in your browser.

Which is also why you see two popups. The two approvals are separate user-signed actions with no batch form, so there is no version of this that is a single prompt.

The approval is verified, not assumed

After the signature goes in, the terminal re-queries Hyperliquid to confirm the approved rate. The response it got back is not trusted, and the approved rate has to be at least what we charge. A user who approved a lower rate than we charge is treated as not approved. The order would otherwise be rejected at fill time, which is the worst possible place to discover it.

Declining the fee is a hard stop

The fee is the only revenue in this product. No subscription, no spread markup, no advertising, no second charge anywhere. A session without the fee has nothing to offer either side, so trading without it is not on offer.

If you decline: nothing was signed, nothing changed, your wallet is still connected and the trading key from the first step survives. You get two options, review the fee or disconnect. There is no third one. The connect flow has no skip path and the state machine underneath it never had one.

How to withdraw the fee approval later

At Hyperliquid, under Account then Builder fee, sign the same action with a rate of 0%. Any other Hyperliquid client can do the same. It stops applying from your next fill. You do not need us to do it and we cannot stop you.