TypeScript SDK for MineBTC, the Solana country-warfare
game. It decodes live round and cycle state, derives PDAs, and builds betting,
claim, stake, and marketplace transactions — straight from RPC, with no MineBTC
backend, GraphQL, or socket. Built on @solana/kit
(web3.js v2), generated from the on-chain IDLs with Codama.
npm i @minebtc/sdkimport { MinebtcClient } from "@minebtc/sdk";
const client = new MinebtcClient({ rpcUrl: "https://your-rpc-endpoint" });
// Read the current round's pools.
const pools = await client.reads.getCountryPools();
console.log("active countries:", pools.activeFactionIds);
// Build and send a bet (signer is a @solana/kit TransactionSigner).
const ixs = await client.writes.placeBet({
bets: [{ factionId: 0, direction: 2 }], // USA, Up
amountPerBet: 100_000n, // lamports per position
authority: signer,
});
const sig = await client.send(signer, ixs); // needs rpcSubscriptionsUrlnew MinebtcClient({
rpcUrl: "https://your-rpc-endpoint", // bring your own; required for real use
rpcSubscriptionsUrl: "wss://your-rpc", // needed for client.send (confirm over WS)
network: "mainnet-beta", // default
});- RPC. Bring your own URL. With no
rpcUrlthe SDK falls back to the public Solana Labs endpoint — fine for a smoke test, rate-limited for anything real. - Network. Mainnet config (program ids, mints, collection, fee recipients,
marketplace PDA) is pinned. Program ids are identical across networks; for
devnet pass a
configoverride with the chain-specific addresses. - Keypair. The SDK signs nothing on its own — write builders return unsigned
Instruction[]. You supply aTransactionSigner(see the examples for loading one from a Solana CLI keypair). - Commitment is
confirmedeverywhere, matching the on-chain cranker. - Live updates. Prefer
accountSubscribeover polling; about five PDAs cover the whole live game (GlobalGameSate,FactionWarConfig,DegenBtcMining, the currentGameSession, the currentFactionWarState).
Each returns a decoded Account<T> (or a derived view).
| Method | Returns |
|---|---|
getGlobalState() |
GlobalGameSate — round id, duration, jackpot pot |
getGlobalConfig() |
GlobalConfig — fee config, tuning |
getMining() |
DegenBtcMining — dBTC per round, LP op count, prices |
getRound(roundId?) |
GameSession — boards, totals, result; default = current |
getCountryPools(roundId?) |
per-country×direction {points, wgtdPoints, sol, active} view |
getFactionState(id) |
one FactionState (name-keyed PDA) |
getFactions() |
all 12 FactionState, indexed by faction id |
getCycleConfig() |
FactionWarConfig — war id, cutoff round, multipliers |
getCycleState(warId?) |
FactionWarState — scores, round wins, MVP; default = current |
getCycleSettlement(warId) |
FactionWarSettlement — final ranks |
getRankings(warId?) |
current standings sorted by score (the public leaderboard) |
getPlayer(wallet) |
PlayerData |
getPendingClaims(wallet) |
pending round + cycle claim counts |
getUserGameBet(wallet, roundId) |
UserGameBet |
getUserCycleBets(wallet, warId) |
UserFactionWarBets |
getAutominer(wallet) |
AutominerVault |
getStakePosition(w, idx, type) |
StakedPosition (dBTC = 0, LP = 1) |
getHashBeast(asset) |
HashBeastMetadata |
Each returns an unsigned Instruction[] (compute-budget, ATA/WSOL pre-ix, and
the program ix in order). Sign and send yourself, or pass to client.send.
Arrays let you batch — e.g. several claim_round_rewards in one transaction.
| Method | Instruction |
|---|---|
placeBet({bets, amountPerBet, …}) |
join_bets (+ WSOL unwrap) |
claimRound({roundId, wallet, caller}) |
claim_round_rewards |
claimRoundsBatch({roundIds, wallet, caller}) |
batched claim_round_rewards (1.4M CU) |
claimAutominer({roundId, owner, caller}) |
claim_autominer_rewards |
claimCycle({warId, wallet, cranker}) |
claim_war_rewards |
stakeDbtc / unstakeDbtc |
stake / unstake_degenbtc (Token-2022) |
stakeLp / unstakeLp |
stake / unstake_lp_tokens (classic SPL) |
claimStakingRewards / withdrawDbtcRewards |
claim_staking_rewards / withdraw_dbtc_rewards |
lockForGameplay / requestUnlock / withdrawGameplay |
HashBeast gameplay lock / unlock |
initPlayer / claimReferral |
initialize_player / claim_referral_rewards |
marketBuy / marketList / marketCancel / marketUpdatePrice |
marketplace CPI wrappers |
The builders fold in correctness work the IDL can't express, each verified
against the production frontend: exact IDL account order; the required
UserFactionWarBetCloseState remaining account on claims, with user_bet_rent_payer
read from the on-chain close-state; CU bumps on heavy claims; mpl-core (not SPL)
on HashBeast and marketplace ix; Token-2022 dBTC vs classic-SPL LP ATAs with
idempotent creation; native-SOL bets that unwrap WSOL first; the optional
referrer and gameplay-HashBeast accounts.
PDA helpers (deriveGlobalGameState, deriveFactionState, deriveGameSession,
deriveStakePosition, …), SPL helpers (deriveAta, buildCreateDbtcAtaIdempotent,
…), and the send path (sendTransaction, buildSignedTransaction,
clampPriorityFee) are exported from the package root. The raw Codama client is
re-exported flat for anything the wrappers don't cover.
The core targets @solana/kit. If you're on web3.js v1 + @coral-xyz/anchor,
the account names and orders are identical: derive PDAs with this SDK's pda
helpers (they return base58 addresses) and pass the same camelCase account
objects to an Anchor Program built from idl/minebtc.json.
In examples/. RPC and keypair come from env (RPC_URL,
RPC_WS_URL, KEYPAIR_PATH); nothing is hardcoded.
read-state.ts— connect and print global state, factions, and the current round's pools.place-bet.ts— build and send one bet from the env keypair.auto-claimer.ts— self-scan a wallet's unclaimed rounds and batchclaim_round_rewards(permissionless cranker).
RPC_URL=https://your-rpc npx tsx examples/read-state.tsThe generated client under src/generated/ is committed and reproducible from
the vendored IDLs — never hand-edit it; change the IDL or codegen and regenerate.
When the contract changes, copy the new IDL into idl/, run npm run codegen,
and update any wrapper whose account list or args changed.
npm ci
npm run codegen && git diff --exit-code src/generated # no codegen drift
npm run build # typecheck + emit
npm run typecheck:examples
npm test
npm run smoke # decode a live accountCI runs the same checks.
- Play: minebtc.fun
- Engine and programs:
LifeOrDream/MineBtc-fi—minebtc1eotiTH2UxCpPMmtzUDGqf1b8dwM7AMKb8a2Tio51an,degenbtc_marketBCuofnvb7QUP6xLH83EEbKFNjxz5T5Jp4xLqfEdURYRg - This SDK:
LifeOrDream/minebtc-ts-sdk
MIT — see LICENSE.