@reinconsole/x402-rails 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -164,6 +164,239 @@ declare const PaymentPayload: z.ZodObject<{
164
164
  };
165
165
  }>;
166
166
  type PaymentPayload = z.infer<typeof PaymentPayload>;
167
+ /**
168
+ * The v2 envelope (PAYMENT-SIGNATURE header): scheme/network live inside
169
+ * `accepted` — the requirement the payer chose — around the SAME signed
170
+ * scheme payload as v1. `.passthrough()` keeps resource/extensions intact
171
+ * because the facilitator re-verifies the envelope verbatim.
172
+ */
173
+ declare const PaymentPayloadV2: z.ZodObject<{
174
+ x402Version: z.ZodLiteral<2>;
175
+ accepted: z.ZodObject<{
176
+ scheme: z.ZodString;
177
+ /** CAIP-2, e.g. "eip155:84532". */
178
+ network: z.ZodString;
179
+ amount: z.ZodString;
180
+ asset: z.ZodString;
181
+ payTo: z.ZodString;
182
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
183
+ scheme: z.ZodString;
184
+ /** CAIP-2, e.g. "eip155:84532". */
185
+ network: z.ZodString;
186
+ amount: z.ZodString;
187
+ asset: z.ZodString;
188
+ payTo: z.ZodString;
189
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
190
+ scheme: z.ZodString;
191
+ /** CAIP-2, e.g. "eip155:84532". */
192
+ network: z.ZodString;
193
+ amount: z.ZodString;
194
+ asset: z.ZodString;
195
+ payTo: z.ZodString;
196
+ }, z.ZodTypeAny, "passthrough">>;
197
+ payload: z.ZodObject<{
198
+ /** 65-byte EIP-712 signature over the authorization. */
199
+ signature: z.ZodString;
200
+ authorization: z.ZodObject<{
201
+ from: z.ZodString;
202
+ to: z.ZodString;
203
+ /** Atomic-unit amount, mirroring the requirement's maxAmountRequired. */
204
+ value: z.ZodString;
205
+ validAfter: z.ZodString;
206
+ validBefore: z.ZodString;
207
+ /** bytes32 — Rein derives it from the intent id (see nonce.ts). */
208
+ nonce: z.ZodString;
209
+ }, "strip", z.ZodTypeAny, {
210
+ from: string;
211
+ to: string;
212
+ value: string;
213
+ validAfter: string;
214
+ validBefore: string;
215
+ nonce: string;
216
+ }, {
217
+ from: string;
218
+ to: string;
219
+ value: string;
220
+ validAfter: string;
221
+ validBefore: string;
222
+ nonce: string;
223
+ }>;
224
+ }, "strip", z.ZodTypeAny, {
225
+ signature: string;
226
+ authorization: {
227
+ from: string;
228
+ to: string;
229
+ value: string;
230
+ validAfter: string;
231
+ validBefore: string;
232
+ nonce: string;
233
+ };
234
+ }, {
235
+ signature: string;
236
+ authorization: {
237
+ from: string;
238
+ to: string;
239
+ value: string;
240
+ validAfter: string;
241
+ validBefore: string;
242
+ nonce: string;
243
+ };
244
+ }>;
245
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
246
+ x402Version: z.ZodLiteral<2>;
247
+ accepted: z.ZodObject<{
248
+ scheme: z.ZodString;
249
+ /** CAIP-2, e.g. "eip155:84532". */
250
+ network: z.ZodString;
251
+ amount: z.ZodString;
252
+ asset: z.ZodString;
253
+ payTo: z.ZodString;
254
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
255
+ scheme: z.ZodString;
256
+ /** CAIP-2, e.g. "eip155:84532". */
257
+ network: z.ZodString;
258
+ amount: z.ZodString;
259
+ asset: z.ZodString;
260
+ payTo: z.ZodString;
261
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
262
+ scheme: z.ZodString;
263
+ /** CAIP-2, e.g. "eip155:84532". */
264
+ network: z.ZodString;
265
+ amount: z.ZodString;
266
+ asset: z.ZodString;
267
+ payTo: z.ZodString;
268
+ }, z.ZodTypeAny, "passthrough">>;
269
+ payload: z.ZodObject<{
270
+ /** 65-byte EIP-712 signature over the authorization. */
271
+ signature: z.ZodString;
272
+ authorization: z.ZodObject<{
273
+ from: z.ZodString;
274
+ to: z.ZodString;
275
+ /** Atomic-unit amount, mirroring the requirement's maxAmountRequired. */
276
+ value: z.ZodString;
277
+ validAfter: z.ZodString;
278
+ validBefore: z.ZodString;
279
+ /** bytes32 — Rein derives it from the intent id (see nonce.ts). */
280
+ nonce: z.ZodString;
281
+ }, "strip", z.ZodTypeAny, {
282
+ from: string;
283
+ to: string;
284
+ value: string;
285
+ validAfter: string;
286
+ validBefore: string;
287
+ nonce: string;
288
+ }, {
289
+ from: string;
290
+ to: string;
291
+ value: string;
292
+ validAfter: string;
293
+ validBefore: string;
294
+ nonce: string;
295
+ }>;
296
+ }, "strip", z.ZodTypeAny, {
297
+ signature: string;
298
+ authorization: {
299
+ from: string;
300
+ to: string;
301
+ value: string;
302
+ validAfter: string;
303
+ validBefore: string;
304
+ nonce: string;
305
+ };
306
+ }, {
307
+ signature: string;
308
+ authorization: {
309
+ from: string;
310
+ to: string;
311
+ value: string;
312
+ validAfter: string;
313
+ validBefore: string;
314
+ nonce: string;
315
+ };
316
+ }>;
317
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
318
+ x402Version: z.ZodLiteral<2>;
319
+ accepted: z.ZodObject<{
320
+ scheme: z.ZodString;
321
+ /** CAIP-2, e.g. "eip155:84532". */
322
+ network: z.ZodString;
323
+ amount: z.ZodString;
324
+ asset: z.ZodString;
325
+ payTo: z.ZodString;
326
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
327
+ scheme: z.ZodString;
328
+ /** CAIP-2, e.g. "eip155:84532". */
329
+ network: z.ZodString;
330
+ amount: z.ZodString;
331
+ asset: z.ZodString;
332
+ payTo: z.ZodString;
333
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
334
+ scheme: z.ZodString;
335
+ /** CAIP-2, e.g. "eip155:84532". */
336
+ network: z.ZodString;
337
+ amount: z.ZodString;
338
+ asset: z.ZodString;
339
+ payTo: z.ZodString;
340
+ }, z.ZodTypeAny, "passthrough">>;
341
+ payload: z.ZodObject<{
342
+ /** 65-byte EIP-712 signature over the authorization. */
343
+ signature: z.ZodString;
344
+ authorization: z.ZodObject<{
345
+ from: z.ZodString;
346
+ to: z.ZodString;
347
+ /** Atomic-unit amount, mirroring the requirement's maxAmountRequired. */
348
+ value: z.ZodString;
349
+ validAfter: z.ZodString;
350
+ validBefore: z.ZodString;
351
+ /** bytes32 — Rein derives it from the intent id (see nonce.ts). */
352
+ nonce: z.ZodString;
353
+ }, "strip", z.ZodTypeAny, {
354
+ from: string;
355
+ to: string;
356
+ value: string;
357
+ validAfter: string;
358
+ validBefore: string;
359
+ nonce: string;
360
+ }, {
361
+ from: string;
362
+ to: string;
363
+ value: string;
364
+ validAfter: string;
365
+ validBefore: string;
366
+ nonce: string;
367
+ }>;
368
+ }, "strip", z.ZodTypeAny, {
369
+ signature: string;
370
+ authorization: {
371
+ from: string;
372
+ to: string;
373
+ value: string;
374
+ validAfter: string;
375
+ validBefore: string;
376
+ nonce: string;
377
+ };
378
+ }, {
379
+ signature: string;
380
+ authorization: {
381
+ from: string;
382
+ to: string;
383
+ value: string;
384
+ validAfter: string;
385
+ validBefore: string;
386
+ nonce: string;
387
+ };
388
+ }>;
389
+ }, z.ZodTypeAny, "passthrough">>;
390
+ type PaymentPayloadV2 = z.infer<typeof PaymentPayloadV2>;
391
+ /** A payment as the vendor sees it, whichever dialect it arrived in. */
392
+ interface DecodedPayment {
393
+ version: 1 | 2;
394
+ scheme: string;
395
+ network: string;
396
+ payload: ExactEvmPayload;
397
+ /** The decoded envelope exactly as sent — what travels to the facilitator. */
398
+ envelope: PaymentPayload | PaymentPayloadV2;
399
+ }
167
400
  /** Facilitator POST /verify response. Reason strings stay lenient on purpose. */
168
401
  declare const VerifyResponse: z.ZodObject<{
169
402
  isValid: z.ZodBoolean;
@@ -203,6 +436,13 @@ declare const SettleResponse: z.ZodObject<{
203
436
  type SettleResponse = z.infer<typeof SettleResponse>;
204
437
  declare function encodePaymentHeader(payload: PaymentPayload): string;
205
438
  declare function decodePaymentHeader(raw: string): PaymentPayload;
439
+ /**
440
+ * Decode a payment header in EITHER dialect to one normalized view. The v2
441
+ * envelope wraps the SAME signed scheme payload as v1, so both unwrap to a
442
+ * single ExactEvmPayload; the envelope is kept verbatim for the facilitator,
443
+ * which wants the payment in the dialect it was presented in.
444
+ */
445
+ declare function decodeAnyPaymentHeader(raw: string): DecodedPayment;
206
446
  declare function encodeSettlementHeader(response: SettleResponse): string;
207
447
 
208
448
  /**
@@ -310,6 +550,15 @@ interface RealVendorOptions {
310
550
  extra?: Record<string, unknown>;
311
551
  /** JSON body served once payment settles. */
312
552
  body?: unknown;
553
+ /**
554
+ * Which x402 dialect the vendor's 402s advertise. 'v1' (default) is the
555
+ * classic JSON body; 'dual' adds the v2 PAYMENT-REQUIRED header beside it;
556
+ * 'v2' advertises ONLY the header (the body is not x402) — a strict v2
557
+ * vendor for proving clients need no v1 fallback. Payments are ACCEPTED in
558
+ * both dialects (PAYMENT-SIGNATURE or X-PAYMENT) regardless of this option,
559
+ * mirroring the gate.
560
+ */
561
+ advertise?: 'v1' | 'dual' | 'v2';
313
562
  }
314
563
  interface VendorCall {
315
564
  url: string;
@@ -325,9 +574,12 @@ interface RealVendor {
325
574
  }
326
575
  /**
327
576
  * An in-process x402 vendor wired to a REAL facilitator: quotes a 402 with
328
- * payment requirements until the request carries X-PAYMENT, then verifies and
577
+ * payment requirements until the request carries a payment, then verifies and
329
578
  * settles through the facilitator — a real on-chain USDC transfer — and serves
330
- * the content with the settlement (tx hash included) in X-PAYMENT-RESPONSE.
579
+ * the content with the settlement (tx hash included) in the response headers.
580
+ * Dual-stack like the gate: payments are accepted on X-PAYMENT (v1) and
581
+ * PAYMENT-SIGNATURE (v2) alike, and `advertise` picks which dialect the 402s
582
+ * quote in.
331
583
  *
332
584
  * Unlike the mock vendor, the quoted requirement is fully populated: the
333
585
  * hosted facilitator validates it strictly (resource must be a URL,
@@ -504,4 +756,4 @@ declare class FacilitatorHttpError extends Error {
504
756
  constructor(status: number, body: string);
505
757
  }
506
758
 
507
- export { BASE_SEPOLIA_USDC, type BaseSepoliaClient, CIRCLE_FAUCET_URL, type ChainReader, DEFAULT_FACILITATOR_URL, type EngineEvents, ExactEvmAuthorization, ExactEvmPayload, FacilitatorClient, type FacilitatorClientOptions, FacilitatorHttpError, type GeneratedWallet, OnchainIndexer, type OnchainIndexerOptions, PaymentPayload, type RailLog, RailsError, type RailsErrorCode, type RealVendor, type RealVendorOptions, SettleResponse, type ShadowSpend, type VendorCall, VerifyResponse, type X402PayerOptions, basescanTxUrl, chainIdForNetwork, createBaseSepoliaClient, createRealVendor, createX402Payer, decodePaymentHeader, encodePaymentHeader, encodeSettlementHeader, generateWallet, getUsdcBalance, intentNonce, railEventsAbi, transferWithAuthorizationTypes };
759
+ export { BASE_SEPOLIA_USDC, type BaseSepoliaClient, CIRCLE_FAUCET_URL, type ChainReader, DEFAULT_FACILITATOR_URL, type DecodedPayment, type EngineEvents, ExactEvmAuthorization, ExactEvmPayload, FacilitatorClient, type FacilitatorClientOptions, FacilitatorHttpError, type GeneratedWallet, OnchainIndexer, type OnchainIndexerOptions, PaymentPayload, PaymentPayloadV2, type RailLog, RailsError, type RailsErrorCode, type RealVendor, type RealVendorOptions, SettleResponse, type ShadowSpend, type VendorCall, VerifyResponse, type X402PayerOptions, basescanTxUrl, chainIdForNetwork, createBaseSepoliaClient, createRealVendor, createX402Payer, decodeAnyPaymentHeader, decodePaymentHeader, encodePaymentHeader, encodeSettlementHeader, generateWallet, getUsdcBalance, intentNonce, railEventsAbi, transferWithAuthorizationTypes };
package/dist/index.js CHANGED
@@ -46,6 +46,18 @@ var PaymentPayload = z.object({
46
46
  network: z.string(),
47
47
  payload: ExactEvmPayload
48
48
  });
49
+ var PaymentPayloadV2 = z.object({
50
+ x402Version: z.literal(2),
51
+ accepted: z.object({
52
+ scheme: z.string(),
53
+ /** CAIP-2, e.g. "eip155:84532". */
54
+ network: z.string(),
55
+ amount: UintString,
56
+ asset: z.string().min(1),
57
+ payTo: z.string().min(1)
58
+ }).passthrough(),
59
+ payload: ExactEvmPayload
60
+ }).passthrough();
49
61
  var VerifyResponse = z.object({
50
62
  isValid: z.boolean(),
51
63
  invalidReason: z.string().optional(),
@@ -75,6 +87,47 @@ function decodePaymentHeader(raw) {
75
87
  }
76
88
  return parsed.data;
77
89
  }
90
+ function decodeAnyPaymentHeader(raw) {
91
+ let json;
92
+ try {
93
+ json = JSON.parse(Buffer.from(raw, "base64").toString("utf8"));
94
+ } catch {
95
+ throw new RailsError("malformed_payment", "the payment header is not base64-encoded JSON");
96
+ }
97
+ if (json?.x402Version === 2) {
98
+ const parsed2 = PaymentPayloadV2.safeParse(json);
99
+ if (!parsed2.success) {
100
+ throw new RailsError(
101
+ "malformed_payment",
102
+ `invalid v2 payment envelope: ${parsed2.error.message}`
103
+ );
104
+ }
105
+ if (parsed2.data.payload.authorization.value !== parsed2.data.accepted.amount) {
106
+ throw new RailsError(
107
+ "malformed_payment",
108
+ `v2 envelope contradicts itself: accepted.amount ${parsed2.data.accepted.amount} vs signed value ${parsed2.data.payload.authorization.value}`
109
+ );
110
+ }
111
+ return {
112
+ version: 2,
113
+ scheme: parsed2.data.accepted.scheme,
114
+ network: parsed2.data.accepted.network,
115
+ payload: parsed2.data.payload,
116
+ envelope: parsed2.data
117
+ };
118
+ }
119
+ const parsed = PaymentPayload.safeParse(json);
120
+ if (!parsed.success) {
121
+ throw new RailsError("malformed_payment", `invalid X-PAYMENT body: ${parsed.error.message}`);
122
+ }
123
+ return {
124
+ version: 1,
125
+ scheme: parsed.data.scheme,
126
+ network: parsed.data.network,
127
+ payload: parsed.data.payload,
128
+ envelope: parsed.data
129
+ };
130
+ }
78
131
  function encodeSettlementHeader(response) {
79
132
  return Buffer.from(JSON.stringify(response)).toString("base64");
80
133
  }
@@ -516,6 +569,81 @@ function atomicToDecimal(atomic, decimals) {
516
569
  const fracPart = digits.slice(digits.length - decimals).replace(/0+$/, "");
517
570
  return fracPart.length > 0 ? `${intPart}.${fracPart}` : intPart;
518
571
  }
572
+ var CAIP2_ALIASES = {
573
+ base: "eip155:8453",
574
+ "base-sepolia": "eip155:84532",
575
+ polygon: "eip155:137",
576
+ "polygon-amoy": "eip155:80002",
577
+ bnb: "eip155:56",
578
+ bsc: "eip155:56",
579
+ solana: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
580
+ "solana-devnet": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"
581
+ };
582
+ function caip2Of(network) {
583
+ const key = network.toLowerCase();
584
+ return CAIP2_ALIASES[key] ?? key;
585
+ }
586
+ function sameNetwork(a, b) {
587
+ return caip2Of(a) === caip2Of(b);
588
+ }
589
+ var PaymentRequirementsV2 = z3.object({
590
+ scheme: z3.string(),
591
+ /** CAIP-2, e.g. "eip155:84532". */
592
+ network: z3.string(),
593
+ /** Atomic units — v2's rename of v1's maxAmountRequired. */
594
+ amount: z3.string().regex(/^\d+$/, "atomic amount must be an integer string"),
595
+ asset: z3.string().min(1),
596
+ payTo: z3.string().min(1),
597
+ maxTimeoutSeconds: z3.number().optional(),
598
+ extra: z3.record(z3.unknown()).optional()
599
+ });
600
+ var ResourceInfoV2 = z3.object({
601
+ url: z3.string(),
602
+ description: z3.string().optional(),
603
+ mimeType: z3.string().optional()
604
+ });
605
+ var PaymentRequiredV2 = z3.object({
606
+ x402Version: z3.literal(2),
607
+ error: z3.string().optional(),
608
+ resource: ResourceInfoV2.optional(),
609
+ accepts: z3.array(PaymentRequirementsV2).min(1),
610
+ extensions: z3.record(z3.unknown()).optional()
611
+ });
612
+ function v2Requirements(requirement) {
613
+ return {
614
+ scheme: requirement.scheme,
615
+ network: caip2Of(requirement.network),
616
+ amount: requirement.maxAmountRequired,
617
+ asset: requirement.asset,
618
+ payTo: requirement.payTo,
619
+ ...requirement.maxTimeoutSeconds !== void 0 ? { maxTimeoutSeconds: requirement.maxTimeoutSeconds } : {},
620
+ ...requirement.extra ? { extra: requirement.extra } : {}
621
+ };
622
+ }
623
+ function buildPaymentRequiredV2(requirement, error) {
624
+ return {
625
+ x402Version: 2,
626
+ error,
627
+ ...requirement.resource ? {
628
+ resource: {
629
+ url: requirement.resource,
630
+ ...requirement.description ? { description: requirement.description } : {},
631
+ ...requirement.mimeType ? { mimeType: requirement.mimeType } : {}
632
+ }
633
+ } : {},
634
+ accepts: [v2Requirements(requirement)],
635
+ extensions: {}
636
+ };
637
+ }
638
+ function encodeBase64Json(value) {
639
+ return Buffer.from(JSON.stringify(value)).toString("base64");
640
+ }
641
+ var V1Envelope = z3.object({
642
+ x402Version: z3.literal(1),
643
+ scheme: z3.string(),
644
+ network: z3.string(),
645
+ payload: z3.record(z3.unknown())
646
+ });
519
647
 
520
648
  // src/wallet.ts
521
649
  import {
@@ -547,6 +675,7 @@ async function getUsdcBalance(client, address, usdc = BASE_SEPOLIA_USDC) {
547
675
  // src/vendor.ts
548
676
  function createRealVendor(options) {
549
677
  const calls = [];
678
+ const advertise = options.advertise ?? "v1";
550
679
  const requirementFor = (url) => PaymentRequirement.parse({
551
680
  scheme: "exact",
552
681
  network: options.network ?? "base-sepolia",
@@ -559,39 +688,57 @@ function createRealVendor(options) {
559
688
  asset: options.asset ?? BASE_SEPOLIA_USDC,
560
689
  extra: options.extra ?? { name: "USDC", version: "2" }
561
690
  });
562
- const paymentRequired = (url, error) => new Response(JSON.stringify({ x402Version: 1, accepts: [requirementFor(url)], error }), {
563
- status: 402,
564
- headers: { "content-type": "application/json" }
565
- });
691
+ const paymentRequired = (url, error) => {
692
+ const requirement = requirementFor(url);
693
+ const body = advertise === "v2" ? { error } : { x402Version: 1, accepts: [requirement], error };
694
+ return new Response(JSON.stringify(body), {
695
+ status: 402,
696
+ headers: {
697
+ "content-type": "application/json",
698
+ ...advertise !== "v1" ? { "PAYMENT-REQUIRED": encodeBase64Json(buildPaymentRequiredV2(requirement, error)) } : {}
699
+ }
700
+ });
701
+ };
566
702
  const fetch = async (input, init) => {
567
703
  const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
568
704
  const headers = new Headers(
569
705
  init?.headers ?? (input instanceof Request ? input.headers : void 0)
570
706
  );
571
- const payment = headers.get("X-PAYMENT");
707
+ const payment = headers.get("PAYMENT-SIGNATURE") ?? headers.get("X-PAYMENT");
572
708
  calls.push({ url, payment });
573
- if (payment === null) return paymentRequired(url, "X-PAYMENT header is required");
709
+ if (payment === null) return paymentRequired(url, "payment is required");
574
710
  const requirement = requirementFor(url);
575
- let payload;
711
+ let decoded;
576
712
  try {
577
- payload = decodePaymentHeader(payment);
713
+ decoded = decodeAnyPaymentHeader(payment);
578
714
  } catch (err) {
579
715
  if (err instanceof RailsError) return paymentRequired(url, err.message);
580
716
  throw err;
581
717
  }
582
- const verified = await options.facilitator.verify(payload, requirement);
718
+ if (!sameNetwork(decoded.network, requirement.network)) {
719
+ return paymentRequired(
720
+ url,
721
+ `payment is on "${decoded.network}" but the requirement wants "${requirement.network}"`
722
+ );
723
+ }
724
+ const requirements = decoded.version === 2 ? v2Requirements(requirement) : requirement;
725
+ const verified = await options.facilitator.verify(decoded.envelope, requirements);
583
726
  if (!verified.isValid) {
584
727
  return paymentRequired(url, verified.invalidReason ?? "payment verification failed");
585
728
  }
586
- const settled = await options.facilitator.settle(payload, requirement);
729
+ const settled = await options.facilitator.settle(decoded.envelope, requirements);
587
730
  if (!settled.success) {
588
731
  return paymentRequired(url, settled.errorReason ?? "payment settlement failed");
589
732
  }
733
+ const settlement = encodeSettlementHeader(settled);
590
734
  return new Response(JSON.stringify(options.body ?? { ok: true }), {
591
735
  status: 200,
592
736
  headers: {
593
737
  "content-type": "application/json",
594
- "X-PAYMENT-RESPONSE": encodeSettlementHeader(settled)
738
+ // Both dialect names carry the same base64 settlement object; the
739
+ // strict v2 vendor sets ONLY the v2 name.
740
+ ...advertise !== "v2" ? { "X-PAYMENT-RESPONSE": settlement } : {},
741
+ "PAYMENT-RESPONSE": settlement
595
742
  }
596
743
  });
597
744
  };
@@ -788,6 +935,7 @@ export {
788
935
  FacilitatorHttpError,
789
936
  OnchainIndexer,
790
937
  PaymentPayload,
938
+ PaymentPayloadV2,
791
939
  RailsError,
792
940
  SettleResponse,
793
941
  VerifyResponse,
@@ -796,6 +944,7 @@ export {
796
944
  createBaseSepoliaClient,
797
945
  createRealVendor,
798
946
  createX402Payer,
947
+ decodeAnyPaymentHeader,
799
948
  decodePaymentHeader,
800
949
  encodePaymentHeader,
801
950
  encodeSettlementHeader,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/wire.ts","../src/errors.ts","../src/nonce.ts","../src/networks.ts","../src/payer.ts","../src/facilitator.ts","../../../packages/core/src/chain.ts","../../../packages/core/src/money.ts","../../../packages/core/src/glob.ts","../../../packages/core/src/ulid.ts","../../../packages/core/src/ids.ts","../../../packages/core/src/agent.ts","../../../packages/core/src/erc8004.ts","../../../packages/core/src/intent.ts","../../../packages/core/src/decision.ts","../../../packages/core/src/canonical.ts","../../../packages/core/src/session.ts","../../../packages/core/src/payment.ts","../../../packages/core/src/receipt.ts","../../../packages/core/src/gate-receipt.ts","../../../packages/core/src/policy.ts","../../../packages/core/src/reputation.ts","../../../packages/core/src/events.ts","../../../packages/sdk/src/errors.ts","../../../packages/sdk/src/client.ts","../../../packages/sdk/src/x402.ts","../../../packages/sdk/src/guard.ts","../src/wallet.ts","../src/vendor.ts","../src/indexer.ts"],"sourcesContent":["import { z } from 'zod';\nimport { RailsError } from './errors.js';\n\n/**\n * Wire codecs for the real x402 v1 exact-EVM scheme: the `X-PAYMENT` header\n * the payer signs (EIP-3009 authorization + signature), the facilitator's\n * verify/settle responses, and the `X-PAYMENT-RESPONSE` header the vendor\n * returns. Verified against the published v1 spec and the hosted facilitator\n * at x402.org (2026-06).\n */\n\nconst Hex = z.string().regex(/^0x[0-9a-fA-F]*$/, 'must be 0x-prefixed hex');\nconst EvmAddress = z.string().regex(/^0x[0-9a-fA-F]{40}$/, 'must be a 20-byte EVM address');\nconst UintString = z.string().regex(/^\\d+$/, 'must be a decimal integer string');\n\n/** The EIP-3009 TransferWithAuthorization message, decimal-stringified. */\nexport const ExactEvmAuthorization = z.object({\n from: EvmAddress,\n to: EvmAddress,\n /** Atomic-unit amount, mirroring the requirement's maxAmountRequired. */\n value: UintString,\n validAfter: UintString,\n validBefore: UintString,\n /** bytes32 — Rein derives it from the intent id (see nonce.ts). */\n nonce: z.string().regex(/^0x[0-9a-fA-F]{64}$/, 'nonce must be bytes32 hex'),\n});\nexport type ExactEvmAuthorization = z.infer<typeof ExactEvmAuthorization>;\n\nexport const ExactEvmPayload = z.object({\n /** 65-byte EIP-712 signature over the authorization. */\n signature: Hex,\n authorization: ExactEvmAuthorization,\n});\nexport type ExactEvmPayload = z.infer<typeof ExactEvmPayload>;\n\n/** The full X-PAYMENT header body (x402 spec v1 envelope). */\nexport const PaymentPayload = z.object({\n x402Version: z.literal(1),\n scheme: z.string(),\n network: z.string(),\n payload: ExactEvmPayload,\n});\nexport type PaymentPayload = z.infer<typeof PaymentPayload>;\n\n/** Facilitator POST /verify response. Reason strings stay lenient on purpose. */\nexport const VerifyResponse = z.object({\n isValid: z.boolean(),\n invalidReason: z.string().optional(),\n payer: z.string().optional(),\n});\nexport type VerifyResponse = z.infer<typeof VerifyResponse>;\n\n/** Facilitator POST /settle response (also what X-PAYMENT-RESPONSE carries). */\nexport const SettleResponse = z.object({\n success: z.boolean(),\n errorReason: z.string().optional(),\n payer: z.string().optional(),\n /** The on-chain tx hash (the guard surfaces this on the receipt). */\n transaction: z.string(),\n network: z.string(),\n});\nexport type SettleResponse = z.infer<typeof SettleResponse>;\n\nexport function encodePaymentHeader(payload: PaymentPayload): string {\n return Buffer.from(JSON.stringify(payload)).toString('base64');\n}\n\nexport function decodePaymentHeader(raw: string): PaymentPayload {\n let json: unknown;\n try {\n json = JSON.parse(Buffer.from(raw, 'base64').toString('utf8'));\n } catch {\n throw new RailsError('malformed_payment', 'X-PAYMENT is not base64-encoded JSON');\n }\n const parsed = PaymentPayload.safeParse(json);\n if (!parsed.success) {\n throw new RailsError('malformed_payment', `invalid X-PAYMENT body: ${parsed.error.message}`);\n }\n return parsed.data;\n}\n\nexport function encodeSettlementHeader(response: SettleResponse): string {\n return Buffer.from(JSON.stringify(response)).toString('base64');\n}\n","export type RailsErrorCode = 'malformed_payment' | 'unsupported_network';\n\n/** A payload or requirement these rails refuse to handle, with a machine-readable code. */\nexport class RailsError extends Error {\n constructor(\n readonly code: RailsErrorCode,\n message: string,\n ) {\n super(message);\n this.name = 'RailsError';\n }\n}\n\n/** The facilitator answered with a non-2xx status; body kept for forensics. */\nexport class FacilitatorHttpError extends Error {\n constructor(\n readonly status: number,\n readonly body: string,\n ) {\n super(`facilitator responded ${status}: ${body.slice(0, 500)}`);\n this.name = 'FacilitatorHttpError';\n }\n}\n","import { keccak256, stringToBytes, type Hex } from 'viem';\n\n/**\n * Deterministic EIP-3009 nonce: keccak256(utf8(intent.id)).\n *\n * This is the on-chain memo. EIP-3009 only requires per-authorizer uniqueness\n * (intent ids are ULIDs, so collisions are off the table), and USDC emits\n * `AuthorizationUsed(authorizer, nonce)` on settlement — so the indexer can\n * recompute this for every allowed intent and reconcile transfers exactly,\n * the same memo-first semantics the mock rails get from a ledger memo field.\n */\nexport function intentNonce(intentId: string): Hex {\n return keccak256(stringToBytes(intentId));\n}\n","/**\n * x402 network ids → EVM chain ids these rails can sign for. Accepts both the\n * v1 names (\"base-sepolia\") and the v2 CAIP-2 ids (\"eip155:84532\"). Unknown\n * networks return undefined — callers must fail closed.\n */\nconst NETWORK_TO_CHAIN_ID: Record<string, number> = {\n base: 8453,\n 'eip155:8453': 8453,\n 'base-sepolia': 84532,\n 'eip155:84532': 84532,\n};\n\nexport function chainIdForNetwork(network: string): number | undefined {\n return NETWORK_TO_CHAIN_ID[network.toLowerCase()];\n}\n","import { privateKeyToAccount } from 'viem/accounts';\nimport type { Hex, LocalAccount } from 'viem';\nimport type { Payer, PaymentRequirement } from '@reinconsole/sdk';\nimport { RailsError } from './errors.js';\nimport { chainIdForNetwork } from './networks.js';\nimport { intentNonce } from './nonce.js';\nimport { encodePaymentHeader, type ExactEvmAuthorization } from './wire.js';\n\n/** The EIP-3009 type tuple USDC's FiatTokenV2 verifies against. */\nexport const transferWithAuthorizationTypes = {\n TransferWithAuthorization: [\n { name: 'from', type: 'address' },\n { name: 'to', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'validAfter', type: 'uint256' },\n { name: 'validBefore', type: 'uint256' },\n { name: 'nonce', type: 'bytes32' },\n ],\n} as const;\n\nexport interface X402PayerOptions {\n /** The agent wallet's private key (a local account; never leaves the process). */\n privateKey: Hex;\n /** How far into the past validAfter reaches, absorbing clock skew. */\n validAfterSkewSeconds?: number;\n /** validBefore window when the requirement omits maxTimeoutSeconds. */\n defaultTimeoutSeconds?: number;\n /** Injectable clock (unix seconds) for deterministic tests. */\n now?: () => number;\n}\n\n/**\n * The real x402 `Payer`: signs an EIP-3009 TransferWithAuthorization for the\n * requirement's token (EIP-712, fully offline — no RPC) and returns the v1\n * X-PAYMENT header. Gasless for the agent: the facilitator submits the tx.\n *\n * The authorization nonce is derived from the intent id, which is what lets\n * the on-chain indexer reconcile the settlement back to the decision that\n * allowed it (see nonce.ts).\n */\nexport function createX402Payer(options: X402PayerOptions): Payer {\n const account: LocalAccount = privateKeyToAccount(options.privateKey);\n const skew = options.validAfterSkewSeconds ?? 600;\n const defaultTimeout = options.defaultTimeoutSeconds ?? 300;\n const now = options.now ?? (() => Math.floor(Date.now() / 1000));\n\n return async (requirement, intent) => {\n const chainId = chainIdForNetwork(requirement.network);\n if (chainId === undefined) {\n throw new RailsError(\n 'unsupported_network',\n `cannot sign for x402 network \"${requirement.network}\"`,\n );\n }\n\n const ts = now();\n const authorization: ExactEvmAuthorization = {\n from: account.address,\n to: requirement.payTo as Hex,\n value: requirement.maxAmountRequired,\n validAfter: String(ts - skew),\n validBefore: String(ts + (requirement.maxTimeoutSeconds ?? defaultTimeout)),\n nonce: intentNonce(intent.id),\n };\n\n const signature = await account.signTypedData({\n domain: {\n name: extraString(requirement, 'name') ?? 'USDC',\n version: extraString(requirement, 'version') ?? '2',\n chainId,\n verifyingContract: requirement.asset as Hex,\n },\n types: transferWithAuthorizationTypes,\n primaryType: 'TransferWithAuthorization',\n message: {\n from: authorization.from as Hex,\n to: authorization.to as Hex,\n value: BigInt(authorization.value),\n validAfter: BigInt(authorization.validAfter),\n validBefore: BigInt(authorization.validBefore),\n nonce: authorization.nonce as Hex,\n },\n });\n\n return encodePaymentHeader({\n x402Version: 1,\n scheme: requirement.scheme,\n network: requirement.network,\n payload: { signature, authorization },\n });\n };\n}\n\n/** EIP-712 domain name/version travel in requirement.extra (per the v1 spec). */\nfunction extraString(requirement: PaymentRequirement, key: string): string | undefined {\n const value = requirement.extra?.[key];\n return typeof value === 'string' ? value : undefined;\n}\n","import type { FetchLike, PaymentRequirement } from '@reinconsole/sdk';\nimport { FacilitatorHttpError } from './errors.js';\nimport { SettleResponse, VerifyResponse, type PaymentPayload } from './wire.js';\n\n/** Coinbase's hosted testnet facilitator: free, no API key, v1 + base-sepolia. */\nexport const DEFAULT_FACILITATOR_URL = 'https://x402.org/facilitator';\n\nexport interface FacilitatorClientOptions {\n /** Facilitator base URL. Defaults to the hosted x402.org testnet facilitator. */\n url?: string;\n /** Transport override (tests inject a stub here). Defaults to global fetch. */\n fetch?: FetchLike;\n}\n\n/** Any x402 payment envelope — the POST's x402Version is read off of it. */\nexport type AnyPaymentPayload = PaymentPayload | ({ x402Version: number } & Record<string, unknown>);\n/** Requirements in whichever dialect matches the payload (v1 or v2 shape). */\nexport type AnyPaymentRequirements = PaymentRequirement | Record<string, unknown>;\n\n/**\n * HTTP client for a real x402 facilitator (v1 AND v2 — x402.org serves both).\n * The vendor side of the rails: verify checks the payment signature against\n * the requirement, settle submits the EIP-3009 authorization on-chain (the\n * facilitator pays gas) and returns the tx hash. The POST's `x402Version` is\n * derived from the payload envelope itself, and the caller must pass\n * requirements in the SAME dialect (v2 payload → v2 `amount`/CAIP-2 shape;\n * @reinconsole/gate's facilitatorClientRails does this conversion).\n */\nexport class FacilitatorClient {\n readonly url: string;\n private readonly fetch: FetchLike;\n\n constructor(options: FacilitatorClientOptions = {}) {\n this.url = (options.url ?? DEFAULT_FACILITATOR_URL).replace(/\\/$/, '');\n const f = options.fetch ?? globalThis.fetch;\n this.fetch = (input, init) => f(input, init);\n }\n\n async verify(\n payload: AnyPaymentPayload,\n requirements: AnyPaymentRequirements,\n ): Promise<VerifyResponse> {\n return VerifyResponse.parse(await this.post('/verify', payload, requirements));\n }\n\n async settle(\n payload: AnyPaymentPayload,\n requirements: AnyPaymentRequirements,\n ): Promise<SettleResponse> {\n return SettleResponse.parse(await this.post('/settle', payload, requirements));\n }\n\n /** The facilitator's advertised (x402Version, scheme, network) kinds. */\n async supported(): Promise<unknown> {\n const res = await this.fetch(`${this.url}/supported`);\n if (!res.ok) throw new FacilitatorHttpError(res.status, await res.text());\n return res.json();\n }\n\n private async post(\n path: string,\n paymentPayload: AnyPaymentPayload,\n paymentRequirements: AnyPaymentRequirements,\n ): Promise<unknown> {\n // The payment travels DECODED (JSON object, not base64) and the\n // requirement is a single object, not the 402 body's accepts array.\n // Same envelope both versions; x402Version mirrors the payload's own.\n const claimed = (paymentPayload as { x402Version?: unknown }).x402Version;\n const x402Version = typeof claimed === 'number' ? claimed : 1;\n const res = await this.fetch(`${this.url}${path}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ x402Version, paymentPayload, paymentRequirements }),\n });\n if (!res.ok) throw new FacilitatorHttpError(res.status, await res.text());\n return res.json();\n }\n}\n","import { z } from 'zod';\n\n/**\n * Chains Rein observes/governs. x402 is multi-chain; Base and Solana ship\n * first, Polygon and BNB follow. The policy/ledger domain is rail-agnostic —\n * this enum is the only place chains are enumerated.\n */\nexport const Chain = z.enum(['base', 'solana', 'polygon', 'bnb']);\nexport type Chain = z.infer<typeof Chain>;\n\n/** Stablecoins settled over x402. */\nexport const Asset = z.enum(['USDC', 'USDT', 'EURC']);\nexport type Asset = z.infer<typeof Asset>;\n","import { z } from 'zod';\n\n/**\n * Monetary amounts in Rein are always non-negative **decimal strings**, never\n * floats. Float arithmetic silently loses precision on values like 0.1 + 0.2,\n * which is unacceptable for money. All comparison/aggregation goes through the\n * BigInt-backed helpers below.\n */\nexport const DecimalString = z\n .string()\n .regex(/^\\d+(\\.\\d+)?$/, 'must be a non-negative decimal string, e.g. \"5.00\"');\nexport type DecimalString = z.infer<typeof DecimalString>;\n\nconst DECIMAL_RE = /^\\d+(\\.\\d+)?$/;\n\nexport function isValidDecimal(value: string): boolean {\n return DECIMAL_RE.test(value);\n}\n\nfunction assertDecimal(value: string): void {\n if (!isValidDecimal(value)) {\n throw new TypeError(`invalid decimal string: ${JSON.stringify(value)}`);\n }\n}\n\nfunction fractionLength(value: string): number {\n const dot = value.indexOf('.');\n return dot === -1 ? 0 : value.length - dot - 1;\n}\n\n/** Scale a decimal string into an integer BigInt at a fixed number of fraction digits. */\nfunction toScaled(value: string, scale: number): bigint {\n const dot = value.indexOf('.');\n const intPart = dot === -1 ? value : value.slice(0, dot);\n const fracPart = dot === -1 ? '' : value.slice(dot + 1);\n const paddedFrac = (fracPart + '0'.repeat(scale)).slice(0, scale);\n return BigInt(intPart + paddedFrac);\n}\n\n/** Render a scaled BigInt back to a normalized decimal string (no trailing zeros). */\nfunction fromScaled(scaled: bigint, scale: number): string {\n if (scale === 0) return scaled.toString();\n const digits = scaled.toString().padStart(scale + 1, '0');\n const intPart = digits.slice(0, digits.length - scale);\n const fracPart = digits.slice(digits.length - scale).replace(/0+$/, '');\n return fracPart.length > 0 ? `${intPart}.${fracPart}` : intPart;\n}\n\n/** Compare two decimal strings. Returns -1 (a<b), 0 (a==b), or 1 (a>b). */\nexport function compareDecimal(a: string, b: string): -1 | 0 | 1 {\n assertDecimal(a);\n assertDecimal(b);\n const scale = Math.max(fractionLength(a), fractionLength(b));\n const av = toScaled(a, scale);\n const bv = toScaled(b, scale);\n return av < bv ? -1 : av > bv ? 1 : 0;\n}\n\n/** Sum a list of decimal strings without floating-point error. */\nexport function sumDecimal(values: readonly string[]): string {\n if (values.length === 0) return '0';\n let scale = 0;\n for (const v of values) {\n assertDecimal(v);\n scale = Math.max(scale, fractionLength(v));\n }\n let total = 0n;\n for (const v of values) total += toScaled(v, scale);\n return fromScaled(total, scale);\n}\n\n/** Multiply two decimal strings exactly (e.g. median * \"3\" for price-sanity). */\nexport function mulDecimal(a: string, b: string): string {\n assertDecimal(a);\n assertDecimal(b);\n const scaleA = fractionLength(a);\n const scaleB = fractionLength(b);\n const product = toScaled(a, scaleA) * toScaled(b, scaleB);\n return fromScaled(product, scaleA + scaleB);\n}\n\n/** Convenience: a > b. */\nexport function gt(a: string, b: string): boolean {\n return compareDecimal(a, b) === 1;\n}\n\n/** Convenience: a < b. */\nexport function lt(a: string, b: string): boolean {\n return compareDecimal(a, b) === -1;\n}\n","/**\n * Minimal, safe glob matcher supporting only the `*` wildcard (matches any run\n * of characters, including none). Used for vendor host allowlists\n * (e.g. \"*.trusted.io\"), agent-id targeting (e.g. \"agt_research_*\"), and\n * Gate route pricing (e.g. \"/api/reports/*\").\n *\n * Deliberately NOT a regex from user input — the pattern is escaped so a\n * malicious policy value cannot inject regex behavior (ReDoS, etc.).\n */\nexport function globMatch(pattern: string, value: string): boolean {\n const escaped = pattern.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'); // escape regex metachars\n const withWildcard = escaped.replace(/\\\\\\*/g, '.*'); // re-enable only `*`\n return new RegExp(`^${withWildcard}$`).test(value);\n}\n\n/** True if `value` matches any pattern in the list. */\nexport function globMatchAny(patterns: readonly string[], value: string): boolean {\n return patterns.some((p) => globMatch(p, value));\n}\n","/**\n * Minimal ULID generation, dependency-free. ULIDs are lexicographically\n * sortable (time-prefixed) and url-safe, which is why Rein uses them for all\n * primary keys instead of UUIDs. Works in Node 22 and modern browsers/edge via\n * the WebCrypto `globalThis.crypto`.\n */\n\n// Crockford's base32 alphabet (excludes I, L, O, U to avoid ambiguity).\nconst ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';\nconst TIME_LEN = 10;\nconst RANDOM_LEN = 16;\n\nfunction randomBytes(length: number): Uint8Array {\n const bytes = new Uint8Array(length);\n globalThis.crypto.getRandomValues(bytes);\n return bytes;\n}\n\nfunction encodeTime(now: number): string {\n let time = now;\n let out = '';\n for (let i = TIME_LEN - 1; i >= 0; i--) {\n out = ENCODING.charAt(time % 32) + out;\n time = Math.floor(time / 32);\n }\n return out;\n}\n\nfunction encodeRandom(): string {\n let out = '';\n for (const byte of randomBytes(RANDOM_LEN)) {\n out += ENCODING.charAt(byte % 32);\n }\n return out;\n}\n\n/** Generate a 26-character ULID. */\nexport function ulid(seedTime: number = Date.now()): string {\n return encodeTime(seedTime) + encodeRandom();\n}\n\n/** Generate a Stripe-style prefixed id, e.g. `newId('agt')` -> `agt_01J...`. */\nexport function newId<P extends string>(prefix: P): `${P}_${string}` {\n return `${prefix}_${ulid()}`;\n}\n","import { z } from 'zod';\n\n/** Crockford base32 ULID body (26 chars), as produced by `ulid()`. */\nconst ULID_BODY = '[0-9A-HJKMNP-TV-Z]{26}';\n\n/**\n * A zod schema for a Stripe-style prefixed ULID, e.g. `agt_01J7...`.\n * Centralizing this keeps id formats consistent across DB rows, API payloads,\n * and SDK types.\n */\nexport function prefixedId(prefix: string) {\n return z\n .string()\n .regex(new RegExp(`^${prefix}_${ULID_BODY}$`), `expected a \"${prefix}_\" prefixed id`);\n}\n\nexport const OrgId = prefixedId('org');\nexport const AgentId = prefixedId('agt');\nexport const PolicyId = prefixedId('pol');\nexport const IntentId = prefixedId('int');\nexport const DecisionId = prefixedId('dec');\nexport const ReceiptId = prefixedId('rcp');\nexport const SessionId = prefixedId('ses');\nexport const GateReceiptId = prefixedId('grc');\n\nexport type OrgId = z.infer<typeof OrgId>;\nexport type AgentId = z.infer<typeof AgentId>;\nexport type PolicyId = z.infer<typeof PolicyId>;\nexport type IntentId = z.infer<typeof IntentId>;\nexport type DecisionId = z.infer<typeof DecisionId>;\nexport type ReceiptId = z.infer<typeof ReceiptId>;\nexport type SessionId = z.infer<typeof SessionId>;\nexport type GateReceiptId = z.infer<typeof GateReceiptId>;\n","import { z } from 'zod';\nimport { AgentId, OrgId } from './ids.js';\nimport { Chain } from './chain.js';\n\n/**\n * Enforcement tier of a given agent wallet:\n * - `observed` — Rein sees spend on-chain but has no control (no SDK either).\n * - `sdk` — agent uses @reinconsole/sdk; advisory + observability (bypassable).\n * - `session-key` — signer-level scope; out-of-policy txs cannot be signed.\n */\nexport const EnforcementMode = z.enum(['observed', 'sdk', 'session-key']);\nexport type EnforcementMode = z.infer<typeof EnforcementMode>;\n\nexport const AgentWallet = z.object({\n chain: Chain,\n address: z.string().min(1),\n mode: EnforcementMode,\n});\nexport type AgentWallet = z.infer<typeof AgentWallet>;\n\nexport const AgentStatus = z.enum(['active', 'frozen']);\nexport type AgentStatus = z.infer<typeof AgentStatus>;\n\nexport const Agent = z.object({\n id: AgentId,\n orgId: OrgId,\n name: z.string().min(1).max(200),\n /** On-chain ERC-8004 identity, if the agent is registered. */\n erc8004Id: z.string().optional(),\n wallets: z.array(AgentWallet).default([]),\n status: AgentStatus.default('active'),\n createdAt: z.coerce.date(),\n});\nexport type Agent = z.infer<typeof Agent>;\n","import { z } from 'zod';\n\n/**\n * The canonical string form of an ERC-8004 agent identity:\n *\n * eip155:{chainId}:{identityRegistry}/{tokenId}\n *\n * The part before the `/` is the spec's registry reference verbatim (the\n * `agentRegistry` field of a registration file, CAIP-10 account form); the\n * tokenId is the ERC-721 id the Identity Registry minted (`agentId` in the\n * spec). This exact string is what `Agent.erc8004Id` / `Vendor.erc8004Id`\n * carry, AND the reputation-subject id a registered agent's evidence keys by.\n *\n * Casing is load-bearing: reputation subject keys for agent-kind ids are\n * case-sensitive unless they start with `0x` (see @reinconsole/graph\n * `normalizeSubject`), and an eip155 string does not. `formatErc8004Id`\n * therefore always emits the registry address in lowercase, and consumers must\n * never hand-build the string — parse then re-format to normalize.\n */\n\nexport interface Erc8004Ref {\n /** EIP-155 chain id (e.g. 8453 Base, 84532 Base Sepolia). */\n chainId: number;\n /** Identity Registry contract address, lowercase 0x-hex. */\n registry: string;\n /** ERC-721 tokenId — the spec's `agentId`. bigint: token ids exceed 2^53. */\n tokenId: bigint;\n}\n\nconst REGISTRY_PATTERN = /^0x[0-9a-fA-F]{40}$/;\nconst ID_PATTERN = /^eip155:(\\d+):(0x[0-9a-fA-F]{40})\\/(\\d+)$/;\n\n/** Build the canonical id string. Throws on a malformed ref (programmer error). */\nexport function formatErc8004Id(ref: Erc8004Ref): string {\n if (!Number.isSafeInteger(ref.chainId) || ref.chainId < 1) {\n throw new RangeError(`erc8004: bad chainId ${ref.chainId}`);\n }\n if (!REGISTRY_PATTERN.test(ref.registry)) {\n throw new RangeError(`erc8004: bad registry address ${ref.registry}`);\n }\n if (typeof ref.tokenId !== 'bigint' || ref.tokenId < 0n) {\n // The typeof guard matters for plain-JS callers: 1.5 < 0n is legal JS and\n // false, and would mint the unparseable \"…/1.5\".\n throw new RangeError(`erc8004: bad tokenId ${ref.tokenId}`);\n }\n return `eip155:${ref.chainId}:${ref.registry.toLowerCase()}/${ref.tokenId}`;\n}\n\n/**\n * Parse a canonical (or hand-written) id string. Accepts any address casing\n * and returns a lowercase ref, or undefined when malformed — so\n * `formatErc8004Id(parseErc8004Id(x)!)` is the normalization step.\n */\nexport function parseErc8004Id(value: string): Erc8004Ref | undefined {\n const match = ID_PATTERN.exec(value);\n if (!match) return undefined;\n const chainId = Number(match[1]);\n if (!Number.isSafeInteger(chainId) || chainId < 1) return undefined;\n return {\n chainId,\n registry: match[2]!.toLowerCase(),\n tokenId: BigInt(match[3]!),\n };\n}\n\n/** Strict boundary schema for the id string (the fields themselves stay free-form). */\nexport const Erc8004Id = z\n .string()\n .refine((value) => parseErc8004Id(value) !== undefined, {\n message: 'expected \"eip155:{chainId}:{registry}/{tokenId}\"',\n });\nexport type Erc8004Id = z.infer<typeof Erc8004Id>;\n","import { z } from 'zod';\nimport { AgentId, IntentId } from './ids.js';\nimport { Chain, Asset } from './chain.js';\nimport { DecimalString } from './money.js';\n\nexport const Vendor = z.object({\n host: z.string().min(1),\n address: z.string().min(1),\n erc8004Id: z.string().optional(),\n});\nexport type Vendor = z.infer<typeof Vendor>;\n\n/**\n * The observability gold: links every micro-payment back to the task and run\n * that caused it, so finance teams can answer \"what was this spend for?\".\n */\nexport const TaskContext = z.object({\n taskId: z.string().optional(),\n parentRunId: z.string().optional(),\n purpose: z.string().max(500).optional(),\n});\nexport type TaskContext = z.infer<typeof TaskContext>;\n\n/**\n * A request to spend, submitted to the policy engine BEFORE any signature is\n * released. The `nonce` provides replay protection on the signer path.\n */\nexport const PaymentIntent = z.object({\n id: IntentId,\n agentId: AgentId,\n vendor: Vendor,\n resource: z.string(),\n amount: DecimalString,\n asset: Asset,\n chain: Chain,\n taskContext: TaskContext.default({}),\n nonce: z.string().min(1),\n createdAt: z.coerce.date(),\n});\nexport type PaymentIntent = z.infer<typeof PaymentIntent>;\n","import { z } from 'zod';\nimport { DecisionId, IntentId } from './ids.js';\n\nexport const DecisionOutcome = z.enum(['allow', 'deny', 'escalate']);\nexport type DecisionOutcome = z.infer<typeof DecisionOutcome>;\n\n/**\n * The signed, hash-chained record of a single policy evaluation. Written BEFORE\n * any signature is released. `prevHash` + `hash` form a tamper-evident chain;\n * `signature` is the policy service's signing key over `hash`. The eventual\n * on-chain `txHash` is attached later by the indexer (see SettledPayment).\n */\nexport const Decision = z.object({\n id: DecisionId,\n intentId: IntentId,\n /**\n * sha256 of the intent's canonical content (see canonical.ts). Binds the\n * decision to the exact transfer it judged — amount, recipient, asset,\n * chain — so a signer can verify an {intent, decision} pair offline as a\n * self-contained spend voucher, not just a reference by id.\n */\n intentHash: z.string(),\n outcome: DecisionOutcome,\n /** Ids of the rules that fired, for explainability. */\n matchedRules: z.array(z.string()).default([]),\n /** Human-readable explanation surfaced in the dashboard. */\n reason: z.string().optional(),\n policyId: z.string(),\n policyVersion: z.string(),\n /** Hash of the previous decision in the chain (tamper-evident log). */\n prevHash: z.string(),\n /** Hash of this decision's canonical content. */\n hash: z.string(),\n /** Service signing-key signature over `hash`. */\n signature: z.string(),\n latencyMs: z.number().nonnegative(),\n decidedAt: z.coerce.date(),\n});\nexport type Decision = z.infer<typeof Decision>;\n","import type { PaymentIntent } from './intent.js';\nimport type { DecisionOutcome } from './decision.js';\n\n/**\n * Canonical byte forms shared by the policy engine (which hashes and signs\n * them) and the signer (which verifies them offline). Field order is fixed,\n * dates are ISO strings, and absent optionals are explicit nulls, so the same\n * parsed object always canonicalizes to the same bytes — including after a\n * JSON round-trip over HTTP.\n *\n * These builders are pure (no node:crypto) so @reinconsole/core stays loadable in a\n * browser; services hash the strings with whatever sha256 they have.\n */\n\n/** Canonical form of an intent — what `Decision.intentHash` commits to. */\nexport function canonicalIntent(intent: PaymentIntent): string {\n return JSON.stringify({\n id: intent.id,\n agentId: intent.agentId,\n vendor: {\n host: intent.vendor.host,\n address: intent.vendor.address,\n erc8004Id: intent.vendor.erc8004Id ?? null,\n },\n resource: intent.resource,\n amount: intent.amount,\n asset: intent.asset,\n chain: intent.chain,\n taskContext: {\n taskId: intent.taskContext.taskId ?? null,\n parentRunId: intent.taskContext.parentRunId ?? null,\n purpose: intent.taskContext.purpose ?? null,\n },\n nonce: intent.nonce,\n createdAt: intent.createdAt.toISOString(),\n });\n}\n\n/** The decision fields covered by `Decision.hash` (and thus its signature). */\nexport interface DecisionContent {\n intentId: string;\n intentHash: string;\n outcome: DecisionOutcome;\n matchedRules: string[];\n policyId: string;\n policyVersion: string;\n prevHash: string;\n decidedAt: Date;\n}\n\n/** Canonical form of a decision — what `Decision.hash` is computed over. */\nexport function canonicalDecision(d: DecisionContent): string {\n return JSON.stringify({\n intentId: d.intentId,\n intentHash: d.intentHash,\n outcome: d.outcome,\n matchedRules: d.matchedRules,\n policyId: d.policyId,\n policyVersion: d.policyVersion,\n prevHash: d.prevHash,\n decidedAt: d.decidedAt.toISOString(),\n });\n}\n","import { z } from 'zod';\nimport { AgentId, SessionId } from './ids.js';\nimport { DecimalString } from './money.js';\n\n/**\n * A session-key grant: the signer tier's unit of delegated authority. The\n * agent process holds only the bearer token — the wallet key never leaves the\n * signer — and the stored record keeps a hash of the token, never the token\n * itself (it is returned exactly once, at creation).\n *\n * Caps here are the signer-side backstop UNDER whatever policy says: a\n * signature is released only when the engine allowed the intent AND the\n * session has room. Amounts are decimal strings in the asset's human units.\n */\nexport const Session = z.object({\n id: SessionId,\n agentId: AgentId,\n /** sha256 hex of the bearer token. */\n tokenHash: z.string(),\n /** Cumulative ceiling across the session's lifetime. Absent = uncapped. */\n capAmount: DecimalString.optional(),\n /** Ceiling per individual signature. Absent = uncapped. */\n maxPerPayment: DecimalString.optional(),\n expiresAt: z.coerce.date(),\n createdAt: z.coerce.date(),\n revokedAt: z.coerce.date().optional(),\n});\nexport type Session = z.infer<typeof Session>;\n","import { z } from 'zod';\nimport { IntentId } from './ids.js';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\n\n/**\n * On-chain confirmation of a settled payment, reconciled by the indexer against\n * the originating intent (amount + recipient + nonce, or facilitator webhook).\n */\nexport const SettledPayment = z.object({\n intentId: IntentId,\n txHash: z.string(),\n chain: Chain,\n blockNumber: z.coerce.bigint(),\n facilitator: z.string().optional(),\n feePaid: DecimalString.optional(),\n confirmedAt: z.coerce.date(),\n});\nexport type SettledPayment = z.infer<typeof SettledPayment>;\n","import { z } from 'zod';\nimport { ReceiptId, IntentId, DecisionId, AgentId } from './ids.js';\nimport { Chain, Asset } from './chain.js';\nimport { DecimalString } from './money.js';\nimport { TaskContext } from './intent.js';\nimport { DecisionOutcome } from './decision.js';\n\n/**\n * What the SDK reports back after settlement: the `X-PAYMENT-RESPONSE` header\n * a vendor returns once payment clears. Mock facilitators fill this in v0.1;\n * the indexer reconciles it against on-chain truth later (see SettledPayment).\n */\nexport const ReceiptSettlement = z.object({\n txHash: z.string().optional(),\n networkId: z.string().optional(),\n /** Raw header payload, kept for forensics until the indexer confirms. */\n raw: z.string().optional(),\n});\nexport type ReceiptSettlement = z.infer<typeof ReceiptSettlement>;\n\n/**\n * The SDK-side record of one guarded payment attempt: which request triggered\n * it, what the engine decided, and (if allowed and paid) how it settled.\n * Receipts are the observability primitive — every 402 the guard touches\n * produces exactly one, whether the payment was allowed or blocked.\n */\nexport const Receipt = z.object({\n id: ReceiptId,\n agentId: AgentId,\n intentId: IntentId,\n decisionId: DecisionId,\n outcome: DecisionOutcome,\n /** The URL the agent actually fetched (the paywalled resource). */\n url: z.string(),\n method: z.string().default('GET'),\n vendorHost: z.string(),\n amount: DecimalString,\n asset: Asset,\n chain: Chain,\n taskContext: TaskContext.default({}),\n /** Human-readable explanation copied from the decision. */\n reason: z.string().optional(),\n /** Present only once a payment was made and the vendor confirmed it. */\n settlement: ReceiptSettlement.optional(),\n createdAt: z.coerce.date(),\n});\nexport type Receipt = z.infer<typeof Receipt>;\n","import { z } from 'zod';\nimport { GateReceiptId } from './ids.js';\nimport { DecimalString } from './money.js';\n\n/**\n * The vendor-side twin of `Receipt`: one settled x402 payment as the GATE saw\n * it — who paid, for which priced route, and the settlement transaction. The\n * agent-side Receipt records what an agent tried to spend; a GateReceipt\n * records what a vendor actually earned.\n */\nexport const GateReceipt = z.object({\n id: GateReceiptId,\n at: z.coerce.date(),\n /** The route pattern that priced this request, e.g. \"/api/reports/*\". */\n route: z.string().min(1),\n /** The concrete resource paid for (URL path actually requested). */\n resource: z.string().min(1),\n method: z.string().min(1),\n /** The paying wallet address, as asserted by the settled payment. */\n payer: z.string().min(1),\n payTo: z.string().min(1),\n /** Human-unit decimal amount, e.g. \"0.05\". */\n amount: DecimalString,\n /** The same amount in the asset's atomic units, e.g. \"50000\". */\n amountAtomic: z.string().regex(/^\\d+$/, 'atomic amount must be an integer string'),\n /** Token symbol or contract address, exactly as quoted in the requirement. */\n asset: z.string().min(1),\n network: z.string().min(1),\n /** Settlement transaction hash (mock ledger or on-chain). */\n transaction: z.string().min(1),\n});\nexport type GateReceipt = z.infer<typeof GateReceipt>;\n","import { z } from 'zod';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\n\n/** A rolling-window spec, e.g. \"24h\", \"1h\", \"30m\", \"7d\". */\nexport const Window = z\n .string()\n .regex(/^\\d+[smhd]$/, 'window must be like \"30s\", \"15m\", \"1h\", or \"7d\"');\nexport type Window = z.infer<typeof Window>;\n\n/** A relative multiplier, e.g. \"3x\" (used for price-sanity checks). */\nexport const Multiplier = z.string().regex(/^\\d+(\\.\\d+)?x$/, 'multiplier must be like \"3x\"');\nexport type Multiplier = z.infer<typeof Multiplier>;\n\n/**\n * The set of predicates a rule can test. Multiple predicates in one condition\n * are ANDed together. Each maps to an evaluator in the policy engine.\n */\nexport const Condition = z\n .object({\n /** Per-transaction amount exceeds this value. */\n amountGt: DecimalString.optional(),\n /** Sum of spend in a rolling window exceeds `gt`. */\n rollingSum: z.object({ window: Window, gt: DecimalString }).optional(),\n /** Transaction count in a rolling window exceeds `gt`. */\n txCount: z.object({ window: Window, gt: z.number().int().nonnegative() }).optional(),\n /** Vendor host matches one of these patterns (supports `*` globs). */\n vendorHostIn: z.array(z.string()).optional(),\n /** First time Rein has seen this vendor for the agent. */\n vendorFirstSeen: z.boolean().optional(),\n /** Vendor reputation score is below this threshold (Phase 3 hook). */\n vendorReputationLt: z.number().min(0).max(100).optional(),\n /** Amount is more than `gt`-times the observed median for this resource. */\n amountVsResourceMedian: z.object({ gt: Multiplier }).optional(),\n })\n .refine((c) => Object.values(c).some((v) => v !== undefined), {\n message: 'a condition must specify at least one predicate',\n });\nexport type Condition = z.infer<typeof Condition>;\n\n/**\n * A single rule: an id plus exactly one action (allow / deny / escalate) whose\n * value is the condition that triggers it.\n */\nexport const Rule = z\n .object({\n id: z.string().min(1),\n allow: Condition.optional(),\n deny: Condition.optional(),\n escalate: Condition.optional(),\n })\n .refine((r) => [r.allow, r.deny, r.escalate].filter((v) => v !== undefined).length === 1, {\n message: 'a rule must specify exactly one of allow / deny / escalate',\n });\nexport type Rule = z.infer<typeof Rule>;\n\nexport const PolicyDefault = z.enum(['allow', 'deny']);\nexport type PolicyDefault = z.infer<typeof PolicyDefault>;\n\nexport const AppliesTo = z.object({\n /** Agent id patterns (supports `*` globs, e.g. \"agt_research_*\"). */\n agents: z.array(z.string()).optional(),\n chains: z.array(Chain).optional(),\n});\nexport type AppliesTo = z.infer<typeof AppliesTo>;\n\nexport const Escalation = z.object({\n approvers: z.array(z.string()).default([]),\n timeoutAction: PolicyDefault.default('deny'),\n timeoutMin: z.number().int().positive().default(15),\n});\nexport type Escalation = z.infer<typeof Escalation>;\n\n/**\n * A declarative, versioned, immutable-once-active policy. Evaluation order in\n * the engine is: explicit DENY > ESCALATE > ALLOW > `default`.\n */\nexport const Policy = z.object({\n policyId: z.string().min(1),\n version: z.string().default('1'),\n appliesTo: AppliesTo.default({}),\n rules: z.array(Rule).default([]),\n default: PolicyDefault.default('deny'),\n /** Below this amount, fail-open is permitted during a policy-service outage. */\n denyFloor: DecimalString.default('0.05'),\n escalation: Escalation.optional(),\n});\nexport type Policy = z.infer<typeof Policy>;\n","import { z } from 'zod';\n\nexport const ReputationSubject = z.object({\n kind: z.enum(['agent', 'vendor']),\n id: z.string(),\n});\nexport type ReputationSubject = z.infer<typeof ReputationSubject>;\n\nexport const ReputationComponents = z.object({\n volume: z.number(),\n longevity: z.number(),\n disputeRate: z.number(),\n counterpartyQuality: z.number(),\n settlementReliability: z.number(),\n});\nexport type ReputationComponents = z.infer<typeof ReputationComponents>;\n\n/**\n * A reputation score for an agent or vendor (Phase 3 — Graph). `confidence` is\n * first-class: a thin-history subject returns LOW confidence rather than a\n * misleadingly high score, so policy can avoid both false trust and unfair\n * freezing.\n */\nexport const ReputationScore = z.object({\n subject: ReputationSubject,\n score: z.number().min(0).max(100),\n components: ReputationComponents,\n confidence: z.number().min(0).max(1),\n asOf: z.coerce.date(),\n /** Hash-anchored attestation, optionally published on-chain (ERC-8004). */\n evidenceUri: z.string().optional(),\n});\nexport type ReputationScore = z.infer<typeof ReputationScore>;\n","import { z } from 'zod';\nimport { AgentId, DecisionId, IntentId, SessionId } from './ids.js';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\nimport { PaymentIntent } from './intent.js';\nimport { Decision } from './decision.js';\nimport { SettledPayment } from './payment.js';\nimport { GateReceipt } from './gate-receipt.js';\n\n/**\n * The canonical event envelope published on the bus (NATS in production).\n * `shadow.spend` is emitted when the indexer sees on-chain spend from a managed\n * wallet with NO corresponding ALLOW decision — the bypass signal that catches\n * SDK-mode evasion and drives the upgrade to the signer tier.\n * `signature.released` / `signature.refused` are that tier's heartbeat: every\n * time the signer does or does not put a key to work, the bus knows why.\n * `gate.*` is the vendor side of the wire: every quote a Gate issues, every\n * payment it accepts, every payment it turns away.\n */\nexport const ReinEvent = z.discriminatedUnion('type', [\n z.object({ type: z.literal('intent.created'), at: z.coerce.date(), intent: PaymentIntent }),\n z.object({ type: z.literal('decision.made'), at: z.coerce.date(), decision: Decision }),\n z.object({ type: z.literal('payment.settled'), at: z.coerce.date(), payment: SettledPayment }),\n z.object({\n type: z.literal('shadow.spend'),\n at: z.coerce.date(),\n agentId: AgentId,\n txHash: z.string(),\n chain: Chain,\n amount: DecimalString,\n }),\n z.object({\n type: z.literal('signature.released'),\n at: z.coerce.date(),\n sessionId: SessionId,\n agentId: AgentId,\n intentId: IntentId,\n decisionId: DecisionId,\n amount: DecimalString,\n }),\n z.object({\n type: z.literal('signature.refused'),\n at: z.coerce.date(),\n /** Refusal code, e.g. \"decision_replayed\" (see @reinconsole/signer). */\n code: z.string(),\n reason: z.string(),\n sessionId: SessionId.optional(),\n agentId: AgentId.optional(),\n intentId: IntentId.optional(),\n }),\n z.object({\n type: z.literal('gate.quoted'),\n at: z.coerce.date(),\n resource: z.string(),\n method: z.string(),\n amount: DecimalString,\n asset: z.string(),\n network: z.string(),\n }),\n z.object({ type: z.literal('gate.settled'), at: z.coerce.date(), receipt: GateReceipt }),\n z.object({\n type: z.literal('gate.refused'),\n at: z.coerce.date(),\n /** Refusal code, e.g. \"payment_replayed\" (see @reinconsole/gate). */\n code: z.string(),\n reason: z.string(),\n resource: z.string(),\n /** Known only when the payment header decoded far enough to name a payer. */\n payer: z.string().optional(),\n }),\n]);\nexport type ReinEvent = z.infer<typeof ReinEvent>;\n","import type { Decision, PaymentIntent, Receipt } from '@reinconsole/core';\n\n/** Base class for everything the SDK throws, so callers can catch broadly. */\nexport class ReinError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\n/** The policy engine answered with a non-2xx status. */\nexport class EngineError extends ReinError {\n constructor(\n readonly status: number,\n readonly body: unknown,\n message = `policy engine responded ${status}`,\n ) {\n super(message);\n }\n}\n\n/**\n * The engine evaluated the intent and did NOT allow it (deny or escalate —\n * v0.1 blocks both; escalation approval flows land later). The payment was\n * never constructed, so no funds moved. Carries the full evidence trail.\n */\nexport class PaymentBlockedError extends ReinError {\n constructor(\n readonly intent: PaymentIntent,\n readonly decision: Decision,\n readonly receipt: Receipt,\n ) {\n super(\n `rein blocked payment of ${intent.amount} ${intent.asset} to ${intent.vendor.host}: ` +\n `${decision.outcome}${decision.reason ? ` (${decision.reason})` : ''}`,\n );\n }\n}\n\n/**\n * The vendor's 402 was x402-shaped but offered no requirement the guard can\n * govern (unknown scheme/network/asset). The guard fails closed rather than\n * letting an ungoverned payment through.\n */\nexport class UnsupportedRequirementError extends ReinError {\n constructor(readonly url: string) {\n super(`no supported x402 payment requirement in 402 from ${url}; failing closed`);\n }\n}\n","import { z } from 'zod';\nimport { Agent, Decision, PaymentIntent, Policy } from '@reinconsole/core';\nimport { EngineError } from './errors.js';\nimport type { IntentSubmission } from './x402.js';\n\n/** Any fetch-compatible function (global fetch, undici, or a test double). */\nexport type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;\n\nconst Health = z.object({ status: z.string(), publicKey: z.string() });\nconst EvaluateResponse = z.object({ intent: PaymentIntent, decision: Decision });\nexport type EvaluateResponse = z.infer<typeof EvaluateResponse>;\n\nexport interface EngineClientOptions {\n /** Base URL of the policy engine, e.g. \"http://localhost:8787\". */\n baseUrl: string;\n /** Override the transport (tests, custom agents). Defaults to global fetch. */\n fetch?: FetchLike;\n}\n\n/**\n * Thin typed client for the policy-engine HTTP API. Every response is parsed\n * through the @reinconsole/core schemas, so wire drift fails loudly at the boundary.\n */\nexport class EngineClient {\n private readonly baseUrl: string;\n private readonly fetchImpl: FetchLike;\n\n constructor(options: EngineClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '');\n const f = options.fetch ?? globalThis.fetch;\n this.fetchImpl = (input, init) => f(input, init);\n }\n\n private async request<T>(\n method: string,\n path: string,\n schema: z.ZodType<T, z.ZodTypeDef, unknown>,\n body?: unknown,\n ): Promise<T> {\n const res = await this.fetchImpl(`${this.baseUrl}${path}`, {\n method,\n headers: body === undefined ? undefined : { 'content-type': 'application/json' },\n body: body === undefined ? undefined : JSON.stringify(body),\n });\n if (!res.ok) {\n const payload = await res\n .clone()\n .json()\n .catch(() => res.text().catch(() => undefined));\n throw new EngineError(res.status, payload);\n }\n if (res.status === 204) return schema.parse(undefined);\n return schema.parse(await res.json());\n }\n\n health(): Promise<z.infer<typeof Health>> {\n return this.request('GET', '/health', Health);\n }\n\n registerAgent(input: {\n orgId: string;\n name: string;\n erc8004Id?: string;\n wallets?: Agent['wallets'];\n }): Promise<Agent> {\n return this.request('POST', '/v1/agents', Agent, input);\n }\n\n listAgents(): Promise<Agent[]> {\n return this.request('GET', '/v1/agents', z.array(Agent));\n }\n\n freeze(agentId: string): Promise<void> {\n return this.request('POST', `/v1/agents/${agentId}/freeze`, z.void());\n }\n\n unfreeze(agentId: string): Promise<void> {\n return this.request('POST', `/v1/agents/${agentId}/unfreeze`, z.void());\n }\n\n addPolicy(policy: z.input<typeof Policy>): Promise<Policy> {\n return this.request('POST', '/v1/policies', Policy, policy);\n }\n\n listPolicies(): Promise<Policy[]> {\n return this.request('GET', '/v1/policies', z.array(Policy));\n }\n\n /** The hot path: submit an intent, get the normalized intent + signed decision. */\n evaluate(submission: IntentSubmission): Promise<EvaluateResponse> {\n return this.request('POST', '/v1/evaluate', EvaluateResponse, submission);\n }\n\n decisions(): Promise<Decision[]> {\n return this.request('GET', '/v1/decisions', z.array(Decision));\n }\n}\n","import { z } from 'zod';\nimport { Chain, Asset, type TaskContext, type Vendor } from '@reinconsole/core';\n\n/**\n * x402 wire shapes (spec v1), mock-first: these schemas are what Rein's mock\n * facilitator and tests speak today, and they track the published x402 spec so\n * real vendors parse identically when the live integration lands.\n */\n\n/** One way to pay, as offered inside a 402 response body. */\nexport const PaymentRequirement = z.object({\n scheme: z.string(),\n network: z.string(),\n /** Amount in the asset's atomic units (e.g. \"10000\" = 0.01 USDC at 6 decimals). */\n maxAmountRequired: z.string().regex(/^\\d+$/, 'atomic amount must be an integer string'),\n resource: z.string().optional(),\n description: z.string().optional(),\n mimeType: z.string().optional(),\n payTo: z.string().min(1),\n maxTimeoutSeconds: z.number().optional(),\n /** Token contract address — or, mock-first, a plain symbol like \"USDC\". */\n asset: z.string().min(1),\n extra: z.record(z.unknown()).optional(),\n});\nexport type PaymentRequirement = z.infer<typeof PaymentRequirement>;\n\n/** The full 402 body a paywalled vendor returns. */\nexport const PaymentRequired = z.object({\n x402Version: z.number(),\n accepts: z.array(PaymentRequirement).min(1),\n error: z.string().optional(),\n});\nexport type PaymentRequired = z.infer<typeof PaymentRequired>;\n\n/**\n * x402 network ids → the chains Rein governs. Testnets map to their mainnet.\n * Both v1 names (\"base-sepolia\") and v2 CAIP-2 ids (\"eip155:84532\") appear in\n * the wild, so the guard accepts either.\n */\nconst NETWORK_TO_CHAIN: Record<string, Chain> = {\n base: 'base',\n 'base-sepolia': 'base',\n 'eip155:8453': 'base',\n 'eip155:84532': 'base',\n solana: 'solana',\n 'solana-devnet': 'solana',\n polygon: 'polygon',\n 'polygon-amoy': 'polygon',\n bnb: 'bnb',\n bsc: 'bnb',\n};\n\n/** Canonical stablecoin contract addresses (EVM keys lowercased). */\nconst KNOWN_ASSET_ADDRESSES: Record<string, Asset> = {\n '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913': 'USDC', // USDC on Base\n '0x036cbd53842c5426634e7929541ec2318f3dcf7e': 'USDC', // USDC on Base Sepolia\n EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v: 'USDC', // USDC on Solana\n};\n\nexport function networkToChain(network: string): Chain | undefined {\n return NETWORK_TO_CHAIN[network.toLowerCase()];\n}\n\n/**\n * Resolve a requirement's asset to a symbol Rein knows. Tries, in order: the\n * asset field as a literal symbol (mock-first), `extra.symbol`, then known\n * contract addresses (exact case for Solana, lowercased for EVM), then any\n * caller-supplied address map.\n */\nexport function resolveAsset(\n requirement: PaymentRequirement,\n extraAddresses: Record<string, Asset> = {},\n): Asset | undefined {\n const direct = Asset.safeParse(requirement.asset.toUpperCase());\n if (direct.success) return direct.data;\n\n const symbol = requirement.extra?.['symbol'];\n if (typeof symbol === 'string') {\n const fromExtra = Asset.safeParse(symbol.toUpperCase());\n if (fromExtra.success) return fromExtra.data;\n }\n\n return (\n extraAddresses[requirement.asset] ??\n extraAddresses[requirement.asset.toLowerCase()] ??\n KNOWN_ASSET_ADDRESSES[requirement.asset] ??\n KNOWN_ASSET_ADDRESSES[requirement.asset.toLowerCase()]\n );\n}\n\n/**\n * Convert an atomic-unit amount to a normalized decimal string without floats,\n * e.g. (\"10000\", 6) -> \"0.01\". Stablecoins Rein supports all use 6 decimals;\n * a requirement can override via `extra.decimals`.\n */\nexport function atomicToDecimal(atomic: string, decimals: number): string {\n if (!/^\\d+$/.test(atomic)) throw new TypeError(`invalid atomic amount: ${atomic}`);\n if (decimals === 0) return atomic.replace(/^0+(?=\\d)/, '');\n const digits = atomic.padStart(decimals + 1, '0');\n const intPart = digits.slice(0, digits.length - decimals).replace(/^0+(?=\\d)/, '');\n const fracPart = digits.slice(digits.length - decimals).replace(/0+$/, '');\n return fracPart.length > 0 ? `${intPart}.${fracPart}` : intPart;\n}\n\n/**\n * The inverse of {@link atomicToDecimal}: a human-unit decimal string to atomic\n * units without floats, e.g. (\"0.05\", 6) -> \"50000\". Throws if the value has\n * more fraction digits than the asset carries (sub-atomic precision is a\n * pricing bug, not something to round silently).\n */\nexport function decimalToAtomic(decimal: string, decimals: number): string {\n if (!/^\\d+(\\.\\d+)?$/.test(decimal)) throw new TypeError(`invalid decimal amount: ${decimal}`);\n const dot = decimal.indexOf('.');\n const intPart = dot === -1 ? decimal : decimal.slice(0, dot);\n const fracPart = dot === -1 ? '' : decimal.slice(dot + 1);\n if (fracPart.length > decimals) {\n throw new TypeError(`amount ${decimal} has more than ${decimals} fraction digits`);\n }\n const atomic = intPart + fracPart.padEnd(decimals, '0');\n return atomic.replace(/^0+(?=\\d)/, '');\n}\n\nexport function requirementDecimals(requirement: PaymentRequirement): number {\n const decimals = requirement.extra?.['decimals'];\n return typeof decimals === 'number' && Number.isInteger(decimals) && decimals >= 0 ? decimals : 6;\n}\n\n/** A requirement the guard fully understood, mapped into Rein's domain. */\nexport interface ResolvedRequirement {\n requirement: PaymentRequirement;\n chain: Chain;\n asset: Asset;\n /** Human-unit decimal amount, e.g. \"0.01\". */\n amount: string;\n}\n\n/**\n * Pick the first offer the guard can govern: scheme `exact`, a network that\n * maps to a supported chain, and a resolvable asset. Returns undefined when\n * no offer qualifies — callers must treat that as fail-closed.\n */\nexport function selectRequirement(\n accepts: readonly PaymentRequirement[],\n extraAddresses: Record<string, Asset> = {},\n): ResolvedRequirement | undefined {\n for (const requirement of accepts) {\n if (requirement.scheme.toLowerCase() !== 'exact') continue;\n const chain = networkToChain(requirement.network);\n if (!chain) continue;\n const asset = resolveAsset(requirement, extraAddresses);\n if (!asset) continue;\n const amount = atomicToDecimal(requirement.maxAmountRequired, requirementDecimals(requirement));\n return { requirement, chain, asset, amount };\n }\n return undefined;\n}\n\n/** What the guard submits to the policy engine (the `/v1/evaluate` shape). */\nexport interface IntentSubmission {\n agentId: string;\n vendor: Vendor;\n resource: string;\n amount: string;\n asset: Asset;\n chain: Chain;\n taskContext?: TaskContext;\n}\n\n/** Build the evaluate payload for a resolved offer on a given request URL. */\nexport function toIntentSubmission(\n resolved: ResolvedRequirement,\n url: string,\n agentId: string,\n taskContext: TaskContext | undefined,\n): IntentSubmission {\n const parsed = new URL(url);\n return {\n agentId,\n vendor: {\n host: parsed.host,\n address: resolved.requirement.payTo,\n },\n resource: resolved.requirement.resource ?? parsed.pathname,\n amount: resolved.amount,\n asset: resolved.asset,\n chain: resolved.chain,\n taskContext,\n };\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n AgentId,\n Receipt,\n newId,\n type Asset,\n type Decision,\n type PaymentIntent,\n type ReceiptSettlement,\n type TaskContext,\n} from '@reinconsole/core';\nimport { EngineClient, type FetchLike } from './client.js';\nimport { PaymentBlockedError, UnsupportedRequirementError } from './errors.js';\nimport {\n PaymentRequired,\n selectRequirement,\n toIntentSubmission,\n type PaymentRequirement,\n} from './x402.js';\n\n/**\n * Builds the `X-PAYMENT` header for an allowed intent. Mock payers and the\n * local EIP-3009 payer ignore the decision; the session-key signer tier\n * requires it — the {intent, decision} pair is the engine-signed voucher the\n * signer verifies before any key is put to work.\n */\nexport type Payer = (\n requirement: PaymentRequirement,\n intent: PaymentIntent,\n decision: Decision,\n) => string | Promise<string>;\n\nexport interface GuardOptions {\n /** Policy engine base URL, e.g. \"http://localhost:8787\". */\n engineUrl: string;\n /** The agent this guard speaks for (must be registered with the engine). */\n agentId: string;\n /** Base fetch the guard wraps by default (vendor-facing). Defaults to global fetch. */\n fetch?: FetchLike;\n /** Transport for talking to the policy engine. Defaults to global fetch. */\n engineFetch?: FetchLike;\n /** Task context attached to every intent unless overridden via withTask(). */\n taskContext?: TaskContext;\n /**\n * What a blocked payment looks like to the caller: 'throw' (default) raises\n * PaymentBlockedError; 'respond' returns a synthetic 402 JSON response, for\n * agent loops that prefer inspecting responses over catching.\n */\n onBlocked?: 'throw' | 'respond';\n /** If set, the guard settles allowed payments itself (pay + retry). */\n payer?: Payer;\n /** Extra token-address -> symbol mappings for asset resolution. */\n assetAddresses?: Record<string, Asset>;\n /** Called once per receipt, as it is recorded. */\n onReceipt?: (receipt: Receipt) => void;\n}\n\n/**\n * The Rein guard: wrap an agent's fetch once, and every x402 paywall it hits\n * is policy-checked before any payment exists, with a receipt either way.\n *\n * Layering: the guard wraps the BASE fetch, underneath any x402 payment\n * library. The first (unpaid) request surfaces the 402; the guard evaluates\n * it and either blocks — so the payment layer never sees the paywall — or\n * releases the 402 upward. The payment layer's `X-PAYMENT` retry then flows\n * back through the guard, which attaches the settlement to the receipt.\n * Alternatively, pass a `payer` and the guard completes the payment itself.\n */\nexport class Guard {\n readonly client: EngineClient;\n private readonly options: GuardOptions;\n private readonly baseFetch: FetchLike;\n private readonly task = new AsyncLocalStorage<TaskContext>();\n private readonly log: Receipt[] = [];\n /** Allowed-but-unsettled receipts awaiting the payment layer's retry, by URL. */\n private readonly pendingByUrl = new Map<string, Receipt>();\n\n constructor(options: GuardOptions) {\n AgentId.parse(options.agentId);\n this.options = options;\n const f = options.fetch ?? globalThis.fetch;\n this.baseFetch = (input, init) => f(input, init);\n this.client = new EngineClient({ baseUrl: options.engineUrl, fetch: options.engineFetch });\n }\n\n /** Every receipt this guard has recorded, oldest first. */\n receipts(): readonly Receipt[] {\n return this.log;\n }\n\n /** Run `fn` with a task context attached to every intent submitted inside it. */\n withTask<T>(context: TaskContext, fn: () => T): T {\n return this.task.run({ ...this.options.taskContext, ...context }, fn);\n }\n\n /**\n * The one-liner: returns a fetch-compatible function that enforces policy on\n * every x402 paywall. Wraps the guard's base fetch unless one is passed.\n */\n wrap(fetchImpl?: FetchLike): FetchLike {\n const inner: FetchLike = fetchImpl ? (input, init) => fetchImpl(input, init) : this.baseFetch;\n\n return async (input, init) => {\n const url = requestUrl(input);\n // A request that already carries a payment is the release leg of an\n // intent this guard allowed — pass it through and capture settlement.\n if (readHeader(input, init, 'X-PAYMENT') !== null) {\n const res = await inner(input, init);\n this.settlePending(url, res);\n return res;\n }\n\n const res = await inner(input, init);\n if (res.status !== 402) return res;\n\n const body = await res\n .clone()\n .json()\n .catch(() => undefined);\n const parsed = PaymentRequired.safeParse(body);\n // Not an x402 paywall — nothing to govern, hand it back untouched.\n if (!parsed.success) return res;\n\n const resolved = selectRequirement(parsed.data.accepts, this.options.assetAddresses);\n if (!resolved) throw new UnsupportedRequirementError(url);\n\n const taskContext = this.task.getStore() ?? this.options.taskContext;\n const submission = toIntentSubmission(resolved, url, this.options.agentId, taskContext);\n const { intent, decision } = await this.client.evaluate(submission);\n\n if (decision.outcome !== 'allow') {\n const receipt = this.record(intent, decision, url, init);\n if (this.options.onBlocked === 'respond') return blockedResponse(receipt);\n throw new PaymentBlockedError(intent, decision, receipt);\n }\n\n if (!this.options.payer) {\n // Advisory mode: release the 402 to the payment layer above us; its\n // X-PAYMENT retry will come back through and settle the receipt.\n const receipt = this.record(intent, decision, url, init);\n this.pendingByUrl.set(url, receipt);\n return res;\n }\n\n const paymentHeader = await this.options.payer(resolved.requirement, intent, decision);\n const retry = await inner(input, withHeader(input, init, 'X-PAYMENT', paymentHeader));\n this.record(intent, decision, url, init, parseSettlement(retry));\n return retry;\n };\n }\n\n private record(\n intent: PaymentIntent,\n decision: Decision,\n url: string,\n init: RequestInit | undefined,\n settlement?: ReceiptSettlement,\n ): Receipt {\n const receipt = Receipt.parse({\n id: newId('rcp'),\n agentId: intent.agentId,\n intentId: intent.id,\n decisionId: decision.id,\n outcome: decision.outcome,\n url,\n method: init?.method ?? 'GET',\n vendorHost: intent.vendor.host,\n amount: intent.amount,\n asset: intent.asset,\n chain: intent.chain,\n taskContext: intent.taskContext,\n reason: decision.reason,\n settlement,\n createdAt: new Date(),\n });\n this.log.push(receipt);\n this.options.onReceipt?.(receipt);\n return receipt;\n }\n\n private settlePending(url: string, res: Response): void {\n const receipt = this.pendingByUrl.get(url);\n if (!receipt || !res.ok) return;\n const settlement = parseSettlement(res);\n if (settlement) receipt.settlement = settlement;\n this.pendingByUrl.delete(url);\n }\n}\n\n/** Convenience factory mirroring the docs: `const guard = createGuard({...})`. */\nexport function createGuard(options: GuardOptions): Guard {\n return new Guard(options);\n}\n\nfunction requestUrl(input: string | URL | Request): string {\n if (typeof input === 'string') return input;\n if (input instanceof URL) return input.toString();\n return input.url;\n}\n\nfunction readHeader(\n input: string | URL | Request,\n init: RequestInit | undefined,\n name: string,\n): string | null {\n const source = init?.headers ?? (input instanceof Request ? input.headers : undefined);\n return source === undefined ? null : new Headers(source).get(name);\n}\n\nfunction withHeader(\n input: string | URL | Request,\n init: RequestInit | undefined,\n name: string,\n value: string,\n): RequestInit {\n const headers = new Headers(\n init?.headers ?? (input instanceof Request ? input.headers : undefined),\n );\n headers.set(name, value);\n return { ...init, headers };\n}\n\n/**\n * Decode the vendor's `X-PAYMENT-RESPONSE` header (base64 JSON per the x402\n * spec; plain JSON tolerated mock-first). Absent or undecodable -> undefined.\n */\nfunction parseSettlement(res: Response): ReceiptSettlement | undefined {\n const raw = res.headers.get('X-PAYMENT-RESPONSE');\n if (raw === null) return undefined;\n let payload: unknown;\n try {\n payload = JSON.parse(raw);\n } catch {\n try {\n payload = JSON.parse(Buffer.from(raw, 'base64').toString('utf8'));\n } catch {\n return { raw };\n }\n }\n const record =\n typeof payload === 'object' && payload !== null ? (payload as Record<string, unknown>) : {};\n return {\n txHash: typeof record['transaction'] === 'string' ? record['transaction'] : undefined,\n networkId: typeof record['network'] === 'string' ? record['network'] : undefined,\n raw,\n };\n}\n\nfunction blockedResponse(receipt: Receipt): Response {\n return new Response(\n JSON.stringify({\n error: 'payment_blocked_by_rein',\n outcome: receipt.outcome,\n reason: receipt.reason,\n intentId: receipt.intentId,\n decisionId: receipt.decisionId,\n receiptId: receipt.id,\n }),\n {\n status: 402,\n headers: { 'content-type': 'application/json', 'x-rein-outcome': receipt.outcome },\n },\n );\n}\n","import {\n createPublicClient,\n erc20Abi,\n http,\n type Address,\n type Hex,\n type HttpTransport,\n type PublicClient,\n} from 'viem';\nimport { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';\nimport { baseSepolia } from 'viem/chains';\n\n/** USDC (FiatTokenV2) on Base Sepolia. */\nexport const BASE_SEPOLIA_USDC: Address = '0x036CbD53842c5426634e7929541eC2318f3dCF7e';\n\n/** Circle's testnet faucet — funds Base Sepolia USDC for free. */\nexport const CIRCLE_FAUCET_URL = 'https://faucet.circle.com';\n\nexport const basescanTxUrl = (txHash: string): string =>\n `https://sepolia.basescan.org/tx/${txHash}`;\n\nexport interface GeneratedWallet {\n privateKey: Hex;\n address: Address;\n}\n\n/** A fresh local account — fund it with faucet USDC; it never needs ETH. */\nexport function generateWallet(): GeneratedWallet {\n const privateKey = generatePrivateKey();\n return { privateKey, address: privateKeyToAccount(privateKey).address };\n}\n\nexport type BaseSepoliaClient = PublicClient<HttpTransport, typeof baseSepolia>;\n\nexport function createBaseSepoliaClient(rpcUrl?: string): BaseSepoliaClient {\n return createPublicClient({ chain: baseSepolia, transport: http(rpcUrl) });\n}\n\n/** Atomic-unit USDC balance (6 decimals). */\nexport async function getUsdcBalance(\n client: BaseSepoliaClient,\n address: Address,\n usdc: Address = BASE_SEPOLIA_USDC,\n): Promise<bigint> {\n return client.readContract({\n address: usdc,\n abi: erc20Abi,\n functionName: 'balanceOf',\n args: [address],\n });\n}\n","import { PaymentRequirement, type FetchLike } from '@reinconsole/sdk';\nimport { RailsError } from './errors.js';\nimport type { FacilitatorClient } from './facilitator.js';\nimport { BASE_SEPOLIA_USDC } from './wallet.js';\nimport { decodePaymentHeader, encodeSettlementHeader } from './wire.js';\n\nexport interface RealVendorOptions {\n facilitator: FacilitatorClient;\n /** Price in atomic units (e.g. \"10000\" = 0.01 USDC at 6 decimals). */\n atomicPrice: string;\n /** Where the vendor wants to be paid (a real EVM address). */\n payTo: string;\n network?: string;\n /** Token contract address. Defaults to USDC on Base Sepolia. */\n asset?: string;\n description?: string;\n maxTimeoutSeconds?: number;\n /** EIP-712 domain hints for the payer. Defaults to Base Sepolia USDC's. */\n extra?: Record<string, unknown>;\n /** JSON body served once payment settles. */\n body?: unknown;\n}\n\nexport interface VendorCall {\n url: string;\n payment: string | null;\n}\n\nexport interface RealVendor {\n /** Drop-in fetch for the guard's vendor-facing side. */\n fetch: FetchLike;\n /** Every request the vendor saw, in order. */\n calls: VendorCall[];\n /** The payment requirement this vendor quotes for a given URL. */\n requirementFor(url: string): PaymentRequirement;\n}\n\n/**\n * An in-process x402 vendor wired to a REAL facilitator: quotes a 402 with\n * payment requirements until the request carries X-PAYMENT, then verifies and\n * settles through the facilitator — a real on-chain USDC transfer — and serves\n * the content with the settlement (tx hash included) in X-PAYMENT-RESPONSE.\n *\n * Unlike the mock vendor, the quoted requirement is fully populated: the\n * hosted facilitator validates it strictly (resource must be a URL,\n * description/mimeType/maxTimeoutSeconds required, real addresses).\n */\nexport function createRealVendor(options: RealVendorOptions): RealVendor {\n const calls: VendorCall[] = [];\n\n const requirementFor = (url: string): PaymentRequirement =>\n PaymentRequirement.parse({\n scheme: 'exact',\n network: options.network ?? 'base-sepolia',\n maxAmountRequired: options.atomicPrice,\n resource: url,\n description: options.description ?? '',\n mimeType: 'application/json',\n payTo: options.payTo,\n maxTimeoutSeconds: options.maxTimeoutSeconds ?? 300,\n asset: options.asset ?? BASE_SEPOLIA_USDC,\n extra: options.extra ?? { name: 'USDC', version: '2' },\n });\n\n const paymentRequired = (url: string, error: string): Response =>\n new Response(JSON.stringify({ x402Version: 1, accepts: [requirementFor(url)], error }), {\n status: 402,\n headers: { 'content-type': 'application/json' },\n });\n\n const fetch: FetchLike = async (input, init) => {\n const url =\n typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url;\n const headers = new Headers(\n init?.headers ?? (input instanceof Request ? input.headers : undefined),\n );\n const payment = headers.get('X-PAYMENT');\n calls.push({ url, payment });\n\n if (payment === null) return paymentRequired(url, 'X-PAYMENT header is required');\n\n const requirement = requirementFor(url);\n let payload;\n try {\n payload = decodePaymentHeader(payment);\n } catch (err) {\n if (err instanceof RailsError) return paymentRequired(url, err.message);\n throw err;\n }\n\n const verified = await options.facilitator.verify(payload, requirement);\n if (!verified.isValid) {\n return paymentRequired(url, verified.invalidReason ?? 'payment verification failed');\n }\n\n const settled = await options.facilitator.settle(payload, requirement);\n if (!settled.success) {\n return paymentRequired(url, settled.errorReason ?? 'payment settlement failed');\n }\n\n return new Response(JSON.stringify(options.body ?? { ok: true }), {\n status: 200,\n headers: {\n 'content-type': 'application/json',\n 'X-PAYMENT-RESPONSE': encodeSettlementHeader(settled),\n },\n });\n };\n\n return { fetch, calls, requirementFor };\n}\n","import { EventEmitter } from 'node:events';\nimport { parseAbi, type Address, type Hex } from 'viem';\nimport { ReinEvent, type Agent, type Chain, type PaymentIntent } from '@reinconsole/core';\nimport { atomicToDecimal } from '@reinconsole/sdk';\nimport { intentNonce } from './nonce.js';\nimport { BASE_SEPOLIA_USDC } from './wallet.js';\n\n/** The slice of the policy engine the indexer subscribes to (NATS in prod). */\nexport interface EngineEvents {\n onEvent(handler: (event: ReinEvent) => void): void;\n}\n\n/** The two FiatTokenV2 events one transferWithAuthorization settlement emits. */\nexport const railEventsAbi = parseAbi([\n 'event Transfer(address indexed from, address indexed to, uint256 value)',\n 'event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce)',\n]);\n\n/** The decoded log shape the indexer consumes. */\nexport interface RailLog {\n eventName: 'Transfer' | 'AuthorizationUsed';\n transactionHash: Hex | null;\n blockNumber: bigint | null;\n args: {\n from?: Address;\n to?: Address;\n value?: bigint;\n authorizer?: Address;\n nonce?: Hex;\n };\n}\n\n/**\n * What the indexer needs from a chain: current head + decoded event logs.\n * viem's PublicClient satisfies this structurally; tests inject a fake.\n */\nexport interface ChainReader {\n getBlockNumber(): Promise<bigint>;\n getLogs(args: {\n address: Address;\n events: typeof railEventsAbi;\n fromBlock: bigint;\n toBlock: bigint;\n }): Promise<readonly RailLog[]>;\n}\n\nexport interface OnchainIndexerOptions {\n client: ChainReader;\n /** Token contract whose transfers are watched. Defaults to Base Sepolia USDC. */\n usdcAddress?: Address;\n /** The Rein chain tag recorded on events (testnets map to mainnet). */\n chain?: Chain;\n /**\n * Directory of managed agents and their wallets (the agents service in\n * prod). Called per transfer, so agents registered later are still seen.\n */\n agents: () => readonly Agent[];\n /** Recorded as SettledPayment.facilitator on reconciled payments. */\n facilitator?: string;\n pollIntervalMs?: number;\n /** First block to scan. Defaults to the chain head at start(). */\n fromBlock?: bigint;\n /** Token decimals for amount conversion. */\n decimals?: number;\n /** RPC errors are retried next tick; surface them here if you care. */\n onError?: (err: unknown) => void;\n}\n\n/** A `shadow.spend` event, extracted for convenience accessors. */\nexport type ShadowSpend = Extract<ReinEvent, { type: 'shadow.spend' }>;\n\n/**\n * The real indexer: polls token logs on Base Sepolia and classifies every\n * transfer that leaves a managed agent wallet — the same semantics as the\n * mock indexer, against a real chain.\n *\n * Reconciliation is memo-first via the EIP-3009 nonce: Rein's payer derives\n * the authorization nonce from the intent id, and settlement emits\n * `AuthorizationUsed(authorizer, nonce)` alongside the `Transfer`. A transfer\n * whose nonce resolves to an allowed, unsettled intent of the same agent is\n * `payment.settled`; anything else leaving a managed wallet — random nonce,\n * replay, plain transfer, no ALLOW behind it — is `shadow.spend`. There is no\n * fuzzy fallback on-chain: the nonce IS the memo.\n */\nexport class OnchainIndexer {\n private readonly options: OnchainIndexerOptions;\n private readonly bus = new EventEmitter();\n private readonly emitted: ReinEvent[] = [];\n /** Every intent the engine has seen, by id (from `intent.created`). */\n private readonly intents = new Map<string, PaymentIntent>();\n /** Intents with an ALLOW decision, by id. */\n private readonly allowed = new Map<string, PaymentIntent>();\n private readonly settledIntents = new Set<string>();\n /** Expected on-chain nonce -> intent id, for every allowed intent. */\n private readonly nonceToIntent = new Map<string, string>();\n private timer: NodeJS.Timeout | undefined;\n private nextBlock: bigint | undefined;\n private scanning = false;\n\n constructor(options: OnchainIndexerOptions) {\n this.options = options;\n }\n\n /** Subscribe to a policy engine's event stream to learn which intents were allowed. */\n connectEngine(engine: EngineEvents): void {\n engine.onEvent((event) => {\n if (event.type === 'intent.created') {\n this.intents.set(event.intent.id, event.intent);\n } else if (event.type === 'decision.made' && event.decision.outcome === 'allow') {\n const intent = this.intents.get(event.decision.intentId);\n if (intent) {\n this.allowed.set(intent.id, intent);\n this.nonceToIntent.set(intentNonce(intent.id).toLowerCase(), intent.id);\n }\n }\n });\n }\n\n /** Begin polling. Scans from `fromBlock` (default: the current head). */\n async start(): Promise<void> {\n if (this.timer !== undefined) return;\n this.nextBlock = this.options.fromBlock ?? (await this.options.client.getBlockNumber()) + 1n;\n const interval = this.options.pollIntervalMs ?? 3000;\n this.timer = setInterval(() => void this.scan(), interval);\n this.timer.unref?.();\n }\n\n stop(): void {\n if (this.timer !== undefined) clearInterval(this.timer);\n this.timer = undefined;\n }\n\n onEvent(handler: (event: ReinEvent) => void): void {\n this.bus.on('event', handler);\n }\n\n /** Everything the indexer has emitted, oldest first. */\n events(): readonly ReinEvent[] {\n return this.emitted;\n }\n\n settledPayments() {\n return this.emitted.flatMap((e) => (e.type === 'payment.settled' ? [e.payment] : []));\n }\n\n shadowSpends(): ShadowSpend[] {\n return this.emitted.filter((e): e is ShadowSpend => e.type === 'shadow.spend');\n }\n\n /** Resolve when an event (past or future) matches; reject on timeout. */\n waitFor(predicate: (event: ReinEvent) => boolean, timeoutMs = 90_000): Promise<ReinEvent> {\n const existing = this.emitted.find(predicate);\n if (existing) return Promise.resolve(existing);\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.bus.off('event', handler);\n reject(new Error(`indexer: no matching event within ${timeoutMs}ms`));\n }, timeoutMs);\n const handler = (event: ReinEvent) => {\n if (!predicate(event)) return;\n clearTimeout(timeout);\n this.bus.off('event', handler);\n resolve(event);\n };\n this.bus.on('event', handler);\n });\n }\n\n /** One poll: fetch logs since the last scanned block and classify them. */\n async scan(): Promise<void> {\n if (this.scanning || this.nextBlock === undefined) return;\n this.scanning = true;\n try {\n const head = await this.options.client.getBlockNumber();\n if (head < this.nextBlock) return;\n const logs = await this.options.client.getLogs({\n address: this.options.usdcAddress ?? BASE_SEPOLIA_USDC,\n events: railEventsAbi,\n fromBlock: this.nextBlock,\n toBlock: head,\n });\n for (const tx of groupByTx(logs)) this.observe(tx);\n // Only advance once the whole range processed — an RPC error above\n // leaves the range to be retried on the next tick.\n this.nextBlock = head + 1n;\n } catch (err) {\n this.options.onError?.(err);\n } finally {\n this.scanning = false;\n }\n }\n\n private emit(event: ReinEvent): void {\n const parsed = ReinEvent.parse(event);\n this.emitted.push(parsed);\n this.bus.emit('event', parsed);\n }\n\n private agentFor(from: string): string | undefined {\n const chain = this.options.chain ?? 'base';\n for (const agent of this.options.agents()) {\n const owns = agent.wallets.some((w) => w.chain === chain && sameAddress(w.address, from));\n if (owns) return agent.id;\n }\n return undefined;\n }\n\n private observe(tx: TxLogs): void {\n for (const transfer of tx.transfers) {\n const from = transfer.args.from;\n if (from === undefined || transfer.args.value === undefined) continue;\n const agentId = this.agentFor(from);\n // Spend from a wallet Rein does not manage is someone else's problem.\n if (agentId === undefined) continue;\n\n const intent = this.reconcile(tx, from, agentId);\n const at = new Date();\n if (intent) {\n this.settledIntents.add(intent.id);\n this.emit({\n type: 'payment.settled',\n at,\n payment: {\n intentId: intent.id,\n txHash: tx.txHash,\n chain: this.options.chain ?? 'base',\n blockNumber: transfer.blockNumber ?? 0n,\n facilitator: this.options.facilitator,\n confirmedAt: at,\n },\n });\n continue;\n }\n\n this.emit({\n type: 'shadow.spend',\n at,\n agentId,\n txHash: tx.txHash,\n chain: this.options.chain ?? 'base',\n amount: atomicToDecimal(transfer.args.value.toString(), this.options.decimals ?? 6),\n });\n }\n }\n\n private reconcile(tx: TxLogs, from: string, agentId: string): PaymentIntent | undefined {\n for (const auth of tx.authorizations) {\n const { authorizer, nonce } = auth.args;\n if (authorizer === undefined || nonce === undefined) continue;\n if (!sameAddress(authorizer, from)) continue;\n const intentId = this.nonceToIntent.get(nonce.toLowerCase());\n if (intentId === undefined) continue;\n const intent = this.allowed.get(intentId);\n if (intent && intent.agentId === agentId && !this.settledIntents.has(intent.id)) {\n return intent;\n }\n }\n return undefined;\n }\n}\n\ninterface TxLogs {\n txHash: string;\n transfers: RailLog[];\n authorizations: RailLog[];\n}\n\nfunction groupByTx(logs: readonly RailLog[]): TxLogs[] {\n const byTx = new Map<string, TxLogs>();\n for (const log of logs) {\n if (log.transactionHash === null) continue;\n let tx = byTx.get(log.transactionHash);\n if (!tx) {\n tx = { txHash: log.transactionHash, transfers: [], authorizations: [] };\n byTx.set(log.transactionHash, tx);\n }\n (log.eventName === 'Transfer' ? tx.transfers : tx.authorizations).push(log);\n }\n return [...byTx.values()];\n}\n\n/** EVM addresses compare case-insensitively. */\nfunction sameAddress(a: string, b: string): boolean {\n return a === b || a.toLowerCase() === b.toLowerCase();\n}\n"],"mappings":"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","names":["z","z","z","z","z","z","privateKeyToAccount"]}
1
+ {"version":3,"sources":["../src/wire.ts","../src/errors.ts","../src/nonce.ts","../src/networks.ts","../src/payer.ts","../src/facilitator.ts","../../../packages/core/src/chain.ts","../../../packages/core/src/money.ts","../../../packages/core/src/glob.ts","../../../packages/core/src/ulid.ts","../../../packages/core/src/ids.ts","../../../packages/core/src/agent.ts","../../../packages/core/src/erc8004.ts","../../../packages/core/src/intent.ts","../../../packages/core/src/decision.ts","../../../packages/core/src/canonical.ts","../../../packages/core/src/session.ts","../../../packages/core/src/payment.ts","../../../packages/core/src/receipt.ts","../../../packages/core/src/gate-receipt.ts","../../../packages/core/src/policy.ts","../../../packages/core/src/reputation.ts","../../../packages/core/src/events.ts","../../../packages/sdk/src/errors.ts","../../../packages/sdk/src/client.ts","../../../packages/sdk/src/x402.ts","../../../packages/sdk/src/x402v2.ts","../../../packages/sdk/src/guard.ts","../src/wallet.ts","../src/vendor.ts","../src/indexer.ts"],"sourcesContent":["import { z } from 'zod';\nimport { RailsError } from './errors.js';\n\n/**\n * Wire codecs for the real x402 v1 exact-EVM scheme: the `X-PAYMENT` header\n * the payer signs (EIP-3009 authorization + signature), the facilitator's\n * verify/settle responses, and the `X-PAYMENT-RESPONSE` header the vendor\n * returns. Verified against the published v1 spec and the hosted facilitator\n * at x402.org (2026-06).\n */\n\nconst Hex = z.string().regex(/^0x[0-9a-fA-F]*$/, 'must be 0x-prefixed hex');\nconst EvmAddress = z.string().regex(/^0x[0-9a-fA-F]{40}$/, 'must be a 20-byte EVM address');\nconst UintString = z.string().regex(/^\\d+$/, 'must be a decimal integer string');\n\n/** The EIP-3009 TransferWithAuthorization message, decimal-stringified. */\nexport const ExactEvmAuthorization = z.object({\n from: EvmAddress,\n to: EvmAddress,\n /** Atomic-unit amount, mirroring the requirement's maxAmountRequired. */\n value: UintString,\n validAfter: UintString,\n validBefore: UintString,\n /** bytes32 — Rein derives it from the intent id (see nonce.ts). */\n nonce: z.string().regex(/^0x[0-9a-fA-F]{64}$/, 'nonce must be bytes32 hex'),\n});\nexport type ExactEvmAuthorization = z.infer<typeof ExactEvmAuthorization>;\n\nexport const ExactEvmPayload = z.object({\n /** 65-byte EIP-712 signature over the authorization. */\n signature: Hex,\n authorization: ExactEvmAuthorization,\n});\nexport type ExactEvmPayload = z.infer<typeof ExactEvmPayload>;\n\n/** The full X-PAYMENT header body (x402 spec v1 envelope). */\nexport const PaymentPayload = z.object({\n x402Version: z.literal(1),\n scheme: z.string(),\n network: z.string(),\n payload: ExactEvmPayload,\n});\nexport type PaymentPayload = z.infer<typeof PaymentPayload>;\n\n/**\n * The v2 envelope (PAYMENT-SIGNATURE header): scheme/network live inside\n * `accepted` — the requirement the payer chose — around the SAME signed\n * scheme payload as v1. `.passthrough()` keeps resource/extensions intact\n * because the facilitator re-verifies the envelope verbatim.\n */\nexport const PaymentPayloadV2 = z\n .object({\n x402Version: z.literal(2),\n accepted: z\n .object({\n scheme: z.string(),\n /** CAIP-2, e.g. \"eip155:84532\". */\n network: z.string(),\n amount: UintString,\n asset: z.string().min(1),\n payTo: z.string().min(1),\n })\n .passthrough(),\n payload: ExactEvmPayload,\n })\n .passthrough();\nexport type PaymentPayloadV2 = z.infer<typeof PaymentPayloadV2>;\n\n/** A payment as the vendor sees it, whichever dialect it arrived in. */\nexport interface DecodedPayment {\n version: 1 | 2;\n scheme: string;\n network: string;\n payload: ExactEvmPayload;\n /** The decoded envelope exactly as sent — what travels to the facilitator. */\n envelope: PaymentPayload | PaymentPayloadV2;\n}\n\n/** Facilitator POST /verify response. Reason strings stay lenient on purpose. */\nexport const VerifyResponse = z.object({\n isValid: z.boolean(),\n invalidReason: z.string().optional(),\n payer: z.string().optional(),\n});\nexport type VerifyResponse = z.infer<typeof VerifyResponse>;\n\n/** Facilitator POST /settle response (also what X-PAYMENT-RESPONSE carries). */\nexport const SettleResponse = z.object({\n success: z.boolean(),\n errorReason: z.string().optional(),\n payer: z.string().optional(),\n /** The on-chain tx hash (the guard surfaces this on the receipt). */\n transaction: z.string(),\n network: z.string(),\n});\nexport type SettleResponse = z.infer<typeof SettleResponse>;\n\nexport function encodePaymentHeader(payload: PaymentPayload): string {\n return Buffer.from(JSON.stringify(payload)).toString('base64');\n}\n\nexport function decodePaymentHeader(raw: string): PaymentPayload {\n let json: unknown;\n try {\n json = JSON.parse(Buffer.from(raw, 'base64').toString('utf8'));\n } catch {\n throw new RailsError('malformed_payment', 'X-PAYMENT is not base64-encoded JSON');\n }\n const parsed = PaymentPayload.safeParse(json);\n if (!parsed.success) {\n throw new RailsError('malformed_payment', `invalid X-PAYMENT body: ${parsed.error.message}`);\n }\n return parsed.data;\n}\n\n/**\n * Decode a payment header in EITHER dialect to one normalized view. The v2\n * envelope wraps the SAME signed scheme payload as v1, so both unwrap to a\n * single ExactEvmPayload; the envelope is kept verbatim for the facilitator,\n * which wants the payment in the dialect it was presented in.\n */\nexport function decodeAnyPaymentHeader(raw: string): DecodedPayment {\n let json: unknown;\n try {\n json = JSON.parse(Buffer.from(raw, 'base64').toString('utf8'));\n } catch {\n throw new RailsError('malformed_payment', 'the payment header is not base64-encoded JSON');\n }\n\n if ((json as { x402Version?: unknown } | null)?.x402Version === 2) {\n const parsed = PaymentPayloadV2.safeParse(json);\n if (!parsed.success) {\n throw new RailsError(\n 'malformed_payment',\n `invalid v2 payment envelope: ${parsed.error.message}`,\n );\n }\n // A self-contradictory envelope (accepted terms vs signed authorization)\n // is malformed on its face — mirroring the gate's inspection.\n if (parsed.data.payload.authorization.value !== parsed.data.accepted.amount) {\n throw new RailsError(\n 'malformed_payment',\n `v2 envelope contradicts itself: accepted.amount ${parsed.data.accepted.amount} vs signed value ${parsed.data.payload.authorization.value}`,\n );\n }\n return {\n version: 2,\n scheme: parsed.data.accepted.scheme,\n network: parsed.data.accepted.network,\n payload: parsed.data.payload,\n envelope: parsed.data,\n };\n }\n\n const parsed = PaymentPayload.safeParse(json);\n if (!parsed.success) {\n throw new RailsError('malformed_payment', `invalid X-PAYMENT body: ${parsed.error.message}`);\n }\n return {\n version: 1,\n scheme: parsed.data.scheme,\n network: parsed.data.network,\n payload: parsed.data.payload,\n envelope: parsed.data,\n };\n}\n\nexport function encodeSettlementHeader(response: SettleResponse): string {\n return Buffer.from(JSON.stringify(response)).toString('base64');\n}\n","export type RailsErrorCode = 'malformed_payment' | 'unsupported_network';\n\n/** A payload or requirement these rails refuse to handle, with a machine-readable code. */\nexport class RailsError extends Error {\n constructor(\n readonly code: RailsErrorCode,\n message: string,\n ) {\n super(message);\n this.name = 'RailsError';\n }\n}\n\n/** The facilitator answered with a non-2xx status; body kept for forensics. */\nexport class FacilitatorHttpError extends Error {\n constructor(\n readonly status: number,\n readonly body: string,\n ) {\n super(`facilitator responded ${status}: ${body.slice(0, 500)}`);\n this.name = 'FacilitatorHttpError';\n }\n}\n","import { keccak256, stringToBytes, type Hex } from 'viem';\n\n/**\n * Deterministic EIP-3009 nonce: keccak256(utf8(intent.id)).\n *\n * This is the on-chain memo. EIP-3009 only requires per-authorizer uniqueness\n * (intent ids are ULIDs, so collisions are off the table), and USDC emits\n * `AuthorizationUsed(authorizer, nonce)` on settlement — so the indexer can\n * recompute this for every allowed intent and reconcile transfers exactly,\n * the same memo-first semantics the mock rails get from a ledger memo field.\n */\nexport function intentNonce(intentId: string): Hex {\n return keccak256(stringToBytes(intentId));\n}\n","/**\n * x402 network ids → EVM chain ids these rails can sign for. Accepts both the\n * v1 names (\"base-sepolia\") and the v2 CAIP-2 ids (\"eip155:84532\"). Unknown\n * networks return undefined — callers must fail closed.\n */\nconst NETWORK_TO_CHAIN_ID: Record<string, number> = {\n base: 8453,\n 'eip155:8453': 8453,\n 'base-sepolia': 84532,\n 'eip155:84532': 84532,\n};\n\nexport function chainIdForNetwork(network: string): number | undefined {\n return NETWORK_TO_CHAIN_ID[network.toLowerCase()];\n}\n","import { privateKeyToAccount } from 'viem/accounts';\nimport type { Hex, LocalAccount } from 'viem';\nimport type { Payer, PaymentRequirement } from '@reinconsole/sdk';\nimport { RailsError } from './errors.js';\nimport { chainIdForNetwork } from './networks.js';\nimport { intentNonce } from './nonce.js';\nimport { encodePaymentHeader, type ExactEvmAuthorization } from './wire.js';\n\n/** The EIP-3009 type tuple USDC's FiatTokenV2 verifies against. */\nexport const transferWithAuthorizationTypes = {\n TransferWithAuthorization: [\n { name: 'from', type: 'address' },\n { name: 'to', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'validAfter', type: 'uint256' },\n { name: 'validBefore', type: 'uint256' },\n { name: 'nonce', type: 'bytes32' },\n ],\n} as const;\n\nexport interface X402PayerOptions {\n /** The agent wallet's private key (a local account; never leaves the process). */\n privateKey: Hex;\n /** How far into the past validAfter reaches, absorbing clock skew. */\n validAfterSkewSeconds?: number;\n /** validBefore window when the requirement omits maxTimeoutSeconds. */\n defaultTimeoutSeconds?: number;\n /** Injectable clock (unix seconds) for deterministic tests. */\n now?: () => number;\n}\n\n/**\n * The real x402 `Payer`: signs an EIP-3009 TransferWithAuthorization for the\n * requirement's token (EIP-712, fully offline — no RPC) and returns the v1\n * X-PAYMENT header. Gasless for the agent: the facilitator submits the tx.\n *\n * The authorization nonce is derived from the intent id, which is what lets\n * the on-chain indexer reconcile the settlement back to the decision that\n * allowed it (see nonce.ts).\n */\nexport function createX402Payer(options: X402PayerOptions): Payer {\n const account: LocalAccount = privateKeyToAccount(options.privateKey);\n const skew = options.validAfterSkewSeconds ?? 600;\n const defaultTimeout = options.defaultTimeoutSeconds ?? 300;\n const now = options.now ?? (() => Math.floor(Date.now() / 1000));\n\n return async (requirement, intent) => {\n const chainId = chainIdForNetwork(requirement.network);\n if (chainId === undefined) {\n throw new RailsError(\n 'unsupported_network',\n `cannot sign for x402 network \"${requirement.network}\"`,\n );\n }\n\n const ts = now();\n const authorization: ExactEvmAuthorization = {\n from: account.address,\n to: requirement.payTo as Hex,\n value: requirement.maxAmountRequired,\n validAfter: String(ts - skew),\n validBefore: String(ts + (requirement.maxTimeoutSeconds ?? defaultTimeout)),\n nonce: intentNonce(intent.id),\n };\n\n const signature = await account.signTypedData({\n domain: {\n name: extraString(requirement, 'name') ?? 'USDC',\n version: extraString(requirement, 'version') ?? '2',\n chainId,\n verifyingContract: requirement.asset as Hex,\n },\n types: transferWithAuthorizationTypes,\n primaryType: 'TransferWithAuthorization',\n message: {\n from: authorization.from as Hex,\n to: authorization.to as Hex,\n value: BigInt(authorization.value),\n validAfter: BigInt(authorization.validAfter),\n validBefore: BigInt(authorization.validBefore),\n nonce: authorization.nonce as Hex,\n },\n });\n\n return encodePaymentHeader({\n x402Version: 1,\n scheme: requirement.scheme,\n network: requirement.network,\n payload: { signature, authorization },\n });\n };\n}\n\n/** EIP-712 domain name/version travel in requirement.extra (per the v1 spec). */\nfunction extraString(requirement: PaymentRequirement, key: string): string | undefined {\n const value = requirement.extra?.[key];\n return typeof value === 'string' ? value : undefined;\n}\n","import type { FetchLike, PaymentRequirement } from '@reinconsole/sdk';\nimport { FacilitatorHttpError } from './errors.js';\nimport { SettleResponse, VerifyResponse, type PaymentPayload } from './wire.js';\n\n/** Coinbase's hosted testnet facilitator: free, no API key, v1 + base-sepolia. */\nexport const DEFAULT_FACILITATOR_URL = 'https://x402.org/facilitator';\n\nexport interface FacilitatorClientOptions {\n /** Facilitator base URL. Defaults to the hosted x402.org testnet facilitator. */\n url?: string;\n /** Transport override (tests inject a stub here). Defaults to global fetch. */\n fetch?: FetchLike;\n}\n\n/** Any x402 payment envelope — the POST's x402Version is read off of it. */\nexport type AnyPaymentPayload = PaymentPayload | ({ x402Version: number } & Record<string, unknown>);\n/** Requirements in whichever dialect matches the payload (v1 or v2 shape). */\nexport type AnyPaymentRequirements = PaymentRequirement | Record<string, unknown>;\n\n/**\n * HTTP client for a real x402 facilitator (v1 AND v2 — x402.org serves both).\n * The vendor side of the rails: verify checks the payment signature against\n * the requirement, settle submits the EIP-3009 authorization on-chain (the\n * facilitator pays gas) and returns the tx hash. The POST's `x402Version` is\n * derived from the payload envelope itself, and the caller must pass\n * requirements in the SAME dialect (v2 payload → v2 `amount`/CAIP-2 shape;\n * @reinconsole/gate's facilitatorClientRails does this conversion).\n */\nexport class FacilitatorClient {\n readonly url: string;\n private readonly fetch: FetchLike;\n\n constructor(options: FacilitatorClientOptions = {}) {\n this.url = (options.url ?? DEFAULT_FACILITATOR_URL).replace(/\\/$/, '');\n const f = options.fetch ?? globalThis.fetch;\n this.fetch = (input, init) => f(input, init);\n }\n\n async verify(\n payload: AnyPaymentPayload,\n requirements: AnyPaymentRequirements,\n ): Promise<VerifyResponse> {\n return VerifyResponse.parse(await this.post('/verify', payload, requirements));\n }\n\n async settle(\n payload: AnyPaymentPayload,\n requirements: AnyPaymentRequirements,\n ): Promise<SettleResponse> {\n return SettleResponse.parse(await this.post('/settle', payload, requirements));\n }\n\n /** The facilitator's advertised (x402Version, scheme, network) kinds. */\n async supported(): Promise<unknown> {\n const res = await this.fetch(`${this.url}/supported`);\n if (!res.ok) throw new FacilitatorHttpError(res.status, await res.text());\n return res.json();\n }\n\n private async post(\n path: string,\n paymentPayload: AnyPaymentPayload,\n paymentRequirements: AnyPaymentRequirements,\n ): Promise<unknown> {\n // The payment travels DECODED (JSON object, not base64) and the\n // requirement is a single object, not the 402 body's accepts array.\n // Same envelope both versions; x402Version mirrors the payload's own.\n const claimed = (paymentPayload as { x402Version?: unknown }).x402Version;\n const x402Version = typeof claimed === 'number' ? claimed : 1;\n const res = await this.fetch(`${this.url}${path}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ x402Version, paymentPayload, paymentRequirements }),\n });\n if (!res.ok) throw new FacilitatorHttpError(res.status, await res.text());\n return res.json();\n }\n}\n","import { z } from 'zod';\n\n/**\n * Chains Rein observes/governs. x402 is multi-chain; Base and Solana ship\n * first, Polygon and BNB follow. The policy/ledger domain is rail-agnostic —\n * this enum is the only place chains are enumerated.\n */\nexport const Chain = z.enum(['base', 'solana', 'polygon', 'bnb']);\nexport type Chain = z.infer<typeof Chain>;\n\n/** Stablecoins settled over x402. */\nexport const Asset = z.enum(['USDC', 'USDT', 'EURC']);\nexport type Asset = z.infer<typeof Asset>;\n","import { z } from 'zod';\n\n/**\n * Monetary amounts in Rein are always non-negative **decimal strings**, never\n * floats. Float arithmetic silently loses precision on values like 0.1 + 0.2,\n * which is unacceptable for money. All comparison/aggregation goes through the\n * BigInt-backed helpers below.\n */\nexport const DecimalString = z\n .string()\n .regex(/^\\d+(\\.\\d+)?$/, 'must be a non-negative decimal string, e.g. \"5.00\"');\nexport type DecimalString = z.infer<typeof DecimalString>;\n\nconst DECIMAL_RE = /^\\d+(\\.\\d+)?$/;\n\nexport function isValidDecimal(value: string): boolean {\n return DECIMAL_RE.test(value);\n}\n\nfunction assertDecimal(value: string): void {\n if (!isValidDecimal(value)) {\n throw new TypeError(`invalid decimal string: ${JSON.stringify(value)}`);\n }\n}\n\nfunction fractionLength(value: string): number {\n const dot = value.indexOf('.');\n return dot === -1 ? 0 : value.length - dot - 1;\n}\n\n/** Scale a decimal string into an integer BigInt at a fixed number of fraction digits. */\nfunction toScaled(value: string, scale: number): bigint {\n const dot = value.indexOf('.');\n const intPart = dot === -1 ? value : value.slice(0, dot);\n const fracPart = dot === -1 ? '' : value.slice(dot + 1);\n const paddedFrac = (fracPart + '0'.repeat(scale)).slice(0, scale);\n return BigInt(intPart + paddedFrac);\n}\n\n/** Render a scaled BigInt back to a normalized decimal string (no trailing zeros). */\nfunction fromScaled(scaled: bigint, scale: number): string {\n if (scale === 0) return scaled.toString();\n const digits = scaled.toString().padStart(scale + 1, '0');\n const intPart = digits.slice(0, digits.length - scale);\n const fracPart = digits.slice(digits.length - scale).replace(/0+$/, '');\n return fracPart.length > 0 ? `${intPart}.${fracPart}` : intPart;\n}\n\n/** Compare two decimal strings. Returns -1 (a<b), 0 (a==b), or 1 (a>b). */\nexport function compareDecimal(a: string, b: string): -1 | 0 | 1 {\n assertDecimal(a);\n assertDecimal(b);\n const scale = Math.max(fractionLength(a), fractionLength(b));\n const av = toScaled(a, scale);\n const bv = toScaled(b, scale);\n return av < bv ? -1 : av > bv ? 1 : 0;\n}\n\n/** Sum a list of decimal strings without floating-point error. */\nexport function sumDecimal(values: readonly string[]): string {\n if (values.length === 0) return '0';\n let scale = 0;\n for (const v of values) {\n assertDecimal(v);\n scale = Math.max(scale, fractionLength(v));\n }\n let total = 0n;\n for (const v of values) total += toScaled(v, scale);\n return fromScaled(total, scale);\n}\n\n/** Multiply two decimal strings exactly (e.g. median * \"3\" for price-sanity). */\nexport function mulDecimal(a: string, b: string): string {\n assertDecimal(a);\n assertDecimal(b);\n const scaleA = fractionLength(a);\n const scaleB = fractionLength(b);\n const product = toScaled(a, scaleA) * toScaled(b, scaleB);\n return fromScaled(product, scaleA + scaleB);\n}\n\n/** Convenience: a > b. */\nexport function gt(a: string, b: string): boolean {\n return compareDecimal(a, b) === 1;\n}\n\n/** Convenience: a < b. */\nexport function lt(a: string, b: string): boolean {\n return compareDecimal(a, b) === -1;\n}\n","/**\n * Minimal, safe glob matcher supporting only the `*` wildcard (matches any run\n * of characters, including none). Used for vendor host allowlists\n * (e.g. \"*.trusted.io\"), agent-id targeting (e.g. \"agt_research_*\"), and\n * Gate route pricing (e.g. \"/api/reports/*\").\n *\n * Deliberately NOT a regex from user input — the pattern is escaped so a\n * malicious policy value cannot inject regex behavior (ReDoS, etc.).\n */\nexport function globMatch(pattern: string, value: string): boolean {\n const escaped = pattern.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'); // escape regex metachars\n const withWildcard = escaped.replace(/\\\\\\*/g, '.*'); // re-enable only `*`\n return new RegExp(`^${withWildcard}$`).test(value);\n}\n\n/** True if `value` matches any pattern in the list. */\nexport function globMatchAny(patterns: readonly string[], value: string): boolean {\n return patterns.some((p) => globMatch(p, value));\n}\n","/**\n * Minimal ULID generation, dependency-free. ULIDs are lexicographically\n * sortable (time-prefixed) and url-safe, which is why Rein uses them for all\n * primary keys instead of UUIDs. Works in Node 22 and modern browsers/edge via\n * the WebCrypto `globalThis.crypto`.\n */\n\n// Crockford's base32 alphabet (excludes I, L, O, U to avoid ambiguity).\nconst ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';\nconst TIME_LEN = 10;\nconst RANDOM_LEN = 16;\n\nfunction randomBytes(length: number): Uint8Array {\n const bytes = new Uint8Array(length);\n globalThis.crypto.getRandomValues(bytes);\n return bytes;\n}\n\nfunction encodeTime(now: number): string {\n let time = now;\n let out = '';\n for (let i = TIME_LEN - 1; i >= 0; i--) {\n out = ENCODING.charAt(time % 32) + out;\n time = Math.floor(time / 32);\n }\n return out;\n}\n\nfunction encodeRandom(): string {\n let out = '';\n for (const byte of randomBytes(RANDOM_LEN)) {\n out += ENCODING.charAt(byte % 32);\n }\n return out;\n}\n\n/** Generate a 26-character ULID. */\nexport function ulid(seedTime: number = Date.now()): string {\n return encodeTime(seedTime) + encodeRandom();\n}\n\n/** Generate a Stripe-style prefixed id, e.g. `newId('agt')` -> `agt_01J...`. */\nexport function newId<P extends string>(prefix: P): `${P}_${string}` {\n return `${prefix}_${ulid()}`;\n}\n","import { z } from 'zod';\n\n/** Crockford base32 ULID body (26 chars), as produced by `ulid()`. */\nconst ULID_BODY = '[0-9A-HJKMNP-TV-Z]{26}';\n\n/**\n * A zod schema for a Stripe-style prefixed ULID, e.g. `agt_01J7...`.\n * Centralizing this keeps id formats consistent across DB rows, API payloads,\n * and SDK types.\n */\nexport function prefixedId(prefix: string) {\n return z\n .string()\n .regex(new RegExp(`^${prefix}_${ULID_BODY}$`), `expected a \"${prefix}_\" prefixed id`);\n}\n\nexport const OrgId = prefixedId('org');\nexport const AgentId = prefixedId('agt');\nexport const PolicyId = prefixedId('pol');\nexport const IntentId = prefixedId('int');\nexport const DecisionId = prefixedId('dec');\nexport const ReceiptId = prefixedId('rcp');\nexport const SessionId = prefixedId('ses');\nexport const GateReceiptId = prefixedId('grc');\n\nexport type OrgId = z.infer<typeof OrgId>;\nexport type AgentId = z.infer<typeof AgentId>;\nexport type PolicyId = z.infer<typeof PolicyId>;\nexport type IntentId = z.infer<typeof IntentId>;\nexport type DecisionId = z.infer<typeof DecisionId>;\nexport type ReceiptId = z.infer<typeof ReceiptId>;\nexport type SessionId = z.infer<typeof SessionId>;\nexport type GateReceiptId = z.infer<typeof GateReceiptId>;\n","import { z } from 'zod';\nimport { AgentId, OrgId } from './ids.js';\nimport { Chain } from './chain.js';\n\n/**\n * Enforcement tier of a given agent wallet:\n * - `observed` — Rein sees spend on-chain but has no control (no SDK either).\n * - `sdk` — agent uses @reinconsole/sdk; advisory + observability (bypassable).\n * - `session-key` — signer-level scope; out-of-policy txs cannot be signed.\n */\nexport const EnforcementMode = z.enum(['observed', 'sdk', 'session-key']);\nexport type EnforcementMode = z.infer<typeof EnforcementMode>;\n\nexport const AgentWallet = z.object({\n chain: Chain,\n address: z.string().min(1),\n mode: EnforcementMode,\n});\nexport type AgentWallet = z.infer<typeof AgentWallet>;\n\nexport const AgentStatus = z.enum(['active', 'frozen']);\nexport type AgentStatus = z.infer<typeof AgentStatus>;\n\nexport const Agent = z.object({\n id: AgentId,\n orgId: OrgId,\n name: z.string().min(1).max(200),\n /** On-chain ERC-8004 identity, if the agent is registered. */\n erc8004Id: z.string().optional(),\n wallets: z.array(AgentWallet).default([]),\n status: AgentStatus.default('active'),\n createdAt: z.coerce.date(),\n});\nexport type Agent = z.infer<typeof Agent>;\n","import { z } from 'zod';\n\n/**\n * The canonical string form of an ERC-8004 agent identity:\n *\n * eip155:{chainId}:{identityRegistry}/{tokenId}\n *\n * The part before the `/` is the spec's registry reference verbatim (the\n * `agentRegistry` field of a registration file, CAIP-10 account form); the\n * tokenId is the ERC-721 id the Identity Registry minted (`agentId` in the\n * spec). This exact string is what `Agent.erc8004Id` / `Vendor.erc8004Id`\n * carry, AND the reputation-subject id a registered agent's evidence keys by.\n *\n * Casing is load-bearing: reputation subject keys for agent-kind ids are\n * case-sensitive unless they start with `0x` (see @reinconsole/graph\n * `normalizeSubject`), and an eip155 string does not. `formatErc8004Id`\n * therefore always emits the registry address in lowercase, and consumers must\n * never hand-build the string — parse then re-format to normalize.\n */\n\nexport interface Erc8004Ref {\n /** EIP-155 chain id (e.g. 8453 Base, 84532 Base Sepolia). */\n chainId: number;\n /** Identity Registry contract address, lowercase 0x-hex. */\n registry: string;\n /** ERC-721 tokenId — the spec's `agentId`. bigint: token ids exceed 2^53. */\n tokenId: bigint;\n}\n\nconst REGISTRY_PATTERN = /^0x[0-9a-fA-F]{40}$/;\nconst ID_PATTERN = /^eip155:(\\d+):(0x[0-9a-fA-F]{40})\\/(\\d+)$/;\n\n/** Build the canonical id string. Throws on a malformed ref (programmer error). */\nexport function formatErc8004Id(ref: Erc8004Ref): string {\n if (!Number.isSafeInteger(ref.chainId) || ref.chainId < 1) {\n throw new RangeError(`erc8004: bad chainId ${ref.chainId}`);\n }\n if (!REGISTRY_PATTERN.test(ref.registry)) {\n throw new RangeError(`erc8004: bad registry address ${ref.registry}`);\n }\n if (typeof ref.tokenId !== 'bigint' || ref.tokenId < 0n) {\n // The typeof guard matters for plain-JS callers: 1.5 < 0n is legal JS and\n // false, and would mint the unparseable \"…/1.5\".\n throw new RangeError(`erc8004: bad tokenId ${ref.tokenId}`);\n }\n return `eip155:${ref.chainId}:${ref.registry.toLowerCase()}/${ref.tokenId}`;\n}\n\n/**\n * Parse a canonical (or hand-written) id string. Accepts any address casing\n * and returns a lowercase ref, or undefined when malformed — so\n * `formatErc8004Id(parseErc8004Id(x)!)` is the normalization step.\n */\nexport function parseErc8004Id(value: string): Erc8004Ref | undefined {\n const match = ID_PATTERN.exec(value);\n if (!match) return undefined;\n const chainId = Number(match[1]);\n if (!Number.isSafeInteger(chainId) || chainId < 1) return undefined;\n return {\n chainId,\n registry: match[2]!.toLowerCase(),\n tokenId: BigInt(match[3]!),\n };\n}\n\n/** Strict boundary schema for the id string (the fields themselves stay free-form). */\nexport const Erc8004Id = z\n .string()\n .refine((value) => parseErc8004Id(value) !== undefined, {\n message: 'expected \"eip155:{chainId}:{registry}/{tokenId}\"',\n });\nexport type Erc8004Id = z.infer<typeof Erc8004Id>;\n","import { z } from 'zod';\nimport { AgentId, IntentId } from './ids.js';\nimport { Chain, Asset } from './chain.js';\nimport { DecimalString } from './money.js';\n\nexport const Vendor = z.object({\n host: z.string().min(1),\n address: z.string().min(1),\n erc8004Id: z.string().optional(),\n});\nexport type Vendor = z.infer<typeof Vendor>;\n\n/**\n * The observability gold: links every micro-payment back to the task and run\n * that caused it, so finance teams can answer \"what was this spend for?\".\n */\nexport const TaskContext = z.object({\n taskId: z.string().optional(),\n parentRunId: z.string().optional(),\n purpose: z.string().max(500).optional(),\n});\nexport type TaskContext = z.infer<typeof TaskContext>;\n\n/**\n * A request to spend, submitted to the policy engine BEFORE any signature is\n * released. The `nonce` provides replay protection on the signer path.\n */\nexport const PaymentIntent = z.object({\n id: IntentId,\n agentId: AgentId,\n vendor: Vendor,\n resource: z.string(),\n amount: DecimalString,\n asset: Asset,\n chain: Chain,\n taskContext: TaskContext.default({}),\n nonce: z.string().min(1),\n createdAt: z.coerce.date(),\n});\nexport type PaymentIntent = z.infer<typeof PaymentIntent>;\n","import { z } from 'zod';\nimport { DecisionId, IntentId } from './ids.js';\n\nexport const DecisionOutcome = z.enum(['allow', 'deny', 'escalate']);\nexport type DecisionOutcome = z.infer<typeof DecisionOutcome>;\n\n/**\n * The signed, hash-chained record of a single policy evaluation. Written BEFORE\n * any signature is released. `prevHash` + `hash` form a tamper-evident chain;\n * `signature` is the policy service's signing key over `hash`. The eventual\n * on-chain `txHash` is attached later by the indexer (see SettledPayment).\n */\nexport const Decision = z.object({\n id: DecisionId,\n intentId: IntentId,\n /**\n * sha256 of the intent's canonical content (see canonical.ts). Binds the\n * decision to the exact transfer it judged — amount, recipient, asset,\n * chain — so a signer can verify an {intent, decision} pair offline as a\n * self-contained spend voucher, not just a reference by id.\n */\n intentHash: z.string(),\n outcome: DecisionOutcome,\n /** Ids of the rules that fired, for explainability. */\n matchedRules: z.array(z.string()).default([]),\n /** Human-readable explanation surfaced in the dashboard. */\n reason: z.string().optional(),\n policyId: z.string(),\n policyVersion: z.string(),\n /** Hash of the previous decision in the chain (tamper-evident log). */\n prevHash: z.string(),\n /** Hash of this decision's canonical content. */\n hash: z.string(),\n /** Service signing-key signature over `hash`. */\n signature: z.string(),\n latencyMs: z.number().nonnegative(),\n decidedAt: z.coerce.date(),\n});\nexport type Decision = z.infer<typeof Decision>;\n","import type { PaymentIntent } from './intent.js';\nimport type { DecisionOutcome } from './decision.js';\n\n/**\n * Canonical byte forms shared by the policy engine (which hashes and signs\n * them) and the signer (which verifies them offline). Field order is fixed,\n * dates are ISO strings, and absent optionals are explicit nulls, so the same\n * parsed object always canonicalizes to the same bytes — including after a\n * JSON round-trip over HTTP.\n *\n * These builders are pure (no node:crypto) so @reinconsole/core stays loadable in a\n * browser; services hash the strings with whatever sha256 they have.\n */\n\n/** Canonical form of an intent — what `Decision.intentHash` commits to. */\nexport function canonicalIntent(intent: PaymentIntent): string {\n return JSON.stringify({\n id: intent.id,\n agentId: intent.agentId,\n vendor: {\n host: intent.vendor.host,\n address: intent.vendor.address,\n erc8004Id: intent.vendor.erc8004Id ?? null,\n },\n resource: intent.resource,\n amount: intent.amount,\n asset: intent.asset,\n chain: intent.chain,\n taskContext: {\n taskId: intent.taskContext.taskId ?? null,\n parentRunId: intent.taskContext.parentRunId ?? null,\n purpose: intent.taskContext.purpose ?? null,\n },\n nonce: intent.nonce,\n createdAt: intent.createdAt.toISOString(),\n });\n}\n\n/** The decision fields covered by `Decision.hash` (and thus its signature). */\nexport interface DecisionContent {\n intentId: string;\n intentHash: string;\n outcome: DecisionOutcome;\n matchedRules: string[];\n policyId: string;\n policyVersion: string;\n prevHash: string;\n decidedAt: Date;\n}\n\n/** Canonical form of a decision — what `Decision.hash` is computed over. */\nexport function canonicalDecision(d: DecisionContent): string {\n return JSON.stringify({\n intentId: d.intentId,\n intentHash: d.intentHash,\n outcome: d.outcome,\n matchedRules: d.matchedRules,\n policyId: d.policyId,\n policyVersion: d.policyVersion,\n prevHash: d.prevHash,\n decidedAt: d.decidedAt.toISOString(),\n });\n}\n","import { z } from 'zod';\nimport { AgentId, SessionId } from './ids.js';\nimport { DecimalString } from './money.js';\n\n/**\n * A session-key grant: the signer tier's unit of delegated authority. The\n * agent process holds only the bearer token — the wallet key never leaves the\n * signer — and the stored record keeps a hash of the token, never the token\n * itself (it is returned exactly once, at creation).\n *\n * Caps here are the signer-side backstop UNDER whatever policy says: a\n * signature is released only when the engine allowed the intent AND the\n * session has room. Amounts are decimal strings in the asset's human units.\n */\nexport const Session = z.object({\n id: SessionId,\n agentId: AgentId,\n /** sha256 hex of the bearer token. */\n tokenHash: z.string(),\n /** Cumulative ceiling across the session's lifetime. Absent = uncapped. */\n capAmount: DecimalString.optional(),\n /** Ceiling per individual signature. Absent = uncapped. */\n maxPerPayment: DecimalString.optional(),\n expiresAt: z.coerce.date(),\n createdAt: z.coerce.date(),\n revokedAt: z.coerce.date().optional(),\n});\nexport type Session = z.infer<typeof Session>;\n","import { z } from 'zod';\nimport { IntentId } from './ids.js';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\n\n/**\n * On-chain confirmation of a settled payment, reconciled by the indexer against\n * the originating intent (amount + recipient + nonce, or facilitator webhook).\n */\nexport const SettledPayment = z.object({\n intentId: IntentId,\n txHash: z.string(),\n chain: Chain,\n blockNumber: z.coerce.bigint(),\n facilitator: z.string().optional(),\n feePaid: DecimalString.optional(),\n confirmedAt: z.coerce.date(),\n});\nexport type SettledPayment = z.infer<typeof SettledPayment>;\n","import { z } from 'zod';\nimport { ReceiptId, IntentId, DecisionId, AgentId } from './ids.js';\nimport { Chain, Asset } from './chain.js';\nimport { DecimalString } from './money.js';\nimport { TaskContext } from './intent.js';\nimport { DecisionOutcome } from './decision.js';\n\n/**\n * What the SDK reports back after settlement: the `X-PAYMENT-RESPONSE` header\n * a vendor returns once payment clears. Mock facilitators fill this in v0.1;\n * the indexer reconciles it against on-chain truth later (see SettledPayment).\n */\nexport const ReceiptSettlement = z.object({\n txHash: z.string().optional(),\n networkId: z.string().optional(),\n /** Raw header payload, kept for forensics until the indexer confirms. */\n raw: z.string().optional(),\n});\nexport type ReceiptSettlement = z.infer<typeof ReceiptSettlement>;\n\n/**\n * The SDK-side record of one guarded payment attempt: which request triggered\n * it, what the engine decided, and (if allowed and paid) how it settled.\n * Receipts are the observability primitive — every 402 the guard touches\n * produces exactly one, whether the payment was allowed or blocked.\n */\nexport const Receipt = z.object({\n id: ReceiptId,\n agentId: AgentId,\n intentId: IntentId,\n decisionId: DecisionId,\n outcome: DecisionOutcome,\n /** The URL the agent actually fetched (the paywalled resource). */\n url: z.string(),\n method: z.string().default('GET'),\n vendorHost: z.string(),\n amount: DecimalString,\n asset: Asset,\n chain: Chain,\n taskContext: TaskContext.default({}),\n /** Human-readable explanation copied from the decision. */\n reason: z.string().optional(),\n /** Present only once a payment was made and the vendor confirmed it. */\n settlement: ReceiptSettlement.optional(),\n createdAt: z.coerce.date(),\n});\nexport type Receipt = z.infer<typeof Receipt>;\n","import { z } from 'zod';\nimport { GateReceiptId } from './ids.js';\nimport { DecimalString } from './money.js';\n\n/**\n * The vendor-side twin of `Receipt`: one settled x402 payment as the GATE saw\n * it — who paid, for which priced route, and the settlement transaction. The\n * agent-side Receipt records what an agent tried to spend; a GateReceipt\n * records what a vendor actually earned.\n */\nexport const GateReceipt = z.object({\n id: GateReceiptId,\n at: z.coerce.date(),\n /** The route pattern that priced this request, e.g. \"/api/reports/*\". */\n route: z.string().min(1),\n /** The concrete resource paid for (URL path actually requested). */\n resource: z.string().min(1),\n method: z.string().min(1),\n /** The paying wallet address, as asserted by the settled payment. */\n payer: z.string().min(1),\n payTo: z.string().min(1),\n /** Human-unit decimal amount, e.g. \"0.05\". */\n amount: DecimalString,\n /** The same amount in the asset's atomic units, e.g. \"50000\". */\n amountAtomic: z.string().regex(/^\\d+$/, 'atomic amount must be an integer string'),\n /** Token symbol or contract address, exactly as quoted in the requirement. */\n asset: z.string().min(1),\n network: z.string().min(1),\n /** Settlement transaction hash (mock ledger or on-chain). */\n transaction: z.string().min(1),\n});\nexport type GateReceipt = z.infer<typeof GateReceipt>;\n","import { z } from 'zod';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\n\n/** A rolling-window spec, e.g. \"24h\", \"1h\", \"30m\", \"7d\". */\nexport const Window = z\n .string()\n .regex(/^\\d+[smhd]$/, 'window must be like \"30s\", \"15m\", \"1h\", or \"7d\"');\nexport type Window = z.infer<typeof Window>;\n\n/** A relative multiplier, e.g. \"3x\" (used for price-sanity checks). */\nexport const Multiplier = z.string().regex(/^\\d+(\\.\\d+)?x$/, 'multiplier must be like \"3x\"');\nexport type Multiplier = z.infer<typeof Multiplier>;\n\n/**\n * The set of predicates a rule can test. Multiple predicates in one condition\n * are ANDed together. Each maps to an evaluator in the policy engine.\n */\nexport const Condition = z\n .object({\n /** Per-transaction amount exceeds this value. */\n amountGt: DecimalString.optional(),\n /** Sum of spend in a rolling window exceeds `gt`. */\n rollingSum: z.object({ window: Window, gt: DecimalString }).optional(),\n /** Transaction count in a rolling window exceeds `gt`. */\n txCount: z.object({ window: Window, gt: z.number().int().nonnegative() }).optional(),\n /** Vendor host matches one of these patterns (supports `*` globs). */\n vendorHostIn: z.array(z.string()).optional(),\n /** First time Rein has seen this vendor for the agent. */\n vendorFirstSeen: z.boolean().optional(),\n /** Vendor reputation score is below this threshold (Phase 3 hook). */\n vendorReputationLt: z.number().min(0).max(100).optional(),\n /** Amount is more than `gt`-times the observed median for this resource. */\n amountVsResourceMedian: z.object({ gt: Multiplier }).optional(),\n })\n .refine((c) => Object.values(c).some((v) => v !== undefined), {\n message: 'a condition must specify at least one predicate',\n });\nexport type Condition = z.infer<typeof Condition>;\n\n/**\n * A single rule: an id plus exactly one action (allow / deny / escalate) whose\n * value is the condition that triggers it.\n */\nexport const Rule = z\n .object({\n id: z.string().min(1),\n allow: Condition.optional(),\n deny: Condition.optional(),\n escalate: Condition.optional(),\n })\n .refine((r) => [r.allow, r.deny, r.escalate].filter((v) => v !== undefined).length === 1, {\n message: 'a rule must specify exactly one of allow / deny / escalate',\n });\nexport type Rule = z.infer<typeof Rule>;\n\nexport const PolicyDefault = z.enum(['allow', 'deny']);\nexport type PolicyDefault = z.infer<typeof PolicyDefault>;\n\nexport const AppliesTo = z.object({\n /** Agent id patterns (supports `*` globs, e.g. \"agt_research_*\"). */\n agents: z.array(z.string()).optional(),\n chains: z.array(Chain).optional(),\n});\nexport type AppliesTo = z.infer<typeof AppliesTo>;\n\nexport const Escalation = z.object({\n approvers: z.array(z.string()).default([]),\n timeoutAction: PolicyDefault.default('deny'),\n timeoutMin: z.number().int().positive().default(15),\n});\nexport type Escalation = z.infer<typeof Escalation>;\n\n/**\n * A declarative, versioned, immutable-once-active policy. Evaluation order in\n * the engine is: explicit DENY > ESCALATE > ALLOW > `default`.\n */\nexport const Policy = z.object({\n policyId: z.string().min(1),\n version: z.string().default('1'),\n appliesTo: AppliesTo.default({}),\n rules: z.array(Rule).default([]),\n default: PolicyDefault.default('deny'),\n /** Below this amount, fail-open is permitted during a policy-service outage. */\n denyFloor: DecimalString.default('0.05'),\n escalation: Escalation.optional(),\n});\nexport type Policy = z.infer<typeof Policy>;\n","import { z } from 'zod';\n\nexport const ReputationSubject = z.object({\n kind: z.enum(['agent', 'vendor']),\n id: z.string(),\n});\nexport type ReputationSubject = z.infer<typeof ReputationSubject>;\n\nexport const ReputationComponents = z.object({\n volume: z.number(),\n longevity: z.number(),\n disputeRate: z.number(),\n counterpartyQuality: z.number(),\n settlementReliability: z.number(),\n});\nexport type ReputationComponents = z.infer<typeof ReputationComponents>;\n\n/**\n * A reputation score for an agent or vendor (Phase 3 — Graph). `confidence` is\n * first-class: a thin-history subject returns LOW confidence rather than a\n * misleadingly high score, so policy can avoid both false trust and unfair\n * freezing.\n */\nexport const ReputationScore = z.object({\n subject: ReputationSubject,\n score: z.number().min(0).max(100),\n components: ReputationComponents,\n confidence: z.number().min(0).max(1),\n asOf: z.coerce.date(),\n /** Hash-anchored attestation, optionally published on-chain (ERC-8004). */\n evidenceUri: z.string().optional(),\n});\nexport type ReputationScore = z.infer<typeof ReputationScore>;\n","import { z } from 'zod';\nimport { AgentId, DecisionId, IntentId, SessionId } from './ids.js';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\nimport { PaymentIntent } from './intent.js';\nimport { Decision } from './decision.js';\nimport { SettledPayment } from './payment.js';\nimport { GateReceipt } from './gate-receipt.js';\n\n/**\n * The canonical event envelope published on the bus (NATS in production).\n * `shadow.spend` is emitted when the indexer sees on-chain spend from a managed\n * wallet with NO corresponding ALLOW decision — the bypass signal that catches\n * SDK-mode evasion and drives the upgrade to the signer tier.\n * `signature.released` / `signature.refused` are that tier's heartbeat: every\n * time the signer does or does not put a key to work, the bus knows why.\n * `gate.*` is the vendor side of the wire: every quote a Gate issues, every\n * payment it accepts, every payment it turns away.\n */\nexport const ReinEvent = z.discriminatedUnion('type', [\n z.object({ type: z.literal('intent.created'), at: z.coerce.date(), intent: PaymentIntent }),\n z.object({ type: z.literal('decision.made'), at: z.coerce.date(), decision: Decision }),\n z.object({ type: z.literal('payment.settled'), at: z.coerce.date(), payment: SettledPayment }),\n z.object({\n type: z.literal('shadow.spend'),\n at: z.coerce.date(),\n agentId: AgentId,\n txHash: z.string(),\n chain: Chain,\n amount: DecimalString,\n }),\n z.object({\n type: z.literal('signature.released'),\n at: z.coerce.date(),\n sessionId: SessionId,\n agentId: AgentId,\n intentId: IntentId,\n decisionId: DecisionId,\n amount: DecimalString,\n }),\n z.object({\n type: z.literal('signature.refused'),\n at: z.coerce.date(),\n /** Refusal code, e.g. \"decision_replayed\" (see @reinconsole/signer). */\n code: z.string(),\n reason: z.string(),\n sessionId: SessionId.optional(),\n agentId: AgentId.optional(),\n intentId: IntentId.optional(),\n }),\n z.object({\n type: z.literal('gate.quoted'),\n at: z.coerce.date(),\n resource: z.string(),\n method: z.string(),\n amount: DecimalString,\n asset: z.string(),\n network: z.string(),\n }),\n z.object({ type: z.literal('gate.settled'), at: z.coerce.date(), receipt: GateReceipt }),\n z.object({\n type: z.literal('gate.refused'),\n at: z.coerce.date(),\n /** Refusal code, e.g. \"payment_replayed\" (see @reinconsole/gate). */\n code: z.string(),\n reason: z.string(),\n resource: z.string(),\n /** Known only when the payment header decoded far enough to name a payer. */\n payer: z.string().optional(),\n }),\n]);\nexport type ReinEvent = z.infer<typeof ReinEvent>;\n","import type { Decision, PaymentIntent, Receipt } from '@reinconsole/core';\n\n/** Base class for everything the SDK throws, so callers can catch broadly. */\nexport class ReinError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\n/** The policy engine answered with a non-2xx status. */\nexport class EngineError extends ReinError {\n constructor(\n readonly status: number,\n readonly body: unknown,\n message = `policy engine responded ${status}`,\n ) {\n super(message);\n }\n}\n\n/**\n * The engine evaluated the intent and did NOT allow it (deny or escalate —\n * v0.1 blocks both; escalation approval flows land later). The payment was\n * never constructed, so no funds moved. Carries the full evidence trail.\n */\nexport class PaymentBlockedError extends ReinError {\n constructor(\n readonly intent: PaymentIntent,\n readonly decision: Decision,\n readonly receipt: Receipt,\n ) {\n super(\n `rein blocked payment of ${intent.amount} ${intent.asset} to ${intent.vendor.host}: ` +\n `${decision.outcome}${decision.reason ? ` (${decision.reason})` : ''}`,\n );\n }\n}\n\n/**\n * The vendor's 402 was x402-shaped but offered no requirement the guard can\n * govern (unknown scheme/network/asset). The guard fails closed rather than\n * letting an ungoverned payment through.\n */\nexport class UnsupportedRequirementError extends ReinError {\n constructor(readonly url: string) {\n super(`no supported x402 payment requirement in 402 from ${url}; failing closed`);\n }\n}\n","import { z } from 'zod';\nimport { Agent, Decision, PaymentIntent, Policy } from '@reinconsole/core';\nimport { EngineError } from './errors.js';\nimport type { IntentSubmission } from './x402.js';\n\n/** Any fetch-compatible function (global fetch, undici, or a test double). */\nexport type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;\n\nconst Health = z.object({ status: z.string(), publicKey: z.string() });\nconst EvaluateResponse = z.object({ intent: PaymentIntent, decision: Decision });\nexport type EvaluateResponse = z.infer<typeof EvaluateResponse>;\n\nexport interface EngineClientOptions {\n /** Base URL of the policy engine, e.g. \"http://localhost:8787\". */\n baseUrl: string;\n /** Override the transport (tests, custom agents). Defaults to global fetch. */\n fetch?: FetchLike;\n}\n\n/**\n * Thin typed client for the policy-engine HTTP API. Every response is parsed\n * through the @reinconsole/core schemas, so wire drift fails loudly at the boundary.\n */\nexport class EngineClient {\n private readonly baseUrl: string;\n private readonly fetchImpl: FetchLike;\n\n constructor(options: EngineClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '');\n const f = options.fetch ?? globalThis.fetch;\n this.fetchImpl = (input, init) => f(input, init);\n }\n\n private async request<T>(\n method: string,\n path: string,\n schema: z.ZodType<T, z.ZodTypeDef, unknown>,\n body?: unknown,\n ): Promise<T> {\n const res = await this.fetchImpl(`${this.baseUrl}${path}`, {\n method,\n headers: body === undefined ? undefined : { 'content-type': 'application/json' },\n body: body === undefined ? undefined : JSON.stringify(body),\n });\n if (!res.ok) {\n const payload = await res\n .clone()\n .json()\n .catch(() => res.text().catch(() => undefined));\n throw new EngineError(res.status, payload);\n }\n if (res.status === 204) return schema.parse(undefined);\n return schema.parse(await res.json());\n }\n\n health(): Promise<z.infer<typeof Health>> {\n return this.request('GET', '/health', Health);\n }\n\n registerAgent(input: {\n orgId: string;\n name: string;\n erc8004Id?: string;\n wallets?: Agent['wallets'];\n }): Promise<Agent> {\n return this.request('POST', '/v1/agents', Agent, input);\n }\n\n listAgents(): Promise<Agent[]> {\n return this.request('GET', '/v1/agents', z.array(Agent));\n }\n\n freeze(agentId: string): Promise<void> {\n return this.request('POST', `/v1/agents/${agentId}/freeze`, z.void());\n }\n\n unfreeze(agentId: string): Promise<void> {\n return this.request('POST', `/v1/agents/${agentId}/unfreeze`, z.void());\n }\n\n addPolicy(policy: z.input<typeof Policy>): Promise<Policy> {\n return this.request('POST', '/v1/policies', Policy, policy);\n }\n\n listPolicies(): Promise<Policy[]> {\n return this.request('GET', '/v1/policies', z.array(Policy));\n }\n\n /** The hot path: submit an intent, get the normalized intent + signed decision. */\n evaluate(submission: IntentSubmission): Promise<EvaluateResponse> {\n return this.request('POST', '/v1/evaluate', EvaluateResponse, submission);\n }\n\n decisions(): Promise<Decision[]> {\n return this.request('GET', '/v1/decisions', z.array(Decision));\n }\n}\n","import { z } from 'zod';\nimport { Chain, Asset, type TaskContext, type Vendor } from '@reinconsole/core';\n\n/**\n * x402 wire shapes (spec v1), mock-first: these schemas are what Rein's mock\n * facilitator and tests speak today, and they track the published x402 spec so\n * real vendors parse identically when the live integration lands.\n */\n\n/** One way to pay, as offered inside a 402 response body. */\nexport const PaymentRequirement = z.object({\n scheme: z.string(),\n network: z.string(),\n /** Amount in the asset's atomic units (e.g. \"10000\" = 0.01 USDC at 6 decimals). */\n maxAmountRequired: z.string().regex(/^\\d+$/, 'atomic amount must be an integer string'),\n resource: z.string().optional(),\n description: z.string().optional(),\n mimeType: z.string().optional(),\n payTo: z.string().min(1),\n maxTimeoutSeconds: z.number().optional(),\n /** Token contract address — or, mock-first, a plain symbol like \"USDC\". */\n asset: z.string().min(1),\n extra: z.record(z.unknown()).optional(),\n});\nexport type PaymentRequirement = z.infer<typeof PaymentRequirement>;\n\n/** The full 402 body a paywalled vendor returns. */\nexport const PaymentRequired = z.object({\n x402Version: z.number(),\n accepts: z.array(PaymentRequirement).min(1),\n error: z.string().optional(),\n});\nexport type PaymentRequired = z.infer<typeof PaymentRequired>;\n\n/**\n * x402 network ids → the chains Rein governs. Testnets map to their mainnet.\n * Both v1 names (\"base-sepolia\") and v2 CAIP-2 ids (\"eip155:84532\") appear in\n * the wild, so the guard accepts either.\n */\nconst NETWORK_TO_CHAIN: Record<string, Chain> = {\n base: 'base',\n 'base-sepolia': 'base',\n 'eip155:8453': 'base',\n 'eip155:84532': 'base',\n solana: 'solana',\n 'solana-devnet': 'solana',\n polygon: 'polygon',\n 'polygon-amoy': 'polygon',\n bnb: 'bnb',\n bsc: 'bnb',\n};\n\n/** Canonical stablecoin contract addresses (EVM keys lowercased). */\nconst KNOWN_ASSET_ADDRESSES: Record<string, Asset> = {\n '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913': 'USDC', // USDC on Base\n '0x036cbd53842c5426634e7929541ec2318f3dcf7e': 'USDC', // USDC on Base Sepolia\n EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v: 'USDC', // USDC on Solana\n};\n\nexport function networkToChain(network: string): Chain | undefined {\n return NETWORK_TO_CHAIN[network.toLowerCase()];\n}\n\n/**\n * Resolve a requirement's asset to a symbol Rein knows. Tries, in order: the\n * asset field as a literal symbol (mock-first), `extra.symbol`, then known\n * contract addresses (exact case for Solana, lowercased for EVM), then any\n * caller-supplied address map.\n */\nexport function resolveAsset(\n requirement: PaymentRequirement,\n extraAddresses: Record<string, Asset> = {},\n): Asset | undefined {\n const direct = Asset.safeParse(requirement.asset.toUpperCase());\n if (direct.success) return direct.data;\n\n const symbol = requirement.extra?.['symbol'];\n if (typeof symbol === 'string') {\n const fromExtra = Asset.safeParse(symbol.toUpperCase());\n if (fromExtra.success) return fromExtra.data;\n }\n\n return (\n extraAddresses[requirement.asset] ??\n extraAddresses[requirement.asset.toLowerCase()] ??\n KNOWN_ASSET_ADDRESSES[requirement.asset] ??\n KNOWN_ASSET_ADDRESSES[requirement.asset.toLowerCase()]\n );\n}\n\n/**\n * Convert an atomic-unit amount to a normalized decimal string without floats,\n * e.g. (\"10000\", 6) -> \"0.01\". Stablecoins Rein supports all use 6 decimals;\n * a requirement can override via `extra.decimals`.\n */\nexport function atomicToDecimal(atomic: string, decimals: number): string {\n if (!/^\\d+$/.test(atomic)) throw new TypeError(`invalid atomic amount: ${atomic}`);\n if (decimals === 0) return atomic.replace(/^0+(?=\\d)/, '');\n const digits = atomic.padStart(decimals + 1, '0');\n const intPart = digits.slice(0, digits.length - decimals).replace(/^0+(?=\\d)/, '');\n const fracPart = digits.slice(digits.length - decimals).replace(/0+$/, '');\n return fracPart.length > 0 ? `${intPart}.${fracPart}` : intPart;\n}\n\n/**\n * The inverse of {@link atomicToDecimal}: a human-unit decimal string to atomic\n * units without floats, e.g. (\"0.05\", 6) -> \"50000\". Throws if the value has\n * more fraction digits than the asset carries (sub-atomic precision is a\n * pricing bug, not something to round silently).\n */\nexport function decimalToAtomic(decimal: string, decimals: number): string {\n if (!/^\\d+(\\.\\d+)?$/.test(decimal)) throw new TypeError(`invalid decimal amount: ${decimal}`);\n const dot = decimal.indexOf('.');\n const intPart = dot === -1 ? decimal : decimal.slice(0, dot);\n const fracPart = dot === -1 ? '' : decimal.slice(dot + 1);\n if (fracPart.length > decimals) {\n throw new TypeError(`amount ${decimal} has more than ${decimals} fraction digits`);\n }\n const atomic = intPart + fracPart.padEnd(decimals, '0');\n return atomic.replace(/^0+(?=\\d)/, '');\n}\n\nexport function requirementDecimals(requirement: PaymentRequirement): number {\n const decimals = requirement.extra?.['decimals'];\n return typeof decimals === 'number' && Number.isInteger(decimals) && decimals >= 0 ? decimals : 6;\n}\n\n/** A requirement the guard fully understood, mapped into Rein's domain. */\nexport interface ResolvedRequirement {\n requirement: PaymentRequirement;\n chain: Chain;\n asset: Asset;\n /** Human-unit decimal amount, e.g. \"0.01\". */\n amount: string;\n}\n\n/**\n * Pick the first offer the guard can govern: scheme `exact`, a network that\n * maps to a supported chain, and a resolvable asset. Returns undefined when\n * no offer qualifies — callers must treat that as fail-closed.\n */\nexport function selectRequirement(\n accepts: readonly PaymentRequirement[],\n extraAddresses: Record<string, Asset> = {},\n): ResolvedRequirement | undefined {\n for (const requirement of accepts) {\n if (requirement.scheme.toLowerCase() !== 'exact') continue;\n const chain = networkToChain(requirement.network);\n if (!chain) continue;\n const asset = resolveAsset(requirement, extraAddresses);\n if (!asset) continue;\n const amount = atomicToDecimal(requirement.maxAmountRequired, requirementDecimals(requirement));\n return { requirement, chain, asset, amount };\n }\n return undefined;\n}\n\n/** What the guard submits to the policy engine (the `/v1/evaluate` shape). */\nexport interface IntentSubmission {\n agentId: string;\n vendor: Vendor;\n resource: string;\n amount: string;\n asset: Asset;\n chain: Chain;\n taskContext?: TaskContext;\n}\n\n/** Build the evaluate payload for a resolved offer on a given request URL. */\nexport function toIntentSubmission(\n resolved: ResolvedRequirement,\n url: string,\n agentId: string,\n taskContext: TaskContext | undefined,\n): IntentSubmission {\n const parsed = new URL(url);\n return {\n agentId,\n vendor: {\n host: parsed.host,\n address: resolved.requirement.payTo,\n },\n resource: resolved.requirement.resource ?? parsed.pathname,\n amount: resolved.amount,\n asset: resolved.asset,\n chain: resolved.chain,\n taskContext,\n };\n}\n","import { z } from 'zod';\nimport { PaymentRequirement } from './x402.js';\n\n/**\n * x402 v2 wire dialect — CAIP-2 network ids, `PAYMENT-REQUIRED` /\n * `PAYMENT-SIGNATURE` / `PAYMENT-RESPONSE` headers, base64-JSON payloads.\n * Verified against the published spec (coinbase/x402\n * specs/x402-specification-v2.md + transports-v2/http.md, re-checked 2026-07)\n * and the live facilitator's /supported.\n *\n * Rein's internal requirement shape stays v1 (the zod contract in x402.ts);\n * v2 is a WIRE dialect converted at the edges. Inbound, the guard converts a\n * PAYMENT-REQUIRED quote into internal requirements. Outbound, it REWRAPS the\n * payer's v1 X-PAYMENT envelope into the v2 PaymentPayload: the scheme payload\n * (e.g. the signed EIP-3009 authorization) is byte-identical in both dialects,\n * so every Payer — mock, EIP-3009, session-signer — is v2-capable without\n * knowing v2 exists. The vendor side (@reinconsole/gate) re-exports these\n * helpers rather than owning its own copies.\n */\n\n/**\n * Known v1 network names → CAIP-2. EVM entries are chain-id math; the Solana\n * ids are what the live facilitator advertises. Unknown names pass through\n * lowercased, so two spellings of an UNKNOWN network still compare equal.\n */\nconst CAIP2_ALIASES: Record<string, string> = {\n base: 'eip155:8453',\n 'base-sepolia': 'eip155:84532',\n polygon: 'eip155:137',\n 'polygon-amoy': 'eip155:80002',\n bnb: 'eip155:56',\n bsc: 'eip155:56',\n solana: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n 'solana-devnet': 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',\n};\n\n/** The CAIP-2 id for a network name, or the lowercased name when unknown. */\nexport function caip2Of(network: string): string {\n const key = network.toLowerCase();\n return CAIP2_ALIASES[key] ?? key;\n}\n\n/** Do two network ids name the same chain, across the v1/CAIP-2 divide? */\nexport function sameNetwork(a: string, b: string): boolean {\n return caip2Of(a) === caip2Of(b);\n}\n\n/** x402 v2 PaymentRequirements (one entry of a 402's `accepts`). */\nexport const PaymentRequirementsV2 = z.object({\n scheme: z.string(),\n /** CAIP-2, e.g. \"eip155:84532\". */\n network: z.string(),\n /** Atomic units — v2's rename of v1's maxAmountRequired. */\n amount: z.string().regex(/^\\d+$/, 'atomic amount must be an integer string'),\n asset: z.string().min(1),\n payTo: z.string().min(1),\n maxTimeoutSeconds: z.number().optional(),\n extra: z.record(z.unknown()).optional(),\n});\nexport type PaymentRequirementsV2 = z.infer<typeof PaymentRequirementsV2>;\n\n/** v2 ResourceInfo — resource facts move out of the requirement in v2. */\nexport const ResourceInfoV2 = z.object({\n url: z.string(),\n description: z.string().optional(),\n mimeType: z.string().optional(),\n});\nexport type ResourceInfoV2 = z.infer<typeof ResourceInfoV2>;\n\n/** v2 PaymentRequired — the decoded PAYMENT-REQUIRED header. */\nexport const PaymentRequiredV2 = z.object({\n x402Version: z.literal(2),\n error: z.string().optional(),\n resource: ResourceInfoV2.optional(),\n accepts: z.array(PaymentRequirementsV2).min(1),\n extensions: z.record(z.unknown()).optional(),\n});\nexport type PaymentRequiredV2 = z.infer<typeof PaymentRequiredV2>;\n\n/** Convert Rein's internal (v1-shaped) requirement to the v2 wire shape. */\nexport function v2Requirements(requirement: PaymentRequirement): PaymentRequirementsV2 {\n return {\n scheme: requirement.scheme,\n network: caip2Of(requirement.network),\n amount: requirement.maxAmountRequired,\n asset: requirement.asset,\n payTo: requirement.payTo,\n ...(requirement.maxTimeoutSeconds !== undefined\n ? { maxTimeoutSeconds: requirement.maxTimeoutSeconds }\n : {}),\n ...(requirement.extra ? { extra: requirement.extra } : {}),\n };\n}\n\n/**\n * The inverse: a v2 offer (plus the 402's shared ResourceInfo) as an internal\n * requirement. The CAIP-2 network id is kept verbatim — networkToChain and\n * chainIdForNetwork resolve both dialects, and sameNetwork compares across\n * them, so nothing downstream needs the v1 spelling back.\n */\nexport function requirementFromV2(\n offer: PaymentRequirementsV2,\n resource?: ResourceInfoV2,\n): PaymentRequirement {\n return PaymentRequirement.parse({\n scheme: offer.scheme,\n network: offer.network,\n maxAmountRequired: offer.amount,\n payTo: offer.payTo,\n asset: offer.asset,\n ...(resource !== undefined ? { resource: resource.url } : {}),\n ...(resource?.description !== undefined ? { description: resource.description } : {}),\n ...(resource?.mimeType !== undefined ? { mimeType: resource.mimeType } : {}),\n ...(offer.maxTimeoutSeconds !== undefined\n ? { maxTimeoutSeconds: offer.maxTimeoutSeconds }\n : {}),\n ...(offer.extra ? { extra: offer.extra } : {}),\n });\n}\n\n/** The full v2 PaymentRequired for one quoted requirement. */\nexport function buildPaymentRequiredV2(\n requirement: PaymentRequirement,\n error: string,\n): PaymentRequiredV2 {\n return {\n x402Version: 2,\n error,\n ...(requirement.resource\n ? {\n resource: {\n url: requirement.resource,\n ...(requirement.description ? { description: requirement.description } : {}),\n ...(requirement.mimeType ? { mimeType: requirement.mimeType } : {}),\n },\n }\n : {}),\n accepts: [v2Requirements(requirement)],\n extensions: {},\n };\n}\n\n/** The one codec every x402 header uses: base64 of compact JSON. */\nexport function encodeBase64Json(value: unknown): string {\n return Buffer.from(JSON.stringify(value)).toString('base64');\n}\n\n/** Base64 JSON → value, or undefined when the header is not decodable. */\nfunction decodeBase64Json(raw: string): unknown {\n try {\n return JSON.parse(Buffer.from(raw, 'base64').toString('utf8'));\n } catch {\n return undefined;\n }\n}\n\n/**\n * Decode a PAYMENT-REQUIRED response header. Lenient by design: a missing,\n * undecodable, or non-v2 header returns undefined so callers fall back to the\n * v1 body — a garbled v2 advertisement must not break a dual-stack 402.\n */\nexport function parsePaymentRequiredHeader(raw: string | null): PaymentRequiredV2 | undefined {\n if (raw === null) return undefined;\n const parsed = PaymentRequiredV2.safeParse(decodeBase64Json(raw));\n return parsed.success ? parsed.data : undefined;\n}\n\n/** The v1 X-PAYMENT envelope, as far as the v2 rewrap needs to see it. */\nconst V1Envelope = z.object({\n x402Version: z.literal(1),\n scheme: z.string(),\n network: z.string(),\n payload: z.record(z.unknown()),\n});\n\n/**\n * Rewrap a payer's v1 X-PAYMENT header as a v2 PaymentPayload for the\n * PAYMENT-SIGNATURE header. The scheme payload transfers verbatim (what the\n * payer signed is envelope-independent); the chosen requirement rides along\n * as `accepted` per the v2 spec. A header that is already a v2 envelope\n * passes through unchanged. Throws TypeError on anything else — a payer\n * returning an unrecognizable header is a programming error, not wire input.\n */\nexport function wrapPaymentV2(\n paymentHeader: string,\n requirement: PaymentRequirement,\n resource?: ResourceInfoV2,\n): string {\n const decoded = decodeBase64Json(paymentHeader);\n if ((decoded as { x402Version?: unknown } | undefined)?.x402Version === 2) {\n return paymentHeader;\n }\n const v1 = V1Envelope.safeParse(decoded);\n if (!v1.success) {\n throw new TypeError(`cannot rewrap payment header as x402 v2: ${v1.error.message}`);\n }\n return encodeBase64Json({\n x402Version: 2,\n ...(resource !== undefined ? { resource } : {}),\n accepted: v2Requirements(requirement),\n payload: v1.data.payload,\n extensions: {},\n });\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n AgentId,\n Receipt,\n newId,\n type Asset,\n type Decision,\n type PaymentIntent,\n type ReceiptSettlement,\n type TaskContext,\n} from '@reinconsole/core';\nimport { EngineClient, type FetchLike } from './client.js';\nimport { PaymentBlockedError, UnsupportedRequirementError } from './errors.js';\nimport {\n PaymentRequired,\n selectRequirement,\n toIntentSubmission,\n type PaymentRequirement,\n type ResolvedRequirement,\n} from './x402.js';\nimport {\n parsePaymentRequiredHeader,\n requirementFromV2,\n wrapPaymentV2,\n type ResourceInfoV2,\n} from './x402v2.js';\n\n/**\n * Builds the `X-PAYMENT` header for an allowed intent. Mock payers and the\n * local EIP-3009 payer ignore the decision; the session-key signer tier\n * requires it — the {intent, decision} pair is the engine-signed voucher the\n * signer verifies before any key is put to work.\n */\nexport type Payer = (\n requirement: PaymentRequirement,\n intent: PaymentIntent,\n decision: Decision,\n) => string | Promise<string>;\n\nexport interface GuardOptions {\n /** Policy engine base URL, e.g. \"http://localhost:8787\". */\n engineUrl: string;\n /** The agent this guard speaks for (must be registered with the engine). */\n agentId: string;\n /** Base fetch the guard wraps by default (vendor-facing). Defaults to global fetch. */\n fetch?: FetchLike;\n /** Transport for talking to the policy engine. Defaults to global fetch. */\n engineFetch?: FetchLike;\n /** Task context attached to every intent unless overridden via withTask(). */\n taskContext?: TaskContext;\n /**\n * What a blocked payment looks like to the caller: 'throw' (default) raises\n * PaymentBlockedError; 'respond' returns a synthetic 402 JSON response, for\n * agent loops that prefer inspecting responses over catching.\n */\n onBlocked?: 'throw' | 'respond';\n /** If set, the guard settles allowed payments itself (pay + retry). */\n payer?: Payer;\n /** Extra token-address -> symbol mappings for asset resolution. */\n assetAddresses?: Record<string, Asset>;\n /** Called once per receipt, as it is recorded. */\n onReceipt?: (receipt: Receipt) => void;\n}\n\n/**\n * The Rein guard: wrap an agent's fetch once, and every x402 paywall it hits\n * is policy-checked before any payment exists, with a receipt either way.\n *\n * Layering: the guard wraps the BASE fetch, underneath any x402 payment\n * library. The first (unpaid) request surfaces the 402; the guard evaluates\n * it and either blocks — so the payment layer never sees the paywall — or\n * releases the 402 upward. The payment layer's `X-PAYMENT` retry then flows\n * back through the guard, which attaches the settlement to the receipt.\n * Alternatively, pass a `payer` and the guard completes the payment itself.\n */\nexport class Guard {\n readonly client: EngineClient;\n private readonly options: GuardOptions;\n private readonly baseFetch: FetchLike;\n private readonly task = new AsyncLocalStorage<TaskContext>();\n private readonly log: Receipt[] = [];\n /** Allowed-but-unsettled receipts awaiting the payment layer's retry, by URL. */\n private readonly pendingByUrl = new Map<string, Receipt>();\n\n constructor(options: GuardOptions) {\n AgentId.parse(options.agentId);\n this.options = options;\n const f = options.fetch ?? globalThis.fetch;\n this.baseFetch = (input, init) => f(input, init);\n this.client = new EngineClient({ baseUrl: options.engineUrl, fetch: options.engineFetch });\n }\n\n /** Every receipt this guard has recorded, oldest first. */\n receipts(): readonly Receipt[] {\n return this.log;\n }\n\n /** Run `fn` with a task context attached to every intent submitted inside it. */\n withTask<T>(context: TaskContext, fn: () => T): T {\n return this.task.run({ ...this.options.taskContext, ...context }, fn);\n }\n\n /**\n * The one-liner: returns a fetch-compatible function that enforces policy on\n * every x402 paywall. Wraps the guard's base fetch unless one is passed.\n */\n wrap(fetchImpl?: FetchLike): FetchLike {\n const inner: FetchLike = fetchImpl ? (input, init) => fetchImpl(input, init) : this.baseFetch;\n\n return async (input, init) => {\n const url = requestUrl(input);\n // A request that already carries a payment (either dialect's header) is\n // the release leg of an intent this guard allowed — pass it through and\n // capture settlement.\n if (\n readHeader(input, init, 'X-PAYMENT') !== null ||\n readHeader(input, init, 'PAYMENT-SIGNATURE') !== null\n ) {\n const res = await inner(input, init);\n this.settlePending(url, res);\n return res;\n }\n\n const res = await inner(input, init);\n if (res.status !== 402) return res;\n\n const paywall = await parse402(res, this.options.assetAddresses);\n // Not an x402 paywall — nothing to govern, hand it back untouched.\n if (!paywall) return res;\n\n const { resolved, wire, resource } = paywall;\n if (!resolved) throw new UnsupportedRequirementError(url);\n\n const taskContext = this.task.getStore() ?? this.options.taskContext;\n const submission = toIntentSubmission(resolved, url, this.options.agentId, taskContext);\n const { intent, decision } = await this.client.evaluate(submission);\n\n if (decision.outcome !== 'allow') {\n const receipt = this.record(intent, decision, url, init);\n if (this.options.onBlocked === 'respond') return blockedResponse(receipt);\n throw new PaymentBlockedError(intent, decision, receipt);\n }\n\n if (!this.options.payer) {\n // Advisory mode: release the 402 to the payment layer above us; its\n // X-PAYMENT retry will come back through and settle the receipt.\n const receipt = this.record(intent, decision, url, init);\n this.pendingByUrl.set(url, receipt);\n return res;\n }\n\n // The payer always produces the v1 envelope it knows; on a v2 paywall\n // the guard rewraps it (same signed payload, v2 PaymentPayload around\n // it) and pays on the v2 header. Every payer is v2-capable this way.\n const paymentHeader = await this.options.payer(resolved.requirement, intent, decision);\n const retry = await inner(\n input,\n wire === 2\n ? withHeader(\n input,\n init,\n 'PAYMENT-SIGNATURE',\n wrapPaymentV2(paymentHeader, resolved.requirement, resource),\n )\n : withHeader(input, init, 'X-PAYMENT', paymentHeader),\n );\n this.record(intent, decision, url, init, parseSettlement(retry));\n return retry;\n };\n }\n\n private record(\n intent: PaymentIntent,\n decision: Decision,\n url: string,\n init: RequestInit | undefined,\n settlement?: ReceiptSettlement,\n ): Receipt {\n const receipt = Receipt.parse({\n id: newId('rcp'),\n agentId: intent.agentId,\n intentId: intent.id,\n decisionId: decision.id,\n outcome: decision.outcome,\n url,\n method: init?.method ?? 'GET',\n vendorHost: intent.vendor.host,\n amount: intent.amount,\n asset: intent.asset,\n chain: intent.chain,\n taskContext: intent.taskContext,\n reason: decision.reason,\n settlement,\n createdAt: new Date(),\n });\n this.log.push(receipt);\n this.options.onReceipt?.(receipt);\n return receipt;\n }\n\n private settlePending(url: string, res: Response): void {\n const receipt = this.pendingByUrl.get(url);\n if (!receipt || !res.ok) return;\n const settlement = parseSettlement(res);\n if (settlement) receipt.settlement = settlement;\n this.pendingByUrl.delete(url);\n }\n}\n\n/** Convenience factory mirroring the docs: `const guard = createGuard({...})`. */\nexport function createGuard(options: GuardOptions): Guard {\n return new Guard(options);\n}\n\n/** What a 402 offered, in whichever dialect the guard could govern. */\ninterface ParsedPaywall {\n /** The offer the guard selected, or undefined when none qualifies. */\n resolved: ResolvedRequirement | undefined;\n /** Which wire dialect to pay on: 2 = PAYMENT-SIGNATURE, 1 = X-PAYMENT. */\n wire: 1 | 2;\n /** The v2 402's shared resource info, echoed into the payment envelope. */\n resource?: ResourceInfoV2;\n}\n\n/**\n * Read a 402 in both dialects. v2 (the PAYMENT-REQUIRED header) is preferred\n * when it carries an offer the guard can govern; otherwise the v1 body gets\n * its chance — a dual-stack vendor is served on whichever channel works.\n * Returns undefined when neither channel is x402 at all (not a paywall).\n */\nasync function parse402(\n res: Response,\n assetAddresses: Record<string, Asset> | undefined,\n): Promise<ParsedPaywall | undefined> {\n const v2 = parsePaymentRequiredHeader(res.headers.get('PAYMENT-REQUIRED'));\n if (v2) {\n const resolved = selectRequirement(\n v2.accepts.map((offer) => requirementFromV2(offer, v2.resource)),\n assetAddresses,\n );\n if (resolved) {\n return v2.resource !== undefined\n ? { resolved, wire: 2, resource: v2.resource }\n : { resolved, wire: 2 };\n }\n }\n\n const body = await res\n .clone()\n .json()\n .catch(() => undefined);\n const parsed = PaymentRequired.safeParse(body);\n if (parsed.success) {\n return { resolved: selectRequirement(parsed.data.accepts, assetAddresses), wire: 1 };\n }\n // A v2 header alone still marks this as a paywall — one the guard must\n // fail closed on if nothing in it was governable.\n return v2 ? { resolved: undefined, wire: 2 } : undefined;\n}\n\nfunction requestUrl(input: string | URL | Request): string {\n if (typeof input === 'string') return input;\n if (input instanceof URL) return input.toString();\n return input.url;\n}\n\nfunction readHeader(\n input: string | URL | Request,\n init: RequestInit | undefined,\n name: string,\n): string | null {\n const source = init?.headers ?? (input instanceof Request ? input.headers : undefined);\n return source === undefined ? null : new Headers(source).get(name);\n}\n\nfunction withHeader(\n input: string | URL | Request,\n init: RequestInit | undefined,\n name: string,\n value: string,\n): RequestInit {\n const headers = new Headers(\n init?.headers ?? (input instanceof Request ? input.headers : undefined),\n );\n headers.set(name, value);\n return { ...init, headers };\n}\n\n/**\n * Decode the vendor's settlement header — `X-PAYMENT-RESPONSE` (v1) or\n * `PAYMENT-RESPONSE` (v2); base64 JSON per the x402 spec, plain JSON\n * tolerated mock-first. Absent or undecodable -> undefined.\n */\nfunction parseSettlement(res: Response): ReceiptSettlement | undefined {\n const raw = res.headers.get('X-PAYMENT-RESPONSE') ?? res.headers.get('PAYMENT-RESPONSE');\n if (raw === null) return undefined;\n let payload: unknown;\n try {\n payload = JSON.parse(raw);\n } catch {\n try {\n payload = JSON.parse(Buffer.from(raw, 'base64').toString('utf8'));\n } catch {\n return { raw };\n }\n }\n const record =\n typeof payload === 'object' && payload !== null ? (payload as Record<string, unknown>) : {};\n return {\n // A failed v2 settle carries transaction: \"\" — no tx is no txHash.\n txHash:\n typeof record['transaction'] === 'string' && record['transaction'] !== ''\n ? record['transaction']\n : undefined,\n networkId: typeof record['network'] === 'string' ? record['network'] : undefined,\n raw,\n };\n}\n\nfunction blockedResponse(receipt: Receipt): Response {\n return new Response(\n JSON.stringify({\n error: 'payment_blocked_by_rein',\n outcome: receipt.outcome,\n reason: receipt.reason,\n intentId: receipt.intentId,\n decisionId: receipt.decisionId,\n receiptId: receipt.id,\n }),\n {\n status: 402,\n headers: { 'content-type': 'application/json', 'x-rein-outcome': receipt.outcome },\n },\n );\n}\n","import {\n createPublicClient,\n erc20Abi,\n http,\n type Address,\n type Hex,\n type HttpTransport,\n type PublicClient,\n} from 'viem';\nimport { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';\nimport { baseSepolia } from 'viem/chains';\n\n/** USDC (FiatTokenV2) on Base Sepolia. */\nexport const BASE_SEPOLIA_USDC: Address = '0x036CbD53842c5426634e7929541eC2318f3dCF7e';\n\n/** Circle's testnet faucet — funds Base Sepolia USDC for free. */\nexport const CIRCLE_FAUCET_URL = 'https://faucet.circle.com';\n\nexport const basescanTxUrl = (txHash: string): string =>\n `https://sepolia.basescan.org/tx/${txHash}`;\n\nexport interface GeneratedWallet {\n privateKey: Hex;\n address: Address;\n}\n\n/** A fresh local account — fund it with faucet USDC; it never needs ETH. */\nexport function generateWallet(): GeneratedWallet {\n const privateKey = generatePrivateKey();\n return { privateKey, address: privateKeyToAccount(privateKey).address };\n}\n\nexport type BaseSepoliaClient = PublicClient<HttpTransport, typeof baseSepolia>;\n\nexport function createBaseSepoliaClient(rpcUrl?: string): BaseSepoliaClient {\n return createPublicClient({ chain: baseSepolia, transport: http(rpcUrl) });\n}\n\n/** Atomic-unit USDC balance (6 decimals). */\nexport async function getUsdcBalance(\n client: BaseSepoliaClient,\n address: Address,\n usdc: Address = BASE_SEPOLIA_USDC,\n): Promise<bigint> {\n return client.readContract({\n address: usdc,\n abi: erc20Abi,\n functionName: 'balanceOf',\n args: [address],\n });\n}\n","import {\n PaymentRequirement,\n buildPaymentRequiredV2,\n encodeBase64Json,\n sameNetwork,\n v2Requirements,\n type FetchLike,\n} from '@reinconsole/sdk';\nimport { RailsError } from './errors.js';\nimport type { FacilitatorClient } from './facilitator.js';\nimport { BASE_SEPOLIA_USDC } from './wallet.js';\nimport { decodeAnyPaymentHeader, encodeSettlementHeader } from './wire.js';\n\nexport interface RealVendorOptions {\n facilitator: FacilitatorClient;\n /** Price in atomic units (e.g. \"10000\" = 0.01 USDC at 6 decimals). */\n atomicPrice: string;\n /** Where the vendor wants to be paid (a real EVM address). */\n payTo: string;\n network?: string;\n /** Token contract address. Defaults to USDC on Base Sepolia. */\n asset?: string;\n description?: string;\n maxTimeoutSeconds?: number;\n /** EIP-712 domain hints for the payer. Defaults to Base Sepolia USDC's. */\n extra?: Record<string, unknown>;\n /** JSON body served once payment settles. */\n body?: unknown;\n /**\n * Which x402 dialect the vendor's 402s advertise. 'v1' (default) is the\n * classic JSON body; 'dual' adds the v2 PAYMENT-REQUIRED header beside it;\n * 'v2' advertises ONLY the header (the body is not x402) — a strict v2\n * vendor for proving clients need no v1 fallback. Payments are ACCEPTED in\n * both dialects (PAYMENT-SIGNATURE or X-PAYMENT) regardless of this option,\n * mirroring the gate.\n */\n advertise?: 'v1' | 'dual' | 'v2';\n}\n\nexport interface VendorCall {\n url: string;\n payment: string | null;\n}\n\nexport interface RealVendor {\n /** Drop-in fetch for the guard's vendor-facing side. */\n fetch: FetchLike;\n /** Every request the vendor saw, in order. */\n calls: VendorCall[];\n /** The payment requirement this vendor quotes for a given URL. */\n requirementFor(url: string): PaymentRequirement;\n}\n\n/**\n * An in-process x402 vendor wired to a REAL facilitator: quotes a 402 with\n * payment requirements until the request carries a payment, then verifies and\n * settles through the facilitator — a real on-chain USDC transfer — and serves\n * the content with the settlement (tx hash included) in the response headers.\n * Dual-stack like the gate: payments are accepted on X-PAYMENT (v1) and\n * PAYMENT-SIGNATURE (v2) alike, and `advertise` picks which dialect the 402s\n * quote in.\n *\n * Unlike the mock vendor, the quoted requirement is fully populated: the\n * hosted facilitator validates it strictly (resource must be a URL,\n * description/mimeType/maxTimeoutSeconds required, real addresses).\n */\nexport function createRealVendor(options: RealVendorOptions): RealVendor {\n const calls: VendorCall[] = [];\n const advertise = options.advertise ?? 'v1';\n\n const requirementFor = (url: string): PaymentRequirement =>\n PaymentRequirement.parse({\n scheme: 'exact',\n network: options.network ?? 'base-sepolia',\n maxAmountRequired: options.atomicPrice,\n resource: url,\n description: options.description ?? '',\n mimeType: 'application/json',\n payTo: options.payTo,\n maxTimeoutSeconds: options.maxTimeoutSeconds ?? 300,\n asset: options.asset ?? BASE_SEPOLIA_USDC,\n extra: options.extra ?? { name: 'USDC', version: '2' },\n });\n\n const paymentRequired = (url: string, error: string): Response => {\n const requirement = requirementFor(url);\n // A strict v2 vendor's body is deliberately NOT x402 — everything the\n // protocol needs rides the PAYMENT-REQUIRED header.\n const body =\n advertise === 'v2' ? { error } : { x402Version: 1, accepts: [requirement], error };\n return new Response(JSON.stringify(body), {\n status: 402,\n headers: {\n 'content-type': 'application/json',\n ...(advertise !== 'v1'\n ? { 'PAYMENT-REQUIRED': encodeBase64Json(buildPaymentRequiredV2(requirement, error)) }\n : {}),\n },\n });\n };\n\n const fetch: FetchLike = async (input, init) => {\n const url =\n typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url;\n const headers = new Headers(\n init?.headers ?? (input instanceof Request ? input.headers : undefined),\n );\n // Dual-stack: v2 payers send PAYMENT-SIGNATURE, v1 payers X-PAYMENT.\n const payment = headers.get('PAYMENT-SIGNATURE') ?? headers.get('X-PAYMENT');\n calls.push({ url, payment });\n\n if (payment === null) return paymentRequired(url, 'payment is required');\n\n const requirement = requirementFor(url);\n let decoded;\n try {\n decoded = decodeAnyPaymentHeader(payment);\n } catch (err) {\n if (err instanceof RailsError) return paymentRequired(url, err.message);\n throw err;\n }\n\n // Compared through CAIP-2 normalization: a v2 envelope naming\n // \"eip155:84532\" satisfies this requirement's v1 \"base-sepolia\".\n if (!sameNetwork(decoded.network, requirement.network)) {\n return paymentRequired(\n url,\n `payment is on \"${decoded.network}\" but the requirement wants \"${requirement.network}\"`,\n );\n }\n\n // Requirements travel to the facilitator in the payment's own dialect —\n // a v2 envelope is verified against v2-shaped (amount/CAIP-2) requirements.\n const requirements = decoded.version === 2 ? v2Requirements(requirement) : requirement;\n const verified = await options.facilitator.verify(decoded.envelope, requirements);\n if (!verified.isValid) {\n return paymentRequired(url, verified.invalidReason ?? 'payment verification failed');\n }\n\n const settled = await options.facilitator.settle(decoded.envelope, requirements);\n if (!settled.success) {\n return paymentRequired(url, settled.errorReason ?? 'payment settlement failed');\n }\n\n const settlement = encodeSettlementHeader(settled);\n return new Response(JSON.stringify(options.body ?? { ok: true }), {\n status: 200,\n headers: {\n 'content-type': 'application/json',\n // Both dialect names carry the same base64 settlement object; the\n // strict v2 vendor sets ONLY the v2 name.\n ...(advertise !== 'v2' ? { 'X-PAYMENT-RESPONSE': settlement } : {}),\n 'PAYMENT-RESPONSE': settlement,\n },\n });\n };\n\n return { fetch, calls, requirementFor };\n}\n","import { EventEmitter } from 'node:events';\nimport { parseAbi, type Address, type Hex } from 'viem';\nimport { ReinEvent, type Agent, type Chain, type PaymentIntent } from '@reinconsole/core';\nimport { atomicToDecimal } from '@reinconsole/sdk';\nimport { intentNonce } from './nonce.js';\nimport { BASE_SEPOLIA_USDC } from './wallet.js';\n\n/** The slice of the policy engine the indexer subscribes to (NATS in prod). */\nexport interface EngineEvents {\n onEvent(handler: (event: ReinEvent) => void): void;\n}\n\n/** The two FiatTokenV2 events one transferWithAuthorization settlement emits. */\nexport const railEventsAbi = parseAbi([\n 'event Transfer(address indexed from, address indexed to, uint256 value)',\n 'event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce)',\n]);\n\n/** The decoded log shape the indexer consumes. */\nexport interface RailLog {\n eventName: 'Transfer' | 'AuthorizationUsed';\n transactionHash: Hex | null;\n blockNumber: bigint | null;\n args: {\n from?: Address;\n to?: Address;\n value?: bigint;\n authorizer?: Address;\n nonce?: Hex;\n };\n}\n\n/**\n * What the indexer needs from a chain: current head + decoded event logs.\n * viem's PublicClient satisfies this structurally; tests inject a fake.\n */\nexport interface ChainReader {\n getBlockNumber(): Promise<bigint>;\n getLogs(args: {\n address: Address;\n events: typeof railEventsAbi;\n fromBlock: bigint;\n toBlock: bigint;\n }): Promise<readonly RailLog[]>;\n}\n\nexport interface OnchainIndexerOptions {\n client: ChainReader;\n /** Token contract whose transfers are watched. Defaults to Base Sepolia USDC. */\n usdcAddress?: Address;\n /** The Rein chain tag recorded on events (testnets map to mainnet). */\n chain?: Chain;\n /**\n * Directory of managed agents and their wallets (the agents service in\n * prod). Called per transfer, so agents registered later are still seen.\n */\n agents: () => readonly Agent[];\n /** Recorded as SettledPayment.facilitator on reconciled payments. */\n facilitator?: string;\n pollIntervalMs?: number;\n /** First block to scan. Defaults to the chain head at start(). */\n fromBlock?: bigint;\n /** Token decimals for amount conversion. */\n decimals?: number;\n /** RPC errors are retried next tick; surface them here if you care. */\n onError?: (err: unknown) => void;\n}\n\n/** A `shadow.spend` event, extracted for convenience accessors. */\nexport type ShadowSpend = Extract<ReinEvent, { type: 'shadow.spend' }>;\n\n/**\n * The real indexer: polls token logs on Base Sepolia and classifies every\n * transfer that leaves a managed agent wallet — the same semantics as the\n * mock indexer, against a real chain.\n *\n * Reconciliation is memo-first via the EIP-3009 nonce: Rein's payer derives\n * the authorization nonce from the intent id, and settlement emits\n * `AuthorizationUsed(authorizer, nonce)` alongside the `Transfer`. A transfer\n * whose nonce resolves to an allowed, unsettled intent of the same agent is\n * `payment.settled`; anything else leaving a managed wallet — random nonce,\n * replay, plain transfer, no ALLOW behind it — is `shadow.spend`. There is no\n * fuzzy fallback on-chain: the nonce IS the memo.\n */\nexport class OnchainIndexer {\n private readonly options: OnchainIndexerOptions;\n private readonly bus = new EventEmitter();\n private readonly emitted: ReinEvent[] = [];\n /** Every intent the engine has seen, by id (from `intent.created`). */\n private readonly intents = new Map<string, PaymentIntent>();\n /** Intents with an ALLOW decision, by id. */\n private readonly allowed = new Map<string, PaymentIntent>();\n private readonly settledIntents = new Set<string>();\n /** Expected on-chain nonce -> intent id, for every allowed intent. */\n private readonly nonceToIntent = new Map<string, string>();\n private timer: NodeJS.Timeout | undefined;\n private nextBlock: bigint | undefined;\n private scanning = false;\n\n constructor(options: OnchainIndexerOptions) {\n this.options = options;\n }\n\n /** Subscribe to a policy engine's event stream to learn which intents were allowed. */\n connectEngine(engine: EngineEvents): void {\n engine.onEvent((event) => {\n if (event.type === 'intent.created') {\n this.intents.set(event.intent.id, event.intent);\n } else if (event.type === 'decision.made' && event.decision.outcome === 'allow') {\n const intent = this.intents.get(event.decision.intentId);\n if (intent) {\n this.allowed.set(intent.id, intent);\n this.nonceToIntent.set(intentNonce(intent.id).toLowerCase(), intent.id);\n }\n }\n });\n }\n\n /** Begin polling. Scans from `fromBlock` (default: the current head). */\n async start(): Promise<void> {\n if (this.timer !== undefined) return;\n this.nextBlock = this.options.fromBlock ?? (await this.options.client.getBlockNumber()) + 1n;\n const interval = this.options.pollIntervalMs ?? 3000;\n this.timer = setInterval(() => void this.scan(), interval);\n this.timer.unref?.();\n }\n\n stop(): void {\n if (this.timer !== undefined) clearInterval(this.timer);\n this.timer = undefined;\n }\n\n onEvent(handler: (event: ReinEvent) => void): void {\n this.bus.on('event', handler);\n }\n\n /** Everything the indexer has emitted, oldest first. */\n events(): readonly ReinEvent[] {\n return this.emitted;\n }\n\n settledPayments() {\n return this.emitted.flatMap((e) => (e.type === 'payment.settled' ? [e.payment] : []));\n }\n\n shadowSpends(): ShadowSpend[] {\n return this.emitted.filter((e): e is ShadowSpend => e.type === 'shadow.spend');\n }\n\n /** Resolve when an event (past or future) matches; reject on timeout. */\n waitFor(predicate: (event: ReinEvent) => boolean, timeoutMs = 90_000): Promise<ReinEvent> {\n const existing = this.emitted.find(predicate);\n if (existing) return Promise.resolve(existing);\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.bus.off('event', handler);\n reject(new Error(`indexer: no matching event within ${timeoutMs}ms`));\n }, timeoutMs);\n const handler = (event: ReinEvent) => {\n if (!predicate(event)) return;\n clearTimeout(timeout);\n this.bus.off('event', handler);\n resolve(event);\n };\n this.bus.on('event', handler);\n });\n }\n\n /** One poll: fetch logs since the last scanned block and classify them. */\n async scan(): Promise<void> {\n if (this.scanning || this.nextBlock === undefined) return;\n this.scanning = true;\n try {\n const head = await this.options.client.getBlockNumber();\n if (head < this.nextBlock) return;\n const logs = await this.options.client.getLogs({\n address: this.options.usdcAddress ?? BASE_SEPOLIA_USDC,\n events: railEventsAbi,\n fromBlock: this.nextBlock,\n toBlock: head,\n });\n for (const tx of groupByTx(logs)) this.observe(tx);\n // Only advance once the whole range processed — an RPC error above\n // leaves the range to be retried on the next tick.\n this.nextBlock = head + 1n;\n } catch (err) {\n this.options.onError?.(err);\n } finally {\n this.scanning = false;\n }\n }\n\n private emit(event: ReinEvent): void {\n const parsed = ReinEvent.parse(event);\n this.emitted.push(parsed);\n this.bus.emit('event', parsed);\n }\n\n private agentFor(from: string): string | undefined {\n const chain = this.options.chain ?? 'base';\n for (const agent of this.options.agents()) {\n const owns = agent.wallets.some((w) => w.chain === chain && sameAddress(w.address, from));\n if (owns) return agent.id;\n }\n return undefined;\n }\n\n private observe(tx: TxLogs): void {\n for (const transfer of tx.transfers) {\n const from = transfer.args.from;\n if (from === undefined || transfer.args.value === undefined) continue;\n const agentId = this.agentFor(from);\n // Spend from a wallet Rein does not manage is someone else's problem.\n if (agentId === undefined) continue;\n\n const intent = this.reconcile(tx, from, agentId);\n const at = new Date();\n if (intent) {\n this.settledIntents.add(intent.id);\n this.emit({\n type: 'payment.settled',\n at,\n payment: {\n intentId: intent.id,\n txHash: tx.txHash,\n chain: this.options.chain ?? 'base',\n blockNumber: transfer.blockNumber ?? 0n,\n facilitator: this.options.facilitator,\n confirmedAt: at,\n },\n });\n continue;\n }\n\n this.emit({\n type: 'shadow.spend',\n at,\n agentId,\n txHash: tx.txHash,\n chain: this.options.chain ?? 'base',\n amount: atomicToDecimal(transfer.args.value.toString(), this.options.decimals ?? 6),\n });\n }\n }\n\n private reconcile(tx: TxLogs, from: string, agentId: string): PaymentIntent | undefined {\n for (const auth of tx.authorizations) {\n const { authorizer, nonce } = auth.args;\n if (authorizer === undefined || nonce === undefined) continue;\n if (!sameAddress(authorizer, from)) continue;\n const intentId = this.nonceToIntent.get(nonce.toLowerCase());\n if (intentId === undefined) continue;\n const intent = this.allowed.get(intentId);\n if (intent && intent.agentId === agentId && !this.settledIntents.has(intent.id)) {\n return intent;\n }\n }\n return undefined;\n }\n}\n\ninterface TxLogs {\n txHash: string;\n transfers: RailLog[];\n authorizations: RailLog[];\n}\n\nfunction groupByTx(logs: readonly RailLog[]): TxLogs[] {\n const byTx = new Map<string, TxLogs>();\n for (const log of logs) {\n if (log.transactionHash === null) continue;\n let tx = byTx.get(log.transactionHash);\n if (!tx) {\n tx = { txHash: log.transactionHash, transfers: [], authorizations: [] };\n byTx.set(log.transactionHash, tx);\n }\n (log.eventName === 'Transfer' ? tx.transfers : tx.authorizations).push(log);\n }\n return [...byTx.values()];\n}\n\n/** EVM addresses compare case-insensitively. */\nfunction sameAddress(a: string, b: string): boolean {\n return a === b || a.toLowerCase() === b.toLowerCase();\n}\n"],"mappings":"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","names":["parsed","z","z","z","z","z","z","z","z","privateKeyToAccount"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reinconsole/x402-rails",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Real x402 rails for Rein — EIP-3009 payer, hosted-facilitator client, and on-chain indexer for Base Sepolia.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/bugiiiii11/rein#readme",
@@ -43,15 +43,15 @@
43
43
  "dependencies": {
44
44
  "viem": "^2.47.0",
45
45
  "zod": "^3.24.1",
46
- "@reinconsole/sdk": "^0.1.0",
47
- "@reinconsole/core": "^0.1.0"
46
+ "@reinconsole/core": "^0.1.1",
47
+ "@reinconsole/sdk": "^0.1.1"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@types/node": "^22.10.0",
51
51
  "tsup": "^8.3.5",
52
52
  "typescript": "^5.7.2",
53
53
  "vitest": "^2.1.8",
54
- "@reinconsole/policy-engine": "0.1.0"
54
+ "@reinconsole/policy-engine": "0.1.1"
55
55
  },
56
56
  "scripts": {
57
57
  "build": "tsup",