Skip to main content
Before trading on Hyperliquid, users must complete the provider’s setup descriptors. The SDK provides methods to discover, build, sign, and submit these. Post-setup tuning is exposed via the provider’s options descriptors (e.g. accountMode) — these never gate trading. The flow:
  1. CheckcheckSetup() returns the outstanding setup steps and whether the account is ready
  2. Sign — sign each step with signProviderSetupAction() (it routes each step to the correct signer by shape)
  3. ExecuteexecuteProviderSetup() submits the signed steps
// Check what's needed
const required = await perps.checkSetup({
  provider: 'hyperliquid',
  address: userAddress,
});

if (!required.isReady) {
  // Sign each outstanding setup step
  const signedActions = await Promise.all(
    required.setup.map((step) =>
      perps.signProviderSetupAction('hyperliquid', userAddress, step),
    ),
  );

  // Submit the signed steps
  await perps.executeProviderSetup({
    provider: 'hyperliquid',
    address: userAddress,
    setup: required.setup,
    signedActions,
  });
}
Parameters for checkSetup:
FieldTypeRequiredDescription
providerstringYesProvider identifier
addressstringYesUser’s wallet address
Returns: ProviderSetup
FieldTypeDescription
setupActionStep[]Outstanding setup steps, ordered by descriptor sequence
isReadybooleanWhether all setup items are already satisfied
Parameters for executeProviderSetup:
FieldTypeRequiredDescription
providerstringYesProvider identifier
addressstringYesUser’s wallet address
setupActionStep[]YesThe outstanding steps from checkSetup()
signedActionsSignedActionStep[]YesSigned counterparts of setup, in the same order
Returns: ExecuteProviderSetupResult{ results: ExecuteActionResponse }

Setup descriptors

The following setup actions are returned in the setup array from GET /providers for Hyperliquid. The SDK executes them automatically during the setup flow.

approveAgent

Authorizes an agent wallet to sign trading operations on the user’s behalf. This is the one-time wallet signature that enables agent-based trading — once approved, the SDK-managed agent can place, cancel, and modify orders without wallet popups.
SignersUSER
ParamsApproveAgentParams{ agentAddress, agentTtlMs? }
When neededFirst time provisioning an agent on this account, or when an existing agent approval has expired

approveBuilderFee

Approves the LI.FI builder fee on the user’s Hyperliquid account. Hyperliquid requires explicit builder fee approval before orders can be routed through third-party builders like LI.FI.
SignersUSER
Params{} (empty — the backend determines the builder address and fee rate)
When neededFirst time trading through LI.FI on this Hyperliquid account

Options descriptors

The following options actions are returned in the options array from GET /providers for Hyperliquid. These never gate trading — they are post-setup tuning controls rendered behind a cog icon in the widget. The accepted parameter values are enumerated on each descriptor’s params[].values array.

accountMode

Switches the account’s operating mode between Hyperliquid abstraction variants. accountMode is a single action that accepts either USER or AGENT signers — the backend dispatches to the appropriate EIP-712 typed-data builder based on which key signs the request. The setup flow pairs a user-signed and agent-signed step when upgrading to unifiedAccount.
SignersUSER, AGENT
ParamsAccountModeParams{ mode: string }
When neededSwitching abstraction mode (e.g. upgrading a new account to unifiedAccount)
Mode values: unifiedAccount (default), dexAbstraction (deprecated — avoid exposing to users), disabled (standard/manual mode). For a full explanation of what each mode means — balance unification behaviour, capital efficiency, and signing requirements — see Account Abstraction.

Low-Level API

Using the low-level API directly:
import { createAction, executeAction } from '@lifi/perps-sdk';

// Build setup payloads
const { actions } = await createAction(client, {
  provider: 'hyperliquid',
  address: userAddress,
  action: 'approveAgent',
  params: { agentAddress: '0x...' },
});

// Sign and execute — APPROVE_AGENT is EIP-712, so each step carries `typedData`
const signedActions = await Promise.all(
  actions.map(async (a) => ({
    action: a.action,
    typedData: a.typedData,
    signature: await walletClient.signTypedData({ ...a.typedData }),
  })),
);

await executeAction(client, {
  provider: 'hyperliquid',
  address: userAddress,
  action: 'approveAgent',
  actions: signedActions,
});