- Notifications
You must be signed in to change notification settings - Fork4
An open-source, serverless, EVM-compatible design for generating digital asset invoices, tracking payments, and sweeping funds into an offline treasury wallet.
License
aws-samples/sample-serverless-digital-asset-payments
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
Authored by: Simon Goldberg and David Dornseifer
This solution supports native (i.e ETH) and ERC20 token payments onanyEVM-compatible blockchain with automated payment detection and fund sweepingcapabilities.
Note: Looking for Solana support? Check out theSolana implementation.
- Architecture
- Deployment
- Using the Payment System
- API Reference
- Development and Testing
- Clean Up
- Troubleshooting
The numbers of each of the steps in the payment flow correspond with the numbersin the architecture diagram above.
- Invoice Creation
- Merchant creates an invoice via the
/create-invoiceREST API (Amazon APIGateway).
- Fetch seed phrase
- The Invoice Generator Lambda is triggered and retrieves the mnemonic from AWSSecrets Manager.
- Increment atomic counter
- An atomic counter is incremented in DynamoDB. This is used todeterministically derive a new HD wallet address.
- Invoice Storage
- The Lambda creates a new invoice with payment
status: pendingand stores itin DynamoDB.
- QR Code Delivery
- A QR code containing the target address, currency, and amount is generated andreturned to the merchant for sharing with the customer.
- Payment Monitoring
- A watcher Lambda, triggered every minute via EventBridge, fetches all pendinginvoices and checks for payments via the RPC endpoint. Paid invoices areupdated accordingly.
- Payment Confirmation
- The watcher Lambda can send payment confirmations via Amazon SNS, which cantrigger email notifications or push updates.
- Sweeper Trigger
- When a payment is detected, a DynamoDB Stream event triggers the SweeperLambda process.
- Gas Top-up
- The Sweeper calculates required gas and sends additional native gas tokens toan invoice's address if necessary (ie for ERC20 invoices).
- Sweeping Funds
- Once sufficient gas is available to make a transaction, funds are "swept" tothe offline treasury wallet. The invoice is then marked as swept.
- Invoice Management
- Merchants can manage invoices (view status, update payments) via RESTendpoints exposed by API Gateway.
To deploy this solution, complete the following prerequisite steps to set upyour environment:
- AWS Account
- Node.js 18.x or later.
- AWS CDK CLI installed (npm install -g aws-cdk)
- Ethereum or EVM-compatible node access (Infura or similar)
Run the following commands to clone the GitHub repo:
git clone https://github.com/aws-samples/sample-serverless-digital-asset-payments.git&&cd sample-serverless-digital-asset-payments
For straightforward deployment and to support the development or extension ofthis payment solution, parameters are sourced from an.env file duringdeployment.
Copy the sample configuration:
cp .env-sample .env
Update the.env file with the following values:
RPC_URL: The HTTPS RPC URL for your blockchain network (for example,Ethereum)TREASURY_PUBLIC_ADDRESS: The cold storage wallet address where collectedfunds will be automatically transferred (swept). This should be a securewallet, such as a hardware wallet (e.g., Ledger, Trezor), to ensure maximumsecurity for your accumulated funds.HOT_WALLET_PK: A funded wallet used to cover gas payments for sweepingoperations. The key must be provided as a 64-character representation, forexample as exported from a development or test MetaMask wallet. Make sure thiswallet holds enough native tokens (ETH) to cover transaction fees. You canobtain testnet ether from a faucet.PAYER_PRIVATE_KEY: Test payer private key (optional variable forexecute_payment script)
For complete automated setup:
# 1. Make sure you have copied and configured your .env file# 2. Run the complete setupnpm run setup
This script handles all installation, deployment, and configuration stepsautomatically.
Ready to test?Use the payment system
If you prefer to set up manually:
- Install dependencies:
npm install
- Deploy the CDK stack:
cdk deploy
- Generate and store secrets:
npm run setup-secrets
The script will securely store the following:
- The generated seed phrase (for deterministic address generation)
- The hot wallet private key you defined in your .env file
Both values are encrypted and stored in Secrets Manager.
- Set up payment notifications (Optional):
To receive email alerts when payments are detected or errors with sweepingoccur, complete the following steps:
- Navigate to AWS Console → SNS topic created by the stack
- Click "Create subscription" → Select "Email" protocol
- Enter your email address and confirm subscription
- Open your inbox and choose the confirmation link to activate the subscription
Optionally, you can integrate Slack, Lambda consumers, or webhooks as needed.
Now that the crypto invoice system is deployed, you can test it by creating aninvoice and making a payment.
First, retrieve the API Gateway URL and API key from the deployed stack andexpose these values as environment variables:
export STACK_NAME="CryptoInvoiceStack"export API_URL=$(aws cloudformation describe-stacks --stack-name"$STACK_NAME" \ --query"Stacks[0].Outputs[?OutputKey=='InvoiceApiBaseUrl'].OutputValue" --output text)export API_KEY_ID=$(aws cloudformation describe-stacks --stack-name"$STACK_NAME" \ --query"Stacks[0].Outputs[?OutputKey=='InvoiceApiKeyId'].OutputValue" --output text)export API_KEY=$(aws apigateway get-api-key --api-key"$API_KEY_ID" --include-value \ --query'value' --output text2>/dev/null)echo"API URL:$API_URL"
Make a request to your API Gateway endpoint and create a sample invoice. Forexample, the following curl request creates a $5 USDC invoice on Ethereum'sSepolia testnet:
curl -X POST"${API_URL}generateInvoice" \ -H"Content-Type: application/json" \ -H"X-API-Key:$API_KEY" \ -d'{ "currency": "ERC20", "tokenAddress": "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238", "tokenSymbol": "USDC", "amount": "5.00", "decimals": 6 }'
You will receive a unique deposit address and a representation of a QR code inthe response:
{"invoiceId":"524dd9e8-82c3-4f70-8540-74c693111dbe","address":"0x...","index":"number","qrcodeBase64":"string"}The QR code is returned as a Base64-encoded Data URL, which can be directlyembedded in HTML. This format allows you to use it as the src attribute of an<img> tag without additional processing. You can also enter the qrcodeBase64value into your web browser's address bar to display the image.
The following code shows an example of how to extract the QR code from theinvoice generator's response and save it in an HTML file:
RESPONSE='{ ... your JSON Invoice response here ... }'echo"$RESPONSE"| jq -r'.qrcodeBase64'| awk'{ print "<img src=\"" $0 "\">" }'> qrcode.html
Openqrcode.html in your browser to view the QR code.
Send testnet USDC to the invoice's address to trigger the payment flow. You canobtain testnet USDC for Ethereum Sepolia throughCircle's Testnet Faucet.
To request a specific invoice, replace the {invoiceID} placeholder with theinvoiceId value received earlier:
curl -X GET"${API_URL}invoices/{invoiceId}" \ -H"X-API-Key:$API_KEY"
You will receive a result similar to the following:
{"currency":"ETH","tokenAddress":null,"path":"m/44'/60'/0'/0/8","sweptAt":"2025-07-07T15:50:40.245Z","status":"swept","tokenSymbol":"ETH","amount":"0.00001","createdAt":"2025-07-07T15:49:41.981Z","address":"0xF67e4b8078d837822b8E602F12af76B228a0c1f5","invoiceId":"ed4880c6-ae2f-4400-ac45-9c263e109caf","paidAt":"2025-07-07T15:50:07.551Z"}The status field of an invoice will change throughout the transaction lifecycle:
pending: Invoice created, awaiting paymentpaid: Payment detected and confirmedswept: Funds successfully transferred to treasury wallet
After it's marked as swept, you can verify that the balance of the paid invoiceappears in the cold wallet balance to confirm the successful transfer of funds.
POST/generateInvoice
Headers:
- Content-Type: application/json
- X-API-Key:
<your-api-key>(Get your API Key from AWS Console → API Gateway →API Keys)
Request Body Parameters:
currency(required): "ETH" or "ERC20"amount(required): Payment amount as stringtokenAddress(required for ERC20): Contract addresstokenSymbol(required for ERC20): Token symboldecimals(required for ERC20): Token decimals
Retrieving API Endpoint and Key:
Use the environment variables set up in the usage section above ($API_URL and$API_KEY).
Example Requests:
- ERC20 Token Invoice (Sepolia Testnet):
curl -X POST"${API_URL}generateInvoice" \ -H"Content-Type: application/json" \ -H"X-API-Key:$API_KEY" \ -d'{ "currency": "ERC20", "tokenAddress": "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238", "tokenSymbol": "USDC", "amount": "5.00", "decimals": 6 }'
- Native ETH Invoice:
curl -X POST"${API_URL}generateInvoice" \ -H"Content-Type: application/json" \ -H"X-API-Key:$API_KEY" \ -d'{ "currency": "ETH", "amount": "0.01" }'
Response:
{"invoiceId":"uuid","address":"0x...","index":"number","qrcodeBase64":"string"}After creating an invoice, payment must be sent to the designated invoiceaddress to initiate the payment process.
Security Note: For production environments, do not accepttokenAddress anddecimals directly from the client-side. Maintain a pre-approved list of tokenson the server/admin side to prevent security risks from spoofed contractaddresses.
Additional endpoints for invoice administration:
- GET
/invoices- Get all invoices (with optional status filtering andpagination) - GET
/invoices/{invoiceId}- Get specific invoice details - PUT
/invoices/{invoiceId}- Update invoice status (limited tosecurity-safe operations) - DELETE
/invoices/{invoiceId}- Delete pending invoices
Query Parameters for GET /invoices:
status(optional): Filter by invoice status (pending,paid,swept,cancelled)limit(optional): Number of invoices to return (default: 50, max: 100)lastKey(optional): Pagination key for retrieving next page
Status Update Rules:
pending↔cancelled(bidirectional for unpaid invoices)paidandsweptstatuses areimmutable to prevent payment manipulation
Example Requests:
# Get all pending invoicescurl -X GET"${API_URL}invoices?status=pending" \ -H"X-API-Key:$API_KEY"# Cancel a pending invoicecurl -X PUT"${API_URL}invoices/{invoiceId}" \ -H"Content-Type: application/json" \ -H"X-API-Key:$API_KEY" \ -d'{"status": "cancelled"}'# Delete a pending invoicecurl -X DELETE"${API_URL}invoices/{invoiceId}" \ -H"X-API-Key:$API_KEY"
Prerequisites for testing:
- Deployed CDK stack
- Test wallet with testnet funds
jq,bc,curlandeth-cliinstalled
npm run setup: Complete deployment with prerequisite checksnpm run test-invoice-management: API endpoint testingnpm run execute-payment: End-to-end payment execution with gasoptimization
To avoid incurring unnecessary charges:
- Delete the CDK stack:
cdk destroy
- Clean up local files:
rm -rf node_modules/ cdk.out/
Invoice Generation Fails:
- Verify seed phrase is stored in Secrets Manager (
npm run setup-secrets) - Check RPC_URL configuration
- Review Lambda function logs in CloudWatch
- Verify seed phrase is stored in Secrets Manager (
Payments Not Detected:
- Ensure Watcher function is running
- Verify RPC node connectivity
- Wait 1-2 minutes for detection cycle
Sweeping Issues:
- Check hot wallet has sufficient ETH for gas
- Verify treasury address configuration
- Monitor Sweeper function logs
- If there is an error and an invoice gets stuck in the "paid" state,navigate to the CryptoInvoices DynamoDB Table in the AWS Console and changethe status of the invoice back to "pending". Then, change it back to"paid". This state transition will reinvoke the Sweeper function.
API Authentication:
- Retrieve API key from AWS Console → API Gateway → API Keys
- Or use AWS CLI:
aws apigateway get-api-key --api-key <api-key-id> --include-value
Testing Issues:
- Ensure test wallet has sufficient testnet funds
- Verify all required tools are installed (
jq,bc,curl) - Check environment variables are properly configured
SeeCONTRIBUTING for moreinformation.
This library is licensed under the MIT-0 License. See the LICENSE file.
About
An open-source, serverless, EVM-compatible design for generating digital asset invoices, tracking payments, and sweeping funds into an offline treasury wallet.
Topics
Resources
License
Code of conduct
Contributing
Security policy
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Contributors4
Uh oh!
There was an error while loading.Please reload this page.

