Bloxwapdocs
Developers

Signing flows

Integrate private-key wallets, session keys, and hardware/software wallets for trading agents.

Trading on Hyperliquid requires signing each order with an EVM-compatible private key. This guide covers the signing options available in @bloxwap/hyperliquid.

Private-key wallets

The fastest path for automated agents. Store a private key and sign locally.

import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
import { createFastLocalWallet } from '@bloxwap/hyperliquid/signing';
import { ExchangeClient, HttpTransport } from '@bloxwap/hyperliquid';

// Generate a new key (do this once, store securely)
const privateKey = generatePrivateKey();
console.log('Store this key securely:', privateKey);

// For signing, use the fast local wallet
const wallet = await createFastLocalWallet(privateKey);

// Create exchange client
const client = new ExchangeClient({
  transport: new HttpTransport(),
  wallet: wallet,
});

// Place an order
await client.limitOrder({
  coin: 'BTC',
  isBuy: true,
  sz: 0.1,
  limitPx: 50000,
  orderType: { limit: { tif: 'Gtc' } },
});

Storage best practices

  • Never commit private keys to source control
  • Use environment variables or a secrets manager
  • For production agents, use hardware security modules (HSMs) or key management services
  • Rotate keys periodically
// Load from environment
const privateKey = process.env.HYPERLIQUID_PRIVATE_KEY as `0x${string}`;
if (!privateKey) {
  throw new Error('HYPERLIQUID_PRIVATE_KEY not set');
}

Agent wallets (session keys)

Delegate trading permission from a user wallet to an automated agent without exposing the user's private key. The agent wallet has limited permissions and can be revoked.

import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
import { createFastLocalWallet } from '@bloxwap/hyperliquid/signing';
import { ExchangeClient, HttpTransport } from '@bloxwap/hyperliquid';

// 1. Generate an agent key (one-time)
const agentKey = generatePrivateKey();
const agentAccount = privateKeyToAccount(agentKey);

// 2. User approves the agent (signed by user's wallet)
const userWallet = /* ... your user's wallet ... */;
const userClient = new ExchangeClient({
  transport: new HttpTransport(),
  wallet: userWallet,
});

await userClient.approveAgent({
  agentAddress: agentAccount.address,
  agentName: 'MyTradingBot', // optional label
});

// 3. Agent trades on behalf of user
const agentWallet = await createFastLocalWallet(agentKey);
const agentClient = new ExchangeClient({
  transport: new HttpTransport(),
  wallet: agentWallet,
});

// Orders are signed by agent but execute in user's account
await agentClient.limitOrder({
  coin: 'ETH',
  isBuy: true,
  sz: 1.0,
  limitPx: 3000,
  orderType: { limit: { tif: 'Gtc' } },
});

// 4. User can revoke agent permission at any time
await userClient.revokeAgent({
  agentAddress: agentAccount.address,
});

Hardware wallets

For higher-value accounts, integrate hardware wallet signing. Bloxwap uses Ledger for on-chain settlement.

import { createWalletClient, http } from 'viem';
import { arbitrum } from 'viem/chains';
import { ExchangeClient, HttpTransport } from '@bloxwap/hyperliquid';

// Connect to Ledger (requires user interaction)
const walletClient = createWalletClient({
  chain: arbitrum,
  transport: http(),
});

const [address] = await walletClient.getAddresses();

// Use hardware wallet for signing
const client = new ExchangeClient({
  transport: new HttpTransport(),
  wallet: walletClient,
});

// Each order requires hardware confirmation
await client.limitOrder({
  coin: 'SOL',
  isBuy: true,
  sz: 10,
  limitPx: 100,
  orderType: { limit: { tif: 'Gtc' } },
});

Hardware wallet considerations

  • Latency: Each signature requires hardware confirmation (~2-5 seconds)
  • User presence: Hardware wallets require physical button presses
  • Not suitable for: High-frequency trading or fully automated agents
  • Best for: Manual trading with enhanced security, or infrequent rebalancing bots

Browser wallets

Integrate with MetaMask, Privy, or other injected wallets for web-based agents.

import { createWalletClient, custom } from 'viem';
import { arbitrum } from 'viem/chains';
import { ExchangeClient, HttpTransport } from '@bloxwap/hyperliquid';

// Connect to browser wallet (e.g., MetaMask)
if (typeof window !== 'undefined' && window.ethereum) {
  const walletClient = createWalletClient({
    chain: arbitrum,
    transport: custom(window.ethereum),
  });

  await walletClient.requestAddresses();
  const [address] = await walletClient.getAddresses();

  const client = new ExchangeClient({
    transport: new HttpTransport(),
    wallet: walletClient,
  });

  // User approves each transaction in browser
  await client.limitOrder({
    coin: 'BTC',
    isBuy: false,
    sz: 0.05,
    limitPx: 55000,
    orderType: { limit: { tif: 'Gtc' } },
  });
}

Testnet vs. mainnet

Always test on testnet first. Pass isTestnet: true to the transport.

// Testnet
const testnetTransport = new HttpTransport({ isTestnet: true });

// Mainnet
const mainnetTransport = new HttpTransport({ isTestnet: false });

Signature warm-up

Pre-warm the signing path to reduce first-signature latency. Useful for agents that trade infrequently.

import { warmupSigning } from '@bloxwap/hyperliquid/signing';

const wallet = await createFastLocalWallet(privateKey);

// Warm up the signing path (once at startup)
await warmupSigning(wallet);

// First signature is now faster

Next steps

On this page