Status: active side project / portfolio work — runs on Solana devnet. Not deployed to mainnet; not audited. Source-available under BUSL-1.1 (see License).
Stokkie digitizes South African stokvels as a Social Yield Protocol on Solana. Groups contribute stablecoins (USDC/PYUSD) to a PDA vault, earn yield between rotations, and receive automated monthly payouts with transparent fees.
Built with Anchor (Rust) + a Next.js App Router frontend. The repo demonstrates an end-to-end Solana program: PDA-based vaults, rotation/payout logic, async on-chain governance, embedded-wallet onboarding (Privy), and a ZAR on/off-ramp design for a "crypto-invisible" UX.
- PDA-based group vaults and config (Anchor 0.30+).
- Stablecoin-first flows (6 decimals),
u64on-chain math. - Rotation payouts with a 0.5% platform fee to treasury.
- Optional yield adapter hooks (Kamino/Jito).
- PDA-based proposals with async member voting.
- Mobile-first Next.js App Router frontend.
- Constitution PDF generator aligned with NASASA guidance.
- 90/10 capital preservation ("Permanent Pot") with endowment growth.
- Dynamic payouts: on-time score priority, emergency swaps, or bidding.
- Weekly/fortnightly cycles + milestone payouts.
- Multi-asset staking portfolio with auto-rebalancing.
- Social insurance add-on (burial/hospital cash).
- Plugin monetization tiers: Free (standard), Pro (bidding/swaps), Elite (endowment + multi-asset).
- Price oracles: Pyth for SOL/USDC (and other pairs) to ensure fair value.
- Emergency pause: pause/unpause instruction for protocol incidents.
- Slippage protection: min-out checks on yield withdrawals using BPS limits.
For a fully "crypto-invisible" UX, integrate South African payment rails:
- Stitch — ZAR bank transfers via their Pay API. User sees "Add R500", backend converts to USDC.
- VALR Pay — Instant ZAR to USDC conversion via VALR's merchant API.
- Luno — USDC withdrawal to ZAR bank account.
- VALR — Similar off-ramp capability.
- User clicks "Add Funds" → Opens Stitch/VALR payment modal
- User pays with EFT/card in ZAR
- Backend receives webhook → Mints/transfers USDC to user's embedded wallet
- User sees "R500 added" without knowing it's now USDC on Solana
- Use Privy embedded wallets so users never see wallet addresses
- Store user's bank account preferences for quick off-ramp
- Show ZAR values everywhere, convert to USDC only for on-chain operations
sequenceDiagram
participant Member
participant WebApp
participant StokkieProgram
participant VaultPDA
participant YieldAdapter
participant TreasuryPDA
Member->>WebApp: SMS/Email auth (Privy)
WebApp->>StokkieProgram: InitializeStokkie
Member->>StokkieProgram: DepositContribution
StokkieProgram->>VaultPDA: Transfer USDC/PYUSD
StokkieProgram->>YieldAdapter: Deposit/Withdraw yield
StokkieProgram->>TreasuryPDA: PlatformFee (0.5%)
StokkieProgram->>Member: Rotation Payout
programs/stokkie/— Anchor program (accounts + instructions).tests/— Anchor unit tests (rotation cycle, fees, late payments).tests/integration/— BDD/Cucumber-style integration tests.web/— Next.js App Router frontend + PDF generator + webhook route.web/lib/— Anchor client hooks and utilities.
/— Landing page./signup— SMS onboarding (Privy)./create— Stokkie creation wizard (auth-gated)./invite— Platform + group invite links./dashboard— Post-login dashboard./constitution— Group selector (auth-gated)./constitution/[stokvelId]— Prefilled constitution builder.
First-time setup — generate the local validator keypair (kept out of git):
mkdir -p keypairs && solana-keygen new --no-bip39-passphrase -o keypairs/localnet.jsonThen run everything with one command:
npm run devThis starts:
solana-test-validator(local blockchain)- Deploys the Stokkie program
- Starts the Next.js frontend at http://localhost:3000
Terminal 1 - Start validator:
solana-test-validator --resetTerminal 2 - Build and deploy:
anchor build
anchor deployTerminal 3 - Start frontend:
cd web
cp env.local.example .env.local # Configure environment
npm install
npm run dev# Ensure you have SOL on devnet
solana airdrop 2 --url devnet
# Deploy
npm run deploy:devnet
# Update web/.env.local with devnet RPC
# NEXT_PUBLIC_SOLANA_RPC_URL=https://api.devnet.solana.comnpm run test:allnpm run test
# or: anchor testThe tests/integration/ folder contains Cucumber-style tests using Given/When/Then format:
npm run test:integration
# or: anchor test -- --grep "Feature:"npm run test:web
# or: cd web && npm run test:integrationcd web
npm install
npm run devnpm install
npm run dev- RPC/webhooks: use Helius in production.
- Stablecoins: USDC/PYUSD with 6 decimals.
- Privy auth: set
NEXT_PUBLIC_PRIVY_APP_IDinweb/.env.local. - Solana RPC: set
NEXT_PUBLIC_SOLANA_RPC_URL(defaults to devnet). - Local validator wallet:
keypairs/localnet.json(configured inAnchor.toml). This file is gitignored — generate your own (see Quick Start). Never commit keypairs.
The frontend uses Solana Wallet Adapter for wallet connection:
- Connect via Phantom or other Solana wallets.
- Create Stokkie groups on-chain from the
/createwizard. - View and manage groups from the dashboard.
Key client files:
web/lib/anchor.ts— Program client setup and PDA derivation.web/lib/useStokkie.ts— React hook for program interactions.
Stokkie is designed as non-custodial software. Funds are controlled by the program and group rules, not the platform. Groups should remain under 100 members and follow NASASA-aligned constitutions.
Source-available under the Business Source License 1.1 (BUSL-1.1) — see
LICENSE.
- ✅ Read, copy, modify, and use for non-production purposes (study, dev, testing).
- ❌ No production or commercial use before the Change Date without a commercial license from the author.
- 🔓 On 2030-06-09 (the Change Date), it automatically converts to Apache-2.0.
For commercial licensing before then, contact the author.