Real XMR pilot

This commit is contained in:
2026-10-22 14:40:00 -04:00
parent 52559f65d7
commit 3f04c3afa9
19 changed files with 408 additions and 50 deletions
+15 -15
View File
@@ -12,7 +12,7 @@ import { useModalFocus } from './useModalFocus.ts';
import { ThemePicker } from './ThemePicker.tsx';
import { TradeDesk } from './TradeDesk.tsx';
import { Marketplace } from './Marketplace.tsx';
import { IS_MAINNET, NETWORK_LABEL } from '../shared/network.ts';
import { IS_MAINNET, IS_PILOT, NETWORK_LABEL } from '../shared/network.ts';
import { StateClient } from '../shared/rpc-client.ts';
import './App.css';
import './testnet.css';
@@ -166,18 +166,18 @@ export default function App() {
const Icon = [LayoutDashboard, Layers3, Globe2, ArrowLeftRight, ShoppingBag][i];
return <button key={item} aria-label={item} aria-current={view === item ? 'page' : undefined} className={`nav-item ${view === item ? 'active' : ''}`} onClick={() => { setView(item); setQuery(''); setCategory('All cards'); }}><Icon size={18} />{item}{item === 'My collection' && <span className="nav-count">{owned.length}</span>}</button>;
})}</nav>
<div className="sidebar-note"><span className="tiny-spark">✦</span><h3>Your cards.<br />Your community.</h3><p>Mine Wikipedia NFT cards, build collections, and trade in peer-hosted markets.</p><button onClick={() => setDialog('guide')}>How it works <ArrowUpRight size={15} /></button></div>
<div className="sidebar-note"><span className="tiny-spark">✦</span><h3>Mine together.<br />Trade your way.</h3><p>Discover illustrated Wikipedia cards, build a deck around what you love, and find your collector community.</p><button onClick={() => setDialog('guide')}>How it works <ArrowUpRight size={15} /></button></div>
<div className="sidebar-bottom"><span className={`network-dot ${!rpcAvailable || !snapshot?.peers ? 'disconnected' : ''}`} /><span>{peerLabel}</span><span className="prototype">{NETWORK_LABEL}</span></div>
<button className="help-link" onClick={() => setDialog('guide')}><CircleHelp size={16} /> The field guide <ArrowUpRight size={14} /></button>
</aside>
<div className="main-shell">
<header className="topbar"><div className="breadcrumbs">Explore <ChevronRight size={13} /><span>{view}</span></div><div className="top-actions"><span className="testnet-brand">RandomX <b>{NETWORK_LABEL}</b></span><ThemePicker /><span className="network-pill"><span className={`network-dot ${!rpcAvailable || !snapshot?.peers ? 'disconnected' : ''}`} />{peerLabel}</span><button className="wallet-button" onClick={openWallet}><span className="wallet-avatar"><WalletIcon size={14} /></span>{wallet ? short(wallet.address) : 'Open wallet'}<ChevronRight size={14} /></button></div></header>
<main>
<div className="testnet-status" role="status"><span><span className={`network-dot ${rpcAvailable ? '' : 'disconnected'}`} /> RPC {rpcAvailable ? 'available' : 'unavailable'}</span><span>{peerLabel}</span><span>{IS_MAINNET?'Gated mainnet candidate · unaudited · mock payments only':'Unbootstrapped testnet · no public mainnet'}</span>{snapshot && !rpcAvailable && <strong>Showing last known state</strong>}</div>
<div className="testnet-status" role="status"><span><span className={`network-dot ${rpcAvailable ? '' : 'disconnected'}`} /> RPC {rpcAvailable ? 'available' : 'unavailable'}</span><span>{peerLabel}</span><span>{IS_MAINNET?'Gated mainnet candidate · unaudited · mock payments only':IS_PILOT?'Private pilot · mock custody only · no real XMR':'Unbootstrapped testnet · no public mainnet'}</span>{snapshot && !rpcAvailable && <strong>Showing last known state</strong>}</div>
{error && <div className="error-banner" role="alert"><CircleHelp size={17} /><span>{error}</span><button onClick={retry}>Retry</button><button aria-label="Dismiss error" onClick={() => setError('')}><X size={16} /></button></div>}
{view === 'Discover' && <>
<section className="hero">
<div className="hero-copy"><span className="eyebrow"><span /> WIKIPEDIA CARDS. THEIR OWN NFT BLOCKCHAIN.</span><h1>Mine knowledge.<br />Collect the <span>extraordinary.</span></h1><p>Mine a block. Earn a Wikipedia NFT card. Build collections, trade discoveries, and find your community in peer-hosted markets. Trading card games are next on the roadmap.</p><div className="hero-actions"><button className="button dark" onClick={goMine}><Pickaxe size={17} /> Start collecting <ArrowUpRight size={17} /></button><button className="text-button" onClick={() => setDialog('guide')}>How it works <ArrowRight size={16} /></button></div><div className="hero-foot"><span><Check size={13} /> Consumer-CPU mining</span><span><Check size={13} /> Peer-hosted markets</span></div></div>
<div className="hero-copy"><span className="eyebrow"><span /> MINE · BUILD A DECK · TRADE WITH YOUR PEOPLE</span><h1>Mine with your CPU.<br />Build a deck from <span>the world.</span></h1><p>Turn random illustrated Wikipedia discoveries into collectible cards. Use the same RandomX algorithm as Monero, grow a collection around what you love, then trade with other collectors. Community markets are here; card games are on the way.</p><div className="hero-actions"><button className="button dark" onClick={goMine}><Pickaxe size={17} /> Explore mining <ArrowUpRight size={17} /></button><button className="text-button" onClick={() => setDialog('guide')}>How it works <ArrowRight size={16} /></button></div><div className="hero-foot"><span><Check size={13} /> CPU-friendly RandomX</span><span><Check size={13} /> Collector-run markets</span></div></div>
<div className="hero-visual"><div className="orbit orbit-one" /><div className="orbit orbit-two" /><span className="orbit-spark spark-one">✳</span><span className="orbit-spark spark-two">+</span><div className="floating-label label-top"><Sparkles size={12} /> Preview cards · not owned</div><div className="hero-card back-card"><Card card={samples[2]} onClick={() => setSelected(samples[2])} /></div><div className="hero-card front-card"><Card card={samples[0]} onClick={() => setSelected(samples[0])} /></div><div className="floating-label label-bottom"><Sparkles size={15} /> A world worth collecting <ArrowUpRight size={13} /></div></div>
</section>
<section className="metrics" aria-label="Canonical chain statistics">
@@ -187,13 +187,13 @@ export default function App() {
<div><span className="metric-icon"><Cpu size={19} /></span><div><span>Proof of work</span><strong className="algorithm">{snapshot?.algorithm ?? 'RandomX'}<small>native CPU mining</small></strong></div></div>
</section>
<section className="mining-panel native-mining" ref={minerPanel}>
<div className="mining-description"><div className="section-eyebrow"><span className="idle-dot" /> RANDOMX · BUILT FOR GENERAL-PURPOSE CPUS</div><h2>Mine blocks. Earn cards.</h2><p>Wikideck uses RandomX, the proof-of-work algorithm also used by Monero, to keep mining competitive on consumer-grade CPUs. Each accepted block rewards its miner with an illustrated Wikipedia NFT card. Results depend on your hardware and network difficulty; Wikideck does not share Monero’s network security.</p><div className="mining-meta"><span><Cpu size={13} /> Consumer hardware</span><span><Shield size={13} /> Independent validating peers</span></div><div className="native-memory"><strong>Light · default</strong><span>256 MiB cache + scratchpad and overhead.</span><strong>Fast · --fast</strong><span>~2 GiB dataset plus cache; budget over 2.3 GiB per process. Mining consumes CPU, memory and energy; RandomX is not a guarantee of ASIC resistance or profitability.</span></div></div>
<div className="miner-controls"><div className="miner-display"><div><span>NEXT WIKIPEDIA ARTICLE</span><strong>{snapshot ? 'Chosen when the miner requests work' : 'Waiting for testnet RPC…'}</strong></div></div><p className="muted">Each mining template requests a random English Wikipedia article with a Wikimedia picture. Pages may repeat; every minted card carries its own statistics snapshot.</p><ol className="native-steps"><li>Build <code>wikideck-randomx</code> using the repository’s native build instructions.</li><li>Save your encrypted backup and keep its password separate.</li><li>Replace <code>&lt;backup.json&gt;</code> with your local file path (quote paths with spaces), then run:</li></ol><pre className="native-command"><code>{nativeCommand}</code></pre><p className="miner-footnote">Node: {window.location.origin}. Same-origin RPC, including the development proxy. Use HTTPS for remote nodes. Password entry stays local; never put it in the command. Defaults to one worker and at most one block. Ctrl+C stops the native miner; closing this page does not.</p><button className="button dark full" onClick={openWallet}><Download size={16} /> Download wallet backup</button><button className="text-button" onClick={() => setDialog('guide')}>Read the testnet field guide <ArrowRight size={14} /></button></div>
<div className="mining-description"><div className="section-eyebrow"><span className="idle-dot" /> RANDOMX · DESIGNED FOR GENERAL-PURPOSE CPUS</div><h2>Mining should be for more people.</h2><p>Wikideck and Monero use RandomX, an algorithm designed to resist specialized ASICs and keep general-purpose CPUs competitive. That can make mining more accessible—not make every machine equally powerful or promise rewards. Each accepted Wikideck block earns its miner a distinct illustrated Wikipedia card. Wikideck is its own independent network.</p><div className="mining-meta"><span><Cpu size={13} /> Mine with a CPU</span><span><Shield size={13} /> Independently validating peers</span></div><details className="mining-details"><summary>Hardware, rewards &amp; network details</summary><div className="native-memory"><strong>Light · default</strong><span>256 MiB cache plus scratchpad and process overhead.</span><strong>Fast · --fast</strong><span>About 2 GiB dataset plus cache; budget over 2.3 GiB per process. Mining uses CPU, memory, electricity and time. ASIC resistance is a design goal, not a guarantee; results depend on hardware and network difficulty. Wikideck does not share Monero’s network, hashpower or security.</span></div></details></div>
<div className="miner-controls"><div className="miner-display"><div><span>NEXT WIKIPEDIA ARTICLE</span><strong>{snapshot ? 'Chosen when the miner requests work' : 'Waiting for testnet RPC…'}</strong></div></div><p className="muted">The miner selects a random illustrated English Wikipedia article. The same article can appear again; each card keeps its own mint-time statistics.</p><details className="mining-details"><summary>Want to run a miner? Setup &amp; safety details</summary><ol className="native-steps"><li>Build <code>wikideck-randomx</code> using the repository’s native build instructions.</li><li>Save your encrypted backup and keep its password separate.</li><li>Replace <code>&lt;backup.json&gt;</code> with your local file path (quote paths with spaces), then run:</li></ol><pre className="native-command"><code>{nativeCommand}</code></pre><p className="miner-footnote">Node: {window.location.origin}. The command connects to this node; use HTTPS for remote nodes. Password entry stays local—never put it in the command. It defaults to one worker and at most one block. Ctrl+C stops the native miner; closing this page does not.</p></details><button className="button dark full" onClick={openWallet}><Download size={16} /> Download wallet backup</button><button className="text-button" onClick={() => setDialog('guide')}>Read the testnet field guide <ArrowRight size={14} /></button></div>
</section>
<section className="project-pillars" aria-label="Collect, host, and play">
<article><Layers3 size={22}/><div className="section-eyebrow">COLLECT & TRADE</div><h2>A collection with a story.</h2><p>Collect Wikipedia pages as cards, swap multiple cards in one trade, or list discoveries at a fixed price or timed auction.</p><button className="text-button" onClick={()=>setView('Trade decks')}>Trade cards <ArrowRight size={14}/></button></article>
<article><Globe2 size={22}/><div className="section-eyebrow">HOST YOUR OWN MARKET</div><h2>Your peer. Your community.</h2><p>Run a peer and host a market for everyone or a community centered on a collection. Sales allocate a hosting fee to the operator and a hardcoded 1% to the project author. Cryptocurrency checkout is designed for XMR; today payments and fees are simulated.</p><button className="text-button" onClick={()=>setView('Marketplace')}>Explore this peer’s market <ArrowRight size={14}/></button></article>
<article><Sparkles size={22}/><div className="section-eyebrow">ON THE ROADMAP · NOT PLAYABLE YET</div><h2>Cards made for more.</h2><p>Trading card games and peer-hosted custom TCGs are planned. The open-source direction is to let communities adapt markets and games; a software license still needs to be published. Built-in collection curation and custom game hosting are not available yet.</p><button className="text-button" onClick={()=>setDialog('guide')}>The project vision <ArrowRight size={14}/></button></article>
<article><Layers3 size={22}/><div className="section-eyebrow">COLLECT · DECK-BUILD · TRADE</div><h2>Make every deck your own.</h2><p>Chase a theme, collect the unexpected, or put together a multi-card swap. List a favorite for a fixed price or let collectors bid in an auction.</p><button className="text-button" onClick={()=>setView('Trade decks')}>Meet other collectors <ArrowRight size={14}/></button></article>
<article><Globe2 size={22}/><div className="section-eyebrow">A MARKET FOR YOUR COMMUNITY</div><h2>Collectors set the scene.</h2><p>Each peer can run its own market, with listings local to that host. New listings use XMR prices, but checkout is simulated: no real XMR is accepted or sent. Host and author fees are shown before you sign.</p><button className="text-button" onClick={()=>setView('Marketplace')}>Explore this peer’s market <ArrowRight size={14}/></button></article>
<article><Sparkles size={22}/><div className="section-eyebrow">NEXT UP · GAMEPLAY IS IN DEVELOPMENT</div><h2>Your cards, ready to play.</h2><p>Trading-card games and community-made rules are the bigger idea: build decks with a point of view, then play your way. The game engine and custom game hosting are planned, not playable today.</p><button className="text-button" onClick={()=>setDialog('guide')}>See what’s here today <ArrowRight size={14}/></button></article>
</section>
</>}
{view === 'Marketplace' ? <Marketplace wallet={wallet} snapshot={snapshot} rpcAvailable={rpcAvailable} onNotice={setToast} /> : view === 'Trade decks' ? <TradeDesk wallet={wallet} snapshot={snapshot} rpcAvailable={rpcAvailable} onNotice={setToast} /> : view !== 'Block explorer' ? <section className="discover-section">
@@ -217,14 +217,14 @@ export default function App() {
{toast && <div className="toast" role="status"><span><Check size={16} /></span>{toast}<button onClick={() => setToast('')} aria-label="Dismiss notification"><X size={14} /></button></div>}
{(dialog || selected) && <div className="modal-backdrop" onClick={e => { if (e.target === e.currentTarget) close(); }}><section className={`modal ${dialog === 'wallet' ? 'wallet-modal' : selected && !dialog ? 'card-modal' : ''}`} role="dialog" aria-modal="true" aria-label={dialog === 'wallet' ? 'Local testnet wallet' : dialog === 'transfer' ? 'Transfer native NFT' : dialog === 'guide' ? 'How Wikideck works' : 'Card details'}><button className="modal-close" aria-label="Close dialog" onClick={close} disabled={transferBusy}><X size={20} /></button>
{dialog === 'guide' ? <>
<span className="modal-icon"><Sparkles size={24}/></span><div className="section-eyebrow">THE WIKIDECK FIELD GUIDE</div><h2>Mine. Collect. Make it yours.</h2>
<span className="modal-icon"><Sparkles size={24}/></span><div className="section-eyebrow">THE WIKIDECK FIELD GUIDE</div><h2>Mine. Build a deck. Find your people.</h2>
<div className="guide-steps">
<div><span>01</span><div><h3>Mine a block. Earn a Wikipedia card.</h3><p>Wikideck is an NFT blockchain: each accepted block rewards its miner with a card based on a random illustrated Wikipedia page and its mint-time statistics. RandomX, also used by Monero, is designed for competitive mining on consumer CPUs. Wikideck is its own network, not part of Monero. Mining uses CPU, memory and energy; rewards depend on hardware and network difficulty.</p></div></div>
<div><span>02</span><div><h3>Build a collection. Trade your discoveries.</h3><p>Collect broadly or focus on a theme. Your encrypted local wallet controls your cards. Trade decks lets two players sign a multi-card swap that settles together when mined. Fixed-price sales and timed auctions live in the connected peer’s market. Transfers remain pending until mined, and chain reorganizations can change ownership and confirmations.</p></div></div>
<div><span>03</span><div><h3>Host a peer. Grow a community.</h3><p>A peer can host a general-purpose market or a community devoted to a collection. Listings and orders stay with that host, while card ownership follows the shared blockchain. Sales allocate a configurable hosting fee to the operator and a hardcoded 1% author fee. Prices are in USD with XMR cryptocurrency settlement planned; today payments, fees and payouts are simulations only.</p></div></div>
<div><span>04</span><div><h3>Custom trading card games — coming later.</h3><p>Playing TCGs with your cards and hosting custom TCGs on a peer are planned, not implemented. The open-source direction is to give operators freedom to adapt their market and future games; publishing the software license is still pending. Built-in collection curation and custom rules hosting are also future work. Shared consensus remains the same across compatible peers.</p></div></div>
<div><span>01</span><div><h3>Mine with a CPU. Discover a card.</h3><p>RandomX—the algorithm used by Wikideck and Monero—is designed to make specialized ASICs less advantageous and general-purpose CPUs more competitive. Mine a block to earn a one-of-a-kind card featuring a random illustrated Wikipedia article.</p><details><summary>Mining, rewards &amp; network facts</summary><p>ASIC resistance is a design goal, not a guarantee of equal performance. Results depend on hardware and network difficulty; there is no promised reward rate or profit. Wikideck is an independent network and does not share Monero’s hashpower or security. Mining uses CPU, memory, electricity and time.</p></details></div></div>
<div><span>02</span><div><h3>Build a deck that feels like yours.</h3><p>Collect across the encyclopedia or follow a theme. Your encrypted local wallet controls your cards. Trade multi-card bundles with another player, then explore fixed-price listings and timed auctions on the connected peer’s market.</p><details><summary>How ownership and trades work</summary><p>Both players sign the same card list; the whole swap is applied together when mined or rejected. Transfers remain pending until confirmed, and a chain reorganization can change confirmed ownership. Looking up a public wallet address reveals its confirmed holdings.</p></details></div></div>
<div><span>03</span><div><h3>Trade locally. Grow a collector community.</h3><p>Every peer can host its own market, so communities can create a place to trade around their interests. New listings are priced in XMR, but all checkout, fees and payouts are simulated today. Never send real XMR.</p><details><summary>Market fees &amp; what “simulated” means</summary><p>Listings and orders stay with the market host; NFT ownership follows the shared blockchain. The operator sets a hosting fee and the project author fee is 1%; both are deducted from simulated seller proceeds. Card delivery is a real on-chain transfer after the mock payment step. No payable Monero address or live payment processor is enabled.</p></details></div></div>
<div><span>04</span><div><h3>And then, play.</h3><p>Trading-card games are the fun we’re building toward: deck-building, collecting, and community-made ways to play with your cards.</p><details><summary>What is available now?</summary><p>Playable TCGs, match systems, deck rules and peer-hosted custom games are not implemented yet. Today’s card stats are collectible snapshots, not final game balance or a promise of financial value. This is an experimental testnet, not a public production network.</p></details></div></div>
</div>
<div className="info-box"><strong>Collectible cards, not ownership of Wikipedia.</strong><p>NFT rewards represent article snapshots, not rights to Wikipedia text or images. Follow each card’s attribution and licenses. This is an experimental testnet, not a launched production network; never send real XMR to its mock checkout. Current stats are not final TCG rules or a promise of financial value.</p></div>
<div className="info-box"><strong>Collectible snapshots—not ownership of Wikipedia.</strong><p>Cards do not grant rights to Wikipedia text or images. Check each card’s attribution and licenses. This is an experimental testnet; cards have no promised monetary value.</p></div>
<button className="button dark full" onClick={() => { close(); goMine(); }}>Explore RandomX mining <ArrowRight size={16}/></button>
</>
: dialog === 'wallet' ? <><span className="modal-icon"><WalletIcon size={24} /></span><div className="section-eyebrow">YOUR LOCAL TESTNET IDENTITY</div><h2>A wallet for your wonders.</h2><p className="muted">No server login. This recoverable wallet controls native NFTs through local signatures. It is separate from the original demo wallet.</p><label className="field-label">YOUR RECEIVE ADDRESS</label><div className="address-box">{wallet?.address ?? 'Wallet unavailable. Enable local browser storage and retry.'}</div><button className="button dark full" onClick={copyAddress} disabled={!wallet}><Copy size={16} /> Copy wallet address</button><div className="wallet-recovery"><WalletPanel wallet={wallet} onRestore={updateWallet} onNotice={setToast} /></div><p className="wallet-count"><Layers3 size={17} /> {owned.length} confirmed native NFTs in your collection</p></>