npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mallow-labs/mallow-sweepstake-sdk

v0.1.1

Published

Kit SDK and independently verifiable draw tooling for mallow sweepstakes

Readme

@mallow-labs/mallow-sweepstake-sdk

Kit-native bindings and backend-free verification for the mallow Sweepstake program (draw algorithm v2). The package does not contain an Anchor 0.29 client or a handwritten instruction serializer.

The public surface has three layers:

  • pure round, drand, transcript and shuffle functions from the package root;
  • a structurally independent draw and seed implementation at ./independent for cross-checks;
  • Codama-generated Kit accounts, instructions, events and PDA helpers at ./generated, derived from the vendored real Anchor IDL.

How a draw works (v2)

  1. create_sweepstake commits the setup identity, the terms and the drand evmnet round: the first round at or after entry close plus 30 seconds (roundForCloseTime, ceiling arithmetic; tyki's evmnetRoundAt floors and must not be used).
  2. Anyone calls settle_draw with the 64-byte evmnet signature for that round. The program verifies the BLS signature itself, freezes n = next_index and k = min(n, item_count), and stores seed = sha256("MALLOW_SWEEPSTAKE_SEED_V2" || program || sweepstake || candy_machine || setup_id || chain_hash || u64_le(round) || sha256(signature) || u32_le(n) || u32_le(k)) (233-byte preimage). A settled seed can never be replaced; there is no Tyki request or Beacon account and no rent for either.
  3. Anyone calls resolve_entry. With no proof, the program evaluates a swap-or-not permutation of [0, n) (the Ethereum consensus compute_shuffled_index structure, 90 rounds, exact rejection-sampled pivots, at most 4 attempts, never a modulo fallback). An entry wins iff shuffle(seed, n, index) < k, so exactly k entries win.

The permutation is pseudorandom, not an exactly uniform subset sampler. Admission (mallow co-signs entries), delivery availability, the creator's machine and guard authority, drand, the upgrade authority and token issuers remain trusted. Winners can self-claim until the seven-day recovery deadline; automatic delivery begins at day three. The guard's thirdPartySigner is the program PDA findMintSignerPda({ sweepstake, authority, programAddress }) (seeds ["mint-signer", sweepstake, authority]), so mallow's key cannot mint directly. Because the signer binds the creating authority, anyone else who tries to create the sweepstake for that machine derives a different signer and the guard check rejects them. Chain verification requires the created mint_signer to match the creating authority.

Commands

pnpm generate
pnpm typecheck
pnpm test
pnpm build
pnpm benchmark:draw
mallow-sweepstake verify <sweepstake> --rpc <url> [--drand-mirror]
mallow-sweepstake result <sweepstake> --user <address> --rpc <url>
mallow-sweepstake settle send <sweepstake> --rpc <url> --keypair ~/.config/solana/id.json --send
mallow-sweepstake resolve send <sweepstake> --user <address> --rpc <url> --keypair ~/.config/solana/id.json --send
mallow-sweepstake verify-manifest path/to/manifest.json
mallow-sweepstake verify-manifest https://archive.example/manifest.json --rpc https://archival-rpc.example
mallow-sweepstake verify-manifest path/to/dev-manifest.json --allow-short-windows
mallow-sweepstake recover sol --program <address> --sweepstake <address> --entry <address> --user <address> --fee-destination <address> --setup-id <64-hex>
mallow-sweepstake recover resolve --program <address> --sweepstake <address> --entry <address> --setup-id <64-hex>
mallow-sweepstake recover send --program <address> --sweepstake <address> --entry <address> --user <address> --setup-id <64-hex> --rpc <url> --keypair ~/.config/solana/id.json --send

verify needs only a sweepstake address and a trusted archival RPC, with no manifest or mallow backend. It decodes the finalized Sweepstake account (owner, size, discriminator, version 2) and scans authenticated events back to this generation's SweepstakeCreated. It reads the drand signature from the authenticated DrawSettled event, verifies it locally against the pinned evmnet key for the committed round, recomputes the seed with both transcript implementations, and recomputes the winners with both draw implementations. Every authenticated Resolved result must match. It works after the Sweepstake account is closed. JSON output includes {ok, status, signatureValid, seedMatches, n, k, winners, resolvedChecked, missingEvidence, errors} plus hex seed, randomness, drandSignature, chainHash and decimal round. Missing or pruned history fails with missingEvidence and a non-zero exit. --drand-mirror also requires a public drand mirror to return the identical signature.

result prints {index, user, isWinner, shuffledIndex} for one entrant from the same verification. settle send fetches the committed round from public drand mirrors (each with a 10-second timeout), verifies it locally, and submits settle_draw with a 400,000 compute-unit limit (measured SBF maximum 283,532 CU over 20 archived rounds; theoretical four-attempt pivot bound about 368,000). resolve send reads the finalized Sweepstake and Entry, rejects a resolved Entry before loading the keypair, and sends the proof-free resolve_entry. Anyone may pay; --keypair and exactly one literal --send are required. Transactions use RPC preflight and wait for finalized confirmation. These commands default to the program address in the generated IDL; use --program <address> for another deployment. Commands reject unrecognized flags; result validates --user before RPC access.

--allow-short-windows accepts only the development close+600 second draw and close+1400 second recovery deadlines, and rejects a mainnet genesis hash.

Manifests (v2)

The default manifest verifier is offline. It rejects anything but manifestVersion: 2 and mallow-sweepstake-draw-v2, checks the PDA, terms, round commitment and deadlines, verifies the archived drand signature cryptographically (it never trusts an archived seed), recomputes the seed and winners, and checks archived results. This establishes internal consistency only. With --rpc, the CLI verifies the cluster genesis hash and program account, then scans finalized history back to this generation's creation event and authenticates every Entered, DrawSettled, Resolved, cancellation, void and closure event against the manifest. A manifest with a closure passes after its candy machine is closed; one without requires it to exist. The RPC must retain archival transaction history; pruned history fails closed. It must also serve v1 (SIMD-0385) transactions (Agave 4.2 or later): mallow resolves winners in batched v1 transactions, and history is read with maxSupportedTransactionVersion: 1.

Recovery without mallow

recover sol, recover resolve and recover principal print unsigned instructions and never read a private key or connect to RPC.

recover send is an explicit local-key opt-in and requires --rpc, --keypair and the literal --send. It reads finalized Sweepstake, Entry and Clock accounts in one snapshot and validates their owner, version, generation, canonical PDAs and the immutable Entry recipient. Before the recovery deadline, a settled but unresolved Entry is resolved in the same transaction as the first withdrawal. For a token entry, the SOL component (rent reserve, plus the entry fee when refundable) finalizes first in its own transaction; if the reserve already went out but the fee is still held at or after the recovery deadline, it sends a fee-only withdraw_entry_sol. It then reloads and submits token principal, which settles any still-held fee. For SOL setups, the writable token-account placeholders are the original Entry.user and the read-only mint and token program are the system program. Never put the system program or an invoked program in a writable slot: the runtime demotes it to read-only and Anchor rejects it. A production operator using multisig custody should assemble the unsigned instructions in its normal workflow instead of exporting a key.

Principal refunds go to the entrant's canonical associated token account when it is missing (the program creates it) or valid. A classic SPL entrant can reassign that ATA's owner with SetAuthority; the program then refuses it. In that case recover send (and planPrincipalRefundDestination for other callers) creates a fresh token account owned by the original entrant for the stored mint, in the same transaction as withdraw_entry: System CreateAccountWithSeed with the payer as base and a random seed, then Token InitializeAccount3. A failed withdrawal reverts the account, so no rent is orphaned. The recovery payer funds that account's rent (about 0.002 SOL); the entrant owns it and can close it to recover the rent. Tokens are never sent to an account owned by anyone else. Token-2022 ATAs are ImmutableOwner and cannot be reassigned. Manual recover principal may pass any existing token account owned by the original entrant for the stored mint; the program checks owner, mint and token program.

Token-2022 payouts: an entrant or treasury token account may enable RequiredMemoTransfers. The program then CPIs the SPL Memo program before the transfer and needs MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr as one trailing read-only, non-signer remaining account (it fails MemoProgramRequired otherwise). The generated builders stay raw; wrap every Token-2022 withdraw_entry, claim_prize, deliver_prize and close_sweepstake with withMemoProgramForToken2022(instruction, sweepstake.tokenProgram). It is idempotent, preserves every other field and meta, and returns SOL and classic SPL instructions unchanged. getPrincipalRecoveryInstruction, recover send and recover principal apply it automatically; withdraw_entry_sol moves no tokens and does not need it.

Entry fees stay in escrow until terminal processing: earned by a successful mint or a resolved loser's full withdrawal before the recovery deadline, and refunded on chain for cancelled, void or expired draws and for anything still open at the recovery deadline.

decodeSweepstakeEvents(logs, expectedProgramAddress) tracks Solana invocation depth and decodes Program data: only while that program is executing.

Benchmarks

pnpm benchmark:draw runs the canonical all-entrant draw, a single-entry evaluation, the independent draw and one local drand verification in fresh processes at 1,000 to 1,000,000 entrants, and requires identical winner sets. Results are in benchmarks/. They measure local CPU and memory only, not compute units or RPC throughput.

drand verification provenance and license attribution are in DRAND_PROVENANCE.md.