Skip to main content
The get vault position endpoint returns total_deposited and total_withdrawn for a wallet. For all vault providers, Privy computes these totals from the deposits and withdrawals made through Privy Earn. Deposits and withdrawals made directly onchain are not counted. This recipe shows how your app can read the same values directly from the vault contract for Morpho and Aave vaults. The onchain totals include every deposit and withdrawal for the wallet, no matter how it was sent.
Your app only needs this recipe if wallets interact with a vault outside the Privy Earn deposit and withdraw endpoints. For example, your app sends a vault deposit call with sendTransaction, or users deposit from another app. If all activity goes through Privy Earn, your app can use the endpoint totals.

Resources

Get vault position

The Privy endpoint that returns a wallet’s vault position.

ERC-4626 standard

The tokenized vault standard that Morpho and Aave Earn vaults implement.

Field sources

The table maps each field of the get vault position response to its source in the endpoint and onchain. The endpoint values for shares_in_vault and assets_in_vault match the onchain reads. This recipe also shows how to read them onchain, so that your app reads all four values at the same block.
This recipe covers Morpho and Aave vaults.

Prerequisites

  • A Privy app with an Earn vault. See Earn setup.
  • Your app ID and app secret, for the Privy API.
  • An RPC URL for the vault’s chain. The chain ID is the number after eip155: in the vault’s caip2.
  • The block number at which the vault contract was deployed. Find the contract creation transaction for the vault address on a block explorer for the vault’s chain.
Install the Privy Node SDK and viem:

1. Get the vault and wallet addresses

The onchain reads need two addresses: the vault contract address and the wallet address. Get the vault address and chain with the vaultDetails method, which calls the get vault details endpoint. Get the wallet address with the get wallet method.
Store the vault address, caip2, and asset decimals with the vault ID. These values do not change, so your app only needs to fetch them once per vault.

2. Read the position

The wallet’s position is its vault share balance. convertToAssets returns the value of these shares in the underlying asset, including accrued yield. These two reads return the same values as shares_in_vault and assets_in_vault.
The optional blockNumber reads the position at a past block. Step 4 uses it to keep the position and the totals at the same block.

3. Compute the totals from vault events

Every ERC-4626 vault emits a Deposit event for each deposit and a Withdraw event for each withdrawal. Both events include assets, the amount of the underlying asset in the token’s smallest unit.
  • Deposit indexes receiver, the address that receives the vault shares.
  • Withdraw indexes owner, the address whose vault shares are burned.
Filter Deposit events by receiver and Withdraw events by owner, then sum assets. Most RPC providers limit the block range of one eth_getLogs request, so the function below scans the range in chunks.
To get the lifetime totals, scan from the vault’s deployment block to the latest block. A full scan is the simplest option, but its cost grows with the age of the vault. For each new read, step 4 scans only the blocks since the last read.

4. Store a checkpoint and scan new blocks

Store the totals and the last scanned block for each wallet and vault. On each read, scan only the blocks after the checkpoint, and add the new amounts to the stored totals.
For the first read of a wallet, start from an empty checkpoint at the block before the vault’s deployment:
Save the returned checkpoint to your database after each sync. Store the amounts as strings or as a numeric type with enough precision, because they can exceed the safe range of a JavaScript number.

5. Calculate earned yield

Read the position at the checkpoint’s lastScannedBlock. This keeps the position and the totals at the same block. If the position is read at the latest block, a deposit in the unscanned blocks increases assetsInVault before it increases totalDeposited, and the earned yield is too high.
The formula is the same one that the get vault position guide uses with the endpoint fields. All amounts are in the asset’s smallest unit. Divide by 10^decimals before your app shows them to users.

Key integration tips

  1. Read events from the vault address. Use the vault_address from get vault details. For Morpho, this is the Privy fee wrapper vault, not the underlying Morpho vault.
  2. Share transfers are not deposits. If a wallet receives vault shares through an ERC-20 Transfer, no Deposit event names the wallet. The shares count in assets_in_vault, but not in total_deposited. The same applies to shares that the wallet sends away.
  3. Use archive access for past blocks. Reads at a past blockNumber need an RPC node that keeps historical state. Most hosted RPC providers support this.
  4. Check the block range limit. If eth_getLogs fails with a range error, lower MAX_BLOCK_RANGE to your provider’s limit.

Next steps

Earn webhooks

Track Privy Earn deposits and withdrawals in real time.

Get vault details

Retrieve vault-level information like APY, TVL, and available liquidity.
Privy does not control DeFi vaults or underlying protocols. Vault information is provided for reference only and may change or be inaccurate. Earnings are generated from third-party vaults and are not guaranteed. Using vaults involves risk, including loss of funds. These materials are for general information purposes only and are not investment advice or a recommendation or solicitation to engage in any specific transaction. You are responsible for evaluating vaults at your own discretion. Privy does not provide investment, financial, legal, or tax advice.