Skip to main content

Trading SDK Quickstart

This guide explains how to use the Speculite SDK.

What You Need

  1. A Speculite account.
  2. A developer API key created in the web app: Settings -> Developer API Keys.
  3. A wallet/private key used by your application to sign orders.

Step 1: Create API Key in the UI

Create your key in:

speculite.com -> Settings -> Developer API Keys

Save these values securely (shown once):

  • api_key
  • api_secret

Step 2: Configure Environment Variables

SPECULITE_API_KEY=...
SPECULITE_API_SECRET=...
PRIVATE_KEY=0x...
RPC_URL=https://...

Step 3: Install the SDK

npm install @speculite/clob-client ethers viem

SDK source: https://github.com/mspurr/speculite-sdk

Step 4: Initialize the SDK Client

import { Wallet } from "ethers";
import { SpeculiteClobClient } from "@speculite/clob-client";

const HOST = "https://api.speculite.com";
const CHAIN_ID = 10143;
const signer = new Wallet(process.env.PRIVATE_KEY!);

const client = new SpeculiteClobClient(
HOST,
CHAIN_ID,
signer,
{
apiKey: process.env.SPECULITE_API_KEY!,
apiSecret: process.env.SPECULITE_API_SECRET!,
}
);

Step 5: Fetch a Market and Place an Order

import { Side } from "@speculite/clob-client";

const markets = await client.getMarkets({ statusFilter: "active", limit: 1 });
const marketId = markets.markets[0].market_id;

const res = await client.createAndPostOrder({
marketId,
outcome: "YES",
side: Side.BUY,
price: 0.5,
size: 10,
orderType: "LIMIT",
});

console.log(res.order_id, res.lifecycle_status);

Step 6: Read Trading State

const open = await client.getOpenOrders();
const history = await client.getOrderHistory({ limit: 100, offset: 0 });
const trades = await client.getTrades({ limit: 100, offset: 0 });
const positions = await client.getPositions({ includeClosed: false });

Step 7: Cancel an Order

await client.cancelOrder("order-id");

Step 8: Run Mint / Merge / Claim / Resolve with Self-Gas

The SDK also supports wallet-native lifecycle actions. These transactions are sent by your wallet and paid by your wallet.

import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { SpeculiteClobClient } from "@speculite/clob-client";

const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const walletClient = createWalletClient({
account,
transport: http(process.env.RPC_URL!),
});

const client = new SpeculiteClobClient(
HOST,
CHAIN_ID,
account as any,
{
apiKey: process.env.SPECULITE_API_KEY!,
apiSecret: process.env.SPECULITE_API_SECRET!,
},
{
walletClient,
rpcUrl: process.env.RPC_URL!,
},
);

const funding = await client.getMintFundingStatus({
marketId,
amount: "25",
});

if (!funding.hasSufficientAllowance) {
await client.approveUsdc({
spender: funding.exchangeAddress,
usdcAddress: funding.usdcAddress,
amount: "25",
});
}

await client.mintTokens({ marketId, amount: "25" });

// Requires paired YES/NO tokens in the holder wallet.
await client.mergeTokens({ marketId, pairs: "5", holder: account.address });

// Requires market to be resolved and wallet to hold winning outcome tokens.
await client.claimWinnings({ marketId });

// Pyth contract address is pulled from backend market metadata.
await client.resolveMarket({ marketId });

Step 9: Resolve via Developer API Key (Optional)

If you want to trigger backend/operator resolution from scripts, use:

await client.resolveExpiredMarket(marketId);

Supported SDK Methods (Current)

  • getAuthMe()
  • getMarkets(query)
  • getMarket(marketId)
  • getOrderbook(marketId)
  • createAndPostOrder(args, marketInfo?)
  • postOrder(order)
  • cancelOrder(orderId)
  • resolveExpiredMarket(marketId)
  • getOpenOrders(marketId?)
  • getOrderHistory({ marketId?, limit?, offset? })
  • getTrades({ marketId?, limit?, offset? })
  • getPositions({ marketId?, includeClosed?, limit?, offset? })
  • prepareApproveUsdcTx(...)
  • prepareMintTx(...)
  • prepareMergeTx(...)
  • prepareClaimTx(...)
  • prepareResolveTx(...)
  • sendPreparedTransaction(...)
  • approveUsdc(...)
  • mintTokens(...)
  • mergeTokens(...)
  • claimWinnings(...)
  • resolveMarket(...)

Notes

  • API keys are currently created through the Speculite UI only.
  • The SDK handles request signing internally.
  • Lifecycle actions use direct wallet transactions (self-gas).
  • resolveExpiredMarket uses developer API key auth and backend/operator execution.
  • Keep API credentials and private keys out of source control.