Skip to content

YSKM523/taskmarket-overview

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 

Repository files navigation

TaskMarket

A campus services marketplace for international students — post a task, get bids, settle in USDC on-chain.

TaskMarket combines a structured task → bid → order → review flow with non-custodial USDC escrow on Coinbase Base, so payment is locked the moment a task is posted and auto-releases when the work is confirmed. The platform never holds user funds.

🔗 Live demo: taskmarket.pages.dev

This repository is the public overview. The application source lives in a private repo.

live overview source status chain stack


Table of Contents


What It Is

For international students, day-to-day help — package pickup, food runs, airport rides, tutoring, moving — gets traded in noisy group chats with no payment guarantee and weak accountability. TaskMarket turns that into a structured marketplace:

  1. A user posts a task with a clear price and optional USDC deposit into the escrow contract.
  2. Other users bid (price + ETA + pitch). The poster sees a ranked bid book.
  3. Poster picks a winner → order created → both sides chat in realtime.
  4. The taker submits completion evidence (text + up to 9 photos).
  5. Poster confirms → smart contract releases USDC to the taker, minus a 5% platform fee.
  6. If there's a disagreement, either side opens a dispute → an admin arbiter does a one-time binary call on-chain (pay taker, or refund poster).

The platform's arbiter key is the only on-chain privilege the operator holds — it can resolve disputes but cannot move funds anywhere else.


Screenshots

Landing — onboarding & value proposition

Landing page

Market — ranked task feed with live bid heat, sort by price/distance, category chips, and fuzzy pinyin search

Task market

Task detail — bid book, poster profile, similar-task recs, realtime activity timeline

Task detail

Post a task — three-step form, with the USDC on-chain escrow opt-in clearly explained

Post a task with USDC escrow

Orders — full lifecycle (MATCHED → WAIT OWNER → DONE), inline evidence submission, dispute trigger

Orders lifecycle

Admin disputes — live arbiter wallet, gas health, chain ID, queue of cases to resolve

Admin disputes

Messages — realtime Socket.IO conversations scoped to each task, with pin / archive / block

Messages

Mobile — responsive throughout

Mobile market view


Product Mind Map

mindmap
  root((TaskMarket))
    Posting
      Category chips
      Price + location
      Urgent flag (boost)
      Auto-match toggle
      USDC escrow opt-in
    Discovery
      Ranked feed
      Sort price / distance
      Fuzzy pinyin search
      Hot tasks ranking
      Top-priced ranking
      Live online counter
    Bidding
      Price + ETA + pitch
      Bid book per task
      Value score
      Realtime updates
    Order Flow
      Match
      In-progress chat
      Evidence form
      Completion confirm
      Auto-timeout release
    Settlement
      USDC on Base
      Non-custodial escrow
      5% platform fee
      Auto split on release
      Refund path
    Disputes
      Either side opens
      Admin arbiter UI
      One-time binary call
      Gas / wallet monitor
    Trust
      Star ratings
      Repeat-history signals
      User profile
      Block / report
    Realtime
      Socket.IO
      Live bid heat
      Live online counter
      Conversation pin / mute / archive
Loading

System Architecture

flowchart LR
  subgraph Client["Client · React 19 + Vite"]
    A1[Landing / Market / Task Detail]
    A2[Post / Bid / Orders]
    A3[Messages · Socket.IO]
    A4[Admin Disputes]
    A5[Wallet · viem]
  end

  subgraph Server["Server · Node 22 + Express"]
    B1[REST · auth / tasks / bids / orders]
    B2[Realtime · Socket.IO]
    B3[Escrow API · ethers v6]
    B4[Workers]
    B5[Fuzzy Search · pinyin-pro]
  end

  subgraph Workers["Background Workers"]
    W1[escrowReleaser]
    W2[gasMonitor]
    W3[orderTimeouts]
    W4[taskLifecycle]
  end

  subgraph Data["Data"]
    D1[(Prisma 6)]
    D2[(SQLite)]
    D3[Uploads · multer]
  end

  subgraph Chain["Coinbase Base"]
    C1[USDC ERC-20]
    C2[TaskEscrow.sol]
  end

  A1 & A2 & A3 & A4 -->|HTTPS / WSS| B1
  A3 <-->|WSS| B2
  A5 -->|approve + deposit| C1
  A5 -->|deposit / release / refund| C2
  B3 -->|read events, resolve disputes| C2
  B1 --> D1 --> D2
  B1 --> D3
  B4 --> W1 & W2 & W3 & W4
  W1 -->|auto-release after timeout| C2
  W2 -->|read arbiter balance| C2
  B5 --> B1
Loading

Escrow Lifecycle

The on-chain state machine inside TaskEscrow.sol is intentionally small — there are exactly four states and no upgrade path:

stateDiagram-v2
  [*] --> None
  None --> Funded: poster<br/>deposit(taskId, payee, amount)
  Funded --> Funded: assignPayee(taskId, taker)<br/>(if payee was zero)
  Funded --> Released: release(taskId)<br/>by poster
  Funded --> Refunded: refund(taskId)<br/>by poster (if not yet released)
  Funded --> Released: resolveByOwner(favorPayee=true)<br/>arbiter
  Funded --> Refunded: resolveByOwner(favorPayee=false)<br/>arbiter
  Released --> [*]
  Refunded --> [*]
Loading

Key invariants:

  • No third destination. resolveByOwner only routes funds to the original payer or the assigned payee.
  • Fee is capped. Max 20% by constant, default 5%. The owner can change fee but cannot exceed the cap.
  • Each taskId is single-shot. Re-funding the same task ID reverts with EscrowAlreadyExists.
  • Self-deal blocked. payer == payee reverts with SelfDeal.

What Makes It Different

Most "campus task" apps TaskMarket
Fixed-price postings Bid book with price + ETA + pitch
Trust = vibes Star ratings + repeat history + value score
Pay via Venmo / e-Transfer USDC on Base locked in a non-custodial contract
Platform holds your money Platform cannot move user funds; only arbiter for disputes
Chinese names → bad search Pinyin fuzzy search for "weixinquanzi" → "微信圈子"
Group-chat threads die Per-task Socket.IO chat + pin / mute / archive / block
No exit path on stale orders Auto-release / auto-refund background workers with timeouts

Tech Stack

Layer Tech Notes
Frontend React 19, Vite 7, Tailwind CSS 4, react-router-dom 7 Server-Components-style data fetching, modern JSX runtime
Wallet / chain viem Type-safe Ethereum client for approve, deposit, release, refund from the browser
UI primitives lucide-react Icon set
Realtime socket.io-client Bid heat, online counter, chat
Backend Node.js 22, Express 4 REST routes for auth / tasks / bids / orders / chat / escrow / admin
Realtime (server) Socket.IO 4 Per-task rooms
Auth JWT + bcryptjs Email + password
ORM Prisma 6 13 models — User, Task, Bid, Order, Review, Favorite, Conversation, Message, ConversationPin, ConversationMute, ConversationArchive, UserBlock, MessageReport
DB SQLite + Prisma Single Prisma schema (dev & prod)
Files multer Avatar + completion-evidence uploads
Search pinyin-pro Chinese-aware fuzzy search
Smart contracts Solidity 0.8.20 TaskEscrow.sol, no external imports
Contract tooling Hardhat 2.22 Compile, test, deploy to Base / Base Sepolia
Chain ops (server) ethers v6 Read contract events, resolve disputes from server
Deployment Cloudflare Pages + Cloudflare Tunnel Frontend on Pages (taskmarket.pages.dev), backend API exposed via Tunnel; run-production.sh lifecycle

Distinctive Features (Deep Dive)

1. Non-Custodial USDC Escrow

The platform's economic core is a single-file Solidity contract (TaskEscrow.sol) deployed on Coinbase Base. It holds USDC for in-flight tasks and is the only path money can move.

  • Deposit — poster calls approve(USDC) then deposit(taskId, payee, amount). taskId is bytes32 generated by the backend (typically keccak256(orderId)).
  • Release — when the poster confirms completion, release(taskId) splits funds: (amount - fee) to the taker, fee to the platform treasury.
  • Refund — if no one takes the task, or the poster cancels before release, refund(taskId) returns the full deposit.
  • DisputeresolveByOwner(taskId, favorPayee: bool) lets the platform arbiter pick one of the two existing outcomes. There is no third destination address, and the operator cannot change the amount.

2. Bid Book + Value Score

Instead of "first taker wins," each task accumulates a bid book where each bid carries price, ETA, and a short pitch. A valueScore utility on the server combines price, taker rating, and completion history into a sortable ranking, so the poster doesn't have to manually compare ten variations of "我能做 $5."

3. Realtime Coordination

Socket.IO drives three live surfaces:

  • Bid heat on the market list — new bids land without a refresh
  • Online counter — visible on the market header (e.g. "192 在线")
  • Per-task chat — when a bid is matched, a conversation opens; conversations support pin / mute / archive / block / report

4. Background Workers

The server runs four small workers (server/src/utils/):

Worker What it does
escrowReleaser Auto-releases on-chain escrow when both sides have confirmed but the poster forgets to click "release"
gasMonitor Watches the arbiter wallet's ETH balance and warns the admin UI before disputes can't be resolved
orderTimeouts Auto-cancels matched orders that the taker never starts
taskLifecycle Sweeps stale tasks back to OPEN or marks them expired

5. Chinese-Aware Fuzzy Search

The fuzzy-search utility uses pinyin-pro so a user can type daiquhongbao and still find 代取红包. This is critical for a Chinese-language student marketplace running on a Latin-keyboard search box.

6. Evidence-Based Completion

When a taker says "done," they fill in an evidence form: short description + up to 9 photos. The poster sees the same evidence inline on the orders page and can either confirm (→ escrow release) or open a dispute (→ admin queue).

7. Admin Operability

The admin dispute screen surfaces the operator's real-time on-chain state in one glance: arbiter address, ETH balance, target chain ID. If gas is low, the screen visually warns before disputes start failing.


Use Cases

  • 📦 Package pickup, parcel handoff at the front desk
  • 🍱 Grocery / food / boba runs
  • 🚗 Airport pickup, Union Station drop-off, local rides
  • 📚 Homework help, paper proofreading, exam tutoring
  • 🧹 Apartment cleaning, kitchen deep-clean
  • 🪑 IKEA assembly, moving day muscle
  • 🐕 Dog walks, plant watering
  • 📸 LinkedIn headshots and other low-friction student gigs

Repository Model

Repository Visibility Purpose
taskmarket-overview Public Product overview, screenshots, diagrams, roadmap
taskmarket-source Private React app, Express API, Prisma schema, Solidity contract, Hardhat deploy scripts

The source is private because it includes deployment configuration, the production database schema, and code paths to the live escrow contract on Base.


Roadmap

  • mainnet launch of TaskEscrow.sol on Base after audit
  • in-app wallet connect (Coinbase Smart Wallet) so users without MetaMask can fund tasks
  • gasless deposits via paymaster / 4337 sponsor for first-time users
  • multi-language UI — English + Simplified Chinese parity
  • reputation rollups — verifiable on-chain rating history (Soulbound NFT) once volume justifies it
  • categorized search filters beyond the current 8 chips
  • task templates for repeat-poster flows (weekly grocery, recurring tutoring)

Links

About

Public overview repository for TaskMarket, a campus task marketplace built around bid-based matching and realtime coordination

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors