Skip to main content
Retrieve token balances held directly in wallet addresses, excluding DeFi protocol positions. This endpoint shows only assets in the wallet’s custody across supported blockchains.
Cost: 1 credit per call
Interactive Playground: Test this endpoint in the API Playground. Get your API key at data.octav.fi

Endpoint

GET https://api.octav.fi/v1/wallet

Parameters

addresses
string
required
Comma-separated list of EVM or Solana wallet addresses
addresses=0xddda947f31da53d8f9b05ab5a0bb07713c256e35

Example

curl "https://api.octav.fi/v1/wallet?addresses=0xddda947f31da53d8f9b05ab5a0bb07713c256e35" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

Returns an array of portfolio objects containing only wallet holdings. The structure follows the same format as the Portfolio endpoint, but filtered to show only the wallet protocol.

Top-Level Fields

address
string
The wallet address
networth
string
Total value of all wallet holdings in USD
cashBalance
string
Cash balance in USD (typically “0” for wallet-only view)
closedPnl
string
Realized profit/loss (if available)
openPnl
string
Unrealized profit/loss (if available)
fees
string
Total transaction fees in wei
feesFiat
string
Total transaction fees in USD
lastUpdated
string
Last sync timestamp (milliseconds since epoch)
assetByProtocols
object
Assets organized by protocol - contains only the wallet key The wallet protocol contains:
  • name: “Wallet”
  • key: “wallet”
  • value: Total USD value
  • chains: Holdings organized by blockchain
chains
object
Chain-level summary of wallet holdings Each chain contains:
  • key: Chain identifier
  • name: Chain display name
  • value: Total value on this chain
  • chainId: Numeric chain ID
  • valuePercentile: Percentage of total portfolio

Asset Fields

Each token asset includes:
balance
string
Token balance (in token units)
symbol
string
Token symbol (e.g., “eth”, “uni”)
name
string
Token full name
value
string
USD value of holding
price
string
Current token price in USD
contract
string
Token contract address (0x000…000 for native tokens)
chainKey
string
Blockchain identifier (e.g., “ethereum”, “arbitrum”)
decimal
string
Token decimals

Example Response

[
  {
    "address": "0xddda947f31da53d8f9b05ab5a0bb07713c256e35",
    "networth": "1504.0972690884063639880894878216512",
    "cashBalance": "0",
    "closedPnl": "13.5466715367602206822681107794098304",
    "fees": "48918091440000",
    "feesFiat": "0.125327383206473102336577",
    "lastUpdated": "1736976333061",
    "assetByProtocols": {
      "wallet": {
        "name": "Wallet",
        "key": "wallet",
        "value": "1055.20576207293341601424",
        "chains": {
          "arbitrum": {
            "name": "Arbitrum",
            "key": "arbitrum",
            "value": "1055.20576207293341601424",
            "protocolPositions": {
              "WALLET": {
                "name": "wallet",
                "totalValue": "1055.20576207293341601424",
                "assets": [
                  {
                    "symbol": "eth",
                    "name": "ethereum",
                    "balance": "0.012695517744456324",
                    "value": "43.70762066990445401424",
                    "price": "3442.76",
                    "contract": "0x0000000000000000000000000000000000000000",
                    "chainKey": "arbitrum",
                    "decimal": "18"
                  },
                  {
                    "symbol": "uni",
                    "name": "uniswap",
                    "balance": "69.9031085959246",
                    "value": "1011.497981383028962",
                    "price": "14.47",
                    "contract": "0xfa7f8980b0f1e64a2062791cc3b0871572f1f7f0",
                    "chainKey": "arbitrum",
                    "decimal": "18"
                  },
                  {
                    "symbol": "ftw",
                    "name": "black agnus",
                    "balance": "15000",
                    "value": "0.00016002",
                    "price": "1.0668e-8",
                    "contract": "0x306fd3e7b169aa4ee19412323e1a5995b8c1a1f4",
                    "chainKey": "arbitrum",
                    "decimal": "18"
                  }
                ]
              }
            }
          }
        }
      }
    },
    "chains": {
      "arbitrum": {
        "name": "Arbitrum",
        "key": "arbitrum",
        "chainId": "42161",
        "value": "1504.0972690884063639880894878216512",
        "valuePercentile": "100"
      }
    }
  }
]

Use Cases

  • List All Tokens
  • Calculate Holdings
  • Filter by Value
  • Track Fees
Get all tokens in a wallet:
async function listWalletTokens(address) {
  const response = await fetch(
    `https://api.octav.fi/v1/wallet?addresses=${address}`,
    {
      headers: { 'Authorization': `Bearer ${apiKey}` }
    }
  );
  const [wallet] = await response.json();
  const walletProtocol = wallet.assetByProtocols.wallet;
  console.log(`Total Value: $${parseFloat(wallet.networth).toFixed(2)}\n`);
  // Iterate through each chain
  Object.values(walletProtocol.chains).forEach(chain => {
    console.log(`\n${chain.name}:`);
    const assets = chain.protocolPositions.WALLET.assets;
    assets.forEach(asset => {
      console.log(`  ${asset.symbol.toUpperCase()}: ${parseFloat(asset.balance).toFixed(4)} ($${parseFloat(asset.value).toFixed(2)})`);
    });
  });
}

Comparison: Wallet vs Portfolio

Wallet Endpoint (/v1/wallet)
  • Returns only tokens in direct wallet custody
  • Shows the wallet protocol only
  • Excludes DeFi positions (lending, staking, liquidity pools)
  • Best for simple balance checks
Portfolio Endpoint (/v1/portfolio)
  • Returns complete portfolio including DeFi positions
  • Shows all protocols (wallet, lending, staking, etc.)
  • Includes positions on Aave, Uniswap, etc.
  • Best for comprehensive portfolio view
Example:
  • Wallet: Shows 1 ETH in your address
  • Portfolio: Shows 1 ETH + 2 ETH deposited in Aave + LP tokens in Uniswap
Use /v1/wallet when:
  • You only need basic token balances
  • Building a simple wallet balance viewer
  • Checking liquid/available assets
  • Monitoring tokens ready to transfer
Use /v1/portfolio when:
  • You need complete financial picture
  • Tracking DeFi positions
  • Calculating total net worth
  • Building portfolio analytics dashboard
Both endpoints return the same data structure:
  • Same top-level fields (address, networth, chains)
  • Same asset format (balance, value, price)
  • Same nested structure
The only difference:
  • Wallet: assetByProtocols contains only wallet key
  • Portfolio: assetByProtocols contains all protocols

Best Practices

Wallets can hold assets on multiple chains:
const walletProtocol = wallet.assetByProtocols.wallet;
const chainCount = Object.keys(walletProtocol.chains).length;
console.log(`Assets on ${chainCount} chains`);
// Process each chain
Object.entries(walletProtocol.chains).forEach(([key, chain]) => {
  console.log(`${chain.name}: $${parseFloat(chain.value).toFixed(2)}`);
});
Native tokens (ETH, MATIC, etc.) have special contract address:
function isNativeToken(asset) {
  return asset.contract === '0x0000000000000000000000000000000000000000';
}
const assets = chain.protocolPositions.WALLET.assets;
const nativeToken = assets.find(isNativeToken);
if (nativeToken) {
  console.log(`Native balance: ${nativeToken.balance} ${nativeToken.symbol}`);
}
Filter out very small token amounts (dust):
const MIN_DUST_VALUE = 0.01; // $0.01
const significantTokens = assets.filter(asset => {
  return parseFloat(asset.value) > MIN_DUST_VALUE;
});
console.log(`${significantTokens.length} tokens above dust threshold`);
Handle scientific notation in prices:
function formatPrice(priceString) {
  const price = parseFloat(priceString);
  if (price < 0.01) {
    // Use scientific notation for very small prices
    return price.toExponential(4);
  } else if (price < 1) {
    return price.toFixed(4);
  } else {
    return price.toFixed(2);
  }
}
console.log(formatPrice("1.0668e-8")); // "1.0668e-08"
console.log(formatPrice("3442.76")); // "3442.76"

Common Patterns

Sum up token holdings across chains:
function getTotalBySymbol(wallet, symbol) {
  let total = 0;
  const walletProtocol = wallet.assetByProtocols.wallet;

  Object.values(walletProtocol.chains).forEach(chain => {
    const assets = chain.protocolPositions.WALLET.assets;
    assets.forEach(asset => {
      if (asset.symbol.toLowerCase() === symbol.toLowerCase()) {
        total += parseFloat(asset.balance);
      }
    });
  });

  return total;
}

const totalETH = getTotalBySymbol(wallet, 'eth');
console.log(`Total ETH across all chains: ${totalETH}`);
Get tokens sorted by USD value:
function getSortedAssets(wallet) {
  const walletProtocol = wallet.assetByProtocols.wallet;
  const allAssets = [];

  Object.values(walletProtocol.chains).forEach(chain => {
    const assets = chain.protocolPositions.WALLET.assets;
    assets.forEach(asset => {
      allAssets.push({
        ...asset,
        chainName: chain.name
      });
    });
  });

  return allAssets.sort((a, b) => {
    return parseFloat(b.value) - parseFloat(a.value);
  });
}

const sorted = getSortedAssets(wallet);
console.log('Top 3 holdings:', sorted.slice(0, 3));
Find if wallet holds a specific token:
function hasToken(wallet, contractAddress) {
  const walletProtocol = wallet.assetByProtocols.wallet;

  for (const chain of Object.values(walletProtocol.chains)) {
    const assets = chain.protocolPositions.WALLET.assets;
    const found = assets.find(asset =>
      asset.contract.toLowerCase() === contractAddress.toLowerCase()
    );

    if (found) {
      return {
        has: true,
        balance: found.balance,
        value: found.value,
        chain: chain.name
      };
    }
  }

  return { has: false };
}

const uniToken = hasToken(wallet, '0xfa7f8980b0f1e64a2062791cc3b0871572f1f7f0');
if (uniToken.has) {
  console.log(`Found ${uniToken.balance} UNI on ${uniToken.chain}`);
}