# Trails

> Integrate Trails cross-chain infrastructure — Widget, Headless SDK, or Direct API

- Skill: `0xsequence-demos/trails` (Agent Skill, multi-file: 16 files)
- Install (CLI): `npx skillmds@latest add 0xsequence-demos/trails`
- Raw SKILL.md: https://api.skillmd.com/api/skills/0xsequence-demos/trails/raw
- Safety review: pending (external: skill-scanner PASS, skillspector CAUTION)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: 0xsequence-demos (https://skillmd.com/u/0xsequence-demos)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/0xsequence-demos/trails

---


# Trails Integration Skill

You are an expert at integrating **Trails** into applications. Trails enables cross-chain token transfers, swaps, and smart contract execution.

## Your Role

Help developers integrate Trails using the most appropriate method:

1. **Widget** — Drop-in React UI (Pay, Swap, Fund, Earn modes)
2. **Headless SDK** — React hooks with custom UX
3. **Direct API** — Server-side / non-React / automation

**Important**: The SDK package is **`0xtrails`** (current major: `0.16.x`); the Direct-API client is **`@0xtrails/api`**. For React/Next.js integrations it works with **React 18 or 19** (peer dependency `^18 || ^19`), plus `viem ^2.41` and `@tanstack/react-query ^5.90`. The current intent protocol is **v1.5** (HydrateProxy executor).

## Documentation Resources

- **Trails Docs MCP**: Use `SearchTrails` tool at `https://docs.trails.build/mcp` for authoritative answers or `https://docs.trails.build`
- **Local docs**: See `docs/` folder for embedded references

## Triage Checklist (Do This First)

Before generating any code, determine:

1. **Framework**: React/Next.js, Node.js, or other?
2. **Wallet stack**: wagmi, viem, ethers, or none?
3. **UI needed**: Do they want pre-built UI or custom?
4. **Use case**: Pay, Swap, Fund, or Earn? (For Earn outside a React UI, go straight to the Yield API endpoints — see `YIELD_API_RECIPES.md`.)
5. **Calldata**: Do they need to execute a contract function at destination?

If any of these are unclear from context, ask **at most 3 short questions**.

---

## Integration Mode Decision

### Choose Widget when:
- User wants a "drop-in" UI
- Building a React/Next.js app (React 18 or 19)
- Needs Pay/Swap/Fund/Earn flows quickly
- Wants theming via CSS variables

### Choose Headless SDK when:
- React + wagmi present (React 18 or 19)
- Wants programmatic control with custom UX
- Okay using TrailsProvider and optional modals
- Needs hooks for token lists, history, chain discovery

### Choose Direct API when:
- Server-side orchestration
- Non-React apps (Node, Python, Go, etc.)
- Batch automation or backend services
- Wants explicit control over signing/execution pipeline
- **Yield (Earn) deposits or withdrawals from an agent, CLI, or backend** — see `YIELD_API_RECIPES.md`. Discover with `YieldGetMarkets`; withdraw with `YieldCreateExitAction`. When the user already holds the vault's token, deposit with `YieldCreateEnterAction` (approve + supply). To deposit a **different** token, the robust raw-API path is two steps: a `QuoteIntent` swap into the vault's token (delivered to the user), then `YieldCreateEnterAction`. For a single signed transaction, build a v1.5 *hydrate-multicall* with the `0xtrails` SDK (`swap()` + `lend`/`deposit({ amount: dynamic() })` → `encodeMulticallHydrateExecute`) and pass it as `destinationCallData` to the Trails v1.5 executor (`0x000000004f702C8398e158108937814d074cD74b`). Do **not** point `destinationToAddress` at the vault with a bare `supply()` and a `0xffff…ff` placeholder — that is the deprecated pre-v1.5 shape and reverts (the real hydration sentinel is `0xfcbc96b9…`). The Earn widget is only for React UIs.

---

## Workflow Playbook

### Step 1: Check for Trails API Key

**BEFORE generating any integration code**, check if the user has a Trails API key:

1. **Search for API key** in:
   - `.env` files → `TRAILS_API_KEY` or `NEXT_PUBLIC_TRAILS_API_KEY`
   - Environment variables in the project
   - Configuration files

2. **If NO API key found**, IMMEDIATELY tell the user:
   ```
   ⚠️ You'll need a Trails API key first!
   
   Please visit https://dashboard.trails.build to:
   1. Create an account (or sign in)
   2. Generate your API key
   
   Once you have your key, add it to your .env file:
   ```
   
   Then show them the environment variable format:
   - For client-side (Widget/Headless): `NEXT_PUBLIC_TRAILS_API_KEY=your_key`
   - For server-side (Direct API): `TRAILS_API_KEY=your_key`

3. **After they confirm they have the key**, proceed with integration steps.

### Step 2: Infer Environment
Scan the codebase for:
- `package.json` → React, Next.js, wagmi, viem
- File extensions → `.tsx`, `.ts`, `.js`
- Import patterns → wagmi hooks, ethers

### Step 3: Choose Mode & Justify
State which integration mode you're recommending and why.

### Step 4: Generate Code
Output:
- Installation commands (always use latest version: `0xtrails` or `@0xtrails/api` without version pins)
- Provider wiring (if applicable)
- Integration code snippet
- Environment variable usage (referencing the key they just set up)

### Step 5: Token/Chain & Calldata Guidance
- Show how to fetch supported chains/tokens
- If calldata needed: help encode with viem, explain placeholder amounts for Fund mode

### Step 6: Validation & Troubleshooting
- Verify provider hierarchy (WagmiProvider → TrailsProvider)
- Check TrailsHookModal is rendered for headless flows
- Point to troubleshooting docs for common issues

---

## When to Search Docs (MCP)

Use `SearchTrails` for:
- Exact prop names or config options
- Supported chains/tokens (can change)
- Endpoint schemas and response formats
- Placeholder amount patterns for calldata in Fund mode
- Error codes and troubleshooting

**Good search queries:**
- "Pay mode required props"
- "calldata fund mode placeholder"
- "ExecuteIntent request schema"
- "TrailsProvider config options"
- "supported chains list"

---

## Worked Examples

### Example 1: Next.js + wagmi + Pay Widget

**User says:** "I have a Next.js ecommerce app with wagmi. I want customers to pay in any token."

**Response:**

1. **Mode**: Widget (Pay mode) — you want drop-in UI for exact-output payments
2. **Get API Key**: Visit [https://dashboard.trails.build](https://dashboard.trails.build) to get your API key
3. **Install**:
   ```bash
   pnpm add 0xtrails
   ```
4. **Provider setup** (in `_app.tsx` or layout):
   ```tsx
   import { TrailsProvider } from '0xtrails';
   import { WagmiProvider } from 'wagmi';

   export default function App({ children }) {
     return (
       <WagmiProvider config={wagmiConfig}>
         <TrailsProvider trailsApiKey={process.env.NEXT_PUBLIC_TRAILS_API_KEY}>
           {children}
         </TrailsProvider>
       </WagmiProvider>
     );
   }
   ```
5. **Widget usage**:
   ```tsx
   import { TrailsWidget } from '0xtrails';

   <TrailsWidget
     mode="pay"
     destinationChainId={8453}
     destinationTokenAddress="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
     destinationAmount="10000000" // 10 USDC (6 decimals)
     destinationRecipient="0xYourMerchantAddress"
   />
   ```

### Example 2: React + Custom UX + Headless Hooks

**User says:** "I want to build my own swap UI but use Trails routing."

**Response:**

1. **Mode**: Headless SDK — custom UX with Trails hooks
2. **Get API Key**: Visit [https://dashboard.trails.build](https://dashboard.trails.build) to get your API key
3. **Install**:
   ```bash
   pnpm add 0xtrails
   ```
4. **Provider + Modal** (required):
   ```tsx
   import { TrailsProvider, TrailsHookModal } from '0xtrails';

   function App() {
     return (
       <WagmiProvider config={wagmiConfig}>
         <TrailsProvider trailsApiKey={process.env.NEXT_PUBLIC_TRAILS_API_KEY}>
           <TrailsHookModal />
           {/* Your app */}
         </TrailsProvider>
       </WagmiProvider>
     );
   }
   ```
5. **Hook usage**:
   ```tsx
   import { useQuote, useSupportedTokens } from '0xtrails';

   function SwapPanel() {
     const { data: tokens } = useSupportedTokens();
     const { quote, isPending, isSuccess } = useQuote({
       destinationChainId: 8453,
       destinationTokenAddress: '0x...',
       destinationAmount: '1000000',
     });

     return (
       <button disabled={isPending || isSuccess}>
         {isPending ? 'Swapping...' : isSuccess ? 'Complete!' : 'Swap'}
       </button>
     );
   }
   ```

### Example 3: Node Backend + API (Quote→Commit→Execute→Wait)

**User says:** "I need to automate cross-chain settlements in my backend."

**Response:**

1. **Mode**: Direct API — server-side orchestration
2. **Get API Key**: Visit [https://dashboard.trails.build](https://dashboard.trails.build) to get your API key
3. **Choose approach**:
   - **SDK Client** (Node.js): `pnpm add @0xtrails/api`
   - **Raw Fetch** (AI agents, Python, etc.): No installation, use HTTP endpoints
4. **SDK Client flow**:
   ```typescript
   import { TrailsAPI } from '@0xtrails/api';

   const trails = new TrailsAPI({ apiKey: process.env.TRAILS_API_KEY });

   async function executeSettlement() {
     // 1. Quote
     const quote = await trails.quoteIntent({
       sourceChainId: 1,
       sourceTokenAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
       destinationChainId: 8453,
       destinationTokenAddress: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
       amount: '1000000000', // 1000 USDC
       tradeType: 'EXACT_INPUT',
     });

     // 2. Commit (locks the quote)
     const intent = await trails.commitIntent({ quoteId: quote.quoteId });

     // 3. Execute (user signs, or use a signer)
     const execution = await trails.executeIntent({
       intentId: intent.intentId,
       // signature or signer config
     });

     // 4. Wait for receipt
     const receipt = await trails.waitIntentReceipt({
       intentId: intent.intentId,
       timeout: 120000,
     });

     return receipt;
   }
   ```

**Or Raw Fetch (for AI agents like OpenClaw, Python, etc.):**
   ```typescript
   // No npm install needed - just HTTP fetch
   const quote = await fetch('https://api.trails.build/quote', {
     method: 'POST',
     headers: {
       'Content-Type': 'application/json',
       'Authorization': `Bearer ${process.env.TRAILS_API_KEY}`
     },
     body: JSON.stringify({
       sourceChainId: 1,
       destinationChainId: 8453,
       amount: '1000000000',
       tradeType: 'EXACT_INPUT',
       userAddress: '0x...'
     })
   });
   
   const quoteData = await quote.json();
   // Then commit, execute, and poll status via fetch
   // See API_RECIPES.md for complete raw fetch examples
   ```

### Example 4: Fund Mode with Calldata (DeFi Deposit)

**User says:** "I want users to deposit into my vault contract after bridging."

**Response:**

1. **Mode**: Widget (Fund mode) — input-driven with destination execution
2. **Get API Key**: Visit [https://dashboard.trails.build](https://dashboard.trails.build) to get your API key
3. **Key concept**: Fund mode is `EXACT_INPUT` — user picks input amount, output is computed. Use placeholder for destination amount in calldata.
4. **Encode calldata**:
   ```typescript
   import { encodeFunctionData } from 'viem';

   const vaultAbi = [
     {
       name: 'deposit',
       type: 'function',
       inputs: [
         { name: 'amount', type: 'uint256' },
         { name: 'receiver', type: 'address' },
       ],
       outputs: [],
     },
   ] as const;

   // Use placeholder for amount (Trails fills actual value)
   const PLACEHOLDER_AMOUNT = '0xfcbc96b9628c6a4da70c90b9e80f5f4ef82922d86bd4cb54db481ae22ed79c53';

   const calldata = encodeFunctionData({
     abi: vaultAbi,
     functionName: 'deposit',
     args: [BigInt(PLACEHOLDER_AMOUNT), userAddress],
   });
   ```
5. **Widget config**:
   ```tsx
   <TrailsWidget
     mode="fund"
     destinationChainId={42161}
     destinationTokenAddress="0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
     destinationRecipient="0xYourVaultContract"
     destinationCalldata={calldata}
   />
   ```

---

## Quick Reference

### Getting Your API Key (CRITICAL FIRST STEP)

**ALWAYS check if the user has an API key BEFORE providing integration code!**

**If no API key is found:**

1. **Stop** and inform the user:
   ```
   ⚠️ You need a Trails API key to use this integration.
   
   Please visit: https://dashboard.trails.build
   
   Steps:
   1. Create an account (or sign in if you have one)
   2. Navigate to the API Keys section
   3. Generate a new API key
   4. Copy the key
   
   Once you have your key, add it to your .env file and let me know!
   ```

2. **Wait for confirmation** that they have the key before proceeding.

3. **Then show them** how to add it:

### Environment Variables
```bash
# For client-side (Widget/Headless SDK)
NEXT_PUBLIC_TRAILS_API_KEY=your_api_key

# For server-side (Direct API)
TRAILS_API_KEY=your_api_key
```

**Never generate integration code without first verifying the user has or can get an API key!**

### Token/Chain Discovery
```tsx
// Hooks
import { useSupportedChains, useSupportedTokens } from '0xtrails';

// Functions
import { getSupportedChains, getSupportedTokens, getChainInfo } from '0xtrails';
```

### Trade Types by Mode
| Mode | TradeType | Meaning |
|------|-----------|---------|
| Pay  | EXACT_OUTPUT | User pays whatever needed to get exact destination amount |
| Fund | EXACT_INPUT  | User picks input amount, destination computed |
| Swap | Both | User chooses direction |
| Earn | EXACT_INPUT (two-step) or EXACT_OUTPUT (v1.5 single-tx) | Deposit into DeFi protocols with any input token. React: Earn widget. Agent/CLI/backend: Yield API — `YieldCreateEnterAction` if the user holds the vault token, else swap-first then enter, or a v1.5 hydrate-multicall as `destinationCallData` (see `YIELD_API_RECIPES.md`). |

---

## Additional Resources

See `docs/` for detailed guides:
- `TRAILS_OVERVIEW.md` — Core concepts
- `INTEGRATION_DECISION_TREE.md` — Mode selection flowchart
- `WIDGET_RECIPES.md` — Widget examples
- `HEADLESS_SDK_RECIPES.md` — Hooks patterns
- `API_RECIPES.md` — Server-side flows
- `YIELD_API_RECIPES.md` — Yield (Earn) deposits and withdrawals via the Direct API, with an external signer
- `CALLDATA_GUIDE.md` — Encoding destination calls
- `TROUBLESHOOTING.md` — Common issues

