Add proper deposit desk: multi-coin, clear custody model, DepositWidget
- /account/add-funds: full rebuild as Deposit Desk
- 3-step how-it-works explainer: you send crypto → we hold it →
you shop with USD credit → we pay vendors with your crypto
- Coin selector: BTC (auto-verify), ETH (manual review), XMR (manual review)
- Each coin shows deposit address from env var with copy button
- BTC: immediate on-chain verify via /api/btc/verify (mempool.space)
- ETH/XMR: submit txhash to /api/pending-deposit for manual review
- Pending deposit history stored in localStorage with status
- Important notes block explaining custody, no-withdrawal, confirmations
- Back-links to checkout, wallets, dashboard
- /api/pending-deposit: new route to log ETH/XMR manual review requests
(logs to console, ready to wire to DB/webhook)
- DepositWidget component: reusable compact + full variants
- compact: balance + "Deposit crypto →" CTA (used in checkout)
- full: balance + how-it-works summary (used in dashboard)
- Dashboard: replace balance section with DepositWidget + stats
- Checkout: add compact DepositWidget above CheckoutFlow, fix back link
from "Sanctuary" → "Market", update feature cards to be accurate
- .env.example: document all three coin address env vars + optional
payment processor URL
- .env.example: add NEXT_PUBLIC_ETH_ADDRESS, NEXT_PUBLIC_XMR_ADDRESS
Made-with: Cursor
This commit is contained in:
85
components/DepositWidget.tsx
Normal file
85
components/DepositWidget.tsx
Normal file
@@ -0,0 +1,85 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { useWallet } from "@/contexts/WalletContext";
|
||||
import { useAccount } from "@/contexts/AccountContext";
|
||||
import { isMerchantBtcConfigured } from "@/lib/merchantBtc";
|
||||
|
||||
type DepositWidgetProps = {
|
||||
compact?: boolean;
|
||||
};
|
||||
|
||||
export default function DepositWidget({ compact = false }: DepositWidgetProps) {
|
||||
const { usdStoreCredit, luxCredits } = useWallet();
|
||||
const { user } = useAccount();
|
||||
const btcReady = isMerchantBtcConfigured();
|
||||
|
||||
if (compact) {
|
||||
return (
|
||||
<div className="glass rounded-2xl border border-neon-cyan/20 p-5">
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<div>
|
||||
<div className="text-xs text-foreground/50">Your balance</div>
|
||||
<div className="mt-0.5 font-orbitron text-2xl text-neon-cyan">
|
||||
${usdStoreCredit.toFixed(2)}
|
||||
<span className="ml-2 text-sm text-foreground/40">USD</span>
|
||||
</div>
|
||||
<div className="mt-0.5 text-xs text-neon-green">{luxCredits.toLocaleString()} LUX</div>
|
||||
</div>
|
||||
<Link
|
||||
href="/account/add-funds"
|
||||
className="shrink-0 rounded-xl bg-gradient-to-r from-neon-cyan to-neon-purple px-5 py-3 text-sm font-bold text-background hover:opacity-90"
|
||||
>
|
||||
Deposit crypto →
|
||||
</Link>
|
||||
</div>
|
||||
{!user && (
|
||||
<p className="mt-3 text-xs text-amber-300/70">
|
||||
<Link href="/sign-in?next=/account/add-funds" className="underline">Sign in</Link> to link deposits to your handle.
|
||||
</p>
|
||||
)}
|
||||
{!btcReady && (
|
||||
<p className="mt-2 text-[10px] text-amber-400/60">
|
||||
Operator: set <code>NEXT_PUBLIC_MERCHANT_BTC_ADDRESS</code> in .env.local to enable deposits.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="glass rounded-2xl border border-white/10 p-6">
|
||||
<div className="mb-4 flex items-start justify-between gap-3">
|
||||
<div>
|
||||
<div className="text-xs text-foreground/50">Account balance</div>
|
||||
<div className="mt-1 font-orbitron text-3xl text-neon-cyan">${usdStoreCredit.toFixed(2)}</div>
|
||||
<div className="mt-0.5 text-sm text-neon-green">{luxCredits.toLocaleString()} LUX</div>
|
||||
</div>
|
||||
<Link
|
||||
href="/account/add-funds"
|
||||
className="rounded-xl bg-gradient-to-r from-neon-cyan to-neon-purple px-5 py-3 text-sm font-bold text-background hover:opacity-90"
|
||||
>
|
||||
Add crypto →
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 rounded-xl border border-white/10 bg-black/30 p-4 text-sm">
|
||||
<div className="mb-2 text-xs font-bold uppercase tracking-wider text-foreground/50">How it works</div>
|
||||
<div className="space-y-2 text-foreground/70">
|
||||
<div className="flex items-start gap-2">
|
||||
<span className="mt-0.5 shrink-0 text-neon-cyan">1.</span>
|
||||
<span>You send crypto to our receiving address.</span>
|
||||
</div>
|
||||
<div className="flex items-start gap-2">
|
||||
<span className="mt-0.5 shrink-0 text-neon-cyan">2.</span>
|
||||
<span>We verify on-chain and credit your account at market USD rate.</span>
|
||||
</div>
|
||||
<div className="flex items-start gap-2">
|
||||
<span className="mt-0.5 shrink-0 text-neon-cyan">3.</span>
|
||||
<span>You shop with USD credits. We hold the crypto and pay vendors on your behalf.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user