Skip to main content

Overview

The SDK provides methods to track user financial activity:
  • getUserPnl - Get profit/loss summary with optional time-series
  • getUserHistory - Get unified transaction history (fills, settlements, deposits, withdrawals)
To avoid ambiguity, we denote the smallest possible multiple of USDC (0.000001 USDC) as one uusdc, which stands for µUSDC (micro-USDC), and denote the smallest possible multiple of a contract (0.01 contract) as one ccontract (centicontract).User-facing USDC balances are specified as fixed-point strings (e.g. "1.2625" for USDC). Contract quantities in the API and SDK are specified as integer ccontracts strings (e.g. "1050" for 10.50 contracts at precision 2).

Getting PNL

getUserPnl

Get a comprehensive PNL summary for a user.
async getUserPnl(
  userId: string,
  params?: GetUserPnlParams
): Promise<GetUserPnlResponse>

Parameters

userId
string
required
User’s Ethereum address
params
object
Optional filtering parameters

Response

{
  totalDeposits: string;      // Total deposits in µUSDC
  totalWithdrawals: string;   // Total withdrawals in µUSDC
  realizedPnl: string;        // Realized PNL in µUSDC
  unrealizedPnl: string;      // Unrealized PNL in µUSDC
  netPnl: string;             // Net PNL (realized + unrealized)
  totalFeesPaid: string;      // Total fees paid in µUSDC
  timeSeries?: {              // Only if granularity is hour/day
    timestamp: number;
    cumulativePnl: string;
  }[];
}

Examples

Basic PNL summary:
import { createBisonClient, uusdcToUsdc } from '@bison-markets/sdk-ts';

const client = createBisonClient({ 
  baseUrl: 'https://api.bison.markets' 
});

const pnl = await client.getUserPnl(
  '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'
);

// Display in dollars
console.log(`Net P&L: $${uusdcToUsdc(pnl.netPnl)}`);
console.log(`Realized: $${uusdcToUsdc(pnl.realizedPnl)}`);
console.log(`Unrealized: $${uusdcToUsdc(pnl.unrealizedPnl)}`);
console.log(`Fees Paid: $${uusdcToUsdc(pnl.totalFeesPaid)}`);
PNL with daily time series (for charts):
const pnl = await client.getUserPnl(
  '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
  { granularity: 'day' }
);

// Build chart data
const chartData = pnl.timeSeries?.map(point => ({
  date: new Date(point.timestamp),
  pnl: Number(point.cumulativePnl) / 1_000_000 // Convert to dollars
})) ?? [];
PNL for a specific market:
const marketPnl = await client.getUserPnl(
  '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
  { marketId: 'KXFEDDECISION-26JAN-T425' }
);

console.log(`Market P&L: $${uusdcToUsdc(marketPnl.realizedPnl)}`);
PNL for a date range:
const oneWeekAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;

const weeklyPnl = await client.getUserPnl(
  '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
  { 
    startTime: oneWeekAgo,
    granularity: 'hour'
  }
);

Getting Transaction History

getUserHistory

Get a chronological list of all financial transactions.
async getUserHistory(
  userId: string,
  params?: GetUserHistoryParams
): Promise<GetUserHistoryResponse>

Parameters

userId
string
required
User’s Ethereum address
params
object
Optional filtering and pagination

Response

Returns an array of transaction records, each with a type discriminator:
{
  records: (FillRecord | SettlementRecord | DepositRecord | WithdrawRecord)[];
  pagination: {
    hasMore: boolean;
    nextCursor?: string;
  };
}

Examples

Get all recent activity:
const { records } = await client.getUserHistory(
  '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'
);

records.forEach(record => {
  const date = new Date(record.timestamp).toLocaleDateString();
  
  switch (record.type) {
    case 'fill':
      console.log(
        `${date}: ${record.action} ${Number(record.ccontracts) / 100} ${record.side} @ $${Number(record.priceUusdc) / 1_000_000}`
      );
      break;
    case 'settlement':
      const won = record.payoutUusdc !== '0';
      console.log(`${date}: Settlement ${won ? 'WON' : 'LOST'} - $${Number(record.payoutUusdc) / 1_000_000}`);
      break;
    case 'deposit':
      console.log(`${date}: Deposited $${Number(record.amountUusdc) / 1_000_000}`);
      break;
    case 'withdraw':
      console.log(`${date}: Withdrew $${Number(record.amountUusdc) / 1_000_000} (${record.status})`);
      break;
  }
});
Get only fills for a market:
const { records } = await client.getUserHistory(
  '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
  { 
    type: 'fill',
    marketId: 'KXFEDDECISION-26JAN-T425'
  }
);
Paginate through all history:
let cursor: string | undefined;
const allRecords = [];

do {
  const result = await client.getUserHistory(
    '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
    { limit: 100, cursor }
  );
  
  allRecords.push(...result.records);
  cursor = result.pagination.nextCursor;
} while (cursor);

console.log(`Total transactions: ${allRecords.length}`);

Error Handling

try {
  const pnl = await client.getUserPnl('0x...');
  console.log('Net PNL:', pnl.netPnl);
} catch (error) {
  if (error instanceof Error) {
    console.error('Failed to get PNL:', error.message);
  }
}

Important Notes

  • All monetary values are in µUSDC (1 USD = 1,000,000 µUSDC)
  • When filtering by marketId, deposits and withdrawals are excluded from PNL calculations
  • Transaction history is sorted newest-first by default
  • Unrealized PNL is estimated based on position cost basis
  • Time series data points represent cumulative PNL at each interval