import type { Article } from './protocol.ts'; export const NETWORK = 'wikideck-randomx-testnet-2' as const; export const CONSENSUS = { version: 2, targetSeconds: 30, retargetInterval: 10, medianWindow: 11, commitments: 'sha256-domain-separated-counted-merkle-v1', randomx: '1.2.1', powEndian: 'big', maxFutureSeconds: 120, epochBlocks: 2048, epochDelay: 64, maxTransactions: 64, coinbaseMaturity: 2, maxBlockBytes: 64 * 1024, } as const; export type NftTransfer = { network: typeof NETWORK; chainId: string; cardHash: string; from: string; to: string; sequence: number; publicKey: string; signature: string; }; export type BlockHeader = { version: 2; network: typeof NETWORK; chainId: string; height: number; previousHash: string; createdAt: number; article: Article; owner: string; publicKey: string; nonce: number; target: string; key: string; transactionsRoot: string; stateRoot: string; }; export type TestnetBlock = BlockHeader & { hash: string; tokenId: string; powHash: string; signature: string; transactions: NftTransfer[]; }; export type MiningTemplate = { header: BlockHeader; transactions: NftTransfer[]; blob: string; nonceOffset: number; }; export type NftState = Record; export type TestnetSnapshot = { network: typeof NETWORK; chainId: string; genesis: string; tip: string; cumulativeWork: string; blocks: TestnetBlock[]; transfers: NftTransfer[]; pendingTransfers: NftTransfer[]; nextArticle: Article; peers: number; algorithm: 'RandomX'; maturity: number; }; export function nftTransferMessage(t: Omit): string { return JSON.stringify([NETWORK, 'nft-transfer', t.chainId, t.cardHash, t.from, t.to, t.sequence]); } export function articleTuple(a: Article): unknown[] { return [a.pageId, a.revisionId, a.title, a.extract, a.image ?? '', a.url, a.source, a.category]; } export function headerMessage(h: BlockHeader): string { return JSON.stringify([NETWORK, h.version, h.chainId, h.height, h.previousHash, h.createdAt, articleTuple(h.article), h.owner, h.publicKey, h.target, h.key, h.transactionsRoot, h.stateRoot]); } export function blockClaimMessage(hash: string): string { return JSON.stringify([NETWORK, 'block-claim', hash]); } export function testnetOwnerOf(state: Pick, hash: string): string | undefined { let owner = state.blocks.find(b => b.tokenId === hash)?.owner; for (const t of state.transfers) if (t.cardHash === hash) owner = t.to; return owner; }