Download src/bridge/settlement.ts from Snapkitty/sealforge: direct link, hf CLI and curl.
- Browser
- Download file 4.89 kB
-
https://huggingface.co/Snapkitty/sealforge/resolve/main/src/bridge/settlement.ts
- Command line
-
hf download hf://Snapkitty/sealforge/src/bridge/settlement.ts
-
curl -L -o settlement.ts https://huggingface.co/Snapkitty/sealforge/resolve/main/src/bridge/settlement.ts
4.89 kB
| /** | |
| * Settlement Engine β SEALFORGE β FORGE token | |
| * | |
| * Reads ALL WORM entries, filters to type === 'event', derives a bytes32 | |
| * wormHash from each chainHash, checks the contract for prior consumption, | |
| * and calls wormMint for any un-minted entries. | |
| * | |
| * Settlement state is persisted to ./data/settlement-state.json as an | |
| * append-only record. Processed entries are NEVER modified or deleted. | |
| * | |
| * NEXUS β Orchestration Agent (connecting SEALFORGE Node 1 β FORGE Node 2) | |
| */ | |
| import * as fs from 'fs' | |
| import * as path from 'path' | |
| import { ethers } from 'ethers' | |
| import { WormLog, WormEntry } from '../storage/worm-log' | |
| import { ForgeContract } from './forge-contract' | |
| import { toBytes32 } from './bytes32' | |
| // 0.01 FRG per settled WORM event (testnet rate) | |
| const BASE_EMISSION = ethers.parseEther('0.01') | |
| const BASE_EMISSION_STR = '0.01' | |
| /** A record of a successful (or attempted) settlement. */ | |
| export interface SettlementRecord { | |
| wormEntryId: string | |
| wormHash: string | |
| txHash: string | |
| recipient: string | |
| amountEther: string | |
| settledAt: string | |
| } | |
| /** Loaded at startup; keyed by wormEntryId for O(1) de-dupe. */ | |
| export interface SettlementState { | |
| processed: Record<string, SettlementRecord> | |
| } | |
| function getStateFilePath(): string { | |
| const dataDir = process.env.DATA_DIR ?? './data' | |
| if (!fs.existsSync(dataDir)) fs.mkdirSync(dataDir, { recursive: true }) | |
| return path.join(dataDir, 'settlement-state.json') | |
| } | |
| function loadState(): SettlementState { | |
| const fp = getStateFilePath() | |
| if (!fs.existsSync(fp)) return { processed: {} } | |
| try { | |
| const raw = fs.readFileSync(fp, 'utf8') | |
| return JSON.parse(raw) as SettlementState | |
| } catch { | |
| console.error('[NEXUS:SETTLEMENT] Could not parse settlement-state.json β starting fresh') | |
| return { processed: {} } | |
| } | |
| } | |
| function saveState(state: SettlementState): void { | |
| const fp = getStateFilePath() | |
| fs.writeFileSync(fp, JSON.stringify(state, null, 2), 'utf8') | |
| } | |
| export interface SettlementRunResult { | |
| checked: number | |
| minted: number | |
| skipped: number | |
| errors: number | |
| txHashes: string[] | |
| } | |
| /** | |
| * Run one pass of the settlement engine. | |
| * Returns a summary of the run. | |
| */ | |
| export async function runSettlement( | |
| worm: WormLog, | |
| forge: ForgeContract, | |
| ): Promise<SettlementRunResult> { | |
| const state = loadState() | |
| const recipient = process.env.MINT_RECIPIENT | |
| if (!recipient) throw new Error('[NEXUS:SETTLEMENT] MINT_RECIPIENT env var is required') | |
| // Pull all entries β use a large limit; production should paginate if needed | |
| const { entries, chainValid } = worm.getAll(100_000, 0) | |
| if (!chainValid) throw new Error('[NEXUS:SETTLEMENT] WORM chain integrity failure β aborting') | |
| // Only settle 'event' type entries β skip lifecycle noise | |
| const events: WormEntry[] = entries.filter(e => e.type === 'event') | |
| const result: SettlementRunResult = { | |
| checked: events.length, | |
| minted: 0, | |
| skipped: 0, | |
| errors: 0, | |
| txHashes: [], | |
| } | |
| for (const entry of events) { | |
| // Already settled locally β skip without hitting the RPC | |
| if (state.processed[entry.id]) { | |
| result.skipped++ | |
| continue | |
| } | |
| const wormHash = toBytes32(entry.chainHash) | |
| try { | |
| // Check on-chain β skip if already consumed | |
| const consumed = await forge.isConsumed(wormHash) | |
| if (consumed) { | |
| console.log(`[NEXUS:SETTLEMENT] SKIP (on-chain consumed) β entry ${entry.id}`) | |
| // Record locally so we don't re-check next cycle | |
| const record: SettlementRecord = { | |
| wormEntryId: entry.id, | |
| wormHash, | |
| txHash: 'ALREADY_CONSUMED', | |
| recipient, | |
| amountEther: BASE_EMISSION_STR, | |
| settledAt: new Date().toISOString(), | |
| } | |
| state.processed[entry.id] = record | |
| result.skipped++ | |
| continue | |
| } | |
| console.log(`[NEXUS:SETTLEMENT] MINT β entry ${entry.id} β ${recipient}`) | |
| const txHash = await forge.mint(recipient, BASE_EMISSION_STR, wormHash) | |
| console.log(`[NEXUS:SETTLEMENT] TX ${txHash} confirmed`) | |
| const record: SettlementRecord = { | |
| wormEntryId: entry.id, | |
| wormHash, | |
| txHash, | |
| recipient, | |
| amountEther: BASE_EMISSION_STR, | |
| settledAt: new Date().toISOString(), | |
| } | |
| // Append-only β write after each successful mint so a crash mid-run | |
| // doesn't lose prior confirmations | |
| state.processed[entry.id] = record | |
| saveState(state) | |
| result.minted++ | |
| result.txHashes.push(txHash) | |
| } catch (err: unknown) { | |
| const msg = err instanceof Error ? err.message : String(err) | |
| console.error(`[NEXUS:SETTLEMENT] ERROR on entry ${entry.id}: ${msg}`) | |
| result.errors++ | |
| // Continue to next entry β never let one failure stop the run | |
| } | |
| } | |
| // Persist final state (covers the skipped-but-recorded entries) | |
| saveState(state) | |
| return result | |
| } | |