/** * Response types for the Untangled portfolio API. * * Shape verified live on 2026-09-01 against * `GET https://api-portfolio-octopos-mainnet.untangled.finance/v1/vaults/{address}/exposure` * for the Gami earnUSDC Stellar vault. */ /** * One protocol slice of a vault's TVL. * * Untangled reports the whole vault, so the slices cover capital held in the * vault contract itself, in custody wallets, and bridged to other chains — not * just on-chain Stellar protocol positions. */ export interface IUntangledProtocolExposure { /** * Untangled protocol slug, e.g. `blend`, `templar`, `aquarius`. Two slugs are * special: `stellar-wallet` is custody wallet cash, and `upshift` is the * vault's own idle buffer plus any position it holds in another Upshift * vault — only the part beyond the `idle` location is deployed capital. */ protocolId: string; /** USD value held in this protocol. */ valueUsd: number; /** Share of the vault's `tvlUsd`, as a percentage (`23.54` means 23.54%). */ pct: number; } /** * One asset slice of a vault's TVL. Vault-wide — the API does not currently * break assets down per protocol. */ export interface IUntangledAssetExposure { /** Asset ticker, e.g. `USDC`, `XLM`. */ symbol: string; /** USD value held in this asset across the whole vault. */ valueUsd: number; /** Share of the vault's `tvlUsd`, as a percentage. */ pct: number; } /** * One address holding part of a vault's capital — the vault contract, a custody * wallet, or a bridged account on another chain. */ export interface IUntangledLocation { /** Address on `chain`. Not necessarily a Stellar address (NEAR accounts appear here). */ address: string; /** Chain slug the address lives on, e.g. `stellar`, `near`. */ chain: string; /** Human-readable label, e.g. `idle`, `ForDefi`, `Templar`. */ label: string; /** USD value held at this address. */ valueUsd: number; /** ISO-8601 timestamp this location was last reconciled. */ asOf: string; } /** * A resolved vault exposure report. * * Untangled answers with `{ resolved: false, reason }` and HTTP 404 for vaults * it does not reconcile; `fetchUntangledVaultExposure` maps that to `null`, so * `resolved` is always `true` on values that reach a caller. */ export interface IUntangledVaultExposure { /** Always `true` — unresolved reports never reach callers. */ resolved: true; /** The vault this report describes. */ vault: { address: string; chain: string; }; /** Total USD value Untangled reconciled across every location. */ tvlUsd: number; /** Protocol-level split of `tvlUsd`. */ byProtocol: IUntangledProtocolExposure[]; /** Asset-level split of `tvlUsd`, vault-wide. */ byAsset: IUntangledAssetExposure[]; /** Per-address drill-down of where the capital sits. */ locations: IUntangledLocation[]; /** ISO-8601 timestamp the report was assembled. */ asOf: string; /** `true` when Untangled served a report it could not refresh in time. */ stale: boolean; }