Cross-border farm input financing on Stellar β diaspora families fund seeds, fertilizer, and equipment directly in their home country. No middlemen. No cash leakage. Repayment built in.
- The Problem
- How RemitRoot Works
- Architecture Overview
- Monorepo Structure
- Packages
- Tech Stack
- Getting Started
- Smart Contract Reference
- Money Flow
- Stellar Primitives Used
- Testing
- Deployment
- Contributing
- Roadmap
- License
Millions of migrants send remittances home every year, but the money rarely creates lasting economic mobility. Smallholder farmers in sub-Saharan Africa and Southeast Asia can't afford seeds or inputs at planting season. Microloans charge 30β60% annual interest. The sender has zero visibility into how money is used β and the farmer has no path to building credit.
RemitRoot turns a remittance into a micro-investment:
- The diaspora sender locks funds for a specific purpose (seed purchase, fertilizer, irrigation equipment)
- The farmer receives a tokenized voucher redeemable only at a verified agro-input vendor
- After harvest, repayment flows back automatically β no bank account required, just a phone
- Every transaction is auditable on Stellar's public ledger
[Sender in US/EU] β Lock USDC via Anchor β Soroban Escrow Contract
β
Mint Voucher Token (RVCH)
β
[Farmer scans QR at Agro Vendor] β Burn voucher, release goods
β
[Harvest season] β Farmer repays via M-Pesa / Mobile Money
β
Repayment streams back to Sender's Stellar account
For the sender: Connect wallet β choose a farmer profile β lock funds β track impact in real time.
For the farmer: Receive an SMS with a QR voucher β visit registered vendor β redeem for approved goods β repay after harvest via mobile money.
For the vendor: Scan the farmer's QR code β burn the voucher on-chain β receive USDC instantly.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β STELLAR NETWORK β
β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββββββ β
β β Stellar β β Path Payment β β Soroban Escrow β β
β β Anchor ββββΆβ (FX / USDC) ββββΆβ Contract β β
β β (Fiat on-ramp)β β β β - Lock funds β β
β ββββββββββββββββ ββββββββββββββββ β - Mint voucher β β
β β - Release on redeem β β
β β - Accept repayments β β
β ββββββββββββββββββββββββ β
β β β
β ββββββββββββΌββββββββββ β
β β Voucher Token (RVCH)β β
β β Stellar Custom Asset β β
β ββββββββββββ¬βββββββββββ β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββββ
β
ββββββββββββββββββββββββ¬ββββββββββββββββ
β β
ββββββββββββΌββββββββ ββββββββββββΌββββββββββββ
β app-farmer β β app-vendor β
β (PWA / USSD) β β (QR Scanner + POS) β
βββββββββββββββββββββ ββββββββββββββββββββββββ
β
ββββββββββββΌββββββββββββ
β oracle β
β Mobile money webhook β
β Triggers repayment β
ββββββββββββββββββββββββ
remitroot/
βββ packages/
β βββ contracts/ # Soroban smart contracts (Rust)
β β βββ escrow/
β βββ app-sender/ # Web app for diaspora senders (Next.js)
β βββ app-farmer/ # PWA + USSD interface for farmers (Next.js)
β βββ app-vendor/ # QR scanner POS for agro vendors (Next.js)
β βββ backend-api/ # REST API + webhook handler (Node/Express)
β βββ oracle/ # Harvest oracle & mobile money listener (Node)
β βββ shared/ # Types, utils, Stellar SDK helpers
βββ docs/ # Architecture docs, diagrams, ADRs
βββ scripts/ # Deployment & CI scripts
βββ .github/
β βββ workflows/ # CI/CD pipelines
βββ package.json # Root workspace config (pnpm)
βββ pnpm-workspace.yaml
βββ turbo.json # Turborepo task graph
βββ README.md
The core Soroban smart contract written in Rust. This is the trustless heart of RemitRoot.
packages/contracts/escrow/
βββ src/
β βββ lib.rs # Contract entry point
β βββ escrow.rs # Core escrow logic
β βββ voucher.rs # Voucher token mint/burn
β βββ repayment.rs # Repayment stream logic
β βββ storage.rs # Persistent state types
β βββ errors.rs # Contract error codes
βββ tests/
β βββ integration.rs # Full flow integration tests
βββ Cargo.toml
Contract state machine:
| State | Trigger | Description |
|---|---|---|
Created |
fund() |
Sender deposits USDC, escrow created |
Funded |
approve_farmer() |
Admin approves farmer, escrow locks |
VoucherMinted |
mint_voucher() |
RVCH token sent to farmer's wallet |
Redeemed |
redeem_voucher() |
Vendor burns token, goods delivered |
Repaying |
trigger_repay() |
Oracle signals harvest season |
Closed |
repay() / default() |
Escrow fully settled or timed out |
Key contract functions:
// Sender locks funds for a specific farmer + vendor + season
pub fn fund(env: Env, sender: Address, vendor_id: BytesN<32>,
crop_season: Symbol, amount: i128) -> Result<BytesN<32>, Error>
// Admin/DAO approves farmer and mints voucher
pub fn approve_farmer(env: Env, escrow_id: BytesN<32>,
farmer: Address) -> Result<(), Error>
// Vendor calls this to burn voucher and release USDC to themselves
pub fn redeem_voucher(env: Env, escrow_id: BytesN<32>,
vendor: Address) -> Result<(), Error>
// Oracle triggers repayment window after harvest
pub fn trigger_repay(env: Env, escrow_id: BytesN<32>) -> Result<(), Error>
// Farmer calls to make a partial repayment
pub fn repay(env: Env, escrow_id: BytesN<32>,
farmer: Address, amount: i128) -> Result<(), Error>
// Cancel and refund if no farmer approved within timeout
pub fn cancel(env: Env, escrow_id: BytesN<32>) -> Result<(), Error>The web application used by diaspora senders (built with Next.js + Freighter wallet integration).
packages/app-sender/
βββ src/
β βββ app/ # Next.js App Router pages
β β βββ page.tsx # Landing / dashboard
β β βββ fund/ # Create a new financing round
β β βββ track/ # Track active escrows
β β βββ history/ # Past transactions
β βββ components/
β β βββ WalletConnect.tsx # Freighter wallet button
β β βββ FarmerCard.tsx # Farmer profile preview
β β βββ EscrowStatus.tsx # Real-time escrow state
β β βββ RepaymentTracker.tsx
β βββ hooks/
β β βββ useStellar.ts # Stellar SDK wrapper
β β βββ useEscrow.ts # Contract interaction hooks
β βββ lib/
β βββ stellar.ts # Horizon + Soroban RPC client
β βββ anchor.ts # SEP-0010 auth + SEP-0024 deposit
βββ public/
βββ package.json
Key user flows:
- Connect Freighter wallet (SEP-0010 auth)
- Browse verified farmer profiles
- Choose vendor, crop season, amount
- Approve USDC deposit via Stellar Anchor
- Monitor escrow state in real time
Progressive Web App optimized for low-bandwidth mobile. Also exposes a USSD menu for feature phones.
packages/app-farmer/
βββ src/
β βββ app/
β β βββ page.tsx # Dashboard: pending vouchers
β β βββ voucher/ # View + share QR voucher
β β βββ repay/ # Submit repayment
β βββ components/
β β βββ VoucherQR.tsx # QR code display (offline capable)
β β βββ RepayForm.tsx # Mobile money repayment form
β βββ ussd/
β β βββ menu.ts # Africa's Talking USSD gateway handler
β βββ lib/
β βββ stellar.ts # Minimal Stellar SDK (wallet-less)
βββ public/
β βββ manifest.json # PWA manifest (offline support)
βββ package.json
USSD menu (feature phone support):
Welcome to RemitRoot
1. Check my voucher
2. Repay loan
3. Check balance
0. Exit
Simple QR scanner interface for agro-input vendors. Works on any Android device with a camera.
packages/app-vendor/
βββ src/
β βββ app/
β β βββ page.tsx # Scan voucher QR
β β βββ confirm/ # Confirm redemption + item list
β β βββ history/ # Transaction history
β βββ components/
β β βββ QRScanner.tsx # Camera QR reader
β β βββ RedemptionCard.tsx # Shows voucher details before burn
β β βββ ReceiptPrint.tsx # Printable paper receipt
β βββ lib/
β βββ stellar.ts
βββ package.json
Central REST API handling off-chain data: farmer profiles, vendor registry, notification dispatch.
packages/backend-api/
βββ src/
β βββ routes/
β β βββ farmers.ts # Farmer CRUD + KYC status
β β βββ vendors.ts # Vendor registry
β β βββ escrows.ts # Escrow state mirror (indexed from chain)
β β βββ webhooks.ts # Mobile money inbound hooks
β βββ services/
β β βββ stellar.ts # Horizon event indexer
β β βββ sms.ts # Africa's Talking SMS gateway
β β βββ kyc.ts # SEP-0012 KYC integration
β βββ db/
β β βββ schema.ts # Drizzle ORM schema
β β βββ migrations/
β βββ index.ts # Express app entry
βββ .env.example
βββ package.json
API routes:
| Method | Path | Description |
|---|---|---|
GET |
/farmers |
List verified farmers |
GET |
/farmers/:id |
Farmer profile + escrow history |
POST |
/farmers/kyc |
Submit KYC (SEP-0012) |
GET |
/vendors |
List verified agro vendors |
GET |
/escrows/:id |
Escrow state (mirrors chain) |
POST |
/webhooks/mpesa |
M-Pesa payment notification |
POST |
/webhooks/momo |
MTN Mobile Money notification |
Node.js service that listens for mobile money payment webhooks and triggers on-chain repayment.
packages/oracle/
βββ src/
β βββ listeners/
β β βββ mpesa.ts # M-Pesa Daraja API listener
β β βββ momo.ts # MTN MoMo listener
β β βββ stellar.ts # Stellar Horizon stream watcher
β βββ triggers/
β β βββ repayment.ts # Calls trigger_repay() on contract
β βββ index.ts
βββ package.json
Oracle flow:
- Mobile money provider calls webhook when farmer pays
- Oracle verifies payment amount and farmer identity
- Oracle calls
trigger_repay(escrow_id)on the Soroban contract - Contract releases proportional USDC back to sender's account
Shared TypeScript types, constants, and Stellar SDK utilities used across all packages.
packages/shared/
βββ src/
β βββ types/
β β βββ escrow.ts # EscrowState, EscrowDetails, etc.
β β βββ farmer.ts # FarmerProfile, KYCStatus
β β βββ vendor.ts # VendorProfile
β βββ constants/
β β βββ contracts.ts # Deployed contract IDs per network
β β βββ assets.ts # USDC, RVCH asset definitions
β βββ stellar/
β βββ client.ts # Horizon + Soroban RPC factory
β βββ sep10.ts # SEP-0010 auth helper
β βββ sep24.ts # SEP-0024 deposit/withdraw helper
βββ package.json
| Layer | Technology |
|---|---|
| Smart contracts | Rust + Soroban (Stellar smart contracts) |
| Blockchain | Stellar Mainnet / Testnet |
| FX / Payments | Stellar Path Payments, Stellar Anchors |
| Voucher token | Stellar Custom Asset (RVCH) |
| Auth | SEP-0010 (Stellar Web Auth), Freighter wallet |
| KYC | SEP-0012 |
| Fiat on/off-ramp | SEP-0024 (Anchor interactive deposit) |
| Frontend | Next.js 14, TypeScript, Tailwind CSS |
| Backend | Node.js, Express, Drizzle ORM, PostgreSQL |
| Mobile money | Africa's Talking (USSD + SMS), M-Pesa Daraja API, MTN MoMo |
| Monorepo | pnpm workspaces + Turborepo |
| CI/CD | GitHub Actions |
| Testnet | Stellar Testnet (Friendbot funded) |
- Node.js v20+
- pnpm v9+
- Rust +
cargo(for contract development) - Stellar CLI (
stellarβ includes Soroban CLI) - A Freighter browser wallet (for testing the sender app)
- A Stellar Testnet account funded via Friendbot
# Clone the repo
git clone https://github.com/your-org/remitroot.git
cd remitroot
# Install all workspace dependencies
pnpm install
# Install the Stellar CLI
cargo install --locked stellar-cli --features opt
# Install Rust Wasm target for Soroban contract compilation
rustup target add wasm32-unknown-unknownCopy and fill in the environment files for each package:
cp packages/backend-api/.env.example packages/backend-api/.env
cp packages/oracle/.env.example packages/oracle/.env
cp packages/app-sender/.env.example packages/app-sender/.env.local
cp packages/app-farmer/.env.example packages/app-farmer/.env.local
cp packages/app-vendor/.env.example packages/app-vendor/.env.localCore variables (all packages share these via .env at the root):
# Stellar network
STELLAR_NETWORK=testnet
STELLAR_RPC_URL=https://soroban-testnet.stellar.org
STELLAR_HORIZON_URL=https://horizon-testnet.stellar.org
STELLAR_NETWORK_PASSPHRASE="Test SDF Network ; September 2015"
# Deployed contract IDs (filled after deployment)
ESCROW_CONTRACT_ID=
# USDC asset on testnet
USDC_ISSUER=GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5
USDC_CODE=USDC
# Voucher token
RVCH_ISSUER= # Your issuer account public key
RVCH_CODE=RVCH
# Anchor
ANCHOR_HOME_DOMAIN=testanchor.stellar.org
# Backend
DATABASE_URL=postgresql://localhost:5432/remitroot
API_SECRET=
# Mobile money (oracle)
MPESA_CONSUMER_KEY=
MPESA_CONSUMER_SECRET=
MPESA_SHORTCODE=
AFRICAS_TALKING_API_KEY=
AFRICAS_TALKING_USERNAME=1. Build the Soroban contract:
cd packages/contracts/escrow
stellar contract build2. Deploy to Stellar Testnet:
stellar contract deploy \
--wasm target/wasm32-unknown-unknown/release/remitroot_escrow.wasm \
--source your-deployer-key \
--network testnetCopy the output contract ID into your .env as ESCROW_CONTRACT_ID.
3. Start all services in development mode:
# From the repo root β Turborepo runs everything in parallel
pnpm devThis starts:
app-senderon http://localhost:3000app-farmeron http://localhost:3001app-vendoron http://localhost:3002backend-apion http://localhost:4000oracleon http://localhost:4001
4. Run individual packages:
pnpm --filter app-sender dev
pnpm --filter backend-api dev
pnpm --filter oracle devfund() βββΆ Funded βββΆ approve_farmer() βββΆ VoucherMinted
β
redeem_voucher()
β
Redeemed
β
trigger_repay() βββ oracle
β
Repaying
β± β²
repay() default()
β β
Repaid Defaulted
If no farmer is approved within APPROVAL_TIMEOUT_LEDGERS (β 7 days on testnet), anyone can call cancel() to refund the sender.
| Code | Name | Meaning |
|---|---|---|
1 |
AlreadyFunded |
fund() called on an existing escrow |
2 |
NotFunded |
Action requires Funded state |
3 |
Unauthorized |
Caller is not the expected party |
4 |
VoucherAlreadyMinted |
Cannot mint twice |
5 |
NotRedeemed |
Cannot trigger repay before redemption |
6 |
RepaymentComplete |
Surplus repayment rejected |
7 |
NotExpired |
Cannot cancel before timeout |
1. Sender deposits $200 USDC via Stellar Anchor (e.g. MoneyGram Ramps)
2. Path payment converts USD β USDC on Stellar DEX (β 5 seconds, < $0.01 fee)
3. Soroban escrow contract locks $200 USDC
4. Contract mints 200 RVCH voucher tokens to farmer's Stellar account
5. Farmer visits vendor, vendor scans QR, burns 200 RVCH
6. Contract instantly releases $200 USDC to vendor's account
7. Vendor gives farmer seeds/fertilizer worth $200
8. [Post-harvest] Farmer sends $220 via M-Pesa (principal + 10% fee)
9. Oracle detects M-Pesa payment, calls trigger_repay() on contract
10. Contract streams $220 USDC back to sender's Stellar account
Fee structure:
| Party | Fee |
|---|---|
| Stellar network fee | ~0.00001 XLM per tx (< $0.001) |
| Anchor on-ramp | 0.5β1% (Anchor-dependent) |
| RemitRoot protocol fee | 1% of amount (held in treasury account) |
| Farmer repayment fee | Configurable per escrow (default 10%) |
| Primitive | Purpose in RemitRoot |
|---|---|
| Stellar Anchors | Cash in/out for both sender (USD β USDC) and farmer (USDC β mobile money) |
| Path Payments | Automatic FX routing β sender pays in any currency, farmer receives local stablecoin |
| Soroban Smart Contracts | Escrow logic, voucher minting, repayment rules |
| Stellar Custom Assets | RVCH voucher token β transferable only to registered vendors |
| SEP-0010 | Web authentication for sender app (wallet sign-in) |
| SEP-0012 | KYC data collection for farmers and vendors |
| SEP-0024 | Interactive deposit/withdrawal flow via Anchors |
| Claimable Balances | Unclaimed farmer vouchers held safely on-chain |
# Run all tests across the monorepo
pnpm test
# Run only contract tests
cd packages/contracts/escrow
cargo test
# Run only backend tests
pnpm --filter backend-api test
# Run full integration test (requires local Stellar testnet)
pnpm test:integrationContract test coverage targets:
fund()β valid deposit, duplicate escrow rejectionapprove_farmer()β auth check, state transitionredeem_voucher()β wrong vendor rejection, double-redeem protectionrepay()β partial repayments, overpayment rejectioncancel()β before/after timeout, refund amount correctnessdefault()β oracle-triggered, funds returned to sender
# Deploy contract
pnpm deploy:testnet
# Verify contract on Stellar Explorer
stellar contract info --id $ESCROW_CONTRACT_ID --network testnet# Requires a funded mainnet deployer account
pnpm deploy:mainnetGitHub Actions CI/CD (.github/workflows/):
| Workflow | Trigger | Actions |
|---|---|---|
ci.yml |
Pull request | Lint, type-check, test all packages |
deploy-testnet.yml |
Push to develop |
Deploy contracts + apps to testnet |
deploy-mainnet.yml |
Push to main |
Deploy to mainnet (manual approval) |
This project was built for the Stellar Wave Hackathon on Drips. Contributions, issues, and pull requests are welcome.
Good first issues (labelled good first issue on GitHub):
- Add USSD language localisation (Swahili, Amharic, Hausa)
- Integrate a second mobile money provider (Airtel Money)
- Add farmer credit scoring based on on-chain repayment history
- Build a vendor onboarding flow with document upload
- Write additional Soroban contract edge-case tests
- Add push notifications for escrow state changes
Contribution steps:
# Fork the repo, then:
git checkout -b feature/your-feature-name
pnpm install
# Make your changes
pnpm lint && pnpm test
git commit -m "feat: describe your change"
git push origin feature/your-feature-name
# Open a pull requestPlease follow the Conventional Commits spec for commit messages.
v0.1 β Hackathon MVP
- Soroban escrow contract (full lifecycle)
- Sender web app (fund + track)
- Farmer PWA (view voucher QR)
- Vendor QR scanner (redeem)
- Oracle (M-Pesa webhook β trigger_repay)
v0.2 β Post-Hackathon
- USSD interface for feature phones (Africa's Talking)
- Second mobile money integration (MTN MoMo)
- Farmer credit score NFT (on-chain repayment history)
- Multi-currency support (local stablecoins via Anchors)
- DAO governance for vendor whitelisting
v1.0 β Production
- Full KYC/AML compliance (SEP-0012 + local regulation)
- Pilot with 3 agro-input vendors in Nigeria / Kenya
- Integration with agricultural NGO disbursement programs
- Mobile app (React Native) for farmer and vendor
MIT Β© 2026 RemitRoot Contributors