Overview
This guide shows how to use Magic’s Express Server Wallet to send USDC on Solana. The private key never leaves the TEE — your server builds the SPL token transfer transaction, signs it via the Express API, and broadcasts the result.Prerequisites
Before starting, ensure you have:- A Magic Secret Key — from your Magic Dashboard
- An OIDC Provider ID — configured for your auth provider (setup guide)
- A Solana RPC endpoint (e.g., from Helius or QuickNode)
- A user JWT from your authentication provider
How It Works
- Your server authenticates the user and obtains a JWT
- JWT is sent to Magic’s TEE to get (or create) the user’s Solana wallet
- Your server builds the SPL token transfer transaction
- Transaction message is signed via the TEE’s
/v1/wallet/sign/messageendpoint - Signed transaction is broadcast to Solana via your RPC provider
TEE Request Helper
All TEE calls use the same authentication headers. Note that Solana usesX-Magic-Chain: SOL instead of ETH.
TypeScript
Get or Create a Wallet
Fetch the user’s Solana wallet address. If one doesn’t exist, it will be created automatically.TypeScript
Sign and Broadcast Transactions
Build the transaction locally, serialize the message, sign via the TEE, and broadcast.TypeScript
Sending USDC
Build the SPL token transfer instruction, creating the recipient’s token account if needed.TypeScript
Creating a recipient’s Associated Token Account costs ~0.002 SOL in rent. This is a one-time cost — subsequent transfers to the same recipient skip this step.
Checking Balance
Query the user’s USDC token account to display their balance.TypeScript
Token Addresses
Key addresses on Solana mainnet:TypeScript
Solana uses mint addresses instead of contract addresses. Each SPL token has a unique mint, and wallets hold tokens in Associated Token Accounts (ATAs) derived from the mint and owner.
TEE Endpoints Used
| Endpoint | Purpose |
|---|---|
POST /v1/wallet | Get or create a Solana wallet |
POST /v1/wallet/sign/message | Sign a base64-encoded transaction message |
Troubleshooting
TEE returns 401 or 403
TEE returns 401 or 403
Symptoms: Authentication errors when calling TEE endpoints.Solutions:
- Verify the JWT token is valid and not expired
- Check that
X-Magic-Secret-Keymatches your dashboard credentials - Ensure the OIDC Provider ID is correct
- Confirm
X-Magic-Chainis set toSOL, notETH
Transfer fails with insufficient funds
Transfer fails with insufficient funds
Symptoms: Transaction simulation fails before sending.Solutions:
- Check that the wallet has enough USDC in their token account
- Ensure the wallet has SOL for transaction fees (~0.000005 SOL)
- If creating a recipient ATA, the wallet needs ~0.002 SOL for rent
Invalid signature error
Invalid signature error
Symptoms: Transaction fails with a signature verification error.Solutions:
- Ensure you’re using
/v1/wallet/sign/message, not/v1/wallet/sign/data - Verify the transaction’s
feePayermatches the wallet’s public key - Check that the signature is correctly decoded (handle both hex and base64 formats)
Token account not found
Token account not found
Symptoms:
getAccount throws an error for the sender’s ATA.Solutions:- The wallet may not have a USDC token account yet
- Send USDC to the wallet first — this creates the ATA automatically
- You can create the ATA manually with
createAssociatedTokenAccountInstruction
Resources
Express API Docs
Learn about Magic’s Express Server Wallet API
Solana Data Preparation
Guide for preparing Solana transaction data for signing
Solana Documentation
Official Solana developer documentation
USDC on Solana
Learn about Circle’s USDC stablecoin