curl --request POST \
--url 'https://dev.api.baanx.com/v1/delegation/solana/post-approval' \
--header 'x-client-key: YOUR_PUBLIC_KEY' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"address": "DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK",
"network": "solana",
"currency": "usdc",
"amount": "5000",
"txHash": "5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW",
"sigHash": "2Uhj5WqpLvZmJqKGx3WKvSC5K1m4YCp1eK3jcGY7GgRqNnBQEXhP9XjWCv4M3nZKF7RqWpLvZmJqKGx3WKvSC5K1",
"sigMessage": "Prove wallet ownership for delegation",
"token": "100a99cf-f4d3-4fa1-9be9-2e9828b20ebc"
}'
import requests
from typing import Dict
def complete_solana_delegation(
delegation_token: str,
wallet_address: str,
currency: str,
amount: str,
tx_hash: str,
sig_hash: str,
sig_message: str
) -> Dict:
url = "https://dev.api.baanx.com/v1/delegation/solana/post-approval"
headers = {
"x-client-key": "YOUR_PUBLIC_KEY",
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"Content-Type": "application/json"
}
payload = {
"address": wallet_address,
"network": "solana",
"currency": currency,
"amount": amount,
"txHash": tx_hash,
"sigHash": sig_hash,
"sigMessage": sig_message,
"token": delegation_token
}
response = requests.post(url, headers=headers, json=payload)
return response.json()
# Usage
result = complete_solana_delegation(
delegation_token="100a99cf-f4d3-4fa1-9be9-2e9828b20ebc",
wallet_address="DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK",
currency="usdc",
amount="5000",
tx_hash="5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW",
sig_hash="2Uhj5WqpLvZmJqKGx3WKvSC5K1m4YCp1eK3jcGY7GgRqNnBQEXhP9XjWCv4M3nZKF7RqWpLvZmJqKGx3WKvSC5K1",
sig_message="Prove wallet ownership for delegation"
)
const completeDelegation = async (delegationData) => {
const url = 'https://dev.api.baanx.com/v1/delegation/solana/post-approval';
const response = await fetch(url, {
method: 'POST',
headers: {
'x-client-key': 'YOUR_PUBLIC_KEY',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
address: delegationData.address,
network: 'solana',
currency: delegationData.currency,
amount: delegationData.amount,
txHash: delegationData.txHash,
sigHash: delegationData.sigHash,
sigMessage: delegationData.sigMessage,
token: delegationData.token
})
});
return await response.json();
};
// Usage
const result = await completeDelegation({
address: 'DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK',
currency: 'usdc',
amount: '5000',
txHash: '5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW',
sigHash: '2Uhj5WqpLvZmJqKGx3WKvSC5K1m4YCp1eK3jcGY7GgRqNnBQEXhP9XjWCv4M3nZKF7RqWpLvZmJqKGx3WKvSC5K1',
sigMessage: 'Prove wallet ownership for delegation',
token: '100a99cf-f4d3-4fa1-9be9-2e9828b20ebc'
});
interface SolanaDelegationRequest {
address: string;
network: 'solana';
currency: 'usdc' | 'usdt';
amount: string;
txHash: string;
sigHash: string;
sigMessage: string;
token: string;
}
interface DelegationResponse {
success: boolean;
}
async function completeSolanaDelegation(
data: SolanaDelegationRequest
): Promise<DelegationResponse> {
const url = 'https://dev.api.baanx.com/v1/delegation/solana/post-approval';
const response = await fetch(url, {
method: 'POST',
headers: {
'x-client-key': 'YOUR_PUBLIC_KEY',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
if (!response.ok) {
throw new Error(`Delegation failed: ${response.statusText}`);
}
return await response.json();
}
// Usage
const result = await completeSolanaDelegation({
address: 'DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK',
network: 'solana',
currency: 'usdc',
amount: '5000',
txHash: '5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW',
sigHash: '2Uhj5WqpLvZmJqKGx3WKvSC5K1m4YCp1eK3jcGY7GgRqNnBQEXhP9XjWCv4M3nZKF7RqWpLvZmJqKGx3WKvSC5K1',
sigMessage: 'Prove wallet ownership for delegation',
token: '100a99cf-f4d3-4fa1-9be9-2e9828b20ebc'
});
{
"success": true
}
{
"message": "Invalid Solana address format"
}
{
"message": "Invalid or expired access token"
}
{
"message": "Validation failed",
"errors": [
{
"field": "txHash",
"message": "Invalid transaction signature format. Must be base58-encoded, 87-88 characters"
}
]
}
{
"message": "An unexpected error occurred. Please try again later."
}
Delegation
Complete Solana Wallet Delegation
Finalize delegation of spending authority from Solana wallets (Step 3 of 3)
POST
/
v1
/
delegation
/
solana
/
post-approval
curl --request POST \
--url 'https://dev.api.baanx.com/v1/delegation/solana/post-approval' \
--header 'x-client-key: YOUR_PUBLIC_KEY' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"address": "DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK",
"network": "solana",
"currency": "usdc",
"amount": "5000",
"txHash": "5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW",
"sigHash": "2Uhj5WqpLvZmJqKGx3WKvSC5K1m4YCp1eK3jcGY7GgRqNnBQEXhP9XjWCv4M3nZKF7RqWpLvZmJqKGx3WKvSC5K1",
"sigMessage": "Prove wallet ownership for delegation",
"token": "100a99cf-f4d3-4fa1-9be9-2e9828b20ebc"
}'
import requests
from typing import Dict
def complete_solana_delegation(
delegation_token: str,
wallet_address: str,
currency: str,
amount: str,
tx_hash: str,
sig_hash: str,
sig_message: str
) -> Dict:
url = "https://dev.api.baanx.com/v1/delegation/solana/post-approval"
headers = {
"x-client-key": "YOUR_PUBLIC_KEY",
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"Content-Type": "application/json"
}
payload = {
"address": wallet_address,
"network": "solana",
"currency": currency,
"amount": amount,
"txHash": tx_hash,
"sigHash": sig_hash,
"sigMessage": sig_message,
"token": delegation_token
}
response = requests.post(url, headers=headers, json=payload)
return response.json()
# Usage
result = complete_solana_delegation(
delegation_token="100a99cf-f4d3-4fa1-9be9-2e9828b20ebc",
wallet_address="DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK",
currency="usdc",
amount="5000",
tx_hash="5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW",
sig_hash="2Uhj5WqpLvZmJqKGx3WKvSC5K1m4YCp1eK3jcGY7GgRqNnBQEXhP9XjWCv4M3nZKF7RqWpLvZmJqKGx3WKvSC5K1",
sig_message="Prove wallet ownership for delegation"
)
const completeDelegation = async (delegationData) => {
const url = 'https://dev.api.baanx.com/v1/delegation/solana/post-approval';
const response = await fetch(url, {
method: 'POST',
headers: {
'x-client-key': 'YOUR_PUBLIC_KEY',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
address: delegationData.address,
network: 'solana',
currency: delegationData.currency,
amount: delegationData.amount,
txHash: delegationData.txHash,
sigHash: delegationData.sigHash,
sigMessage: delegationData.sigMessage,
token: delegationData.token
})
});
return await response.json();
};
// Usage
const result = await completeDelegation({
address: 'DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK',
currency: 'usdc',
amount: '5000',
txHash: '5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW',
sigHash: '2Uhj5WqpLvZmJqKGx3WKvSC5K1m4YCp1eK3jcGY7GgRqNnBQEXhP9XjWCv4M3nZKF7RqWpLvZmJqKGx3WKvSC5K1',
sigMessage: 'Prove wallet ownership for delegation',
token: '100a99cf-f4d3-4fa1-9be9-2e9828b20ebc'
});
interface SolanaDelegationRequest {
address: string;
network: 'solana';
currency: 'usdc' | 'usdt';
amount: string;
txHash: string;
sigHash: string;
sigMessage: string;
token: string;
}
interface DelegationResponse {
success: boolean;
}
async function completeSolanaDelegation(
data: SolanaDelegationRequest
): Promise<DelegationResponse> {
const url = 'https://dev.api.baanx.com/v1/delegation/solana/post-approval';
const response = await fetch(url, {
method: 'POST',
headers: {
'x-client-key': 'YOUR_PUBLIC_KEY',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
if (!response.ok) {
throw new Error(`Delegation failed: ${response.statusText}`);
}
return await response.json();
}
// Usage
const result = await completeSolanaDelegation({
address: 'DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK',
network: 'solana',
currency: 'usdc',
amount: '5000',
txHash: '5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW',
sigHash: '2Uhj5WqpLvZmJqKGx3WKvSC5K1m4YCp1eK3jcGY7GgRqNnBQEXhP9XjWCv4M3nZKF7RqWpLvZmJqKGx3WKvSC5K1',
sigMessage: 'Prove wallet ownership for delegation',
token: '100a99cf-f4d3-4fa1-9be9-2e9828b20ebc'
});
{
"success": true
}
{
"message": "Invalid Solana address format"
}
{
"message": "Invalid or expired access token"
}
{
"message": "Validation failed",
"errors": [
{
"field": "txHash",
"message": "Invalid transaction signature format. Must be base58-encoded, 87-88 characters"
}
]
}
{
"message": "An unexpected error occurred. Please try again later."
}
Overview
This endpoint finalizes the delegation of spending authority from a user’s Solana wallet. After the user has completed wallet connection and token account delegation transaction in your frontend, call this endpoint to register the wallet with the platform.When to Use: Call this endpoint after the user has successfully completed the token account delegation transaction on Solana in your frontend application (Step 2). This is the final step in the delegation workflow for Solana wallets.
Solana-Specific Validation
This endpoint performs strict validation for Solana blockchain:- Address Format: Must be a valid Solana public key (base58-encoded, 32-44 characters)
- Transaction Signature: Must be a valid Solana transaction signature (base58-encoded, 87-88 characters)
- Message Signature: Must be a valid Solana signature (base58-encoded, 87-88 characters)
- Network: Must be
solana
Authentication
string
required
Your public client key for API authentication
string
required
Bearer token format:
Bearer {access_token}string
required
Must be
application/jsonQuery Parameters
string
Region identifier for environment routing. Use
us for US-specific routing.Example: ?region=usNote: Alternatively, you can use the x-us-env: true header instead of the region query parameter.Request Body
string
required
Solana wallet public key that will be delegated. Must be a valid base58-encoded Solana public key (32-44 characters).Pattern:
^[1-9A-HJ-NP-Za-km-z]{32,44}$Example: DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKKThis address must match the one that signed the delegation transaction.string
required
Must be
solana for Solana blockchain.Allowed values:solana- Solana mainnet
string
required
SPL token that was approved for delegation.Allowed values:
usdc- USD Coin (SPL)usdt- Tether USD (SPL)
string
required
Spending limit approved in the delegation. Specified in the currency’s base unit (e.g., 5000 for 5000 USDC). This is the maximum amount the platform can spend from the delegated wallet.Pattern:
^\d+(\.\d+)?$Example: "5000" or "5000.50"string
required
Solana transaction signature of the token account delegation. Must be a valid base58-encoded signature (87-88 characters).Pattern:
^[1-9A-HJ-NP-Za-km-z]{87,88}$Example: 5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUWThe API verifies this transaction exists on-chain and is confirmed.string
required
Solana signature hash proving wallet ownership. Result of signing
sigMessage with the wallet’s private key. Must be a valid base58-encoded signature (87-88 characters).Pattern: ^[1-9A-HJ-NP-Za-km-z]{87,88}$Example: 2Uhj5WqpLvZmJqKGx3WKvSC5K1m4YCp1eK3jcGY7GgRqNnBQEXhP9XjWCv4M3nZKF7RqWpLvZmJqKGx3WKvSC5K1string
required
The message that was signed by the Solana wallet to prove ownership. Can be any string that proves ownership, but should be meaningful.Minimum length: 10 charactersExample:
"Prove wallet ownership for delegation"Recommended format: Include purpose, timestamp, and nonce for securitystring
required
Single-use delegation token obtained from
GET /v1/delegation/token (Step 1). Must be a valid UUID.Format: UUID v4Example: 100a99cf-f4d3-4fa1-9be9-2e9828b20ebcNote: Token expires after ~10 minutes or after successful use.Response
boolean
required
Indicates whether the wallet delegation was completed successfully.
curl --request POST \
--url 'https://dev.api.baanx.com/v1/delegation/solana/post-approval' \
--header 'x-client-key: YOUR_PUBLIC_KEY' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"address": "DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK",
"network": "solana",
"currency": "usdc",
"amount": "5000",
"txHash": "5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW",
"sigHash": "2Uhj5WqpLvZmJqKGx3WKvSC5K1m4YCp1eK3jcGY7GgRqNnBQEXhP9XjWCv4M3nZKF7RqWpLvZmJqKGx3WKvSC5K1",
"sigMessage": "Prove wallet ownership for delegation",
"token": "100a99cf-f4d3-4fa1-9be9-2e9828b20ebc"
}'
import requests
from typing import Dict
def complete_solana_delegation(
delegation_token: str,
wallet_address: str,
currency: str,
amount: str,
tx_hash: str,
sig_hash: str,
sig_message: str
) -> Dict:
url = "https://dev.api.baanx.com/v1/delegation/solana/post-approval"
headers = {
"x-client-key": "YOUR_PUBLIC_KEY",
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"Content-Type": "application/json"
}
payload = {
"address": wallet_address,
"network": "solana",
"currency": currency,
"amount": amount,
"txHash": tx_hash,
"sigHash": sig_hash,
"sigMessage": sig_message,
"token": delegation_token
}
response = requests.post(url, headers=headers, json=payload)
return response.json()
# Usage
result = complete_solana_delegation(
delegation_token="100a99cf-f4d3-4fa1-9be9-2e9828b20ebc",
wallet_address="DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK",
currency="usdc",
amount="5000",
tx_hash="5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW",
sig_hash="2Uhj5WqpLvZmJqKGx3WKvSC5K1m4YCp1eK3jcGY7GgRqNnBQEXhP9XjWCv4M3nZKF7RqWpLvZmJqKGx3WKvSC5K1",
sig_message="Prove wallet ownership for delegation"
)
const completeDelegation = async (delegationData) => {
const url = 'https://dev.api.baanx.com/v1/delegation/solana/post-approval';
const response = await fetch(url, {
method: 'POST',
headers: {
'x-client-key': 'YOUR_PUBLIC_KEY',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
address: delegationData.address,
network: 'solana',
currency: delegationData.currency,
amount: delegationData.amount,
txHash: delegationData.txHash,
sigHash: delegationData.sigHash,
sigMessage: delegationData.sigMessage,
token: delegationData.token
})
});
return await response.json();
};
// Usage
const result = await completeDelegation({
address: 'DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK',
currency: 'usdc',
amount: '5000',
txHash: '5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW',
sigHash: '2Uhj5WqpLvZmJqKGx3WKvSC5K1m4YCp1eK3jcGY7GgRqNnBQEXhP9XjWCv4M3nZKF7RqWpLvZmJqKGx3WKvSC5K1',
sigMessage: 'Prove wallet ownership for delegation',
token: '100a99cf-f4d3-4fa1-9be9-2e9828b20ebc'
});
interface SolanaDelegationRequest {
address: string;
network: 'solana';
currency: 'usdc' | 'usdt';
amount: string;
txHash: string;
sigHash: string;
sigMessage: string;
token: string;
}
interface DelegationResponse {
success: boolean;
}
async function completeSolanaDelegation(
data: SolanaDelegationRequest
): Promise<DelegationResponse> {
const url = 'https://dev.api.baanx.com/v1/delegation/solana/post-approval';
const response = await fetch(url, {
method: 'POST',
headers: {
'x-client-key': 'YOUR_PUBLIC_KEY',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
if (!response.ok) {
throw new Error(`Delegation failed: ${response.statusText}`);
}
return await response.json();
}
// Usage
const result = await completeSolanaDelegation({
address: 'DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK',
network: 'solana',
currency: 'usdc',
amount: '5000',
txHash: '5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW',
sigHash: '2Uhj5WqpLvZmJqKGx3WKvSC5K1m4YCp1eK3jcGY7GgRqNnBQEXhP9XjWCv4M3nZKF7RqWpLvZmJqKGx3WKvSC5K1',
sigMessage: 'Prove wallet ownership for delegation',
token: '100a99cf-f4d3-4fa1-9be9-2e9828b20ebc'
});
{
"success": true
}
{
"message": "Invalid Solana address format"
}
{
"message": "Invalid or expired access token"
}
{
"message": "Validation failed",
"errors": [
{
"field": "txHash",
"message": "Invalid transaction signature format. Must be base58-encoded, 87-88 characters"
}
]
}
{
"message": "An unexpected error occurred. Please try again later."
}
Response Codes
| Code | Description |
|---|---|
| 201 | Wallet delegation completed successfully |
| 400 | Bad request - invalid data format or verification failed |
| 401 | Authentication failed - invalid or expired access token |
| 422 | Validation error - invalid request parameters |
| 498 | Invalid client key |
| 499 | Missing client key |
| 500 | Internal server error |
What Happens After Success
When this endpoint returns successfully:- Wallet Registration: The external wallet is registered and linked to the user’s account
- Card Payments Enabled: User can now make card purchases using delegated wallet funds
- Wallet Visibility: Wallet appears in
GET /v1/wallet/externalendpoint response - Priority Assignment: Wallet is assigned a default priority for transaction processing
- Balance Tracking: Platform begins tracking wallet balance and allowance
Solana Token Delegation
On Solana, delegation uses SPL Token’s approve instruction to delegate token account authority:import { Token, TOKEN_PROGRAM_ID } from '@solana/spl-token';
import { Connection, PublicKey } from '@solana/web3.js';
const connection = new Connection('https://api.mainnet-beta.solana.com');
// Create approve instruction
const approveInstruction = Token.createApproveInstruction(
TOKEN_PROGRAM_ID,
tokenAccountAddress, // User's token account
delegateAddress, // Platform's delegate address
walletPublicKey, // User's wallet
[], // Signers (empty for wallet adapter)
amount // Amount to approve
);
Complete Implementation Example
Here’s a full end-to-end example of the Solana delegation flow:import { Connection, PublicKey, Transaction } from '@solana/web3.js';
import { Token, TOKEN_PROGRAM_ID } from '@solana/spl-token';
import bs58 from 'bs58';
async function delegateSolanaWallet(delegationToken: string, amount: string) {
try {
// Step 1: Check if Phantom is installed
const provider = (window as any).solana;
if (!provider?.isPhantom) {
throw new Error('Phantom wallet not found');
}
// Step 2: Connect wallet
await provider.connect();
const walletPublicKey = new PublicKey(provider.publicKey.toString());
console.log('Connected to wallet:', walletPublicKey.toBase58());
// Step 3: Setup connection and token accounts
const connection = new Connection('https://api.mainnet-beta.solana.com');
const tokenMintAddress = new PublicKey(
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' // USDC mint
);
// Get user's token account
const tokenAccounts = await connection.getParsedTokenAccountsByOwner(
walletPublicKey,
{ mint: tokenMintAddress }
);
if (tokenAccounts.value.length === 0) {
throw new Error('No USDC token account found');
}
const tokenAccountAddress = tokenAccounts.value[0].pubkey;
// Step 4: Create delegation transaction
const delegateAddress = new PublicKey('YOUR_PLATFORM_DELEGATE_ADDRESS');
const amountLamports = parseFloat(amount) * 1_000_000; // USDC has 6 decimals
const transaction = new Transaction().add(
Token.createApproveInstruction(
TOKEN_PROGRAM_ID,
tokenAccountAddress,
delegateAddress,
walletPublicKey,
[],
amountLamports
)
);
// Set recent blockhash
const { blockhash } = await connection.getRecentBlockhash();
transaction.recentBlockhash = blockhash;
transaction.feePayer = walletPublicKey;
// Step 5: Sign and send delegation transaction
const signedTx = await provider.signTransaction(transaction);
const txSignature = await connection.sendRawTransaction(
signedTx.serialize()
);
console.log('Delegation transaction sent:', txSignature);
// Wait for confirmation
await connection.confirmTransaction(txSignature, 'confirmed');
console.log('Delegation transaction confirmed');
// Step 6: Sign message for ownership proof
const message = `Prove wallet ownership for delegation\nTimestamp: ${Date.now()}\nNonce: ${Math.random().toString(36).substring(7)}`;
const encodedMessage = new TextEncoder().encode(message);
const signedMessage = await provider.signMessage(encodedMessage, 'utf8');
const signature = bs58.encode(signedMessage.signature);
console.log('Message signed successfully');
// Step 7: Submit to API
const response = await fetch(
'https://dev.api.baanx.com/v1/delegation/solana/post-approval',
{
method: 'POST',
headers: {
'x-client-key': 'YOUR_PUBLIC_KEY',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
address: walletPublicKey.toBase58(),
network: 'solana',
currency: 'usdc',
amount: amount,
txHash: txSignature,
sigHash: signature,
sigMessage: message,
token: delegationToken
})
}
);
const result = await response.json();
if (response.ok) {
console.log('Delegation completed successfully!');
return { success: true, data: result };
} else {
console.error('Delegation failed:', result);
return { success: false, error: result };
}
} catch (error) {
console.error('Error during delegation:', error);
return { success: false, error: (error as Error).message };
}
}
// Usage
const result = await delegateSolanaWallet(
'100a99cf-f4d3-4fa1-9be9-2e9828b20ebc',
'5000'
);
import { useWallet, useConnection } from '@solana/wallet-adapter-react';
import { Transaction } from '@solana/web3.js';
import { Token, TOKEN_PROGRAM_ID } from '@solana/spl-token';
import bs58 from 'bs58';
function DelegationComponent() {
const { publicKey, signTransaction, signMessage } = useWallet();
const { connection } = useConnection();
const handleDelegation = async (delegationToken: string, amount: string) => {
if (!publicKey || !signTransaction || !signMessage) {
throw new Error('Wallet not connected');
}
try {
// Get token account
const tokenMintAddress = new PublicKey(
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' // USDC
);
const tokenAccounts = await connection.getParsedTokenAccountsByOwner(
publicKey,
{ mint: tokenMintAddress }
);
const tokenAccountAddress = tokenAccounts.value[0].pubkey;
const delegateAddress = new PublicKey('YOUR_PLATFORM_DELEGATE_ADDRESS');
const amountLamports = parseFloat(amount) * 1_000_000;
// Create and send delegation transaction
const transaction = new Transaction().add(
Token.createApproveInstruction(
TOKEN_PROGRAM_ID,
tokenAccountAddress,
delegateAddress,
publicKey,
[],
amountLamports
)
);
const { blockhash } = await connection.getRecentBlockhash();
transaction.recentBlockhash = blockhash;
transaction.feePayer = publicKey;
const signed = await signTransaction(transaction);
const txSignature = await connection.sendRawTransaction(
signed.serialize()
);
await connection.confirmTransaction(txSignature);
// Sign ownership message
const message = `Prove wallet ownership for delegation\nTimestamp: ${Date.now()}`;
const encodedMessage = new TextEncoder().encode(message);
const signedMsg = await signMessage(encodedMessage);
const signature = bs58.encode(signedMsg);
// Submit to API
const response = await fetch(
'https://dev.api.baanx.com/v1/delegation/solana/post-approval',
{
method: 'POST',
headers: {
'x-client-key': process.env.NEXT_PUBLIC_CLIENT_KEY!,
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
address: publicKey.toBase58(),
network: 'solana',
currency: 'usdc',
amount: amount,
txHash: txSignature,
sigHash: signature,
sigMessage: message,
token: delegationToken
})
}
);
return await response.json();
} catch (error) {
console.error('Delegation error:', error);
throw error;
}
};
return (
<button onClick={() => handleDelegation(token, '5000')}>
Delegate Wallet
</button>
);
}
Message Signing
For Solana, thesigMessage should be a clear, descriptive message. Here’s a recommended format:
function generateSolanaMessage(): string {
const timestamp = Date.now();
const nonce = Math.random().toString(36).substring(7);
return `Prove wallet ownership for delegation
Timestamp: ${timestamp}
Nonce: ${nonce}
Action: Delegate spending authority to Baanx platform`;
}
// Sign the message
const message = generateSolanaMessage();
const encodedMessage = new TextEncoder().encode(message);
const signedMessage = await wallet.signMessage(encodedMessage, 'utf8');
const signature = bs58.encode(signedMessage.signature);
Redelegation
To update an existing delegation (change allowance, upgrade contracts, etc.), simply call this endpoint again with the same wallet address. The new delegation will replace the previous one. Common redelegation scenarios:- Increase spending limit: User wants to approve a higher amount
- Contract upgrade: Platform deploys new smart contracts
- Token account change: User wants to delegate a different token account
When redelegating, the user must complete a new token account delegation transaction with the updated parameters before calling this endpoint.
Verification After Delegation
After successful delegation, verify the wallet was registered:curl --request GET \
--url 'https://dev.api.baanx.com/v1/wallet/external' \
--header 'x-client-key: YOUR_PUBLIC_KEY' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
[
{
"id": 552,
"address": "DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK",
"currency": "usdc",
"balance": "5000.00",
"allowance": "5000",
"network": "solana",
"priority": 1
}
]
Common Error Scenarios
Invalid Transaction Signature
{
"message": "Transaction not found on blockchain"
}
- Transaction hasn’t been confirmed yet
- Invalid transaction signature format
- Wrong network (e.g., devnet instead of mainnet)
- Wait for transaction confirmation (typically 10-30 seconds)
- Verify signature is base58-encoded and 87-88 characters
- Ensure transaction was sent to mainnet
Signature Verification Failed
{
"message": "Signature verification failed"
}
sigHashdoesn’t match the wallet that signedsigMessagewas modified after signing- Wrong encoding used for signature
- Ensure the same wallet signs both the delegation and message
- Don’t modify
sigMessageafter user signs it - Use
bs58.encode()for signature encoding
Invalid Address Format
{
"message": "Invalid Solana address format"
}
- Address is not base58-encoded
- Address length is incorrect
- Contains invalid base58 characters (0, O, I, l)
- Use
publicKey.toBase58()to get correct format - Verify address is 32-44 characters
- Don’t include prefixes or suffixes
Expired Delegation Token
{
"message": "Delegation token has expired or already been used"
}
- More than 10 minutes passed since token generation
- Token was already used in a previous request
- Generate a new delegation token from Step 1
- Complete the flow more quickly
- Don’t reuse tokens
SPL Token Addresses
Common SPL token addresses on Solana mainnet:| Token | Mint Address |
|---|---|
| USDC | EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v |
| USDT | Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB |
Always verify token addresses with official sources before using them in production.
Best Practices
Transaction Confirmation
Transaction Confirmation
Always wait for transaction confirmation before calling this endpoint:
- Wait for ‘confirmed’ commitment level minimum
- For higher security, wait for ‘finalized’ commitment
- Display transaction status to users
- Implement timeout handling (typically 60 seconds)
- Provide transaction link to Solana Explorer
Wallet Support
Wallet Support
Support popular Solana wallets:
- Phantom (most popular)
- Solflare
- Backpack
- Glow
- Use @solana/wallet-adapter for easy integration
- Handle wallet not installed gracefully
Error Handling
Error Handling
Implement comprehensive error handling:
- Handle user rejection gracefully
- Retry failed transactions with same parameters
- Provide clear error messages to users
- Log errors for debugging (without exposing sensitive data)
- Implement exponential backoff for API retries
Security
Security
Follow security best practices:
- Never store private keys
- Validate all addresses before submission
- Use HTTPS only for all API calls
- Implement rate limiting on your backend
- Verify transaction on blockchain before submitting to API
- Use recent blockhashes (prevent replay attacks)
User Experience
User Experience
Create a smooth user experience:
- Show progress indicators during each step
- Display transaction fees before approval
- Explain delegation in simple terms
- Provide transaction links to Solana Explorer
- Allow users to easily retry on failure
- Show estimated confirmation time
Solana-Specific Considerations
Transaction Fees
Solana transactions require SOL for transaction fees:- Typical fee: 0.000005 SOL (~$0.0001)
- Ensure user has small amount of SOL for fees
- Display estimated fee before transaction
Token Accounts
Users must have a token account for the SPL token:- Check if token account exists before delegation
- Create token account if needed (costs ~0.002 SOL)
- Handle associated token account vs regular token account
Network Congestion
During high network activity:- Transactions may take longer to confirm
- Consider using higher priority fees
- Implement retry logic with exponential backoff
- Display status updates to user
Related Endpoints
- GET /v1/delegation/token - Generate delegation token (Step 1)
- POST /v1/delegation/evm/post-approval - Complete EVM wallet delegation
- GET /v1/wallet/external - List delegated wallets
- Manage External Wallet Priority - Get and update wallet priority order
Further Reading
- Delegation Overview - Understand delegation concepts
- Implementation Guide - Complete integration walkthrough
- Solana Implementation - Detailed Solana-specific implementation
- Priority Management - Managing multiple wallets
- Redelegation - Updating existing delegations
External Resources
Was this page helpful?