This guide explains how to add new leverage tokens to the Seamless Protocol frontend application.
Leverage tokens are configured in src/features/leverage-tokens/leverageTokens.config.ts. Each token requires specific configuration parameters and assets (logos) to be properly displayed in the UI.
First, add a new key to the LeverageTokenKey enum:
export enum LeverageTokenKey {
WSTETH_ETH_2X_MAINNET = 'wsteth-eth-2x-mainnet',
// Add your new token key here
YOUR_NEW_TOKEN = 'your-new-token-key',
}Create logo components for your token's assets in src/components/icons/logos/:
- Create individual logo files (e.g.,
your-token-logo.tsx) - Export them from
src/components/icons/logos/index.ts
Logo Component Template:
import type { SVGProps } from 'react'
import { useId } from 'react'
export function YourTokenLogo({ className, ...props }: SVGProps<SVGSVGElement>) {
const logoId = useId()
return (
<svg
className={className}
fill="none"
preserveAspectRatio="none"
viewBox="0 0 32 32"
role="img"
aria-labelledby={logoId}
{...props}
>
<title id={logoId}>Your Token Logo</title>
{/* Your SVG content here */}
</svg>
)
}Add your token configuration to the leverageTokenConfigs object using the example below:
Here's the complete configuration for WSTETH_ETH_2X_MAINNET as a reference:
[LeverageTokenKey.WSTETH_ETH_2X_MAINNET]: {
// === MANDATORY FIELDS ===
address: '0x10041DFFBE8fB54Ca4Dfa56F2286680EC98A37c3' as Address,
name: 'wstETH / ETH 2x Leverage Token',
symbol: 'WSTETH-ETH-2x',
description: 'wstETH / ETH 2x leverage token that amplifies relative price movements between Wrapped stETH and Wrapped Ether',
decimals: 18,
leverageRatio: 2,
chainId: 1,
chainName: 'Ethereum',
chainLogo: EthereumLogo,
collateralAsset: {
symbol: 'wstETH',
name: 'Wrapped stETH',
address: '0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0' as Address,
decimals: 18,
},
debtAsset: {
symbol: 'WETH',
name: 'Wrapped Ether',
address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' as Address,
decimals: 18,
},
// === OPTIONAL FIELDS ===
supplyCap: 150,
isTestOnly: true, // Optional: Only shows when VITE_INCLUDE_TEST_TOKENS=true
// APY Configuration (optional)
apyConfig: {
aprProvider: {
type: APR_PROVIDERS.LIDO,
// Note: Lido only supports stETH, so no 'id' field needed
},
pointsMultiplier: 2, // Optional: Points multiplier for rewards (defaults to 0 if not provided)
},
swaps: {
debtToCollateral: {
type: 'lifi',
allowBridges: 'none',
},
collateralToDebt: {
type: 'lifi',
allowBridges: 'none',
},
},
relatedResources: {
underlyingPlatforms: [
{
id: 'morpho-lending',
title: 'Morpho Lending Market',
description: 'View the underlying lending market powering this leverage token',
url: 'https://app.morpho.org/base/market/0xfd0895ba253889c243bf59bc4b96fd1e06d68631241383947b04d1c293a0cfea',
icon: Building2,
badge: {
text: 'Primary Market',
color: 'amber' as const,
},
highlight: true,
},
{
id: 'etherfi-protocol',
title: 'Ether.fi Protocol',
description: 'Learn more about the weETH liquid staking token',
url: 'https://ether.fi/',
icon: Globe,
badge: {
text: 'Protocol Info',
color: 'blue' as const,
},
},
],
additionalRewards: [
{
id: 'etherfi-points',
title: 'Ether.fi Points',
description: 'Track your points and rewards from weETH staking activity',
url: 'https://www.ether.fi/app/portfolio',
icon: Coins,
badge: {
text: 'Rewards Program',
color: 'emerald' as const,
},
highlight: true,
},
{
id: 'merkl-rewards',
title: 'Merkl Rewards',
description: 'Additional DeFi rewards and incentive tracking',
// Default goes to dashboard; if connected, deep-link to user page
url: 'https://app.merkl.xyz/users/',
getUrl: ({ address }) =>
address ? `https://app.merkl.xyz/users/${address}` : 'https://app.merkl.xyz/users/',
icon: TrendingUp,
badge: {
text: 'Incentives',
color: 'purple' as const,
},
},
],
},
},The apyConfig section allows you to configure how APY data is calculated and displayed for your leverage token:
apyConfig: {
// APR Provider Configuration
aprProvider?: {
type: APR_PROVIDERS.LIDO | APR_PROVIDERS.ETHERFI | APR_PROVIDERS.DEFI_LLAMA,
id?: string // Required only for DeFi Llama (protocol ID)
},
// Borrow APR Provider Configuration
borrowAprProvider?: {
type: BORROW_APR_PROVIDERS.MORPHO,
},
// Rewards Provider Configuration
rewardsProvider?: {
type: REWARDS_PROVIDERS.MERKL,
},
// Points Multiplier Configuration
pointsMultiplier?: number // Points multiplier for rewards calculation
}Lido APR Provider:
- Only supports stETH tokens
- No
idfield needed - automatically uses stETH - Fetches APR data from Lido's API:
https://eth-api.lido.fi/v1/protocol/steth/apr/sma - Uses 24-hour average for current APR values
Ether.fi APR Provider:
- Supports weETH tokens
- No
idfield needed - automatically uses weETH - Fetches APR data from Ether.fi's API
- Uses 7-day average (based on API's
7_day_aprfield)
DeFi Llama APR Provider:
- Supports multiple protocols (stETH, Aave, etc.)
- Requires
idfield to specify the protocol (e.g.,'747c1d2a-c668-4682-b9f9-296708a3dd90'for stETH) - Fetches APR data from DeFi Llama's API:
https://yields.llama.fi/chart/{protocolId} - Uses 24-hour average for current APR values
pointsMultiplier: Defaults to0if not provided- APR Providers: Defaults to Ether.fi if no provider specified
- Borrow APR: Defaults to Morpho if no provider specified
- Rewards: Defaults to Merkl if no provider specified
- When
pointsMultiplieris defined: Points are calculated aspointsMultiplier(static value) - When
pointsMultiplieris not defined: Points default to0and are hidden in the UI - UI Display: Points are only shown when they have a non-zero value
Basic Configuration (no points):
apyConfig: {
aprProvider: {
type: APR_PROVIDERS.LIDO,
// No 'id' needed - Lido only supports stETH
},
// No pointsMultiplier = points will be 0 and hidden
}With Points Rewards:
apyConfig: {
aprProvider: {
type: APR_PROVIDERS.ETHERFI,
},
pointsMultiplier: 5, // Shows "5 x" points in UI
}Current Provider Configurations:
Lido (stETH only):
apyConfig: {
aprProvider: {
type: APR_PROVIDERS.LIDO,
// No 'id' field needed - automatically uses stETH
},
}Ether.fi (weETH only):
apyConfig: {
aprProvider: {
type: APR_PROVIDERS.ETHERFI,
// No 'id' needed - automatically uses weETH
},
}DeFi Llama (multiple protocols):
apyConfig: {
aprProvider: {
type: APR_PROVIDERS.DEFI_LLAMA,
id: '747c1d2a-c668-4682-b9f9-296708a3dd90',
},
}Tokens marked with isTestOnly: true will only appear in the UI when the environment variable VITE_INCLUDE_TEST_TOKENS=true is set. This is useful for:
- Development and testing environments
- Tenderly VNet deployments
- Staging environments
For production leverage tokens, use LiFi routing with bridges disabled:
swaps: {
debtToCollateral: {
type: 'lifi',
allowBridges: 'none',
},
collateralToDebt: {
type: 'lifi',
allowBridges: 'none',
},
}For test-only tokens, you can use specific Uniswap V3 pool configurations for deterministic testing.