Skip to content

OpenLedger-Foundation/Kora-Frontend

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

385 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Stellar Soroban Next.js 15 TypeScript TailwindCSS MIT License

⬡ Kora Protocol

On-chain Invoice Financing built on Stellar Soroban

SMEs tokenize unpaid invoices as NFTs and sell them at a discount to global liquidity providers — unlocking instant stablecoin liquidity without banks.


Table of Contents


Overview

Kora Protocol is a decentralized invoice financing platform built on Stellar Soroban. It bridges the gap between SMEs in emerging markets who need working capital and global investors seeking yield on short-duration, real-world assets.

The problem: SMEs in Africa, Asia, and Latin America hold trillions of dollars in unpaid invoices. Traditional invoice financing is slow, expensive, and inaccessible to most small businesses.

The solution: Kora tokenizes invoices as NFTs on Stellar Soroban. Investors fund them via USDC. Settlement is instant, transparent, and non-custodial.

How It Works

SME                    Kora Protocol              Investor
 │                          │                         │
 ├─ Upload Invoice ─────────►                         │
 │                          ├─ Store on IPFS          │
 │                          ├─ Mint NFT on Soroban    │
 │                          ├─ List on Marketplace ───►
 │                          │                         ├─ Browse & Fund
 │◄─ Receive USDC ──────────┤◄─ USDC Deposited ───────┤
 │                          │                         │
 │  (on due date)           │                         │
 ├─ Repay Principal ────────►                         │
 │                          ├─ Distribute Yield ──────►
 │                          │                         │

Live Demo

Testnet deployment: https://kora-protocol.vercel.app (coming soon)

To run locally, see Getting Started.


Features

For SMEs

  • ✅ Connect Stellar wallet (Freighter, xBull, LOBSTR, Albedo)
  • ✅ Upload invoice PDF to IPFS via Pinata
  • ✅ Mint invoice as NFT on Soroban with one click
  • ✅ Set custom discount rate and minimum investment
  • ✅ Receive USDC instantly when invoice is funded
  • ✅ Dashboard to track all active invoices and repayments

For Investors

  • ✅ Browse marketplace with filters (category, jurisdiction, risk tier, APR)
  • ✅ View detailed invoice information and risk scores
  • ✅ Fund invoices with USDC (partial or full)
  • ✅ Real-time funding progress bars
  • ✅ Portfolio dashboard with yield tracking
  • ✅ Analytics with charts (portfolio growth, yield, risk distribution)

Protocol

  • ✅ Non-custodial — funds held in Soroban smart contract escrow
  • ✅ On-chain risk scoring and repayment history
  • ✅ IPFS-stored invoice metadata (tamper-proof)
  • ✅ Transaction status toasts with hash links
  • ✅ Optimistic UI updates

Tech Stack

Layer Technology
Framework Next.js 15 (App Router)
Language TypeScript 5.6
Styling TailwindCSS 3.4 + CSS Variables
UI Components Custom + Radix UI primitives
State Management Zustand 5
Data Fetching TanStack Query v5
Animations Framer Motion 11
Forms React Hook Form + Zod
Charts Recharts 2
File Upload React Dropzone
Notifications Sonner
Blockchain Stellar Soroban (via @stellar/stellar-sdk)
Wallet Stellar Wallets Kit (@creit.tech/stellar-wallets-kit)
Storage IPFS via Pinata

Design System

The Kora frontend uses a semantic Tailwind-based design system with CSS custom properties in app/globals.css.

  • Color tokens are defined in HSL and mapped through tailwind.config.ts.
  • The app is dark-mode-first and supports light mode through theme overrides.
  • Reusable primitives live under components/ui.

Read the full design system documentation in DESIGN_SYSTEM.md.


Getting Started

Prerequisites

  • Node.js 18+ and npm/yarn/pnpm
  • A Stellar wallet browser extension (Freighter recommended)
  • A Pinata account for IPFS uploads (free tier works)

Installation

# 1. Clone the repository
git clone https://github.com/your-org/kora-frontend.git
cd kora-frontend

# 2. Install dependencies
npm install

# 3. Set up environment variables
cp .env.example .env.local
# Edit .env.local with your values (see Environment Variables section)

# 4. Start the development server
npm run dev

Open http://localhost:3000 in your browser.

Docker (Alternative)

If you prefer Docker, run:

cp .env.example .env.local
# Edit .env.local with your values
docker compose up

The app will be available at http://localhost:3000 with hot reload enabled.

Quick Start with Mock Data

The app ships with mock data enabled by default (NEXT_PUBLIC_ENABLE_MOCK_DATA=true). You can browse the marketplace, view invoice details, and explore dashboards without a live Soroban connection.

To test wallet interactions, install Freighter, switch it to Testnet, and fund your account via Stellar Friendbot.

Seeding Testnet Data

Once you have real contract IDs deployed to testnet (NEXT_PUBLIC_ENABLE_MOCK_DATA=false), scripts/seed-testnet.ts sets up a wallet with sample data to develop against:

npm run seed:testnet

This generates a new keypair, funds it via Friendbot, mints it testnet USDC, mints 5 sample invoices, partially funds 2 of them, and prints the wallet's public/secret key and the minted token IDs to the console — save the secret key if you want to reuse that wallet (e.g. to import it into Freighter).

Validate the script against your configured contracts without writing any invoice or funding state on-chain:

npm run seed:testnet -- --dry-run

--dry-run still generates and funds a keypair (a real, funded account is required to simulate contract calls at all) and builds + simulates every mint call, but never signs or submits a mint or fund transaction.

The script refuses to run unless NEXT_PUBLIC_STELLAR_NETWORK=testnet — it will never touch mainnet. It reuses lib/stellar/contracts.ts and @stellar/stellar-sdk directly (no extra tooling needed) via Node's built-in TypeScript support, so it requires Node.js 22.6+.


Project Structure

kora-frontend/
├── app/                          # Next.js App Router pages
│   ├── page.tsx                  # Landing page
│   ├── layout.tsx                # Root layout + providers
│   ├── globals.css               # Global styles + CSS variables
│   ├── providers.tsx             # QueryClient, Toaster, WalletModal
│   ├── marketplace/
│   │   ├── page.tsx              # Invoice marketplace listing
│   │   └── [id]/page.tsx         # Invoice detail + fund panel
│   ├── invoice/
│   │   └── create/page.tsx       # 3-step create invoice wizard
│   ├── dashboard/
│   │   ├── sme/page.tsx          # SME dashboard
│   │   └── investor/page.tsx     # Investor dashboard
│   └── analytics/page.tsx        # Portfolio analytics + charts
│
├── components/
│   ├── ui/                       # Reusable primitive components
│   │   ├── button.tsx
│   │   ├── card.tsx              # Card + GlassCard
│   │   ├── badge.tsx
│   │   ├── skeleton.tsx
│   │   ├── progress.tsx
│   │   ├── input.tsx
│   │   ├── dialog.tsx
│   │   ├── select.tsx
│   │   └── stat-card.tsx
│   ├── invoice/
│   │   └── InvoiceCard.tsx       # Marketplace invoice card
│   ├── wallet/
│   │   ├── WalletConnectModal.tsx
│   │   └── WalletButton.tsx
│   └── layout/
│       └── Navbar.tsx
│
├── hooks/
│   ├── useWallet.ts              # Stellar Wallets Kit wrapper
│   ├── useTransaction.ts         # Build → sign → submit lifecycle
│   └── useInvoices.ts            # TanStack Query invoice hooks
│
├── lib/
│   ├── stellar/
│   │   ├── client.ts             # Soroban RPC + Horizon client
│   │   ├── contracts.ts          # Contract call builders
│   │   └── index.ts
│   ├── ipfs.ts                   # Pinata upload helpers
│   ├── utils.ts                  # cn(), formatCurrency, etc.
│   └── validations/
│       └── invoice.ts            # Zod schemas
│
├── services/
│   ├── mockData.ts               # Mock invoices + stats
│   └── invoiceService.ts         # Invoice CRUD + contract calls
│
├── store/
│   ├── walletStore.ts            # Wallet state (persisted)
│   ├── invoiceStore.ts           # Marketplace filters + sort
│   ├── uiStore.ts                # Modal + tx state
│   └── index.ts
│
├── types/
│   ├── invoice.ts                # Invoice, InvoiceMetadata, etc.
│   ├── user.ts                   # WalletState, UserProfile, etc.
│   ├── contract.ts               # ContractConfig, TxState, etc.
│   └── index.ts
│
├── .env.example                  # Environment variable template
├── next.config.js
├── tailwind.config.ts
├── tsconfig.json
└── package.json

Environment Variables

Copy .env.example to .env.local and fill in the values:

# Stellar Network
NEXT_PUBLIC_STELLAR_NETWORK=testnet
NEXT_PUBLIC_STELLAR_RPC_URL=https://soroban-testnet.stellar.org
NEXT_PUBLIC_STELLAR_HORIZON_URL=https://horizon-testnet.stellar.org
NEXT_PUBLIC_STELLAR_NETWORK_PASSPHRASE="Test SDF Network ; September 2015"

# Contract Addresses — v0.2 testnet deployments (replace with your own if needed)
NEXT_PUBLIC_INVOICE_CONTRACT_ID=CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA
NEXT_PUBLIC_MARKETPLACE_CONTRACT_ID=CBWOAOZCOAJQH7HHZRE5BVNL2C4HRP4JCQZF3YQCQYDL5BZJRN4YGK4
NEXT_PUBLIC_TOKEN_CONTRACT_ID=CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC

# IPFS (Pinata)
NEXT_PUBLIC_IPFS_GATEWAY=https://gateway.pinata.cloud/ipfs
PINATA_JWT=your_pinata_jwt_token

# Feature Flags
NEXT_PUBLIC_ENABLE_MOCK_DATA=true   # Set to false for live on-chain calls
NEXT_PUBLIC_ENABLE_DEVTOOLS=true
NEXT_PUBLIC_ENABLE_COMPARISON=true  # Invoice comparison bar (marketplace); share via ?compare=id1,id2
NEXT_PUBLIC_ENABLE_ONBOARDING_TOUR=false
NEXT_PUBLIC_ENABLE_BATCH_ACTIONS=false

Invoice comparison: When NEXT_PUBLIC_ENABLE_COMPARISON=true, marketplace cards show Add to Compare. Select up to 4 invoices, open the comparison table, and share the URL (?compare=…) to restore the selection. See lib/featureFlags.ts and lib/comparison.ts.


Core User Flows

SME: Create and Finance an Invoice

  1. Connect wallet via Connect Wallet button
  2. Navigate to Create Invoice
  3. Fill in invoice details (debtor, amount, due date, jurisdiction)
  4. Set discount rate and minimum investment
  5. Upload invoice PDF
  6. Click Mint Invoice NFT — this:
    • Uploads PDF to IPFS via Pinata
    • Uploads metadata JSON to IPFS
    • Builds a Soroban mint_invoice transaction
    • Prompts wallet for signature
    • Submits to Stellar network
  7. Invoice appears on marketplace
  8. As investors fund it, USDC flows to your wallet

Investor: Fund an Invoice

  1. Connect wallet
  2. Browse Marketplace — filter by APR, risk tier, jurisdiction
  3. Click an invoice card to view details
  4. Enter investment amount (respects min/max)
  5. Review expected return
  6. Click Fund Invoice — this:
    • Builds a Soroban fund_invoice transaction
    • Prompts wallet for signature
    • Submits to Stellar network
  7. Position appears in Investor Dashboard
  8. On repayment date, principal + yield is returned

Smart Contract Integration

The frontend interacts with two Soroban contracts:

v0.2 Testnet Deployments

Contract Address Explorer
Invoice NFT CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA View
Marketplace CBWOAOZCOAJQH7HHZRE5BVNL2C4HRP4JCQZF3YQCQYDL5BZJRN4YGK4 View
USDC Token CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC View

Smart Contract Deployment

To deploy your own contracts to testnet:

Prerequisites

Steps

# 1. Install Stellar CLI
cargo install --locked stellar-cli --features opt

# 2. Generate or import a deployer keypair
stellar keys generate --global deployer --network testnet
stellar keys fund deployer --network testnet   # fund via Friendbot

# 3. Build contract WASM (from the contracts repo)
stellar contract build

# 4. Deploy the Invoice NFT contract
stellar contract deploy \
  --wasm target/wasm32-unknown-unknown/release/invoice_nft.wasm \
  --source deployer \
  --network testnet
# → Outputs: CONTRACT_ID  (copy this to NEXT_PUBLIC_INVOICE_CONTRACT_ID)

# 5. Deploy the Marketplace contract
stellar contract deploy \
  --wasm target/wasm32-unknown-unknown/release/marketplace.wasm \
  --source deployer \
  --network testnet
# → Outputs: CONTRACT_ID  (copy this to NEXT_PUBLIC_MARKETPLACE_CONTRACT_ID)

# 6. Deploy or note the USDC token contract
#    On testnet you can use the Stellar Lab USDC contract or deploy a test token.
#    Copy its contract ID to NEXT_PUBLIC_TOKEN_CONTRACT_ID.

# 7. Update .env.local with the three contract IDs, then:
NEXT_PUBLIC_ENABLE_MOCK_DATA=false npm run dev

Note: The v0.2 testnet addresses in .env.example are the canonical deployments. Override them only if you need a private deployment for development/testing.

Network-aware Contract Switching

lib/stellar/contracts.ts maintains a NETWORK_CONTRACTS registry keyed by network name. When NEXT_PUBLIC_STELLAR_NETWORK changes (e.g. testnetmainnet), the correct addresses are picked automatically — no code changes needed, only env vars.

To add mainnet addresses when ready, extend the registry:

// lib/stellar/contracts.ts
const NETWORK_CONTRACTS = {
  testnet: { invoice: "CBIELTK...", marketplace: "CBWOAOZ...", token: "CDLZFC3..." },
  mainnet: { invoice: "C...",       marketplace: "C...",       token: "C..."       },
};

Invoice Contract (lib/stellar/contracts.ts)

Method Description
mint_invoice(ipfs_cid, amount, financing_amount, discount_rate, due_date) Mints a new invoice NFT
get_invoice(token_id) Reads invoice state
update_status(token_id, status) Updates invoice status (owner only)

Marketplace Contract

Method Description
fund_invoice(token_id, amount) Investor funds an invoice
repay_invoice(token_id) SME repays; triggers yield distribution
get_positions(investor) Returns all investor positions

Transaction Flow

// 1. Build unsigned transaction
const unsignedXdr = await invoiceContract.mintInvoice(params, walletAddress);

// 2. Sign with wallet
const signedXdr = await walletKit.signTransaction(unsignedXdr, { ... });

// 3. Submit to Soroban RPC
const result = await rpc.sendTransaction(tx);

// 4. Poll for confirmation
const confirmed = await waitForTransaction(result.hash);

Contributing

See CONTRIBUTING.md for guidelines on how to contribute to this project.


Roadmap

  • v0.2 — Live Soroban contract deployment on testnet
  • v0.3 — KYC/KYB integration (Synaps or Fractal ID)
  • v0.4 — Secondary market for invoice positions
  • v0.5 — Risk oracle integration (on-chain credit scoring)
  • v0.6 — Multi-currency support (EURC, native XLM)
  • v1.0 — Mainnet launch

License

MIT © 2025 Kora Protocol Contributors


Built with ❤️ on Stellar Soroban

Stellar · Soroban · Next.js

About

Onchain invoice finance protocol

Resources

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages