import assert from 'node:assert/strict'; import { createContractReceipt, createServiceCard, verifyContractReceipt, verifyServiceCard, type Contract, type LedgerEntry, type Offer, type TenantReputation, } from 'satonomous'; type WorkOrder = { schema: 'satonomous.work-order/v0'; work_order_id: string; status: 'accepted'; accepted_at: string; service_card_ref: string; buyer_agent_id: string; seller_agent_id: string; title: string; scope: string; deliverables: Array<{ kind: string; description: string; }>; budget_sats: number; currency: 'sats'; escrow_policy: { rail: 'lightning'; release: 'buyer_confirmed_or_timeout'; dispute_window_minutes: number; }; proof_required: { kind: 'uri_with_hash'; description: string; }; deadline_at: string; receipt_policy: { expected_schema: 'satonomous.contract-receipt/v0'; must_include_work_order_id: true; must_link_work_order: true; }; }; const offer: Offer = { id: 'offer_research_summary_001', seller_tenant_id: 'seller_agent_456', service_type: 'research_summary', title: 'Summarize one technical article', description: 'Return a concise summary with three implementation takeaways.', terms: { sla_minutes: 1440, dispute_window_minutes: 120, proof_requirements: ['Delivery URL', 'payload hash'], }, price_sats: 5000, max_concurrent_contracts: 2, active: 1, created_at: '2026-06-12T12:00:00Z', expires_at: null, }; const reputation: TenantReputation = { tenant_id: 'seller_agent_456', seller: { tenant_id: 'seller_agent_456', role: 'seller', score: 82, level: 'gold', summary: { settled_contracts: 9, completed_contracts: 9, released_contracts: 9, disputed_contracts: 0, seller_lost_disputes: 0, expired_delivery_contracts: 0, dispute_rate: 0, seller_win_rate: null, median_delivery_minutes: 42, total_volume_sats: 50000, unique_counterparties: 7, }, last_updated_at: '2026-06-12T12:00:00Z', }, buyer: { tenant_id: 'seller_agent_456', role: 'buyer', score: 50, level: 'bronze', summary: { settled_contracts: 0, funded_contracts: 0, released_contracts: 0, disputes_opened: 0, buyer_lost_disputes: 0, dispute_rate: 0, total_volume_sats: 0, unique_counterparties: 0, }, last_updated_at: '2026-06-12T12:00:00Z', }, }; const serviceCard = createServiceCard(offer, reputation, { issuedAt: '2026-06-12T12:30:00.000Z', links: { quickstart: 'https://github.com/jordiagi/satonomous/blob/main/examples/first-contract.ts', work_order_docs: 'https://github.com/jordiagi/satonomous/blob/main/WORK_ORDERS.md', }, }); const serviceVerification = verifyServiceCard(serviceCard); assert.equal( serviceVerification.valid, true, `ServiceCard verifier failed: ${JSON.stringify(serviceVerification, null, 2)}` ); const workOrder: WorkOrder = { schema: 'satonomous.work-order/v0', work_order_id: 'wo_research_summary_001', status: 'accepted', accepted_at: '2026-06-12T13:00:00Z', service_card_ref: serviceCard.card_id, buyer_agent_id: 'buyer_agent_123', seller_agent_id: offer.seller_tenant_id, title: offer.title, scope: offer.description ?? 'Summarize one technical article.', deliverables: [ { kind: 'markdown_summary', description: 'Summary plus implementation takeaways', }, ], budget_sats: offer.price_sats, currency: 'sats', escrow_policy: { rail: 'lightning', release: 'buyer_confirmed_or_timeout', dispute_window_minutes: 120, }, proof_required: { kind: 'uri_with_hash', description: 'Delivery URL plus payload hash', }, deadline_at: '2026-06-13T13:00:00Z', receipt_policy: { expected_schema: 'satonomous.contract-receipt/v0', must_include_work_order_id: true, must_link_work_order: true, }, }; const contract: Contract = { id: 'contract_work_order_demo_001', offer_id: offer.id, buyer_tenant_id: workOrder.buyer_agent_id, seller_tenant_id: workOrder.seller_agent_id, terms_snapshot: { work_order_id: workOrder.work_order_id, service_card_ref: workOrder.service_card_ref, title: workOrder.title, description: workOrder.scope, service_type: offer.service_type, deliverables: workOrder.deliverables, budget_sats: workOrder.budget_sats, deadline_at: workOrder.deadline_at, dispute_window_minutes: workOrder.escrow_policy.dispute_window_minutes, receipt_policy: workOrder.receipt_policy, }, price_sats: workOrder.budget_sats, fee_sats: 50, status: 'released', delivery_proof: { url: 'https://example.com/delivery/work-order-demo-summary', payload_hash: 'sha256:fa27f93007e5a6fddf9f81d820d0057acba9479cf7c5cb2af1129389e558ba61', }, dispute_reason: null, accepted_at: workOrder.accepted_at, funded_at: '2026-06-12T13:05:00Z', completed_at: '2026-06-12T13:45:00Z', released_at: '2026-06-12T14:00:00Z', disputed_at: null, created_at: workOrder.accepted_at, }; assert.equal(contract.terms_snapshot.work_order_id, workOrder.work_order_id); const ledgerEntries: LedgerEntry[] = [ { id: 1, type: 'debit', amount_sats: contract.price_sats + contract.fee_sats, source: 'contract_funding', reference_id: contract.id, balance_after: 950, created_at: contract.funded_at ?? contract.created_at, }, { id: 2, type: 'credit', amount_sats: contract.price_sats, source: 'contract_release', reference_id: contract.id, balance_after: 5950, created_at: contract.released_at ?? contract.created_at, }, ]; const receipt = createContractReceipt(contract, ledgerEntries, { links: { quickstart: 'https://github.com/jordiagi/satonomous/blob/main/examples/first-contract.ts', service_card: `satonomous:service-card:${serviceCard.card_id}`, work_order: `satonomous:work-order:${workOrder.work_order_id}`, }, }); const receiptVerification = verifyContractReceipt(receipt); assert.equal( receiptVerification.valid, true, `ContractReceipt verifier failed: ${JSON.stringify(receiptVerification, null, 2)}` ); assert.equal(receipt.terms.work_order_id, workOrder.work_order_id); assert.equal(receipt.links?.work_order, `satonomous:work-order:${workOrder.work_order_id}`); assert.equal(receipt.settlement.ledger_reference_ids.includes(contract.id), true); console.log( JSON.stringify( { service_card_id: serviceCard.card_id, work_order_id: workOrder.work_order_id, contract_id: contract.id, receipt_id: receipt.receipt_id, receipt_work_order_id: receipt.terms.work_order_id, receipt_work_order_link: receipt.links?.work_order, service_card_valid: serviceVerification.valid, receipt_valid: receiptVerification.valid, receipt_warnings: receiptVerification.warnings, }, null, 2 ) );