Skip to main content
GET
/
v1
/
wallet
/
external
[
  {
    "address": "0x3a11a86cf218c448be519728cd3ac5c741fb3424",
    "currency": "usdc",
    "balance": "1250.50",
    "allowance": "5000",
    "network": "linea"
  },
  {
    "address": "0x7b22c1e6f8a4d92b5c3d8e9f1a2b3c4d5e6f7890",
    "currency": "usdt",
    "balance": "500.00",
    "allowance": "1000",
    "network": "ethereum"
  },
  {
    "address": "DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK",
    "currency": "usdc",
    "balance": "2000.00",
    "allowance": "3000",
    "network": "solana"
  }
]

Overview

External wallets are non-custodial wallet addresses where users maintain full control of their private keys. These wallets are registered through the delegation flow and can be used for card payments and withdrawal destinations. Key Differences from Internal Wallets:
  • User controls private keys (non-custodial)
  • Requires delegation to grant spending authority to platform
  • Real-time balance checking from blockchain
  • Allowance limits control maximum spendable amount
Use Cases:
  • View all registered external wallets
  • Check current balance and allowance
  • Verify wallet registration status
  • Display available payment sources

Authentication

x-client-key
string
required
Your public API client key
Authorization
string
required
Bearer token for authentication

Query Parameters

x-us-env
boolean
default:false
Route to US backend environment

Response

Returns an array of registered external wallets.
address
string
Blockchain address of the external wallet
currency
string
Currency held in the wallet (e.g., “usdc”, “usdt”)
balance
string
Current on-chain balance (decimal string)
allowance
string
Maximum amount platform can spend from this wallet (delegation limit)
network
string
Blockchain network (e.g., “linea”, “ethereum”, “solana”)
[
  {
    "address": "0x3a11a86cf218c448be519728cd3ac5c741fb3424",
    "currency": "usdc",
    "balance": "1250.50",
    "allowance": "5000",
    "network": "linea"
  },
  {
    "address": "0x7b22c1e6f8a4d92b5c3d8e9f1a2b3c4d5e6f7890",
    "currency": "usdt",
    "balance": "500.00",
    "allowance": "1000",
    "network": "ethereum"
  },
  {
    "address": "DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK",
    "currency": "usdc",
    "balance": "2000.00",
    "allowance": "3000",
    "network": "solana"
  }
]

Code Examples

curl -X GET "https://dev.api.baanx.com/v1/wallet/external" \
  -H "x-client-key: YOUR_CLIENT_KEY" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Understanding Balance vs Allowance

Available Amount: The actual spendable amount is the MINIMUM of balance and allowance. If balance is 1000 but allowance is 500, only 500 can be spent.
Calculate Available Amount
function calculateAvailableAmount(wallet) {
  const balance = parseFloat(wallet.balance);
  const allowance = parseFloat(wallet.allowance);

  return {
    balance,
    allowance,
    available: Math.min(balance, allowance),
    needsTopUp: balance < allowance * 0.2,
    needsRedelegate: allowance < balance * 0.5
  };
}

const wallet = wallets[0];
const status = calculateAvailableAmount(wallet);

console.log(`Available: $${status.available}`);
if (status.needsTopUp) {
  console.log('⚠️ Wallet balance low - consider depositing more');
}
if (status.needsRedelegate) {
  console.log('⚠️ Allowance low - consider redelegating with higher limit');
}

Integration Patterns

Display Wallet Summary

async function getWalletsSummary() {
  const wallets = await getExternalWallets();

  const summary = {
    total: wallets.length,
    byNetwork: {},
    totalAvailable: 0
  };

  wallets.forEach(wallet => {
    const available = Math.min(
      parseFloat(wallet.balance),
      parseFloat(wallet.allowance)
    );

    if (!summary.byNetwork[wallet.network]) {
      summary.byNetwork[wallet.network] = 0;
    }
    summary.byNetwork[wallet.network] += available;
    summary.totalAvailable += available;
  });

  return summary;
}

const summary = await getWalletsSummary();
console.log(`Total available across all wallets: $${summary.totalAvailable.toFixed(2)}`);

Check if User Has External Wallet

async function hasExternalWallet(currency, network) {
  const wallets = await getExternalWallets();

  return wallets.some(
    w => w.currency === currency && w.network === network
  );
}

const hasLineaUSDC = await hasExternalWallet('usdc', 'linea');
if (!hasLineaUSDC) {
  console.log('User needs to complete delegation for USDC on Linea');
}

Find Wallet with Best Balance

function findBestWallet(wallets, currency) {
  const currencyWallets = wallets.filter(w => w.currency === currency);

  if (currencyWallets.length === 0) {
    return null;
  }

  return currencyWallets.reduce((best, current) => {
    const bestAvailable = Math.min(
      parseFloat(best.balance),
      parseFloat(best.allowance)
    );
    const currentAvailable = Math.min(
      parseFloat(current.balance),
      parseFloat(current.allowance)
    );

    return currentAvailable > bestAvailable ? current : best;
  });
}

const bestUSDC = findBestWallet(wallets, 'usdc');
console.log(`Best USDC wallet: ${bestUSDC.address} with $${bestUSDC.balance}`);

Important Notes

Allowance Limitations: Even if balance is high, transactions cannot exceed the delegated allowance. Users must redelegate to increase allowance.
Real-Time Balance: Balances are fetched from the blockchain in real-time. For frequently updated UI, consider caching with appropriate TTL (e.g., 30 seconds).
Network Specificity: Same address on different networks represents different wallets. Always check both address AND network when identifying wallets.

Edge Cases

Empty Wallet List

User has not completed delegation:
const wallets = await getExternalWallets();

if (wallets.length === 0) {
  // Redirect to delegation flow
  console.log('No external wallets registered');
  console.log('Please complete delegation to add a wallet');
}

Zero Balance

Wallet is registered but empty:
const emptyWallets = wallets.filter(w => parseFloat(w.balance) === 0);

if (emptyWallets.length > 0) {
  console.log('⚠️ Some wallets have zero balance:');
  emptyWallets.forEach(w => {
    console.log(`  ${w.address} (${w.network})`);
  });
}

Exceeded Allowance

Balance exceeds allowance:
const needsRedelegation = wallets.filter(w =>
  parseFloat(w.balance) > parseFloat(w.allowance)
);

if (needsRedelegation.length > 0) {
  console.log('💡 Consider increasing allowance for these wallets:');
  needsRedelegation.forEach(w => {
    const excess = parseFloat(w.balance) - parseFloat(w.allowance);
    console.log(`  ${w.address}: $${excess.toFixed(2)} unusable`);
  });
}

Delegation Flow

To register a new external wallet, users must complete the delegation flow:
1

Get Delegation Token

Call GET /v1/delegation/token to initiate
2

Connect Wallet

User connects wallet in your frontend (MetaMask, WalletConnect, etc.)
3

Approve Transaction

User signs blockchain transaction granting spending authority
4

Submit Proof

Call blockchain-specific endpoint:
  • POST /v1/delegation/evm/post-approval for Linea/Ethereum
  • POST /v1/delegation/solana/post-approval for Solana
5

Verify Registration

Check this endpoint to confirm wallet appears in list
See the Delegation Guide for complete implementation details.