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

# Quick Start Guide

> Learn how to bundle multiple transactions into a single atomic execution using the Compass SDK. Combine allowance and swap actions to save gas and improve UX.

export const GithubCodeBlock = ({typescript, python}) => {
  const [typescriptCode, setTypescriptCode] = useState("");
  const [pythonCode, setPythonCode] = useState("");
  function removeWhitespace(strings, x) {
    return strings.map(str => {
      let count = 0;
      let i = 0;
      while (i < str.length && count < x && str[i] === " ") {
        count++;
        i++;
      }
      return str.slice(i);
    });
  }
  function cropToSnippet({text, from, to}) {
    const lines = text.split("\n");
    let result = [];
    let isCollecting = false;
    for (const line of lines) {
      if (line.trim() === from) {
        isCollecting = true;
        continue;
      }
      if (line.trim() === to) {
        break;
      }
      if (isCollecting) {
        result.push(line);
      }
    }
    const whitespaceToDelete = result[0].length - result[0].trimStart().length;
    result = removeWhitespace(result, whitespaceToDelete);
    return result.join("\n");
  }
  function removeSnippetComments(code) {
    return code.replace(/(\/\/|#) SNIPPET (START|END) \d+(\n|$)/g, "");
  }
  useEffect(() => {
    if (!typescript) return;
    fetch(typescript.url).then(response => response.text()).then(text => {
      let code = text;
      if (typescript.snippetNumber) {
        code = cropToSnippet({
          text,
          from: `// SNIPPET START ${typescript.snippetNumber}`,
          to: `// SNIPPET END ${typescript.snippetNumber}`
        });
      } else {
        code = removeSnippetComments(code);
      }
      setTypescriptCode(code);
    }).catch(error => {
      console.error("Error loading file:", error);
    });
  }, [typescript]);
  useEffect(() => {
    if (!python) return;
    fetch(python.url).then(response => response.text()).then(text => {
      let code = text;
      if (python.snippetNumber) {
        code = cropToSnippet({
          text,
          from: `# SNIPPET START ${python.snippetNumber}`,
          to: `# SNIPPET END ${python.snippetNumber}`
        });
      } else {
        code = removeSnippetComments(code);
      }
      setPythonCode(code);
    }).catch(error => {
      console.error("Error loading file:", error);
    });
  }, [python]);
  if (!python && !typescript) return null;
  if (!python) {
    return <CodeBlock language="typescript" filename={typescript.name} expandable={typescript?.numOfLinesExpandable ? "true" : null} lines="true" icon="https://upload.wikimedia.org/wikipedia/commons/f/f5/Typescript.svg" code={typescriptCode} children={typescriptCode || !typescript?.numOfLinesExpandable || <div style={{
      whiteSpace: "pre-wrap"
    }}>
        {Array(typescript?.numOfLinesExpandable).fill("-").map(x => x).join("\n")}
      </div>} />;
  }
  if (!typescript) {
    return <CodeBlock language="python" filename={python.name} expandable={python?.numOfLinesExpandable ? "true" : null} lines="true" icon="https://upload.wikimedia.org/wikipedia/commons/c/c3/Python-logo-notext.svg" code={pythonCode} children={pythonCode || !python?.numOfLinesExpandable || <div style={{
      whiteSpace: "pre-wrap"
    }}>
        {Array(python?.numOfLinesExpandable).fill("-").map(x => x).join("\n")}
      </div>} />;
  }
  return <CodeGroup>
  <CodeBlock language="typescript" filename={typescript.name} expandable={typescript?.numOfLinesExpandable ? "true" : null} lines="true" icon="https://upload.wikimedia.org/wikipedia/commons/f/f5/Typescript.svg" code={typescriptCode} children={typescriptCode || !typescript?.numOfLinesExpandable || <div style={{
    whiteSpace: "pre-wrap"
  }}>
          {Array(typescript?.numOfLinesExpandable).fill("-").map(x => x).join("\n")}
        </div>} />
  <CodeBlock language="python" filename={python.name} expandable={python?.numOfLinesExpandable ? "true" : null} lines="true" icon="https://upload.wikimedia.org/wikipedia/commons/c/c3/Python-logo-notext.svg" code={pythonCode} children={pythonCode || !python?.numOfLinesExpandable || <div style={{
    whiteSpace: "pre-wrap"
  }}>
          {Array(python?.numOfLinesExpandable).fill("-").map(x => x).join("\n")}
        </div>} />
</CodeGroup>;
};

🕐 Time to complete: ±10 minutes

🧰 What you need:

* Free [Compass API Key](https://www.compasslabs.ai/login)
* Wallet (EOA or [smart account guide](/v1/wallet-support/overview))

## Introduction

This guide demonstrates how to combine two simple transactions:

* Set allowance on Uniswap
* Swap on Uniswap

Bundling actions into a single transaction ensures they execute atomically, saving gas, improving UX, and avoiding partial execution risks.

Any action available on the [API Reference](https://docs.compasslabs.ai/v1/api-reference/transaction-batching/construct-bundled-transaction#body-actions) can be used for bundling.

## Setup

<Steps>
  <Step title="Install Dependencies">
    Install the required packages.

    <CodeGroup>
      ```shellscript Typescript theme={"system"}
      npm install @compass-labs/api-sdk viem dotenv
      ```

      ```shellscript Python theme={"system"}
      pip install compass_api_sdk web3 python-dotenv
      ```
    </CodeGroup>
  </Step>

  <Step title="Set Environment Variables">
    Create a .env file in your project root.

    ```dotenv .env theme={"system"}
    PRIVATE_KEY="your_wallet_private_key"
    RPC_URL="your_ethereum_rpc_url"
    COMPASS_API_KEY="your_compass_api_key"
    ```
  </Step>

  <Step title="Import Libraries & Environment Variables">
    <GithubCodeBlock
      typescript={{
name: "index.ts",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/main/v1/transaction_bundler/typescript/src/index.ts",
snippetNumber: 1,
}}
      python={{
name: "main.py",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/main/v1/transaction_bundler/python/src/main.py",
snippetNumber: 1,
}}
    />
  </Step>

  <Step title="Initialize SDK and Account">
    <GithubCodeBlock
      typescript={{
name: "index.ts",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/main/v1/transaction_bundler/typescript/src/index.ts",
snippetNumber: 2,
}}
      python={{
name: "main.py",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/main/v1/transaction_bundler/python/src/main.py",
snippetNumber: 2,
}}
    />
  </Step>
</Steps>

<Note>
  The full, uninterrupted code is available at the end of the tutorial.
</Note>

## Get Authorization

Before you can bundle transactions, you need to get an authorization from the Compass API and sign it with your private key. This ensures only you can execute the batch.

<Steps>
  <Step title="Get and Sign Authorization">
    Request authorization from the Compass API and sign it with your wallet to authenticate the transaction batching.

    <GithubCodeBlock
      typescript={{
name: "index.ts",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/main/v1/transaction_bundler/typescript/src/index.ts",
snippetNumber: 3,
}}
      python={{
name: "main.py",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/main/v1/transaction_bundler/python/src/main.py",
snippetNumber: 3,
}}
    />
  </Step>
</Steps>

## Bundle the Actions

Now let's bundle the allowance and swap actions for atomic execution. This step shows how to combine both actions into a single transaction using the Compass API.

<Steps>
  <Step title="Create Bundled Transaction">
    Bundle the allowance and swap actions for atomic execution. This step shows how to combine both actions into a single transaction using the Compass API.

    Any transactional endpoint in Compass API can be turned into an action, see [API Reference](https://docs.compasslabs.ai/v1/api-reference/transaction-batching/construct-bundled-transaction#body-actions).

    <GithubCodeBlock
      typescript={{
name: "index.ts",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/main/v1/transaction_bundler/typescript/src/index.ts",
snippetNumber: 4,
}}
      python={{
name: "main.py",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/main/v1/transaction_bundler/python/src/main.py",
snippetNumber: 4,
}}
    />
  </Step>
</Steps>

## Execute the Transaction

The final step is to sign and broadcast the transaction to the network. This will execute your bundled actions in a single atomic transaction.

<Steps>
  <Step title="Sign and Broadcast Transaction">
    Sign the returned transaction with your private key and broadcast it to the network. This is the final step to actually send your bundled transaction to Ethereum.

    <GithubCodeBlock
      typescript={{
name: "index.ts",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/main/v1/transaction_bundler/typescript/src/index.ts",
snippetNumber: 5,
}}
      python={{
name: "main.py",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/main/v1/transaction_bundler/python/src/main.py",
snippetNumber: 5,
}}
    />
  </Step>
</Steps>

<Tip>
  For further practice, try bundling different combinations of actions, test with various token pairs, or explore other [Compass Bundler](/v1/transaction-bundler/introduction) features to create more complex transaction bundles.
</Tip>

## Full Code

Here is the full script from the tutorial. Copy and paste into your code editor and play around!

<GithubCodeBlock
  typescript={{
name: "index.ts",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/main/v1/transaction_bundler/typescript/src/index.ts",
numOfLinesExpandable: 88,
}}
  python={{
name: "main.py",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/main/v1/transaction_bundler/python/src/main.py",
numOfLinesExpandable: 77,
}}
/>

## Resources

<CardGroup cols={2}>
  <Card title="Compass API Docs" icon="compass" href="/">
    Access detailed API documentation and references
  </Card>

  <Card title="GitHub Examples" icon="github" href="https://github.com/CompassLabs/api_usecases/tree/main/v1/transaction_bundler/">
    View more code examples and implementations
  </Card>
</CardGroup>
