Bloxwapdocs
Developers

Agent templates

Reference agent implementations using LangGraph, CrewAI, and custom frameworks.

These templates demonstrate automated trading agents that consume market signals and execute orders through Hyperliquid. All examples default to testnet and dry-run mode for safety.

Prerequisites

All templates require:

npm install @bloxwap/hyperliquid viem

Set your private key (generate a testnet key first):

export HYPERLIQUID_PRIVATE_KEY="0x..."
export HYPERLIQUID_TESTNET=true

Custom agent (minimal)

A standalone trading agent without dependencies on LangGraph or CrewAI.

import { HttpTransport, ExchangeClient, InfoClient } from '@bloxwap/hyperliquid';
import { createFastLocalWallet } from '@bloxwap/hyperliquid/signing';

interface Signal {
  coin: string;
  action: 'buy' | 'sell' | 'close';
  confidence: number; // 0-1
  reason: string;
}

class TradingAgent {
  private client: ExchangeClient;
  private info: InfoClient;
  private wallet: string;
  private dryRun: boolean;

  constructor(privateKey: string, isTestnet = true, dryRun = true) {
    this.dryRun = dryRun;
    const transport = new HttpTransport({ isTestnet });
    this.info = new InfoClient({ transport });
    
    // Only create exchange client if not in dry-run mode
    if (!dryRun) {
      createFastLocalWallet(privateKey).then(wallet => {
        this.wallet = wallet.address;
        this.client = new ExchangeClient({ transport, wallet });
      });
    }
  }

  async generateSignal(coin: string): Promise<Signal | null> {
    // Example: Simple momentum signal
    const mids = await this.info.allMids();
    const currentPrice = parseFloat(mids[coin]);
    
    // Get historical prices (simplified - use real data in production)
    const ma20 = await this.getMA(coin, 20);
    const ma50 = await this.getMA(coin, 50);
    
    if (!ma20 || !ma50) return null;
    
    // Golden cross
    if (ma20 > ma50 && currentPrice > ma20) {
      return {
        coin,
        action: 'buy',
        confidence: 0.7,
        reason: 'Golden cross: MA20 > MA50 and price > MA20',
      };
    }
    
    // Death cross
    if (ma20 < ma50 && currentPrice < ma20) {
      return {
        coin,
        action: 'sell',
        confidence: 0.7,
        reason: 'Death cross: MA20 < MA50 and price < MA20',
      };
    }
    
    return null;
  }

  async executeSignal(signal: Signal) {
    console.log(`[${this.dryRun ? 'DRY RUN' : 'LIVE'}] Signal:`, signal);
    
    if (this.dryRun) {
      console.log('Dry run - order not placed');
      return;
    }
    
    // Real order execution (requires low confidence threshold for safety)
    if (signal.confidence < 0.8) {
      console.log('Confidence too low, skipping');
      return;
    }
    
    const price = await this.getCurrentPrice(signal.coin);
    const notional = 100; // $100 position size
    const size = notional / price;
    
    if (signal.action === 'buy') {
      await this.client.limitOrder({
        coin: signal.coin,
        isBuy: true,
        sz: size,
        limitPx: price * 1.001, // 0.1% above market
        orderType: { limit: { tif: 'Ioc' } },
      });
    } else if (signal.action === 'sell') {
      await this.client.limitOrder({
        coin: signal.coin,
        isBuy: false,
        sz: size,
        limitPx: price * 0.999, // 0.1% below market
        orderType: { limit: { tif: 'Ioc' } },
      });
    }
  }

  private async getCurrentPrice(coin: string): Promise<number> {
    const mids = await this.info.allMids();
    return parseFloat(mids[coin]);
  }

  private async getMA(coin: string, periods: number): Promise<number | null> {
    // Implement using historical data source
    // This is a placeholder
    return null;
  }

  async run() {
    const markets = ['BTC', 'ETH', 'SOL'];
    
    console.log(`Starting agent (${this.dryRun ? 'DRY RUN' : 'LIVE MODE'})`);
    console.log('Press Ctrl+C to stop');
    
    setInterval(async () => {
      for (const market of markets) {
        try {
          const signal = await this.generateSignal(market);
          if (signal) {
            await this.executeSignal(signal);
          }
        } catch (error) {
          console.error(`Error processing ${market}:`, error);
        }
      }
    }, 60_000); // Check every minute
  }
}

// Run in dry-run mode by default
const agent = new TradingAgent(
  process.env.HYPERLIQUID_PRIVATE_KEY!,
  process.env.HYPERLIQUID_TESTNET === 'true',
  process.env.DRY_RUN !== 'false', // Defaults to true
);

agent.run();

LangGraph agent

Use LangGraph for complex decision-making workflows.

First, install dependencies:

npm install @langchain/core @langchain/openai langgraph
import { StateGraph, END, Annotation } from "@langchain/langgraph";
import { ChatOpenAI } from "@langchain/openai";
import { HttpTransport, InfoClient } from '@bloxwap/hyperliquid';

// Define agent state
const AgentState = Annotation.Root({
  market: Annotation<string>,
  price: Annotation<number>,
  signal: Annotation<'buy' | 'sell' | 'hold' | null>,
  confidence: Annotation<number>,
  reasoning: Annotation<string>,
  dryRun: Annotation<boolean>,
});

// Node: Fetch market data
async function fetchMarketData(state: typeof AgentState.State) {
  const transport = new HttpTransport({ 
    isTestnet: process.env.HYPERLIQUID_TESTNET === 'true' 
  });
  const info = new InfoClient({ transport });
  
  const mids = await info.allMids();
  const price = parseFloat(mids[state.market]);
  
  return { price };
}

// Node: Analyze with LLM
async function analyzeMarket(state: typeof AgentState.State) {
  const llm = new ChatOpenAI({
    modelName: "gpt-4",
    temperature: 0.7,
  });
  
  const prompt = `
    Analyze the following market data and provide a trading signal.
    
    Market: ${state.market}
    Current Price: $${state.price}
    
    Respond in JSON format:
    {
      "signal": "buy" | "sell" | "hold",
      "confidence": 0.0-1.0,
      "reasoning": "Brief explanation"
    }
  `;
  
  const response = await llm.invoke(prompt);
  const analysis = JSON.parse(response.content as string);
  
  return {
    signal: analysis.signal,
    confidence: analysis.confidence,
    reasoning: analysis.reasoning,
  };
}

// Node: Execute trade (or log in dry-run)
async function executeTrade(state: typeof AgentState.State) {
  if (state.dryRun) {
    console.log('[DRY RUN] Would execute:', {
      market: state.market,
      signal: state.signal,
      confidence: state.confidence,
      reasoning: state.reasoning,
    });
    return {};
  }
  
  // Real execution (requires additional setup)
  if (state.confidence > 0.8 && state.signal !== 'hold') {
    // Place order via Hyperliquid
    console.log('Executing live trade:', state.signal, state.market);
  }
  
  return {};
}

// Build the graph
const workflow = new StateGraph(AgentState)
  .addNode("fetchData", fetchMarketData)
  .addNode("analyze", analyzeMarket)
  .addNode("execute", executeTrade)
  .addEdge("fetchData", "analyze")
  .addEdge("analyze", "execute")
  .addEdge("execute", END)
  .setEntryPoint("fetchData");

const app = workflow.compile();

// Run the agent
async function runLangGraphAgent() {
  const markets = ['BTC', 'ETH', 'SOL'];
  
  for (const market of markets) {
    const result = await app.invoke({
      market,
      dryRun: process.env.DRY_RUN !== 'false',
    });
    
    console.log(`${market} analysis complete:`, result);
  }
}

runLangGraphAgent();

CrewAI agent

Use CrewAI for multi-agent collaboration.

First, install dependencies:

npm install crewai-js @langchain/openai
import { Agent, Task, Crew } from 'crewai-js';
import { ChatOpenAI } from '@langchain/openai';
import { HttpTransport, InfoClient } from '@bloxwap/hyperliquid';

const llm = new ChatOpenAI({ modelName: "gpt-4" });

// Agent 1: Market researcher
const researcher = new Agent({
  role: 'Market Researcher',
  goal: 'Analyze market data and identify trading opportunities',
  backstory: 'Expert in technical analysis and market trends',
  llm: llm,
  verbose: true,
});

// Agent 2: Risk manager
const riskManager = new Agent({
  role: 'Risk Manager',
  goal: 'Evaluate risk and position sizing for trades',
  backstory: 'Conservative risk manager focused on capital preservation',
  llm: llm,
  verbose: true,
});

// Agent 3: Trade executor
const executor = new Agent({
  role: 'Trade Executor',
  goal: 'Execute approved trades with optimal timing',
  backstory: 'Experienced trader focused on execution quality',
  llm: llm,
  verbose: true,
});

// Task 1: Research
const researchTask = new Task({
  description: `
    Analyze BTC market conditions and provide a trading recommendation.
    Consider: price trends, volume, and market sentiment.
  `,
  agent: researcher,
  expectedOutput: 'Trading signal with reasoning',
});

// Task 2: Risk assessment
const riskTask = new Task({
  description: `
    Review the trading signal and assess:
    - Position size
    - Stop loss placement
    - Risk/reward ratio
    Approve or reject the trade.
  `,
  agent: riskManager,
  expectedOutput: 'Risk assessment and approval decision',
});

// Task 3: Execution
const executeTask = new Task({
  description: `
    If approved, execute the trade with:
    - Optimal entry timing
    - Stop loss and take profit orders
    - Position size as recommended
    
    DRY RUN: Log the order without executing.
  `,
  agent: executor,
  expectedOutput: 'Execution report',
});

// Create the crew
const tradingCrew = new Crew({
  agents: [researcher, riskManager, executor],
  tasks: [researchTask, riskTask, executeTask],
  verbose: true,
});

// Run the crew
async function runCrewAI() {
  console.log('[DRY RUN] Starting CrewAI trading analysis');
  
  const result = await tradingCrew.kickoff();
  
  console.log('Crew result:', result);
}

runCrewAI();

Signal integration

Integrate external signals (e.g., from Bloxwap analytics):

interface BloxwapSignal {
  market: string;
  signal: 'bullish' | 'bearish' | 'neutral';
  strength: number; // 0-100
  indicators: {
    rsi?: number;
    macdCross?: boolean;
    volumeSpike?: boolean;
  };
}

async function fetchBloxwapSignals(): Promise<BloxwapSignal[]> {
  // Example: Fetch from Bloxwap API or analytics service
  const response = await fetch('https://bloxwap.app/api/v1/signals', {
    headers: { 'X-API-Key': process.env.BLOXWAP_API_KEY! },
  });
  
  return await response.json();
}

async function processSignals() {
  const signals = await fetchBloxwapSignals();
  
  for (const signal of signals) {
    if (signal.strength > 80) {
      console.log('Strong signal detected:', signal);
      // Execute via your agent
    }
  }
}

Safety checklist

Before deploying any agent:

  1. ✅ Test on testnet — Run for at least 48 hours
  2. ✅ Dry-run mode — Log orders without executing
  3. ✅ Position limits — Implement max notional caps
  4. ✅ Stop losses — Required on every position
  5. ✅ Circuit breakers — Auto-disable on large losses
  6. ✅ Monitoring — Real-time alerts and logs
  7. ✅ Emergency stop — Manual kill switch
  8. ✅ Gradual ramp — Start with tiny positions

Environment variables

All templates support these environment variables:

# Required
HYPERLIQUID_PRIVATE_KEY=0x...        # Your wallet private key

# Optional
HYPERLIQUID_TESTNET=true             # Use testnet (default: true)
DRY_RUN=true                         # Log orders without executing (default: true)
MAX_POSITION_SIZE=100                # Max notional USD per position (default: 100)
BLOXWAP_API_KEY=...                  # For Bloxwap signal integration

# LLM providers (for LangGraph/CrewAI)
OPENAI_API_KEY=...                   # OpenAI API key
ANTHROPIC_API_KEY=...                # Anthropic API key

Production deployment

When moving to production:

  1. Generate a dedicated mainnet private key
  2. Set HYPERLIQUID_TESTNET=false
  3. Set DRY_RUN=false
  4. Start with minimum position sizes
  5. Monitor continuously for 24 hours
  6. Gradually increase position sizes

Next steps

On this page