Decentralized P2P Marketplace on Stellar Soroban — Trustless trading with secure escrow, soulbound reputation, and community-powered dispute resolution.
GitHub Actions runs on every push to main:
- Frontend → TypeScript type-check + Next.js production build
- Contracts → Rust/Soroban WASM compilation
Here are some UI screenshots of the project:
| Contract | Address | Deploy Tx |
|---|---|---|
marketplace_factory |
CDSBEWQJJB2TKSCYUHRRBPLD73YV65JS53X4GA3FX5EC3N2DABOEVAEF |
f8fb8abb2b8faef3186b3f9c611acc3cb77810f574574b654148e26924dd84ca |
trade_escrow (WASM) |
CAZ4R235C4NVV2UQ4K5VRBERGA22S7XUE2KUMWGMRO3XFOW3TMTZF54R |
199e94f02bbe735b784ddb5f33c70b1b455380e7b6db31b3397e599c38c3a1a3 |
dispute_oracle |
CB5OCX4D23NJUR2FI77AFYCHYUUWDHAU6WIF76YDVAQMRR2JZQK5SPY2 |
b005041320c62458598f9d935e5cbd2ad699407b0b1a9314e384fb6035b239e5 |
fee_vault |
CD5D43GGNHZG7V2TYVHIOP6IAIOS65BV43WZYAQPCBDNQWME5J2JOGMX |
e6c0a67611374a83dc66209371c8b0ee692dbf76e467179e0969cbbff070819d |
Inter-contract calls verified: TradeEscrow → DisputeOracle.create() on dispute initiation; MarketplaceFactory deploys TradeEscrow per trade.
| Token Name | TRUST |
| Contract | ReputationToken |
| Address | CAWPBDK4PITD5B54EAVN3H3EEGYYQZEHQ23SOL5QN6KKNERDX5ETJWAW |
| Type | Soulbound (non-transferable) on Stellar Testnet |
| Purpose | On-chain reputation — earned via trades, burned on dispute loss |
Peer-to-peer trading on the internet suffers from three critical issues:
- No Trust — Buyers fear sending money without receiving goods; sellers fear delivering without payment
- No Accountability — Bad actors can scam and create new accounts with zero consequences
- Centralized Middlemen — Platforms like eBay/Upwork take 10-20% fees and control dispute outcomes
TrustMarket DEX solves this with a fully on-chain P2P marketplace:
| Problem | TrustMarket Solution |
|---|---|
| No Trust | Smart contract escrow locks funds until delivery confirmed |
| No Accountability | Soulbound TRUST tokens create permanent reputation |
| Centralized Middlemen | Decentralized arbitration by staked community members |
- Buyer funds locked in smart contract until delivery confirmed
- Automatic timeout refunds if seller doesn't deliver (30-day expiry)
- 1% platform fee collected to FeeVault on successful trade
- Cancel anytime before funding (by buyer)
- Non-transferable — reputation can't be bought or sold
- +10 TRUST to seller, +5 to buyer on each completed trade
- -50 TRUST penalty to losing party in dispute
- Reputation decay over time (incentivizes active participation)
- Trust levels:
Newcomer (0)→Bronze (25)→Silver (50)→Gold (100)→Diamond (200+)
- Minimum 100 TRUST required to register as arbitrator
- Panel of arbitrators randomly selected from eligible pool
- Majority vote determines dispute outcome
- Three outcomes:
BuyerWins|SellerWins|Split (50/50) - 3-day voting window before force-finalize
- Real-time platform statistics
- Trade status distribution
- Success rate visualization
- Recent activity feed
An arbitrator is a trusted community member who has earned 100+ TRUST tokens through successful trading. They review disputed trades and vote on outcomes.
1. Complete trades → Earn TRUST tokens
(Seller gets +10 TRUST, Buyer gets +5 TRUST per trade)
2. Reach 100 TRUST minimum threshold
3. Register on /arbitrate page → "Register as Arbitrator"
(Calls reputation_token.register_arbitrator())
4. Get randomly assigned to disputes
fn select_arbitrators(env, buyer, seller) -> Vec<Address> {
// 1. Get all registered arbitrators
let all = storage.get(Arbitrators);
// 2. Filter: exclude buyer & seller, check active + min_rep
let eligible = all.filter(|a| a != buyer && a != seller
&& a.active && balance(a) >= min_rep);
// 3. Random selection using ledger timestamp + sequence as seed
let seed = ledger.timestamp() ^ ledger.sequence();
let selected = pick PANEL_SIZE from eligible using seed;
return selected; // Currently PANEL_SIZE = 1 (testnet)
}Buyer/Seller Escrow Contract Dispute Oracle
│ │ │
│── initiate_dispute() ─────►│ │
│ (reason: Symbol) │── create(dispute) ─────►│
│ │ │── select_arbitrators()
│ │ │── assign panel
│ │ │── start 3-day vote
│ │ │
│◄─── Dispute assigned ──────┼─────────────────────────│
│ │ │
│ (Arbitrators see dispute on /arbitrate) │
│ │ │
Arbitrator ──── vote() ──────────────────────────────► │
│ │ │── count votes
│ │ │── majority wins
│ │ │
│ │◄── resolve(outcome) ────│
│ │ │
│ │ BuyerWins → refund buyer, burn seller -50 TRUST
│ │ SellerWins → pay seller, burn buyer -50 TRUST
│ │ Split → 50/50, both -25 TRUST
│◄── Funds distributed ──────│ │
┌─────────────────────────────────────────────┐
│ ⚖️ Arbitrator Panel │
│ │
│ TRUST Score: 275 ████████░░░░ 275/100 │
│ ✅ Eligible for Arbitrator! │
│ │
│ Status: 🟢 Active Arbitrator │
│ │
│ Assigned Disputes: [Dispute #1] [Dispute #2]│
│ │
│ [Vote: BuyerWins] [Vote: SellerWins] [Split]│
│ │
│ ── Admin Tools (Testnet Only) ── │
│ [+100 TRUST Instantly] [Custom: ___] [Mint]│
└─────────────────────────────────────────────┘
Seller Smart Contract Buyer
│ │ │
│── create_trade() ────────►│ │
│ (sets buyer, seller, │ │
│ token, amount, desc) │ │
│ │◄──── lock_funds() ───────────│
│ │ (XLM locked in escrow) │
│ │ │
│ ──┼── NORMAL PATH ───────────────┼──
│ │◄──── confirm_delivery() ─────│
│ │ (buyer confirms) │
│◄─── funds released ──────│ │
│ (seller gets 99%) │── fee to FeeVault (1%) │
│◄─── +10 TRUST ───────────│──── +5 TRUST ───────────────►│
│ │ │
│ ──┼── DISPUTE PATH ──────────────┼──
│ │◄──── initiate_dispute() ─────│
│ │── dispute_oracle.create() ──►│
│ │ (select 1+ arbitrators) │
│ │ │
│ Arbitrator votes on /arbitrate page │
│ │ │
│ │◄── dispute_oracle.finalize() │
│◄─── BuyerWins: refund ───│ OR │
│◄─── SellerWins: pay ─────│ │
│◄─── Split: 50/50 ────────│ │
TrustMarket includes a protected admin panel accessible at /admin — not linked or indexed anywhere in the app.
- Navigate directly to
/adminin the browser - A passcode-protected gate authenticates access server-side (passcode is never exposed in the client bundle)
- 3 failed attempts trigger a 30-second lockout
- Session is persisted via
sessionStorageso you won't need to re-enter on the same tab
- Mint TRUST Tokens — Mint any amount of TRUST to any wallet address for testnet testing
- Quick preset buttons (50 / 100 / 200 / 500 TRUST) and custom amount input
- "Use my wallet" shortcut to auto-fill connected address
- Inline success/error feedback
- Passcode stored as
ADMIN_PASSCODEenvironment variable — server-side only (noNEXT_PUBLIC_prefix) - Defaults to
trust@admin2024on localhost if not set - Set your own in
frontend/.env.localbefore deploying:
# Server-side only — never sent to browser
ADMIN_PASSCODE=your_secure_passcode
⚠️ Always change the default passcode before deploying to production.
| Layer | Technology |
|---|---|
| Frontend | Next.js 14, TypeScript, TailwindCSS |
| State | Zustand |
| Smart Contracts | Rust, Soroban SDK v21 |
| Blockchain | Stellar Testnet (Soroban RPC) |
| Wallet | Freighter Browser Extension |
| Icons | Lucide React |
| Notifications | Custom inline toast system + EventToast |
TrustMarket DEX/
├── contracts/ # Soroban smart contracts (Rust)
│ ├── trade_escrow/ # Core escrow: lock, confirm, dispute, cancel
│ ├── marketplace_factory/ # Trade registry & listing, escrow deployer
│ ├── dispute_oracle/ # Arbitrator selection, voting, resolution
│ ├── reputation_token/ # Soulbound TRUST token + balance/balance_of
│ └── fee_vault/ # Fee collection & distribution
│
├── frontend/ # Next.js frontend
│ ├── app/
│ │ ├── page.tsx # Homepage
│ │ ├── dashboard/ # Analytics dashboard
│ │ ├── marketplace/ # Trade listings + detail + actions
│ │ ├── create/ # Create new trade
│ │ ├── arbitrate/ # Arbitrator Panel (register, vote)
│ │ ├── admin/ # Protected admin panel (passcode-gated)
│ │ ├── disputes/ # Dispute management
│ │ ├── vault/ # Staking interface
│ │ ├── profile/ # User profile + trust history
│ │ └── docs/ # Documentation
│ ├── components/
│ │ ├── EscrowActions.tsx # Lock/Confirm/Dispute/Cancel buttons + toasts
│ │ ├── EventToast.tsx # Blockchain event notifications
│ │ ├── Navbar.tsx # Navigation
│ │ └── WalletConnect.tsx # Freighter wallet connection
│ ├── stores/
│ │ ├── walletStore.ts # Freighter wallet state
│ │ ├── tradeStore.ts # Trade CRUD + BigInt fixes
│ │ ├── disputeStore.ts # Dispute fetch & actions
│ │ ├── reputationStore.ts # TRUST balance, arbitrator status, adminMint
│ │ └── vaultStore.ts # Fee vault state
│ └── lib/
│ ├── contracts.ts # Contract addresses (all networks)
│ ├── stellar.ts # invokeContract, readContract, signTransaction
│ └── events.ts # Stellar event stream
- Node.js 18+
- Rust & Cargo
- Stellar CLI (
stellar) - Freighter Wallet (browser extension) — Install
# Clone the repository
git clone https://github.com/iamomm-hack/TrustMarket-DEX.git
cd "TrustMarket DEX"
# Install frontend dependencies
cd frontend
npm install
# Run development server
npm run dev
# → http://localhost:3000cd contracts/<contract_name>
cargo build --target wasm32-unknown-unknown --release
# Output: contracts/target/wasm32-unknown-unknown/release/<name>.wasm| Contract | Address |
|---|---|
marketplace_factory |
CDSBEWQJJB2TKSCYUHRRBPLD73YV65JS53X4GA3FX5EC3N2DABOEVAEF |
reputation_token |
CAWPBDK4PITD5B54EAVN3H3EEGYYQZEHQ23SOL5QN6KKNERDX5ETJWAW |
dispute_oracle |
CB5OCX4D23NJUR2FI77AFYCHYUUWDHAU6WIF76YDVAQMRR2JZQK5SPY2 |
fee_vault |
CD5D43GGNHZG7V2TYVHIOP6IAIOS65BV43WZYAQPCBDNQWME5J2JOGMX |
trade_escrow (WASM) |
CAZ4R235C4NVV2UQ4K5VRBERGA22S7XUE2KUMWGMRO3XFOW3TMTZF54R |
Network: Stellar Testnet | RPC:
https://soroban-testnet.stellar.org
Soroban contracts return u64/i128 as JavaScript BigInt. All comparisons and arithmetic use explicit Number() conversion:
const count = Number(rawCount ?? 0); // Fix for for-loop BigInt comparisonreputation_token exposes both balance_of (standard) and balance (alias) so the dispute_oracle contract can call it correctly via cross-contract invocation.
The /arbitrate page includes an admin mint panel to quickly add TRUST tokens for testing dispute flows without completing many trades.
All escrow actions (Lock Funds, Confirm Delivery, Open Dispute, Cancel) show inline success/error toast that auto-dismisses after 5 seconds.
- < 5 second finality — instant trade confirmations
- < $0.01 transaction fees — accessible to everyone
- Soroban — production-ready smart contract platform
- Global reach — built for cross-border P2P commerce
- Stellar Community Fund — active ecosystem support
MIT License — free to use, modify, and distribute.
Built with ❤️ on Stellar for the decentralized future







