use {
crate::{
error::PerpetualsError,
state::{
multisig::{AdminInstruction, Multisig},
perpetuals::Perpetuals,
pool::Pool,
},
},
anchor_lang::prelude::*,
anchor_spl::token::{Mint, Token},
};
#[derive(Accounts)]
#[instruction(params: AddPoolParams)]
pub struct AddPool<'info> {
#[account(mut)]
pub admin: Signer<'info>,
#[account(
mut,
seeds = [b"multisig"],
bump = multisig.load()?.bump
)]
pub multisig: AccountLoader<'info, Multisig>,
#[account(
seeds = [b"transfer_authority"],
bump = perpetuals.transfer_authority_bump
)]
pub transfer_authority: AccountInfo<'info>,
#[account(
mut,
realloc = Perpetuals::LEN + (perpetuals.pools.len() + 1) * std::mem::size_of::<Pubkey>(),
realloc::payer = admin,
realloc::zero = false,
seeds = [b"perpetuals"],
bump = perpetuals.perpetuals_bump
)]
pub perpetuals: Box<Account<'info, Perpetuals>>,
#[account(
init_if_needed,
payer = admin,
space = Pool::LEN,
seeds = [b"pool",
params.name.as_bytes()],
bump
)]
pub pool: Box<Account<'info, Pool>>,
#[account(
init_if_needed,
payer = admin,
mint::authority = transfer_authority,
mint::freeze_authority = transfer_authority,
mint::decimals = Perpetuals::LP_DECIMALS,
seeds = [b"lp_token_mint",
pool.key().as_ref()],
bump
)]
pub lp_token_mint: Box<Account<'info, Mint>>,
system_program: Program<'info, System>,
token_program: Program<'info, Token>,
rent: Sysvar<'info, Rent>,
}
#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct AddPoolParams {
pub name: String,
}
pub fn add_pool<'info>(
ctx: Context<'_, '_, '_, 'info, AddPool<'info>>,
params: &AddPoolParams,
) -> Result<u8> {
if params.name.is_empty() || params.name.len() > 64 {
return Err(ProgramError::InvalidArgument.into());
}
let mut multisig = ctx.accounts.multisig.load_mut()?;
let signatures_left = multisig.sign_multisig(
&ctx.accounts.admin,
&Multisig::get_account_infos(&ctx)[1..],
&Multisig::get_instruction_data(AdminInstruction::AddPool, params)?,
)?;
if signatures_left > 0 {
msg!(
"Instruction has been signed but more signatures are required: {}",
signatures_left
);
return Ok(signatures_left);
}
let perpetuals = ctx.accounts.perpetuals.as_mut();
let pool = ctx.accounts.pool.as_mut();
if pool.inception_time != 0 {
return Err(ProgramError::AccountAlreadyInitialized.into());
}
msg!("Record pool: {}", params.name);
pool.inception_time = perpetuals.get_time()?;
pool.name = params.name.clone();
pool.bump = *ctx.bumps.get("pool").ok_or(ProgramError::InvalidSeeds)?;
pool.lp_token_bump = *ctx
.bumps
.get("lp_token_mint")
.ok_or(ProgramError::InvalidSeeds)?;
if !pool.validate() {
return err!(PerpetualsError::InvalidPoolConfig);
}
perpetuals.pools.push(ctx.accounts.pool.key());
Ok(0)
}