fix(marketplace): live BTC/USD sats estimate; drop dead Pay button

- Sats prices used a hardcoded $1 = 2500 sats (i.e. $40k/BTC), so buyers were
  quoted wrong amounts; now uses the live useUsdToSats rate, handles sats/BTC
  directly, and shows no estimate for unsupported fiat
- Removed the 'Pay with Cashu' button, which only ever showed a 'coming soon'
  toast — a dead affordance. Buyers use Contact Seller.
This commit is contained in:
SkateSpots 2026-09-26 18:02:24 +07:00
parent dca0c0ede1
commit 102d6017bc

View file

@ -26,6 +26,7 @@ import { Label } from '@/components/ui/label';
import { useAuthor } from '@/hooks/useAuthor'; import { useAuthor } from '@/hooks/useAuthor';
import { useCurrentUser } from '@/hooks/useCurrentUser'; import { useCurrentUser } from '@/hooks/useCurrentUser';
import { useCashu } from '@/hooks/wallet/useCashu'; import { useCashu } from '@/hooks/wallet/useCashu';
import { useUsdToSats } from '@/hooks/useExchangeRate';
import { useToast } from '@/hooks/useToast'; import { useToast } from '@/hooks/useToast';
import { useNostrPublish } from '@/hooks/useNostrPublish'; import { useNostrPublish } from '@/hooks/useNostrPublish';
import { useListingReports } from '@/hooks/useListingReports'; import { useListingReports } from '@/hooks/useListingReports';
@ -84,7 +85,7 @@ export function MarketplaceItemCard({ item, compact = false }: MarketplaceItemCa
const { data: trustScore } = useTrustScore(item.pubkey); const { data: trustScore } = useTrustScore(item.pubkey);
// Cashu wallet integration // Cashu wallet integration
const { totalBalance: cashuBalance, isInitialized: hasCashu, coco } = useCashu(); const { totalBalance: cashuBalance, coco } = useCashu();
const [showPaymentDialog, setShowPaymentDialog] = useState(false); const [showPaymentDialog, setShowPaymentDialog] = useState(false);
const [showReportDialog, setShowReportDialog] = useState(false); const [showReportDialog, setShowReportDialog] = useState(false);
const [showDeleteDialog, setShowDeleteDialog] = useState(false); const [showDeleteDialog, setShowDeleteDialog] = useState(false);
@ -116,9 +117,19 @@ export function MarketplaceItemCard({ item, compact = false }: MarketplaceItemCa
// Get price type label // Get price type label
const priceTypeLabel = item.priceType ? PRICE_TYPES[item.priceType]?.label : null; const priceTypeLabel = item.priceType ? PRICE_TYPES[item.priceType]?.label : null;
// Calculate price in sats (rough estimate: $1 = 2500 sats at $40k/BTC) // Sats estimate from the LIVE BTC/USD rate — never a hardcoded constant
const priceInSats = item.price?.amount ? Math.round(parseFloat(item.price.amount) * 2500) : 0; // (that quoted buyers wildly wrong amounts). Non-USD fiat is left unestimated
const canPayWithCashu = hasCashu && cashuBalance >= priceInSats && priceInSats > 0; // rather than inventing a number.
const priceAmount = item.price?.amount ? parseFloat(item.price.amount) : 0;
const priceCurrency = item.price?.currency || 'USD';
const usdAsSats = useUsdToSats(priceCurrency === 'USD' ? priceAmount : null);
const priceInSats = !priceAmount
? 0
: priceCurrency === 'sats'
? Math.round(priceAmount)
: priceCurrency === 'BTC'
? Math.round(priceAmount * 100000000)
: (usdAsSats ?? 0);
// Seller verification status // Seller verification status
const isVerifiedSeller = sellerInfo?.hasNip05 || false; const isVerifiedSeller = sellerInfo?.hasNip05 || false;
@ -466,16 +477,10 @@ export function MarketplaceItemCard({ item, compact = false }: MarketplaceItemCa
{/* Action Buttons */} {/* Action Buttons */}
<div className="space-y-2"> <div className="space-y-2">
{/* Pay with Cashu button */} {/* NOTE: there is deliberately no "Pay with Cashu" button here.
{user && !isOwnListing && canPayWithCashu && item.status === 'active' && !isWTB && ( Payments are not implemented, and a button that only shows a
<Button "coming soon" toast is a dead end — buyers contact the seller
onClick={() => setShowPaymentDialog(true)} and arrange payment directly. */}
size="sm"
className="w-full gap-2 bg-orange-500 hover:bg-orange-600 text-white"
>
🥜 Pay {priceInSats.toLocaleString()} sats with Cashu
</Button>
)}
{/* Contact button */} {/* Contact button */}
<Button <Button