@armory-sh/middleware-hono 0.3.17 → 0.3.19

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,7 +1,30 @@
1
1
  import { Context, Next } from 'hono';
2
- import { PaymentPayloadV2, PaymentRequirements } from '@armory-sh/base';
2
+ import { PaymentRequirementsV2, ValidationError, PaymentRequirements, PaymentPayloadV2 } from '@armory-sh/base';
3
3
 
4
- interface PaymentMiddlewareConfig {
4
+ /**
5
+ * Simplified middleware API for easy x402 payment integration
6
+ * Just specify payTo address and optional chains/tokens by name
7
+ */
8
+
9
+ type NetworkId = string | number;
10
+ type TokenId = string;
11
+ interface PaymentConfig {
12
+ payTo: string;
13
+ chains?: NetworkId[];
14
+ chain?: NetworkId;
15
+ tokens?: TokenId[];
16
+ token?: TokenId;
17
+ amount?: string;
18
+ maxTimeoutSeconds?: number;
19
+ }
20
+ interface ResolvedSimpleConfig {
21
+ requirements: PaymentRequirementsV2[];
22
+ error?: ValidationError;
23
+ }
24
+ declare function createPaymentRequirements(config: PaymentConfig): ResolvedSimpleConfig;
25
+ declare function paymentMiddleware(config: PaymentConfig): (c: Context, next: Next) => Promise<Response | void>;
26
+
27
+ interface AdvancedPaymentConfig {
5
28
  requirements: PaymentRequirements;
6
29
  facilitatorUrl?: string;
7
30
  skipVerification?: boolean;
@@ -14,6 +37,6 @@ interface AugmentedRequest extends Request {
14
37
  verified: boolean;
15
38
  };
16
39
  }
17
- declare const paymentMiddleware: (config: PaymentMiddlewareConfig) => (c: Context, next: Next) => Promise<Response | void>;
40
+ declare const advancedPaymentMiddleware: (config: AdvancedPaymentConfig) => (c: Context, next: Next) => Promise<Response | void>;
18
41
 
19
- export { type AugmentedRequest, type PaymentMiddlewareConfig, paymentMiddleware };
42
+ export { type AdvancedPaymentConfig, type AugmentedRequest, type PaymentConfig, advancedPaymentMiddleware, createPaymentRequirements, paymentMiddleware };
package/dist/index.js CHANGED
@@ -1,11 +1,185 @@
1
1
  // src/index.ts
2
2
  import {
3
3
  createPaymentRequiredHeaders,
4
- createSettlementHeaders,
5
4
  PAYMENT_SIGNATURE_HEADER,
6
5
  decodePaymentV2
7
6
  } from "@armory-sh/base";
8
- var paymentMiddleware = (config) => {
7
+
8
+ // src/simple.ts
9
+ import {
10
+ resolveNetwork,
11
+ resolveToken,
12
+ safeBase64Encode,
13
+ V2_HEADERS,
14
+ registerToken
15
+ } from "@armory-sh/base";
16
+ import {
17
+ TOKENS
18
+ } from "@armory-sh/base";
19
+ var isValidationError = (value) => {
20
+ return typeof value === "object" && value !== null && "code" in value;
21
+ };
22
+ function ensureTokensRegistered() {
23
+ for (const token of Object.values(TOKENS)) {
24
+ try {
25
+ registerToken(token);
26
+ } catch {
27
+ }
28
+ }
29
+ }
30
+ function resolveChainTokenInputs(chains, tokens) {
31
+ const resolvedNetworks = [];
32
+ const resolvedTokens = [];
33
+ const errors = [];
34
+ const networkInputs = chains?.length ? chains : Object.keys({
35
+ ethereum: 1,
36
+ base: 8453,
37
+ "base-sepolia": 84532,
38
+ "skale-base": 1187947933,
39
+ "skale-base-sepolia": 324705682,
40
+ "ethereum-sepolia": 11155111
41
+ });
42
+ for (const networkId of networkInputs) {
43
+ const resolved = resolveNetwork(networkId);
44
+ if (isValidationError(resolved)) {
45
+ errors.push(`Network "${networkId}": ${resolved.message}`);
46
+ } else {
47
+ resolvedNetworks.push(resolved);
48
+ }
49
+ }
50
+ const tokenInputs = tokens?.length ? tokens : ["usdc"];
51
+ for (const tokenId of tokenInputs) {
52
+ let found = false;
53
+ for (const network of resolvedNetworks) {
54
+ const resolved = resolveToken(tokenId, network);
55
+ if (isValidationError(resolved)) {
56
+ continue;
57
+ }
58
+ resolvedTokens.push(resolved);
59
+ found = true;
60
+ break;
61
+ }
62
+ if (!found) {
63
+ errors.push(`Token "${tokenId}" not found on any specified network`);
64
+ }
65
+ }
66
+ if (errors.length > 0) {
67
+ return {
68
+ networks: resolvedNetworks,
69
+ tokens: resolvedTokens,
70
+ error: {
71
+ code: "VALIDATION_FAILED",
72
+ message: errors.join("; ")
73
+ }
74
+ };
75
+ }
76
+ return { networks: resolvedNetworks, tokens: resolvedTokens };
77
+ }
78
+ function toAtomicUnits(amount) {
79
+ if (amount.includes(".")) {
80
+ const [whole, fractional = ""] = amount.split(".");
81
+ const paddedFractional = fractional.padEnd(6, "0").slice(0, 6);
82
+ return `${whole}${paddedFractional}`.replace(/^0+/, "") || "0";
83
+ }
84
+ return `${amount}000000`;
85
+ }
86
+ function createPaymentRequirements(config) {
87
+ ensureTokensRegistered();
88
+ const {
89
+ payTo,
90
+ chains,
91
+ chain,
92
+ tokens,
93
+ token,
94
+ amount = "1.0",
95
+ maxTimeoutSeconds = 300
96
+ } = config;
97
+ const chainInputs = chain ? [chain] : chains;
98
+ const tokenInputs = token ? [token] : tokens;
99
+ const { networks, tokens: resolvedTokens, error } = resolveChainTokenInputs(
100
+ chainInputs,
101
+ tokenInputs
102
+ );
103
+ if (error) {
104
+ return { requirements: [], error };
105
+ }
106
+ const requirements = [];
107
+ for (const network of networks) {
108
+ for (const resolvedToken of resolvedTokens) {
109
+ if (resolvedToken.network.config.chainId !== network.config.chainId) {
110
+ continue;
111
+ }
112
+ const atomicAmount = toAtomicUnits(amount);
113
+ const tokenConfig = resolvedToken.config;
114
+ requirements.push({
115
+ scheme: "exact",
116
+ network: network.caip2,
117
+ amount: atomicAmount,
118
+ asset: tokenConfig.contractAddress,
119
+ payTo,
120
+ maxTimeoutSeconds,
121
+ extra: {
122
+ name: tokenConfig.name,
123
+ version: tokenConfig.version
124
+ }
125
+ });
126
+ }
127
+ }
128
+ return { requirements };
129
+ }
130
+ function paymentMiddleware(config) {
131
+ const { requirements, error } = createPaymentRequirements(config);
132
+ return async (c, next) => {
133
+ if (error) {
134
+ c.status(500);
135
+ return c.json({
136
+ error: "Payment middleware configuration error",
137
+ details: error.message
138
+ });
139
+ }
140
+ const paymentHeader = c.req.header(V2_HEADERS.PAYMENT_SIGNATURE);
141
+ if (!paymentHeader) {
142
+ const resource = {
143
+ url: c.req.url,
144
+ description: "API Access",
145
+ mimeType: "application/json"
146
+ };
147
+ const paymentRequired = {
148
+ x402Version: 2,
149
+ error: "Payment required",
150
+ resource,
151
+ accepts: requirements
152
+ };
153
+ c.status(402);
154
+ c.header(V2_HEADERS.PAYMENT_REQUIRED, safeBase64Encode(JSON.stringify(paymentRequired)));
155
+ return c.json({
156
+ error: "Payment required",
157
+ accepts: requirements
158
+ });
159
+ }
160
+ const payload = paymentHeader;
161
+ let parsedPayload;
162
+ try {
163
+ const decoded = atob(payload);
164
+ parsedPayload = JSON.parse(decoded);
165
+ } catch {
166
+ try {
167
+ parsedPayload = JSON.parse(payload);
168
+ } catch {
169
+ c.status(400);
170
+ return c.json({ error: "Invalid payment payload" });
171
+ }
172
+ }
173
+ c.set("payment", {
174
+ payload: parsedPayload,
175
+ verified: false
176
+ });
177
+ return next();
178
+ };
179
+ }
180
+
181
+ // src/index.ts
182
+ var advancedPaymentMiddleware = (config) => {
9
183
  const { requirements, facilitatorUrl, skipVerification = false, network = "base" } = config;
10
184
  return async (c, next) => {
11
185
  const paymentHeader = c.req.header(PAYMENT_SIGNATURE_HEADER);
@@ -22,11 +196,8 @@ var paymentMiddleware = (config) => {
22
196
  }
23
197
  let paymentPayload = null;
24
198
  try {
25
- console.log("[x402 Debug] Raw payment header:", paymentHeader);
26
199
  paymentPayload = decodePaymentV2(paymentHeader);
27
- console.log("[x402 Debug] Decoded payload:", JSON.stringify(paymentPayload, null, 2));
28
200
  } catch (e) {
29
- console.error("[x402 Debug] Decode error:", e);
30
201
  c.status(400);
31
202
  return c.json({ error: "Invalid payment payload", details: String(e) });
32
203
  }
@@ -35,15 +206,6 @@ var paymentMiddleware = (config) => {
35
206
  return c.json({ error: "Invalid payment payload" });
36
207
  }
37
208
  const payerAddress = paymentPayload.payload.authorization.from;
38
- const settlement = {
39
- success: true,
40
- transaction: "",
41
- network
42
- };
43
- const settlementHeaders = createSettlementHeaders(settlement);
44
- for (const [key, value] of Object.entries(settlementHeaders)) {
45
- c.header(key, value);
46
- }
47
209
  c.set("payment", {
48
210
  payload: paymentPayload,
49
211
  payerAddress,
@@ -53,5 +215,7 @@ var paymentMiddleware = (config) => {
53
215
  };
54
216
  };
55
217
  export {
218
+ advancedPaymentMiddleware,
219
+ createPaymentRequirements,
56
220
  paymentMiddleware
57
221
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@armory-sh/middleware-hono",
3
- "version": "0.3.17",
3
+ "version": "0.3.19",
4
4
  "license": "MIT",
5
5
  "author": "Sawyer Cutler <sawyer@dirtroad.dev>",
6
6
  "type": "module",
@@ -28,7 +28,7 @@
28
28
  "hono": "^4"
29
29
  },
30
30
  "dependencies": {
31
- "@armory-sh/base": "0.2.17"
31
+ "@armory-sh/base": "0.2.19"
32
32
  },
33
33
  "devDependencies": {
34
34
  "bun-types": "latest",