Files
agents-marketplace/buyer/scripts/cleanup-agent-b.ts
david 8249fd3c67 buyer: marketplace-buyer-pair adversarial + happy-path runners (testnet)
run-agent-a.ts: drives Marketplace.submitPrompt + runAccept for 3 cycles
against the live supplier. Logs every tx hash, HTTP code, receipt
verification step. Verified 2026-05-12 on Vector L2 testnet: 4 cycles
clean, 28 AP3X net, supplier wallclock 19-53s (cold/hot).

run-agent-b.ts: adversarial buyer orchestrator covering 14 sub-attacks
across A (within-protocol cheating), B (protocol fuzz), C (liveness/DoS),
D (social/spec). Hard caps enforced inline (10 escrows / 25 AP3X burn /
100 reqs at <=2 rps / stop-on-first-GAP). Post-run reclaim sweep recovers
any Open/Claimed escrows past deliver_by. Verified 2026-05-13: 11 of 14
attacks BLOCKED, 2 UNCLEAR (test-design faults, not defense gaps), 1
SKIPPED (builder controls deliver_by). Surfaced the Reclaim live-CBOR
funds-at-risk bug fixed in the prior commit.

reclaim-orphans.ts + cleanup-agent-b.ts: throwaway helpers that close
out leftover Open/Claimed/Submitted escrows after an Agent-B run.

prompts/marketplace-buyer-pair.md: paired spec for Agent A + Agent B
(the source for these runs).

buyer/.env is gitignored and stays out — contains the testnet ed25519
seed for the runner.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 11:58:14 +02:00

66 lines
2.5 KiB
TypeScript

/**
* cleanup-agent-b.ts — close out Agent B's lingering escrows.
* - Accept D3 Submitted (supplier processed, just needs Accept)
* - Reclaim A1 + A4 Open (deliver_by passed, recover funds)
* Throwaway.
*/
import { readFileSync } from "fs";
import { createHash } from "crypto";
import * as ed from "@noble/ed25519";
import { LiveOgmiosProvider } from "@marketplace/shared/chain";
import { buildReclaimTx } from "@marketplace/shared/tx";
import { runAccept } from "../src/cli/acceptFlow.js";
import { deriveWalletKey } from "../src/index.js";
ed.etc.sha512Sync = (...m: Uint8Array[]): Uint8Array => {
const h = createHash("sha512");
for (const x of m) h.update(x);
return new Uint8Array(h.digest());
};
const env: Record<string, string> = {};
for (const line of readFileSync("/home/david/code/agents-marketplace/buyer/.env", "utf-8").split("\n")) {
if (!line.trim() || line.trim().startsWith("#")) continue;
const i = line.indexOf("=");
if (i === -1) continue;
env[line.slice(0, i).trim()] = line.slice(i + 1).trim();
}
const wk = deriveWalletKey(env.BUYER_PRIV_KEY_HEX, 1);
const chain = new LiveOgmiosProvider({ ogmiosUrl: env.OGMIOS_URL });
async function main(): Promise<void> {
// D3's Submitted ref needs Accept.
const d3Submitted = { txHash: "2d3db522d4e2f5221d75afcd31e4dbcc247866558a7841b5cf6be9bebfc93347", index: 0 };
try {
const r = await runAccept({
chain, walletKey: wk, escrowRef: d3Submitted,
log: (line) => console.log(`[D3-accept] ${line}`),
});
console.log(`D3 accept tx ${r.txHash}`);
} catch (e) {
console.error(`D3 accept FAILED:`, e instanceof Error ? e.message : String(e));
}
// A1 + A4 Open escrows need Reclaim.
const openRefs = [
{ id: "A1", txHash: "45879f707e7c8521233ee3bd5b024300211b8d8675f2400784f6ac1744848184", index: 0 },
{ id: "A4", txHash: "8f1ec769bd883ed617b4f05143b4997d20bd93d970371c0358a0e395cb676271", index: 0 },
];
for (const { id, txHash, index } of openRefs) {
try {
const r = await buildReclaimTx({ chain, buyerKey: wk, escrowRef: { txHash, index } });
await chain.awaitTx(r.expectedTxHash, 90_000);
console.log(`${id} reclaim tx ${r.expectedTxHash}`);
} catch (e) {
console.error(`${id} reclaim FAILED:`, e instanceof Error ? e.message : String(e));
}
}
const utxos = await chain.queryUtxosByAddress(wk.address);
const bal = utxos.reduce((a, u) => a + BigInt(u.lovelace), 0n);
console.log(`final wallet bal: ${bal} lovelace (~${Number(bal) / 1e6} AP3X)`);
}
main().catch((e) => { console.error(e); process.exit(1); });