@apitoll/seller-sdk 0.1.0-beta.1

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.
@@ -0,0 +1,43 @@
1
+ import type { Request, Response, NextFunction } from "express";
2
+ import { type SellerConfig, type EndpointConfig, type FeeBreakdown } from "@apitoll/shared";
3
+ export interface PaymentMiddlewareOptions extends SellerConfig {
4
+ }
5
+ /**
6
+ * Express middleware that adds x402 payment requirements to protected endpoints.
7
+ * Now supports platform fee splitting — a percentage of each payment goes to the platform.
8
+ *
9
+ * Usage:
10
+ * ```ts
11
+ * import { paymentMiddleware } from "@apitoll/seller-sdk";
12
+ *
13
+ * app.use(paymentMiddleware({
14
+ * walletAddress: "0xYourWallet...",
15
+ * endpoints: {
16
+ * "GET /api/data": {
17
+ * price: "0.005",
18
+ * chains: ["base", "solana"],
19
+ * description: "Premium data feed",
20
+ * },
21
+ * },
22
+ * platformFee: {
23
+ * feeBps: 300, // 3%
24
+ * platformWalletBase: "0xPlatformWallet...",
25
+ * },
26
+ * }));
27
+ * ```
28
+ */
29
+ export declare function paymentMiddleware(options: PaymentMiddlewareOptions): (req: Request, res: Response, next: NextFunction) => Promise<void>;
30
+ /**
31
+ * Helper to access the payment receipt from a request.
32
+ */
33
+ export declare function getPaymentReceipt(req: Request): any;
34
+ /**
35
+ * Helper to access full x402 context from a request (includes fee info).
36
+ */
37
+ export declare function getX402Context(req: Request): {
38
+ receipt: ReturnType<typeof getPaymentReceipt>;
39
+ feeBreakdown?: FeeBreakdown;
40
+ endpoint: string;
41
+ config: EndpointConfig;
42
+ } | null;
43
+ //# sourceMappingURL=middleware-express.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware-express.d.ts","sourceRoot":"","sources":["../src/middleware-express.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,cAAc,EAGnB,KAAK,YAAY,EAGlB,MAAM,iBAAiB,CAAC;AAUzB,MAAM,WAAW,wBAAyB,SAAQ,YAAY;CAAG;AAEjE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,IAoH/D,KAAK,OAAO,EACZ,KAAK,QAAQ,EACb,MAAM,YAAY,KACjB,OAAO,CAAC,IAAI,CAAC,CAwIjB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,OAE7C;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG;IAC5C,OAAO,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;IAC9C,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,cAAc,CAAC;CACxB,GAAG,IAAI,CAEP"}
@@ -0,0 +1,239 @@
1
+ import { DEFAULT_CHAIN_CONFIGS, SECURITY_HEADERS, } from "@apitoll/shared";
2
+ import { buildPaymentRequirements, encodePaymentRequired, verifyPayment, findEndpointConfig, getEndpointFeeBreakdown, } from "./payment";
3
+ import { AnalyticsReporter } from "./analytics";
4
+ /**
5
+ * Express middleware that adds x402 payment requirements to protected endpoints.
6
+ * Now supports platform fee splitting — a percentage of each payment goes to the platform.
7
+ *
8
+ * Usage:
9
+ * ```ts
10
+ * import { paymentMiddleware } from "@apitoll/seller-sdk";
11
+ *
12
+ * app.use(paymentMiddleware({
13
+ * walletAddress: "0xYourWallet...",
14
+ * endpoints: {
15
+ * "GET /api/data": {
16
+ * price: "0.005",
17
+ * chains: ["base", "solana"],
18
+ * description: "Premium data feed",
19
+ * },
20
+ * },
21
+ * platformFee: {
22
+ * feeBps: 300, // 3%
23
+ * platformWalletBase: "0xPlatformWallet...",
24
+ * },
25
+ * }));
26
+ * ```
27
+ */
28
+ export function paymentMiddleware(options) {
29
+ const { walletAddress, endpoints, chainConfigs: customChainConfigs, facilitatorUrl, webhookUrl, platformApiKey, platformFee, } = options;
30
+ // Merge custom chain configs with defaults
31
+ const chainConfigs = {
32
+ base: { ...DEFAULT_CHAIN_CONFIGS.base, ...customChainConfigs?.base },
33
+ solana: { ...DEFAULT_CHAIN_CONFIGS.solana, ...customChainConfigs?.solana },
34
+ };
35
+ // Initialize analytics reporter
36
+ const reporter = new AnalyticsReporter({
37
+ apiKey: platformApiKey,
38
+ webhookUrl,
39
+ verbose: process.env.NODE_ENV !== "production",
40
+ });
41
+ // Rate limiting: Redis-backed distributed rate limiting with circuit breaker
42
+ const RATE_LIMIT_WINDOW_MS = 60_000; // 1 minute
43
+ const RATE_LIMIT_MAX = 120; // max requests per window per IP
44
+ // Circuit breaker state for Redis failures
45
+ let redisFailureCount = 0;
46
+ let circuitOpen = false;
47
+ let circuitOpenedAt = 0;
48
+ const CIRCUIT_FAILURE_THRESHOLD = 5; // Open circuit after 5 consecutive failures
49
+ const CIRCUIT_RESET_MS = 30_000; // Try again after 30 seconds
50
+ // Redis is optional — if not available, falls through to in-memory rate limiting
51
+ let redis = null;
52
+ try {
53
+ const Redis = require('redis');
54
+ redis = Redis.createClient({
55
+ host: process.env.REDIS_HOST || 'localhost',
56
+ port: parseInt(process.env.REDIS_PORT || '6379'),
57
+ retryStrategy: (times) => Math.min(times * 50, 2000),
58
+ });
59
+ redis.on('error', (err) => {
60
+ console.warn('Redis connection error, using in-memory rate limiting:', err.message);
61
+ });
62
+ }
63
+ catch {
64
+ // Redis not installed — start with circuit open to use in-memory fallback
65
+ circuitOpen = true;
66
+ circuitOpenedAt = Date.now();
67
+ }
68
+ // In-memory fallback rate limiter (used when Redis circuit is open)
69
+ const fallbackRateLimitMap = new Map();
70
+ function checkFallbackRateLimit(key, limit, windowMs) {
71
+ const now = Date.now();
72
+ const timestamps = fallbackRateLimitMap.get(key) || [];
73
+ const recent = timestamps.filter((t) => now - t < windowMs);
74
+ recent.push(now);
75
+ fallbackRateLimitMap.set(key, recent);
76
+ // Periodic cleanup to prevent memory leaks
77
+ if (fallbackRateLimitMap.size > 10_000) {
78
+ for (const [k, v] of fallbackRateLimitMap) {
79
+ if (v.every((t) => now - t > windowMs)) {
80
+ fallbackRateLimitMap.delete(k);
81
+ }
82
+ }
83
+ }
84
+ return recent.length <= limit;
85
+ }
86
+ async function checkRateLimit(key, limit) {
87
+ // If circuit is open, check if enough time has passed to try again
88
+ if (circuitOpen) {
89
+ if (Date.now() - circuitOpenedAt > CIRCUIT_RESET_MS) {
90
+ // Half-open: try Redis again
91
+ circuitOpen = false;
92
+ redisFailureCount = 0;
93
+ }
94
+ else {
95
+ // Circuit still open — use in-memory fallback
96
+ return checkFallbackRateLimit(key, limit, RATE_LIMIT_WINDOW_MS);
97
+ }
98
+ }
99
+ try {
100
+ if (!redis)
101
+ throw new Error('Redis not available');
102
+ const count = await redis.incr(key);
103
+ if (count === 1) {
104
+ await redis.expire(key, Math.ceil(RATE_LIMIT_WINDOW_MS / 1000));
105
+ }
106
+ // Success — reset failure counter
107
+ redisFailureCount = 0;
108
+ return count <= limit;
109
+ }
110
+ catch (e) {
111
+ console.error('Rate limit Redis error:', e);
112
+ redisFailureCount++;
113
+ if (redisFailureCount >= CIRCUIT_FAILURE_THRESHOLD) {
114
+ circuitOpen = true;
115
+ circuitOpenedAt = Date.now();
116
+ console.warn(`⚠️ Redis circuit breaker OPEN after ${redisFailureCount} failures. ` +
117
+ `Falling back to in-memory rate limiting for ${CIRCUIT_RESET_MS / 1000}s.`);
118
+ }
119
+ // Fallback to in-memory rate limiting (never fail open)
120
+ return checkFallbackRateLimit(key, limit, RATE_LIMIT_WINDOW_MS);
121
+ }
122
+ }
123
+ return async function x402PaymentMiddleware(req, res, next) {
124
+ const startTime = Date.now();
125
+ // Apply security headers
126
+ for (const [header, value] of Object.entries(SECURITY_HEADERS)) {
127
+ res.setHeader(header, value);
128
+ }
129
+ // Rate limiting by IP (Redis-backed, distributed)
130
+ const clientIp = req.ip || req.socket.remoteAddress || "unknown";
131
+ const key = `ratelimit:${clientIp}:${Math.floor(Date.now() / 60000)}`;
132
+ const allowed = await checkRateLimit(key, RATE_LIMIT_MAX);
133
+ if (!allowed) {
134
+ res.status(429);
135
+ res.json({
136
+ error: "Too Many Requests",
137
+ message: "Rate limit exceeded. Try again later.",
138
+ retryAfter: Math.ceil(RATE_LIMIT_WINDOW_MS / 1000),
139
+ });
140
+ return;
141
+ }
142
+ // Check if this route requires payment
143
+ const match = findEndpointConfig(req.method, req.path, endpoints);
144
+ if (!match) {
145
+ // Not a paid endpoint — pass through
146
+ return next();
147
+ }
148
+ const { pattern, config } = match;
149
+ // Validate Content-Type for POST/PUT/PATCH
150
+ if (["POST", "PUT", "PATCH"].includes(req.method)) {
151
+ const contentType = req.headers["content-type"];
152
+ if (contentType && !contentType.includes("application/json")) {
153
+ res.status(415);
154
+ res.json({
155
+ error: "Unsupported Media Type",
156
+ message: "Content-Type must be application/json",
157
+ });
158
+ return;
159
+ }
160
+ }
161
+ // Check for X-PAYMENT header (client already paid)
162
+ const paymentHeader = req.headers["x-payment"];
163
+ if (!paymentHeader) {
164
+ // No payment provided — return 402 with payment requirements
165
+ const requirements = buildPaymentRequirements(config, walletAddress, chainConfigs, platformFee);
166
+ const feeBreakdown = getEndpointFeeBreakdown(config, platformFee);
167
+ res.status(402);
168
+ res.setHeader("PAYMENT-REQUIRED", encodePaymentRequired(requirements));
169
+ res.setHeader("Content-Type", "application/json");
170
+ res.json({
171
+ error: "Payment Required",
172
+ paymentRequirements: requirements,
173
+ description: config.description,
174
+ feeBreakdown: platformFee ? feeBreakdown : undefined,
175
+ });
176
+ return;
177
+ }
178
+ // Payment provided — verify it
179
+ const requirements = buildPaymentRequirements(config, walletAddress, chainConfigs, platformFee);
180
+ const resolvedFacilitatorUrl = facilitatorUrl || chainConfigs.base.facilitatorUrl;
181
+ const verification = await verifyPayment({
182
+ paymentHeader,
183
+ requirements,
184
+ facilitatorUrl: resolvedFacilitatorUrl,
185
+ }, platformFee);
186
+ if (!verification.valid) {
187
+ await reporter.reportRejection(pattern, req.method, verification.error || "unknown");
188
+ res.status(402);
189
+ res.json({
190
+ error: "Payment Invalid",
191
+ message: verification.error,
192
+ });
193
+ return;
194
+ }
195
+ // Payment verified — attach receipt + fee info to request and continue
196
+ req.paymentReceipt = verification.receipt;
197
+ req.x402 = {
198
+ receipt: verification.receipt,
199
+ feeBreakdown: verification.feeBreakdown,
200
+ endpoint: pattern,
201
+ config,
202
+ };
203
+ // Intercept response to report analytics (including fee data)
204
+ const originalEnd = res.end.bind(res);
205
+ res.end = function (chunk, encoding, cb) {
206
+ const latencyMs = Date.now() - startTime;
207
+ if (verification.receipt) {
208
+ reporter.report({
209
+ endpoint: pattern,
210
+ method: req.method,
211
+ receipt: verification.receipt,
212
+ responseStatus: res.statusCode,
213
+ latencyMs,
214
+ feeBreakdown: verification.feeBreakdown,
215
+ });
216
+ }
217
+ if (typeof encoding === 'function') {
218
+ return originalEnd(chunk, encoding);
219
+ }
220
+ else {
221
+ return originalEnd(chunk, encoding, cb);
222
+ }
223
+ };
224
+ next();
225
+ };
226
+ }
227
+ /**
228
+ * Helper to access the payment receipt from a request.
229
+ */
230
+ export function getPaymentReceipt(req) {
231
+ return req.paymentReceipt || null;
232
+ }
233
+ /**
234
+ * Helper to access full x402 context from a request (includes fee info).
235
+ */
236
+ export function getX402Context(req) {
237
+ return req.x402 || null;
238
+ }
239
+ //# sourceMappingURL=middleware-express.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware-express.js","sourceRoot":"","sources":["../src/middleware-express.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { MiddlewareHandler } from "hono";
2
+ import { type SellerConfig } from "@apitoll/shared";
3
+ /**
4
+ * Hono middleware for x402 payments with platform fee support.
5
+ *
6
+ * Usage:
7
+ * ```ts
8
+ * import { Hono } from "hono";
9
+ * import { paymentMiddleware } from "@apitoll/seller-sdk/hono";
10
+ *
11
+ * const app = new Hono();
12
+ *
13
+ * app.use("*", paymentMiddleware({
14
+ * walletAddress: "0xYourWallet...",
15
+ * endpoints: {
16
+ * "GET /api/data": {
17
+ * price: "0.005",
18
+ * chains: ["base", "solana"],
19
+ * description: "Premium data feed",
20
+ * },
21
+ * },
22
+ * platformFee: {
23
+ * feeBps: 300, // 3%
24
+ * platformWalletBase: "0xPlatformWallet...",
25
+ * },
26
+ * }));
27
+ * ```
28
+ */
29
+ export declare function paymentMiddleware(options: SellerConfig): MiddlewareHandler;
30
+ //# sourceMappingURL=middleware-hono.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware-hono.d.ts","sourceRoot":"","sources":["../src/middleware-hono.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC7D,OAAO,EACL,KAAK,YAAY,EAKlB,MAAM,iBAAiB,CAAC;AAUzB;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,GAAG,iBAAiB,CAsN1E"}
@@ -0,0 +1,192 @@
1
+ import { DEFAULT_CHAIN_CONFIGS, SECURITY_HEADERS, } from "@apitoll/shared";
2
+ import { buildPaymentRequirements, encodePaymentRequired, verifyPayment, findEndpointConfig, getEndpointFeeBreakdown, } from "./payment";
3
+ import { AnalyticsReporter } from "./analytics";
4
+ /**
5
+ * Hono middleware for x402 payments with platform fee support.
6
+ *
7
+ * Usage:
8
+ * ```ts
9
+ * import { Hono } from "hono";
10
+ * import { paymentMiddleware } from "@apitoll/seller-sdk/hono";
11
+ *
12
+ * const app = new Hono();
13
+ *
14
+ * app.use("*", paymentMiddleware({
15
+ * walletAddress: "0xYourWallet...",
16
+ * endpoints: {
17
+ * "GET /api/data": {
18
+ * price: "0.005",
19
+ * chains: ["base", "solana"],
20
+ * description: "Premium data feed",
21
+ * },
22
+ * },
23
+ * platformFee: {
24
+ * feeBps: 300, // 3%
25
+ * platformWalletBase: "0xPlatformWallet...",
26
+ * },
27
+ * }));
28
+ * ```
29
+ */
30
+ export function paymentMiddleware(options) {
31
+ const { walletAddress, endpoints, chainConfigs: customChainConfigs, facilitatorUrl, webhookUrl, platformApiKey, platformFee, } = options;
32
+ const chainConfigs = {
33
+ base: { ...DEFAULT_CHAIN_CONFIGS.base, ...customChainConfigs?.base },
34
+ solana: { ...DEFAULT_CHAIN_CONFIGS.solana, ...customChainConfigs?.solana },
35
+ };
36
+ const reporter = new AnalyticsReporter({
37
+ apiKey: platformApiKey,
38
+ webhookUrl,
39
+ verbose: process.env.NODE_ENV !== "production",
40
+ });
41
+ // Rate limiting: Redis-backed with circuit breaker fallback
42
+ const RATE_LIMIT_WINDOW_MS = 60_000;
43
+ const RATE_LIMIT_MAX = 120;
44
+ let redis = null;
45
+ try {
46
+ const Redis = require('redis');
47
+ redis = Redis.createClient({
48
+ host: process.env.REDIS_HOST || 'localhost',
49
+ port: parseInt(process.env.REDIS_PORT || '6379'),
50
+ retryStrategy: (times) => Math.min(times * 50, 2000),
51
+ });
52
+ }
53
+ catch {
54
+ console.warn('Redis not available for Hono middleware, using in-memory rate limiting');
55
+ }
56
+ // Circuit breaker state
57
+ let redisFailureCount = 0;
58
+ let circuitOpen = false;
59
+ let circuitOpenedAt = 0;
60
+ const CIRCUIT_FAILURE_THRESHOLD = 5;
61
+ const CIRCUIT_RESET_MS = 30_000;
62
+ // In-memory fallback
63
+ const fallbackRateLimitMap = new Map();
64
+ function checkFallbackRateLimit(key, limit, windowMs) {
65
+ const now = Date.now();
66
+ const timestamps = fallbackRateLimitMap.get(key) || [];
67
+ const recent = timestamps.filter((t) => now - t < windowMs);
68
+ recent.push(now);
69
+ fallbackRateLimitMap.set(key, recent);
70
+ if (fallbackRateLimitMap.size > 10_000) {
71
+ for (const [k, v] of fallbackRateLimitMap) {
72
+ if (v.every((t) => now - t > windowMs)) {
73
+ fallbackRateLimitMap.delete(k);
74
+ }
75
+ }
76
+ }
77
+ return recent.length <= limit;
78
+ }
79
+ async function checkRateLimit(key, limit) {
80
+ if (!redis) {
81
+ return checkFallbackRateLimit(key, limit, RATE_LIMIT_WINDOW_MS);
82
+ }
83
+ if (circuitOpen) {
84
+ if (Date.now() - circuitOpenedAt > CIRCUIT_RESET_MS) {
85
+ circuitOpen = false;
86
+ redisFailureCount = 0;
87
+ }
88
+ else {
89
+ return checkFallbackRateLimit(key, limit, RATE_LIMIT_WINDOW_MS);
90
+ }
91
+ }
92
+ try {
93
+ const count = await redis.incr(key);
94
+ if (count === 1) {
95
+ await redis.expire(key, Math.ceil(RATE_LIMIT_WINDOW_MS / 1000));
96
+ }
97
+ redisFailureCount = 0;
98
+ return count <= limit;
99
+ }
100
+ catch (e) {
101
+ console.error('Rate limit Redis error (Hono):', e);
102
+ redisFailureCount++;
103
+ if (redisFailureCount >= CIRCUIT_FAILURE_THRESHOLD) {
104
+ circuitOpen = true;
105
+ circuitOpenedAt = Date.now();
106
+ console.warn(`⚠️ Redis circuit breaker OPEN (Hono). Falling back to in-memory rate limiting.`);
107
+ }
108
+ return checkFallbackRateLimit(key, limit, RATE_LIMIT_WINDOW_MS);
109
+ }
110
+ }
111
+ return async (c, next) => {
112
+ const startTime = Date.now();
113
+ const url = new URL(c.req.url);
114
+ const method = c.req.method;
115
+ const path = url.pathname;
116
+ // Apply security headers
117
+ for (const [header, value] of Object.entries(SECURITY_HEADERS)) {
118
+ c.header(header, value);
119
+ }
120
+ // Rate limiting by IP (Redis-backed with circuit breaker)
121
+ const clientIp = c.req.header("x-forwarded-for") || "unknown";
122
+ const key = `ratelimit:${clientIp}:${Math.floor(Date.now() / 60000)}`;
123
+ const allowed = await checkRateLimit(key, RATE_LIMIT_MAX);
124
+ if (!allowed) {
125
+ return c.json({
126
+ error: "Too Many Requests",
127
+ message: "Rate limit exceeded. Try again later.",
128
+ retryAfter: Math.ceil(RATE_LIMIT_WINDOW_MS / 1000),
129
+ }, 429);
130
+ }
131
+ // Check if this route requires payment
132
+ const match = findEndpointConfig(method, path, endpoints);
133
+ if (!match) {
134
+ return next();
135
+ }
136
+ const { pattern, config } = match;
137
+ // Validate Content-Type for mutation methods
138
+ if (["POST", "PUT", "PATCH"].includes(method)) {
139
+ const contentType = c.req.header("content-type");
140
+ if (contentType && !contentType.includes("application/json")) {
141
+ return c.json({ error: "Unsupported Media Type", message: "Content-Type must be application/json" }, 415);
142
+ }
143
+ }
144
+ const paymentHeader = c.req.header("x-payment");
145
+ if (!paymentHeader) {
146
+ const requirements = buildPaymentRequirements(config, walletAddress, chainConfigs, platformFee);
147
+ const feeBreakdown = getEndpointFeeBreakdown(config, platformFee);
148
+ return c.json({
149
+ error: "Payment Required",
150
+ paymentRequirements: requirements,
151
+ description: config.description,
152
+ feeBreakdown: platformFee ? feeBreakdown : undefined,
153
+ }, 402, {
154
+ "PAYMENT-REQUIRED": encodePaymentRequired(requirements),
155
+ });
156
+ }
157
+ // Verify payment
158
+ const requirements = buildPaymentRequirements(config, walletAddress, chainConfigs, platformFee);
159
+ const resolvedFacilitatorUrl = facilitatorUrl || chainConfigs.base.facilitatorUrl;
160
+ const verification = await verifyPayment({
161
+ paymentHeader,
162
+ requirements,
163
+ facilitatorUrl: resolvedFacilitatorUrl,
164
+ }, platformFee);
165
+ if (!verification.valid) {
166
+ await reporter.reportRejection(pattern, method, verification.error || "unknown");
167
+ return c.json({ error: "Payment Invalid", message: verification.error }, 402);
168
+ }
169
+ // Attach receipt + fee info to context
170
+ c.set("paymentReceipt", verification.receipt);
171
+ c.set("x402", {
172
+ receipt: verification.receipt,
173
+ feeBreakdown: verification.feeBreakdown,
174
+ endpoint: pattern,
175
+ config,
176
+ });
177
+ await next();
178
+ // Report after response (including fee data)
179
+ const latencyMs = Date.now() - startTime;
180
+ if (verification.receipt) {
181
+ reporter.report({
182
+ endpoint: pattern,
183
+ method,
184
+ receipt: verification.receipt,
185
+ responseStatus: c.res.status,
186
+ latencyMs,
187
+ feeBreakdown: verification.feeBreakdown,
188
+ });
189
+ }
190
+ };
191
+ }
192
+ //# sourceMappingURL=middleware-hono.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware-hono.js","sourceRoot":"","sources":["../src/middleware-hono.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import { type SupportedChain, type PaymentRequirement, type PaymentReceipt, type EndpointConfig, type ChainConfig, type PlatformFeeConfig, type FeeBreakdown } from "@apitoll/shared";
2
+ /**
3
+ * Build the PaymentRequired response body for a given endpoint config.
4
+ * Returns an array of PaymentRequirement objects (one per supported chain).
5
+ * When platform fees are configured, the response includes fee metadata.
6
+ */
7
+ export declare function buildPaymentRequirements(endpoint: EndpointConfig, sellerWallet: string, chainConfigs: Record<SupportedChain, ChainConfig>, platformFee?: PlatformFeeConfig): PaymentRequirement[];
8
+ /**
9
+ * Get the fee breakdown for an endpoint price.
10
+ */
11
+ export declare function getEndpointFeeBreakdown(endpoint: EndpointConfig, platformFee?: PlatformFeeConfig): FeeBreakdown;
12
+ /**
13
+ * Build the base64-encoded PAYMENT-REQUIRED header value.
14
+ */
15
+ export declare function encodePaymentRequired(requirements: PaymentRequirement[]): string;
16
+ export interface VerifyPaymentOptions {
17
+ /** The X-PAYMENT header value from the client */
18
+ paymentHeader: string;
19
+ /** The payment requirements that were sent in the 402 response */
20
+ requirements: PaymentRequirement[];
21
+ /** Facilitator URL for verification */
22
+ facilitatorUrl: string;
23
+ }
24
+ export interface VerificationResult {
25
+ valid: boolean;
26
+ receipt?: PaymentReceipt;
27
+ feeBreakdown?: FeeBreakdown;
28
+ error?: string;
29
+ }
30
+ /**
31
+ * Verify a payment by calling the x402 facilitator.
32
+ * The facilitator checks on-chain that the payment is valid and settles it.
33
+ */
34
+ export declare function verifyPayment(options: VerifyPaymentOptions, platformFee?: PlatformFeeConfig): Promise<VerificationResult>;
35
+ /**
36
+ * Find the matching endpoint config for a given request.
37
+ */
38
+ export declare function findEndpointConfig(method: string, path: string, endpoints: Record<string, EndpointConfig>): {
39
+ pattern: string;
40
+ config: EndpointConfig;
41
+ } | null;
42
+ //# sourceMappingURL=payment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payment.d.ts","sourceRoot":"","sources":["../src/payment.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAQlB,MAAM,iBAAiB,CAAC;AAIzB;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,cAAc,EACxB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,CAAC,cAAc,EAAE,WAAW,CAAC,EACjD,WAAW,CAAC,EAAE,iBAAiB,GAC9B,kBAAkB,EAAE,CA+BtB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,cAAc,EACxB,WAAW,CAAC,EAAE,iBAAiB,GAC9B,YAAY,CAEd;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,kBAAkB,EAAE,GAAG,MAAM,CAEhF;AAID,MAAM,WAAW,oBAAoB;IACnC,iDAAiD;IACjD,aAAa,EAAE,MAAM,CAAC;IACtB,kEAAkE;IAClE,YAAY,EAAE,kBAAkB,EAAE,CAAC;IACnC,uCAAuC;IACvC,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,oBAAoB,EAC7B,WAAW,CAAC,EAAE,iBAAiB,GAC9B,OAAO,CAAC,kBAAkB,CAAC,CAuE7B;AAaD;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,GACxC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,GAAG,IAAI,CAOpD"}