@delphimarkets/sdk
v0.1.0
Published
TypeScript SDK for the Delphi Order Router
Maintainers
Readme
@delphimarkets/sdk
TypeScript SDK for the Delphi Order Router. Routes orders to prediction market exchanges (Polymarket, Kalshi, Opinion Labs, Gemini, Limitless, Predict.fun) through a hosted server-side proxy.
Install
npm install github:piraterobot0/delphi-sdkRequires Node 18+ (native fetch).
Setup
Copy the environment template and fill in your credentials:
cp .env.example .envConfigure the SDK:
import { DelphiClient } from '@delphimarkets/sdk'; const client = new DelphiClient({ apiKey: process.env.DELPHI_API_KEY, // Your Delphi API key baseUrl: process.env.DELPHI_BASE_URL, // Router URL (provided by Delphi) timeout: 30_000, // Optional (default: 30s) });
See .env.example for all configuration options.
Polymarket Flow
Polymarket uses EIP-712 signed orders with a Gnosis Safe proxy wallet.
import { DelphiClient, buildPolymarketOrder, deriveSafeAddress } from '@delphimarkets/sdk';
import { createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { polygon } from 'viem/chains';
const client = new DelphiClient({
apiKey: process.env.DELPHI_API_KEY,
baseUrl: process.env.DELPHI_BASE_URL,
});
// 1. Derive CLOB credentials (server stores them automatically)
await client.derivePolymarketCredentials(process.env.POLYMARKET_PRIVATE_KEY);
// 2. Build and sign an order (client-side, never leaves your machine)
const account = privateKeyToAccount(`0x${process.env.POLYMARKET_PRIVATE_KEY}`);
const wallet = createWalletClient({ account, chain: polygon, transport: http() });
const signedOrder = await buildPolymarketOrder(
{
tokenId: '12345...', // Polymarket outcome token ID
side: 'BUY', // 'BUY' or 'SELL'
price: 0.55, // Price per share (0.01 to 0.99)
size: '5000000', // Size in base units (5 USDC at 6 decimals)
},
wallet,
true, // useSafe: true for Safe wallet, false for EOA
);
// 3. Place through the router
const order = await client.placeOrder({
exchange: 'polymarket',
market_id: 'my-market',
order_type: 'GTC',
signed_order: signedOrder,
});
console.log(`Placed: ${order.order_id} (${order.status})`);
// 4. Query, list, cancel
const status = await client.getOrder(order.order_id);
const all = await client.listOrders('polymarket');
await client.cancelOrder(order.order_id);Kalshi Flow
Kalshi uses RSA-PSS authentication with standard limit orders. No client-side signing — the server signs requests using your registered RSA key.
import { DelphiClient } from '@delphimarkets/sdk';
import { readFileSync } from 'node:fs';
const client = new DelphiClient({
apiKey: process.env.DELPHI_API_KEY,
baseUrl: process.env.DELPHI_BASE_URL,
});
// 1. Register Kalshi credentials (API key ID + RSA private key PEM)
await client.registerCredentials('kalshi', {
api_key: process.env.KALSHI_API_KEY_ID,
api_secret: readFileSync(process.env.KALSHI_PRIVATE_KEY_FILE, 'utf-8'),
api_passphrase: '', // Not used for Kalshi
});
// 2. Place a limit order
const order = await client.placeOrder({
exchange: 'kalshi',
market_id: 'KXNHLGAME-26MAR30PITNYI-NYI',
order_type: 'GTC',
signed_order: {
ticker: 'KXNHLGAME-26MAR30PITNYI-NYI',
side: 'yes', // 'yes' or 'no'
price_cents: '54', // Price in cents ($0.54)
count: '1', // Number of contracts
},
});
console.log(`Placed: ${order.order_id} (${order.status})`);
// 3. Query, list, cancel
const status = await client.getOrder(order.order_id, 'kalshi');
const all = await client.listOrders('kalshi');
await client.cancelOrder(order.order_id, 'kalshi');Opinion Labs Flow
Opinion Labs uses EIP-712 signed orders on BNB Chain with a Gnosis Safe wallet.
import {
DelphiClient, getSafeAddress, getSafeApprovalStatus,
enableTrading, buildOpinionLabsOrder,
} from '@delphimarkets/sdk';
import { createWalletClient, createPublicClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { bsc } from 'viem/chains';
const client = new DelphiClient({
apiKey: process.env.DELPHI_API_KEY,
baseUrl: process.env.DELPHI_BASE_URL,
});
const account = privateKeyToAccount(`0x${process.env.OPINIONLABS_PRIVATE_KEY}`);
const walletClient = createWalletClient({ account, chain: bsc, transport: http() });
const publicClient = createPublicClient({ chain: bsc, transport: http() });
// 1. Get your Safe wallet address
const safeAddress = await getSafeAddress(process.env.OPINIONLABS_API_KEY);
// 2. Enable trading (one-time Safe approval — USDT + ConditionalTokens)
const status = await getSafeApprovalStatus(publicClient, safeAddress);
if (!status.allApproved) {
const txHash = await enableTrading(safeAddress, walletClient, publicClient);
await publicClient.waitForTransactionReceipt({ hash: txHash });
}
// 3. Register credentials with Delphi server
await client.registerCredentials('opinionlabs', {
api_key: process.env.OPINIONLABS_API_KEY,
api_secret: '',
api_passphrase: '',
signer_address: account.address,
});
// 4. Build and sign an order (Safe as maker, EOA signs)
const signedOrder = await buildOpinionLabsOrder(
{
marketId: 8453,
tokenId: '1087612329966...', // From market API
side: 'BUY',
price: 0.50,
amount: 3, // USDT amount
safeAddress,
},
walletClient,
);
// 5. Place through the router
const order = await client.placeOrder({
exchange: 'opinionlabs',
market_id: '8453',
order_type: 'GTC',
signed_order: signedOrder,
});Gemini Predictions Flow
Gemini uses HMAC-SHA512 authentication handled server-side. No client-side signing needed.
import { DelphiClient, buildGeminiOrder } from '@delphimarkets/sdk';
const client = new DelphiClient({
apiKey: process.env.DELPHI_API_KEY,
baseUrl: process.env.DELPHI_BASE_URL,
});
// 1. Register credentials
await client.registerCredentials('gemini', {
api_key: process.env.GEMINI_API_KEY,
api_secret: process.env.GEMINI_API_SECRET,
api_passphrase: '',
});
// 2. Build and place an order
const order = await client.placeOrder({
exchange: 'gemini',
market_id: 'GEMI-FEDJAN26-DN25',
order_type: 'GTC',
signed_order: buildGeminiOrder({
symbol: 'GEMI-FEDJAN26-DN25',
side: 'buy',
outcome: 'yes',
quantity: 1,
price: 0.55,
}),
});
console.log(`Placed: ${order.order_id} (${order.status})`);
// 3. Query, list, cancel
const status = await client.getOrder(order.order_id, 'gemini');
const all = await client.listOrders('gemini');
await client.cancelOrder(order.order_id, 'gemini');Limitless Flow
Limitless uses EIP-712 signed orders on Base chain with an EOA wallet.
import { DelphiClient, buildLimitlessOrder } from '@delphimarkets/sdk';
import { createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { base } from 'viem/chains';
const client = new DelphiClient({
apiKey: process.env.DELPHI_API_KEY,
baseUrl: process.env.DELPHI_BASE_URL,
});
const account = privateKeyToAccount(`0x${process.env.LIMITLESS_PRIVATE_KEY}`);
const walletClient = createWalletClient({ account, chain: base, transport: http() });
// 1. Register credentials
await client.registerCredentials('limitless', {
api_key: process.env.LIMITLESS_API_KEY,
api_secret: process.env.LIMITLESS_API_SECRET,
api_passphrase: '',
signer_address: account.address,
});
// 2. Build and sign an order (EOA signs directly)
const signedOrder = await buildLimitlessOrder(
{
marketSlug: 'trump-out-as-president-before-2027-1768933068297',
tokenId: '56154308...', // Outcome token ID
side: 'BUY',
price: 0.10, // Price per share
size: 1, // USDC amount
ownerId: 1292635, // From /profiles endpoint
},
walletClient,
);
// 3. Place through the router
const order = await client.placeOrder({
exchange: 'limitless',
market_id: 'trump-out-as-president-before-2027-1768933068297',
order_type: 'GTC',
signed_order: signedOrder,
});
console.log(`Placed: ${order.order_id} (${order.status})`);
// 4. Query, list, cancel
const status = await client.getOrder(order.order_id, 'limitless');
const all = await client.listOrders('limitless');
await client.cancelOrder(order.order_id, 'limitless');Predict.fun Flow
Predict.fun uses EIP-712 signed orders on BNB Chain. Supports both EOA wallets and Predict Account (Kernel smart wallet) flow.
import {
DelphiClient, buildPredictFunOrder,
approvePredictFunExchange, getPredictFunApprovalStatus,
} from '@delphimarkets/sdk';
import { createWalletClient, createPublicClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { bsc } from 'viem/chains';
const client = new DelphiClient({
apiKey: process.env.DELPHI_API_KEY,
baseUrl: process.env.DELPHI_BASE_URL,
});
const account = privateKeyToAccount(`0x${process.env.PREDICTFUN_PRIVY_KEY}`);
const walletClient = createWalletClient({ account, chain: bsc, transport: http() });
const publicClient = createPublicClient({ chain: bsc, transport: http() });
const predictAccount = process.env.PREDICTFUN_PREDICT_ACCOUNT as `0x${string}`;
// 1. Approve exchange contracts (one-time per market variant)
const status = await getPredictFunApprovalStatus(publicClient, predictAccount, {
isNegRisk: false,
isYieldBearing: true,
});
if (!status.usdtApproved || !status.ctfApproved) {
const hashes = await approvePredictFunExchange(walletClient, publicClient, {
isNegRisk: false,
isYieldBearing: true,
predictAccount,
});
for (const hash of hashes) {
await publicClient.waitForTransactionReceipt({ hash });
}
}
// 2. Register credentials (Privy key + predict account address)
await client.registerCredentials('predictfun', {
api_key: process.env.PREDICTFUN_API_KEY,
api_secret: process.env.PREDICTFUN_PRIVY_KEY,
api_passphrase: '',
signer_address: predictAccount,
});
// 3. Build and sign an order (Kernel-wrapped for predict account)
const signedOrder = await buildPredictFunOrder(
{
tokenId: '11050832...', // Outcome token ID (from market API)
side: 'BUY',
price: 0.50, // Price per share (0.01 to 0.99)
size: (50n * 10n ** 18n).toString(), // 50 shares (1e18 per share)
feeRateBps: '200', // From market.feeRateBps
isNegRisk: false,
isYieldBearing: true,
predictAccount, // Enables Kernel signing
},
walletClient,
);
// 4. Place through the router
const order = await client.placeOrder({
exchange: 'predictfun',
market_id: '174032',
order_type: 'GTC',
signed_order: signedOrder,
});
console.log(`Placed: ${order.order_id} (${order.status})`);
// 5. Query, list, cancel
const orderStatus = await client.getOrder(order.order_id, 'predictfun');
const all = await client.listOrders('predictfun');
await client.cancelOrder(order.order_id, 'predictfun');Credential Differences
| | Polymarket | Kalshi | Opinion Labs | Gemini | Limitless | Predict.fun |
|---|---|---|---|---|---|---|
| Setup | derivePolymarketCredentials(pk) | registerCredentials('kalshi', creds) | registerCredentials('opinionlabs', creds) | registerCredentials('gemini', creds) | registerCredentials('limitless', creds) | registerCredentials('predictfun', creds) |
| api_key | CLOB HMAC (auto-derived) | Kalshi API key ID | Opinion Labs API key | Gemini API key | Limitless API key | Predict.fun API key |
| api_secret | CLOB HMAC (auto-derived) | RSA private key (PEM) | Unused ('') | HMAC-SHA512 secret | HMAC secret | Privy wallet key (hex) |
| Order format | EIP-712 signed | { ticker, side, price_cents, count } | EIP-712 signed (camelCase) | { symbol, side, outcome, quantity, price } | EIP-712 signed (nested order) | EIP-712 signed (1e18 precision) |
| Signing | Client-side (Polygon) | Server-side (RSA-PSS) | Client-side (BNB Chain) | Server-side (HMAC-SHA512) | Client-side (Base) | Client-side (BNB Chain) |
| Wallet | Gnosis Safe (Polygon) | N/A | Gnosis Safe (BNB Chain) | N/A | EOA (Base) | Predict Account / EOA (BNB Chain) |
API Reference
new DelphiClient(config)
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| apiKey | string | (required) | Delphi API key (dphi_live_xxx or dphi_test_xxx) |
| baseUrl | string | http://localhost:8080 | Order router URL |
| timeout | number | 30000 | Request timeout (ms) |
Orders
client.placeOrder(req: PlaceOrderRequest): Promise<PlaceOrderResponse>
client.getOrder(orderId, exchange?): Promise<OrderStatusResponse>
client.listOrders(exchange?): Promise<ListOrdersResponse>
client.cancelOrder(orderId, exchange?): Promise<CancelOrderResponse>Credentials
client.registerCredentials(exchange, creds): Promise<RegisterCredentialsResponse>
client.listCredentials(): Promise<ListCredentialsResponse>
client.derivePolymarketCredentials(privateKey): Promise<DeriveCredentialsResponse>
client.verifyPolymarketCredentials(creds?): Promise<VerifyCredentialsResponse>
client.getPolymarketSafeAddress(eoaAddress): Promise<SafeAddressResponse>Polymarket Helpers (standalone, no server needed)
import { deriveSafeAddress, buildPolymarketOrder, signOrder } from '@delphimarkets/sdk';
const safe = deriveSafeAddress('0xYourEOA');
const order = await buildPolymarketOrder(params, walletClient);
const signed = await signOrder(unsignedOrder, walletClient, signatureType);Opinion Labs Helpers (standalone, no server needed)
import {
getSafeAddress, getSafeApprovalStatus, enableTrading,
buildOpinionLabsOrder, signOpinionLabsOrder,
} from '@delphimarkets/sdk';
const safe = await getSafeAddress(apiKey);
const status = await getSafeApprovalStatus(publicClient, safe);
const order = await buildOpinionLabsOrder(params, walletClient);Gemini Helpers (standalone, no server needed)
import { buildGeminiOrder } from '@delphimarkets/sdk';
const order = buildGeminiOrder({ symbol, side, outcome, quantity, price });Limitless Helpers (standalone, no server needed)
import { buildLimitlessOrder, signLimitlessOrder } from '@delphimarkets/sdk';
const order = await buildLimitlessOrder(params, walletClient);Predict.fun Helpers (standalone, no server needed)
import {
buildPredictFunOrder, signPredictFunOrder,
approvePredictFunExchange, getPredictFunApprovalStatus,
} from '@delphimarkets/sdk';
const status = await getPredictFunApprovalStatus(publicClient, owner, { isNegRisk, isYieldBearing });
const hashes = await approvePredictFunExchange(walletClient, publicClient, { isNegRisk, isYieldBearing, predictAccount });
const order = await buildPredictFunOrder(params, walletClient);Error Handling
import { DelphiError } from '@delphimarkets/sdk';
try {
await client.placeOrder(req);
} catch (err) {
if (err instanceof DelphiError) {
console.error(`API error ${err.statusCode}: ${err.message}`);
// 400 = bad request, 401 = auth failed, 502 = exchange error
}
}Development
npm install
npm run lint # Type check
npm test # Run tests (58 tests)
npm run build # Build ESM + CJS + types