import { type IAddress, type IHistoricalTimeseriesPoint, type IHistoricalTimeseriesResponse, type INormalizedNumber, type ISubgraphReserveDeposit, type ISubgraphTransfer, type ISubgraphUserHistoryItem, type ITokenizedVault, type ISubgraphWithdrawProccessed, type ISubgraphWithdrawRequest, type IVault, type IVaultAllocations, type IVaultAnnualizedApy, type IVaultAvailableRedemption, type IVaultLoan, type IVaultPosition, type IVaultRedemptionHistoryItem, type IVaultSummary, type IVaultWithdrawals, type IVaultPendingRedemptions, type IActiveStakingPosition, type IVaultHistoricalParams, type IVaultUserLifetimePnl, type IVaultBorrowerHealthFactor, type IVaultPnl, type VaultAddress } from '../../types'; import type { IVaultBaseOptions } from './types'; /** * Vault Data Getters * * Main query functions for vault data across chains: * - getVault: Comprehensive vault details with loans/allocations * - getVaultLoans: Active loan data with on-chain enrichment * - getVaultAllocations: DeFi/CeFi/OTC allocation breakdowns * - getVaultAvailableRedemptions: Claimable redemption requests * - getVaultRedemptionHistory: Historical redemption data * - getVaultPositions: User positions across vaults * - getVaultApy: @deprecated Current and historical APY data * - getRewardsStakingPositions: Staking positions and rewards * - getVaultTvl: Current and historical TVL * - getVaultHistoricalTimeseries: Time series data for vault metrics */ /** * Fetch comprehensive vault data including on-chain state and backend metadata. * Routes to appropriate chain adapter (EVM v1/v2, Solana, or Stellar) based on vault version. * Optionally enriches with loan and allocation data. * @param vault - Vault contract address (EVM hex, Stellar C-address, or Solana program ID) * @param loans - Include active loan data. EVM vaults only — there is no * non-EVM loan book to read, so other families keep the empty default. * @param allocations - Include DeFi/CeFi allocation breakdowns. Resolved for EVM * vaults (via DeBank) and Stellar vaults (via the Untangled portfolio API). * Solana and Sui have no vault-level portfolio provider and keep the empty * default. * @param options - RPC and service configuration * @param tokenizedVault - Optional pre-fetched backend row for `vault`. When a * caller already holds the row (e.g. `getVaults` fetched the whole list one * call earlier), passing it skips this function's own * `GET /tokenized_vault/{address}` — a pure de-duplication of backend * traffic. The row must have been fetched with the same * `loadSubaccounts`/`loadSnapshots` flags the caller passes here. * @returns Complete vault object with optional enrichments */ export declare function getVault({ vault, loans, allocations, options, loadSubaccounts, loadSnapshots, tokenizedVault: prefetchedRow, }: { vault: IAddress; loans?: boolean; allocations?: boolean; options: IVaultBaseOptions; loadSubaccounts?: boolean; loadSnapshots?: boolean; tokenizedVault?: ITokenizedVault; }): Promise; /** * Vault Loans */ export declare function getVaultLoans(vault: VaultAddress | IVault, options: IVaultBaseOptions): Promise; /** * Vault Subaccount Loans */ export declare function getVaultSubaccountLoans(vault: VaultAddress | IVault, options: IVaultBaseOptions): Promise; /** * Vault Allocations */ /** * Fetch comprehensive vault asset allocation breakdown. * Includes DeFi protocols (via DeBank), CeFi balances, OTC positions, and loans. * Categorizes exposures by borrowing, supplying, lending, and wallet holdings. * * DeFi exposure resolves per chain family: EVM vaults via DeBank, Solana * borrowers via Octav.fi, and Stellar vaults via the Untangled portfolio API — * one vault-level call covering the idle buffer, Stellar protocol positions, * custody wallets, and capital bridged to other chains. The Stellar path adds * exactly 1 HTTP call and zero for every other chain; when it fails, the * exposure section comes back empty and the CeFi, OTC and loan allocations are * still returned. * * @param vault - Vault address * @param options - RPC configuration * @param tokenizedVault - Optional pre-fetched backend row for `vault`. When a * caller already holds the row (e.g. `getVault` fetched it one call earlier), * passing it skips this function's own `GET /tokenized_vault/{address}` — a * pure de-duplication of backend traffic. The row must carry the subaccount * data this function reads (`.subaccounts`, `.eoa_operators`), so it must not * have been fetched with `loadSubaccounts: false`; a row fetched that way * would silently resolve zero borrowers. * @returns Detailed allocation data with exposure categorization */ export declare function getVaultAllocations(vault: IAddress, options: IVaultBaseOptions, tokenizedVault?: ITokenizedVault): Promise; export declare function getVaultAvailableRedemptions({ vault, wallet, options, prefetchedReads, }: { vault: IAddress; wallet?: IAddress; options: IVaultBaseOptions & { verbose?: boolean; }; /** * Values already read via a Multicall3 batch (see * `modules/vaults/prefetch.ts`). When `lagDuration` is present the * per-vault `lagDuration()` RPC is skipped; when omitted, behavior is * exactly the pre-batching per-call path. * @internal */ prefetchedReads?: { lagDuration?: number; }; }): Promise<{ processedWithdrawals: ISubgraphWithdrawProccessed[]; requestedWithdrawals: ISubgraphWithdrawRequest[]; availableRedemptions: IVaultAvailableRedemption[]; pendingRedemptions: IVaultAvailableRedemption[]; }>; export declare function getVaultRedemptionHistory({ vault, wallet, lookbackBlocks, options, }: { vault: IAddress; wallet?: IAddress; lookbackBlocks?: number; options: IVaultBaseOptions; }): Promise; export { getSwapRouterDepositResult } from '../../core/helpers/swap-router'; /** * Vault Positions */ export declare function getVaultPositions({ vault, wallet, solanaWallet, stellarWallet, options, prefetchedReads, }: { vault: IAddress; wallet?: IAddress; solanaWallet?: string; stellarWallet?: string; options: IVaultBaseOptions; /** * Per-vault values already read via a Multicall3 batch at the fan-out call * sites (see `modules/vaults/prefetch.ts`). Supplied fields skip the * corresponding `balanceOf` / `lagDuration` RPC for the vault matching the * `vault` parameter; when omitted, behavior is exactly the pre-batching * per-call path. * @internal */ prefetchedReads?: { balance?: bigint; lagDuration?: number; }; }): Promise; /** * @deprecated use getVaultHistoricalTimeseries instead */ export declare function getVaultApy({ vault, options, historical, }: { vault: IAddress; options?: IVaultBaseOptions; historical?: IVaultHistoricalParams; }): Promise<{ value: number; timestamp: string; }[]>; export declare function getRewardsStakingPositions({ rpcUrl, wallet, coinGeckoKey, }: { wallet?: IAddress; rpcUrl: string; coinGeckoKey?: string; }): Promise; export declare function getVaultTvl({ vault, options, historical, }: { vault: IAddress; options: IVaultBaseOptions; historical?: IVaultHistoricalParams; }): Promise<{ value: INormalizedNumber; timestamp: string; }[]>; /** * Build the per-loan borrower / health-factor list for a single vault. * * Resilience: individual loan reads (`loanState()`, `borrower()`) and the * per-borrower August backend call are isolated with `Promise.allSettled` and * try/catch so one bad loan — a test loan whose address isn't a real contract, * a borrower the backend doesn't recognize, an intermittent RPC error — drops * that single row from the result instead of rejecting the whole batch. Failed * rows are logged via `Logger.log.warn`; the loan is still returned with * `health_factor: undefined` so callers can render an explicit empty state * rather than a perpetual loading skeleton. * * @param vault - Vault address to scope the fetch to. * @param options - Standard vault options — `rpcUrl` must point at `vault`'s chain. * @returns Array of `IVaultBorrowerHealthFactor`, one entry per active loan. */ export declare function getVaultBorrowerHealthFactor({ vault, options, }: { vault: IAddress; options: IVaultBaseOptions; }): Promise; /** * Aggregate borrower-health-factor data, optionally scoped to a single vault. * * - When `vault` is provided, only that vault's tokenized record is fetched * and only its loans are read. This is the path callers should use when * they already know which vault they care about — it skips the cross-chain * fanout entirely. * - When `vault` is omitted, the function fetches every tokenized vault and * builds health factors for each, preserving the legacy behavior. Per-vault * failures are isolated with `Promise.allSettled` so one bad vault returns * an empty array instead of rejecting the whole map. * * The returned map is keyed by **lowercased** vault address so callers can * look up entries without worrying about EIP-55 checksum casing in either the * backend response or the caller's input. * * @param options - Standard vault options — `rpcUrl` should match `vault`'s chain. * @param vault - Optional vault address to scope the fetch to. * @returns Map of lowercased vault address → array of borrower-health-factor rows. */ export declare function getHealthFactorOfBorrowersByVault({ options, vault, }: { options: IVaultBaseOptions; vault?: IAddress; }): Promise>; /** * Fetch user points from the backend API endpoint. * This replaces client-side points calculation with server-side processing. * @param userAddress - User wallet address (EVM or Solana) * @param options - Request options including headers * @returns Points data from the backend API */ export declare function getUserPoints({ userAddress, options, }: { userAddress: IAddress; options?: IVaultBaseOptions; }): Promise; /** * Register a user for the points program, authenticated by a wallet signature. * * The caller must obtain a personal_sign (EIP-191) signature over the * canonical message template below — the backend reconstructs the same * string from these fields and verifies the signature recovers to * `userAddress`. Building the message client-side and server-side from the * same primitives means a hostile client cannot show one message in the * wallet prompt while submitting a different one for validation. * * Canonical message (`\n`-separated, no trailing newline): * * ``` * Upshift: register {userAddress.toLowerCase()} * referrer: {referrerAddress.toLowerCase() || "none"} * chain: {chainId} * nonce: {nonce} * expires: {expiry} * ``` * * @param userAddress - EVM wallet address being registered. Must match the * signer that produced `signature`. Lowercased before being embedded in * the canonical message. * @param referrerAddress - Optional EVM address that referred this user. * Lowercased when embedded; the literal string `"none"` is used when * absent. Tampering with this field after signing produces 401. * @param chainId - Chain on which the wallet signed. For smart-contract wallets * (Safe etc.) this is the chain whose RPC the backend will use to run the * EIP-1271 `isValidSignature` check; for EOAs it still pins the signature * to a chain so it can't be replayed cross-chain. Must be one of the chains * Upshift supports (see backend `SUPPORTED_REGISTRATION_CHAINS`). * @param signature - `0x`-prefixed hex of the personal_sign signature over * the canonical message. Single-use: replays within ~10 min are rejected. * @param nonce - Caller-generated random string (8–128 chars). Pair with * `userAddress` to form the single-use key in the backend's nonce store. * @param expiry - Unix timestamp (seconds). Must be in the future and within * the backend's TTL window (currently 10 min). * @param options - Request options (headers). * @returns Raw `Response` from the backend. 200 on success, 401 for * expired / replayed / mismatched-signer / tampered-referrer, 422 for an * unsupported `chainId`. * * @example * ```ts * const nonce = crypto.randomUUID().replace(/-/g, ''); * const expiry = Math.floor(Date.now() / 1000) + 300; * const message = * `Upshift: register ${address.toLowerCase()}\n` + * `referrer: ${referrer?.toLowerCase() ?? 'none'}\n` + * `chain: ${chainId}\n` + * `nonce: ${nonce}\n` + * `expires: ${expiry}`; * const signature = await walletClient.signMessage({ account: address, message }); * await registerUserForPoints({ userAddress: address, referrerAddress: referrer, chainId, signature, nonce, expiry }); * ``` */ export declare function registerUserForPoints({ userAddress, referrerAddress, chainId, signature, nonce, expiry, options, }: { userAddress: IAddress; referrerAddress?: IAddress; chainId: number; signature: string; nonce: string; expiry: number; options?: IVaultBaseOptions; }): Promise; /** * Fetch the points leaderboard data. * @param params - Optional parameters for pagination and sorting * @param options - Request options including headers * @returns Leaderboard response data */ export declare function fetchPointsLeaderboard({ params, options, }: { params?: { page?: number; perPage?: number; sortBy?: 'streakDays' | 'totalPoints'; }; options?: IVaultBaseOptions; }): Promise; /** * Fetch the timestamp when yield was last realized for a vault. * Returns the assetsUpdatedOn timestamp from the vault contract. * @param vault - Vault contract address * @param options - RPC configuration * @returns Timestamp (Unix timestamp in seconds) when yield was last realized */ export declare function getYieldLastRealizedOn({ vault, options, }: { vault: IAddress; options: IVaultBaseOptions; }): Promise; /** Inputs the lifetime-PnL history guard inspects. */ export interface PnlHistoryConsistencyParams { /** Vault contract address, used for the error message and context. */ vault: IAddress; /** User wallet address, used for the error message and context. */ wallet: IAddress; /** * Whether the resolved deposit history contains at least one deposit record * (subgraph deposits or LayerZero cross-chain deposits). */ hasDeposits: boolean; /** * Whether the indexed deposits explain every share mint to the wallet (see * {@link historyCoversMints}). Defaults to `true`. */ mintsMatchHistory?: boolean; /** * Shares received by peer transfer, priced in raw base units (asset * decimals) by {@link transferCostBasis}. Defaults to zero. */ receivedByTransferRaw?: bigint; /** Total withdrawn, in raw base units (asset decimals). */ totalWithdrawnRaw: bigint; /** Current on-chain position value, in raw base units (asset decimals). */ currentPositionRaw: bigint; } /** * Guard against lifetime-PnL over-inflation when the deposit history fails to load. * * Lifetime PnL is `currentPosition + totalWithdrawn - totalDeposited`. When the * deposit/withdrawal history fails to load it collapses to empty, so both * `totalDeposited` and `totalWithdrawn` read as zero. If the wallet still holds * a live on-chain position, the formula degenerates to reporting the entire * position as pure profit — a plausible-looking but wrong number. * * This guard rejects exactly that state: a non-zero position with no recorded * deposits, no shares received by transfer *and* no recorded withdrawals. It * also rejects a non-zero position with no recorded deposits when a share mint * to the wallet has no matching deposit (`mintsMatchHistory: false`): the mint * proves a deposit the history failed to return, so neither a peer transfer * nor a withdrawal makes the cost basis complete. Otherwise, any of the * following is treated as consistent and passes: * - deposits are present (the normal, computable case); * - shares were received by transfer and priced (see {@link transferCostBasis}); * - withdrawals are present (a fully-exited-then-re-entered position is still * computable — the withdrawal records prove history loaded); * - the current position is zero (the wallet never interacted or fully exited, * so a zero PnL is correct, not inflated). * * Pure and synchronous — no RPC, no I/O — so it is safe to call inside the hot * path with no added latency. * * Shares received by a direct token transfer (never deposited, never withdrew) * reach this guard as `receivedByTransferRaw`: {@link getVaultUserLifetimePnl} * prices them with {@link transferCostBasis} first. The guard still throws for * such a wallet when its transfers cannot be read or priced, or when a share * mint to it has no indexed deposit. * * @param params - See {@link PnlHistoryConsistencyParams}. * @returns `void` when the history is consistent. * @throws {@link AugustHistoryUnavailableError} with code `HISTORY_UNAVAILABLE` * and `context: { vault, wallet }` when a non-zero position has no deposits * recorded and either a share mint without a matching deposit or neither * received shares nor withdrawals. The message carries the * `#getVaultUserLifetimePnl::::` prefix so it groups with the * other errors leaving the getter. * @example * ```ts * assertPnlHistoryConsistent({ * vault, * wallet, * hasDeposits: depositsByAsset.size > 0, * mintsMatchHistory, * receivedByTransferRaw: costBasis.receivedByTransferRaw, * totalWithdrawnRaw, * currentPositionRaw: currentPositionValue.raw, * }); * ``` */ export declare function assertPnlHistoryConsistent({ vault, wallet, hasDeposits, mintsMatchHistory, receivedByTransferRaw, totalWithdrawnRaw, currentPositionRaw, }: PnlHistoryConsistencyParams): void; /** Inputs the lifetime-PnL price guard inspects. */ export interface PnlTokenPriceParams { /** Vault contract address, used for the error message and context. */ vault: IAddress; /** User wallet address, used for the error message and context. */ wallet: IAddress; /** * The vault's underlying asset (`asset()`) that was priced, or `undefined` * when `asset()` could not be read and no price lookup was possible. */ asset: IAddress | undefined; /** * USD price of `asset` as resolved by the price server. `0` means the lookup * failed or the token is unknown to it (`fetchTokenPriceByAddress` never * throws). */ tokenPriceUsd: number; } /** * Guard against converting lifetime PnL to USD with a fabricated price. * * Every USD field `getVaultUserLifetimePnl` returns is a native amount times * the underlying asset's USD price. When the price server has no price, the * only honest outcome is "no USD value" — substituting a stand-in (the getter * previously used `1`) reports a non-dollar vault's position at $1 per asset, * a plausible-looking but wrong number that callers cannot detect. * * Pure and synchronous — no RPC, no I/O. * * @param params - See {@link PnlTokenPriceParams}. * @returns `tokenPriceUsd`, unchanged, when it is a finite number above zero. * @throws {@link AugustPriceUnavailableError} with code `PRICE_UNAVAILABLE` * and `context: { vault, wallet, asset }` when the price is zero, negative, * or not finite. The message carries the * `#getVaultUserLifetimePnl::::` prefix so it groups with the * other errors leaving the getter. * @example * ```ts * const price = assertPnlTokenPrice({ * vault, * wallet, * asset: underlyingAssetAddress, * tokenPriceUsd: await pricePromise, * }); * ``` */ export declare function assertPnlTokenPrice({ vault, wallet, asset, tokenPriceUsd, }: PnlTokenPriceParams): number; /** * Sum a wallet's per-asset deposits into the vault's own decimals, at face * value — 1 unit of any deposited asset is treated as 1 unit of the vault's * reporting currency, with no live price conversion. * * Used by {@link getVaultUserLifetimePnl} for `totalDeposited`. Pre-deposit * multi-asset vaults only accept dollar-pegged stablecoins (USDC, USDT, DAI, * USDS, RLUSD, etc.) into a dollar-denominated vault, so face value is a * reasonable stand-in for USD value. This intentionally does NOT re-quote * through a live price oracle: doing so priced a historical deposit at * today's market rate, so `totalDeposited` (and lifetimePnl) drifted between * calls purely from stablecoin peg noise, and approximately re-inflated * deposits back toward face value — which silently excluded the vault's * entry fee from PnL. The fee is money the user actually paid, so PnL must * be computed net of it. * * @param depositsByAsset - Raw deposited amount per asset, keyed by * lowercased asset address (or `'default'` / `'lz-default'` for * single-asset / cross-chain rows). * @param assetDecimals - Decimals for each key in `depositsByAsset`. * @param vaultDecimals - The vault's own decimals — the target scale every * asset is rescaled to. * @returns Total deposited, in raw base units at `vaultDecimals`. */ export declare function sumDepositsAtFaceValue(depositsByAsset: Map, assetDecimals: Map, vaultDecimals: number): bigint; /** The receipt-token transfer fields the transfer cost basis reads. */ export type PnlTransfer = Pick; /** * Keep the receipt-token transfers that moved shares between `wallet` and * another holder. * * Vault shares are transferable ERC-20 tokens, so a wallet can hold a position * it never deposited into — a migration airdrop, a DEX purchase, a transfer from * another wallet. Mints (from the zero address), burns (to it) and transfers to * or from the vault itself are dropped: those are the deposit and withdrawal * legs the subgraph history already records, and counting them again would * double the cost basis. Transfers to or from `exclude` are dropped too. * * @param transfers - Receipt-token transfers touching `wallet`, as returned by * the vault's transfer subgraph. * @param wallet - The wallet whose position is being valued. * @param vault - The vault contract address. * @param exclude - Other counterparties whose transfers are not peer * transfers, such as a LayerZero OVault's hub composer and share OFT * (`hubComposer` / `hubShareOFT` in `LAYERZERO_VAULTS`). Defaults to none. * @returns The peer-to-peer transfers, in input order. Addresses compare * case-insensitively. * @example * ```ts * const peer = selectPeerTransfers(transfers, wallet, vault); * ``` */ export declare function selectPeerTransfers(transfers: T[], wallet: IAddress, vault: IAddress, exclude?: string[]): T[]; /** Inputs {@link transferCostBasis} prices. */ export interface TransferCostBasisParams { /** Peer transfers touching `wallet` — see {@link selectPeerTransfers}. */ transfers: PnlTransfer[]; /** The wallet whose cost basis is being computed. */ wallet: IAddress; /** The vault contract address, used for the error message and context. */ vault: IAddress; /** * The vault's daily history from `fetchVaultHistoricalTimeseries`, keyed by * UTC date (`YYYY-MM-DD`). Only `asset_share_ratio` (assets per share) is * read. */ history: Record>; /** * Report sent shares even when none were received. Defaults to `false`, which * zeroes them so a zero-deposit wallet's history guard still decides; pass * `true` when the caller applies that rule itself, as {@link pnlCostBasis} * does. */ countSentWithoutReceipt?: boolean; } /** Asset amounts that peer transfers moved into and out of a position. */ export interface TransferCostBasis { /** Assets the received shares were worth on arrival, raw at vault decimals. */ receivedRaw: bigint; /** Assets the sent shares were worth when they left, raw at vault decimals. */ sentRaw: bigint; } /** * Value peer share transfers in the vault's asset, at the vault's share ratio * on the day each one happened. * * Used by {@link getVaultUserLifetimePnl} when a wallet has no indexed * deposits: received shares become its cost basis and sent shares count as * withdrawn, so lifetime PnL for a transfer recipient reads "PnL since the * shares arrived" rather than failing or reporting the whole position as * profit. A day with no usable ratio takes the latest earlier day's, and a * transfer older than the history takes the earliest day's. * * Sent shares count only against a received basis by default. A wallet that * sent shares but received none gets a zero basis, so the lifetime-PnL history * guard still decides for it instead of reporting the sent shares as profit. * `countSentWithoutReceipt: true` reports them anyway, for a caller that knows * the wallet also deposited. * * Pure and synchronous. Assumes, as the getter does, that shares and assets * share the vault's decimals. * * @param params - See {@link TransferCostBasisParams}. * @returns The received and sent asset amounts, raw at the vault's decimals; * both zero when no shares were received. * @throws {@link AugustHistoryUnavailableError} (`HISTORY_UNAVAILABLE`) when no * day in `history` carries a positive, finite `asset_share_ratio`. * @example * ```ts * const { data } = await fetchVaultHistoricalTimeseries(vault, nDays); * const { receivedRaw, sentRaw } = transferCostBasis({ * transfers: selectPeerTransfers(transfers, wallet, vault), * wallet, * vault, * history: data, * }); * ``` */ export declare function transferCostBasis({ transfers, wallet, vault, history, countSentWithoutReceipt, }: TransferCostBasisParams): TransferCostBasis; /** Inputs {@link historyCoversMints} compares. */ export interface HistoryCoversMintsParams { /** Every share-token transfer touching `wallet`, mints included. */ transfers: Pick[]; /** The wallet whose history is being checked. */ wallet: IAddress; /** Transaction hashes of the wallet's indexed deposits. */ depositTransactionHashes: string[]; } /** * Check that a wallet's indexed deposit history accounts for every share mint * its share-token ledger shows. * * A deposit mints shares to the wallet in the same transaction, so a mint with * no deposit of the same hash means the history is missing that deposit (an * older deposit the subgraph never indexed, or one a third party made for the * wallet). Folding peer transfers into such a history would credit the wallet * for shares it sent while missing what it paid for them, so * {@link getVaultUserLifetimePnl} only folds transfers for a depositor when * this holds. * * Pure and synchronous. Hashes and addresses compare case-insensitively. * * @param params - See {@link HistoryCoversMintsParams}. * @returns `true` when every mint to `wallet` has a matching deposit, including * when there are no mints. * @example * ```ts * const covered = historyCoversMints({ * transfers, * wallet, * depositTransactionHashes: history * .filter((item) => item.type === 'deposit') * .map((item) => item.transactionHash_), * }); * ``` */ export declare function historyCoversMints({ transfers, wallet, depositTransactionHashes, }: HistoryCoversMintsParams): boolean; /** Inputs {@link selectReserveDeposits} matches. */ export interface SelectReserveDepositsParams { /** The wallet's `ReserveDeposit` events (see `getSubgraphUserReserveDeposits`). */ reserveDeposits: ISubgraphReserveDeposit[]; /** Every share-token transfer touching `wallet`, mints included. */ transfers: Pick[]; /** The wallet whose history is being completed. */ wallet: IAddress; /** Transaction hashes of the wallet's indexed deposits. */ depositTransactionHashes: string[]; } /** * Keep the `ReserveDeposit` events that explain a share mint the indexed * deposit history misses. * * High Growth ETH mints shares for deposits made through Kelp's gain adapter * with a `ReserveDeposit` event instead of an ERC-4626 `Deposit`, so those * deposits are absent from the user history and fail {@link historyCoversMints}. * An event counts only when its transaction mints shares to `wallet` and holds * no indexed deposit, so a deposit is never counted twice. * * Pure and synchronous. Hashes and addresses compare case-insensitively. * * @param params - See {@link SelectReserveDepositsParams}. * @returns The matching events, in input order. * @example * ```ts * const reserve = selectReserveDeposits({ * reserveDeposits: await getSubgraphUserReserveDeposits(wallet, provider, vault), * transfers, * wallet, * depositTransactionHashes, * }); * ``` */ export declare function selectReserveDeposits({ reserveDeposits, transfers, wallet, depositTransactionHashes, }: SelectReserveDepositsParams): ISubgraphReserveDeposit[]; /** Inputs {@link countWithdrawalRequestsOnce} reads. */ export interface CountWithdrawalRequestsOnceParams { /** The wallet's user history (see `getSubgraphUserHistory`). */ history: ISubgraphUserHistoryItem[]; /** Every share-token transfer touching `wallet`. */ transfers: Pick[]; /** The wallet whose history is being read. */ wallet: IAddress; /** The vault contract address. */ vault: IAddress; } /** * Drop withdrawal-request rows the vault logged more than once for a single * request. * * A redemption requested through Kelp's gain adapter makes High Growth ETH emit * `WithdrawalRequested` twice for one share transfer, and the subgraph indexes * both. In a transaction where the share ledger shows the wallet sending shares * to the vault `n` times, at most `n` request rows are kept. A transaction the * ledger shows no such transfer for keeps every row, so a missing ledger leaves * the history unchanged. * * Pure and synchronous. Hashes and addresses compare case-insensitively. * * @param params - See {@link CountWithdrawalRequestsOnceParams}. * @returns The history without the surplus request rows, in input order. * @example * ```ts * const history = countWithdrawalRequestsOnce({ history: userHistory, transfers, wallet, vault }); * ``` */ export declare function countWithdrawalRequestsOnce({ history, transfers, wallet, vault, }: CountWithdrawalRequestsOnceParams): ISubgraphUserHistoryItem[]; /** Inputs {@link settleV2Redemptions} values. */ export interface SettleV2RedemptionsParams { /** The wallet's user history (see `getSubgraphUserHistory`). */ history: ISubgraphUserHistoryItem[]; /** The vault's `lagDuration()`, in seconds. */ lagDuration: number; /** * The vault's daily history from `fetchVaultHistoricalTimeseries`, keyed by * UTC date (`YYYY-MM-DD`). Only `asset_share_ratio` (assets per share) is * read. */ ratios: Record>; /** The current time, in unix seconds. */ now: number; } /** What a wallet's Tokenized Vault V2 redemption requests are worth. */ export interface V2RedemptionValue { /** Assets paid, or due, for requests past their claim date; raw at vault decimals. */ settledAssetsRaw: bigint; /** Shares to value at the current share price, raw. */ pendingShares: bigint; } /** * Value a wallet's Tokenized Vault V2 redemption requests, which carry only * shares. * * Every processed withdrawal (`WithdrawalProcessed.assetsAmount`) counts at the * assets the vault paid. Its shares, estimated at the vault's * `asset_share_ratio` on the day it was processed, retire the oldest requests * first. Request shares left over count at the ratio on their claim date (see * `computeClaimableDate`) once claimable: the subgraph lacks some processed rows * (none for earnAUSD before 2026-02-01), and that ratio lands within about * 0.05% of what the vault paid. Shares not yet claimable are left to the * current share price. Matching by amount, not by claim date, keeps the result * right when a vault processes a request before the date today's `lagDuration` * implies. A leftover under 0.5% of a request that a later processed * withdrawal followed is rounding from the daily ratio, so it is dropped. * * Pure and synchronous. Assumes, as the getter does, that shares and assets * share the vault's decimals. A day with no usable ratio takes the latest * earlier day's, and a date older than the history takes the earliest day's. * * @param params - See {@link SettleV2RedemptionsParams}. * @returns The settled assets and the shares left to the current price; every * requested share is pending when `ratios` holds no usable day. * @example * ```ts * const { settledAssetsRaw, pendingShares } = settleV2Redemptions({ * history, * lagDuration: 259_200, * ratios: (await fetchVaultHistoricalTimeseries(vault, nDays)).data, * now: Math.floor(Date.now() / 1000), * }); * ``` */ export declare function settleV2Redemptions({ history, lagDuration, ratios, now, }: SettleV2RedemptionsParams): V2RedemptionValue; /** Inputs {@link pnlCostBasis} folds together. */ export interface PnlCostBasisParams { /** Indexed deposits at face value, raw at the vault's decimals. */ depositedRaw: bigint; /** Withdrawals already in asset terms, raw at the vault's decimals. */ withdrawnAssetsRaw: bigint; /** Whether history indexed any deposit, LayerZero deposits included. */ hasDeposits: boolean; /** Whether the history accounts for every share mint (see {@link historyCoversMints}). */ mintsMatchHistory: boolean; /** * Peer transfers priced by {@link transferCostBasis} with * `countSentWithoutReceipt: true`. */ transfers: TransferCostBasis; } /** The cost basis {@link getVaultUserLifetimePnl} computes PnL against. */ export interface PnlCostBasis { /** Indexed deposits plus shares received by transfer, raw at vault decimals. */ depositedRaw: bigint; /** Asset-terms withdrawals plus shares sent by transfer, raw at vault decimals. */ withdrawnAssetsRaw: bigint; /** The part of `depositedRaw` that came from shares received by transfer. */ receivedByTransferRaw: bigint; } /** * Fold peer share transfers into a wallet's lifetime-PnL cost basis. * * Shares a wallet received from another holder (a migration airdrop, a DEX * purchase, a transfer from another wallet) cost the wallet their value on * arrival, so they add to the deposited amount; shares it sent away count as * withdrawn. This applies whether or not the wallet also deposited, so a holder * who received shares and then topped up is not credited with the received * shares as profit, and a depositor who moved its shares elsewhere (a lending * market, a DEX) is not shown as having lost them. A wallet with no deposit and * no received shares keeps a zero basis, so the history guard still decides. * * A depositor whose history misses a mint ({@link historyCoversMints}) is the * exception: its transfers do not count, so the result matches what the getter * returned before transfers counted for depositors. A wallet with no deposit * still gets a basis here when its history misses a mint, but * {@link assertPnlHistoryConsistent} rejects it. On a LayerZero OVault the * caller leaves the hub composer and share OFT out of the transfers (see * {@link selectPeerTransfers}): the composer's deliveries are already counted * as LayerZero deposits, and shares bridged to a spoke chain still count in the * position. * * Pure and synchronous. * * @param params - See {@link PnlCostBasisParams}. * @returns The deposited and withdrawn amounts to compute PnL from, and the * transfer-priced part of the deposited amount (zero when transfers did not * count). * @example * ```ts * const basis = pnlCostBasis({ * depositedRaw, * withdrawnAssetsRaw, * hasDeposits: depositedRaw > BigInt(0), * mintsMatchHistory: historyCoversMints({ * transfers, * wallet, * depositTransactionHashes, * }), * transfers: transferCostBasis({ * transfers, * wallet, * vault, * history, * countSentWithoutReceipt: true, * }), * }); * ``` */ export declare function pnlCostBasis({ depositedRaw, withdrawnAssetsRaw, hasDeposits, mintsMatchHistory, transfers, }: PnlCostBasisParams): PnlCostBasis; /** * Calculate lifetime PnL for a user in a specific vault. * * Basic logic: * 1. Get user's list of deposits and withdrawals from subgraph * 2. Fetch user's current assets (balanceOf * sharePrice via convertToAssets) * 3. Calculate PnL = assets withdrawn + current assets - assets deposited * * `totalDeposited` is the face value of what the user actually paid in * (each deposited asset's raw amount, rescaled to the vault's decimals — no * live price conversion), so any entry/exit fee the vault charges is * automatically counted as a cost against PnL rather than excluded from it. * Pre-deposit multi-asset vaults are assumed to only accept dollar-pegged * stablecoins into a dollar-denominated vault; a vault accepting a * non-pegged deposit asset would need deposit-time price conversion, which * this function does not perform. * * Every USD field is the native amount times the underlying asset's USD price * from the price server. There is no stand-in price: when none resolves the * getter throws rather than returning USD values it cannot know. * * Shares moved by transfer: peer transfers of the share token (see * {@link selectPeerTransfers}) are valued at the vault's daily share ratio * ({@link transferCostBasis}) and folded in by {@link pnlCostBasis} — received * shares add to `totalDeposited` (and are reported again as * `receivedByTransfer`), sent shares add to `totalWithdrawn`. This holds * alongside indexed deposits, so a wallet that received shares and also * deposited is not credited with the received shares as profit. On LayerZero * OVaults, transfers from or to the hub composer and share OFT do not count, * because the composer delivers cross-chain deposits by transfer and those * are already counted as LayerZero deposits. * * Gaps in the indexed history: a share mint with no `Deposit` event counts as * a deposit of the assets in its `ReserveDeposit` event * ({@link selectReserveDeposits}; High Growth ETH emits it for Kelp gain-adapter * deposits), and a withdrawal request the vault logged twice counts once * ({@link countWithdrawalRequestsOnce}). Transfers fold in for a depositor only * once every mint is explained. A wallet with no indexed deposit and a mint * that no deposit explains throws `HISTORY_UNAVAILABLE`. * * Tokenized Vault V2 redemptions carry only shares, so a settled one counts at * the assets the vault paid, or at the share ratio on its claim date when the * subgraph has no processed row for it ({@link settleV2Redemptions}). Only a * request not yet claimable is valued at the current share price. When the lag * or the ratio history cannot be read, every request is valued at the current * share price instead. * * Request cost: one receipt-transfer subgraph query (and a `symbol()` RPC read) * per call, plus one backend timeseries request when peer transfers exist and * one `reserveDeposits` subgraph query when a mint has no indexed deposit, and * for a Tokenized Vault V2 wallet with redemption requests, a `lagDuration()` * read plus one backend timeseries request. A timeseries window with no usable * ratio (a closed vault whose history stopped earlier) is read again in full, * so the latest earlier day still prices it. The transfer query runs for * every vault, in parallel with the history read. * * @param vault - Vault contract address * @param wallet - User wallet address * @param options - RPC configuration and service options * @returns Lifetime PnL data in both native token and USD * @throws {@link AugustHistoryUnavailableError} (`HISTORY_UNAVAILABLE`) when a * live position has no indexed deposits, withdrawals or priceable share * transfers, or has no indexed deposit while a share mint to the wallet has * no matching deposit. * @throws {@link AugustPriceUnavailableError} (`PRICE_UNAVAILABLE`) when the * underlying asset has no USD price, or `asset()` cannot be read. */ export declare function getVaultUserLifetimePnl({ vault, wallet, options, }: { vault: IAddress; wallet: IAddress; options: IVaultBaseOptions; coingeckoKey?: string; }): Promise; /** * Calculate PnL for a vault (vault-level, not user-specific). * Returns the vault's overall profit and loss across all users. * * @param vault - Vault contract address * @param options - RPC configuration and service options * @returns Vault PnL in USD and notional value */ export declare function getVaultPnl({ vault, options, }: { vault: IAddress; options: IVaultBaseOptions; }): Promise; export declare function getVaultHistoricalTimeseries({ vault, nDays, options, }: { vault: IAddress; nDays?: number; options?: IVaultBaseOptions; }): Promise; /** * Fetch annualized APY metrics for a vault. * * Supported Vaults: cUSDO, tETH, wstETH, rsETH * * @deprecated The `hgETH30dLiquidAPY` and `hgETH7dLiquidAPY` response fields are deprecated. * These fields will be removed in the next major release. * Use `liquidAPY30Day` and `liquidAPY7Day` fields instead. * * @param vault - Vault contract address * @param options - Request options including headers * @returns Annualized APY data including liquidity APY */ export declare function getVaultAnnualizedApy({ vault, options, }: { vault: IAddress; options?: IVaultBaseOptions; }): Promise; /** * Fetch summary data for a vault (name, type, chain, recent returns). * @param vault - Vault contract address * @param options - Request options including headers * @returns Vault summary data */ export declare function getVaultSummary({ vault, options, }: { vault: IAddress; options?: IVaultBaseOptions; }): Promise; /** * Fetch withdrawal summary and pending queue for a vault. * @param vault - Vault contract address * @param chain - Chain identifier (e.g., chain ID as string) * @param options - Request options including headers * @returns Withdrawal summary and pending queue */ export declare function getVaultWithdrawals({ vault, chain, options, }: { vault: IAddress; chain: string; options?: IVaultBaseOptions; }): Promise; /** * Fetch pending redemptions for a vault with liquidity analysis. * @param vault - Vault contract address * @param pastDays - Number of past days to include (default 7, min 1, max 30) * @param futureDays - Number of future days to include (default 14, min 1, max 30) * @param options - Request options including headers * @returns Pending redemptions grouped by date with liquidity summary */ export declare function getVaultPendingRedemptions({ vault, pastDays, futureDays, options, }: { vault: IAddress; pastDays?: number; futureDays?: number; options?: IVaultBaseOptions; }): Promise; /** * Preview the amount of assets that would be received for redeeming shares (queued redemption). * @param vault - Vault contract address * @param sharesAmount - Amount of shares to redeem (human-readable, raw bigint, or string) * @param options - RPC configuration * @returns The amount of assets as an INormalizedNumber with `normalized` and `raw` fields */ export declare function getPreviewRedemption({ vault, sharesAmount, options, }: { vault: IAddress; sharesAmount: string | bigint | number; options: IVaultBaseOptions; }): Promise; /** * Withdrawal request with computed claimable date and current processing status. * The unique identifier is (receiver, claimableDate). * * @interface WithdrawalRequestStatus */ export interface WithdrawalRequestStatus { /** Transaction hash of the withdrawal request */ transactionHash: string; /** Block timestamp when the withdrawal was requested (seconds, UTC) */ requestTimestamp: number; /** Shares amount being redeemed */ shares: bigint; /** Receiver address for the withdrawal */ receiver: string; /** Computed claimable date in UTC (year, month, day) */ claimableDate: { year: number; month: number; day: number; }; /** Epoch timestamp when this withdrawal becomes claimable */ claimableEpoch: number; /** Current status of the withdrawal */ status: 'pending' | 'ready_to_claim' | 'processed'; /** Transaction hash of the processing transaction (if processed) */ processedTransactionHash?: string; /** Assets received (if processed) */ assetsReceived?: bigint; } /** * Returns all withdrawal requests for a vault, enriched with computed claimable dates * and current processing status. * * The unique identifier for matching requests to processed events is: * (receiver, claimableDate.year, claimableDate.month, claimableDate.day) * * This is the primary method for integrators to reliably track withdrawal status * when multiple requests are submitted by the same receiver. * * ## Data sources * - **Withdrawal requests** come from the subgraph (all historical requests). * - **Processed events** come from on-chain `WithdrawalProcessed` logs, which are * limited to a finite lookback window determined by the chain's block parameters. * * ## Lookback window & filtering * On-chain logs only cover a limited number of recent blocks (e.g. ~20 days on Monad, * ~21 days on Ethereum). The `lookbackBlocks` parameter controls how far back to scan * and is applied uniformly to both data sources: it bounds the `WithdrawalProcessed` * log query *and* drops any withdrawal request whose submission timestamp falls outside * the window — regardless of whether a matching processed event was found. Callers who * need deeper history should widen `lookbackBlocks`. * * ## Status determination * - `'processed'` — A matching `WithdrawalProcessed` event was found (by receiver + claimable date). * - `'ready_to_claim'` — Claimable date has passed (within the lookback window) but no processed event found. * - `'pending'` — Claimable date is still in the future. * * @param params - Query parameters: * - `vault` — Vault address to query. * - `receiver` — (Optional) Filter by receiver address. * - `lookbackBlocks` — (Optional) On-chain log lookback window in blocks. * Defaults to a chain-specific value (e.g. 150,000 for Ethereum, 3,456,000 for Monad). * Increasing this scans more history but requires more RPC calls. * - `options` — Standard vault query options (provider, RPC URL, etc.). * @returns Array of withdrawal requests with status and claimable dates * * @example * ```typescript * const requests = await getWithdrawalRequestsWithStatus({ * vault: '0xVault...', * receiver: '0xReceiver...' * }); * * // Results show exact status + claimable date * requests.forEach(req => { * console.log( * `${req.claimableDate.year}-${req.claimableDate.month}-${req.claimableDate.day}: ${req.status}` * ); * }); * * // With custom lookback window (e.g. 30 days on Ethereum ≈ 216,000 blocks) * const moreResults = await getWithdrawalRequestsWithStatus({ * vault: '0xVault...', * lookbackBlocks: 216_000, * }); * ``` */ export declare function getWithdrawalRequestsWithStatus(params: { vault: IAddress; receiver?: IAddress; lookbackBlocks?: number; options: IVaultBaseOptions; }): Promise;