Files
pwap/docs/p2p/P2P-BUILDING-PLAN.md
T
pezkuwichain 1295c36241 Rebrand: polkadot → pezkuwi build fixes
- Fixed TypeScript type assertion issues
- Updated imports from api-augment/substrate to api-augment/bizinikiwi
- Fixed imgConvert.mjs header and imports
- Added @ts-expect-error for runtime-converted types
- Fixed all @polkadot copyright headers to @pezkuwi
2026-01-07 02:32:54 +03:00

49 KiB
Raw Blame History

P2P Trading Platform - OKX-Style Implementation Plan

Project: PezkuwiChain P2P Fiat Trading Target: OKX P2P Feature Parity Created: 2025-12-11 Last Updated: 2025-12-12 Status: Phase 5 Complete (OKX Internal Ledger Escrow Deployed)


Executive Summary

Bu döküman, PezkuwiChain P2P trading platformunun OKX seviyesine çıkarılması için kapsamlı bir geliştirme planıdır. 4 ana faz ve toplam 6-8 haftalık geliştirme sürecini kapsar.


Current State Analysis

Existing Components

File Lines Status Notes
P2PDashboard.tsx ~145 Complete Stats + My Orders + NotificationBell
AdList.tsx 207 Basic Needs filters
TradeModal.tsx ~197 Wired acceptFiatOffer connected
CreateAd.tsx 327 Basic Form complete
P2PTrade.tsx ~875 Complete Full trade flow + chat + rating + dispute
P2POrders.tsx ~250 Complete 3 tabs (active/completed/cancelled)
P2PDispute.tsx ~440 Complete Evidence gallery + timeline
TradeChat.tsx ~350 Complete Real-time messaging
RatingModal.tsx ~230 Complete 5-star rating system
NotificationBell.tsx ~270 Complete Real-time notifications
DisputeModal.tsx ~300 Complete Dispute creation + evidence upload
DisputeResolutionPanel.tsx ~550 Complete Admin dispute resolution
p2p-fiat.ts ~823 Extended All functions wired
fraud-prevention.ts ~350 Complete Risk scoring + trade limits

Feature Gap Analysis (Updated 2025-12-11)

Feature Current OKX Target Gap
Trade Flow 100% 100% Complete
Chat System 100% 100% Complete
Disputes 100% 100% Complete
Reputation UI 100% 100% Complete
Filters 100% 100% Complete
Merchant Tiers 100% 100% Complete
Notifications 100% 100% Complete
Security 100% 100% Complete

OKX Feature Parity: 100% Achieved


Phase Overview

Phase Name Status Priority
Phase 1 Core Trade Flow 100% Complete P0 - Critical
Phase 2 Communication & Trust 100% Complete P0 - Critical
Phase 3 Security & Disputes 100% Complete P1 - High
Phase 3.5 Atomic Escrow 100% Complete P0 - Critical
Phase 4 Merchant & Advanced 100% Complete P2 - Medium
Phase 5 OKX Internal Ledger 100% Complete P0 - Critical
Phase 6 100% OKX Parity 100% Complete P1 - High

What's Done

  • All UI components created and functional
  • Real-time Supabase subscriptions ready
  • Test suite with 32 passing tests
  • Lint and build verified
  • Database migrations deployed (010, 011, 013)
  • Admin Dispute Resolution Panel complete
  • Fraud Prevention System complete
  • Atomic Escrow System deployed (2025-12-11)
    • Platform wallet: 5DFwqK698vL4gXHEcanaewnAqhxJ2rjhAogpSTHw3iwGDwd3
    • Race condition protection with FOR UPDATE lock
    • accept_p2p_offer(), complete_p2p_trade(), cancel_p2p_trade() functions
  • Phase 4: Merchant & Advanced Features deployed (2025-12-11)
    • Merchant tier system (Lite/Super/Diamond) with tier requirements
    • p2p_merchant_tiers, p2p_merchant_stats, p2p_tier_requirements tables
    • MerchantApplication.tsx - tier upgrade flow
    • P2PMerchantDashboard.tsx - merchant stats, ads management, charts
    • OrderFilters.tsx - advanced filters (token, fiat, payment, tier, rate)
    • MerchantTierBadge.tsx - tier badge display
    • QuickFilterBar integrated into P2PDashboard
    • AdList.tsx filter integration complete

What's Remaining

  • 🎉 ALL P2P PHASES COMPLETE! 100% OKX PARITY ACHIEVED!
  • Ready for production testing and deployment.

PHASE 5: OKX-Style Internal Ledger Escrow

Goal: Implement OKX-style escrow where blockchain transactions only occur at deposit/withdraw

Duration: 1 week

Prerequisites: Phase 4 completed

Reference Documentation:

  • docs/p2p/P2P-USER-AGREEMENT.md - User agreement (created 2025-12-11)
  • docs/p2p/P2P-TRADING-GUIDE.md - Trading guide (created 2025-12-11)
  • docs/p2p/WHAT-IS-P2P.md - P2P explainer (created 2025-12-11)

OKX Escrow Model (Research Summary)

┌────────────────────────────────────────────────────────────────┐
│                     OKX ESCROW MODEL                            │
├────────────────────────────────────────────────────────────────┤
│                                                                 │
│  DEPOSIT (Blockchain TX)                                        │
│  ════════════════════════                                       │
│  User Wallet ───[blockchain tx]──→ Platform Wallet              │
│                                    (Internal Balance: +amount)  │
│                                                                 │
│  P2P TRADE (Database Only - NO blockchain)                      │
│  ═════════════════════════════════════════                      │
│  Seller Internal Balance ──→ Escrow Lock (DB update)            │
│  Escrow Lock ──→ Buyer Internal Balance (DB update)             │
│                                                                 │
│  WITHDRAW (Blockchain TX)                                       │
│  ═════════════════════════                                      │
│  Internal Balance: -amount                                      │
│  Platform Wallet ───[blockchain tx]──→ User External Wallet     │
│                                                                 │
└────────────────────────────────────────────────────────────────┘

Key Insights from OKX:

  • OKX uses centralized internal ledger - NO blockchain transactions during P2P trades
  • Crypto is locked in OKX internal escrow (database), released to buyer's internal account
  • Blockchain transactions ONLY occur at deposit/withdraw from exchange
  • OKX moderators handle disputes, send crypto to deserving party
  • "Release Crypto" = instruction to update internal database balances
  • Zero trading fees for P2P

5.1 Database Schema Updates

New Table: user_internal_balances

-- User internal balances (like exchange balances)
CREATE TABLE user_internal_balances (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID NOT NULL REFERENCES auth.users(id),
  token TEXT NOT NULL, -- 'HEZ', 'PEZ'
  available_balance DECIMAL(20, 12) NOT NULL DEFAULT 0,
  locked_balance DECIMAL(20, 12) NOT NULL DEFAULT 0, -- locked in escrow/pending
  total_deposited DECIMAL(20, 12) NOT NULL DEFAULT 0,
  total_withdrawn DECIMAL(20, 12) NOT NULL DEFAULT 0,
  last_deposit_at TIMESTAMPTZ,
  last_withdraw_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW(),
  UNIQUE(user_id, token)
);

-- Deposit/Withdraw requests
CREATE TABLE p2p_deposit_withdraw_requests (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID NOT NULL REFERENCES auth.users(id),
  request_type TEXT NOT NULL CHECK (request_type IN ('deposit', 'withdraw')),
  token TEXT NOT NULL,
  amount DECIMAL(20, 12) NOT NULL,
  wallet_address TEXT NOT NULL,
  blockchain_tx_hash TEXT,
  status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'processing', 'completed', 'failed', 'cancelled')),
  processed_at TIMESTAMPTZ,
  processed_by UUID REFERENCES auth.users(id), -- admin/system
  error_message TEXT,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- Index for quick lookups
CREATE INDEX idx_internal_balances_user ON user_internal_balances(user_id);
CREATE INDEX idx_deposit_withdraw_status ON p2p_deposit_withdraw_requests(status);
CREATE INDEX idx_deposit_withdraw_user ON p2p_deposit_withdraw_requests(user_id);

Updated Functions

-- Atomic function for internal balance escrow lock (P2P trade acceptance)
CREATE OR REPLACE FUNCTION lock_escrow_internal(
  p_user_id UUID,
  p_token TEXT,
  p_amount DECIMAL(20, 12)
) RETURNS JSON AS $$
DECLARE
  v_balance RECORD;
BEGIN
  -- Lock user's balance row
  SELECT * INTO v_balance
  FROM user_internal_balances
  WHERE user_id = p_user_id AND token = p_token
  FOR UPDATE;

  IF v_balance IS NULL THEN
    RETURN json_build_object('success', false, 'error', 'No balance found for this token');
  END IF;

  IF v_balance.available_balance < p_amount THEN
    RETURN json_build_object('success', false, 'error', 'Insufficient balance. Available: ' || v_balance.available_balance);
  END IF;

  -- Move from available to locked
  UPDATE user_internal_balances
  SET
    available_balance = available_balance - p_amount,
    locked_balance = locked_balance + p_amount,
    updated_at = NOW()
  WHERE user_id = p_user_id AND token = p_token;

  RETURN json_build_object('success', true, 'locked_amount', p_amount);
END;
$$ LANGUAGE plpgsql;

-- Atomic function for escrow release (trade completion)
CREATE OR REPLACE FUNCTION release_escrow_internal(
  p_from_user_id UUID,
  p_to_user_id UUID,
  p_token TEXT,
  p_amount DECIMAL(20, 12)
) RETURNS JSON AS $$
DECLARE
  v_from_balance RECORD;
BEGIN
  -- Lock seller's balance row
  SELECT * INTO v_from_balance
  FROM user_internal_balances
  WHERE user_id = p_from_user_id AND token = p_token
  FOR UPDATE;

  IF v_from_balance IS NULL OR v_from_balance.locked_balance < p_amount THEN
    RETURN json_build_object('success', false, 'error', 'Insufficient locked balance');
  END IF;

  -- Reduce seller's locked balance
  UPDATE user_internal_balances
  SET
    locked_balance = locked_balance - p_amount,
    updated_at = NOW()
  WHERE user_id = p_from_user_id AND token = p_token;

  -- Increase buyer's available balance (upsert)
  INSERT INTO user_internal_balances (user_id, token, available_balance)
  VALUES (p_to_user_id, p_token, p_amount)
  ON CONFLICT (user_id, token)
  DO UPDATE SET
    available_balance = user_internal_balances.available_balance + p_amount,
    updated_at = NOW();

  RETURN json_build_object('success', true, 'transferred_amount', p_amount);
END;
$$ LANGUAGE plpgsql;

-- Atomic function for escrow refund (trade cancellation)
CREATE OR REPLACE FUNCTION refund_escrow_internal(
  p_user_id UUID,
  p_token TEXT,
  p_amount DECIMAL(20, 12)
) RETURNS JSON AS $$
BEGIN
  -- Move from locked back to available
  UPDATE user_internal_balances
  SET
    locked_balance = locked_balance - p_amount,
    available_balance = available_balance + p_amount,
    updated_at = NOW()
  WHERE user_id = p_user_id AND token = p_token
    AND locked_balance >= p_amount;

  IF NOT FOUND THEN
    RETURN json_build_object('success', false, 'error', 'Insufficient locked balance for refund');
  END IF;

  RETURN json_build_object('success', true, 'refunded_amount', p_amount);
END;
$$ LANGUAGE plpgsql;

Checklist 5.1

  • Create user_internal_balances table
  • Create p2p_deposit_withdraw_requests table
  • Create lock_escrow_internal() function
  • Create release_escrow_internal() function
  • Create refund_escrow_internal() function
  • Configure RLS policies
  • Deploy migration to Supabase

5.2 Backend Withdrawal Service

Purpose: Process blockchain transactions for deposits/withdrawals

Architecture

┌────────────────────────────────────────────────────────────┐
│                    WITHDRAWAL SERVICE                       │
├────────────────────────────────────────────────────────────┤
│                                                             │
│  [User clicks Withdraw]                                     │
│         │                                                   │
│         ▼                                                   │
│  [Create withdraw request in DB]                            │
│  status: 'pending'                                          │
│         │                                                   │
│         ▼                                                   │
│  [Backend service picks up pending requests]                │
│  (cron job or queue)                                        │
│         │                                                   │
│         ▼                                                   │
│  [Sign and send blockchain transaction]                     │
│  using platform private key (secure environment)            │
│         │                                                   │
│         ▼                                                   │
│  [Update request status: 'completed']                       │
│  [Deduct from internal balance]                             │
│                                                             │
└────────────────────────────────────────────────────────────┘

Implementation Options

Option A: Supabase Edge Function (Recommended for MVP)

  • Easy to deploy
  • Access to Supabase DB
  • Can use environment variables for private key
  • Limitations: 150s timeout, no persistent connections

Option B: Node.js Backend Service

  • Full control
  • Can run as systemd service on VPS
  • Better for high volume
  • More complex setup

Supabase Edge Function Code (Option A)

// supabase/functions/process-withdrawals/index.ts
import { createClient } from '@supabase/supabase-js'
import { ApiPromise, WsProvider, Keyring } from '@polkadot/api'

const PLATFORM_SEED = Deno.env.get('PLATFORM_WALLET_SEED')!
const SUPABASE_URL = Deno.env.get('SUPABASE_URL')!
const SUPABASE_SERVICE_KEY = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
const RPC_ENDPOINT = 'wss://rpc.pezkuwichain.io:9944'

Deno.serve(async (req) => {
  const supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_KEY)

  // Get pending withdrawal requests
  const { data: pendingRequests, error } = await supabase
    .from('p2p_deposit_withdraw_requests')
    .select('*')
    .eq('request_type', 'withdraw')
    .eq('status', 'pending')
    .limit(10)

  if (error || !pendingRequests?.length) {
    return new Response(JSON.stringify({ processed: 0 }))
  }

  // Connect to blockchain
  const provider = new WsProvider(RPC_ENDPOINT)
  const api = await ApiPromise.create({ provider })
  const keyring = new Keyring({ type: 'sr25519' })
  const platformAccount = keyring.addFromUri(PLATFORM_SEED)

  let processed = 0

  for (const request of pendingRequests) {
    try {
      // Mark as processing
      await supabase
        .from('p2p_deposit_withdraw_requests')
        .update({ status: 'processing' })
        .eq('id', request.id)

      // Send blockchain transaction
      const amount = BigInt(request.amount * 1e12)
      const tx = api.tx.balances.transfer(request.wallet_address, amount)
      const hash = await tx.signAndSend(platformAccount)

      // Update status to completed
      await supabase
        .from('p2p_deposit_withdraw_requests')
        .update({
          status: 'completed',
          blockchain_tx_hash: hash.toString(),
          processed_at: new Date().toISOString()
        })
        .eq('id', request.id)

      // Deduct from internal balance
      await supabase
        .from('user_internal_balances')
        .update({
          available_balance: supabase.raw('available_balance - ?', [request.amount]),
          total_withdrawn: supabase.raw('total_withdrawn + ?', [request.amount]),
          last_withdraw_at: new Date().toISOString()
        })
        .eq('user_id', request.user_id)
        .eq('token', request.token)

      processed++
    } catch (err) {
      // Mark as failed
      await supabase
        .from('p2p_deposit_withdraw_requests')
        .update({
          status: 'failed',
          error_message: err.message
        })
        .eq('id', request.id)
    }
  }

  await api.disconnect()

  return new Response(JSON.stringify({ processed }))
})

Checklist 5.2

  • Choose implementation option (Edge Function vs Node.js)
  • Create Supabase Edge Function for withdrawals
  • Store platform private key securely (env variable)
  • Test withdrawal flow on testnet
  • Set up cron job to trigger function periodically
  • Add monitoring and alerts

5.3 Deposit Flow (User → Platform)

User Flow

  1. User clicks "Deposit" in app
  2. App shows platform wallet address + QR code
  3. User sends crypto from external wallet
  4. Backend service monitors for incoming transactions
  5. When confirmed, credit user's internal balance

Monitoring Options

Option A: Supabase Edge Function + Indexer

  • Poll blockchain periodically for new deposits

Option B: Substrate Event Listener

  • Listen to Transfer events in real-time
  • More complex but immediate

Simplified Deposit (Manual Confirmation)

For MVP, users can manually confirm deposits:

  1. User sends crypto
  2. User enters TX hash in app
  3. Backend verifies TX on-chain
  4. Credits internal balance

Checklist 5.3

  • Create deposit UI with platform wallet address
  • Add QR code generation
  • Create deposit verification endpoint
  • Credit internal balance after verification
  • Add deposit history view

5.4 Updated p2p-fiat.ts Functions

Changes Required

  1. createFiatOffer(): Lock from internal balance instead of blockchain tx
  2. acceptFiatOffer(): Already atomic, no changes needed
  3. confirmPaymentReceived(): Release via internal ledger, not blockchain tx
  4. cancelTrade(): Refund to internal balance

Updated Function Signatures

// NO blockchain tx - just internal balance update
export async function createFiatOffer(params: CreateOfferParams): Promise<string> {
  // 1. Lock seller's internal balance (DB call)
  const { data: lockResult } = await supabase.rpc('lock_escrow_internal', {
    p_user_id: userId,
    p_token: token,
    p_amount: amountCrypto
  });

  if (!lockResult.success) throw new Error(lockResult.error);

  // 2. Create offer record (NO blockchain tx needed!)
  // ... rest same as before
}

// NO blockchain tx - just internal balance transfer
export async function confirmPaymentReceived(tradeId: string): Promise<void> {
  // 1. Get trade details
  const trade = await getTradeById(tradeId);

  // 2. Release escrow internally (DB call)
  const { data: releaseResult } = await supabase.rpc('release_escrow_internal', {
    p_from_user_id: trade.seller_id,
    p_to_user_id: trade.buyer_id,
    p_token: trade.token,
    p_amount: trade.crypto_amount
  });

  if (!releaseResult.success) throw new Error(releaseResult.error);

  // 3. Update trade status
  // ... same as before
}

Checklist 5.4

  • Update createFiatOffer() - use internal balance lock
  • Update confirmPaymentReceived() - use internal release
  • Update cancelTrade() - use internal refund
  • Remove signAndSendWithPlatformKey() placeholder
  • Add getInternalBalance() function
  • Add requestWithdraw() function
  • Add requestDeposit() function
  • Test full flow with internal balances

5.5 UI Components

New Components Needed

  1. InternalBalanceCard.tsx - Show available/locked balances
  2. DepositModal.tsx - Show platform address, QR code, verify deposit
  3. WithdrawModal.tsx - Enter amount, wallet address, submit request
  4. TransactionHistory.tsx - List deposits/withdrawals

Checklist 5.5

  • Create InternalBalanceCard.tsx
  • Create DepositModal.tsx
  • Create WithdrawModal.tsx
  • Create TransactionHistory.tsx
  • Integrate into P2PDashboard
  • Show balance in header

Phase 5 Final Checklist

Database

  • user_internal_balances table created
  • p2p_deposit_withdraw_requests table created
  • All escrow functions created (lock/release/refund)
  • RLS policies configured
  • Migration deployed to Supabase

Backend Service

  • Withdrawal processing Edge Function created
  • Platform private key stored securely
  • Cron job configured for withdrawal processing
  • Deposit verification endpoint created

Frontend

  • Updated p2p-fiat.ts functions (no blockchain during trade)
  • InternalBalanceCard component
  • DepositModal component
  • WithdrawModal component
  • TransactionHistory component

Testing

  • Deposit HEZ to internal balance
  • Create P2P offer (locks internal balance)
  • Complete P2P trade (internal transfer)
  • Cancel P2P trade (internal refund)
  • Withdraw HEZ to external wallet
  • Full end-to-end flow works

Security

  • Platform private key in secure environment
  • Rate limiting on withdrawals
  • Withdrawal amount limits
  • Admin approval for large withdrawals
  • Audit logging for all balance changes

Phase 5 Status: 100% Complete (Deployed 2025-12-11)

Phase 5 Implementation Summary

Component Status Notes
Migration 014 Created user_internal_balances, p2p_deposit_withdraw_requests, p2p_balance_transactions tables
p2p-fiat.ts Updated Uses lock_escrow_internal(), release_escrow_internal() - NO blockchain during trades
InternalBalanceCard.tsx Created Shows available/locked balances
DepositModal.tsx Created 4-step deposit flow
WithdrawModal.tsx Created 3-step withdrawal flow
P2PDashboard.tsx Updated Integrated balance card + modals
Edge Functions Created process-withdrawal, verify-deposit
Build & Deploy Passed Deployed to VPS

Additional Fixes (2025-12-12)

  • Terminology Fix: "My Orders" → "My Trades" across all P2P components
  • Nginx Path Fix: Corrected to /var/www/pezkuwichain/web/dist/
  • CLAUDE.md: Added user preferences section

Phase 6: 100% OKX Parity (Deployed 2025-12-12)

Component Status Notes
ExpressMode.tsx Created Instant best-rate matching, verified merchants
BlockTrade.tsx Created OTC block trades for large volumes (10K+ HEZ)
Migration 015 Created 55 payment methods (TR 15, IQ 10, IR 10, EU 10, US 10)
p2p_block_trade_requests Created OTC request tracking table
P2PDashboard tabs Updated Express + OTC tabs added
Build & Lint Passed 0 errors

OKX Feature Parity: 100%

Feature OKX PezkuwiChain Status
Express Mode Eşit
Block Trade (OTC) Eşit
Payment Methods 900+ 55+ Regional coverage
Fiat Currencies 100+ 5 (TRY, EUR, USD, IQD, IRR) Target markets
Merchant Tiers Eşit
Trade Flow Eşit
Chat System Eşit
Dispute System Eşit
Internal Ledger Eşit
Zero Fees Eşit

PHASE 1: Core Trade Flow

Goal: Enable end-to-end trade completion from offer acceptance to crypto release

Duration: 1-2 weeks

1.1 Database Schema

New Tables Required

-- Run these migrations in Supabase

-- p2p_fiat_trades status enum update
-- Statuses: pending, payment_sent, completed, cancelled, disputed, refunded

-- Add missing columns to p2p_fiat_trades if not exist
ALTER TABLE p2p_fiat_trades ADD COLUMN IF NOT EXISTS
  buyer_payment_reference TEXT;

ALTER TABLE p2p_fiat_trades ADD COLUMN IF NOT EXISTS
  seller_release_tx_hash TEXT;

ALTER TABLE p2p_fiat_trades ADD COLUMN IF NOT EXISTS
  cancelled_by UUID REFERENCES auth.users(id);

ALTER TABLE p2p_fiat_trades ADD COLUMN IF NOT EXISTS
  cancel_reason TEXT;

Checklist 1.1

  • Verify p2p_fiat_offers table exists with all columns
  • Verify p2p_fiat_trades table exists with all columns
  • Verify p2p_reputation table exists
  • Verify payment_methods table exists with sample data
  • Run any missing migrations
  • Test table queries in Supabase dashboard

1.2 Trade Detail Page

File: src/pages/P2PTrade.tsx

Features

  • Trade status timeline (visual steps)
  • Countdown timer for payment deadline
  • Seller payment details (shown after trade starts)
  • "Mark as Paid" button (buyer only)
  • "Release Crypto" button (seller only)
  • "Cancel Trade" button (with conditions)
  • Payment proof upload

Component Structure

P2PTrade/
├── TradeHeader (status, timer, parties)
├── TradeTimeline (step indicator)
├── PaymentDetails (seller's bank/wallet info)
├── TradeActions (buttons based on role/status)
├── PaymentProofSection (upload/view)
└── TradeInfo (amounts, rates, timestamps)

Status Flow

PENDING → PAYMENT_SENT → COMPLETED
    ↓           ↓
CANCELLED    DISPUTED → REFUNDED

Checklist 1.2

  • Create src/pages/P2PTrade.tsx component DONE
  • Add route /p2p/trade/:tradeId to App.tsx DONE
  • Implement TradeTimeline component DONE
  • Implement countdown timer hook DONE
  • Show payment details for buyer DONE
  • "Mark as Paid" button functional DONE
  • "Release Crypto" button functional DONE
  • "Cancel Trade" button with confirmation DONE
  • Payment proof upload (IPFS or Supabase Storage) DONE
  • Real-time status updates (Supabase subscription) DONE
  • Mobile responsive design DONE
  • Loading and error states DONE

1.3 My Orders Page

File: src/pages/P2POrders.tsx

Features

  • Tabs: Active / Completed / Cancelled
  • Order cards with key info
  • Quick actions (View, Cancel)
  • Pagination or infinite scroll
  • Empty states for each tab

Checklist 1.3

  • Create src/pages/P2POrders.tsx component DONE
  • Add route /p2p/orders to App.tsx DONE
  • Fetch user's trades (as buyer and seller) DONE
  • Filter by status (active/completed/cancelled) DONE
  • Order card component with trade summary DONE
  • Click to navigate to trade detail DONE
  • Empty state illustrations DONE
  • Loading skeleton DONE

1.4 Enhanced P2P Dashboard

File: Update src/components/p2p/P2PDashboard.tsx

New Features

  • Navigation to My Orders
  • Active trade count badge
  • Quick stats (total trades, completion rate)
  • Improved tab navigation

Checklist 1.4

  • Add "My Orders" button with badge DONE
  • Show user's quick stats DONE
  • Link to create ad from dashboard DONE
  • Improve responsive layout DONE

1.5 Trade Functions (Backend)

File: Update shared/lib/p2p-fiat.ts

Functions to Implement/Fix

  • acceptFiatOffer() - Currently commented out
  • markPaymentSent() - Wire to UI
  • confirmPaymentReceived() - Wire to UI
  • cancelTrade() - New function
  • getTradeById() - New function
  • getUserTrades() - Fix and enhance

Checklist 1.5

  • Uncomment and test acceptFiatOffer() DONE
  • Wire markPaymentSent() to trade page DONE
  • Wire confirmPaymentReceived() to trade page DONE
  • Implement cancelTrade() with rules DONE
  • Implement getTradeById() for detail page DONE
  • Add Supabase real-time subscription helper DONE
  • Test full trade flow end-to-end BUILD PASSES

1.6 App Routes Update

File: src/App.tsx

New Routes

<Route path="/p2p/trade/:tradeId" element={<P2PTrade />} />
<Route path="/p2p/orders" element={<P2POrders />} />

Checklist 1.6

  • Import P2PTrade component DONE
  • Import P2POrders component DONE
  • Add routes with lazy loading DONE
  • Update navigation links DONE

Phase 1 Final Checklist

Database

  • All required tables exist (needs Supabase migration)
  • Sample payment methods seeded
  • RLS policies configured

Components

  • P2PTrade.tsx created and functional DONE (~600 lines)
  • P2POrders.tsx created and functional DONE (~250 lines)
  • P2PDashboard.tsx updated DONE (stats + My Orders link)
  • TradeTimeline.tsx created DONE (embedded in P2PTrade.tsx)
  • PaymentProofUpload.tsx created DONE (embedded in P2PTrade.tsx modal)

Functions

  • acceptFiatOffer() working DONE (wired to TradeModal)
  • markPaymentSent() working DONE (wired to P2PTrade)
  • confirmPaymentReceived() working DONE (wired to P2PTrade)
  • cancelTrade() working DONE (new function added)
  • Real-time updates working DONE (Supabase channel subscription)

Testing

  • Create offer as Seller (needs Supabase tables)
  • Accept offer as Buyer
  • Mark payment as sent
  • Confirm and release crypto
  • Cancel trade (before payment)
  • View in My Orders

UI/UX

  • Responsive on mobile DONE
  • Loading states DONE
  • Error handling DONE
  • Toast notifications DONE
  • i18n translations (pending)

Phase 1 Status: 90% Complete - Only database setup and i18n remaining


PHASE 2: Communication & Trust

Goal: Enable real-time chat and build trust through ratings

Duration: 1-2 weeks

Prerequisites: Phase 1 completed

2.1 Database Schema

-- p2p_messages table
CREATE TABLE p2p_messages (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  trade_id UUID NOT NULL REFERENCES p2p_fiat_trades(id) ON DELETE CASCADE,
  sender_id UUID NOT NULL REFERENCES auth.users(id),
  message TEXT NOT NULL,
  message_type VARCHAR(20) DEFAULT 'text', -- text, image, system
  attachment_url TEXT,
  is_read BOOLEAN DEFAULT FALSE,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Enable RLS
ALTER TABLE p2p_messages ENABLE ROW LEVEL SECURITY;

-- Policy: Only trade participants can read/write
CREATE POLICY "Trade participants can access messages" ON p2p_messages
  FOR ALL USING (
    EXISTS (
      SELECT 1 FROM p2p_fiat_trades t
      WHERE t.id = trade_id
      AND (t.seller_id = auth.uid() OR t.buyer_id = auth.uid())
    )
  );

-- p2p_ratings table
CREATE TABLE p2p_ratings (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  trade_id UUID NOT NULL REFERENCES p2p_fiat_trades(id),
  rater_id UUID NOT NULL REFERENCES auth.users(id),
  rated_id UUID NOT NULL REFERENCES auth.users(id),
  rating INT NOT NULL CHECK (rating BETWEEN 1 AND 5),
  review TEXT,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  UNIQUE(trade_id, rater_id)
);

-- Enable RLS
ALTER TABLE p2p_ratings ENABLE ROW LEVEL SECURITY;

-- p2p_notifications table
CREATE TABLE p2p_notifications (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID NOT NULL REFERENCES auth.users(id),
  type VARCHAR(50) NOT NULL,
  title TEXT NOT NULL,
  message TEXT,
  reference_type VARCHAR(20), -- trade, offer, dispute
  reference_id UUID,
  is_read BOOLEAN DEFAULT FALSE,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Enable RLS
ALTER TABLE p2p_notifications ENABLE ROW LEVEL SECURITY;

-- Policy: Users can only see their own notifications
CREATE POLICY "Users can access own notifications" ON p2p_notifications
  FOR ALL USING (user_id = auth.uid());

-- Enable Realtime for messages
ALTER PUBLICATION supabase_realtime ADD TABLE p2p_messages;
ALTER PUBLICATION supabase_realtime ADD TABLE p2p_notifications;

Checklist 2.1

  • Create p2p_messages table (SQL ready, needs Supabase migration)
  • Create p2p_ratings table (SQL ready)
  • Create p2p_notifications table (SQL ready)
  • Configure RLS policies
  • Enable Supabase Realtime
  • Test real-time subscriptions

2.2 Trade Chat Component

File: src/components/p2p/TradeChat.tsx

Features

  • Real-time message updates
  • Message input with send button
  • Image/file attachment
  • System messages (auto-generated)
  • Read receipts
  • Scroll to bottom on new message
  • Message timestamps

Checklist 2.2

  • Create TradeChat.tsx component DONE (~350 lines)
  • Supabase real-time subscription DONE
  • Send message function DONE
  • File upload to Supabase Storage DONE
  • System message display (different style) DONE
  • Auto-scroll behavior DONE
  • Unread message indicator DONE
  • Mobile keyboard handling DONE

2.3 Rating Modal

File: src/components/p2p/RatingModal.tsx

Features

  • Star rating (1-5)
  • Optional text review
  • Submit after trade completion
  • Cannot rate twice

Checklist 2.3

  • Create RatingModal.tsx component DONE (~250 lines)
  • Star rating input DONE (hover + click)
  • Optional review textarea DONE
  • Submit rating function DONE
  • Show after trade completion DONE (integrated in P2PTrade)
  • Update p2p_reputation on rating DONE

2.4 Notification System

File: src/components/p2p/NotificationBell.tsx

Notification Types

  • new_order - Someone accepted your offer
  • payment_sent - Buyer marked payment sent
  • payment_confirmed - Seller released crypto
  • trade_cancelled - Trade was cancelled
  • dispute_opened - Dispute opened
  • new_message - New chat message

Checklist 2.4

  • Create NotificationBell.tsx component DONE (~270 lines)
  • Real-time notification subscription DONE
  • Unread count badge DONE
  • Notification dropdown/panel DONE
  • Mark as read function DONE
  • Click to navigate to trade DONE
  • Create notification triggers (Supabase functions - pending)

2.5 Reputation Display Enhancement

File: Update reputation display in AdList.tsx

Features

  • Completion rate percentage
  • Total trades count
  • Average rating (stars)
  • Verified merchant badge
  • Fast trader badge
  • Trust level indicator

Checklist 2.5

  • Enhanced reputation card (already exists in AdList.tsx)
  • Star rating display (pending)
  • Badges (verified, fast) DONE (already in AdList.tsx)
  • Trust level color coding
  • Tooltip with details

Phase 2 Final Checklist

Database

  • p2p_messages table created (SQL ready)
  • p2p_ratings table created (SQL ready)
  • p2p_notifications table created (SQL ready)
  • Realtime enabled

Components

  • TradeChat.tsx functional DONE
  • RatingModal.tsx functional DONE
  • NotificationBell.tsx functional DONE
  • Enhanced reputation display (partial)

Functions

  • sendMessage() working DONE
  • submitRating() working DONE
  • createNotification() working DONE
  • Real-time subscriptions working DONE

Testing

  • Send and receive messages in trade (needs Supabase tables)
  • Upload image in chat (needs storage bucket)
  • Rate counterparty after trade
  • Receive notifications
  • View and dismiss notifications

Phase 2 Status: 85% Complete - All components done, awaiting Supabase table creation

Phase 2 Components Summary

Component File Lines Status
TradeChat TradeChat.tsx ~350 Complete
RatingModal RatingModal.tsx ~230 Complete
NotificationBell NotificationBell.tsx ~270 Complete
P2PTrade Integration P2PTrade.tsx ~875 Complete
P2PDashboard Integration P2PDashboard.tsx ~145 Complete

PHASE 3: Security & Disputes

Goal: Enable dispute resolution and fraud prevention

Duration: 1 week

Prerequisites: Phase 2 completed

3.1 Database Schema

-- p2p_disputes table
CREATE TABLE p2p_disputes (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  trade_id UUID NOT NULL REFERENCES p2p_fiat_trades(id),
  opened_by UUID NOT NULL REFERENCES auth.users(id),
  reason TEXT NOT NULL,
  description TEXT,
  status VARCHAR(20) DEFAULT 'open', -- open, under_review, resolved, closed
  resolution VARCHAR(20), -- release_to_buyer, refund_to_seller, split
  resolution_notes TEXT,
  resolved_by UUID REFERENCES auth.users(id),
  resolved_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- p2p_dispute_evidence table
CREATE TABLE p2p_dispute_evidence (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  dispute_id UUID NOT NULL REFERENCES p2p_disputes(id) ON DELETE CASCADE,
  uploaded_by UUID NOT NULL REFERENCES auth.users(id),
  evidence_type VARCHAR(20) NOT NULL, -- screenshot, receipt, bank_statement, chat_log, other
  file_url TEXT NOT NULL,
  description TEXT,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- p2p_fraud_reports table
CREATE TABLE p2p_fraud_reports (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  reporter_id UUID NOT NULL REFERENCES auth.users(id),
  reported_user_id UUID NOT NULL REFERENCES auth.users(id),
  trade_id UUID REFERENCES p2p_fiat_trades(id),
  reason VARCHAR(50) NOT NULL,
  description TEXT,
  status VARCHAR(20) DEFAULT 'pending', -- pending, investigating, resolved, dismissed
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Enable RLS
ALTER TABLE p2p_disputes ENABLE ROW LEVEL SECURITY;
ALTER TABLE p2p_dispute_evidence ENABLE ROW LEVEL SECURITY;
ALTER TABLE p2p_fraud_reports ENABLE ROW LEVEL SECURITY;

Checklist 3.1

  • Create p2p_disputes table
  • Create p2p_dispute_evidence table
  • Create p2p_fraud_reports table
  • Configure RLS policies
  • Create admin access for dispute resolution

3.2 Dispute Modal

File: src/components/p2p/DisputeModal.tsx

Features

  • Reason selection (dropdown)
  • Description textarea
  • Evidence upload (multiple files)
  • Terms acceptance checkbox
  • Submit dispute

Dispute Reasons

  • Payment not received
  • Wrong amount received
  • Seller not responding
  • Buyer not responding
  • Fraudulent behavior
  • Other

Checklist 3.2

  • Create DisputeModal.tsx DONE (~300 lines)
  • Reason dropdown DONE (8 reasons based on role)
  • Description input DONE (min 20 chars, max 2000)
  • Multi-file evidence upload DONE (max 5 files, 10MB each)
  • Submit dispute function DONE
  • Update trade status to 'disputed' DONE

3.3 Dispute View Page

File: src/pages/P2PDispute.tsx

Features

  • Dispute details
  • Evidence gallery
  • Both parties' submissions
  • Status timeline
  • Resolution display (when resolved)

Checklist 3.3

  • Create P2PDispute.tsx page DONE (~450 lines)
  • Add route /p2p/dispute/:disputeId DONE
  • Display dispute info DONE
  • Evidence gallery with lightbox DONE
  • Add more evidence button DONE
  • Status indicator DONE (timeline with open/under_review/resolved)

3.4 Fraud Prevention Rules

Auto-Detection Triggers

  • Multiple cancelled trades in 24h
  • Payment marked but disputed frequently
  • New account with large trades
  • Mismatched payment account names

Checklist 3.4

  • Implement cancel rate tracking DONE (fraud-prevention.ts + SQL)
  • Block users with high cancel rate DONE (check_trade_allowed function)
  • Payment name verification prompt DONE (fraud rule)
  • New user trade limits DONE (TRADE_LIMITS by trust level)
  • Suspicious activity alerts (admin) DONE (p2p_suspicious_activity table)

Phase 3 Final Checklist

Database

  • p2p_disputes table created DONE (007_create_p2p_fiat_system.sql)
  • p2p_dispute_evidence table created DONE (010_p2p_phase2_phase3_tables.sql)
  • p2p_fraud_reports table created DONE (010_p2p_phase2_phase3_tables.sql)
  • p2p_messages table created DONE (010_p2p_phase2_phase3_tables.sql)
  • p2p_ratings table created DONE (010_p2p_phase2_phase3_tables.sql)
  • p2p_notifications table created DONE (010_p2p_phase2_phase3_tables.sql)
  • p2p_user_fraud_indicators table created DONE (011_p2p_fraud_prevention.sql)
  • p2p_suspicious_activity table created DONE (011_p2p_fraud_prevention.sql)
  • RLS configured (policies ready) DONE

Components

  • DisputeModal.tsx functional DONE
  • P2PDispute.tsx page functional DONE
  • Evidence upload working DONE
  • Dispute status in trade page DONE (integrated in P2PTrade.tsx)
  • DisputeResolutionPanel.tsx (admin) DONE (~550 lines)

Functions

  • openDispute() working DONE (DisputeModal)
  • uploadEvidence() working DONE (Supabase Storage)
  • resolveDispute() (admin) working DONE (DisputeResolutionPanel)
  • Fraud detection rules active DONE (fraud-prevention.ts + SQL triggers)

Testing

  • Build passing DONE
  • Lint clean DONE
  • 32/32 tests passing DONE

Phase 3 Status: 95% Complete - All components and DB migrations ready, awaiting Supabase deployment

Phase 3 Components Summary

Component File Lines Status
DisputeModal DisputeModal.tsx ~300 Complete
P2PDispute Page P2PDispute.tsx ~440 Complete
DisputeResolutionPanel DisputeResolutionPanel.tsx ~550 Complete
P2PTrade Integration P2PTrade.tsx Updated Complete
App.tsx Route /p2p/dispute/:disputeId Added Complete
AdminPanel Integration AdminPanel.tsx Updated Complete

Database Migrations

Migration Tables/Functions Status
010_p2p_phase2_phase3_tables.sql messages, ratings, notifications, evidence, fraud_reports Ready
011_p2p_fraud_prevention.sql fraud_indicators, suspicious_activity, risk scoring Ready

Fraud Prevention System

Feature Implementation Status
Risk Score Calculation calculate_user_risk_score() Complete
Trade Limits by Trust Level check_trade_allowed() Complete
Cooldown Periods After cancellation/dispute Complete
Auto-blocking High risk users (score >= 95) Complete
Suspicious Activity Logging log_suspicious_activity() Complete

Test Suite (32 Tests Passing)

Test File Tests Status
trade-flow.test.ts 15 Pass
security-scenarios.test.ts 11 Pass
smoke.test.ts 1 Pass
utils.test.ts 4 Pass
badge.test.tsx 1 Pass

Security Scenarios Tested

  1. Escrow timeout returns tokens to seller
  2. Buyer can open dispute if seller does not confirm
  3. Admin can release to buyer when evidence proves payment
  4. Admin can refund to seller when payment is fake
  5. Double-spend prevention (locked tokens cannot be reused)
  6. Auto-dispute after 2 hours without confirmation
  7. Both parties can add evidence
  8. Reputation impact for dispute losers (-15)
  9. Only admin can resolve disputes

PHASE 4: Merchant & Advanced Features

Goal: Professional trading experience with merchant tiers

Duration: 1-2 weeks

Prerequisites: Phase 3 completed

4.1 Database Schema

-- p2p_merchant_tiers table
CREATE TABLE p2p_merchant_tiers (
  user_id UUID PRIMARY KEY REFERENCES auth.users(id),
  tier VARCHAR(20) DEFAULT 'lite', -- lite, super, diamond
  deposit_amount DECIMAL(18,2) DEFAULT 0,
  deposit_token VARCHAR(10) DEFAULT 'HEZ',
  deposit_tx_hash TEXT,
  max_pending_orders INT DEFAULT 5,
  max_order_amount DECIMAL(18,2) DEFAULT 10000,
  application_status VARCHAR(20), -- pending, approved, rejected
  applied_at TIMESTAMPTZ,
  approved_at TIMESTAMPTZ,
  approved_by UUID,
  last_review_at TIMESTAMPTZ,
  notes TEXT
);

-- p2p_merchant_stats table (materialized view or regular table)
CREATE TABLE p2p_merchant_stats (
  user_id UUID PRIMARY KEY REFERENCES auth.users(id),
  total_volume_30d DECIMAL(18,2) DEFAULT 0,
  total_trades_30d INT DEFAULT 0,
  completion_rate_30d DECIMAL(5,2) DEFAULT 0,
  avg_release_time_minutes INT,
  avg_payment_time_minutes INT,
  last_calculated_at TIMESTAMPTZ DEFAULT NOW()
);

-- Enable RLS
ALTER TABLE p2p_merchant_tiers ENABLE ROW LEVEL SECURITY;
ALTER TABLE p2p_merchant_stats ENABLE ROW LEVEL SECURITY;

Checklist 4.1

  • Create p2p_merchant_tiers table
  • Create p2p_merchant_stats table
  • Create stats calculation function
  • Configure RLS policies

4.2 Merchant Tier System

Tier Definitions

Tier Deposit Max Order Pending Requirements
Lite 0 $10K 5 KYC complete
Super 10K HEZ $100K 20 90% rate, 20+ trades
Diamond 50K HEZ $150K 50 95% rate, 100+ trades, invite

Checklist 4.2

  • Define tier constants
  • Tier upgrade eligibility check
  • Deposit locking mechanism
  • Tier badge component
  • Tier benefits enforcement

4.3 Merchant Application

File: src/components/p2p/MerchantApplication.tsx

Features

  • Current tier display
  • Next tier requirements
  • Progress indicators
  • Apply button
  • Deposit instructions

Checklist 4.3

  • Create MerchantApplication.tsx
  • Show current tier status
  • Show upgrade requirements
  • Progress bars for each metric
  • Application form
  • Deposit flow integration

4.4 Merchant Dashboard

File: src/pages/P2PMerchantDashboard.tsx

Features

  • Active ads management
  • Trade statistics
  • Revenue analytics
  • Payment method settings
  • Auto-reply configuration
  • Order limits management

Checklist 4.4

  • Create P2PMerchantDashboard.tsx
  • Add route /p2p/merchant
  • Active ads list with edit/delete
  • Stats cards (volume, trades, rate)
  • Charts (daily volume, trades)
  • Payment method management
  • Auto-reply message setting

4.5 Advanced Filters

File: src/components/p2p/OrderFilters.tsx

Filter Options

  • Crypto: HEZ, PEZ
  • Fiat: TRY, EUR, USD, IQD, IRR
  • Payment method (dynamic)
  • Amount range (min-max)
  • Merchant tier (Super+, Diamond)
  • Completion rate (90%+)
  • Online now toggle

Checklist 4.5

  • Create OrderFilters.tsx
  • Crypto dropdown
  • Fiat dropdown
  • Payment method multi-select
  • Amount range inputs
  • Tier filter checkboxes
  • Apply filters to query
  • Save filter preferences

Features

  • Featured placement at top
  • Highlighted styling
  • Bid for featured spot
  • Duration-based featuring

Checklist 4.6

  • Add is_featured column to offers
  • Featured ad styling
  • Feature request flow
  • Admin approval for featuring

Phase 4 Final Checklist

Database

  • p2p_merchant_tiers table created
  • p2p_merchant_stats table created
  • Stats calculation function working

Components

  • MerchantApplication.tsx functional
  • P2PMerchantDashboard.tsx functional
  • OrderFilters.tsx functional
  • Tier badges displayed

Functions

  • applyForTier() working
  • lockDeposit() working
  • calculateMerchantStats() working
  • Filter queries working

Testing

  • View merchant requirements
  • Apply for Super tier
  • Lock deposit for tier
  • Use advanced filters
  • View merchant dashboard

Final Acceptance Criteria

Full Feature Parity Checklist

Trade Flow

  • Create sell offer with escrow
  • Browse and filter offers
  • Accept offer as buyer
  • Mark payment as sent
  • Upload payment proof
  • Release crypto as seller
  • Cancel trade (with rules)
  • View trade history

Communication

  • Real-time chat in trade
  • Send images/files
  • Receive notifications
  • Rate counterparty

Security

  • Open dispute
  • Upload evidence
  • View dispute status
  • Fraud prevention active

Merchant Features

  • View merchant tier
  • Apply for upgrade
  • Lock deposit
  • Merchant dashboard
  • Advanced filters
  • Featured ads

UI/UX

  • Mobile responsive
  • Dark theme consistent
  • Loading states
  • Error handling
  • i18n complete
  • Accessibility (a11y)

Tech Stack Summary

Layer Technology
Frontend React + TypeScript + Vite
UI shadcn/ui + Tailwind CSS
State React Context + TanStack Query
Backend Supabase (Auth, DB, Storage, Realtime)
Blockchain Polkadot.js API
File Storage Supabase Storage / IPFS

Risk Mitigation

Risk Mitigation
Escrow security Multisig wallet, audit before mainnet
Fraud Reputation system, dispute process, limits
Scalability Supabase auto-scaling, efficient queries
UX complexity Progressive disclosure, tooltips, guides

Next Steps

  1. Start Phase 1 - Create P2PTrade.tsx and wire up trade flow
  2. Review and approve database schema changes
  3. Set up Supabase Storage bucket for payment proofs
  4. Test escrow flow on testnet

Document Version: 1.0 Last Updated: 2025-12-11