{"_id":"@bonkit/airdrop-sdk","_rev":"3-27cad20babb4309b56484306fea203ca","name":"@bonkit/airdrop-sdk","dist-tags":{"latest":"0.3.4"},"versions":{"0.3.2":{"name":"@bonkit/airdrop-sdk","version":"0.3.2","keywords":["solana","anchor","airdrop","sdk","bonkit"],"author":{"name":"Bonkit-Dev"},"license":"MIT","_id":"@bonkit/airdrop-sdk@0.3.2","maintainers":[{"name":"bonkit-dev","email":"dev@bonkit.dev"}],"homepage":"https://github.com/bonkit-dev/airdrop-sdk#readme","bugs":{"url":"https://github.com/bonkit-dev/airdrop-sdk/issues"},"dist":{"shasum":"ee52db1634bf89fa86ffd1043563942d07124e45","tarball":"https://registry.npmjs.org/@bonkit/airdrop-sdk/-/airdrop-sdk-0.3.2.tgz","fileCount":7,"integrity":"sha512-RSapLtLXFMJFSj8NiTzzWYH2zzul73pKCEg2sW4CHnE1JAqD5XVmrJBh+vVf8h0wHTaxSefVgFygimKJJyAzqQ==","signatures":[{"sig":"MEQCIHuisXDvMioPnPhmM4qTNuSKikI+FZ4Mf8TKKH3PUTHUAiAYUNh+/dRKE2SGo1qsM8jUq1CJIt7KHWAvWeZEmDi3vA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1695032},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","gitHead":"d454320564bf961247a3e0a09cd37e03dd9390d6","private":false,"scripts":{"build":"tsup --config tsup.config.ts","clean":"shx rm -rf dist","sync-idl":"bash ../../scripts/sync-idl-public.sh"},"_npmUser":{"name":"bonkit-dev","email":"dev@bonkit.dev"},"repository":{"url":"git+https://github.com/bonkit-dev/airdrop-sdk.git","type":"git"},"_npmVersion":"10.9.2","description":"Public Airdrop Studio SDK.","directories":{},"_nodeVersion":"22.16.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"peerDependencies":{"@solana/web3.js":"^1.98.4","@coral-xyz/anchor":"^0.31.1","@solana/spl-token":"^0.4.14"},"_npmOperationalInternal":{"tmp":"tmp/airdrop-sdk_0.3.2_1774584155337_0.5448669120890071","host":"s3://npm-registry-packages-npm-production"}},"0.3.3":{"name":"@bonkit/airdrop-sdk","version":"0.3.3","keywords":["solana","anchor","airdrop","sdk","bonkit"],"author":{"name":"Bonkit-Dev"},"license":"MIT","_id":"@bonkit/airdrop-sdk@0.3.3","maintainers":[{"name":"bonkit-dev","email":"dev@bonkit.dev"}],"homepage":"https://github.com/bonkit-dev/airdrop-sdk#readme","bugs":{"url":"https://github.com/bonkit-dev/airdrop-sdk/issues"},"dist":{"shasum":"faacb0726d4ddcd3afa621e5c9ba8a51ca3d5af0","tarball":"https://registry.npmjs.org/@bonkit/airdrop-sdk/-/airdrop-sdk-0.3.3.tgz","fileCount":8,"integrity":"sha512-2mDRJJ+xEsG41Pnampj4PikETA61bq2MRWG1Vn/D49XA/Dl1UuLZqSt9NXQ0Jj58xrKcws/Pvjz2bjgeL0Pr1g==","signatures":[{"sig":"MEUCIQCKqaRcbSXOxMf8eAvstjIJIgjXYcBA9hxtth/ty7P7IQIgI8HzjSkZC3KRftiqJuz/IURkh5lK/j/eFsCC/D8XJsk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bonkit%2fairdrop-sdk@0.3.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1698509},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","gitHead":"c4d2050fe0bddd1b9d1831e010c84d9fcda31655","private":false,"scripts":{"build":"tsup --config tsup.config.ts","clean":"shx rm -rf dist","sync-idl":"bash ../../scripts/sync-idl-public.sh"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:c21d0397-fc4e-4763-8d26-914f33fdd7b1"}},"repository":{"url":"git+https://github.com/bonkit-dev/airdrop-sdk.git","type":"git"},"_npmVersion":"11.12.1","description":"Public Airdrop Studio SDK.","directories":{},"_nodeVersion":"22.22.1","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"peerDependencies":{"@solana/web3.js":"^1.98.4","@coral-xyz/anchor":"^0.31.1","@solana/spl-token":"^0.4.14"},"_npmOperationalInternal":{"tmp":"tmp/airdrop-sdk_0.3.3_1774932089199_0.1330992500321282","host":"s3://npm-registry-packages-npm-production"}},"0.3.4":{"name":"@bonkit/airdrop-sdk","private":false,"version":"0.3.4","description":"Public Airdrop Studio SDK.","keywords":["solana","anchor","airdrop","sdk","bonkit"],"license":"MIT","author":{"name":"Bonkit-Dev"},"type":"module","main":"dist/index.cjs","module":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"repository":{"type":"git","url":"git+https://github.com/bonkit-dev/airdrop-sdk.git"},"homepage":"https://github.com/bonkit-dev/airdrop-sdk#readme","bugs":{"url":"https://github.com/bonkit-dev/airdrop-sdk/issues"},"scripts":{"sync-idl":"bash ../../scripts/sync-idl-public.sh","build":"tsup --config tsup.config.ts","clean":"shx rm -rf dist"},"peerDependencies":{"@coral-xyz/anchor":"^0.31.1","@solana/spl-token":"^0.4.14","@solana/web3.js":"^1.98.4"},"gitHead":"2b437ea3cd97351c8fa8692345576d11aa32a73d","_id":"@bonkit/airdrop-sdk@0.3.4","_nodeVersion":"22.22.1","_npmVersion":"11.12.1","dist":{"integrity":"sha512-UAwNhFow6kxxYhvAzo2SMr1ogIqgajcQAEJB3AFJDDq8w4tZyG7FXbbp80rMGyQM3scm6hEAQ9GY7aIKVx59HQ==","shasum":"f506dee954fcd06b85ea1e36dc07ceafa7791ec4","tarball":"https://registry.npmjs.org/@bonkit/airdrop-sdk/-/airdrop-sdk-0.3.4.tgz","fileCount":8,"unpackedSize":1706824,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bonkit%2fairdrop-sdk@0.3.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQClBdqz4DniFuH7/YGSuioSeebpNiTKP47okBId5vFmgQIhANtzhdBTX65WRCsNq3n9l8Vd9l/iXz2kS8eqdobX89sP"}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:c21d0397-fc4e-4763-8d26-914f33fdd7b1"}},"directories":{},"maintainers":[{"name":"bonkit-dev","email":"dev@bonkit.dev"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/airdrop-sdk_0.3.4_1774939428461_0.3984097839222114"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-27T04:02:35.249Z","modified":"2026-03-31T06:43:48.948Z","0.3.2":"2026-03-27T04:02:35.517Z","0.3.3":"2026-03-31T04:41:29.343Z","0.3.4":"2026-03-31T06:43:48.699Z"},"bugs":{"url":"https://github.com/bonkit-dev/airdrop-sdk/issues"},"author":{"name":"Bonkit-Dev"},"license":"MIT","homepage":"https://github.com/bonkit-dev/airdrop-sdk#readme","keywords":["solana","anchor","airdrop","sdk","bonkit"],"repository":{"type":"git","url":"git+https://github.com/bonkit-dev/airdrop-sdk.git"},"description":"Public Airdrop Studio SDK.","maintainers":[{"name":"bonkit-dev","email":"dev@bonkit.dev"}],"readme":"# @bonkit/airdrop-sdk\n\nTypeScript SDK for interacting with Airdrop Studio on Solana.\n\n## Install\n\n### npm\n\n```bash\nnpm install @bonkit/airdrop-sdk\n```\n\n```bash\nnpm install @coral-xyz/anchor @solana/web3.js @solana/spl-token\n```\n\n### yarn\n\n```bash\nyarn add @bonkit/airdrop-sdk\n```\n\n```bash\nyarn add @coral-xyz/anchor @solana/web3.js @solana/spl-token\n```\n\n### pnpm\n\n```bash\npnpm add @bonkit/airdrop-sdk\n```\n\n```bash\npnpm add @coral-xyz/anchor @solana/web3.js @solana/spl-token\n```\n\n## Quick Start\n\n```ts\nimport { Connection } from '@solana/web3.js'\nimport { AirdropStudioClient } from '@bonkit/airdrop-sdk'\n\nconst connection = new Connection('https://api.devnet.solana.com', 'confirmed')\n\nconst client = await AirdropStudioClient.init({\n  connection,\n  network: 'devnet',\n})\n```\n\nThe client accepts these commonly used options:\n\n- `connection`\n  Solana RPC connection used for reads and transaction building.\n- `network`\n  Runtime network used by the client. Supported values are `devnet`, `mainnet-beta`, and `mainnet`.\n- `defaultCommitment`\n  Optional default commitment for account reads and blockhash lookup.\n- `lookupTableAddress`\n  Optional transaction lookup override for advanced setups.\n\n## Client Usage\n\nThe SDK client is designed around two usage patterns:\n\n1. Read on-chain state\n   Fetch recipient lists and claim status for existing airdrops.\n2. Build transactions\n   Create versioned transactions for merkle and on-chain airdrop flows, then sign and send them in your app or backend.\n\nMost transaction methods return a `VersionedTransaction`. The SDK builds the transaction, but sending it is left to the caller.\n\n```ts\nimport { Connection, PublicKey } from '@solana/web3.js'\nimport { AirdropStudioClient } from '@bonkit/airdrop-sdk'\n\nconst connection = new Connection('https://api.devnet.solana.com', 'confirmed')\n\nconst client = await AirdropStudioClient.init({\n  connection,\n  network: 'devnet',\n})\n\nconst airdrop = new PublicKey('<replace-with-airdrop-address>')\nconst recipients = await client.listOnchainRecipients({ airdrop, limit: 10 })\n\nconsole.log(recipients.length)\n```\n\n## Included API Surface\n\n- `AirdropStudioClient`\n  Read Airdrop Studio accounts and build versioned transactions for merkle and on-chain airdrop flows.\n- `createPdas`\n  Derive Airdrop Studio PDAs directly from a program id.\n- Merkle builders\n  Build roots, derive proofs, and generate claim parameters from recipient input.\n- Serialized merkle helpers\n  Store compact tree data and derive claim proofs later without precomputing every proof.\n- Payload helpers\n  Generate fully materialized JSON payloads when you want every proof expanded ahead of time.\n- On-chain list helpers\n  Decode recipient list chunks and map recipient indices into chunk ranges.\n- Mint validation helpers\n  Pre-check whether a mint is compatible with Airdrop Studio flows.\n- Error helpers\n  Normalize low-level program failures into predictable application errors.\n\n## API Reference\n\n### `AirdropStudioClient`\n\nInitialize the client once and reuse it for reads and transaction-building flows.\n\n```ts\nconst client = await AirdropStudioClient.init({\n  connection,\n  network: 'devnet',\n  defaultCommitment: 'confirmed',\n})\n```\n\nCommon config fields:\n\n- `connection`\n  Solana RPC connection used for account reads and transaction building.\n- `network`\n  Runtime network used by the client. Supported values are `devnet`, `mainnet-beta`, and `mainnet`.\n- `defaultCommitment`\n  Default commitment used by read methods and blockhash lookup.\n- `lookupTableAddress`\n  Optional transaction lookup override for advanced setups.\n\nRead methods:\n\n- `listOnchainRecipients({ airdrop, offset?, limit? })`\n  Reads and decodes recipients stored in list chunk accounts.\n- `fetchClaimStatusFromLeaf({ airdrop, leaf })`\n  Looks up a claim status PDA derived from a merkle leaf hash.\n- `fetchClaimStatusFromIndex({ airdrop, entryIndex })`\n  Looks up a claim status PDA derived from an on-chain entry index.\n\nTransaction methods:\n\n- `createMerkleAirdrop`\n- `registerMerkleRoot`\n- `depositMerkleAirdrop`\n- `startMerkleAirdrop`\n- `claimMerkleTokens`\n- `withdrawMerkleAirdrop`\n- `createOnchainAirdrop`\n- `appendOnchainRecipients`\n- `depositOnchainAirdrop`\n- `startOnchainAirdrop`\n- `claimOnchainTokens`\n- `withdrawOnchainAirdrop`\n- `cancelMerkleAirdrop`\n- `cancelOnchainAirdrop`\n\nEach transaction method returns a `VersionedTransaction`. In general, the call shape is:\n\n```ts\nconst tx = await client.someMethod({\n  params,\n  accounts,\n  payer,\n  signers,\n})\n```\n\nWhere:\n\n- `params`\n  Instruction-specific values such as merkle roots, claim proofs, or timestamps.\n- `accounts`\n  The accounts required by that instruction.\n- `payer`\n  The public key that pays transaction fees.\n- `signers`\n  Optional signers used to sign the returned transaction before sending.\n\n### `createPdas`\n\nUse `createPdas(programId)` when you need deterministic addresses without creating the client first.\n\nCommon PDA builders include:\n\n- `draftIndex(creator)`\n- `airdrop(creator, draftIndex)`\n- Claim status PDA builders\n- List-related PDA builders\n\nThis is useful in backends, indexers, migration scripts, and tests where you already know the target program id.\n\n### Merkle builders\n\nUse these helpers to prepare merkle-based airdrops off-chain.\n\n- `buildMerkleTree(recipients, { airdrop, rootIndex })`\n  Builds one in-memory tree for a single root. Use it when your full recipient set fits into one root or when you want direct access to one tree object.\n- `buildMerkleRoots(recipients, { airdrop, maxRoots?, maxLeavesPerRoot? })`\n  Splits recipients into multiple roots when necessary and returns:\n  - `rootEntries`, which you pass into `registerMerkleRoot`\n  - `trees`, which you keep to derive proofs or claim parameters later\n- `getMerkleProof(tree, leafIndex)`\n  Derives the proof path for one leaf from an in-memory tree.\n- `createClaimMerkleParams(tree, leafIndex)`\n  Builds the `ClaimMerkleParams` object expected by `claimMerkleTokens`.\n\nUse `buildMerkleRoots` when you need both registration data and proof derivation. Use `buildMerkleTree` when you only need one root.\n\n### Serialized merkle helpers\n\nUse these helpers when you want a compact storage format instead of storing a fully materialized proof for every recipient.\n\n- `serializeMerkleTree(tree)`\n  Converts one in-memory tree into a JSON-friendly format that stores leaves and layers once.\n- `serializeMerkleRoots(result)`\n  Serializes the output of `buildMerkleRoots`, including both root entries and trees.\n- `getMerkleProofFromSerializedTree(serializedTree, leafIndex)`\n  Rebuilds the proof path for one leaf from serialized layers.\n- `createClaimMerkleParamsFromSerializedTree(serializedTree, leafIndex)`\n  Rebuilds the full claim parameters directly from serialized data.\n\nThis path is usually the better choice when storing merkle data in Redis, KV, databases, or object storage for large recipient sets.\n\n### Payload helpers\n\nUse these helpers when you want every proof precomputed and embedded into the output payload.\n\n- `createMerklePayload(leaves)`\n  Builds a single-root payload that includes root metadata, leaf hashes, and proofs.\n- `createMerklePayloadBundle(recipients, options)`\n  Builds a multi-root payload bundle with all proofs expanded.\n\nThis is convenient for static payload distribution, but it produces much larger output than serialized tree storage.\n\n### On-chain list helpers\n\nUse these helpers when your recipient source is on-chain list chunk data.\n\n- `parseListChunk`\n  Decodes a full list chunk into recipient entries.\n- `parseRecipient`\n  Decodes one recipient from serialized list data.\n- `parseRecipientAtIndex`\n  Decodes one recipient at a given index.\n- `getListChunkRange`, `getRecipientRange`, `getListChunkIndex`, `getListChunkOffset`\n  Map entry indices to chunk ranges and offsets.\n\nThese functions are most useful for readers, explorers, indexers, and custom tooling.\n\n### Mint validation helpers\n\nUse `validateMintForAirdrop` before building transactions when you want to fail early on unsupported or unsafe mint configurations.\n\n### Error helpers\n\nUse `normalizeProgramError`, `getAirdropStudioErrorByCode`, and `getAirdropStudioErrorByName` when you want to translate low-level Solana or Anchor failures into stable application-level messages.\n\n## Examples\n\n### Read on-chain recipients and claim status\n\n```ts\nimport { Connection, PublicKey } from '@solana/web3.js'\nimport { AirdropStudioClient } from '@bonkit/airdrop-sdk'\n\nconst connection = new Connection('https://api.devnet.solana.com', 'confirmed')\n\nconst client = await AirdropStudioClient.init({\n  connection,\n  network: 'devnet',\n})\n\nconst airdrop = new PublicKey('<replace-with-airdrop-address>')\nconst recipients = await client.listOnchainRecipients({ airdrop })\nconst firstRecipient = recipients[0]\n\nconsole.log(recipients.length)\n\nif (firstRecipient) {\n  const claimStatus = await client.fetchClaimStatusFromIndex({\n    airdrop,\n    entryIndex: firstRecipient.entryIndex,\n  })\n\n  console.log(claimStatus)\n}\n```\n\n### Build merkle roots for on-chain registration\n\n```ts\nimport { BN } from '@coral-xyz/anchor'\nimport { Keypair, PublicKey } from '@solana/web3.js'\nimport { buildMerkleRoots } from '@bonkit/airdrop-sdk'\n\nconst airdrop = new PublicKey('<replace-with-airdrop-address>')\nconst recipients = [\n  { wallet: Keypair.generate().publicKey, amount: new BN(1_000_000) },\n  { wallet: Keypair.generate().publicKey, amount: new BN(2_000_000) },\n]\n\nconst built = buildMerkleRoots(recipients, { airdrop })\n\nconsole.log(built.rootEntries)\nconsole.log(built.trees[0].root.hash)\n```\n\nUse `rootEntries` when calling `registerMerkleRoot`, and keep `trees` if you want to derive claim proofs later.\n\n### Store a compact serialized merkle tree and derive claim params on demand\n\n```ts\nimport { BN } from '@coral-xyz/anchor'\nimport { Keypair, PublicKey } from '@solana/web3.js'\nimport {\n  buildMerkleRoots,\n  createClaimMerkleParamsFromSerializedTree,\n  serializeMerkleRoots,\n} from '@bonkit/airdrop-sdk'\n\nconst airdrop = new PublicKey('<replace-with-airdrop-address>')\nconst recipients = [\n  { wallet: Keypair.generate().publicKey, amount: new BN(1_000_000) },\n  { wallet: Keypair.generate().publicKey, amount: new BN(2_000_000) },\n]\n\nconst built = buildMerkleRoots(recipients, { airdrop })\nconst serialized = serializeMerkleRoots(built)\n\nconsole.log(serialized.rootEntries[0].leafCount)\n\nconst firstRoot = serialized.trees[0]\nconst claimParams = createClaimMerkleParamsFromSerializedTree(firstRoot, 0)\n\nconsole.log(claimParams.rootIndex)\nconsole.log(claimParams.leafIndex)\nconsole.log(claimParams.proof.length)\n```\n\nThis approach is usually better than storing fully materialized payloads when you have a large number of recipients, because the serialized tree stores each node once and derives proofs only when needed.\n\n### Build a transaction with the client\n\n```ts\nimport { BN } from '@coral-xyz/anchor'\nimport { Connection, Keypair, PublicKey } from '@solana/web3.js'\nimport { AirdropStudioClient, createClaimMerkleParamsFromSerializedTree } from '@bonkit/airdrop-sdk'\n\nconst connection = new Connection('https://api.devnet.solana.com', 'confirmed')\nconst payer = Keypair.generate()\nconst claimant = Keypair.generate()\n\nconst client = await AirdropStudioClient.init({\n  connection,\n  network: 'devnet',\n})\n\nconst airdrop = new PublicKey('<replace-with-airdrop-address>')\nconst mint = new PublicKey('<replace-with-mint-address>')\nconst serializedTree = JSON.parse('<serialized tree JSON>')\nconst claimParams = createClaimMerkleParamsFromSerializedTree(serializedTree, 0)\n\nconst tx = await client.claimMerkleTokens({\n  params: claimParams,\n  accounts: {\n    airdrop,\n    mint,\n    claimant: claimant.publicKey,\n  },\n  payer: payer.publicKey,\n  signers: [payer, claimant],\n})\n\nconsole.log(tx)\n```\n","readmeFilename":"README.md"}