Data Marketplace

Data Labeling Marketplace

The Data Labeling Marketplace on PandaChain connects data requesters with workers who label data for ML training. Budgets are held in escrow, payments are automatic, and reputation is tracked on-chain.


How It Works

RoleActionOutcome
RequesterPosts labeling request with budgetBudget locked in escrow
WorkerClaims task, submits labelsEarns PANDA per accepted label
RequesterReviews submissions, accepts/rejectsAccepted = payment released
SystemTracks reputation, enforces deadlinesQuality incentives maintained

Posting a Labeling Request

  1. Navigate to /app/labor/post
  2. Fill in the request form:
    • Title: Clear description of the labeling task
    • Category: Image, Text, Audio, Video, RLHF, or Code
    • Description: Detailed guidelines for workers
    • Data Schema: JSON schema for expected label format
    • Price per Label: How much PANDA each accepted label pays
    • Total Labels: Number of labels needed
    • Reputation Required: Minimum worker reputation (0-100)
    • Deadline: When the request expires
  3. Submit -- your budget (price x labels) is locked in the LaborMarketplace escrow
# On-chain: DataMarketplace contract (contracts/labor/data_marketplace.py)
# Simplified illustration -- the real signature is
# list_request(self, requester, title, category, description, schema, ...)
def list_request(self, requester, title, category, description, schema, budget, price_per_label, reputation_required, deadline, total_labels):
    """Post a new labeling request. Budget is locked in escrow."""
    request_id = self.state.next_id
    self.state.requests[str(request_id)] = {
        "title": title,
        "requester": requester,
        "category": category,
        "budget": budget,
        "price_per_label": price_per_label,
        "status": "open",
        ...
    }
    # Lock funds
    self.state.escrow[str(request_id)] = budget
    self.state.next_id += 1

Submitting Labels (Workers)

  1. Browse the marketplace at /app/labor
  2. Filter by category, pay rate, deadline, or reputation requirement
  3. Click a request to view details and schema
  4. Click Claim Task to reserve a spot
  5. Submit your label data as JSON matching the schema
  6. Wait for the requester to review

Quality Tips

  • Follow the schema exactly -- malformed submissions are auto-rejected
  • Higher quality scores improve your reputation
  • Reputation unlocks higher-paying tasks
  • Consistent accuracy leads to more claims

Earning Reputation

Your on-chain reputation score (0-100) is calculated from:

FactorWeight
Acceptance rate40%
Average quality score30%
Total labels submitted20%
Account age10%

Higher reputation unlocks:

  • Access to premium requests (reputation-gated)
  • Priority in task claiming during high demand
  • Higher visibility to requesters

Earning from Datasets

Beyond individual labels, workers can earn ongoing revenue:

  1. Dataset Royalties: If a requester publishes a dataset using your labels, you earn a percentage of future sales
  2. Quality Bonuses: Some requesters offer bonus payments for top-quality submissions
  3. Referral Rewards: Invite other workers and earn from their first 10 tasks

Dispute Resolution

If a worker disagrees with a rejection:

  1. Worker initiates a dispute within 48 hours
  2. A panel of 3 randomly-selected high-reputation workers reviews the submission
  3. Majority vote decides the outcome
  4. If the dispute is upheld, the label is accepted and the requester's rejection rate increases
  5. Frivolous disputes cost a small stake
# Simplified illustration -- the real signature is
# dispute_rejection(self, worker, label_id) -> Label
def dispute_rejection(self, worker, label_id):
    """Initiate a dispute for a rejected label."""
    label = self.state.labels[label_id]
    if label["worker"] != worker:
        raise ValueError("Only the worker can dispute")
    if label["status"] != "rejected":
        raise ValueError("Can only dispute rejected labels")
    # Mark the label as disputed
    label["status"] = "disputed"

Contract Architecture

The marketplace is implemented as a single DataMarketplace contract (contracts/labor/data_marketplace.py). It handles requests, claims, submissions, escrow, reputation, and disputes in one place:

ResponsibilityWhere
Requests, claims, submissionsDataMarketplace methods (list_request, claim_task, submit_label)
Escrow of requester budgetsHeld internally; queryable via get_escrow_balance(request_id)
Worker reputationTracked internally; updated on accept/reject
Disputesdispute_rejection(worker, label_id)

Categories

CategoryExamples
ImageObject detection, segmentation, classification
TextSentiment analysis, NER, summarization quality
AudioTranscription, speaker identification, emotion
VideoAction recognition, temporal annotation
RLHFPreference ranking, helpfulness scoring
CodeCode review, bug classification, complexity

API Reference

These are the methods on the DataMarketplace contract (contracts/labor/data_marketplace.py). The caller/worker/requester address is passed explicitly as the first argument.

Query Methods

  • get_open_requests(category=None, min_pay=None) -- Browse open requests
  • get_request(request_id) -- Get request details (returns DataRequest or None)
  • get_request_stats(request_id) -- Stats for a single request
  • get_label(label_id) -- Get a submitted label (returns Label or None)
  • get_worker_balance(worker) -- A worker's withdrawable balance
  • get_escrow_balance(request_id) -- Escrow still locked for a request
  • get_price_history(category, epochs=10) -- Per-category price candles
  • get_market_stats() -- Marketplace-wide statistics (MarketStats)

Call Methods

  • list_request(requester, title, category, description, schema, ...) -- Post a new labeling request (locks budget in escrow)
  • claim_task(worker, request_id) -- Claim a task as a worker
  • submit_label(worker, request_id, data_hash, label_data) -- Submit a label
  • accept_label(caller, request_id, label_id) -- Accept a submission (requester)
  • reject_label(caller, request_id, label_id, reason) -- Reject a submission (requester)
  • dispute_rejection(worker, label_id) -- Initiate a dispute (worker)
  • register_worker(worker, initial_reputation=0) -- Register a worker
  • withdraw(worker, amount) -- Withdraw earned balance
  • advance_epoch() -- Advance the marketplace epoch (price candles)