@koshfinance/sdk
@koshfinance/sdk
Typed TypeScript client for kosh finance, a Solana prediction market for World Cup
matches that settles trustlessly through the TxODDS TxLINE oracle. The SDK targets the
pm_market program deployed on devnet at
6yRqxBy8JykXZGybtrvMMYW7o7DWSiMt86Km8h5QJ7FE.
The package is intended for bots, integrations, and backend services that sign with a keypair. Frontend applications should use a wallet adapter together with the generated instruction builders directly.
Installation
npm install @koshfinance/sdk
The client is built on @solana/kit, which installs
as a dependency. Node 18 or newer is recommended.
Quick start
KoshClient is the high level entry point. It accepts human units such as whole tokens
and probabilities, and handles PDA derivation, associated token accounts, and
transaction signing internally.
import { KoshClient, Cmp } from "@koshfinance/sdk";
const kosh = await KoshClient.connect({ secretKey }); // 64 byte wallet secret
// Discover markets.
const open = await kosh.listOpenMarkets(); // every live market on chain
const openable = await kosh.openableMarkets(fixtures); // fixtures with no market yet
// Open a market and seed it in a single transaction. The creator becomes the first LP.
const { market } = await kosh.createMarket({
fixtureId,
statKeyA: 1,
statKeyB: 2,
period: 4,
predicate: { __kind: "Sum", threshold: 2, op: Cmp.GreaterThan }, // total goals over 2
mint,
expiryTs,
voidAfterTs,
feeBps: 200,
seedLiquidity: 1000, // omit to open an empty, untradeable market
});
// Provide liquidity and place a bet.
await kosh.addLiquidity(market, mint, 500);
await kosh.bet(market, mint, { toPrice: 0.6, maxCost: 300 }); // move YES price to 60 percent
Reading a market
Reads require only an RPC connection and no signer.
import { createSolanaRpc, address } from "@solana/kit";
import { fetchMarket, zToPrice, SCALE } from "@koshfinance/sdk";
const rpc = createSolanaRpc("https://api.devnet.solana.com");
const { data: m } = await fetchMarket(rpc, address("MARKET_ADDRESS"));
console.log("YES price", zToPrice(m.z).toFixed(4)); // for example 0.5398
console.log("liquidity", Number(m.l0) / SCALE); // for example 1000
KoshClient reference
| Method | Purpose |
|---|---|
KoshClient.connect({ secretKey, rpcUrl?, wsUrl? }) |
Create a client from a wallet secret key. Defaults to devnet RPC. |
createMarket(params) |
Open a market and optionally seed liquidity in one transaction. Requires a whitelisted opener wallet. |
addLiquidity(market, mint, whole) |
Deposit collateral as a liquidity provider. |
bet(market, mint, { toPrice, maxCost }) |
Move the pool YES price to toPrice. maxCost is a required slippage cap. |
getMarket(market) |
Fetch and decode a market account. |
resolve(market, proof) |
Settle a market after expiry using a TxODDS proof. Sets the outcome by CPI into the oracle. |
listOpenMarkets() |
Return every market with open status. |
openableMarkets(specs) |
Return the specs whose market account does not yet exist. |
marketPda(spec) |
Derive the market address for a spec. |
initializeConfig() |
One time call that makes the signer the config admin. |
addOpener(wallet) / removeOpener(wallet) |
Admin only management of the opener whitelist. |
address |
The connected signer address. |
What is included
Most of the SDK is generated from the program Anchor IDL by Codama. The pricing bridge and the settlement mapping are written by hand.
| Generated instruction builders |
|---|
getInitializeConfigInstruction, getAddOpenerInstruction, getRemoveOpenerInstruction |
getInitializeMarketInstruction, getAddLiquidityInstruction, getWithdrawLiquidityInstruction |
getTradeBinaryInstruction, getResolveInstruction, getClaimInstruction, getVoidInstruction |
| Generated reads and PDAs |
|---|
fetchMarket, fetchPosition, fetchLpPosition, fetchConfig, fetchOpener with decoders |
findConfigPda, findVaultPda, findOpenerPda, findPositionPda, findLpPositionPda |
MarketStatus, Predicate, Cmp, ScoreStat, and related types and enums |
| Handwritten helpers |
|---|
priceToZ(p): target YES price to the zNew a trade requests. Uses probit on the client, since the program never runs the inverse normal CDF. |
zToPrice(z): on chain z value to a probability, for display. |
deriveMarketPda(spec): market address derivation, because the predicate seeds are computed and cannot be expressed in the IDL. |
proofToResolveArgs(proof), dailyScoresPda(ts), proofSeedTs(proof): map a TxODDS proof into the resolve instruction. |
SCALE: the fixed point scale, 1e9. All amounts use this scale, and the collateral mint must have 9 decimals. |
Concepts
The maxCost argument on bet is required. A round trip against the pool is provably
free, but a sandwich attack is not. Without a cost cap a sandwich attacker can force you
to absorb the slippage, so always supply a realistic cap.
Opening and seeding a market is a single atomic transaction. createMarket with
seedLiquidity bundles initialize_market and add_liquidity together. An unseeded
market is valid but cannot be traded, so seeding at open time is the default.
Market creation is curated. Only wallets on the on chain opener whitelist can open a market, while trading, liquidity provision, and settlement are permissionless. The config admin manages the whitelist and cannot touch funds or outcomes.
Local development
These commands are for contributors working inside this repository, not for consumers of the published package.
npm install # install dependencies
npm run build # compile TypeScript to dist
npm test # self checks and a live devnet decode, read only
node codegen.mjs # regenerate src/generated from the program IDL
Code generation reads ../contracts/target/idl/pm_market.json. The generator removes one
function, the pmMarketProgram() plugin factory, because it pulls a version of
@solana/addresses that conflicts with the installed @solana/kit. Nothing consumes that
factory, so instruction builders and PDA helpers are unaffected.
Addresses
| Item | Address |
|---|---|
pm_market program (devnet) |
6yRqxBy8JykXZGybtrvMMYW7o7DWSiMt86Km8h5QJ7FE |
txoracle settlement program (devnet) |
6pW64gN1s2uqjHkn1unFeEjAwJkPGHoppGvS715wyP2J |
| kosh API | https://kosh-api.silonelabs.workers.dev |