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:
drjones
2026-04-16 01:03:14 -07:00
parent 2f928fbdc4
commit 348e55b63e
5 changed files with 596 additions and 143 deletions

View File

@@ -4,6 +4,7 @@ import { FormEvent, useEffect, useMemo, useState } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import Navbar from "@/components/Navbar";
import DepositWidget from "@/components/DepositWidget";
import { useAccount } from "@/contexts/AccountContext";
import { useWallet } from "@/contexts/WalletContext";
import { computeUserActivityStats } from "@/lib/userActivityStats";
@@ -100,33 +101,21 @@ export default function DashboardPage() {
</form>
</section>
<section className="glass rounded-2xl border border-neon-cyan/20 p-6">
<h2 className="font-orbitron text-lg font-bold text-neon-green">Balance</h2>
<p className="mt-2 text-sm text-zinc-500">
USD is credited after verified Bitcoin deposits to your merchant address. LUX is loyalty currency (e.g.
completed checkouts).
</p>
<ul className="mt-4 space-y-2 font-mono text-sm">
<li className="flex justify-between">
<span className="text-zinc-500">LUX</span>
<section>
<DepositWidget />
<div className="mt-3 glass rounded-xl border border-white/10 p-4 font-mono text-xs">
<div className="flex justify-between text-zinc-500">
<span>Vault keys</span>
<span className="text-zinc-300">{vault.keys.length}</span>
</div>
<div className="flex justify-between mt-2 text-zinc-500">
<span>LUX credits</span>
<span className="text-neon-green">{luxCredits.toLocaleString()}</span>
</li>
<li className="flex justify-between">
<span className="text-zinc-500">USD (spendable)</span>
</div>
<div className="flex justify-between mt-2 text-zinc-500">
<span>USD balance</span>
<span className="text-neon-cyan">${usdStoreCredit.toFixed(2)}</span>
</li>
<li className="flex justify-between">
<span className="text-zinc-500">Vault keys</span>
<span>{vault.keys.length}</span>
</li>
</ul>
<div className="mt-4 flex flex-wrap gap-3 text-xs font-bold uppercase tracking-wider">
<Link href="/account/add-funds" className="text-neon-green hover:underline">
Add funds (BTC)
</Link>
<Link href="/checkout" className="text-neon-cyan hover:underline">
Checkout
</Link>
</div>
</div>
</section>
</div>