( headerValue: string, sessionSpentUSD: number, )
| 339 | * Returns the payment header value, or null if payment is not possible. |
| 340 | */ |
| 341 | export function handlePaymentRequired( |
| 342 | headerValue: string, |
| 343 | sessionSpentUSD: number, |
| 344 | ): { |
| 345 | paymentHeader: string |
| 346 | record: X402PaymentRecord |
| 347 | } | null { |
| 348 | const requirement = parsePaymentRequirement(headerValue) |
| 349 | const validation = validatePaymentRequirement(requirement, sessionSpentUSD) |
| 350 | |
| 351 | if (!validation.valid) { |
| 352 | logForDebugging(`[x402] Payment rejected: ${validation.reason}`) |
| 353 | return null |
| 354 | } |
| 355 | |
| 356 | const privateKey = getX402PrivateKey() |
| 357 | if (!privateKey) { |
| 358 | logForDebugging('[x402] No private key configured') |
| 359 | return null |
| 360 | } |
| 361 | |
| 362 | const config = getX402Config() |
| 363 | const fromAddress = config.address |
| 364 | if (!fromAddress) { |
| 365 | logForDebugging('[x402] No wallet address configured') |
| 366 | return null |
| 367 | } |
| 368 | |
| 369 | const payment = createPayment(requirement, fromAddress, privateKey) |
| 370 | const paymentHeader = encodePaymentHeader(payment) |
| 371 | |
| 372 | const record: X402PaymentRecord = { |
| 373 | timestamp: Date.now(), |
| 374 | resource: requirement.resource, |
| 375 | amount: requirement.maxAmountRequired, |
| 376 | amountUSD: tokenAmountToUSD(requirement.maxAmountRequired), |
| 377 | token: requirement.extra?.name ?? 'USDC', |
| 378 | network: requirement.network, |
| 379 | payTo: requirement.payTo, |
| 380 | signature: payment.payload.signature, |
| 381 | } |
| 382 | |
| 383 | // Track the payment |
| 384 | addX402Payment(record) |
| 385 | |
| 386 | logForDebugging( |
| 387 | `[x402] Payment signed: $${record.amountUSD.toFixed(4)} to ${requirement.payTo} for ${requirement.resource}`, |
| 388 | ) |
| 389 | |
| 390 | return { paymentHeader, record } |
| 391 | } |
| 392 | |
| 393 | /** |
| 394 | * Get the facilitator URL for a given network. |
no test coverage detected