> ## 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.

# Pendle: Trade fixed & variable yield

> Buy fixed yield (PT), go long variable yield (YT) and provide liquidity on Pendle protocol on Arbitrum using the Compass SDK. No Solidity needed. 

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

Pendle lets you tokenize and trade future yield. With Compass Labs, you can interact with Pendle markets - including buying/selling PT, YT, and LP positions - in just a few lines of code.

Normally this would require complex smart contract logic and allowance juggling. With Compass SDK, you abstract all of that away. This tutorial walks you through a full strategy lifecycle across fixed and variable yield.

## 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 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: "pendle.ts",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/refs/heads/main/v1/pendle/typescript/src/index.ts",
snippetNumber: 21,
}}
      python={{
name: "pendle.py",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/refs/heads/main/v1/pendle/python/src/main.py",
snippetNumber: 21,
}}
    />
  </Step>

  <Step title="Instantiate Required Clients">
    <GithubCodeBlock
      typescript={{
name: "pendle.ts",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/refs/heads/main/v1/pendle/typescript/src/index.ts",
snippetNumber: 20,
}}
      python={{
name: "pendle.py",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/refs/heads/main/v1/pendle/python/src/main.py",
snippetNumber: 20,
}}
    />
  </Step>
</Steps>

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

## Query Pendle Markets

First, we need a Pendle market on Arbitrum to perform transactions with. Let's query the list of active markets and select one we'd like to interact with.

<Steps>
  <Step title="Query Active Markets">
    Use the Pendle Markets function to query a list of active markets on Arbitrum.

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

  <Step title="Select a Market">
    For simplicity, we are selecting the first market returned of the list of
    active markets with `markets[0]`. Consider things like implied yield,
    maturity date and the underlying token when deciding which Pendle market to
    transact with.

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

  <Step title="Destructure Variables">
    Destructure variables from the selected market that will be used multiple
    times throughout the rest of the tutorial.

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

## Fixed Yield

### Buy Principal Token (PT) to Earn Fixed Yield

Now that we have decided on a Pendle market to transact with, let us take our first position in the market by buying fixed yield. Fixed yield positions are represented by **PT** tokens. The price difference between 1 **PT** and 1 **Underlying Asset** represents the fixed yield your entitled to claim after the maturity date of the market when **PT** tokens can be redeemed 1:1 for the **Underlying Asset**.

<Steps>
  <Step title="Check and Set Allowance">
    Check the current allowance given for the **Pendle Router** on the
    **USDC** contract. If that allowance is less than the amount of
    **USDC** we intend to use to purchase **PT**, then set the
    allowance to a sufficient level.

    <GithubCodeBlock
      typescript={{
name: "pendle.ts",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/refs/heads/main/v1/pendle/typescript/src/index.ts",
snippetNumber: 5,
numOfLinesExpandable: 26,
}}
      python={{
name: "pendle.py",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/refs/heads/main/v1/pendle/python/src/main.py",
snippetNumber: 5,
numOfLinesExpandable: 19,
}}
    />
  </Step>

  <Step title="Buy PT">
    Buy **PT** with 100 **USDC** and await confirmation
    that the transaction has been included on a block.

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

### Sell Principal Token (PT) Before Maturity Date

Let's say some time after we purchsed our **PT**, we notice the market offering a more favorable signal for going long on yield. This likely means the implied yield rate has come down since we first took the PT position. Before going long on yield, we may want to sell our **PT** position beforehand and use the proceeds to fund our **YT** position.

<Steps>
  <Step title="Check User Position">
    Check our current position in the Pendle market by including a user address with the Pendle Market
    function. This will allow us to obtain our current **PT** balance.

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

  <Step title="Check and Set Allowance">
    Check the current allowance given for the **Pendle Router** on the **PT**
    contract. If that allowance is less than the amount of **PT** we intend to
    sell, then set the allowance to a sufficient level.

    <GithubCodeBlock
      typescript={{
name: "pendle.ts",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/refs/heads/main/v1/pendle/typescript/src/index.ts",
snippetNumber: 8,
numOfLinesExpandable: 26,
}}
      python={{
name: "pendle.py",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/refs/heads/main/v1/pendle/python/src/main.py",
snippetNumber: 8,
numOfLinesExpandable: 19,
}}
    />
  </Step>

  <Step title="Sell PT">
    Sell our current **PT** balance for the market's **Underlying Asset** and await confirmation
    that the transaction has been included on a block.

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

<Note>
  Both **Principal Tokens (PT)** and **Yield Tokens (YT)** are ERC-20 compatible
  and, just like the **Underlying Asset**, require sufficient spending
  allowances to be set on them before a given contract can spend a user's
  balance.
</Note>

## Variable Yield

### Buy Yield Token (YT) to Earn Variable Yield

We have decided a long yield position is now favorable. This is likely because the implied yield rate has lowered. We now think that the yield generated from the **Underlying Asset** will be greater than the current implied yield from now until the market's maturity date.

<Steps>
  <Step title="Check User Position">
    Check our current position in the Pendle market by including a user address with the Pendle Market
    function. This will allow us to obtain our current **Underlying Asset** balance.

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

  <Step title="Check and Set Allowance">
    Check the current allowance given for the **Pendle Router** on the
    **Underlying Asset** contract. If that allowance is less than the amount of
    **Underlying Asset** we intend to use to purchase **YT**, then set the
    allowance to a sufficient level.

    <GithubCodeBlock
      typescript={{
name: "pendle.ts",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/refs/heads/main/v1/pendle/typescript/src/index.ts",
snippetNumber: 11,
numOfLinesExpandable: 26,
}}
      python={{
name: "pendle.py",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/refs/heads/main/v1/pendle/python/src/main.py",
snippetNumber: 11,
numOfLinesExpandable: 19,
}}
    />
  </Step>

  <Step title="Buy YT">
    Buy **YT** with our current **Underlying Asset** balance and await confirmation
    that the transaction has been included on a block.

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

### Redeem Claimable Yield and Sell YT Position

Perhaps now the implied yield has increased again and we'd like to sell our **Yield Tokens (YT)** for a profit before the maturity date of the market.

<Steps>
  <Step title="Redeem Claimable Yield">
    Redeem any outstanding claimable yield on our **YT**. This will land in our wallet in the form of the market's **Underlying Asset**.

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

  <Step title="Check User Position">
    Check our current position in the Pendle market using the `position`
    function.

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

  <Step title="Check and Set Allowance">
    Check the current allowance given for the **Pendle Router** on the **YT**
    contract. If that allowance is less than the amount of **YT** we intend to
    sell, then set the allowance to a sufficient level.

    <GithubCodeBlock
      typescript={{
name: "pendle.ts",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/refs/heads/main/v1/pendle/typescript/src/index.ts",
snippetNumber: 15,
numOfLinesExpandable: 26,
}}
      python={{
name: "pendle.py",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/refs/heads/main/v1/pendle/python/src/main.py",
snippetNumber: 15,
numOfLinesExpandable: 19,
}}
    />
  </Step>

  <Step title="Sell YT">
    Sell **YT** for **USDT** this time and await confirmation
    that the transaction has been included on a block.

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

<Warning>
  It's best practice to always redeem claimable yield before selling any of your
  YT balance. Once the YT is sold, you relinquish ownership and thus lose the
  ability to claim any yield, as the yield rights are tied to the token itself,
  not your past ownership.
</Warning>

## Provide Liquidity

### Add Liquidity (LP)

Let's say we are uncertain whether to take fixed yield or go long yield in a particular Pendle market but we'd still like to earn yield. Another option is to provide liquidity to the market and earn yield in the form of fees accrued by the market from other users taking positions. The liquidity you provide to a given Pendle market is represented by **LP** tokens.

<Steps>
  <Step title="Check USDT Balance">
    Check our current balance of **USDT** we obtained by selling our **YT**.

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

  <Step title="Check and Set Allowance">
    Check the current allowance given for the **Pendle Router** on the
    **USDT** contract. If that allowance is less than the amount of
    **USDT** we intend to use to purchase **LP**, then set the
    allowance to a sufficient level.

    <GithubCodeBlock
      typescript={{
name: "pendle.ts",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/refs/heads/main/v1/pendle/typescript/src/index.ts",
snippetNumber: 18,
numOfLinesExpandable: 26,
}}
      python={{
name: "pendle.py",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/refs/heads/main/v1/pendle/python/src/main.py",
snippetNumber: 18,
numOfLinesExpandable: 19,
}}
    />
  </Step>

  <Step title="Add Liquidity">
    Add liquidity with our current **USDT** balance in exchange for **LP**
    and await confirmation that the transaction has been included on a block.

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

<Tip>
  For further practice, try removing liquidity from the market, test with
  different Pendle markets, or explore [Compass
  Bundler](/v1/transaction-bundler/introduction)
  to bundle transactions.
</Tip>

## Full Code

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

<GithubCodeBlock
  typescript={{
name: "pendle.ts",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/refs/heads/main/v1/pendle/typescript/src/index.ts",
numOfLinesExpandable: 357 - 21 * 2,
}}
  python={{
name: "pendle.py",
url: "https://raw.githubusercontent.com/CompassLabs/api_usecases/refs/heads/main/v1/pendle/python/src/main.py",
numOfLinesExpandable: 290 - 21 * 2,
}}
/>
