-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathx402-sar-integration.js
More file actions
170 lines (148 loc) · 5.98 KB
/
x402-sar-integration.js
File metadata and controls
170 lines (148 loc) · 5.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/**
* InsumerAPI + x402 SAR Integration Example
*
* End-to-end flow: attestation → payment → SAR receipt → offline verification
*
* This example demonstrates how a pre-transaction wallet attestation (InsumerAPI)
* composes with a post-transaction delivery proof (SAR) in the x402 ecosystem.
* A consistent agent_id threads through all four steps.
*
* Steps 1 & 4 are fully runnable against InsumerAPI.
* Steps 2 & 3 are stubs showing the SAR interface — fill in with your SAR
* implementation (see github.com/coinbase/x402/issues/1195).
*
* Usage:
* npm install insumer-verify jose
* INSUMER_API_KEY=insr_live_... node x402-sar-integration.js
*
* Get a free API key:
* curl -s -X POST https://api.insumermodel.com/v1/keys/create \
* -H "Content-Type: application/json" \
* -d '{"email":"you@example.com","appName":"SAR Integration","tier":"free"}'
*/
const { verify } = require("insumer-verify");
const { createRemoteJWKSet, jwtVerify } = require("jose");
const API = "https://api.insumermodel.com";
const KEY = process.env.INSUMER_API_KEY;
if (!KEY) {
console.error("Set INSUMER_API_KEY environment variable");
process.exit(1);
}
// Consistent identity across all four steps
const AGENT_ID = `agent-${Date.now()}`;
// Example: verify counterparty holds USDC on Base before transacting
const WALLET = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"; // vitalik.eth (demo)
const CONDITIONS = [
{
type: "token_balance",
contractAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
chainId: 8453,
threshold: 1,
label: "USDC on Base",
},
];
async function main() {
console.log(`Agent: ${AGENT_ID}\n`);
// ─── Step 1: Pre-transaction attestation (InsumerAPI) ───
console.log("Step 1: Pre-transaction attestation");
console.log(" Verifying counterparty wallet meets conditions...\n");
const attestRes = await fetch(`${API}/v1/attest`, {
method: "POST",
headers: { "Content-Type": "application/json", "X-API-Key": KEY },
body: JSON.stringify({
wallet: WALLET,
conditions: CONDITIONS,
format: "jwt",
}),
});
const attestResult = await attestRes.json();
if (!attestResult.ok) {
console.error("Attestation failed:", attestResult.error);
process.exit(1);
}
const { attestation, sig, kid, jwt } = attestResult.data;
console.log(` Attestation ID: ${attestation.id}`);
console.log(` Pass: ${attestation.pass}`);
console.log(` Results:`);
attestation.results.forEach((r) => {
console.log(` [${r.met ? "MET" : "NOT MET"}] ${r.label} (chain ${r.chainId})`);
});
console.log(` Signature: ${sig.substring(0, 20)}...`);
console.log(` JWT: ${jwt.substring(0, 40)}...`);
console.log(` Agent: ${AGENT_ID}\n`);
// ─── Step 2: x402 payment (your implementation) ───
console.log("Step 2: x402 payment");
console.log(" [Stub] Execute x402 payment flow here.");
console.log(" The attestation from Step 1 tells the agent whether to proceed.");
console.log(` Thread agent_id: ${AGENT_ID} through the payment request.\n`);
// In production, this is where you'd call the x402 facilitator.
// The attestation result (pass/fail) informs the agent's decision
// to initiate payment. The agent_id links this payment to the
// pre-transaction attestation.
const paymentTxHash = "0x_simulated_payment_hash";
// ─── Step 3: SAR receipt (your implementation) ───
console.log("Step 3: SAR receipt");
console.log(" [Stub] SAR receipt issued after delivery verification.");
console.log(` Thread agent_id: ${AGENT_ID} into the SAR receipt.\n`);
// In production, the SAR verifier issues an Ed25519-signed receipt
// with verdict PASS | FAIL | INDETERMINATE. The receipt includes
// agent_id, linking it to the attestation and payment.
//
// Expected SAR receipt shape (from SAR v0.1 spec):
// {
// receipt_id: "...",
// agent_id: AGENT_ID,
// verdict: "PASS",
// confidence: 0.95,
// reason_code: "DELIVERY_CONFIRMED",
// timestamp: "...",
// signature: "..." // Ed25519
// }
const sarReceipt = {
receipt_id: "sar-simulated",
agent_id: AGENT_ID,
verdict: "PASS",
confidence: 0.95,
reason_code: "DELIVERY_CONFIRMED",
};
// ─── Step 4: Offline verification of both artifacts ───
console.log("Step 4: Offline verification\n");
// 4a. Verify InsumerAPI attestation (ECDSA P-256 via insumer-verify)
console.log(" 4a. Verifying InsumerAPI attestation...");
try {
const attestVerify = await verify(attestResult.data);
console.log(` Valid: ${attestVerify.valid}`);
if (!attestVerify.valid) {
console.log(` Reason: ${attestVerify.reason}`);
}
} catch (err) {
console.log(` Error: ${err.message}`);
}
// 4b. Verify JWT independently (standard ES256 via JWKS)
console.log(" 4b. Verifying JWT via JWKS...");
try {
const JWKS = createRemoteJWKSet(new URL(`${API}/v1/jwks`));
const { payload } = await jwtVerify(jwt, JWKS, {
issuer: "https://api.insumermodel.com",
algorithms: ["ES256"],
});
console.log(` JWT valid. Subject: ${payload.sub}, Pass: ${payload.pass}`);
} catch (err) {
console.log(` JWT verification error: ${err.message}`);
}
// 4c. Verify SAR receipt (Ed25519 — use SAR verifier)
console.log(" 4c. SAR receipt verification...");
console.log(" [Stub] Verify Ed25519 signature via SAR key registry.");
console.log(" See: https://defaultverifier.com/.well-known/sar-keys.json\n");
// ─── Summary: agent_id links all artifacts ───
console.log("─── Artifact Summary ───");
console.log(`Agent ID: ${AGENT_ID}`);
console.log(`Attestation ID: ${attestation.id}`);
console.log(`Payment TX: ${paymentTxHash}`);
console.log(`SAR Receipt ID: ${sarReceipt.receipt_id}`);
console.log(
"\nAll four artifacts are linked by agent_id and independently"
);
console.log("verifiable offline — no callbacks to either issuer required.");
}
main().catch(console.error);