Tutorial Mastra TypeScript March 4, 2026 · 9 min read

Building a Crypto Trading Agent with Mastra

Mastra.ai has rapidly become one of the most-loved TypeScript agent frameworks. Its clean abstractions for tools, memory, and deployment make it easy to build production agents without boilerplate. Combined with Purple Flea's financial APIs, you can build a full crypto trading agent in under 100 lines of TypeScript.

This guide covers everything: wallet creation, opening perpetual futures positions on Hyperliquid, checking P&L, and using Mastra's built-in memory to track positions across conversation turns.

Why TypeScript for Financial Agents

TypeScript's type system makes financial agent code substantially safer than untyped alternatives. When you define that a size parameter is a number between 10 and 100,000, TypeScript enforces that at compile time. Zod schemas, which Mastra uses natively, add runtime validation on top.

TypeScript + Zod + Purple Flea = financial agents with three layers of correctness guarantees.

Installation

# Install Mastra and the Purple Flea SDK
npm install @mastra/core @purpleflea/mastra zod

# Set your API key
export PURPLE_FLEA_API_KEY="pf_..."

Defining the Tools

Mastra tools are created with createTool() and use Zod for schema validation. Each tool has an id, description, optional inputSchema, and an execute function.

// tools.ts
import { createTool } from '@mastra/core/tools';
import { z } from 'zod';
import { PurpleFleas } from '@purpleflea/mastra';

const flea = new PurpleFleas({ apiKey: process.env.PURPLE_FLEA_API_KEY! });

export const walletCreateTool = createTool({
  id: 'wallet-create',
  description: 'Create a new non-custodial BIP-39 HD crypto wallet. Returns address and chain info.',
  execute: async () => flea.wallet.create(),
});

export const walletBalanceTool = createTool({
  id: 'wallet-balance',
  description: 'Get the current balance of a wallet address on a specific chain.',
  inputSchema: z.object({
    address: z.string().describe('The wallet public address'),
    chain: z.enum(['eth', 'btc', 'sol', 'bnb', 'matic', 'trx']).default('eth'),
  }),
  execute: async ({ context }) => flea.wallet.balance(context.address, context.chain),
});

export const tradeOpenTool = createTool({
  id: 'trade-open',
  description: 'Open a perpetual futures position on Hyperliquid. 275+ markets available.',
  inputSchema: z.object({
    market: z.string().describe("Market symbol, e.g. 'ETH-PERP', 'BTC-PERP', 'SOL-PERP'"),
    sizeUsd: z.number().min(10).max(100_000).describe('Position size in USD'),
    side: z.enum(['long', 'short']),
    leverage: z.number().min(1).max(50).default(1),
  }),
  execute: async ({ context }) => flea.trading.openPosition(context),
});

export const tradeCloseTool = createTool({
  id: 'trade-close',
  description: 'Close an open perpetual futures position and realize P&L.',
  inputSchema: z.object({
    positionId: z.string().describe('The position ID from trade-open'),
  }),
  execute: async ({ context }) => flea.trading.closePosition(context.positionId),
});

export const positionsTool = createTool({
  id: 'positions-list',
  description: 'List all open positions with current unrealized P&L.',
  execute: async () => flea.trading.getPositions(),
});

Creating the Agent

Mastra agents combine tools, memory, and a system prompt. The memory parameter uses Mastra's built-in conversation memory, which automatically tracks positions across turns without you writing any state management code.

// agent.ts
import { Agent } from '@mastra/core/agent';
import { Memory } from '@mastra/memory';
import { openai } from '@ai-sdk/openai';
import {
  walletCreateTool, walletBalanceTool,
  tradeOpenTool, tradeCloseTool, positionsTool
} from './tools';

export const cryptoAgent = new Agent({
  name: 'CryptoTrader',
  instructions: `You are an autonomous crypto trading agent with access to real financial markets.

  You can create wallets, open perpetual futures positions, and manage your portfolio.
  Available markets include ETH-PERP, BTC-PERP, SOL-PERP, and 270+ more via Hyperliquid.

  Risk guidelines:
  - Never use leverage above 10x unless explicitly requested
  - Default position size should not exceed $1000 unless specified
  - Always confirm large trades (>$5000) before execution

  After opening a position, always share: market, side, size, entry price, and position ID.`,
  model: openai('gpt-4o'),
  tools: {
    walletCreate: walletCreateTool,
    walletBalance: walletBalanceTool,
    tradeOpen: tradeOpenTool,
    tradeClose: tradeCloseTool,
    positionsList: positionsTool,
  },
  memory: new Memory(),  // Automatically tracks context across turns
});

Running the Agent

// index.ts
import { cryptoAgent } from './agent';

const threadId = 'session-001';  // Use per-user/agent thread IDs

async function main() {
  // Turn 1: Create a wallet
  const t1 = await cryptoAgent.generate(
    'Create a new Ethereum wallet for me.',
    { threadId }
  );
  console.log(t1.text);

  // Turn 2: Open a trade (agent remembers the wallet from turn 1)
  const t2 = await cryptoAgent.generate(
    'Open a $100 long position on ETH-PERP with 2x leverage.',
    { threadId }
  );
  console.log(t2.text);

  // Turn 3: Check positions (agent uses memory to recall open positions)
  const t3 = await cryptoAgent.generate(
    'What are my current positions and their P&L?',
    { threadId }
  );
  console.log(t3.text);
}

main().catch(console.error);

Using Mastra's Workflow Composer

For complex trading strategies, Mastra's workflow API lets you define multi-step sequences that execute deterministically. Unlike pure LLM agents, workflows guarantee execution order — critical for financial operations.

import { createWorkflow, createStep } from '@mastra/core/workflow';

const dca_step = createStep({
  id: 'dca-buy',
  execute: async ({ inputData }) => {
    // Dollar-cost average into ETH-PERP every hour
    const { amount, market } = inputData;
    return flea.trading.openPosition({
      market,
      sizeUsd: amount,
      side: 'long',
      leverage: 1,
    });
  },
});

const dca_workflow = createWorkflow({
  id: 'dca-strategy',
  inputSchema: z.object({
    market: z.string(),
    amountPerInterval: z.number(),
    intervals: z.number().int().min(1).max(24),
  }),
})
  .then(dca_step)
  .commit();

Deploying with Mastra

Mastra includes a built-in deployment system. Run npx mastra dev locally, or deploy to any Node.js hosting provider. Mastra also supports Cloudflare Workers and edge deployments for low-latency global trading.

# Start Mastra dev server with hot reload
npx mastra dev

# Deploy to production
npx mastra build
# Then deploy dist/ to your hosting provider

Referral Income: 20% on Trading Fees

Every Purple Flea API key carries a referral code. When agents you build (or distribute) generate trading activity, you earn 20% of their trading fees — forever. Build once, earn passively.

Trading: 20% referral · Casino: 10% referral · Wallets: 10% referral · Domains: 15% referral

What's Next

You've built a complete Mastra trading agent with Purple Flea. From here you can add more sophisticated strategies, integrate Mastra's RAG tools for market analysis, or distribute the agent and earn referral commissions.

Explore more: Purple Flea for Mastra · Trading API reference · Hyperliquid API · Vercel AI SDK integration