@markit.market/sdk
v0.1.1
Published
TypeScript SDK for MarkIt prediction markets on Base
Downloads
182
Maintainers
Readme
@markit.market/sdk
TypeScript SDK for MarkIt prediction markets on Base.
Builders earn 0.25% of every bet placed through their integration, carved from the existing 2% protocol fee. Zero cost to users.
Install
npm install @markit.market/sdk viemQuick Start
import { createMarkitClient } from '@markit.market/sdk'
import { createWalletClient, http } from 'viem'
import { base } from 'viem/chains'
import { privateKeyToAccount } from 'viem/accounts'
const markit = createMarkitClient({
builderCode: 'your-builder-code',
chain: 'base',
})
// Browse open markets
const markets = await markit.markets.list({ state: 'open' })
console.log(markets[0].question) // "Will the Lakers beat the Celtics?"
console.log(markets[0].yesPrice) // "0.65" (65 cents)
// Get a quote before betting
const quote = await markit.markets.getQuote({
market: markets[0].address,
side: 'yes',
usdcAmount: 10_000_000n, // $10 USDC (6 decimals)
})
console.log(quote.sharesOut) // shares you'd receive
console.log(quote.effectivePrice) // effective price per share
console.log(quote.totalFee) // total fees in USDC
// Place the bet
const account = privateKeyToAccount('0x...')
const signer = createWalletClient({ account, chain: base, transport: http() })
const result = await markit.trade.placeBet({
market: markets[0].address,
side: 'yes',
usdcAmount: 10_000_000n,
signer,
})
console.log(result.txHash) // transaction hash
console.log(result.attributed) // true if builder fee was creditedSmart Wallet Integration
For Coinbase Smart Wallet, Safe, or other batching wallets, use buildPlaceBetCalls() to get raw calldata:
const calls = markit.trade.buildPlaceBetCalls({
market: '0x...',
side: 'yes',
usdcAmount: 10_000_000n,
})
// calls = [
// { to: USDC_ADDRESS, data: '0x...' }, // approve
// { to: MARKET_ADDRESS, data: '0x...' }, // placeBet
// ]
// Send via your smart wallet's batch method
await smartWallet.sendCalls(calls)
// Then report attribution separately so you earn the builder fee
await markit.trade.reportAttribution({
market: '0x...',
txHash: '0x...',
bettor: '0x...',
})Builder Codes
Register at markit.market/builders to get your builder code and API key.
const markit = createMarkitClient({
builderCode: 'your-code',
apiKey: 'mk_live_...', // from registration — needed for stats
})
// View your earnings
const stats = await markit.builder.getStats()
console.log(stats.totalVolume) // total bet volume through your integration
console.log(stats.totalFees) // total fees earned (USD)
console.log(stats.unpaidFees) // fees pending payout
console.log(stats.uniqueUsers) // unique bettors
// Per-bet fee history
const fees = await markit.builder.getFeeHistory({ limit: 20 })API Reference
createMarkitClient(config)
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| builderCode | string | required | Your registered builder code |
| chain | 'base' \| 'baseSepolia' | 'base' | Target chain |
| rpcUrl | string | Public RPC | Custom RPC endpoint |
| apiKey | string | — | API key for builder.getStats() and builder.getFeeHistory() |
markit.markets
list(options?)
List markets from the MarkIt indexer.
const markets = await markit.markets.list({
state: 'open', // 'open' | 'closeOnly' | 'resolved' | 'all'
sport: 'nba', // 'nba' | 'ncaab' | 'all'
limit: 20,
})Returns MarketSummary[]:
| Field | Type | Description |
|-------|------|-------------|
| address | Address | Market contract address |
| question | string | e.g. "Will the Lakers beat the Celtics?" |
| slug | string \| null | URL slug, e.g. lakers-at-celtics-mar-17 |
| state | number | 0=Created, 1=Funded, 2=Open, 3=CloseOnly, 4=Resolved, 5=Withdrawable |
| outcome | number | 0=None, 1=Yes, 2=No |
| sport | string | 'nba' or 'ncaab' |
| yesPrice | string | Current YES price (0-1) |
| noPrice | string | Current NO price (0-1) |
| yesLiability | string | Total YES payouts owed (WAD) |
| noLiability | string | Total NO payouts owed (WAD) |
| engineUsdc | string | USDC balance in contract (6 decimals) |
| bettingCloseTime | number | Unix timestamp when betting closes |
| resolveTime | number | Unix timestamp when market resolves |
| homeLogoUrl | string \| null | ESPN team logo URL |
| awayLogoUrl | string \| null | ESPN team logo URL |
get(slugOrAddress)
Get full market details by address or slug.
const market = await markit.markets.get('lakers-at-celtics-mar-17')
// or
const market = await markit.markets.get('0x1234...')Returns MarketDetail (extends MarketSummary with LP parameters, fees, seed imbalance).
getPrice(market)
Get live on-chain mark prices (reads directly from the contract via RPC).
const price = await markit.markets.getPrice('0x...')
console.log(price.yes) // 0.65
console.log(price.no) // 0.35getQuote({ market, side, usdcAmount })
Simulate a bet and get a detailed fee breakdown.
const quote = await markit.markets.getQuote({
market: '0x...',
side: 'yes',
usdcAmount: 50_000_000n, // $50
})Returns BetQuote:
| Field | Type | Description |
|-------|------|-------------|
| sharesOut | string | Shares you'd receive (WAD, 18 decimals) |
| avgPrice | string | Average price per share |
| priceImpact | string | Price impact as a decimal (0.01 = 1%) |
| lpFee | string | LP fee in USDC (6 decimals) |
| protocolFee | string | Protocol fee in USDC (6 decimals) |
| builderFee | string | Builder fee in USDC (6 decimals) |
| totalFee | string | Total fees in USDC (6 decimals) |
| effectivePrice | string | Effective price per share after fees |
getLiveScores()
Get ESPN live scores matched to MarkIt markets.
const scores = await markit.markets.getLiveScores()
// [{ homeTeam: "Lakers", awayTeam: "Celtics", homeScore: 98, awayScore: 95, status: "in_progress", period: "4th", clock: "2:15" }]markit.trade
placeBet({ market, side, usdcAmount, signer, minSharesOut? })
Full flow: checks USDC allowance, approves if needed, places the bet, reports builder attribution.
const result = await markit.trade.placeBet({
market: '0x...',
side: 'yes',
usdcAmount: 10_000_000n, // $10 USDC
minSharesOut: 9_000_000_000n, // optional: slippage protection
signer: walletClient,
})
// { txHash: '0x...', attributed: true }signermust be a viem WalletClient with anaccount- Attribution is fire-and-forget — the bet succeeds even if attribution fails
- USDC uses 6 decimals:
$1 = 1_000_000n,$10 = 10_000_000n,$100 = 100_000_000n
buildPlaceBetCalls({ market, side, usdcAmount, minSharesOut? })
Returns raw { to, data } call objects for smart wallet batching. Does not send any transactions.
const calls = markit.trade.buildPlaceBetCalls({
market: '0x...',
side: 'no',
usdcAmount: 25_000_000n,
})
// Returns: [approveCall, placeBetCall]After sending via your smart wallet, call reportAttribution() to credit the builder fee.
reportAttribution({ market, txHash, bettor })
Report a bet for builder fee attribution. Called automatically by placeBet(), but must be called manually when using buildPlaceBetCalls().
const ok = await markit.trade.reportAttribution({
market: '0x...',
txHash: '0x...',
bettor: '0x...',
})
// true if attribution was acceptedgetPositions(user)
Get a user's open positions across all markets.
const positions = await markit.trade.getPositions('0x...')
// [{ market: '0x...', yesShares: 15000000000000000000n, noShares: 0n }]markit.vault
The LP vault underwrites all markets. Depositors earn fees from every bet.
getState()
const vault = await markit.vault.getState()
console.log(vault.nav) // total NAV in USDC (6 decimals)
console.log(vault.sharePrice) // price per share (WAD)
console.log(vault.float) // undeployed USDC (6 decimals)
console.log(vault.activeMarketCount) // number of live marketsgetUserPosition(user)
const pos = await markit.vault.getUserPosition('0x...')
console.log(pos.shares) // vault shares (WAD)
console.log(pos.value) // current USDC value (6 decimals)deposit({ usdcAmount, signer })
Deposit USDC into the vault. Handles approval automatically.
const txHash = await markit.vault.deposit({
usdcAmount: 1_000_000_000n, // $1,000
signer: walletClient,
})requestWithdrawal({ shares, signer })
Request a withdrawal from the vault (enters FIFO queue).
const txHash = await markit.vault.requestWithdrawal({
shares: 500_000_000_000_000_000_000n, // 500 shares (WAD)
signer: walletClient,
})markit.builder
Requires apiKey in client config (received during registration at /builders).
getStats()
const stats = await markit.builder.getStats()Returns BuilderStats:
| Field | Type | Description |
|-------|------|-------------|
| totalVolume | number | All-time bet volume (USD) |
| totalFees | number | All-time builder fees earned (USD) |
| totalBets | number | Total bets attributed |
| uniqueUsers | number | Unique bettors |
| unpaidFees | number | Fees pending payout (USD) |
| last30dVolume | number | 30-day rolling volume |
| last30dFees | number | 30-day rolling fees |
getFeeHistory({ limit? })
const fees = await markit.builder.getFeeHistory({ limit: 50 })
// [{ market, bettor, usdcBet, builderFee, txHash, createdAt, paidAt }]Error Handling
All SDK errors throw MarkitError with a typed code:
import { MarkitError, ErrorCode } from '@markit.market/sdk'
try {
await markit.trade.placeBet({ ... })
} catch (err) {
if (err instanceof MarkitError) {
switch (err.code) {
case ErrorCode.TX_REJECTED: // user rejected in wallet
case ErrorCode.INSUFFICIENT_USDC: // not enough USDC balance
case ErrorCode.BET_TOO_SMALL: // below minimum bet
case ErrorCode.SKEW_CAP_EXCEEDED: // market too skewed
case ErrorCode.MARKET_NOT_OPEN: // market not accepting bets
case ErrorCode.TX_REVERTED: // on-chain revert
case ErrorCode.NETWORK_ERROR: // RPC/fetch failure
case ErrorCode.INVALID_PARAMS: // bad input
}
}
}USDC Amounts
USDC uses 6 decimals. Common values:
| Amount | BigInt |
|--------|--------|
| $0.01 | 10_000n |
| $1 | 1_000_000n |
| $10 | 10_000_000n |
| $100 | 100_000_000n |
| $1,000 | 1_000_000_000n |
Testnet
Use Base Sepolia for development:
const markit = createMarkitClient({
builderCode: 'your-code',
chain: 'baseSepolia',
})Testnet USDC can be minted freely via the MockUSDC contract.
Requirements
- Node.js 18+
viem>= 2.0.0 (peer dependency)
License
MIT
