Skip to main content

Solana USDC Demo

The Solana demo shows how to implement HTTP 402 paywalls on Solana blockchain using the Faremeter middleware with Crossmint smart wallet integration. This demonstrates cross-chain compatibility of the x402 payment protocol.

Overview

This demo implements a payment-protected endpoint on Solana, supporting both:
  • Crossmint API Signer: Server-side signing with Crossmint smart wallets
  • Crossmint Delegated Wallet: External private key signer to Crossmint smart wallet
Key Features:
  • Solana blockchain payment settlement
  • USDC SPL token payments
  • Faremeter middleware for Solana x402 support
  • Crossmint wallet integration for Solana
  • Protected /protected endpoint requiring 0.01 USDC
  • Supports both devnet and mainnet-beta

Prerequisites

Development Tools

  • Node.js 18+
  • Solana CLI tools (for keypair generation)
  • npm

Crossmint Account

  1. Create account at https://www.crossmint.com/
  2. Generate Server API Key (sk_staging_...)
  3. Configure for Solana network support

Testnet Tokens (Devnet)

SOL for transaction fees: USDC for payments:

Setup

Method 1: Crossmint API Signer

1. Generate Keypairs

mkdir keypairs

# Generate payer keypair
solana-keygen new --no-bip39-passphrase -o keypairs/payer.json

# Generate payment recipient keypair
solana-keygen new --no-bip39-passphrase -o keypairs/payto.json

2. Configure Environment

Create .env file:
.env
# Keypair paths
PAYTO_KEYPAIR_PATH=./keypairs/payto.json
PAYER_KEYPAIR_PATH=./keypairs/payer.json

# Solana Network: "devnet" or "mainnet-beta"
NETWORK=devnet

# Crossmint Configuration
CROSSMINT_API_KEY=sk_staging_...
CROSSMINT_WALLET=
CROSSMINT_ENVIRONMENT=staging

# Server Configuration
PORT=3000

# Solana RPC URL
RPC_URL=https://solana-devnet.g.alchemy.com/v2/YOUR_API_KEY

# Facilitator URL
FACILITATOR_URL=https://facilitator.corbits.dev
# Or run locally: http://localhost:4000
Configuration Options:
  • PAYTO_KEYPAIR_PATH - Recipient wallet keypair file
  • PAYER_KEYPAIR_PATH - Payer wallet keypair file
  • NETWORK - Solana cluster (devnet or mainnet-beta)
  • CROSSMINT_API_KEY - Your Crossmint server API key
  • PORT - Server listen port
  • RPC_URL - Solana RPC endpoint
  • FACILITATOR_URL - Faremeter facilitator endpoint

3. Fund Accounts

Get the public keys:
# View payer address
solana-keygen pubkey keypairs/payer.json

# View payto address
solana-keygen pubkey keypairs/payto.json
Fund both addresses with SOL and USDC using the faucets mentioned above.

4. Install and Build

npm install
npm run build

5. Start Server

npm run start:server
Expected Output:
Server starting on port 3000
Network: devnet
PayTo: 8xK...abc
Facilitator URL: https://facilitator.corbits.dev

6. Run Test Script

npm run start:test
This script:
  1. Attempts to access /protected without payment (gets 402)
  2. Creates payment authorization
  3. Retries with X-PAYMENT header
  4. Receives success response

Method 2: Crossmint Delegated Wallet

Delegated wallets use an external private key as admin signer for a Crossmint smart wallet.

1. Generate Payer Keypair

mkdir keypairs
solana-keygen new --no-bip39-passphrase -o keypairs/payer.json

2. Fund Payer

Ensure the payer has SOL and USDC on Solana devnet.

3. Create Delegated Wallet

npm run create:wallet
Output:
Creating Crossmint delegated wallet...
✅ Wallet created!
Address: 9xY...xyz
Admin Signer: 8xK...abc (from payer.json)
Save the wallet address to your .env:
CROSSMINT_WALLET=9xY...xyz

4. Check Wallet Configuration

npm run check:wallet
Verifies:
  • Wallet exists
  • Admin signer is configured
  • Balances (SOL and USDC)

5. Start Facilitator (Terminal 1)

Clone and run Faremeter locally:
git clone https://github.com/faremeter/faremeter
cd faremeter
# Follow QUICKSTART.md
npm install
npm run dev

6. Start Server (Terminal 2)

npm run start:server

7. Run Delegated Wallet Test (Terminal 3)

npm run start:delegated

Server Implementation

The server uses Faremeter middleware for Solana x402 support:
src/server.ts
import express from "express";
import { createMiddleware } from "@faremeter/middleware/express";
import { x402Exact, type KnownCluster } from "@faremeter/info/solana";
import { Keypair } from "@solana/web3.js";
import fs from "fs";

const { PAYTO_KEYPAIR_PATH, NETWORK, PORT, FACILITATOR_URL } = process.env;

// Load payment recipient keypair
const payToKeypair = Keypair.fromSecretKey(
  Uint8Array.from(JSON.parse(fs.readFileSync(PAYTO_KEYPAIR_PATH, "utf-8")))
);

const network = (NETWORK || "mainnet-beta") as KnownCluster;
const port = parseInt(PORT || "3000", 10);
const payTo = payToKeypair.publicKey.toBase58();

const app = express();
const facilitatorURL = FACILITATOR_URL || "http://localhost:4000";

// Protected endpoint with payment requirement
app.get(
  "/protected",
  await createMiddleware({
    facilitatorURL,
    accepts: [
      // USDC Exact Payment
      x402Exact({
        network,
        asset: "USDC",
        amount: "10000", // 0.01 USDC (6 decimals)
        payTo,
      }),
    ],
  }),
  (_, res) => {
    res.json({ msg: "success" });
  }
);

app.listen(port);

Payment Configuration

The x402Exact function creates payment requirements:
x402Exact({
  network: "devnet",           // Solana cluster
  asset: "USDC",               // SPL token name
  amount: "10000",             // 0.01 USDC in base units
  payTo: "8xK...abc",          // Recipient address
})

Alternative: Native SOL Payments

You can also accept native SOL:
import { xSolanaSettlement } from "@faremeter/info/solana";

accepts: [
  xSolanaSettlement({
    network: "devnet",
    asset: "sol",
    amount: "1000000",  // 0.001 SOL (9 decimals)
    payTo,
  })
]

Usage

Request Without Payment

curl -H "Accept: application/vnd.x402+json" http://localhost:3000/protected
Response (HTTP 402):
{
  "accepts": [{
    "payTo": "8xK...abc",
    "network": "devnet",
    "asset": "USDC",
    "amount": "10000"
  }],
  "version": "2"
}

Request With Payment

Generate and include payment authorization:
curl -H "X-PAYMENT: <base64-payment-data>" http://localhost:3000/protected
Response (HTTP 200):
{
  "msg": "success"
}

Crossmint Wallet Integration

API Signer

Server-side signing with Crossmint:
import { createCrossmint } from "@crossmint/wallets-sdk";

const crossmint = createCrossmint({
  apiKey: process.env.CROSSMINT_API_KEY,
  environment: "staging"
});

const wallet = await crossmint.wallets.create({
  chain: "solana-devnet",
  type: "solana-custodial-wallet"
});

console.log("Wallet address:", wallet.address);

Delegated Wallet

External signer for Crossmint smart wallet:
const adminKeypair = Keypair.fromSecretKey(/* your keypair */);

const wallet = await crossmint.wallets.create({
  chain: "solana-devnet",
  type: "solana-mpc-wallet",
  config: {
    adminPublicKey: adminKeypair.publicKey.toBase58()
  }
});

// Sign transactions with admin keypair
const signature = await adminKeypair.sign(transactionData);

Faremeter Facilitator

Faremeter provides Solana-specific x402 middleware and facilitator services.

Running Facilitator Locally

git clone https://github.com/faremeter/faremeter
cd faremeter
npm install
npm run dev
Facilitator runs on http://localhost:4000 by default.

Using Hosted Facilitator

For testing, use the public facilitator:
FACILITATOR_URL=https://facilitator.corbits.dev
Note: Production applications should run their own facilitator or use a trusted provider.

Payment Flow

1

Client Requests Endpoint

Client makes GET request to /protected without payment
2

Server Returns 402

Faremeter middleware returns payment requirements
3

Client Creates Payment

Client signs Solana transaction for USDC transfer
4

Client Includes Payment

X-PAYMENT header contains signed transaction data
5

Facilitator Validates

Facilitator verifies signature and payment details
6

Settlement Executes

USDC transferred on Solana blockchain
7

Server Returns Content

Endpoint returns {"msg":"success"}

Network Configuration

Devnet (Testing)

NETWORK=devnet
RPC_URL=https://api.devnet.solana.com
Get Testnet Tokens:

Mainnet (Production)

NETWORK=mainnet-beta
RPC_URL=https://api.mainnet-beta.solana.com
Use Real Funds:
  • Purchase SOL from exchanges
  • Swap for USDC on Solana DEXs (Jupiter, Raydium)

Dependencies

package.json
{
  "dependencies": {
    "express": "latest",
    "@faremeter/middleware": "latest",
    "@faremeter/info": "latest",
    "@solana/web3.js": "^1.87.0",
    "@crossmint/wallets-sdk": "latest",
    "dotenv": "^17.2.2"
  }
}

Key Differences from EVM

FeatureEVM (Ethereum/Base)Solana
Middlewarex402-express@faremeter/middleware
Signature TypeEIP-712 typed dataSolana transaction
Token StandardERC-20SPL Token
Payment AssetUSDC (ERC-20)USDC (SPL)
Decimals6 (USDC)6 (USDC), 9 (SOL)
Account ModelSmart contractsProgram accounts
FacilitatorCoinbase x402Faremeter

Next Steps

Ping Demo

Start with basic EVM implementation

Ping Crossmint

Learn Crossmint EVM integration

Faremeter Docs

Deep dive into Faremeter middleware

Solana Docs

Learn Solana development

Troubleshooting

Keypair Generation Fails

Error: solana-keygen: command not found Solution: Install Solana CLI tools:
sh -c "$(curl -sSfL https://release.solana.com/stable/install)"

Insufficient Funds

Error: Transaction fails with “insufficient funds” Solution:
  • Ensure payer has SOL for transaction fees (~0.001 SOL per transaction)
  • Ensure payer has USDC for payment amount (0.01 USDC for this demo)
  • Check balances: solana balance <address>

RPC Connection Failed

Error: Cannot connect to Solana RPC Solution:
  • Verify RPC_URL is correct for your network
  • Use Alchemy/QuickNode for reliable RPC access
  • Check network status: https://status.solana.com

Facilitator Unreachable

Error: Cannot connect to facilitator Solution:
  • Verify FACILITATOR_URL is accessible
  • If using local facilitator, ensure it’s running
  • Check firewall/network settings
  • Try public facilitator: https://facilitator.corbits.dev

Crossmint Wallet Creation Fails

Error: Invalid API key or wallet creation failed Solution:
  • Verify API key format (sk_staging_...)
  • Ensure Crossmint account has Solana enabled
  • Check network parameter matches (devnet vs mainnet)
  • Review Crossmint dashboard for account status

Build docs developers (and LLMs) love