Skip to content

solana-program/multi-delegator

Repository files navigation

Multi Delegator

Solana program and clients for managed token delegations on SPL Token and Token-2022.

SECURITY NOTICE: This program has not been audited. Use at your own risk. Not recommended for production use with real funds without a thorough security review.

Overview

For each (user, mint) pair, the program creates a Multi Delegate Authority (MDA) PDA and sets it as the single delegate on the user's token account with u64::MAX approval. The MDA can only transfer tokens when a Delegation PDA authorizes it, making the system as secure as traditional approval-based delegations while enabling multiple simultaneous delegations from a single token account.

This works for both token programs: SPL Token and Token-2022.

Supported delegation models:

  • Fixed delegation: authorize a delegatee to spend up to a total amount with an optional expiry timestamp.
  • Recurring delegation: authorize a delegatee to spend up to a per-period amount that resets each period, with configurable period length and overall expiry.
  • Subscription plan: a merchant publishes a plan with pricing terms; subscribers accept those terms and the merchant (or whitelisted pullers) can pull funds each billing period.

The program emits on-chain events via self-CPI for indexer integration (subscription created/cancelled, fixed/recurring/subscription transfers).

Token-2022 mints are supported, but the following extensions are rejected during MDA initialization: ConfidentialTransfer, NonTransferable, PermanentDelegate, TransferHook, TransferFee, MintCloseAuthority, and Pausable.

Delegation accounts include a version field and the program implements a three-tier migration framework (lazy in-place update, explicit migrate instruction, revoke/recreate) for future upgrades. See ADR-003 for details.

This repository contains:

  • A Rust Solana program built with Pinocchio
  • IDL generation via Codama
  • Generated clients via Codama:
    • TypeScript client (@multidelegator/client) in clients/typescript
    • Rust client (multidelegator-client) in clients/rust
  • A local demo webapp in webapp/
  • CI pipeline with build, test, lint, and CU benchmarking

Program ID

EPEUTog1kptYkthDJF6MuB1aM4aDAwHYwoF32Rzv5rqg

Project Structure

multi-delegator/
├── programs/multi_delegator/      # Rust Solana program
│   ├── src/
│   │   ├── instructions/          # Instruction handlers
│   │   │   └── helpers/           # Transfer validation, token helpers, traits
│   │   ├── state/                 # Account types (MDA, fixed, recurring, plan, subscription)
│   │   │   └── versioning/        # Version checks and migration logic
│   │   ├── events/                # On-chain event definitions
│   │   ├── event_engine.rs        # Self-CPI event emission
│   │   ├── errors.rs              # Error codes
│   │   ├── constants.rs           # Program constants
│   │   └── tests/                 # Rust unit tests (LiteSVM)
│   └── idl/                       # Generated IDL (multi_delegator.json)
├── clients/
│   ├── typescript/                # TypeScript SDK + integration tests
│   └── rust/                      # Rust generated client
├── webapp/                        # Demo UI (React) + local API server
│   ├── src/                       # React app (routes, components, hooks)
│   ├── api/                       # Node.js API server (faucet, deploy, config)
│   └── scripts/                   # Environment init, mock USDC minting
├── scripts/                       # Shell scripts (validator, webapp launcher)
├── docs/                          # Architecture Decision Records
├── runbooks/                      # Surfpool deployment runbooks
├── .github/                       # CI workflows and shared setup action
├── .githooks/                     # Git hooks (pre-push: fmt + lint checks)
├── patches/                       # pnpm patch overrides
├── keys/                          # Program keypair (gitignored)
├── justfile                       # Build/test/dev task runner
├── codama.js                      # Codama client generation config
├── codama-visitors.mjs            # Codama visitors (event authority PDA, defaults)
└── txtx.yml                       # Surfpool runbook config

Quick Start

git clone git@github.com:solana-program/multi-delegator.git
cd multi-delegator
just setup
just build
just test-program

For the full suite (program + client tests):

just test

Prerequisites

just setup checks for these tools: pnpm, cargo, solana-keygen, and surfpool.

Install the toolchain:

  1. Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  1. Solana CLI (includes solana-keygen)
sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"
  1. pnpm
curl -fsSL https://get.pnpm.io/install.sh | sh -
  1. Just
curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to ~/.local/bin
  1. Surfpool CLI
curl -sL https://run.surfpool.run/ | bash
  1. Node.js (required by webapp/ scripts)

Keypair and Program ID

Local workflows use keys/multi_delegator-keypair.json as the source keypair. The just build and just build-program recipes copy it to target/deploy/ and verify that the keypair matches the declare_id! in lib.rs.

The keypair is checked into the repository. If it is missing, prepare-deploy-keys will error and prompt you to restore it:

git show <commit>^:keys/multi_delegator-keypair.json > keys/multi_delegator-keypair.json

Print the program ID at any time:

just program-id

Build and Test

The justfile is the main entrypoint for day-to-day development.

Build

Recipe Description
just build Build program + generate IDL + generate clients + build TypeScript client
just build-program Compile the SBF program (.so)
just generate-idl Regenerate programs/multi_delegator/idl/multi_delegator.json
just generate-client Regenerate TypeScript and Rust clients from IDL via Codama
just build-client Build clients/typescript into clients/typescript/dist

Test

Recipe Description
just test Run program tests + client integration tests
just test-program Run Rust SBF tests (cargo test-sbf with LiteSVM)
just test-client Run TypeScript integration tests (vitest with Surfpool)
just test-and-benchmark Run tests and generate cu_report.md with compute unit usage

Code Quality

Recipe Description
just check Run fmt-check + lint-check
just fmt-check Check Rust and TypeScript formatting
just fmt Auto-format Rust and TypeScript
just lint-check Check Rust (clippy) and TypeScript (biome) linting
just lint Lint with auto-fix

Cleanup

Recipe Description
just clean Remove all build artifacts, node_modules, validator state
just webapp-clean Stop webapp processes, remove webapp-specific generated state
just kill-validator Stop all running validators (surfpool + solana-test-validator)

Validator Modes

Two local validator flows are available:

  • just test-client starts a Surfpool validator automatically via ensure-surfpool. The program is deployed from target/deploy/ using Surfpool's built-in deployment.
  • just webapp-run starts solana-test-validator via scripts/start-webapp.sh, then deploys the program and initializes the test environment.

Both default to http://localhost:8899.

TypeScript Client SDK

The @multidelegator/client package in clients/typescript provides a high-level MultiDelegatorClient class wrapping all program instructions:

Method Purpose
initMultiDelegate / closeMultiDelegate Create or close the MDA for a (user, mint) pair
createFixedDelegation / transferFixed Create a fixed delegation and execute transfers against it
createRecurringDelegation / transferRecurring Create a recurring delegation and execute transfers against it
createPlan / updatePlan / deletePlan Manage merchant subscription plans
subscribe / cancelSubscription / transferSubscription Subscribe to plans, cancel, and pull payments
revokeDelegation Close any delegation PDA and return rent to the original payer
getDelegationsForWallet / getPlansForOwner Query on-chain accounts
isMultiDelegateInitialized Check if an MDA exists for a wallet/mint pair

PDA derivation helpers are exported from pdas.ts: getMultiDelegatePDA, getDelegationPDA, getPlanPDA, getSubscriptionPDA, getEventAuthorityPDA.

Install and use:

pnpm add @multidelegator/client
import { MultiDelegatorClient } from '@multidelegator/client';

Webapp Demo

The demo app in webapp/ provides a local UI and API for development flows.

Tech stack: React 19, Vite, Tailwind CSS, Radix UI, TanStack Query, Jotai, Solana Kit, Wallet UI.

just build          # build program + clients
just webapp-run     # start validator + init + API + web UI

Expected local endpoints:

  • Validator RPC: http://localhost:8899
  • API server: http://localhost:3001
  • Web UI: http://localhost:5173

Features

Route Feature
/setup Setup wizard (validator, program deploy, mock USDC)
/ Dashboard overview
/delegations Create and manage fixed/recurring delegations
/plans Create and manage merchant subscription plans
/plans/collect Collect subscription payments
/subscriptions View and manage active subscriptions
/marketplace Browse available plans
/faucet SOL and USDC airdrops (localnet/devnet)
/program Program deploy/upgrade status

Stop local processes:

just kill-validator
just webapp-clean     # also removes generated state

CI Pipeline

The GitHub Actions workflow (.github/workflows/ci.yml) runs on PRs and pushes to main:

Job Description
build Build program + client, upload artifacts
unit-test just test-program (Rust SBF tests)
lint just check (formatting + clippy + biome)
integration-test Start Surfpool, run TypeScript integration tests
benchmark (PRs only) Generate CU report and post as PR comment

Architecture Docs

Document Description
ADR-001 Core program architecture: MDA, fixed/recurring delegations, PDA design
ADR-002 Subscription plans: merchant plans, subscriber flow, pull payments
ADR-003 Versioning and migration: three-tier fallback chain for on-chain account upgrades

Smart Wallet Support

The TypeScript client integration tests cover smart wallet flows with Squads (multisig) and Swig wallets, verifying that delegations work when the delegator or delegatee is a program-controlled authority.

About

Solana program for third party assets delegations

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors