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>
59 lines
2.2 KiB
TypeScript
59 lines
2.2 KiB
TypeScript
/**
|
|
* Reclaim B2 + C2 escrows that were left Open after their post-escrow
|
|
* rejections in run-agent-b's first pass. 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 { 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 });
|
|
|
|
const refs = [
|
|
{ txHash: "50c59e7621a05bde5df06e4ded1513f821f56c26e2af0a3aacc05a6448ae690b", index: 0 },
|
|
{ txHash: "6449cb53f1a15a48c9c1c01ca885a3dbd238930d86d91501215be87d9739384c", index: 0 },
|
|
];
|
|
|
|
async function main(): Promise<void> {
|
|
for (const escrowRef of refs) {
|
|
try {
|
|
const r = await buildReclaimTx({ chain, buyerKey: wk, escrowRef });
|
|
// eslint-disable-next-line no-console
|
|
console.log(`reclaim ${escrowRef.txHash}#${escrowRef.index} -> tx ${r.expectedTxHash}`);
|
|
await chain.awaitTx(r.expectedTxHash, 90000);
|
|
// eslint-disable-next-line no-console
|
|
console.log(` confirmed`);
|
|
} catch (e) {
|
|
// eslint-disable-next-line no-console
|
|
console.error(`reclaim ${escrowRef.txHash}#${escrowRef.index} 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);
|
|
// eslint-disable-next-line no-console
|
|
console.log(`wallet bal: ${bal} lovelace (~${Number(bal) / 1e6} AP3X)`);
|
|
}
|
|
|
|
main().catch((e) => {
|
|
// eslint-disable-next-line no-console
|
|
console.error(e);
|
|
process.exit(1);
|
|
});
|