@findloot/sdkv0.1.1MITStellar testnet
Ship puzzle chests
from TypeScript.
Create, read and claim Loot chests on Stellar. Answers stay on the device; proofs are bound to the solver's address and verified on Soroban.
Quickstart
From install to a live chest.
Three calls. The answer is hashed on the device; only the fingerprint reaches the ledger.
- 1
Install
One ESM package. It pulls in @stellar/stellar-sdk and circomlibjs.
terminalShell $ npm i @findloot/sdk - 2
Create a chest
Hash the answer on the device, then escrow XLM behind the fingerprint. Returns the chest id.
create.tsTypeScript import { createChestClient, fingerprintAnswer, CONTRACTS, DEFAULT_AMOUNT_PER_SLOT_STROOPS,} from "@findloot/sdk";// 1. Hash the answer locally — only the fingerprint goes on-chainconst { fingerprintHex } = await fingerprintAnswer("alexandria", 7n);// 2. Escrow 10 XLM behind itconst client = createChestClient({ publicKey: creator });const tx = await client.create_chest({ creator, fingerprint: Buffer.from(fingerprintHex, "hex"), token: CONTRACTS.xlm, prize: DEFAULT_AMOUNT_PER_SLOT_STROOPS, max_claims: 1, deadline: BigInt(Math.floor(Date.now() / 1000) + 7 * 86400),});// signer passed at send time (wiring unverified)const sent = await tx.signAndSend({ signTransaction });const chestId = sent.result.unwrap(); - 3
Solve and claim
Read the chest, prove the answer for your own address and claim. Soroban verifies the proof on-chain.
claim.tsTypeScript const chest = (await client.get_chest({ chest_id: chestId })).result.unwrap();// proof + nullifier come from the Loot Groth16 circuit (BN254),// generated in the browser — not exported by @findloot/sdk 0.1.1const tx = await client.claim({ chest_id: chestId, recipient: solver, // public input of the proof nullifier, proof: { a, b, c },});await tx.signAndSend({ signTransaction });
Use cases
One primitive, many games.
Treasure hunts
Riddles and puzzle trails with an XLM prize at the end. The first valid proof wins.
CTF and bounty prizes
Gate a payout behind a flag. A proof copied from the mempool pays nobody else.
Campaign quests
Onboarding quests and campaigns with a fixed number of winners, set with max_claims.
API reference
Everything in @findloot/sdk.
Helpers
Client · @findloot/chest
Constants
Proof generation (witness + Groth16 prove) is not exported in 0.1.1. Pass your wallet signer to signAndSend({ signTransaction }) (wiring unverified). client.* methods come from @findloot/chest.
Concepts
Why bots can't steal the prize.
Proof bound to your address
The solver address is a public input of the Groth16 proof. A copied proof cannot pay anyone else.
Nullifier
Every claim spends a nullifier stored on-chain, so the same proof can never be replayed.
Soroban verifier
The registry calls the verifier contract, which checks the BN254 proof on-chain.
Relayer gas
Claims can go through a relayer, so new solvers need no XLM for fees.