Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.polygon.technology/llms.txt

Use this file to discover all available pages before exploring further.

Trails lets you compose multiple onchain operations: bridge, swap, deposit, stake, or any contract call, into a single user-facing transaction. The user approves once. Trails handles routing, execution, and gas across every step. This is the foundation for any flow where funds need to move and land in a specific protocol state: a yield vault, a liquidity position, a staking contract, a cross-chain swap. The source chain, token, and amount are flexible. The destination action is whatever your protocol requires.

How it works

User approves once
  → Trails quotes the full route
      → Funds bridge and swap to the destination chain and token
          → Trails executes typed destination actions from the intent wallet
              → User lands in the desired protocol state
Composable actions describe the destination steps with typed builders such as deposit, lend, swap, and assertCondition. Amounts are human-readable decimal strings, so "100" means 100 USDC when the selected token is USDC.

Composing actions

The example below routes funds to Polygon USDC, lends 10 USDC into an Aave USDC market, swaps the remaining USDC to USDT, then deposits the USDT into a Morpho vault. Use useEarnMarkets to discover live marketId values for Morpho, Aave, and other supported earn providers.
import { useQuote, dynamic, lend, swap, deposit } from "0xtrails";

const aaveUsdcMarketId = "polygon-usdc-aave-v3-lending";
const morphoUsdtVaultId = "polygon-usdt-bbqusdt0-0xb7c9988d3922f25a336a469f3bb26ca61fe79e24-4626-vault";

export function ComposedYieldButton() {

  const userWalletAddress = "0x..."

  const { send, isLoadingQuote, quoteError } = useQuote({
    from: { chain: "base", token: "USDC", amount: "100" },
    to: { chain: "polygon", token: "USDC" },
    actions: [
      lend({
        marketId: aaveUsdcMarketId,
        amount: "10"
      }),
      swap({
        tokenIn: "USDC",
        tokenOut: "USDT",
        amountIn: dynamic(),
        fee: "0.3",
      }),
      deposit({
        marketId: morphoUsdtVaultId,
        amount: dynamic()
      }),
    ],
    onStatusUpdate: (states) => console.log("Intent status:", states),
  });

  if (isLoadingQuote) return <button disabled>Preparing...</button>;
  if (quoteError) return <p>{quoteError.message}</p>;

  return <button disabled={!send} onClick={() => send?.()}>Execute actions</button>;
}
The user can start on Base, Ethereum, Arbitrum, or another supported chain. Trails handles any required bridge or swap before running the destination actions.

What you can compose

Use typed builders for common money actions:
ActionBuilderNotes
Yield vault depositdeposit({ marketId, amount })ERC-4626-style vaults such as Morpho
Lending supplylend({ marketId, amount })Lending markets such as Aave
Destination swapswap({ tokenIn, tokenOut, amountIn })On-chain swap after funds arrive
Safety checkassertCondition({ erc20Balance })Reverts the whole destination batch if the condition fails
Custom contract callcustom(...) or to.callsEscape hatch for unsupported protocols
Use dynamic() when a later action should consume whatever amount is available at execution time:
import { useQuote, dynamic, swap, lend } from "0xtrails";

const { send } = useQuote({
  from: { chain: "arbitrum", token: "USDC", amount: "100" },
  to: { chain: "polygon", token: "USDC" },
  actions: [
    swap({
      tokenIn: "USDC",
      tokenOut: "USDT",
      amountIn: dynamic(),
      fee: "0.3",
    }),
    lend({
      marketId: "polygon-usdt-aave-v3-lending",
      amount: dynamic(),
    }),
  ],
});

Widget integration

For built-in earn flows, use the Earn mode widget. It gives users a ready-made UI for depositing into supported earn markets:
import { Earn } from "0xtrails/widget";

<Earn
  apiKey="YOUR_API_KEY"
  to={{
    chain: "polygon",
    token: "USDC",
    amount: "100",
  }}
  buttonText="Start earning"
  onEarnSuccess={({ sessionId }) => updateUserState(sessionId)}
/>
For a custom protocol sequence, use useQuote({ actions }) as shown above so your app controls the exact destination actions.

Example: yield accounts

One common use of composable actions is offering savings accounts in a fintech or neobank app. Users deposit USDC into a yield vault. The entire flow (bridge, swap, deposit) happens in a single tap, with no gas, no wallet management, and no protocol knowledge required from the user.

Offer yield accounts to your users

Step-by-step guide: wallet setup, Morpho vault deposit with composable actions, and withdraw flow.

Next steps

Fund from Anywhere

Let users fund your protocol from any token, chain, credit card, or bank account.

Smart Sessions

Automate recurring actions without per-transaction prompts.

Trails API reference

Full endpoint reference for QuoteIntent, CommitIntent, and ExecuteIntent.