Skip to main content

Ship a yield product in weeks, not quarters.

Enso Earn is the Yield-as-a-Service layer for wallets, fintechs, custodians, and apps. Production-grade integrations to the venues your risk team already trusts — Aave, Morpho, Maple, Pendle, Ondo, EtherFi — reachable from any chain your users already hold capital on. One integration. No five-vendor stitch-up. Who it’s for: wallets turning idle balances into positions, fintechs and neobanks launching stablecoin yield, custodians serving institutional clients, and asset managers distributing strategies — teams that want to own the customer relationship while outsourcing the protocol integration burden.

Curated coverage

Yield from the protocols you’d actually approve — lending, vaults, RWAs, structured yield, and liquid staking that already pass institutional risk and policy review. Not a long tail of unaudited markets.

Cross-chain by default

Reach yield wherever the user already holds capital. A user holding USDC on Base can enter a vault on Ethereum in a single signature — the chain becomes an implementation detail, not a dead end.

Partner-controlled monetization

Earn opens a partner-owned revenue line. Layer your fee model on top of execution so your economics sit alongside the deposit, in the same flow your team controls.

Why Now

Regulation forces yield out of the core product. The GENIUS Act and MiCA prevent fintechs and neobanks from paying yield natively on stablecoins. Yield has to ship as a distinct, DeFi-routed product surface — and the teams winning the next cycle are buying the rails, not building them. Custody, execution, security, sourcing, audits, and reporting make up a stack that is too deep to assemble vendor-by-vendor before competitors ship. Enso Earn is execution infrastructure, not a parallel compliance stack. KYC, eligibility, region rules, signing policy, and approval workflow stay inside the systems your risk team already operates — Enso plugs into them rather than asking you to migrate.
Enso Earn is the pattern for adding yield inside your application. A first Earn product does not need the full Enso API surface. It needs a curated list of yield destinations, the user’s current balances, a route into the selected position, your fee on top of the deposit, and a refreshed balance view after the transaction lands. Execution safety is built in — every route is simulated and protected by Enso before it is returned. Use this guide when you want to build an Earn tab, yield marketplace, wallet yield flow, or simple position migrator.

Core Endpoints

The Earn path is built from these endpoints:
StepEndpointUse it for
1GET /v1/tokensBuild the approved yield catalog. This is where APY, TVL, protocol, underlying assets, decimals, symbols, names, and logos come from.
2GET /v1/wallet/balancesShow the user’s current assets and current DeFi positions before and after execution.
3POST /v1/shortcuts/routeQuote and build the signer-ready transaction from the user’s input asset or current position into the selected Earn destination. Pass fee + feeReceiver here to monetize the deposit.
4GET /v1/wallet/approveRequired only when the user is spending an ERC-20 through routingStrategy: "router" and allowance is not already high enough.
Every route Enso returns is already simulated and protected under the hood, so there is no separate safety call to add to this flow. Enso Quoter is available as a standalone API when you want to independently simulate or validate transactions generated outside Enso (for example, a payload from another aggregator before you sign it).
APY is not a separate endpoint. Read it from GET /v1/tokens. New balances are not returned by the route endpoint. After the transaction confirms, call GET /v1/wallet/balances again.

Build Flow

End-To-End Example

This is the full Earn loop in one place: build the catalog, read the user’s balances, route into the selected destination with your fee applied, approve if needed, submit the returned transaction, and refresh balances. The route is simulated and protected by Enso before it is returned — no extra safety call is required.
import { EnsoClient } from "@ensofinance/sdk";

const enso = new EnsoClient({ apiKey: process.env.ENSO_API_KEY });

const chainId = 8453;
const user = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045";
const sourceToken = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"; // USDC on Base
const earnDestination = "0x4e65fe4dba92790696d040ac24aa414708f5c0ab"; // Aave Base USDC
const amountIn = "100000000"; // 100 USDC
const feeReceiver = "0x220866B1A2219f40e72f5c628B65D54268cA3A9D"; // your revenue address

const catalog = await enso.getTokenData({
  chainId,
  type: "defi",
  includeMetadata: true,
  includeUnderlying: true,
  tvlFrom: 1_000_000,
});

const startingBalances = await enso.getBalances({
  chainId,
  eoaAddress: user,
  useEoa: true,
});

const route = await enso.getRouteData({
  chainId,
  fromAddress: user,
  receiver: user,
  spender: user,
  routingStrategy: "router",
  tokenIn: [sourceToken],
  tokenOut: [earnDestination],
  amountIn: [amountIn],
  slippage: "50",
  fee: ["20"], // 0.20% partner fee, in basis points
  feeReceiver, // required when fee is set
  referralCode: "EARN_BASE_USDC", // attribution for on-chain tracking
});

// Replace this with your allowance check. Native gas tokens do not need approval.
if (await needsApproval({ chainId, owner: user, token: sourceToken, amount: amountIn })) {
  const approval = await enso.getApprovalData({
    chainId,
    fromAddress: user,
    routingStrategy: "router",
    tokenAddress: sourceToken,
    amount: amountIn,
  });

  await wallet.sendTransaction(approval.tx);
}

await wallet.sendTransaction(route.tx);

const updatedBalances = await enso.getBalances({
  chainId,
  eoaAddress: user,
  useEoa: true,
});

const destinationMetadata = catalog.data.find((token) => token.address === earnDestination);
Use the first balance snapshot for the review screen and the second balance snapshot for the completed state.

UI Fields

UI momentShow thisSource
CatalogAPY, base APY, reward APY, TVL, protocol, chain, underlying assets, token symbol, decimals, logoGET /v1/tokens
User starting pointSpendable source assets and existing DeFi positionsGET /v1/wallet/balances
Route reviewExpected output, minimum output, estimated gas, price impact, selected route, your fee amount, approval requirementPOST /v1/shortcuts/route and conditional GET /v1/wallet/approve
SigningThe returned approval tx if needed, then the returned route tx (already simulated by Enso)Approval and route responses
Completed stateNew Earn position, remaining source balance, APY, TVL, protocol, underlying assets, logoRefreshed GET /v1/wallet/balances plus GET /v1/tokens

1. Build The Yield Catalog

Use GET /v1/tokens to fetch the positions your product is allowed to show. For a normal Earn shelf, filter by chain, token type, APY, TVL, approved protocol, and underlying asset:
import { EnsoClient } from "@ensofinance/sdk";

const enso = new EnsoClient({ apiKey: process.env.ENSO_API_KEY });

const catalog = await enso.getTokenData({
  chainId: 1,
  type: "defi",
  protocolSlug: "yearn-v2",
  apyFrom: 3,
  tvlFrom: 1_000_000,
  includeMetadata: true,
  includeUnderlying: true,
});

const approvedDestinations = catalog.data.filter((position) => {
  return position.apy && position.tvl && position.symbol;
});
Filtering by protocolSlug, apyFrom, and tvlFrom is how you curate: ship only the destinations your risk and policy review already approved, rather than the full long tail. APY is point-in-time as of the response — surface it as a current rate, not a guarantee, and refetch on display. For a yield migrator, start from the source position’s exact underlying assets and show comparable destinations:
const targets = await enso.getTokenData({
  chainId: sourcePosition.chainId,
  type: "defi",
  underlyingTokensExact: sourcePosition.underlyingTokens.map((token) => token.address),
  includeMetadata: true,
  includeUnderlying: true,
});

const alternatives = targets.data
  .filter((position) => position.address !== sourcePosition.address && position.apy)
  .sort((a, b) => b.apy - a.apy);
Show these fields in the catalog:
  • name, symbol, logosUri, decimals
  • project, protocolSlug, chainId
  • underlyingTokens
  • apy, apyBase, apyReward
  • tvl
  • address

2. Show User Balances And Current Positions

Use GET /v1/wallet/balances for the user’s starting point.
const balances = await enso.getBalances({
  chainId: 1,
  eoaAddress: user,
  useEoa: true,
});
The balance response includes token address, amount, decimals, price, name, symbol, and logo. Use it to show deposit sources and existing positions. To turn balances into current yield positions, look those balance token addresses up with GET /v1/tokens and type=defi:
const balanceTokenAddresses = balances
  .filter((balance) => Number(balance.price) > 0)
  .map((balance) => balance.token);

const positionTokens = await enso.getTokenData({
  chainId: 1,
  address: balanceTokenAddresses,
  type: "defi",
  includeMetadata: true,
  includeUnderlying: true,
});

const currentPositions = balances
  .map((balance) => ({
    balance,
    token: positionTokens.data.find((token) => token.address === balance.token),
  }))
  .filter((position) => position.token);

3. Quote The Earn Route

Use POST /v1/shortcuts/route when the user chooses a source asset and one final Earn destination. Route handles swaps, wraps, deposits, redeems, and position migrations underneath.
const route = await enso.getRouteData({
  chainId: 8453,
  fromAddress: user,
  receiver: user,
  spender: user,
  routingStrategy: "router",
  tokenIn: ["0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"], // USDC on Base
  tokenOut: ["0x4e65fe4dba92790696d040ac24aa414708f5c0ab"], // Aave Base USDC
  amountIn: ["100000000"], // 100 USDC
  slippage: "50",
});
Show these route response fields on the review screen:
  • amountOut: expected destination position amount.
  • minAmountOut: the slippage-protected minimum output.
  • gas: estimated gas.
  • priceImpact: estimated price impact.
  • feeAmount: your partner fee charged on this deposit (when fee is set — see below).
  • route: the path Enso selected.
  • tx: the transaction the user signs.
Always submit the returned tx as-is, including the returned tx.to.

4. Monetize The Deposit

Earn opens a partner-owned revenue line. Set your fee directly on the route call — it is collected as part of the same transaction, so your economics sit alongside the deposit rather than in a separate wrapper.
ParameterTypeDescription
feestring[]Fee in basis points (1 bp = 0.01%, 100 bps = 1%), one value per amountIn.
feeReceiverstringAddress that receives the collected fee. Required when fee is set.
referralCodestringTags the transaction for on-chain attribution tracking (emits a ShortcutExecuted event).
const route = await enso.getRouteData({
  chainId: 8453,
  fromAddress: user,
  receiver: user,
  spender: user,
  routingStrategy: "router",
  tokenIn: ["0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"], // USDC on Base
  tokenOut: ["0x4e65fe4dba92790696d040ac24aa414708f5c0ab"], // Aave Base USDC
  amountIn: ["100000000"], // 100 USDC
  slippage: "50",
  fee: ["20"], // 0.20% partner fee
  feeReceiver: "0x220866B1A2219f40e72f5c628B65D54268cA3A9D",
  referralCode: "EARN_BASE_USDC",
});
The response returns feeAmount (your fee) and ensoFeeAmount (Enso’s platform fee) so you can show the user an itemized breakdown. For multi-step destination-chain logic, you can instead apply a fee action inside a Bundle. See Request Tracking for how to read referralCode attribution from on-chain events.

Execution Safety Is Built In

You do not need to add a separate safety step. Every route Enso returns is simulated and protected before it reaches you: outputs are quoted with deterministic slippage bounds (minAmountOut), bundles settle atomically, and revert protection stops a partially executed workflow from stranding funds. Submit the returned route.tx as-is — the amountOut, minAmountOut, and priceImpact on the response are what you surface to the user on the review screen.
Enso Quoter is the same simulation-and-validation engine exposed as a standalone API for transactions generated outside Enso — for example, validating a payload from another aggregator before signing. For an Enso-routed Earn deposit it already runs in the background, so there is nothing extra to call. See Enso Quoter if you also need to verify third-party transactions.

5. Approve If Needed

If the source token is an ERC-20 and the route uses routingStrategy: "router", the user must approve the Enso spender before signing the route transaction. You can use the approval endpoint:
const approval = await enso.getApprovalData({
  chainId: 8453,
  fromAddress: user,
  routingStrategy: "router",
  tokenAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
  amount: "100000000",
});

await wallet.sendTransaction(approval.tx);
Then send the route transaction:
await wallet.sendTransaction(route.tx);
If the source token is native gas token, approval is not needed.

6. Show The New Balances

After the route transaction confirms, call balances again:
const updatedBalances = await enso.getBalances({
  chainId: 8453,
  eoaAddress: user,
  useEoa: true,
});
Compare updatedBalances with the balance snapshot from before execution:
  • source asset decreased
  • destination position increased
  • any small dust or gas changes are visible
Use the destination token metadata from GET /v1/tokens to show the new position’s APY, TVL, protocol, underlying assets, and logo.

What You Can Build

Earn-shaped journeys from the full Use Cases library:

Embedded Yield

The productized Earn surface for wallets, fintechs, and allocation products.

Cross-Chain Zap To Yield

Take a source-chain asset into a destination-chain position in one signature.

Yield Migrator

Compare destinations and move users from one position into a better one.

Deposit & Withdraw

Accept any token in and route the full exit path back out.

Stablecoin Issuers

Route minting, distribution, and yield for stablecoin and RWA issuers.

Wallet Zap & Earn

Turn idle wallet balances into approved yield positions in-app.

API & Safety Reference

Route API

Quote and execute direct entry into Earn destinations.

Balances

Show user assets and current DeFi positions before and after routing.

Protocol Data

Use token data for APY, TVL, metadata, and underlying assets.

Monetization & Attribution

Apply partner fees and read referral attribution from on-chain events.

Enso Quoter

Built into every Enso route — and available standalone to validate transactions generated outside Enso.

Updated