2026-04-06 16:27:52 -04:00
|
|
|
/**
|
|
|
|
|
* x402 v2 axios example — USDC on Base (CAIP-2). Run from repo root:
|
|
|
|
|
* `node examples/01-x402-axios-client.js`
|
|
|
|
|
* The x402 stack pulls in `siwe`, which expects `ethers` as a peer — it is listed in package.json.
|
|
|
|
|
*
|
|
|
|
|
* Uses `toClientEvmSigner(account, publicClient)` so the signer has `readContract` (required by
|
|
|
|
|
* @x402/evm ClientEvmSigner). Optional: `BASE_RPC_URL` for Base / Base Sepolia HTTP RPC.
|
|
|
|
|
*/
|
|
|
|
|
import axios, { AxiosHeaders } from 'axios'
|
2026-03-18 20:26:01 -04:00
|
|
|
|
2026-04-06 16:27:52 -04:00
|
|
|
import { createPublicClient, http } from 'viem'
|
|
|
|
|
import { base, baseSepolia } from 'viem/chains'
|
|
|
|
|
import { privateKeyToAccount } from 'viem/accounts'
|
|
|
|
|
import { x402Client, wrapAxiosWithPayment } from '@x402/axios'
|
|
|
|
|
import { registerExactEvmScheme } from '@x402/evm/exact/client'
|
|
|
|
|
import { toClientEvmSigner } from '@x402/evm'
|
2026-03-10 15:25:38 -04:00
|
|
|
|
2026-04-21 19:24:56 -07:00
|
|
|
// const baseURL = 'http://localhost:5942' // Local
|
|
|
|
|
const baseURL = 'https://x402.fullstack.cash' // Production
|
2026-03-23 12:57:24 -07:00
|
|
|
|
2026-03-10 15:25:38 -04:00
|
|
|
const endpointPath = '/v6/full-node/blockchain/getBlockchainInfo'
|
2026-04-06 16:27:52 -04:00
|
|
|
const pKey = process.env.PRIVATE_KEY || process.env.EVM_PRIVATE_KEY || ''
|
2026-04-21 19:24:56 -07:00
|
|
|
console.log('pKey: ', pKey)
|
2026-04-06 16:27:52 -04:00
|
|
|
|
2026-04-21 19:24:56 -07:00
|
|
|
// const x402Network = 'eip155:84532' // sepolia eip155:84532
|
|
|
|
|
const x402Network = 'eip155:8453' // mainnet eip155:8453
|
2026-04-06 16:27:52 -04:00
|
|
|
|
|
|
|
|
if (!pKey) throw new Error('PRIVATE_KEY or EVM_PRIVATE_KEY env required!')
|
2026-03-10 15:25:38 -04:00
|
|
|
|
2026-03-18 20:26:01 -04:00
|
|
|
const account = privateKeyToAccount(pKey)
|
2026-04-06 16:27:52 -04:00
|
|
|
const chain = x402Network === 'eip155:84532' ? baseSepolia : base
|
|
|
|
|
const defaultRpc =
|
|
|
|
|
x402Network === 'eip155:84532'
|
|
|
|
|
? 'https://sepolia.base.org'
|
|
|
|
|
: 'https://mainnet.base.org'
|
|
|
|
|
const publicClient = createPublicClient({
|
|
|
|
|
chain,
|
|
|
|
|
transport: http(process.env.BASE_RPC_URL || defaultRpc)
|
2026-03-10 15:25:38 -04:00
|
|
|
})
|
2026-04-06 16:27:52 -04:00
|
|
|
const signer = toClientEvmSigner(account, publicClient)
|
2026-03-10 15:25:38 -04:00
|
|
|
|
2026-04-06 16:27:52 -04:00
|
|
|
// eslint-disable-next-line new-cap
|
|
|
|
|
const client = new x402Client()
|
|
|
|
|
registerExactEvmScheme(client, {
|
|
|
|
|
signer,
|
|
|
|
|
networks: [x402Network]
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const api = wrapAxiosWithPayment(
|
2026-03-10 15:25:38 -04:00
|
|
|
axios.create({
|
2026-03-18 20:26:01 -04:00
|
|
|
baseURL,
|
2026-04-06 16:27:52 -04:00
|
|
|
headers: new AxiosHeaders({
|
2026-03-18 20:26:01 -04:00
|
|
|
'Content-Type': 'application/json'
|
2026-04-06 16:27:52 -04:00
|
|
|
})
|
2026-03-10 15:25:38 -04:00
|
|
|
}),
|
|
|
|
|
client
|
|
|
|
|
)
|
2026-04-21 19:24:56 -07:00
|
|
|
|
2026-03-10 15:25:38 -04:00
|
|
|
const request = async () => {
|
|
|
|
|
console.log('\n\nStep 1: Making first call, expecting a 402 error returned.')
|
|
|
|
|
try {
|
|
|
|
|
const response = await axios.get(baseURL + endpointPath)
|
|
|
|
|
console.log(response.data)
|
|
|
|
|
console.log('Step 1 failed. Expected a 402 error.')
|
|
|
|
|
} catch (err) {
|
|
|
|
|
console.log(`Status code: ${err?.response?.status}`)
|
|
|
|
|
console.log(`Error data: ${JSON.stringify(err.response.data, null, 2)}`)
|
2026-04-06 16:27:52 -04:00
|
|
|
console.log(
|
|
|
|
|
`Error StatusText: ${JSON.stringify(err.response.statusText, null, 2)}`
|
|
|
|
|
)
|
|
|
|
|
|
2026-03-10 15:25:38 -04:00
|
|
|
console.log('\n\n')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log('\n\nStep 2: Making second call with a payment.')
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// Call the same endpoint path with a payment.
|
|
|
|
|
const paidRes = await api.get(endpointPath)
|
|
|
|
|
console.log('Data returned after payment: ', paidRes.data)
|
|
|
|
|
} catch (err) {
|
|
|
|
|
console.log('Step 2 failed. Expected a 200 success status code.')
|
|
|
|
|
console.log(`Status code: ${err?.response?.status}`)
|
2026-04-21 19:24:56 -07:00
|
|
|
// console.log('err: ', err)
|
2026-04-06 16:27:52 -04:00
|
|
|
console.log(
|
|
|
|
|
`Error StatusText: ${JSON.stringify(err.response.statusText, null, 2)}`
|
|
|
|
|
)
|
2026-03-10 15:25:38 -04:00
|
|
|
console.log(`Error data: ${JSON.stringify(err.response.data, null, 2)}`)
|
2026-04-21 19:24:56 -07:00
|
|
|
console.log('payment-required header: ', err.response.headers['payment-required'])
|
2026-03-10 15:25:38 -04:00
|
|
|
|
|
|
|
|
process.exit(1)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
request()
|