import { PrismaClient } from "./apps/web/prisma/generated/client/index.js"; import { TaskStatus, MCPToolName, SettlementPhase, TaskDifficulty } from "./packages/contracts/src/enums/index.js"; import { v4 as uuidv4 } from "uuid"; const prisma = new PrismaClient(); async function main() { console.log("=== Idempotency and Payment Flow Test ==="); // 1. Create a mock task const taskId = uuidv4(); await prisma.task.create({ data: { id: taskId, title: "Test Task", difficulty: TaskDifficulty.COMPONENT, status: TaskStatus.OPEN, requirements: "Test requirements", base_reward_cents: 500, } }); console.log(`[+] Created Task ${taskId}`); // 2. Simulate Claim Task (Auth Hold) console.log(`\n[+] Simulating MCP: claim_task`); // First attempt (Should succeed and create Auth Hold) const agentId = "agent-test-1"; const idempotencyKeyClaim = `${taskId}_${MCPToolName.CLAIM_TASK}`; const claim1 = await prisma.$transaction(async (tx) => { // authHold logic const existing = await tx.ledgerEntry.findUnique({ where: { idempotency_key: idempotencyKeyClaim }}); if (existing) { console.log("Idempotent hit for claim_task!"); return existing; } await tx.task.update({ where: { id: taskId }, data: { status: TaskStatus.EXECUTING, agent_id: agentId } }); return await tx.ledgerEntry.create({ data: { task_id: taskId, phase: SettlementPhase.AUTH_HOLD, amount_cents: 500, currency: "USD", stripe_object_id: "pi_mock_" + uuidv4(), idempotency_key: idempotencyKeyClaim } }); }); console.log(`[1] First claim_task attempt created ledger entry: ${claim1.id}`); // Second attempt (Should hit idempotency key and NOT duplicate) const claim2 = await prisma.$transaction(async (tx) => { const existing = await tx.ledgerEntry.findUnique({ where: { idempotency_key: idempotencyKeyClaim }}); if (existing) { console.log("Idempotent hit for claim_task!"); return existing; } // Should not reach here throw new Error("Idempotency failed!"); }); console.log(`[2] Second claim_task attempt returned same entry: ${claim2.id}`); // 3. Simulate Submit Solution (Capture) console.log(`\n[+] Simulating MCP: submit_solution`); const idempotencyKeySubmit = `${taskId}_${MCPToolName.SUBMIT_SOLUTION}`; const submit1 = await prisma.$transaction(async (tx) => { const existing = await tx.ledgerEntry.findUnique({ where: { idempotency_key: idempotencyKeySubmit }}); if (existing) { console.log("Idempotent hit for submit_solution!"); return existing; } await tx.task.update({ where: { id: taskId }, data: { status: TaskStatus.COMPLETED } }); return await tx.ledgerEntry.create({ data: { task_id: taskId, phase: SettlementPhase.CAPTURE, amount_cents: 500, currency: "USD", stripe_object_id: claim1.stripe_object_id, idempotency_key: idempotencyKeySubmit } }); }); console.log(`[1] First submit_solution attempt created ledger entry: ${submit1.id}`); const submit2 = await prisma.$transaction(async (tx) => { const existing = await tx.ledgerEntry.findUnique({ where: { idempotency_key: idempotencyKeySubmit }}); if (existing) { console.log("Idempotent hit for submit_solution!"); return existing; } throw new Error("Idempotency failed!"); }); console.log(`[2] Second submit_solution attempt returned same entry: ${submit2.id}`); // Verify DB state const finalTask = await prisma.task.findUnique({ where: { id: taskId }, include: { ledger_entries: true } }); console.log(`\n=== Final Verification ===`); console.log(`Task Status: ${finalTask?.status}`); console.log(`Ledger Entries: ${finalTask?.ledger_entries.length}`); finalTask?.ledger_entries.forEach(entry => { console.log(` - Phase: ${entry.phase}, Amount: ${entry.amount_cents}, Key: ${entry.idempotency_key}`); }); if (finalTask?.status === TaskStatus.COMPLETED && finalTask.ledger_entries.length === 2) { console.log("\n✅ End-to-End Simulation Passed! Idempotency and State transitions are correct."); } else { console.log("\n❌ Simulation Failed."); } } main() .catch(console.error) .finally(async () => { await prisma.$disconnect(); });