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
Your public API client key
Bearer token for authentication
Query Parameters
Route to US backend environment
Response
Returns an array of registered external wallets.
Blockchain address of the external wallet
Currency held in the wallet (e.g., “usdc”, “usdt”)
Current on-chain balance (decimal string)
Maximum amount platform can spend from this wallet (delegation limit)
Blockchain network (e.g., “linea”, “ethereum”, “solana”)
200 - Success
401 - Authentication Error
403 - Authorization Error
500 - Internal Server Error
[
{
"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
Python
JavaScript
TypeScript
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:
Get Delegation Token
Call GET /v1/delegation/token to initiate
Connect Wallet
User connects wallet in your frontend (MetaMask, WalletConnect, etc.)
Approve Transaction
User signs blockchain transaction granting spending authority
Submit Proof
Call blockchain-specific endpoint:
POST /v1/delegation/evm/post-approval for Linea/Ethereum
POST /v1/delegation/solana/post-approval for Solana
Verify Registration
Check this endpoint to confirm wallet appears in list
See the Delegation Guide for complete implementation details.