@armory-sh/middleware-elysia 0.3.27 → 0.3.28

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
@@ -16,6 +16,7 @@ interface PaymentConfig {
16
16
  facilitatorUrl?: string;
17
17
  facilitatorUrlByChain?: Record<string, string>;
18
18
  facilitatorUrlByToken?: Record<string, Record<string, string>>;
19
+ extensions?: Record<string, unknown>;
19
20
  }
20
21
  interface ResolvedRequirementsConfig {
21
22
  requirements: PaymentRequirementsV2[];
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  export { routeAwarePaymentMiddleware } from './chunk-L45RQOFN.js';
2
- import { resolveNetwork, isValidationError, resolveToken, createPaymentRequirements as createPaymentRequirements$1, PAYMENT_SIGNATURE_HEADER, createPaymentRequiredHeaders, decodePayloadHeader, findRequirementByAccepted, verifyPayment, settlePayment, createSettlementHeaders, TOKENS, registerToken } from '@armory-sh/base';
2
+ import { resolveNetwork, isValidationError, resolveToken, createPaymentRequirements as createPaymentRequirements$1, PAYMENT_SIGNATURE_HEADER, decodePayloadHeader, findRequirementByAccepted, verifyPayment, settlePayment, createSettlementHeaders, createPaymentRequiredHeaders, TOKENS, registerToken, getSupported } from '@armory-sh/base';
3
3
  import { Elysia } from 'elysia';
4
4
 
5
+ var extensionCapabilityCache = /* @__PURE__ */ new Map();
6
+ var EXTENSION_CAPABILITY_TTL_MS = 5 * 60 * 1e3;
5
7
  function ensureTokensRegistered() {
6
8
  for (const token of Object.values(TOKENS)) {
7
9
  try {
@@ -18,17 +20,13 @@ function resolveFacilitatorUrlFromRequirement(config, requirement) {
18
20
  config.facilitatorUrlByToken
19
21
  )) {
20
22
  const resolvedChain = resolveNetwork(chainKey);
21
- if (!isValidationError(resolvedChain) && resolvedChain.config.chainId === chainId) {
22
- for (const [, url] of Object.entries(tokenMap)) {
23
- const network = resolveNetwork(chainKey);
24
- if (!isValidationError(network)) {
25
- for (const tokenKey of Object.keys(tokenMap)) {
26
- const resolvedToken = resolveToken(tokenKey, network);
27
- if (!isValidationError(resolvedToken) && resolvedToken.config.contractAddress.toLowerCase() === assetAddress) {
28
- return url;
29
- }
30
- }
31
- }
23
+ if (isValidationError(resolvedChain) || resolvedChain.config.chainId !== chainId) {
24
+ continue;
25
+ }
26
+ for (const [tokenKey, url] of Object.entries(tokenMap)) {
27
+ const resolvedToken = resolveToken(tokenKey, resolvedChain);
28
+ if (!isValidationError(resolvedToken) && resolvedToken.config.contractAddress.toLowerCase() === assetAddress) {
29
+ return url;
32
30
  }
33
31
  }
34
32
  }
@@ -63,12 +61,60 @@ function createPaymentRequirements(config) {
63
61
  ensureTokensRegistered();
64
62
  return createPaymentRequirements$1(config);
65
63
  }
64
+ async function resolvePaymentRequiredExtensions(config, requirements) {
65
+ if (!config.extensions) {
66
+ return {};
67
+ }
68
+ let filtered = { ...config.extensions };
69
+ for (const requirement of requirements) {
70
+ const facilitatorUrl = resolveFacilitatorUrlFromRequirement(config, requirement);
71
+ if (!facilitatorUrl) {
72
+ continue;
73
+ }
74
+ const cacheKey = `${facilitatorUrl}|${requirement.network.toLowerCase()}`;
75
+ const now = Date.now();
76
+ let keys = extensionCapabilityCache.get(cacheKey);
77
+ if (!keys || keys.expiresAt <= now) {
78
+ try {
79
+ const supported = await getSupported({ url: facilitatorUrl });
80
+ const nextKeys = /* @__PURE__ */ new Set();
81
+ for (const kind of supported.kinds) {
82
+ if (kind.network.toLowerCase() !== requirement.network.toLowerCase()) {
83
+ continue;
84
+ }
85
+ if (kind.extra && typeof kind.extra === "object") {
86
+ for (const key of Object.keys(kind.extra)) {
87
+ nextKeys.add(key);
88
+ }
89
+ }
90
+ }
91
+ keys = { expiresAt: now + EXTENSION_CAPABILITY_TTL_MS, keys: nextKeys };
92
+ } catch {
93
+ keys = { expiresAt: now + EXTENSION_CAPABILITY_TTL_MS, keys: /* @__PURE__ */ new Set() };
94
+ }
95
+ extensionCapabilityCache.set(cacheKey, keys);
96
+ }
97
+ filtered = Object.fromEntries(
98
+ Object.entries(filtered).filter(([key]) => keys.keys.has(key))
99
+ );
100
+ if (Object.keys(filtered).length === 0) {
101
+ return {};
102
+ }
103
+ }
104
+ return filtered;
105
+ }
66
106
  var errorResponse = (error, status, headers) => new Response(JSON.stringify(error), {
67
107
  status,
68
108
  headers: { "Content-Type": "application/json", ...headers }
69
109
  });
70
110
  var paymentMiddleware = (config) => {
71
111
  const { requirements, error } = createPaymentRequirements(config);
112
+ const resolvePaymentRequiredHeaders = async () => createPaymentRequiredHeaders(requirements, {
113
+ extensions: await resolvePaymentRequiredExtensions(
114
+ config,
115
+ requirements
116
+ )
117
+ });
72
118
  return new Elysia({ name: "armory-payment" }).derive(() => ({
73
119
  payment: void 0
74
120
  })).onBeforeHandle(async (context) => {
@@ -95,10 +141,11 @@ var paymentMiddleware = (config) => {
95
141
  PAYMENT_SIGNATURE_HEADER
96
142
  );
97
143
  if (!paymentHeader) {
144
+ const requiredHeaders = await resolvePaymentRequiredHeaders();
98
145
  return errorResponse(
99
146
  { error: "Payment required", accepts: requirements },
100
147
  402,
101
- createPaymentRequiredHeaders(requirements)
148
+ requiredHeaders
102
149
  );
103
150
  }
104
151
  let paymentPayload;
@@ -147,13 +194,14 @@ var paymentMiddleware = (config) => {
147
194
  { url: facilitatorUrl }
148
195
  );
149
196
  if (!verifyResult.isValid) {
197
+ const requiredHeaders = await resolvePaymentRequiredHeaders();
150
198
  return errorResponse(
151
199
  {
152
200
  error: "Payment verification failed",
153
201
  message: verifyResult.invalidReason
154
202
  },
155
203
  402,
156
- createPaymentRequiredHeaders(requirements)
204
+ requiredHeaders
157
205
  );
158
206
  }
159
207
  const payerAddress = verifyResult.payer ?? paymentPayload.payload.authorization.from;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@armory-sh/middleware-elysia",
3
- "version": "0.3.27",
3
+ "version": "0.3.28",
4
4
  "license": "MIT",
5
5
  "author": "Sawyer Cutler <sawyer@dirtroad.dev>",
6
6
  "keywords": [
@@ -47,7 +47,7 @@
47
47
  "elysia": "^1"
48
48
  },
49
49
  "dependencies": {
50
- "@armory-sh/base": "0.2.29"
50
+ "@armory-sh/base": "0.2.30"
51
51
  },
52
52
  "devDependencies": {
53
53
  "bun-types": "latest",