@pincerpay/merchant 0.4.1 → 0.5.0

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,4 +1,3 @@
1
- export { pincerpay } from "./middleware/express.js";
2
- export { pincerpayHono } from "./middleware/hono.js";
1
+ export { createPincerPayMiddleware } from "./middleware/nextjs.js";
3
2
  export { PincerPayClient, toBaseUnits, resolveRouteChains, getUsdcAsset } from "./client.js";
4
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,3 @@
1
- export { pincerpay } from "./middleware/express.js";
2
- export { pincerpayHono } from "./middleware/hono.js";
1
+ export { createPincerPayMiddleware } from "./middleware/nextjs.js";
3
2
  export { PincerPayClient, toBaseUnits, resolveRouteChains, getUsdcAsset } from "./client.js";
4
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,31 @@
1
+ import type { PincerPayConfig } from "@pincerpay/core";
2
+ /**
3
+ * Lightweight Next.js / Hono middleware for PincerPay x402 paywalls.
4
+ *
5
+ * Zero @x402/*, viem, @solana/kit imports — settlement is delegated
6
+ * entirely to the PincerPay facilitator via fetch().
7
+ *
8
+ * ```ts
9
+ * // app/api/[...route]/route.ts
10
+ * import { Hono } from "hono";
11
+ * import { handle } from "hono/vercel";
12
+ * import { createPincerPayMiddleware } from "@pincerpay/merchant/nextjs";
13
+ *
14
+ * const app = new Hono().basePath("/api");
15
+ *
16
+ * app.use("*", createPincerPayMiddleware({
17
+ * apiKey: process.env.PINCERPAY_API_KEY!,
18
+ * merchantAddress: "YOUR_WALLET_ADDRESS",
19
+ * routes: {
20
+ * "GET /api/weather": { price: "0.01", chain: "solana", description: "Weather data" },
21
+ * },
22
+ * }));
23
+ *
24
+ * app.get("/weather", (c) => c.json({ temp: 72 }));
25
+ *
26
+ * export const GET = handle(app);
27
+ * export const POST = handle(app);
28
+ * ```
29
+ */
30
+ export declare function createPincerPayMiddleware(config: PincerPayConfig): any;
31
+ //# sourceMappingURL=nextjs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nextjs.d.ts","sourceRoot":"","sources":["../../src/middleware/nextjs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAoBvD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,eAAe,GAmMzD,GAAG,CACV"}
@@ -0,0 +1,182 @@
1
+ import { resolveChain, DEFAULT_FACILITATOR_URL, API_KEY_HEADER, FACILITATOR_ROUTES, } from "@pincerpay/core";
2
+ /**
3
+ * Convert human-readable USDC price (e.g., "0.01") to base units (e.g., "10000").
4
+ */
5
+ function toBaseUnits(amount) {
6
+ const parts = amount.split(".");
7
+ const whole = parts[0] ?? "0";
8
+ const frac = (parts[1] ?? "").padEnd(6, "0").slice(0, 6);
9
+ const result = BigInt(whole) * BigInt(1_000_000) + BigInt(frac);
10
+ return result.toString();
11
+ }
12
+ /**
13
+ * Lightweight Next.js / Hono middleware for PincerPay x402 paywalls.
14
+ *
15
+ * Zero @x402/*, viem, @solana/kit imports — settlement is delegated
16
+ * entirely to the PincerPay facilitator via fetch().
17
+ *
18
+ * ```ts
19
+ * // app/api/[...route]/route.ts
20
+ * import { Hono } from "hono";
21
+ * import { handle } from "hono/vercel";
22
+ * import { createPincerPayMiddleware } from "@pincerpay/merchant/nextjs";
23
+ *
24
+ * const app = new Hono().basePath("/api");
25
+ *
26
+ * app.use("*", createPincerPayMiddleware({
27
+ * apiKey: process.env.PINCERPAY_API_KEY!,
28
+ * merchantAddress: "YOUR_WALLET_ADDRESS",
29
+ * routes: {
30
+ * "GET /api/weather": { price: "0.01", chain: "solana", description: "Weather data" },
31
+ * },
32
+ * }));
33
+ *
34
+ * app.get("/weather", (c) => c.json({ temp: 72 }));
35
+ *
36
+ * export const GET = handle(app);
37
+ * export const POST = handle(app);
38
+ * ```
39
+ */
40
+ export function createPincerPayMiddleware(config) {
41
+ // Normalize: strip trailing /v1 if present — FACILITATOR_ROUTES already include the version prefix
42
+ const rawUrl = config.facilitatorUrl ?? DEFAULT_FACILITATOR_URL;
43
+ const facilitatorUrl = rawUrl.replace(/\/v1\/?$/, "");
44
+ // Warn if using devnet facilitator or default URL without explicit config
45
+ if (!config.facilitatorUrl) {
46
+ console.log("[pincerpay] Using production facilitator:", DEFAULT_FACILITATOR_URL);
47
+ }
48
+ // Fetch facilitator's supported schemes eagerly — provides correct `extra` fields
49
+ // (e.g., Solana feePayer = facilitator's address, EVM EIP-712 domain params)
50
+ const facilitatorExtraPromise = fetch(`${facilitatorUrl}${FACILITATOR_ROUTES.supported}`)
51
+ .then((res) => res.json())
52
+ .then((data) => {
53
+ const map = new Map();
54
+ for (const kind of data.kinds) {
55
+ if (kind.extra)
56
+ map.set(kind.network, kind.extra);
57
+ }
58
+ return map;
59
+ })
60
+ .catch(() => new Map());
61
+ const resolvedRoutes = new Map();
62
+ // Default extra fields per namespace (used as fallback if facilitator fetch fails)
63
+ function defaultExtra(namespace) {
64
+ return namespace === "solana"
65
+ ? { feePayer: config.merchantAddress }
66
+ : { name: "USD Coin", version: "2" };
67
+ }
68
+ for (const [pattern, routeConfig] of Object.entries(config.routes)) {
69
+ const chains = routeConfig.chains ??
70
+ (routeConfig.chain ? [routeConfig.chain] : ["solana"]);
71
+ const accepts = chains.map((chainShorthand) => {
72
+ const chain = resolveChain(chainShorthand);
73
+ if (!chain)
74
+ throw new Error(`Unknown chain: ${chainShorthand}`);
75
+ return {
76
+ scheme: "exact",
77
+ network: chain.caip2Id,
78
+ amount: toBaseUnits(routeConfig.price),
79
+ asset: chain.usdcAddress,
80
+ payTo: config.merchantAddress,
81
+ maxTimeoutSeconds: 300,
82
+ extra: defaultExtra(chain.namespace),
83
+ };
84
+ });
85
+ resolvedRoutes.set(pattern, {
86
+ description: routeConfig.description ?? pattern,
87
+ accepts,
88
+ });
89
+ }
90
+ // Once facilitator responds, merge its extra fields into resolved routes
91
+ let facilitatorExtraResolved = false;
92
+ facilitatorExtraPromise.then((extraMap) => {
93
+ if (extraMap.size === 0)
94
+ return;
95
+ for (const route of resolvedRoutes.values()) {
96
+ for (const accept of route.accepts) {
97
+ const extra = extraMap.get(accept.network);
98
+ if (extra)
99
+ accept.extra = { ...accept.extra, ...extra };
100
+ }
101
+ }
102
+ facilitatorExtraResolved = true;
103
+ });
104
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
105
+ return (async (c, next) => {
106
+ const method = c.req.method;
107
+ const path = c.req.path;
108
+ const routeKey = `${method} ${path}`;
109
+ const route = resolvedRoutes.get(routeKey);
110
+ // Not a paywalled route — pass through
111
+ if (!route)
112
+ return next();
113
+ // Ensure facilitator extra fields are resolved before returning 402
114
+ if (!facilitatorExtraResolved)
115
+ await facilitatorExtraPromise;
116
+ // Check for x402 v2 payment signature header
117
+ const paymentHeader = c.req.header("payment-signature") ?? c.req.header("x-payment");
118
+ if (!paymentHeader) {
119
+ // Return 402 Payment Required
120
+ const paymentRequired = {
121
+ x402Version: 2,
122
+ error: "Payment required",
123
+ resource: {
124
+ resource: path,
125
+ description: route.description,
126
+ mimeType: "application/json",
127
+ },
128
+ accepts: route.accepts,
129
+ extensions: {},
130
+ };
131
+ const encoded = Buffer.from(JSON.stringify(paymentRequired)).toString("base64");
132
+ c.header("payment-required", encoded);
133
+ return c.json(paymentRequired, 402);
134
+ }
135
+ // Payment header present — settle via facilitator
136
+ try {
137
+ // x402 may send as raw JSON or base64-encoded JSON
138
+ let decoded;
139
+ try {
140
+ decoded = JSON.parse(paymentHeader);
141
+ }
142
+ catch {
143
+ decoded = JSON.parse(Buffer.from(paymentHeader, "base64").toString("utf-8"));
144
+ }
145
+ const paymentRequirements = decoded.accepted ?? decoded.paymentRequirements;
146
+ const settleRes = await fetch(`${facilitatorUrl}${FACILITATOR_ROUTES.settle}`, {
147
+ method: "POST",
148
+ headers: {
149
+ "content-type": "application/json",
150
+ [API_KEY_HEADER]: config.apiKey,
151
+ },
152
+ body: JSON.stringify({
153
+ paymentPayload: decoded,
154
+ paymentRequirements,
155
+ }),
156
+ });
157
+ const settle = (await settleRes.json());
158
+ if (!settle.success) {
159
+ return c.json({
160
+ error: "Payment settlement failed",
161
+ reason: settle.errorReason,
162
+ message: settle.errorMessage,
163
+ }, 402);
164
+ }
165
+ // Payment succeeded — attach settlement response header and serve resource
166
+ const settleResponse = {
167
+ x402Version: 2,
168
+ success: true,
169
+ transaction: settle.transaction,
170
+ network: settle.network,
171
+ };
172
+ c.header("payment-response", Buffer.from(JSON.stringify(settleResponse)).toString("base64"));
173
+ return next();
174
+ }
175
+ catch (err) {
176
+ console.error("[pincerpay] settlement error:", err);
177
+ return c.json({ error: "Payment processing failed", detail: String(err) }, 500);
178
+ }
179
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
180
+ });
181
+ }
182
+ //# sourceMappingURL=nextjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nextjs.js","sourceRoot":"","sources":["../../src/middleware/nextjs.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@pincerpay/merchant",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
- "description": "Merchant SDK for PincerPay. Express and Hono middleware for accepting USDC payments from AI agents.",
5
+ "description": "Merchant SDK for PincerPay. Lightweight Next.js middleware for accepting USDC payments from AI agents via x402.",
6
6
  "license": "MIT",
7
7
  "publishConfig": {
8
8
  "access": "public"
@@ -25,7 +25,7 @@
25
25
  "solana",
26
26
  "merchant-sdk",
27
27
  "middleware",
28
- "express",
28
+ "nextjs",
29
29
  "hono",
30
30
  "typescript",
31
31
  "web3",
@@ -48,47 +48,20 @@
48
48
  "types": "./dist/index.d.ts",
49
49
  "import": "./dist/index.js"
50
50
  },
51
- "./express": {
52
- "types": "./dist/middleware/express.d.ts",
53
- "import": "./dist/middleware/express.js"
54
- },
55
- "./hono": {
56
- "types": "./dist/middleware/hono.d.ts",
57
- "import": "./dist/middleware/hono.js"
51
+ "./nextjs": {
52
+ "types": "./dist/middleware/nextjs.d.ts",
53
+ "import": "./dist/middleware/nextjs.js"
58
54
  }
59
55
  },
60
56
  "dependencies": {
61
- "@x402/core": "^2.6.0",
62
- "@x402/evm": "^2.6.0",
63
- "@x402/svm": "^2.6.0",
64
57
  "zod": "^3.24",
65
- "@pincerpay/core": "0.2.0"
58
+ "@pincerpay/core": "0.5.0"
66
59
  },
67
60
  "peerDependencies": {
68
- "@x402/express": "^2.3",
69
- "@x402/hono": "^2.3",
70
- "express": "^4 || ^5",
71
61
  "hono": "^4"
72
62
  },
73
- "peerDependenciesMeta": {
74
- "@x402/express": {
75
- "optional": true
76
- },
77
- "@x402/hono": {
78
- "optional": true
79
- },
80
- "express": {
81
- "optional": true
82
- },
83
- "hono": {
84
- "optional": true
85
- }
86
- },
87
63
  "devDependencies": {
88
- "@types/express": "^5",
89
- "@x402/express": "^2.6.0",
90
- "@x402/hono": "^2.6.0",
91
- "express": "^5",
64
+ "@types/node": "^22",
92
65
  "hono": "^4.12.0",
93
66
  "typescript": "^5.7"
94
67
  },
@@ -1,18 +0,0 @@
1
- import type { PincerPayConfig } from "@pincerpay/core";
2
- import { type PaywallConfig } from "@x402/express";
3
- /**
4
- * Express middleware factory — the dead-simple API from the plan:
5
- *
6
- * ```ts
7
- * app.use(pincerpay({
8
- * apiKey: process.env.PINCERPAY_API_KEY!,
9
- * merchantAddress: "0xYourAddress",
10
- * routes: {
11
- * "GET /api/weather": { price: "0.01", chain: "base", description: "Weather data" },
12
- * },
13
- * }));
14
- * ```
15
- */
16
- export declare function pincerpay(config: PincerPayConfig, paywallConfig?: PaywallConfig): (req: import("express").Request, res: import("express").Response, next: import("express").NextFunction) => Promise<void>;
17
- export { PincerPayClient } from "../client.js";
18
- //# sourceMappingURL=express.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../src/middleware/express.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,eAAe,CAAC;AAMvB;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,eAAe,EAAE,aAAa,CAAC,EAAE,aAAa,4HA+D/E;AAED,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
@@ -1,62 +0,0 @@
1
- import { resolveChain, DEFAULT_FACILITATOR_URL } from "@pincerpay/core";
2
- import { paymentMiddlewareFromConfig, } from "@x402/express";
3
- import { HTTPFacilitatorClient } from "@x402/core/server";
4
- import { ExactEvmScheme } from "@x402/evm/exact/server";
5
- import { ExactSvmScheme } from "@x402/svm/exact/server";
6
- /**
7
- * Express middleware factory — the dead-simple API from the plan:
8
- *
9
- * ```ts
10
- * app.use(pincerpay({
11
- * apiKey: process.env.PINCERPAY_API_KEY!,
12
- * merchantAddress: "0xYourAddress",
13
- * routes: {
14
- * "GET /api/weather": { price: "0.01", chain: "base", description: "Weather data" },
15
- * },
16
- * }));
17
- * ```
18
- */
19
- export function pincerpay(config, paywallConfig) {
20
- const facilitatorUrl = config.facilitatorUrl ?? DEFAULT_FACILITATOR_URL;
21
- // Build x402-compatible routes config
22
- // Pass price as Money (string) so the EVM server scheme handles conversion
23
- // and automatically includes EIP-712 domain parameters (name, version)
24
- const x402Routes = {};
25
- for (const [pattern, routeConfig] of Object.entries(config.routes)) {
26
- const chains = routeConfig.chains ?? (routeConfig.chain ? [routeConfig.chain] : ["solana"]);
27
- const accepts = chains.map((chainShorthand) => {
28
- const chain = resolveChain(chainShorthand);
29
- if (!chain)
30
- throw new Error(`Unknown chain: ${chainShorthand}`);
31
- return {
32
- scheme: "exact",
33
- network: chain.caip2Id,
34
- payTo: config.merchantAddress,
35
- price: routeConfig.price,
36
- maxTimeoutSeconds: 300,
37
- };
38
- });
39
- x402Routes[pattern] = {
40
- accepts,
41
- description: routeConfig.description ?? pattern,
42
- };
43
- }
44
- // Create facilitator client pointing to PincerPay
45
- const facilitatorClient = new HTTPFacilitatorClient({
46
- url: facilitatorUrl,
47
- createAuthHeaders: async () => ({
48
- verify: { "x-pincerpay-api-key": config.apiKey },
49
- settle: { "x-pincerpay-api-key": config.apiKey },
50
- supported: { "x-pincerpay-api-key": config.apiKey },
51
- }),
52
- });
53
- // Register server schemes so the resource server can build payment requirements
54
- const schemes = [
55
- { network: "eip155:*", server: new ExactEvmScheme() },
56
- { network: "solana:*", server: new ExactSvmScheme() },
57
- ];
58
- return paymentMiddlewareFromConfig(x402Routes, facilitatorClient, schemes, paywallConfig, undefined, // paywall provider
59
- config.syncFacilitatorOnStart ?? true);
60
- }
61
- export { PincerPayClient } from "../client.js";
62
- //# sourceMappingURL=express.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"express.js","sourceRoot":"","sources":["../../src/middleware/express.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,EACL,2BAA2B,GAE5B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,SAAS,CAAC,MAAuB,EAAE,aAA6B;IAC9E,MAAM,cAAc,GAAG,MAAM,CAAC,cAAc,IAAI,uBAAuB,CAAC;IAExE,sCAAsC;IACtC,2EAA2E;IAC3E,uEAAuE;IACvE,MAAM,UAAU,GASX,EAAE,CAAC;IAER,KAAK,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACnE,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAE5F,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,cAAc,EAAE,EAAE;YAC5C,MAAM,KAAK,GAAG,YAAY,CAAC,cAAc,CAAC,CAAC;YAC3C,IAAI,CAAC,KAAK;gBAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,cAAc,EAAE,CAAC,CAAC;YAEhE,OAAO;gBACL,MAAM,EAAE,OAAgB;gBACxB,OAAO,EAAE,KAAK,CAAC,OAAkB;gBACjC,KAAK,EAAE,MAAM,CAAC,eAAe;gBAC7B,KAAK,EAAE,WAAW,CAAC,KAAK;gBACxB,iBAAiB,EAAE,GAAG;aACvB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,UAAU,CAAC,OAAO,CAAC,GAAG;YACpB,OAAO;YACP,WAAW,EAAE,WAAW,CAAC,WAAW,IAAI,OAAO;SAChD,CAAC;IACJ,CAAC;IAED,kDAAkD;IAClD,MAAM,iBAAiB,GAAG,IAAI,qBAAqB,CAAC;QAClD,GAAG,EAAE,cAAc;QACnB,iBAAiB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YAC9B,MAAM,EAAE,EAAE,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE;YAChD,MAAM,EAAE,EAAE,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE;YAChD,SAAS,EAAE,EAAE,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE;SACpD,CAAC;KACH,CAAC,CAAC;IAEH,gFAAgF;IAChF,MAAM,OAAO,GAAG;QACd,EAAE,OAAO,EAAE,UAAqB,EAAE,MAAM,EAAE,IAAI,cAAc,EAAE,EAAE;QAChE,EAAE,OAAO,EAAE,UAAqB,EAAE,MAAM,EAAE,IAAI,cAAc,EAAE,EAAE;KACjE,CAAC;IAEF,OAAO,2BAA2B,CAChC,UAAU,EACV,iBAAiB,EACjB,OAAO,EACP,aAAa,EACb,SAAS,EAAE,mBAAmB;IAC9B,MAAM,CAAC,sBAAsB,IAAI,IAAI,CACtC,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
@@ -1,18 +0,0 @@
1
- import type { PincerPayConfig } from "@pincerpay/core";
2
- import { type PaywallConfig } from "@x402/hono";
3
- /**
4
- * Hono middleware factory for PincerPay merchants.
5
- *
6
- * ```ts
7
- * app.use("*", pincerpayHono({
8
- * apiKey: process.env.PINCERPAY_API_KEY!,
9
- * merchantAddress: "0xYourAddress",
10
- * routes: {
11
- * "GET /api/weather": { price: "0.01", chain: "base", description: "Weather data" },
12
- * },
13
- * }));
14
- * ```
15
- */
16
- export declare function pincerpayHono(config: PincerPayConfig, paywallConfig?: PaywallConfig): import("hono").MiddlewareHandler;
17
- export { PincerPayClient } from "../client.js";
18
- //# sourceMappingURL=hono.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hono.d.ts","sourceRoot":"","sources":["../../src/middleware/hono.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAMpB;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,eAAe,EAAE,aAAa,CAAC,EAAE,aAAa,oCA+DnF;AAED,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
@@ -1,62 +0,0 @@
1
- import { resolveChain, DEFAULT_FACILITATOR_URL } from "@pincerpay/core";
2
- import { paymentMiddlewareFromConfig, } from "@x402/hono";
3
- import { HTTPFacilitatorClient } from "@x402/core/server";
4
- import { ExactEvmScheme } from "@x402/evm/exact/server";
5
- import { ExactSvmScheme } from "@x402/svm/exact/server";
6
- /**
7
- * Hono middleware factory for PincerPay merchants.
8
- *
9
- * ```ts
10
- * app.use("*", pincerpayHono({
11
- * apiKey: process.env.PINCERPAY_API_KEY!,
12
- * merchantAddress: "0xYourAddress",
13
- * routes: {
14
- * "GET /api/weather": { price: "0.01", chain: "base", description: "Weather data" },
15
- * },
16
- * }));
17
- * ```
18
- */
19
- export function pincerpayHono(config, paywallConfig) {
20
- const facilitatorUrl = config.facilitatorUrl ?? DEFAULT_FACILITATOR_URL;
21
- // Build x402-compatible routes config
22
- // Pass price as Money (string) so the EVM server scheme handles conversion
23
- // and automatically includes EIP-712 domain parameters (name, version)
24
- const x402Routes = {};
25
- for (const [pattern, routeConfig] of Object.entries(config.routes)) {
26
- const chains = routeConfig.chains ?? (routeConfig.chain ? [routeConfig.chain] : ["solana"]);
27
- const accepts = chains.map((chainShorthand) => {
28
- const chain = resolveChain(chainShorthand);
29
- if (!chain)
30
- throw new Error(`Unknown chain: ${chainShorthand}`);
31
- return {
32
- scheme: "exact",
33
- network: chain.caip2Id,
34
- payTo: config.merchantAddress,
35
- price: routeConfig.price,
36
- maxTimeoutSeconds: 300,
37
- };
38
- });
39
- x402Routes[pattern] = {
40
- accepts,
41
- description: routeConfig.description ?? pattern,
42
- };
43
- }
44
- // Create facilitator client pointing to PincerPay
45
- const facilitatorClient = new HTTPFacilitatorClient({
46
- url: facilitatorUrl,
47
- createAuthHeaders: async () => ({
48
- verify: { "x-pincerpay-api-key": config.apiKey },
49
- settle: { "x-pincerpay-api-key": config.apiKey },
50
- supported: { "x-pincerpay-api-key": config.apiKey },
51
- }),
52
- });
53
- // Register server schemes so the resource server can build payment requirements
54
- const schemes = [
55
- { network: "eip155:*", server: new ExactEvmScheme() },
56
- { network: "solana:*", server: new ExactSvmScheme() },
57
- ];
58
- return paymentMiddlewareFromConfig(x402Routes, facilitatorClient, schemes, paywallConfig, undefined, // paywall provider
59
- config.syncFacilitatorOnStart ?? true);
60
- }
61
- export { PincerPayClient } from "../client.js";
62
- //# sourceMappingURL=hono.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hono.js","sourceRoot":"","sources":["../../src/middleware/hono.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,EACL,2BAA2B,GAE5B,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,aAAa,CAAC,MAAuB,EAAE,aAA6B;IAClF,MAAM,cAAc,GAAG,MAAM,CAAC,cAAc,IAAI,uBAAuB,CAAC;IAExE,sCAAsC;IACtC,2EAA2E;IAC3E,uEAAuE;IACvE,MAAM,UAAU,GASX,EAAE,CAAC;IAER,KAAK,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACnE,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAE5F,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,cAAc,EAAE,EAAE;YAC5C,MAAM,KAAK,GAAG,YAAY,CAAC,cAAc,CAAC,CAAC;YAC3C,IAAI,CAAC,KAAK;gBAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,cAAc,EAAE,CAAC,CAAC;YAEhE,OAAO;gBACL,MAAM,EAAE,OAAgB;gBACxB,OAAO,EAAE,KAAK,CAAC,OAAkB;gBACjC,KAAK,EAAE,MAAM,CAAC,eAAe;gBAC7B,KAAK,EAAE,WAAW,CAAC,KAAK;gBACxB,iBAAiB,EAAE,GAAG;aACvB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,UAAU,CAAC,OAAO,CAAC,GAAG;YACpB,OAAO;YACP,WAAW,EAAE,WAAW,CAAC,WAAW,IAAI,OAAO;SAChD,CAAC;IACJ,CAAC;IAED,kDAAkD;IAClD,MAAM,iBAAiB,GAAG,IAAI,qBAAqB,CAAC;QAClD,GAAG,EAAE,cAAc;QACnB,iBAAiB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YAC9B,MAAM,EAAE,EAAE,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE;YAChD,MAAM,EAAE,EAAE,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE;YAChD,SAAS,EAAE,EAAE,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE;SACpD,CAAC;KACH,CAAC,CAAC;IAEH,gFAAgF;IAChF,MAAM,OAAO,GAAG;QACd,EAAE,OAAO,EAAE,UAAqB,EAAE,MAAM,EAAE,IAAI,cAAc,EAAE,EAAE;QAChE,EAAE,OAAO,EAAE,UAAqB,EAAE,MAAM,EAAE,IAAI,cAAc,EAAE,EAAE;KACjE,CAAC;IAEF,OAAO,2BAA2B,CAChC,UAAU,EACV,iBAAiB,EACjB,OAAO,EACP,aAAa,EACb,SAAS,EAAE,mBAAmB;IAC9B,MAAM,CAAC,sBAAsB,IAAI,IAAI,CACtC,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}