Skip to content

paltalabs/defindex-distributor

Repository files navigation

DeFindex Distributor

Smart contract + CLI to distribute dfTokens (DeFindex Vault Tokens) to users in a transparent and secure way.

The Distributor enables fund distribution in campaigns or events for DeFindex users: it deposits assets into a vault and distributes the resulting dfTokens to recipients from a CSV that contains asset, vault, user and amount; as if each user had deposited directly. The smart contract ensures that each user receives the corresponding amount of dfTokens verifiably on-chain.

How it works

  1. The script reads a CSV with recipients and amounts per vault
  2. Groups by vault and splits into batches (to respect Soroban's instruction limit)
  3. For each batch, calls the distribute contract which in a single transaction:
    • Caller sends the total underlying amount to the distributor contract
    • Distributor deposits the total amount in the vault and receives minted dfTokens
    • Distributes dfTokens pro-rata to each recipient
  4. Verifies balances before/after and generates incremental CSV + log files with the results

Prerequisites

Key Management

Secret keys are stored in the OS keychain (macOS Keychain, Linux Secret Service, Windows Credential Manager) — never in plaintext on disk.

pnpm setup-keys [testnet|mainnet]   # store key (prompts for secret key, seed phrase, or generates one)
pnpm setup-keys --show              # print stored public key
pnpm setup-keys --delete            # remove from keychain

Fallback: if no keychain entry is found, the scripts fall back to STELLAR_SECRET_KEY_TESTNET / STELLAR_SECRET_KEY_MAINNET in .env (useful for CI).

Mainnet Usage

1. Setup

pnpm i
pnpm setup-keys mainnet

For CI or environments without a keychain, copy .env.example and set the key there instead:

cp .env.example .env
STELLAR_NETWORK=mainnet
STELLAR_SECRET_KEY_MAINNET=S...
SOROBAN_RPC_MAINNET=https://soroban-rpc.mainnet.stellar.gateway.fm
HORIZON_RPC_MAINNET=https://horizon.stellar.org

2. Prepare the CSV

The CSV must have the columns: asset, vault, user, amount (order doesn't matter, parsed by header name).

  • asset: vault's underlying asset address (token to deposit)
  • vault: DeFindex vault address
  • user: recipient address
  • amount: amount in the asset's minimum unit (stroops, 7 decimals)
asset,vault,user,amount
CCZGLAUBDKJSQK72QOZHVU7CUWKW45OZWYWCLL27AEK74U2OIBK6LXF2,CDHZFQZWSU7GSHUBWFEL2FJ7R2RNVHI3RPY5QMCQ3MGJXOSHSTSW5PE7,GCGI4UWY3JDN2NH4L33Y7GHOGFTV3WTGAPPCQONZJOPOL5BSSCVS6UQI,7952002150
CCZGLAUBDKJSQK72QOZHVU7CUWKW45OZWYWCLL27AEK74U2OIBK6LXF2,CDHZFQZWSU7GSHUBWFEL2FJ7R2RNVHI3RPY5QMCQ3MGJXOSHSTSW5PE7,GCUJW46S35TBIOS2R42LLK4W3O2HRHMQBXGLNSTVTUYCZWN5BML3H7XI,4303465857

3. Run the distribution

STELLAR_NETWORK=mainnet pnpm distribute path/to/file.csv

Add --xdr to print the unsigned and signed XDR of each transaction (useful for debugging).

The script will:

  • Show the status of each batch and vault
  • Compare balances before/after for each user
  • Write incremental logs to output/distributor/distributor_<timestamp>.csv and .log

Testnet Usage

To test on testnet, run the demo script that creates test vaults and users.

1. Setup for testnet

pnpm i
pnpm setup-keys testnet

If you prefer .env, copy the example — it comes configured for testnet by default:

cp .env.example .env

2. Run the demo

pnpm demo

This will:

  • Fund the manager account via Friendbot
  • Mint Blend USDC tokens via ephemeral accounts
  • Fetch blend strategy addresses from the DeFindex repo
  • Create 2 vaults (USDC + XLM) with blend strategies via the DeFindex API
  • Create a random number of users per vault (between 5 and 20)
  • Generate a test CSV at output/demo/demo_testnet_<timestamp>.csv
  • Auto-run mint if additional tokens are needed (XLM via Friendbot, Blend tokens via ephemeral accounts)

3. Distribute

pnpm distribute output/demo/demo_testnet_<timestamp>.csv

Add --xdr to print the unsigned and signed XDR of each transaction (useful for debugging).

Environment Variables

All environment variables are suffixed by network (_TESTNET or _MAINNET). The STELLAR_NETWORK variable determines which suffix is used.

STELLAR_NETWORK=testnet              # "testnet" or "mainnet"

# Secret keys are loaded from the OS keychain (pnpm setup-keys).
# These env vars are only needed as a fallback (e.g. CI environments).
STELLAR_SECRET_KEY_TESTNET=          # optional fallback
STELLAR_SECRET_KEY_MAINNET=          # optional fallback

SOROBAN_RPC_TESTNET=https://soroban-testnet.stellar.org
HORIZON_RPC_TESTNET=https://horizon-testnet.stellar.org

SOROBAN_RPC_MAINNET=
HORIZON_RPC_MAINNET=

DEFINDEX_API_KEY=                    # Optional: DeFindex API key for demo vault creation
MINT_BLEND_TOKENS_URL=               # Optional: Blend faucet URL for demo token minting

Deploying the Distributor contract

Deploying from GitHub Release (verified on Stellar Expert)

Deploys the wasm built by the CI release workflow, so Stellar Expert can verify and link the source code automatically.

Prerequisites: gh CLI authenticated (gh auth login), stellar CLI.

./scripts/deploy.sh <network> <stellar-identity> [release-tag]

Examples:

./scripts/deploy.sh testnet user
./scripts/deploy.sh testnet user main_defindex-distributor_pkg0.0.1_cli22.8.1

After deploying, update the contract address in src/addresses.ts manually.

Deploying from local build (development)

make test
make build # build and optimize
stellar keys generate alice --network testnet --fund
stellar contract deploy \
  --wasm target/wasm32v1-none/release/defindex_distributor.wasm \
  --source-account alice \
  --network testnet \
  --alias defindex-distributor

The Contract ID will be stored at ~/.config/stellar/contract-ids/defindex-distributor.json

Optional: replace the address in src/addresses.ts

NEW_ADDR=$(cat ~/.config/stellar/contract-ids/defindex-distributor.json | python3 -c "import sys,json; print(json.load(sys.stdin)['ids']['Test SDF Network ; September 2015'])") && \
sed -i "s/export const DISTRIBUTOR_TESTNET = \".*\"/export const DISTRIBUTOR_TESTNET = \"$NEW_ADDR\"/" src/addresses.ts

Project structure

src/
├── utils.ts          # Network config, env helpers, Stellar SDK helpers
├── addresses.ts      # Contract addresses and API URLs
├── keychain.ts       # OS keychain wrapper (macOS/Linux/Windows)
├── setup-keys.ts     # One-time CLI to store keys in the keychain
├── distribute.ts     # Main script: deposit + distribute via contract
├── demo.ts           # Testnet demo: create vaults via DeFindex API, generate CSV
├── mint.ts           # Mint testnet tokens (Blend faucet, Soroswap, Friendbot)
└── logger.ts         # Incremental CSV + log file writer

contracts/
└── defindex-distributor/  # Soroban smart contract (Rust)

output/                    # Script outputs (gitignored)
├── demo/                  # demo_testnet_*.csv
└── distributor/           # distributor_*.csv + distributor_*.log

Scripts

Command Description
pnpm setup-keys [network] Store your Stellar key in the OS keychain (run once)
pnpm demo Create testnet vaults with blend strategies, generate test CSV
pnpm mint <csv> Mint testnet tokens (Soroswap faucet + XLM via Friendbot)
pnpm distribute <csv> Distribute dfTokens to users with incremental logging
./scripts/deploy.sh <network> <identity> Deploy contract from GitHub Release (Stellar Expert verified)

About

CLI + Soroban smart contract that batch-deposits campaign funds into a DeFindex vault and distributes the minted dfTokens to CSV-listed recipients, giving each user an on-chain verifiable “as-if-they-deposited” allocation.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors