Getting Wallet Balances
Once a user is authenticated and their Sphere smart wallet is accessible, you can retrieve information about their token balances. The Sphere SDK provides methods to fetch balances for specific tokens or all tokens on specific chains, or across all chains.
This page outlines how to use the Sphere SDK to fetch these balances.
Prerequisites
Before you can fetch wallet balances, ensure:
- User Authentication: The user must be authenticated. See OTP Verification & Session Management.
- SDK Authenticated: Your Sphere SDK instance must be authenticated by setting the bearer token obtained from a successful login. See Creating & Accessing User Wallets.
import Sphere, {
Environment,
ChainName,
TokenSymbol,
Balance,
} from "@stratosphere-network/wallet";
const sphere = new Sphere({
apiKey: "YOUR_API_KEY",
environment: Environment.DEVELOPMENT,
});
sphere.setBearerToken("USER_ACCESS_TOKEN"); // Token obtained after successful login
Fetching All Balances Across All Chains (wallet.getChainBalance
)
To retrieve a comprehensive list of all token balances held by a user's wallet across all supported networks, use sphere.wallet.getChainBalance()
without specifying a chain.
SDK Usage
async function fetchAllUserBalances(): Promise<Balance[] | null> {
if (!sphere.isAuthenticated()) {
console.error("SDK is not authenticated. Please log in the user first.");
return null;
}
try {
console.log("Fetching all balances for the authenticated user...");
// Call without arguments or with an empty object to get balances from all chains
const balanceData = await sphere.wallet.getChainBalance();
console.log("Successfully fetched all balances:");
if (balanceData.success && balanceData.data) {
if (balanceData.data.length > 0) {
balanceData.data.forEach((balance) => {
console.log(`\nChain: ${balance.chainName} (ID: ${balance.chain})`);
console.log(` Token: ${balance.token}`);
console.log(` Amount: ${balance.amount}`);
});
} else {
console.log("No token balances found for this user.");
}
return balanceData.data;
} else {
console.error(
"Failed to fetch balances:",
balanceData.message || balanceData.error
);
return null;
}
} catch (error) {
console.error("Error fetching all wallet balances:", error);
// Handle error appropriately (e.g., display message to user)
throw error;
}
}
// Example usage:
/*
fetchAllUserBalances()
.then(balances => {
if (balances) {
// Update your UI with the balances
}
})
.catch(err => {
// Handle error in UI
});
*/
Example JSON Response (sphere.wallet.getChainBalance()
)
The structure of the response when fetching all balances:
{
"success": true,
"data": [
{
"amount": 5.12345,
"chain": "ethereum_chain_id_or_slug",
"token": "ETH",
"chainName": "ETHEREUM"
},
{
"amount": 1000.75,
"chain": "ethereum_chain_id_or_slug",
"token": "USDC",
"chainName": "ETHEREUM"
},
{
"amount": 250.0,
"chain": "polygon_chain_id_or_slug",
"token": "MATIC",
"chainName": "POLYGON"
}
// ... other token balances across different chains
],
"message": "Balances retrieved successfully"
}
Note: The actual field names and structure are based on the Sphere SDK's Balance
and ApiResponse
types.
Fetching Balances for a Specific Chain (wallet.getChainBalance
)
To retrieve all token balances for a specific chain, use sphere.wallet.getChainBalance()
and provide the chain name.
SDK Usage
async function fetchBalancesForChain(
chain: ChainName
): Promise<Balance[] | null> {
if (!sphere.isAuthenticated()) {
console.error("SDK is not authenticated. Please log in the user first.");
return null;
}
try {
console.log(`Fetching all balances for chain: ${chain}`);
const balanceData = await sphere.wallet.getChainBalance({ chain });
console.log(`Successfully fetched balances for ${chain}:`);
if (balanceData.success && balanceData.data) {
if (balanceData.data.length > 0) {
balanceData.data.forEach((balance) => {
console.log(` Token: ${balance.token}`);
console.log(` Amount: ${balance.amount}`);
});
} else {
console.log(`No token balances found for this user on ${chain}.`);
}
return balanceData.data;
} else {
console.error(
`Failed to fetch balances for ${chain}:`,
balanceData.message || balanceData.error
);
return null;
}
} catch (error) {
console.error(`Error fetching wallet balances for chain ${chain}:`, error);
throw error;
}
}
// Example usage:
/*
fetchBalancesForChain(ChainName.POLYGON)
.then(balances => {
if (balances) {
// Update UI
}
});
*/
This will return a response similar to the "all balances" example, but the data
array will only contain Balance
objects for the specified chain.
Fetching Balance for a Specific Token (wallet.getTokenBalance
)
If you need the balance of a single token type (e.g., USDC), potentially on a specific chain, or across all chains where the user holds it, use sphere.wallet.getTokenBalance()
.
SDK Usage
async function fetchSpecificTokenBalance(
tokenSymbol: TokenSymbol,
chain?: ChainName
): Promise<Balance[] | null> {
if (!sphere.isAuthenticated()) {
console.error("SDK is not authenticated.");
return null;
}
try {
const params: { token: TokenSymbol; chain?: ChainName } = {
token: tokenSymbol,
};
if (chain) {
params.chain = chain;
}
console.log(
`Fetching balance for token ${tokenSymbol}` +
(chain ? ` on chain ${chain}` : " across all applicable chains")
);
const tokenBalanceData = await sphere.wallet.getTokenBalance(params);
if (tokenBalanceData.success && tokenBalanceData.data) {
if (tokenBalanceData.data.length > 0) {
tokenBalanceData.data.forEach((balance) => {
console.log(
`Balance for ${balance.token} on ${balance.chainName}: ${balance.amount}`
);
});
} else {
console.log(
`No balance found for token ${tokenSymbol}` +
(chain ? ` on chain ${chain}` : ".")
);
}
return tokenBalanceData.data; // Returns an array of balances, or empty if none found
} else {
console.error(
`Failed to fetch token balance for ${tokenSymbol}:`,
tokenBalanceData.message || tokenBalanceData.error
);
return null;
}
} catch (error) {
console.error(`Error fetching balance for token ${tokenSymbol}:`, error);
throw error;
}
}
// Example:
/*
// Fetch USDC balance on Ethereum
fetchSpecificTokenBalance(TokenSymbol.USDC, ChainName.ETHEREUM);
// Fetch ETH balance (will typically be on its native chain, e.g., Ethereum)
fetchSpecificTokenBalance(TokenSymbol.ETH);
// Fetch USDC balance across all chains it might exist on for the user
fetchSpecificTokenBalance(TokenSymbol.USDC);
*/
Example JSON Response (sphere.wallet.getTokenBalance
)
If fetching USDC on Ethereum:
{
"success": true,
"data": [
{
"amount": 1000.75,
"chain": "ethereum_chain_id_or_slug",
"token": "USDC",
"chainName": "ETHEREUM"
}
],
"message": "Token balance retrieved successfully"
}
If fetching USDC without specifying a chain, and the user has USDC on multiple chains:
{
"success": true,
"data": [
{
"amount": 1000.75,
"chain": "ethereum_chain_id_or_slug",
"token": "USDC",
"chainName": "ETHEREUM"
},
{
"amount": 500.0,
"chain": "polygon_chain_id_or_slug",
"token": "USDC",
"chainName": "POLYGON"
}
],
"message": "Token balance retrieved successfully"
}
Identifying Native Currency Balances
When using sphere.wallet.getChainBalance()
, the native currency for a given chain (e.g., ETH for Ethereum, MATIC for Polygon) will be listed like any other token. You can typically identify it by its symbol (e.g., "ETH", "MATIC", "BNB") in the token
field of the Balance
object.
SDK Usage
async function fetchNativeCurrencyBalanceForChain(chain: ChainName): Promise<Balance | null> {
if (!sphere.isAuthenticated()) {
console.error("SDK is not authenticated.");
return null;
}
try {
console.log(`Fetching balances for chain ${chain} to find native currency...`);
const balanceData = await sphere.wallet.getChainBalance({ chain });
if (balanceData.success && balanceData.data) {
let nativeTokenSymbol: string;
// Determine the expected native token symbol for the given chain
switch (chain) {
case ChainName.ETHEREUM: nativeTokenSymbol = TokenSymbol.ETH; break;
case ChainName.POLYGON: nativeTokenSymbol = TokenSymbol.MATIC; break;
case ChainName.BNB: nativeTokenSymbol = TokenSymbol.BNB; break;
case ChainName.ARBITRUM: nativeTokenSymbol = TokenSymbol.ETH; break; // Arbitrum's native token is ETH
case ChainName.OPTIMISM: nativeTokenSymbol = TokenSymbol.ETH; break; // Optimism's native token is ETH
case ChainName.BASE: nativeTokenSymbol = TokenSymbol.ETH; break; // Base's native token is ETH
case ChainName.LISK: nativeTokenSymbol = TokenSymbol.LSK; break;
case ChainName.BERACHAIN: nativeTokenSymbol = TokenSymbol.WBERA; break; // Or "BERA" if that's the native symbol
default:
// For unmapped chains, you might need a more dynamic way to identify native assets
// or consult the SDK/API documentation for how native assets are represented.
console.warn(`Native token symbol for chain ${chain} is not explicitly mapped in this example.`);
// Attempt to find a common native asset (e.g. if chainName matches token symbol)
const potentialNative = balanceData.data.find(b => b.token.toUpperCase() === chain.toUpperCase());
if (potentialNative) {
console.log(`Inferred native balance on ${chain} (${potentialNative.token}): ${potentialNative.amount}`);
return potentialNative;
}
return null;
}
const nativeAsset = balanceData.data.find(b => b.token === nativeTokenSymbol);
if (nativeAsset) {
console.log(
`Native balance on ${chain} (${nativeAsset.token}): ${nativeAsset.amount}`
);
return nativeAsset;
} else {
console.log(`No native balance found for ${chain} with symbol ${nativeTokenSymbol}. It might be zero or not present.`);
return null;
}
} else {
console.log(`No balance data returned for ${chain}. Error: ${balanceData.message || balanceData.error}`);
return null;
}
} catch (error) {
console.error(`Error fetching native balance for chain ${chain}:`, error);
throw error;
}
}
// Example:
/*
fetchNativeCurrencyBalanceForChain(ChainName.ETHEREUM).then(balance => {
if (balance) { /* Use native ETH balance */ }
});
fetchNativeCurrencyBalanceForChain(ChainName.POLYGON).then(balance => {
if (balance) { /* Use native MATIC balance */ }
});
*/
Important Considerations
- Authentication Requirement: All balance-fetching methods require an authenticated SDK instance (i.e.,
sphere.setBearerToken(accessToken)
must have been called after a successful user login). - Data Freshness: Balance data is typically fetched in near real-time but might be subject to minor delays due to blockchain confirmations or API caching by the Sphere Network.
- Rate Limiting: Be mindful of API rate limits. Avoid polling for balances too frequently. Implement caching on your application side if needed.
- Error Handling: Implement robust error handling for scenarios like:
- User not authenticated / Invalid or expired token.
- Network errors when communicating with the Sphere Network.
- Invalid parameters passed to SDK methods.
Next Steps
After successfully fetching user balances, you can:
- Display the portfolio and individual token balances in your application's UI.
- Enable users to Make Transactions.
- Integrate with DeFi Swap Functionality.
For further details on specific parameters, response structures, and advanced features, consult the complete Sphere SDK API reference or contact Sphere support.