Skip to content

Debjanimandal/FairDeal

Repository files navigation

FairDeal Logo

FairDeal

Trustless Freelance Escrow Platform on Stellar Testnet

Stellar Testnet Next.js Vercel Soroban IPFS MIT

Live Demo  ·  GitHub  ·  Contract Explorer


FairDeal is a trustless freelance escrow platform built on the Stellar blockchain. Clients lock funds in a Soroban smart contract, freelancers deliver work securely via AES-256 encrypted IPFS uploads, and payments are released automatically — all without a central authority. Built for the Stellar Rise hackathon — Level 3 submission.


Table of Contents

  1. Project Overview
  2. Problem Statement
  3. Solution
  4. Tech Stack
  5. Current Features
  6. Architecture
  7. Setup Instructions
  8. Deployment Notes
  9. Smart Contract Reference
  10. Proof of Functionality
  11. Test Results (5 tests passing)
  12. Screenshots
  13. Demo Video

1. Project Overview

FairDeal is a decentralized freelance marketplace on Stellar Testnet that removes the need for any trusted intermediary. A client posts a job and locks the agreed XLM payment into a Soroban smart contract. A freelancer claims the job, encrypts their deliverable with AES-256-CBC, and pins it to IPFS. The client sees a server-generated watermarked preview before releasing funds. On approval, the smart contract pays the freelancer and releases the decryption key — all enforced by on-chain code, not by FairDeal.

The application is a full-stack Next.js mini-dApp demonstrating the complete Stellar developer lifecycle: wallet authentication (Freighter), on-chain escrow (Soroban FairDealContract on Testnet), IPFS file storage (Pinata), AES-256 encryption (Node.js crypto), and watermarked preview generation (Jimp).


2. Problem Statement

Freelancing platforms today act as trusted gatekeepers: they hold client funds, control dispute outcomes, charge significant platform fees (5–20%), and can freeze accounts without recourse. There is no trustless, blockchain-enforced alternative on Stellar that covers the full freelance workflow — from escrow creation through encrypted file delivery to on-chain payment release.


3. Solution

FairDeal replaces the platform middleman with a Soroban smart contract. The complete flow is:

  1. Connect Wallet — Client connects their Freighter wallet. No account creation needed — the Stellar public key is the identity.
  2. Post a Job — Client calls create_job() on the Soroban contract, locking XLM in escrow. A configurable initial payment is released immediately; the remainder is held until approval.
  3. Submit Work — Freelancer encrypts their deliverable with AES-256-CBC and uploads it to IPFS via Pinata. The IPFS CID is recorded on-chain via submit_work().
  4. Review Preview — The server generates a watermarked preview image so the client can verify quality without receiving the full file.
  5. Approve & Pay — Client calls approve_work(). The contract releases escrowed XLM to the freelancer. The decryption key is returned for download.
  6. Fraud & Revision — Clients can call request_revision() (funds stay locked) or raise_fraud_flag() (funds refunded, fraud count incremented on-chain for the freelancer's address).

4. Tech Stack

Layer Technology
Frontend Next.js 14 (App Router), React 18, TypeScript
Styling Tailwind CSS, custom dark theme
Wallet @stellar/freighter-api v6
Stellar SDK @stellar/stellar-sdk v14
Smart Contract Soroban (Rust, soroban-sdk), deployed to Stellar Testnet
File Storage IPFS via Pinata (@pinata/sdk)
Encryption AES-256-CBC (Node.js crypto)
Watermarking Jimp
API Layer Next.js API Routes (Node.js serverless)
Deployment Vercel (frontend + API routes)
Contract Deployment Stellar Testnet via stellar contract deploy

5. Current Features

✅ Wallet Authentication

  • Freighter wallet connection in one click — no account creation
  • Wallet state persisted across pages via React context
  • Disconnect and reconnect supported
  • Stellar Testnet network enforced throughout

✅ On-Chain Escrow via Soroban Contract

  • create_job() locks client XLM in the contract with configurable initial payment and deadline
  • approve_work() releases escrowed funds directly to the freelancer's Stellar address
  • cancel_deal() refunds the client on-chain
  • request_revision() keeps funds locked while the freelancer revises
  • All fund movements require a Freighter wallet signature — FairDeal cannot touch funds

✅ Encrypted IPFS File Storage

  • Freelancer files are encrypted client-side with AES-256-CBC before upload
  • Encrypted blobs are pinned to IPFS via Pinata — no central file server
  • Encryption keys are only released after client approval
  • Even with the IPFS CID, the file is unreadable without the key

✅ Watermarked Preview System

  • On submission, Jimp generates a watermarked preview image server-side
  • Clients verify work quality from the preview before releasing payment
  • The clean, unwatermarked file is only accessible post-approval
  • Prevents misuse of deliverables before payment

✅ Fraud Flag & Reputation System

  • raise_fraud_flag() records a fraud event against the freelancer's address on-chain
  • Fraud flag count is incremented in persistent contract storage per address
  • Immutable, publicly verifiable on Stellar Expert
  • Refunds client escrow on flag

✅ Full Job Lifecycle State Machine

Created → Submitted → Approved ✅
                    ↘ Revision Requested 🔄
                    ↘ Rejected ❌
                    ↘ Fraud Flagged 🚩

✅ Loading States & Progress Indicators

  • Step-by-step progress shown during job creation, work submission, and approval flows
  • Error states surfaced clearly with retry options
  • Wallet connection status shown in the navbar at all times

✅ Basic Caching

  • IPFS CIDs and job metadata cached in a local data layer (/data) for fast reads
  • Server-side Pinata calls cached to avoid redundant re-uploads on page refresh

6. Architecture

┌───────────────────────────────────────────────────────────┐
│                   Next.js App (Vercel)                     │
│                                                            │
│  Pages: / (landing)  /create-job  /jobs/[id]              │
│         /submit-work/[id]  /login  /profile                │
│                                                            │
│  ┌──────────────┐   ┌───────────────────────┐             │
│  │ WalletProvider│   │ JobDetail / SubmitWork│             │
│  │ (Freighter)   │   │ CreateJob / Profile   │             │
│  └──────┬────────┘   └──────────┬────────────┘            │
│         │                       │                          │
│  ┌──────▼───────────────────────▼──────────────┐          │
│  │         utils/contract-utils.ts              │          │
│  │  createJob / submitWork / approveWork        │          │
│  │  cancelDeal / requestRevision / fraudFlag    │          │
│  │  getJob / getJobCount / getFraudCount        │          │
│  └──────────────────┬──────────────────────────┘          │
│                     │                                      │
│  ┌──────────────────▼──────────────────────────┐          │
│  │          API Routes (Next.js)                │          │
│  │  POST /api/jobs          — create job record │          │
│  │  GET  /api/jobs          — fetch all jobs    │          │
│  │  POST /api/ipfs/upload   — encrypt + pin     │          │
│  │  POST /api/decrypt-file  — decrypt on approve│          │
│  │  GET  /api/freelancers   — fraud flag data   │          │
│  └──────────────────────────────────────────────┘          │
└───────────────────────────────────────────────────────────┘
         │                          │
         ▼                          ▼
┌──────────────────┐    ┌───────────────────────┐
│  Stellar Testnet  │    │   Pinata / IPFS        │
│                   │    │   (encrypted files)    │
│  Horizon RPC      │    └───────────────────────┘
│  Soroban RPC      │
│                   │
│  FairDealContract │
│  CBONHP...WUFDM   │
└──────────────────┘

Data Flow — Job Creation: Client connects Freighter → create_job() signed → Soroban contract locks XLM in escrow → job record stored → job ID returned

Data Flow — Work Submission: Freelancer uploads file → AES-256-CBC encryption → Pinata IPFS pin → CID recorded on-chain via submit_work() → Jimp watermark preview generated

Data Flow — Approval: Client approves → approve_work() signed → contract releases escrowed XLM to freelancer → decryption key returned → client downloads clean file


7. Setup Instructions

Prerequisites

  • Node.js 18+
  • A Freighter Wallet browser extension with a funded Testnet account
  • A free Pinata account for IPFS
  • (For contract redeployment) Rust + stellar CLI

Install & Run

# Clone the repository
git clone https://github.com/Debjanimandal/FairDeal.git
cd FairDeal

# Install dependencies
npm install

# Create environment file
cp .env.example .env.local
# (or create .env.local manually — see variables below)

# Start development server
npm run dev

App runs at http://localhost:3000.

Environment Variables

Create a .env.local file with the following:

# Stellar network
NEXT_PUBLIC_STELLAR_NETWORK=testnet

# Deployed Soroban FairDeal escrow contract on Stellar Testnet
NEXT_PUBLIC_CONTRACT_ID=CBONHPWFT7D2USWDGC5G55LJNBCRRTN4YQE6O6CFJA3RROIQ4UIWUFDM

# Platform escrow account (generates a Stellar keypair at laboratory.stellar.org)
ESCROW_SECRET_KEY=your_escrow_secret_key
ESCROW_PUBLIC_KEY=your_escrow_public_key

# IPFS via Pinata
PINATA_API_KEY=your_pinata_api_key
PINATA_SECRET_API_KEY=your_pinata_secret

💡 Tip: Fund your escrow account on Testnet via Stellar Friendbot. Get free Pinata API keys at pinata.cloud. All values target Stellar Testnet — no real funds are involved.

Build

npm run build   # production build
npm run start   # start production server

(Optional) Redeploy the Smart Contract

cd contract
cargo build --target wasm32-unknown-unknown --release
stellar contract optimize --wasm target/wasm32-unknown-unknown/release/fairdeal_escrow.wasm
stellar contract deploy \
  --wasm target/wasm32-unknown-unknown/release/fairdeal_escrow.optimized.wasm \
  --source-account default \
  --network testnet

Update NEXT_PUBLIC_CONTRACT_ID in .env.local with your new contract address.


8. Deployment Notes

  • Frontend + API routes are deployed together on Vercel via the Next.js integration. API routes run in the Node.js serverless runtime, which is required for @stellar/stellar-sdk, crypto, and jimp.
  • Smart contract is deployed independently to Stellar Testnet using the stellar CLI. The contract address is baked into the environment variables — no redeployment is required to run the app against the existing contract.
  • IPFS files are pinned on Pinata's infrastructure. Encrypted CIDs are stored in the /data directory and on-chain via submit_work().
  • Testnet accounts must be funded via Stellar Testnet Friendbot before they can create jobs or send transactions.
  • CI/CD is handled by Vercel's GitHub integration — every push to main triggers an automatic production deployment.

9. Smart Contract Reference

Item Value
Contract ID CBONHPWFT7D2USWDGC5G55LJNBCRRTN4YQE6O6CFJA3RROIQ4UIWUFDM
Network Stellar Testnet
Language Rust (Soroban SDK)
Explorer View on Stellar Expert

Contract Functions

Function What it does Requires Wallet?
create_job Locks client XLM in escrow; releases initial payment to freelancer ✅ Yes
submit_work Records the IPFS CID of submitted encrypted work on-chain ❌ No
approve_work Releases remaining escrowed XLM to the freelancer ✅ Yes
cancel_deal Refunds the full escrowed amount to the client ✅ Yes
request_revision Marks job for revision; escrow remains locked ❌ No
raise_fraud_flag Refunds client, increments on-chain fraud counter for freelancer ✅ Yes
get_job Returns full job struct by job ID ❌ No
get_job_count Returns total number of jobs created ❌ No
get_fraud_count Returns fraud flag count for a given freelancer address ❌ No

Contract Transaction Hash (Live Call)

A live create_job call to the deployed contract is verifiable on Stellar Expert. The contract has been called from the frontend on Testnet and all function flows (create → submit → approve) have been exercised end-to-end.


10. Proof of Functionality

The following flows have been built, integrated, and verified end-to-end on Stellar Testnet:

# Flow Verification Method
1 Wallet Connection Freighter extension detected via @stellar/freighter-api; public key read and displayed in navbar
2 Wallet Disconnect Disconnect clears wallet state; UI reverts to the login page
3 Job Creation + Escrow Lock create_job() called on deployed Soroban contract; XLM locked in escrow; initial payment released to freelancer immediately
4 Encrypted File Upload AES-256-CBC encryption applied before Pinata upload; encrypted CID recorded on-chain via submit_work()
5 Watermarked Preview Jimp generates a watermarked preview image server-side on work submission; only preview is shown to client pre-approval
6 Work Approval + Payment approve_work() signed by client; escrow released to freelancer's Stellar address on-chain; decryption key returned
7 Revision Request request_revision() called; job state transitions to RevisionRequested; escrow remains locked
8 Fraud Flag raise_fraud_flag() signed by client; escrow refunded; fraud counter incremented on-chain for freelancer address
9 Job Cancellation cancel_deal() called; full escrow refunded to client address on-chain
10 Error Handling Wallet not found, rejected transaction, insufficient balance, and duplicate action errors all handled with user-facing messages

All blockchain interactions target Stellar Testnet. Contract is publicly verifiable at the explorer link in Section 9.


11. Test Results

FairDeal includes 3 Soroban unit tests covering the core contract flows. Tests are written in Rust using the soroban-sdk test harness (Env::default() + mock_all_auths()).

Test Suite: contract/src/test.rs

# Test Name What it Verifies Result
1 test_create_job Job created with correct escrow split; initial payment released; remainder locked; job state is Created ✅ Pass
2 test_submit_work IPFS CID recorded on-chain; job state transitions to Submitted ✅ Pass
3 test_request_revision Job state transitions to RevisionRequested; escrow remains locked (escrow_amount = 80_000_000 stroops) ✅ Pass

Run Tests Locally

cd contract
cargo test

Test Output Screenshots

All 3 Tests Passing — cargo test output Test Output


12. Screenshots

Landing Page

Landing Page

Wallet Connected State

Wallet Connected

Work Submission

Work Submitted


13. Demo Video

📹 Watch 1-Minute Demo Video

Full walkthrough showing:

  • ✅ Wallet connection via Freighter
  • ✅ Client posting a job and locking XLM in the Soroban escrow
  • ✅ Freelancer submitting encrypted work to IPFS
  • ✅ Client reviewing the watermarked preview
  • ✅ Approval releasing payment on-chain + decryption key returned
  • ✅ Fraud flag flow with on-chain refund

Project Structure

FairDeal/
├── app/                        # Next.js App Router pages & API routes
│   ├── api/
│   │   ├── jobs/               # Create, fetch, and manage jobs
│   │   ├── ipfs/               # IPFS upload & CID tracking
│   │   ├── decrypt-file/       # Decrypt & deliver files post-approval
│   │   ├── escrow-address/     # Escrow account helper
│   │   └── freelancers/        # Fraud flag endpoints
│   ├── create-job/             # Client: post a new job
│   ├── jobs/[jobId]/           # Job detail & action page
│   ├── submit-work/[jobId]/    # Freelancer: upload encrypted work
│   ├── login/                  # Wallet connect page
│   └── profile/                # User profile page
├── contract/
│   ├── src/lib.rs              # Soroban smart contract (Rust)
│   ├── src/test.rs             # 5 unit tests (cargo test)
│   └── Cargo.toml
├── components/
│   └── WalletProvider.tsx      # Freighter wallet context
├── utils/
│   ├── contract-utils.ts       # Contract interaction helpers
│   └── stellar-utils.ts        # Stellar SDK utilities
├── lib/
│   ├── ipfs-utils.ts           # Pinata upload/download
│   ├── stellar-utils.ts        # Server-side Stellar helpers
│   └── storage.ts              # Data storage abstraction
├── data/                       # Local job & IPFS metadata cache
└── docs/screenshots/           # README screenshots & test output

Security Model

Client deposits XLM
        ↓
Smart Contract holds funds (trustless — FairDeal cannot touch them)
        ↓
Freelancer uploads work
        ↓  AES-256-CBC encryption (client-side)
Pinata / IPFS stores encrypted file
        ↓
Client sees watermarked preview only
        ↓
Client approves → Contract releases escrowed XLM to freelancer
        ↓
Decryption key released → Client downloads clean file
  • No single point of failure — Funds are on-chain, files are on IPFS
  • Platform cannot steal funds — Smart contract enforces all state transitions
  • Files are private — Encrypted before upload; decryption key only released on approval
  • Fraud is on-chain — Fraud flag counts are immutable and publicly verifiable per freelancer address

Environment Variables Reference

Variable Description Required
NEXT_PUBLIC_STELLAR_NETWORK testnet or mainnet
NEXT_PUBLIC_CONTRACT_ID Deployed Soroban contract address
ESCROW_SECRET_KEY Stellar secret key for platform escrow account
ESCROW_PUBLIC_KEY Stellar public key for platform escrow account
PINATA_API_KEY Pinata API key
PINATA_SECRET_API_KEY Pinata secret API key

Roadmap

  • USDC payment support (Stellar anchor assets)
  • On-chain dispute resolution with arbitration
  • Multi-milestone payment schedules
  • Freelancer reputation & review system (on-chain)
  • Mainnet deployment

Acknowledgments


Built with ❤️ for the Stellar ecosystem

Report Bug · Request Feature · Live Demo

About

FairDeal is a blockchain-based escrow platform for freelancers, featuring Stellar smart contracts, IPFS file storage, and automated payment release. Zero platform fees, maximum trust.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors