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

# Jupiter Lend Earn instructions

> Deposit vault capital into Jupiter Lend Earn jlToken vaults through policy-gated execution

Use these instructions when your strategy vault should deposit underlying tokens into [Jupiter Lend Earn](https://jup.ag/lend) jlToken vaults. For Jupiter's collateralized borrowing product, see [Jupiter Lend Borrow instructions](/developer-strategy-vaults/jupiter-lend-borrow-instructions).

Jupiter Earn exposes eight on-chain operations split into two account groups:

* **Asset-in** (deposit / mint variants) — vault sends the underlying token, receives jlTokens.
* **Asset-out** (withdraw / redeem variants) — vault sends jlTokens, receives the underlying token.

The SDK provides one raw `createJupiterEarn*Instruction(...)` per op and matching `jupiterEarnAction.<method>(...)` wrappers that register the op as a vault step.

## Transaction structure

Every Jupiter Earn action goes through `createVaultSyncTransaction`.

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

const depositIx = createJupiterEarnDepositInstruction(assetInAccounts, 50_000_000n);

const { setupInstructions, preInstructions, instruction, postInstructions } =
  await createVaultSyncTransaction({
    instructions: [
      jupiterEarnAction.deposit({ instruction: depositIx }),
    ],
    owner: vaultPda,
    connection,
    policyPda,
    vaultPda,
    signer: wallet.publicKey,
    vaultAddress,
  });

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

| Part                | What it contains                                                                      |
| ------------------- | ------------------------------------------------------------------------------------- |
| `setupInstructions` | Setup instructions that must run before refreshes or the sync step                    |
| `preInstructions`   | Permissionless refresh instructions that must run before the sync step                |
| `instruction`       | The Squads sync transaction instruction wrapping the vault-signed Jupiter Earn action |
| `postInstructions`  | Permissionless refresh instructions that must run after the sync step                 |

## Asset-in accounts

All four asset-in operations (`deposit`, `depositWithMinAmountOut`, `mint`, `mintWithMaxAssets`) share the same `JupiterEarnAssetInAccounts` shape. Build it once and pass it into each instruction builder.

```typescript theme={null}
import type { JupiterEarnAssetInAccounts } from "@exponent-labs/exponent-sdk";
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";

const assetInAccounts: JupiterEarnAssetInAccounts = {
  signer: vaultPda,                          // Squads vault PDA — the trader signing through the policy
  depositorTokenAccount: vaultUnderlyingAta, // Vault's underlying token ATA (e.g., USDC)
  recipientTokenAccount: vaultJlTokenAta,    // Vault's jlToken ATA (will receive the receipt)
  mint: USDC_MINT,                           // Underlying token mint
  lendingAdmin: JUPITER_LENDING_ADMIN,
  lending: JUPITER_EARN_USDC_LENDING_ID,
  fTokenMint: JUPITER_EARN_USDC_JL_TOKEN_MINT_ID,
  supplyTokenReservesLiquidity: JUPITER_LEND_SUPPLY_TOKEN_RESERVES_LIQUIDITY_ID,
  lendingSupplyPositionOnLiquidity: JUPITER_LEND_LENDING_SUPPLY_POSITION_ON_LIQUIDITY_ID,
  rateModel: JUPITER_LEND_RATE_MODEL_ID,
  vault: JUPITER_LEND_VAULT_ID,
  liquidity: JUPITER_LEND_LIQUIDITY_ID,
  liquidityProgram: JUPITER_LENDING_POOLS_PROGRAM_ID,
  rewardsRateModel: JUPITER_LEND_REWARDS_RATE_MODEL_ID,
  tokenProgram: TOKEN_PROGRAM_ID,
};
```

<Tip>
  `buildJupiterLendPriceInterfaceAccounts(accounts)` returns the price-interface `AccountMeta[]` Jupiter expects for downstream price reads, derived from the same accounts struct.
</Tip>

## Deposit

`createJupiterEarnDepositInstruction(accounts, assets)` deposits an exact amount of underlying tokens and receives jlTokens at the current rate.

`createJupiterEarnDepositWithMinAmountOutInstruction(accounts, assets, minAmountOut)` is the same operation with a slippage floor on the jlTokens received.

```typescript theme={null}
import {
  createJupiterEarnDepositInstruction,
  createJupiterEarnDepositWithMinAmountOutInstruction,
  jupiterEarnAction,
} from "@exponent-labs/exponent-sdk";

// Plain deposit
const depositIx = createJupiterEarnDepositInstruction(assetInAccounts, 50_000_000n);

// Deposit with slippage floor
const depositMinIx = createJupiterEarnDepositWithMinAmountOutInstruction(
  assetInAccounts,
  50_000_000n,   // assets to deposit
  49_500_000n,   // minimum jlTokens to receive
);

// Wrap as a vault step
jupiterEarnAction.deposit({ instruction: depositIx });
jupiterEarnAction.depositWithMinAmountOut({ instruction: depositMinIx });
```

### Parameters

| Name           | Type                               | Description                                                         |
| -------------- | ---------------------------------- | ------------------------------------------------------------------- |
| `accounts`     | `JupiterEarnAssetInAccounts`       | Asset-in account set                                                |
| `assets`       | `bigint \| number \| string \| BN` | Underlying token amount in atomic units                             |
| `minAmountOut` | `bigint \| number \| string \| BN` | With-min variant only. Minimum jlTokens to receive — slippage floor |

## Mint

`createJupiterEarnMintInstruction(accounts, shares)` mints an exact amount of jlTokens, paying the current required underlying.

`createJupiterEarnMintWithMaxAssetsInstruction(accounts, shares, maxAssets)` adds a cap on the underlying spent.

```typescript theme={null}
import {
  createJupiterEarnMintInstruction,
  createJupiterEarnMintWithMaxAssetsInstruction,
  jupiterEarnAction,
} from "@exponent-labs/exponent-sdk";

const mintIx = createJupiterEarnMintInstruction(assetInAccounts, 5_000_000n);

const mintMaxIx = createJupiterEarnMintWithMaxAssetsInstruction(
  assetInAccounts,
  5_000_000n,    // jlTokens to mint
  5_100_000n,    // maximum underlying to spend
);

jupiterEarnAction.mint({ instruction: mintIx });
jupiterEarnAction.mintWithMaxAssets({ instruction: mintMaxIx });
```

### Parameters

| Name        | Type                               | Description                                         |
| ----------- | ---------------------------------- | --------------------------------------------------- |
| `accounts`  | `JupiterEarnAssetInAccounts`       | Asset-in account set                                |
| `shares`    | `bigint \| number \| string \| BN` | jlToken amount to mint, in atomic units             |
| `maxAssets` | `bigint \| number \| string \| BN` | With-max variant only. Maximum underlying spend cap |

## Asset-out accounts

The four asset-out operations (`withdraw`, `withdrawWithMaxSharesBurn`, `redeem`, `redeemWithMinAmountOut`) share `JupiterEarnAssetOutAccounts`. The shape mirrors asset-in, with the source/recipient roles flipped.

```typescript theme={null}
import type { JupiterEarnAssetOutAccounts } from "@exponent-labs/exponent-sdk";

const assetOutAccounts: JupiterEarnAssetOutAccounts = {
  signer: vaultPda,                          // Squads vault PDA
  ownerTokenAccount: vaultJlTokenAta,        // Vault's jlToken ATA — the source
  recipientTokenAccount: vaultUnderlyingAta, // Vault's underlying ATA — receives the unwound underlying
  lendingAdmin: JUPITER_LENDING_ADMIN,
  lending: JUPITER_EARN_USDC_LENDING_ID,
  mint: USDC_MINT,
  fTokenMint: JUPITER_EARN_USDC_JL_TOKEN_MINT_ID,
  supplyTokenReservesLiquidity: JUPITER_LEND_SUPPLY_TOKEN_RESERVES_LIQUIDITY_ID,
  lendingSupplyPositionOnLiquidity: JUPITER_LEND_LENDING_SUPPLY_POSITION_ON_LIQUIDITY_ID,
  rateModel: JUPITER_LEND_RATE_MODEL_ID,
  vault: JUPITER_LEND_VAULT_ID,
  liquidity: JUPITER_LEND_LIQUIDITY_ID,
  liquidityProgram: JUPITER_LENDING_POOLS_PROGRAM_ID,
  rewardsRateModel: JUPITER_LEND_REWARDS_RATE_MODEL_ID,
  claimAccount: JUPITER_CLAIM_ACCOUNT,
  tokenProgram: TOKEN_PROGRAM_ID,
};
```

## Withdraw

`createJupiterEarnWithdrawInstruction(accounts, amount)` withdraws an exact amount of underlying by burning the implied jlTokens at the current rate.

`createJupiterEarnWithdrawWithMaxSharesBurnInstruction(accounts, amount, maxSharesBurn)` adds a cap on the jlTokens burned.

```typescript theme={null}
import {
  createJupiterEarnWithdrawInstruction,
  createJupiterEarnWithdrawWithMaxSharesBurnInstruction,
  jupiterEarnAction,
} from "@exponent-labs/exponent-sdk";

const withdrawIx = createJupiterEarnWithdrawInstruction(assetOutAccounts, 25_000_000n);

const withdrawMaxIx = createJupiterEarnWithdrawWithMaxSharesBurnInstruction(
  assetOutAccounts,
  25_000_000n,   // underlying to withdraw
  26_000_000n,   // maximum jlTokens to burn
);

jupiterEarnAction.withdraw({ instruction: withdrawIx });
jupiterEarnAction.withdrawWithMaxSharesBurn({ instruction: withdrawMaxIx });
```

### Parameters

| Name            | Type                               | Description                                      |
| --------------- | ---------------------------------- | ------------------------------------------------ |
| `accounts`      | `JupiterEarnAssetOutAccounts`      | Asset-out account set                            |
| `amount`        | `bigint \| number \| string \| BN` | Underlying amount to withdraw, in atomic units   |
| `maxSharesBurn` | `bigint \| number \| string \| BN` | With-max variant only. Maximum jlTokens burn cap |

## Redeem

`createJupiterEarnRedeemInstruction(accounts, shares)` redeems an exact amount of jlTokens for underlying at the current rate.

`createJupiterEarnRedeemWithMinAmountOutInstruction(accounts, shares, minAmountOut)` adds a slippage floor on the underlying received.

```typescript theme={null}
import {
  createJupiterEarnRedeemInstruction,
  createJupiterEarnRedeemWithMinAmountOutInstruction,
  jupiterEarnAction,
} from "@exponent-labs/exponent-sdk";

const redeemIx = createJupiterEarnRedeemInstruction(assetOutAccounts, 5_000_000n);

const redeemMinIx = createJupiterEarnRedeemWithMinAmountOutInstruction(
  assetOutAccounts,
  5_000_000n,    // jlTokens to redeem
  4_950_000n,    // minimum underlying to receive
);

jupiterEarnAction.redeem({ instruction: redeemIx });
jupiterEarnAction.redeemWithMinAmountOut({ instruction: redeemMinIx });
```

### Parameters

| Name           | Type                               | Description                                     |
| -------------- | ---------------------------------- | ----------------------------------------------- |
| `accounts`     | `JupiterEarnAssetOutAccounts`      | Asset-out account set                           |
| `shares`       | `bigint \| number \| string \| BN` | jlTokens to redeem, in atomic units             |
| `minAmountOut` | `bigint \| number \| string \| BN` | With-min variant only. Minimum underlying floor |

## Action wrappers

Every Earn op has a matching `jupiterEarnAction.<method>` that registers the raw instruction as a vault step. All wrappers take a single `{ instruction }` object.

| Wrapper                                       | Pairs with                                              |
| --------------------------------------------- | ------------------------------------------------------- |
| `jupiterEarnAction.deposit`                   | `createJupiterEarnDepositInstruction`                   |
| `jupiterEarnAction.depositWithMinAmountOut`   | `createJupiterEarnDepositWithMinAmountOutInstruction`   |
| `jupiterEarnAction.mint`                      | `createJupiterEarnMintInstruction`                      |
| `jupiterEarnAction.mintWithMaxAssets`         | `createJupiterEarnMintWithMaxAssetsInstruction`         |
| `jupiterEarnAction.withdraw`                  | `createJupiterEarnWithdrawInstruction`                  |
| `jupiterEarnAction.withdrawWithMaxSharesBurn` | `createJupiterEarnWithdrawWithMaxSharesBurnInstruction` |
| `jupiterEarnAction.redeem`                    | `createJupiterEarnRedeemInstruction`                    |
| `jupiterEarnAction.redeemWithMinAmountOut`    | `createJupiterEarnRedeemWithMinAmountOutInstruction`    |

## Constants

| Constant                       | Description                                                              |
| ------------------------------ | ------------------------------------------------------------------------ |
| `JUPITER_LEND_EARN_PROGRAM_ID` | Jupiter Lend Earn program: `jup3YeL8QhtSx1e253b2FDvsMNC87fDrgQZivbrndc9` |

For policy authoring or custom data-constraint work, the SDK also exports `JUPITER_EARN_DISCRIMINATORS` (per-action discriminators) and `JUPITER_EARN_ACCOUNT_INDICES` (account-index maps for asset-in and asset-out paths).

A matching policy must exist before executing. See [Jupiter Lend Earn Policy](/developer-strategy-vaults/policy-builders#jupiter-lend-earn-policy).

## Full flow example

This example deposits underlying into a Jupiter Earn vault, then unwinds with a redeem.

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

// Step 1: Deposit 50 USDC into the jlUSDC vault.
{
  const depositIx = createJupiterEarnDepositInstruction(assetInAccounts, 50_000_000n);
  const { setupInstructions, preInstructions, instruction, postInstructions } =
    await createVaultSyncTransaction({
      instructions: [jupiterEarnAction.deposit({ instruction: depositIx })],
      owner: vaultPda,
      connection,
      policyPda,
      vaultPda,
      signer: wallet.publicKey,
      vaultAddress,
    });
  const tx = new Transaction().add(
    ...setupInstructions,
    ...preInstructions,
    instruction,
    ...postInstructions,
  );
  await sendAndConfirmTransaction(connection, tx, [wallet]);
}

// Step 2: Redeem 5 jlUSDC back to underlying.
{
  const redeemIx = createJupiterEarnRedeemInstruction(assetOutAccounts, 5_000_000n);
  const { setupInstructions, preInstructions, instruction, postInstructions } =
    await createVaultSyncTransaction({
      instructions: [jupiterEarnAction.redeem({ instruction: redeemIx })],
      owner: vaultPda,
      connection,
      policyPda,
      vaultPda,
      signer: wallet.publicKey,
      vaultAddress,
    });
  const tx = new Transaction().add(
    ...setupInstructions,
    ...preInstructions,
    instruction,
    ...postInstructions,
  );
  await sendAndConfirmTransaction(connection, tx, [wallet]);
}
```
