An interview-ready Solana escrow dApp built with Anchor. A client funds an escrow in SOL, a freelancer submits work as text or a delivery link, and the client either approves the work to release funds or raises a dispute to return the locked SOL.
- An Anchor program that stores escrow state and custody of deposited SOL
- TypeScript tests covering the approval and dispute flows
- A React + Vite frontend with Solana wallet connection
- Clear project structure, setup notes, and local development scripts
- The client creates and funds an escrow PDA.
- The freelancer submits work as plain text or a URL.
- The client approves the work to release SOL to the freelancer.
- Or the client disputes the work, which closes the escrow and returns funds to the client.
- Solana
- Anchor
- Rust
- TypeScript
- React
- Vite
- Solana Wallet Adapter
.
├── app/ # React frontend
├── migrations/ # Anchor deployment hook
├── programs/freelancer-escrow/ # On-chain program
├── tests/ # Anchor TypeScript tests
├── Anchor.toml
├── Cargo.toml
└── package.json
The Escrow account stores:
clientfreelancerescrow_seedtitleamount_lamportsstatussubmissiondispute_reasoncreated_atupdated_at
Each escrow is a PDA derived from:
["escrow", client, freelancer, escrow_seed]
This makes it easy to support multiple gigs between the same client and freelancer.
initialize_escrow- Creates the escrow account and transfers the client deposit into it.
submit_work- Lets the assigned freelancer attach a delivery note or URL.
approve_work- Sends the escrowed SOL to the freelancer and closes the account.
raise_dispute- Marks the escrow as disputed and closes the account back to the client.
- Rust
- Solana CLI
- Anchor CLI
- Node.js 20+
- A local validator or devnet wallet for testing
npm install
npm --prefix app installanchor buildanchor testnpm run app:devBy default the app points to http://127.0.0.1:8899. You can override it with VITE_RPC_URL.
Build the frontend container from the app folder:
docker build -t freelancer-escrow-app ./appRun it locally:
docker run --rm -p 4173:4173 freelancer-escrow-appThen open http://localhost:4173 in your browser.
Alternatively, use Docker Compose from the repository root:
docker compose up --buildThis container serves the built React app. It does not start a Solana validator or deploy the on-chain program; for full Anchor development, continue using solana-test-validator, anchor build, and anchor deploy.
- Start
solana-test-validator. - Build and deploy with
anchor build && anchor deploy. - Open the app and connect a wallet.
- Create an escrow with a freelancer public key and deposit amount.
- Switch to the freelancer wallet and submit a GitHub, Figma, Loom, or live-demo link.
- Switch back to the client wallet and approve or dispute the escrow.
- The contract intentionally keeps dispute resolution simple for the interview scope: a dispute refunds the client immediately.
- The frontend is lightweight by design and focuses on demonstrating the contract lifecycle clearly.
- The repository is organized so the on-chain logic, tests, and UI can each be reviewed independently.
- Add third-party arbitration instead of client-only disputes
- Support SPL token escrows in addition to SOL
- Add escrow expiration windows and cancellation rules
- Persist richer off-chain metadata with IPFS or Arweave
- Add CI for formatting, tests, and Anchor builds
MIT