x402-payments 0.1.0 → 1.0.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 42c2b33d7692d31886f45dde66a23fc750502aa7fe44db52d2c11ebd6d59b069
4
- data.tar.gz: '081a125a98b562d5202396f96ceaaf950980f575d112b7c20dc2c3e96e2a235c'
3
+ metadata.gz: 6dc411d32e832d03fd677129c82073d40d921a878389e034a4ad66a6ac6b8844
4
+ data.tar.gz: 81fb4038fa051babdf3314dbff9bfd1e7dfa81a41954eb520ce401d8cd22b4ab
5
5
  SHA512:
6
- metadata.gz: 6d79fed8b305baa86cc5378229bc039715cd70a4cfbce99424e84501d5890301698e80efc82b9d61d55ccd907aea2ec71eeaf1a7056dfe788b8ce8c99fffc683
7
- data.tar.gz: 1fdc0978f6443a9d34de4e9596410fddf000461de27a2573a2e3adece08aeaae979d2029a1c569637541179a6902acb39cf0fda6e1c3b6f8af913339bbace821
6
+ metadata.gz: b6be1da37e65cd6fd6d2bf603a6d0119bc9b6c0888b0365e1364aa66959cf182f5733765a964fd64818ef6c1bc9371d00357d0e00755b7714ba631fde982db47
7
+ data.tar.gz: 0d4db3d797a2b1ea19f0e330ddb91c4a56ad0494d57636501e05d2286fe19a86d8f69ddacdbf75d7ef37fb7daa47b8db8207878f73a9cb075318cf2b91b33e52
data/CHANGELOG.md ADDED
@@ -0,0 +1,37 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [1.0.0] - 2026-01-08
6
+
7
+ ### Added
8
+
9
+ - **Solana support** - Full support for Solana payments on `solana-devnet` and `solana` mainnet
10
+ - SPL Token `TransferChecked` transactions with partial signing
11
+ - Custom ATA (Associated Token Account) derivation with correct Ed25519 curve checking
12
+ - Facilitator fee payer model (uses x402.org facilitator by default)
13
+ - Inline `fee_payer:` override for different facilitators
14
+ - Configurable compute budget via `X402_SOLANA_COMPUTE_UNIT_LIMIT` and `X402_SOLANA_COMPUTE_UNIT_PRICE`
15
+ - **Protocol v1 and v2 support** - Both protocol versions fully supported
16
+ - v1: `X-PAYMENT` header, human-readable network names
17
+ - v2: `PAYMENT-SIGNATURE` header, CAIP-2 network identifiers
18
+ - Override protocol version per-request with `version:` parameter
19
+ - **Custom EVM chain registration** - `config.register_chain()` for adding custom EVM networks
20
+ - **Custom token registration** - `config.register_token()` for adding tokens beyond USDC
21
+ - **Networks module** - CAIP-2 network identifier conversion
22
+
23
+ ### Changed
24
+
25
+ - Default protocol version is v2
26
+ - Solana uses CAIP-2 format: `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` (devnet)
27
+ - Improved error messages for configuration issues
28
+
29
+ ### Fixed
30
+
31
+ - ATA derivation now uses correct Ed25519 curve equation (fixes `recipient_mismatch` errors)
32
+
33
+ ## [0.1.0] - Initial Release
34
+
35
+ - Initial release with v1 protocol support
36
+ - EIP-712 signing for USDC payments
37
+ - Support for Base and Avalanche networks
data/README.md CHANGED
@@ -1,10 +1,12 @@
1
1
  # X402::Payments
2
2
 
3
+ ## Now supporting x402 v2!
4
+
3
5
  ![Coverage](./coverage/coverage.svg)
4
6
 
5
7
  Ruby gem for generating signed payment HTTP headers and links using the [x402 protocol](https://www.x402.org/).
6
8
 
7
- Supports USDC payments on Base, Avalanche, and other EVM networks with EIP-712 signing.
9
+ Supports USDC and other token payments on Base, Avalanche, Solana, and other EVM networks with EIP-712 signing.
8
10
 
9
11
  ## Installation
10
12
 
@@ -52,31 +54,168 @@ gem install x402-payments
52
54
 
53
55
  ## Configuration
54
56
 
55
- The gem uses environment variables for configuration with sensible defaults:
56
-
57
- ```bash
58
- # Required
59
- export X402_PAY_TO="0xYourWalletAddress" # Default address to receive payments
60
- export X402_PRIVATE_KEY="0xYourPrivateKey" # Private key for signing
61
-
62
- # Optional (with defaults shown)
63
- export X402_CHAIN="base-sepolia" # Network to use
64
- export X402_MAX_TIMEOUT_SECONDS="600" # Payment validity timeout
65
-
66
- # Optional: Custom RPC URLs (override default RPC endpoints)
67
- export X402_BASE_RPC_URL="https://your-custom-rpc.com"
68
- export X402_BASE_SEPOLIA_RPC_URL="https://your-sepolia-rpc.com"
69
- export X402_AVALANCHE_RPC_URL="https://your-avax-rpc.com"
70
- export X402_AVALANCHE_FUJI_RPC_URL="https://your-avax-testnet-rpc.com"
71
- ```
57
+ Configure the gem using environment variables. See `examples/.env.example` for a template.
58
+
59
+ ### Environment Variables
60
+
61
+ | Variable | Required | Description |
62
+ | -------------------------------- | ------------ | ------------------------------------------------ |
63
+ | `X402_PRIVATE_KEY` | Yes (EVM) | EVM private key for signing |
64
+ | `X402_PAY_TO` | Yes (EVM) | EVM recipient wallet address |
65
+ | `X402_SOL_PRIVATE_KEY` | Yes (Solana) | Solana private key (base58 or JSON array) |
66
+ | `X402_SOL_PAY_TO` | Yes (Solana) | Solana recipient wallet address |
67
+ | `X402_CHAIN` | No | Network to use (default: `base-sepolia`) |
68
+ | `X402_CURRENCY` | No | Token symbol (default: `USDC`) |
69
+ | `X402_PROTOCOL_VERSION` | No | Protocol version 1 or 2 (default: `2`) |
70
+ | `X402_MAX_TIMEOUT_SECONDS` | No | Payment validity timeout (default: `600`) |
71
+ | `X402_SOLANA_FEE_PAYER` | No | Solana fee payer (default: x402.org facilitator) |
72
+ | `X402_SOLANA_COMPUTE_UNIT_LIMIT` | No | Solana compute unit limit (default: `200000`) |
73
+ | `X402_SOLANA_COMPUTE_UNIT_PRICE` | No | Priority fee in micro-lamports (default: `1000`) |
74
+ | `X402_SOLANA_RPC_URL` | No | Custom Solana mainnet RPC URL |
75
+ | `X402_SOLANA_DEVNET_RPC_URL` | No | Custom Solana devnet RPC URL |
76
+ | `X402_BASE_RPC_URL` | No | Custom Base mainnet RPC URL |
77
+ | `X402_BASE_SEPOLIA_RPC_URL` | No | Custom Base Sepolia RPC URL |
78
+ | `X402_AVALANCHE_RPC_URL` | No | Custom Avalanche mainnet RPC URL |
79
+ | `X402_AVALANCHE_FUJI_RPC_URL` | No | Custom Avalanche Fuji RPC URL |
72
80
 
73
81
  ### Supported Networks
74
82
 
83
+ **EVM Networks:**
84
+
75
85
  - `base-sepolia` (testnet) - Default
76
86
  - `base` (mainnet)
77
87
  - `avalanche-fuji` (testnet)
78
88
  - `avalanche` (mainnet)
79
89
 
90
+ **Solana Networks:**
91
+
92
+ - `solana-devnet` (testnet)
93
+ - `solana` (mainnet)
94
+
95
+ ### Custom Chains and Tokens
96
+
97
+ You can register custom EVM chains and tokens beyond the built-in options.
98
+
99
+ #### Register a Custom Chain
100
+
101
+ ```ruby
102
+ X402::Payments.configure do |config|
103
+ config.default_pay_to = ENV['X402_PAY_TO']
104
+ config.private_key = ENV['X402_PRIVATE_KEY']
105
+
106
+ # Register Polygon Amoy testnet
107
+ config.register_chain(
108
+ name: "polygon-amoy",
109
+ chain_id: 80002,
110
+ standard: "eip155"
111
+ )
112
+
113
+ # Register the token for that chain
114
+ config.register_token(
115
+ chain: "polygon-amoy",
116
+ symbol: "USDC",
117
+ address: "0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582",
118
+ decimals: 6,
119
+ name: "USD Coin",
120
+ version: "2"
121
+ )
122
+
123
+ # Set the RPC URL for the custom chain
124
+ config.rpc_urls["polygon-amoy"] = "https://bitter-attentive-pool.matic-amoy.quiknode.pro"
125
+
126
+ config.chain = "polygon-amoy"
127
+ config.currency = "USDC"
128
+ end
129
+ ```
130
+
131
+ You can also set RPC URLs via environment variables using the pattern `X402_<CHAIN>_RPC_URL`:
132
+
133
+ ```bash
134
+ export X402_POLYGON_AMOY_RPC_URL="https://bitter-attentive-pool.matic-amoy.quiknode.pro"
135
+ ```
136
+
137
+ #### Register a Custom Token on a Built-in Chain
138
+
139
+ ```ruby
140
+ X402::Payments.configure do |config|
141
+ config.default_pay_to = ENV['X402_PAY_TO']
142
+ config.private_key = ENV['X402_PRIVATE_KEY']
143
+
144
+ # Accept WETH on Base instead of USDC
145
+ config.register_token(
146
+ chain: "base",
147
+ symbol: "WETH",
148
+ address: "0x4200000000000000000000000000000000000006",
149
+ decimals: 18,
150
+ name: "Wrapped Ether",
151
+ version: "1"
152
+ )
153
+
154
+ config.chain = "base"
155
+ config.currency = "WETH"
156
+ end
157
+ ```
158
+
159
+ #### Token Registration Parameters
160
+
161
+ | Parameter | Required | Description |
162
+ | ---------- | -------- | ---------------------------------------------- |
163
+ | `chain` | Yes | Chain name (built-in or custom registered) |
164
+ | `symbol` | Yes | Token symbol (e.g., "USDC", "WETH") |
165
+ | `address` | Yes | Token contract address |
166
+ | `decimals` | Yes | Token decimals (e.g., 6 for USDC, 18 for WETH) |
167
+ | `name` | Yes | Token name for EIP-712 domain |
168
+ | `version` | No | EIP-712 version (default: "1") |
169
+
170
+ ### Solana Configuration
171
+
172
+ For Solana payments, ensure you've set the Solana-specific environment variables (see Configuration section above), then set your chain:
173
+
174
+ ```bash
175
+ export X402_CHAIN="solana-devnet" # or "solana" for mainnet
176
+ ```
177
+
178
+ You can also override the fee payer per-request:
179
+
180
+ ```ruby
181
+ X402::Payments.generate_header(
182
+ amount: 0.001,
183
+ resource: "http://example.com/api",
184
+ network: "solana-devnet",
185
+ fee_payer: "CustomFacilitatorFeePayer" # use different facilitator
186
+ )
187
+ ```
188
+
189
+ > **Note**: Both sender and receiver must have a USDC [Associated Token Account (ATA)](https://spl.solana.com/associated-token-account). The sender must have USDC in their wallet (receiving USDC creates the ATA automatically).
190
+
191
+ ## Protocol Versions
192
+
193
+ x402-payments supports both v1 and v2 of the x402 protocol. **v2 is the default**.
194
+
195
+ ### v2 (Default)
196
+
197
+ ```ruby
198
+ X402::Payments.configure do |config|
199
+ config.private_key = ENV['X402_PRIVATE_KEY']
200
+ config.default_pay_to = ENV['X402_PAY_TO']
201
+ config.protocol_version = 2 # Default, can be omitted
202
+ end
203
+ ```
204
+
205
+ v2 uses CAIP-2 network identifiers (`eip155:84532`) and the `PAYMENT-SIGNATURE` header.
206
+
207
+ ### v1 (Legacy)
208
+
209
+ ```ruby
210
+ X402::Payments.configure do |config|
211
+ config.private_key = ENV['X402_PRIVATE_KEY']
212
+ config.default_pay_to = ENV['X402_PAY_TO']
213
+ config.protocol_version = 1
214
+ end
215
+ ```
216
+
217
+ v1 uses simple network names (`base-sepolia`) and the `X-PAYMENT` header.
218
+
80
219
  ## Usage
81
220
 
82
221
  ### Basic Usage
@@ -92,8 +231,8 @@ header = X402::Payments.generate_header(
92
231
  pay_to: "0xRecipientAddress" # Optional: override recipient (defaults to config)
93
232
  )
94
233
 
95
- # Use the header in an HTTP request
96
- # curl -H "X-PAYMENT: #{header}" http://localhost:3000/api/weather
234
+ # Use the header in an HTTP request (v2 uses PAYMENT-SIGNATURE, v1 uses X-PAYMENT)
235
+ # curl -H "PAYMENT-SIGNATURE: #{header}" http://localhost:3000/api/weather
97
236
  ```
98
237
 
99
238
  **Note**: The `pay_to` parameter allows you to specify a different recipient wallet address per payment. If not provided, it uses the configured `default_pay_to`.
@@ -146,27 +285,27 @@ end
146
285
  header = X402::Payments.generate_header(
147
286
  amount: 0.001,
148
287
  resource: "http://localhost:3000/api/data",
288
+ # version: 1, # Override configured protocol version (1 or 2)
149
289
  # network: "avalanche", # Override default network
150
- # private_key: "0xDifferentKey", # Override default key
151
- # pay_to: "0xRecipientWalletAddress", # Override recipient address
152
- # extra: { # Override EIP-712 domain
153
- # name: "Custom Token",
154
- # version: "1"
155
- # }
290
+ # private_key: "0xDifferentKey", # Override default key
291
+ # pay_to: "0xRecipientWalletAddress", # Override recipient address
156
292
  )
157
293
 
158
294
  puts "Payment Header:"
159
295
  puts header
160
296
 
161
- HTTParty.get("http://localhost:3000/api/data", headers: { "X-PAYMENT" => header })
297
+ # v2 (default) uses PAYMENT-SIGNATURE, v1 uses X-PAYMENT
298
+ HTTParty.get("http://localhost:3000/api/data", headers: { "PAYMENT-SIGNATURE" => header })
162
299
  ```
163
300
 
164
301
  ## How It Works
165
302
 
166
303
  1. **Payment Requirements**: The gem creates a payment requirement specifying the amount (in USDC atomic units), network, and resource
167
- 2. **EIP-712 Signing**: Uses EIP-3009 `TransferWithAuthorization` to create a signature that authorizes the payment
168
- 3. **Header Encoding**: Encodes the signed payment data as a base64 string for the `X-PAYMENT` HTTP header
169
- 4. **Server Validation**: The server validates the signature and settles the payment on-chain
304
+ 2. **Transaction Signing**:
305
+ - **EVM**: Uses EIP-3009 `TransferWithAuthorization` to create a signature that authorizes the payment
306
+ - **Solana**: Creates a partially-signed `TransferChecked` transaction (facilitator adds fee payer signature)
307
+ 3. **Header Encoding**: Encodes the signed payment data as a base64 string for the HTTP header (`PAYMENT-SIGNATURE` for v2, `X-PAYMENT` for v1)
308
+ 4. **Server Validation**: The server validates the signature/transaction and settles the payment on-chain via the [facilitator](https://x402.org/facilitator)
170
309
 
171
310
  ## Example Script
172
311
 
@@ -1,14 +1,51 @@
1
+ # ===========================================
1
2
  # X402 Payments Configuration
2
- # Copy this file to .env and fill in your actual values
3
+ # ===========================================
4
+ # Copy this file to .env and fill in your values
3
5
 
4
- # Required: Private key for signing payments
5
- X402_PRIVATE_KEY=0xYourPrivateKeyHere
6
+ # -------------------------------------------
7
+ # EVM Configuration (Required for EVM chains)
8
+ # -------------------------------------------
9
+ X402_PRIVATE_KEY=0xYourEvmPrivateKey
10
+ X402_PAY_TO=0xEvmPayToAddress
6
11
 
7
- # Required: Default recipient wallet address for payments
8
- X402_PAY_TO=0xYourRecipientAddressHere
12
+ # -------------------------------------------
13
+ # Solana Configuration (Required for Solana)
14
+ # -------------------------------------------
15
+ X402_SOL_PRIVATE_KEY=YourSolPrivateKey
16
+ X402_SOL_PAY_TO=SolPayToWalletAddress
9
17
 
10
- # Optional: Network/chain to use (default: base-sepolia)
11
- X402_CHAIN=base-sepolia
18
+ # Optional: Override default x402.org facilitator
19
+ X402_SOLANA_FEE_PAYER=CKPKJWNdJEqa81x7CkZ14BVPiY6y16Sxs7owznqtWYp5
12
20
 
13
- # Optional: Payment timeout in seconds (default: 600)
14
- X402_MAX_TIMEOUT_SECONDS=600
21
+ # Optional: Solana compute budget for priority fees
22
+ # X402_SOLANA_COMPUTE_UNIT_LIMIT=200000
23
+ # X402_SOLANA_COMPUTE_UNIT_PRICE=1000
24
+
25
+ # -------------------------------------------
26
+ # General Configuration (Optional)
27
+ # -------------------------------------------
28
+ # X402_CHAIN=base-sepolia
29
+ # X402_CURRENCY=USDC
30
+ # X402_PROTOCOL_VERSION=2
31
+ # X402_MAX_TIMEOUT_SECONDS=600
32
+
33
+ # -------------------------------------------
34
+ # Custom RPC URLs (Optional)
35
+ # -------------------------------------------
36
+ # Override default RPC endpoints for any chain
37
+ # Pattern: X402_<CHAIN_NAME>_RPC_URL (dashes become underscores)
38
+
39
+ # EVM chains
40
+ # X402_BASE_RPC_URL=https://your-base-rpc.com
41
+ # X402_BASE_SEPOLIA_RPC_URL=https://your-base-sepolia-rpc.com
42
+ # X402_AVALANCHE_RPC_URL=https://your-avalanche-rpc.com
43
+ # X402_AVALANCHE_FUJI_RPC_URL=https://your-avalanche-fuji-rpc.com
44
+
45
+ # Solana chains
46
+ # X402_SOLANA_RPC_URL=https://your-solana-mainnet-rpc.com
47
+ # X402_SOLANA_DEVNET_RPC_URL=https://your-solana-devnet-rpc.com
48
+
49
+ # Custom chains (example)
50
+ # X402_POLYGON_AMOY_RPC_URL=https://your-rpc-amoy-rpc.com
51
+ # X402_POLYGON_RPC_URL=https://your-polygon-rpc.com
data/examples/README.md CHANGED
@@ -4,7 +4,7 @@ This directory contains example scripts demonstrating how to use the x402-paymen
4
4
 
5
5
  ## generate_payment.rb
6
6
 
7
- Generates a signed payment header and curl command for testing x402 payments.
7
+ Generates a signed payment header and curl command for testing x402 payments on EVM chains and Solana.
8
8
 
9
9
  ### Setup
10
10
 
@@ -20,44 +20,123 @@ cp .env.example .env
20
20
 
21
21
  ```bash
22
22
  # From the gem root directory
23
- cd /Users/zachp/Dev/gems/x402-payments
23
+ cd /path/to/x402-payments
24
24
 
25
25
  # Load environment variables and run
26
26
  export $(cat examples/.env | xargs)
27
27
  ruby examples/generate_payment.rb
28
28
 
29
- # Or set variables inline
29
+ # Or set variables inline (EVM)
30
30
  X402_PRIVATE_KEY="0xYourPrivateKey" \
31
31
  X402_PAY_TO="0xYourRecipientAddress" \
32
- X402_CHAIN="base-sepolia" \
33
32
  ruby examples/generate_payment.rb
33
+
34
+ # Or set variables inline (Solana)
35
+ X402_SOL_PRIVATE_KEY="YourBase58PrivateKey" \
36
+ X402_SOL_PAY_TO="YourSolanaWalletAddress" \
37
+ ruby examples/generate_payment.rb -c solana-devnet
38
+ ```
39
+
40
+ ### Command Line Options
41
+
42
+ ```bash
43
+ ruby examples/generate_payment.rb [options]
44
+
45
+ Options:
46
+ -v, --version VERSION Protocol version (1 or 2, default: 2)
47
+ -c, --chain CHAIN Chain name (e.g., base-sepolia, solana-devnet)
48
+ -h, --help Show help
49
+ ```
50
+
51
+ ### Examples
52
+
53
+ ```bash
54
+ # EVM: Use v2 protocol on Base Sepolia (default)
55
+ ruby examples/generate_payment.rb -v 2
56
+
57
+ # EVM: Use Polygon Amoy testnet (custom chain)
58
+ ruby examples/generate_payment.rb -c polygon-amoy -v 2
59
+
60
+ # EVM: Use built-in Base Sepolia with v1
61
+ ruby examples/generate_payment.rb -c base-sepolia -v 1
62
+
63
+ # Solana: Use Solana devnet
64
+ ruby examples/generate_payment.rb -c solana-devnet -v 2
65
+
66
+ # Solana: Use Solana mainnet
67
+ ruby examples/generate_payment.rb -c solana -v 2
34
68
  ```
35
69
 
36
70
  ### Environment Variables
37
71
 
38
- - `X402_PRIVATE_KEY` - Private key for signing (required)
39
- - `X402_PAY_TO` - Default recipient wallet address for payments (required)
40
- - `X402_CHAIN` - Network to use: `base-sepolia`, `base`, `avalanche-fuji`, or `avalanche` (default: `base-sepolia`)
72
+ **EVM chains:**
73
+ - `X402_PRIVATE_KEY` - EVM private key for signing (required for EVM)
74
+ - `X402_PAY_TO` - EVM recipient wallet address (required for EVM)
75
+
76
+ **Solana chains:**
77
+ - `X402_SOL_PRIVATE_KEY` - Solana private key in base58 or JSON array format (required for Solana)
78
+ - `X402_SOL_PAY_TO` - Solana recipient wallet address (required for Solana)
79
+ - `X402_SOLANA_FEE_PAYER` - Facilitator fee payer (optional, defaults to x402.org facilitator)
80
+ - `X402_SOLANA_COMPUTE_UNIT_LIMIT` - Compute unit limit (optional, default: 200000)
81
+ - `X402_SOLANA_COMPUTE_UNIT_PRICE` - Priority fee in micro-lamports (optional, default: 1000)
82
+
83
+ **General:**
84
+ - `X402_CHAIN` - Network to use (default: `base-sepolia`, can be overridden with `-c`)
85
+
86
+ ### Supported Chains
87
+
88
+ **EVM chains (built-in):**
89
+ - `base-sepolia` (testnet) - default
90
+ - `base` (mainnet)
91
+ - `avalanche-fuji` (testnet)
92
+ - `avalanche` (mainnet)
93
+
94
+ **Solana chains (built-in):**
95
+ - `solana-devnet` (testnet)
96
+ - `solana` (mainnet)
41
97
 
42
- ### Example Output
98
+ **Custom EVM chains (pre-configured in example):**
99
+ - `polygon-amoy` (Polygon testnet, chain ID: 80002)
100
+ - `polygon` (Polygon mainnet, chain ID: 137)
101
+
102
+ ### Example Output (EVM)
43
103
 
44
104
  ```
45
- === X402 Payment Generator ===
46
- Default Pay To: 0xYourRecipientAddress
105
+ === X402 Payment Generator (V2) ===
47
106
  Chain: base-sepolia
107
+ CAIP-2: eip155:84532
108
+ Protocol Version: 2
109
+
110
+ Resource: http://localhost:3000/api/v2/weather/paywalled_info
111
+ Amount: $0.001 USD
48
112
 
49
- Generating payment for:
50
- Resource: http://localhost:3000/api/weather/current
51
- Amount: $0.001 USD
113
+ Header Name: PAYMENT-SIGNATURE
52
114
 
53
- Payment Header (X-PAYMENT):
54
- eyJ4NDAyVmVyc2lvbiI6MSwic2NoZW1lIjoiZXhhY3QiLCJuZXR3b3JrIjoi...
115
+ Payment Header:
116
+ eyJ4NDAyVmVyc2lvbiI6Miwic...
55
117
 
56
118
  Curl Command:
57
- curl -i -H "X-PAYMENT: eyJ4NDAyVmVyc2lvbiI6..." http://localhost:3000/api/weather/current
119
+ curl -s -H "PAYMENT-SIGNATURE: eyJ4NDAyVmVyc2lvbiI6Miwic..." http://localhost:3000/api/v2/weather/paywalled_info | jq .
120
+ ```
121
+
122
+ ### Example Output (Solana)
123
+
124
+ ```
125
+ === X402 Payment Generator (V2) ===
126
+ Chain: solana-devnet (Solana)
127
+ CAIP-2: solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1
128
+ Protocol Version: 2
129
+
130
+ Resource: http://localhost:3000/api/v2/weather/paywalled_info_sol
131
+ Amount: $0.001 USD
132
+
133
+ Header Name: PAYMENT-SIGNATURE
58
134
 
59
- To test the payment, run:
60
- curl -i -H "X-PAYMENT: eyJ4NDAyVmVyc2lvbiI6..." http://localhost:3000/api/weather/current
135
+ Payment Header:
136
+ eyJ4NDAyVmVyc2lvbiI6Miwic...
137
+
138
+ Curl Command:
139
+ curl -s -H "PAYMENT-SIGNATURE: eyJ4NDAyVmVyc2lvbiI6Miwic..." http://localhost:3000/api/v2/weather/paywalled_info_sol | jq .
61
140
  ```
62
141
 
63
142
  You can copy and paste the curl command to test your x402-enabled API endpoint.
@@ -68,21 +147,54 @@ You can modify `generate_payment.rb` to:
68
147
 
69
148
  - Change the amount (e.g., `amount = 0.005` for $0.005)
70
149
  - Target different resources (e.g., `resource_url = "https://api.example.com/data"`)
71
- - Use different networks (set `X402_CHAIN` environment variable)
150
+ - Use different networks (set `X402_CHAIN` environment variable or `-c` flag)
72
151
  - Add custom descriptions
152
+ - Override the fee payer for Solana transactions
73
153
 
74
- ### Example: Generate Payment for Different Resource
154
+ ### Example: Generate EVM Payment Programmatically
75
155
 
76
156
  ```ruby
77
- # At the end of generate_payment.rb, add:
157
+ require 'x402/payments'
78
158
 
79
- puts "\n=== Custom Payment ==="
80
- custom_link = X402::Payments.generate_link(
159
+ X402::Payments.configure do |config|
160
+ config.private_key = ENV['X402_PRIVATE_KEY']
161
+ config.default_pay_to = ENV['X402_PAY_TO']
162
+ config.chain = 'base-sepolia'
163
+ end
164
+
165
+ link = X402::Payments.generate_link(
81
166
  amount: 0.005,
82
167
  resource: "http://localhost:3000/api/premium/data",
83
168
  description: "Premium API access"
84
169
  )
85
170
 
86
- puts "Custom Curl Command:"
87
- puts custom_link[:curl_command]
171
+ puts link[:curl_command]
88
172
  ```
173
+
174
+ ### Example: Generate Solana Payment Programmatically
175
+
176
+ ```ruby
177
+ require 'x402/payments'
178
+
179
+ X402::Payments.configure do |config|
180
+ config.private_key = ENV['X402_SOL_PRIVATE_KEY']
181
+ config.default_pay_to = ENV['X402_SOL_PAY_TO']
182
+ config.chain = 'solana-devnet'
183
+ end
184
+
185
+ link = X402::Payments.generate_link(
186
+ amount: 0.001,
187
+ resource: "http://localhost:3000/api/sol/data",
188
+ description: "Solana payment",
189
+ # fee_payer: "CustomFeePayerAddress" # Optional: override default facilitator
190
+ )
191
+
192
+ puts link[:curl_command]
193
+ ```
194
+
195
+ ### Solana Notes
196
+
197
+ - Both sender and receiver must have a USDC Associated Token Account (ATA)
198
+ - The sender must have USDC in their wallet
199
+ - Transactions are partially signed by the sender; the facilitator adds the fee payer signature
200
+ - Default facilitator is x402.org (`CKPKJWNdJEqa81x7CkZ14BVPiY6y16Sxs7owznqtWYp5`)