Overview
Earn mode enables users to deposit into DeFi protocols for yield generation and staking. It supports both pre-integrated protocols (Aave, Morpho) and custom contract integrations with arbitrary calldata.Earn mode includes both deposit and withdrawal tabs. To deep-link users directly into withdrawals, use Withdraw mode.
Quick start
Props
Required
| Prop | Type | Description |
|---|---|---|
apiKey | string | Trails API key |
Destination (optional)
| Prop | Type | Description |
|---|---|---|
to.recipient | string | Protocol contract address |
to.token | string | Token to deposit — symbol or contract address |
to.chain | ChainIdentifier | Protocol chain — name, ID, or viem Chain |
to.defaultToken | string | Default token — user can change |
to.defaultChain | ChainIdentifier | Default chain — user can change |
to.amount | string | number | Fixed deposit amount |
to.calldata | string | ABI-encoded function call to execute after deposit |
Source (optional)
Thefrom shape is a discriminated union on paymentMethod.
Crypto source (paymentMethod is "CONNECTED_WALLET", "EXCHANGE", "CRYPTO_TRANSFER", or omitted):
| Prop | Type | Description |
|---|---|---|
from.token | string | Source ERC-20 token — symbol or contract address |
from.chain | ChainIdentifier | Source chain |
from.amount | string | number | Source amount |
from.walletAddress | string | Source wallet (defaults to connected wallet) |
from.exchange | string | Mesh exchange key (e.g. "coinbase"). EXCHANGE arm only. |
paymentMethod is "CREDIT_DEBIT_CARD"):
| Prop | Type | Description |
|---|---|---|
from.currency | string | ISO 4217 fiat code, e.g. "USD", "EUR", "GBP" |
from.amount | string | number | Fiat amount to charge |
Payment method (optional)
paymentMethod controls how the user sources funds:
| Value | Method |
|---|---|
"CONNECTED_WALLET" | Connected wallet (default) |
"CRYPTO_TRANSFER" | QR code / address deposit |
"CREDIT_DEBIT_CARD" | Fiat on-ramp |
"EXCHANGE" | CEX transfer |
Lifecycle callbacks
| Callback | Signature | When it fires |
|---|---|---|
onEarnStart | ({ sessionId }) => void | User begins the deposit flow |
onEarnSuccess | ({ sessionId }) => void | Deposit completes successfully |
onEarnError | ({ sessionId, error }) => void | Deposit encounters an error |
Examples
Protocol selection — user picks everything
Fixed amount protocol deposit
Deposit 1 USDC into Aave V3 on Arbitrum:ERC-4626 vault with dynamic amount
UseTRAILS_ROUTER_PLACEHOLDER_AMOUNT when the deposit amount is a parameter and the user selects it:
Use
TRAILS_ROUTER_PLACEHOLDER_AMOUNT when:- Deposit amount is a function parameter
- User selects the deposit amount
- Amount needs to reflect post-swap/bridge output
depositAll()).Composable actions (pre-integrated protocols)
For Aave, Compound, Morpho, Yearn, and other natively supported protocols, use composable actions instead of manual calldata encoding:useEarnMarkets to discover available market IDs. See Markets and Providers.
Calldata reference
When to use TRAILS_ROUTER_PLACEHOLDER_AMOUNT
TRAILS_ROUTER_PLACEHOLDER_AMOUNT is uint256.max internally. Trails replaces it with the actual output amount at execution time.
See also
- Earn use cases — DeFi integration patterns
- Composable actions — programmatic protocol deposits
- Fund mode — similar input-driven flow
- Configuration reference — full prop list