Unlocking liquidity for businesses. Earning yield for investors. Powered by Soroban smart contracts on Stellar.
Live Demo Β· API Docs Β· Smart Contracts Β· Report Bug Β· Request Feature
- The Problem
- The Solution
- System Architecture
- Smart Contract Design
- Backend Services
- Core Features
- Tech Stack
- Project Structure
- Getting Started
- Smart Contract Reference
- REST API Reference
- Frontend Guide
- Security Model
- Testing
- Deployment
- Environment Variables
- Roadmap
- Contributing
- License
Every year, $3.1 trillion in unpaid invoices paralyze businesses worldwide. Small and medium enterprises (SMEs) especially in emerging markets issue invoices to their buyers and then wait 30, 60, even 90 days for payment, while:
- Payroll comes due every two weeks
- Suppliers demand upfront cash
- Growth opportunities disappear while cash is frozen
Traditional invoice factoring exists to solve this β but it's broken:
| Pain Point | Reality |
|---|---|
| π¦ Gatekeeping | Only bankable businesses qualify |
| πΈ Opaque pricing | Discount rates are negotiated in the dark |
| π Geographic limits | Cross-border factoring is rare and expensive |
| β³ Slow settlement | Days of manual verification before cash is released |
| π Counterparty risk | No guarantees; trust-based with little recourse |
| π Double-financing fraud | Same invoice sold to multiple factors simultaneously |
FactorChain is a full-stack, on-chain invoice factoring marketplace built on Soroban β Stellar's smart contract platform. It pairs trustless smart contracts with a purpose-built off-chain backend that handles everything the blockchain cannot: document storage, search indexing, risk scoring, and real-time notifications.
Seller tokenizes invoice β Lists on marketplace β Investors bid
β β
Smart contract enforces Seller receives immediate USDC
payment at maturity β Buyer settles β Funds held in escrow contract
For sellers: Convert your receivables into immediate liquidity without a bank. For investors: Earn short-duration, real-yield returns backed by real-world invoices. For buyers: Structured, auditable payment commitments with on-chain settlement.
FactorChain is a three-layer system. Smart contracts handle all money and state. The backend handles everything off-chain. The frontend stitches both together.
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β FACTORCHAIN SYSTEM β
βββββββββββββββββββββββ¬βββββββββββββββββββββββββββ¬βββββββββββββββββββββββββ€
β FRONTEND (React) β BACKEND (NestJS) β SOROBAN CONTRACTS β
β β β β
β βββββββββββββββββ β ββββββββββββββββββββββ β ββββββββββββββββββββ β
β β Seller Portal ββββΌββΆβ REST API β β β InvoiceRegistry β β
β βββββββββββββββββ β β (NestJS) β β ββββββββββββββββββββ β
β β ββββββββββ¬ββββββββββββ β β β
β βββββββββββββββββ β β β ββββββββββββββββββββ β
β β Investor UI ββββΌββββββββββββ€ β β Marketplace β β
β βββββββββββββββββ β β β ββββββββββββββββββββ β
β β β ββββββββββΌββββββββββββ β β β
β Direct β β β Event Indexer ββββΌββββββββββββ€ β
β RPC β β β (Stellar events) β β ββββββββββββββββββββ β
β β β ββββββββββ¬ββββββββββββ β β EscrowContract β β
β βββββββββΌββββββββ β β β ββββββββββββββββββββ β
β β Buyer Panel β β ββββββββββΌββββββββββββ β β β
β βββββββββββββββββ β β PostgreSQL DB β β ββββββββββββββββββββ β
β β ββββββββββββββββββββββ β β LiquidityPool β β
β βββββββββββββββββ β β ββββββββββββββββββββ β
β β Admin / β β ββββββββββββββββββββββ β β β
β β Risk DashboardββββΌββΆβ Oracle Service ββββΌβββΆββββββββββββββββββββ β
β βββββββββββββββββ β β (risk scoring) β β β OracleContract β β
β β ββββββββββββββββββββββ β ββββββββββββββββββββ β
β β β β
β β ββββββββββββββββββββββ β β
β β β Document Service ββββΌβββΆ IPFS (Pinata) β
β β β (PDF β IPFS) β β β
β β ββββββββββββββββββββββ β β
β β β β
β β ββββββββββββββββββββββ β β
β β β Notification Svc β β β
β β β (Email / Webhook) β β β
β β ββββββββββββββββββββββ β β
βββββββββββββββββββββββ΄βββββββββββββββββββββββββββ΄βββββββββββββββββββββββββ
β
ββββββββββ΄βββββββββ
β Stellar Network β
β (XLM / USDC) β
βββββββββββββββββββ
| Responsibility | Handled By | Why |
|---|---|---|
| Fund custody & release | Smart contract | Trustless, non-custodial |
| Invoice lifecycle state | Smart contract | Immutable audit trail |
| Payment authorization | Smart contract | Wallet signature required |
| Invoice document storage | Backend β IPFS | Chain can't store files |
| Marketplace search & filtering | Backend (PostgreSQL) | Chain has no query layer |
| Risk scoring & oracle feeds | Backend β Oracle contract | Requires off-chain data |
| Email / webhook notifications | Backend | Chain can't call HTTP |
| KYB / compliance checks | Backend | Regulatory, off-chain |
| Event history & analytics | Backend (indexer) | Efficient historical queries |
FactorChain is composed of 5 core Soroban contracts, each with a single, auditable responsibility:
Handles the tokenization and lifecycle of invoices. Each invoice is minted as a unique on-chain record with a cryptographic hash of its off-chain document for tamper-proof verification.
pub struct InvoiceState {
pub seller: Address,
pub buyer: Address,
pub face_value: i128, // in stroops (USDC)
pub due_date: u64, // Unix timestamp
pub doc_hash: BytesN<32>, // SHA-256 of invoice PDF
pub status: InvoiceStatus, // Draft | Listed | Funded | Settled | Defaulted
pub created_at: u64,
}
pub enum InvoiceStatus {
Draft,
Listed,
Funded,
Settled,
Defaulted,
}Double-financing guard: Each (seller, doc_hash) pair is checked for uniqueness at mint time. Attempting to tokenize the same invoice twice results in a hard contract error.
Manages invoice listings, investor bids, and the auction/direct-sale mechanics. Supports two sale modes:
- Dutch Auction β Discount rate starts high and drops until a bid is placed
- Fixed-Rate Listing β Seller names a discount rate; first matching investor wins
pub struct Listing {
pub invoice_id: BytesN<32>,
pub mode: SaleMode,
pub discount_rate_bps: u32, // basis points, e.g. 250 = 2.5%
pub min_fill_pct: u32, // minimum % to accept (enables partial funding)
pub deadline: u64,
pub bids: Vec<Bid>,
}When a bid is accepted, funds move immediately from the investor to a time-locked escrow. The escrow contract:
- Releases principal + discount to the investor when the buyer settles
- Enforces a grace period before triggering a default flag
- Handles partial repayments gracefully
Allows passive investors to deposit USDC into a shared pool that auto-funds invoices within pre-set risk parameters. Pool shares are represented as fungible tokens, enabling secondary market trading of pool positions.
pub struct PoolConfig {
pub max_invoice_size: i128,
pub min_discount_rate_bps: u32,
pub max_tenor_days: u32,
pub max_single_buyer_exposure_pct: u32, // concentration limit
}An on-chain risk oracle that aggregates scores submitted by authorized backend oracle operators to produce a Buyer Risk Score (0β100) used to price invoices and gate pool eligibility. The backend oracle service is the sole authorized submitter.
The backend is a NestJS monorepo composed of four focused services, all sharing a single PostgreSQL database.
The primary interface for the frontend. Handles authentication, invoice document upload, and serves indexed marketplace data that the chain cannot efficiently query.
Responsibilities:
- JWT authentication (signed with Stellar wallet β no passwords)
- Invoice PDF upload β virus scan β SHA-256 hash β IPFS pin β return CID + hash
- Marketplace search and filtering (tenor, rate, risk score, buyer country)
- Portfolio analytics aggregation for sellers and investors
- Webhook registration for third-party integrations
A long-running process that streams Soroban contract events from the Stellar RPC node and writes structured records into PostgreSQL. This is what makes marketplace search fast.
Indexed events:
InvoiceMinted β invoices table
InvoiceListed β listings table
BidPlaced β bids table
BidAccepted β escrows table
InvoiceSettled β settlements table
InvoiceDefaulted β defaults table
PoolDeposit β pool_positions table
PoolWithdrawal β pool_positions table
Indexer guarantee: All writes are idempotent. Re-processing the same event twice produces the same database state β safe to replay on restart.
A scheduled service that fetches buyer credit signals from external data providers and submits risk scores to the OracleContract on-chain.
Data sources (configurable):
- Business registration APIs
- Trade credit bureau feeds
- On-chain payment history (from the indexer's
settlementstable) - Self-reported financial data (submitted via API)
Scoring pipeline:
Fetch signals β Normalize (0β100) β Weighted median β Submit to OracleContract
Runs on a 24-hour cron, with an on-demand re-score endpoint for newly registered buyers.
Listens to the indexer's event stream via an internal queue and dispatches notifications to users.
Triggers:
| Event | Notification Sent To |
|---|---|
| New bid on your listing | Seller (email + in-app) |
| Your bid was accepted | Investor (email + in-app) |
| Invoice due in 3 days | Buyer (email) |
| Invoice settled | Investor (email + in-app) |
| Invoice defaulted | Investor (email + in-app) |
| Pool auto-funded your invoice | Seller (in-app) |
Supports email (via Resend) and webhooks for B2B integrations.
- Guided invoice tokenization β Upload PDF; backend hashes, pins to IPFS, and mints on-chain in one flow
- Flexible funding modes β Dutch auction, fixed-rate, or pool auto-funding
- Partial funding support β Get funded for 50%, 75%, or 100% of invoice face value
- Real-time dashboard β Track listed, funded, and settled invoices in a single view
- Settlement reminders β Automated buyer notifications via email 3 days before due date
- Searchable marketplace β Filter by tenor, discount rate, buyer risk score, sector, and geography
- Liquidity pool β Deposit and earn yield passively; pool auto-allocates capital
- Portfolio analytics β Real-time IRR, weighted average tenor, and exposure breakdown
- Pool shares tradeable β Secondary liquidity on your pool position via SAC tokens
- Bid notifications β Instant alerts when bids are accepted or invoices settle
- Structured settlement β On-chain payment schedule with smart contract enforcement
- Reputation building β On-chain settlement history builds a verifiable, portable credit trail
- Multi-invoice netting β Settle multiple invoices in a single transaction
- Risk score transparency β View your own buyer risk score and the signals behind it
- Full auditability β Every state transition recorded on Stellar's immutable ledger
- Cross-border native β USDC-denominated; no FX risk, no correspondent banking fees
- Non-custodial β Funds always in smart contract escrow; platform never touches money
- Multi-wallet support β Freighter, Lobstr, Albedo, xBull
- Webhook API β B2B integrations with ERP systems (SAP, QuickBooks)
| Technology | Purpose |
|---|---|
| Rust | Contract implementation language |
| Soroban SDK | Stellar smart contract framework |
| soroban-cli | Build, deploy, and invoke contracts |
| cargo-llvm-cov | Contract test coverage |
| Technology | Purpose |
|---|---|
| Node.js 20 + TypeScript | Runtime and language |
| NestJS | Backend framework (monorepo) |
| PostgreSQL 16 | Primary database |
| Prisma | ORM and schema migrations |
| BullMQ + Redis | Job queue (indexer β notifications) |
| @stellar/stellar-sdk | Soroban RPC client & event streaming |
| Pinata SDK | IPFS document storage |
| Resend | Transactional email |
| Swagger / OpenAPI | Auto-generated API documentation |
| Passport + JWT | Wallet-based authentication |
| Zod | Runtime input validation |
| Technology | Purpose |
|---|---|
| React 18 + TypeScript | UI framework |
| Vite | Build tool |
| Stellar Wallets Kit | Multi-wallet connector |
| @stellar/stellar-sdk | Contract client bindings |
| Zustand | Client state management |
| TanStack Query | Server state, caching, background refetch |
| Tailwind CSS + shadcn/ui | Component library |
| Recharts | Portfolio analytics charts |
| Technology | Purpose |
|---|---|
| Docker + Docker Compose | Local development environment |
| GitHub Actions | CI/CD pipelines |
| Railway / Render | Backend hosting |
| Vercel | Frontend hosting |
| Upstash Redis | Managed Redis for job queue |
factorchain/
β
βββ contracts/ # Soroban smart contracts (Rust)
β βββ invoice-registry/
β β βββ src/
β β β βββ lib.rs # Contract entrypoint
β β β βββ invoice.rs # Invoice data types & state
β β β βββ mint.rs # Tokenization logic
β β β βββ validation.rs # Hash & duplicate checks
β β β βββ events.rs # Contract events
β β βββ Cargo.toml
β β βββ tests/
β βββ marketplace/
β β βββ src/
β β β βββ lib.rs
β β β βββ listing.rs
β β β βββ bidding.rs
β β β βββ matching.rs
β β β βββ events.rs
β β βββ Cargo.toml
β β βββ tests/
β βββ escrow/
β β βββ src/
β β β βββ lib.rs
β β β βββ escrow.rs
β β β βββ settlement.rs
β β β βββ default.rs
β β β βββ events.rs
β β βββ Cargo.toml
β β βββ tests/
β βββ liquidity-pool/
β β βββ src/
β β β βββ lib.rs
β β β βββ pool.rs
β β β βββ allocation.rs
β β β βββ shares.rs
β β β βββ events.rs
β β βββ Cargo.toml
β β βββ tests/
β βββ oracle/
β β βββ src/
β β β βββ lib.rs
β β β βββ score.rs
β β β βββ operators.rs
β β β βββ events.rs
β β βββ Cargo.toml
β β βββ tests/
β βββ shared/ # Shared types & error codes
β βββ src/
β βββ types.rs
β βββ errors.rs
β βββ constants.rs
β
βββ backend/ # NestJS monorepo
β βββ apps/
β β βββ api/ # REST API service
β β β βββ src/
β β β β βββ main.ts
β β β β βββ app.module.ts
β β β β βββ auth/ # Wallet-based JWT auth
β β β β β βββ auth.module.ts
β β β β β βββ auth.service.ts
β β β β β βββ stellar.strategy.ts
β β β β β βββ jwt.guard.ts
β β β β βββ invoices/ # Invoice CRUD & upload
β β β β β βββ invoices.module.ts
β β β β β βββ invoices.controller.ts
β β β β β βββ invoices.service.ts
β β β β β βββ dto/
β β β β βββ marketplace/ # Search & listing queries
β β β β β βββ marketplace.module.ts
β β β β β βββ marketplace.controller.ts
β β β β β βββ marketplace.service.ts
β β β β β βββ filters.dto.ts
β β β β βββ portfolio/ # Investor/seller analytics
β β β β β βββ portfolio.module.ts
β β β β β βββ portfolio.controller.ts
β β β β β βββ portfolio.service.ts
β β β β βββ buyers/ # Buyer profiles & risk scores
β β β β β βββ buyers.module.ts
β β β β β βββ buyers.controller.ts
β β β β β βββ buyers.service.ts
β β β β βββ webhooks/ # Outbound webhook management
β β β β βββ webhooks.module.ts
β β β β βββ webhooks.controller.ts
β β β β βββ webhooks.service.ts
β β β βββ test/
β β β
β β βββ indexer/ # Soroban event indexer
β β β βββ src/
β β β βββ main.ts
β β β βββ indexer.module.ts
β β β βββ stream.service.ts # Stellar RPC event stream
β β β βββ processor.service.ts # Event β DB writes
β β β βββ handlers/ # Per-event-type handlers
β β β βββ invoice.handler.ts
β β β βββ listing.handler.ts
β β β βββ escrow.handler.ts
β β β βββ pool.handler.ts
β β β
β β βββ oracle/ # Risk scoring oracle
β β β βββ src/
β β β βββ main.ts
β β β βββ oracle.module.ts
β β β βββ scorer.service.ts # Scoring pipeline
β β β βββ submitter.service.ts # On-chain score submission
β β β βββ providers/ # External data source adapters
β β β βββ credit-bureau.provider.ts
β β β βββ onchain-history.provider.ts
β β β βββ self-reported.provider.ts
β β β
β β βββ notifications/ # Notification dispatcher
β β βββ src/
β β βββ main.ts
β β βββ notifications.module.ts
β β βββ listener.service.ts # Listens to BullMQ events
β β βββ email.service.ts # Resend integration
β β βββ webhook.service.ts # Outbound webhook dispatch
β β
β βββ libs/
β β βββ prisma/ # Prisma client & schema
β β β βββ schema.prisma
β β β βββ migrations/
β β βββ soroban/ # Shared Soroban client
β β β βββ soroban.module.ts
β β β βββ soroban.service.ts
β β βββ common/ # Shared DTOs, guards, pipes
β β
β βββ docker-compose.yml # Local Postgres + Redis
β βββ nest-cli.json
β βββ package.json
β βββ tsconfig.json
β
βββ frontend/ # React + TypeScript frontend
β βββ src/
β β βββ features/
β β β βββ seller/
β β β βββ investor/
β β β βββ buyer/
β β β βββ admin/
β β βββ components/
β β β βββ ui/
β β β βββ invoice/
β β β βββ wallet/
β β β βββ charts/
β β βββ hooks/
β β β βββ useContract.ts # Direct Soroban RPC calls
β β β βββ useApi.ts # Backend REST API calls
β β β βββ useWallet.ts
β β β βββ useInvoice.ts
β β βββ lib/
β β β βββ soroban.ts
β β β βββ api.ts # Axios client (β backend)
β β β βββ utils.ts
β β βββ store/
β βββ package.json
β βββ tsconfig.json
β
βββ scripts/
β βββ deploy.sh # Contract deployment
β βββ initialize.sh # Post-deploy setup
β βββ seed-testnet.sh # Testnet data seeding
β
βββ .github/
β βββ workflows/
β βββ test-contracts.yml
β βββ test-backend.yml
β βββ test-frontend.yml
β βββ deploy.yml
β
βββ .env.example # β copy this to .env
βββ Cargo.toml # Rust workspace manifest
βββ README.md
# Rust (latest stable) + WASM target
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup target add wasm32-unknown-unknown
# Soroban CLI
cargo install --locked soroban-cli --features opt
# Node.js 20+
node --version # >= 20.0.0
# Docker (for local Postgres + Redis)
docker --version
# Generate a funded testnet keypair
soroban keys generate --global factorchain-dev --network testnetgit clone https://github.com/factorchain/factorchain.git
cd factorchain
# Copy environment template
cp .env.example .env
# β Edit .env with your keys (see Environment Variables section)cd backend
docker compose up -d
# Run database migrations
npx prisma migrate dev# Build all contracts
cargo build --target wasm32-unknown-unknown --release
# Deploy to testnet (writes addresses to .env automatically)
chmod +x scripts/deploy.sh
./scripts/deploy.sh --network testnet --account factorchain-devcd backend
npm install
# Start all services in development mode
npm run start:dev # API on :3000
npm run start:dev indexer # Indexer (background process)
npm run start:dev oracle # Oracle (cron + on-demand)
npm run start:dev notifications # Notification dispatcher
# Or start everything at once
npm run start:all:devAPI docs available at: http://localhost:3000/docs (Swagger UI)
cd frontend
npm install
npm run dev # http://localhost:5173Connect Freighter wallet (set to Testnet) and you're live.
| Function | Parameters | Description |
|---|---|---|
mint_invoice |
seller, buyer, face_value, due_date, doc_hash |
Tokenize a new invoice |
get_invoice |
invoice_id |
Fetch invoice state |
update_status |
invoice_id, new_status |
Update lifecycle status (authorized callers only) |
verify_document |
invoice_id, doc_hash |
Verify document hash matches on-chain record |
list_by_seller |
seller, page, page_size |
Paginated seller invoice history |
list_by_buyer |
buyer, page, page_size |
Paginated buyer invoice history |
| Function | Parameters | Description |
|---|---|---|
create_listing |
invoice_id, mode, discount_rate_bps, min_fill_pct, deadline |
List an invoice for funding |
place_bid |
listing_id, amount, rate_bps |
Submit a funding bid |
accept_bid |
listing_id, bid_id |
Accept bid; triggers escrow creation |
cancel_listing |
listing_id |
Cancel an unfunded listing |
get_listing |
listing_id |
Fetch listing details and bids |
| Function | Parameters | Description |
|---|---|---|
create_escrow |
invoice_id, investor, seller, amount, due_date |
Lock investor funds |
settle |
escrow_id |
Buyer repays; releases funds to investor |
partial_settle |
escrow_id, amount |
Partial repayment |
trigger_default |
escrow_id |
Mark defaulted after grace period |
get_escrow |
escrow_id |
Fetch escrow state |
| Function | Parameters | Description |
|---|---|---|
deposit |
amount |
Add USDC; receive pool share tokens |
withdraw |
share_amount |
Burn shares; receive proportional USDC |
auto_fund |
invoice_id |
Pool-fund an eligible invoice |
get_pool_state |
β | Total deposits, deployed capital, pending returns |
get_position |
investor |
Individual share balance and estimated value |
Base URL: https://api.factorchain.app/v1
Full interactive docs: /docs (Swagger UI)
All authenticated endpoints require:
Authorization: Bearer <jwt_token>
JWT tokens are obtained by signing a server-issued challenge with your Stellar wallet.
Request a sign challenge for a given Stellar address.
Request:
{ "address": "GABC...XYZ" }Response:
{ "challenge": "factorchain:auth:1718000000:abc123" }Submit signed challenge to receive a JWT.
Request:
{
"address": "GABC...XYZ",
"challenge": "factorchain:auth:1718000000:abc123",
"signature": "base64_signature_of_challenge"
}Response:
{ "access_token": "eyJ...", "expires_in": 86400 }Upload an invoice PDF. Returns the IPFS CID and SHA-256 hash to use when minting on-chain.
Request: multipart/form-data with field file (PDF, max 10MB)
Response:
{
"cid": "bafybei...",
"doc_hash": "a3f8c2...",
"ipfs_url": "https://ipfs.io/ipfs/bafybei..."
}Fetch enriched invoice data (on-chain state + off-chain metadata).
Response:
{
"invoice_id": "abc123...",
"seller": "GABC...XYZ",
"buyer": "GDEF...UVW",
"face_value": "50000.00",
"currency": "USDC",
"due_date": "2025-09-01T00:00:00Z",
"status": "Listed",
"doc_hash": "a3f8c2...",
"ipfs_url": "https://ipfs.io/ipfs/bafybei...",
"buyer_risk_score": 72,
"created_at": "2025-07-01T10:00:00Z"
}Search and filter active invoice listings.
Query parameters:
| Param | Type | Description |
|---|---|---|
min_rate_bps |
number | Minimum discount rate (basis points) |
max_rate_bps |
number | Maximum discount rate |
max_tenor_days |
number | Maximum days until due date |
min_risk_score |
number | Minimum buyer risk score (0β100) |
max_face_value |
number | Maximum invoice face value (USDC) |
page |
number | Page number (default: 1) |
page_size |
number | Results per page (default: 20, max: 100) |
Response:
{
"data": [
{
"listing_id": "lst_abc...",
"invoice_id": "inv_xyz...",
"face_value": "50000.00",
"discount_rate_bps": 250,
"tenor_days": 45,
"buyer_risk_score": 72,
"mode": "FixedRate",
"funded_pct": 0,
"deadline": "2025-07-10T00:00:00Z"
}
],
"total": 142,
"page": 1,
"page_size": 20
}Seller portfolio: all invoices with funding and settlement status.
Investor portfolio: active positions, settled returns, IRR.
Response (investor):
{
"total_deployed": "250000.00",
"total_returned": "182500.00",
"pending_return": "68750.00",
"realized_irr_pct": 14.2,
"positions": [
{
"escrow_id": "esc_abc...",
"invoice_id": "inv_xyz...",
"funded_amount": "25000.00",
"expected_return": "25625.00",
"due_date": "2025-09-01T00:00:00Z",
"status": "Active"
}
]
}Fetch the current on-chain risk score and contributing signals for a buyer address.
Response:
{
"address": "GDEF...UVW",
"risk_score": 72,
"score_date": "2025-07-01T00:00:00Z",
"signals": {
"on_chain_settlement_rate": 0.96,
"average_days_to_settle": 38,
"total_invoices_settled": 14,
"credit_bureau_score": 68
}
}Register a webhook URL to receive real-time event notifications.
Request:
{
"url": "https://your-erp.com/factorchain-events",
"events": ["invoice.settled", "invoice.defaulted", "bid.accepted"],
"secret": "your_webhook_secret"
}Webhook payload (example):
{
"event": "invoice.settled",
"timestamp": "2025-09-01T14:22:00Z",
"data": {
"invoice_id": "inv_xyz...",
"escrow_id": "esc_abc...",
"settled_amount": "50000.00",
"tx_hash": "abc123..."
}
}Payloads are signed with HMAC-SHA256 using your webhook secret. Verify the X-FactorChain-Signature header on receipt.
1. Connect wallet (Freighter / Lobstr / Albedo)
2. Seller Portal β New Invoice
3. Upload PDF β backend hashes + pins to IPFS β returns doc_hash
4. Fill details: buyer wallet, face value, due date
5. Sign & submit β InvoiceRegistry.mint_invoice() with doc_hash
6. Choose listing mode: Fixed Rate or Dutch Auction
7. Submit listing β MarketplaceContract.create_listing()
8. Monitor bids in real-time (indexed by backend, served via REST)
9. Accept a bid β EscrowContract.create_escrow() triggered
10. USDC arrives in seller wallet immediately (minus discount)
1. Connect wallet
2. Marketplace β filter by tenor, rate, risk score
3. Click invoice β view details + buyer risk score from API
4. Place bid or direct fund (on-chain transaction)
5. Funds locked in EscrowContract
6. Monitor portfolio via /portfolio/investor endpoint
7. Receive notification when invoice settles or defaults
1. Connect wallet (must match buyer address on invoice)
2. Pending Settlements dashboard (served by backend indexer)
3. Click invoice β see face value due + due date
4. Settle β USDC transferred to EscrowContract
5. EscrowContract releases funds to investor
6. Invoice status updated on-chain; indexer syncs to DB
| Threat | Mitigation |
|---|---|
| Double-financing fraud | (seller, doc_hash) uniqueness enforced at mint time |
| Unauthorized status updates | Role-based access; only authorized contract addresses can call update_status |
| Front-running bids | Commitment-reveal scheme for Dutch auction bids |
| Reentrancy | Soroban's execution model prevents cross-contract reentrancy by design |
| Oracle manipulation | Multi-signal median aggregation; outlier rejection; operator whitelist |
| Escrow theft | Funds only releasable to pre-set addresses; no admin withdrawal function |
| Integer overflow | All arithmetic uses Soroban's checked arithmetic primitives |
| Threat | Mitigation |
|---|---|
| Document tampering | SHA-256 hash stored on-chain; backend verifies before serving |
| API auth bypass | Wallet-signed challenge; no passwords, no sessions |
| Forged webhook events | HMAC-SHA256 payload signing with per-endpoint secrets |
| Oracle data manipulation | Multi-provider aggregation; scores anchored to on-chain settlement history |
| SQL injection | Prisma ORM parameterized queries throughout |
| Rate abuse | Per-IP and per-wallet rate limiting on all API endpoints |
| Indexer replay attacks | Idempotent event writes keyed on (contract_address, ledger_sequence, event_index) |
β οΈ FactorChain smart contracts are unaudited. Do not use with real funds until a formal security audit has been completed.Audit engagement is planned for Q4 2025 before any mainnet deployment.
# Run all contract unit tests
cargo test
# Run with output
cargo test -- --nocapture
# Run a specific test
cargo test test_double_financing_rejected -- --nocapture
# Run cross-contract integration tests
cargo test --test integration -- --nocapture
# Generate coverage report
cargo install cargo-llvm-cov
cargo llvm-cov --all-features --workspace --htmlKey test scenarios:
- Full invoice lifecycle: mint β list β bid β accept β settle
- Dutch auction price decay and bid acceptance
- Pool auto-funding with risk filter gating
- Default workflow: escrow creation β grace period β default flag
- Partial funding and partial settlement flows
cd backend
# Unit tests
npm run test
# Integration tests (requires Docker services running)
npm run test:e2e
# Coverage report
npm run test:covKey backend test scenarios:
- Invoice upload: PDF hashing, IPFS pinning, duplicate detection
- Marketplace search: filter combinations, pagination, sorting
- Indexer: idempotent event processing, replay safety
- Oracle: scoring pipeline, on-chain submission, signal weighting
- Auth: challenge generation, signature verification, JWT expiry
cd frontend
npm test # Vitest unit tests
npm run test:e2e # Playwright end-to-end tests# Start all infrastructure
cd backend && docker compose up -d
# Start all backend services
npm run start:all:dev
# Start frontend
cd ../frontend && npm run dev# Deploy contracts
./scripts/deploy.sh --network testnet --account factorchain-dev
# Deploy backend (Railway)
railway up --service api
railway up --service indexer
railway up --service oracle
railway up --service notifications
# Deploy frontend (Vercel)
cd frontend && vercel --prod
β οΈ Mainnet deployment requires a completed security audit and a 3-of-5 multisig approval.
./scripts/deploy.sh --network mainnet --account factorchain-mainnetContract upgrades are controlled by the admin multisig (3-of-5 key threshold). No single key can upgrade any contract unilaterally.
Testnet addresses will be published here upon first testnet deployment. Mainnet deployment is pending audit completion.
Copy .env.example to .env and fill in all values before running any service.
# βββ Stellar / Soroban ββββββββββββββββββββββββββββββββββββββββ
STELLAR_NETWORK=testnet
SOROBAN_RPC_URL=https://soroban-testnet.stellar.org
STELLAR_NETWORK_PASSPHRASE="Test SDF Network ; September 2015"
ORACLE_OPERATOR_SECRET=S... # Stellar secret key for oracle submissions
# βββ Contract Addresses (populated by deploy.sh) ββββββββββββββ
INVOICE_REGISTRY_CONTRACT=C...
MARKETPLACE_CONTRACT=C...
ESCROW_CONTRACT=C...
LIQUIDITY_POOL_CONTRACT=C...
ORACLE_CONTRACT=C...
# βββ Database βββββββββββββββββββββββββββββββββββββββββββββββββ
DATABASE_URL=postgresql://user:pass@localhost:5432/factorchain
# βββ Redis ββββββββββββββββββββββββββββββββββββββββββββββββββββ
REDIS_URL=redis://localhost:6379
# βββ IPFS / Pinata ββββββββββββββββββββββββββββββββββββββββββββ
PINATA_API_KEY=...
PINATA_SECRET=...
# βββ Auth βββββββββββββββββββββββββββββββββββββββββββββββββββββ
JWT_SECRET=... # Minimum 32 random characters
JWT_EXPIRES_IN=86400 # Seconds (24h)
# βββ Email ββββββββββββββββββββββββββββββββββββββββββββββββββββ
RESEND_API_KEY=re_...
EMAIL_FROM=notifications@factorchain.app
# βββ Frontend (Vite) ββββββββββββββββββββββββββββββββββββββββββ
VITE_API_BASE_URL=http://localhost:3000/v1
VITE_SOROBAN_RPC_URL=https://soroban-testnet.stellar.org
VITE_NETWORK_PASSPHRASE="Test SDF Network ; September 2015"
VITE_INVOICE_REGISTRY_CONTRACT=C...
VITE_MARKETPLACE_CONTRACT=C...
VITE_ESCROW_CONTRACT=C...
VITE_LIQUIDITY_POOL_CONTRACT=C...- Invoice tokenization (InvoiceRegistry contract)
- Fixed-rate marketplace listings
- Single-investor escrow and settlement
- Backend API + event indexer
- Basic seller and investor frontend portals
- Testnet deployment
- Dutch auction mechanism
- Partial funding (multiple investors per invoice)
- Liquidity pool contract + passive yield
- Buyer settlement portal
- Oracle service v1 (on-chain risk scoring)
- Email notification service
- Pool share token secondary market
- Multi-currency support (EURC, BRLA)
- Advanced oracle with ML-assisted scoring
- Webhook API for ERP integrations
- Mobile app (React Native)
- Security audit completion
- DAO governance for pool risk parameters
- Cross-chain bridge (Ethereum USDC β Stellar)
- Insurance layer for default protection
- Mainnet launch
FactorChain is built in the open. We welcome Rust developers, TypeScript engineers, security researchers, and domain experts in trade finance.
- Fork the repository
- Create a feature branch:
git checkout -b feat/your-feature-name - Write tests β required for all PRs touching
contracts/orbackend/ - Run the full test suite:
cargo test && cd backend && npm test - Submit a PR β describe what changed and why, and link any related issues
See CONTRIBUTING.md for full guidelines including commit message format, PR review process, and code style.
- π¦ Rust / Soroban β Contract features, gas optimization, security review
- π Security β Audit contracts and backend; open issues for any findings
- βοΈ Backend β Oracle data providers, indexer performance, additional API endpoints
- π¨ Frontend β UX improvements, mobile responsiveness, accessibility
- π Documentation β User guides, integration tutorials, video walkthroughs
- π Translations β Priority: Portuguese, French, Swahili
MIT License β see LICENSE for details.
- Stellar Development Foundation β for Soroban and the Stellar ecosystem
- Circle β for USDC on Stellar
- Pinata β for IPFS infrastructure
- NestJS β for the backend framework
- The global factoring community for decades of financial infrastructure that FactorChain builds upon