Como começar com x402 na Solana

O que é x402?

O x402 é um protocolo aberto para pagamentos nativos da internet. O código de erro 402 significa "Pagamento Necessário" e existe há muito tempo nas especificações HTTP, mas só agora se tornou viável de utilizar graças ao crescimento das redes blockchain. O protocolo 402 refere-se à implementação do padrão HTTP 402 Payment Required: o servidor exige um pagamento antes de retornar uma resposta protegida. Na Solana, isso é comumente implementado pedindo ao cliente que envie uma pequena transferência; o servidor então verifica isso on-chain e serve o conteúdo.

No momento, ainda não está claro qual dos SDKs 402 será o mais popular. Por isso, neste guia mostraremos como implementar o x402 usando um servidor e cliente mínimos, e listaremos todos os SDKs 402 disponíveis com o suporte atual à Solana descrito.

Como funciona?

Existem várias formas de implementar o x402, desde soluções super enxutas até totalmente gerenciadas.

Ideia do protocolo: Use HTTP simples. Um cliente acessa sua URL → você responde com 402 Payment Required e um objeto JSON Payment Requirements → o cliente paga e tenta novamente com um cabeçalho X-PAYMENT → você verifica/liquida → responde 200 OK. Sem contas, sem OAuth.

Diagrama de Fluxo x402Diagrama de Fluxo x402

Nota: O facilitador é completamente opcional e você também pode implementar sua própria lógica de validação com poucas linhas de código. O facilitador abstrai os detalhes de integração com a blockchain do servidor e do cliente, facilitando a implementação.

Bits da especificação para saber: A estrutura PaymentRequirements, o cabeçalho X-PAYMENT codificado em base64, o X-PAYMENT-RESPONSE opcional em caso de sucesso, e a API do facilitador (opcional) para /verify, /settle, /supported. O esquema concreto atual é exato (pagar um valor específico). Outros como upto estão propostos.

Suporte à Solana: O próprio protocolo é agnóstico em relação à chain; na Solana ele suporta todos os tokens SPL. O suporte à Solana está disponível ou em desenvolvimento para a maioria dos SDKs 402.

Mais abaixo há uma lista dos SDKs 402 disponíveis com seu suporte atual à Solana.

Casos de Uso

O x402 viabiliza uma ampla gama de cenários de micropagamento e pagamento por uso que antes não eram economicamente viáveis com blockchain. Imagine a Netflix pagando por cada visualização ou o Spotify pagando por cada música em vez de cobrar assinaturas. Aqui estão algumas ideias possíveis. Mas todo o espectro de possibilidades está aberto à imaginação:

IA & Comércio de Agentes:

  • Acesso a APIs de Agentes de IA: Pague por inferência de LLM, geração de imagens ou chamada de API de modelo de IA (Veja exemplo ACK)
  • Monetização de Servidores MCP: Cobre pelo uso de ferramentas do Model Context Protocol, fontes de dados e capacidades especializadas de agentes (Veja MCPay.tech)
  • Pagamentos entre Agentes: Habilite agentes autônomos a transacionar entre si por serviços e dados (Veja exemplo a2a-x402)
  • Dados Premium de Treinamento de IA: Venda acesso a conjuntos de dados curados por consulta

Conteúdo & Mídia:

  • Artigos com Paywall: Cobre micro-valores por artigo em vez de assinaturas completas
  • Streaming de Vídeo/Áudio: Pague por visualização ou por minuto de conteúdo
  • Imagens em Alta Resolução: Desbloqueie downloads em alta resolução após o pagamento (veja exemplo ACK) ou exemplo x402 coinbase
  • Acesso a Newsletters Premium: Monetize edições individuais de newsletters

Serviços para Desenvolvedores:

  • Medição de API: Pague por chamada RPC, consulta de banco de dados ou unidade de computação (Veja exemplo Corbits)
  • Funções Serverless: Cobre pela execução de funções individuais

Dados & Análises:

  • Dados de Mercado em Tempo Real: Preços por cotação ou por tick
  • Dashboards de Análises: Desbloqueie relatórios específicos ou exportações de dados
  • Dados de Sensores IoT: Micropagamentos por leituras de sensores de redes DePIN

Jogos & Bens Virtuais:

  • Acesso a Servidores de Jogos: Pague por sessão ou por hora
  • Downloads de Mods/Assets: Monetize conteúdo gerado por usuários
  • Taxas de Inscrição em Torneios: Distribuição automatizada de prêmios

Diversos:

  • Filtragem de E-mail/DM: Exija pagamento para acessar sua caixa de entrada (prevenção de spam)
  • Recursos de Computação: Pague por hora de CPU, minuto de GPU ou GB de armazenamento
  • Acesso a VPN/Proxy: Preço por GB de largura de banda
  • Downloads de Arquivos Únicos: Venda arquivos digitais sem overhead de assinatura (Veja exemplo ACK)

A principal vantagem do x402 na Solana são os baixos custos de transação (frações de centavo), tornando os verdadeiros micropagamentos viáveis, além da liquidação instantânea que permite controle de acesso em tempo real.

SDKs e seu suporte à Solana

Esta é uma lista em evolução e será atualizada à medida que mais SDKs forem lançados ou o suporte à Solana for adicionado.

SDK / ProjetoSuporte à SolanaNotasDocs / URL
CorbitsSimSDK conveniente para 402 na SolanaDocs
MCPay.techSimPague por servidores MCP em micropagamentosSite
PayAI FacilitatorSimFacilitador x402 com suporte à Solanapayai.network
CoinbaseSim / Python em andamentoA implementação de referência da Coinbase do protocolo x402GitHub
ACKEm PRUm protocolo de pagamento para agentes com suporte a x402GitHub
CrossmintEm desenvolvimentoPagamentos, carteiras; finanças agênticas; não específico para x402crossmint.com
A2A x402 (Google)Em desenvolvimentoPagamentos entre agentes usando IA do GoogleGitHub
Nexus (Thirdweb)Em desenvolvimentoWrapper x402 em torno de chaves de APINexus
x402scanN/A (Explorer)Explorer do ecossistema x402 (não é um SDK)x402scan.com
Exemplo NativoSimExemplo mínimo sem dependênciasExemplos

Corbits

SDK focado em Solana para implementar fluxos x402 rapidamente na Solana. Veja a documentação: https://corbits.dev/

Exemplo que permite pagar por requisições RPC na Solana.

npm install @faremeter/payment-solana @faremeter/fetch @faremeter/info
@solana/web3.js

Crie um payer-wallet.json e financie-o com algum USDC e algum SOL na mainnet.

import {
Keypair,
PublicKey,
VersionedTransaction,
Connection
} from "@solana/web3.js";
import { createPaymentHandler } from "@faremeter/payment-solana/exact";
import { wrap } from "@faremeter/fetch";
import { lookupKnownSPLToken } from "@faremeter/info/solana";
import * as fs from "fs";
// Load keypair from file
const keypairData = JSON.parse(fs.readFileSync("./payer-wallet.json", "utf-8"));
const keypair = Keypair.fromSecretKey(Uint8Array.from(keypairData));
const network = "mainnet-beta";
const connection = new Connection("https://api.mainnet.solana.com");
const usdcInfo = lookupKnownSPLToken(network, "USDC");
const usdcMint = new PublicKey(usdcInfo.address);
// Create wallet interface
const wallet = {
network,
publicKey: keypair.publicKey,
updateTransaction: async (tx: VersionedTransaction) => {
tx.sign([keypair]);
return tx;
}
};
// Setup payment handler
const handler = createPaymentHandler(wallet, usdcMint, connection);
const fetchWithPayer = wrap(fetch, { handlers: [handler] });
// Call the API - payment happens automatically
const response = await fetchWithPayer("https://helius.api.corbits.dev", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "getBlockHeight"
})
});
const data = await response.json();
console.log(data);
npx tsx e2e.ts

Isso pagará pela requisição RPC e retornará a altura do bloco, pagando usando o protocolo corbits 402.

Coinbase

A implementação de referência da Coinbase do protocolo x402 fornece bibliotecas TypeScript e exemplos tanto para fluxos de cliente quanto de servidor. O repositório inclui testes de ponta a ponta cobrindo 6 cenários diferentes de SVM (Solana Virtual Machine). A implementação abrange verificação de pagamento, geração de recibos e tratamento de erros.

Principais recursos:

  • Implementações de cliente e servidor em TypeScript
  • Utilitários de verificação de pagamento
  • Suporte a múltiplos esquemas de pagamento (valor exato, valor máximo)
  • Suite de testes com exemplos de transações na Solana
  • Separação entre lógica de protocolo e lógica de negócio

Você pode encontrar um exemplo fácil de usar com um servidor e cliente mínimos aqui.

const app = express();
const PORT = 3000;
// Apply x402 payment middleware
// This automatically handles:
// - 402 responses with payment requirements
// - Payment verification (pre-flight checks)
// - Transaction submission via facilitator
// - Settlement confirmation
app.use(
paymentMiddleware(RECIPIENT, {
// Protected endpoint: requires $0.001 USDC payment
"GET /premium": {
price: "$0.0001", // Price in USD (converted to USDC)
network: "solana-devnet" // Solana devnet
},
// Another endpoint with different price
"GET /expensive": {
price: "$0.001",
network: "solana-devnet"
}
})
);
// Protected endpoints - only accessible after payment
app.get("/premium", (req, res) => {
res.json({
message: "🎉 Premium content accessed!",
data: {
secret: "This is premium content",
timestamp: new Date().toISOString()
}
});
});

O suporte a Python está em desenvolvimento com um exemplo funcional de ponta a ponta disponível aqui.

ACK

O Agent Commerce Kit (ACK) suporta o protocolo x402, mas adiciona camadas críticas para a economia de agentes: identidade verificável de agentes (ACK-ID) usando W3C DIDs/VCs e recibos criptograficamente seguros (ACK-Pay) como Credenciais Verificáveis. Isso permite que os agentes provem propriedade, se autentiquem de forma autônoma e gerem provas de pagamento prontas para conformidade, abordando a crise de identidade e as barreiras de transação que impedem os agentes de IA de participar do comércio.

Diagrama de Fluxo ACKDiagrama de Fluxo ACK

Há um PR com um exemplo e2e que ainda não foi mesclado, mas funciona. Há também um Exemplo ao Vivo mostrando como criar paywall em imagens, uma jukebox e uma API que anima imagens. O código-fonte dos exemplos junto com um bot no Twitter que usa a API para animar imagens na timeline pode ser encontrado aqui.

MCPay.tech

Micropagamentos por requisição para servidores MCP (Model Context Protocol) usando fluxos semelhantes ao x402. Permite que desenvolvedores monetizem ferramentas e recursos MCP exigindo pequenos pagamentos por cada chamada de API ou invocação de ferramenta, facilitando a cobrança pelo acesso de agentes de IA a fontes de dados premium, ferramentas especializadas ou recursos computacionais. Site: https://mcpay.tech/

PayAI Facilitator

Facilitador x402 focado em Solana com um merchant echo ao vivo para testar e reembolsar pagamentos. O PayAI está, no momento, absorvendo todas as taxas de transação. Site: https://payai.network/

A2A x402 (Google)

Iniciativa de pagamentos 402 entre agentes que explora fluxos padronizados de pagamento obrigatório. O suporte à Solana está atualmente em andamento e um exemplo funcional de chat pode ser encontrado aqui

Crossmint

A Crossmint é uma plataforma completa para empresas e agentes integrarem trilhos cripto — incluindo carteiras, onramps, orquestração de stablecoins e muito mais. O suporte ao x402 na Solana está atualmente em andamento e deve ser concluído até 30/10/2025. Site: https://www.crossmint.com/

x402scan

Explorer para o ecossistema x402 que fornece estatísticas abrangentes, listagens de projetos e análises para implementações x402. Acompanhe volumes de transações, descubra merchants ativos e monitore o crescimento dos endpoints de pagamento obrigatório em diferentes redes. Site: https://x402scan.com/

Nexus (Thirdweb)

O Thirdweb Nexus desenvolve um wrapper x402 em torno de chaves de API (atualmente em desenvolvimento). Site: https://nexus.thirdweb.com/

Exemplo nativo

Um exemplo nativo sem dependências e com um servidor e cliente mínimos.

Você pode clonar o repositório e executar o exemplo:

git clone https://github.com/Woody4618/x402-solana-examples
npm install
# Terminal 1: Start server
npm run usdc:server
# Terminal 2: Run client (requires devnet USDC)
npm run usdc:client

Visão Geral do Fluxo

  1. O cliente faz uma requisição para /premium.
  2. O servidor responde com 402 e os termos de pagamento: destinatário e valor.
  3. O cliente cria uma transação com uma instrução de transferência para o destinatário.
  4. O cliente tenta novamente /premium com o payload da transação.
  5. O servidor verifica a transação e a envia para a rede.
  6. Após a confirmação, o servidor responde com 200.

Alternativa específica para Solana: No Solana, você poderia implementar uma variante em que o cliente envia a transação diretamente para a rede com uma instrução de memo (em vez de enviá-la ao servidor), e então envia apenas a assinatura da transação ao servidor para verificação. Isso resolve o problema de perda de conexão—se o cliente desconectar após o pagamento, mas antes de receber o conteúdo, ele pode tentar novamente com a mesma assinatura, pois o pagamento já está confirmado onchain. No entanto, essa abordagem se desvia do fluxo padrão do x402.org (que espera que o servidor transmita a transação), portanto estamos utilizando a abordagem padrão neste exemplo.

Nota: O código deste exemplo não foi auditado, não está pronto para produção e destina-se apenas a fins de demonstração. Ele mostra que é possível implementar o x402 sem dependências e sem o uso de um facilitador. Usar um facilitador é conveniente porque eles ocultam a complexidade e podem assumir as taxas de transação, mas também podem ser um ponto único de falha — quando a carteira do facilitador ficar sem fundos, por exemplo. O servidor de exemplo envia transações assinadas pelo cliente. Pode ser necessário validar essas transações.

Servidor Mínimo (Express)

// x402-compliant server with USDC (SPL Token) payments
import express from "express";
import { Connection, PublicKey, Transaction } from "@solana/web3.js";
import { TOKEN_PROGRAM_ID, getAssociatedTokenAddress } from "@solana/spl-token";
const connection = new Connection("https://api.devnet.solana.com", "confirmed");
// Devnet USDC mint address
const USDC_MINT = new PublicKey("4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU");
// Your recipient wallet address (same as SOL example)
const RECIPIENT_WALLET = new PublicKey(
"seFkxFkXEY9JGEpCyPfCWTuPZG9WK6ucf95zvKCfsRX"
);
// Derive the recipient's USDC token account (Associated Token Account)
const RECIPIENT_TOKEN_ACCOUNT = await getAssociatedTokenAddress(
USDC_MINT,
RECIPIENT_WALLET
);
// Picking a small USDC price
const PRICE_USDC = 100; // 0.0001 USDC
const app = express();
app.use(express.json());
// x402 endpoint - Quote or verify payment
app.get("/premium", async (req, res) => {
const xPaymentHeader = req.header("X-Payment");
// If client provided X-Payment header, verify and submit transaction
if (xPaymentHeader) {
try {
// Decode base64 and parse JSON (x402 standard)
const paymentData = JSON.parse(
Buffer.from(xPaymentHeader, "base64").toString("utf-8")
) as {
x402Version: number;
scheme: string;
network: string;
payload: {
serializedTransaction: string;
};
};
console.log("Received USDC payment proof from client");
console.log(` Network: ${paymentData.network}`);
// Deserialize the transaction
const txBuffer = Buffer.from(
paymentData.payload.serializedTransaction,
"base64"
);
const tx = Transaction.from(txBuffer);
console.log("Verifying SPL Token transfer instructions...");
// Step 1: Introspect and decode SPL Token transfer instruction
const instructions = tx.instructions;
let validTransfer = false;
let transferAmount = 0;
for (const ix of instructions) {
// Check if this is a Token Program instruction
if (ix.programId.equals(TOKEN_PROGRAM_ID)) {
// SPL Token Transfer instruction layout:
// [0] = instruction type (3 for Transfer)
// [1-8] = amount (u64, little-endian)
if (ix.data.length >= 9 && ix.data[0] === 3) {
// Read the amount (u64 in little-endian, starts at byte 1)
transferAmount = Number(ix.data.readBigUInt64LE(1));
// Verify accounts: [source, destination, owner]
if (ix.keys.length >= 2) {
const destAccount = ix.keys[1].pubkey;
if (
destAccount.equals(RECIPIENT_TOKEN_ACCOUNT) &&
transferAmount >= PRICE_USDC
) {
validTransfer = true;
console.log(
` ✓ Valid USDC transfer: ${transferAmount / 1000000} USDC`
);
console.log(` To: ${RECIPIENT_TOKEN_ACCOUNT.toBase58()}`);
break;
}
}
}
}
}
if (!validTransfer) {
return res.status(402).json({
error:
"Transaction does not contain valid USDC transfer to recipient with correct amount",
details:
transferAmount > 0
? `Found transfer of ${transferAmount}, expected ${PRICE_USDC}`
: "No valid token transfer instruction found"
});
}
// Step 2: Simulate the transaction BEFORE submitting
console.log("Simulating transaction...");
try {
const simulation = await connection.simulateTransaction(tx);
if (simulation.value.err) {
console.error("Simulation failed:", simulation.value.err);
return res.status(402).json({
error: "Transaction simulation failed",
details: simulation.value.err,
logs: simulation.value.logs
});
}
console.log(" ✓ Simulation successful");
} catch (simError) {
console.error("Simulation error:", simError);
return res.status(402).json({
error: "Failed to simulate transaction",
details:
simError instanceof Error ? simError.message : "Unknown error"
});
}
// Step 3: Submit the transaction (only if verified and simulated successfully)
// Note: Solana blockchain automatically rejects duplicate transaction signatures
console.log("Submitting transaction to network...");
const signature = await connection.sendRawTransaction(txBuffer, {
skipPreflight: false,
preflightCommitment: "confirmed"
});
console.log(`Transaction submitted: ${signature}`);
// Wait for confirmation
const confirmation = await connection.confirmTransaction(
signature,
"confirmed"
);
if (confirmation.value.err) {
return res.status(402).json({
error: "Transaction failed onchain",
details: confirmation.value.err
});
}
// Fetch the transaction to verify payment details
const confirmedTx = await connection.getTransaction(signature, {
commitment: "confirmed",
maxSupportedTransactionVersion: 0
});
if (!confirmedTx) {
return res.status(402).json({
error: "Could not fetch confirmed transaction"
});
}
// Verify token balance changes from transaction metadata
const postTokenBalances = confirmedTx.meta?.postTokenBalances ?? [];
const preTokenBalances = confirmedTx.meta?.preTokenBalances ?? [];
// Find the recipient's token account in the balance changes
let amountReceived = 0;
for (let i = 0; i < postTokenBalances.length; i++) {
const postBal = postTokenBalances[i];
const preBal = preTokenBalances.find(
(pre) => pre.accountIndex === postBal.accountIndex
);
// Check if this is the recipient's account
const accountKey =
confirmedTx.transaction.message.staticAccountKeys[
postBal.accountIndex
];
if (accountKey && accountKey.equals(RECIPIENT_TOKEN_ACCOUNT)) {
const postAmount = postBal.uiTokenAmount.amount;
const preAmount = preBal?.uiTokenAmount.amount ?? "0";
amountReceived = Number(postAmount) - Number(preAmount);
break;
}
}
if (amountReceived < PRICE_USDC) {
return res.status(402).json({
error: `Insufficient payment: received ${amountReceived}, expected ${PRICE_USDC}`
});
}
console.log(
`Payment verified: ${amountReceived / 1000000} USDC received`
);
console.log(
`View transaction: https://explorer.solana.com/tx/${signature}?cluster=devnet`
);
// Payment verified! Return premium content
return res.json({
data: "Premium content - USDC payment verified!",
paymentDetails: {
signature,
amount: amountReceived,
amountUSDC: amountReceived / 1000000,
recipient: RECIPIENT_TOKEN_ACCOUNT.toBase58(),
explorerUrl: `https://explorer.solana.com/tx/${signature}?cluster=devnet`
}
});
} catch (e) {
console.error("Payment verification error:", e);
return res.status(402).json({
error: "Payment verification failed",
details: e instanceof Error ? e.message : "Unknown error"
});
}
}
// No payment provided - return 402 with payment details
console.log("New USDC payment quote requested");
return res.status(402).json({
payment: {
recipientWallet: RECIPIENT_WALLET.toBase58(),
tokenAccount: RECIPIENT_TOKEN_ACCOUNT.toBase58(),
mint: USDC_MINT.toBase58(),
amount: PRICE_USDC,
amountUSDC: PRICE_USDC / 1000000,
cluster: "devnet",
message: "Send USDC to the token account"
}
});
});
app.listen(3001, () => console.log("x402 USDC server listening on :3001"));

Cliente Mínimo (Node)

import { Connection, Keypair, PublicKey, Transaction } from "@solana/web3.js";
import {
createTransferInstruction,
getOrCreateAssociatedTokenAccount,
createAssociatedTokenAccountInstruction,
getAccount
} from "@solana/spl-token";
import fetch from "node-fetch";
import { readFileSync } from "fs";
const connection = new Connection("https://api.devnet.solana.com", "confirmed");
const keypairData = JSON.parse(
readFileSync("./pay-in-usdc/client.json", "utf-8")
);
const payer = Keypair.fromSecretKey(Uint8Array.from(keypairData));
async function run() {
// 1) Request payment quote from server
const quote = await fetch("http://localhost:3001/premium");
const q = (await quote.json()) as {
payment: {
tokenAccount: string;
mint: string;
amount: number;
amountUSDC: number;
cluster: string;
};
};
if (quote.status !== 402) throw new Error("Expected 402 quote");
const recipientTokenAccount = new PublicKey(q.payment.tokenAccount);
const mint = new PublicKey(q.payment.mint);
const amount = q.payment.amount;
console.log("USDC Payment required:");
console.log(` Recipient Token Account: ${q.payment.tokenAccount}`);
console.log(` Mint (USDC): ${q.payment.mint}`);
console.log(
` Amount: ${q.payment.amountUSDC} USDC (${amount} smallest units)`
);
// 2) Get or create the payer's associated token account
console.log("\nChecking/creating associated token account...");
const payerTokenAccount = await getOrCreateAssociatedTokenAccount(
connection,
payer,
mint,
payer.publicKey
);
console.log(` Payer Token Account: ${payerTokenAccount.address.toBase58()}`);
// Check if payer has enough USDC
const balance = await connection.getTokenAccountBalance(
payerTokenAccount.address
);
console.log(` Current Balance: ${balance.value.uiAmountString} USDC`);
if (Number(balance.value.amount) < amount) {
throw new Error(
`Insufficient USDC balance. Have: ${balance.value.uiAmountString}, Need: ${q.payment.amountUSDC}`
);
}
// 3) Check if recipient token account exists, create if not
console.log("\nChecking recipient token account...");
let recipientAccountExists = false;
try {
await getAccount(connection, recipientTokenAccount);
recipientAccountExists = true;
console.log(" ✓ Recipient token account exists");
} catch (error) {
console.log(" ⚠ Recipient token account doesn't exist, will create it");
}
// 4) Create USDC transfer transaction (but DON'T submit it)
const { blockhash } = await connection.getLatestBlockhash();
const tx = new Transaction({
feePayer: payer.publicKey,
blockhash,
lastValidBlockHeight: (await connection.getLatestBlockhash())
.lastValidBlockHeight
});
// Add create account instruction if needed
if (!recipientAccountExists) {
// We need to know the recipient wallet address to create the ATA
// The server should provide this, so let's get it from the wallet address
// Usually the server will already have the token account, but to be sure for the examples
// lets create one.
const recipientWallet = new PublicKey(
"seFkxFkXEY9JGEpCyPfCWTuPZG9WK6ucf95zvKCfsRX"
);
const createAccountIx = createAssociatedTokenAccountInstruction(
payer.publicKey, // payer
recipientTokenAccount, // associated token account address
recipientWallet, // owner
mint // mint
);
tx.add(createAccountIx);
console.log(" + Added create token account instruction");
}
// Add transfer instruction
const transferIx = createTransferInstruction(
payerTokenAccount.address, // source
recipientTokenAccount, // destination
payer.publicKey, // owner
amount // amount in smallest units
);
tx.add(transferIx);
// Sign the transaction (but don't send it, the server will do that)
tx.sign(payer);
// Serialize the signed transaction
const serializedTx = tx.serialize().toString("base64");
console.log("\nTransaction created and signed (not submitted yet)");
console.log(` Instructions: ${tx.instructions.length}`);
// 4) Send X-Payment header with serialized transaction (x402 standard)
const paymentProof = {
x402Version: 1,
scheme: "exact",
network:
q.payment.cluster === "devnet" ? "solana-devnet" : "solana-mainnet",
payload: {
serializedTransaction: serializedTx
}
};
// Base64 encode the payment proof
const xPaymentHeader = Buffer.from(JSON.stringify(paymentProof)).toString(
"base64"
);
console.log(
"\nSending payment proof to server (server will submit transaction)..."
);
const paid = await fetch("http://localhost:3001/premium", {
headers: {
"X-Payment": xPaymentHeader
}
});
const result = (await paid.json()) as {
data?: string;
error?: string;
paymentDetails?: {
signature: string;
amount: number;
amountUSDC: number;
recipient: string;
explorerUrl: string;
};
};
console.log("\nServer response:");
console.log(result);
// Display explorer link if payment was successful
if (result.paymentDetails?.explorerUrl) {
console.log("\n🔗 View transaction on Solana Explorer:");
console.log(result.paymentDetails.explorerUrl);
}
}
run().catch(console.error);

Melhorias

  • Considere retornar um JWT após o pagamento para que os clientes possam reutilizar o acesso brevemente. O ACK torna isso bastante simples.
  • Certifique-se de que suas chaves não sejam expostas e armazene-as em variáveis de ambiente.

Is this page helpful?

Índice

Editar Página
© 2026 Fundação Solana. Todos os direitos reservados.
Como começar com x402 na Solana | Solana