@armory-sh/middleware 0.2.0 → 0.2.2

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
@@ -1,6 +1,7 @@
1
- import { Address, CAIP2ChainId, CAIPAssetId, PaymentRequirements, SettlementResponse, PaymentPayload, ResolvedPaymentConfig, AcceptPaymentOptions, NetworkId, TokenId, ValidationError } from '@armory-sh/base';
2
- export { AcceptPaymentOptions, NetworkId, FacilitatorConfig as SimpleFacilitatorConfig, TokenId } from '@armory-sh/base';
3
- import { VerifyPaymentOptions } from '@armory-sh/facilitator';
1
+ import * as _armory_sh_base from '@armory-sh/base';
2
+ import { Address, CAIP2ChainId, CAIPAssetId, PaymentRequirements as PaymentRequirements$1, X402SettlementResponse, SettlementResponseV1, SettlementResponseV2, X402PaymentPayload, X402PaymentRequirements, ResolvedPaymentConfig, AcceptPaymentOptions, NetworkId, TokenId, ValidationError } from '@armory-sh/base';
3
+ export { AcceptPaymentOptions, NetworkId, PaymentRequirementsV1, PaymentRequirementsV2, SettlementResponseV1, SettlementResponseV2, FacilitatorConfig as SimpleFacilitatorConfig, TokenId } from '@armory-sh/base';
4
+ import { X402VerifyOptions } from '@armory-sh/facilitator';
4
5
 
5
6
  interface FacilitatorConfig {
6
7
  url: string;
@@ -39,16 +40,40 @@ interface FacilitatorSettleResult {
39
40
  error?: string;
40
41
  }
41
42
 
42
- declare const createPaymentRequirements: (config: MiddlewareConfig, version?: 1 | 2) => PaymentRequirements;
43
+ declare const createPaymentRequirements: (config: MiddlewareConfig, version?: 1 | 2) => PaymentRequirements$1;
43
44
  declare const verifyWithFacilitator: (request: HttpRequest, facilitator: FacilitatorConfig) => Promise<FacilitatorVerifyResult>;
44
45
  declare const settleWithFacilitator: (request: HttpRequest, facilitator: FacilitatorConfig) => Promise<FacilitatorSettleResult>;
45
- declare const createPaymentRequiredHeaders: (requirements: PaymentRequirements, version: 1 | 2) => Record<string, string>;
46
- declare const createSettlementHeaders: (response: SettlementResponse, version: 1 | 2) => Record<string, string>;
46
+ declare const createPaymentRequiredHeaders: (requirements: PaymentRequirements$1, version: 1 | 2) => Record<string, string>;
47
+ /**
48
+ * Accepts both X402SettlementResponse and legacy SettlementResponseV1/V2
49
+ * For V1, manually constructs the header. For V2/x402, uses the x402 encoder.
50
+ */
51
+ declare const createSettlementHeaders: (response: X402SettlementResponse | SettlementResponseV1 | SettlementResponseV2, version: 1 | 2) => Record<string, string>;
47
52
 
53
+ interface LegacyPaymentPayloadV1 {
54
+ amount: string;
55
+ network: string;
56
+ contractAddress: string;
57
+ payTo: string;
58
+ from: string;
59
+ expiry: number;
60
+ signature: string;
61
+ }
62
+ interface LegacyPaymentPayloadV2 {
63
+ to: string;
64
+ from: string;
65
+ amount: string;
66
+ chainId: string;
67
+ assetId: string;
68
+ nonce: string;
69
+ expiry: number;
70
+ signature: string;
71
+ }
72
+ type AnyPaymentPayload = X402PaymentPayload | LegacyPaymentPayloadV1 | LegacyPaymentPayloadV2;
48
73
  type PaymentVersion = 1 | 2;
49
74
  interface PaymentVerificationResult {
50
75
  success: boolean;
51
- payload?: PaymentPayload;
76
+ payload?: AnyPaymentPayload;
52
77
  version?: PaymentVersion;
53
78
  payerAddress?: string;
54
79
  error?: string;
@@ -59,14 +84,17 @@ interface PaymentHeaders {
59
84
  response: string;
60
85
  }
61
86
  declare const getHeadersForVersion: (version: PaymentVersion) => PaymentHeaders;
62
- declare const getRequirementsVersion: (requirements: PaymentRequirements) => PaymentVersion;
63
- declare const encodeRequirements: (requirements: PaymentRequirements) => string;
87
+ declare const getRequirementsVersion: (requirements: X402PaymentRequirements) => PaymentVersion;
88
+ declare const encodeRequirements: (requirements: X402PaymentRequirements) => string;
64
89
  declare const decodePayload: (headerValue: string) => {
65
- payload: PaymentPayload;
90
+ payload: AnyPaymentPayload;
66
91
  version: PaymentVersion;
67
92
  };
68
- declare const verifyPaymentWithRetry: (payload: PaymentPayload, requirements: PaymentRequirements, facilitatorUrl?: string, verifyOptions?: VerifyPaymentOptions) => Promise<PaymentVerificationResult>;
69
- declare const extractPayerAddress: (payload: PaymentPayload) => string;
93
+ declare const verifyPaymentWithRetry: (payload: AnyPaymentPayload, requirements: X402PaymentRequirements, facilitatorUrl?: string, verifyOptions?: X402VerifyOptions) => Promise<PaymentVerificationResult>;
94
+ /**
95
+ * Extract payer address from various payload formats
96
+ */
97
+ declare const extractPayerAddress: (payload: AnyPaymentPayload) => string;
70
98
  declare const createResponseHeaders: (payerAddress: string, version: PaymentVersion) => Record<string, string>;
71
99
 
72
100
  /**
@@ -105,7 +133,7 @@ declare const resolveMiddlewareConfig: (config: SimpleMiddlewareConfig) => Resol
105
133
  /**
106
134
  * Get payment requirements for a specific network/token combination
107
135
  */
108
- declare const getRequirements: (config: ResolvedMiddlewareConfig, network: NetworkId, token: TokenId) => PaymentRequirements | ValidationError;
136
+ declare const getRequirements: (config: ResolvedMiddlewareConfig, network: NetworkId, token: TokenId) => PaymentRequirements$1 | ValidationError;
109
137
  /**
110
138
  * Get the primary/default middleware config for legacy middlewares
111
139
  */
@@ -160,4 +188,7 @@ declare const acceptPaymentsViaArmory: (config: SimpleMiddlewareConfig & {
160
188
  waitForSettlement?: boolean;
161
189
  }) => BunMiddleware;
162
190
 
163
- export { type BunMiddleware, type BunMiddlewareConfig, type FacilitatorConfig, type FacilitatorSettleResult, type FacilitatorVerifyResult, type HttpRequest, type HttpResponse, type MiddlewareConfig, type PayToAddress, type PaymentVerificationResult, type PaymentVersion, type ResolvedMiddlewareConfig, type SettlementMode, type SimpleMiddlewareConfig, acceptPaymentsViaArmory, createBunMiddleware, createPaymentRequiredHeaders, createPaymentRequirements, createResponseHeaders, createSettlementHeaders, decodePayload, encodeRequirements, extractPayerAddress, getHeadersForVersion, getPrimaryConfig, getRequirements, getRequirementsVersion, getSupportedNetworks, getSupportedTokens, isSupported, resolveMiddlewareConfig, settleWithFacilitator, verifyPaymentWithRetry, verifyWithFacilitator };
191
+ type PaymentRequirements = _armory_sh_base.PaymentRequirementsV1 | _armory_sh_base.PaymentRequirementsV2;
192
+ type SettlementResponse = _armory_sh_base.SettlementResponseV1 | _armory_sh_base.SettlementResponseV2;
193
+
194
+ export { type AnyPaymentPayload, type BunMiddleware, type BunMiddlewareConfig, type FacilitatorConfig, type FacilitatorSettleResult, type FacilitatorVerifyResult, type HttpRequest, type HttpResponse, type LegacyPaymentPayloadV1, type LegacyPaymentPayloadV2, type MiddlewareConfig, type PayToAddress, type AnyPaymentPayload as PaymentPayload, type PaymentRequirements, type PaymentVerificationResult, type PaymentVersion, type ResolvedMiddlewareConfig, type SettlementMode, type SettlementResponse, type SimpleMiddlewareConfig, acceptPaymentsViaArmory, createBunMiddleware, createPaymentRequiredHeaders, createPaymentRequirements, createResponseHeaders, createSettlementHeaders, decodePayload, encodeRequirements, extractPayerAddress, getHeadersForVersion, getPrimaryConfig, getRequirements, getRequirementsVersion, getSupportedNetworks, getSupportedTokens, isSupported, resolveMiddlewareConfig, settleWithFacilitator, verifyPaymentWithRetry, verifyWithFacilitator };
package/dist/index.js CHANGED
@@ -1,5 +1,15 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
1
8
  // src/core.ts
2
- import { getNetworkConfig, getNetworkByChainId } from "@armory-sh/base";
9
+ import {
10
+ getNetworkConfig,
11
+ getNetworkByChainId
12
+ } from "@armory-sh/base";
3
13
  var getNetworkName = (network) => {
4
14
  if (typeof network === "string") return network;
5
15
  const net = getNetworkByChainId(network);
@@ -32,6 +42,9 @@ var createV2Requirements = (config, expiry) => {
32
42
  };
33
43
  };
34
44
  var createPaymentRequirements = (config, version = 1) => {
45
+ const networkName = getNetworkName(config.network);
46
+ const network = getNetworkConfig(networkName);
47
+ if (!network) throw new Error(`Unsupported network: ${networkName}`);
35
48
  const expiry = Math.floor(Date.now() / 1e3) + 3600;
36
49
  return version === 1 ? createV1Requirements(config, expiry) : createV2Requirements(config, expiry);
37
50
  };
@@ -117,32 +130,68 @@ var settleWithFacilitator = async (request, facilitator) => {
117
130
  };
118
131
  }
119
132
  };
120
- var encode = (data) => btoa(JSON.stringify(data));
121
133
  var createPaymentRequiredHeaders = (requirements, version) => {
122
134
  if (version === 1) {
123
- return { "X-PAYMENT-REQUIRED": encode(requirements) };
135
+ const { encodePaymentPayload: encodeV1Payload } = __require("@armory-sh/base");
136
+ return { "X-PAYMENT-REQUIRED": encodeV1Payload(requirements) };
124
137
  }
125
- return { "PAYMENT-REQUIRED": encode(requirements) };
138
+ return { "PAYMENT-REQUIRED": Buffer.from(JSON.stringify(requirements)).toString("base64") };
126
139
  };
127
140
  var createSettlementHeaders = (response, version) => {
128
141
  if (version === 1) {
129
- return { "X-PAYMENT-RESPONSE": encode(response) };
142
+ const isSuccess2 = "success" in response ? response.success : response.status === "success";
143
+ const txHash2 = "transaction" in response ? response.transaction : response.txHash || "";
144
+ const settlementJson2 = JSON.stringify({
145
+ status: isSuccess2 ? "success" : "failed",
146
+ txHash: txHash2 ?? ""
147
+ });
148
+ return { "X-PAYMENT-RESPONSE": Buffer.from(settlementJson2).toString("base64") };
130
149
  }
131
- return { "PAYMENT-RESPONSE": encode(response) };
150
+ const txHash = "transaction" in response ? response.transaction : response.txHash || "";
151
+ const isSuccess = "success" in response ? response.success : response.status === "success";
152
+ const settlementJson = JSON.stringify({
153
+ status: isSuccess ? "success" : "failed",
154
+ txHash: txHash || ""
155
+ });
156
+ return { "PAYMENT-RESPONSE": Buffer.from(settlementJson).toString("base64") };
132
157
  };
133
158
 
134
159
  // src/payment-utils.ts
135
- import { decodePayment, detectPaymentVersion, isPaymentV1 } from "@armory-sh/base";
136
- import { verifyPayment } from "@armory-sh/facilitator";
160
+ import { extractPaymentFromHeaders, X402_HEADERS } from "@armory-sh/base";
161
+ import { verifyX402Payment as verifyPayment } from "@armory-sh/facilitator";
137
162
  var getHeadersForVersion = (version) => version === 1 ? { payment: "X-PAYMENT", required: "X-PAYMENT-REQUIRED", response: "X-PAYMENT-RESPONSE" } : { payment: "PAYMENT-SIGNATURE", required: "PAYMENT-REQUIRED", response: "PAYMENT-RESPONSE" };
138
163
  var getRequirementsVersion = (requirements) => "contractAddress" in requirements && "network" in requirements ? 1 : 2;
139
164
  var encodeRequirements = (requirements) => JSON.stringify(requirements);
165
+ function isLegacyV1(payload) {
166
+ return typeof payload === "object" && payload !== null && "contractAddress" in payload && "network" in payload && "signature" in payload && typeof payload.signature === "string";
167
+ }
168
+ function isLegacyV2(payload) {
169
+ return typeof payload === "object" && payload !== null && "chainId" in payload && "assetId" in payload && "signature" in payload && typeof payload.signature === "string";
170
+ }
140
171
  var decodePayload = (headerValue) => {
172
+ let parsed;
173
+ try {
174
+ if (headerValue.startsWith("{")) {
175
+ parsed = JSON.parse(headerValue);
176
+ } else {
177
+ parsed = JSON.parse(atob(headerValue));
178
+ }
179
+ } catch {
180
+ throw new Error("Invalid payment payload");
181
+ }
141
182
  const headers = new Headers();
142
- headers.set(headerValue.startsWith("{") ? "PAYMENT-SIGNATURE" : "X-PAYMENT", headerValue);
143
- const payload = decodePayment(headers);
144
- const version = detectPaymentVersion(headers) ?? 2;
145
- return { payload, version };
183
+ headers.set(X402_HEADERS.PAYMENT, headerValue);
184
+ const x402Payload = extractPaymentFromHeaders(headers);
185
+ if (x402Payload) {
186
+ return { payload: x402Payload, version: 2 };
187
+ }
188
+ if (isLegacyV1(parsed)) {
189
+ return { payload: parsed, version: 1 };
190
+ }
191
+ if (isLegacyV2(parsed)) {
192
+ return { payload: parsed, version: 2 };
193
+ }
194
+ throw new Error("Unrecognized payment payload format");
146
195
  };
147
196
  var verifyWithFacilitator2 = async (facilitatorUrl, payload, requirements, verifyOptions) => {
148
197
  try {
@@ -168,6 +217,12 @@ var verifyWithFacilitator2 = async (facilitatorUrl, payload, requirements, verif
168
217
  }
169
218
  };
170
219
  var verifyLocally = async (payload, requirements, verifyOptions) => {
220
+ if (isLegacyV1(payload) || isLegacyV2(payload)) {
221
+ return {
222
+ success: false,
223
+ error: "Local verification not supported for legacy payload formats. Use a facilitator."
224
+ };
225
+ }
171
226
  const result = await verifyPayment(payload, requirements, verifyOptions);
172
227
  if (!result.success) {
173
228
  return {
@@ -182,7 +237,18 @@ var verifyLocally = async (payload, requirements, verifyOptions) => {
182
237
  return { success: true, payerAddress: result.payerAddress };
183
238
  };
184
239
  var verifyPaymentWithRetry = async (payload, requirements, facilitatorUrl, verifyOptions) => facilitatorUrl ? verifyWithFacilitator2(facilitatorUrl, payload, requirements, verifyOptions) : verifyLocally(payload, requirements, verifyOptions);
185
- var extractPayerAddress = (payload) => isPaymentV1(payload) ? payload.from : payload.from;
240
+ var extractPayerAddress = (payload) => {
241
+ if ("payload" in payload) {
242
+ const x402Payload = payload;
243
+ if ("authorization" in x402Payload.payload) {
244
+ return x402Payload.payload.authorization.from;
245
+ }
246
+ }
247
+ if ("from" in payload && typeof payload.from === "string") {
248
+ return payload.from;
249
+ }
250
+ throw new Error("Unable to extract payer address from payload");
251
+ };
186
252
  var createResponseHeaders = (payerAddress, version) => ({
187
253
  [getHeadersForVersion(version).response]: JSON.stringify({
188
254
  status: "verified",
@@ -192,7 +258,7 @@ var createResponseHeaders = (payerAddress, version) => ({
192
258
  });
193
259
 
194
260
  // src/bun.ts
195
- import { decodePayment as decodePayment2, isV1, isV2 } from "@armory-sh/base";
261
+ import { decodePayment, isExactEvmPayload, X402_HEADERS as X402_HEADERS2 } from "@armory-sh/base";
196
262
 
197
263
  // src/simple.ts
198
264
  import {
@@ -287,17 +353,25 @@ var isSupported = (config, network, token) => {
287
353
 
288
354
  // src/bun.ts
289
355
  var parsePaymentHeader = async (request) => {
356
+ const x402Sig = request.headers.get(X402_HEADERS2.PAYMENT);
357
+ if (x402Sig) {
358
+ try {
359
+ const payload = decodePayment(x402Sig);
360
+ if (isExactEvmPayload(payload)) {
361
+ return { payload, version: 2, payerAddress: payload.payload.authorization.from };
362
+ }
363
+ } catch {
364
+ }
365
+ }
290
366
  const v1 = request.headers.get("X-PAYMENT");
291
367
  if (v1) {
292
- const headers = new Headers({ "X-PAYMENT": v1 });
293
- const payload = decodePayment2(headers);
294
- return isV1(payload) ? { payload, version: 1, payerAddress: payload.from } : null;
295
- }
296
- const v2 = request.headers.get("PAYMENT-SIGNATURE");
297
- if (v2) {
298
- const headers = new Headers({ "PAYMENT-SIGNATURE": v2 });
299
- const payload = decodePayment2(headers);
300
- return isV2(payload) ? { payload, version: 2, payerAddress: payload.from } : null;
368
+ try {
369
+ const payload = decodePayment(v1);
370
+ if (isExactEvmPayload(payload)) {
371
+ return { payload, version: 2, payerAddress: payload.payload.authorization.from };
372
+ }
373
+ } catch {
374
+ }
301
375
  }
302
376
  return null;
303
377
  };
@@ -313,14 +387,14 @@ var errorResponse = (error, status, headers) => new Response(JSON.stringify({ er
313
387
  headers: { "Content-Type": "application/json", ...headers }
314
388
  });
315
389
  var createSettlementResponse = (success, txHash) => ({
316
- status: success ? "success" : "failed",
317
- txHash,
318
- txId: txHash,
319
- timestamp: Math.floor(Date.now() / 1e3)
390
+ success,
391
+ transaction: txHash ?? "",
392
+ errorReason: success ? void 0 : "Settlement failed",
393
+ network: "base"
320
394
  });
321
395
  var successResponse = (payerAddress, version, settlement) => {
322
- const isSuccess = settlement ? "success" in settlement ? settlement.success : settlement.status === "success" : void 0;
323
- const txHash = settlement?.txHash;
396
+ const isSuccess = settlement?.success;
397
+ const txHash = settlement?.transaction;
324
398
  return new Response(
325
399
  JSON.stringify({
326
400
  verified: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@armory-sh/middleware",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "license": "MIT",
5
5
  "author": "Sawyer Cutler <sawyer@dirtroad.dev>",
6
6
  "type": "module",
@@ -27,8 +27,8 @@
27
27
  "directory": "packages/middleware"
28
28
  },
29
29
  "dependencies": {
30
- "@armory-sh/base": "workspace:*",
31
- "@armory-sh/facilitator": "workspace:*"
30
+ "@armory-sh/base": "0.2.2",
31
+ "@armory-sh/facilitator": "0.2.2"
32
32
  },
33
33
  "devDependencies": {
34
34
  "typescript": "5.9.3",