import {
Connection,
PublicKey,
Transaction,
Keypair
} from '@solana/web3.js';
import { Token, TOKEN_PROGRAM_ID } from '@solana/spl-token';
async function createPayment(
payer: Keypair,
recipient: string,
amountUsdc: number
): Promise<string> {
const connection = new Connection('https://api.devnet.solana.com');
const usdcMint = new PublicKey('4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU');
const amountMicro = Math.floor(amountUsdc * 1_000_000);
// Get token accounts
const token = new Token(connection, usdcMint, TOKEN_PROGRAM_ID, payer);
const fromAccount = await token.getOrCreateAssociatedAccountInfo(payer.publicKey);
const toAccount = await token.getOrCreateAssociatedAccountInfo(new PublicKey(recipient));
// Create transfer instruction
const instruction = Token.createTransferInstruction(
TOKEN_PROGRAM_ID,
fromAccount.address,
toAccount.address,
payer.publicKey,
[],
amountMicro
);
// Build transaction
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
const transaction = new Transaction().add(instruction);
transaction.recentBlockhash = blockhash;
transaction.lastValidBlockHeight = lastValidBlockHeight;
transaction.feePayer = payer.publicKey;
// Sign
transaction.sign(payer);
// Create x402 payload
const payload = {
x402Version: 1,
scheme: 'exact',
network: 'solana-devnet',
payload: {
authorization: {
from: payer.publicKey.toBase58(),
to: recipient,
value: amountMicro.toString(),
asset: usdcMint.toBase58(),
validBefore: Math.floor(Date.now() / 1000) + 120,
nonce: crypto.randomUUID()
},
signedTransaction: transaction.serialize().toString('base64'),
transactionMeta: { blockhash, lastValidBlockHeight }
}
};
return Buffer.from(JSON.stringify(payload)).toString('base64');
}