The usePortfolio hook provides comprehensive portfolio management functionality, including asset balances, valuations, and chain-organized data for connected wallets.
This hook must be used within a component wrapped by InterwovenKitProvider to access portfolio data across all supported chains.
Overview
The usePortfolio hook aggregates balance and asset information from all chains in the Initia ecosystem, providing organized views of:
- Chain-based portfolio breakdown with total values
- Asset groupings across multiple chains by symbol
- Price information and total portfolio valuation
- Unlisted assets that don’t have registry entries
Return Values
Array of chains ordered by total portfolio value, with the default chain appearing first.
Asset groups organized by symbol, combining the same asset across different chains.
Assets that exist in the wallet but are not registered in the chain registry.
Total USD value of all assets across all chains in the portfolio.
Loading state that is true when any balance, asset, or price queries are in progress.
Function to refetch all balance, asset, and price data across all chains.
Data Structures
PortfolioChainItem
interface PortfolioChainItem {
chainId: string
chainName: string
logoUrl: string
value: number // Total USD value of assets on this chain
}
PortfolioAssetGroup
interface PortfolioAssetGroup {
symbol: string
logoUrl: string
assets: PortfolioAssetItem[] // Same asset across different chains
}
PortfolioAssetItem
interface PortfolioAssetItem {
// Asset identification
symbol: string
name: string
logoUrl: string
denom: string
// Balance information
amount: string // Raw amount in base units
decimals: number
quantity: string // Human-readable amount
// Valuation
price?: number // USD price per token
value?: number // Total USD value (quantity * price)
// Chain context
chain: {
chainId: string
chainName: string
logoUrl: string
}
// Asset metadata
address?: string // Contract address for token contracts
unlisted: boolean // true if not in chain registry
}
Usage Examples
Basic Portfolio Display
function Portfolio() {
const { chainsByValue, totalValue, isLoading } = usePortfolio()
if (isLoading) return <div>Loading portfolio...</div>
return (
<div>
<h2>Total Portfolio Value: ${totalValue.toLocaleString()}</h2>
{chainsByValue.map((chain) => (
<div key={chain.chainId}>
<img src={chain.logoUrl} alt={chain.chainName} />
<span>{chain.chainName}</span>
<span>${chain.value.toLocaleString()}</span>
</div>
))}
</div>
)
}
Asset Groups with Cross-Chain Balances
function AssetGroups() {
const { assetGroups } = usePortfolio()
return (
<div>
{assetGroups.map((group) => (
<div key={group.symbol}>
<div className="header">
<img src={group.logoUrl} alt={group.symbol} />
<h3>{group.symbol}</h3>
</div>
{group.assets.map((asset) => (
<div key={`${asset.chain.chainId}-${asset.denom}`}>
<span>{asset.chain.chainName}</span>
<span>{asset.quantity}</span>
{asset.value && <span>${asset.value.toLocaleString()}</span>}
</div>
))}
</div>
))}
</div>
)
}
Handling Unlisted Assets
function UnlistedAssets() {
const { unlistedAssets } = usePortfolio()
if (unlistedAssets.length === 0) return null
return (
<div>
<h3>Unlisted Assets</h3>
<Warning>
These assets are not verified in the chain registry and may not have accurate price information.
</Warning>
{unlistedAssets.map((asset) => (
<div key={`${asset.chain.chainId}-${asset.denom}`}>
<span>{asset.denom}</span>
<span>{asset.quantity}</span>
<span>{asset.chain.chainName}</span>
</div>
))}
</div>
)
}
Refreshing Portfolio Data
function PortfolioWithRefresh() {
const { totalValue, isLoading, refetch } = usePortfolio()
return (
<div>
<div>
<span>Portfolio Value: ${totalValue.toLocaleString()}</span>
<button onClick={refetch} disabled={isLoading}>
{isLoading ? 'Refreshing...' : 'Refresh'}
</button>
</div>
</div>
)
}