papertrade-sdk docs

Quickstart

Install#

npm install papertrade-sdk viem

viem is a peer dependency. Node 20 or newer is required for the global fetch and AbortSignal.any.

Read the market#

import { PapertradeClient, paperMintRate, wadToNumber } from 'papertrade-sdk';

const client = new PapertradeClient();
const trading = await client.tradingState();
for (const m of trading.instruments) {
  console.log(m.symbol, `max ${m.maxLeverage}x`, m.openable ? 'open' : 'closed');
}

const { points } = await client.priceHistory({ instrumentId: 0, lookbackMs: 15 * 60_000 });
console.log('BTC mark', points.at(-1)?.price);

const s = await client.protocolSummary();
console.log('PAPER per $1 of loss:', paperMintRate({
  trackedLpUsd: wadToNumber(s.paper.trackedLp),
  tailProgressUsd: wadToNumber(s.paper.tailProgress),
}));

Quote a position before you open it#

import { PapertradeClient, estimateClose, liquidationPriceRaw, priceFromRaw, priceToRaw, usdToWad } from 'papertrade-sdk';

const btc = (await new PapertradeClient().tradingState()).instruments[0];
const entry = priceToRaw(83000, btc.priceScale);

const est = estimateClose({
  instrument: btc,
  isLong: true,
  entryPriceRaw: entry,
  exitPriceRaw: priceToRaw(83083, btc.priceScale),
  marginRaw: usdToWad(100),
  leverage: 500,
});
console.log(est.netPnlUsd, est.keptFraction);

const bust = liquidationPriceRaw({ entryPriceRaw: entry, leverage: 500, isLong: true, bustBufferRaw: btc.bustBufferRaw });
console.log('bust', priceFromRaw(bust, btc.priceScale));

The same numbers come from the MCP tool papertrade_estimate_position, and the home page runs this code live.

Watch a wallet#

import { streamWallet, wadToNumber } from 'papertrade-sdk';

const stop = streamWallet({
  wallet: '0x...',
  onState(state, kind) {
    console.log(kind, wadToNumber(state.balance), state.positions.length, 'open');
  },
});
// later: stop();

For a one-off snapshot use fetchWalletState(address).

Trade with a session key#

A wallet authorizes a session key once. The key can open and close positions but can never withdraw.

import { PapertradeTrader, createSessionKey } from 'papertrade-sdk';
import { privateKeyToAccount } from 'viem/accounts';

const wallet = privateKeyToAccount(process.env.PAPERTRADE_WALLET_KEY as `0x${string}`);
const trader = new PapertradeTrader({ user: wallet.address, wallet });
await trader.registerSession(createSessionKey());

const intent = await trader.prepareOpen({ market: 'BTC', side: 'long', marginUsd: 10, leverage: 1000 });
console.log(intent.summary);              // show the user exactly what will be sent
const { receipt } = await trader.submit(intent); // only after an explicit yes

Never submit an open, close, withdrawal, stake or deposit without the user's explicit confirmation of that specific action.

Browsers and CORS#

exchange.papertrade.xyz sends no CORS headers. Run a same-origin proxy and point the client at it:

new PapertradeClient({ baseUrl: '/api/papertrade' });

This site ships one as a Pages Function; see Self-hosting.

Raw Markdown: /docs/quickstart.md