<!-- tempo-docs-context -->
> Source: [/docs/earn/integrate](https://tempo.xyz/developers/docs/earn/integrate.md)
> Section: [Earn](https://tempo.xyz/developers/docs/earn.md). Choose a vault, deposit stablecoins, read positions, and withdraw. Earn is in beta; see the introduction for access.
> [Documentation index](https://tempo.xyz/developers/llms.txt) · [Docs skill](https://tempo.xyz/developers/SKILL.md)

> Tempo MCP: Use `search`, `find_pages`, `read_page`, and `code` at `https://mcp.tempo.xyz` for Tempo and related documentation.
> If an indexed page is missing or reflects an older site, read this site’s [documentation index](https://tempo.xyz/developers/llms.txt) and Markdown pages directly.

<span id="deposit-funds" />

# Deposit

Deposit from a funded Tempo account into a [vault](https://tempo.xyz/developers/docs/earn/vaults) that accepts its stablecoin. Approve and submit the deposit with your account’s signer, then read the resulting shares and asset value.

<span id="select-a-vault" />

<span id="connect-deposits" />

<span id="display-the-position" />

<span id="handle-withdrawals" />

<span id="build-the-earning-balance" />

## Try a deposit

Create a passkey test account, get faucet funds, and deposit into a verified pathUSD vault on Moderato testnet. The vault and network are selected for you, and the amount starts at 1 pathUSD. The demo checks the live deployment before enabling deposits. You can withdraw the test position afterward.

In the interactive web page, create a testnet passkey account, get test pathUSD from the faucet, choose a deposit amount (1 pathUSD by default), approve it for the verified vault, and confirm a deposit. Inspect the resulting shares and receipt, then withdraw the test position. Every transaction requires your confirmation and uses Moderato testnet.

## Deposit into a vault

Use the [testnet setup](https://tempo.xyz/developers/docs/earn/example) for your tool: CLI variables and `minimum_output`, a Viem `client`, or Wagmi imports and a connected React component. Every version deposits 1 pathUSD into the same vault. Keep the signer and vault on the same network.

::::steps
### Check the asset and access requirements

Save the vault address and network together. Match the account's token to the accepted asset and confirm the account's eligibility. Read `capabilities` and `state.depositsPaused` before enabling the deposit action.

<span id="prepare-the-deposit" />

### Approve funds

Approve the deposit amount so you can simulate the vault call. Show the asset, amount, and vault before asking the account to sign.

:::code-group
```ts [Viem]
await client.token.approveSync({
  token: assetToken,
  spender: vault,
  amount: assetAmount,
})
```

```bash [CLI (Cast)]
cast erc20 approve "$ASSET_TOKEN" "$VAULT" "$ASSET_AMOUNT" \
  --rpc-url "$TEMPO_RPC_URL" --account "$KEYSTORE" \
  --tempo.fee-token "$ASSET_TOKEN"
```

```tsx [Wagmi]
const approval = Hooks.token.useApproveSync({
  mutation: { onSuccess: () => setApproved(true) },
})
const approve = () => approval.mutateAsync({
  token: assetToken, spender: vault, amount: assetAmount,
})
```
:::

After approval confirms, simulate with a positive minimum to obtain the expected shares. The signed deposit below accepts at most 0.5% less than this quote. `Actions`, `Abis`, and `EarnShares` come from `viem/tempo`.

:::code-group
```ts [Viem]
const { result: quotedShares } = await Actions.earn.deposit.simulate(client, {
  vault,
  assetAmount,
  shareAmountMin: 1n,
})
const shareAmountMin = EarnShares.minimumOutput(quotedShares, 50)
```

```bash [CLI (Cast)]
QUOTED_SHARES=$(cast call "$VAULT" \
  'deposit(uint256,address,uint256)(uint256)' \
  "$ASSET_AMOUNT" "$ACCOUNT" 1 --from "$ACCOUNT" \
  --rpc-url "$TEMPO_RPC_URL" --json | \
  python3 -c 'import json,sys; print(json.load(sys.stdin)[0])')
MIN_SHARES=$(minimum_output "$QUOTED_SHARES")
```

```tsx [Wagmi]
const quote = useSimulateContract({
  abi: Abis.earnVault, address: vault, account: address,
  functionName: 'deposit', args: [assetAmount, address, 1n],
  query: { enabled: approved },
})
const shareAmountMin = quote.data
  ? EarnShares.minimumOutput(quote.data.result, 50)
  : undefined
```
:::

Refresh the simulation if the customer waits before signing. In Wagmi, call `quote.refetch()` to refresh and keep the deposit button disabled until a positive quote is available.

A deposit is a contract interaction. Transferring stablecoins directly to the vault address does not establish a position. The Earn read API does not submit deposits or withdrawals.

<span id="submit-and-verify-the-position" />

### Make a deposit

Viem and Wagmi batch the required approval and deposit in one transaction. Cast uses the approval confirmed above. The account receives shares; the positive minimum output bounds execution.

:::code-group
```ts [Viem]
const { receipt, shareAmount } = await client.earn.depositSync({
  vault,
  assetAmount,
  shareAmountMin,
})
```

```bash [CLI (Cast)]
cast send "$VAULT" 'deposit(uint256,address,uint256)' \
  "$ASSET_AMOUNT" "$ACCOUNT" "$MIN_SHARES" \
  --rpc-url "$TEMPO_RPC_URL" --account "$KEYSTORE" \
  --tempo.fee-token "$ASSET_TOKEN"
```

```tsx [Wagmi]
const deposit = useSendCallsSync()
const submitDeposit = async () => {
  if (!shareAmountMin) return
  const calls = Actions.earn.deposit.calls({
    vault, assetToken, assetAmount,
    recipient: address, shareAmountMin,
  })
  return deposit.mutateAsync({ calls, forceAtomic: true })
}
```
:::

Confirm the receipt succeeded and save its transaction hash, deposited amount, and shares received for reconciliation.

### Confirm your position

The API example starts with the same vault and `testnet` network. Replace `address` with your test account’s address; use a matching vault and network for other deposits. Use **Try** to read the position or switch the request’s code language to copy an example.

`GET /v1/earn/vaults/{vaultId}/positions/{address}`

Get account position

[API reference](https://tempo.xyz/developers/docs/api/earn#getearnvaultposition) — request parameters, authentication, and response schema. The examples below use editable sample values.

**cURL**

```bash
curl 'https://api.tempo.xyz/v1/earn/vaults/0x20147491b5701dea880263241c335caca9be326d/positions/0xbe058e1c4df8a4366a387bf595b284246a93039e?chainId=testnet'
```

**TypeScript**

```ts
fetch('https://api.tempo.xyz/v1/earn/vaults/0x20147491b5701dea880263241c335caca9be326d/positions/0xbe058e1c4df8a4366a387bf595b284246a93039e?chainId=testnet')
```

Read `shareBalance` for the shares held and `value` for their current asset value. Do not treat the share count as the same amount of stablecoins.
::::

<span id="show-rates-and-rewards-accurately" />

## Display the earning balance

Follow [Balances and earnings](https://tempo.xyz/developers/docs/earn/balances) to show position value, earnings, and rate measurement windows. Make [withdrawal behavior](https://tempo.xyz/developers/docs/earn/withdraw) visible before accepting the deposit.

## Track private Earn activity

For a [Zone](https://tempo.xyz/developers/docs/zones) integration, check `capabilities.privateRouting` and the vault's configured Zone routes. Zone-routed positions use Zone withdrawals rather than the direct account approval flow.

Use `GET /v1/earn/transactions/{senderTag}` to track private Earn execution and return delivery. Show returned funds as available once delivery completes. See the [Earn transaction reference](https://tempo.xyz/developers/docs/api/earn#getearntransaction) for the status fields.

Account position listing supports private Zones; earnings data is currently unavailable for those positions.

<span id="earn-api-operations" />

## Read Earn data

The [Earn API](https://tempo.xyz/developers/docs/api/earn) covers vault discovery, positions, share prices, and earnings. Keep `chainId` consistent across discovery, transactions, and reads.
