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

# Exponent Core Instructions

> Strip and merge yield assets through policy-gated vault execution

The core instructions module enables vault managers and allocators to strip base tokens (e.g., LSTs) into PT (Principal Tokens) and YT (Yield Tokens), and merge them back. All interactions are executed as Squads sync transactions validated against onchain policies.

For background on how stripping and merging works, see [Core Concepts](/developer-core/core-concepts).

## Transaction Structure

Every core interaction goes through `createVaultSyncTransaction`, which returns three parts:

```typescript theme={null}
const { preInstructions, instruction, postInstructions } =
  await createVaultSyncTransaction({
    instructions,   // Array of VaultInstruction descriptors
    owner,          // Vault PDA (the Squads smart account)
    connection,
    policyPda,      // Policy authorizing this execution
    vaultPda,       // Squads vault PDA
    signer,         // The allocator or manager wallet
    vaultAddress,   // ExponentStrategyVault PDA (auto-resolves hook accounts)
  });

// Send all three parts in order
const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);
```

| Part               | What it contains                                               | Why it's separate                                 |
| ------------------ | -------------------------------------------------------------- | ------------------------------------------------- |
| `preInstructions`  | Any permissionless setup instructions                          | Must be top-level instructions                    |
| `instruction`      | Squads sync transaction wrapping all vault-signed instructions | Executes with the vault's smart account as signer |
| `postInstructions` | Any post-operation instructions                                | Must be top-level instructions                    |

***

## Initialize Yield Position

Before the vault can strip or merge tokens, a yield position account must exist on the Exponent Core program. `coreAction.initializeYieldPosition` creates this account.

<Note>
  Orderbook and CLMM operations automatically initialize the yield position if it doesn't exist. You only need to call this manually if strip or merge is your **first** Core interaction for a given vault.
</Note>

```typescript theme={null}
import {
  coreAction,
  createVaultSyncTransaction,
} from "@exponent-labs/exponent-sdk";

const { preInstructions, instruction, postInstructions } =
  await createVaultSyncTransaction({
    instructions: [
      coreAction.initializeYieldPosition({
        vault: new PublicKey("..."),       // Exponent Core vault address
      }),
    ],
    owner: vaultPda,
    connection,
    policyPda,
    vaultPda,
    signer: wallet.publicKey,
    vaultAddress,
  });

const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);
```

### Parameters

| Parameter | Type        | Description                                                                         |
| --------- | ----------- | ----------------------------------------------------------------------------------- |
| `vault`   | `PublicKey` | The Exponent Core vault address (the yield-stripping vault, not the strategy vault) |

A matching policy must exist before executing. See [Policy Builders](/vault-sdk/typescript/manager-operations/policy-builders#core-policy).

***

## Strip

`coreAction.strip` strips a base token (e.g., an LST like JitoSOL) into equal amounts of PT and YT through the Exponent Core program.

```typescript theme={null}
import {
  coreAction,
  createVaultSyncTransaction,
} from "@exponent-labs/exponent-sdk";

const { preInstructions, instruction, postInstructions } =
  await createVaultSyncTransaction({
    instructions: [
      coreAction.strip({
        vault: new PublicKey("..."),       // Exponent Core vault address
        amountBase: 1_000_000_000n,       // 1 token in native units
      }),
    ],
    owner: vaultPda,
    connection,
    policyPda,
    vaultPda,
    signer: wallet.publicKey,
    vaultAddress,
  });

const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);
```

### Parameters

| Parameter    | Type        | Description                                                                         |
| ------------ | ----------- | ----------------------------------------------------------------------------------- |
| `vault`      | `PublicKey` | The Exponent Core vault address (the yield-stripping vault, not the strategy vault) |
| `amountBase` | `bigint`    | Amount of base token to strip, in native units                                      |

A matching policy must exist before executing. See [Policy Builders](/vault-sdk/typescript/manager-operations/policy-builders#core-policy).

***

## Merge

`coreAction.merge` merges equal amounts of PT and YT back into the base token.

```typescript theme={null}
const { preInstructions, instruction, postInstructions } =
  await createVaultSyncTransaction({
    instructions: [
      coreAction.merge({
        vault: new PublicKey("..."),
        amountPy: 1_000_000_000n,       // Must hold equal PT and YT
      }),
    ],
    owner: vaultPda,
    connection,
    policyPda,
    vaultPda,
    signer: wallet.publicKey,
    vaultAddress,
  });

const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);
```

### Parameters

| Parameter  | Type        | Description                                                |
| ---------- | ----------- | ---------------------------------------------------------- |
| `vault`    | `PublicKey` | The Exponent Core vault address                            |
| `amountPy` | `bigint`    | Amount of PT/YT to merge — must hold equal amounts of both |

<Warning>
  The merge operation requires the vault to hold equal amounts of PT and YT. If the vault holds 100 PT and 80 YT, you can merge at most 80.
</Warning>

A matching policy must exist before executing. See [Policy Builders](/developer-strategy-vaults/typescript/policy-builders).

***

## AMM (Market Two) Swaps

The AMM (Market Two) is the legacy AMM market type on the `exponent_core` program. The SDK exposes its three swap operations as `marketTwoAction.tradePt`, `marketTwoAction.buyYt`, and `marketTwoAction.sellYt`. Each one trades against the market's underlying SY mint.

### Trade PT

`marketTwoAction.tradePt` is a bidirectional PT/SY swap. The sign of `netTraderPt` selects the direction; `syConstraint` is the signed slippage bound matching the on-chain handler.

```typescript theme={null}
import {
  marketTwoAction,
  createVaultSyncTransaction,
} from "@exponent-labs/exponent-sdk";

const { preInstructions, instruction, postInstructions } =
  await createVaultSyncTransaction({
    instructions: [
      marketTwoAction.tradePt({
        market: new PublicKey("..."),
        netTraderPt: 1_000_000_000n,    // positive = buy PT (spend SY), negative = sell PT (receive SY)
        syConstraint: 950_000_000n,     // signed slippage bound
      }),
    ],
    owner: vaultPda,
    connection,
    policyPda,
    vaultPda,
    signer: wallet.publicKey,
    vaultAddress,
  });

const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);
```

#### Parameters

| Parameter      | Type        | Description                                                        |
| -------------- | ----------- | ------------------------------------------------------------------ |
| `market`       | `PublicKey` | The Market Two PDA being traded against                            |
| `netTraderPt`  | `bigint`    | Signed PT amount. Positive = buy PT (spend SY); negative = sell PT |
| `syConstraint` | `bigint`    | Signed SY slippage bound matching the on-chain `trade_pt` handler  |

A matching policy must exist before executing. See [AMM Swap Policies](/developer-strategy-vaults/policy-builders#amm-swap-policies).

### Buy YT

`marketTwoAction.buyYt` buys YT with SY. PT is transient inside the same instruction.

```typescript theme={null}
const { preInstructions, instruction, postInstructions } =
  await createVaultSyncTransaction({
    instructions: [
      marketTwoAction.buyYt({
        market: new PublicKey("..."),
        syIn: 100_000_000n,              // Maximum SY to spend
        ytOut: 1_000_000_000n,           // Target YT to receive
      }),
    ],
    owner: vaultPda,
    connection,
    policyPda,
    vaultPda,
    signer: wallet.publicKey,
    vaultAddress,
  });

const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);
```

#### Parameters

| Parameter | Type        | Description                               |
| --------- | ----------- | ----------------------------------------- |
| `market`  | `PublicKey` | The Market Two PDA being traded against   |
| `syIn`    | `bigint`    | Maximum SY the trader is willing to spend |
| `ytOut`   | `bigint`    | Target YT to receive                      |

A matching policy must exist before executing. See [AMM Swap Policies](/developer-strategy-vaults/policy-builders#amm-swap-policies).

### Sell YT

`marketTwoAction.sellYt` sells YT for SY. PT is transient inside the same instruction.

```typescript theme={null}
const { preInstructions, instruction, postInstructions } =
  await createVaultSyncTransaction({
    instructions: [
      marketTwoAction.sellYt({
        market: new PublicKey("..."),
        ytIn: 1_000_000_000n,            // YT to sell
        minSyOut: 95_000_000n,           // Slippage floor
      }),
    ],
    owner: vaultPda,
    connection,
    policyPda,
    vaultPda,
    signer: wallet.publicKey,
    vaultAddress,
  });

const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);
```

#### Parameters

| Parameter  | Type        | Description                             |
| ---------- | ----------- | --------------------------------------- |
| `market`   | `PublicKey` | The Market Two PDA being traded against |
| `ytIn`     | `bigint`    | YT to sell                              |
| `minSyOut` | `bigint`    | Minimum SY to receive — slippage floor  |

A matching policy must exist before executing. See [AMM Swap Policies](/developer-strategy-vaults/policy-builders#amm-swap-policies).

***

## Full Flow Example

This example demonstrates stripping a base token into PT + YT, then merging them back.

### Step 1: Strip Base Token into PT + YT

```typescript theme={null}
import {
  coreAction,
  createVaultSyncTransaction,
} from "@exponent-labs/exponent-sdk";
import { Connection, PublicKey, Transaction, sendAndConfirmTransaction } from "@solana/web3.js";

const connection = new Connection("https://api.mainnet-beta.solana.com");

const EXPONENT_VAULT = new PublicKey("..."); // Exponent Core vault

const { preInstructions, instruction, postInstructions } =
  await createVaultSyncTransaction({
    instructions: [
      coreAction.strip({
        vault: EXPONENT_VAULT,
        amountBase: 2_000_000_000n,   // 2 tokens
      }),
    ],
    owner: vaultPda,
    connection,
    policyPda,
    vaultPda,
    signer: wallet.publicKey,
    vaultAddress,
  });

const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);
```

### Step 2: Merge PT + YT Back to Base Token

```typescript theme={null}
const { preInstructions, instruction, postInstructions } =
  await createVaultSyncTransaction({
    instructions: [
      coreAction.merge({
        vault: EXPONENT_VAULT,
        amountPy: 2_000_000_000n,
      }),
    ],
    owner: vaultPda,
    connection,
    policyPda,
    vaultPda,
    signer: wallet.publicKey,
    vaultAddress,
  });

const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);
```
