@reinconsole/gate 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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  The supply side of **[Rein](https://github.com/bugiiiii11/rein)** — vendor-side [x402](https://www.x402.org) monetization middleware. Price your routes once and every payment into your API is quoted, cross-checked, screened, rate-limited, settled, and receipted before your handler runs.
4
4
 
5
- > **Status: v0.1 — early open-source infrastructure, live on testnet.** Verified live on Base Sepolia against the hosted x402.org facilitator. APIs may change before 1.0. See it running: [Rein console](https://reinconsole-production.up.railway.app/).
5
+ > **Status: v0.1 — early open-source infrastructure, live on testnet.** Verified live on Base Sepolia against the hosted x402.org facilitator. APIs may change before 1.0. See it running: [Rein console](https://app.reinconsole.com).
6
6
 
7
7
  ## Install
8
8
 
package/dist/index.cjs CHANGED
@@ -15,59 +15,19 @@ var GateError = class extends Error {
15
15
  this.code = code;
16
16
  this.name = "GateError";
17
17
  this.retryAfterSeconds = options.retryAfterSeconds;
18
+ this.paymentResponse = options.paymentResponse;
18
19
  }
19
20
  code;
20
21
  /** Seconds until the refused payment could be admitted (throttle codes). */
21
22
  retryAfterSeconds;
23
+ /**
24
+ * The rails' own failed settlement response, when there is one (a
25
+ * facilitator settle that answered `success: false`). Refusals of v2
26
+ * payments relay it verbatim in the PAYMENT-RESPONSE header instead of a
27
+ * synthesized one, so the payer sees the facilitator's real errorReason.
28
+ */
29
+ paymentResponse;
22
30
  };
23
-
24
- // src/v2.ts
25
- var CAIP2_ALIASES = {
26
- base: "eip155:8453",
27
- "base-sepolia": "eip155:84532",
28
- polygon: "eip155:137",
29
- "polygon-amoy": "eip155:80002",
30
- bnb: "eip155:56",
31
- bsc: "eip155:56",
32
- solana: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
33
- "solana-devnet": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"
34
- };
35
- function caip2Of(network) {
36
- const key = network.toLowerCase();
37
- return CAIP2_ALIASES[key] ?? key;
38
- }
39
- function sameNetwork(a, b) {
40
- return caip2Of(a) === caip2Of(b);
41
- }
42
- function v2Requirements(requirement) {
43
- return {
44
- scheme: requirement.scheme,
45
- network: caip2Of(requirement.network),
46
- amount: requirement.maxAmountRequired,
47
- asset: requirement.asset,
48
- payTo: requirement.payTo,
49
- ...requirement.maxTimeoutSeconds !== void 0 ? { maxTimeoutSeconds: requirement.maxTimeoutSeconds } : {},
50
- ...requirement.extra ? { extra: requirement.extra } : {}
51
- };
52
- }
53
- function buildPaymentRequiredV2(requirement, error) {
54
- return {
55
- x402Version: 2,
56
- error,
57
- ...requirement.resource ? {
58
- resource: {
59
- url: requirement.resource,
60
- ...requirement.description ? { description: requirement.description } : {},
61
- ...requirement.mimeType ? { mimeType: requirement.mimeType } : {}
62
- }
63
- } : {},
64
- accepts: [v2Requirements(requirement)],
65
- extensions: {}
66
- };
67
- }
68
- function encodeBase64Json(value) {
69
- return Buffer.from(JSON.stringify(value)).toString("base64");
70
- }
71
31
  var UintString = zod.z.string().regex(/^\d+$/, "must be a decimal integer string");
72
32
  var Transfer = zod.z.object({
73
33
  from: zod.z.string().min(1),
@@ -209,7 +169,7 @@ function mockFacilitatorRails(facilitator) {
209
169
  function facilitatorClientRails(client) {
210
170
  const dialectRequirements = (paymentHeader, requirement) => {
211
171
  const { envelope, version } = inspectPaymentHeader(paymentHeader);
212
- return { envelope, requirements: version === 2 ? v2Requirements(requirement) : requirement };
172
+ return { envelope, requirements: version === 2 ? sdk.v2Requirements(requirement) : requirement };
213
173
  };
214
174
  return {
215
175
  async verify(paymentHeader, requirement) {
@@ -233,7 +193,9 @@ function facilitatorClientRails(client) {
233
193
  classifyTransport(err);
234
194
  }
235
195
  if (!settled.success) {
236
- throw new GateError("settle_failed", settled.errorReason ?? "payment settlement failed");
196
+ throw new GateError("settle_failed", settled.errorReason ?? "payment settlement failed", {
197
+ paymentResponse: settled
198
+ });
237
199
  }
238
200
  return {
239
201
  header: encodeSettlementHeader(settled),
@@ -470,9 +432,11 @@ var Gate = class {
470
432
  };
471
433
  }
472
434
  let payer;
435
+ let wire;
473
436
  try {
474
437
  const payment = inspectPaymentHeader(request.payment);
475
438
  payer = payment.payer;
439
+ wire = payment.version;
476
440
  this.checkRate(payment.payer);
477
441
  this.checkConsistency(payment, requirement);
478
442
  this.screenPayer(payment.payer);
@@ -498,7 +462,7 @@ var Gate = class {
498
462
  return { kind: "paid", receipt, settlementHeader: settlement.header };
499
463
  } catch (err) {
500
464
  if (!(err instanceof GateError)) throw err;
501
- return this.refuse(err, url.pathname, requirement, payer);
465
+ return this.refuse(err, url.pathname, requirement, payer, wire);
502
466
  }
503
467
  }
504
468
  stats() {
@@ -542,7 +506,7 @@ var Gate = class {
542
506
  `payment scheme "${payment.scheme}" does not match the quoted "${requirement.scheme}"`
543
507
  );
544
508
  }
545
- if (!sameNetwork(payment.network, requirement.network)) {
509
+ if (!sdk.sameNetwork(payment.network, requirement.network)) {
546
510
  throw new GateError(
547
511
  "network_mismatch",
548
512
  `payment is on "${payment.network}" but the quote wants "${requirement.network}"`
@@ -699,7 +663,7 @@ var Gate = class {
699
663
  );
700
664
  }
701
665
  }
702
- refuse(err, resource, requirement, payer) {
666
+ refuse(err, resource, requirement, payer, wire) {
703
667
  this.fire(() => this.store.recordRefusal());
704
668
  this.emit({
705
669
  type: "gate.refused",
@@ -749,14 +713,15 @@ var Gate = class {
749
713
  code: err.code,
750
714
  reason: err.message,
751
715
  body: { x402Version: 1, accepts: [requirement], error: err.message },
752
- ...this.v2Quote(requirement, err.message)
716
+ ...this.v2Quote(requirement, err.message),
717
+ ...wire === 2 ? { paymentResponseHeader: v2FailureHeader(err, requirement, payer) } : {}
753
718
  };
754
719
  }
755
720
  /** The v2 half of a dual-stack 402 (see advertiseV2), or nothing. */
756
721
  v2Quote(requirement, error) {
757
722
  if (!this.advertiseV2) return {};
758
723
  return {
759
- paymentRequiredHeader: encodeBase64Json(buildPaymentRequiredV2(requirement, error))
724
+ paymentRequiredHeader: sdk.encodeBase64Json(sdk.buildPaymentRequiredV2(requirement, error))
760
725
  };
761
726
  }
762
727
  };
@@ -766,6 +731,17 @@ function createGate(options) {
766
731
  function replayKey(paymentHeader) {
767
732
  return crypto.createHash("sha256").update(paymentHeader).digest("hex");
768
733
  }
734
+ function v2FailureHeader(err, requirement, payer) {
735
+ return sdk.encodeBase64Json(
736
+ err.paymentResponse ?? {
737
+ success: false,
738
+ errorReason: err.code,
739
+ transaction: "",
740
+ network: sdk.caip2Of(requirement.network),
741
+ ...payer !== void 0 ? { payer } : {}
742
+ }
743
+ );
744
+ }
769
745
  function messageOf2(err) {
770
746
  return err instanceof Error ? err.message : String(err);
771
747
  }
@@ -792,6 +768,7 @@ function gateMiddleware(gate, options = {}) {
792
768
  res.writeHead(outcome.status, {
793
769
  "content-type": "application/json",
794
770
  ...outcome.paymentRequiredHeader !== void 0 ? { "payment-required": outcome.paymentRequiredHeader } : {},
771
+ ...outcome.kind === "refused" && outcome.paymentResponseHeader !== void 0 ? { "payment-response": outcome.paymentResponseHeader } : {},
795
772
  ...outcome.kind === "refused" && outcome.retryAfterSeconds !== void 0 ? { "retry-after": String(outcome.retryAfterSeconds) } : {}
796
773
  });
797
774
  res.end(JSON.stringify(outcome.body));
@@ -835,21 +812,39 @@ function createGatedFetch(gate, options = {}) {
835
812
  headers: {
836
813
  "content-type": "application/json",
837
814
  ...outcome.paymentRequiredHeader !== void 0 ? { "payment-required": outcome.paymentRequiredHeader } : {},
815
+ ...outcome.kind === "refused" && outcome.paymentResponseHeader !== void 0 ? { "payment-response": outcome.paymentResponseHeader } : {},
838
816
  ...outcome.kind === "refused" && outcome.retryAfterSeconds !== void 0 ? { "retry-after": String(outcome.retryAfterSeconds) } : {}
839
817
  }
840
818
  });
841
819
  };
842
820
  }
843
821
 
822
+ Object.defineProperty(exports, "buildPaymentRequiredV2", {
823
+ enumerable: true,
824
+ get: function () { return sdk.buildPaymentRequiredV2; }
825
+ });
826
+ Object.defineProperty(exports, "caip2Of", {
827
+ enumerable: true,
828
+ get: function () { return sdk.caip2Of; }
829
+ });
830
+ Object.defineProperty(exports, "encodeBase64Json", {
831
+ enumerable: true,
832
+ get: function () { return sdk.encodeBase64Json; }
833
+ });
834
+ Object.defineProperty(exports, "sameNetwork", {
835
+ enumerable: true,
836
+ get: function () { return sdk.sameNetwork; }
837
+ });
838
+ Object.defineProperty(exports, "v2Requirements", {
839
+ enumerable: true,
840
+ get: function () { return sdk.v2Requirements; }
841
+ });
844
842
  exports.Gate = Gate;
845
843
  exports.GateError = GateError;
846
844
  exports.InMemoryGateStore = InMemoryGateStore;
847
845
  exports.RailsUnreachableError = RailsUnreachableError;
848
- exports.buildPaymentRequiredV2 = buildPaymentRequiredV2;
849
- exports.caip2Of = caip2Of;
850
846
  exports.createGate = createGate;
851
847
  exports.createGatedFetch = createGatedFetch;
852
- exports.encodeBase64Json = encodeBase64Json;
853
848
  exports.facilitatorClientRails = facilitatorClientRails;
854
849
  exports.gateMiddleware = gateMiddleware;
855
850
  exports.inspectPaymentHeader = inspectPaymentHeader;
@@ -857,8 +852,6 @@ exports.matchRoute = matchRoute;
857
852
  exports.mockFacilitatorRails = mockFacilitatorRails;
858
853
  exports.requirementFor = requirementFor;
859
854
  exports.routeDecimals = routeDecimals;
860
- exports.sameNetwork = sameNetwork;
861
- exports.v2Requirements = v2Requirements;
862
855
  exports.validateVelocity = validateVelocity;
863
856
  //# sourceMappingURL=index.cjs.map
864
857
  //# sourceMappingURL=index.cjs.map