Rich card data

This commit is contained in:
2026-10-19 16:47:27 -04:00
parent f26e38b096
commit 6155e8b3ed
31 changed files with 633 additions and 25 deletions
+1 -1
View File
@@ -139,4 +139,4 @@ export async function validateBlock(raw: unknown, ancestors: TestnetBlock[], par
if (BigInt(`0x${b.powHash}`) > BigInt(`0x${b.target}`)) throw new Error('Insufficient work');
if (await pow.hash(b.key, blob) !== b.powHash) throw new Error('Invalid RandomX proof');
return { block: b, state: next };
}
}
+13 -1
View File
@@ -10,6 +10,8 @@ import { CHAIN_ID, blockSchema, transferSchema } from './consensus.ts';
import { RandomX } from './randomx.ts';
import { Ledger } from './ledger.ts';
import { PeerNetwork } from './peers.ts';
import { wikipediaEnrichment } from '../enrichment.ts';
import { STARTER_ARTICLES } from '../../shared/catalog.ts';
const root = fileURLToPath(new URL('../../', import.meta.url));
const dataDir = process.env.WIKIDECK_DATA_DIR ?? resolve(root,'data');
@@ -50,6 +52,16 @@ app.use(['/api','/p2p'],(req,res,next)=>{
app.get('/api/state',(_req,res)=>res.json(ledger.snapshot()));
app.get('/api/chain',(_req,res)=>res.json(ledger.snapshot()));
app.get('/api/peers',(_req,res)=>res.json({peers:peers.status()}));
// Optional live data is intentionally not used by genesis, block validation or NFT ownership.
app.get('/api/wikipedia/:pageId', rateLimit({windowMs:60000,limit:60,standardHeaders:'draft-8',legacyHeaders:false}), async(req,res)=>{
if(typeof req.params.pageId!=='string'||!/^[1-9]\d{0,9}$/.test(req.params.pageId)){res.status(400).json({error:'Invalid Wikipedia page ID'});return;}
const pageId=Number(req.params.pageId);
if(!STARTER_ARTICLES.some(a=>a.pageId===pageId)){
res.status(404).json({error:'Page is not in the current consensus catalog'});return;
}
try {res.json(await wikipediaEnrichment.get(pageId));}
catch {res.status(503).json({error:'Wikipedia enrichment is temporarily unavailable. NFT data is unaffected.'});}
});
app.get('/p2p/status',(_req,res)=>res.json({network:NETWORK,chainId:CHAIN_ID,size:ledger.size,tip:ledger.snapshot().tip}));
app.get('/p2p/blocks',(req,res)=>{
const offset=Number(req.query.offset??0);
@@ -103,4 +115,4 @@ for(const signal of ['SIGTERM','SIGINT']as const)process.once(signal,()=>{
const timeout=setTimeout(()=>process.exit(1),25000);timeout.unref();
server.close(async()=>{engine.close();await lock.close();await unlink(lockPath).catch(()=>{});clearTimeout(timeout);process.exit(0);});
});
server.on('error',async()=>{peers.close();engine.close();await lock.close();await unlink(lockPath).catch(()=>{});process.exit(1);});
server.on('error',async()=>{peers.close();engine.close();await lock.close();await unlink(lockPath).catch(()=>{});process.exit(1);});
+1 -1
View File
@@ -210,4 +210,4 @@ export class Ledger {
}
} finally { await unlink(temp).catch(() => undefined); }
}
}
}
+1 -1
View File
@@ -90,4 +90,4 @@ try {
}
}
} catch(e) { if(!stopping) { console.error((e as Error).message); process.exitCode=1; } }
finally { engine.close(); process.off('SIGINT',stop);process.off('SIGTERM',stop); }
finally { engine.close(); process.off('SIGINT',stop);process.off('SIGTERM',stop); }
+1 -1
View File
@@ -192,4 +192,4 @@ export class PeerNetwork {
});
} finally { clearTimeout(timeout); this.active.delete(controller); }
}
}
}
+1 -1
View File
@@ -205,4 +205,4 @@ export class RandomX implements PowEngine {
this.shutdownTimer.unref();
}
}
}
}