GuidesPayroll Example

Payroll Example

Example: Setting up private payroll payments for employees.

Use Case

A company wants to pay employees weekly without exposing:

  • Who gets paid
  • Individual salaries
  • Total payroll amount

Setup

import { VeilClient } from "@veil-dev/sdk";
import { PublicKey } from "@solana/web3.js";
import { BN } from "@coral-xyz/anchor";
 
const client = new VeilClient({ connection, wallet });
const USDC = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");

Step 1: Initialize Payroll Vault

// Create vault for payroll
await client.initVault(USDC);
 
// Deposit monthly payroll budget
const monthlyBudget = new BN(100_000_000); // 100 USDC
await client.deposit(monthlyBudget, USDC);

Step 2: Define Employee Recipients

const employees = [
  {
    name: "Alice",
    address: new PublicKey("AliceAddress..."),
    salary: 2_000_000n, // 2 USDC per week
  },
  {
    name: "Bob",
    address: new PublicKey("BobAddress..."),
    salary: 1_500_000n, // 1.5 USDC per week
  },
  {
    name: "Charlie",
    address: new PublicKey("CharlieAddress..."),
    salary: 1_800_000n, // 1.8 USDC per week
  },
];
 
const recipients = employees.map((e) => ({
  address: e.address,
  amount: e.salary,
}));

Step 3: Create Weekly Payroll Schedule

// Weekly payroll (7 days)
const weeklyInterval = 7 * 24 * 60 * 60; // 604800 seconds
 
// Reserve for 4 weeks
const weeksToReserve = 4;
const totalWeeklyPayroll = recipients.reduce(
  (sum, r) => sum + r.amount,
  0n
);
const reservedAmount = new BN(Number(totalWeeklyPayroll) * weeksToReserve);
 
const { scheduleId } = await client.createScheduleFromRecipients({
  recipients,
  intervalSecs: weeklyInterval,
  reservedAmount,
  perExecutionAmount: new BN(Number(totalWeeklyPayroll)),
});

Step 4: Monitor Execution

import { getVaultPda, getSchedulePda } from "@veil-dev/sdk";
 
const [vaultPda] = getVaultPda(wallet.publicKey);
const [schedulePda] = getSchedulePda(vaultPda, scheduleId);
 
// Check schedule status
const schedule = await client.getSchedule(schedulePda);
console.log("Next payment:", new Date(schedule.nextExecution.toNumber() * 1000));
console.log("Batches executed:", schedule.lastExecutedBatch.toString());

Step 5: Add New Employee

To add a new employee, create a new schedule with updated recipients:

const updatedRecipients = [
  ...recipients,
  { address: newPublicKey("NewEmployee..."), amount: 1_200_000n },
];
 
// Create new schedule with updated list
const { scheduleId: newScheduleId } = await client.createScheduleFromRecipients({
  recipients: updatedRecipients,
  intervalSecs: weeklyInterval,
  reservedAmount: new BN(Number(totalWeeklyPayroll) * 4),
  perExecutionAmount: new BN(Number(totalWeeklyPayroll)),
});

Privacy Benefits

What’s Public:

  • Vault address
  • Schedule PDA
  • Merkle root (32 bytes)
  • Total recipients count (3)
  • Execution interval

What’s Private:

  • Individual employee addresses
  • Individual salaries
  • Total payroll amount
  • Employee order/index

Complete Example

async function setupPayroll() {
  // Setup
  const client = new VeilClient({ connection, wallet });
  const USDC = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
 
  // 1. Create vault
  await client.initVault(USDC);
  await client.deposit(new BN(100_000_000), USDC);
 
  // 2. Define employees
  const employees = [
    { address: new PublicKey("..."), amount: 2_000_000n },
    { address: new PublicKey("..."), amount: 1_500_000n },
  ];
 
  // 3. Create weekly schedule
  const weeklyPayroll = employees.reduce((sum, e) => sum + e.amount, 0n);
  const { scheduleId } = await client.createScheduleFromRecipients({
    recipients: employees,
    intervalSecs: 604800, // Weekly
    reservedAmount: new BN(Number(weeklyPayroll) * 4), // 4 weeks
    perExecutionAmount: new BN(Number(weeklyPayroll)),
  });
 
  console.log("Payroll schedule created:", scheduleId);
}
 
setupPayroll();