mppx 0.8.6 → 0.8.8
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 +19 -0
- package/dist/cli/internal.js +2 -2
- package/dist/cli/internal.js.map +1 -1
- package/dist/cli/plugins/evm.d.ts +2 -0
- package/dist/cli/plugins/evm.d.ts.map +1 -0
- package/dist/cli/plugins/evm.js +51 -0
- package/dist/cli/plugins/evm.js.map +1 -0
- package/dist/cli/plugins/index.d.ts +1 -0
- package/dist/cli/plugins/index.d.ts.map +1 -1
- package/dist/cli/plugins/index.js +1 -0
- package/dist/cli/plugins/index.js.map +1 -1
- package/dist/cli/plugins/stripe.d.ts.map +1 -1
- package/dist/cli/plugins/stripe.js +3 -2
- package/dist/cli/plugins/stripe.js.map +1 -1
- package/dist/cli/validate/challenge.d.ts +2 -0
- package/dist/cli/validate/challenge.d.ts.map +1 -1
- package/dist/cli/validate/challenge.js +191 -84
- package/dist/cli/validate/challenge.js.map +1 -1
- package/dist/cli/validate/discovery.d.ts +1 -0
- package/dist/cli/validate/discovery.d.ts.map +1 -1
- package/dist/cli/validate/discovery.js +99 -35
- package/dist/cli/validate/discovery.js.map +1 -1
- package/dist/cli/validate/helpers.d.ts +14 -1
- package/dist/cli/validate/helpers.d.ts.map +1 -1
- package/dist/cli/validate/helpers.js +0 -13
- package/dist/cli/validate/helpers.js.map +1 -1
- package/dist/cli/validate/index.d.ts +1 -0
- package/dist/cli/validate/index.d.ts.map +1 -1
- package/dist/cli/validate/index.js +102 -153
- package/dist/cli/validate/index.js.map +1 -1
- package/dist/cli/validate/payment.d.ts +4 -1
- package/dist/cli/validate/payment.d.ts.map +1 -1
- package/dist/cli/validate/payment.js +312 -106
- package/dist/cli/validate/payment.js.map +1 -1
- package/dist/evm/Chains.d.ts +4 -0
- package/dist/evm/Chains.d.ts.map +1 -1
- package/dist/evm/Chains.js +4 -0
- package/dist/evm/Chains.js.map +1 -1
- package/dist/internal/AcceptPayment.d.ts.map +1 -1
- package/dist/internal/AcceptPayment.js +7 -1
- package/dist/internal/AcceptPayment.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/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/server/internal/request-body.d.ts.map +1 -1
- package/dist/tempo/server/internal/request-body.js +2 -0
- package/dist/tempo/server/internal/request-body.js.map +1 -1
- package/dist/tempo/session/server/ChannelStore.js +4 -4
- package/dist/tempo/session/server/ChannelStore.js.map +1 -1
- package/dist/tempo/session/server/CredentialVerification.d.ts +8 -0
- package/dist/tempo/session/server/CredentialVerification.d.ts.map +1 -1
- package/dist/tempo/session/server/CredentialVerification.js +21 -1
- package/dist/tempo/session/server/CredentialVerification.js.map +1 -1
- package/dist/tempo/session/server/Session.d.ts.map +1 -1
- package/dist/tempo/session/server/Session.js +1 -0
- package/dist/tempo/session/server/Session.js.map +1 -1
- package/dist/validation/core.d.ts +75 -0
- package/dist/validation/core.d.ts.map +1 -0
- package/dist/validation/core.js +269 -0
- package/dist/validation/core.js.map +1 -0
- package/dist/validation/index.d.ts +3 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +2 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/x402/Assets.d.ts +9 -0
- package/dist/x402/Assets.d.ts.map +1 -1
- package/dist/x402/Assets.js +38 -0
- package/dist/x402/Assets.js.map +1 -1
- package/package.json +9 -4
- package/src/cli/internal.ts +2 -2
- package/src/cli/plugins/evm.ts +55 -0
- package/src/cli/plugins/index.ts +1 -0
- package/src/cli/plugins/stripe.ts +3 -2
- package/src/cli/validate/challenge.ts +345 -127
- package/src/cli/validate/discovery.test.ts +307 -0
- package/src/cli/validate/discovery.ts +104 -38
- package/src/cli/validate/helpers.ts +15 -13
- package/src/cli/validate/index.ts +121 -242
- package/src/cli/validate/payment.ts +413 -144
- package/src/cli/validate.test.ts +237 -3
- package/src/client/internal/Fetch.test.ts +142 -2
- package/src/evm/Chains.ts +6 -0
- package/src/evm/PublicInterface.test-d.ts +7 -0
- package/src/internal/AcceptPayment.test.ts +45 -0
- package/src/internal/AcceptPayment.ts +11 -1
- package/src/stripe/server/internal/html/package.json +1 -1
- package/src/stripe/server/internal/html.gen.ts +1 -1
- package/src/tempo/server/internal/html/package.json +1 -1
- package/src/tempo/server/internal/html.gen.ts +1 -1
- package/src/tempo/server/internal/request-body.test.ts +9 -0
- package/src/tempo/server/internal/request-body.ts +2 -0
- package/src/tempo/session/server/ChannelStore.test.ts +17 -0
- package/src/tempo/session/server/ChannelStore.ts +4 -4
- package/src/tempo/session/server/CredentialVerification.test.ts +118 -1
- package/src/tempo/session/server/CredentialVerification.ts +30 -0
- package/src/tempo/session/server/Session.integration.test.ts +5 -0
- package/src/tempo/session/server/Session.test.ts +119 -53
- package/src/tempo/session/server/Session.ts +1 -0
- package/src/validation/core.ts +374 -0
- package/src/validation/index.ts +11 -0
- package/src/x402/Assets.test.ts +42 -0
- package/src/x402/Assets.ts +40 -0
- package/src/x402/Exact.localnet.test.ts +475 -0
|
@@ -1,25 +1,9 @@
|
|
|
1
1
|
import { Cli, z } from 'incur'
|
|
2
2
|
|
|
3
|
-
import { validate as
|
|
3
|
+
import { validate as validateCore, validateStream } from '../../validation/core.js'
|
|
4
4
|
import { pc } from '../utils.js'
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
extractEndpointsFromDiscovery,
|
|
8
|
-
extractRequestBodyFromDiscovery,
|
|
9
|
-
fetchDiscoveryDoc,
|
|
10
|
-
} from './discovery.js'
|
|
11
|
-
import {
|
|
12
|
-
check,
|
|
13
|
-
fail,
|
|
14
|
-
parseEndpointArg,
|
|
15
|
-
printCheck,
|
|
16
|
-
printResults,
|
|
17
|
-
printSection,
|
|
18
|
-
resolveBodyForEndpoint,
|
|
19
|
-
warn,
|
|
20
|
-
} from './helpers.js'
|
|
21
|
-
import type { Counts, EndpointSpec } from './helpers.js'
|
|
22
|
-
import { validatePaymentFlow } from './payment.js'
|
|
5
|
+
import type { Counts } from './helpers.js'
|
|
6
|
+
import { printResults, printSection } from './helpers.js'
|
|
23
7
|
|
|
24
8
|
const validate = Cli.create('validate', {
|
|
25
9
|
description: 'Validate an MPP server implementation end-to-end',
|
|
@@ -37,260 +21,157 @@ const validate = Cli.create('validate', {
|
|
|
37
21
|
query: z.array(z.string()).optional().describe('Query parameter (key=value, repeatable)'),
|
|
38
22
|
verbose: z.number().default(0).meta({ count: true }).describe('Verbosity level'),
|
|
39
23
|
yes: z.boolean().default(false).describe('Auto-approve mainnet payments'),
|
|
24
|
+
outputJson: z.boolean().default(false).describe('Output results as JSON'),
|
|
40
25
|
}),
|
|
41
26
|
alias: {
|
|
42
27
|
endpoint: 'e',
|
|
43
28
|
verbose: 'v',
|
|
44
29
|
yes: 'y',
|
|
30
|
+
outputJson: 'j',
|
|
45
31
|
},
|
|
46
32
|
async run(c) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
33
|
+
// JSON mode: batch everything
|
|
34
|
+
if (c.options.outputJson) {
|
|
35
|
+
const result = await validateCore({
|
|
36
|
+
url: c.args.url,
|
|
37
|
+
endpoint: c.options.endpoint,
|
|
38
|
+
body: c.options.body,
|
|
39
|
+
query: c.options.query,
|
|
40
|
+
verbose: c.options.verbose > 0,
|
|
41
|
+
yes: c.options.yes,
|
|
42
|
+
interactive: false,
|
|
43
|
+
})
|
|
44
|
+
console.log(JSON.stringify(result, null, 2))
|
|
45
|
+
const noEndpoints = result.endpoints.length === 0 && !c.options.endpoint
|
|
46
|
+
if (result.summary.failed > 0 || !result.discovery.found || noEndpoints) process.exit(1)
|
|
47
|
+
return
|
|
48
|
+
}
|
|
50
49
|
|
|
50
|
+
// Streaming human-readable output
|
|
51
|
+
const baseUrl = c.args.url.replace(/\/$/, '').replace(/\/openapi\.json$/i, '')
|
|
51
52
|
console.log(`\n${pc.bold('mppx validate')} ${pc.dim(baseUrl)}\n`)
|
|
52
53
|
|
|
53
|
-
const {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
const counts: Counts = { passed: 0, failed: 0, warnings: 0, skipped: 0 }
|
|
55
|
+
let sawMppEndpoint = false
|
|
56
|
+
let sawNonMppPaymentEndpoint = false
|
|
57
|
+
let sawMalformedChallenge = false
|
|
58
|
+
let sawTestnet = false
|
|
59
|
+
let sawMainnet = false
|
|
60
|
+
let paymentSucceeded = false
|
|
61
|
+
let discoveryFound = false
|
|
62
|
+
let endpointCount = 0
|
|
63
|
+
|
|
64
|
+
for await (const event of validateStream({
|
|
65
|
+
url: c.args.url,
|
|
61
66
|
endpoint: c.options.endpoint,
|
|
62
67
|
body: c.options.body,
|
|
63
68
|
query: c.options.query,
|
|
69
|
+
verbose: c.options.verbose > 0,
|
|
64
70
|
yes: c.options.yes,
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
} else {
|
|
119
|
-
printCheck(check('Document found and parseable'))
|
|
120
|
-
counts.passed++
|
|
121
|
-
|
|
122
|
-
const issues = validateDiscovery(discoveryResult.doc)
|
|
123
|
-
const errors = issues.filter((i) => i.severity === 'error')
|
|
124
|
-
const warnings = issues.filter((i) => i.severity === 'warning')
|
|
125
|
-
|
|
126
|
-
if (errors.length > 0) {
|
|
127
|
-
printCheck(fail('Valid OpenAPI structure', `${errors.length} error(s)`))
|
|
128
|
-
counts.failed++
|
|
129
|
-
for (const issue of errors) {
|
|
130
|
-
console.log(pc.dim(` ${issue.path}: ${issue.message}`))
|
|
71
|
+
interactive: !!process.stdin.isTTY,
|
|
72
|
+
onPaymentResults: (results) => printResults(results, counts),
|
|
73
|
+
})) {
|
|
74
|
+
switch (event.phase) {
|
|
75
|
+
case 'discovery':
|
|
76
|
+
printSection('Discovery (/openapi.json)')
|
|
77
|
+
printResults(event.results, counts)
|
|
78
|
+
discoveryFound = event.discovery.found
|
|
79
|
+
if (!discoveryFound && !c.options.endpoint) {
|
|
80
|
+
console.log('')
|
|
81
|
+
console.log(pc.yellow(' No discovery document found.'))
|
|
82
|
+
console.log(
|
|
83
|
+
pc.dim(
|
|
84
|
+
' MPP servers must serve an OpenAPI document at /openapi.json with x-payment-info extensions.',
|
|
85
|
+
),
|
|
86
|
+
)
|
|
87
|
+
console.log(
|
|
88
|
+
pc.dim(
|
|
89
|
+
' To test a specific endpoint: mppx validate <url> --endpoint POST:/your/path',
|
|
90
|
+
),
|
|
91
|
+
)
|
|
92
|
+
console.log('')
|
|
93
|
+
process.exit(1)
|
|
94
|
+
}
|
|
95
|
+
if (event.discovery.endpoints.length === 0 && !c.options.endpoint && discoveryFound) {
|
|
96
|
+
console.log(pc.dim(' Use --endpoint to specify endpoints manually.'))
|
|
97
|
+
console.log('')
|
|
98
|
+
process.exit(1)
|
|
99
|
+
}
|
|
100
|
+
break
|
|
101
|
+
case 'endpoint':
|
|
102
|
+
endpointCount++
|
|
103
|
+
printSection(`${event.endpoint.method} ${event.endpoint.path}`)
|
|
104
|
+
break
|
|
105
|
+
case 'challenge':
|
|
106
|
+
console.log(pc.dim(' Challenge'))
|
|
107
|
+
printResults(event.results, counts)
|
|
108
|
+
if (event.isMpp) {
|
|
109
|
+
sawMppEndpoint = true
|
|
110
|
+
if (event.isTestnet) sawTestnet = true
|
|
111
|
+
if (event.isMainnet) sawMainnet = true
|
|
112
|
+
}
|
|
113
|
+
if (event.isNonMppPayment) sawNonMppPaymentEndpoint = true
|
|
114
|
+
if (event.isMalformedChallenge) sawMalformedChallenge = true
|
|
115
|
+
break
|
|
116
|
+
case 'errorHandling':
|
|
117
|
+
console.log(pc.dim(' Error Handling'))
|
|
118
|
+
printResults(event.results, counts)
|
|
119
|
+
break
|
|
120
|
+
case 'payment':
|
|
121
|
+
if (event.succeeded) paymentSucceeded = true
|
|
122
|
+
break
|
|
131
123
|
}
|
|
132
|
-
} else {
|
|
133
|
-
printCheck(check('Valid OpenAPI structure'))
|
|
134
|
-
counts.passed++
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
for (const w of warnings) {
|
|
138
|
-
printCheck(warn(w.message, w.path))
|
|
139
|
-
counts.warnings++
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
discoveryDoc = discoveryResult.doc as Record<string, unknown>
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Resolve endpoints: --endpoint overrides discovery
|
|
146
|
-
if (options.endpoint) {
|
|
147
|
-
const parsed = parseEndpointArg(options.endpoint)
|
|
148
|
-
if (!parsed) {
|
|
149
|
-
console.log(
|
|
150
|
-
pc.red(
|
|
151
|
-
`Invalid endpoint format: "${options.endpoint}". Use METHOD:path (e.g. GET:/api/data)`,
|
|
152
|
-
),
|
|
153
|
-
)
|
|
154
|
-
return { endpoints, discoveryDoc, shouldExit: true }
|
|
155
124
|
}
|
|
156
|
-
endpoints.push(parsed)
|
|
157
|
-
} else if (discoveryDoc) {
|
|
158
|
-
endpoints = extractEndpointsFromDiscovery(discoveryDoc)
|
|
159
125
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const bAmt = b.amount ? BigInt(b.amount) : NO_AMOUNT
|
|
164
|
-
return aAmt < bAmt ? -1 : aAmt > bAmt ? 1 : 0
|
|
165
|
-
})
|
|
166
|
-
|
|
167
|
-
if (endpoints.length === 0) {
|
|
168
|
-
printCheck(warn('Paid endpoints found', 'No endpoints with x-payment-info'))
|
|
169
|
-
counts.warnings++
|
|
170
|
-
console.log(pc.dim(' Use --endpoint to specify endpoints manually.'))
|
|
171
|
-
return { endpoints, discoveryDoc, shouldExit: true }
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
printCheck(check('Paid endpoints found', `${endpoints.length} endpoint(s)`))
|
|
175
|
-
counts.passed++
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
return { endpoints, discoveryDoc }
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
async function validateEndpoints(
|
|
182
|
-
baseUrl: string,
|
|
183
|
-
endpoints: EndpointSpec[],
|
|
184
|
-
discoveryDoc: Record<string, unknown> | null,
|
|
185
|
-
counts: Counts,
|
|
186
|
-
options: {
|
|
187
|
-
verbose: boolean
|
|
188
|
-
endpoint?: string | undefined
|
|
189
|
-
body?: string | undefined
|
|
190
|
-
query?: string[] | undefined
|
|
191
|
-
yes: boolean
|
|
192
|
-
},
|
|
193
|
-
): Promise<{
|
|
194
|
-
sawMppEndpoint: boolean
|
|
195
|
-
sawNonMppPaymentEndpoint: boolean
|
|
196
|
-
sawTestnet: boolean
|
|
197
|
-
sawMainnet: boolean
|
|
198
|
-
paymentSucceeded: boolean
|
|
199
|
-
}> {
|
|
200
|
-
let sawTestnet = false
|
|
201
|
-
let sawMainnet = false
|
|
202
|
-
let paymentSucceeded = false
|
|
203
|
-
let sawMppEndpoint = false
|
|
204
|
-
let sawNonMppPaymentEndpoint = false
|
|
205
|
-
|
|
206
|
-
for (const endpoint of endpoints) {
|
|
207
|
-
printSection(`${endpoint.method} ${endpoint.path}`)
|
|
208
|
-
|
|
209
|
-
// With --endpoint, --body is used directly. In discovery mode, resolve per-path or auto-generate.
|
|
210
|
-
let body: string | undefined
|
|
211
|
-
if (options.endpoint) {
|
|
212
|
-
body = options.body
|
|
213
|
-
} else {
|
|
214
|
-
body = resolveBodyForEndpoint(options.body, endpoint.path)
|
|
215
|
-
if (!body && discoveryDoc) {
|
|
216
|
-
body = extractRequestBodyFromDiscovery(discoveryDoc, endpoint)
|
|
217
|
-
if (body && options.verbose) {
|
|
218
|
-
console.log(pc.dim(` Auto-generated body: ${body}`))
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// Challenge
|
|
224
|
-
console.log(pc.dim(' Challenge'))
|
|
225
|
-
const { results: challengeResults, resolvedBody } = await validateChallenge(
|
|
226
|
-
baseUrl,
|
|
227
|
-
endpoint,
|
|
228
|
-
options.verbose,
|
|
126
|
+
// Summary
|
|
127
|
+
printSummary(
|
|
128
|
+
counts,
|
|
229
129
|
{
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
130
|
+
sawMppEndpoint,
|
|
131
|
+
sawNonMppPaymentEndpoint,
|
|
132
|
+
sawMalformedChallenge,
|
|
133
|
+
sawTestnet,
|
|
134
|
+
sawMainnet,
|
|
135
|
+
paymentSucceeded,
|
|
233
136
|
},
|
|
137
|
+
endpointCount,
|
|
234
138
|
)
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
const isMppEndpoint = challengeResults.some(
|
|
239
|
-
(r) => r.severity === 'pass' && r.label === 'Challenge parseable',
|
|
240
|
-
)
|
|
241
|
-
if (!isMppEndpoint) {
|
|
242
|
-
if (challengeResults.some((r) => r.label === 'Not an MPP endpoint'))
|
|
243
|
-
sawNonMppPaymentEndpoint = true
|
|
244
|
-
continue
|
|
245
|
-
}
|
|
246
|
-
sawMppEndpoint = true
|
|
247
|
-
|
|
248
|
-
const isTestnetEndpoint = challengeResults.some(
|
|
249
|
-
(r) =>
|
|
250
|
-
r.severity === 'pass' && r.label === 'Valid currency address' && r.detail === 'testnet',
|
|
251
|
-
)
|
|
252
|
-
if (isTestnetEndpoint) sawTestnet = true
|
|
253
|
-
else sawMainnet = true
|
|
254
|
-
|
|
255
|
-
// Error Handling
|
|
256
|
-
console.log(pc.dim(' Error Handling'))
|
|
257
|
-
const errorResults = await validateErrorHandling(baseUrl, endpoint, {
|
|
258
|
-
body: effectiveBody,
|
|
259
|
-
query: options.query,
|
|
260
|
-
})
|
|
261
|
-
printResults(errorResults, counts)
|
|
262
|
-
|
|
263
|
-
// Payment
|
|
264
|
-
console.log(pc.dim(' Payment'))
|
|
265
|
-
const paymentResults = await validatePaymentFlow(baseUrl, endpoint, options.verbose, {
|
|
266
|
-
body: effectiveBody,
|
|
267
|
-
query: options.query,
|
|
268
|
-
yes: options.yes,
|
|
269
|
-
})
|
|
270
|
-
printResults(paymentResults, counts)
|
|
271
|
-
if (paymentResults.some((r) => r.severity === 'pass' && r.label === 'Payment: successful')) {
|
|
272
|
-
paymentSucceeded = true
|
|
273
|
-
}
|
|
274
|
-
}
|
|
139
|
+
},
|
|
140
|
+
})
|
|
275
141
|
|
|
276
|
-
|
|
277
|
-
}
|
|
142
|
+
export default validate
|
|
278
143
|
|
|
279
144
|
function printSummary(
|
|
280
145
|
counts: Counts,
|
|
281
146
|
flags: {
|
|
282
147
|
sawMppEndpoint: boolean
|
|
283
148
|
sawNonMppPaymentEndpoint: boolean
|
|
149
|
+
sawMalformedChallenge: boolean
|
|
284
150
|
sawTestnet: boolean
|
|
285
151
|
sawMainnet: boolean
|
|
286
152
|
paymentSucceeded: boolean
|
|
287
153
|
},
|
|
288
154
|
endpointsLength: number,
|
|
289
155
|
): void {
|
|
290
|
-
// No MPP endpoints found
|
|
291
156
|
if (!flags.sawMppEndpoint && endpointsLength > 0) {
|
|
292
157
|
console.log('')
|
|
293
|
-
if (flags.
|
|
158
|
+
if (flags.sawMalformedChallenge) {
|
|
159
|
+
console.log(
|
|
160
|
+
pc.yellow(
|
|
161
|
+
` Payment scheme detected but challenge format is invalid on ${endpointsLength} endpoint(s).`,
|
|
162
|
+
),
|
|
163
|
+
)
|
|
164
|
+
console.log(
|
|
165
|
+
pc.dim(
|
|
166
|
+
' The server uses WWW-Authenticate: Payment but the challenge parameters do not conform to MPP.',
|
|
167
|
+
),
|
|
168
|
+
)
|
|
169
|
+
console.log(
|
|
170
|
+
pc.dim(
|
|
171
|
+
' Fix: encode payment details as base64url JSON in a request="..." parameter. See errors above.',
|
|
172
|
+
),
|
|
173
|
+
)
|
|
174
|
+
} else if (flags.sawNonMppPaymentEndpoint) {
|
|
294
175
|
console.log(
|
|
295
176
|
pc.yellow(
|
|
296
177
|
` No MPP endpoints found. Tested ${endpointsLength} endpoint(s) but none use WWW-Authenticate: Payment.`,
|
|
@@ -318,7 +199,6 @@ function printSummary(
|
|
|
318
199
|
process.exit(1)
|
|
319
200
|
}
|
|
320
201
|
|
|
321
|
-
// Summary
|
|
322
202
|
console.log('')
|
|
323
203
|
const parts: string[] = []
|
|
324
204
|
if (counts.passed > 0) parts.push(pc.green(`${counts.passed} passed`))
|
|
@@ -327,17 +207,16 @@ function printSummary(
|
|
|
327
207
|
if (counts.skipped > 0) parts.push(pc.yellow(`${counts.skipped} skipped`))
|
|
328
208
|
console.log(`${pc.bold('Summary:')} ${parts.join(', ')}`)
|
|
329
209
|
|
|
330
|
-
// Cross-promotion
|
|
331
210
|
if (flags.paymentSucceeded && flags.sawTestnet && !flags.sawMainnet) {
|
|
332
211
|
console.log('')
|
|
333
212
|
console.log(
|
|
334
|
-
pc.dim(' Tip: validate your mainnet server
|
|
213
|
+
pc.dim(' Tip: also validate your mainnet server to confirm real payments work end-to-end.'),
|
|
335
214
|
)
|
|
336
215
|
} else if (flags.sawMainnet && !flags.sawTestnet) {
|
|
337
216
|
console.log('')
|
|
338
217
|
console.log(
|
|
339
218
|
pc.dim(
|
|
340
|
-
' Tip: validate
|
|
219
|
+
' Tip: also validate your testnet server for free. This CLI automatically provisions and funds a testnet wallet for testing.',
|
|
341
220
|
),
|
|
342
221
|
)
|
|
343
222
|
}
|