Zum Inhalt

Blockchain-IO

Übersicht

Die BO-Engine interagiert mit der Blockchain über zwei Schichten:

┌──────────────────────────────────────────────┐
│  CLI / Workers                               │
│  (settle.ts, recoverBuyIntents.ts, etc.)     │
├──────────────────────────────────────────────┤
│  ChainReader (Read-Only)                     │
│  - getPotAcc(), getRolloverAcc(), etc.       │
├──────────────────────────────────────────────┤
│  ethers.js 6.x                               │
│  - JsonRpcProvider                           │
│  - Wallet (Operator)                         │
│  - Contract (ABIs)                           │
├──────────────────────────────────────────────┤
│  Arbitrum One RPC                            │
│  (Primary + Fallback)                        │
└──────────────────────────────────────────────┘

ChainReader

Datei: io/ChainReader.ts (66 Zeilen) Typ: Read-Only-Blockchain-Zugriff

Methoden

class ChainReader {
  // Regular Pot für alle 5 Pools
  async getPotAcc(): Promise<bigint[]>

  // Rollover-Akkumulatoren für alle 5 Pools
  async getRolloverAcc(): Promise<bigint[]>

  // Jackpot-Reserve für alle 5 Pools
  async getJackpotReserveAcc(): Promise<bigint[]>

  // Operator-Fee für einen bestimmten Tag
  async getFeeAcc(dayId: number): Promise<bigint>

  // No-Hit-Streak (Tage ohne Jackpot) pro Pool
  async getJackpotNoHitStreak(): Promise<number[]>
}

Verwendete Contracts

Contract Methoden Verwendung
GameTreasury potAcc(), rolloverAcc(), jackpotReserveAcc(), feeAcc() Pot-State für Settlement
SettlementV4/V5 jackpotStates(), daySettled(), lastSettledDay() Jackpot-State, Settlement-Status

Initialisierung

// ChainReader.ts
const provider = new JsonRpcProvider(RPC_URL);
const treasury = new Contract(GAME_TREASURY, GameTreasuryABI, provider);
const settlement = new Contract(SETTLEMENTV4, SettlementV4ABI, provider);

Contract-Interaktionen

Write-Operationen (mit Operator-Wallet)

Operation Contract Methode Worker
Settlement Commit SettlementV4/V5 commitMerkleSettlement() commit_from_db.ts
VRF-Seed-Request VRFReceiverV3 requestVrfSeed() refreshSeeds.ts
Drand-Seed-Setzen GameManagerV3 setDrandSeed() refreshSeeds.ts
Auto-Bonus-Vergabe BonusManager grantAutoBonus() processBonusGrant.ts

Read-Operationen (ohne Wallet)

Operation Contract Methode Worker
Pot-Sizes GameTreasury potAcc(), rolloverAcc() updatePotSizes.ts
Jackpot-State SettlementV4/V5 jackpotStates() ChainReader, updatePotSizes
Day-Settled SettlementV4/V5 daySettled() settle.ts
VRF-Status VRFReceiverV3 vrfSeed(), fulfilledTimestamp() refreshSeeds.ts
Ticket-Counter GameManagerV3 vrfTicketCounter() refreshSeeds.ts
Charity-Balance USDT Token balanceOf(CharityVault) updatePotSizes.ts
Relayer-Balance - getBalance() Watchdog

Event-Listening

Event Contract Verwendung
PrizeVaultPayout PrizeVault backfill_claim_events.ts
AffiliateVaultPayout AffiliateVault backfill_claim_events.ts
TicketCreated GameManager finalizeBuyIntent_v2.ts

Contract-ABIs

Verzeichnis: abi/ und types/solidity.ts

solidity.ts

// types/solidity.ts (100 Zeilen)
// Enthält inline ABI-Definitionen für:

const GameTreasuryABI = [
  "function potAcc(uint256 poolId) view returns (uint256)",
  "function rolloverAcc(uint256 poolId) view returns (uint256)",
  "function jackpotReserveAcc(uint256 poolId) view returns (uint256)",
  "function feeAcc(uint256 dayId) view returns (uint256)"
];

const SettlementV4ABI = [
  "function commitMerkleSettlement(...)",
  "function jackpotStates(uint256 poolId) view returns (tuple(...))",
  "function daySettled(uint256 dayId) view returns (bool)",
  "function lastSettledDay() view returns (uint256)"
];

const GameManagerABI = [
  "function vrfSeed() view returns (bytes32)",
  "function drandSeed() view returns (bytes32)",
  "function vrfTicketCounter() view returns (uint256)",
  "function setDrandSeed(bytes32 seed)"
];

const VRFReceiverABI = [
  "function requestVrfSeed()",
  "function lastVrfSeed() view returns (bytes32)",
  "function fulfilledTimestamp() view returns (uint256)"
];

SettlementV4.json

Vollständige ABI (~15 KB) für das Settlement-Contract.


Artefakt-Writer

Datei: io/artifactWriter.ts (118 Zeilen)

Funktionen

class ArtifactWriter {
  // JSON schreiben mit stabiler Key-Sortierung
  async writeJson(filename: string, data: object): Promise<string>

  // Text-Datei schreiben
  async writeText(filename: string, content: string): Promise<string>

  // Checksums.json generieren (SHA256 aller Dateien)
  async finalize(): Promise<void>
}

Features

  • Deterministische Serialisierung: Keys alphabetisch sortiert
  • BigInt-Konvertierung: BigInt → String (für JSON-Kompatibilität)
  • SHA256-Checksums: Jede Datei erhält einen Hash in checksums.json
  • Verzeichnisstruktur: artifacts/dayId=X/

Artefakt-Dateien pro Tag

Datei Inhalt Quelle
inputs.json Gewinner nach Pool/Klasse export_inputsDB.ts
affiliates.json Affiliate-Daten export_affiliatesDB.ts
settlement_result.json Berechnungsergebnis + Audit run.ts
winners_merkle.json Merkle-Root + Leaves + Proofs run.ts
affiliate_merkle.json Affiliate-Merkle-Daten run.ts
commit_bundle.json On-Chain-Commit-Parameter run.ts
checksums.json SHA256 aller Dateien finalize()

RPC-Konfiguration

Primary + Fallback

// Environment-Variablen
RPC_URL          // Primary Arbitrum RPC
FALLBACK_RPC_URL // Backup (optional, default: RPC_URL)

Dual-RPC-Nutzung

recoverBuyIntents.ts:
├── Primary RPC: Erste Receipt-Abfrage
└── Fallback RPC: Wenn Primary kein Ergebnis liefert

Watchdog:
└── Primary RPC: Health-Check (S2)

Settlement:
├── Finalized Block: waitUntilDayIsReady()
└── ChainReader: State-Abfragen

Error-Handling

// Typisches Pattern für RPC-Aufrufe
try {
  const result = await provider.getTransactionReceipt(txHash);
  return result;
} catch (e) {
  console.error("RPC error:", e.message);
  // Fallback oder Retry je nach Kontext
}

USDT-Beträge

Alle Beträge werden als Integer mit 6 Dezimalstellen gespeichert (USDT-Standard):

1 USDT = 1_000_000  (10^6)
100 USDT = 100_000_000

Beispiel: stat_value "2807880252" = 2.807,88 USDT