@parallel-protocol/mpp 0.1.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/README.md +566 -0
- package/dist/chunk-DXHOWEAQ.js +17 -0
- package/dist/chunk-HTUIO2MB.js +340 -0
- package/dist/chunk-ILKUNJBE.cjs +355 -0
- package/dist/chunk-RNM3RDKR.cjs +20 -0
- package/dist/express.cjs +131 -0
- package/dist/express.d.cts +20 -0
- package/dist/express.d.ts +20 -0
- package/dist/express.js +128 -0
- package/dist/fastify.cjs +75 -0
- package/dist/fastify.d.cts +17 -0
- package/dist/fastify.d.ts +17 -0
- package/dist/fastify.js +72 -0
- package/dist/hono.cjs +77 -0
- package/dist/hono.d.cts +19 -0
- package/dist/hono.d.ts +19 -0
- package/dist/hono.js +74 -0
- package/dist/index.cjs +63 -0
- package/dist/index.d.cts +62 -0
- package/dist/index.d.ts +62 -0
- package/dist/index.js +2 -0
- package/dist/next.cjs +79 -0
- package/dist/next.d.cts +18 -0
- package/dist/next.d.ts +18 -0
- package/dist/next.js +76 -0
- package/dist/types-CCE-FI8i.d.cts +81 -0
- package/dist/types-CCE-FI8i.d.ts +81 -0
- package/package.json +125 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkILKUNJBE_cjs = require('./chunk-ILKUNJBE.cjs');
|
|
4
|
+
var mppTypes = require('@parallel-protocol/mpp-types');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
Object.defineProperty(exports, "MPP_ERROR_CODES", {
|
|
9
|
+
enumerable: true,
|
|
10
|
+
get: function () { return chunkILKUNJBE_cjs.MPP_ERROR_CODES; }
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "MppConfigError", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () { return chunkILKUNJBE_cjs.MppConfigError; }
|
|
15
|
+
});
|
|
16
|
+
Object.defineProperty(exports, "MppFacilitatorClient", {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: function () { return chunkILKUNJBE_cjs.MppFacilitatorClient; }
|
|
19
|
+
});
|
|
20
|
+
Object.defineProperty(exports, "MppRuntimeError", {
|
|
21
|
+
enumerable: true,
|
|
22
|
+
get: function () { return chunkILKUNJBE_cjs.MppRuntimeError; }
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(exports, "buildChallenge", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () { return chunkILKUNJBE_cjs.buildChallenge; }
|
|
27
|
+
});
|
|
28
|
+
Object.defineProperty(exports, "chainIdFromSlug", {
|
|
29
|
+
enumerable: true,
|
|
30
|
+
get: function () { return chunkILKUNJBE_cjs.chainIdFromSlug; }
|
|
31
|
+
});
|
|
32
|
+
Object.defineProperty(exports, "createMppPaymentGate", {
|
|
33
|
+
enumerable: true,
|
|
34
|
+
get: function () { return chunkILKUNJBE_cjs.createMppPaymentGate; }
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(exports, "createMppPaymentMiddleware", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
get: function () { return chunkILKUNJBE_cjs.createMppPaymentMiddleware; }
|
|
39
|
+
});
|
|
40
|
+
Object.defineProperty(exports, "matchRoute", {
|
|
41
|
+
enumerable: true,
|
|
42
|
+
get: function () { return chunkILKUNJBE_cjs.matchRoute; }
|
|
43
|
+
});
|
|
44
|
+
Object.defineProperty(exports, "parseAuthorizationHeader", {
|
|
45
|
+
enumerable: true,
|
|
46
|
+
get: function () { return chunkILKUNJBE_cjs.parseAuthorizationHeader; }
|
|
47
|
+
});
|
|
48
|
+
Object.defineProperty(exports, "parsePrice", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function () { return chunkILKUNJBE_cjs.parsePrice; }
|
|
51
|
+
});
|
|
52
|
+
Object.defineProperty(exports, "serializeChallenge", {
|
|
53
|
+
enumerable: true,
|
|
54
|
+
get: function () { return chunkILKUNJBE_cjs.serializeChallenge; }
|
|
55
|
+
});
|
|
56
|
+
Object.defineProperty(exports, "decodeBase64Url", {
|
|
57
|
+
enumerable: true,
|
|
58
|
+
get: function () { return mppTypes.decodeBase64Url; }
|
|
59
|
+
});
|
|
60
|
+
Object.defineProperty(exports, "encodeBase64Url", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
get: function () { return mppTypes.encodeBase64Url; }
|
|
63
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { MppChargeCredential } from '@parallel-protocol/mpp-types';
|
|
2
|
+
export { MppChargeCredential, MppReceipt, decodeBase64Url, encodeBase64Url } from '@parallel-protocol/mpp-types';
|
|
3
|
+
import { a as MppRouteConfig, b as MppFacilitatorConfig, c as MppSettleResult, M as MppMiddlewareConfig, H as HTTPAdapter, P as PaymentGateResult, d as MiddlewareResult, e as PassResult } from './types-CCE-FI8i.cjs';
|
|
4
|
+
export { f as MppSettleFailure, g as MppSettleSuccess, R as RunHandlerResult } from './types-CCE-FI8i.cjs';
|
|
5
|
+
import 'viem';
|
|
6
|
+
|
|
7
|
+
/** The challenge echoed back inside a credential (derived — mpp-types has no standalone export). */
|
|
8
|
+
type MppChallenge = MppChargeCredential["challenge"];
|
|
9
|
+
/**
|
|
10
|
+
* Build the MPP charge challenge a 402 advertises. `id`/`expires` are derived now,
|
|
11
|
+
* so this is a runtime call (not pure). Pass a precomputed `request`
|
|
12
|
+
* (from {@link buildChargeRequestB64}) to skip re-encoding the static fields.
|
|
13
|
+
*/
|
|
14
|
+
declare function buildChallenge(route: MppRouteConfig, request?: string): MppChallenge;
|
|
15
|
+
/**
|
|
16
|
+
* Serialize a challenge into a `WWW-Authenticate: Payment …` header value
|
|
17
|
+
* (RFC 9110 auth-params). Undefined fields are omitted.
|
|
18
|
+
*/
|
|
19
|
+
declare function serializeChallenge(challenge: MppChallenge): string;
|
|
20
|
+
/**
|
|
21
|
+
* Parse an `Authorization: Payment <token>` header into a validated MPP charge
|
|
22
|
+
* credential. The token is base64url(JSON(credential)). Returns `null` when the
|
|
23
|
+
* header is absent, not the `Payment` scheme, or malformed.
|
|
24
|
+
*/
|
|
25
|
+
declare function parseAuthorizationHeader(header: string | undefined): MppChargeCredential | null;
|
|
26
|
+
|
|
27
|
+
/** Talks to the facilitator's MPP endpoints (`POST /mpp/verify`, `POST /mpp/settle`). */
|
|
28
|
+
declare class MppFacilitatorClient {
|
|
29
|
+
private readonly url;
|
|
30
|
+
private readonly headers;
|
|
31
|
+
constructor(config: MppFacilitatorConfig);
|
|
32
|
+
/** Verify a credential (phase 1, no on-chain tx). Throws {@link MppRuntimeError} on failure. */
|
|
33
|
+
verify(credential: MppChargeCredential): Promise<void>;
|
|
34
|
+
/** Settle a credential (phase 2, on-chain). Returns the receipt or a failure. */
|
|
35
|
+
settle(credential: MppChargeCredential): Promise<MppSettleResult>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
declare const MPP_ERROR_CODES: {
|
|
39
|
+
readonly FACILITATOR_UNAVAILABLE: "FACILITATOR_UNAVAILABLE";
|
|
40
|
+
readonly FACILITATOR_INVALID_RESPONSE: "FACILITATOR_INVALID_RESPONSE";
|
|
41
|
+
readonly INVALID_CREDENTIAL: "INVALID_CREDENTIAL";
|
|
42
|
+
readonly METHOD_MISMATCH: "METHOD_MISMATCH";
|
|
43
|
+
};
|
|
44
|
+
type MppErrorCode = (typeof MPP_ERROR_CODES)[keyof typeof MPP_ERROR_CODES];
|
|
45
|
+
declare class MppConfigError extends Error {
|
|
46
|
+
constructor(message: string, cause?: unknown);
|
|
47
|
+
}
|
|
48
|
+
declare class MppRuntimeError extends Error {
|
|
49
|
+
readonly code: string;
|
|
50
|
+
constructor(code: string);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
declare function createMppPaymentGate(config: MppMiddlewareConfig): (adapter: Pick<HTTPAdapter, "getHeader" | "getPath" | "getUrl" | "getMethod">) => Promise<PaymentGateResult>;
|
|
54
|
+
declare function createMppPaymentMiddleware(config: MppMiddlewareConfig): (adapter: HTTPAdapter) => Promise<MiddlewareResult | PassResult>;
|
|
55
|
+
|
|
56
|
+
/** Parse a human price ("0.01") or pass a bigint through. Default 6 decimals (stablecoins). */
|
|
57
|
+
declare function parsePrice(price: string | bigint, decimals?: number): bigint;
|
|
58
|
+
/** Resolve an EVM chain id from a chain slug via the static catalogue. */
|
|
59
|
+
declare function chainIdFromSlug(network: string): number | undefined;
|
|
60
|
+
declare function matchRoute<T>(path: string, routes: Record<string, T>): T | undefined;
|
|
61
|
+
|
|
62
|
+
export { HTTPAdapter, MPP_ERROR_CODES, MiddlewareResult, type MppChallenge, MppConfigError, type MppErrorCode, MppFacilitatorClient, MppFacilitatorConfig, MppMiddlewareConfig, MppRouteConfig, MppRuntimeError, MppSettleResult, PassResult, PaymentGateResult, buildChallenge, chainIdFromSlug, createMppPaymentGate, createMppPaymentMiddleware, matchRoute, parseAuthorizationHeader, parsePrice, serializeChallenge };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { MppChargeCredential } from '@parallel-protocol/mpp-types';
|
|
2
|
+
export { MppChargeCredential, MppReceipt, decodeBase64Url, encodeBase64Url } from '@parallel-protocol/mpp-types';
|
|
3
|
+
import { a as MppRouteConfig, b as MppFacilitatorConfig, c as MppSettleResult, M as MppMiddlewareConfig, H as HTTPAdapter, P as PaymentGateResult, d as MiddlewareResult, e as PassResult } from './types-CCE-FI8i.js';
|
|
4
|
+
export { f as MppSettleFailure, g as MppSettleSuccess, R as RunHandlerResult } from './types-CCE-FI8i.js';
|
|
5
|
+
import 'viem';
|
|
6
|
+
|
|
7
|
+
/** The challenge echoed back inside a credential (derived — mpp-types has no standalone export). */
|
|
8
|
+
type MppChallenge = MppChargeCredential["challenge"];
|
|
9
|
+
/**
|
|
10
|
+
* Build the MPP charge challenge a 402 advertises. `id`/`expires` are derived now,
|
|
11
|
+
* so this is a runtime call (not pure). Pass a precomputed `request`
|
|
12
|
+
* (from {@link buildChargeRequestB64}) to skip re-encoding the static fields.
|
|
13
|
+
*/
|
|
14
|
+
declare function buildChallenge(route: MppRouteConfig, request?: string): MppChallenge;
|
|
15
|
+
/**
|
|
16
|
+
* Serialize a challenge into a `WWW-Authenticate: Payment …` header value
|
|
17
|
+
* (RFC 9110 auth-params). Undefined fields are omitted.
|
|
18
|
+
*/
|
|
19
|
+
declare function serializeChallenge(challenge: MppChallenge): string;
|
|
20
|
+
/**
|
|
21
|
+
* Parse an `Authorization: Payment <token>` header into a validated MPP charge
|
|
22
|
+
* credential. The token is base64url(JSON(credential)). Returns `null` when the
|
|
23
|
+
* header is absent, not the `Payment` scheme, or malformed.
|
|
24
|
+
*/
|
|
25
|
+
declare function parseAuthorizationHeader(header: string | undefined): MppChargeCredential | null;
|
|
26
|
+
|
|
27
|
+
/** Talks to the facilitator's MPP endpoints (`POST /mpp/verify`, `POST /mpp/settle`). */
|
|
28
|
+
declare class MppFacilitatorClient {
|
|
29
|
+
private readonly url;
|
|
30
|
+
private readonly headers;
|
|
31
|
+
constructor(config: MppFacilitatorConfig);
|
|
32
|
+
/** Verify a credential (phase 1, no on-chain tx). Throws {@link MppRuntimeError} on failure. */
|
|
33
|
+
verify(credential: MppChargeCredential): Promise<void>;
|
|
34
|
+
/** Settle a credential (phase 2, on-chain). Returns the receipt or a failure. */
|
|
35
|
+
settle(credential: MppChargeCredential): Promise<MppSettleResult>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
declare const MPP_ERROR_CODES: {
|
|
39
|
+
readonly FACILITATOR_UNAVAILABLE: "FACILITATOR_UNAVAILABLE";
|
|
40
|
+
readonly FACILITATOR_INVALID_RESPONSE: "FACILITATOR_INVALID_RESPONSE";
|
|
41
|
+
readonly INVALID_CREDENTIAL: "INVALID_CREDENTIAL";
|
|
42
|
+
readonly METHOD_MISMATCH: "METHOD_MISMATCH";
|
|
43
|
+
};
|
|
44
|
+
type MppErrorCode = (typeof MPP_ERROR_CODES)[keyof typeof MPP_ERROR_CODES];
|
|
45
|
+
declare class MppConfigError extends Error {
|
|
46
|
+
constructor(message: string, cause?: unknown);
|
|
47
|
+
}
|
|
48
|
+
declare class MppRuntimeError extends Error {
|
|
49
|
+
readonly code: string;
|
|
50
|
+
constructor(code: string);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
declare function createMppPaymentGate(config: MppMiddlewareConfig): (adapter: Pick<HTTPAdapter, "getHeader" | "getPath" | "getUrl" | "getMethod">) => Promise<PaymentGateResult>;
|
|
54
|
+
declare function createMppPaymentMiddleware(config: MppMiddlewareConfig): (adapter: HTTPAdapter) => Promise<MiddlewareResult | PassResult>;
|
|
55
|
+
|
|
56
|
+
/** Parse a human price ("0.01") or pass a bigint through. Default 6 decimals (stablecoins). */
|
|
57
|
+
declare function parsePrice(price: string | bigint, decimals?: number): bigint;
|
|
58
|
+
/** Resolve an EVM chain id from a chain slug via the static catalogue. */
|
|
59
|
+
declare function chainIdFromSlug(network: string): number | undefined;
|
|
60
|
+
declare function matchRoute<T>(path: string, routes: Record<string, T>): T | undefined;
|
|
61
|
+
|
|
62
|
+
export { HTTPAdapter, MPP_ERROR_CODES, MiddlewareResult, type MppChallenge, MppConfigError, type MppErrorCode, MppFacilitatorClient, MppFacilitatorConfig, MppMiddlewareConfig, MppRouteConfig, MppRuntimeError, MppSettleResult, PassResult, PaymentGateResult, buildChallenge, chainIdFromSlug, createMppPaymentGate, createMppPaymentMiddleware, matchRoute, parseAuthorizationHeader, parsePrice, serializeChallenge };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { MPP_ERROR_CODES, MppConfigError, MppFacilitatorClient, MppRuntimeError, buildChallenge, chainIdFromSlug, createMppPaymentGate, createMppPaymentMiddleware, matchRoute, parseAuthorizationHeader, parsePrice, serializeChallenge } from './chunk-HTUIO2MB.js';
|
|
2
|
+
export { decodeBase64Url, encodeBase64Url } from '@parallel-protocol/mpp-types';
|
package/dist/next.cjs
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkRNM3RDKR_cjs = require('./chunk-RNM3RDKR.cjs');
|
|
4
|
+
var chunkILKUNJBE_cjs = require('./chunk-ILKUNJBE.cjs');
|
|
5
|
+
var mppTypes = require('@parallel-protocol/mpp-types');
|
|
6
|
+
var server = require('next/server');
|
|
7
|
+
|
|
8
|
+
// src/next/adapter.ts
|
|
9
|
+
var NextAdapter = class {
|
|
10
|
+
constructor(req) {
|
|
11
|
+
this.req = req;
|
|
12
|
+
}
|
|
13
|
+
req;
|
|
14
|
+
getHeader(name) {
|
|
15
|
+
return this.req.headers.get(name) ?? void 0;
|
|
16
|
+
}
|
|
17
|
+
getMethod() {
|
|
18
|
+
return this.req.method;
|
|
19
|
+
}
|
|
20
|
+
getPath() {
|
|
21
|
+
return this.req.nextUrl.pathname;
|
|
22
|
+
}
|
|
23
|
+
getUrl() {
|
|
24
|
+
return this.req.url;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// src/next/index.ts
|
|
29
|
+
function withPayment(config, handler) {
|
|
30
|
+
const gate = chunkILKUNJBE_cjs.createMppPaymentGate(config);
|
|
31
|
+
return async (req) => {
|
|
32
|
+
const gateResult = await gate(new NextAdapter(req));
|
|
33
|
+
if (gateResult.type === "pass") {
|
|
34
|
+
return handler(req);
|
|
35
|
+
}
|
|
36
|
+
if (gateResult.type === "error") {
|
|
37
|
+
return new server.NextResponse(JSON.stringify(gateResult.result.body), {
|
|
38
|
+
status: gateResult.result.status,
|
|
39
|
+
headers: {
|
|
40
|
+
...gateResult.result.headers,
|
|
41
|
+
"Content-Type": "application/json"
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
let response;
|
|
46
|
+
try {
|
|
47
|
+
const outcome = await chunkRNM3RDKR_cjs.raceTimeout(handler(req));
|
|
48
|
+
if (outcome === chunkRNM3RDKR_cjs.HANDLER_TIMEOUT) {
|
|
49
|
+
return new server.NextResponse(null, { status: 504 });
|
|
50
|
+
}
|
|
51
|
+
response = outcome;
|
|
52
|
+
} catch {
|
|
53
|
+
return new server.NextResponse(null, { status: 504 });
|
|
54
|
+
}
|
|
55
|
+
if (chunkILKUNJBE_cjs.isSuccessStatus(response.status)) {
|
|
56
|
+
try {
|
|
57
|
+
const settleResponse = await gateResult.settle();
|
|
58
|
+
if (settleResponse.success) {
|
|
59
|
+
const headers = new Headers(response.headers);
|
|
60
|
+
headers.set(
|
|
61
|
+
"Payment-Receipt",
|
|
62
|
+
mppTypes.encodeBase64Url(settleResponse.receipt)
|
|
63
|
+
);
|
|
64
|
+
headers.set("access-control-expose-headers", "Payment-Receipt");
|
|
65
|
+
return new server.NextResponse(response.body, {
|
|
66
|
+
status: response.status,
|
|
67
|
+
headers
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
} catch {
|
|
71
|
+
}
|
|
72
|
+
return server.NextResponse.json(chunkILKUNJBE_cjs.SETTLE_FAILURE_BODY, { status: 402 });
|
|
73
|
+
}
|
|
74
|
+
return response;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
exports.NextAdapter = NextAdapter;
|
|
79
|
+
exports.withPayment = withPayment;
|
package/dist/next.d.cts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
import { H as HTTPAdapter, M as MppMiddlewareConfig } from './types-CCE-FI8i.cjs';
|
|
3
|
+
import '@parallel-protocol/mpp-types';
|
|
4
|
+
import 'viem';
|
|
5
|
+
|
|
6
|
+
declare class NextAdapter implements HTTPAdapter {
|
|
7
|
+
private readonly req;
|
|
8
|
+
constructor(req: NextRequest);
|
|
9
|
+
getHeader(name: string): string | undefined;
|
|
10
|
+
getMethod(): string;
|
|
11
|
+
getPath(): string;
|
|
12
|
+
getUrl(): string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type NextHandler = (req: NextRequest) => Promise<NextResponse>;
|
|
16
|
+
declare function withPayment(config: MppMiddlewareConfig, handler: NextHandler): NextHandler;
|
|
17
|
+
|
|
18
|
+
export { NextAdapter, withPayment };
|
package/dist/next.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
import { H as HTTPAdapter, M as MppMiddlewareConfig } from './types-CCE-FI8i.js';
|
|
3
|
+
import '@parallel-protocol/mpp-types';
|
|
4
|
+
import 'viem';
|
|
5
|
+
|
|
6
|
+
declare class NextAdapter implements HTTPAdapter {
|
|
7
|
+
private readonly req;
|
|
8
|
+
constructor(req: NextRequest);
|
|
9
|
+
getHeader(name: string): string | undefined;
|
|
10
|
+
getMethod(): string;
|
|
11
|
+
getPath(): string;
|
|
12
|
+
getUrl(): string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type NextHandler = (req: NextRequest) => Promise<NextResponse>;
|
|
16
|
+
declare function withPayment(config: MppMiddlewareConfig, handler: NextHandler): NextHandler;
|
|
17
|
+
|
|
18
|
+
export { NextAdapter, withPayment };
|
package/dist/next.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { raceTimeout, HANDLER_TIMEOUT } from './chunk-DXHOWEAQ.js';
|
|
2
|
+
import { createMppPaymentGate, isSuccessStatus, SETTLE_FAILURE_BODY } from './chunk-HTUIO2MB.js';
|
|
3
|
+
import { encodeBase64Url } from '@parallel-protocol/mpp-types';
|
|
4
|
+
import { NextResponse } from 'next/server';
|
|
5
|
+
|
|
6
|
+
// src/next/adapter.ts
|
|
7
|
+
var NextAdapter = class {
|
|
8
|
+
constructor(req) {
|
|
9
|
+
this.req = req;
|
|
10
|
+
}
|
|
11
|
+
req;
|
|
12
|
+
getHeader(name) {
|
|
13
|
+
return this.req.headers.get(name) ?? void 0;
|
|
14
|
+
}
|
|
15
|
+
getMethod() {
|
|
16
|
+
return this.req.method;
|
|
17
|
+
}
|
|
18
|
+
getPath() {
|
|
19
|
+
return this.req.nextUrl.pathname;
|
|
20
|
+
}
|
|
21
|
+
getUrl() {
|
|
22
|
+
return this.req.url;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// src/next/index.ts
|
|
27
|
+
function withPayment(config, handler) {
|
|
28
|
+
const gate = createMppPaymentGate(config);
|
|
29
|
+
return async (req) => {
|
|
30
|
+
const gateResult = await gate(new NextAdapter(req));
|
|
31
|
+
if (gateResult.type === "pass") {
|
|
32
|
+
return handler(req);
|
|
33
|
+
}
|
|
34
|
+
if (gateResult.type === "error") {
|
|
35
|
+
return new NextResponse(JSON.stringify(gateResult.result.body), {
|
|
36
|
+
status: gateResult.result.status,
|
|
37
|
+
headers: {
|
|
38
|
+
...gateResult.result.headers,
|
|
39
|
+
"Content-Type": "application/json"
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
let response;
|
|
44
|
+
try {
|
|
45
|
+
const outcome = await raceTimeout(handler(req));
|
|
46
|
+
if (outcome === HANDLER_TIMEOUT) {
|
|
47
|
+
return new NextResponse(null, { status: 504 });
|
|
48
|
+
}
|
|
49
|
+
response = outcome;
|
|
50
|
+
} catch {
|
|
51
|
+
return new NextResponse(null, { status: 504 });
|
|
52
|
+
}
|
|
53
|
+
if (isSuccessStatus(response.status)) {
|
|
54
|
+
try {
|
|
55
|
+
const settleResponse = await gateResult.settle();
|
|
56
|
+
if (settleResponse.success) {
|
|
57
|
+
const headers = new Headers(response.headers);
|
|
58
|
+
headers.set(
|
|
59
|
+
"Payment-Receipt",
|
|
60
|
+
encodeBase64Url(settleResponse.receipt)
|
|
61
|
+
);
|
|
62
|
+
headers.set("access-control-expose-headers", "Payment-Receipt");
|
|
63
|
+
return new NextResponse(response.body, {
|
|
64
|
+
status: response.status,
|
|
65
|
+
headers
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
} catch {
|
|
69
|
+
}
|
|
70
|
+
return NextResponse.json(SETTLE_FAILURE_BODY, { status: 402 });
|
|
71
|
+
}
|
|
72
|
+
return response;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export { NextAdapter, withPayment };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { MppReceipt } from '@parallel-protocol/mpp-types';
|
|
2
|
+
import { Address } from 'viem';
|
|
3
|
+
|
|
4
|
+
interface MppFacilitatorConfig {
|
|
5
|
+
url: string;
|
|
6
|
+
apiKey?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A protected route's charge configuration. One charge currency per route — the
|
|
10
|
+
* MPP charge intent settles a single (amount, currency) onto `payTo`.
|
|
11
|
+
*/
|
|
12
|
+
interface MppRouteConfig {
|
|
13
|
+
/** Human-readable amount (e.g. "0.01") or a raw bigint in token base units. */
|
|
14
|
+
price: string | bigint;
|
|
15
|
+
/** Decimals used to parse `price` when it is a decimal string. Default 6. */
|
|
16
|
+
decimals?: number;
|
|
17
|
+
/** Chain slug, e.g. "base", "ethereum". */
|
|
18
|
+
network: string;
|
|
19
|
+
/** Merchant recipient — receives the funds. */
|
|
20
|
+
payTo: Address;
|
|
21
|
+
/** ERC-20 charge currency (the token the payer authorizes). */
|
|
22
|
+
currency: Address;
|
|
23
|
+
/**
|
|
24
|
+
* `evm` (default) — standard EIP-3009 authorization, Route A, max interop.
|
|
25
|
+
* `parallel` — the credential payload is a full SignedPaymentPayload (any route).
|
|
26
|
+
*/
|
|
27
|
+
method?: "evm" | "parallel";
|
|
28
|
+
/** Seconds the challenge stays valid; informational on the challenge. Default 300. */
|
|
29
|
+
maxTimeoutSeconds?: number;
|
|
30
|
+
description?: string;
|
|
31
|
+
realm?: string;
|
|
32
|
+
}
|
|
33
|
+
interface MppMiddlewareConfig {
|
|
34
|
+
facilitator: MppFacilitatorConfig;
|
|
35
|
+
routes: Record<string, MppRouteConfig>;
|
|
36
|
+
}
|
|
37
|
+
interface RunHandlerResult {
|
|
38
|
+
status: number;
|
|
39
|
+
setResponseHeader(name: string, value: string): void;
|
|
40
|
+
sendResponse(): void;
|
|
41
|
+
discardResponse(): void;
|
|
42
|
+
}
|
|
43
|
+
interface HTTPAdapter {
|
|
44
|
+
getHeader(name: string): string | undefined;
|
|
45
|
+
getMethod(): string;
|
|
46
|
+
getPath(): string;
|
|
47
|
+
getUrl(): string;
|
|
48
|
+
runHandler?(): Promise<RunHandlerResult>;
|
|
49
|
+
}
|
|
50
|
+
interface MppSettleSuccess {
|
|
51
|
+
success: true;
|
|
52
|
+
receipt: MppReceipt;
|
|
53
|
+
}
|
|
54
|
+
interface MppSettleFailure {
|
|
55
|
+
success: false;
|
|
56
|
+
error: {
|
|
57
|
+
code: string;
|
|
58
|
+
message: string;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
type MppSettleResult = MppSettleSuccess | MppSettleFailure;
|
|
62
|
+
interface MiddlewareResult {
|
|
63
|
+
status: number;
|
|
64
|
+
headers: Record<string, string>;
|
|
65
|
+
body: unknown;
|
|
66
|
+
}
|
|
67
|
+
interface PassResult {
|
|
68
|
+
pass: true;
|
|
69
|
+
handlerRan?: true;
|
|
70
|
+
}
|
|
71
|
+
type PaymentGateResult = {
|
|
72
|
+
type: "pass";
|
|
73
|
+
} | {
|
|
74
|
+
type: "error";
|
|
75
|
+
result: MiddlewareResult;
|
|
76
|
+
} | {
|
|
77
|
+
type: "verified";
|
|
78
|
+
settle(): Promise<MppSettleResult>;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export type { HTTPAdapter as H, MppMiddlewareConfig as M, PaymentGateResult as P, RunHandlerResult as R, MppRouteConfig as a, MppFacilitatorConfig as b, MppSettleResult as c, MiddlewareResult as d, PassResult as e, MppSettleFailure as f, MppSettleSuccess as g };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { MppReceipt } from '@parallel-protocol/mpp-types';
|
|
2
|
+
import { Address } from 'viem';
|
|
3
|
+
|
|
4
|
+
interface MppFacilitatorConfig {
|
|
5
|
+
url: string;
|
|
6
|
+
apiKey?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A protected route's charge configuration. One charge currency per route — the
|
|
10
|
+
* MPP charge intent settles a single (amount, currency) onto `payTo`.
|
|
11
|
+
*/
|
|
12
|
+
interface MppRouteConfig {
|
|
13
|
+
/** Human-readable amount (e.g. "0.01") or a raw bigint in token base units. */
|
|
14
|
+
price: string | bigint;
|
|
15
|
+
/** Decimals used to parse `price` when it is a decimal string. Default 6. */
|
|
16
|
+
decimals?: number;
|
|
17
|
+
/** Chain slug, e.g. "base", "ethereum". */
|
|
18
|
+
network: string;
|
|
19
|
+
/** Merchant recipient — receives the funds. */
|
|
20
|
+
payTo: Address;
|
|
21
|
+
/** ERC-20 charge currency (the token the payer authorizes). */
|
|
22
|
+
currency: Address;
|
|
23
|
+
/**
|
|
24
|
+
* `evm` (default) — standard EIP-3009 authorization, Route A, max interop.
|
|
25
|
+
* `parallel` — the credential payload is a full SignedPaymentPayload (any route).
|
|
26
|
+
*/
|
|
27
|
+
method?: "evm" | "parallel";
|
|
28
|
+
/** Seconds the challenge stays valid; informational on the challenge. Default 300. */
|
|
29
|
+
maxTimeoutSeconds?: number;
|
|
30
|
+
description?: string;
|
|
31
|
+
realm?: string;
|
|
32
|
+
}
|
|
33
|
+
interface MppMiddlewareConfig {
|
|
34
|
+
facilitator: MppFacilitatorConfig;
|
|
35
|
+
routes: Record<string, MppRouteConfig>;
|
|
36
|
+
}
|
|
37
|
+
interface RunHandlerResult {
|
|
38
|
+
status: number;
|
|
39
|
+
setResponseHeader(name: string, value: string): void;
|
|
40
|
+
sendResponse(): void;
|
|
41
|
+
discardResponse(): void;
|
|
42
|
+
}
|
|
43
|
+
interface HTTPAdapter {
|
|
44
|
+
getHeader(name: string): string | undefined;
|
|
45
|
+
getMethod(): string;
|
|
46
|
+
getPath(): string;
|
|
47
|
+
getUrl(): string;
|
|
48
|
+
runHandler?(): Promise<RunHandlerResult>;
|
|
49
|
+
}
|
|
50
|
+
interface MppSettleSuccess {
|
|
51
|
+
success: true;
|
|
52
|
+
receipt: MppReceipt;
|
|
53
|
+
}
|
|
54
|
+
interface MppSettleFailure {
|
|
55
|
+
success: false;
|
|
56
|
+
error: {
|
|
57
|
+
code: string;
|
|
58
|
+
message: string;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
type MppSettleResult = MppSettleSuccess | MppSettleFailure;
|
|
62
|
+
interface MiddlewareResult {
|
|
63
|
+
status: number;
|
|
64
|
+
headers: Record<string, string>;
|
|
65
|
+
body: unknown;
|
|
66
|
+
}
|
|
67
|
+
interface PassResult {
|
|
68
|
+
pass: true;
|
|
69
|
+
handlerRan?: true;
|
|
70
|
+
}
|
|
71
|
+
type PaymentGateResult = {
|
|
72
|
+
type: "pass";
|
|
73
|
+
} | {
|
|
74
|
+
type: "error";
|
|
75
|
+
result: MiddlewareResult;
|
|
76
|
+
} | {
|
|
77
|
+
type: "verified";
|
|
78
|
+
settle(): Promise<MppSettleResult>;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export type { HTTPAdapter as H, MppMiddlewareConfig as M, PaymentGateResult as P, RunHandlerResult as R, MppRouteConfig as a, MppFacilitatorConfig as b, MppSettleResult as c, MiddlewareResult as d, PassResult as e, MppSettleFailure as f, MppSettleSuccess as g };
|
package/package.json
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@parallel-protocol/mpp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Parallel Protocol MPP (Machine Payments Protocol) merchant middleware — the Payment HTTP auth-scheme dance (402 challenge → credential → receipt) over the facilitator's /mpp endpoints",
|
|
5
|
+
"author": "Parallel Protocol <contact@parallel.best>",
|
|
6
|
+
"repository": "github:parallel-protocol/sdk-merchant",
|
|
7
|
+
"homepage": "https://github.com/parallel-protocol/sdk-merchant",
|
|
8
|
+
"bugs": {
|
|
9
|
+
"url": "https://github.com/parallel-protocol/sdk-merchant/issues"
|
|
10
|
+
},
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"sideEffects": false,
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "./dist/index.cjs",
|
|
15
|
+
"module": "./dist/index.js",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"import": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"default": "./dist/index.js"
|
|
22
|
+
},
|
|
23
|
+
"require": {
|
|
24
|
+
"types": "./dist/index.d.cts",
|
|
25
|
+
"default": "./dist/index.cjs"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"./express": {
|
|
29
|
+
"import": {
|
|
30
|
+
"types": "./dist/express.d.ts",
|
|
31
|
+
"default": "./dist/express.js"
|
|
32
|
+
},
|
|
33
|
+
"require": {
|
|
34
|
+
"types": "./dist/express.d.cts",
|
|
35
|
+
"default": "./dist/express.cjs"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"./next": {
|
|
39
|
+
"import": {
|
|
40
|
+
"types": "./dist/next.d.ts",
|
|
41
|
+
"default": "./dist/next.js"
|
|
42
|
+
},
|
|
43
|
+
"require": {
|
|
44
|
+
"types": "./dist/next.d.cts",
|
|
45
|
+
"default": "./dist/next.cjs"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"./fastify": {
|
|
49
|
+
"import": {
|
|
50
|
+
"types": "./dist/fastify.d.ts",
|
|
51
|
+
"default": "./dist/fastify.js"
|
|
52
|
+
},
|
|
53
|
+
"require": {
|
|
54
|
+
"types": "./dist/fastify.d.cts",
|
|
55
|
+
"default": "./dist/fastify.cjs"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"./hono": {
|
|
59
|
+
"import": {
|
|
60
|
+
"types": "./dist/hono.d.ts",
|
|
61
|
+
"default": "./dist/hono.js"
|
|
62
|
+
},
|
|
63
|
+
"require": {
|
|
64
|
+
"types": "./dist/hono.d.cts",
|
|
65
|
+
"default": "./dist/hono.cjs"
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"./package.json": "./package.json"
|
|
69
|
+
},
|
|
70
|
+
"files": [
|
|
71
|
+
"dist",
|
|
72
|
+
"README.md"
|
|
73
|
+
],
|
|
74
|
+
"publishConfig": {
|
|
75
|
+
"registry": "https://registry.npmjs.org",
|
|
76
|
+
"access": "public"
|
|
77
|
+
},
|
|
78
|
+
"scripts": {
|
|
79
|
+
"build": "tsup",
|
|
80
|
+
"dev": "tsup --watch",
|
|
81
|
+
"clean": "rm -rf dist coverage",
|
|
82
|
+
"type-check": "tsc --noEmit",
|
|
83
|
+
"test": "vitest"
|
|
84
|
+
},
|
|
85
|
+
"peerDependencies": {
|
|
86
|
+
"viem": "^2.0.0",
|
|
87
|
+
"express": "^4.0.0 || ^5.0.0",
|
|
88
|
+
"next": "^14.0.0 || ^15.0.0",
|
|
89
|
+
"fastify": "^4.0.0 || ^5.0.0",
|
|
90
|
+
"hono": "^4.0.0"
|
|
91
|
+
},
|
|
92
|
+
"peerDependenciesMeta": {
|
|
93
|
+
"viem": {
|
|
94
|
+
"optional": true
|
|
95
|
+
},
|
|
96
|
+
"express": {
|
|
97
|
+
"optional": true
|
|
98
|
+
},
|
|
99
|
+
"next": {
|
|
100
|
+
"optional": true
|
|
101
|
+
},
|
|
102
|
+
"fastify": {
|
|
103
|
+
"optional": true
|
|
104
|
+
},
|
|
105
|
+
"hono": {
|
|
106
|
+
"optional": true
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
"devDependencies": {
|
|
110
|
+
"@types/express": "^5.0.1",
|
|
111
|
+
"@types/node": "^22.0.0",
|
|
112
|
+
"fastify": "^5.0.0",
|
|
113
|
+
"hono": "^4.0.0",
|
|
114
|
+
"next": "^15.0.0",
|
|
115
|
+
"tsup": "^8.0.0",
|
|
116
|
+
"typescript": "^5.9.0",
|
|
117
|
+
"viem": "^2.47.0",
|
|
118
|
+
"vitest": "^4.0.14"
|
|
119
|
+
},
|
|
120
|
+
"dependencies": {
|
|
121
|
+
"@parallel-protocol/chains": "^0.1.0",
|
|
122
|
+
"@parallel-protocol/mpp-types": "^0.1.0",
|
|
123
|
+
"zod": "^4.4.3"
|
|
124
|
+
}
|
|
125
|
+
}
|