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

# Earn CPI Integration

> Cross-Program Invocation integration for Jupiter Lend Earn deposit and withdraw.

This guide covers Cross-Program Invocation (CPI) integration for the Earn protocol's deposit and withdraw functions. Use this when your on-chain program needs to call Jupiter Lend Earn directly.

For TypeScript SDK integration (off-chain), see [Deposit](https://developers.jup.ag/docs/lend/earn/deposit.md) and [Withdraw](https://developers.jup.ag/docs/lend/earn/withdraw.md).

## Program Addresses

| Program | Mainnet | Devnet |
| - | - | - |
| Lending | `jup3YeL8QhtSx1e253b2FDvsMNC87fDrgQZivbrndc9` | `7tjE28izRUjzmxC1QNXnNwcc4N82CNYCexf3k8mw67s3` |
| Liquidity | `jupeiUmn818Jg1ekPURTpr4mFo29p46vygyykFJ3wZC` | `5uDkCoM96pwGYhAUucvCzLfm5UcjVRuxz6gH81RnRBmL` |

***

## Deposit CPI

### Discriminator

```rust theme={null}
fn get_deposit_discriminator() -> Vec<u8> {
    // discriminator = sha256("global:deposit")[0..8]
    vec![242, 35, 198, 137, 82, 225, 242, 182]
}
```

### Deposit CPI Struct

```rust theme={null}
pub struct DepositParams<'info> {
    // User accounts
    pub signer: AccountInfo<'info>,
    pub depositor_token_account: AccountInfo<'info>,
    pub recipient_token_account: AccountInfo<'info>,

    pub mint: AccountInfo<'info>,

    // Protocol accounts
    pub lending_admin: AccountInfo<'info>,
    pub lending: AccountInfo<'info>,
    pub f_token_mint: AccountInfo<'info>,

    // Liquidity protocol accounts
    pub supply_token_reserves_liquidity: AccountInfo<'info>,
    pub lending_supply_position_on_liquidity: AccountInfo<'info>,
    pub rate_model: AccountInfo<'info>,
    pub vault: AccountInfo<'info>,
    pub liquidity: AccountInfo<'info>,
    pub liquidity_program: AccountInfo<'info>,

    // Rewards and programs
    pub rewards_rate_model: AccountInfo<'info>,
    pub token_program: AccountInfo<'info>,
    pub associated_token_program: AccountInfo<'info>,
    pub system_program: AccountInfo<'info>,

    // Target lending program
    pub lending_program: UncheckedAccount<'info>,
}
```

### Deposit Implementation

```rust theme={null}
impl<'info> DepositParams<'info> {
    pub fn deposit(&self, amount: u64) -> Result<()> {
        let mut instruction_data = get_deposit_discriminator();
        instruction_data.extend_from_slice(&amount.to_le_bytes());

        let account_metas = vec![
            AccountMeta::new(*self.signer.key, true),
            AccountMeta::new(*self.depositor_token_account.key, false),
            AccountMeta::new(*self.recipient_token_account.key, false),
            AccountMeta::new_readonly(*self.mint.key, false),
            AccountMeta::new_readonly(*self.lending_admin.key, false),
            AccountMeta::new(*self.lending.key, false),
            AccountMeta::new(*self.f_token_mint.key, false),
            AccountMeta::new(*self.supply_token_reserves_liquidity.key, false),
            AccountMeta::new(*self.lending_supply_position_on_liquidity.key, false),
            AccountMeta::new_readonly(*self.rate_model.key, false),
            AccountMeta::new(*self.vault.key, false),
            AccountMeta::new(*self.liquidity.key, false),
            AccountMeta::new(*self.liquidity_program.key, false),
            AccountMeta::new_readonly(*self.rewards_rate_model.key, false),
            AccountMeta::new_readonly(*self.token_program.key, false),
            AccountMeta::new_readonly(*self.associated_token_program.key, false),
            AccountMeta::new_readonly(*self.system_program.key, false),
        ];

        let instruction = Instruction {
            program_id: *self.lending_program.key,
            accounts: account_metas,
            data: instruction_data,
        };

        invoke(&instruction, &[
            self.signer.clone(), self.depositor_token_account.clone(),
            self.recipient_token_account.clone(), self.mint.clone(),
            self.lending_admin.clone(), self.lending.clone(),
            self.f_token_mint.clone(), self.supply_token_reserves_liquidity.clone(),
            self.lending_supply_position_on_liquidity.clone(), self.rate_model.clone(),
            self.vault.clone(), self.liquidity.clone(),
            self.liquidity_program.clone(), self.rewards_rate_model.clone(),
            self.token_program.clone(), self.associated_token_program.clone(),
            self.system_program.clone(),
        ]).map_err(|_| ErrorCodes::CpiToLendingProgramFailed.into())
    }
}
```

### Deposit Account Explanations

| Account | Purpose | Mutability |
| - | - | - |
| `signer` | User performing deposit | Mutable, signer |
| `depositor_token_account` | User's underlying token account (source) | Mutable |
| `recipient_token_account` | User's jlToken account (destination) | Mutable |
| `mint` | Underlying token mint | Immutable |
| `lending_admin` | Protocol configuration PDA | Immutable |
| `lending` | Pool-specific configuration PDA | Mutable |
| `f_token_mint` | jlToken mint account | Mutable |
| `supply_token_reserves_liquidity` | Liquidity protocol token reserves | Mutable |
| `lending_supply_position_on_liquidity` | Protocol's position in liquidity pool | Mutable |
| `rate_model` | Interest rate calculation model | Immutable |
| `vault` | Protocol vault holding deposited tokens | Mutable |
| `liquidity` | Main liquidity protocol PDA | Mutable |
| `liquidity_program` | Liquidity protocol program ID | Mutable |
| `rewards_rate_model` | Rewards calculation model PDA | Immutable |

***

## Withdraw CPI

### Discriminator

```rust theme={null}
fn get_withdraw_discriminator() -> Vec<u8> {
    // discriminator = sha256("global:withdraw")[0..8]
    vec![183, 18, 70, 156, 148, 109, 161, 34]
}
```

### Withdraw CPI Struct

```rust theme={null}
pub struct WithdrawParams<'info> {
    // User accounts
    pub signer: AccountInfo<'info>,
    pub owner_token_account: AccountInfo<'info>,
    pub recipient_token_account: AccountInfo<'info>,

    // Protocol accounts
    pub lending_admin: AccountInfo<'info>,
    pub lending: AccountInfo<'info>,
    pub mint: AccountInfo<'info>,
    pub f_token_mint: AccountInfo<'info>,

    // Liquidity protocol accounts
    pub supply_token_reserves_liquidity: AccountInfo<'info>,
    pub lending_supply_position_on_liquidity: AccountInfo<'info>,
    pub rate_model: AccountInfo<'info>,
    pub vault: AccountInfo<'info>,
    pub claim_account: AccountInfo<'info>,
    pub liquidity: AccountInfo<'info>,
    pub liquidity_program: AccountInfo<'info>,

    // Rewards and programs
    pub rewards_rate_model: AccountInfo<'info>,
    pub token_program: AccountInfo<'info>,
    pub associated_token_program: AccountInfo<'info>,
    pub system_program: AccountInfo<'info>,

    // Target lending program
    pub lending_program: UncheckedAccount<'info>,
}
```

### Withdraw Account Explanations

| Account | Purpose | Mutability |
| - | - | - |
| `signer` | User performing withdrawal | Mutable, signer |
| `owner_token_account` | User's jlToken account (source, burned) | Mutable |
| `recipient_token_account` | User's underlying token account (destination) | Mutable |
| `lending_admin` | Protocol configuration PDA | Immutable |
| `lending` | Pool-specific configuration PDA | Mutable |
| `mint` | Underlying token mint | Immutable |
| `f_token_mint` | jlToken mint account (burned from supply) | Mutable |
| `supply_token_reserves_liquidity` | Liquidity protocol token reserves | Mutable |
| `lending_supply_position_on_liquidity` | Protocol's position in liquidity pool | Mutable |
| `rate_model` | Interest rate calculation model | Immutable |
| `vault` | Protocol vault (source of withdrawn tokens) | Mutable |
| `claim_account` | Handles withdrawal claim processing | Mutable |
| `liquidity` | Main liquidity protocol PDA | Mutable |
| `liquidity_program` | Liquidity protocol program ID | Mutable |
| `rewards_rate_model` | Rewards calculation model PDA | Immutable |

***

## Context Helpers (TypeScript)

For frontend/client code that needs to resolve CPI accounts, the SDK provides context helpers that return all required account addresses:

```typescript theme={null}
import { getDepositContext, getWithdrawContext } from "@jup-ag/lend/earn";

// Get all accounts needed for a deposit CPI
const depositContext = await getDepositContext({
  asset: usdcMint,
  signer: userPublicKey,
});

// Get all accounts needed for a withdraw CPI
const withdrawContext = await getWithdrawContext({
  asset: usdcMint,
  signer: userPublicKey,
});

// Pass these accounts to your Anchor program
await program.methods
  .yourDepositMethod(amount)
  .accounts({
    signer: depositContext.signer,
    depositorTokenAccount: depositContext.depositorTokenAccount,
    recipientTokenAccount: depositContext.recipientTokenAccount,
    lendingAdmin: depositContext.lendingAdmin,
    lending: depositContext.lending,
    fTokenMint: depositContext.fTokenMint,
    // ... all other accounts from context
    lendingProgram: new PublicKey("jup3YeL8QhtSx1e253b2FDvsMNC87fDrgQZivbrndc9"),
  })
  .rpc();
```

***

## Key Notes

### Account Derivation

Most accounts follow standard PDA derivation patterns:

* Lending PDA: `[LENDING_SEED, mint.key(), f_token_mint.key()]`
* jlToken Mint: `[F_TOKEN_MINT_SEED, mint.key()]`
* Lending Admin: `[LENDING_ADMIN_SEED]`

### Special Considerations

* **Amount = u64::MAX**: Deposits/withdraws the entire balance
* **Account Creation**: ATA accounts are created automatically when needed (`init_if_needed`)
* **Claim Account**: Only present in withdraw operations for processing withdrawal claims

### Error Codes

| Error | Description |
| - | - |
| `FTokenMinAmountOut` | Slippage protection triggered |
| `FTokenMaxAmount` | Maximum amount exceeded |
| `FTokenOnlyAuth` | Unauthorised operation |
| `FTokenOnlyRebalancer` | Rebalancer-only operation |
| `CpiToLendingProgramFailed` | CPI call failed |

### Return Values

* `deposit()` returns shares minted
* `withdraw()` returns shares burned


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.