@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 +45 -14
- package/dist/index.js +103 -29
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
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
|
-
|
|
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?:
|
|
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:
|
|
63
|
-
declare const encodeRequirements: (requirements:
|
|
87
|
+
declare const getRequirementsVersion: (requirements: X402PaymentRequirements) => PaymentVersion;
|
|
88
|
+
declare const encodeRequirements: (requirements: X402PaymentRequirements) => string;
|
|
64
89
|
declare const decodePayload: (headerValue: string) => {
|
|
65
|
-
payload:
|
|
90
|
+
payload: AnyPaymentPayload;
|
|
66
91
|
version: PaymentVersion;
|
|
67
92
|
};
|
|
68
|
-
declare const verifyPaymentWithRetry: (payload:
|
|
69
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
-
|
|
135
|
+
const { encodePaymentPayload: encodeV1Payload } = __require("@armory-sh/base");
|
|
136
|
+
return { "X-PAYMENT-REQUIRED": encodeV1Payload(requirements) };
|
|
124
137
|
}
|
|
125
|
-
return { "PAYMENT-REQUIRED":
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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(
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
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) =>
|
|
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
|
|
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
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
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
|
-
|
|
317
|
-
txHash,
|
|
318
|
-
|
|
319
|
-
|
|
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
|
|
323
|
-
const txHash = settlement?.
|
|
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.
|
|
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": "
|
|
31
|
-
"@armory-sh/facilitator": "
|
|
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",
|