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 fasterNext steps
- Low-latency recipes — Optimize signing performance
- Agent permissions — Risk management and scopes
- Agent templates — Reference implementations