# Trigger a swap

## 1. Import quote and swap execution functions from useWallet hook&#x20;

```tsx
export function Page() {
     const {
         computeQuote,
         executeSwap,
         executeHeadlessSwap
     } = useWallet();
}
```

## 2. Compute quote for a token swap

```typescript
const quoteResult: any = await calculateQuote({
    fromToken: {
      amount: ethers
        .parseUnits(fromAmount, fromToken.decimals)
        .toString(),
      chainId: fromChain.chainId,
      tokenAddress: fromChain.address,
      
      // Optional
      metadata: {
        tokenName: fromToken.name,
        tokenSymbol: fromToken.symbol,
        decimals: fromToken.decimals,
        logoURI: fromToken.logoURI,
        chainIds: fromToken.chainIds,
      },
    },
    toToken: {
      chainId: toChain.chainId,
      tokenAddress: toChain.address,
      
      // Optional
      metadata: {
        tokenName: toToken.name,
        tokenSymbol: toToken.symbol,
        decimals: toToken.decimals,
        logoURI: toToken.logoURI,
        chainIds: toToken.chainIds,
      },
    },
});
```

## 3. Execute the swap

### 3.a. Normal swap

Trigger the swap modal built into the embedded wallet

```typescript
swap({
  fromToken: {
    tokenAddress: fromTokenAddress,
    chainId: fromTokenChainId,
    
    // Optional
    metadata: {
      tokenName: fromTokenName,
      tokenSymbol: fromTokenSymbol,
      decimals: fromTokenDecimals,
      logoURI: fromTokenLogoURI
    },
  },
  toToken: {
    tokenAddress: toTokenAddress,
    chainId: toTokenChainId,
  },
});
```

Calling **swap()** triggers the swap modal where user's can execute their trade

<figure><img src="https://2429876521-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGaftPmsUdt8hxUf6uzhp%2Fuploads%2F0RaPpWY1QViI9FvSTFX9%2FScreenshot%202025-06-30%20at%206.18.49%E2%80%AFPM.png?alt=media&#x26;token=08ba390e-bc20-4596-8c93-08022eb26bdc" alt="" width="375"><figcaption></figcaption></figure>

### 3.b. Headless swap

A headless swap is a swap that's executed directly from the context of the parent application without triggering the embedded wallet swap popup. This alternate method can be used when the app wants complete end-to-end control over the swap UX without relying on the embedded wallet's swap interface.

#### Quote Selection

For headless swaps, since user's don't go through the embedded wallet interface, the quote response provides the app developer the option of choosing between the quote with best price execution and the quote that executes the swap the fastest. The developer can pass this decision on to the user or choose on behalf of the user.

Quote results have 2 types: **quote.bestQuote** which returns the highest amount out for the given input token amount and swap pair and **quote.fastestQuote** which executes the swap in the lowest possible time. When **quote.duplicate** is **true** then both the quotes (the one with the best rate and one with the fastest execution time) are from the same provider and there is no choice to be made. If not, the app developer can choose on behalf of the user or&#x20;

```typescript
const handleExecuteSwap = async () => {
    if (!isLoggedIn || !quote) {
      connect();
      return;
    }

    try {
      setIsLoading(true);
      const fromChain = fromToken.chainIds[0];
      const toChain = toToken.chainIds[0];

      // Get the provider from the selected quote
      
      // App developers can write their own logic to select between 
      // quoteResult.bestQuote and quoteResult.fastestQuote from the quoteResult object
      // in the code snippet above, where we call calculateQuote
      const selectedQuote = getSelectedQuote();
      const provider =
        selectedQuote && "provider" in selectedQuote
          ? (selectedQuote.provider as ProtocolProvider)
          : isMultipleQuotesResponse(quote)
          ? selectedQuoteType === "best"
            ? quote.bestQuote.provider
            : quote.fastestQuote.provider
          : undefined;

      const result = await executeSwap({
        fromToken: {
          amount: ethers.parseUnits(fromAmount, fromToken.decimals).toString(),
          chainId: fromChain.chainId,
          tokenAddress: fromChain.address,
          
          // Optional
          metadata: {
            tokenName: fromToken.name,
            tokenSymbol: fromToken.symbol,
            decimals: fromToken.decimals,
            logoURI: fromToken.logoURI,
            
            // For multichain swaps, the user can select which chains to spend funds from
            // For example a user with 100 USDC on Arbitrum Base and Solana each could
            // choose to spend 50 USDC from Base and 50 from Solana
            // chainIds: [
            //  {chainId: Networks.SOLANA, amount: 50000000, address: solanaTokenAddress},
            //  {chainId: Networks.BASE, amount: 50000000, address: baseTokenAddress},
            // ]
            // If left blank then Enclave's best path algorithm automatically selects the
            // most optimal distribution to spend based on available liquidity and gas fees
            chainIds: fromToken.chainIds,
          },
        },
        toToken: {
          chainId: toChain.chainId,
          tokenAddress: toChain.address,
          
          // Optional
          metadata: {
            tokenName: toToken.name,
            tokenSymbol: toToken.symbol,
            decimals: toToken.decimals,
            logoURI: toToken.logoURI,
            
            // For multichain swaps, the user can select which chains to receive funds on
            // For example a user could choose to receive USDT as the output token on 
            // Binance smart chain.
            // chainIds: [
            //  {chainId: Networks.BSC, address: bscTokenAddress},
            // ]
            // If left blank then Enclave's best path algorithm automatically selects the
            // most optimal output chain based on available liquidity and gas fees
            chainIds: toToken.chainIds,
          },
        },
        ...(provider && { provider: provider as ProtocolProvider }),
      });

      console.log("Swap executed:", result);
    } catch (error) {
      console.error("Swap execution failed:", error);
    } finally {
      setIsLoading(false);
    }
  };
```
