@seedhape/x402-merchant-sdk 0.4.0 → 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/README.md +105 -0
- package/dist/commerce.d.ts +38 -0
- package/dist/commerce.d.ts.map +1 -0
- package/dist/commerce.js +35 -0
- package/dist/commerce.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/mpp.d.ts +22 -0
- package/dist/mpp.d.ts.map +1 -0
- package/dist/mpp.js +23 -0
- package/dist/mpp.js.map +1 -0
- package/dist/seller.d.ts +93 -0
- package/dist/seller.d.ts.map +1 -0
- package/dist/seller.js +249 -0
- package/dist/seller.js.map +1 -0
- package/dist/stripe-mpp.d.ts +59 -0
- package/dist/stripe-mpp.d.ts.map +1 -0
- package/dist/stripe-mpp.js +79 -0
- package/dist/stripe-mpp.js.map +1 -0
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -1,5 +1,72 @@
|
|
|
1
1
|
# @seedhape/x402-merchant-sdk
|
|
2
2
|
|
|
3
|
+
## One catalog for agent commerce
|
|
4
|
+
|
|
5
|
+
Use `createMerchantCommerce` to define products once. The same product
|
|
6
|
+
definitions can feed the SDK's current x402 paywall and future ACP/UCP/MPP
|
|
7
|
+
adapters; merchants do not maintain protocol-specific catalogs.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
const commerce = createMerchantCommerce({
|
|
11
|
+
paywall: { payTo, ...base, facilitator: base.facilitator },
|
|
12
|
+
products: [{
|
|
13
|
+
id: "weather", name: "Weather API", description: "Current weather",
|
|
14
|
+
endpoint: "/weather",
|
|
15
|
+
price: { amount: 50_000n, ...base },
|
|
16
|
+
}],
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
commerce.catalog(); // publish to your agent-facing catalog
|
|
20
|
+
commerce.paywallFor("weather"); // pass to existing paywall middleware
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The helper normalizes discovery metadata and product lookup. Fulfillment and
|
|
24
|
+
refunds remain merchant-owned and should use the purchase ID as their durable
|
|
25
|
+
idempotency key.
|
|
26
|
+
|
|
27
|
+
## Unified seller facade (preview)
|
|
28
|
+
|
|
29
|
+
`createSeedhapeSeller` is the single-drop-in entry point for a server-side
|
|
30
|
+
Express route. Define each product once and keep provider credentials in the
|
|
31
|
+
server environment:
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { base, createSeedhapeSeller } from "@seedhape/x402-merchant-sdk";
|
|
35
|
+
|
|
36
|
+
const seller = createSeedhapeSeller({
|
|
37
|
+
products: [{
|
|
38
|
+
id: "weather",
|
|
39
|
+
name: "Weather API",
|
|
40
|
+
description: "Current weather data",
|
|
41
|
+
endpoint: "/weather",
|
|
42
|
+
price: "0.50",
|
|
43
|
+
fulfill: async () => ({ temperature: 24 }),
|
|
44
|
+
}],
|
|
45
|
+
payments: {
|
|
46
|
+
x402: {
|
|
47
|
+
payTo: process.env.MERCHANT_WALLET!,
|
|
48
|
+
network: base.network,
|
|
49
|
+
asset: base.asset,
|
|
50
|
+
decimals: base.decimals,
|
|
51
|
+
facilitator: base.facilitator,
|
|
52
|
+
},
|
|
53
|
+
stripeMpp: {
|
|
54
|
+
stripeSecretKey: process.env.STRIPE_SECRET_KEY!,
|
|
55
|
+
profileId: process.env.STRIPE_PROFILE_ID!,
|
|
56
|
+
mppSecretKey: process.env.MPP_SECRET_KEY!,
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
app.all("/weather", seller.route("weather"));
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The facade preserves the existing x402 Bazaar discovery challenge. It selects
|
|
65
|
+
Stripe MPP when a client advertises the MPP payment scheme and selects x402
|
|
66
|
+
otherwise. ACP/UCP checkout remains a separate integration gate; it will
|
|
67
|
+
consume the same catalog rather than requiring another merchant catalog or
|
|
68
|
+
middleware stack.
|
|
69
|
+
|
|
3
70
|
Add an x402 payment gate to an existing Express, Hono, or `node:http` service. The SDK returns a standard `402 Payment Required` challenge, verifies the buyer's payment through an x402 facilitator, settles USDC directly to the merchant wallet, and exposes a receipt for your application ledger.
|
|
4
71
|
|
|
5
72
|
## Install
|
|
@@ -8,6 +75,44 @@ Add an x402 payment gate to an existing Express, Hono, or `node:http` service. T
|
|
|
8
75
|
npm install @seedhape/x402-merchant-sdk
|
|
9
76
|
```
|
|
10
77
|
|
|
78
|
+
## Stripe machine payments (MPP)
|
|
79
|
+
|
|
80
|
+
Install the optional MPP runtime when you want agents to pay with Stripe cards
|
|
81
|
+
or Shared Payment Tokens:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npm install mppx
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Create one Stripe MPP paywall per seller endpoint. The seller keeps the Stripe
|
|
88
|
+
secret key and `profile_test_...` profile ID on the server; the SDK returns the
|
|
89
|
+
payment challenge and settles the credential without exposing either value:
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import { createStripeMppPaywall } from "@seedhape/x402-merchant-sdk";
|
|
93
|
+
|
|
94
|
+
const mpp = await createStripeMppPaywall({
|
|
95
|
+
stripeSecretKey: process.env.STRIPE_SECRET_KEY!,
|
|
96
|
+
profileId: process.env.STRIPE_PROFILE_ID!,
|
|
97
|
+
mppSecretKey: process.env.MPP_SECRET_KEY!,
|
|
98
|
+
amount: "0.50",
|
|
99
|
+
currency: "usd",
|
|
100
|
+
description: "Weather API request",
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
export async function weather(request: Request) {
|
|
104
|
+
return mpp.handle(request, async () =>
|
|
105
|
+
Response.json({ temperature: 24, conditions: "clear" }),
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
An unpaid agent receives HTTP `402`; a valid credential is verified and
|
|
111
|
+
settled before the fulfillment callback runs. For a Stripe Connect direct
|
|
112
|
+
charge, pass `connect: { stripeAccount: "acct_..." }`. To enable Stripe's
|
|
113
|
+
stablecoin MPP rail as well, supply a Stripe SDK client and a test Tempo deposit
|
|
114
|
+
address. Use `profile_test_...` and `sk_test_...` in a Stripe Sandbox.
|
|
115
|
+
|
|
11
116
|
## Express
|
|
12
117
|
|
|
13
118
|
```ts
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Money, PaywallConfig, RouteMetadata } from "./middleware.js";
|
|
2
|
+
/** A merchant's protocol-neutral, agent-readable product definition. */
|
|
3
|
+
export interface MerchantProduct {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
price: Money;
|
|
8
|
+
endpoint: string;
|
|
9
|
+
/** A human-readable policy; fulfillment/refund behavior stays merchant-owned. */
|
|
10
|
+
refundPolicy?: string;
|
|
11
|
+
metadata?: RouteMetadata;
|
|
12
|
+
}
|
|
13
|
+
export interface MerchantCommerceConfig {
|
|
14
|
+
/** Base paywall/provider configuration shared by every product. */
|
|
15
|
+
paywall: Omit<PaywallConfig, "price">;
|
|
16
|
+
products: readonly MerchantProduct[];
|
|
17
|
+
}
|
|
18
|
+
export interface MerchantCatalogProduct extends Omit<MerchantProduct, "price"> {
|
|
19
|
+
price: {
|
|
20
|
+
amount: string;
|
|
21
|
+
asset: string;
|
|
22
|
+
network: string;
|
|
23
|
+
decimals: number;
|
|
24
|
+
};
|
|
25
|
+
capabilities: readonly ["quote", "purchase", "receipt"];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* One merchant integration surface for catalogs and paid routes. Protocol
|
|
29
|
+
* adapters consume the same product definitions, so a merchant does not keep
|
|
30
|
+
* separate ACP/UCP/x402/MPP catalogs. The returned PaywallConfig remains
|
|
31
|
+
* compatible with the existing Express/Hono/node:http middleware.
|
|
32
|
+
*/
|
|
33
|
+
export declare function createMerchantCommerce(config: MerchantCommerceConfig): {
|
|
34
|
+
catalog(): MerchantCatalogProduct[];
|
|
35
|
+
product(id: string): MerchantProduct | null;
|
|
36
|
+
paywallFor(id: string): PaywallConfig;
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=commerce.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commerce.d.ts","sourceRoot":"","sources":["../src/commerce.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE3E,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC,mEAAmE;IACnE,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IACtC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;CACtC;AAED,MAAM,WAAW,sBAAuB,SAAQ,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC;IAC5E,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5E,YAAY,EAAE,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;CACzD;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,sBAAsB;eAKtD,sBAAsB,EAAE;gBAOvB,MAAM,GAAG,eAAe,GAAG,IAAI;mBAG5B,MAAM,GAAG,aAAa;EAWxC"}
|
package/dist/commerce.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One merchant integration surface for catalogs and paid routes. Protocol
|
|
3
|
+
* adapters consume the same product definitions, so a merchant does not keep
|
|
4
|
+
* separate ACP/UCP/x402/MPP catalogs. The returned PaywallConfig remains
|
|
5
|
+
* compatible with the existing Express/Hono/node:http middleware.
|
|
6
|
+
*/
|
|
7
|
+
export function createMerchantCommerce(config) {
|
|
8
|
+
const byId = new Map(config.products.map((product) => [product.id, product]));
|
|
9
|
+
if (byId.size !== config.products.length)
|
|
10
|
+
throw new Error("Merchant product IDs must be unique.");
|
|
11
|
+
return {
|
|
12
|
+
catalog() {
|
|
13
|
+
return config.products.map((product) => ({
|
|
14
|
+
...product,
|
|
15
|
+
price: { ...product.price, amount: product.price.amount.toString() },
|
|
16
|
+
capabilities: ["quote", "purchase", "receipt"],
|
|
17
|
+
}));
|
|
18
|
+
},
|
|
19
|
+
product(id) {
|
|
20
|
+
return byId.get(id) ?? null;
|
|
21
|
+
},
|
|
22
|
+
paywallFor(id) {
|
|
23
|
+
const product = byId.get(id);
|
|
24
|
+
if (!product)
|
|
25
|
+
throw new Error(`Unknown merchant product: ${id}`);
|
|
26
|
+
return {
|
|
27
|
+
...config.paywall,
|
|
28
|
+
price: product.price,
|
|
29
|
+
description: product.description,
|
|
30
|
+
route: { ...product.metadata, name: product.metadata?.name ?? product.name, description: product.description },
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=commerce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commerce.js","sourceRoot":"","sources":["../src/commerce.ts"],"names":[],"mappings":"AAyBA;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAA8B;IACnE,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAC9E,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,QAAQ,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAElG,OAAO;QACL,OAAO;YACL,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBACvC,GAAG,OAAO;gBACV,KAAK,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE;gBACpE,YAAY,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,CAAU;aACxD,CAAC,CAAC,CAAC;QACN,CAAC;QACD,OAAO,CAAC,EAAU;YAChB,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC;QAC9B,CAAC;QACD,UAAU,CAAC,EAAU;YACnB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC7B,IAAI,CAAC,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,EAAE,EAAE,CAAC,CAAC;YACjE,OAAO;gBACL,GAAG,MAAM,CAAC,OAAO;gBACjB,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,KAAK,EAAE,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,IAAI,IAAI,OAAO,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE;aAC/G,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,4 +2,8 @@ export * from "./middleware.js";
|
|
|
2
2
|
export * from "./mcp.js";
|
|
3
3
|
export * from "./ap2.js";
|
|
4
4
|
export * from "./browser-paywall.js";
|
|
5
|
+
export * from "./commerce.js";
|
|
6
|
+
export * from "./mpp.js";
|
|
7
|
+
export * from "./stripe-mpp.js";
|
|
8
|
+
export * from "./seller.js";
|
|
5
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,4 +2,8 @@ export * from "./middleware.js";
|
|
|
2
2
|
export * from "./mcp.js";
|
|
3
3
|
export * from "./ap2.js";
|
|
4
4
|
export * from "./browser-paywall.js";
|
|
5
|
+
export * from "./commerce.js";
|
|
6
|
+
export * from "./mpp.js";
|
|
7
|
+
export * from "./stripe-mpp.js";
|
|
8
|
+
export * from "./seller.js";
|
|
5
9
|
//# 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,cAAc,iBAAiB,CAAC;AAChC,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC"}
|
package/dist/mpp.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type MppCredential } from "@seedhape/core";
|
|
2
|
+
export interface MppChallengeOptions {
|
|
3
|
+
/** HTTP authentication realm shown to the paying client. */
|
|
4
|
+
realm: string;
|
|
5
|
+
/** Provider method identifier, for example `stripe` or `tempo`. */
|
|
6
|
+
method: string;
|
|
7
|
+
/** Intent profile, normally `charge` for a one-shot API request. */
|
|
8
|
+
intent?: string;
|
|
9
|
+
/** Provider-specific request body; never accept this from an untrusted client. */
|
|
10
|
+
request: Record<string, unknown>;
|
|
11
|
+
/** Challenge lifetime in seconds. Defaults to five minutes. */
|
|
12
|
+
expiresInSeconds?: number;
|
|
13
|
+
/** Optional provider/profile metadata represented as string auth parameters. */
|
|
14
|
+
extensions?: Record<string, string>;
|
|
15
|
+
/** Inject a stable ID in tests or use the default random challenge ID. */
|
|
16
|
+
id?: string;
|
|
17
|
+
}
|
|
18
|
+
/** Build a standards-shaped MPP `WWW-Authenticate` value for a server response. */
|
|
19
|
+
export declare function createMppChallenge(options: MppChallengeOptions, now?: number): string;
|
|
20
|
+
/** Parse the client credential so a provider adapter can verify it. */
|
|
21
|
+
export declare function readMppCredential(header: string): MppCredential;
|
|
22
|
+
//# sourceMappingURL=mpp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mpp.d.ts","sourceRoot":"","sources":["../src/mpp.ts"],"names":[],"mappings":"AACA,OAAO,EAA6D,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/G,MAAM,WAAW,mBAAmB;IAClC,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,+DAA+D;IAC/D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gFAAgF;IAChF,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,0EAA0E;IAC1E,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,mFAAmF;AACnF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,EAAE,GAAG,SAAgC,GAAG,MAAM,CAa5G;AAED,uEAAuE;AACvE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAE/D"}
|
package/dist/mpp.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { formatMppChallenge, parseMppCredential } from "@seedhape/core";
|
|
3
|
+
/** Build a standards-shaped MPP `WWW-Authenticate` value for a server response. */
|
|
4
|
+
export function createMppChallenge(options, now = Math.floor(Date.now() / 1000)) {
|
|
5
|
+
const lifetime = options.expiresInSeconds ?? 300;
|
|
6
|
+
if (!Number.isSafeInteger(lifetime) || lifetime <= 0)
|
|
7
|
+
throw new Error("MPP challenge lifetime must be a positive integer.");
|
|
8
|
+
const challenge = {
|
|
9
|
+
id: options.id ?? randomUUID(),
|
|
10
|
+
realm: options.realm,
|
|
11
|
+
method: options.method,
|
|
12
|
+
intent: options.intent ?? "charge",
|
|
13
|
+
request: options.request,
|
|
14
|
+
expires: now + lifetime,
|
|
15
|
+
...(options.extensions ?? {}),
|
|
16
|
+
};
|
|
17
|
+
return formatMppChallenge(challenge);
|
|
18
|
+
}
|
|
19
|
+
/** Parse the client credential so a provider adapter can verify it. */
|
|
20
|
+
export function readMppCredential(header) {
|
|
21
|
+
return parseMppCredential(header);
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=mpp.js.map
|
package/dist/mpp.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mpp.js","sourceRoot":"","sources":["../src/mpp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAyC,MAAM,gBAAgB,CAAC;AAmB/G,mFAAmF;AACnF,MAAM,UAAU,kBAAkB,CAAC,OAA4B,EAAE,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;IAClG,MAAM,QAAQ,GAAG,OAAO,CAAC,gBAAgB,IAAI,GAAG,CAAC;IACjD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,QAAQ,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IAC5H,MAAM,SAAS,GAAiB;QAC9B,EAAE,EAAE,OAAO,CAAC,EAAE,IAAI,UAAU,EAAE;QAC9B,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,QAAQ;QAClC,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,OAAO,EAAE,GAAG,GAAG,QAAQ;QACvB,GAAG,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC;KAC9B,CAAC;IACF,OAAO,kBAAkB,CAAC,SAAS,CAAC,CAAC;AACvC,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;AACpC,CAAC"}
|
package/dist/seller.d.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { PaywallConfig, Money, Receipt, RouteMetadata } from "./middleware.js";
|
|
2
|
+
import { Paywall } from "./middleware.js";
|
|
3
|
+
import { type StripeMppPaywallOptions } from "./stripe-mpp.js";
|
|
4
|
+
export type SellerCapabilityState = "enabled" | "preview" | "unavailable";
|
|
5
|
+
export interface SellerCapability {
|
|
6
|
+
state: SellerCapabilityState;
|
|
7
|
+
reason?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface SellerPriceContext {
|
|
10
|
+
path: string;
|
|
11
|
+
method: string;
|
|
12
|
+
query: URLSearchParams;
|
|
13
|
+
}
|
|
14
|
+
/** A product price can be an x402 Money value, a decimal string, or a resolver. */
|
|
15
|
+
export type SellerPrice = Money | string | ((context: SellerPriceContext) => Money | string | null | Promise<Money | string | null>);
|
|
16
|
+
export interface SellerFulfillmentContext {
|
|
17
|
+
product: SeedhapeSellerProduct;
|
|
18
|
+
orderId: string;
|
|
19
|
+
request: unknown;
|
|
20
|
+
receipt?: Receipt;
|
|
21
|
+
}
|
|
22
|
+
export type SellerFulfillment = unknown | Response | {
|
|
23
|
+
body: unknown;
|
|
24
|
+
status?: number;
|
|
25
|
+
headers?: Record<string, string>;
|
|
26
|
+
};
|
|
27
|
+
export interface SeedhapeSellerProduct {
|
|
28
|
+
id: string;
|
|
29
|
+
name: string;
|
|
30
|
+
description: string;
|
|
31
|
+
endpoint: string;
|
|
32
|
+
price: SellerPrice;
|
|
33
|
+
metadata?: RouteMetadata;
|
|
34
|
+
fulfill: (context: SellerFulfillmentContext) => SellerFulfillment | Promise<SellerFulfillment>;
|
|
35
|
+
}
|
|
36
|
+
export interface SeedhapeSellerX402Config extends Omit<PaywallConfig, "price" | "description" | "route"> {
|
|
37
|
+
/** The default asset denomination used when a product price is a decimal. */
|
|
38
|
+
decimals?: number;
|
|
39
|
+
}
|
|
40
|
+
export interface SeedhapeSellerConfig {
|
|
41
|
+
merchantId?: string;
|
|
42
|
+
products: readonly SeedhapeSellerProduct[];
|
|
43
|
+
/** Existing x402 configuration. Omit this to publish a catalog without payment. */
|
|
44
|
+
x402?: SeedhapeSellerX402Config;
|
|
45
|
+
/** Stripe-managed MPP card and stablecoin payments. */
|
|
46
|
+
stripeMpp?: Omit<StripeMppPaywallOptions, "amount" | "description" | "metadata"> & {
|
|
47
|
+
metadata?: Record<string, string>;
|
|
48
|
+
};
|
|
49
|
+
/** Backward-compatible capability hint; use stripeMpp for payment setup. */
|
|
50
|
+
mpp?: {
|
|
51
|
+
enabled?: boolean;
|
|
52
|
+
};
|
|
53
|
+
/** Preferred unified spelling. `payments.x402` and `payments.stripeMpp` are aliases. */
|
|
54
|
+
payments?: {
|
|
55
|
+
x402?: SeedhapeSellerX402Config;
|
|
56
|
+
stripeMpp?: SeedhapeSellerConfig["stripeMpp"];
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export interface SeedhapeSellerCatalogProduct {
|
|
60
|
+
id: string;
|
|
61
|
+
name: string;
|
|
62
|
+
description: string;
|
|
63
|
+
endpoint: string;
|
|
64
|
+
price: {
|
|
65
|
+
amount: string;
|
|
66
|
+
asset?: string;
|
|
67
|
+
network?: string;
|
|
68
|
+
decimals?: number;
|
|
69
|
+
dynamic?: boolean;
|
|
70
|
+
};
|
|
71
|
+
capabilities: readonly ["quote", "purchase", "receipt"];
|
|
72
|
+
metadata?: RouteMetadata;
|
|
73
|
+
}
|
|
74
|
+
export interface SeedhapeSeller {
|
|
75
|
+
catalog(): SeedhapeSellerCatalogProduct[];
|
|
76
|
+
product(id: string): SeedhapeSellerProduct | null;
|
|
77
|
+
capabilities(): Record<"x402" | "mpp" | "acp" | "ucp" | "ap2" | "webmcp" | "webBotAuth", SellerCapability>;
|
|
78
|
+
/** Express-compatible route. The merchant only supplies product fulfillment. */
|
|
79
|
+
route(productId: string): (req: any, res: any, next: any) => Promise<void>;
|
|
80
|
+
/** Fetch-compatible route for Next.js, Hono, and other web runtimes. */
|
|
81
|
+
fetch(productId: string): (request: Request) => Promise<Response>;
|
|
82
|
+
/** Build the underlying x402 paywall for advanced framework adapters. */
|
|
83
|
+
paywallFor(productId: string): Paywall | null;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Create the first unified merchant integration surface.
|
|
87
|
+
*
|
|
88
|
+
* This intentionally wraps the existing x402 middleware first. ACP/UCP and
|
|
89
|
+
* MPP adapters consume this same catalog in later releases; they are reported
|
|
90
|
+
* explicitly as preview/unavailable instead of being silently advertised.
|
|
91
|
+
*/
|
|
92
|
+
export declare function createSeedhapeSeller(config: SeedhapeSellerConfig): SeedhapeSeller;
|
|
93
|
+
//# sourceMappingURL=seller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seller.d.ts","sourceRoot":"","sources":["../src/seller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAiB,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACnG,OAAO,EAAkB,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAA0B,KAAK,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAEvF,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,CAAC;AAE1E,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,qBAAqB,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,eAAe,CAAC;CACxB;AAED,mFAAmF;AACnF,MAAM,MAAM,WAAW,GACnB,KAAK,GACL,MAAM,GACN,CAAC,CAAC,OAAO,EAAE,kBAAkB,KAAK,KAAK,GAAG,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,KAAK,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;AAE9F,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,qBAAqB,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,MAAM,iBAAiB,GACzB,OAAO,GACP,QAAQ,GACR;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC;AAEzE,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,OAAO,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAChG;AAED,MAAM,WAAW,wBACf,SAAQ,IAAI,CAAC,aAAa,EAAE,OAAO,GAAG,aAAa,GAAG,OAAO,CAAC;IAC9D,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAC3C,mFAAmF;IACnF,IAAI,CAAC,EAAE,wBAAwB,CAAC;IAChC,uDAAuD;IACvD,SAAS,CAAC,EAAE,IAAI,CAAC,uBAAuB,EAAE,QAAQ,GAAG,aAAa,GAAG,UAAU,CAAC,GAAG;QACjF,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACnC,CAAC;IACF,4EAA4E;IAC5E,GAAG,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC5B,wFAAwF;IACxF,QAAQ,CAAC,EAAE;QACT,IAAI,CAAC,EAAE,wBAAwB,CAAC;QAChC,SAAS,CAAC,EAAE,oBAAoB,CAAC,WAAW,CAAC,CAAC;KAC/C,CAAC;CACH;AAED,MAAM,WAAW,4BAA4B;IAC3C,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAClG,YAAY,EAAE,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IACxD,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,IAAI,4BAA4B,EAAE,CAAC;IAC1C,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,qBAAqB,GAAG,IAAI,CAAC;IAClD,YAAY,IAAI,MAAM,CAAC,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,GAAG,YAAY,EAAE,gBAAgB,CAAC,CAAC;IAC3G,gFAAgF;IAChF,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,wEAAwE;IACxE,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClE,yEAAyE;IACzE,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;CAC/C;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,GAAG,cAAc,CAyLjF"}
|
package/dist/seller.js
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { expressPaywall, Paywall } from "./middleware.js";
|
|
2
|
+
import { createStripeMppPaywall } from "./stripe-mpp.js";
|
|
3
|
+
/**
|
|
4
|
+
* Create the first unified merchant integration surface.
|
|
5
|
+
*
|
|
6
|
+
* This intentionally wraps the existing x402 middleware first. ACP/UCP and
|
|
7
|
+
* MPP adapters consume this same catalog in later releases; they are reported
|
|
8
|
+
* explicitly as preview/unavailable instead of being silently advertised.
|
|
9
|
+
*/
|
|
10
|
+
export function createSeedhapeSeller(config) {
|
|
11
|
+
const x402Config = config.payments?.x402 ?? config.x402;
|
|
12
|
+
const stripeMppConfig = config.payments?.stripeMpp ?? config.stripeMpp;
|
|
13
|
+
const products = new Map(config.products.map((product) => [product.id, product]));
|
|
14
|
+
if (products.size !== config.products.length)
|
|
15
|
+
throw new Error("Seller product IDs must be unique.");
|
|
16
|
+
for (const product of config.products) {
|
|
17
|
+
if (!product.id.trim() || !product.endpoint.trim())
|
|
18
|
+
throw new Error("Seller products require an id and endpoint.");
|
|
19
|
+
if (typeof product.fulfill !== "function")
|
|
20
|
+
throw new Error(`Seller product ${product.id} requires a fulfill callback.`);
|
|
21
|
+
}
|
|
22
|
+
const productFor = (id) => {
|
|
23
|
+
const product = products.get(id);
|
|
24
|
+
if (!product)
|
|
25
|
+
throw new Error(`Unknown seller product: ${id}`);
|
|
26
|
+
return product;
|
|
27
|
+
};
|
|
28
|
+
const resolvePrice = async (product, context) => {
|
|
29
|
+
const raw = typeof product.price === "function" ? await product.price(context) : product.price;
|
|
30
|
+
if (raw === null)
|
|
31
|
+
return null;
|
|
32
|
+
if (typeof raw !== "string")
|
|
33
|
+
return raw;
|
|
34
|
+
return decimalToMoney(raw, x402Config);
|
|
35
|
+
};
|
|
36
|
+
const paywallFor = (id) => {
|
|
37
|
+
if (!x402Config)
|
|
38
|
+
return null;
|
|
39
|
+
const product = productFor(id);
|
|
40
|
+
const price = ({ path, method, query }) => {
|
|
41
|
+
const raw = product.price;
|
|
42
|
+
if (typeof raw === "function") {
|
|
43
|
+
// Paywall's resolver is synchronous by contract. Dynamic async prices
|
|
44
|
+
// are rejected clearly instead of creating an under-priced challenge.
|
|
45
|
+
const resolved = raw({ path, method, query });
|
|
46
|
+
if (resolved instanceof Promise)
|
|
47
|
+
throw new Error("Async seller prices require a quote service before x402 payment.");
|
|
48
|
+
return typeof resolved === "string" ? decimalToMoney(resolved, x402Config) : resolved;
|
|
49
|
+
}
|
|
50
|
+
return typeof raw === "string" ? decimalToMoney(raw, x402Config) : raw;
|
|
51
|
+
};
|
|
52
|
+
return new Paywall({
|
|
53
|
+
...x402Config,
|
|
54
|
+
price,
|
|
55
|
+
description: product.description,
|
|
56
|
+
route: { ...product.metadata, name: product.metadata?.name ?? product.name, description: product.description },
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
return {
|
|
60
|
+
catalog() {
|
|
61
|
+
return config.products.map((product) => {
|
|
62
|
+
const price = typeof product.price === "string"
|
|
63
|
+
? { amount: product.price, decimals: x402Config?.decimals, asset: x402Config?.asset, network: x402Config?.network }
|
|
64
|
+
: typeof product.price === "function"
|
|
65
|
+
? { amount: "dynamic", dynamic: true, decimals: x402Config?.decimals, asset: x402Config?.asset, network: x402Config?.network }
|
|
66
|
+
: { amount: product.price.amount.toString(), decimals: product.price.decimals, asset: product.price.asset, network: product.price.network };
|
|
67
|
+
return { id: product.id, name: product.name, description: product.description, endpoint: product.endpoint, price, capabilities: ["quote", "purchase", "receipt"], ...(product.metadata ? { metadata: product.metadata } : {}) };
|
|
68
|
+
});
|
|
69
|
+
},
|
|
70
|
+
product: (id) => products.get(id) ?? null,
|
|
71
|
+
capabilities() {
|
|
72
|
+
return {
|
|
73
|
+
x402: x402Config ? { state: "enabled" } : { state: "unavailable", reason: "Configure x402 settlement to accept wallet payments." },
|
|
74
|
+
mpp: stripeMppConfig ? { state: "preview", reason: "Stripe MPP is enabled for clients that advertise the MPP payment scheme." } : config.mpp?.enabled ? { state: "preview", reason: "MPP provider settlement still requires an adapter configuration." } : { state: "unavailable", reason: "Configure MPP provider access to enable machine payments." },
|
|
75
|
+
acp: { state: "unavailable", reason: "ACP checkout adapter is not yet mounted in the merchant SDK." },
|
|
76
|
+
ucp: { state: "unavailable", reason: "UCP checkout adapter is not yet mounted in the merchant SDK." },
|
|
77
|
+
ap2: x402Config?.ap2 ? { state: "enabled" } : { state: "unavailable", reason: "AP2 authorization evidence is optional for this seller." },
|
|
78
|
+
webmcp: { state: "preview", reason: "WebMCP tools must be exposed by the host application." },
|
|
79
|
+
webBotAuth: { state: "preview", reason: "Web Bot Auth is configured at the host boundary." },
|
|
80
|
+
};
|
|
81
|
+
},
|
|
82
|
+
paywallFor,
|
|
83
|
+
fetch(productId) {
|
|
84
|
+
const product = productFor(productId);
|
|
85
|
+
const paywall = paywallFor(productId);
|
|
86
|
+
let mppPromise;
|
|
87
|
+
return async (request) => {
|
|
88
|
+
const orderId = request.headers.get("x-order-id") ?? request.headers.get("idempotency-key") ?? `${config.merchantId ?? "merchant"}:${product.id}:${Date.now()}`;
|
|
89
|
+
const fulfill = async (receipt) => toFetchResponse(await product.fulfill({ product, orderId, request, receipt }));
|
|
90
|
+
const authorization = request.headers.get("authorization") ?? "";
|
|
91
|
+
const wantsMpp = authorization.startsWith("Payment ") || request.headers.has("accept-payment");
|
|
92
|
+
if (stripeMppConfig && wantsMpp) {
|
|
93
|
+
if (!mppPromise) {
|
|
94
|
+
const amount = typeof product.price === "string"
|
|
95
|
+
? product.price
|
|
96
|
+
: typeof product.price === "function"
|
|
97
|
+
? (() => { throw new Error("Dynamic seller prices require a quote service before Stripe MPP payment."); })()
|
|
98
|
+
: unitsToDecimal(product.price);
|
|
99
|
+
mppPromise = createStripeMppPaywall({ ...stripeMppConfig, amount, description: product.description });
|
|
100
|
+
}
|
|
101
|
+
return (await mppPromise).handle(request, () => fulfill());
|
|
102
|
+
}
|
|
103
|
+
if (!paywall)
|
|
104
|
+
return fulfill();
|
|
105
|
+
const url = new URL(request.url);
|
|
106
|
+
const outcome = await paywall.handle({
|
|
107
|
+
path: url.pathname,
|
|
108
|
+
method: request.method,
|
|
109
|
+
query: url.searchParams,
|
|
110
|
+
resource: paywall.resourceUrl(request.url),
|
|
111
|
+
paymentHeader: request.headers.get("payment-signature") ?? request.headers.get("x-payment"),
|
|
112
|
+
merchantRef: request.headers.get("x-merchant-ref") ?? undefined,
|
|
113
|
+
});
|
|
114
|
+
if (outcome.kind === "free")
|
|
115
|
+
return fulfill();
|
|
116
|
+
if (outcome.kind === "paid") {
|
|
117
|
+
const response = await fulfill(outcome.receipt);
|
|
118
|
+
if (outcome.settlementHeader) {
|
|
119
|
+
response.headers.set("PAYMENT-RESPONSE", outcome.settlementHeader);
|
|
120
|
+
response.headers.set("X-PAYMENT-RESPONSE", outcome.settlementHeader);
|
|
121
|
+
}
|
|
122
|
+
return response;
|
|
123
|
+
}
|
|
124
|
+
const headers = new Headers({ "content-type": "application/json" });
|
|
125
|
+
if (outcome.paymentRequiredHeader)
|
|
126
|
+
headers.set("PAYMENT-REQUIRED", outcome.paymentRequiredHeader);
|
|
127
|
+
if (outcome.ap2CheckoutJwt)
|
|
128
|
+
headers.set("AP2-CHECKOUT-JWT", outcome.ap2CheckoutJwt);
|
|
129
|
+
return new Response(JSON.stringify({ error: outcome.reason, ...(outcome.challenge ?? {}) }), { status: outcome.status ?? 402, headers });
|
|
130
|
+
};
|
|
131
|
+
},
|
|
132
|
+
route(productId) {
|
|
133
|
+
const product = productFor(productId);
|
|
134
|
+
const middleware = x402Config ? expressPaywall({
|
|
135
|
+
...x402Config,
|
|
136
|
+
price: ({ path, method, query }) => {
|
|
137
|
+
const raw = product.price;
|
|
138
|
+
if (typeof raw === "function") {
|
|
139
|
+
const resolved = raw({ path, method, query });
|
|
140
|
+
if (resolved instanceof Promise)
|
|
141
|
+
throw new Error("Async seller prices require a quote service before x402 payment.");
|
|
142
|
+
return typeof resolved === "string" ? decimalToMoney(resolved, x402Config) : resolved;
|
|
143
|
+
}
|
|
144
|
+
return typeof raw === "string" ? decimalToMoney(raw, x402Config) : raw;
|
|
145
|
+
},
|
|
146
|
+
description: product.description,
|
|
147
|
+
route: { ...product.metadata, name: product.metadata?.name ?? product.name, description: product.description },
|
|
148
|
+
}) : null;
|
|
149
|
+
let mppPromise;
|
|
150
|
+
const wantsMpp = (req) => {
|
|
151
|
+
const authorization = String(req.headers?.authorization ?? "");
|
|
152
|
+
return authorization.startsWith("Payment ") || Boolean(req.headers?.["accept-payment"]);
|
|
153
|
+
};
|
|
154
|
+
return async (req, res, next) => {
|
|
155
|
+
const fulfill = async () => {
|
|
156
|
+
const receipt = req.x402Receipt;
|
|
157
|
+
const orderId = String(req.headers?.["x-order-id"] ?? req.headers?.["idempotency-key"] ?? `${config.merchantId ?? "merchant"}:${product.id}:${Date.now()}`);
|
|
158
|
+
const result = await product.fulfill({ product, orderId, request: req, receipt });
|
|
159
|
+
if (result instanceof Response) {
|
|
160
|
+
const body = Buffer.from(await result.arrayBuffer());
|
|
161
|
+
res.status(result.status);
|
|
162
|
+
result.headers.forEach((value, key) => res.setHeader(key, value));
|
|
163
|
+
return res.send(body);
|
|
164
|
+
}
|
|
165
|
+
if (result && typeof result === "object" && "body" in result) {
|
|
166
|
+
const response = result;
|
|
167
|
+
for (const [key, value] of Object.entries(response.headers ?? {}))
|
|
168
|
+
res.setHeader(key, value);
|
|
169
|
+
return res.status(response.status ?? 200).json(response.body);
|
|
170
|
+
}
|
|
171
|
+
return res.json(result);
|
|
172
|
+
};
|
|
173
|
+
try {
|
|
174
|
+
if (stripeMppConfig && wantsMpp(req)) {
|
|
175
|
+
if (!mppPromise) {
|
|
176
|
+
const amount = typeof product.price === "string"
|
|
177
|
+
? product.price
|
|
178
|
+
: typeof product.price === "function"
|
|
179
|
+
? (() => { throw new Error("Dynamic seller prices require a quote service before Stripe MPP payment."); })()
|
|
180
|
+
: unitsToDecimal(product.price);
|
|
181
|
+
mppPromise = createStripeMppPaywall({
|
|
182
|
+
...stripeMppConfig,
|
|
183
|
+
amount,
|
|
184
|
+
description: product.description,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
const mpp = await mppPromise;
|
|
188
|
+
const request = toFetchRequest(req);
|
|
189
|
+
const response = await mpp.handle(request, async () => {
|
|
190
|
+
const result = await product.fulfill({ product, orderId: String(req.headers?.["x-order-id"] ?? req.headers?.["idempotency-key"] ?? `${config.merchantId ?? "merchant"}:${product.id}:${Date.now()}`), request: req });
|
|
191
|
+
return toFetchResponse(result);
|
|
192
|
+
});
|
|
193
|
+
return sendFetchResponse(res, response);
|
|
194
|
+
}
|
|
195
|
+
if (middleware)
|
|
196
|
+
return await middleware(req, res, () => fulfill().then(() => undefined));
|
|
197
|
+
await fulfill();
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
return next(error);
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
function decimalToMoney(value, x402) {
|
|
207
|
+
if (!x402?.asset || !x402.network || !x402.facilitator)
|
|
208
|
+
throw new Error("Decimal seller prices require x402 asset, network, and facilitator configuration.");
|
|
209
|
+
if (!/^\d+(?:\.\d+)?$/.test(value) || Number(value) <= 0)
|
|
210
|
+
throw new Error("Seller price must be a positive decimal string.");
|
|
211
|
+
const decimals = x402.decimals ?? 6;
|
|
212
|
+
const [whole, fraction = ""] = value.split(".");
|
|
213
|
+
if (fraction.length > decimals)
|
|
214
|
+
throw new Error(`Seller price has more than ${decimals} decimal places.`);
|
|
215
|
+
return { amount: BigInt(whole) * 10n ** BigInt(decimals) + BigInt(fraction.padEnd(decimals, "0") || "0"), asset: x402.asset, network: x402.network, decimals };
|
|
216
|
+
}
|
|
217
|
+
function unitsToDecimal(price) {
|
|
218
|
+
const scale = 10n ** BigInt(price.decimals);
|
|
219
|
+
const whole = price.amount / scale;
|
|
220
|
+
const fraction = (price.amount % scale).toString().padStart(price.decimals, "0").replace(/0+$/, "");
|
|
221
|
+
return fraction ? `${whole}.${fraction}` : whole.toString();
|
|
222
|
+
}
|
|
223
|
+
function toFetchRequest(req) {
|
|
224
|
+
const url = new URL(req.originalUrl ?? req.url, `http://${req.headers?.host ?? "localhost"}`);
|
|
225
|
+
const headers = new Headers();
|
|
226
|
+
for (const [key, value] of Object.entries(req.headers ?? {})) {
|
|
227
|
+
if (Array.isArray(value))
|
|
228
|
+
headers.set(key, value.join(", "));
|
|
229
|
+
else if (value !== undefined)
|
|
230
|
+
headers.set(key, String(value));
|
|
231
|
+
}
|
|
232
|
+
const hasBody = !["GET", "HEAD"].includes(String(req.method).toUpperCase());
|
|
233
|
+
return new Request(url, { method: req.method, headers, body: hasBody ? req : undefined });
|
|
234
|
+
}
|
|
235
|
+
async function sendFetchResponse(res, response) {
|
|
236
|
+
res.status(response.status);
|
|
237
|
+
response.headers.forEach((value, key) => res.setHeader(key, value));
|
|
238
|
+
res.send(Buffer.from(await response.arrayBuffer()));
|
|
239
|
+
}
|
|
240
|
+
function toFetchResponse(result) {
|
|
241
|
+
if (result instanceof Response)
|
|
242
|
+
return result;
|
|
243
|
+
if (result && typeof result === "object" && "body" in result) {
|
|
244
|
+
const value = result;
|
|
245
|
+
return Response.json(value.body, { status: value.status ?? 200, headers: value.headers });
|
|
246
|
+
}
|
|
247
|
+
return Response.json(result);
|
|
248
|
+
}
|
|
249
|
+
//# sourceMappingURL=seller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seller.js","sourceRoot":"","sources":["../src/seller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export type StripeMppPaymentMethod = "card" | "crypto";
|
|
2
|
+
export interface StripeMppConnectConfig {
|
|
3
|
+
/** Connected account that should receive a direct charge. */
|
|
4
|
+
stripeAccount: string;
|
|
5
|
+
applicationFeeAmount?: number;
|
|
6
|
+
onBehalfOf?: string;
|
|
7
|
+
transferData?: {
|
|
8
|
+
amount?: number;
|
|
9
|
+
destination: string;
|
|
10
|
+
};
|
|
11
|
+
transferGroup?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface StripeMppPaywallOptions {
|
|
14
|
+
/** Stripe sandbox/live secret key. Never expose this to an agent or browser. */
|
|
15
|
+
stripeSecretKey: string;
|
|
16
|
+
/** Stripe business profile ID (`profile_test_...` in a sandbox). */
|
|
17
|
+
profileId: string;
|
|
18
|
+
/** HMAC key used to bind a credential to the challenge. */
|
|
19
|
+
mppSecretKey: string;
|
|
20
|
+
/** Price in the configured currency, for example `0.50`. */
|
|
21
|
+
amount: string | ((request: Request) => string | Promise<string>);
|
|
22
|
+
currency?: string;
|
|
23
|
+
decimals?: number;
|
|
24
|
+
description?: string;
|
|
25
|
+
paymentMethodTypes?: string[];
|
|
26
|
+
/** Optional Stripe Connect settlement policy for this seller. */
|
|
27
|
+
connect?: StripeMppConnectConfig;
|
|
28
|
+
/** Tempo deposit address enables stablecoin MPP alongside card SPTs. */
|
|
29
|
+
depositAddresses?: {
|
|
30
|
+
tempo?: string;
|
|
31
|
+
base?: string;
|
|
32
|
+
solana?: string;
|
|
33
|
+
};
|
|
34
|
+
/** Optional Stripe SDK client. Supply this with depositAddresses to enable stablecoin rails. */
|
|
35
|
+
stripeClient?: unknown;
|
|
36
|
+
realm?: string;
|
|
37
|
+
metadata?: Record<string, string>;
|
|
38
|
+
}
|
|
39
|
+
export type StripeMppPaymentResult = {
|
|
40
|
+
status: 402;
|
|
41
|
+
response: Response;
|
|
42
|
+
} | {
|
|
43
|
+
status: 200;
|
|
44
|
+
response: Response;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Create a Stripe MPP paywall for a Fetch-compatible server.
|
|
48
|
+
*
|
|
49
|
+
* The returned handler issues a 402 challenge when the agent has not paid and
|
|
50
|
+
* verifies/settles the MPP credential before calling the resource function.
|
|
51
|
+
* Stripe credentials stay inside the SDK and are never included in a challenge.
|
|
52
|
+
*/
|
|
53
|
+
export declare function createStripeMppPaywall(options: StripeMppPaywallOptions): Promise<{
|
|
54
|
+
/** Run the payment check and return the raw 402/200 response. */
|
|
55
|
+
charge: (request: Request) => Promise<StripeMppPaymentResult>;
|
|
56
|
+
/** Run the payment check, then serve the resource only after settlement. */
|
|
57
|
+
handle(request: Request, fulfill: () => Response | Promise<Response>): Promise<Response>;
|
|
58
|
+
}>;
|
|
59
|
+
//# sourceMappingURL=stripe-mpp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stripe-mpp.d.ts","sourceRoot":"","sources":["../src/stripe-mpp.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEvD,MAAM,WAAW,sBAAsB;IACrC,6DAA6D;IAC7D,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,uBAAuB;IACtC,gFAAgF;IAChF,eAAe,EAAE,MAAM,CAAC;IACxB,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,YAAY,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,iEAAiE;IACjE,OAAO,CAAC,EAAE,sBAAsB,CAAC;IACjC,wEAAwE;IACxE,gBAAgB,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE,gGAAgG;IAChG,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,MAAM,MAAM,sBAAsB,GAC9B;IAAE,MAAM,EAAE,GAAG,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GACnC;IAAE,MAAM,EAAE,GAAG,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAAC;AAiBxC;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,uBAAuB;IAqCzE,iEAAiE;sBAjBnC,OAAO,KAAG,OAAO,CAAC,sBAAsB,CAAC;IAmBvE,4EAA4E;oBACtD,OAAO,WAAW,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC;GAejG"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
async function loadMppx() {
|
|
2
|
+
try {
|
|
3
|
+
// Keep mppx optional so existing x402-only SDK users do not download or
|
|
4
|
+
// initialize Stripe's MPP runtime until they opt into this adapter.
|
|
5
|
+
const dynamicImport = new Function("specifier", "return import(specifier)");
|
|
6
|
+
return await dynamicImport("mppx/server");
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
throw new Error("Stripe MPP requires the optional mppx dependency. Install it with `npm install mppx`.");
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Create a Stripe MPP paywall for a Fetch-compatible server.
|
|
14
|
+
*
|
|
15
|
+
* The returned handler issues a 402 challenge when the agent has not paid and
|
|
16
|
+
* verifies/settles the MPP credential before calling the resource function.
|
|
17
|
+
* Stripe credentials stay inside the SDK and are never included in a challenge.
|
|
18
|
+
*/
|
|
19
|
+
export async function createStripeMppPaywall(options) {
|
|
20
|
+
if (!options.stripeSecretKey.trim())
|
|
21
|
+
throw new Error("Stripe MPP requires stripeSecretKey.");
|
|
22
|
+
if (!options.profileId.trim())
|
|
23
|
+
throw new Error("Stripe MPP requires a Stripe profileId.");
|
|
24
|
+
if (options.mppSecretKey.length < 32)
|
|
25
|
+
throw new Error("Stripe MPP mppSecretKey must be at least 32 characters.");
|
|
26
|
+
const { Mppx, stripe } = await loadMppx();
|
|
27
|
+
const methods = options.stripeClient && !options.connect
|
|
28
|
+
? await stripe.create({
|
|
29
|
+
client: options.stripeClient,
|
|
30
|
+
networkId: options.profileId,
|
|
31
|
+
livemode: !options.stripeSecretKey.includes("_test_"),
|
|
32
|
+
...(options.depositAddresses ? { depositAddresses: options.depositAddresses } : {}),
|
|
33
|
+
}).defaultMethods()
|
|
34
|
+
: [stripe.charge({
|
|
35
|
+
...(options.stripeClient ? { client: options.stripeClient } : { secretKey: options.stripeSecretKey }),
|
|
36
|
+
networkId: options.profileId,
|
|
37
|
+
paymentMethodTypes: options.paymentMethodTypes ?? ["card"],
|
|
38
|
+
...(options.connect ? { connect: options.connect } : {}),
|
|
39
|
+
})];
|
|
40
|
+
const mppx = Mppx.create({ methods, secretKey: options.mppSecretKey, ...(options.realm ? { realm: options.realm } : {}) });
|
|
41
|
+
const handler = async (request) => {
|
|
42
|
+
const amount = typeof options.amount === "function" ? await options.amount(request) : options.amount;
|
|
43
|
+
if (!/^\d+(?:\.\d+)?$/.test(amount) || Number(amount) <= 0)
|
|
44
|
+
throw new Error("Stripe MPP amount must be a positive decimal string.");
|
|
45
|
+
const chargeOptions = {
|
|
46
|
+
amount,
|
|
47
|
+
currency: options.currency ?? "usd",
|
|
48
|
+
decimals: options.decimals ?? 2,
|
|
49
|
+
...(options.description ? { description: options.description } : {}),
|
|
50
|
+
paymentMethodTypes: options.paymentMethodTypes ?? ["card"],
|
|
51
|
+
...(options.metadata ? { metadata: options.metadata } : {}),
|
|
52
|
+
};
|
|
53
|
+
const result = await mppx.stripe.charge(chargeOptions)(request);
|
|
54
|
+
if (result.status === 402)
|
|
55
|
+
return { status: 402, response: result.challenge };
|
|
56
|
+
return { status: 200, response: result.withReceipt(new Response(null, { status: 204 })) };
|
|
57
|
+
};
|
|
58
|
+
return {
|
|
59
|
+
/** Run the payment check and return the raw 402/200 response. */
|
|
60
|
+
charge: handler,
|
|
61
|
+
/** Run the payment check, then serve the resource only after settlement. */
|
|
62
|
+
async handle(request, fulfill) {
|
|
63
|
+
const amount = typeof options.amount === "function" ? await options.amount(request) : options.amount;
|
|
64
|
+
const chargeOptions = {
|
|
65
|
+
amount,
|
|
66
|
+
currency: options.currency ?? "usd",
|
|
67
|
+
decimals: options.decimals ?? 2,
|
|
68
|
+
...(options.description ? { description: options.description } : {}),
|
|
69
|
+
paymentMethodTypes: options.paymentMethodTypes ?? ["card"],
|
|
70
|
+
...(options.metadata ? { metadata: options.metadata } : {}),
|
|
71
|
+
};
|
|
72
|
+
const result = await mppx.stripe.charge(chargeOptions)(request);
|
|
73
|
+
if (result.status === 402)
|
|
74
|
+
return result.challenge;
|
|
75
|
+
return result.withReceipt(await fulfill());
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=stripe-mpp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stripe-mpp.js","sourceRoot":"","sources":["../src/stripe-mpp.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seedhape/x402-merchant-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Add x402 payment-gated routes, settlement receipts, and merchant accounting to Node.js services.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"license": "MIT",
|
|
30
30
|
"repository": {
|
|
31
31
|
"type": "git",
|
|
32
|
-
"url": "https://github.com/seedhape/seedhape.git",
|
|
32
|
+
"url": "git+https://github.com/seedhape/seedhape.git",
|
|
33
33
|
"directory": "packages/merchant-sdk"
|
|
34
34
|
},
|
|
35
35
|
"bugs": {
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
+
"@seedhape/core": "0.1.0",
|
|
42
43
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
43
44
|
"@solana/kit": "^5.5.1",
|
|
44
45
|
"@x402/core": "2.23.0",
|
|
@@ -50,9 +51,13 @@
|
|
|
50
51
|
"zod": "^3.25.76"
|
|
51
52
|
},
|
|
52
53
|
"peerDependencies": {
|
|
54
|
+
"mppx": "^0.10.1",
|
|
53
55
|
"@x402/paywall": "^2.23.0"
|
|
54
56
|
},
|
|
55
57
|
"peerDependenciesMeta": {
|
|
58
|
+
"mppx": {
|
|
59
|
+
"optional": true
|
|
60
|
+
},
|
|
56
61
|
"@x402/paywall": {
|
|
57
62
|
"optional": true
|
|
58
63
|
}
|