@armory-sh/middleware-hono 0.3.29 → 0.3.31
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 +30 -6
- package/dist/index.d.ts +1 -0
- package/dist/index.js +62 -15
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -14,24 +14,47 @@ bun add @armory-sh/middleware-hono
|
|
|
14
14
|
|
|
15
15
|
Armory enables HTTP API payments via EIP-3009 `transferWithAuthorization`. Accept payments from any x402-compatible client—Coinbase SDK, Armory SDK, or your own implementation.
|
|
16
16
|
|
|
17
|
-
##
|
|
17
|
+
## API Reference
|
|
18
|
+
|
|
19
|
+
### Middleware
|
|
18
20
|
|
|
19
21
|
```typescript
|
|
20
22
|
import {
|
|
21
|
-
// Middleware
|
|
22
23
|
paymentMiddleware,
|
|
23
24
|
routeAwarePaymentMiddleware,
|
|
24
25
|
|
|
25
|
-
// Requirements
|
|
26
|
-
createPaymentRequirements,
|
|
27
|
-
|
|
28
26
|
// Types
|
|
29
27
|
type PaymentConfig,
|
|
30
28
|
type RouteAwarePaymentConfig,
|
|
31
|
-
type
|
|
29
|
+
type AugmentedContext,
|
|
32
30
|
} from '@armory-sh/middleware-hono';
|
|
33
31
|
```
|
|
34
32
|
|
|
33
|
+
### Payment Requirements
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import {
|
|
37
|
+
createPaymentRequirements,
|
|
38
|
+
|
|
39
|
+
// Types
|
|
40
|
+
type ResolvedRequirementsConfig,
|
|
41
|
+
} from '@armory-sh/middleware-hono';
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Extensions
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import {
|
|
48
|
+
buildExtensions,
|
|
49
|
+
extractExtension,
|
|
50
|
+
|
|
51
|
+
// Types
|
|
52
|
+
type ExtensionConfig,
|
|
53
|
+
} from '@armory-sh/middleware-hono';
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
35
58
|
## Quick Start
|
|
36
59
|
|
|
37
60
|
### Basic Middleware
|
|
@@ -168,6 +191,7 @@ interface RouteAwarePaymentConfig extends PaymentConfig {
|
|
|
168
191
|
| Base Sepolia | 84532 |
|
|
169
192
|
| SKALE Base | 1187947933 |
|
|
170
193
|
| SKALE Base Sepolia | 324705682 |
|
|
194
|
+
| Ethereum Sepolia | 11155111 |
|
|
171
195
|
|
|
172
196
|
## License
|
|
173
197
|
|
package/dist/index.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ interface PaymentConfig {
|
|
|
23
23
|
facilitatorUrl?: string;
|
|
24
24
|
facilitatorUrlByChain?: Record<string, string>;
|
|
25
25
|
facilitatorUrlByToken?: Record<string, Record<string, string>>;
|
|
26
|
+
extensions?: Record<string, unknown>;
|
|
26
27
|
}
|
|
27
28
|
interface ResolvedRequirementsConfig {
|
|
28
29
|
requirements: PaymentRequirementsV2[];
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { buildExtensions, extractExtension } from './chunk-XYM6YXAQ.js';
|
|
2
|
-
import { matchRoute, V2_HEADERS, safeBase64Encode, decodePayloadHeader, findRequirementByAccepted, verifyPayment, createPaymentRequiredHeaders, settlePayment, createSettlementHeaders, resolveNetwork, isValidationError, resolveToken, createPaymentRequirements as createPaymentRequirements$1, PAYMENT_SIGNATURE_HEADER, PAYMENT_REQUIRED_HEADER, validateRouteConfig, TOKENS, registerToken } from '@armory-sh/base';
|
|
2
|
+
import { matchRoute, V2_HEADERS, safeBase64Encode, decodePayloadHeader, findRequirementByAccepted, verifyPayment, createPaymentRequiredHeaders, settlePayment, createSettlementHeaders, resolveNetwork, isValidationError, resolveToken, enrichPaymentRequirements, createPaymentRequirements as createPaymentRequirements$1, PAYMENT_SIGNATURE_HEADER, PAYMENT_REQUIRED_HEADER, validateRouteConfig, TOKENS, registerToken, getSupported } from '@armory-sh/base';
|
|
3
3
|
|
|
4
4
|
var resolveRouteConfig = (config) => {
|
|
5
5
|
const validationError = validateRouteConfig(config);
|
|
@@ -155,6 +155,8 @@ var routeAwarePaymentMiddleware = (config) => {
|
|
|
155
155
|
};
|
|
156
156
|
|
|
157
157
|
// src/index.ts
|
|
158
|
+
var extensionCapabilityCache = /* @__PURE__ */ new Map();
|
|
159
|
+
var EXTENSION_CAPABILITY_TTL_MS = 5 * 60 * 1e3;
|
|
158
160
|
function ensureTokensRegistered() {
|
|
159
161
|
for (const token of Object.values(TOKENS)) {
|
|
160
162
|
try {
|
|
@@ -171,17 +173,13 @@ function resolveFacilitatorUrlFromRequirement(config, requirement) {
|
|
|
171
173
|
config.facilitatorUrlByToken
|
|
172
174
|
)) {
|
|
173
175
|
const resolvedChain = resolveNetwork(chainKey);
|
|
174
|
-
if (
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
return url;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
176
|
+
if (isValidationError(resolvedChain) || resolvedChain.config.chainId !== chainId) {
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
for (const [tokenKey, url] of Object.entries(tokenMap)) {
|
|
180
|
+
const resolvedToken = resolveToken(tokenKey, resolvedChain);
|
|
181
|
+
if (!isValidationError(resolvedToken) && resolvedToken.config.contractAddress.toLowerCase() === assetAddress) {
|
|
182
|
+
return url;
|
|
185
183
|
}
|
|
186
184
|
}
|
|
187
185
|
}
|
|
@@ -200,8 +198,9 @@ function resolveFacilitatorUrlFromRequirement(config, requirement) {
|
|
|
200
198
|
}
|
|
201
199
|
function createPaymentRequirements(config) {
|
|
202
200
|
if (config.requirements) {
|
|
201
|
+
const requirements = Array.isArray(config.requirements) ? config.requirements : [config.requirements];
|
|
203
202
|
return {
|
|
204
|
-
requirements:
|
|
203
|
+
requirements: enrichPaymentRequirements(requirements)
|
|
205
204
|
};
|
|
206
205
|
}
|
|
207
206
|
if (!config.payTo) {
|
|
@@ -216,8 +215,56 @@ function createPaymentRequirements(config) {
|
|
|
216
215
|
ensureTokensRegistered();
|
|
217
216
|
return createPaymentRequirements$1(config);
|
|
218
217
|
}
|
|
218
|
+
async function resolvePaymentRequiredExtensions(config, requirements) {
|
|
219
|
+
if (!config.extensions) {
|
|
220
|
+
return {};
|
|
221
|
+
}
|
|
222
|
+
let filtered = { ...config.extensions };
|
|
223
|
+
for (const requirement of requirements) {
|
|
224
|
+
const facilitatorUrl = resolveFacilitatorUrlFromRequirement(config, requirement);
|
|
225
|
+
if (!facilitatorUrl) {
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
const cacheKey = `${facilitatorUrl}|${requirement.network.toLowerCase()}`;
|
|
229
|
+
const now = Date.now();
|
|
230
|
+
let keys = extensionCapabilityCache.get(cacheKey);
|
|
231
|
+
if (!keys || keys.expiresAt <= now) {
|
|
232
|
+
try {
|
|
233
|
+
const supported = await getSupported({ url: facilitatorUrl });
|
|
234
|
+
const nextKeys = /* @__PURE__ */ new Set();
|
|
235
|
+
for (const kind of supported.kinds) {
|
|
236
|
+
if (kind.network.toLowerCase() !== requirement.network.toLowerCase()) {
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
if (kind.extra && typeof kind.extra === "object") {
|
|
240
|
+
for (const key of Object.keys(kind.extra)) {
|
|
241
|
+
nextKeys.add(key);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
keys = { expiresAt: now + EXTENSION_CAPABILITY_TTL_MS, keys: nextKeys };
|
|
246
|
+
} catch {
|
|
247
|
+
keys = { expiresAt: now + EXTENSION_CAPABILITY_TTL_MS, keys: /* @__PURE__ */ new Set() };
|
|
248
|
+
}
|
|
249
|
+
extensionCapabilityCache.set(cacheKey, keys);
|
|
250
|
+
}
|
|
251
|
+
filtered = Object.fromEntries(
|
|
252
|
+
Object.entries(filtered).filter(([key]) => keys.keys.has(key))
|
|
253
|
+
);
|
|
254
|
+
if (Object.keys(filtered).length === 0) {
|
|
255
|
+
return {};
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return filtered;
|
|
259
|
+
}
|
|
219
260
|
function paymentMiddleware(config) {
|
|
220
261
|
const { requirements, error } = createPaymentRequirements(config);
|
|
262
|
+
const resolvePaymentRequiredHeader = async () => createPaymentRequiredHeaders(requirements, {
|
|
263
|
+
extensions: await resolvePaymentRequiredExtensions(
|
|
264
|
+
config,
|
|
265
|
+
requirements
|
|
266
|
+
)
|
|
267
|
+
})[PAYMENT_REQUIRED_HEADER];
|
|
221
268
|
return async (c, next) => {
|
|
222
269
|
if (error) {
|
|
223
270
|
c.status(500);
|
|
@@ -250,7 +297,7 @@ function paymentMiddleware(config) {
|
|
|
250
297
|
c.status(402);
|
|
251
298
|
c.header(
|
|
252
299
|
PAYMENT_REQUIRED_HEADER,
|
|
253
|
-
safeBase64Encode(JSON.stringify(paymentRequired))
|
|
300
|
+
await resolvePaymentRequiredHeader() ?? safeBase64Encode(JSON.stringify(paymentRequired))
|
|
254
301
|
);
|
|
255
302
|
return c.json({
|
|
256
303
|
error: "Payment required",
|
|
@@ -297,7 +344,7 @@ function paymentMiddleware(config) {
|
|
|
297
344
|
c.status(402);
|
|
298
345
|
c.header(
|
|
299
346
|
PAYMENT_REQUIRED_HEADER,
|
|
300
|
-
|
|
347
|
+
await resolvePaymentRequiredHeader()
|
|
301
348
|
);
|
|
302
349
|
return c.json({
|
|
303
350
|
error: "Payment verification failed",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@armory-sh/middleware-hono",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.31",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Sawyer Cutler <sawyer@dirtroad.dev>",
|
|
6
6
|
"keywords": [
|
|
@@ -52,8 +52,8 @@
|
|
|
52
52
|
"hono": "^4"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@armory-sh/base": "0.2.
|
|
56
|
-
"@armory-sh/extensions": "0.1.
|
|
55
|
+
"@armory-sh/base": "0.2.31",
|
|
56
|
+
"@armory-sh/extensions": "0.1.12"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"bun-types": "latest",
|