From 78f643d7a9a7871d9771bc9072b16e0888b4241e Mon Sep 17 00:00:00 2001 From: SkateSpots Date: Sat, 26 Sep 2026 22:39:58 +0700 Subject: [PATCH] feat(mints,escrow): MintRadar polish + escrow status in shared actions - Mints page: 'Online only' toggle + result count ('N of M mints') - Wallet page: 'Browse Cashu mints' link to /mints - ListingTradeActions now renders the EscrowPanel for a viewer's active escrow, so escrow status shows on both the grid card and the detail page - AGENTS.md project map: marketplace detail page + shared actions Gate: 101 tests, 0 errors/warnings, boot smoke green. --- AGENTS.md | 9 ++++-- src/components/ListingTradeActions.tsx | 4 +++ src/pages/MintsPage.tsx | 38 ++++++++++++++++++++------ src/pages/WalletPage.tsx | 12 ++++++++ 4 files changed, 51 insertions(+), 12 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 926f919..422b287 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -43,9 +43,12 @@ session with **no other memory of this project**. So: → `src/hooks/useTradeAttestations.ts`; reputation UI in `TradeReputationCard` - `35000–35012` role profiles (skater/filmer/coach/…) · `35006` crews · `30003` spot collections - `24899` spot chat · `2259` spot status · `32671` Sasquatch Pro · `7103` event updates -- **Marketplace**: `GearSwapPage` + `MarketplaceItemCard`. Buyer/seller trade - attestations build mutual, WoT-weighted reputation. **No payments are - implemented** — "Buy" is intentionally absent; only Contact/Offer/Trade. +- **Marketplace**: `GearSwapPage` (grid) + `MarketplaceItemCard` and a listing + detail page at **`/listing/:pubkey/:identifier`**. Trade/escrow actions live in + the shared **`ListingTradeActions`** (used by BOTH the card and the detail page + — one implementation). Buyer/seller attestations build mutual, WoT-weighted + reputation. **No payments are implemented** — "Buy" is intentionally absent; + buyers contact the seller and settle off-app. - **Cashu escrow** (marketplace): time-locked **P2PK** (lock to seller + buyer refund key + locktime) — see **`ESCROW.md`** and `src/lib/cashuEscrow.ts` (unit-tested). Protocol: `cashu_token` on the `31872`; each user advertises a diff --git a/src/components/ListingTradeActions.tsx b/src/components/ListingTradeActions.tsx index a68f480..ed38732 100644 --- a/src/components/ListingTradeActions.tsx +++ b/src/components/ListingTradeActions.tsx @@ -13,6 +13,7 @@ import { } from '@/hooks/useTradeAttestations'; import { useCashuEscrow } from '@/hooks/wallet/useCashuEscrow'; import { EscrowRequestDialog } from '@/components/EscrowRequestDialog'; +import { EscrowPanel } from '@/components/EscrowPanel'; import { parseEscrowToken } from '@/lib/cashuEscrow'; import { MessageCircle, Loader2, CheckCircle, Lock, Send, RotateCcw } from 'lucide-react'; import type { MarketplaceItem } from '@/lib/types'; @@ -132,6 +133,9 @@ export function ListingTradeActions({ item }: { item: MarketplaceItem }) { return (
+ {/* Active escrow the viewer holds on this listing (refundable after locktime) */} + {myEscrowToken && } + {/* Buyer: confirm the trade the seller recorded (builds both reps) */} {sellerNamedMe && !iConfirmedTrade && (
-
- - setQuery(e.target.value)} - placeholder="Search mints by name or URL…" - className="h-11 border-gray-700 bg-gray-900 pl-10 text-white" - /> +
+
+ + setQuery(e.target.value)} + placeholder="Search mints by name or URL…" + className="h-11 border-gray-700 bg-gray-900 pl-10 text-white" + /> +
+
+ {!isLoading && !error && ( +

+ {filtered.length} of {data?.length ?? 0} mints +

+ )} + {isLoading && (
{Array.from({ length: 6 }).map((_, i) => ( diff --git a/src/pages/WalletPage.tsx b/src/pages/WalletPage.tsx index 046f4db..9a20bff 100644 --- a/src/pages/WalletPage.tsx +++ b/src/pages/WalletPage.tsx @@ -1,5 +1,6 @@ import { useState } from 'react'; import { useSeoMeta } from '@unhead/react'; +import { Link } from 'react-router-dom'; import { Layout } from '@/components/Layout'; import { PageHeader } from '@/components/PageHeader'; import { WalletModal } from '@/components/WalletModal'; @@ -26,6 +27,7 @@ import { ChevronDown, ChevronUp, Wallet, + Coins, } from 'lucide-react'; // ─── Wallet status bar ──────────────────────────────────────────────────────── @@ -257,6 +259,16 @@ export default function WalletPage() { + + + Browse Cashu mints + + + + {/* Get a wallet — collapsed by default */}