mppx 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Challenge.d.ts +3 -3
- package/dist/Challenge.js +4 -6
- package/dist/Challenge.js.map +1 -1
- package/dist/PaymentRequest.d.ts +2 -2
- package/dist/PaymentRequest.js +4 -4
- package/dist/PaymentRequest.js.map +1 -1
- package/dist/server/Mppx.js +1 -1
- package/package.json +2 -2
- package/src/Challenge.test.ts +155 -16
- package/src/Challenge.ts +8 -10
- package/src/PaymentRequest.test.ts +4 -4
- package/src/PaymentRequest.ts +4 -4
- package/src/client/Mppx.test.ts +4 -4
- package/src/client/Transport.test.ts +5 -5
- package/src/mcp-sdk/client/McpClient.test.ts +1 -1
- package/src/server/Mppx.ts +1 -1
- package/src/server/Transport.test.ts +6 -6
package/dist/Challenge.d.ts
CHANGED
|
@@ -139,7 +139,7 @@ export declare namespace from {
|
|
|
139
139
|
* import { Methods } from 'mppx/tempo'
|
|
140
140
|
*
|
|
141
141
|
* // With HMAC-bound ID (recommended for servers)
|
|
142
|
-
* const challenge = Challenge.
|
|
142
|
+
* const challenge = Challenge.fromMethod(
|
|
143
143
|
* Methods.charge,
|
|
144
144
|
* {
|
|
145
145
|
* realm: 'api.example.com',
|
|
@@ -154,8 +154,8 @@ export declare namespace from {
|
|
|
154
154
|
* )
|
|
155
155
|
* ```
|
|
156
156
|
*/
|
|
157
|
-
export declare function
|
|
158
|
-
export declare namespace
|
|
157
|
+
export declare function fromMethod<const method extends Method.Method>(method: method, parameters: fromMethod.Parameters<method>): fromMethod.ReturnType<method>;
|
|
158
|
+
export declare namespace fromMethod {
|
|
159
159
|
type Parameters<method extends Method.Method> = OneOf<{
|
|
160
160
|
/** Explicit challenge ID. */
|
|
161
161
|
id: string;
|
package/dist/Challenge.js
CHANGED
|
@@ -100,7 +100,7 @@ export function from(parameters, options) {
|
|
|
100
100
|
* import { Methods } from 'mppx/tempo'
|
|
101
101
|
*
|
|
102
102
|
* // With HMAC-bound ID (recommended for servers)
|
|
103
|
-
* const challenge = Challenge.
|
|
103
|
+
* const challenge = Challenge.fromMethod(
|
|
104
104
|
* Methods.charge,
|
|
105
105
|
* {
|
|
106
106
|
* realm: 'api.example.com',
|
|
@@ -115,10 +115,10 @@ export function from(parameters, options) {
|
|
|
115
115
|
* )
|
|
116
116
|
* ```
|
|
117
117
|
*/
|
|
118
|
-
export function
|
|
118
|
+
export function fromMethod(method, parameters) {
|
|
119
119
|
const { name: methodName, intent } = method;
|
|
120
120
|
const { description, digest, expires, id, realm, secretKey } = parameters;
|
|
121
|
-
const request = PaymentRequest.
|
|
121
|
+
const request = PaymentRequest.fromMethod(method, parameters.request);
|
|
122
122
|
return from({
|
|
123
123
|
...(id ? { id } : { secretKey }),
|
|
124
124
|
realm,
|
|
@@ -271,9 +271,7 @@ function computeId(challenge, options) {
|
|
|
271
271
|
PaymentRequest.serialize(challenge.request),
|
|
272
272
|
challenge.expires ?? '',
|
|
273
273
|
challenge.digest ?? '',
|
|
274
|
-
]
|
|
275
|
-
.filter(Boolean)
|
|
276
|
-
.join('|');
|
|
274
|
+
].join('|');
|
|
277
275
|
const key = Bytes.fromString(options.secretKey);
|
|
278
276
|
const data = Bytes.fromString(input);
|
|
279
277
|
const mac = Hash.hmac256(key, data, { as: 'Bytes' });
|
package/dist/Challenge.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Challenge.js","sourceRoot":"","sources":["../src/Challenge.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"Challenge.js","sourceRoot":"","sources":["../src/Challenge.ts"],"names":[],"mappings":"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"}
|
package/dist/PaymentRequest.d.ts
CHANGED
|
@@ -60,7 +60,7 @@ export declare function from<const request extends Request>(request: request): r
|
|
|
60
60
|
* import { Request } from 'mppx'
|
|
61
61
|
* import { Methods } from 'mppx/tempo'
|
|
62
62
|
*
|
|
63
|
-
* const request = Request.
|
|
63
|
+
* const request = Request.fromMethod(Methods.charge, {
|
|
64
64
|
* amount: '1000000',
|
|
65
65
|
* currency: '0x20c0000000000000000000000000000000000001',
|
|
66
66
|
* recipient: '0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00',
|
|
@@ -69,7 +69,7 @@ export declare function from<const request extends Request>(request: request): r
|
|
|
69
69
|
* })
|
|
70
70
|
* ```
|
|
71
71
|
*/
|
|
72
|
-
export declare function
|
|
72
|
+
export declare function fromMethod<const method extends Method.Method>(method: method, request: z.input<method['schema']['request']>): Request<z.output<method['schema']['request']>>;
|
|
73
73
|
/**
|
|
74
74
|
* Serializes a request to a base64url string.
|
|
75
75
|
*
|
package/dist/PaymentRequest.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Base64 } from 'ox';
|
|
1
|
+
import { Base64, Json } from 'ox';
|
|
2
2
|
/**
|
|
3
3
|
* Deserializes a base64url string to a request.
|
|
4
4
|
*
|
|
@@ -48,7 +48,7 @@ export function from(request) {
|
|
|
48
48
|
* import { Request } from 'mppx'
|
|
49
49
|
* import { Methods } from 'mppx/tempo'
|
|
50
50
|
*
|
|
51
|
-
* const request = Request.
|
|
51
|
+
* const request = Request.fromMethod(Methods.charge, {
|
|
52
52
|
* amount: '1000000',
|
|
53
53
|
* currency: '0x20c0000000000000000000000000000000000001',
|
|
54
54
|
* recipient: '0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00',
|
|
@@ -57,7 +57,7 @@ export function from(request) {
|
|
|
57
57
|
* })
|
|
58
58
|
* ```
|
|
59
59
|
*/
|
|
60
|
-
export function
|
|
60
|
+
export function fromMethod(method, request) {
|
|
61
61
|
return method.schema.request.parse(request);
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
@@ -75,7 +75,7 @@ export function fromIntent(method, request) {
|
|
|
75
75
|
* ```
|
|
76
76
|
*/
|
|
77
77
|
export function serialize(request) {
|
|
78
|
-
const json =
|
|
78
|
+
const json = Json.canonicalize(request);
|
|
79
79
|
return Base64.fromString(json, { pad: false, url: true });
|
|
80
80
|
}
|
|
81
81
|
//# sourceMappingURL=PaymentRequest.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PaymentRequest.js","sourceRoot":"","sources":["../src/PaymentRequest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"PaymentRequest.js","sourceRoot":"","sources":["../src/PaymentRequest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;AAsBjC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;IACrC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,IAAI,CAAgC,OAAgB;IAClE,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,UAAU,CACxB,MAAc,EACd,OAA6C;IAE7C,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAmD,CAAA;AAC/F,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,SAAS,CAAC,OAAgB;IACxC,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAA;IACvC,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAA;AAC3D,CAAC"}
|
package/dist/server/Mppx.js
CHANGED
|
@@ -70,7 +70,7 @@ function createMethodFn(parameters) {
|
|
|
70
70
|
// Recompute challenge from options. The HMAC-bound ID means we don't need to
|
|
71
71
|
// store challenges server-side—if the client echoes back a credential with
|
|
72
72
|
// a matching ID, we know it was issued by us with these exact parameters.
|
|
73
|
-
const challenge = Challenge.
|
|
73
|
+
const challenge = Challenge.fromMethod(method, {
|
|
74
74
|
description,
|
|
75
75
|
expires,
|
|
76
76
|
realm,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mppx",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.2",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"files": [
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
"@remix-run/fetch-proxy": "^0.7.1",
|
|
106
106
|
"@remix-run/node-fetch-server": "^0.13.0",
|
|
107
107
|
"cac": "^6.7.14",
|
|
108
|
-
"ox": "^0.12.
|
|
108
|
+
"ox": "^0.12.2",
|
|
109
109
|
"zod": "^4.3.6"
|
|
110
110
|
},
|
|
111
111
|
"sideEffects": false,
|
package/src/Challenge.test.ts
CHANGED
|
@@ -53,21 +53,160 @@ describe('from', () => {
|
|
|
53
53
|
`)
|
|
54
54
|
})
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// HMAC Challenge ID Test Vectors
|
|
58
|
+
//
|
|
59
|
+
// HMAC input: realm | method | intent | base64url(canonicalize(request)) | expires | digest
|
|
60
|
+
// HMAC key: UTF-8 bytes of secretKey
|
|
61
|
+
// Output: base64url(HMAC-SHA256(key, input), no padding)
|
|
62
|
+
//
|
|
63
|
+
// These vectors cover every combination of optional HMAC fields (expires, digest)
|
|
64
|
+
// and variations in each required field (realm, method, intent, request).
|
|
65
|
+
// Use them to verify HMAC challenge ID computation in other implementations.
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
const hmacVectors = [
|
|
68
|
+
{
|
|
69
|
+
label: 'required fields only',
|
|
70
|
+
params: {
|
|
71
|
+
realm: 'api.example.com',
|
|
72
|
+
method: 'tempo',
|
|
73
|
+
intent: 'charge',
|
|
74
|
+
request: { amount: '1000000' },
|
|
75
|
+
},
|
|
76
|
+
expectedId: 'SOfbA51LV3LCkGE7RbomqwXdbWVlrZwlW-Z9aOHolxw',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
label: 'with expires',
|
|
80
|
+
params: {
|
|
81
|
+
realm: 'api.example.com',
|
|
82
|
+
method: 'tempo',
|
|
83
|
+
intent: 'charge',
|
|
84
|
+
request: { amount: '1000000' },
|
|
85
|
+
expires: '2025-01-06T12:00:00Z',
|
|
86
|
+
},
|
|
87
|
+
expectedId: 'R1ZSIwoIjkFhMCSzUGiCTesiigf5vV65EQ_3gVNtsNw',
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
label: 'with digest',
|
|
91
|
+
params: {
|
|
92
|
+
realm: 'api.example.com',
|
|
93
|
+
method: 'tempo',
|
|
94
|
+
intent: 'charge',
|
|
95
|
+
request: { amount: '1000000' },
|
|
96
|
+
digest: 'sha-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE',
|
|
97
|
+
},
|
|
98
|
+
expectedId: 'AiMmBdsSOkOYpXTupMnzVnrzZbqMY_P2i80vENRUSN4',
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
label: 'with expires and digest',
|
|
102
|
+
params: {
|
|
103
|
+
realm: 'api.example.com',
|
|
104
|
+
method: 'tempo',
|
|
105
|
+
intent: 'charge',
|
|
106
|
+
request: { amount: '1000000' },
|
|
107
|
+
expires: '2025-01-06T12:00:00Z',
|
|
108
|
+
digest: 'sha-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE',
|
|
109
|
+
},
|
|
110
|
+
expectedId: 'FMBGqN7MzpKagHsCcartZM09CnUqv7UgmaCy45Ozgug',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
label: 'with description (not in HMAC input)',
|
|
114
|
+
params: {
|
|
115
|
+
realm: 'api.example.com',
|
|
116
|
+
method: 'tempo',
|
|
117
|
+
intent: 'charge',
|
|
118
|
+
request: { amount: '1000000' },
|
|
119
|
+
description: 'Test payment',
|
|
120
|
+
},
|
|
121
|
+
expectedId: 'SOfbA51LV3LCkGE7RbomqwXdbWVlrZwlW-Z9aOHolxw',
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
label: 'with multi-field request',
|
|
125
|
+
params: {
|
|
126
|
+
realm: 'api.example.com',
|
|
127
|
+
method: 'tempo',
|
|
128
|
+
intent: 'charge',
|
|
129
|
+
request: { amount: '1000000', currency: '0x1234', recipient: '0xabcd' },
|
|
130
|
+
},
|
|
131
|
+
expectedId: '5CXJi4bWMz2W54WjnlmoxnwTYe-JKwhw0z32ICQ65Es',
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
label: 'with nested methodDetails in request',
|
|
135
|
+
params: {
|
|
136
|
+
realm: 'api.example.com',
|
|
137
|
+
method: 'tempo',
|
|
138
|
+
intent: 'charge',
|
|
139
|
+
request: { amount: '1000000', currency: '0x1234', methodDetails: { chainId: 42431 } },
|
|
140
|
+
},
|
|
141
|
+
expectedId: 'eid66xXUZsj46Pb30AfAf7m5kPehgianI16rZ-QY8HU',
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
label: 'with empty request',
|
|
145
|
+
params: {
|
|
146
|
+
realm: 'api.example.com',
|
|
147
|
+
method: 'tempo',
|
|
148
|
+
intent: 'charge',
|
|
149
|
+
request: {},
|
|
150
|
+
},
|
|
151
|
+
expectedId: '6kq-PYTyXtaGAHTHCVUrc_hIsAwLeskeQFtDZerMYhM',
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
label: 'different realm',
|
|
155
|
+
params: {
|
|
156
|
+
realm: 'payments.other.com',
|
|
157
|
+
method: 'tempo',
|
|
158
|
+
intent: 'charge',
|
|
159
|
+
request: { amount: '1000000' },
|
|
160
|
+
},
|
|
161
|
+
expectedId: '-gMjd8UeUvBcqUaUzarVj6ikH_YoDowpaNbEwK1Tmx8',
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
label: 'different method',
|
|
165
|
+
params: {
|
|
166
|
+
realm: 'api.example.com',
|
|
167
|
+
method: 'stripe',
|
|
168
|
+
intent: 'charge',
|
|
169
|
+
request: { amount: '1000000' },
|
|
170
|
+
},
|
|
171
|
+
expectedId: 'DRH9ycmIlZ2lYUatIHCrxpm9K7ig5pniZ3ulleb7vl0',
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
label: 'different intent',
|
|
175
|
+
params: {
|
|
176
|
+
realm: 'api.example.com',
|
|
177
|
+
method: 'tempo',
|
|
178
|
+
intent: 'session',
|
|
179
|
+
request: { amount: '1000000' },
|
|
180
|
+
},
|
|
181
|
+
expectedId: 'INeBi93MhinvbwdUxeUUIaT5Q_ufgLKPYZb5Tg43A1o',
|
|
182
|
+
},
|
|
183
|
+
] as const
|
|
184
|
+
|
|
185
|
+
test.each(hmacVectors)('hmac: $label', ({ params, expectedId }) => {
|
|
186
|
+
const challenge = Challenge.from({ ...params, secretKey: 'test-vector-secret' })
|
|
187
|
+
expect(challenge.id).toBe(expectedId)
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
test('hmac: description does not affect id', () => {
|
|
191
|
+
const withDesc = Challenge.from({
|
|
58
192
|
realm: 'api.example.com',
|
|
59
193
|
method: 'tempo',
|
|
60
194
|
intent: 'charge',
|
|
61
|
-
request: { amount: '1000000'
|
|
62
|
-
|
|
195
|
+
request: { amount: '1000000' },
|
|
196
|
+
description: 'Test payment',
|
|
197
|
+
secretKey: 'test-vector-secret',
|
|
63
198
|
})
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
199
|
+
const without = Challenge.from({
|
|
200
|
+
realm: 'api.example.com',
|
|
201
|
+
method: 'tempo',
|
|
202
|
+
intent: 'charge',
|
|
203
|
+
request: { amount: '1000000' },
|
|
204
|
+
secretKey: 'test-vector-secret',
|
|
205
|
+
})
|
|
206
|
+
expect(withDesc.id).toBe(without.id)
|
|
68
207
|
})
|
|
69
208
|
|
|
70
|
-
test('
|
|
209
|
+
test('hmac: same params with same secretKey produce same id', () => {
|
|
71
210
|
const challenge1 = Challenge.from({
|
|
72
211
|
realm: 'api.example.com',
|
|
73
212
|
method: 'tempo',
|
|
@@ -86,7 +225,7 @@ describe('from', () => {
|
|
|
86
225
|
expect(challenge1.id).toBe(challenge2.id)
|
|
87
226
|
})
|
|
88
227
|
|
|
89
|
-
test('
|
|
228
|
+
test('hmac: different secretKey produces different id', () => {
|
|
90
229
|
const challenge1 = Challenge.from({
|
|
91
230
|
realm: 'api.example.com',
|
|
92
231
|
method: 'tempo',
|
|
@@ -106,9 +245,9 @@ describe('from', () => {
|
|
|
106
245
|
})
|
|
107
246
|
})
|
|
108
247
|
|
|
109
|
-
describe('
|
|
248
|
+
describe('fromMethod', () => {
|
|
110
249
|
test('behavior: creates validated challenge from intent', () => {
|
|
111
|
-
const challenge = Challenge.
|
|
250
|
+
const challenge = Challenge.fromMethod(Methods.charge, {
|
|
112
251
|
id: 'abc123',
|
|
113
252
|
realm: 'api.example.com',
|
|
114
253
|
request: {
|
|
@@ -138,7 +277,7 @@ describe('fromIntent', () => {
|
|
|
138
277
|
})
|
|
139
278
|
|
|
140
279
|
test('behavior: includes methodDetails in request', () => {
|
|
141
|
-
const challenge = Challenge.
|
|
280
|
+
const challenge = Challenge.fromMethod(Methods.charge, {
|
|
142
281
|
id: 'abc123',
|
|
143
282
|
realm: 'api.example.com',
|
|
144
283
|
request: {
|
|
@@ -174,7 +313,7 @@ describe('fromIntent', () => {
|
|
|
174
313
|
})
|
|
175
314
|
|
|
176
315
|
test('behavior: includes optional digest and expires', () => {
|
|
177
|
-
const challenge = Challenge.
|
|
316
|
+
const challenge = Challenge.fromMethod(Methods.charge, {
|
|
178
317
|
id: 'abc123',
|
|
179
318
|
realm: 'api.example.com',
|
|
180
319
|
request: {
|
|
@@ -193,7 +332,7 @@ describe('fromIntent', () => {
|
|
|
193
332
|
})
|
|
194
333
|
|
|
195
334
|
test('behavior: creates challenge with HMAC-bound id via secretKey', () => {
|
|
196
|
-
const challenge = Challenge.
|
|
335
|
+
const challenge = Challenge.fromMethod(Methods.charge, {
|
|
197
336
|
realm: 'api.example.com',
|
|
198
337
|
request: {
|
|
199
338
|
amount: '1',
|
|
@@ -212,7 +351,7 @@ describe('fromIntent', () => {
|
|
|
212
351
|
|
|
213
352
|
test('error: invalid request', () => {
|
|
214
353
|
expect(() =>
|
|
215
|
-
Challenge.
|
|
354
|
+
Challenge.fromMethod(Methods.charge, {
|
|
216
355
|
id: 'abc123',
|
|
217
356
|
realm: 'api.example.com',
|
|
218
357
|
request: {
|
package/src/Challenge.ts
CHANGED
|
@@ -186,7 +186,7 @@ export declare namespace from {
|
|
|
186
186
|
* import { Methods } from 'mppx/tempo'
|
|
187
187
|
*
|
|
188
188
|
* // With HMAC-bound ID (recommended for servers)
|
|
189
|
-
* const challenge = Challenge.
|
|
189
|
+
* const challenge = Challenge.fromMethod(
|
|
190
190
|
* Methods.charge,
|
|
191
191
|
* {
|
|
192
192
|
* realm: 'api.example.com',
|
|
@@ -201,14 +201,14 @@ export declare namespace from {
|
|
|
201
201
|
* )
|
|
202
202
|
* ```
|
|
203
203
|
*/
|
|
204
|
-
export function
|
|
204
|
+
export function fromMethod<const method extends Method.Method>(
|
|
205
205
|
method: method,
|
|
206
|
-
parameters:
|
|
207
|
-
):
|
|
206
|
+
parameters: fromMethod.Parameters<method>,
|
|
207
|
+
): fromMethod.ReturnType<method> {
|
|
208
208
|
const { name: methodName, intent } = method
|
|
209
209
|
const { description, digest, expires, id, realm, secretKey } = parameters
|
|
210
210
|
|
|
211
|
-
const request = PaymentRequest.
|
|
211
|
+
const request = PaymentRequest.fromMethod(method, parameters.request)
|
|
212
212
|
|
|
213
213
|
return from({
|
|
214
214
|
...(id ? { id } : { secretKey }),
|
|
@@ -219,10 +219,10 @@ export function fromIntent<const method extends Method.Method>(
|
|
|
219
219
|
description,
|
|
220
220
|
digest,
|
|
221
221
|
expires,
|
|
222
|
-
} as from.Parameters) as
|
|
222
|
+
} as from.Parameters) as fromMethod.ReturnType<method>
|
|
223
223
|
}
|
|
224
224
|
|
|
225
|
-
export declare namespace
|
|
225
|
+
export declare namespace fromMethod {
|
|
226
226
|
type Parameters<method extends Method.Method> = OneOf<
|
|
227
227
|
| {
|
|
228
228
|
/** Explicit challenge ID. */
|
|
@@ -410,9 +410,7 @@ function computeId(challenge: Omit<Challenge, 'id'>, options: { secretKey: strin
|
|
|
410
410
|
PaymentRequest.serialize(challenge.request),
|
|
411
411
|
challenge.expires ?? '',
|
|
412
412
|
challenge.digest ?? '',
|
|
413
|
-
]
|
|
414
|
-
.filter(Boolean)
|
|
415
|
-
.join('|')
|
|
413
|
+
].join('|')
|
|
416
414
|
|
|
417
415
|
const key = Bytes.fromString(options.secretKey)
|
|
418
416
|
const data = Bytes.fromString(input)
|
|
@@ -19,9 +19,9 @@ describe('from', () => {
|
|
|
19
19
|
})
|
|
20
20
|
})
|
|
21
21
|
|
|
22
|
-
describe('
|
|
22
|
+
describe('fromMethod', () => {
|
|
23
23
|
test('creates a validated request from intent', () => {
|
|
24
|
-
const request = PaymentRequest.
|
|
24
|
+
const request = PaymentRequest.fromMethod(Methods.charge, {
|
|
25
25
|
amount: '1',
|
|
26
26
|
currency: '0x20c0000000000000000000000000000000000001',
|
|
27
27
|
decimals: 6,
|
|
@@ -39,7 +39,7 @@ describe('fromIntent', () => {
|
|
|
39
39
|
})
|
|
40
40
|
|
|
41
41
|
test('includes methodDetails fields', () => {
|
|
42
|
-
const request = PaymentRequest.
|
|
42
|
+
const request = PaymentRequest.fromMethod(Methods.charge, {
|
|
43
43
|
amount: '1',
|
|
44
44
|
currency: '0x20c0000000000000000000000000000000000001',
|
|
45
45
|
decimals: 6,
|
|
@@ -62,7 +62,7 @@ describe('fromIntent', () => {
|
|
|
62
62
|
|
|
63
63
|
test('throws on invalid request', () => {
|
|
64
64
|
expect(() =>
|
|
65
|
-
PaymentRequest.
|
|
65
|
+
PaymentRequest.fromMethod(Methods.charge, {
|
|
66
66
|
amount: 123,
|
|
67
67
|
currency: '0x20c0000000000000000000000000000000000001',
|
|
68
68
|
recipient: '0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00',
|
package/src/PaymentRequest.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Base64 } from 'ox'
|
|
1
|
+
import { Base64, Json } from 'ox'
|
|
2
2
|
import type { Compute } from './internal/types.js'
|
|
3
3
|
import type * as Method from './Method.js'
|
|
4
4
|
import type * as z from './zod.js'
|
|
@@ -71,7 +71,7 @@ export function from<const request extends Request>(request: request): request {
|
|
|
71
71
|
* import { Request } from 'mppx'
|
|
72
72
|
* import { Methods } from 'mppx/tempo'
|
|
73
73
|
*
|
|
74
|
-
* const request = Request.
|
|
74
|
+
* const request = Request.fromMethod(Methods.charge, {
|
|
75
75
|
* amount: '1000000',
|
|
76
76
|
* currency: '0x20c0000000000000000000000000000000000001',
|
|
77
77
|
* recipient: '0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00',
|
|
@@ -80,7 +80,7 @@ export function from<const request extends Request>(request: request): request {
|
|
|
80
80
|
* })
|
|
81
81
|
* ```
|
|
82
82
|
*/
|
|
83
|
-
export function
|
|
83
|
+
export function fromMethod<const method extends Method.Method>(
|
|
84
84
|
method: method,
|
|
85
85
|
request: z.input<method['schema']['request']>,
|
|
86
86
|
): Request<z.output<method['schema']['request']>> {
|
|
@@ -102,6 +102,6 @@ export function fromIntent<const method extends Method.Method>(
|
|
|
102
102
|
* ```
|
|
103
103
|
*/
|
|
104
104
|
export function serialize(request: Request): string {
|
|
105
|
-
const json =
|
|
105
|
+
const json = Json.canonicalize(request)
|
|
106
106
|
return Base64.fromString(json, { pad: false, url: true })
|
|
107
107
|
}
|
package/src/client/Mppx.test.ts
CHANGED
|
@@ -79,7 +79,7 @@ describe('createCredential', () => {
|
|
|
79
79
|
methods: [tempo({ account: accounts[1], getClient: () => client })],
|
|
80
80
|
})
|
|
81
81
|
|
|
82
|
-
const challenge = Challenge.
|
|
82
|
+
const challenge = Challenge.fromMethod(Methods.charge, {
|
|
83
83
|
realm,
|
|
84
84
|
secretKey,
|
|
85
85
|
request: {
|
|
@@ -192,7 +192,7 @@ describe('createCredential', () => {
|
|
|
192
192
|
methods: [tempo({ getClient: () => client })],
|
|
193
193
|
})
|
|
194
194
|
|
|
195
|
-
const challenge = Challenge.
|
|
195
|
+
const challenge = Challenge.fromMethod(Methods.charge, {
|
|
196
196
|
realm,
|
|
197
197
|
secretKey,
|
|
198
198
|
request: {
|
|
@@ -224,7 +224,7 @@ describe('createCredential', () => {
|
|
|
224
224
|
methods: [tempo({ account: accounts[1], getClient: () => client })],
|
|
225
225
|
})
|
|
226
226
|
|
|
227
|
-
const challenge = Challenge.
|
|
227
|
+
const challenge = Challenge.fromMethod(Methods.charge, {
|
|
228
228
|
realm,
|
|
229
229
|
secretKey,
|
|
230
230
|
request: {
|
|
@@ -255,7 +255,7 @@ describe('createCredential', () => {
|
|
|
255
255
|
transport: Transport.mcp(),
|
|
256
256
|
})
|
|
257
257
|
|
|
258
|
-
const challenge = Challenge.
|
|
258
|
+
const challenge = Challenge.fromMethod(Methods.charge, {
|
|
259
259
|
realm,
|
|
260
260
|
secretKey,
|
|
261
261
|
request: {
|
|
@@ -6,7 +6,7 @@ import { describe, expect, test } from 'vitest'
|
|
|
6
6
|
const realm = 'api.example.com'
|
|
7
7
|
const secretKey = 'test-secret-key'
|
|
8
8
|
|
|
9
|
-
const challenge = Challenge.
|
|
9
|
+
const challenge = Challenge.fromMethod(Methods.charge, {
|
|
10
10
|
realm,
|
|
11
11
|
secretKey,
|
|
12
12
|
request: {
|
|
@@ -60,7 +60,7 @@ describe('http', () => {
|
|
|
60
60
|
expect(transport.getChallenge(response)).toMatchInlineSnapshot(`
|
|
61
61
|
{
|
|
62
62
|
"expires": "2025-01-01T00:00:00.000Z",
|
|
63
|
-
"id": "
|
|
63
|
+
"id": "i1474pQ7BtfAx76cLch6u8_AQkcp3akMkerEYrL5Rwo",
|
|
64
64
|
"intent": "charge",
|
|
65
65
|
"method": "tempo",
|
|
66
66
|
"realm": "api.example.com",
|
|
@@ -91,7 +91,7 @@ describe('http', () => {
|
|
|
91
91
|
const headers = result.headers as Headers
|
|
92
92
|
|
|
93
93
|
expect(headers.get('Authorization')).toMatchInlineSnapshot(
|
|
94
|
-
`"Payment
|
|
94
|
+
`"Payment eyJjaGFsbGVuZ2UiOnsiZXhwaXJlcyI6IjIwMjUtMDEtMDFUMDA6MDA6MDAuMDAwWiIsImlkIjoiaTE0NzRwUTdCdGZBeDc2Y0xjaDZ1OF9BUWtjcDNha01rZXJFWXJMNVJ3byIsImludGVudCI6ImNoYXJnZSIsIm1ldGhvZCI6InRlbXBvIiwicmVhbG0iOiJhcGkuZXhhbXBsZS5jb20iLCJyZXF1ZXN0IjoiZXlKaGJXOTFiblFpT2lJeE1EQXdJaXdpWTNWeWNtVnVZM2tpT2lJd2VESXdZekF3TURBd01EQXdNREF3TURBd01EQXdNREF3TURBd01EQXdNREF3TURBd01EQXdNREVpTENKbGVIQnBjbVZ6SWpvaU1qQXlOUzB3TVMwd01WUXdNRG93TURvd01DNHdNREJhSWl3aWNtVmphWEJwWlc1MElqb2lNSGczTkRKa016VkRZelkyTXpSRE1EVXpNamt5TldFellqZzBORUpqT1dVM05UazFaamhtUlRBd0luMCJ9LCJwYXlsb2FkIjp7InNpZ25hdHVyZSI6IjB4YWJjMTIzIiwidHlwZSI6InRyYW5zYWN0aW9uIn19"`,
|
|
95
95
|
)
|
|
96
96
|
})
|
|
97
97
|
|
|
@@ -182,7 +182,7 @@ describe('mcp', () => {
|
|
|
182
182
|
expect(transport.getChallenge(response)).toMatchInlineSnapshot(`
|
|
183
183
|
{
|
|
184
184
|
"expires": "2025-01-01T00:00:00.000Z",
|
|
185
|
-
"id": "
|
|
185
|
+
"id": "i1474pQ7BtfAx76cLch6u8_AQkcp3akMkerEYrL5Rwo",
|
|
186
186
|
"intent": "charge",
|
|
187
187
|
"method": "tempo",
|
|
188
188
|
"realm": "api.example.com",
|
|
@@ -239,7 +239,7 @@ describe('mcp', () => {
|
|
|
239
239
|
"org.paymentauth/credential": {
|
|
240
240
|
"challenge": {
|
|
241
241
|
"expires": "2025-01-01T00:00:00.000Z",
|
|
242
|
-
"id": "
|
|
242
|
+
"id": "i1474pQ7BtfAx76cLch6u8_AQkcp3akMkerEYrL5Rwo",
|
|
243
243
|
"intent": "charge",
|
|
244
244
|
"method": "tempo",
|
|
245
245
|
"realm": "api.example.com",
|
|
@@ -154,7 +154,7 @@ describe('McpClient.wrap', () => {
|
|
|
154
154
|
})
|
|
155
155
|
|
|
156
156
|
test('error: throws when method not found', async () => {
|
|
157
|
-
const challenge = Challenge.
|
|
157
|
+
const challenge = Challenge.fromMethod(tempo_server.charge({ getClient: () => testClient }), {
|
|
158
158
|
realm,
|
|
159
159
|
secretKey,
|
|
160
160
|
request: {
|
package/src/server/Mppx.ts
CHANGED
|
@@ -160,7 +160,7 @@ function createMethodFn(parameters: createMethodFn.Parameters): createMethodFn.R
|
|
|
160
160
|
// Recompute challenge from options. The HMAC-bound ID means we don't need to
|
|
161
161
|
// store challenges server-side—if the client echoes back a credential with
|
|
162
162
|
// a matching ID, we know it was issued by us with these exact parameters.
|
|
163
|
-
const challenge = Challenge.
|
|
163
|
+
const challenge = Challenge.fromMethod(method, {
|
|
164
164
|
description,
|
|
165
165
|
expires,
|
|
166
166
|
realm,
|
|
@@ -7,7 +7,7 @@ import { BadRequestError, ChannelClosedError } from '../Errors.js'
|
|
|
7
7
|
const realm = 'api.example.com'
|
|
8
8
|
const secretKey = 'test-secret-key'
|
|
9
9
|
|
|
10
|
-
const challenge = Challenge.
|
|
10
|
+
const challenge = Challenge.fromMethod(Methods.charge, {
|
|
11
11
|
realm,
|
|
12
12
|
secretKey,
|
|
13
13
|
request: {
|
|
@@ -43,7 +43,7 @@ describe('http', () => {
|
|
|
43
43
|
{
|
|
44
44
|
"challenge": {
|
|
45
45
|
"expires": "2025-01-01T00:00:00.000Z",
|
|
46
|
-
"id": "
|
|
46
|
+
"id": "N_Q_IM9V5tO3JMcOTniz7anX81m7MdEp4aLW9q5KNK0",
|
|
47
47
|
"intent": "charge",
|
|
48
48
|
"method": "tempo",
|
|
49
49
|
"realm": "api.example.com",
|
|
@@ -93,7 +93,7 @@ describe('http', () => {
|
|
|
93
93
|
{
|
|
94
94
|
"headers": {
|
|
95
95
|
"cache-control": "no-store",
|
|
96
|
-
"www-authenticate": "Payment id="
|
|
96
|
+
"www-authenticate": "Payment id="N_Q_IM9V5tO3JMcOTniz7anX81m7MdEp4aLW9q5KNK0", realm="api.example.com", method="tempo", intent="charge", request="eyJhbW91bnQiOiIxMDAwMDAwMDAwIiwiY3VycmVuY3kiOiIweDIwYzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEiLCJleHBpcmVzIjoiMjAyNS0wMS0wMVQwMDowMDowMC4wMDBaIiwicmVjaXBpZW50IjoiMHg3NDJkMzVDYzY2MzRDMDUzMjkyNWEzYjg0NEJjOWU3NTk1ZjhmRTAwIn0", expires="2025-01-01T00:00:00.000Z"",
|
|
97
97
|
},
|
|
98
98
|
"status": 402,
|
|
99
99
|
}
|
|
@@ -183,7 +183,7 @@ describe('mcp', () => {
|
|
|
183
183
|
{
|
|
184
184
|
"challenge": {
|
|
185
185
|
"expires": "2025-01-01T00:00:00.000Z",
|
|
186
|
-
"id": "
|
|
186
|
+
"id": "N_Q_IM9V5tO3JMcOTniz7anX81m7MdEp4aLW9q5KNK0",
|
|
187
187
|
"intent": "charge",
|
|
188
188
|
"method": "tempo",
|
|
189
189
|
"realm": "api.example.com",
|
|
@@ -221,7 +221,7 @@ describe('mcp', () => {
|
|
|
221
221
|
"challenges": [
|
|
222
222
|
{
|
|
223
223
|
"expires": "2025-01-01T00:00:00.000Z",
|
|
224
|
-
"id": "
|
|
224
|
+
"id": "N_Q_IM9V5tO3JMcOTniz7anX81m7MdEp4aLW9q5KNK0",
|
|
225
225
|
"intent": "charge",
|
|
226
226
|
"method": "tempo",
|
|
227
227
|
"realm": "api.example.com",
|
|
@@ -262,7 +262,7 @@ describe('mcp', () => {
|
|
|
262
262
|
"result": {
|
|
263
263
|
"_meta": {
|
|
264
264
|
"org.paymentauth/receipt": {
|
|
265
|
-
"challengeId": "
|
|
265
|
+
"challengeId": "N_Q_IM9V5tO3JMcOTniz7anX81m7MdEp4aLW9q5KNK0",
|
|
266
266
|
"method": "tempo",
|
|
267
267
|
"reference": "0xtxhash",
|
|
268
268
|
"status": "success",
|