From b906e3dc7819dfed59ba6f96c50437003d6aa987 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Fri, 30 Sep 2022 13:21:01 +0200 Subject: [PATCH] Token deposit: Split into signed and permissionless ix Token accounts are a limited resource, so allowing other users to make use of them can cause problems. --- client/src/client.rs | 1 + .../src/instructions/token_deposit.rs | 224 ++++++++++++------ programs/mango-v4/src/lib.rs | 7 + .../tests/program_test/mango_client.rs | 71 ++++++ .../tests/program_test/mango_setup.rs | 1 + .../mango-v4/tests/test_bankrupt_tokens.rs | 7 + programs/mango-v4/tests/test_basic.rs | 1 + .../mango-v4/tests/test_health_compute.rs | 2 + programs/mango-v4/tests/test_health_region.rs | 2 + programs/mango-v4/tests/test_liq_perps.rs | 2 + programs/mango-v4/tests/test_liq_tokens.rs | 3 + programs/mango-v4/tests/test_margin_trade.rs | 1 + .../mango-v4/tests/test_perp_settle_fees.rs | 4 + .../mango-v4/tests/test_position_lifetime.rs | 34 ++- ts/client/src/client.ts | 1 + ts/client/src/mango_v4.ts | 112 +++++++++ 16 files changed, 402 insertions(+), 71 deletions(-) diff --git a/client/src/client.rs b/client/src/client.rs index cba8d94db..849831e47 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -344,6 +344,7 @@ impl MangoClient { &mango_v4::accounts::TokenDeposit { group: self.group(), account: self.mango_account_address, + owner: self.owner(), bank: mint_info.first_bank(), vault: mint_info.first_vault(), oracle: mint_info.oracle, diff --git a/programs/mango-v4/src/instructions/token_deposit.rs b/programs/mango-v4/src/instructions/token_deposit.rs index e040dd9dc..17dd3bd29 100644 --- a/programs/mango-v4/src/instructions/token_deposit.rs +++ b/programs/mango-v4/src/instructions/token_deposit.rs @@ -11,8 +11,9 @@ use crate::util::checked_math as cm; use crate::logs::{DepositLog, TokenBalanceLog}; +// Same as TokenDeposit, but without the owner signing #[derive(Accounts)] -pub struct TokenDeposit<'info> { +pub struct TokenDepositIntoExisting<'info> { pub group: AccountLoader<'info, Group>, #[account(mut, has_one = group)] @@ -41,8 +42,50 @@ pub struct TokenDeposit<'info> { pub token_program: Program<'info, Token>, } -impl<'info> TokenDeposit<'info> { - pub fn transfer_ctx(&self) -> CpiContext<'_, '_, '_, 'info, token::Transfer<'info>> { +#[derive(Accounts)] +pub struct TokenDeposit<'info> { + pub group: AccountLoader<'info, Group>, + + #[account(mut, has_one = group, has_one = owner)] + pub account: AccountLoaderDynamic<'info, MangoAccount>, + pub owner: Signer<'info>, + + #[account( + mut, + has_one = group, + has_one = vault, + has_one = oracle, + // the mints of bank/vault/token_account are implicitly the same because + // spl::token::transfer succeeds between token_account and vault + )] + pub bank: AccountLoader<'info, Bank>, + + #[account(mut)] + pub vault: Account<'info, TokenAccount>, + + /// CHECK: The oracle can be one of several different account types + pub oracle: UncheckedAccount<'info>, + + #[account(mut)] + pub token_account: Box>, + pub token_authority: Signer<'info>, + + pub token_program: Program<'info, Token>, +} + +struct DepositCommon<'a, 'info> { + pub group: &'a AccountLoader<'info, Group>, + pub account: &'a AccountLoaderDynamic<'info, MangoAccount>, + pub bank: &'a AccountLoader<'info, Bank>, + pub vault: &'a Account<'info, TokenAccount>, + pub oracle: &'a UncheckedAccount<'info>, + pub token_account: &'a Box>, + pub token_authority: &'a Signer<'info>, + pub token_program: &'a Program<'info, Token>, +} + +impl<'a, 'info> DepositCommon<'a, 'info> { + fn transfer_ctx(&self) -> CpiContext<'_, '_, '_, 'info, token::Transfer<'info>> { let program = self.token_program.to_account_info(); let accounts = token::Transfer { from: self.token_account.to_account_info(), @@ -51,78 +94,119 @@ impl<'info> TokenDeposit<'info> { }; CpiContext::new(program, accounts) } + + fn deposit_into_existing( + &self, + remaining_accounts: &[AccountInfo], + amount: u64, + allow_token_account_closure: bool, + ) -> Result<()> { + require_msg!(amount > 0, "deposit amount must be positive"); + + let token_index = self.bank.load()?.token_index; + + // Get the account's position for that token index + let mut account = self.account.load_mut()?; + + let (position, raw_token_index) = account.token_position_mut(token_index)?; + + let amount_i80f48 = I80F48::from(amount); + let position_is_active = { + let mut bank = self.bank.load_mut()?; + bank.deposit(position, amount_i80f48)? + }; + + // Transfer the actual tokens + token::transfer(self.transfer_ctx(), amount)?; + + let indexed_position = position.indexed_position; + let bank = self.bank.load()?; + let oracle_price = bank.oracle_price(&AccountInfoRef::borrow(self.oracle.as_ref())?)?; + + // Update the net deposits - adjust by price so different tokens are on the same basis (in USD terms) + let amount_usd = cm!(amount_i80f48 * oracle_price).to_num::(); + cm!(account.fixed.net_deposits += amount_usd); + + emit!(TokenBalanceLog { + mango_group: self.group.key(), + mango_account: self.account.key(), + token_index, + indexed_position: indexed_position.to_bits(), + deposit_index: bank.deposit_index.to_bits(), + borrow_index: bank.borrow_index.to_bits(), + }); + + // + // Health computation + // + // Since depositing can only increase health, we can skip the usual pre-health computation. + // Also, TokenDeposit is one of the rare instructions that is allowed even during being_liquidated. + // + if !account.fixed.is_in_health_region() { + let retriever = + new_fixed_order_account_retriever(remaining_accounts, &account.borrow())?; + let health = compute_health(&account.borrow(), HealthType::Init, &retriever) + .context("post-deposit init health")?; + msg!("health: {}", health); + account.fixed.maybe_recover_from_being_liquidated(health); + } + + // + // Deactivate the position only after the health check because the user passed in + // remaining_accounts for all banks/oracles, including the account that will now be + // deactivated. + // Deposits can deactivate a position if they cancel out a previous borrow. + // + if allow_token_account_closure && !position_is_active { + account.deactivate_token_position_and_log(raw_token_index, self.account.key()); + } + + emit!(DepositLog { + mango_group: self.group.key(), + mango_account: self.account.key(), + signer: self.token_authority.key(), + token_index, + quantity: amount, + price: oracle_price.to_bits(), + }); + + Ok(()) + } } pub fn token_deposit(ctx: Context, amount: u64) -> Result<()> { - require_msg!(amount > 0, "deposit amount must be positive"); - - let token_index = ctx.accounts.bank.load()?.token_index; - - // Get the account's position for that token index - let mut account = ctx.accounts.account.load_mut()?; - - let (position, raw_token_index, _active_token_index) = + { + let token_index = ctx.accounts.bank.load()?.token_index; + let mut account = ctx.accounts.account.load_mut()?; account.ensure_token_position(token_index)?; - - let amount_i80f48 = I80F48::from(amount); - let position_is_active = { - let mut bank = ctx.accounts.bank.load_mut()?; - bank.deposit(position, amount_i80f48)? - }; - - // Transfer the actual tokens - token::transfer(ctx.accounts.transfer_ctx(), amount)?; - - let indexed_position = position.indexed_position; - let bank = ctx.accounts.bank.load()?; - let oracle_price = bank.oracle_price(&AccountInfoRef::borrow(ctx.accounts.oracle.as_ref())?)?; - - // Update the net deposits - adjust by price so different tokens are on the same basis (in USD terms) - let amount_usd = cm!(amount_i80f48 * oracle_price).to_num::(); - cm!(account.fixed.net_deposits += amount_usd); - - emit!(TokenBalanceLog { - mango_group: ctx.accounts.group.key(), - mango_account: ctx.accounts.account.key(), - token_index, - indexed_position: indexed_position.to_bits(), - deposit_index: bank.deposit_index.to_bits(), - borrow_index: bank.borrow_index.to_bits(), - }); - - // - // Health computation - // - // Since depositing can only increase health, we can skip the usual pre-health computation. - // Also, TokenDeposit is one of the rare instructions that is allowed even during being_liquidated. - // - if !account.fixed.is_in_health_region() { - let retriever = - new_fixed_order_account_retriever(ctx.remaining_accounts, &account.borrow())?; - let health = compute_health(&account.borrow(), HealthType::Init, &retriever) - .context("post-deposit init health")?; - msg!("health: {}", health); - account.fixed.maybe_recover_from_being_liquidated(health); } - // - // Deactivate the position only after the health check because the user passed in - // remaining_accounts for all banks/oracles, including the account that will now be - // deactivated. - // Deposits can deactivate a position if they cancel out a previous borrow. - // - if !position_is_active { - account.deactivate_token_position_and_log(raw_token_index, ctx.accounts.account.key()); + DepositCommon { + group: &ctx.accounts.group, + account: &ctx.accounts.account, + bank: &ctx.accounts.bank, + vault: &ctx.accounts.vault, + oracle: &ctx.accounts.oracle, + token_account: &ctx.accounts.token_account, + token_authority: &ctx.accounts.token_authority, + token_program: &ctx.accounts.token_program, } - - emit!(DepositLog { - mango_group: ctx.accounts.group.key(), - mango_account: ctx.accounts.account.key(), - signer: ctx.accounts.token_authority.key(), - token_index, - quantity: amount, - price: oracle_price.to_bits(), - }); - - Ok(()) + .deposit_into_existing(ctx.remaining_accounts, amount, true) +} + +pub fn token_deposit_into_existing( + ctx: Context, + amount: u64, +) -> Result<()> { + DepositCommon { + group: &ctx.accounts.group, + account: &ctx.accounts.account, + bank: &ctx.accounts.bank, + vault: &ctx.accounts.vault, + oracle: &ctx.accounts.oracle, + token_account: &ctx.accounts.token_account, + token_authority: &ctx.accounts.token_authority, + token_program: &ctx.accounts.token_program, + } + .deposit_into_existing(ctx.remaining_accounts, amount, false) } diff --git a/programs/mango-v4/src/lib.rs b/programs/mango-v4/src/lib.rs index 5dfe4fd97..72494cbb7 100644 --- a/programs/mango-v4/src/lib.rs +++ b/programs/mango-v4/src/lib.rs @@ -211,6 +211,13 @@ pub mod mango_v4 { instructions::token_deposit(ctx, amount) } + pub fn token_deposit_into_existing( + ctx: Context, + amount: u64, + ) -> Result<()> { + instructions::token_deposit_into_existing(ctx, amount) + } + pub fn token_withdraw( ctx: Context, amount: u64, diff --git a/programs/mango-v4/tests/program_test/mango_client.rs b/programs/mango-v4/tests/program_test/mango_client.rs index ccb5fcb56..94167d754 100644 --- a/programs/mango-v4/tests/program_test/mango_client.rs +++ b/programs/mango-v4/tests/program_test/mango_client.rs @@ -564,6 +564,7 @@ pub struct TokenDepositInstruction { pub amount: u64, pub account: Pubkey, + pub owner: TestKeypair, pub token_account: Pubkey, pub token_authority: TestKeypair, pub bank_index: usize, @@ -607,6 +608,76 @@ impl ClientInstruction for TokenDepositInstruction { ) .await; + let accounts = Self::Accounts { + group: account.fixed.group, + account: self.account, + owner: self.owner.pubkey(), + bank: mint_info.banks[self.bank_index], + vault: mint_info.vaults[self.bank_index], + oracle: mint_info.oracle, + token_account: self.token_account, + token_authority: self.token_authority.pubkey(), + token_program: Token::id(), + }; + + let mut instruction = make_instruction(program_id, &accounts, instruction); + instruction.accounts.extend(health_check_metas.into_iter()); + + (accounts, instruction) + } + + fn signers(&self) -> Vec { + vec![self.token_authority, self.owner] + } +} + +pub struct TokenDepositIntoExistingInstruction { + pub amount: u64, + + pub account: Pubkey, + pub token_account: Pubkey, + pub token_authority: TestKeypair, + pub bank_index: usize, +} +#[async_trait::async_trait(?Send)] +impl ClientInstruction for TokenDepositIntoExistingInstruction { + type Accounts = mango_v4::accounts::TokenDepositIntoExisting; + type Instruction = mango_v4::instruction::TokenDepositIntoExisting; + async fn to_instruction( + &self, + account_loader: impl ClientAccountLoader + 'async_trait, + ) -> (Self::Accounts, instruction::Instruction) { + let program_id = mango_v4::id(); + let instruction = Self::Instruction { + amount: self.amount, + }; + + // load account so we know its mint + let token_account: TokenAccount = account_loader.load(&self.token_account).await.unwrap(); + let account = account_loader + .load_mango_account(&self.account) + .await + .unwrap(); + let mint_info = Pubkey::find_program_address( + &[ + b"MintInfo".as_ref(), + account.fixed.group.as_ref(), + token_account.mint.as_ref(), + ], + &program_id, + ) + .0; + let mint_info: MintInfo = account_loader.load(&mint_info).await.unwrap(); + + let health_check_metas = derive_health_check_remaining_account_metas( + &account_loader, + &account, + Some(mint_info.banks[self.bank_index]), + false, + None, + ) + .await; + let accounts = Self::Accounts { group: account.fixed.group, account: self.account, diff --git a/programs/mango-v4/tests/program_test/mango_setup.rs b/programs/mango-v4/tests/program_test/mango_setup.rs index a5b949f2d..3cc8f49a9 100644 --- a/programs/mango-v4/tests/program_test/mango_setup.rs +++ b/programs/mango-v4/tests/program_test/mango_setup.rs @@ -178,6 +178,7 @@ pub async fn create_funded_account( TokenDepositInstruction { amount: amounts, account, + owner, token_account: payer.token_accounts[mint.index], token_authority: payer.key, bank_index, diff --git a/programs/mango-v4/tests/test_bankrupt_tokens.rs b/programs/mango-v4/tests/test_bankrupt_tokens.rs index 755d7621a..6fb130f23 100644 --- a/programs/mango-v4/tests/test_bankrupt_tokens.rs +++ b/programs/mango-v4/tests/test_bankrupt_tokens.rs @@ -59,6 +59,7 @@ async fn test_bankrupt_tokens_socialize_loss() -> Result<(), TransportError> { TokenDepositInstruction { amount: 10, account: vault_account, + owner, token_account: payer_mint_accounts[0], token_authority: payer.clone(), bank_index: 0, @@ -94,6 +95,7 @@ async fn test_bankrupt_tokens_socialize_loss() -> Result<(), TransportError> { TokenDepositInstruction { amount: deposit1_amount, account, + owner, token_account: payer_mint_accounts[2], token_authority: payer.clone(), bank_index: 0, @@ -106,6 +108,7 @@ async fn test_bankrupt_tokens_socialize_loss() -> Result<(), TransportError> { TokenDepositInstruction { amount: deposit2_amount, account, + owner, token_account: payer_mint_accounts[3], token_authority: payer.clone(), bank_index: 0, @@ -354,6 +357,7 @@ async fn test_bankrupt_tokens_insurance_fund() -> Result<(), TransportError> { TokenDepositInstruction { amount: vault_amount, account: vault_account, + owner, token_account, token_authority: payer.clone(), bank_index: 1, @@ -369,6 +373,7 @@ async fn test_bankrupt_tokens_insurance_fund() -> Result<(), TransportError> { TokenDepositInstruction { amount: 10, account: vault_account, + owner, token_account: payer_mint_accounts[0], token_authority: payer.clone(), bank_index: 0, @@ -404,6 +409,7 @@ async fn test_bankrupt_tokens_insurance_fund() -> Result<(), TransportError> { TokenDepositInstruction { amount: deposit1_amount, account, + owner, token_account: payer_mint_accounts[2], token_authority: payer.clone(), bank_index: 0, @@ -416,6 +422,7 @@ async fn test_bankrupt_tokens_insurance_fund() -> Result<(), TransportError> { TokenDepositInstruction { amount: deposit2_amount, account, + owner, token_account: payer_mint_accounts[3], token_authority: payer.clone(), bank_index: 0, diff --git a/programs/mango-v4/tests/test_basic.rs b/programs/mango-v4/tests/test_basic.rs index 1a733e287..9a78bae97 100644 --- a/programs/mango-v4/tests/test_basic.rs +++ b/programs/mango-v4/tests/test_basic.rs @@ -84,6 +84,7 @@ async fn test_basic() -> Result<(), TransportError> { TokenDepositInstruction { amount: deposit_amount, account, + owner, token_account: payer_mint0_account, token_authority: payer.clone(), bank_index: 0, diff --git a/programs/mango-v4/tests/test_health_compute.rs b/programs/mango-v4/tests/test_health_compute.rs index 656e2e534..03fd91773 100644 --- a/programs/mango-v4/tests/test_health_compute.rs +++ b/programs/mango-v4/tests/test_health_compute.rs @@ -145,6 +145,7 @@ async fn test_health_compute_serum() -> Result<(), TransportError> { TokenDepositInstruction { amount: 10, account, + owner, token_account: payer_mint_accounts[0], token_authority: payer.clone(), bank_index: 0, @@ -264,6 +265,7 @@ async fn test_health_compute_perp() -> Result<(), TransportError> { TokenDepositInstruction { amount: 10, account, + owner, token_account: payer_mint_accounts[0], token_authority: payer.clone(), bank_index: 0, diff --git a/programs/mango-v4/tests/test_health_region.rs b/programs/mango-v4/tests/test_health_region.rs index 80e7eb8ce..6f58d7822 100644 --- a/programs/mango-v4/tests/test_health_region.rs +++ b/programs/mango-v4/tests/test_health_region.rs @@ -63,6 +63,7 @@ async fn test_health_wrap() -> Result<(), TransportError> { TokenDepositInstruction { amount: 1, account, + owner, token_account: payer_mint_accounts[0], token_authority: payer.clone(), bank_index: 0, @@ -89,6 +90,7 @@ async fn test_health_wrap() -> Result<(), TransportError> { tx.add_instruction(TokenDepositInstruction { amount: repay_amount, account, + owner, token_account: payer_mint_accounts[1], token_authority: payer.clone(), bank_index: 0, diff --git a/programs/mango-v4/tests/test_liq_perps.rs b/programs/mango-v4/tests/test_liq_perps.rs index 693d0039a..2275c1f57 100644 --- a/programs/mango-v4/tests/test_liq_perps.rs +++ b/programs/mango-v4/tests/test_liq_perps.rs @@ -94,6 +94,7 @@ async fn test_liq_perps_force_cancel() -> Result<(), TransportError> { TokenDepositInstruction { amount: 1, account, + owner, token_account: payer_mint_accounts[1], token_authority: payer, bank_index: 0, @@ -307,6 +308,7 @@ async fn test_liq_perps_base_position_and_bankruptcy() -> Result<(), TransportEr TokenDepositInstruction { amount: 1, account, + owner, token_account: payer_mint_accounts[1], token_authority: payer, bank_index: 0, diff --git a/programs/mango-v4/tests/test_liq_tokens.rs b/programs/mango-v4/tests/test_liq_tokens.rs index bb9315141..88f13db63 100644 --- a/programs/mango-v4/tests/test_liq_tokens.rs +++ b/programs/mango-v4/tests/test_liq_tokens.rs @@ -233,6 +233,7 @@ async fn test_liq_tokens_with_token() -> Result<(), TransportError> { TokenDepositInstruction { amount: 100000, account: vault_account, + owner, token_account, token_authority: payer.clone(), bank_index: 0, @@ -269,6 +270,7 @@ async fn test_liq_tokens_with_token() -> Result<(), TransportError> { TokenDepositInstruction { amount: deposit1_amount, account, + owner, token_account: payer_mint_accounts[2], token_authority: payer.clone(), bank_index: 0, @@ -281,6 +283,7 @@ async fn test_liq_tokens_with_token() -> Result<(), TransportError> { TokenDepositInstruction { amount: deposit2_amount, account, + owner, token_account: payer_mint_accounts[3], token_authority: payer.clone(), bank_index: 0, diff --git a/programs/mango-v4/tests/test_margin_trade.rs b/programs/mango-v4/tests/test_margin_trade.rs index bcb8242ee..65bc68111 100644 --- a/programs/mango-v4/tests/test_margin_trade.rs +++ b/programs/mango-v4/tests/test_margin_trade.rs @@ -89,6 +89,7 @@ async fn test_margin_trade() -> Result<(), BanksClientError> { TokenDepositInstruction { amount: deposit_amount_initial, account, + owner, token_account: payer_mint0_account, token_authority: payer.clone(), bank_index: 0, diff --git a/programs/mango-v4/tests/test_perp_settle_fees.rs b/programs/mango-v4/tests/test_perp_settle_fees.rs index b4b7e41f5..7359078bf 100644 --- a/programs/mango-v4/tests/test_perp_settle_fees.rs +++ b/programs/mango-v4/tests/test_perp_settle_fees.rs @@ -80,6 +80,7 @@ async fn test_perp_settle_fees() -> Result<(), TransportError> { TokenDepositInstruction { amount: deposit_amount, account: account_0, + owner, token_account: payer_mint_accounts[0], token_authority: payer.clone(), bank_index: 0, @@ -93,6 +94,7 @@ async fn test_perp_settle_fees() -> Result<(), TransportError> { TokenDepositInstruction { amount: deposit_amount, account: account_0, + owner, token_account: payer_mint_accounts[1], token_authority: payer.clone(), bank_index: 0, @@ -110,6 +112,7 @@ async fn test_perp_settle_fees() -> Result<(), TransportError> { TokenDepositInstruction { amount: deposit_amount, account: account_1, + owner, token_account: payer_mint_accounts[0], token_authority: payer.clone(), bank_index: 0, @@ -123,6 +126,7 @@ async fn test_perp_settle_fees() -> Result<(), TransportError> { TokenDepositInstruction { amount: deposit_amount, account: account_1, + owner, token_account: payer_mint_accounts[1], token_authority: payer.clone(), bank_index: 0, diff --git a/programs/mango-v4/tests/test_position_lifetime.rs b/programs/mango-v4/tests/test_position_lifetime.rs index ad982691f..8913dd725 100644 --- a/programs/mango-v4/tests/test_position_lifetime.rs +++ b/programs/mango-v4/tests/test_position_lifetime.rs @@ -71,14 +71,30 @@ async fn test_position_lifetime() -> Result<()> { { let start_balance = solana.token_account_balance(payer_mint_accounts[0]).await; - // this activates the positions let deposit_amount = 100; + + // cannot deposit_into_existing if no token deposit exists + assert!(send_tx( + solana, + TokenDepositIntoExistingInstruction { + amount: deposit_amount, + account, + token_account: payer_mint_accounts[0], + token_authority: payer, + bank_index: 0, + } + ) + .await + .is_err()); + + // this activates the positions for &payer_token in payer_mint_accounts { send_tx( solana, TokenDepositInstruction { amount: deposit_amount, account, + owner, token_account: payer_token, token_authority: payer.clone(), bank_index: 0, @@ -88,6 +104,20 @@ async fn test_position_lifetime() -> Result<()> { .unwrap(); } + // now depositing into an active account works + send_tx( + solana, + TokenDepositIntoExistingInstruction { + amount: deposit_amount, + account, + token_account: payer_mint_accounts[0], + token_authority: payer, + bank_index: 0, + }, + ) + .await + .unwrap(); + // this closes the positions for &payer_token in payer_mint_accounts { send_tx( @@ -131,6 +161,7 @@ async fn test_position_lifetime() -> Result<()> { TokenDepositInstruction { amount: collateral_amount, account, + owner, token_account: payer_mint_accounts[0], token_authority: payer.clone(), bank_index: 0, @@ -167,6 +198,7 @@ async fn test_position_lifetime() -> Result<()> { // deposit withdraw amount + some more to cover loan origination fees amount: borrow_amount + 2, account, + owner, token_account: payer_mint_accounts[1], token_authority: payer.clone(), bank_index: 0, diff --git a/ts/client/src/client.ts b/ts/client/src/client.ts index 2d5e762a2..364c7fb9a 100644 --- a/ts/client/src/client.ts +++ b/ts/client/src/client.ts @@ -809,6 +809,7 @@ export class MangoClient { .accounts({ group: group.publicKey, account: mangoAccount.publicKey, + owner: mangoAccount.owner, bank: bank.publicKey, vault: bank.vault, oracle: bank.oracle, diff --git a/ts/client/src/mango_v4.ts b/ts/client/src/mango_v4.ts index 03b01928f..9292bb01c 100644 --- a/ts/client/src/mango_v4.ts +++ b/ts/client/src/mango_v4.ts @@ -1076,6 +1076,62 @@ export type MangoV4 = { }, { "name": "tokenDeposit", + "accounts": [ + { + "name": "group", + "isMut": false, + "isSigner": false + }, + { + "name": "account", + "isMut": true, + "isSigner": false + }, + { + "name": "owner", + "isMut": false, + "isSigner": true + }, + { + "name": "bank", + "isMut": true, + "isSigner": false + }, + { + "name": "vault", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + }, + { + "name": "tokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenAuthority", + "isMut": false, + "isSigner": true + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "tokenDepositIntoExisting", "accounts": [ { "name": "group", @@ -7282,6 +7338,62 @@ export const IDL: MangoV4 = { }, { "name": "tokenDeposit", + "accounts": [ + { + "name": "group", + "isMut": false, + "isSigner": false + }, + { + "name": "account", + "isMut": true, + "isSigner": false + }, + { + "name": "owner", + "isMut": false, + "isSigner": true + }, + { + "name": "bank", + "isMut": true, + "isSigner": false + }, + { + "name": "vault", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + }, + { + "name": "tokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenAuthority", + "isMut": false, + "isSigner": true + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "tokenDepositIntoExisting", "accounts": [ { "name": "group",