@obbyx/sdk 0.1.0 → 0.2.0

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.
@@ -1,9 +1,12 @@
1
1
  import type { AssetAmount, Network, PaymentRequirements, Price, SchemeNetworkServer, SchemePaymentRequiredContext, SchemeServerHooks } from '@x402/core/types';
2
2
  import { type Logger } from '@obbyx/obyte/logger';
3
+ import { BATCH_SCHEME, EXACT_SCHEME } from '@obbyx/x402-obyte';
3
4
  import type { ConsumedProofsStore } from './consumed-proofs.js';
4
5
  /**
5
- * Obyte `exact` for the OFFICIAL x402 resource server (`@x402/core/server`,
6
- * `@x402/express`, `@x402/hono`, …): a SchemeNetworkServer.
6
+ * Obyte schemes for the OFFICIAL x402 resource server (`@x402/core/server`,
7
+ * `@x402/express`, `@x402/hono`, …): SchemeNetworkServer implementations for
8
+ * `exact` ({@link ObyteExactServer}) and `batch-settlement`
9
+ * ({@link ObyteBatchServer}), sharing {@link ObyteSchemeServer}.
7
10
  *
8
11
  * - Binding (I1/I2): `enrichPaymentRequiredResponse` adds a per-request HMAC
9
12
  * binding + quote to every offer. On a paid request it recomputes the HMAC
@@ -17,7 +20,9 @@ import type { ConsumedProofsStore } from './consumed-proofs.js';
17
20
  * Unlike `@obbyx/sdk`'s ObytePaywall, a repeated request gets a 402 instead
18
21
  * of the stored response (the official middleware cannot replay responses).
19
22
  */
20
- export interface ObyteExactServerOptions {
23
+ export interface ObyteSchemeServerOptions {
24
+ /** How long a request may hold a payment in `serving` before a retry takes over (default 300 s). */
25
+ readonly servingLeaseSeconds?: number;
21
26
  readonly sellerId: string;
22
27
  /** HMAC key for bindings (≥ 32 bytes). */
23
28
  readonly secret: string | Uint8Array;
@@ -26,9 +31,34 @@ export interface ObyteExactServerOptions {
26
31
  readonly quoteTtlSeconds?: number;
27
32
  readonly now?: () => number;
28
33
  }
29
- export declare class ObyteExactServer implements SchemeNetworkServer {
34
+ /** @deprecated Use {@link ObyteSchemeServerOptions}. */
35
+ export type ObyteExactServerOptions = ObyteSchemeServerOptions;
36
+ /** Options of {@link ObyteBatchServer}. */
37
+ export interface ObyteBatchServerOptions extends ObyteSchemeServerOptions {
38
+ /** Minimum channel dispute window the seller accepts (seconds); must match the facilitator's. */
39
+ readonly minChannelTimeoutSeconds: number;
40
+ }
41
+ /** Per-scheme parts of an Obyte resource-server scheme. */
42
+ export interface ObyteSchemeSpec {
43
+ readonly scheme: typeof EXACT_SCHEME | typeof BATCH_SCHEME;
44
+ /** `extra` fields the scheme adds to every offer besides binding and quote. */
45
+ readonly staticExtra: Record<string, unknown>;
46
+ /** Parses the quote fields of the accepted offer. */
47
+ readonly acceptedExtra: (extra: unknown) => {
48
+ readonly binding: string;
49
+ readonly quoteId: string;
50
+ readonly validUntil: number;
51
+ };
52
+ /** Proof id and key kind of a payment payload (undefined when malformed). */
53
+ readonly proofOf: (payload: Record<string, unknown>) => {
54
+ kind: string;
55
+ id: string;
56
+ } | undefined;
57
+ }
58
+ export declare abstract class ObyteSchemeServer implements SchemeNetworkServer {
30
59
  private readonly options;
31
- readonly scheme = "exact";
60
+ private readonly spec;
61
+ readonly scheme: string;
32
62
  readonly defaultAssetTransferMethod = "default";
33
63
  readonly paymentFlows: {
34
64
  default: {
@@ -40,11 +70,11 @@ export declare class ObyteExactServer implements SchemeNetworkServer {
40
70
  readonly schemeHooks: SchemeServerHooks;
41
71
  private readonly log;
42
72
  private readonly now;
43
- constructor(options: ObyteExactServerOptions);
73
+ protected constructor(options: ObyteSchemeServerOptions, spec: ObyteSchemeSpec);
44
74
  /** `{asset, amount}` in atomic units, or "20000 bytes" / "0.00002 GBYTE". */
45
75
  parsePrice(price: Price, network: Network): Promise<AssetAmount>;
46
76
  getAssetDecimals(asset: string): number | undefined;
47
- /** Nothing to add from /supported for exact; the per-request fields come from the enrich hook. */
77
+ /** Nothing to add from /supported; the per-request fields come from the enrich hook. */
48
78
  enhancePaymentRequirements(requirements: PaymentRequirements): Promise<PaymentRequirements>;
49
79
  /** Adds (or, for a valid paid request, re-confirms) the per-request binding and quote. */
50
80
  enrichPaymentRequiredResponse: (ctx: SchemePaymentRequiredContext) => Promise<PaymentRequirements[]>;
@@ -52,6 +82,18 @@ export declare class ObyteExactServer implements SchemeNetworkServer {
52
82
  private bindingFor;
53
83
  /** Proof key of the payment in a hook context (undefined when malformed). */
54
84
  private keyOf;
55
- private key;
85
+ }
86
+ /** `exact`: the proof is the unit (key `<network>:unit:<hash>`, as ObytePaywall). */
87
+ export declare class ObyteExactServer extends ObyteSchemeServer {
88
+ constructor(options: ObyteSchemeServerOptions);
89
+ }
90
+ /**
91
+ * `batch-settlement` (AA payment channels): the proof is the voucher (key
92
+ * `<network>:voucher:<sha256 of the canonical signed package>`, as
93
+ * ObytePaywall). Offers carry the channel base AA and the minimum dispute
94
+ * window. Needs a facilitator with batch-settlement and the seller's watcher.
95
+ */
96
+ export declare class ObyteBatchServer extends ObyteSchemeServer {
97
+ constructor(options: ObyteBatchServerOptions);
56
98
  }
57
99
  //# sourceMappingURL=x402-server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"x402-server.d.ts","sourceRoot":"","sources":["../../src/seller/x402-server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,OAAO,EACP,mBAAmB,EACnB,KAAK,EACL,mBAAmB,EACnB,4BAA4B,EAC5B,iBAAiB,EAClB,MAAM,kBAAkB,CAAC;AAS1B,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,qBAAqB,CAAC;AAEhE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAGhE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAwBD,qBAAa,gBAAiB,YAAW,mBAAmB;IAW9C,OAAO,CAAC,QAAQ,CAAC,OAAO;IAVpC,QAAQ,CAAC,MAAM,WAAgB;IAC/B,QAAQ,CAAC,0BAA0B,aAAa;IAChD,QAAQ,CAAC,YAAY;;;;;MAEnB;IACF,QAAQ,CAAC,kBAAkB,WAAwC;IACnE,QAAQ,CAAC,WAAW,EAAE,iBAAiB,CAAC;IACxC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;gBAEN,OAAO,EAAE,uBAAuB;IAoD7D,6EAA6E;IACvE,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAmBtE,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAInD,kGAAkG;IAC5F,0BAA0B,CAC9B,YAAY,EAAE,mBAAmB,GAChC,OAAO,CAAC,mBAAmB,CAAC;IAI/B,0FAA0F;IAC1F,6BAA6B,GAC3B,KAAK,4BAA4B,KAChC,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAmB/B;IAEF,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,UAAU;IAUlB,6EAA6E;IAC7E,OAAO,CAAC,KAAK;IAQb,OAAO,CAAC,GAAG;CAGZ"}
1
+ {"version":3,"file":"x402-server.d.ts","sourceRoot":"","sources":["../../src/seller/x402-server.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,8 @@
1
1
  import { decodePaymentSignatureHeader } from '@x402/core/http';
2
- import { ObbyxError, fromDisplay, getNetwork, isAssetId, networkKey, parseAmount, } from '@obbyx/obyte';
2
+ import { CHANNEL_BASE_AA, ObbyxError, fromDisplay, getNetwork, isAssetId, networkKey, parseAmount, } from '@obbyx/obyte';
3
3
  import { moduleLogger } from '@obbyx/obyte/logger';
4
- import { EXACT_SCHEME, bindingsEqual, exactExtraSchema } from '@obbyx/x402-obyte';
4
+ import { BATCH_SCHEME, EXACT_SCHEME, batchExtraSchema, bindingsEqual, canonical, exactExtraSchema, sha256Hex, } from '@obbyx/x402-obyte';
5
+ import { DEFAULT_QUOTE_TTL_SECONDS, DEFAULT_SERVING_LEASE_SECONDS } from './defaults.js';
5
6
  import { bodyHashOf, newQuote, offerBinding } from './quote.js';
6
7
  function requestOf(transportContext) {
7
8
  const request = transportContext?.request;
@@ -16,9 +17,10 @@ function requestOf(transportContext) {
16
17
  paymentHeader: typeof request?.['paymentHeader'] === 'string' ? request['paymentHeader'] : undefined,
17
18
  };
18
19
  }
19
- export class ObyteExactServer {
20
+ export class ObyteSchemeServer {
20
21
  options;
21
- scheme = EXACT_SCHEME;
22
+ spec;
23
+ scheme;
22
24
  defaultAssetTransferMethod = 'default';
23
25
  paymentFlows = {
24
26
  default: { supported: ['upfront'], default: 'upfront' },
@@ -27,22 +29,24 @@ export class ObyteExactServer {
27
29
  schemeHooks;
28
30
  log;
29
31
  now;
30
- constructor(options) {
32
+ constructor(options, spec) {
31
33
  this.options = options;
32
- this.log = moduleLogger(options.logger, 'sdk.x402-server', { scheme: EXACT_SCHEME });
34
+ this.spec = spec;
35
+ this.scheme = spec.scheme;
36
+ this.log = moduleLogger(options.logger, 'sdk.x402-server', { scheme: spec.scheme });
33
37
  this.now = options.now ?? (() => Math.floor(Date.now() / 1000));
34
38
  this.schemeHooks = {
35
39
  onBeforeVerify: async (ctx) => {
36
- const unit = ctx.paymentPayload.payload.unit?.unit;
40
+ const key = this.keyOf(ctx);
37
41
  const binding = ctx.requirements.extra.binding;
38
- if (typeof unit !== 'string' || typeof binding !== 'string') {
42
+ if (key === undefined || typeof binding !== 'string') {
39
43
  return { abort: true, reason: 'invalid_payload' };
40
44
  }
41
- const { record } = this.options.proofs.begin(this.key(ctx.requirements.network, unit), binding);
45
+ const { record } = this.options.proofs.begin(key, binding);
42
46
  if (!bindingsEqual(record.binding, binding))
43
47
  return { abort: true, reason: 'invalid_payment_reused' };
44
48
  if (record.state === 'served') {
45
- this.log.warn({ proofId: unit }, 'payment already served a request; refused');
49
+ this.log.warn({ proofId: key }, 'payment already served a request; refused');
46
50
  return { abort: true, reason: 'payment_already_used' };
47
51
  }
48
52
  return undefined;
@@ -55,8 +59,14 @@ export class ObyteExactServer {
55
59
  const key = this.keyOf(ctx);
56
60
  if (key === undefined)
57
61
  return { abort: true, reason: 'invalid_payload' };
58
- if (this.options.proofs.transition(key, 'settling', 'serving'))
62
+ const proofs = this.options.proofs;
63
+ // A claim left behind by a crashed process is taken over after the lease.
64
+ proofs.reclaimStale(key, this.options.servingLeaseSeconds ?? DEFAULT_SERVING_LEASE_SECONDS);
65
+ if (proofs.transition(key, 'settling', 'serving') ||
66
+ // settled earlier, but the handler failed: serve it now (settle is idempotent)
67
+ proofs.transition(key, 'paid_not_served', 'serving')) {
59
68
  return undefined;
69
+ }
60
70
  const state = this.options.proofs.get(key)?.state;
61
71
  this.log.warn({ state }, 'payment already in use by another request; refused');
62
72
  return {
@@ -75,6 +85,20 @@ export class ObyteExactServer {
75
85
  else
76
86
  this.options.proofs.transition(key, 'serving', 'settling');
77
87
  },
88
+ // The handler failed or threw after the payment was settled (upfront):
89
+ // the payment stays usable for the SAME operation instead of "already used".
90
+ onVerifiedPaymentCanceled: async (ctx) => {
91
+ const key = this.keyOf(ctx);
92
+ if (key === undefined)
93
+ return;
94
+ if (ctx.settledPhases.includes('before-handler')) {
95
+ this.options.proofs.transition(key, 'served', 'paid_not_served');
96
+ }
97
+ else {
98
+ this.options.proofs.transition(key, 'serving', 'settling');
99
+ }
100
+ this.log.warn({ reason: ctx.reason }, 'paid request not served; the same payment can retry');
101
+ },
78
102
  onSettleFailure: async (ctx) => {
79
103
  const key = this.keyOf(ctx);
80
104
  if (key !== undefined)
@@ -100,7 +124,7 @@ export class ObyteExactServer {
100
124
  getAssetDecimals(asset) {
101
125
  return asset === 'base' ? 9 : undefined;
102
126
  }
103
- /** Nothing to add from /supported for exact; the per-request fields come from the enrich hook. */
127
+ /** Nothing to add from /supported; the per-request fields come from the enrich hook. */
104
128
  async enhancePaymentRequirements(requirements) {
105
129
  return requirements;
106
130
  }
@@ -108,21 +132,22 @@ export class ObyteExactServer {
108
132
  enrichPaymentRequiredResponse = async (ctx) => {
109
133
  const request = requestOf(ctx.transportContext);
110
134
  if (request === undefined)
111
- throw new ObbyxError('no_request', 'Obyte exact needs the HTTP request context');
135
+ throw new ObbyxError('no_request', `Obyte ${this.scheme} needs the HTTP request context`);
112
136
  const accepted = this.acceptedQuote(request);
113
137
  return ctx.requirements.map((req) => {
114
- if (req.scheme !== EXACT_SCHEME)
138
+ if (req.scheme !== this.spec.scheme)
115
139
  return req;
116
140
  const quote = accepted !== undefined &&
117
141
  bindingsEqual(this.bindingFor(req, request, accepted), accepted.binding)
118
142
  ? accepted
119
143
  : undefined;
144
+ const extra = { ...req.extra, ...this.spec.staticExtra };
120
145
  if (quote !== undefined)
121
- return { ...req, extra: { ...req.extra, ...quote } };
122
- const fresh = newQuote(this.now(), this.options.quoteTtlSeconds ?? 300);
146
+ return { ...req, extra: { ...extra, ...quote } };
147
+ const fresh = newQuote(this.now(), this.options.quoteTtlSeconds ?? DEFAULT_QUOTE_TTL_SECONDS);
123
148
  return {
124
149
  ...req,
125
- extra: { ...req.extra, binding: this.bindingFor(req, request, fresh), ...fresh },
150
+ extra: { ...extra, binding: this.bindingFor(req, request, fresh), ...fresh },
126
151
  };
127
152
  });
128
153
  };
@@ -130,23 +155,60 @@ export class ObyteExactServer {
130
155
  if (request.paymentHeader === undefined)
131
156
  return undefined;
132
157
  try {
133
- const extra = exactExtraSchema.safeParse(decodePaymentSignatureHeader(request.paymentHeader).accepted?.extra);
134
- return extra.success ? extra.data : undefined;
158
+ const accepted = decodePaymentSignatureHeader(request.paymentHeader).accepted;
159
+ if (accepted?.scheme !== this.spec.scheme)
160
+ return undefined;
161
+ const extra = this.spec.acceptedExtra(accepted.extra);
162
+ return { quoteId: extra.quoteId, validUntil: extra.validUntil, binding: extra.binding };
135
163
  }
136
164
  catch {
137
165
  return undefined;
138
166
  }
139
167
  }
140
168
  bindingFor(req, request, quote) {
141
- return offerBinding(this.options, EXACT_SCHEME, quote, { method: request.method, url: request.url, bodyHash: bodyHashOf(request.body) }, { network: req.network, asset: req.asset, amount: req.amount, payTo: req.payTo });
169
+ return offerBinding(this.options, this.spec.scheme, quote, { method: request.method, url: request.url, bodyHash: bodyHashOf(request.body) }, { network: req.network, asset: req.asset, amount: req.amount, payTo: req.payTo });
142
170
  }
143
171
  /** Proof key of the payment in a hook context (undefined when malformed). */
144
172
  keyOf(ctx) {
145
- const unit = ctx.paymentPayload.payload.unit?.unit;
146
- return typeof unit === 'string' ? this.key(ctx.requirements.network, unit) : undefined;
173
+ const proof = this.spec.proofOf(ctx.paymentPayload.payload);
174
+ return proof === undefined
175
+ ? undefined
176
+ : networkKey(getNetwork(ctx.requirements.network), proof.kind, proof.id);
177
+ }
178
+ }
179
+ /** `exact`: the proof is the unit (key `<network>:unit:<hash>`, as ObytePaywall). */
180
+ export class ObyteExactServer extends ObyteSchemeServer {
181
+ constructor(options) {
182
+ super(options, {
183
+ scheme: EXACT_SCHEME,
184
+ staticExtra: {},
185
+ acceptedExtra: (extra) => exactExtraSchema.parse(extra),
186
+ proofOf: (payload) => {
187
+ const unit = payload.unit?.unit;
188
+ return typeof unit === 'string' ? { kind: 'unit', id: unit } : undefined;
189
+ },
190
+ });
147
191
  }
148
- key(network, unit) {
149
- return networkKey(getNetwork(network), 'unit', unit);
192
+ }
193
+ /**
194
+ * `batch-settlement` (AA payment channels): the proof is the voucher (key
195
+ * `<network>:voucher:<sha256 of the canonical signed package>`, as
196
+ * ObytePaywall). Offers carry the channel base AA and the minimum dispute
197
+ * window. Needs a facilitator with batch-settlement and the seller's watcher.
198
+ */
199
+ export class ObyteBatchServer extends ObyteSchemeServer {
200
+ constructor(options) {
201
+ super(options, {
202
+ scheme: BATCH_SCHEME,
203
+ staticExtra: { baseAa: CHANNEL_BASE_AA, minTimeout: options.minChannelTimeoutSeconds },
204
+ acceptedExtra: (extra) => batchExtraSchema.parse(extra),
205
+ proofOf: (payload) => {
206
+ const pkg = payload['signedPackage'];
207
+ return pkg !== null && typeof pkg === 'object'
208
+ ? { kind: 'voucher', id: sha256Hex(canonical(pkg)) }
209
+ : undefined;
210
+ },
211
+ });
150
212
  }
151
213
  }
152
214
  //# sourceMappingURL=x402-server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"x402-server.js","sourceRoot":"","sources":["../../src/seller/x402-server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"x402-server.js","sourceRoot":"","sources":["../../src/seller/x402-server.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@obbyx/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Accept and make x402 payments on Obyte: Express paywall, adapter for the official @x402 servers, paying fetch with spending budgets",
5
5
  "keywords": [
6
6
  "x402",
@@ -44,7 +44,7 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "@obbyx/obyte": "^0.1.0",
47
- "@obbyx/x402-obyte": "^0.1.0",
47
+ "@obbyx/x402-obyte": "^0.2.1",
48
48
  "@x402/core": "^2.29.0",
49
49
  "obyte": "0.2.1",
50
50
  "zod": "^4.6.7"
package/src/index.ts CHANGED
@@ -32,4 +32,13 @@ export {
32
32
  type BudgetReservation,
33
33
  SpendingBudget,
34
34
  } from './client/budget.js';
35
- export { ObyteExactServer, type ObyteExactServerOptions } from './seller/x402-server.js';
35
+ export {
36
+ ObyteBatchServer,
37
+ type ObyteBatchServerOptions,
38
+ ObyteExactServer,
39
+ type ObyteExactServerOptions,
40
+ ObyteSchemeServer,
41
+ type ObyteSchemeSpec,
42
+ type ObyteSchemeServerOptions,
43
+ } from './seller/x402-server.js';
44
+ export type { PaywallCorsOptions } from './seller/cors.js';
@@ -174,6 +174,28 @@ export class ConsumedProofsStore {
174
174
  return Number(res.changes) === 1;
175
175
  }
176
176
 
177
+ /**
178
+ * Records a SETTLED payment as paid (`settling → paid_not_served`), also when
179
+ * a concurrent request removed or moved its row meanwhile: the payment did
180
+ * settle, so it must stay servable once. Atomic; returns the stored state.
181
+ */
182
+ markSettled(key: string, binding: string, paymentResponse: string): ProofState {
183
+ const ts = this.now();
184
+ // One UPSERT statement: atomic on its own.
185
+ this.db
186
+ .prepare(
187
+ `INSERT INTO consumed_proofs (key, binding, state, payment_response, created_at, updated_at)
188
+ VALUES (?, ?, 'paid_not_served', ?, ?, ?)
189
+ ON CONFLICT(key) DO UPDATE SET state = 'paid_not_served', payment_response = excluded.payment_response,
190
+ updated_at = excluded.updated_at
191
+ WHERE consumed_proofs.state = 'settling'`,
192
+ )
193
+ .run(key, binding, paymentResponse, ts, ts);
194
+ const record = this.get(key);
195
+ if (record === undefined) throw new Error(`consumed proof ${key} vanished`);
196
+ return record.state;
197
+ }
198
+
177
199
  /**
178
200
  * Recovers a proof stuck in `serving` (the process died while the handler
179
201
  * ran): after `leaseSeconds` it goes back to `paid_not_served` (already
@@ -0,0 +1,106 @@
1
+ import type { Request, RequestHandler, Response } from 'express';
2
+
3
+ /**
4
+ * CORS for browser clients of a paid route (x402 `transports-v2/http.md`,
5
+ * "Browser clients"). None of the x402 headers is CORS-safelisted: without
6
+ * these headers a cross-origin page cannot read the price (402) or send the
7
+ * payment. CORS decides who may READ a response; it is not a payment control.
8
+ */
9
+ export interface PaywallCorsOptions {
10
+ /** Allowed origins (exact `scheme://host[:port]`), or `'*'` for any. */
11
+ readonly origins: readonly string[] | '*';
12
+ /** Whether requests may carry credentials (cookies); origins are then reflected, never `*`. */
13
+ readonly credentials?: boolean;
14
+ /** Preflight cache lifetime (default 600 s). */
15
+ readonly maxAgeSeconds?: number;
16
+ }
17
+
18
+ /** Response headers a browser client must read: the price and the settlement. */
19
+ export const EXPOSED_HEADERS = ['PAYMENT-REQUIRED', 'PAYMENT-RESPONSE'] as const;
20
+ /** Request headers a browser client sends: the payment, and Content-Type for a JSON body. */
21
+ export const ALLOWED_HEADERS = ['PAYMENT-SIGNATURE', 'Content-Type'] as const;
22
+ const DEFAULT_MAX_AGE_SECONDS = 600;
23
+
24
+ /** Merges header names into a comma-separated list, keeping existing ones (case-insensitive). */
25
+ export function mergeHeaderList(
26
+ existing: string | number | readonly string[] | undefined,
27
+ add: readonly string[],
28
+ ): string {
29
+ const current =
30
+ existing === undefined
31
+ ? []
32
+ : (Array.isArray(existing) ? existing.join(',') : String(existing))
33
+ .split(',')
34
+ .map((h) => h.trim())
35
+ .filter((h) => h.length > 0);
36
+ const seen = new Set(current.map((h) => h.toLowerCase()));
37
+ for (const h of add) {
38
+ if (!seen.has(h.toLowerCase())) {
39
+ current.push(h);
40
+ seen.add(h.toLowerCase());
41
+ }
42
+ }
43
+ return current.join(', ');
44
+ }
45
+
46
+ /** Always: lets a cross-origin page read the x402 headers (merged with any value already set). */
47
+ export function exposePaymentHeaders(res: Response): void {
48
+ res.setHeader(
49
+ 'Access-Control-Expose-Headers',
50
+ mergeHeaderList(res.getHeader('Access-Control-Expose-Headers'), EXPOSED_HEADERS),
51
+ );
52
+ }
53
+
54
+ /** Sets `Access-Control-Allow-Origin` for an allowed calling origin; false when not allowed. */
55
+ export function allowOrigin(req: Request, res: Response, cors: PaywallCorsOptions): boolean {
56
+ const origin = req.get('origin');
57
+ if (origin === undefined) return false;
58
+ const anyOrigin = cors.origins === '*';
59
+ if (!anyOrigin && !cors.origins.includes(origin)) return false;
60
+ if (anyOrigin && cors.credentials !== true) {
61
+ res.setHeader('Access-Control-Allow-Origin', '*');
62
+ } else {
63
+ // A reflected origin varies per request: shared caches must key on it.
64
+ res.setHeader('Access-Control-Allow-Origin', origin);
65
+ res.setHeader('Vary', mergeHeaderList(res.getHeader('Vary'), ['Origin']));
66
+ }
67
+ if (cors.credentials === true) res.setHeader('Access-Control-Allow-Credentials', 'true');
68
+ return true;
69
+ }
70
+
71
+ /**
72
+ * Answers the CORS preflight (`OPTIONS`) of paid routes without requiring
73
+ * payment. Allows the x402 request headers plus whatever else the browser
74
+ * announces: x402 client SDKs have added request headers of their own, and an
75
+ * allow list naming exactly the protocol headers would refuse their retry.
76
+ */
77
+ export function preflightHandler(cors: PaywallCorsOptions): RequestHandler {
78
+ return (req, res, next) => {
79
+ if (req.method !== 'OPTIONS' || req.get('access-control-request-method') === undefined) {
80
+ next();
81
+ return;
82
+ }
83
+ if (!allowOrigin(req, res, cors)) {
84
+ res.status(204).end(); // no CORS headers: the browser refuses the call
85
+ return;
86
+ }
87
+ const requested = (req.get('access-control-request-headers') ?? '')
88
+ .split(',')
89
+ .map((h) => h.trim())
90
+ .filter((h) => h.length > 0);
91
+ res.setHeader(
92
+ 'Access-Control-Allow-Headers',
93
+ mergeHeaderList(undefined, [...ALLOWED_HEADERS, ...requested]),
94
+ );
95
+ res.setHeader(
96
+ 'Access-Control-Allow-Methods',
97
+ mergeHeaderList(undefined, [
98
+ req.get('access-control-request-method') ?? 'POST',
99
+ 'GET',
100
+ 'POST',
101
+ ]),
102
+ );
103
+ res.setHeader('Access-Control-Max-Age', String(cors.maxAgeSeconds ?? DEFAULT_MAX_AGE_SECONDS));
104
+ res.status(204).end();
105
+ };
106
+ }
@@ -0,0 +1,6 @@
1
+ /** Seller-side defaults shared by ObytePaywall and ObyteExactServer (seconds). */
2
+ export const DEFAULT_QUOTE_TTL_SECONDS = 300;
3
+ /** Freshness window of the payment unit's timestamp offered in `maxTimeoutSeconds`. */
4
+ export const DEFAULT_MAX_TIMEOUT_SECONDS = 300;
5
+ /** How long a request may hold a payment in `serving` before a retry takes it over. */
6
+ export const DEFAULT_SERVING_LEASE_SECONDS = 300;