Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.tedprotocol.io/llms.txt

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

How to integrate TED Protocol into your application.

Overview

TED Protocol integration methods:
MethodComplexityStatus
Direct contract callsMediumAvailable
SDKLowComing soon
Embeddable widgetLowestComing soon
This guide covers direct contract integration.

Prerequisites

  • Web3 library (ethers.js, web3.js, or viem)
  • TED Protocol addresses from the Contract Addresses page
  • Contract ABIs

Setup

Initialize your connection to TED Protocol:
import { ethers } from 'ethers';

// Contract addresses (example - verify on contract-addresses page)
const DIAMOND_ADDRESS = "0x...";  // Network-specific

// Combined ABI (includes all facets)
const TED_ABI = [
    // IFXSwap
    "function swap(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, uint256 deadline) returns (uint256)",
    "function getQuote(address tokenIn, address tokenOut, uint256 amountIn) view returns (tuple(uint256 amountOut, uint256 priceImpact, address[] route, uint256 gasEstimate))",

    // ICrossChainSwap
    "function crossChainSwap(tuple(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, uint32 srcChainId, uint32 dstChainId, address recipient, uint256 deadline, bytes bridgeOptions)) payable returns (bytes32)",
    "function estimateFees(tuple(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, uint32 srcChainId, uint32 dstChainId, address recipient, uint256 deadline, bytes bridgeOptions)) view returns (uint256, uint256)",

    // Events
    "event Swap(address indexed sender, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut, address dex)",
    "event CrossChainSwapInitiated(bytes32 indexed messageId, address indexed sender, uint32 srcChainId, uint32 dstChainId, address tokenIn, address tokenOut, uint256 amountIn)"
];

// Initialize
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const tedProtocol = new ethers.Contract(DIAMOND_ADDRESS, TED_ABI, signer);

Same-Chain Swap

Execute a swap on a single chain:
  1. Approve tokens
  2. Get a quote
  3. Calculate minimum output with slippage
  4. Execute swap
async function executeSwap(tokenIn, tokenOut, amountIn, slippageBps = 50) {
    // 1. Approve tokens (if not already approved)
    const tokenContract = new ethers.Contract(tokenIn, ERC20_ABI, signer);
    const allowance = await tokenContract.allowance(userAddress, DIAMOND_ADDRESS);

    if (allowance < amountIn) {
        const approveTx = await tokenContract.approve(DIAMOND_ADDRESS, amountIn);
        await approveTx.wait();
    }

    // 2. Get quote
    const quote = await tedProtocol.getQuote(tokenIn, tokenOut, amountIn);

    // 3. Calculate minimum output with slippage
    const minAmountOut = quote.amountOut * (10000n - BigInt(slippageBps)) / 10000n;

    // 4. Execute swap
    const deadline = Math.floor(Date.now() / 1000) + 600; // 10 minutes

    const tx = await tedProtocol.swap(
        tokenIn,
        tokenOut,
        amountIn,
        minAmountOut,
        deadline
    );

    const receipt = await tx.wait();

    // 5. Parse events for confirmation
    const swapEvent = receipt.logs.find(log => {
        try {
            return tedProtocol.interface.parseLog(log)?.name === 'Swap';
        } catch { return false; }
    });

    if (swapEvent) {
        const parsed = tedProtocol.interface.parseLog(swapEvent);
        return {
            amountIn: parsed.args.amountIn,
            amountOut: parsed.args.amountOut,
            txHash: receipt.hash
        };
    }
}

Cross-Chain Swap

Execute swaps across different blockchains:
async function executeCrossChainSwap(params) {
    const {
        tokenIn,
        tokenOut,
        amountIn,
        srcChainId,
        dstChainId,
        recipient,
        slippageBps = 100
    } = params;

    // 1. Approve tokens
    const tokenContract = new ethers.Contract(tokenIn, ERC20_ABI, signer);
    const approveTx = await tokenContract.approve(DIAMOND_ADDRESS, amountIn);
    await approveTx.wait();

    // 2. Estimate fees
    const crossChainParams = {
        tokenIn,
        tokenOut,
        amountIn,
        minAmountOut: 0n,  // Will calculate after quote
        srcChainId,
        dstChainId,
        recipient,
        deadline: Math.floor(Date.now() / 1000) + 3600,
        bridgeOptions: "0x"
    };

    const [nativeFee, bridgeFee] = await tedProtocol.estimateFees(crossChainParams);

    // 3. Get expected output and set minimum
    const quote = await tedProtocol.getQuote(tokenIn, tokenOut, amountIn);
    crossChainParams.minAmountOut = quote.amountOut * (10000n - BigInt(slippageBps)) / 10000n;

    // 4. Execute cross-chain swap
    const tx = await tedProtocol.crossChainSwap(crossChainParams, {
        value: nativeFee
    });

    const receipt = await tx.wait();

    // 5. Get message ID for tracking
    const event = receipt.logs.find(log => {
        try {
            return tedProtocol.interface.parseLog(log)?.name === 'CrossChainSwapInitiated';
        } catch { return false; }
    });

    if (event) {
        const parsed = tedProtocol.interface.parseLog(event);
        return {
            messageId: parsed.args.messageId,
            txHash: receipt.hash
        };
    }
}

Tracking Cross-Chain Transfers

Monitor transfer status using the LayerZero Scan API:
async function trackTransfer(messageId) {
    const response = await fetch(
        `https://api.layerzeroscan.com/tx/${messageId}`
    );
    const data = await response.json();

    return {
        status: data.status,  // 'INFLIGHT', 'DELIVERED', 'FAILED'
        srcTxHash: data.srcTxHash,
        dstTxHash: data.dstTxHash
    };
}

Token Approvals

Standard Approval

Grants the protocol permission to spend your tokens:
async function approveToken(tokenAddress, amount) {
    const token = new ethers.Contract(tokenAddress, ERC20_ABI, signer);
    const tx = await token.approve(DIAMOND_ADDRESS, amount);
    await tx.wait();
}

Permit (Gasless Approval)

Supported by TEDP and some stablecoins via ERC-2612.
  • Sign approval off-chain
  • Include in your swap transaction
  • Save gas on separate approval transaction
See the API Reference for permit implementation details.

Error Handling

Always simulate transactions before executing and handle custom errors:
async function safeSwap(tokenIn, tokenOut, amountIn) {
    try {
        // Simulate first
        await tedProtocol.swap.staticCall(
            tokenIn,
            tokenOut,
            amountIn,
            0n,  // Will fail if there's an issue
            Math.floor(Date.now() / 1000) + 600
        );

        // Execute if simulation passes
        return await executeSwap(tokenIn, tokenOut, amountIn);

    } catch (error) {
        // Parse custom errors
        if (error.data) {
            const iface = new ethers.Interface([
                "error InsufficientOutput(uint256 expected, uint256 actual)",
                "error DeadlineExpired(uint256 deadline, uint256 timestamp)",
                "error UnsupportedToken(address token)",
                "error ProtocolPaused()"
            ]);

            try {
                const decoded = iface.parseError(error.data);
                console.error(`Error: ${decoded.name}`, decoded.args);
            } catch {
                console.error("Unknown error:", error);
            }
        }
        throw error;
    }
}

Best Practices

Always Get Fresh Quotes

Quotes are valid for a short time. Execute immediately after quoting.

Set Appropriate Slippage

Swap TypeRecommended Slippage
Stablecoin pairs0.1-0.5%
Cross-chain swaps0.5-1%
Large amountsUse lower values

Handle Network Switching

Ensure users are on the correct network before executing transactions:
async function ensureCorrectNetwork(requiredChainId) {
    const currentChainId = await provider.getNetwork().then(n => n.chainId);

    if (currentChainId !== requiredChainId) {
        await window.ethereum.request({
            method: 'wallet_switchEthereumChain',
            params: [{ chainId: ethers.toQuantity(requiredChainId) }]
        });
    }
}

Implement Retry Logic

Network issues can cause temporary failures. Retrying with exponential backoff improves reliability.

Support