Getting StartedQuick Start

Quick Start

Get Veil up and running in 5 minutes.

Prerequisites

  • Node.js 18+ and yarn / npm / pnpm / bun
  • Solana CLI installed
  • Wallet with SOL for transaction fees
  • Basic familiarity with Solana and TypeScript

Installation

Install the Veil SDK:

npm install @veil-dev/sdk

Setup

import { Connection, Keypair, PublicKey } from "@solana/web3.js";
import { Wallet, BN } from "@coral-xyz/anchor";
import { VeilClient, getSchedulePda, getVaultPda } from "@veil-dev/sdk";
 
const connection = new Connection("https://api.devnet.solana.com");
const keypair = Keypair.fromSecretKey(/* your secret key */);
const wallet = new Wallet(keypair);
const client = new VeilClient({ connection, wallet });
 
const USDC_MINT = new PublicKey("4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU");

Step 1: Create a Vault

A vault holds tokens for your payment schedules. Each employer can create one vault per token mint.

const signature = await client.initVault(USDC_MINT);
console.log("Vault created:", signature);

Step 2: Deposit Tokens

const amount = new BN(1_000_000); // 1 USDC (6 decimals)
 
const signature = await client.deposit(amount, USDC_MINT);
console.log("Deposited:", signature);

Step 3: Create a Payment Schedule

Individual recipient addresses and per-recipient amounts are not stored on-chain. Veil stores the Merkle root plus the schedule totals and timing metadata.

const recipients = [
  { address: new PublicKey("recipient1..."), amount: 100_000n },
  { address: new PublicKey("recipient2..."), amount: 200_000n },
  { address: new PublicKey("recipient3..."), amount: 200_000n },
];
 
const { signature, scheduleId, merkleRoot } =
  await client.createScheduleFromRecipients({
    tokenMint: USDC_MINT,
    recipients,
    intervalSecs: 86400, // Daily (24 hours)
    reservedAmount: new BN(10_000_000), // Total reserved: 10 USDC
    perExecutionAmount: new BN(500_000), // Per cycle: 0.5 USDC
  });
 
console.log("Schedule created:", signature);
console.log("Schedule ID:", scheduleId);
console.log("Merkle Root:", merkleRoot);
 
const [vaultPda] = getVaultPda(wallet.publicKey, USDC_MINT);
const [schedulePda] = getSchedulePda(vaultPda, scheduleId);

Step 4: Register with the Coordinator

Register the schedule with a coordinator so it can store recipient proofs and drive automated execution.

const response = await fetch("https://your-coordinator-domain.com/api/schedules", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    schedulePda: schedulePda.toString(),
    scheduleId: Array.from(scheduleId),
    vaultEmployer: wallet.publicKey.toString(),
    tokenMint: USDC_MINT.toString(),
    recipients: recipients.map((recipient) => ({
      address: recipient.address.toString(),
      amount: recipient.amount.toString(),
    })),
  }),
});
 
const data = await response.json();
console.log(data);

If you retry the exact same registration payload, the coordinator responds successfully with alreadyRegistered: true.

Dashboard Alternative

The employer dashboard supports the same core flow without wiring the SDK first:

  • create vaults by allowed mint
  • deposit and withdraw balances
  • import recipients from CSV or Excel
  • save local schedule templates per wallet
  • inspect coordinator execution history

What’s Next?