Skip to content

Commit f067a6c

Browse files
authored
split verify and settlement for fair billing (verify→generate→settle) flow with README feedback updates (#7)
* feat: verify→generate→settle flow with README feedback updates - Reorder serverless seller: middleware verifies only, route handler generates content then settles - Reorder agentic seller: /generate_image verifies and returns nonce, new /settle endpoint for deferred settlement - Update tools.py: generate_image extracts nonce, calls /settle after successful Bedrock generation - README flows: remove hardcoded pricing, remove idempotency step, reorder steps to match code - Add PAYMENT-RESPONSE header mention to serverless settlement step - Add CloudFront + Lambda@Edge scaling section with Coinbase reference - Align arrow color groupings with new step numbering across all three READMEs * audit vulnerabilities
1 parent b1e05e4 commit f067a6c

File tree

9 files changed

+156
-95
lines changed

9 files changed

+156
-95
lines changed

README.md

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ This solution demonstrates pay-per-use AI content generation using the x402 paym
1010
- [Serverless](#serverless)
1111
- [Agentic](#agentic)
1212
- [Architecture Comparison](#architecture-comparison)
13+
- [Scaling with CloudFront and Lambda@Edge](#scaling-with-cloudfront-and-lambdaedge)
1314
- [Deployment](#deployment)
1415
- [Prerequisites](#prerequisites)
1516
- [Quick Start](#quick-start)
@@ -26,39 +27,37 @@ This solution demonstrates pay-per-use AI content generation using the x402 paym
2627

2728
![AWS Serverless x402 Payments Architecture](assets/AWS-Serverless-X402-Payments.png)
2829

29-
The solution includes three main components: Request Initiation (salmon arrows, steps 1-2, 5, 12), Payment Processing (green arrows, steps 3-4, 6, 7-9), and Content Delivery (orange arrows, steps 10-11).
30+
The solution includes three main components: Request Initiation (salmon arrows, steps 1-2, 5, 11), Payment Processing (green arrows, steps 3-4, 6-7, 9), and Content Delivery (orange arrows, steps 8, 10).
3031

3132
The numbers in the following flow correspond to the serverless stablecoin payment for AI-generated content:
3233

3334
1. **Wallet Connection:** The user clicks the wallet connect button in the React frontend. The application uses Reown AppKit to display available wallet options. The user selects their wallet and approves the connection request.
3435

3536
2. **Initial Request:** The user submits a prompt through the chat interface. The application sends a POST request to the `/generate` endpoint on Amazon API Gateway without payment credentials.
3637

37-
3. **Cost Estimation:** The Estimator Lambda function uses Amazon Bedrock `CountTokens` API to calculate input tokens. It estimates output tokens using a conservative formula (minimum 800 tokens with 20% safety margin) and applies Amazon Nova 2 Lite pricing ($0.0003 input, $0.0025 output per 1K tokens). Amazon Nova Canvas returns a fixed $0.04 per image.
38+
3. **Cost Estimation:** The Estimator Lambda function uses Amazon Bedrock `CountTokens` API to calculate input tokens. It estimates output tokens using a conservative formula (minimum 800 tokens with 20% safety margin) and estimates pricing based on the selected model.
3839

3940
4. **Payment Requirements:** The Seller Lambda function detects the missing `PAYMENT-SIGNATURE` header and returns `HTTP 402`. The response includes the USDC amount in wei, the seller wallet address, the USDC contract address on Base Sepolia, and `EIP-712` domain parameters.
4041

4142
5. **Payment Authorization:** The frontend is hosted on AWS Amplify and displays a payment modal with the cost preview. The user confirms and the application generates an `EIP-712` typed data signature using the connected wallet. The wallet prompts the user to sign the message. The signature authorizes the USDC transfer with validity timestamps and a unique nonce.
4243

4344
6. **Payment Submission:** The frontend retries the `/generate` request with the `EIP-712` signature in the `PAYMENT-SIGNATURE` header. The request includes the authorization object (from, to, value, validAfter, validBefore, nonce) and signature.
4445

45-
7. **Idempotency Check:** The Seller Lambda extracts the nonce and checks an in-memory cache to prevent replay attacks. If the nonce exists, it returns `HTTP 409`.
46+
7. **Payment Verification:** The AWS Lambda function sends the payment payload to the x402.org facilitator's `/verify` endpoint. The facilitator validates the `EIP-712` signature against the USDC contract domain on Base Sepolia.
4647

47-
8. **Payment Verification:** The AWS Lambda function sends the payment payload to the x402.org facilitator's `/verify` endpoint. The facilitator validates the `EIP-712` signature against the USDC contract domain on Base Sepolia.
48+
8. **Content Generation:** The AWS Lambda function invokes the Bedrock Lambda function. For text, it calls Amazon Nova 2 Lite using the `invoke_model` API. For images, it invokes Amazon Nova Canvas.
4849

49-
9. **Payment Settlement:** The Lambda calls the facilitator's `/settle` endpoint. The facilitator executes the USDC transfer on-chain using `EIP-3009 transferWithAuthorization` and returns the transaction hash.
50+
9. **Payment Settlement:** After successful content generation, the Lambda calls the facilitator's `/settle` endpoint. The facilitator executes the USDC transfer on-chain using `EIP-3009 transferWithAuthorization` and returns the transaction hash. The Lambda includes the settlement details in the `PAYMENT-RESPONSE` header.
5051

51-
10. **Content Generation:** The AWS Lambda function invokes the Bedrock Lambda function. For text, it calls Amazon Nova 2 Lite using the `invoke_model` API. For images, it invokes Amazon Nova Canvas.
52+
10. **Response Delivery:** The Bedrock Lambda returns the generated content. The Seller Lambda constructs a response with the success message, transaction url (`https://sepolia.basescan.org/tx/{hash}`), and generated content.
5253

53-
11. **Response Delivery:** The Bedrock Lambda returns the generated content. The Seller Lambda constructs a response with the success message, transaction url (`https://sepolia.basescan.org/tx/{hash}`), and generated content.
54-
55-
12. **Frontend Display:** The application displays the payment confirmation, transaction hash, and AI-generated content in the chat interface.
54+
11. **Frontend Display:** The application displays the payment confirmation, transaction hash, and AI-generated content in the chat interface.
5655

5756
### Agentic
5857

5958
![AWS Agentic x402 Payments Architecture](assets/AWS-Agentic-X402-Payments.png)
6059

61-
The solution includes three main components: Request Initiation (salmon arrows, steps 1-2), Payment Processing (green arrows, steps 4-11), and Content Delivery (orange arrows, steps 3, 12-14).
60+
The solution includes three main components: Request Initiation (salmon arrows, steps 1-2), Payment Processing (green arrows, steps 4-10, 12), and Content Delivery (orange arrows, steps 3, 11, 13-14).
6261

6362
The numbers in the following flow correspond to an autonomous agent executing stablecoin payments for AI-generated content:
6463

@@ -68,25 +67,25 @@ The numbers in the following flow correspond to an autonomous agent executing st
6867

6968
3. **Agent Initialization:** Amazon Bedrock AgentCore loads the agent configuration and initializes Amazon Bedrock AgentCore Memory for session storage. The agent using Anthropic Claude Sonnet 4.5 as the reasoning engine, receives the prompt and determines the required action.
7069

71-
4. **Cost Estimation:** The agent invokes the `estimate_image_cost` tool. The tool calculates the fixed cost ($0.04 USDC for `1024x1024` standard quality) and generates a unique request ID. The cost, prompt, and authorization status (`auth: false`) are stored in Amazon Bedrock AgentCore Memory.
70+
4. **Cost Estimation:** The agent invokes the `estimate_image_cost` tool. The tool calculates the cost and generates a unique request ID. The cost, prompt, and authorization status (`auth: false`) are stored in Amazon Bedrock AgentCore Memory.
7271

7372
5. **Authorization Check:** The agent calls `generate_image` tool. The tool checks the authorization status in session storage and finds `auth:false`. The tool returns `AUTHORIZE_CHECK` status directly to the agent without calling the gateway. This confirms user intent to pay and is not part of the x402 flow. The check is automatic but can be an explicit natural language confirmation corresponding to an CDP AgentKit wallet’s allowance.
7473

75-
6. **Payment Authorization:** The agent calls `make_payment`. The tool verifies sufficient balance exists and sets `auth:true` in session storage. This marks the user's intent to proceed with payment but does not transfer funds
74+
6. **Payment Authorization:** The agent calls `make_payment`. The tool verifies sufficient balance exists and sets `auth:true` in session storage. This marks the user's intent to proceed with payment but does not transfer funds.
7675

7776
7. **Initial x402 Request:** The agent calls `generate_image` again. The tool finds `auth:true` and creates an x402 HTTP client that signs with the CDP AgentKit wallet through CDP APIs (no private key export). The client sends a POST request to Amazon API Gateway without an `PAYMENT-SIGNATURE` header.
7877

7978
8. **402 Payment Required:** AWS Lambda receives the request and returns `HTTP 402` with payment requirements. The response includes the USDC amount in wei, seller wallet address, USDC contract address, and `EIP-712` domain parameters (name: 'USDC', version: '2', chainId: 84532).
8079

8180
9. **EIP-712 Signature Generation:** The x402 client receives the 402 response and constructs `EIP-712` typed data. It requests a signature from the CDP-managed wallet, base64-encodes the signature payload, and retries the POST request with the signature in the `PAYMENT-SIGNATURE` header.
8281

83-
10. **Payment Verification:** Lambda extracts the payment payload from the `PAYMENT-SIGNATURE` header. It checks the nonce against the `processedPayments` map to prevent replay attacks. Lambda sends the signature to the x402.org facilitator's `/verify` endpoint, which validates the `EIP-712` signature against the USDC contract domain on Base Sepolia.
82+
10. **Payment Verification:** Lambda extracts the payment payload from the `PAYMENT-SIGNATURE` header. Lambda sends the signature to the x402.org facilitator's `/verify` endpoint, which validates the `EIP-712` signature against the USDC contract domain on Base Sepolia.
8483

85-
11. **Payment Settlement:** AWS Lambda calls the facilitator's `/settle` endpoint. The facilitator executes the USDC transfer on Base Sepolia using `EIP-3009 transferWithAuthorization` and returns the transaction hash. Lambda stores the hash in context, marks the nonce as processed, and returns `HTTP 200` with payment confirmation.
84+
11. **Image Generation:** The tool invokes Amazon Nova Canvas model using the `invoke_model` API. Nova Canvas generates a `1024x1024` image based on the prompt.
8685

87-
12. **Image Generation:** The tool invokes Amazon Nova Canvas model using the `invoke_model` API. Nova Canvas generates a `1024x1024` image based on the prompt.
86+
12. **Payment Settlement:** After successful image generation, the tool calls the seller Lambda's `/settle` endpoint with the nonce. Lambda looks up the pending payment data, calls the x402.org facilitator's `/settle` endpoint, and the facilitator executes the USDC transfer on Base Sepolia using `EIP-3009 transferWithAuthorization`. The transaction hash is returned to the agent.
8887

89-
13. **Response Delivery:** The generated image is stored in Amazon Simple Storage Service , and its unique ID is stored in session storage. The agent returns a success message to the frontend hosted an AWS Amplifywhich includes the base64-encoded image, transaction hash, and a BaseScan explorer link(`https://sepolia.basescan.org/tx/{hash}`) for on-chain verification.
88+
13. **Response Delivery:** The generated image is stored in Amazon Simple Storage Service, and its unique ID is stored in session storage. The agent returns a success message to the frontend hosted on AWS Amplify which includes the base64-encoded image, transaction hash, and a BaseScan explorer link (`https://sepolia.basescan.org/tx/{hash}`) for on-chain verification.
9089

9190
14. **Session Cleanup:** The tool clears the current request ID from session storage. This allows new image generation requests while maintaining payment history for the session.
9291

@@ -140,6 +139,12 @@ Serverless incurs cold start latency when AWS Lambda functions initialize. Subse
140139

141140
Agentic maintains warm WebSocket connections, eliminating connection establishment overhead. However, Amazon Bedrock AgentCore Runtime introduces reasoning latency as Claude Sonnet 4.5 analyzes prompts and plans tool invocations.
142141

142+
## Scaling with CloudFront and Lambda@Edge
143+
144+
This sample handles x402 payment verification within the application Lambda functions. An alternative approach moves payment verification to the edge using Amazon CloudFront and Lambda@Edge. This separates payment logic from application code and applies x402 to any origin without backend changes.
145+
146+
For a reference implementation of this pattern, see the [CloudFront + Lambda@Edge x402 example](https://github.com/coinbase/x402/tree/main/examples/typescript/servers/cloudfront-lambda-edge) in the Coinbase x402 repository.
147+
143148
## Deployment
144149

145150
### Prerequisites

agentic/README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ For full platform deployment including the serverless architecture and frontend,
1818

1919
![AWS Agentic x402 Payments Architecture](../assets/AWS-Agentic-X402-Payments.png)
2020

21-
The solution includes three main components: Request Initiation (salmon arrows, steps 1-2), Payment Processing (green arrows, steps 4-11), and Content Delivery (orange arrows, steps 3, 12-14).
21+
The solution includes three main components: Request Initiation (salmon arrows, steps 1-2), Payment Processing (green arrows, steps 4-10, 12), and Content Delivery (orange arrows, steps 3, 11, 13-14).
2222

2323
The numbers in the following flow correspond to an autonomous agent executing stablecoin payments for AI-generated content:
2424

@@ -28,23 +28,23 @@ The numbers in the following flow correspond to an autonomous agent executing st
2828

2929
3. **Agent Initialization:** Amazon Bedrock AgentCore loads the agent configuration and initializes Amazon Bedrock AgentCore Memory for session storage. The agent using Anthropic Claude Sonnet 4.5 as the reasoning engine, receives the prompt and determines the required action.
3030

31-
4. **Cost Estimation:** The agent invokes the `estimate_image_cost` tool. The tool calculates the fixed cost ($0.04 USDC for `1024x1024` standard quality) and generates a unique request ID. The cost, prompt, and authorization status (`auth: false`) are stored in Amazon Bedrock AgentCore Memory.
31+
4. **Cost Estimation:** The agent invokes the `estimate_image_cost` tool. The tool calculates the cost and generates a unique request ID. The cost, prompt, and authorization status (`auth: false`) are stored in Amazon Bedrock AgentCore Memory.
3232

3333
5. **Authorization Check:** The agent calls `generate_image` tool. The tool checks the authorization status in session storage and finds `auth:false`. The tool returns `AUTHORIZE_CHECK` status directly to the agent without calling the gateway. This confirms user intent to pay and is not part of the x402 flow. The check is automatic but can be an explicit natural language confirmation corresponding to an CDP AgentKit wallet's allowance.
3434

35-
6. **Payment Authorization:** The agent calls `make_payment`. The tool verifies sufficient balance exists and sets `auth:true` in session storage. This marks the user's intent to proceed with payment but does not transfer funds
35+
6. **Payment Authorization:** The agent calls `make_payment`. The tool verifies sufficient balance exists and sets `auth:true` in session storage. This marks the user's intent to proceed with payment but does not transfer funds.
3636

3737
7. **Initial x402 Request:** The agent calls `generate_image` again. The tool finds `auth:true` and creates an x402 HTTP client that signs with the CDP AgentKit wallet through CDP APIs (no private key export). The client sends a POST request to Amazon API Gateway without an `PAYMENT-SIGNATURE` header.
3838

3939
8. **402 Payment Required:** AWS Lambda receives the request and returns `HTTP 402` with payment requirements. The response includes the USDC amount in wei, seller wallet address, USDC contract address, and `EIP-712` domain parameters (name: 'USDC', version: '2', chainId: 84532).
4040

4141
9. **EIP-712 Signature Generation:** The x402 client receives the 402 response and constructs `EIP-712` typed data. It requests a signature from the CDP-managed wallet, base64-encodes the signature payload, and retries the POST request with the signature in the `PAYMENT-SIGNATURE` header.
4242

43-
10. **Payment Verification:** Lambda extracts the payment payload from the `PAYMENT-SIGNATURE` header. It checks the nonce against the `processedPayments` map to prevent replay attacks. Lambda sends the signature to the x402.org facilitator's `/verify` endpoint, which validates the `EIP-712` signature against the USDC contract domain on Base Sepolia.
43+
10. **Payment Verification:** Lambda extracts the payment payload from the `PAYMENT-SIGNATURE` header. Lambda sends the signature to the x402.org facilitator's `/verify` endpoint, which validates the `EIP-712` signature against the USDC contract domain on Base Sepolia.
4444

45-
11. **Payment Settlement:** AWS Lambda calls the facilitator's `/settle` endpoint. The facilitator executes the USDC transfer on Base Sepolia using `EIP-3009 transferWithAuthorization` and returns the transaction hash. Lambda stores the hash in context, marks the nonce as processed, and returns `HTTP 200` with payment confirmation.
45+
11. **Image Generation:** The tool invokes Amazon Nova Canvas model using the `invoke_model` API. Nova Canvas generates a `1024x1024` image based on the prompt.
4646

47-
12. **Image Generation:** The tool invokes Amazon Nova Canvas model using the `invoke_model` API. Nova Canvas generates a `1024x1024` image based on the prompt.
47+
12. **Payment Settlement:** After successful image generation, the tool calls the seller Lambda's `/settle` endpoint with the nonce. Lambda looks up the pending payment data, calls the x402.org facilitator's `/settle` endpoint, and the facilitator executes the USDC transfer on Base Sepolia using `EIP-3009 transferWithAuthorization`. The transaction hash is returned to the agent.
4848

4949
13. **Response Delivery:** The generated image is stored in Amazon Simple Storage Service, and its unique ID is stored in session storage. The agent returns a success message to the frontend hosted on AWS Amplify which includes the base64-encoded image, transaction hash, and a BaseScan explorer link (`https://sepolia.basescan.org/tx/{hash}`) for on-chain verification.
5050

0 commit comments

Comments
 (0)