-
Notifications
You must be signed in to change notification settings - Fork 425
feat(samples): add human-present crypto-solana scenario (AP2 + Solana Pay reference binding) #228
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
chopmob-cloud
wants to merge
4
commits into
google-agentic-commerce:main
Choose a base branch
from
chopmob-cloud:feat/crypto-solana-scenario
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 3 commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
8048992
feat(samples): add crypto-solana human-present scenario (AP2 + Solana…
chopmob-cloud 47a9b77
fix(ci): set executable bit on crypto-solana run.sh (BASH_EXEC lint)
chopmob-cloud 278025a
fix(ci): resolve markdown-lint + cspell errors in crypto-solana README
chopmob-cloud 8557f75
fix(ci): add cspell:words declaration to crypto-solana run.sh
chopmob-cloud File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
142 changes: 142 additions & 0 deletions
142
samples/python/scenarios/a2a/human-present/crypto-solana/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| <!-- cspell:words Hedera Solflare keypair mainnet devnet ALGOVOI algv Helius Backpack Triton Phantom --> | ||
|
|
||
| # Agent Payments Protocol Sample: Human Present Purchases with On-Chain Solana USDC | ||
|
|
||
| This sample demonstrates the A2A `ap2-extension` for a human-present transaction | ||
| where the buyer settles with on-chain USDC on Solana (or native SOL for | ||
| micropayments). It mirrors the existing `x402` scenario but uses Solana Pay | ||
| semantics — specifically the **`reference` pubkey** primitive — to bind the | ||
| settling transaction to a specific AP2 `PaymentMandate`. | ||
|
|
||
| **Note:** This sample pairs with the separate `crypto-algo` human-present | ||
| scenario. Together they cover non-EVM settlement on Algorand and Solana as a | ||
| complement to the EVM-focused `x402` path. | ||
|
|
||
| ## Scenario | ||
|
|
||
| Human-present flows are commerce flows where the user is present to confirm | ||
| purchase details. The user signs the `PaymentMandate` giving all parties high | ||
| confidence in the transaction. | ||
|
|
||
| The Solana variant adds one additional primitive on top of the standard AP2 | ||
| mandate chain: | ||
|
|
||
| ### Solana Pay `reference` binding | ||
|
|
||
| Solana has no native transaction memo field (unlike Algorand or Hedera), and | ||
| the SPL Memo Program is unreliable across wallets. Instead, Solana Pay defines | ||
| a `reference` pubkey mechanism: | ||
|
|
||
| 1. The merchant (or its Merchant Agent) generates a fresh, single-use ed25519 | ||
| keypair per checkout. | ||
| 2. The public key is embedded in the Solana Pay URL: | ||
|
|
||
| ```text | ||
| solana:<recipient> | ||
| ?amount=<amount> | ||
| &spl-token=<USDC_MINT> | ||
| &reference=<reference_pubkey> | ||
| &label=<label> | ||
| &message=<order-id> | ||
| ``` | ||
|
|
||
| 3. The buyer's wallet (Phantom, Solflare, Backpack, etc.) includes the | ||
| `reference` pubkey as a read-only, non-signer account in the transfer | ||
| instruction. | ||
| 4. After the user signs and broadcasts the SPL Token transfer, the merchant | ||
| (or facilitator) queries `getSignaturesForAddress(<reference>)` to locate | ||
| the exact transaction that settled this order. | ||
| 5. Final verification compares the on-chain transfer's recipient, amount, and | ||
| SPL mint against the AP2 `PaymentMandate` contents. All three must match. | ||
|
|
||
| This is stronger than relying on amount uniqueness (EVM-style) and more | ||
| wallet-compatible than relying on memos. It also means the merchant never has | ||
| to ask the buyer to paste a transaction signature back. | ||
|
|
||
| ## Key Actors | ||
|
|
||
| This sample consists of: | ||
|
|
||
| - **Shopping Agent:** The main orchestrator that handles the user's shopping | ||
| request and delegates to specialist agents. | ||
| - **Merchant Agent:** Handles product queries and assembles the `CartMandate`. | ||
| - **Merchant Payment Processor Agent:** Takes payments on behalf of the | ||
| merchant and, in the Solana flow, verifies the on-chain USDC transfer | ||
| against the expected `reference`, amount, and mint. | ||
| - **Credentials Provider Agent:** Holds the user's payment credentials — in | ||
| this flow, the Solana wallet address and optional mint preferences. | ||
|
|
||
| ## Mandate Chain | ||
|
|
||
| The AP2 mandate chain is unchanged by the Solana variant: | ||
|
|
||
| ```text | ||
| IntentMandate ──▶ CartMandate ──▶ PaymentMandate | ||
| (user) (merchant) (user-signed) | ||
| │ | ||
| ▼ | ||
| Solana Pay URL (reference-bound) | ||
| │ | ||
| ▼ | ||
| SPL Token Transfer + reference pubkey | ||
| │ | ||
| ▼ | ||
| getSignaturesForAddress(reference) | ||
| │ | ||
| ▼ | ||
| PaymentReceipt | ||
| ``` | ||
|
|
||
| ## Payment Method | ||
|
|
||
| This scenario sets `PAYMENT_METHOD=CRYPTO_SOLANA` at startup. Downstream agents | ||
| treat it as a non-card, non-x402 payment flow and route through the | ||
| Solana-aware credentials provider path. | ||
|
|
||
| ## Assets Supported | ||
|
|
||
| | Asset | Mint | Decimals | | ||
| | --- | --- | --- | | ||
| | USDC (Solana mainnet) | `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v` | 6 | | ||
| | USDT (Solana mainnet) | `Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB` | 6 | | ||
| | USDC (Solana devnet) | `4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU` | 6 | | ||
| | Native SOL | — | 9 | | ||
|
|
||
| The Solana Pay URL format | ||
| (`solana:<recipient>?amount=...&spl-token=<mint>&reference=<pubkey>`) carries | ||
| the mint identifier, so supporting additional SPL tokens is a configuration | ||
| concern on the Merchant Agent and does not require protocol changes. | ||
|
|
||
| ## Running the sample | ||
|
|
||
| ```bash | ||
| # From the repository root: | ||
| export ALGOVOI_API_KEY="algv_..." # or any Solana-aware facilitator | ||
| export SOLANA_RPC_URL="https://..." # Solana mainnet or devnet RPC | ||
| export GOOGLE_API_KEY="..." # or GOOGLE_GENAI_USE_VERTEXAI=true | ||
| ./samples/python/scenarios/a2a/human-present/crypto-solana/run.sh | ||
| ``` | ||
|
|
||
| The sample script starts the Merchant, Credentials Provider, and Merchant | ||
| Payment Processor agents locally, then launches the Shopping Agent via the ADK | ||
| web UI. You can then drive a purchase end-to-end with USDC on Solana. | ||
|
|
||
| ## Why Solana Pay `reference` matters for AP2 | ||
|
|
||
| AP2 mandates are already cryptographically signed, but they describe intent | ||
| and authorization — not the on-chain settlement event itself. The `reference` | ||
| pubkey is the missing link that ties a specific blockchain transaction to a | ||
| specific `PaymentMandate` deterministically, without trusting the buyer to | ||
| self-report their transaction signature. For agent-initiated commerce, where | ||
| the "buyer" may be an AI agent and the "merchant" may be another AI agent, | ||
| this mechanical binding removes an otherwise social trust layer. | ||
|
|
||
| ## Reference implementations | ||
|
|
||
| - [AlgoVoi facilitator](https://api1.ilovechicken.co.uk) — verifies Solana | ||
| USDC transfers by (a) resolving `getSignaturesForAddress(reference)`, | ||
| (b) fetching the transaction, (c) checking mint + amount + recipient, and | ||
| (d) confirming the `reference` pubkey appears in the transaction's | ||
| account keys. | ||
| - [Solana Pay specification](https://solanapay.com/) — the canonical | ||
| reference for URL format and merchant-side flow. |
122 changes: 122 additions & 0 deletions
122
samples/python/scenarios/a2a/human-present/crypto-solana/run.sh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| #!/bin/bash | ||
|
|
||
| # A script to automate the execution of the crypto-solana (on-chain USDC on Solana) | ||
| # AP2 example. It starts all necessary servers and agents in the background. | ||
| # | ||
| # This scenario uses Solana Pay `reference` pubkey binding to link the settling | ||
| # transaction deterministically to the signed AP2 PaymentMandate. See README.md | ||
| # for the full flow. | ||
|
|
||
| set -e | ||
|
|
||
| export PAYMENT_METHOD=CRYPTO_SOLANA | ||
|
|
||
| AGENTS_DIR="samples/python/src/roles" | ||
| LOG_DIR=".logs" | ||
|
|
||
| if [ ! -d "$AGENTS_DIR" ]; then | ||
| echo "Error: Directory '$AGENTS_DIR' not found." | ||
| echo "Please run this script from the root of the repository." | ||
| exit 1 | ||
| fi | ||
|
|
||
| if [ -f .env ]; then | ||
| set -a | ||
| source .env | ||
| set +a | ||
| fi | ||
|
|
||
| USE_VERTEXAI=$(printf "%s" "${GOOGLE_GENAI_USE_VERTEXAI}" | tr '[:upper:]' '[:lower:]') | ||
| if [ -z "${GOOGLE_API_KEY}" ] && [ "${USE_VERTEXAI}" != "true" ]; then | ||
| echo "Please set your GOOGLE_API_KEY environment variable before running." | ||
| echo "Alternatively, set GOOGLE_GENAI_USE_VERTEXAI=true to use Vertex AI with ADC." | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Facilitator for on-chain verification. Defaults point at AlgoVoi Cloud but | ||
| # any Solana-aware AP2 facilitator works; set the env var to override. | ||
| if [ -z "${ALGOVOI_API_KEY}" ]; then | ||
| echo "Please set your ALGOVOI_API_KEY environment variable before running." | ||
| echo "Sign up at https://cloud.algovoi.co.uk (or use any Solana-aware AP2 facilitator)." | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Solana RPC. Defaults to mainnet public; override with a paid provider | ||
| # (Helius, Alchemy, Triton) for reliability. | ||
| if [ -z "${SOLANA_RPC_URL}" ]; then | ||
| export SOLANA_RPC_URL="https://api.mainnet-beta.solana.com" | ||
| echo "SOLANA_RPC_URL not set; defaulting to the public Solana mainnet endpoint." | ||
| echo "For production usage, configure a paid RPC provider for rate-limit headroom." | ||
| fi | ||
|
|
||
| echo "Setting up the Python virtual environment..." | ||
|
|
||
| if [ ! -d ".venv" ]; then | ||
| uv venv | ||
| fi | ||
|
|
||
| case "$OSTYPE" in | ||
| msys* | cygwin*) | ||
| source .venv/Scripts/activate | ||
| ;; | ||
| *) | ||
| source .venv/bin/activate | ||
| ;; | ||
| esac | ||
| echo "Virtual environment activated." | ||
|
|
||
| mkdir -p "$LOG_DIR" | ||
|
|
||
| cleanup() { | ||
| echo "" | ||
| echo "Shutting down background processes..." | ||
| if [ ${#pids[@]} -ne 0 ]; then | ||
| kill "${pids[@]}" 2>/dev/null | ||
| wait "${pids[@]}" 2>/dev/null | ||
| fi | ||
| echo "Cleanup complete." | ||
| } | ||
|
|
||
| trap cleanup EXIT | ||
|
|
||
| echo "Syncing virtual environment with uv sync..." | ||
| if uv sync --package ap2-samples; then | ||
| echo "Virtual environment synced successfully." | ||
| else | ||
| echo "Error: uv sync failed. Aborting." | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "Clearing the logs directory..." | ||
| if [ -d "$LOG_DIR" ]; then | ||
| find "$LOG_DIR" -mindepth 1 -delete | ||
| fi | ||
|
|
||
| pids=() | ||
|
|
||
| echo "" | ||
| echo "Starting remote servers and agents as background processes..." | ||
|
|
||
| UV_RUN_CMD="uv run --no-sync" | ||
|
|
||
| if [ -f ".env" ]; then | ||
| UV_RUN_CMD="$UV_RUN_CMD --env-file .env" | ||
| fi | ||
|
|
||
| echo "-> Starting the Merchant Agent (port:8001 log:$LOG_DIR/merchant_agent.log)..." | ||
| $UV_RUN_CMD --package ap2-samples python -m roles.merchant_agent >"$LOG_DIR/merchant_agent.log" 2>&1 & | ||
| pids+=($!) | ||
|
|
||
| echo "-> Starting the Credentials Provider (port:8002 log:$LOG_DIR/credentials_provider_agent.log)..." | ||
| $UV_RUN_CMD --package ap2-samples python -m roles.credentials_provider_agent >"$LOG_DIR/credentials_provider_agent.log" 2>&1 & | ||
| pids+=($!) | ||
|
|
||
| echo "-> Starting the Merchant Payment Processor Agent (port:8003 log:$LOG_DIR/mpp_agent.log)..." | ||
| $UV_RUN_CMD --package ap2-samples python -m roles.merchant_payment_processor_agent >"$LOG_DIR/mpp_agent.log" 2>&1 & | ||
| pids+=($!) | ||
|
|
||
| echo "" | ||
| echo "All remote servers are starting." | ||
|
|
||
| echo "Starting the Shopping Agent..." | ||
| $UV_RUN_CMD --package ap2-samples adk web --host 0.0.0.0 $AGENTS_DIR/shopping_agent | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
PAYMENT_METHODenvironment variable is set at line 12, but then.envis sourced at line 25. If the user hasPAYMENT_METHODdefined in their.envfile, it will override the scenario-specific value (CRYPTO_SOLANA), potentially causing the script to execute with the wrong payment logic. It is safer to source the.envfile first and then set scenario-specific overrides. Additionally, initializing thepidsarray early ensures that thecleanuptrap (line 80) is always safe even if the script fails during early setup (e.g., line 20).