/** * rExchange Schemas — P2P on/off-ramp exchange intents, trades, and reputation. * * DocId formats: * {space}:rexchange:intents → ExchangeIntentsDoc (active buy/sell intents) * {space}:rexchange:trades → ExchangeTradesDoc (active & historical trades) * {space}:rexchange:reputation → ExchangeReputationDoc (per-member trading reputation) */ import type { DocSchema } from '../../shared/local-first/document'; // ── Enums / Literals ── export type ExchangeSide = 'buy' | 'sell'; export type TokenId = 'cusdc' | 'myco' | 'fusdc'; export type FiatCurrency = 'EUR' | 'USD' | 'GBP' | 'BRL' | 'MXN' | 'INR' | 'NGN' | 'ARS'; export type RateType = 'fixed' | 'market_plus_bps'; export type IntentStatus = 'active' | 'matched' | 'completed' | 'cancelled' | 'expired'; export type TradeStatus = | 'proposed' | 'accepted' | 'escrow_locked' | 'fiat_sent' | 'fiat_confirmed' | 'completed' | 'disputed' | 'resolved' | 'cancelled' | 'timed_out'; // ── Exchange Intent ── export interface ExchangeIntent { id: string; creatorDid: string; creatorName: string; side: ExchangeSide; tokenId: TokenId; fiatCurrency: FiatCurrency; tokenAmountMin: number; // base units (6 decimals) tokenAmountMax: number; rateType: RateType; rateFixed?: number; // fiat per token (e.g. 0.98 EUR/cUSDC) rateMarketBps?: number; // basis points spread over market rate paymentMethods: string[]; // "SEPA", "Revolut", "PIX", "M-Pesa", "Cash", etc. isStandingOrder: boolean; // LP flag — re-activates after fill autoAccept: boolean; // skip manual match acceptance allowInstitutionalFallback: boolean; // escalate to HyperSwitch if unmatched minCounterpartyReputation?: number; // 0-100 preferredCounterparties?: string[]; // DID list status: IntentStatus; createdAt: number; expiresAt?: number; } // ── Trade Chat Message ── export interface TradeChatMessage { id: string; senderDid: string; senderName: string; text: string; timestamp: number; } // ── Exchange Trade ── export interface ExchangeTrade { id: string; buyIntentId: string; sellIntentId: string; buyerDid: string; buyerName: string; sellerDid: string; sellerName: string; tokenId: TokenId; tokenAmount: number; // agreed amount in base units fiatCurrency: FiatCurrency; fiatAmount: number; // agreed fiat amount agreedRate: number; // fiat per token paymentMethod: string; escrowTxId?: string; status: TradeStatus; acceptances: Record; // did → accepted? chatMessages: TradeChatMessage[]; fiatConfirmDeadline?: number; // timestamp — 24h default disputeReason?: string; resolution?: 'released_to_buyer' | 'returned_to_seller'; createdAt: number; completedAt?: number; } // ── Reputation ── export interface ExchangeReputationRecord { did: string; tradesCompleted: number; tradesCancelled: number; disputesRaised: number; disputesLost: number; totalVolumeBase: number; // total token volume in base units avgConfirmTimeMs: number; score: number; // 0-100 badges: string[]; // 'verified_seller', 'liquidity_provider', 'top_trader' } // ── Documents ── export interface ExchangeIntentsDoc { meta: { module: string; collection: string; version: number; spaceSlug: string; createdAt: number; }; intents: Record; } export interface ExchangeTradesDoc { meta: { module: string; collection: string; version: number; spaceSlug: string; createdAt: number; }; trades: Record; } export interface ExchangeReputationDoc { meta: { module: string; collection: string; version: number; spaceSlug: string; createdAt: number; }; records: Record; } // ── DocId helpers ── export function exchangeIntentsDocId(space: string) { return `${space}:rexchange:intents` as const; } export function exchangeTradesDocId(space: string) { return `${space}:rexchange:trades` as const; } export function exchangeReputationDocId(space: string) { return `${space}:rexchange:reputation` as const; } // ── Schema registrations ── export const exchangeIntentsSchema: DocSchema = { module: 'rexchange', collection: 'intents', version: 1, init: (): ExchangeIntentsDoc => ({ meta: { module: 'rexchange', collection: 'intents', version: 1, spaceSlug: '', createdAt: Date.now(), }, intents: {}, }), }; export const exchangeTradesSchema: DocSchema = { module: 'rexchange', collection: 'trades', version: 1, init: (): ExchangeTradesDoc => ({ meta: { module: 'rexchange', collection: 'trades', version: 1, spaceSlug: '', createdAt: Date.now(), }, trades: {}, }), }; export const exchangeReputationSchema: DocSchema = { module: 'rexchange', collection: 'reputation', version: 1, init: (): ExchangeReputationDoc => ({ meta: { module: 'rexchange', collection: 'reputation', version: 1, spaceSlug: '', createdAt: Date.now(), }, records: {}, }), };