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_satsof 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:
min_daysrequirement. Ifmin_days = 90, the candidate must have held the bonded UTXO for at least 90 days as of "now". Dramatically raises the cost to farm.- Past block-height floor. Read the protocol spec's verification algorithm — verifiers can be instructed to compute
days_unspentagainst 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 8and a long timeline.