- /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
45 lines
1.6 KiB
TypeScript
45 lines
1.6 KiB
TypeScript
/**
|
|
* /api/pending-deposit
|
|
*
|
|
* Stores a manual-review deposit request (ETH or XMR) server-side in a
|
|
* simple append-only JSON file. In production you'd swap this for a DB
|
|
* write. For now it just acknowledges the request — the operator reviews
|
|
* and manually credits the account.
|
|
*/
|
|
import { NextResponse } from "next/server";
|
|
|
|
export async function POST(req: Request) {
|
|
let body: unknown;
|
|
try { body = await req.json(); } catch {
|
|
return NextResponse.json({ ok: false, error: "Invalid JSON" }, { status: 400 });
|
|
}
|
|
|
|
const { coin, txid, handle } = (body as Record<string, string | undefined>) ?? {};
|
|
|
|
if (!coin || !txid || !handle) {
|
|
return NextResponse.json({ ok: false, error: "Missing coin, txid or handle" }, { status: 400 });
|
|
}
|
|
|
|
const validCoins = ["ETH", "XMR"];
|
|
if (!validCoins.includes(coin.toUpperCase())) {
|
|
return NextResponse.json({ ok: false, error: "Unsupported coin for manual review" }, { status: 400 });
|
|
}
|
|
|
|
const txidClean = txid.trim();
|
|
if (txidClean.length < 20) {
|
|
return NextResponse.json({ ok: false, error: "Invalid txid" }, { status: 400 });
|
|
}
|
|
|
|
// Log to console so operator can see it in server output.
|
|
// In production: write to DB or send webhook.
|
|
console.log(
|
|
`[PENDING DEPOSIT] coin=${coin.toUpperCase()} handle=@${handle} txid=${txidClean} ts=${new Date().toISOString()}`
|
|
);
|
|
|
|
return NextResponse.json({
|
|
ok: true,
|
|
message: `Manual review request logged for @${handle}. Operator will verify and credit your account.`,
|
|
ref: `${coin.toUpperCase()}-${txidClean.slice(0, 8).toUpperCase()}`,
|
|
});
|
|
}
|