Skip to main content

getVaultTransparencyStats (API)

Returns a delayed off-chain portfolio breakdown for a vault: total USD, per-asset, per-protocol, and per-network slices. The Concrete app uses this endpoint for the Vault Transparency panel on Earn vault pages.

This is a Concrete API route, not an on-chain eth_call. It is not exposed on the @concrete-xyz/sdk vault instance at this time. Integrators call the HTTP endpoint directly.

tip

Treat amountUsd and totalPortfolioAssetsOffchainUsd as display numbers in USD. Asset amount values use the asset's native decimals as reported by the API.

HTTP request

GET /v1/vault:transparency/stats?address={vaultAddress}&chain_id={chainId}

Query parameters

ParameterTypeDescription
addressstringVault contract address. The app lowercases the address before sending.
chain_idnumberEVM chain ID for the vault (for example 1 for Ethereum mainnet).

Response

type VaultTransparencyStats = {
totalPortfolioAssetsOffchainUsd: number;
timestamp: string;
byAsset: {
symbol: string;
amount: number;
amountUsd: number;
logoUrl: string | null;
}[];
byProtocol: {
name: string;
amountUsd: number;
logoUrl: string | null;
}[];
byPlatform: {
platformId: string;
amountUsd: number;
}[];
};

byPlatform rows do not include logoUrl. timestamp is an ISO-style string indicating when the breakdown was captured.

Example

const vaultAddress = "0xe2d8267d285a7ae1edf48498ff044241d04e9608";
const chainId = 1;

const url = new URL("https://api.concrete.xyz/v1/vault:transparency/stats");
url.searchParams.set("address", vaultAddress.toLowerCase());
url.searchParams.set("chain_id", String(chainId));

const res = await fetch(url);
if (!res.ok) throw new Error(`transparency stats failed: ${res.status}`);

const stats: VaultTransparencyStats = await res.json();

console.log(stats.totalPortfolioAssetsOffchainUsd);
console.log(stats.byAsset);
console.log(stats.byProtocol);
console.log(stats.byPlatform);

Replace the base URL with the Concrete API host your environment uses.

Notes

  • Staleness: panel copy in the app states a 24-hour delay. Cache responses accordingly; the app uses a 60-minute client cache.
  • Empty breakdown: when all of byAsset, byProtocol, and byPlatform are empty, the app hides the Vault Transparency panel.
  • Errors: handle non-2xx responses and network failures; the UI omits the panel when data is unavailable.

Minimal guard

try {
const stats = await fetchTransparencyStats(address, chainId);
const hasBreakdown =
stats.byAsset.length > 0 ||
stats.byProtocol.length > 0 ||
stats.byPlatform.length > 0;
if (!hasBreakdown) {
// no panel
}
} catch {
// fallback UI
}