mppx 0.8.12 → 0.8.14
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 +34 -0
- package/README.md +16 -1
- package/dist/Errors.d.ts +10 -0
- package/dist/Errors.d.ts.map +1 -1
- package/dist/Errors.js +11 -2
- package/dist/Errors.js.map +1 -1
- package/dist/Method.d.ts +105 -3
- package/dist/Method.d.ts.map +1 -1
- package/dist/Method.js +102 -2
- package/dist/Method.js.map +1 -1
- package/dist/cli/account.d.ts +88 -0
- package/dist/cli/account.d.ts.map +1 -1
- package/dist/cli/account.js +39 -9
- package/dist/cli/account.js.map +1 -1
- package/dist/cli/cli.d.ts +2 -1
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +59 -2
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/sessions/Manager.d.ts +31 -0
- package/dist/cli/sessions/Manager.d.ts.map +1 -0
- package/dist/cli/sessions/Manager.js +56 -0
- package/dist/cli/sessions/Manager.js.map +1 -0
- package/dist/cli/sessions/commands.d.ts +36 -0
- package/dist/cli/sessions/commands.d.ts.map +1 -0
- package/dist/cli/sessions/commands.js +407 -0
- package/dist/cli/sessions/commands.js.map +1 -0
- package/dist/cli/sessions/request.d.ts +35 -0
- package/dist/cli/sessions/request.d.ts.map +1 -0
- package/dist/cli/sessions/request.js +271 -0
- package/dist/cli/sessions/request.js.map +1 -0
- package/dist/cli/sessions/store.d.ts +134 -0
- package/dist/cli/sessions/store.d.ts.map +1 -0
- package/dist/cli/sessions/store.js +723 -0
- package/dist/cli/sessions/store.js.map +1 -0
- package/dist/cli/utils.d.ts +2 -0
- package/dist/cli/utils.d.ts.map +1 -1
- package/dist/cli/utils.js +12 -0
- package/dist/cli/utils.js.map +1 -1
- package/dist/cli/validate/index.d.ts.map +1 -1
- package/dist/cli/validate/index.js +12 -6
- package/dist/cli/validate/index.js.map +1 -1
- package/dist/cli/validate/messages.d.ts +2 -0
- package/dist/cli/validate/messages.d.ts.map +1 -0
- package/dist/cli/validate/messages.js +8 -0
- package/dist/cli/validate/messages.js.map +1 -0
- package/dist/client/internal/Fetch.d.ts.map +1 -1
- package/dist/client/internal/Fetch.js +12 -2
- package/dist/client/internal/Fetch.js.map +1 -1
- package/dist/client/internal/MethodChallenge.d.ts +17 -0
- package/dist/client/internal/MethodChallenge.d.ts.map +1 -0
- package/dist/client/internal/MethodChallenge.js +11 -0
- package/dist/client/internal/MethodChallenge.js.map +1 -0
- package/dist/client/node.d.ts +29 -0
- package/dist/client/node.d.ts.map +1 -0
- package/dist/client/node.js +177 -0
- package/dist/client/node.js.map +1 -0
- package/dist/internal/types.d.ts +24 -0
- package/dist/internal/types.d.ts.map +1 -1
- package/dist/server/Mppx.d.ts +23 -4
- package/dist/server/Mppx.d.ts.map +1 -1
- package/dist/server/Mppx.js +91 -82
- package/dist/server/Mppx.js.map +1 -1
- package/dist/stripe/server/Charge.d.ts +8 -4
- package/dist/stripe/server/Charge.d.ts.map +1 -1
- package/dist/stripe/server/Charge.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/Methods.d.ts +2 -1
- package/dist/tempo/client/Methods.d.ts.map +1 -1
- package/dist/tempo/internal/fee-payer.d.ts +1 -0
- package/dist/tempo/internal/fee-payer.d.ts.map +1 -1
- package/dist/tempo/internal/fee-payer.js +7 -2
- package/dist/tempo/internal/fee-payer.js.map +1 -1
- package/dist/tempo/internal/types.d.ts +10 -1
- package/dist/tempo/internal/types.d.ts.map +1 -1
- package/dist/tempo/legacy/client/ChannelOps.d.ts.map +1 -1
- package/dist/tempo/legacy/client/ChannelOps.js +2 -1
- package/dist/tempo/legacy/client/ChannelOps.js.map +1 -1
- package/dist/tempo/legacy/client/Session.d.ts +2 -2
- package/dist/tempo/legacy/server/Session.d.ts +3 -3
- package/dist/tempo/legacy/server/Session.d.ts.map +1 -1
- package/dist/tempo/legacy/server/Session.js.map +1 -1
- package/dist/tempo/server/Charge.d.ts +40 -78
- package/dist/tempo/server/Charge.d.ts.map +1 -1
- package/dist/tempo/server/Charge.js +289 -209
- package/dist/tempo/server/Charge.js.map +1 -1
- package/dist/tempo/server/Methods.d.ts +13 -23
- package/dist/tempo/server/Methods.d.ts.map +1 -1
- package/dist/tempo/server/Methods.js +6 -2
- package/dist/tempo/server/Methods.js.map +1 -1
- package/dist/tempo/server/Relay.d.ts +48 -0
- package/dist/tempo/server/Relay.d.ts.map +1 -0
- package/dist/tempo/server/Relay.js +177 -0
- package/dist/tempo/server/Relay.js.map +1 -0
- package/dist/tempo/server/SponsorBudget.d.ts +59 -0
- package/dist/tempo/server/SponsorBudget.d.ts.map +1 -0
- package/dist/tempo/server/SponsorBudget.js +144 -0
- package/dist/tempo/server/SponsorBudget.js.map +1 -0
- package/dist/tempo/server/Subscription.d.ts +3 -2
- package/dist/tempo/server/Subscription.d.ts.map +1 -1
- package/dist/tempo/server/Subscription.js.map +1 -1
- package/dist/tempo/server/index.d.ts +1 -1
- package/dist/tempo/server/index.d.ts.map +1 -1
- package/dist/tempo/server/index.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/Snapshot.d.ts +9 -0
- package/dist/tempo/session/Snapshot.d.ts.map +1 -1
- package/dist/tempo/session/Snapshot.js +6 -0
- package/dist/tempo/session/Snapshot.js.map +1 -1
- package/dist/tempo/session/client/ChannelOps.d.ts +7 -1
- package/dist/tempo/session/client/ChannelOps.d.ts.map +1 -1
- package/dist/tempo/session/client/ChannelOps.js +17 -3
- package/dist/tempo/session/client/ChannelOps.js.map +1 -1
- package/dist/tempo/session/client/CredentialState.d.ts +26 -2
- package/dist/tempo/session/client/CredentialState.d.ts.map +1 -1
- package/dist/tempo/session/client/CredentialState.js +99 -16
- package/dist/tempo/session/client/CredentialState.js.map +1 -1
- package/dist/tempo/session/client/Runtime.d.ts +8 -0
- package/dist/tempo/session/client/Runtime.d.ts.map +1 -1
- package/dist/tempo/session/client/Runtime.js +17 -0
- package/dist/tempo/session/client/Runtime.js.map +1 -1
- package/dist/tempo/session/client/Session.d.ts +16 -6
- package/dist/tempo/session/client/Session.d.ts.map +1 -1
- package/dist/tempo/session/client/Session.js +93 -36
- package/dist/tempo/session/client/Session.js.map +1 -1
- package/dist/tempo/session/client/SessionManager.d.ts +10 -3
- package/dist/tempo/session/client/SessionManager.d.ts.map +1 -1
- package/dist/tempo/session/client/SessionManager.js +176 -50
- package/dist/tempo/session/client/SessionManager.js.map +1 -1
- package/dist/tempo/session/client/Transports.d.ts +18 -7
- package/dist/tempo/session/client/Transports.d.ts.map +1 -1
- package/dist/tempo/session/client/Transports.js +81 -33
- package/dist/tempo/session/client/Transports.js.map +1 -1
- package/dist/tempo/session/client/internal/SessionManager.d.ts +19 -0
- package/dist/tempo/session/client/internal/SessionManager.d.ts.map +1 -0
- package/dist/tempo/session/client/internal/SessionManager.js +13 -0
- package/dist/tempo/session/client/internal/SessionManager.js.map +1 -0
- package/dist/tempo/session/precompile/Chain.d.ts.map +1 -1
- package/dist/tempo/session/precompile/Chain.js +109 -12
- package/dist/tempo/session/precompile/Chain.js.map +1 -1
- package/dist/tempo/session/precompile/Channel.d.ts +2 -0
- package/dist/tempo/session/precompile/Channel.d.ts.map +1 -1
- package/dist/tempo/session/precompile/Channel.js +4 -0
- package/dist/tempo/session/precompile/Channel.js.map +1 -1
- package/dist/tempo/session/server/CredentialVerification.d.ts +3 -0
- package/dist/tempo/session/server/CredentialVerification.d.ts.map +1 -1
- package/dist/tempo/session/server/CredentialVerification.js +14 -0
- package/dist/tempo/session/server/CredentialVerification.js.map +1 -1
- package/dist/tempo/session/server/MeteredStream.d.ts +7 -1
- package/dist/tempo/session/server/MeteredStream.d.ts.map +1 -1
- package/dist/tempo/session/server/MeteredStream.js +5 -4
- package/dist/tempo/session/server/MeteredStream.js.map +1 -1
- package/dist/tempo/session/server/RequestState.d.ts +5 -1
- package/dist/tempo/session/server/RequestState.d.ts.map +1 -1
- package/dist/tempo/session/server/RequestState.js +13 -5
- package/dist/tempo/session/server/RequestState.js.map +1 -1
- package/dist/tempo/session/server/Session.d.ts +21 -6
- package/dist/tempo/session/server/Session.d.ts.map +1 -1
- package/dist/tempo/session/server/Session.js +4 -1
- package/dist/tempo/session/server/Session.js.map +1 -1
- package/dist/tempo/session/server/Settlement.d.ts +20 -0
- package/dist/tempo/session/server/Settlement.d.ts.map +1 -1
- package/dist/tempo/session/server/Settlement.js +20 -0
- package/dist/tempo/session/server/Settlement.js.map +1 -1
- package/dist/tempo/session/server/Ws.d.ts +2 -0
- package/dist/tempo/session/server/Ws.d.ts.map +1 -1
- package/dist/tempo/session/server/Ws.js.map +1 -1
- package/dist/tempo/session/server/index.d.ts +1 -1
- package/dist/tempo/session/server/index.d.ts.map +1 -1
- package/dist/tempo/subscription/KeyAuthorization.d.ts +21 -21
- package/dist/validation/core.d.ts.map +1 -1
- package/dist/validation/core.js +6 -2
- package/dist/validation/core.js.map +1 -1
- package/dist/viem/Client.d.ts.map +1 -1
- package/dist/viem/Client.js +24 -17
- package/dist/viem/Client.js.map +1 -1
- package/package.json +6 -1
- package/src/Errors.test.ts +23 -0
- package/src/Errors.ts +21 -2
- package/src/Method.test.ts +102 -1
- package/src/Method.ts +241 -5
- package/src/cli/account.ts +45 -10
- package/src/cli/cli.test.ts +165 -70
- package/src/cli/cli.ts +67 -2
- package/src/cli/mcp.test.ts +11 -0
- package/src/cli/sessions/Manager.test.ts +249 -0
- package/src/cli/sessions/Manager.ts +93 -0
- package/src/cli/sessions/commands.ts +444 -0
- package/src/cli/sessions/request.test.ts +51 -0
- package/src/cli/sessions/request.ts +353 -0
- package/src/cli/sessions/store.test.ts +581 -0
- package/src/cli/sessions/store.ts +940 -0
- package/src/cli/utils.test.ts +23 -0
- package/src/cli/utils.ts +10 -0
- package/src/cli/validate/index.ts +12 -14
- package/src/cli/validate/messages.ts +7 -0
- package/src/cli/validate.test.ts +38 -5
- package/src/client/Mppx.test-d.ts +3 -3
- package/src/client/internal/Fetch.ts +16 -7
- package/src/client/internal/MethodChallenge.ts +30 -0
- package/src/client/node.test.ts +115 -0
- package/src/client/node.ts +247 -0
- package/src/internal/types.test-d.ts +21 -0
- package/src/internal/types.ts +33 -0
- package/src/server/Mppx.test-d.ts +44 -0
- package/src/server/Mppx.test.ts +205 -0
- package/src/server/Mppx.ts +167 -103
- package/src/stripe/Methods.test.ts +10 -0
- package/src/stripe/server/Charge.test-d.ts +66 -0
- package/src/stripe/server/Charge.ts +8 -5
- package/src/stripe/server/internal/html.gen.ts +1 -1
- package/src/tempo/PublicExports.test-d.ts +20 -0
- package/src/tempo/internal/fee-payer.ts +7 -3
- package/src/tempo/internal/types.ts +13 -2
- package/src/tempo/legacy/client/ChannelOps.test.ts +7 -0
- package/src/tempo/legacy/client/ChannelOps.ts +2 -1
- package/src/tempo/legacy/server/Defaults.test-d.ts +9 -0
- package/src/tempo/legacy/server/Session.ts +6 -5
- package/src/tempo/server/Charge.test.ts +337 -63
- package/src/tempo/server/Charge.ts +440 -270
- package/src/tempo/server/Methods.ts +16 -4
- package/src/tempo/server/Relay.test.ts +523 -0
- package/src/tempo/server/Relay.ts +288 -0
- package/src/tempo/server/SponsorBudget.test.ts +125 -0
- package/src/tempo/server/SponsorBudget.ts +213 -0
- package/src/tempo/server/Subscription.ts +6 -4
- package/src/tempo/server/index.ts +5 -1
- package/src/tempo/server/internal/html.gen.ts +1 -1
- package/src/tempo/session/README.md +201 -0
- package/src/tempo/session/Snapshot.ts +21 -0
- package/src/tempo/session/client/ChannelOps.test.ts +55 -0
- package/src/tempo/session/client/ChannelOps.ts +21 -3
- package/src/tempo/session/client/CredentialState.test.ts +2 -2
- package/src/tempo/session/client/CredentialState.ts +159 -16
- package/src/tempo/session/client/Runtime.test.ts +12 -0
- package/src/tempo/session/client/Runtime.ts +22 -0
- package/src/tempo/session/client/Session.test.ts +238 -5
- package/src/tempo/session/client/Session.ts +130 -41
- package/src/tempo/session/client/SessionManager.test.ts +239 -8
- package/src/tempo/session/client/SessionManager.ts +204 -54
- package/src/tempo/session/client/Transports.test.ts +181 -8
- package/src/tempo/session/client/Transports.ts +127 -45
- package/src/tempo/session/client/internal/SessionManager.ts +36 -0
- package/src/tempo/session/precompile/Chain.integration.test.ts +19 -1
- package/src/tempo/session/precompile/Chain.test.ts +223 -10
- package/src/tempo/session/precompile/Chain.ts +119 -12
- package/src/tempo/session/precompile/Channel.test.ts +9 -0
- package/src/tempo/session/precompile/Channel.ts +5 -0
- package/src/tempo/session/server/CredentialVerification.ts +18 -1
- package/src/tempo/session/server/MeteredStream.ts +12 -5
- package/src/tempo/session/server/RequestState.test.ts +47 -4
- package/src/tempo/session/server/RequestState.ts +15 -8
- package/src/tempo/session/server/Session.test.ts +461 -0
- package/src/tempo/session/server/Session.ts +31 -8
- package/src/tempo/session/server/Settlement.ts +45 -0
- package/src/tempo/session/server/Ws.test.ts +113 -0
- package/src/tempo/session/server/Ws.ts +2 -0
- package/src/tempo/session/server/index.ts +2 -0
- package/src/validation/core.ts +7 -1
- package/src/viem/Client.test.ts +44 -1
- package/src/viem/Client.ts +31 -17
package/src/internal/types.ts
CHANGED
|
@@ -277,6 +277,39 @@ export type ExactPartial<type> = {
|
|
|
277
277
|
[key in keyof type]?: type[key] | undefined
|
|
278
278
|
}
|
|
279
279
|
|
|
280
|
+
/**
|
|
281
|
+
* Keys whose values are known to be present and defined.
|
|
282
|
+
*
|
|
283
|
+
* This is useful when a factory accepts partial configuration and its return
|
|
284
|
+
* type needs to distinguish values supplied as defaults from fields that
|
|
285
|
+
* callers must still provide later. Optional and `undefined`-able properties
|
|
286
|
+
* are excluded because their runtime values cannot be assumed to be defaults.
|
|
287
|
+
*
|
|
288
|
+
* @internal
|
|
289
|
+
*/
|
|
290
|
+
export type DefinedKeys<type> = {
|
|
291
|
+
[key in keyof type]-?: {} extends Pick<type, key>
|
|
292
|
+
? never
|
|
293
|
+
: undefined extends type[key]
|
|
294
|
+
? never
|
|
295
|
+
: key
|
|
296
|
+
}[keyof type]
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Request defaults known to have been configured by a factory caller.
|
|
300
|
+
*
|
|
301
|
+
* Optional and `undefined`-able parameters are omitted: their runtime values
|
|
302
|
+
* are not guaranteed to be usable defaults for a subsequently returned
|
|
303
|
+
* handler. Factories can intersect this type with values they resolve
|
|
304
|
+
* unconditionally at runtime.
|
|
305
|
+
*
|
|
306
|
+
* @internal
|
|
307
|
+
*/
|
|
308
|
+
export type ConfiguredDefaults<parameters, defaults> = Pick<
|
|
309
|
+
parameters,
|
|
310
|
+
Extract<DefinedKeys<parameters>, keyof defaults>
|
|
311
|
+
>
|
|
312
|
+
|
|
280
313
|
/** @internal */
|
|
281
314
|
export type ExactRequired<type> = {
|
|
282
315
|
[key in keyof type]-?: Exclude<type[key], undefined>
|
|
@@ -223,6 +223,8 @@ describe('Mppx type tests', () => {
|
|
|
223
223
|
const mppx = Mppx.create({ methods: [alphaMethod], realm, secretKey })
|
|
224
224
|
|
|
225
225
|
expectTypeOf(mppx.verifyCredential).toBeFunction()
|
|
226
|
+
expectTypeOf(mppx.broadcastCredential).toBeFunction()
|
|
227
|
+
expectTypeOf(mppx.validateCredential).toBeFunction()
|
|
226
228
|
})
|
|
227
229
|
|
|
228
230
|
test('server events receive typed method context', () => {
|
|
@@ -313,4 +315,46 @@ describe('Mppx type tests', () => {
|
|
|
313
315
|
}),
|
|
314
316
|
).toBeFunction()
|
|
315
317
|
})
|
|
318
|
+
|
|
319
|
+
test('tempo factories expose resolved currency and decimals as defaults', () => {
|
|
320
|
+
const charge = Mppx.create({ methods: [tempo.charge()], realm, secretKey })
|
|
321
|
+
expectTypeOf(charge.tempo.charge({ amount: '1' })).toBeFunction()
|
|
322
|
+
// @ts-expect-error amount is not supplied by Tempo's runtime defaults.
|
|
323
|
+
void charge.tempo.charge({})
|
|
324
|
+
|
|
325
|
+
const subscription = Mppx.create({
|
|
326
|
+
methods: [
|
|
327
|
+
tempo.subscription({
|
|
328
|
+
recipient: '0x1234567890abcdef1234567890abcdef12345678',
|
|
329
|
+
resolve: async () => null,
|
|
330
|
+
}),
|
|
331
|
+
],
|
|
332
|
+
realm,
|
|
333
|
+
secretKey,
|
|
334
|
+
})
|
|
335
|
+
expectTypeOf(
|
|
336
|
+
subscription.tempo.subscription({
|
|
337
|
+
amount: '1',
|
|
338
|
+
periodCount: 1n,
|
|
339
|
+
periodUnit: 'day',
|
|
340
|
+
subscriptionExpires: new Date('2026-01-01T00:00:00Z'),
|
|
341
|
+
}),
|
|
342
|
+
).toBeFunction()
|
|
343
|
+
|
|
344
|
+
const session = Mppx.create({ methods: [tempo.session()], realm, secretKey })
|
|
345
|
+
expectTypeOf(session.tempo.session({ amount: '1', unitType: 'request' })).toBeFunction()
|
|
346
|
+
|
|
347
|
+
const common = Mppx.create({
|
|
348
|
+
methods: [
|
|
349
|
+
tempo.common({
|
|
350
|
+
amount: '1',
|
|
351
|
+
recipient: '0x1234567890abcdef1234567890abcdef12345678',
|
|
352
|
+
}),
|
|
353
|
+
],
|
|
354
|
+
realm,
|
|
355
|
+
secretKey,
|
|
356
|
+
})
|
|
357
|
+
expectTypeOf(common.tempo.charge({})).toBeFunction()
|
|
358
|
+
expectTypeOf(common.tempo.session({ unitType: 'request' })).toBeFunction()
|
|
359
|
+
})
|
|
316
360
|
})
|
package/src/server/Mppx.test.ts
CHANGED
|
@@ -4872,6 +4872,211 @@ describe('verifyCredential', () => {
|
|
|
4872
4872
|
expect(verifyArgs).toBeDefined()
|
|
4873
4873
|
})
|
|
4874
4874
|
|
|
4875
|
+
test('validateCredential uses pure method validation without broadcast', async () => {
|
|
4876
|
+
const calls: string[] = []
|
|
4877
|
+
const splitServer = Method.toServer(mockCharge, {
|
|
4878
|
+
async validate({ credential, request }) {
|
|
4879
|
+
calls.push('validate')
|
|
4880
|
+
return {
|
|
4881
|
+
challenge: credential.challenge,
|
|
4882
|
+
credential,
|
|
4883
|
+
details: { token: credential.payload.token },
|
|
4884
|
+
intent: 'charge',
|
|
4885
|
+
method: 'alpha',
|
|
4886
|
+
request,
|
|
4887
|
+
source: credential.source,
|
|
4888
|
+
}
|
|
4889
|
+
},
|
|
4890
|
+
async broadcast() {
|
|
4891
|
+
calls.push('broadcast')
|
|
4892
|
+
return mockReceipt('broadcast')
|
|
4893
|
+
},
|
|
4894
|
+
})
|
|
4895
|
+
const mppx = Mppx.create({ methods: [splitServer], realm, secretKey })
|
|
4896
|
+
const challenge = await mppx.challenge.alpha.charge(challengeOpts)
|
|
4897
|
+
const credential = Credential.from({ challenge, payload: { token: 'valid' } })
|
|
4898
|
+
|
|
4899
|
+
const validation = await mppx.validateCredential(credential)
|
|
4900
|
+
|
|
4901
|
+
expect(validation.details).toEqual({ token: 'valid' })
|
|
4902
|
+
expect(calls).toEqual(['validate'])
|
|
4903
|
+
})
|
|
4904
|
+
|
|
4905
|
+
test('broadcastCredential revalidates and uses method broadcast', async () => {
|
|
4906
|
+
const calls: string[] = []
|
|
4907
|
+
const splitServer = Method.toServer(mockCharge, {
|
|
4908
|
+
async validate({ credential, request }) {
|
|
4909
|
+
calls.push('validate')
|
|
4910
|
+
return {
|
|
4911
|
+
challenge: credential.challenge,
|
|
4912
|
+
credential,
|
|
4913
|
+
details: {},
|
|
4914
|
+
intent: 'charge',
|
|
4915
|
+
method: 'alpha',
|
|
4916
|
+
request,
|
|
4917
|
+
source: credential.source,
|
|
4918
|
+
}
|
|
4919
|
+
},
|
|
4920
|
+
async broadcast() {
|
|
4921
|
+
calls.push('broadcast')
|
|
4922
|
+
return mockReceipt('broadcast')
|
|
4923
|
+
},
|
|
4924
|
+
})
|
|
4925
|
+
const mppx = Mppx.create({ methods: [splitServer], realm, secretKey })
|
|
4926
|
+
const challenge = await mppx.challenge.alpha.charge(challengeOpts)
|
|
4927
|
+
const credential = Credential.from({ challenge, payload: { token: 'valid' } })
|
|
4928
|
+
|
|
4929
|
+
const receipt = await mppx.broadcastCredential(credential)
|
|
4930
|
+
|
|
4931
|
+
expect(receipt.method).toBe('broadcast')
|
|
4932
|
+
expect(calls).toEqual(['validate', 'broadcast'])
|
|
4933
|
+
})
|
|
4934
|
+
|
|
4935
|
+
test('verifyCredential remains a legacy alias for broadcast', async () => {
|
|
4936
|
+
const calls: string[] = []
|
|
4937
|
+
const splitServer = Method.toServer(mockCharge, {
|
|
4938
|
+
async validate({ credential, request }) {
|
|
4939
|
+
calls.push('validate')
|
|
4940
|
+
return {
|
|
4941
|
+
challenge: credential.challenge,
|
|
4942
|
+
credential,
|
|
4943
|
+
details: {},
|
|
4944
|
+
intent: 'charge',
|
|
4945
|
+
method: 'alpha',
|
|
4946
|
+
request,
|
|
4947
|
+
source: credential.source,
|
|
4948
|
+
}
|
|
4949
|
+
},
|
|
4950
|
+
async broadcast() {
|
|
4951
|
+
calls.push('broadcast')
|
|
4952
|
+
return mockReceipt('broadcast')
|
|
4953
|
+
},
|
|
4954
|
+
})
|
|
4955
|
+
const mppx = Mppx.create({ methods: [splitServer], realm, secretKey })
|
|
4956
|
+
const challenge = await mppx.challenge.alpha.charge(challengeOpts)
|
|
4957
|
+
const credential = Credential.from({ challenge, payload: { token: 'valid' } })
|
|
4958
|
+
|
|
4959
|
+
const receipt = await mppx.verifyCredential(credential)
|
|
4960
|
+
|
|
4961
|
+
expect(receipt.method).toBe('broadcast')
|
|
4962
|
+
expect(calls).toEqual(['validate', 'broadcast'])
|
|
4963
|
+
})
|
|
4964
|
+
|
|
4965
|
+
test('validateCredential rejects legacy-only methods without emitting payment failure', async () => {
|
|
4966
|
+
const events: string[] = []
|
|
4967
|
+
const mppx = Mppx.create({ methods: [alphaChargeServer], realm, secretKey })
|
|
4968
|
+
mppx.onPaymentFailed((context) => {
|
|
4969
|
+
events.push(context.error.name)
|
|
4970
|
+
})
|
|
4971
|
+
const challenge = await mppx.challenge.alpha.charge(challengeOpts)
|
|
4972
|
+
const credential = Credential.from({ challenge, payload: { token: 'valid' } })
|
|
4973
|
+
|
|
4974
|
+
await expect(mppx.validateCredential(credential)).rejects.toThrow(
|
|
4975
|
+
'does not support non-mutating credential validation',
|
|
4976
|
+
)
|
|
4977
|
+
|
|
4978
|
+
expect(events).toEqual([])
|
|
4979
|
+
})
|
|
4980
|
+
|
|
4981
|
+
test('validateCredential enforces supplied route requirements', async () => {
|
|
4982
|
+
const splitServer = Method.toServer(mockCharge, {
|
|
4983
|
+
async validate({ credential, request }) {
|
|
4984
|
+
return {
|
|
4985
|
+
challenge: credential.challenge,
|
|
4986
|
+
credential,
|
|
4987
|
+
details: { amount: request.amount },
|
|
4988
|
+
intent: 'charge',
|
|
4989
|
+
method: 'alpha',
|
|
4990
|
+
request,
|
|
4991
|
+
source: credential.source,
|
|
4992
|
+
}
|
|
4993
|
+
},
|
|
4994
|
+
async broadcast() {
|
|
4995
|
+
return mockReceipt('broadcast')
|
|
4996
|
+
},
|
|
4997
|
+
})
|
|
4998
|
+
const mppx = Mppx.create({ methods: [splitServer], realm, secretKey })
|
|
4999
|
+
const challenge = await mppx.challenge.alpha.charge(challengeOpts)
|
|
5000
|
+
const credential = Credential.from({ challenge, payload: { token: 'valid' } })
|
|
5001
|
+
|
|
5002
|
+
const validation = await mppx.validateCredential(credential, { request: challengeOpts })
|
|
5003
|
+
expect(validation.details).toEqual({ amount: '1000' })
|
|
5004
|
+
|
|
5005
|
+
await expect(
|
|
5006
|
+
mppx.validateCredential(credential, {
|
|
5007
|
+
request: {
|
|
5008
|
+
...challengeOpts,
|
|
5009
|
+
amount: '2000',
|
|
5010
|
+
},
|
|
5011
|
+
}),
|
|
5012
|
+
).rejects.toThrow('credential amount does not match this route')
|
|
5013
|
+
})
|
|
5014
|
+
|
|
5015
|
+
test('broadcastCredential emits payment failure when split validation fails', async () => {
|
|
5016
|
+
const calls: string[] = []
|
|
5017
|
+
const events: string[] = []
|
|
5018
|
+
const splitServer = Method.toServer(mockCharge, {
|
|
5019
|
+
async validate() {
|
|
5020
|
+
calls.push('validate')
|
|
5021
|
+
throw new Errors.VerificationFailedError({ reason: 'risk denied' })
|
|
5022
|
+
},
|
|
5023
|
+
async broadcast() {
|
|
5024
|
+
calls.push('broadcast')
|
|
5025
|
+
return mockReceipt('broadcast')
|
|
5026
|
+
},
|
|
5027
|
+
})
|
|
5028
|
+
const mppx = Mppx.create({ methods: [splitServer], realm, secretKey })
|
|
5029
|
+
mppx.onPaymentFailed((context) => {
|
|
5030
|
+
events.push(context.error.name)
|
|
5031
|
+
})
|
|
5032
|
+
const challenge = await mppx.challenge.alpha.charge(challengeOpts)
|
|
5033
|
+
const credential = Credential.from({ challenge, payload: { token: 'valid' } })
|
|
5034
|
+
|
|
5035
|
+
await expect(mppx.broadcastCredential(credential)).rejects.toThrow('risk denied')
|
|
5036
|
+
|
|
5037
|
+
expect(calls).toEqual(['validate'])
|
|
5038
|
+
expect(events).toEqual(['VerificationFailedError'])
|
|
5039
|
+
})
|
|
5040
|
+
|
|
5041
|
+
test('route handlers revalidate before broadcast for split methods', async () => {
|
|
5042
|
+
const calls: string[] = []
|
|
5043
|
+
const splitServer = Method.toServer(mockCharge, {
|
|
5044
|
+
async validate({ credential, request }) {
|
|
5045
|
+
calls.push('validate')
|
|
5046
|
+
return {
|
|
5047
|
+
challenge: credential.challenge,
|
|
5048
|
+
credential,
|
|
5049
|
+
details: {},
|
|
5050
|
+
intent: 'charge',
|
|
5051
|
+
method: 'alpha',
|
|
5052
|
+
request,
|
|
5053
|
+
source: credential.source,
|
|
5054
|
+
}
|
|
5055
|
+
},
|
|
5056
|
+
async broadcast() {
|
|
5057
|
+
calls.push('broadcast')
|
|
5058
|
+
return mockReceipt('broadcast')
|
|
5059
|
+
},
|
|
5060
|
+
})
|
|
5061
|
+
const mppx = Mppx.create({ methods: [splitServer], realm, secretKey })
|
|
5062
|
+
const firstResult = await mppx.charge(challengeOpts)(
|
|
5063
|
+
new Request('https://api.example.com/resource'),
|
|
5064
|
+
)
|
|
5065
|
+
expect(firstResult.status).toBe(402)
|
|
5066
|
+
if (firstResult.status !== 402) throw new Error()
|
|
5067
|
+
|
|
5068
|
+
const challenge = Challenge.fromResponse(firstResult.challenge)
|
|
5069
|
+
const credential = Credential.from({ challenge, payload: { token: 'valid' } })
|
|
5070
|
+
const result = await mppx.charge(challengeOpts)(
|
|
5071
|
+
new Request('https://api.example.com/resource', {
|
|
5072
|
+
headers: { Authorization: Credential.serialize(credential) },
|
|
5073
|
+
}),
|
|
5074
|
+
)
|
|
5075
|
+
|
|
5076
|
+
expect(result.status).toBe(200)
|
|
5077
|
+
expect(calls).toEqual(['validate', 'broadcast'])
|
|
5078
|
+
})
|
|
5079
|
+
|
|
4875
5080
|
test('verifies a parsed Credential object (charge)', async () => {
|
|
4876
5081
|
verifyArgs = undefined
|
|
4877
5082
|
const mppx = Mppx.create({
|