Agrocylo is an Agro-DeFi platform. The aim is to make life easier for farmers (especially homegrown/urban), enabling exchange of agro-goods and services using an escrow system. It eliminates middlemen, allows peer-to-peer trade between farmers and consumers, and gives both parties access to Blockchain, Native DeFi, and Digital services.
Each purchase is secured using an escrow mechanism: funds are locked when a customer places an order and are released only after the buyer confirms receipt of goods. This guarantees protection for both parties while maintaining full user custody.
Configuration: docs/deployment/environment.md is the authoritative environment-variable reference for all four apps and the contract set, including secret-management and key-rotation procedures. Drift between each app's .env.example and its code is caught by scripts/check-env-drift.js in CI.
-
On-chain escrow settlement - Funds are locked in an escrow smart contract until buyers confirm receipt of goods.
-
Non-custodial payments - Users retain full control of funds at all times.
-
Peer-to-peer Farmer-Consumer Marketplace - Farmers sell directly to consumers without middlemen, retaining price control and increasing income.
-
Token-based payment - Supports stablecoin and token payments (USDC and XLM)
-
Buyer-confirmed settlement - Funds are never released to farmer/seller until the buyer confirms receipt of goods.
-
Unlimited parallel transactions - Unlimited concurrent trades can be carried out at a time, and each transaction is tracked by ID, time, status, amount, and associated addresses.
-
Order indexing by role - Buyers can view all their purchases and order statuses. Farmers can track incoming orders and pending payments.
-
Real-time updates and notifications - On-chain events are indexed and transmitted off-chain to deliver real-time order updates and notifications.
- Wider market reach and ease of payment - Small scale farmers face limited market access and fragmented payment systems.
- Post-harvest loss reduction - Farmers incure losses due to lack of storage facilities and limited market access
- Higher farmer profit and lower consumer cost - enabled by peer-to-peer interaction between farmer and consumer (Absence of middleman).
- Digital transformation of agriculture - price discovery tools, demand/supply aggregation tools to aid data-driven production.
a. Primary users * Farmers/Producers * Consumers/buyers
b. Secondary stakeholders * Platform operators: analytics, monitoring and support. * NGOβs, cooperatives or government programs promoting farmer inclusion
Escrow creation
Order lifecycle management
Dispute handling
Farmer dashboards
Consumer checkout & order tracking
Wallet integration
Event indexing
Notifications (email, push, in-app)
Analytics and reporting
Frontend (Web / Mobile)
β Smart Contracts (Escrow)
β Stellar Network
β Off-Chain Indexers & Notification Services
βββββββββββββββββββ β FRONTEND β β (Web/Mobile) β ββββββββββ¬βββββββββ β β β β---------ββ β ββββββΌββββββββββββ βSmart Contracts β β (Soroban Rust) β----------ββ ββββββ¬ββββββββββββ | β ββββββΌββββββββββββ β Backend | β β ββββββββββββββββββ
Network: Stellar Testnet
Smart Contracts: Rust (Soroban)
Frontend: Next.js (React)
Wallets: Freighter
Indexing: Custom event indexer / Subgraph-style service
Notifications: In-app (DB-persisted, delivered via REST API)
Enable swift, fair, and transparent trade
Found a vulnerability? Please report it privately β see SECURITY.md for scope, response SLAs, and how to reach us. Do not open a public issue for security findings.
The client/ app talks to exactly one Stellar network, chosen by a single
switch. It fails fast rather than silently falling back to testnet β a
mainnet deployment missing a variable renders a configuration-error state
instead of quietly signing real transactions against the wrong ledger.
| Variable | Required | Notes |
|---|---|---|
NEXT_PUBLIC_STELLAR_ENV |
recommended | testnet | mainnet. The single source of truth. Unset β inferred from the passphrase, else testnet (local dev only). |
NEXT_PUBLIC_NETWORK_PASSPHRASE |
yes | Test SDF Network ; September 2015 or Public Global Stellar Network ; September 2015. In mainnet mode a missing/testnet value is a hard error. |
NEXT_PUBLIC_SOROBAN_RPC_URL |
yes | Soroban RPC endpoint; must match the network. |
NEXT_PUBLIC_CONTRACT_ID |
yes for on-chain UI | Deployed escrow contract. Gates transaction-capable UI via isContractConfigured(). |
NEXT_PUBLIC_HORIZON_URL |
optional | Overrides the Horizon endpoint; defaults follow NEXT_PUBLIC_STELLAR_ENV. |
Fail-fast contract:
- Build time β
next.config.tsthrows on a production build ifNEXT_PUBLIC_SOROBAN_RPC_URLorNEXT_PUBLIC_NETWORK_PASSPHRASEis unset. - Runtime, mainnet mode β
getNetworkConfig(),getExpectedNetworkPassphrase(),getRpcServer()/getServer()(src/lib/stellar.ts) andresolveNetworkPassphrase()(src/lib/signTransaction.ts) throw instead of returning testnet defaults when wallet/network detection fails. - Runtime, testnet / unset β the testnet fallback is retained for local dev.
- Wallet mismatch β if the connected wallet's network differs from
NEXT_PUBLIC_STELLAR_ENV, a persistent banner is shown and signing/submission is refused with aNetworkMismatchError(src/context/WalletContext.tsx,src/components/NetworkMismatchBanner.tsx).
See client/.env.example for the full list.
Contributions are welcome! Whether you're fixing bugs, adding features, improving docs, or writing tests, your help is valued.
See CONTRIBUTING.md for:
- Local setup instructions per app (Rust contracts, Node.js backend, Next.js frontend)
- Pre-PR expectations (test requirements, Rust-specific checks like
cargo check, etc.) - Merge & review practices (especially important for Rust contracts holding real funds)
- Stellar Wave bounty workflow for external contributors
Quick start:
- Fork the repository
- Clone your fork:
git clone https://github.com/YOUR_USERNAME/Agrocylo-Global.git - Create a feature branch:
git checkout -b fix/issue-number - Follow the setup in CONTRIBUTING.md
- Open a PR referencing the issue(s) it closes
# Client unit tests (vitest + jsdom)
cd client && npm test
# Server unit tests (vitest + node)
cd server && npm run test:coverage
# Contract tests (Rust soroban-sdk)
cargo test --workspace
# Or test individual crates:
cargo test -p escrow
cargo test -p weather-insurance
cargo test -p registry
cargo test -p production-escrow-v2
cargo test -p investment-basket
cargo test -p governance# Run Playwright E2E tests
cd client && npm run test:e2e
# Run E2E tests with interactive UI
cd client && npm run test:e2e:uiE2E tests mock Freighter wallet and use NEXT_PUBLIC_DEMO_MODE=true for deterministic responses. See .github/workflows/e2e.yml for CI configuration.
The repository includes Docker Compose orchestration for containerized development and deployment. Note: This repo contains multiple app pairings (legacy server/client and current agro-production/server/agro-production/client), and the compose setup currently covers only the legacy pair.
Root docker-compose.yml (legacy server/client)
- Orchestrates PostgreSQL, Redis, and the backend service from
./server - Exposes backend on port 5000
- Recommended for: Contributors working on the legacy server/client apps
- Usage:
docker-compose up
agro-production/server/docker-compose.redis.yml (Redis only for agro-production)
- Standalone Redis service with persistent storage (
appendonlymode) - Exposes Redis on port 6379
- Currently not linked to a full app compose file β this repo's primary dev workflow for agro-production apps uses
npm run dev(see "Running locally" below) - Usage (if needed for production/staging deployments):
cd agro-production/server && docker-compose -f docker-compose.redis.yml up
For local development of agro-production/server and agro-production/client, see "Running locally" below β the recommended approach is npm-based development, not Docker.
The quickest way to get the full stack running is a single command:
docker compose upThis brings up all four applications (two backends + two frontends) along with both Postgres databases and Redis:
| Service | Port | Description |
|---|---|---|
| Caddy proxy | 80 |
Unified entry point (http://localhost) |
| Root client | 3000 |
Marketplace frontend |
| Agro-production client | 3001 |
Campaign/crowdfunding frontend |
| Root backend | 5000 |
Marketplace API |
| Agro-production backend | 5001 |
Campaign API |
| Postgres (marketplace) | 5432 |
agrocylo_db |
| Postgres (campaigns) | 5433 |
agrocylo_production |
| Redis | 6379 |
Shared cache/queues |
Once running, visit:
- http://localhost β root marketplace (Caddy proxy)
- http://localhost/agro β agro-production (Caddy proxy)
- http://localhost:5000 β root backend API (direct)
- http://localhost:5001 β agro-production backend API (direct)
Customising environment variables:
Edit the .env file in the repo root. Sensible development defaults are provided
so docker compose up works out-of-the-box from a fresh clone.
Tearing down:
docker compose down -v # stops containers + wipes database volumesIf you prefer to run services individually, start them from the documented working directory.
Both frontends use one root npm workspace install and the committed root lockfile. From the repository root:
npm ci
npm run dev # both: marketplace 3000, production 3001
npm run dev:marketplace # marketplace only: http://localhost:3000
npm run dev:production # production only: http://localhost:3001Copy each app's .env.example to .env.local inside that app. See the
canonical frontend setup and troubleshooting guide
for the supported Node/npm policy, port overrides, environment files, and
startup recovery.
From agro-production/server/, install its server dependencies, configure
.env, run npx prisma migrate deploy, then npm run dev. It listens on
http://localhost:5001 by default.
From server/, install its server dependencies, copy .env.example to
.env, run npx prisma migrate deploy, then npm run dev. It listens on
http://localhost:5000 by default.
The backend server (/agro-production/server) exposes product endpoints for the marketplace.
Get all products
GET /api/v1/products
Get product by ID
GET /api/v1/products/:id
Environment Variables
For production, ensure the following are configured (see .env.example):
NODE_ENV: Set toproductionDATABASE_URL: Supabase PostgreSQL connection string (for production data)CORS_ORIGINS: Comma-separated list of allowed origins