Environment variables

This commit is contained in:
2026-10-20 16:24:01 -04:00
parent 4cac26d84b
commit 7734d8ae90
29 changed files with 267 additions and 38 deletions
+16 -1
View File
@@ -65,7 +65,20 @@ export function CustodyPanel({ wallet, snapshot, rpcAvailable }: Props) {
return () => { generation.current++; };
}, [refresh, rpcAvailable]);
useEffect(() => { if (review) reviewElement.current?.focus(); }, [review]);
const prepare = (action: CustodyAction, description: string) => { setError(''); setNotice(''); setReview({ action, description }); };
const prepare = (action: CustodyAction, description: string) => {
if (['list','reserve','mock-credit'].includes(action.type) && (page?.info.marketEnabled === false || page?.info.tradingEnabled === false)) {
setError('This host is not accepting new trading or funding. Existing balances and cancellation/withdrawal requests remain accessible.'); return;
}
if (action.type === 'list' || action.type === 'reserve') {
const listingId = action.type === 'reserve' ? action.listingId : undefined;
const recipient = action.type === 'reserve'
? page?.listings.find(l => l.id === listingId)?.hostFeeAddress ?? ADDITIONAL_MARKET_FEE.address
: page?.info.hostFeeAddress ?? ADDITIONAL_MARKET_FEE.address;
action = { ...action, hostFeeAddress: recipient };
description += ` Host fee recipient: ${recipient}. The separate fixed author fee is unchanged.`;
}
setError(''); setNotice(''); setReview({ action, description });
};
const submit = async (again?: CustodyCommand) => {
if (!wallet || !page || pending.current || (!review && !again)) return;
pending.current = true; setBusy(true); setError('');
@@ -93,6 +106,8 @@ export function CustodyPanel({ wallet, snapshot, rpcAvailable }: Props) {
<h2>A balance for this market.</h2>
<p>A future custodian would hold pooled XMR and track what each customer is owed. Purchases would move ledger balances, not XMR between subaddresses. You would trust the operator with your deposits.</p>
{enabled === false && <p className="market-reserved">This host has not enabled the custody sandbox. Real custody is unavailable.</p>}
{page&&(page.info.marketEnabled===false||page.info.tradingEnabled===false)&&<p role="status">{page.info.marketEnabled===false?'Public market disabled on this host.':'New trading paused on this host.'} Existing balances, cancellations and withdrawal requests remain accessible.</p>}
{page?.info.hostFeeAddress&&<p className="custody-identity">Host fee wallet (not a deposit address): {page.info.hostFeeAddress}</p>}
{!rpcAvailable && <p className="market-error">Reconnect to the node to use this preview.</p>}
{!wallet && <p>Open your Wikideck wallet to view private balances and authorize sandbox commands.</p>}
{page && <p className="muted custody-identity">Sandbox custodian {page.info.custodianId} · {page.info.network} · host {page.info.feeBps / 100}% + author 1%. Fresh custody signatures are required; legacy mock authorizations do not debit balances.</p>}
+16 -1
View File
@@ -86,7 +86,20 @@ export function Marketplace({ wallet, snapshot, rpcAvailable, onNotice }: Props)
const timer = setInterval(() => { setNow(Date.now()); if (rpcAvailable && !inFlight.current) load(); }, 15000);
return () => { active = false; version.current++; clearInterval(timer); };
}, [refresh, rpcAvailable]);
const prepare = (action: MarketAction | MarketActionV3, text: string, legacy = false) => { setError(''); setReview({ action, text, legacy }); };
const prepare = (action: MarketAction | MarketActionV3, text: string, legacy = false) => {
if (['list','bid','buy'].includes(action.type) && (page?.info.marketEnabled === false || page?.info.tradingEnabled === false)) {
setError('This host is not accepting new trading. Existing orders can still be resolved.'); return;
}
if (!legacy && (action.type === 'list' || action.type === 'buy')) {
const listingId = action.type === 'buy' ? action.listingId : undefined;
const recipient = action.type === 'buy'
? page?.listings.find(l => l.id === listingId)?.hostFeeAddress ?? ADDITIONAL_MARKET_FEE.address
: page?.info.hostFeeAddress ?? ADDITIONAL_MARKET_FEE.address;
action = { ...action, hostFeeAddress: recipient } as MarketActionV3;
text += ` Host fee recipient: ${recipient}. The separate fixed author fee is unchanged.`;
}
setError(''); setReview({ action, text, legacy });
};
const submit = async () => {
if (!wallet || !page || !review || inFlight.current || !rpcAvailable) return;
const currentVersion = version.current;
@@ -139,6 +152,8 @@ export function Marketplace({ wallet, snapshot, rpcAvailable, onNotice }: Props)
};
const disabled = busy || !wallet || !rpcAvailable || !page;
return <section className="marketplace">
{page&&(page.info.marketEnabled===false||page.info.tradingEnabled===false)&&<p className="market-simulation" role="status">{page.info.marketEnabled===false?'This peer does not offer a public marketplace.':'This peer has paused new trading.'} Existing orders, cancellations and resolution remain accessible through Your activity.</p>}
{page?.info.hostFeeAddress&&<p className="market-fee-recipient">Host fee wallet (public payout recipient, not a deposit address): <span>{page.info.hostFeeAddress}</span></p>}
<header className="market-hero"><div><div className="section-eyebrow">THIS PEER’S COLLECTOR EXCHANGE</div><h1>Your next find.<br/><span>Your kind of market.</span></h1><p>Buy a fixed-price card or join a timed auction. Prices are listed directly in XMR atomic units (12 decimal places). Every peer can host its own market; listings and orders remain local to that host.</p></div><div className="market-symbol"><ShoppingBag size={52}/><span>PEER-HOSTED · COMMUNITY-DRIVEN</span></div></header>
<p className="muted">Sales support the hosting peer’s operator through a configurable fee and the project author through a hardcoded 1% fee. Both are deducted from seller proceeds. Collection-specific curation tools and peer-hosted custom TCGs are planned, not available yet.</p>
<div className="market-simulation" role="note"><ShieldNote/><div><strong>Mock payments only · never send real XMR</strong><p>Quotes, payment confirmations, refunds, fees, and automatic seller payouts are simulated. Card delivery is a real on-chain transfer. There is no payable Monero address. Listings are local to this marketplace node, not shared by peers.</p></div><span className="market-mode">SANDBOX</span></div>