Insurance That Pays Automatically. Canopy is a decentralized agricultural insurance platform built on the XRPL blockchain. It uses parametric triggers and real-time weather oracles to provide instant liquidity to farmers, removing claims, disputes, and delays.
- Data-Driven Triggers: Policies activated by objective NOAA/NASA weather data.
- Instant Payouts: Smart contracts on XRPL Escrow release funds immediately.
- Total Transparency: Audited on-chain logic ensures guaranteed liquidity.
The Canopy platform consists of three integrated phases that work together to provide end-to-end automated insurance:
flowchart TB
subgraph Frontend["π₯οΈ Frontend (Next.js)"]
WZ["Wizard Component"]
QR["Xaman QR Payment"]
DB_UI["Dashboard"]
CLAIM["NFT Claim UI"]
end
subgraph API["π Server Actions & API"]
PA["activatePolicy<br/>(Server Action)"]
CO["/api/cron/oracle"]
end
subgraph Backend["π€ AI Oracle (Python)"]
FASTAPI["FastAPI Server"]
ML["ML Risk Model"]
GEO["Geometry/GeoJSON Processor"]
end
subgraph XRPL["βοΈ XRPL Testnet"]
PAY["Premium Payment"]
ESC["EscrowCreate<br/>(Coverage Lock)"]
NFT["NFTokenMint<br/>(Policy NFT)"]
FIN["EscrowFinish<br/>(Payout)"]
end
subgraph Database["ποΈ Supabase/Prisma"]
POL[("Policy Table")]
ORA[("OracleLog")]
end
WZ --> QR --> PAY
PAY --> PA
PA --> ESC --> NFT
PA --> POL
CO --> FASTAPI
FASTAPI --> ML
FASTAPI --> GEO
CO --> FIN
FIN --> DB_UI
DB_UI --> CLAIM
sequenceDiagram
participant Farmer
participant Wizard as Wizard UI
participant Xaman
participant Actions as Server Actions
participant XRPL as XRPL Ledger
participant DB as Database
participant Cron as Oracle Cron
Note over Farmer,Cron: π° Premium Payment
Farmer->>Wizard: Click "Protect My Farm"
Wizard->>Actions: createPaymentRequest()
Actions->>Farmer: QR Code
Farmer->>Xaman: Scan & Approve (100 XRP)
Xaman->>XRPL: Submit Payment TX
Xaman-->>Wizard: Payment Confirmed
Note over Wizard,XRPL: β‘ Phase 1: Escrow Creation
Wizard->>Actions: activatePolicy(paymentData)
Actions->>XRPL: EscrowCreate (2000 XRP + condition)
XRPL-->>Actions: escrowSequence, txHash
Note over Actions,XRPL: π¨ Phase 2: NFT Minting
Actions->>XRPL: NFTokenMint (policy metadata)
XRPL-->>Actions: NFTokenID
Actions->>XRPL: NFTokenCreateOffer (to Farmer)
XRPL-->>Actions: offerId
Note over Actions,DB: πΎ Database Update
Actions->>DB: Create Policy (ACTIVE status)
Actions-->>Wizard: Success + XRPL links
Wizard->>Farmer: Show escrow & NFT data
Note over Cron,XRPL: π§οΈ Phase 3: Oracle Check (Every 6 hours)
Cron->>DB: Fetch ACTIVE policies
Cron->>Backend: POST /oracle/evaluate (geometry)
Backend->>Backend: ML Risk Evaluation (0-1 severity)
alt severity >= 0.5 (threshold)
Cron->>XRPL: EscrowFinish (fulfillment)
XRPL->>Farmer: 2000 XRP Released β
Cron->>DB: Mark policy CLAIMED
else No trigger
Cron->>DB: Log check (status: ACTIVE)
end
- Theme: Premium Startup Aesthetic (Dark Mode, Deep Forest Void, Neon Cyber Lime).
- Documentation:
This project is equipped with specialized AI agent skills and workflows to accelerate development.
Usage: These are "folders of instructions" the agent can use to perform complex tasks.
| Skill Name | Description | When to Use |
|---|---|---|
| blockchain-developer | Builds production-ready Web3 applications and smart contracts. | Use for XRPL integration, escrow logic, NFT minting. |
| prisma-expert | Prisma ORM expert for schema design and migrations. | Use for database schema updates and queries. |
| react-components | Generates React components. | Use when converting a design into functional React code. |
Usage: These are step-by-step guides for specific technical implementations.
| Workflow Name | Description | When to Use |
|---|---|---|
| nextauth-js | Sets up NextAuth.js authentication. | Use when implementing user authentication (OAuth, Email, Credentials). |
| supabase-rls | Configures Supabase Row Level Security. | Use when setting up database permissions and security rules. |
The "Lock-and-Trigger" lifecycle for agriculture insurance is implemented on XRPL Testnet.
sequenceDiagram
participant Insurer
participant XRPL as XRPL Ledger
participant Oracle
participant Farmer
Note over Insurer,Farmer: Policy Creation
Insurer->>XRPL: EscrowCreate (2000 XRP + SHA-256 Condition)
XRPL-->>Insurer: Escrow Sequence #14630109
Note over Oracle,Farmer: Trigger Event (Drought Detected)
Oracle->>XRPL: EscrowFinish (Fulfillment Secret)
XRPL->>Farmer: 2000 XRP Released β
-
EscrowCreate Transaction
- Insurer locks coverage amount (e.g., 2000 XRP = 20x premium)
- Includes SHA-256 crypto-condition (hash of secret fulfillment)
- Specifies Farmer as destination wallet
- Sets
FinishAftertimestamp for minimum hold period
-
Crypto-Condition
- Uses
five-bells-conditionlibrary (PREIMAGE-SHA-256) - 32-byte random preimage generates condition/fulfillment pair
- Only the Oracle holds the fulfillment secret
- Escrow cannot be released without correct fulfillment
- Uses
-
EscrowFinish Transaction
- Oracle submits fulfillment when weather threshold met
- XRPL validates fulfillment against stored condition
- Funds released atomically to Farmer's wallet
Configure in .env:
XRPL_INSURER_SEED=sXXX... # Locks coverage XRP
XRPL_FARMER_SEED=sXXX... # Receives payout
XRPL_ORACLE_SEED=sXXX... # Triggers release
INSURER_WALLET_ADDRESS=rXXX... # For EscrowFinish Owner field| File | Purpose |
|---|---|
src/lib/xrpl/escrow-create.ts |
Creates escrow with crypto-condition |
src/lib/xrpl/escrow-finish.ts |
Oracle releases locked XRP |
src/lib/xrpl/policy-activation.ts |
Orchestrates full Phase 1+2 flow |
scripts/verify-phase1.ts |
End-to-end test script |
# Ensure Insurer has >2100 XRP for escrow + fees
npx tsx scripts/verify-phase1.tsExpected output: Farmer balance increases by 2000 XRP.
XLS-20 NFTs that store parametric policy data with transferability enabled.
sequenceDiagram
participant Insurer
participant XRPL as XRPL Ledger
participant Farmer
Note over Insurer,Farmer: NFT Minting
Insurer->>XRPL: NFTokenMint (Policy Metadata in URI)
XRPL-->>Insurer: NFTokenID
Note over Insurer,Farmer: Policy Transfer
Insurer->>XRPL: NFTokenCreateOffer (to Farmer, 0 XRP)
Farmer->>XRPL: NFTokenAcceptOffer
XRPL-->>Farmer: NFT Ownership Transferred β
-
NFTokenMint Transaction
- Insurer mints NFT with policy details in URI field
- Metadata encoded as hex-JSON (compact format for 256-byte limit)
tfTransferableflag enables secondary market trading- NFTokenTaxon=1 identifies as policy category
-
Metadata Schema (Compact)
{ "t": "Corn Drought Protection", "la": 36.7783, "lo": -119.4179, "th": "Rainfall < 10mm", "p": "2000000000", "es": 14630109 }Field Description tPolicy type/title la,loLatitude, Longitude thWeather threshold pPayout amount (drops) esLinked escrow sequence -
NFTokenCreateOffer
- Creates sell offer to Farmer at 0 XRP (free transfer)
- Farmer can claim NFT via NFTokenAcceptOffer
- NFT proves policy ownership and terms
| File | Purpose |
|---|---|
src/lib/xrpl/nft-types.ts |
PolicyNFTMetadata interface |
src/lib/xrpl/nft-mint.ts |
Hex encoding + NFT utilities |
scripts/verify-phase2.ts |
End-to-end NFT test |
npx tsx scripts/verify-phase2.tsExpected output: NFT minted, transferred to Farmer, metadata decoded.
Automated weather monitoring and escrow trigger system with modular design.
flowchart TB
subgraph Oracle["Oracle Service"]
WM["π§οΈ Weather Module"] --> TL{"Trigger Logic"}
TL -->|"rainfall < threshold"| ML["π€ ML Score (TODO)"]
ML --> XE["β‘ XRPL Executor"]
TL -->|"rainfall >= threshold"| NO["β No Payout"]
end
subgraph External["Data Sources / Backend"]
API["π Python FastAPI"] -.->|"ML Model"| WM
DB[("π Supabase")] --> TL
end
subgraph Ledger["XRPL Testnet"]
XE --> EF["EscrowFinish"]
EF --> F["π° Farmer Wallet"]
end
sequenceDiagram
participant Cron as Cron Job
participant DB as Database
participant WO as Weather Oracle
participant XRPL as XRPL Ledger
participant Farmer
Cron->>DB: Fetch ACTIVE policies
loop For each policy
Cron->>WO: evaluateRiskViaBackend(geometry)
WO-->>Cron: {severity: 0.85}
Cron->>Cron: Compare severity to threshold (0.5)
alt severity >= threshold
Cron->>XRPL: EscrowFinish (fulfillment)
XRPL->>Farmer: XRP Released β
Cron->>DB: Update status=CLAIMED
else No trigger
Cron->>DB: Log check results
end
end
-
Cron Job Endpoint (
/api/cron/oracle)- Protected by
CRON_SECRETheader - Fetches all ACTIVE policies with escrow data
- Checks weather for each policy's coordinates
- Triggers EscrowFinish when threshold met
- Protected by
-
Mock Weather (Development)
- Returns simulated drought: 2mm rainfall
- Below typical 10mm threshold = always triggers
- Replace with OpenWeather API for production
-
Policy Status Updates
- ACTIVE β CLAIMED on successful payout
- claimTxHash records EscrowFinish transaction
- OracleLog tracks all weather checks
| File | Purpose |
|---|---|
src/app/api/cron/oracle/route.ts |
Cron endpoint for oracle checks |
src/lib/oracle/weather-oracle.ts |
Mock weather + OpenWeather TODO |
src/lib/oracle/OracleService.ts |
Main orchestration + ML TODO |
scripts/test-trigger.ts |
End-to-end oracle test |
# Development (no auth required)
curl -X POST http://localhost:3000/api/cron/oracle
# Production (with auth)
curl -X POST http://localhost:3000/api/cron/oracle \
-H "Authorization: Bearer YOUR_CRON_SECRET"Expected output: Oracle triggers payout when rainfall < threshold.
- OpenWeather API - Replace mock with real weather data
- ML Score - Add probability scoring for edge cases
- Real Cron - Set up Vercel Cron or external scheduler
A LangGraph-powered autonomous agent that orchestrates underwriting, monitoring, and claims adjudication.
flowchart TB
subgraph Agent["π€ LangGraph Agent (Python)"]
direction TB
SM[("StateGraph")]
UW["Underwrite Node<br/>(Gatekeeper)"]
MN["Monitor Node<br/>(Watchman)"]
VF["Verify Node<br/>(Investigator)"]
ST["Settle Node<br/>(Paymaster)"]
SM --> UW
SM --> MN
MN --> VF
VF --> ST
end
subgraph Tools["π§ Worker Tools"]
WT["weather_tool<br/>Open-Meteo API"]
RT["risk_tool<br/>XGBoost ML Model"]
PT["pricing_tool<br/>Dynamic Premium Calc"]
XT["xrpl_escrow_tool<br/>EscrowFinish TX"]
end
subgraph External["π‘ Data Sources"]
OM["Open-Meteo<br/>Weather API"]
ML["XGBoost Model<br/>(Stress Indices)"]
XL["XRPL Ledger"]
end
UW --> WT --> OM
UW --> RT --> ML
UW --> PT
ST --> XT --> XL
subgraph Observability["ποΈ LangSmith"]
TR["Traces"]
LG["Logs"]
end
Agent -.-> Observability
stateDiagram-v2
[*] --> quote_pending: New Application
state Underwriting {
quote_pending --> rejected: Risk > 95%
quote_pending --> active: Premium Paid
}
state Monitoring {
active --> monitoring: Cron Check
monitoring --> active: Safe
monitoring --> claim_triggered: Risk > 80%
}
state Adjudication {
claim_triggered --> verify: Satellite Check
verify --> claim_triggered: Confirmed
verify --> monitoring: Conflict
}
claim_triggered --> settled: EscrowFinish
settled --> [*]
rejected --> [*]
-
Underwrite Node (Gatekeeper)
- Fetches 7-day weather forecast via
weather_tool - Runs risk assessment via
risk_tool(uses OracleService + XGBoost) - Calculates dynamic premium:
Premium = (Coverage Γ 5%) Γ (1 + RiskScore) Γ Volatility - Rejects policies with CRITICAL risk (>85%) - cannot insure active disasters
- Fetches 7-day weather forecast via
-
Monitor Node (Watchman)
- Periodic checks on active policies (cron-triggered)
- Compares current conditions against trigger thresholds
- Escalates to verification when risk score exceeds 80%
-
Verify Node (Investigator)
- Cross-references weather data with satellite imagery (TODO)
- Resolves conflicts between data sources
- "Physics beats Model" - hard data overrides ML predictions
-
Settle Node (Paymaster)
- Executes
EscrowFinishtransaction on XRPL - Releases locked XRP to farmer's wallet
- Logs audit trail with confidence score
- Executes
The agent operates under strict principles:
Core Principles:
1. Solvency First - Never insure already-materialized risks
2. Data Consensus - Satellite/Physics > ML Model when in conflict
3. Transparency - Every decision requires plain English reasoning
Data Weighting:
- XGBoost Model (Medium) β Baseline probability
- Open-Meteo/NASA (CRITICAL) β Hard physics override
- Satellite (HIGH) β Tie-breaker verification
| Endpoint | Method | Description |
|---|---|---|
/agent/quote |
POST | Generate insurance quote with dynamic pricing |
/agent/monitor |
POST | Check policy status and trigger conditions |
/agent/settle |
POST | Execute policy settlement on XRPL |
/agent/chat |
POST | Interactive assistant for users |
/agent/check-land |
POST | Verify if usage is agricultural |
/agent/audit-log |
GET | Retrieve natural language decision history |
Quote Request:
{
"latitude": 40.0,
"longitude": -80.0,
"farm_size_hectares": 50,
"crop_type": "corn",
"coverage_xrp": 1000
}Quote Response:
{
"status": "quote_pending",
"premium_xrp": 105.5,
"risk_score": 0.42,
"risk_level": "MEDIUM",
"reasoning_log": [
"β
Quote generated: 105.5 XRP for 1000 XRP coverage.",
" Risk: MEDIUM (42.00%), Volatility: 1.15x"
]
}| File | Purpose |
|---|---|
backend/agent/graph.py |
LangGraph StateGraph definition |
backend/agent/tools.py |
Worker tools (Weather, Risk, Pricing, XRPL) |
backend/agent/prompts.py |
System prompt for "The Guardian" persona |
backend/main.py |
FastAPI endpoints (/agent/*) |
# LangSmith Observability (Optional)
LANGCHAIN_TRACING_V2=true
LANGCHAIN_API_KEY=lsv2_...
LANGCHAIN_PROJECT="canopy-agent"
# OpenAI (for LLM reasoning)
OPENAI_API_KEY=sk-...cd backend
pip install -r requirements.txt
# Start FastAPI server
uvicorn main:app --reload --port 8000
# Test quote endpoint
curl -X POST http://localhost:8000/agent/quote \
-H "Content-Type: application/json" \
-d '{"latitude": 40.0, "longitude": -80.0, "farm_size_hectares": 50, "crop_type": "corn", "coverage_xrp": 1000}'// src/app/actions/payment.ts
activatePolicy(data: ActivatePolicyData)Orchestrates full XRPL policy lifecycle after premium payment.
Input Data:
{
premiumAmount: 100,
crop: "corn",
riskLevel: 10,
coordinates: { lat: 36.7783, lng: -119.4179 },
areaHectares: 50,
premiumTxHash: "ABC123..."
}Response:
{
"success": true,
"policyId": "clxyz123...",
"coverageAmount": 2000,
"escrow": {
"sequence": 14630109,
"txHash": "DEF456...",
"explorerUrl": "https://testnet.xrpl.org/transactions/DEF456"
},
"nft": {
"tokenId": "000800...",
"mintTxHash": "GHI789...",
"explorerUrl": "https://testnet.xrpl.org/nft/000800"
}
}
POST /api/cron/oracle
Authorization: Bearer {CRON_SECRET}Checks all active policies and triggers payouts.
Response:
{
"success": true,
"timestamp": "2024-02-06T05:00:00Z",
"processed": 5,
"triggered": 2,
"results": [
{
"policyId": "clxyz123...",
"triggered": true,
"reason": "Rainfall 2mm < 10mm threshold",
"txHash": "JKL012..."
}
]
}# Database
DATABASE_URL="postgresql://..."
DIRECT_URL="postgresql://..."
# XRPL Testnet Wallets
XRPL_INSURER_SEED="sXXX..." # Locks coverage XRP
XRPL_FARMER_SEED="sXXX..." # Receives payout
XRPL_ORACLE_SEED="sXXX..." # Triggers release
INSURER_WALLET_ADDRESS="rXXX..." # For EscrowFinish
# Supabase
NEXT_PUBLIC_SUPABASE_URL="https://xxx.supabase.co"
NEXT_PUBLIC_SUPABASE_ANON_KEY="sb_publishable_..."
SUPABASE_SERVICE_ROLE_KEY="sb_secret_..."
SUPABASE_JWT_SECRET="xxx-xxx-xxx"
# Xaman (Xumm)
XUMM_API_KEY="xxx-xxx"
XUMM_API_SECRET="xxx-xxx"
# Oracle Cron
CRON_SECRET="your-secret-key"
# App
NEXT_PUBLIC_APP_URL="http://localhost:3000"
NEXT_PUBLIC_MAPBOX_TOKEN="pk.xxx..."- Node.js 18+
- pnpm (recommended)
- XRPL Testnet wallets with XRP (get test XRP from faucet)
# Clone and install
git clone https://github.com/yourorg/xrp_farmer
cd xrp_farmer
pnpm install
# Set up environment
cp .env.example .env
# Edit .env with your credentials
# Run database migrations
pnpm prisma migrate dev
# Start development server
pnpm dev# Test Phase 1: Escrow
npx tsx scripts/verify-phase1.ts
# Test Phase 2: NFT
npx tsx scripts/verify-phase2.ts
# Test Phase 3: Oracle
npx tsx scripts/test-trigger.tsOpen http://localhost:3000 with your browser to see the result.
MIT License - See LICENSE for details.