> ## Documentation Index
> Fetch the complete documentation index at: https://docs.li.fi/llms.txt
> Use this file to discover all available pages before exploring further.

# Stellar Providers

> Stellar Architecture

export const SupportedTools = ({chainId}) => {
  const [chains, setChains] = useState(null);
  const [tools, setTools] = useState(null);
  const [error, setError] = useState(null);
  useEffect(() => {
    const fetchChains = async () => {
      try {
        const response = await fetch('https://li.quest/v1/chains?chainTypes=EVM,SVM,UTXO,MVM,TVM,STL');
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        const jsonData = await response.json();
        setChains(jsonData.chains);
      } catch (err) {
        setError(err.message);
      }
    };
    fetchChains();
  }, []);
  useEffect(() => {
    const fetchTools = async () => {
      try {
        const response = await fetch('https://li.quest/v1/tools');
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        const jsonData = await response.json();
        setTools(jsonData);
      } catch (err) {
        setError(err.message);
      }
    };
    fetchTools();
  }, []);
  const parseBridges = (bridges, selectedChainId) => bridges.map(bridge => {
    const fromChainIds = bridge.supportedChains.filter(connection => connection.toChainId === selectedChainId).map(connection => connection.fromChainId);
    const toChainIds = bridge.supportedChains.filter(connection => connection.fromChainId === selectedChainId).map(connection => connection.toChainId);
    const connectedChainIds = [...new Set([...fromChainIds, ...toChainIds])];
    return {
      ...bridge,
      fromChainIds,
      toChainIds,
      connectedChainIds
    };
  }).filter(bridge => bridge.connectedChainIds.length).sort((a, b) => b.connectedChainIds.length - a.connectedChainIds.length);
  const parseExchanges = (exchanges, selectedChainId) => exchanges.filter(exchange => exchange.supportedChains.includes(selectedChainId));
  const renderChains = chains => <div className="p-2">
      <div className="flex flex-wrap gap-4">
        {chains.map(chain => <div key={chain.key} className="relative group flex-shrink-0">
            <img src={chain.logoURI} alt={chain.name} className="w-10 h-10 rounded-full object-cover not-prose" />
            <div className="absolute bottom-full left-1/2 transform -translate-x-1/2 mb-2 hidden group-hover:block bg-gray-800 text-white text-xs rounded py-1 px-2 whitespace-nowrap z-10">
              {chain.name}
            </div>
          </div>)}
      </div>
    </div>;
  const renderTools = (tools, chains) => {
    const bridges = parseBridges(tools.bridges, Number(chainId));
    const exchanges = parseExchanges(tools.exchanges, Number(chainId));
    return <div>
      <h2>Supported Bridges</h2>
      <ul>
        {bridges.map(bridge => <li>
            {bridge.name} (<code>{bridge.key}</code>) connects to:
            {renderChains(chains.filter(chain => bridge.connectedChainIds.includes(chain.id)))}
          </li>)}
      </ul>

      <h2>Supported Exchanges</h2>
      <ul>
        {exchanges.map(exchange => <li>{exchange.name} (<code>{exchange.key}</code>)</li>)}
        {exchanges.length === 0 ? '-' : ''}
      </ul>
    </div>;
  };
  if (error) return <div>Error: {error}</div>; else if (chains && tools) return renderTools(tools, chains); else return <div>Loading...</div>;
};

LI.FI offers same-chain swaps on Stellar, bridging into Stellar from EVM chains, Solana, Bitcoin and Tron, and bridging USDC out of Stellar to major EVM chains.

<Note>
  Stellar chainId in LI.FI is `1201081091099710`. The chain key is `xlm` and the chain type is `STL`.

  `GET /v1/chains` returns EVM chains only by default. Pass `chainTypes` to include Stellar, for example `GET /v1/chains?chainTypes=EVM,STL`.

  All Stellar tokens, including native XLM, are addressed by their Soroban contract (Stellar Asset Contract, SAC) `C...` address. Native XLM is represented as `CAS3J7GYLGXMF6TDJBBYYSE3HQ6BBSMLNUQ34T6TZMYMW2EVH34XOWMA` (7 decimals).

  Stellar token addresses are case-sensitive. Always pass them exactly as returned by the API.
</Note>

<SupportedTools chainId="1201081091099710" />

## Requesting a quote

A quote for Stellar can be requested using the same endpoints as EVM. Only the chain ids, token addresses and the transaction data differ.

<Note>
  `fromAddress` when the source chain is Stellar must be an ed25519 `G...` account address. Muxed `M...` addresses and Soroban contract `C...` addresses are not supported as senders.

  The LI.FI SDK also resolves SEP-2 federation addresses (`name*domain.com`) to a `G...` address before it builds a request. It refuses a federation record that carries a memo, because a route request cannot carry one.

  `toAddress` when Stellar is the destination chain accepts a `G...` account address. When bridging out of Stellar, `toAddress` is a regular address on the destination chain (for example an EVM address).

  The sender account must exist on the network. Stellar accounts only exist once they are funded, so no quote is returned for an unfunded sender account.
</Note>

## Token approvals

Not every Stellar route requires a token approval. Depending on the tool, the executing contract either moves funds directly under the authorization carried by your signed transaction, or pulls them through a token allowance.

The decision is made per included step, never from the route-level estimate. Scan the quote's `includedSteps` and treat a step as needing an approval when both of these hold:

* `estimate.skipApproval` is not `true`.
* `estimate.approvalAddress` is a Soroban contract (`C...`) address.

For that step, approve its `estimate.approvalAddress` as the spender, its `action.fromToken.address` as the token, and at least its `estimate.fromAmount` as the amount. A Stellar route pulls at most one allowance today, so the first step that meets both conditions is the one to approve.

<Note>
  Soroban token allowances always have an expiration ledger (a mandatory TTL). Unlimited or indefinite approvals do not exist on Stellar — every allowance eventually expires and will need to be renewed.

  Because allowances are never indefinite, it is also safe to approve a buffer: we recommend approving about 10% on top of the required amount so the allowance still covers positive slippage from a preceding swap.
</Note>

<Warning>
  **Do not approve the route-level `approvalAddress`**

  The `estimate.approvalAddress` on the top-level step is a summary. When no included step pulls funds it falls back to a placeholder — a `G...` account, or the EVM diamond address — and neither can call `transfer_from`. Approving it grants an allowance that nothing ever consumes.

  Take the token from the included step too, not from the route. A route that swaps and then bridges through CCTP needs the allowance on the intermediate asset the swap produces, not on the route's `fromToken`.
</Warning>

<Warning>
  **Approve before requesting transaction data**

  An approval is a separate Stellar transaction that consumes your account's sequence number, and the transaction envelope LI.FI returns is built against your account's current sequence number.

  Submit the approval and wait for it to be confirmed before requesting the transaction data. An approval submitted after you already hold an envelope invalidates that envelope through the sequence advance, and an unconfirmed approval still in flight does the same.
</Warning>

## Soroswap integration

Registered as the exchange key `soroswap`. Enables users to perform same-chain swaps on Stellar. Soroswap aggregates liquidity across Stellar AMMs and splits the trade across venues for the best output.

<Note>
  For same-chain swaps on Stellar, `toAddress` must equal `fromAddress`. The router measures the swap output through the sender's balance change, so no transaction is returned for a different recipient.
</Note>

## Polymer integration

Polymer is registered as two tools, `polymer` ("Polymer (Fast)") and `polymerStandard` ("Polymer (Standard)"). Both bridge USDC into Stellar from EVM chains using Circle's Cross-Chain Transfer Protocol (CCTP). They differ in the Circle attestation they settle on: `polymer` is faster, `polymerStandard` is cheaper.

<Note>
  Receiving a non-XLM asset on Stellar requires the recipient account to hold a trustline for that asset. If the recipient has no trustline, no quote is returned.
</Note>

## Circle CCTP integration

Registered as the tool key `cctp` ("Circle CCTP"). It is the only bridge that routes out of Stellar today. It carries USDC to 10 chains: Ethereum, Arbitrum, Avalanche, Base, Injective, Monad, OP Mainnet, Polygon, Unichain, and World Chain.

<Note>
  A route out of Stellar that starts from a non-USDC asset swaps on Soroswap first, then bridges the resulting USDC. That route pulls a token allowance, and the allowance belongs on the intermediate USDC, not on the route's `fromToken`. See [Token approvals](#token-approvals).
</Note>

## NearIntents integration

Registered as the tool key `near` ("NearIntents"). Enables users to bridge XLM and USDC into Stellar from other supported ecosystems, including EVM chains, Solana, Bitcoin, and Tron.

## Executing a transaction

### Transaction data

`transactionRequest.data` is a base64-encoded, unsigned Stellar `TransactionEnvelope` XDR. The envelope is built against a fresh sequence number of the sender account, and the network fee and Soroban resources are already set from simulation.

To execute the transaction:

1. Request the transaction data through the regular quote flow.
2. Sign the envelope with the sender account's key.
3. Submit the signed transaction to the Stellar network.

<Warning>
  **Envelope validity window**

  The envelope is only valid for about 5 minutes (enforced through timebounds) and becomes invalid as soon as the sender account's sequence number advances.

  * Sign and submit promptly after receiving the transaction data.
  * Request a new transaction if the envelope is stale.
  * Do not modify the envelope. It is assembled from simulation, and any change can invalidate it.
</Warning>

### Gas

The estimated network fee is returned in the step's `estimate.gasCosts` in stroops (XLM, 7 decimals).

### Account reserve

Every Stellar account must hold a minimum XLM balance, the account reserve, and cannot spend it. Two consequences follow:

* A route that starts on Stellar cannot spend the sender's whole XLM balance.
* A route that bridges into Stellar delivers XLM to the receiver and holds back a buffer for the account reserve and for the destination step fees.

## Status tracking

Transaction status can be tracked using the regular [status tracking](/introduction/user-flows-and-examples/status-tracking) flow.

<Note>
  When polling `/status` for a transaction that originates on Stellar, always pass `fromChain=XLM` (or the Stellar chain id `1201081091099710`). Stellar transaction hashes are 64-character hex strings and are otherwise indistinguishable from Bitcoin transaction hashes.
</Note>
