#!/usr/bin/env node import { parseArgs } from "util"; import { createPublicClient, http, parseAbiParameters, decodeAbiParameters } from "viem"; import { contracts } from "alkahest-ts"; import { getChainFromNetwork, loadDeploymentWithDefaults } from "../utils.js"; // Helper function to display usage function displayHelp() { console.log(` Natural Language Agreement - Check Escrow Status Usage: bun status-escrow.ts [options] Options: --escrow-uid Escrow UID to check (required) --deployment Load addresses from deployment file (optional) --help, -h Display this help message Environment Variables: RPC_URL RPC URL for blockchain connection Examples: # Check escrow status bun status-escrow.ts --escrow-uid 0x... # Use specific deployment file bun status-escrow.ts --escrow-uid 0x... --deployment ./deployments/sepolia.json `); } // Parse command line arguments function parseCliArgs() { const { values } = parseArgs({ args: process.argv.slice(2), options: { "escrow-uid": { type: "string" }, "deployment": { type: "string" }, "help": { type: "boolean", short: "h" }, }, strict: true, }); return values; } // Main function async function main() { try { const args = parseCliArgs(); // Display help if requested if (args.help) { displayHelp(); process.exit(0); } const escrowUid = args["escrow-uid"]; const deploymentFile = args["deployment"]; // Validate required parameters if (!escrowUid) { console.error("āŒ Error: --escrow-uid is required"); console.error("Run with --help for usage information."); process.exit(1); } console.log("šŸ” Checking Escrow Status\n"); // Load deployment file (auto-detects current network if not specified) const deployment = loadDeploymentWithDefaults(deploymentFile); const addresses = deployment.addresses; console.log(`Configuration:`); console.log(` šŸ“¦ Escrow UID: ${escrowUid}`); console.log(` 🌐 Network: ${deployment.network}`); console.log(` šŸ“” RPC URL: ${deployment.rpcUrl}\n`); if (!addresses.eas) { console.error("āŒ Error: EAS address not found in deployment file."); console.error(" Make sure you have a valid deployment file."); process.exit(1); } // Create public client const chain = getChainFromNetwork(deployment.network); const publicClient = createPublicClient({ chain, transport: http(deployment.rpcUrl), }); // Get escrow attestation console.log("šŸ“‹ Fetching escrow details...\n"); const escrow = await publicClient.readContract({ address: addresses.eas as `0x${string}`, abi: contracts.IEAS.abi.abi, functionName: "getAttestation", args: [escrowUid as `0x${string}`], }) as any; console.log("šŸ“¦ Escrow Information:"); console.log(` UID: ${escrow.uid}`); console.log(` Schema: ${escrow.schema}`); console.log(` Attester: ${escrow.attester}`); console.log(` Recipient: ${escrow.recipient}`); console.log(` Revoked: ${escrow.revocationTime > 0n ? "Yes āŒ" : "No āœ…"}`); // Try to decode the data try { const llmAbi = parseAbiParameters("(string demand, string arbitrationModel, address arbitrator)"); const decoded = decodeAbiParameters(llmAbi, escrow.data); console.log(`\nšŸ“ Escrow Details:`); console.log(` Demand: "${decoded[0].demand}"`); console.log(` Model: ${decoded[0].arbitrationModel}`); console.log(` Arbitrator: ${decoded[0].arbitrator}`); } catch (e) { console.log(`\nšŸ“ Raw Data: ${escrow.data}`); } // Check for fulfillments console.log(`\nšŸ”Ž Checking for fulfillments...`); // Get all Attested events const filter = await publicClient.createContractEventFilter({ address: addresses.eas as `0x${string}`, abi: contracts.IEAS.abi.abi, eventName: "Attested", fromBlock: 0n, }); const events = await publicClient.getFilterLogs({ filter }); // Debug: log total events found console.log(` Total events found: ${events.length}`); // Debug: show all refUIDs console.log(` Debug - Looking for escrow UID: ${escrowUid.toLowerCase()}`); events.forEach((event: any, index: number) => { const refUID = event.args?.refUID; console.log(` Event ${index}: refUID = ${refUID ? refUID.toLowerCase() : 'null'}, uid = ${event.args?.uid}`); }); // Find fulfillments that reference this escrow const fulfillments = events.filter((event: any) => { const refUID = event.args?.refUID; // Compare as lowercase hex strings to avoid case sensitivity issues return refUID && refUID.toLowerCase() === escrowUid.toLowerCase(); }); console.log(` Fulfillments matching escrow: ${fulfillments.length}`); if (fulfillments.length === 0) { console.log(` No fulfillments found yet\n`); } else { console.log(` Found ${fulfillments.length} fulfillment(s):\n`); for (const fulfillment of fulfillments) { const fulfillmentUid = fulfillment.args?.uid; if (!fulfillmentUid) continue; const fulfillmentAttestation = await publicClient.readContract({ address: addresses.eas as `0x${string}`, abi: contracts.IEAS.abi.abi, functionName: "getAttestation", args: [fulfillmentUid], }) as any; console.log(` šŸ“Ø Fulfillment UID: ${fulfillmentUid}`); console.log(` Attester: ${fulfillmentAttestation.attester}`); console.log(` Revoked: ${fulfillmentAttestation.revocationTime > 0n ? "Yes āŒ" : "No āœ…"}`); // Try to decode fulfillment data try { const fulfillmentAbi = parseAbiParameters("(string item)"); const fulfillmentData = decodeAbiParameters(fulfillmentAbi, fulfillmentAttestation.data); console.log(` Fulfillment Text: "${fulfillmentData[0].item}"`); } catch (e) { // Skip if can't decode } // Check for arbitration decision const decisions = events.filter((e: any) => { const refUID = e.args?.refUID; return refUID && refUID.toLowerCase() === fulfillmentUid.toLowerCase(); }); if (decisions.length > 0) { console.log(` āš–ļø Arbitration: Decision recorded`); for (const decision of decisions) { const decisionUid = decision.args?.uid; if (!decisionUid) continue; const decisionAttestation = await publicClient.readContract({ address: addresses.eas as `0x${string}`, abi: contracts.IEAS.abi.abi, functionName: "getAttestation", args: [decisionUid], }) as any; try { const decisionAbi = parseAbiParameters("(bool item)"); const decisionData = decodeAbiParameters(decisionAbi, decisionAttestation.data); console.log(` Result: ${decisionData[0].item ? "āœ… APPROVED" : "āŒ REJECTED"}`); } catch (e) { console.log(` Result: Unknown`); } } } else { console.log(` āš–ļø Arbitration: Pending...`); } console.log(); } } console.log("✨ Status check complete!\n"); } catch (error) { console.error("āŒ Fatal error:", error); process.exit(1); } } // Run the script main();