#![allow(deprecated)]
#![allow(clippy::too_many_arguments)]
use {
crate::{
find_deposit_authority_program_address, find_ephemeral_stake_program_address,
find_stake_program_address, find_transient_stake_program_address,
find_withdraw_authority_program_address,
inline_mpl_token_metadata::{self, pda::find_metadata_account},
state::{Fee, FeeType, StakePool, ValidatorList, ValidatorStakeInfo},
MAX_VALIDATORS_TO_UPDATE,
},
borsh::{BorshDeserialize, BorshSchema, BorshSerialize},
solana_program::{
instruction::{AccountMeta, Instruction},
program_error::ProgramError,
pubkey::Pubkey,
stake,
stake_history::Epoch,
system_program, sysvar,
},
std::num::NonZeroU32,
};
#[repr(C)]
#[derive(Clone, Debug, PartialEq, BorshSerialize, BorshDeserialize, BorshSchema)]
pub enum PreferredValidatorType {
Deposit,
Withdraw,
}
#[repr(C)]
#[derive(Clone, Debug, PartialEq, BorshSerialize, BorshDeserialize, BorshSchema)]
pub enum FundingType {
StakeDeposit,
SolDeposit,
SolWithdraw,
}
#[repr(C)]
#[derive(Clone, Debug, PartialEq, BorshSerialize, BorshDeserialize)]
pub enum StakePoolInstruction {
Initialize {
fee: Fee,
withdrawal_fee: Fee,
deposit_fee: Fee,
referral_fee: u8,
max_validators: u32,
},
AddValidatorToPool(u32),
RemoveValidatorFromPool,
DecreaseValidatorStake {
lamports: u64,
transient_stake_seed: u64,
},
IncreaseValidatorStake {
lamports: u64,
transient_stake_seed: u64,
},
SetPreferredValidator {
validator_type: PreferredValidatorType,
validator_vote_address: Option<Pubkey>,
},
UpdateValidatorListBalance {
start_index: u32,
no_merge: bool,
},
UpdateStakePoolBalance,
CleanupRemovedValidatorEntries,
DepositStake,
WithdrawStake(u64),
SetManager,
SetFee {
fee: FeeType,
},
SetStaker,
DepositSol(u64),
SetFundingAuthority(FundingType),
WithdrawSol(u64),
CreateTokenMetadata {
name: String,
symbol: String,
uri: String,
},
UpdateTokenMetadata {
name: String,
symbol: String,
uri: String,
},
IncreaseAdditionalValidatorStake {
lamports: u64,
transient_stake_seed: u64,
ephemeral_stake_seed: u64,
},
DecreaseAdditionalValidatorStake {
lamports: u64,
transient_stake_seed: u64,
ephemeral_stake_seed: u64,
},
DecreaseValidatorStakeWithReserve {
lamports: u64,
transient_stake_seed: u64,
},
#[deprecated(
since = "2.0.0",
note = "The stake redelegate instruction used in this will not be enabled."
)]
Redelegate {
#[allow(dead_code)] lamports: u64,
#[allow(dead_code)] source_transient_stake_seed: u64,
#[allow(dead_code)] ephemeral_stake_seed: u64,
#[allow(dead_code)] destination_transient_stake_seed: u64,
},
DepositStakeWithSlippage {
minimum_pool_tokens_out: u64,
},
WithdrawStakeWithSlippage {
pool_tokens_in: u64,
minimum_lamports_out: u64,
},
DepositSolWithSlippage {
lamports_in: u64,
minimum_pool_tokens_out: u64,
},
WithdrawSolWithSlippage {
pool_tokens_in: u64,
minimum_lamports_out: u64,
},
}
pub fn initialize(
program_id: &Pubkey,
stake_pool: &Pubkey,
manager: &Pubkey,
staker: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
validator_list: &Pubkey,
reserve_stake: &Pubkey,
pool_mint: &Pubkey,
manager_pool_account: &Pubkey,
token_program_id: &Pubkey,
deposit_authority: Option<Pubkey>,
fee: Fee,
withdrawal_fee: Fee,
deposit_fee: Fee,
referral_fee: u8,
max_validators: u32,
) -> Instruction {
let init_data = StakePoolInstruction::Initialize {
fee,
withdrawal_fee,
deposit_fee,
referral_fee,
max_validators,
};
let data = borsh::to_vec(&init_data).unwrap();
let mut accounts = vec![
AccountMeta::new(*stake_pool, false),
AccountMeta::new_readonly(*manager, true),
AccountMeta::new_readonly(*staker, false),
AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
AccountMeta::new(*validator_list, false),
AccountMeta::new_readonly(*reserve_stake, false),
AccountMeta::new(*pool_mint, false),
AccountMeta::new(*manager_pool_account, false),
AccountMeta::new_readonly(*token_program_id, false),
];
if let Some(deposit_authority) = deposit_authority {
accounts.push(AccountMeta::new_readonly(deposit_authority, true));
}
Instruction {
program_id: *program_id,
accounts,
data,
}
}
pub fn add_validator_to_pool(
program_id: &Pubkey,
stake_pool: &Pubkey,
staker: &Pubkey,
reserve: &Pubkey,
stake_pool_withdraw: &Pubkey,
validator_list: &Pubkey,
stake: &Pubkey,
validator: &Pubkey,
seed: Option<NonZeroU32>,
) -> Instruction {
let accounts = vec![
AccountMeta::new(*stake_pool, false),
AccountMeta::new_readonly(*staker, true),
AccountMeta::new(*reserve, false),
AccountMeta::new_readonly(*stake_pool_withdraw, false),
AccountMeta::new(*validator_list, false),
AccountMeta::new(*stake, false),
AccountMeta::new_readonly(*validator, false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
#[allow(deprecated)]
AccountMeta::new_readonly(stake::config::id(), false),
AccountMeta::new_readonly(system_program::id(), false),
AccountMeta::new_readonly(stake::program::id(), false),
];
let data = borsh::to_vec(&StakePoolInstruction::AddValidatorToPool(
seed.map(|s| s.get()).unwrap_or(0),
))
.unwrap();
Instruction {
program_id: *program_id,
accounts,
data,
}
}
pub fn remove_validator_from_pool(
program_id: &Pubkey,
stake_pool: &Pubkey,
staker: &Pubkey,
stake_pool_withdraw: &Pubkey,
validator_list: &Pubkey,
stake_account: &Pubkey,
transient_stake_account: &Pubkey,
) -> Instruction {
let accounts = vec![
AccountMeta::new(*stake_pool, false),
AccountMeta::new_readonly(*staker, true),
AccountMeta::new_readonly(*stake_pool_withdraw, false),
AccountMeta::new(*validator_list, false),
AccountMeta::new(*stake_account, false),
AccountMeta::new(*transient_stake_account, false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(stake::program::id(), false),
];
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::RemoveValidatorFromPool).unwrap(),
}
}
#[deprecated(
since = "0.7.0",
note = "please use `decrease_validator_stake_with_reserve`"
)]
pub fn decrease_validator_stake(
program_id: &Pubkey,
stake_pool: &Pubkey,
staker: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
validator_list: &Pubkey,
validator_stake: &Pubkey,
transient_stake: &Pubkey,
lamports: u64,
transient_stake_seed: u64,
) -> Instruction {
let accounts = vec![
AccountMeta::new_readonly(*stake_pool, false),
AccountMeta::new_readonly(*staker, true),
AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
AccountMeta::new(*validator_list, false),
AccountMeta::new(*validator_stake, false),
AccountMeta::new(*transient_stake, false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
AccountMeta::new_readonly(system_program::id(), false),
AccountMeta::new_readonly(stake::program::id(), false),
];
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::DecreaseValidatorStake {
lamports,
transient_stake_seed,
})
.unwrap(),
}
}
pub fn decrease_additional_validator_stake(
program_id: &Pubkey,
stake_pool: &Pubkey,
staker: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
validator_list: &Pubkey,
reserve_stake: &Pubkey,
validator_stake: &Pubkey,
ephemeral_stake: &Pubkey,
transient_stake: &Pubkey,
lamports: u64,
transient_stake_seed: u64,
ephemeral_stake_seed: u64,
) -> Instruction {
let accounts = vec![
AccountMeta::new_readonly(*stake_pool, false),
AccountMeta::new_readonly(*staker, true),
AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
AccountMeta::new(*validator_list, false),
AccountMeta::new(*reserve_stake, false),
AccountMeta::new(*validator_stake, false),
AccountMeta::new(*ephemeral_stake, false),
AccountMeta::new(*transient_stake, false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
AccountMeta::new_readonly(system_program::id(), false),
AccountMeta::new_readonly(stake::program::id(), false),
];
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::DecreaseAdditionalValidatorStake {
lamports,
transient_stake_seed,
ephemeral_stake_seed,
})
.unwrap(),
}
}
pub fn decrease_validator_stake_with_reserve(
program_id: &Pubkey,
stake_pool: &Pubkey,
staker: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
validator_list: &Pubkey,
reserve_stake: &Pubkey,
validator_stake: &Pubkey,
transient_stake: &Pubkey,
lamports: u64,
transient_stake_seed: u64,
) -> Instruction {
let accounts = vec![
AccountMeta::new_readonly(*stake_pool, false),
AccountMeta::new_readonly(*staker, true),
AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
AccountMeta::new(*validator_list, false),
AccountMeta::new(*reserve_stake, false),
AccountMeta::new(*validator_stake, false),
AccountMeta::new(*transient_stake, false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
AccountMeta::new_readonly(system_program::id(), false),
AccountMeta::new_readonly(stake::program::id(), false),
];
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::DecreaseValidatorStakeWithReserve {
lamports,
transient_stake_seed,
})
.unwrap(),
}
}
pub fn increase_validator_stake(
program_id: &Pubkey,
stake_pool: &Pubkey,
staker: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
validator_list: &Pubkey,
reserve_stake: &Pubkey,
transient_stake: &Pubkey,
validator_stake: &Pubkey,
validator: &Pubkey,
lamports: u64,
transient_stake_seed: u64,
) -> Instruction {
let accounts = vec![
AccountMeta::new_readonly(*stake_pool, false),
AccountMeta::new_readonly(*staker, true),
AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
AccountMeta::new(*validator_list, false),
AccountMeta::new(*reserve_stake, false),
AccountMeta::new(*transient_stake, false),
AccountMeta::new_readonly(*validator_stake, false),
AccountMeta::new_readonly(*validator, false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
#[allow(deprecated)]
AccountMeta::new_readonly(stake::config::id(), false),
AccountMeta::new_readonly(system_program::id(), false),
AccountMeta::new_readonly(stake::program::id(), false),
];
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::IncreaseValidatorStake {
lamports,
transient_stake_seed,
})
.unwrap(),
}
}
pub fn increase_additional_validator_stake(
program_id: &Pubkey,
stake_pool: &Pubkey,
staker: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
validator_list: &Pubkey,
reserve_stake: &Pubkey,
ephemeral_stake: &Pubkey,
transient_stake: &Pubkey,
validator_stake: &Pubkey,
validator: &Pubkey,
lamports: u64,
transient_stake_seed: u64,
ephemeral_stake_seed: u64,
) -> Instruction {
let accounts = vec![
AccountMeta::new_readonly(*stake_pool, false),
AccountMeta::new_readonly(*staker, true),
AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
AccountMeta::new(*validator_list, false),
AccountMeta::new(*reserve_stake, false),
AccountMeta::new(*ephemeral_stake, false),
AccountMeta::new(*transient_stake, false),
AccountMeta::new_readonly(*validator_stake, false),
AccountMeta::new_readonly(*validator, false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
#[allow(deprecated)]
AccountMeta::new_readonly(stake::config::id(), false),
AccountMeta::new_readonly(system_program::id(), false),
AccountMeta::new_readonly(stake::program::id(), false),
];
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::IncreaseAdditionalValidatorStake {
lamports,
transient_stake_seed,
ephemeral_stake_seed,
})
.unwrap(),
}
}
#[deprecated(
since = "2.0.0",
note = "The stake redelegate instruction used in this will not be enabled."
)]
pub fn redelegate(
program_id: &Pubkey,
stake_pool: &Pubkey,
staker: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
validator_list: &Pubkey,
reserve_stake: &Pubkey,
source_validator_stake: &Pubkey,
source_transient_stake: &Pubkey,
ephemeral_stake: &Pubkey,
destination_transient_stake: &Pubkey,
destination_validator_stake: &Pubkey,
validator: &Pubkey,
lamports: u64,
source_transient_stake_seed: u64,
ephemeral_stake_seed: u64,
destination_transient_stake_seed: u64,
) -> Instruction {
let accounts = vec![
AccountMeta::new_readonly(*stake_pool, false),
AccountMeta::new_readonly(*staker, true),
AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
AccountMeta::new(*validator_list, false),
AccountMeta::new(*reserve_stake, false),
AccountMeta::new(*source_validator_stake, false),
AccountMeta::new(*source_transient_stake, false),
AccountMeta::new(*ephemeral_stake, false),
AccountMeta::new(*destination_transient_stake, false),
AccountMeta::new_readonly(*destination_validator_stake, false),
AccountMeta::new_readonly(*validator, false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
#[allow(deprecated)]
AccountMeta::new_readonly(stake::config::id(), false),
AccountMeta::new_readonly(system_program::id(), false),
AccountMeta::new_readonly(stake::program::id(), false),
];
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::Redelegate {
lamports,
source_transient_stake_seed,
ephemeral_stake_seed,
destination_transient_stake_seed,
})
.unwrap(),
}
}
pub fn set_preferred_validator(
program_id: &Pubkey,
stake_pool_address: &Pubkey,
staker: &Pubkey,
validator_list_address: &Pubkey,
validator_type: PreferredValidatorType,
validator_vote_address: Option<Pubkey>,
) -> Instruction {
Instruction {
program_id: *program_id,
accounts: vec![
AccountMeta::new(*stake_pool_address, false),
AccountMeta::new_readonly(*staker, true),
AccountMeta::new_readonly(*validator_list_address, false),
],
data: borsh::to_vec(&StakePoolInstruction::SetPreferredValidator {
validator_type,
validator_vote_address,
})
.unwrap(),
}
}
pub fn add_validator_to_pool_with_vote(
program_id: &Pubkey,
stake_pool: &StakePool,
stake_pool_address: &Pubkey,
vote_account_address: &Pubkey,
seed: Option<NonZeroU32>,
) -> Instruction {
let pool_withdraw_authority =
find_withdraw_authority_program_address(program_id, stake_pool_address).0;
let (stake_account_address, _) =
find_stake_program_address(program_id, vote_account_address, stake_pool_address, seed);
add_validator_to_pool(
program_id,
stake_pool_address,
&stake_pool.staker,
&stake_pool.reserve_stake,
&pool_withdraw_authority,
&stake_pool.validator_list,
&stake_account_address,
vote_account_address,
seed,
)
}
pub fn remove_validator_from_pool_with_vote(
program_id: &Pubkey,
stake_pool: &StakePool,
stake_pool_address: &Pubkey,
vote_account_address: &Pubkey,
validator_stake_seed: Option<NonZeroU32>,
transient_stake_seed: u64,
) -> Instruction {
let pool_withdraw_authority =
find_withdraw_authority_program_address(program_id, stake_pool_address).0;
let (stake_account_address, _) = find_stake_program_address(
program_id,
vote_account_address,
stake_pool_address,
validator_stake_seed,
);
let (transient_stake_account, _) = find_transient_stake_program_address(
program_id,
vote_account_address,
stake_pool_address,
transient_stake_seed,
);
remove_validator_from_pool(
program_id,
stake_pool_address,
&stake_pool.staker,
&pool_withdraw_authority,
&stake_pool.validator_list,
&stake_account_address,
&transient_stake_account,
)
}
pub fn increase_validator_stake_with_vote(
program_id: &Pubkey,
stake_pool: &StakePool,
stake_pool_address: &Pubkey,
vote_account_address: &Pubkey,
lamports: u64,
validator_stake_seed: Option<NonZeroU32>,
transient_stake_seed: u64,
) -> Instruction {
let pool_withdraw_authority =
find_withdraw_authority_program_address(program_id, stake_pool_address).0;
let (transient_stake_address, _) = find_transient_stake_program_address(
program_id,
vote_account_address,
stake_pool_address,
transient_stake_seed,
);
let (validator_stake_address, _) = find_stake_program_address(
program_id,
vote_account_address,
stake_pool_address,
validator_stake_seed,
);
increase_validator_stake(
program_id,
stake_pool_address,
&stake_pool.staker,
&pool_withdraw_authority,
&stake_pool.validator_list,
&stake_pool.reserve_stake,
&transient_stake_address,
&validator_stake_address,
vote_account_address,
lamports,
transient_stake_seed,
)
}
pub fn increase_additional_validator_stake_with_vote(
program_id: &Pubkey,
stake_pool: &StakePool,
stake_pool_address: &Pubkey,
vote_account_address: &Pubkey,
lamports: u64,
validator_stake_seed: Option<NonZeroU32>,
transient_stake_seed: u64,
ephemeral_stake_seed: u64,
) -> Instruction {
let pool_withdraw_authority =
find_withdraw_authority_program_address(program_id, stake_pool_address).0;
let (ephemeral_stake_address, _) =
find_ephemeral_stake_program_address(program_id, stake_pool_address, ephemeral_stake_seed);
let (transient_stake_address, _) = find_transient_stake_program_address(
program_id,
vote_account_address,
stake_pool_address,
transient_stake_seed,
);
let (validator_stake_address, _) = find_stake_program_address(
program_id,
vote_account_address,
stake_pool_address,
validator_stake_seed,
);
increase_additional_validator_stake(
program_id,
stake_pool_address,
&stake_pool.staker,
&pool_withdraw_authority,
&stake_pool.validator_list,
&stake_pool.reserve_stake,
&ephemeral_stake_address,
&transient_stake_address,
&validator_stake_address,
vote_account_address,
lamports,
transient_stake_seed,
ephemeral_stake_seed,
)
}
pub fn decrease_validator_stake_with_vote(
program_id: &Pubkey,
stake_pool: &StakePool,
stake_pool_address: &Pubkey,
vote_account_address: &Pubkey,
lamports: u64,
validator_stake_seed: Option<NonZeroU32>,
transient_stake_seed: u64,
) -> Instruction {
let pool_withdraw_authority =
find_withdraw_authority_program_address(program_id, stake_pool_address).0;
let (validator_stake_address, _) = find_stake_program_address(
program_id,
vote_account_address,
stake_pool_address,
validator_stake_seed,
);
let (transient_stake_address, _) = find_transient_stake_program_address(
program_id,
vote_account_address,
stake_pool_address,
transient_stake_seed,
);
decrease_validator_stake_with_reserve(
program_id,
stake_pool_address,
&stake_pool.staker,
&pool_withdraw_authority,
&stake_pool.validator_list,
&stake_pool.reserve_stake,
&validator_stake_address,
&transient_stake_address,
lamports,
transient_stake_seed,
)
}
pub fn increase_additional_validator_stake_with_list(
program_id: &Pubkey,
stake_pool: &StakePool,
validator_list: &ValidatorList,
stake_pool_address: &Pubkey,
vote_account_address: &Pubkey,
lamports: u64,
ephemeral_stake_seed: u64,
) -> Result<Instruction, ProgramError> {
let validator_info = validator_list
.find(vote_account_address)
.ok_or(ProgramError::InvalidInstructionData)?;
let transient_stake_seed = u64::from(validator_info.transient_seed_suffix);
let validator_stake_seed = NonZeroU32::new(validator_info.validator_seed_suffix.into());
Ok(increase_additional_validator_stake_with_vote(
program_id,
stake_pool,
stake_pool_address,
vote_account_address,
lamports,
validator_stake_seed,
transient_stake_seed,
ephemeral_stake_seed,
))
}
pub fn decrease_additional_validator_stake_with_list(
program_id: &Pubkey,
stake_pool: &StakePool,
validator_list: &ValidatorList,
stake_pool_address: &Pubkey,
vote_account_address: &Pubkey,
lamports: u64,
ephemeral_stake_seed: u64,
) -> Result<Instruction, ProgramError> {
let validator_info = validator_list
.find(vote_account_address)
.ok_or(ProgramError::InvalidInstructionData)?;
let transient_stake_seed = u64::from(validator_info.transient_seed_suffix);
let validator_stake_seed = NonZeroU32::new(validator_info.validator_seed_suffix.into());
Ok(decrease_additional_validator_stake_with_vote(
program_id,
stake_pool,
stake_pool_address,
vote_account_address,
lamports,
validator_stake_seed,
transient_stake_seed,
ephemeral_stake_seed,
))
}
pub fn decrease_additional_validator_stake_with_vote(
program_id: &Pubkey,
stake_pool: &StakePool,
stake_pool_address: &Pubkey,
vote_account_address: &Pubkey,
lamports: u64,
validator_stake_seed: Option<NonZeroU32>,
transient_stake_seed: u64,
ephemeral_stake_seed: u64,
) -> Instruction {
let pool_withdraw_authority =
find_withdraw_authority_program_address(program_id, stake_pool_address).0;
let (validator_stake_address, _) = find_stake_program_address(
program_id,
vote_account_address,
stake_pool_address,
validator_stake_seed,
);
let (ephemeral_stake_address, _) =
find_ephemeral_stake_program_address(program_id, stake_pool_address, ephemeral_stake_seed);
let (transient_stake_address, _) = find_transient_stake_program_address(
program_id,
vote_account_address,
stake_pool_address,
transient_stake_seed,
);
decrease_additional_validator_stake(
program_id,
stake_pool_address,
&stake_pool.staker,
&pool_withdraw_authority,
&stake_pool.validator_list,
&stake_pool.reserve_stake,
&validator_stake_address,
&ephemeral_stake_address,
&transient_stake_address,
lamports,
transient_stake_seed,
ephemeral_stake_seed,
)
}
#[deprecated(
since = "1.1.0",
note = "please use `update_validator_list_balance_chunk`"
)]
pub fn update_validator_list_balance(
program_id: &Pubkey,
stake_pool: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
validator_list_address: &Pubkey,
reserve_stake: &Pubkey,
validator_list: &ValidatorList,
validator_vote_accounts: &[Pubkey],
start_index: u32,
no_merge: bool,
) -> Instruction {
let mut accounts = vec![
AccountMeta::new_readonly(*stake_pool, false),
AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
AccountMeta::new(*validator_list_address, false),
AccountMeta::new(*reserve_stake, false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
AccountMeta::new_readonly(stake::program::id(), false),
];
accounts.append(
&mut validator_vote_accounts
.iter()
.flat_map(|vote_account_address| {
let validator_stake_info = validator_list.find(vote_account_address);
if let Some(validator_stake_info) = validator_stake_info {
let (validator_stake_account, _) = find_stake_program_address(
program_id,
vote_account_address,
stake_pool,
NonZeroU32::new(validator_stake_info.validator_seed_suffix.into()),
);
let (transient_stake_account, _) = find_transient_stake_program_address(
program_id,
vote_account_address,
stake_pool,
validator_stake_info.transient_seed_suffix.into(),
);
vec![
AccountMeta::new(validator_stake_account, false),
AccountMeta::new(transient_stake_account, false),
]
} else {
vec![]
}
})
.collect::<Vec<AccountMeta>>(),
);
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::UpdateValidatorListBalance {
start_index,
no_merge,
})
.unwrap(),
}
}
pub fn update_validator_list_balance_chunk(
program_id: &Pubkey,
stake_pool: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
validator_list_address: &Pubkey,
reserve_stake: &Pubkey,
validator_list: &ValidatorList,
len: usize,
start_index: usize,
no_merge: bool,
) -> Result<Instruction, ProgramError> {
let mut accounts = vec![
AccountMeta::new_readonly(*stake_pool, false),
AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
AccountMeta::new(*validator_list_address, false),
AccountMeta::new(*reserve_stake, false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
AccountMeta::new_readonly(stake::program::id(), false),
];
let validator_list_subslice = validator_list
.validators
.get(start_index..start_index.saturating_add(len))
.ok_or(ProgramError::InvalidInstructionData)?;
accounts.extend(validator_list_subslice.iter().flat_map(
|ValidatorStakeInfo {
vote_account_address,
validator_seed_suffix,
transient_seed_suffix,
..
}| {
let (validator_stake_account, _) = find_stake_program_address(
program_id,
vote_account_address,
stake_pool,
NonZeroU32::new((*validator_seed_suffix).into()),
);
let (transient_stake_account, _) = find_transient_stake_program_address(
program_id,
vote_account_address,
stake_pool,
(*transient_seed_suffix).into(),
);
[
AccountMeta::new(validator_stake_account, false),
AccountMeta::new(transient_stake_account, false),
]
},
));
Ok(Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::UpdateValidatorListBalance {
start_index: start_index.try_into().unwrap(),
no_merge,
})
.unwrap(),
})
}
pub fn update_stale_validator_list_balance_chunk(
program_id: &Pubkey,
stake_pool: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
validator_list_address: &Pubkey,
reserve_stake: &Pubkey,
validator_list: &ValidatorList,
len: usize,
start_index: usize,
no_merge: bool,
current_epoch: Epoch,
) -> Result<Option<Instruction>, ProgramError> {
let validator_list_subslice = validator_list
.validators
.get(start_index..start_index.saturating_add(len))
.ok_or(ProgramError::InvalidInstructionData)?;
if validator_list_subslice.iter().all(|info| {
let last_update_epoch: u64 = info.last_update_epoch.into();
last_update_epoch >= current_epoch
}) {
return Ok(None);
}
update_validator_list_balance_chunk(
program_id,
stake_pool,
stake_pool_withdraw_authority,
validator_list_address,
reserve_stake,
validator_list,
len,
start_index,
no_merge,
)
.map(Some)
}
pub fn update_stake_pool_balance(
program_id: &Pubkey,
stake_pool: &Pubkey,
withdraw_authority: &Pubkey,
validator_list_storage: &Pubkey,
reserve_stake: &Pubkey,
manager_fee_account: &Pubkey,
stake_pool_mint: &Pubkey,
token_program_id: &Pubkey,
) -> Instruction {
let accounts = vec![
AccountMeta::new(*stake_pool, false),
AccountMeta::new_readonly(*withdraw_authority, false),
AccountMeta::new(*validator_list_storage, false),
AccountMeta::new_readonly(*reserve_stake, false),
AccountMeta::new(*manager_fee_account, false),
AccountMeta::new(*stake_pool_mint, false),
AccountMeta::new_readonly(*token_program_id, false),
];
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::UpdateStakePoolBalance).unwrap(),
}
}
pub fn cleanup_removed_validator_entries(
program_id: &Pubkey,
stake_pool: &Pubkey,
validator_list_storage: &Pubkey,
) -> Instruction {
let accounts = vec![
AccountMeta::new_readonly(*stake_pool, false),
AccountMeta::new(*validator_list_storage, false),
];
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::CleanupRemovedValidatorEntries).unwrap(),
}
}
pub fn update_stake_pool(
program_id: &Pubkey,
stake_pool: &StakePool,
validator_list: &ValidatorList,
stake_pool_address: &Pubkey,
no_merge: bool,
) -> (Vec<Instruction>, Vec<Instruction>) {
let (withdraw_authority, _) =
find_withdraw_authority_program_address(program_id, stake_pool_address);
let update_list_instructions = validator_list
.validators
.chunks(MAX_VALIDATORS_TO_UPDATE)
.enumerate()
.map(|(i, chunk)| {
update_validator_list_balance_chunk(
program_id,
stake_pool_address,
&withdraw_authority,
&stake_pool.validator_list,
&stake_pool.reserve_stake,
validator_list,
chunk.len(),
i.saturating_mul(MAX_VALIDATORS_TO_UPDATE),
no_merge,
)
.unwrap()
})
.collect();
let final_instructions = vec![
update_stake_pool_balance(
program_id,
stake_pool_address,
&withdraw_authority,
&stake_pool.validator_list,
&stake_pool.reserve_stake,
&stake_pool.manager_fee_account,
&stake_pool.pool_mint,
&stake_pool.token_program_id,
),
cleanup_removed_validator_entries(
program_id,
stake_pool_address,
&stake_pool.validator_list,
),
];
(update_list_instructions, final_instructions)
}
pub fn update_stale_stake_pool(
program_id: &Pubkey,
stake_pool: &StakePool,
validator_list: &ValidatorList,
stake_pool_address: &Pubkey,
no_merge: bool,
current_epoch: Epoch,
) -> (Vec<Instruction>, Vec<Instruction>) {
let (withdraw_authority, _) =
find_withdraw_authority_program_address(program_id, stake_pool_address);
let update_list_instructions = validator_list
.validators
.chunks(MAX_VALIDATORS_TO_UPDATE)
.enumerate()
.filter_map(|(i, chunk)| {
update_stale_validator_list_balance_chunk(
program_id,
stake_pool_address,
&withdraw_authority,
&stake_pool.validator_list,
&stake_pool.reserve_stake,
validator_list,
chunk.len(),
i.saturating_mul(MAX_VALIDATORS_TO_UPDATE),
no_merge,
current_epoch,
)
.unwrap()
})
.collect();
let final_instructions = vec![
update_stake_pool_balance(
program_id,
stake_pool_address,
&withdraw_authority,
&stake_pool.validator_list,
&stake_pool.reserve_stake,
&stake_pool.manager_fee_account,
&stake_pool.pool_mint,
&stake_pool.token_program_id,
),
cleanup_removed_validator_entries(
program_id,
stake_pool_address,
&stake_pool.validator_list,
),
];
(update_list_instructions, final_instructions)
}
fn deposit_stake_internal(
program_id: &Pubkey,
stake_pool: &Pubkey,
validator_list_storage: &Pubkey,
stake_pool_deposit_authority: Option<&Pubkey>,
stake_pool_withdraw_authority: &Pubkey,
deposit_stake_address: &Pubkey,
deposit_stake_withdraw_authority: &Pubkey,
validator_stake_account: &Pubkey,
reserve_stake_account: &Pubkey,
pool_tokens_to: &Pubkey,
manager_fee_account: &Pubkey,
referrer_pool_tokens_account: &Pubkey,
pool_mint: &Pubkey,
token_program_id: &Pubkey,
minimum_pool_tokens_out: Option<u64>,
) -> Vec<Instruction> {
let mut instructions = vec![];
let mut accounts = vec![
AccountMeta::new(*stake_pool, false),
AccountMeta::new(*validator_list_storage, false),
];
if let Some(stake_pool_deposit_authority) = stake_pool_deposit_authority {
accounts.push(AccountMeta::new_readonly(
*stake_pool_deposit_authority,
true,
));
instructions.extend_from_slice(&[
stake::instruction::authorize(
deposit_stake_address,
deposit_stake_withdraw_authority,
stake_pool_deposit_authority,
stake::state::StakeAuthorize::Staker,
None,
),
stake::instruction::authorize(
deposit_stake_address,
deposit_stake_withdraw_authority,
stake_pool_deposit_authority,
stake::state::StakeAuthorize::Withdrawer,
None,
),
]);
} else {
let stake_pool_deposit_authority =
find_deposit_authority_program_address(program_id, stake_pool).0;
accounts.push(AccountMeta::new_readonly(
stake_pool_deposit_authority,
false,
));
instructions.extend_from_slice(&[
stake::instruction::authorize(
deposit_stake_address,
deposit_stake_withdraw_authority,
&stake_pool_deposit_authority,
stake::state::StakeAuthorize::Staker,
None,
),
stake::instruction::authorize(
deposit_stake_address,
deposit_stake_withdraw_authority,
&stake_pool_deposit_authority,
stake::state::StakeAuthorize::Withdrawer,
None,
),
]);
};
accounts.extend_from_slice(&[
AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
AccountMeta::new(*deposit_stake_address, false),
AccountMeta::new(*validator_stake_account, false),
AccountMeta::new(*reserve_stake_account, false),
AccountMeta::new(*pool_tokens_to, false),
AccountMeta::new(*manager_fee_account, false),
AccountMeta::new(*referrer_pool_tokens_account, false),
AccountMeta::new(*pool_mint, false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
AccountMeta::new_readonly(*token_program_id, false),
AccountMeta::new_readonly(stake::program::id(), false),
]);
instructions.push(
if let Some(minimum_pool_tokens_out) = minimum_pool_tokens_out {
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::DepositStakeWithSlippage {
minimum_pool_tokens_out,
})
.unwrap(),
}
} else {
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::DepositStake).unwrap(),
}
},
);
instructions
}
pub fn deposit_stake(
program_id: &Pubkey,
stake_pool: &Pubkey,
validator_list_storage: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
deposit_stake_address: &Pubkey,
deposit_stake_withdraw_authority: &Pubkey,
validator_stake_account: &Pubkey,
reserve_stake_account: &Pubkey,
pool_tokens_to: &Pubkey,
manager_fee_account: &Pubkey,
referrer_pool_tokens_account: &Pubkey,
pool_mint: &Pubkey,
token_program_id: &Pubkey,
) -> Vec<Instruction> {
deposit_stake_internal(
program_id,
stake_pool,
validator_list_storage,
None,
stake_pool_withdraw_authority,
deposit_stake_address,
deposit_stake_withdraw_authority,
validator_stake_account,
reserve_stake_account,
pool_tokens_to,
manager_fee_account,
referrer_pool_tokens_account,
pool_mint,
token_program_id,
None,
)
}
pub fn deposit_stake_with_slippage(
program_id: &Pubkey,
stake_pool: &Pubkey,
validator_list_storage: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
deposit_stake_address: &Pubkey,
deposit_stake_withdraw_authority: &Pubkey,
validator_stake_account: &Pubkey,
reserve_stake_account: &Pubkey,
pool_tokens_to: &Pubkey,
manager_fee_account: &Pubkey,
referrer_pool_tokens_account: &Pubkey,
pool_mint: &Pubkey,
token_program_id: &Pubkey,
minimum_pool_tokens_out: u64,
) -> Vec<Instruction> {
deposit_stake_internal(
program_id,
stake_pool,
validator_list_storage,
None,
stake_pool_withdraw_authority,
deposit_stake_address,
deposit_stake_withdraw_authority,
validator_stake_account,
reserve_stake_account,
pool_tokens_to,
manager_fee_account,
referrer_pool_tokens_account,
pool_mint,
token_program_id,
Some(minimum_pool_tokens_out),
)
}
pub fn deposit_stake_with_authority(
program_id: &Pubkey,
stake_pool: &Pubkey,
validator_list_storage: &Pubkey,
stake_pool_deposit_authority: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
deposit_stake_address: &Pubkey,
deposit_stake_withdraw_authority: &Pubkey,
validator_stake_account: &Pubkey,
reserve_stake_account: &Pubkey,
pool_tokens_to: &Pubkey,
manager_fee_account: &Pubkey,
referrer_pool_tokens_account: &Pubkey,
pool_mint: &Pubkey,
token_program_id: &Pubkey,
) -> Vec<Instruction> {
deposit_stake_internal(
program_id,
stake_pool,
validator_list_storage,
Some(stake_pool_deposit_authority),
stake_pool_withdraw_authority,
deposit_stake_address,
deposit_stake_withdraw_authority,
validator_stake_account,
reserve_stake_account,
pool_tokens_to,
manager_fee_account,
referrer_pool_tokens_account,
pool_mint,
token_program_id,
None,
)
}
pub fn deposit_stake_with_authority_and_slippage(
program_id: &Pubkey,
stake_pool: &Pubkey,
validator_list_storage: &Pubkey,
stake_pool_deposit_authority: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
deposit_stake_address: &Pubkey,
deposit_stake_withdraw_authority: &Pubkey,
validator_stake_account: &Pubkey,
reserve_stake_account: &Pubkey,
pool_tokens_to: &Pubkey,
manager_fee_account: &Pubkey,
referrer_pool_tokens_account: &Pubkey,
pool_mint: &Pubkey,
token_program_id: &Pubkey,
minimum_pool_tokens_out: u64,
) -> Vec<Instruction> {
deposit_stake_internal(
program_id,
stake_pool,
validator_list_storage,
Some(stake_pool_deposit_authority),
stake_pool_withdraw_authority,
deposit_stake_address,
deposit_stake_withdraw_authority,
validator_stake_account,
reserve_stake_account,
pool_tokens_to,
manager_fee_account,
referrer_pool_tokens_account,
pool_mint,
token_program_id,
Some(minimum_pool_tokens_out),
)
}
fn deposit_sol_internal(
program_id: &Pubkey,
stake_pool: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
reserve_stake_account: &Pubkey,
lamports_from: &Pubkey,
pool_tokens_to: &Pubkey,
manager_fee_account: &Pubkey,
referrer_pool_tokens_account: &Pubkey,
pool_mint: &Pubkey,
token_program_id: &Pubkey,
sol_deposit_authority: Option<&Pubkey>,
lamports_in: u64,
minimum_pool_tokens_out: Option<u64>,
) -> Instruction {
let mut accounts = vec![
AccountMeta::new(*stake_pool, false),
AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
AccountMeta::new(*reserve_stake_account, false),
AccountMeta::new(*lamports_from, true),
AccountMeta::new(*pool_tokens_to, false),
AccountMeta::new(*manager_fee_account, false),
AccountMeta::new(*referrer_pool_tokens_account, false),
AccountMeta::new(*pool_mint, false),
AccountMeta::new_readonly(system_program::id(), false),
AccountMeta::new_readonly(*token_program_id, false),
];
if let Some(sol_deposit_authority) = sol_deposit_authority {
accounts.push(AccountMeta::new_readonly(*sol_deposit_authority, true));
}
if let Some(minimum_pool_tokens_out) = minimum_pool_tokens_out {
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::DepositSolWithSlippage {
lamports_in,
minimum_pool_tokens_out,
})
.unwrap(),
}
} else {
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::DepositSol(lamports_in)).unwrap(),
}
}
}
pub fn deposit_sol(
program_id: &Pubkey,
stake_pool: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
reserve_stake_account: &Pubkey,
lamports_from: &Pubkey,
pool_tokens_to: &Pubkey,
manager_fee_account: &Pubkey,
referrer_pool_tokens_account: &Pubkey,
pool_mint: &Pubkey,
token_program_id: &Pubkey,
lamports_in: u64,
) -> Instruction {
deposit_sol_internal(
program_id,
stake_pool,
stake_pool_withdraw_authority,
reserve_stake_account,
lamports_from,
pool_tokens_to,
manager_fee_account,
referrer_pool_tokens_account,
pool_mint,
token_program_id,
None,
lamports_in,
None,
)
}
pub fn deposit_sol_with_slippage(
program_id: &Pubkey,
stake_pool: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
reserve_stake_account: &Pubkey,
lamports_from: &Pubkey,
pool_tokens_to: &Pubkey,
manager_fee_account: &Pubkey,
referrer_pool_tokens_account: &Pubkey,
pool_mint: &Pubkey,
token_program_id: &Pubkey,
lamports_in: u64,
minimum_pool_tokens_out: u64,
) -> Instruction {
deposit_sol_internal(
program_id,
stake_pool,
stake_pool_withdraw_authority,
reserve_stake_account,
lamports_from,
pool_tokens_to,
manager_fee_account,
referrer_pool_tokens_account,
pool_mint,
token_program_id,
None,
lamports_in,
Some(minimum_pool_tokens_out),
)
}
pub fn deposit_sol_with_authority(
program_id: &Pubkey,
stake_pool: &Pubkey,
sol_deposit_authority: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
reserve_stake_account: &Pubkey,
lamports_from: &Pubkey,
pool_tokens_to: &Pubkey,
manager_fee_account: &Pubkey,
referrer_pool_tokens_account: &Pubkey,
pool_mint: &Pubkey,
token_program_id: &Pubkey,
lamports_in: u64,
) -> Instruction {
deposit_sol_internal(
program_id,
stake_pool,
stake_pool_withdraw_authority,
reserve_stake_account,
lamports_from,
pool_tokens_to,
manager_fee_account,
referrer_pool_tokens_account,
pool_mint,
token_program_id,
Some(sol_deposit_authority),
lamports_in,
None,
)
}
pub fn deposit_sol_with_authority_and_slippage(
program_id: &Pubkey,
stake_pool: &Pubkey,
sol_deposit_authority: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
reserve_stake_account: &Pubkey,
lamports_from: &Pubkey,
pool_tokens_to: &Pubkey,
manager_fee_account: &Pubkey,
referrer_pool_tokens_account: &Pubkey,
pool_mint: &Pubkey,
token_program_id: &Pubkey,
lamports_in: u64,
minimum_pool_tokens_out: u64,
) -> Instruction {
deposit_sol_internal(
program_id,
stake_pool,
stake_pool_withdraw_authority,
reserve_stake_account,
lamports_from,
pool_tokens_to,
manager_fee_account,
referrer_pool_tokens_account,
pool_mint,
token_program_id,
Some(sol_deposit_authority),
lamports_in,
Some(minimum_pool_tokens_out),
)
}
fn withdraw_stake_internal(
program_id: &Pubkey,
stake_pool: &Pubkey,
validator_list_storage: &Pubkey,
stake_pool_withdraw: &Pubkey,
stake_to_split: &Pubkey,
stake_to_receive: &Pubkey,
user_stake_authority: &Pubkey,
user_transfer_authority: &Pubkey,
user_pool_token_account: &Pubkey,
manager_fee_account: &Pubkey,
pool_mint: &Pubkey,
token_program_id: &Pubkey,
pool_tokens_in: u64,
minimum_lamports_out: Option<u64>,
) -> Instruction {
let accounts = vec![
AccountMeta::new(*stake_pool, false),
AccountMeta::new(*validator_list_storage, false),
AccountMeta::new_readonly(*stake_pool_withdraw, false),
AccountMeta::new(*stake_to_split, false),
AccountMeta::new(*stake_to_receive, false),
AccountMeta::new_readonly(*user_stake_authority, false),
AccountMeta::new_readonly(*user_transfer_authority, true),
AccountMeta::new(*user_pool_token_account, false),
AccountMeta::new(*manager_fee_account, false),
AccountMeta::new(*pool_mint, false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(*token_program_id, false),
AccountMeta::new_readonly(stake::program::id(), false),
];
if let Some(minimum_lamports_out) = minimum_lamports_out {
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::WithdrawStakeWithSlippage {
pool_tokens_in,
minimum_lamports_out,
})
.unwrap(),
}
} else {
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::WithdrawStake(pool_tokens_in)).unwrap(),
}
}
}
pub fn withdraw_stake(
program_id: &Pubkey,
stake_pool: &Pubkey,
validator_list_storage: &Pubkey,
stake_pool_withdraw: &Pubkey,
stake_to_split: &Pubkey,
stake_to_receive: &Pubkey,
user_stake_authority: &Pubkey,
user_transfer_authority: &Pubkey,
user_pool_token_account: &Pubkey,
manager_fee_account: &Pubkey,
pool_mint: &Pubkey,
token_program_id: &Pubkey,
pool_tokens_in: u64,
) -> Instruction {
withdraw_stake_internal(
program_id,
stake_pool,
validator_list_storage,
stake_pool_withdraw,
stake_to_split,
stake_to_receive,
user_stake_authority,
user_transfer_authority,
user_pool_token_account,
manager_fee_account,
pool_mint,
token_program_id,
pool_tokens_in,
None,
)
}
pub fn withdraw_stake_with_slippage(
program_id: &Pubkey,
stake_pool: &Pubkey,
validator_list_storage: &Pubkey,
stake_pool_withdraw: &Pubkey,
stake_to_split: &Pubkey,
stake_to_receive: &Pubkey,
user_stake_authority: &Pubkey,
user_transfer_authority: &Pubkey,
user_pool_token_account: &Pubkey,
manager_fee_account: &Pubkey,
pool_mint: &Pubkey,
token_program_id: &Pubkey,
pool_tokens_in: u64,
minimum_lamports_out: u64,
) -> Instruction {
withdraw_stake_internal(
program_id,
stake_pool,
validator_list_storage,
stake_pool_withdraw,
stake_to_split,
stake_to_receive,
user_stake_authority,
user_transfer_authority,
user_pool_token_account,
manager_fee_account,
pool_mint,
token_program_id,
pool_tokens_in,
Some(minimum_lamports_out),
)
}
fn withdraw_sol_internal(
program_id: &Pubkey,
stake_pool: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
user_transfer_authority: &Pubkey,
pool_tokens_from: &Pubkey,
reserve_stake_account: &Pubkey,
lamports_to: &Pubkey,
manager_fee_account: &Pubkey,
pool_mint: &Pubkey,
token_program_id: &Pubkey,
sol_withdraw_authority: Option<&Pubkey>,
pool_tokens_in: u64,
minimum_lamports_out: Option<u64>,
) -> Instruction {
let mut accounts = vec![
AccountMeta::new(*stake_pool, false),
AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
AccountMeta::new_readonly(*user_transfer_authority, true),
AccountMeta::new(*pool_tokens_from, false),
AccountMeta::new(*reserve_stake_account, false),
AccountMeta::new(*lamports_to, false),
AccountMeta::new(*manager_fee_account, false),
AccountMeta::new(*pool_mint, false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
AccountMeta::new_readonly(stake::program::id(), false),
AccountMeta::new_readonly(*token_program_id, false),
];
if let Some(sol_withdraw_authority) = sol_withdraw_authority {
accounts.push(AccountMeta::new_readonly(*sol_withdraw_authority, true));
}
if let Some(minimum_lamports_out) = minimum_lamports_out {
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::WithdrawSolWithSlippage {
pool_tokens_in,
minimum_lamports_out,
})
.unwrap(),
}
} else {
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::WithdrawSol(pool_tokens_in)).unwrap(),
}
}
}
pub fn withdraw_sol(
program_id: &Pubkey,
stake_pool: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
user_transfer_authority: &Pubkey,
pool_tokens_from: &Pubkey,
reserve_stake_account: &Pubkey,
lamports_to: &Pubkey,
manager_fee_account: &Pubkey,
pool_mint: &Pubkey,
token_program_id: &Pubkey,
pool_tokens_in: u64,
) -> Instruction {
withdraw_sol_internal(
program_id,
stake_pool,
stake_pool_withdraw_authority,
user_transfer_authority,
pool_tokens_from,
reserve_stake_account,
lamports_to,
manager_fee_account,
pool_mint,
token_program_id,
None,
pool_tokens_in,
None,
)
}
pub fn withdraw_sol_with_slippage(
program_id: &Pubkey,
stake_pool: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
user_transfer_authority: &Pubkey,
pool_tokens_from: &Pubkey,
reserve_stake_account: &Pubkey,
lamports_to: &Pubkey,
manager_fee_account: &Pubkey,
pool_mint: &Pubkey,
token_program_id: &Pubkey,
pool_tokens_in: u64,
minimum_lamports_out: u64,
) -> Instruction {
withdraw_sol_internal(
program_id,
stake_pool,
stake_pool_withdraw_authority,
user_transfer_authority,
pool_tokens_from,
reserve_stake_account,
lamports_to,
manager_fee_account,
pool_mint,
token_program_id,
None,
pool_tokens_in,
Some(minimum_lamports_out),
)
}
pub fn withdraw_sol_with_authority(
program_id: &Pubkey,
stake_pool: &Pubkey,
sol_withdraw_authority: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
user_transfer_authority: &Pubkey,
pool_tokens_from: &Pubkey,
reserve_stake_account: &Pubkey,
lamports_to: &Pubkey,
manager_fee_account: &Pubkey,
pool_mint: &Pubkey,
token_program_id: &Pubkey,
pool_tokens_in: u64,
) -> Instruction {
withdraw_sol_internal(
program_id,
stake_pool,
stake_pool_withdraw_authority,
user_transfer_authority,
pool_tokens_from,
reserve_stake_account,
lamports_to,
manager_fee_account,
pool_mint,
token_program_id,
Some(sol_withdraw_authority),
pool_tokens_in,
None,
)
}
pub fn withdraw_sol_with_authority_and_slippage(
program_id: &Pubkey,
stake_pool: &Pubkey,
sol_withdraw_authority: &Pubkey,
stake_pool_withdraw_authority: &Pubkey,
user_transfer_authority: &Pubkey,
pool_tokens_from: &Pubkey,
reserve_stake_account: &Pubkey,
lamports_to: &Pubkey,
manager_fee_account: &Pubkey,
pool_mint: &Pubkey,
token_program_id: &Pubkey,
pool_tokens_in: u64,
minimum_lamports_out: u64,
) -> Instruction {
withdraw_sol_internal(
program_id,
stake_pool,
stake_pool_withdraw_authority,
user_transfer_authority,
pool_tokens_from,
reserve_stake_account,
lamports_to,
manager_fee_account,
pool_mint,
token_program_id,
Some(sol_withdraw_authority),
pool_tokens_in,
Some(minimum_lamports_out),
)
}
pub fn set_manager(
program_id: &Pubkey,
stake_pool: &Pubkey,
manager: &Pubkey,
new_manager: &Pubkey,
new_fee_receiver: &Pubkey,
) -> Instruction {
let accounts = vec![
AccountMeta::new(*stake_pool, false),
AccountMeta::new_readonly(*manager, true),
AccountMeta::new_readonly(*new_manager, true),
AccountMeta::new_readonly(*new_fee_receiver, false),
];
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::SetManager).unwrap(),
}
}
pub fn set_fee(
program_id: &Pubkey,
stake_pool: &Pubkey,
manager: &Pubkey,
fee: FeeType,
) -> Instruction {
let accounts = vec![
AccountMeta::new(*stake_pool, false),
AccountMeta::new_readonly(*manager, true),
];
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::SetFee { fee }).unwrap(),
}
}
pub fn set_staker(
program_id: &Pubkey,
stake_pool: &Pubkey,
set_staker_authority: &Pubkey,
new_staker: &Pubkey,
) -> Instruction {
let accounts = vec![
AccountMeta::new(*stake_pool, false),
AccountMeta::new_readonly(*set_staker_authority, true),
AccountMeta::new_readonly(*new_staker, false),
];
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::SetStaker).unwrap(),
}
}
pub fn set_funding_authority(
program_id: &Pubkey,
stake_pool: &Pubkey,
manager: &Pubkey,
new_sol_deposit_authority: Option<&Pubkey>,
funding_type: FundingType,
) -> Instruction {
let mut accounts = vec![
AccountMeta::new(*stake_pool, false),
AccountMeta::new_readonly(*manager, true),
];
if let Some(auth) = new_sol_deposit_authority {
accounts.push(AccountMeta::new_readonly(*auth, false))
}
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::SetFundingAuthority(funding_type)).unwrap(),
}
}
pub fn update_token_metadata(
program_id: &Pubkey,
stake_pool: &Pubkey,
manager: &Pubkey,
pool_mint: &Pubkey,
name: String,
symbol: String,
uri: String,
) -> Instruction {
let (stake_pool_withdraw_authority, _) =
find_withdraw_authority_program_address(program_id, stake_pool);
let (token_metadata, _) = find_metadata_account(pool_mint);
let accounts = vec![
AccountMeta::new_readonly(*stake_pool, false),
AccountMeta::new_readonly(*manager, true),
AccountMeta::new_readonly(stake_pool_withdraw_authority, false),
AccountMeta::new(token_metadata, false),
AccountMeta::new_readonly(inline_mpl_token_metadata::id(), false),
];
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::UpdateTokenMetadata { name, symbol, uri })
.unwrap(),
}
}
pub fn create_token_metadata(
program_id: &Pubkey,
stake_pool: &Pubkey,
manager: &Pubkey,
pool_mint: &Pubkey,
payer: &Pubkey,
name: String,
symbol: String,
uri: String,
) -> Instruction {
let (stake_pool_withdraw_authority, _) =
find_withdraw_authority_program_address(program_id, stake_pool);
let (token_metadata, _) = find_metadata_account(pool_mint);
let accounts = vec![
AccountMeta::new_readonly(*stake_pool, false),
AccountMeta::new_readonly(*manager, true),
AccountMeta::new_readonly(stake_pool_withdraw_authority, false),
AccountMeta::new_readonly(*pool_mint, false),
AccountMeta::new(*payer, true),
AccountMeta::new(token_metadata, false),
AccountMeta::new_readonly(inline_mpl_token_metadata::id(), false),
AccountMeta::new_readonly(system_program::id(), false),
];
Instruction {
program_id: *program_id,
accounts,
data: borsh::to_vec(&StakePoolInstruction::CreateTokenMetadata { name, symbol, uri })
.unwrap(),
}
}