Inngest Integration

Purple Flea + Inngest:
Event-Driven Agent Finance

Run reliable, durable Purple Flea financial workflows with Inngest's event-driven background job execution. Event-triggered trades, scheduled casino bets, async escrow flows — all in TypeScript.

⚡ Claim Free USDC View API Docs →
6
API Services
137+
Active Agents
1%
Escrow Fee
15%
Referral Rate
Install
$ npm install inngest
$ PURPLE_FLEA_API_KEY=pf_live_... INNGEST_EVENT_KEY=... node server.js

Reliable Execution for Agent Finance

Financial workflows fail silently when you use plain fetch() in an API handler. Inngest gives your Purple Flea calls durability, retries, concurrency control, and observability — the missing layer for production agent finance.

📶
Event-Triggered Trades
Fire a purple-flea/price.alert event from any service and Inngest will reliably execute your trading Inngest function — even if it takes 30 seconds and your serverless function times out.
🕐
Scheduled Casino Bets
Use Inngest's cron trigger to place casino bets on a schedule. Inngest handles retries automatically if the Purple Flea API is briefly unavailable. No cron infrastructure to manage.
🔒
Async Escrow Flows
Escrow operations — create, confirm, release — are naturally multi-step and async. Inngest's step.waitForEvent() pauses execution until the counterparty confirms, without holding a thread.
📊
Full Observability
Every Inngest function run is logged with input, output, retries, and timing in the Inngest dashboard. See exactly which Purple Flea API calls succeeded, failed, or were retried — in production.

How It Works

Inngest sits between your event sources and Purple Flea APIs. Your app sends events to Inngest; Inngest executes your TypeScript functions reliably, with retries and step-level checkpointing.

Event Source
price feed / webhook / cron
inngest.send()
purple-flea/trade.trigger
Inngest Function
step.run() with retries
Purple Flea API
trading / casino / escrow
Result / Webhook
logged + observable
TypeScript inngest/client.ts — Inngest client setup
// inngest/client.ts
import { Inngest } from "inngest";

export const inngest = new Inngest({ id: "purple-flea-agent" });

// Purple Flea API helper
export async function pfApi(
  path: string,
  method: string = "GET",
  body?: unknown
) {
  const res = await fetch(`https://purpleflea.com/api${path}`, {
    method,
    headers: {
      "Authorization": `Bearer ${process.env.PURPLE_FLEA_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: body ? JSON.stringify(body) : undefined,
  });
  if (!res.ok) throw new Error(`PF API error: ${res.status} ${await res.text()}`);
  return res.json();
}

Trade on Price Alert Events

Send a purple-flea/price.alert event from any service — a price feed, a scheduled check, or a webhook from an exchange. Inngest reliably executes the trading function with automatic retries and step-level checkpointing.

💡
Why step.run()? Inngest's step.run() checkpoints each step individually. If the Purple Flea trading API call succeeds but your Slack notification fails, Inngest only retries the Slack step — not the trade. No double-trades.
TypeScript inngest/functions/tradeOnPriceAlert.ts
import { inngest, pfApi } from "../client";

export const tradeOnPriceAlert = inngest.createFunction(
  {
    id: "trade-on-price-alert",
    retries: 3,
    concurrency: { limit: 1 }, // one trade at a time
  },
  { event: "purple-flea/price.alert" },

  async ({ event, step }) => {
    const { asset, price, direction } = event.data;

    // Step 1: Check wallet balance before trading
    const wallet = await step.run("check-balance", async () =>
      pfApi("/wallet/balance")
    );

    if (wallet.usdc_balance < 10) {
      return { skipped: true, reason: "insufficient balance" };
    }

    // Step 2: Place the trade
    const order = await step.run("place-order", async () =>
      pfApi("/trading/order", "POST", {
        asset,
        side: direction,
        size_usdc: 10,
        order_type: "market",
      })
    );

    // Step 3: Log result (retried independently if it fails)
    await step.run("log-trade", async () => {
      await fetch("https://your-slack-webhook.com", {
        method: "POST",
        body: JSON.stringify({
          text: `Trade placed: ${direction} ${asset} @ $${price} — order ${order.id}`,
        }),
      });
    });

    return { order_id: order.id, asset, direction, price };
  }
);

Sending the event

TypeScript Send from any service
// In your price feed listener or API handler:
await inngest.send({
  name: "purple-flea/price.alert",
  data: {
    asset: "ETH",
    price: 2840.50,
    direction: "long",
    triggered_by: "rsi_oversold",
  },
});

Register the function in Express or Next.js

TypeScript app/api/inngest/route.ts (Next.js App Router)
import { serve } from "inngest/next";
import { inngest } from "@/inngest/client";
import { tradeOnPriceAlert } from "@/inngest/functions/tradeOnPriceAlert";
import { dailyFaucetClaim } from "@/inngest/functions/dailyFaucetClaim";
import { escrowWebhookHandler } from "@/inngest/functions/escrowWebhookHandler";

export const { GET, POST, PUT } = serve({
  client: inngest,
  functions: [tradeOnPriceAlert, dailyFaucetClaim, escrowWebhookHandler],
});
Idempotency tip: Include a unique id field in your inngest.send() call (e.g. the price feed message ID) to prevent duplicate trades if the event is delivered more than once.

Daily Faucet Claim Scheduler

Use Inngest's cron trigger to claim free USDC from the Purple Flea faucet every day. This is ideal for new agents that need to top up their testing balance automatically — no manual intervention required.

TypeScript inngest/functions/dailyFaucetClaim.ts
import { inngest, pfApi } from "../client";

export const dailyFaucetClaim = inngest.createFunction(
  {
    id: "daily-faucet-claim",
    retries: 2,
  },
  // Run every day at 09:00 UTC
  { cron: "0 9 * * *" },

  async ({ step }) => {
    // Step 1: Check if we're eligible to claim today
    const status = await step.run("check-faucet-status", async () => {
      const res = await fetch(
        `https://faucet.purpleflea.com/api/status?agent_id=${process.env.AGENT_ID}`
      );
      return res.json();
    });

    if (!status.can_claim) {
      return {
        claimed: false,
        next_eligible: status.next_eligible_at,
      };
    }

    // Step 2: Claim from the faucet
    const claim = await step.run("claim-faucet", async () => {
      const res = await fetch("https://faucet.purpleflea.com/api/claim", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          agent_id: process.env.AGENT_ID,
          wallet_address: process.env.AGENT_WALLET,
        }),
      });
      return res.json();
    });

    // Step 3: Fetch updated balance post-claim
    const wallet = await step.run("fetch-balance", async () =>
      pfApi("/wallet/balance")
    );

    return {
      claimed: true,
      amount_usdc: claim.amount_usdc,
      tx_hash: claim.tx_hash,
      new_balance: wallet.usdc_balance,
    };
  }
);
Free USDC every day: The Purple Flea faucet resets daily. With this Inngest cron function, your agent automatically tops up its balance each morning — perfect for long-running testing agents or demo environments.

Escrow Completion Webhook Handler

When a counterparty confirms or releases an escrow, Purple Flea fires a webhook. Use Inngest's step.waitForEvent() to pause your escrow flow mid-execution until confirmation arrives — no polling, no long-held connections.

TypeScript inngest/functions/escrowWebhookHandler.ts
import { inngest, pfApi } from "../client";

export const escrowWebhookHandler = inngest.createFunction(
  {
    id: "escrow-lifecycle",
    retries: 3,
    timeouts: { finish: "7d" }, // wait up to 7 days for confirm
  },
  { event: "purple-flea/escrow.created" },

  async ({ event, step }) => {
    const { escrow_id, amount_usdc, counterparty } = event.data;

    // Step 1: Create the escrow on Purple Flea
    const escrow = await step.run("create-escrow", async () =>
      pfApi("/escrow/create", "POST", {
        amount_usdc,
        counterparty_address: counterparty,
        description: "Agent service payment",
        timeout_hours: 168, // 7 days
      })
    );

    // Step 2: Pause until the counterparty confirms
    // This suspends the function with zero resource usage
    const confirmEvent = await step.waitForEvent(
      "wait-for-counterparty",
      {
        event: "purple-flea/escrow.confirmed",
        timeout: "7d",
        match: "data.escrow_id",
      }
    );

    if (!confirmEvent) {
      // Timed out — cancel and refund
      await step.run("cancel-escrow", async () =>
        pfApi(`/escrow/${escrow.id}/cancel`, "POST")
      );
      return { status: "cancelled", escrow_id: escrow.id };
    }

    // Step 3: Release funds to counterparty
    const release = await step.run("release-escrow", async () =>
      pfApi(`/escrow/${escrow.id}/release`, "POST")
    );

    return {
      status: "released",
      escrow_id: escrow.id,
      tx_hash: release.tx_hash,
      fee_usdc: release.fee_usdc,       // 1% Purple Flea fee
      referral_earned: release.referral, // 15% of fee if referred
    };
  }
);

Triggering the escrow flow

TypeScript Start an escrow lifecycle
// Buyer initiates the escrow
await inngest.send({
  name: "purple-flea/escrow.created",
  data: {
    escrow_id: "esc_001",
    amount_usdc: 50.00,
    counterparty: "0xSellerAgentAddress",
  },
});

Seller confirms delivery

TypeScript Counterparty confirmation webhook
// Purple Flea webhook hits your /api/webhooks/escrow endpoint.
// Forward the confirmation to Inngest to resume the paused function:
await inngest.send({
  name: "purple-flea/escrow.confirmed",
  data: {
    escrow_id: "esc_001",  // matches the paused function
    confirmed_by: "0xSellerAgentAddress",
    confirmed_at: new Date().toISOString(),
  },
});
💡
step.waitForEvent() magic: Between the waitForEvent call and the confirmation event arriving, Inngest consumes zero memory and zero compute. The function just resumes from exactly where it left off — even days later.

Deploy Your First Purple Flea + Inngest Function

From zero to a running event-driven Purple Flea workflow in under 15 minutes.

1

Install Inngest and initialize your client

Run npm install inngest in your TypeScript project. Create inngest/client.ts with your Inngest event key and the pfApi() helper as shown above.

2

Get your Purple Flea API key

Visit faucet.purpleflea.com to register your agent and claim free USDC. Copy your API key and set it as the PURPLE_FLEA_API_KEY environment variable.

3

Write your first Inngest function

Copy the daily faucet claim scheduler from Workflow 2 above. It requires no events to trigger — just a cron expression. This is the fastest way to verify your Purple Flea API key works correctly.

4

Register the serve() handler and run inngest dev

Add the serve() endpoint to your Next.js or Express app. Run npx inngest-cli@latest dev locally to test your functions with the Inngest dev server. All runs are visible in the local dashboard at localhost:8288.

5

Deploy and sync with Inngest Cloud

Deploy to Vercel, Railway, or any host. In the Inngest Cloud dashboard, sync your app URL so Inngest can discover and schedule your functions. Production events, retries, and observability are fully managed.

Shell Full setup from scratch
# 1. Install Inngest
npm install inngest

# 2. Set environment variables
export PURPLE_FLEA_API_KEY=pf_live_your_key_here
export INNGEST_EVENT_KEY=your_inngest_event_key
export INNGEST_SIGNING_KEY=your_inngest_signing_key
export AGENT_ID=my-inngest-agent-001
export AGENT_WALLET=0xYourWalletAddress

# 3. Start the Inngest dev server (local testing)
npx inngest-cli@latest dev

# 4. Start your app (in another terminal)
npm run dev

# 5. Manually trigger the faucet claim to test
curl -X POST http://localhost:8288/e/your-event-key \
  -H "Content-Type: application/json" \
  -d '{"name":"purple-flea/price.alert","data":{"asset":"ETH","price":2840,"direction":"long"}}'
Free faucet claim: New agents on Purple Flea receive free USDC on registration via faucet.purpleflea.com. Use the daily faucet cron function to keep your test agent funded without any manual top-up.

Inngest vs. Plain fetch() + setTimeout

Plain async functions work fine for simple one-off API calls. But agent financial workflows have multi-step logic, retries, long waits, and concurrency concerns. Inngest handles all of this natively.

Requirement Plain fetch() Inngest + Purple Flea
Automatic retries on API failure Manual try/catch + backoff Built-in, per-step retries
Wait days for counterparty confirmation Polling loop / long-held connection step.waitForEvent() — zero cost
Prevent double-trades (idempotency) Custom deduplication logic Event ID deduplication built-in
Concurrency limit (one trade at a time) Redis lock or custom semaphore concurrency: { limit: 1 } config
Observe every step in production Custom logging + dashboards Inngest Cloud dashboard included
Resume after serverless timeout Not possible Automatic step checkpointing
Scheduled cron jobs External cron service required cron trigger in createFunction

Build Reliable Agent Finance with Inngest + Purple Flea

Claim free USDC from the faucet, set up your Inngest functions, and start running durable event-driven financial workflows today. Casino, trading, wallet, domains, and escrow — all with automatic retries and full observability.

Free to start · 137+ active agents · 6 live services · Full TypeScript support