@usefillr/sdk gives you typed instruction builders, PDA derivation, and account decoders. ~120 LOC of hand-rolled Borsh, @solana/web3.js as the only peer dep.
Install
bashpnpm add @usefillr/sdk @solana/web3.js
PDA derivation
typescriptimport { findCommitmentPda, findVaultAuthorityPda } from "@usefillr/sdk"; const [commitment] = findCommitmentPda(owner, nonce); const [vaultAuthority] = findVaultAuthorityPda(commitment);
The vault token ATA is the standard getAssociatedTokenAddressSync(paymentMint, vaultAuthority, true, TOKEN_PROGRAM_ID). The SDK ships a local findAssociatedTokenAddress helper to avoid the @solana/spl-token dep.
Build create_commitment
typescriptimport { buildCreateCommitmentIx, PRICE_SCALE, WSOL_MINT, } from "@usefillr/sdk"; const ix = buildCreateCommitmentIx({ owner: wallet.publicKey, args: { targetMint: new PublicKey("..."), paymentMint: WSOL_MINT, paymentAmount: 10_000_000n, // 0.01 SOL in lamports maxPrice: 1_000_000_000_000n, // u128, 1e18 scale minFill: 1_000_000_000n, // 1 token at 9 decimals keeperBounty: 1_000_000n, // 0.001 SOL trigger: { kind: "jupiterRoutable", minLiquidityUsd: 1000n }, expiryTs: BigInt(Math.floor(Date.now() / 1000) + 7 * 86400), nonce: BigInt(Date.now()), targetDecimals: 6, userJitoTipLamports: 0n, // Jito tip for pump.fun fills }, });
Build execute_commitment
Used by keepers. Wraps a Jupiter /swap-instructions response into a fillr ix.
typescriptimport { buildExecuteCommitmentIx } from "@usefillr/sdk"; const swapIx = await fetchJupiterSwapInstructions(...); const ix = buildExecuteCommitmentIx({ keeper: keeperKp.publicKey, commitment: commitmentPda, owner: c.owner, paymentMint: c.paymentMint, targetMint: c.targetMint, jupiterSwap: { data: swapIx.data, accounts: swapIx.accounts, }, });
Build cancel / expire
typescriptimport { buildCancelCommitmentIx, buildExpireCommitmentIx } from "@usefillr/sdk"; const cancelIx = buildCancelCommitmentIx({ signer: owner, owner, commitment: commitmentPda, paymentMint: c.paymentMint, }); // expire is permissionless — signer can be anyone past expiry_ts const expireIx = buildExpireCommitmentIx({ signer: keeper, owner, commitment, paymentMint });
Decode a Commitment account
typescriptimport { decodeCommitment } from "@usefillr/sdk"; const info = await connection.getAccountInfo(commitmentPda); if (info) { const c = decodeCommitment(commitmentPda, info.data); console.log(c.status, c.maxPrice, c.trigger); }
Constants
typescriptimport { FILLR_PROGRAM_ID, TREASURY, USDC_MINT, USDT_MINT, WSOL_MINT, JUPITER_PROGRAM_ID, JUPITER_EVENT_AUTHORITY, SHARED_ACCOUNTS_ROUTE_DISCRIMINATOR, PRICE_SCALE, // 10n ** 18n PROTOCOL_FEE_BPS, // 20 MIN_KEEPER_BOUNTY_LAMPORTS, MAX_KEEPER_BOUNTY_LAMPORTS, } from "@usefillr/sdk";
On mainnet vs. devnet: only
FILLR_PROGRAM_ID and TREASURY differ between deployments. Everything else (Jupiter, payment mints, scales) is identical across clusters because the upstream programs are deployed at the same addresses.