Skip to content

Neverland-Money/neverland-tide-draw

Repository files navigation

Neverland Tide Draw

CLI tooling to fetch leaderboard data and select Tide winners using a bracketed, weighted random process. It is designed to be auditable and reproducible: a published seed plus the saved leaderboard file must allow anyone to re-run the selection and get identical winners.

Purpose

  • Provide a transparent, deterministic methodology for selecting Tide winners.
  • Keep the selection logic separate from the indexer, so results can be verified independently.
  • Produce machine-readable outputs for publication and analysis.

How It Works (Methodology)

  1. Fetch and rank leaderboard entries for an epoch:
    • Pulls all entries from the indexer in batches.
    • Sorts by totalPointsWithMultiplier (descending), with a stable tie-breaker by address.
    • Writes tides/{epoch}/leaderboard.json, including both display points and raw 18-decimal values.
  2. Build the eligible pool:
    • Reads the saved leaderboard file.
    • Excludes blacklisted addresses (optional input file).
    • Excludes entries with zero Pearls.
    • Uses 18-decimal raw totals for selection weights when available.
  3. Split into rank brackets:
    • Ranks 1–100: 50 winners
    • Ranks 101–200: 25 winners
    • Ranks 201–300: 15 winners
    • Ranks 301+: 10 winners
  4. Run weighted random draws per bracket (no replacement):
    • For each winner slot, draw one winner.
    • A wallet's chance in a draw is: Pearls / Total Remaining Pearls in that bracket
    • After a wallet wins, it is removed from that bracket for subsequent draws.
  5. Write results:
    • Outputs tides/{epochId}/winners.json including the seed and per-draw probability for each winner.

Reproducibility

  • If you run pick-winners with --seed <hex>, the draw is fully deterministic.
  • If you do not pass a seed, one is generated and stored in the output file.
  • Publish both the seed and the exact tides/{epoch}/leaderboard.json used for selection so anyone can reproduce the results.

Eligibility Rules

  • Only addresses with non-zero Pearls are eligible.
  • Blacklisted addresses can be excluded via a supplied blacklist file.
  • Eligibility is evaluated at the time of selection using the saved leaderboard file.

Inputs and Outputs

Leaderboard file (tides/{epoch}/leaderboard.json)

Written by fetch-leaderboard.

  • Includes ranks and display points with 2 decimals.
  • Also preserves raw 18-decimal values for accurate weighting.

Example fields:

{
  "totalPointsWithMultiplier": "21010489.03",
  "totalPointsWithMultiplierRaw": "21010489030000000000000000"
}

Winners file (tides/{epochId}/winners.json)

Written by pick-winners.

{
  "epochId": 1,
  "timestamp": "2026-02-01T11:51:00.000Z",
  "seed": "random-seed-hex",
  "totalParticipants": 500,
  "totalWinners": 100,
  "winners": [
    {
      "address": "0x...",
      "rank": 5,
      "pearls": "1234567890123456789012",
      "bracket": "Ranks 1-100",
      "probability": 5.234
    }
  ]
}

Winners text file (tides/{epochId}/winners.txt)

One wallet address per line for non-technical sharing.

Report file (tides/{epochId}/report.json)

Written by export-report.

  • Summarizes participants, total Pearls, and winners per bracket.

Report markdown (tides/{epochId}/report.md)

GitHub-friendly report with summary, bracket breakdown, and winner table.

Usage

Setup

  1. Create .env:
cp .env.example .env
  1. Configure Hasura credentials:
INDEXER_ENDPOINT=https://index.neverland.money/v1/graphql
HASURA_ADMIN_SECRET=your-actual-admin-secret

If you run the indexer locally, you don't need to set up Hasura credentials, as the indexer will use the local Hasura instance. See neverland-hyperindex/README.md for more details.

  1. Install dependencies:
pnpm install

Fetch Leaderboard

pnpm fetch-leaderboard <epoch> [--blacklist <path>]

Blacklist input can be provided via --blacklist or BLACKLIST_PATH and supports:

  • JSON array: ["0x...", "0x..."]
  • JSON object: { "addresses": ["0x..."] }
  • Newline-delimited addresses

Pick Winners

pnpm pick-winners <epochId> [--seed <hex>] [--blacklist <path>]

Reproducible run with a published seed:

pnpm pick-winners 1 --seed <seed-hex>

Export Report

pnpm export-report <epochId>

One-Command Tide Run

Generate leaderboard, pick winners, and export reports in one step:

pnpm run-tide <epochId> [--seed <hex>] [--blacklist <path>]

Generate Safe Transaction Batch

Create a Safe transaction batch JSON for permanent lock rewards:

pnpm generate-safe-batch <epochId> [--contract <address>] [--amount <dust>] [--safe <address>] [--chain <id>] [--batch-size <n>]

Options:

  • --contract: Voting escrow contract address (default: from env or 0xBB4738D05AD1b3Da57a4881baE62Ce9bb1eEeD6C)
  • --amount: DUST amount (default: from env or 100), automatically converted to wei (×10¹⁸)
  • --safe: Safe multisig address (default: from env or 0xb83a6637c87E6a7192b3ADA845c0745F815e9006)
  • --chain: Chain ID (default: from env or 143)
  • --batch-size: Split winners into multiple batches of this size (optional, e.g., 50 for block gas limit constraints)

Single batch (default): Generates tides/{epochId}/safe-batch.json

Multiple batches:

pnpm generate-safe-batch 1 --batch-size 50

Generates safe-batch-1.json, safe-batch-2.json, etc. Execute sequentially in the Safe Transaction Builder.

Configuration

Edit src/config.ts to change:

  • Bracket ranges and winner counts
  • Pearls decimals
  • Hasura endpoint and admin secret

Testing and Coverage

The core selection logic has deterministic unit tests.

pnpm test
pnpm test:coverage

Coverage is scoped to the core algorithm modules:

  • src/blacklist.ts
  • src/random.ts
  • src/selection.ts

Notes

  • Pearls are stored with 18-decimal precision (like ETH wei).
  • Probabilities are per draw, not guarantees.
  • Selection is fair by process, not by outcome; winners are random but weighted.

License

This project is licensed under the MIT License - a permissive open-source license that allows you to:

  • Use the code commercially or privately
  • Modify and distribute the code
  • Sublicense the code
  • Use the code without warranty

The only requirement is that you include the original copyright notice and license text in any substantial portions of the software.

See the LICENSE file for the full license text.

About

Provides a transparent, deterministic methodology for selecting Tide winners.

Resources

License

Stars

Watchers

Forks

Contributors