Trust-based, collateral-free lending on Stellar.
StellarCred lets users borrow without locking up collateral. Instead of assets, creditworthiness is determined by on-chain behaviour, repayment history, and social endorsements — a human-based credit system built natively on Stellar's payment and identity primitives.
- Why Stellar
- How It Works
- Architecture
- Repo Structure
- Tech Stack
- Credit Scoring Model
- Loan Lifecycle
- Getting Started
- Running Tests
- API Reference
- Smart Contracts (Soroban)
- Roadmap
- Contributing
Most DeFi lending protocols require over-collateralisation — you lock up $150 to borrow $100. This excludes the majority of the world who need credit precisely because they don't have assets to lock up.
Stellar is uniquely suited to fix this:
| Stellar Primitive | How StellarCred Uses It |
|---|---|
| Accounts with signers | Identity anchor for borrowers and lenders |
| Trustlines | Native credit relationships between accounts |
| Anchors (USDC, fiat) | Real-money disbursement and repayment |
| Low fees (~0.00001 XLM) | Micro-credit becomes economically viable |
| 5-second finality | Near-instant loan disbursement |
| Soroban smart contracts | On-chain loan validation and debt tracking |
- Join — Connect your Stellar wallet. Your public key is your identity.
- Build reputation — Your credit score (0–1000) is computed from your on-chain history and social endorsements.
- Get endorsed — Existing users vouch for you. Their reputation is at stake if you default.
- Borrow — Request a loan. If your score meets the threshold, USDC is disbursed to your account.
- Repay — Repay on time and your score increases. Default and your score drops — and so do your endorsers'.
┌──────────────────────────────────────────────────────┐
│ Web App (Next.js) │
│ Dashboard · Loan Form · Credit Score · Trust Graph │
└────────────────────────┬─────────────────────────────┘
│ REST
┌────────────────────────▼─────────────────────────────┐
│ API (Node.js / Express) │
│ /loans /reputation /endorsements /users │
├──────────────────────────────────────────────────────┤
│ Reputation Engine Trust Graph │
│ (4-factor scorer) (Neo4j — Phase 4) │
├──────────────────────────────────────────────────────┤
│ Stellar SDK + Soroban │
│ Trustlines · Asset Issuance · Credit Manager │
│ Reputation Oracle · Debt Token │
├──────────────────────────────────────────────────────┤
│ PostgreSQL (loans, users, endorsements) │
│ IPFS (score snapshots / audit trail) │
└──────────────────────────────────────────────────────┘
Off-chain scoring, on-chain enforcement. The reputation engine runs off-chain (fast, cheap, upgradeable) but writes scores to the on-chain ReputationOracle contract. The CreditManager contract reads from the oracle before approving any loan — so the chain is the source of truth for approvals.
Issuer model for credit. The protocol acts as the USDC issuer. When a loan is approved, USDC is issued to the borrower's account. Repayment burns the corresponding DebtToken balance tracked on-chain.
Social slashing. Endorsers stake their reputation. If a borrower defaults, all endorsers take a proportional score penalty. This creates real skin-in-the-game without requiring token collateral.
stellar-cred/
├── apps/
│ ├── api/ # Node.js REST API
│ │ └── src/
│ │ ├── db/ # SQL migrations
│ │ ├── middleware/ # Auth (Stellar pubkey validation)
│ │ ├── models/ # TypeScript types
│ │ ├── routes/ # loans, reputation, endorsements, users
│ │ └── services/ # loanService, reputationService, stellarService, endorsementService
│ └── web/ # Next.js frontend
│ └── src/
│ ├── components/ # CreditScore, LoanForm, TrustNetwork
│ ├── hooks/ # useStellarWallet
│ ├── lib/ # apiFetch helper
│ └── pages/ # index, dashboard, loan
├── contracts/ # Soroban smart contracts (Rust)
│ ├── credit-manager/ # Loan lifecycle + debt cap + oracle check
│ ├── reputation-oracle/ # Score store, readable cross-contract
│ └── debt-token/ # Mint/burn outstanding debt balances
├── packages/
│ ├── reputation-engine/ # 4-factor credit scorer (pure TS, tested)
│ ├── stellar-client/ # Horizon SDK wrappers (trustlines, asset issuance)
│ └── trust-graph/ # Neo4j endorsement graph (Phase 4)
├── infra/
│ └── docker-compose.yml # Postgres + Neo4j + IPFS
├── docs/
│ ├── architecture.md
│ ├── scoring-model.md
│ └── loan-lifecycle.md
├── .env.example
└── turbo.json # Turborepo monorepo config
| Layer | Technology |
|---|---|
| Frontend | Next.js 14, React 18, TypeScript |
| API | Node.js, Express, TypeScript |
| Smart Contracts | Soroban (Rust), Stellar SDK |
| Reputation Engine | TypeScript (pure, no runtime deps) |
| Primary DB | PostgreSQL 16 |
| Graph DB | Neo4j 5 (trust graph — Phase 4) |
| Storage | IPFS (score snapshots) |
| Monorepo | Turborepo + npm workspaces |
| Testing | Jest + ts-jest (TS), Soroban test harness (Rust) |
Scores range from 0 to 1000. A minimum of 500 is required to borrow.
| Factor | Weight | Source | Notes |
|---|---|---|---|
| Repayment history | 40% | On-chain loan records | repaid / (repaid + defaulted) |
| Account age | 20% | Horizon API | Capped at 365 days |
| Transaction volume | 20% | Horizon API | Operation count, capped at 500 |
| Social endorsements | 20% | Trust graph | Endorser count, capped at 10 |
| Score | Band | Max Loan |
|---|---|---|
| 0–499 | Poor — ineligible | — |
| 500–649 | Fair | $100 |
| 650–799 | Good | $500 |
| 800–1000 | Excellent | $1,000 |
When a borrower defaults, each endorser loses:
penalty = default_amount_usd / endorser_count (in score points)
This creates genuine accountability — endorsers only vouch for people they trust.
REQUESTED ──► APPROVED ──► ACTIVE ──► REPAID
│ │
REJECTED DEFAULTED
| State | Trigger | Effect |
|---|---|---|
| REQUESTED | Borrower submits request | Score check begins |
| APPROVED | Score ≥ 500 | USDC issued, DebtToken minted |
| REJECTED | Score < 500 | No funds moved |
| ACTIVE | Funds disbursed | Repayment clock starts |
| REPAID | Full repayment received | DebtToken burned, score +boost |
| DEFAULTED | Missed deadline | Score slashed, endorsers penalised |
- Node.js ≥ 20
- Rust +
wasm32-unknown-unknowntarget (for contracts) - Docker (for local Postgres + Neo4j + IPFS)
git clone https://github.com/your-org/stellar-cred
cd stellar-cred
npm installcp .env.example .env
# Fill in STELLAR_ISSUER_SECRET, DATABASE_URL, etc.docker compose -f infra/docker-compose.yml up -dpsql $DATABASE_URL -f apps/api/src/db/001_initial.sqlnpm run dev # starts both API (:3001) and web (:3000) via Turborepo# All TypeScript tests (API + reputation engine)
npm run test --workspaces
# API only
cd apps/api && npx jest
# Reputation engine only
cd packages/reputation-engine && npx jest
# Soroban contracts (Rust)
cd contracts && cargo testCurrent test coverage:
| Suite | Tests | Status |
|---|---|---|
| API (routes, services, auth) | 30 | ✅ passing |
| Reputation engine (factors + scorer) | 19 | ✅ passing |
| Soroban contracts (credit-manager, oracle, debt-token) | 21 | ✅ passing |
| Total | 70 | ✅ |
All endpoints require Authorization: Bearer <stellar-pubkey>.
GET /reputation/:pubkey
→ { pubkey, score, eligible, breakdown: { repayment, age, volume, endorsements } }
POST /loans
Body: { amount: number, duration_days: number }
→ Loan object (201)
GET /loans
→ Loan[] for the authenticated user
GET /loans/:id
→ Loan object
PATCH /loans/:id/repay
→ Updated Loan object
POST /endorsements
Body: { borrower_pubkey: string }
→ Endorsement object (201)
GET /endorsements/:pubkey
→ Endorsement[] for the given pubkey
GET /users/me
→ { pubkey }
All contracts are in contracts/ and written in Rust for the Soroban VM.
Tracks the full loan lifecycle on-chain.
| Function | Description |
|---|---|
initialize(admin, min_score) |
One-time setup |
set_oracle(oracle_address) |
Register the ReputationOracle contract |
create_loan(borrower, amount, duration_ledgers) |
Validates score via oracle, enforces debt cap, emits event |
repay(loan_id) |
Marks repaid, reduces borrower debt balance |
default_loan(loan_id) |
Marks defaulted, reduces borrower debt balance |
borrower_debt(address) |
Returns total outstanding debt for an address |
Admin-controlled score store. Readable cross-contract by CreditManager.
| Function | Description |
|---|---|
set_score(account, score) |
Write score 0–1000, emits event |
get_score(account) |
Read score (0 if unset) |
is_eligible(account, min_score) |
Returns bool — used by CreditManager |
Tracks outstanding debt balances. Minted on loan creation, burned on repayment/default.
| Function | Description |
|---|---|
mint(to, amount) |
Increase debt balance + total supply |
burn(from, amount) |
Decrease debt balance + total supply |
balance_of(account) |
Outstanding debt for an address |
total_supply() |
Protocol-wide total outstanding debt |
| Phase | Status | Description |
|---|---|---|
| 1 — Foundations | ✅ Done | Monorepo, Stellar SDK setup, account/trustline primitives |
| 2 — Basic Lending MVP | ✅ Done | Loan CRUD, auth middleware, in-memory store, API routes |
| 3 — Reputation System | 🔄 In progress (30%) | 4-factor scorer, endorsements, Soroban oracle integration |
| 4 — Trust Graph | ⬜ Planned | Neo4j graph, weighted endorsement edges, social slashing |
| 5 — Soroban Integration | ⬜ Planned | Cross-contract calls, WASM deployment, Horizon event indexing |
| 6 — UI/UX | ⬜ Planned | Freighter wallet, trust network visualisation, full dashboard |
| 7 — Production | ⬜ Planned | PostgreSQL persistence, IPFS score snapshots, mainnet deploy |
- Fork the repo and create a feature branch.
- Run
npm installfrom the root. - Make your changes — all tests must pass before opening a PR.
- Run
cargo testincontracts/if you touched Rust. - Open a PR with a clear description of what changed and why.
MIT