Skip to content

Instantly share code, notes, and snippets.

@patcito
Last active January 16, 2026 14:10
Show Gist options
  • Select an option

  • Save patcito/06a54d578e81476d67cf0b237edde5d6 to your computer and use it in GitHub Desktop.

Select an option

Save patcito/06a54d578e81476d67cf0b237edde5d6 to your computer and use it in GitHub Desktop.
Infra Setup Guide: Investor Wave Import Service

Investor Wave Import - Infrastructure Setup Guide

This guide explains how to set up the import_wave service in your Docker Compose configuration.

Overview

The investor wave system imports whitelisted investors from a CSV file and generates merkle proofs for on-chain verification. The import runs as a one-time job during deployments, after database migrations.

compose.production.yaml Configuration

Add the following service to your compose.production.yaml:

import_wave:
  image: ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/flying-tulip/ft-api:${IMAGE_TAG}
  command: ["/bin/import-wave"]
  env_file:
    - .env.prod
  environment:
    # Optional: Override defaults
    # INVESTOR_CSV_PATH: /assets/whitelist/investors.csv  # Default path
    # INVESTOR_CHAIN_IDS: 1                               # Default: Ethereum (1)
  depends_on:
    - postgres
  networks:
    - backend

Deploy Workflow

The GitHub Actions workflow already includes the import step:

migrate → import_wave → up -d

This sequence ensures:

  1. Database migrations run first (creates tables)
  2. Investor wave import runs (loads CSV, creates merkle tree)
  3. API starts with wave data already loaded

Environment Variables

Variable Default Description
INVESTOR_CSV_PATH /assets/whitelist/investors.csv Path to the investor CSV file
INVESTOR_CHAIN_IDS 1 Comma-separated chain IDs to import for

The CSV file is baked into the Docker image at /assets/whitelist/investors.csv. To use a different file, mount a volume or set INVESTOR_CSV_PATH.

Behavior

  • Idempotent: If the CSV hasn't changed (same SHA256 hash), no reimport occurs
  • Versioned: Each new CSV creates a new "wave" with its own merkle root
  • Archives: Previous waves are marked as archived with timestamp
  • Graceful: If CSV file doesn't exist, exits successfully (no error)

Logs

On successful import, you'll see:

level=INFO msg="Starting investor wave import" csvPath=/assets/whitelist/investors.csv chainIds=[1]
level=INFO msg="Parsed investor CSV" path=/assets/whitelist/investors.csv chainId=1 entries=100 hash=abc123...
level=INFO msg="Created new wave" waveId=uuid waveNumber=1 merkleRoot=0x...
level=INFO msg="Wave import complete" chainId=1 waveId=uuid waveNumber=1 merkleRoot=0x... entryCount=100 isCurrent=true
level=INFO msg="All wave imports completed successfully"

If the CSV hasn't changed:

level=INFO msg="Wave with this CSV hash already exists" waveId=uuid waveNumber=1 isCurrent=true

Troubleshooting

  1. "pg not initialized": Database connection failed. Check POSTGRES_URL in env.
  2. "failed to parse CSV": Invalid CSV format. Check file has format: wallet,token,amount
  3. "No investor CSV file found, skipping import": File not found at path. Check mount/path.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment