Skip to main content

Documentation Index

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

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

Portal’s Enclave MPC API provides comprehensive cross-chain bridging and swapping capabilities through the Li.Fi integration. This guide covers getting quotes, finding routes, executing swaps and bridges, and tracking transaction status.

Overview

The Li.Fi functionality allows you to:
  • Get quotes for bridging or swapping tokens across chains
  • Find routes to discover the best paths for your cross-chain transfers
  • Execute swaps and bridges by signing and submitting transactions
  • Track transaction status for cross-chain transfers
  • Get available tokens supported by Li.Fi across chains

Prerequisites

Before using Li.Fi operations, ensure you have:

Getting a Quote

Use the POST /api/v3/clients/me/integrations/lifi/quote endpoint to get a quote for bridging or swapping tokens across chains. For complete API documentation, see the Client API reference.
curl --request POST \
  --url 'https://api.portalhq.io/api/v3/clients/me/integrations/lifi/quote' \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
  --header 'Content-Type: application/json' \
  --data '{
  "fromChain": "eip155:1",
  "fromAmount": "1000000000000000000",
  "fromToken": "ETH",
  "toChain": "eip155:137",
  "toToken": "USDC",
  "fromAddress": "0x3fa7bc5cf02f07ed174d124a72fcf8d5276df546"
}'
The response includes a transactionRequest object with the transaction details (from, to, value, data) that you’ll need to sign and submit.

Finding Routes

Use the POST /api/v3/clients/me/integrations/lifi/routes endpoint to discover available routes for your cross-chain transfer. For complete API documentation, see the Client API reference.
curl --request POST \
  --url 'https://api.portalhq.io/api/v3/clients/me/integrations/lifi/routes' \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
  --header 'Content-Type: application/json' \
  --data '{
  "fromChainId": "eip155:1",
  "fromAmount": "1000000000000000000",
  "fromTokenAddress": "0x0000000000000000000000000000000000000000",
  "toChainId": "eip155:137",
  "toTokenAddress": "USDC"
}'
The response includes an array of routes with estimates, fees, and gas costs. Routes may be tagged as RECOMMENDED, CHEAPEST, or FASTEST.

Getting Route Step Details

Use the POST /api/v3/clients/me/integrations/lifi/route-step-details endpoint to get detailed transaction information for a specific route step, including an unsigned transaction that you can then sign and submit to an RPC provider (the transactionRequest field). For complete API documentation, see the Client API reference.
curl --request POST \
  --url 'https://api.portalhq.io/api/v3/clients/me/integrations/lifi/route-step-details' \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
  --header 'Content-Type: application/json' \
  --data '{
  "id": "a8dc011a-f52d-4492-9e99-21de64b5453a",
  "type": "lifi",
  "tool": "1inch",
  "toolDetails": {
    "key": "1inch",
    "logoURI": "https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/exchanges/oneinch.svg",
    "name": "1inch"
  },
  "action": {
    "fromChainId": "eip155:100",
    "toChainId": "eip155:100",
    "fromToken": {
      "address": "0x0000000000000000000000000000000000000000",
      "symbol": "xDai",
      "decimals": 18,
      "chainId": "eip155:100",
      "name": "xDai",
      "coinKey": "xDai",
      "priceUSD": "1",
      "logoURI": "https://static.debank.com/image/xdai_token/logo_url/xdai/1207e67652b691ef3bfe04f89f4b5362.png"
    },
    "toToken": {
      "name": "Minerva Wallet SuperToken",
      "symbol": "MIVA",
      "coinKey": "MIVA",
      "decimals": 18,
      "chainId": "eip155:100",
      "priceUSD": "1",
      "logoURI": "https://minerva.digital/i/MIVA-Token_200x200.png",
      "address": "0x63e62989d9eb2d37dfdb1f93a22f063635b07d51"
    },
    "fromAmount": "1000000000000000000",
    "slippage": 0.003,
    "fromAddress": "0x552008c0f6870c2f77e5cC1d2eb9bdff03e30Ea0",
    "toAddress": "0x552008c0f6870c2f77e5cC1d2eb9bdff03e30Ea0"
  },
  "estimate": {
    "fromAmount": "1000000000000000000",
    "toAmount": "21922914496086353975",
    "toAmountMin": "21265227061203763356",
    "tool": "1inch",
    "executionDuration": 30,
    "approvalAddress": "0x1111111254fb6c44bac0bed2854e76f90643097d",
    "feeCosts": [],
    "gasCosts": [
      {
        "type": "SEND",
        "price": "1",
        "estimate": "252364",
        "limit": "315455",
        "amount": "252364",
        "amountUSD": "0.00",
        "token": {
          "address": "0x0000000000000000000000000000000000000000",
          "symbol": "xDai",
          "decimals": 18,
          "chainId": "eip155:100",
          "name": "xDai",
          "coinKey": "xDai",
          "priceUSD": "1",
          "logoURI": "https://static.debank.com/image/xdai_token/logo_url/xdai/1207e67652b691ef3bfe04f89f4b5362.png"
        }
      }
    ]
  },
  "integrator": "fee-demo",
  "includedSteps": [
    {
      "id": "a8dc011a-f52d-4492-9e99-21de64b5453a",
      "type": "swap",
      "tool": "1inch",
      "toolDetails": {
        "key": "1inch",
        "logoURI": "https://raw.githubusercontent.com/lifinance/types/main/src/assets/icons/exchanges/oneinch.svg",
        "name": "1inch"
      },
      "action": {
        "fromChainId": "eip155:100",
        "toChainId": "eip155:100",
        "fromToken": {
          "address": "0x0000000000000000000000000000000000000000",
          "symbol": "xDai",
          "decimals": 18,
          "chainId": "eip155:100",
          "name": "xDai",
          "coinKey": "xDai",
          "priceUSD": "1",
          "logoURI": "https://static.debank.com/image/xdai_token/logo_url/xdai/1207e67652b691ef3bfe04f89f4b5362.png"
        },
        "toToken": {
          "name": "Minerva Wallet SuperToken",
          "symbol": "MIVA",
          "coinKey": "MIVA",
          "decimals": 18,
          "chainId": "eip155:100",
          "priceUSD": "1",
          "logoURI": "https://minerva.digital/i/MIVA-Token_200x200.png",
          "address": "0x63e62989d9eb2d37dfdb1f93a22f063635b07d51"
        },
        "fromAmount": "1000000000000000000",
        "slippage": 0.003,
        "fromAddress": "0x552008c0f6870c2f77e5cC1d2eb9bdff03e30Ea0",
        "toAddress": "0x552008c0f6870c2f77e5cC1d2eb9bdff03e30Ea0"
      },
      "estimate": {
        "fromAmount": "1000000000000000000",
        "toAmount": "21922914496086353975",
        "toAmountMin": "21265227061203763356",
        "tool": "1inch",
        "executionDuration": 30,
        "approvalAddress": "0x1111111254fb6c44bac0bed2854e76f90643097d",
        "feeCosts": [],
        "gasCosts": [
          {
            "type": "SEND",
            "price": "1",
            "estimate": "252364",
            "limit": "315455",
            "amount": "252364",
            "amountUSD": "0.00",
            "token": {
              "address": "0x0000000000000000000000000000000000000000",
              "symbol": "xDai",
              "decimals": 18,
              "chainId": "eip155:100",
              "name": "xDai",
              "coinKey": "xDai",
              "priceUSD": "1",
              "logoURI": "https://static.debank.com/image/xdai_token/logo_url/xdai/1207e67652b691ef3bfe04f89f4b5362.png"
            }
          }
        ]
      }
    }
  ]
}'
The response includes a transactionRequest object with the transaction details you’ll need to sign and submit.

Getting Available Tokens

Use the GET /api/v3/clients/me/integrations/lifi/tokens endpoint to retrieve all tokens supported by Li.Fi. You can filter results by chain, chain type, minimum price, or tag. For complete API documentation, see the Client API reference.
curl --request GET \
  --url 'https://api.portalhq.io/api/v3/clients/me/integrations/lifi/tokens?chains=ETH,ARB&minPriceUSD=0.01' \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]'

Executing a Swap or Bridge

After getting a quote or route step details, you’ll receive a transactionRequest object. Extract the from, to, value, and data fields to sign and submit the transaction.

Step 0: Approve the ERC-20 fromToken (if needed)

If your fromToken is an ERC-20, the Li.Fi router cannot move it on your behalf until you grant an on-chain allowance. Skip this step when the fromToken is the chain’s native asset (its address is 0x0000000000000000000000000000000000000000). Extract the following values from the quote response:
  • chainId: the fromChain you sent into the quote request.
  • approvalAddress: data.rawResponse.estimate.approvalAddress.
  • fromTokenAddress: data.rawResponse.action.fromToken.address.
  • amount: the fromAmount you sent into the quote request, divided by 10^data.rawResponse.action.fromToken.decimals (use a BigInt util for this). Pass it as a string in the token’s primary denomination (e.g. "0.01" for 0.01 USDC).
Then call the approvals endpoint to build an unsigned approval transaction:
curl --request POST \
  --url 'https://api.portalhq.io/api/v3/clients/me/chains/<chainId>/assets/<fromTokenAddress>/approvals' \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
  --header 'Content-Type: application/json' \
  --data '{
  "delegateAddress": "[approvalAddress]",
  "amount": "[amount]"
}'
The response returns a transactions array. Sign each entry with the eth_sendTransaction flow shown in Step 1 before continuing on to sign the swap transaction itself. For complete endpoint documentation, see the Client API reference.

Step 1: Sign the Transaction

Use the Enclave MPC API to sign the transaction:
curl --request POST \
  --url https://mpc-client.portalhq.io/v1/sign \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
  --header 'Content-Type: application/json' \
  --data '{
  "share": "[share]",
  "method": "eth_sendTransaction",
  "params": {
    "from": "0x3fa7bc5cf02f07ed174d124a72fcf8d5276df546",
    "to": "0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE",
    "value": "0xde0b6b3a7640000",
    "data": "0x25d374e800000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000220..."
  },
  "rpcUrl": "https://api.portalhq.io/rpc/v1/eip155/1",
  "chainId": "eip155:1"
}'
The transactionRequest from Li.Fi may include gasPrice and gasLimit fields. You can remove these if you want Portal to estimate the gas for you, or include them if you want to use Li.Fi’s estimates.

Step 2: Track Transaction Status

After signing and broadcasting the transaction, use the GET /api/v3/clients/me/integrations/lifi/status endpoint to track the status of your cross-chain transfer. For complete API documentation, see the Client API reference.
curl --request GET \
  --url 'https://api.portalhq.io/api/v3/clients/me/integrations/lifi/status?fromChain=eip155:1&txHash=0x...' \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]'

Example Flow

Here’s a complete example of executing a cross-chain bridge:
# 1. Get a quote for bridging ETH from Ethereum to Polygon
QUOTE_RESPONSE=$(curl --request POST \
  --url 'https://api.portalhq.io/api/v3/clients/me/integrations/lifi/quote' \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
  --header 'Content-Type: application/json' \
  --data '{
  "fromChain": "eip155:1",
  "fromAmount": "1000000000000000000",
  "fromToken": "ETH",
  "toChain": "eip155:137",
  "toToken": "USDC",
  "fromAddress": "0x3fa7bc5cf02f07ed174d124a72fcf8d5276df546"
}')

# Extract transactionRequest from response (parse JSON)
# transactionRequest contains: from, to, value, data, chainId

# 2. If fromToken is an ERC-20 (its address is not 0x0000...0000),
#    build an approval transaction and sign it before signing the swap.
#    Skip this block for native-asset swaps.
APPROVAL_RESPONSE=$(curl --request POST \
  --url 'https://api.portalhq.io/api/v3/clients/me/chains/[chainId]/assets/[fromTokenAddress]/approvals' \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
  --header 'Content-Type: application/json' \
  --data '{
  "delegateAddress": "[approvalAddress]",
  "amount": "[amount]"
}')

# Sign each transaction returned in APPROVAL_RESPONSE.transactions[]
# using the same eth_sendTransaction flow as below.

# 3. Sign and submit the transaction
curl --request POST \
  --url https://mpc-client.portalhq.io/v1/sign \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
  --header 'Content-Type: application/json' \
  --data '{
  "share": "[share]",
  "method": "eth_sendTransaction",
  "params": {
    "from": "[fromAddress]",
    "to": "[toAddress]",
    "value": "[value]",
    "data": "[data]"
  },
  "rpcUrl": "https://api.portalhq.io/rpc/v1/eip155/1",
  "chainId": "eip155:1"
}'

# 4. Extract transaction hash from response and track status
curl --request GET \
  --url 'https://api.portalhq.io/api/v3/clients/me/integrations/lifi/status?fromChain=eip155:1&txHash=0xTransactionHash' \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]'

Best Practices

  1. Compare quotes/routes before signing and submitting the transaction(s) to find the best option for your use case
  2. Handle network errors gracefully and provide user feedback
  3. Monitor transaction status for cross-chain transfers, as they may take longer than single-chain transactions
  4. Validate user balances before initiating swaps or bridges

Supported Networks

Portal’s Li.Fi integration supports the following mainnet networks:
  • Monad (eip155:143)
  • Ethereum (eip155:1)
  • Optimism (eip155:10)
  • BSC (eip155:56)
  • Gnosis (eip155:100)
  • Unichain (eip155:130)
  • Polygon (eip155:137)
  • Sonic (eip155:146)
  • Mantle (eip155:5000)
  • Base (eip155:8453)
  • Arbitrum (eip155:42161)
  • Celo (eip155:42220)
  • Avalanche (eip155:43114)
  • Linea (eip155:59144)
  • Berachain (eip155:80094)
  • Katana (eip155:747474)
  • Solana (solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp)
  • Bitcoin (bip122:000000000019d6689c085ae165831e93-p2wpkh)
For the complete list of networks Li.Fi supports across its ecosystem, refer to the Li.Fi documentation. If you need a chain that isn’t listed above, contact Portal support.
Testnets are not supported.

Next Steps