docs / gate an airdrop

Gate an airdrop

You have a list of candidate Bitcoin addresses. You want to drop tokens only on the ones that have skin in the game. @orangecheck/airdrop-gate does this in one command.

Install

yarn global add @orangecheck/airdrop-gate

CLI

oc-airdrop filter --min-sats 100000 --min-days 30 \
  < candidates.txt \
  > allowlist.txt \
  2> rejections.log
  • stdin: one address per line (blanks + # comments ignored).
  • stdout: allowlist, one address per line.
  • stderr: per-decision progress + final summary.

Full audit trail (JSON)

oc-airdrop filter --min-sats 1000000 --min-days 180 --json \
  < candidates.txt > report.json

Output shape:

{
  "total":      100,
  "passed":     72,
  "rejected":   28,
  "allowlist":  ["bc1q...", ...],
  "rejections": [
    { "address": "bc1q...", "ok": false, "reasons": ["below_min_sats"], "check": { ... } }
  ]
}

Try it in-browser

/airdrop is a live demo: paste candidates, set thresholds, watch them filter in real time. Good for sanity-checking before running a large batch.

Library

For programmatic use inside your own distribution pipeline:

import { filterAllowlist } from '@orangecheck/airdrop-gate';

const { ok, rejected } = await filterAllowlist(candidates, {
  minSats:     100_000,
  minDays:     30,
  concurrency: 8,
  onProgress:  (done, total) => console.log(`${done}/${total}`),
});

// Now distribute to `ok`

Threat model

What it raises the cost of

  • Mass sybil attacks. 10 000 fresh wallets × min_sats of locked Bitcoin each → ruinous.
  • Throwaway bot accounts. Candidates need real on-chain history.

What it doesn't solve

  • A single determined attacker with real capital and time.
  • Collusion between real users pooling capital.
  • Front-running: candidates locking sats right before snapshot.

Mitigate front-running

The best mitigation is snapshotting in the past. Instead of "right now", require proofs that reference a block height from 30+ days ago. Two ways:

  1. min_days requirement. If min_days = 90, the candidate must have held the bonded UTXO for at least 90 days as of "now". Dramatically raises the cost to farm.
  2. Past block-height floor. Read the protocol spec's verification algorithm — verifiers can be instructed to compute days_unspent against a specific block height rather than current time.

Also consider:

  • Publishing the thresholds before the snapshot. Sybil farmers need time to accumulate; telegraphing the rules prevents last-minute farming.
  • Capping per-address allocation. Even if a legit address passes, don't give any single address an outsized share.

Rate limits

Free /api/check tier: 60 req/min/IP → 3,600 candidates/hour. For bigger drops:

  • Self-host the verifier (the entire stack is open-source).
  • Contact us for a higher-tier hosted key.
  • Run the CLI with --concurrency 8 and a long timeline.

Further