mppx 0.6.28 → 0.6.30
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/CHANGELOG.md +23 -0
- package/dist/Challenge.d.ts.map +1 -1
- package/dist/Challenge.js +16 -10
- package/dist/Challenge.js.map +1 -1
- package/dist/Method.d.ts +1 -1
- package/dist/Method.d.ts.map +1 -1
- package/dist/client/Methods.d.ts +1 -0
- package/dist/client/Methods.d.ts.map +1 -1
- package/dist/client/Methods.js +1 -0
- package/dist/client/Methods.js.map +1 -1
- package/dist/client/Mppx.d.ts +3 -3
- package/dist/client/Mppx.d.ts.map +1 -1
- package/dist/client/Mppx.js +1 -0
- package/dist/client/Mppx.js.map +1 -1
- package/dist/client/Transport.d.ts +10 -3
- package/dist/client/Transport.d.ts.map +1 -1
- package/dist/client/Transport.js +60 -7
- package/dist/client/Transport.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal/Fetch.d.ts +3 -0
- package/dist/client/internal/Fetch.d.ts.map +1 -1
- package/dist/client/internal/Fetch.js +12 -20
- package/dist/client/internal/Fetch.js.map +1 -1
- package/dist/evm/Assets.d.ts +2 -0
- package/dist/evm/Assets.d.ts.map +1 -0
- package/dist/evm/Assets.js +2 -0
- package/dist/evm/Assets.js.map +1 -0
- package/dist/evm/Chains.d.ts +5 -0
- package/dist/evm/Chains.d.ts.map +1 -0
- package/dist/evm/Chains.js +5 -0
- package/dist/evm/Chains.js.map +1 -0
- package/dist/evm/Methods.d.ts +68 -0
- package/dist/evm/Methods.d.ts.map +1 -0
- package/dist/evm/Methods.js +28 -0
- package/dist/evm/Methods.js.map +1 -0
- package/dist/evm/Types.d.ts +143 -0
- package/dist/evm/Types.d.ts.map +1 -0
- package/dist/evm/Types.js +102 -0
- package/dist/evm/Types.js.map +1 -0
- package/dist/evm/client/Charge.d.ts +102 -0
- package/dist/evm/client/Charge.d.ts.map +1 -0
- package/dist/evm/client/Charge.js +141 -0
- package/dist/evm/client/Charge.js.map +1 -0
- package/dist/evm/client/Methods.d.ts +81 -0
- package/dist/evm/client/Methods.d.ts.map +1 -0
- package/dist/evm/client/Methods.js +16 -0
- package/dist/evm/client/Methods.js.map +1 -0
- package/dist/evm/client/index.d.ts +6 -0
- package/dist/evm/client/index.d.ts.map +1 -0
- package/dist/evm/client/index.js +6 -0
- package/dist/evm/client/index.js.map +1 -0
- package/dist/evm/index.d.ts +10 -0
- package/dist/evm/index.d.ts.map +1 -0
- package/dist/evm/index.js +9 -0
- package/dist/evm/index.js.map +1 -0
- package/dist/evm/server/Charge.d.ts +62 -0
- package/dist/evm/server/Charge.d.ts.map +1 -0
- package/dist/evm/server/Charge.js +172 -0
- package/dist/evm/server/Charge.js.map +1 -0
- package/dist/evm/server/Methods.d.ts +80 -0
- package/dist/evm/server/Methods.d.ts.map +1 -0
- package/dist/evm/server/Methods.js +16 -0
- package/dist/evm/server/Methods.js.map +1 -0
- package/dist/evm/server/index.d.ts +6 -0
- package/dist/evm/server/index.d.ts.map +1 -0
- package/dist/evm/server/index.js +6 -0
- package/dist/evm/server/index.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/HeaderCodec.d.ts +18 -0
- package/dist/internal/HeaderCodec.d.ts.map +1 -0
- package/dist/internal/HeaderCodec.js +31 -0
- package/dist/internal/HeaderCodec.js.map +1 -0
- package/dist/middlewares/elysia.d.ts.map +1 -1
- package/dist/middlewares/elysia.js +2 -3
- package/dist/middlewares/elysia.js.map +1 -1
- package/dist/middlewares/express.js +2 -1
- package/dist/middlewares/express.js.map +1 -1
- package/dist/proxy/internal/Headers.d.ts.map +1 -1
- package/dist/proxy/internal/Headers.js +11 -1
- package/dist/proxy/internal/Headers.js.map +1 -1
- package/dist/proxy/services/openai.d.ts.map +1 -1
- package/dist/proxy/services/openai.js +2 -0
- package/dist/proxy/services/openai.js.map +1 -1
- package/dist/server/Methods.d.ts +1 -0
- package/dist/server/Methods.d.ts.map +1 -1
- package/dist/server/Methods.js +1 -0
- package/dist/server/Methods.js.map +1 -1
- package/dist/server/Mppx.d.ts.map +1 -1
- package/dist/server/Mppx.js +90 -12
- package/dist/server/Mppx.js.map +1 -1
- package/dist/server/Transport.d.ts +10 -0
- package/dist/server/Transport.d.ts.map +1 -1
- package/dist/server/Transport.js +9 -0
- package/dist/server/Transport.js.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/stripe/server/internal/html.gen.d.ts +1 -1
- package/dist/stripe/server/internal/html.gen.d.ts.map +1 -1
- package/dist/stripe/server/internal/html.gen.js +1 -1
- package/dist/stripe/server/internal/html.gen.js.map +1 -1
- package/dist/tempo/client/ChannelOps.d.ts +3 -3
- package/dist/tempo/client/ChannelOps.d.ts.map +1 -1
- package/dist/tempo/client/ChannelOps.js +13 -6
- package/dist/tempo/client/ChannelOps.js.map +1 -1
- package/dist/tempo/client/Charge.d.ts.map +1 -1
- package/dist/tempo/client/Charge.js +8 -5
- package/dist/tempo/client/Charge.js.map +1 -1
- package/dist/tempo/client/Methods.d.ts +0 -1
- package/dist/tempo/client/Methods.d.ts.map +1 -1
- package/dist/tempo/client/Session.d.ts +2 -4
- package/dist/tempo/client/Session.d.ts.map +1 -1
- package/dist/tempo/client/Session.js +10 -12
- package/dist/tempo/client/Session.js.map +1 -1
- package/dist/tempo/client/SessionManager.d.ts +3 -3
- package/dist/tempo/client/SessionManager.d.ts.map +1 -1
- package/dist/tempo/client/SessionManager.js +1 -1
- package/dist/tempo/client/SessionManager.js.map +1 -1
- package/dist/tempo/internal/account.d.ts +5 -0
- package/dist/tempo/internal/account.d.ts.map +1 -1
- package/dist/tempo/internal/account.js +8 -0
- package/dist/tempo/internal/account.js.map +1 -1
- package/dist/tempo/internal/fee-payer.d.ts.map +1 -1
- package/dist/tempo/internal/fee-payer.js +5 -2
- package/dist/tempo/internal/fee-payer.js.map +1 -1
- package/dist/tempo/server/Charge.d.ts.map +1 -1
- package/dist/tempo/server/Charge.js +23 -1
- package/dist/tempo/server/Charge.js.map +1 -1
- package/dist/tempo/server/Session.d.ts.map +1 -1
- package/dist/tempo/server/Session.js +13 -12
- package/dist/tempo/server/Session.js.map +1 -1
- package/dist/tempo/server/internal/html.gen.d.ts +1 -1
- package/dist/tempo/server/internal/html.gen.d.ts.map +1 -1
- package/dist/tempo/server/internal/html.gen.js +1 -1
- package/dist/tempo/server/internal/html.gen.js.map +1 -1
- package/dist/tempo/session/Chain.d.ts +2 -0
- package/dist/tempo/session/Chain.d.ts.map +1 -1
- package/dist/tempo/session/Chain.js +8 -8
- package/dist/tempo/session/Chain.js.map +1 -1
- package/dist/tempo/session/Voucher.d.ts +4 -3
- package/dist/tempo/session/Voucher.d.ts.map +1 -1
- package/dist/tempo/session/Voucher.js +71 -44
- package/dist/tempo/session/Voucher.js.map +1 -1
- package/dist/tempo/session/Ws.d.ts.map +1 -1
- package/dist/tempo/session/Ws.js +15 -0
- package/dist/tempo/session/Ws.js.map +1 -1
- package/dist/tempo/subscription/KeyAuthorization.d.ts +2 -2
- package/dist/x402/Assets.d.ts +29 -0
- package/dist/x402/Assets.d.ts.map +1 -0
- package/dist/x402/Assets.js +46 -0
- package/dist/x402/Assets.js.map +1 -0
- package/dist/x402/Header.d.ts +14 -0
- package/dist/x402/Header.d.ts.map +1 -0
- package/dist/x402/Header.js +18 -0
- package/dist/x402/Header.js.map +1 -0
- package/dist/x402/Types.d.ts +289 -0
- package/dist/x402/Types.d.ts.map +1 -0
- package/dist/x402/Types.js +139 -0
- package/dist/x402/Types.js.map +1 -0
- package/dist/x402/client/Exact.d.ts +38 -0
- package/dist/x402/client/Exact.d.ts.map +1 -0
- package/dist/x402/client/Exact.js +141 -0
- package/dist/x402/client/Exact.js.map +1 -0
- package/dist/x402/index.d.ts +6 -0
- package/dist/x402/index.d.ts.map +1 -0
- package/dist/x402/index.js +6 -0
- package/dist/x402/index.js.map +1 -0
- package/dist/x402/internal/ChallengeBrand.d.ts +5 -0
- package/dist/x402/internal/ChallengeBrand.d.ts.map +1 -0
- package/dist/x402/internal/ChallengeBrand.js +13 -0
- package/dist/x402/internal/ChallengeBrand.js.map +1 -0
- package/dist/x402/internal/RouteBinding.d.ts +8 -0
- package/dist/x402/internal/RouteBinding.d.ts.map +1 -0
- package/dist/x402/internal/RouteBinding.js +12 -0
- package/dist/x402/internal/RouteBinding.js.map +1 -0
- package/dist/x402/server/EvmCharge.d.ts +50 -0
- package/dist/x402/server/EvmCharge.d.ts.map +1 -0
- package/dist/x402/server/EvmCharge.js +301 -0
- package/dist/x402/server/EvmCharge.js.map +1 -0
- package/dist/x402/server/Facilitator.d.ts +12 -0
- package/dist/x402/server/Facilitator.d.ts.map +1 -0
- package/dist/x402/server/Facilitator.js +42 -0
- package/dist/x402/server/Facilitator.js.map +1 -0
- package/package.json +41 -21
- package/src/Challenge.test.ts +54 -0
- package/src/Challenge.ts +17 -10
- package/src/Method.ts +1 -1
- package/src/client/Methods.ts +1 -0
- package/src/client/Mppx.ts +4 -3
- package/src/client/Transport.test.ts +165 -30
- package/src/client/Transport.ts +76 -8
- package/src/client/index.ts +1 -1
- package/src/client/internal/Fetch.test.ts +31 -2
- package/src/client/internal/Fetch.ts +26 -19
- package/src/evm/Assets.ts +1 -0
- package/src/evm/Chains.ts +5 -0
- package/src/evm/Methods.ts +44 -0
- package/src/evm/PublicInterface.test-d.ts +114 -0
- package/src/evm/Types.ts +140 -0
- package/src/evm/client/Charge.test.ts +99 -0
- package/src/evm/client/Charge.ts +198 -0
- package/src/evm/client/Methods.ts +19 -0
- package/src/evm/client/index.ts +5 -0
- package/src/evm/index.ts +14 -0
- package/src/evm/server/Charge.test.ts +199 -0
- package/src/evm/server/Charge.ts +283 -0
- package/src/evm/server/Methods.ts +22 -0
- package/src/evm/server/index.ts +5 -0
- package/src/index.ts +2 -0
- package/src/internal/HeaderCodec.ts +36 -0
- package/src/middlewares/elysia.test.ts +25 -0
- package/src/middlewares/elysia.ts +1 -2
- package/src/middlewares/express.test.ts +28 -0
- package/src/middlewares/express.ts +1 -1
- package/src/middlewares/hono.test.ts +138 -2
- package/src/middlewares/nextjs.test.ts +22 -0
- package/src/proxy/internal/Headers.test.ts +20 -0
- package/src/proxy/internal/Headers.ts +12 -1
- package/src/proxy/services/openai.test.ts +57 -1
- package/src/proxy/services/openai.ts +2 -0
- package/src/server/Methods.ts +1 -0
- package/src/server/Mppx.test.ts +244 -1
- package/src/server/Mppx.ts +124 -11
- package/src/server/NodeListener.test.ts +28 -1
- package/src/server/Transport.test.ts +19 -0
- package/src/server/Transport.ts +20 -0
- package/src/server/index.ts +1 -1
- package/src/stripe/server/internal/html.gen.ts +1 -1
- package/src/tempo/AccessKeyAuthorization.test.ts +231 -0
- package/src/tempo/client/ChannelOps.test.ts +61 -7
- package/src/tempo/client/ChannelOps.ts +18 -7
- package/src/tempo/client/Charge.test.ts +126 -0
- package/src/tempo/client/Charge.ts +10 -6
- package/src/tempo/client/Session.test.ts +130 -1
- package/src/tempo/client/Session.ts +12 -19
- package/src/tempo/client/SessionManager.test.ts +69 -2
- package/src/tempo/client/SessionManager.ts +4 -4
- package/src/tempo/internal/account.ts +13 -0
- package/src/tempo/internal/fee-payer.test.ts +32 -2
- package/src/tempo/internal/fee-payer.ts +6 -2
- package/src/tempo/server/Charge.test.ts +69 -0
- package/src/tempo/server/Charge.ts +32 -0
- package/src/tempo/server/Session.test.ts +30 -0
- package/src/tempo/server/Session.ts +15 -16
- package/src/tempo/server/internal/html.gen.ts +1 -1
- package/src/tempo/session/Chain.test.ts +4 -4
- package/src/tempo/session/Chain.ts +10 -6
- package/src/tempo/session/Voucher.test.ts +230 -1
- package/src/tempo/session/Voucher.ts +96 -48
- package/src/tempo/session/Ws.test.ts +71 -0
- package/src/tempo/session/Ws.ts +13 -0
- package/src/x402/Assets.ts +65 -0
- package/src/x402/Exact.e2e.test.ts +448 -0
- package/src/x402/Header.test.ts +73 -0
- package/src/x402/Header.ts +34 -0
- package/src/x402/PublicInterface.test-d.ts +39 -0
- package/src/x402/Types.ts +248 -0
- package/src/x402/client/Exact.test.ts +180 -0
- package/src/x402/client/Exact.ts +198 -0
- package/src/x402/index.ts +5 -0
- package/src/x402/internal/ChallengeBrand.ts +14 -0
- package/src/x402/internal/RouteBinding.ts +18 -0
- package/src/x402/server/EvmCharge.ts +394 -0
- package/src/x402/server/Facilitator.test.ts +111 -0
- package/src/x402/server/Facilitator.ts +56 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mppx",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.6.
|
|
4
|
+
"version": "0.6.30",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"files": [
|
|
@@ -11,93 +11,113 @@
|
|
|
11
11
|
],
|
|
12
12
|
"exports": {
|
|
13
13
|
".": {
|
|
14
|
-
"types": "./dist/index.d.ts",
|
|
15
14
|
"src": "./src/index.ts",
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
16
|
"default": "./dist/index.js"
|
|
17
17
|
},
|
|
18
18
|
"./cli": {
|
|
19
|
-
"types": "./dist/cli/config.d.ts",
|
|
20
19
|
"src": "./src/cli/config.ts",
|
|
20
|
+
"types": "./dist/cli/config.d.ts",
|
|
21
21
|
"default": "./dist/cli/config.js"
|
|
22
22
|
},
|
|
23
23
|
"./cli/plugins": {
|
|
24
|
-
"types": "./dist/cli/plugins/index.d.ts",
|
|
25
24
|
"src": "./src/cli/plugins/index.ts",
|
|
25
|
+
"types": "./dist/cli/plugins/index.d.ts",
|
|
26
26
|
"default": "./dist/cli/plugins/index.js"
|
|
27
27
|
},
|
|
28
28
|
"./client": {
|
|
29
|
-
"types": "./dist/client/index.d.ts",
|
|
30
29
|
"src": "./src/client/index.ts",
|
|
30
|
+
"types": "./dist/client/index.d.ts",
|
|
31
31
|
"default": "./dist/client/index.js"
|
|
32
32
|
},
|
|
33
33
|
"./discovery": {
|
|
34
|
-
"types": "./dist/discovery/index.d.ts",
|
|
35
34
|
"src": "./src/discovery/index.ts",
|
|
35
|
+
"types": "./dist/discovery/index.d.ts",
|
|
36
36
|
"default": "./dist/discovery/index.js"
|
|
37
37
|
},
|
|
38
|
+
"./evm": {
|
|
39
|
+
"src": "./src/evm/index.ts",
|
|
40
|
+
"types": "./dist/evm/index.d.ts",
|
|
41
|
+
"default": "./dist/evm/index.js"
|
|
42
|
+
},
|
|
43
|
+
"./evm/client": {
|
|
44
|
+
"src": "./src/evm/client/index.ts",
|
|
45
|
+
"types": "./dist/evm/client/index.d.ts",
|
|
46
|
+
"default": "./dist/evm/client/index.js"
|
|
47
|
+
},
|
|
48
|
+
"./evm/server": {
|
|
49
|
+
"src": "./src/evm/server/index.ts",
|
|
50
|
+
"types": "./dist/evm/server/index.d.ts",
|
|
51
|
+
"default": "./dist/evm/server/index.js"
|
|
52
|
+
},
|
|
38
53
|
"./mcp-sdk/client": {
|
|
39
|
-
"types": "./dist/mcp-sdk/client/index.d.ts",
|
|
40
54
|
"src": "./src/mcp-sdk/client/index.ts",
|
|
55
|
+
"types": "./dist/mcp-sdk/client/index.d.ts",
|
|
41
56
|
"default": "./dist/mcp-sdk/client/index.js"
|
|
42
57
|
},
|
|
43
58
|
"./mcp-sdk/server": {
|
|
44
|
-
"types": "./dist/mcp-sdk/server/index.d.ts",
|
|
45
59
|
"src": "./src/mcp-sdk/server/index.ts",
|
|
60
|
+
"types": "./dist/mcp-sdk/server/index.d.ts",
|
|
46
61
|
"default": "./dist/mcp-sdk/server/index.js"
|
|
47
62
|
},
|
|
48
63
|
"./proxy": {
|
|
49
|
-
"types": "./dist/proxy/index.d.ts",
|
|
50
64
|
"src": "./src/proxy/index.ts",
|
|
65
|
+
"types": "./dist/proxy/index.d.ts",
|
|
51
66
|
"default": "./dist/proxy/index.js"
|
|
52
67
|
},
|
|
53
68
|
"./server": {
|
|
54
|
-
"types": "./dist/server/index.d.ts",
|
|
55
69
|
"src": "./src/server/index.ts",
|
|
70
|
+
"types": "./dist/server/index.d.ts",
|
|
56
71
|
"default": "./dist/server/index.js"
|
|
57
72
|
},
|
|
58
73
|
"./stripe": {
|
|
59
|
-
"types": "./dist/stripe/index.d.ts",
|
|
60
74
|
"src": "./src/stripe/index.ts",
|
|
75
|
+
"types": "./dist/stripe/index.d.ts",
|
|
61
76
|
"default": "./dist/stripe/index.js"
|
|
62
77
|
},
|
|
63
78
|
"./stripe/client": {
|
|
64
|
-
"types": "./dist/stripe/client/index.d.ts",
|
|
65
79
|
"src": "./src/stripe/client/index.ts",
|
|
80
|
+
"types": "./dist/stripe/client/index.d.ts",
|
|
66
81
|
"default": "./dist/stripe/client/index.js"
|
|
67
82
|
},
|
|
68
83
|
"./stripe/server": {
|
|
69
|
-
"types": "./dist/stripe/server/index.d.ts",
|
|
70
84
|
"src": "./src/stripe/server/index.ts",
|
|
85
|
+
"types": "./dist/stripe/server/index.d.ts",
|
|
71
86
|
"default": "./dist/stripe/server/index.js"
|
|
72
87
|
},
|
|
88
|
+
"./x402": {
|
|
89
|
+
"src": "./src/x402/index.ts",
|
|
90
|
+
"types": "./dist/x402/index.d.ts",
|
|
91
|
+
"default": "./dist/x402/index.js"
|
|
92
|
+
},
|
|
73
93
|
"./tempo": {
|
|
74
|
-
"types": "./dist/tempo/index.d.ts",
|
|
75
94
|
"src": "./src/tempo/index.ts",
|
|
95
|
+
"types": "./dist/tempo/index.d.ts",
|
|
76
96
|
"default": "./dist/tempo/index.js"
|
|
77
97
|
},
|
|
78
98
|
"./html": {
|
|
79
|
-
"types": "./dist/Html.d.ts",
|
|
80
99
|
"src": "./src/Html.ts",
|
|
100
|
+
"types": "./dist/Html.d.ts",
|
|
81
101
|
"default": "./dist/Html.js"
|
|
82
102
|
},
|
|
83
103
|
"./hono": {
|
|
84
|
-
"types": "./dist/middlewares/hono.d.ts",
|
|
85
104
|
"src": "./src/middlewares/hono.ts",
|
|
105
|
+
"types": "./dist/middlewares/hono.d.ts",
|
|
86
106
|
"default": "./dist/middlewares/hono.js"
|
|
87
107
|
},
|
|
88
108
|
"./express": {
|
|
89
|
-
"types": "./dist/middlewares/express.d.ts",
|
|
90
109
|
"src": "./src/middlewares/express.ts",
|
|
110
|
+
"types": "./dist/middlewares/express.d.ts",
|
|
91
111
|
"default": "./dist/middlewares/express.js"
|
|
92
112
|
},
|
|
93
113
|
"./nextjs": {
|
|
94
|
-
"types": "./dist/middlewares/nextjs.d.ts",
|
|
95
114
|
"src": "./src/middlewares/nextjs.ts",
|
|
115
|
+
"types": "./dist/middlewares/nextjs.d.ts",
|
|
96
116
|
"default": "./dist/middlewares/nextjs.js"
|
|
97
117
|
},
|
|
98
118
|
"./elysia": {
|
|
99
|
-
"types": "./dist/middlewares/elysia.d.ts",
|
|
100
119
|
"src": "./src/middlewares/elysia.ts",
|
|
120
|
+
"types": "./dist/middlewares/elysia.d.ts",
|
|
101
121
|
"default": "./dist/middlewares/elysia.js"
|
|
102
122
|
}
|
|
103
123
|
},
|
|
@@ -106,7 +126,7 @@
|
|
|
106
126
|
"elysia": ">=1",
|
|
107
127
|
"express": ">=5",
|
|
108
128
|
"hono": ">=4.12.18",
|
|
109
|
-
"viem": ">=2.
|
|
129
|
+
"viem": ">=2.51.0"
|
|
110
130
|
},
|
|
111
131
|
"peerDependenciesMeta": {
|
|
112
132
|
"@modelcontextprotocol/sdk": {
|
|
@@ -124,7 +144,7 @@
|
|
|
124
144
|
},
|
|
125
145
|
"dependencies": {
|
|
126
146
|
"incur": "^0.4.5",
|
|
127
|
-
"ox": "0.14.
|
|
147
|
+
"ox": "0.14.24",
|
|
128
148
|
"zod": "^4.4.3"
|
|
129
149
|
},
|
|
130
150
|
"repository": {
|
package/src/Challenge.test.ts
CHANGED
|
@@ -453,6 +453,60 @@ describe('serialize', () => {
|
|
|
453
453
|
expect(header).toContain('digest="sha-256=abc"')
|
|
454
454
|
expect(header).toContain('expires="2025-01-06T12:00:00Z"')
|
|
455
455
|
})
|
|
456
|
+
|
|
457
|
+
test.each([
|
|
458
|
+
{
|
|
459
|
+
description: 'Plain payment description',
|
|
460
|
+
escaped: 'Plain payment description',
|
|
461
|
+
label: 'plain values',
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
description: 'Pay "premium"',
|
|
465
|
+
escaped: 'Pay \\"premium\\"',
|
|
466
|
+
label: 'double quotes',
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
description: 'Path C:\\tempo\\api',
|
|
470
|
+
escaped: 'Path C:\\\\tempo\\\\api',
|
|
471
|
+
label: 'backslashes',
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
description: 'Pay "premium" path C:\\tempo\\api',
|
|
475
|
+
escaped: 'Pay \\"premium\\" path C:\\\\tempo\\\\api',
|
|
476
|
+
label: 'mixed quotes and backslashes',
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
description: 'Ends with slash \\',
|
|
480
|
+
escaped: 'Ends with slash \\\\',
|
|
481
|
+
label: 'trailing backslash',
|
|
482
|
+
},
|
|
483
|
+
])('behavior: escapes quoted-string values: $label', ({ description, escaped }) => {
|
|
484
|
+
const challenge = Challenge.from({
|
|
485
|
+
id: 'abc123',
|
|
486
|
+
realm: 'api.example.com',
|
|
487
|
+
method: 'tempo',
|
|
488
|
+
intent: 'charge',
|
|
489
|
+
request: { amount: '1000000' },
|
|
490
|
+
description,
|
|
491
|
+
})
|
|
492
|
+
|
|
493
|
+
const header = Challenge.serialize(challenge)
|
|
494
|
+
expect(header).toContain(`description="${escaped}"`)
|
|
495
|
+
expect(Challenge.deserialize(header).description).toBe(description)
|
|
496
|
+
})
|
|
497
|
+
|
|
498
|
+
test('error: rejects CRLF in quoted-string values', () => {
|
|
499
|
+
const challenge = Challenge.from({
|
|
500
|
+
id: 'abc123',
|
|
501
|
+
realm: 'api.example.com',
|
|
502
|
+
method: 'tempo',
|
|
503
|
+
intent: 'charge',
|
|
504
|
+
request: { amount: '1000000' },
|
|
505
|
+
description: 'Line one\r\nLine two',
|
|
506
|
+
})
|
|
507
|
+
|
|
508
|
+
expect(() => Challenge.serialize(challenge)).toThrow('Invalid quoted-string value.')
|
|
509
|
+
})
|
|
456
510
|
})
|
|
457
511
|
|
|
458
512
|
describe('deserialize', () => {
|
package/src/Challenge.ts
CHANGED
|
@@ -294,23 +294,30 @@ export declare namespace fromMethod {
|
|
|
294
294
|
*/
|
|
295
295
|
export function serialize(challenge: Challenge): string {
|
|
296
296
|
const parts = [
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
297
|
+
authParam('id', challenge.id),
|
|
298
|
+
authParam('realm', challenge.realm),
|
|
299
|
+
authParam('method', challenge.method),
|
|
300
|
+
authParam('intent', challenge.intent),
|
|
301
|
+
authParam('request', PaymentRequest.serialize(challenge.request)),
|
|
302
302
|
]
|
|
303
303
|
|
|
304
|
-
if (challenge.description !== undefined)
|
|
305
|
-
|
|
306
|
-
if (challenge.
|
|
307
|
-
if (challenge.
|
|
304
|
+
if (challenge.description !== undefined)
|
|
305
|
+
parts.push(authParam('description', challenge.description))
|
|
306
|
+
if (challenge.digest !== undefined) parts.push(authParam('digest', challenge.digest))
|
|
307
|
+
if (challenge.expires !== undefined) parts.push(authParam('expires', challenge.expires))
|
|
308
|
+
if (challenge.opaque !== undefined) parts.push(authParam('opaque', challenge.opaque))
|
|
308
309
|
else if (challenge.meta !== undefined)
|
|
309
|
-
parts.push(
|
|
310
|
+
parts.push(authParam('opaque', PaymentRequest.serialize(challenge.meta)))
|
|
310
311
|
|
|
311
312
|
return `Payment ${parts.join(', ')}`
|
|
312
313
|
}
|
|
313
314
|
|
|
315
|
+
/** @internal */
|
|
316
|
+
function authParam(name: string, value: string): string {
|
|
317
|
+
if (/[\r\n]/.test(value)) throw new Error('Invalid quoted-string value.')
|
|
318
|
+
return `${name}="${value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`
|
|
319
|
+
}
|
|
320
|
+
|
|
314
321
|
/**
|
|
315
322
|
* Deserializes a WWW-Authenticate header value to a challenge.
|
|
316
323
|
*
|
package/src/Method.ts
CHANGED
|
@@ -334,7 +334,7 @@ export declare namespace toServer {
|
|
|
334
334
|
request?: RequestFn<method> | undefined
|
|
335
335
|
respond?: RespondFn<method> | undefined
|
|
336
336
|
stableBinding?: StableBindingFn<method> | undefined
|
|
337
|
-
transport?: transportOverride | undefined
|
|
337
|
+
transport?: transportOverride | Transport.AnyTransport | undefined
|
|
338
338
|
verify: VerifyFn<method>
|
|
339
339
|
}
|
|
340
340
|
}
|
package/src/client/Methods.ts
CHANGED
package/src/client/Mppx.ts
CHANGED
|
@@ -7,7 +7,7 @@ import * as Fetch from './internal/Fetch.js'
|
|
|
7
7
|
import * as Transport from './Transport.js'
|
|
8
8
|
|
|
9
9
|
export type Methods = readonly (Method.AnyClient | readonly Method.AnyClient[])[]
|
|
10
|
-
type EventResponseOf<transport extends Transport.
|
|
10
|
+
type EventResponseOf<transport extends Transport.AnyTransport> =
|
|
11
11
|
| Response
|
|
12
12
|
| Transport.ResponseOf<transport>
|
|
13
13
|
|
|
@@ -16,7 +16,7 @@ type EventResponseOf<transport extends Transport.Transport> =
|
|
|
16
16
|
*/
|
|
17
17
|
export type Mppx<
|
|
18
18
|
methods extends Methods = Methods,
|
|
19
|
-
transport extends Transport.
|
|
19
|
+
transport extends Transport.AnyTransport = Transport.Transport,
|
|
20
20
|
> = {
|
|
21
21
|
/** Payment-aware fetch function that automatically handles 402 responses. */
|
|
22
22
|
fetch: Fetch.from.Fetch<FlattenMethods<methods>>
|
|
@@ -125,6 +125,7 @@ export function create<
|
|
|
125
125
|
...(resolvedOnChallenge && { onChallenge: resolvedOnChallenge }),
|
|
126
126
|
...(orderChallenges && { orderChallenges }),
|
|
127
127
|
methods,
|
|
128
|
+
transport,
|
|
128
129
|
} satisfies Fetch.from.Config<FlattenMethods<methods>>
|
|
129
130
|
const fetch = Fetch.from<FlattenMethods<methods>>(config_fetch)
|
|
130
131
|
|
|
@@ -282,7 +283,7 @@ export function restore(): void {
|
|
|
282
283
|
export declare namespace create {
|
|
283
284
|
type Config<
|
|
284
285
|
methods extends Methods = Methods,
|
|
285
|
-
transport extends Transport.
|
|
286
|
+
transport extends Transport.AnyTransport = Transport.Transport,
|
|
286
287
|
> = {
|
|
287
288
|
/** Controls when `Accept-Payment` is injected. */
|
|
288
289
|
acceptPaymentPolicy?: Fetch.from.Config['acceptPaymentPolicy'] | undefined
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Challenge, Credential, Mcp } from 'mppx'
|
|
2
2
|
import { Transport } from 'mppx/client'
|
|
3
3
|
import { Methods } from 'mppx/tempo'
|
|
4
|
+
import { Header as x402_Header, Types as x402_Types, type PaymentRequired } from 'mppx/x402'
|
|
4
5
|
import { describe, expect, test } from 'vp/test'
|
|
5
6
|
|
|
6
7
|
const realm = 'api.example.com'
|
|
@@ -23,27 +24,34 @@ const credential = Credential.from({
|
|
|
23
24
|
payload: { signature: '0xabc123', type: 'transaction' },
|
|
24
25
|
})
|
|
25
26
|
|
|
27
|
+
const x402PaymentRequired = {
|
|
28
|
+
accepts: [
|
|
29
|
+
{
|
|
30
|
+
amount: '10000',
|
|
31
|
+
asset: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',
|
|
32
|
+
maxTimeoutSeconds: 60,
|
|
33
|
+
network: 'eip155:84532',
|
|
34
|
+
payTo: '0x209693Bc6afc0C5328bA36FaF03C514EF312287C',
|
|
35
|
+
scheme: x402_Types.schemes[0],
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
resource: {
|
|
39
|
+
url: 'https://api.example.com/x402',
|
|
40
|
+
},
|
|
41
|
+
x402Version: 2,
|
|
42
|
+
} satisfies PaymentRequired
|
|
43
|
+
|
|
26
44
|
describe('http', () => {
|
|
27
45
|
describe('isPaymentRequired', () => {
|
|
28
|
-
test(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
46
|
+
test.each([
|
|
47
|
+
{ expected: true, status: 402 },
|
|
48
|
+
{ expected: false, status: 200 },
|
|
49
|
+
{ expected: false, status: 401 },
|
|
50
|
+
])('returns $expected for $status response', ({ expected, status }) => {
|
|
51
|
+
const response = new Response(null, { status })
|
|
34
52
|
|
|
35
|
-
test('returns false for 200 response', () => {
|
|
36
53
|
const transport = Transport.http()
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
expect(transport.isPaymentRequired(response)).toBe(false)
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
test('returns false for other error responses', () => {
|
|
43
|
-
const transport = Transport.http()
|
|
44
|
-
const response = new Response(null, { status: 401 })
|
|
45
|
-
|
|
46
|
-
expect(transport.isPaymentRequired(response)).toBe(false)
|
|
54
|
+
expect(transport.isPaymentRequired(response)).toBe(expected)
|
|
47
55
|
})
|
|
48
56
|
})
|
|
49
57
|
|
|
@@ -80,32 +88,159 @@ describe('http', () => {
|
|
|
80
88
|
})
|
|
81
89
|
|
|
82
90
|
describe('getChallenges', () => {
|
|
83
|
-
test(
|
|
91
|
+
test.each([
|
|
92
|
+
{
|
|
93
|
+
expectedIds: [challenge.id, 'alternate'],
|
|
94
|
+
expectedMethods: ['tempo', 'stripe'],
|
|
95
|
+
headers: () => ({
|
|
96
|
+
'WWW-Authenticate': `${Challenge.serialize(challenge)}, ${Challenge.serialize({
|
|
97
|
+
...challenge,
|
|
98
|
+
id: 'alternate',
|
|
99
|
+
method: 'stripe' as const,
|
|
100
|
+
})}`,
|
|
101
|
+
}),
|
|
102
|
+
name: 'Payment auth challenges',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
expectedIds: [`${x402_Types.syntheticChallengeIdPrefix}0`],
|
|
106
|
+
expectedMethods: [x402_Types.paymentMethod],
|
|
107
|
+
headers: () => ({
|
|
108
|
+
'PAYMENT-REQUIRED': x402_Header.encodePaymentRequired(x402PaymentRequired),
|
|
109
|
+
}),
|
|
110
|
+
name: 'x402 challenges',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
expectedIds: [
|
|
114
|
+
`${x402_Types.syntheticChallengeIdPrefix}0`,
|
|
115
|
+
`${x402_Types.syntheticChallengeIdPrefix}1`,
|
|
116
|
+
],
|
|
117
|
+
expectedMethods: [x402_Types.paymentMethod, x402_Types.paymentMethod],
|
|
118
|
+
headers: () => ({
|
|
119
|
+
'PAYMENT-REQUIRED': x402_Header.encodePaymentRequired({
|
|
120
|
+
...x402PaymentRequired,
|
|
121
|
+
accepts: [
|
|
122
|
+
x402PaymentRequired.accepts[0]!,
|
|
123
|
+
{
|
|
124
|
+
...x402PaymentRequired.accepts[0]!,
|
|
125
|
+
amount: '20000',
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
}),
|
|
129
|
+
}),
|
|
130
|
+
name: 'multiple x402 accepts',
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
expectedIds: [challenge.id, `${x402_Types.syntheticChallengeIdPrefix}0`],
|
|
134
|
+
expectedMethods: ['tempo', x402_Types.paymentMethod],
|
|
135
|
+
headers: () => ({
|
|
136
|
+
'PAYMENT-REQUIRED': x402_Header.encodePaymentRequired(x402PaymentRequired),
|
|
137
|
+
'WWW-Authenticate': Challenge.serialize(challenge),
|
|
138
|
+
}),
|
|
139
|
+
name: 'Payment auth and x402 challenges when both are present',
|
|
140
|
+
},
|
|
141
|
+
])('returns $name', ({ expectedIds, expectedMethods, headers }) => {
|
|
84
142
|
const transport = Transport.http()
|
|
85
|
-
const alternate = { ...challenge, id: 'alternate', method: 'stripe' as const }
|
|
86
143
|
const response = new Response(null, {
|
|
87
144
|
status: 402,
|
|
88
|
-
headers:
|
|
89
|
-
'WWW-Authenticate': `${Challenge.serialize(challenge)}, ${Challenge.serialize(alternate)}`,
|
|
90
|
-
},
|
|
145
|
+
headers: headers(),
|
|
91
146
|
})
|
|
147
|
+
const challenges = transport.getChallenges?.(response) ?? []
|
|
92
148
|
|
|
93
|
-
expect(
|
|
94
|
-
|
|
95
|
-
'alternate',
|
|
96
|
-
])
|
|
149
|
+
expect(challenges.map((entry) => entry.id)).toEqual(expectedIds)
|
|
150
|
+
expect(challenges.map((entry) => entry.method)).toEqual(expectedMethods)
|
|
97
151
|
})
|
|
98
152
|
})
|
|
99
153
|
|
|
100
154
|
describe('setCredential', () => {
|
|
101
|
-
test(
|
|
155
|
+
test.each([
|
|
156
|
+
{
|
|
157
|
+
challenge,
|
|
158
|
+
credential: Credential.serialize(credential),
|
|
159
|
+
expectedHeader: 'Authorization',
|
|
160
|
+
expectedValue: Credential.serialize(credential),
|
|
161
|
+
name: 'Payment auth credential for Payment auth challenge',
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
challenge: Transport.http().getChallenges!(
|
|
165
|
+
new Response(null, {
|
|
166
|
+
status: 402,
|
|
167
|
+
headers: {
|
|
168
|
+
'PAYMENT-REQUIRED': x402_Header.encodePaymentRequired(x402PaymentRequired),
|
|
169
|
+
},
|
|
170
|
+
}),
|
|
171
|
+
)[0],
|
|
172
|
+
credential: 'x402-signature',
|
|
173
|
+
expectedHeader: 'PAYMENT-SIGNATURE',
|
|
174
|
+
expectedValue: 'x402-signature',
|
|
175
|
+
name: 'raw x402 credential for x402 challenge',
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
challenge,
|
|
179
|
+
credential: 'custom-credential',
|
|
180
|
+
expectedHeader: 'Authorization',
|
|
181
|
+
expectedValue: 'custom-credential',
|
|
182
|
+
name: 'non-Payment credential for non-x402 challenge',
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
challenge: undefined,
|
|
186
|
+
credential: 'custom-credential',
|
|
187
|
+
expectedHeader: 'Authorization',
|
|
188
|
+
expectedValue: 'custom-credential',
|
|
189
|
+
name: 'credential without selected challenge',
|
|
190
|
+
},
|
|
191
|
+
])('writes $name', ({ challenge, credential, expectedHeader, expectedValue }) => {
|
|
102
192
|
const transport = Transport.http()
|
|
103
|
-
const serialized = Credential.serialize(credential)
|
|
104
193
|
|
|
105
|
-
const result = transport.setCredential({},
|
|
194
|
+
const result = transport.setCredential({}, credential, { challenge })
|
|
195
|
+
const headers = result.headers as Headers
|
|
196
|
+
|
|
197
|
+
expect(headers.get(expectedHeader)).toBe(expectedValue)
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
test('does not treat unbranded Payment-auth challenges as x402', () => {
|
|
201
|
+
const transport = Transport.http()
|
|
202
|
+
const untrustedChallenge = Challenge.from({
|
|
203
|
+
id: `${x402_Types.syntheticChallengeIdPrefix}0`,
|
|
204
|
+
intent: x402_Types.exactIntent,
|
|
205
|
+
method: x402_Types.paymentMethod,
|
|
206
|
+
realm: 'api.example.com',
|
|
207
|
+
request: x402PaymentRequired.accepts[0]!,
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
const result = transport.setCredential({}, 'credential', {
|
|
211
|
+
challenge: untrustedChallenge,
|
|
212
|
+
})
|
|
213
|
+
const headers = result.headers as Headers
|
|
214
|
+
|
|
215
|
+
expect(headers.get('Authorization')).toBe('credential')
|
|
216
|
+
expect(headers.get(x402_Types.paymentSignatureHeader)).toBeNull()
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
test('removes stale credential headers before setting the retry credential', () => {
|
|
220
|
+
const transport = Transport.http()
|
|
221
|
+
const x402Challenge = Transport.http().getChallenges!(
|
|
222
|
+
new Response(null, {
|
|
223
|
+
status: 402,
|
|
224
|
+
headers: {
|
|
225
|
+
'PAYMENT-REQUIRED': x402_Header.encodePaymentRequired(x402PaymentRequired),
|
|
226
|
+
},
|
|
227
|
+
}),
|
|
228
|
+
)[0]
|
|
229
|
+
|
|
230
|
+
const result = transport.setCredential(
|
|
231
|
+
{
|
|
232
|
+
headers: {
|
|
233
|
+
Authorization: 'Payment stale',
|
|
234
|
+
[x402_Types.paymentSignatureHeader]: 'stale-x402',
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
'fresh-x402',
|
|
238
|
+
{ challenge: x402Challenge },
|
|
239
|
+
)
|
|
106
240
|
const headers = result.headers as Headers
|
|
107
241
|
|
|
108
|
-
expect(headers.get('Authorization')).
|
|
242
|
+
expect(headers.get('Authorization')).toBeNull()
|
|
243
|
+
expect(headers.get(x402_Types.paymentSignatureHeader)).toBe('fresh-x402')
|
|
109
244
|
})
|
|
110
245
|
|
|
111
246
|
test('preserves existing headers', () => {
|
package/src/client/Transport.ts
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
import * as Challenge from '../Challenge.js'
|
|
2
2
|
import * as Credential from '../Credential.js'
|
|
3
3
|
import * as Mcp from '../Mcp.js'
|
|
4
|
+
import * as x402_Header from '../x402/Header.js'
|
|
5
|
+
import * as x402_ChallengeBrand from '../x402/internal/ChallengeBrand.js'
|
|
6
|
+
import * as x402_Types from '../x402/Types.js'
|
|
7
|
+
|
|
8
|
+
const paymentRequiredStatus = 402
|
|
9
|
+
const paymentAuthChallengeHeader = 'WWW-Authenticate'
|
|
10
|
+
const paymentAuthCredentialHeader = 'Authorization'
|
|
11
|
+
const credentialHeaders = [
|
|
12
|
+
paymentAuthCredentialHeader,
|
|
13
|
+
x402_Types.paymentRequiredHeader,
|
|
14
|
+
x402_Types.paymentResponseHeader,
|
|
15
|
+
x402_Types.paymentSignatureHeader,
|
|
16
|
+
]
|
|
4
17
|
|
|
5
18
|
/**
|
|
6
19
|
* Client-side transport adapter.
|
|
@@ -18,10 +31,21 @@ export type Transport<in out request = unknown, in out response = unknown> = {
|
|
|
18
31
|
/** Extracts the challenge from a payment-required response. */
|
|
19
32
|
getChallenge: (response: response) => Challenge.Challenge
|
|
20
33
|
/** Attaches a credential to a request. */
|
|
21
|
-
setCredential: (
|
|
34
|
+
setCredential: (
|
|
35
|
+
request: request,
|
|
36
|
+
credential: string,
|
|
37
|
+
options?: setCredential.Options | undefined,
|
|
38
|
+
) => request
|
|
22
39
|
}
|
|
23
40
|
export type AnyTransport = Transport<any, any>
|
|
24
41
|
|
|
42
|
+
export declare namespace setCredential {
|
|
43
|
+
type Options = {
|
|
44
|
+
/** Challenge selected for credential creation. */
|
|
45
|
+
challenge?: Challenge.Challenge | undefined
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
25
49
|
/** Extracts the response type from a transport. */
|
|
26
50
|
export type ResponseOf<transport extends Transport> =
|
|
27
51
|
transport extends Transport<any, infer response> ? response : never
|
|
@@ -55,33 +79,77 @@ export function from<request, response>(
|
|
|
55
79
|
* HTTP transport for client-side payment handling.
|
|
56
80
|
*
|
|
57
81
|
* - Detects payment required via 402 status
|
|
58
|
-
* - Extracts challenges from `WWW-Authenticate`
|
|
59
|
-
* -
|
|
82
|
+
* - Extracts Payment auth challenges from `WWW-Authenticate`
|
|
83
|
+
* - Falls back to x402 exact challenges from `PAYMENT-REQUIRED`
|
|
84
|
+
* - Sends credentials via `Authorization` or `PAYMENT-SIGNATURE`
|
|
60
85
|
*/
|
|
61
86
|
export function http() {
|
|
62
87
|
return from<RequestInit, Response>({
|
|
63
88
|
name: 'http',
|
|
64
89
|
|
|
65
90
|
isPaymentRequired(response) {
|
|
66
|
-
return response.status ===
|
|
91
|
+
return response.status === paymentRequiredStatus
|
|
67
92
|
},
|
|
68
93
|
|
|
69
94
|
getChallenges(response) {
|
|
70
|
-
return
|
|
95
|
+
return paymentRequiredChallenges(response)
|
|
71
96
|
},
|
|
72
97
|
|
|
73
98
|
getChallenge(response) {
|
|
74
|
-
|
|
99
|
+
const challenge = paymentRequiredChallenges(response)[0]
|
|
100
|
+
if (!challenge) throw new Error('No challenge in response.')
|
|
101
|
+
return challenge
|
|
75
102
|
},
|
|
76
103
|
|
|
77
|
-
setCredential(request, credential) {
|
|
104
|
+
setCredential(request, credential, options) {
|
|
78
105
|
const headers = new Headers(request.headers)
|
|
79
|
-
headers.
|
|
106
|
+
for (const header of credentialHeaders) headers.delete(header)
|
|
107
|
+
if (isX402Challenge(options?.challenge)) {
|
|
108
|
+
headers.set(x402_Types.paymentSignatureHeader, credential)
|
|
109
|
+
} else {
|
|
110
|
+
headers.set(paymentAuthCredentialHeader, credential)
|
|
111
|
+
}
|
|
80
112
|
return { ...request, headers }
|
|
81
113
|
},
|
|
82
114
|
})
|
|
83
115
|
}
|
|
84
116
|
|
|
117
|
+
function paymentRequiredChallenges(response: Response): Challenge.Challenge[] {
|
|
118
|
+
return [
|
|
119
|
+
...(response.headers.has(paymentAuthChallengeHeader)
|
|
120
|
+
? Challenge.fromResponseList(response)
|
|
121
|
+
: []),
|
|
122
|
+
...x402Challenges(response),
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function x402Challenges(response: Response): Challenge.Challenge[] {
|
|
127
|
+
const header = response.headers.get(x402_Types.paymentRequiredHeader)
|
|
128
|
+
if (!header) return []
|
|
129
|
+
const paymentRequired = x402_Header.decodePaymentRequired(header)
|
|
130
|
+
if (response.url && paymentRequired.resource.url !== response.url)
|
|
131
|
+
throw new Error('x402 payment-required resource does not match response URL.')
|
|
132
|
+
return paymentRequired.accepts.map((accepted, index) =>
|
|
133
|
+
x402_ChallengeBrand.mark(
|
|
134
|
+
Challenge.from({
|
|
135
|
+
id: `${x402_Types.syntheticChallengeIdPrefix}${index}`,
|
|
136
|
+
intent: x402_Types.exactIntent,
|
|
137
|
+
method: x402_Types.paymentMethod,
|
|
138
|
+
realm: new URL(paymentRequired.resource.url).host,
|
|
139
|
+
request: {
|
|
140
|
+
...accepted,
|
|
141
|
+
...(paymentRequired.extensions ? { extensions: paymentRequired.extensions } : {}),
|
|
142
|
+
resource: paymentRequired.resource,
|
|
143
|
+
},
|
|
144
|
+
}),
|
|
145
|
+
),
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function isX402Challenge(challenge: Challenge.Challenge | undefined): boolean {
|
|
150
|
+
return x402_ChallengeBrand.is(challenge)
|
|
151
|
+
}
|
|
152
|
+
|
|
85
153
|
/**
|
|
86
154
|
* MCP transport for client-side payment handling.
|
|
87
155
|
*
|
package/src/client/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export * as Expires from '../Expires.js'
|
|
2
2
|
export * as Fetch from './internal/Fetch.js'
|
|
3
|
-
export { session, stripe, tempo } from './Methods.js'
|
|
3
|
+
export { evm, session, stripe, tempo } from './Methods.js'
|
|
4
4
|
export * as Mppx from './Mppx.js'
|
|
5
5
|
export * as Transport from './Transport.js'
|