1#![allow(deprecated)]
6#![allow(clippy::too_many_arguments)]
7
8use {
9 crate::{
10 find_deposit_authority_program_address, find_ephemeral_stake_program_address,
11 find_stake_program_address, find_transient_stake_program_address,
12 find_withdraw_authority_program_address,
13 inline_mpl_token_metadata::{self, pda::find_metadata_account},
14 state::{Fee, FeeType, StakePool, ValidatorList, ValidatorStakeInfo},
15 MAX_VALIDATORS_TO_UPDATE,
16 },
17 borsh::{BorshDeserialize, BorshSchema, BorshSerialize},
18 solana_instruction::{AccountMeta, Instruction},
19 solana_program_error::ProgramError,
20 solana_pubkey::Pubkey,
21 solana_stake_interface::stake_history::Epoch,
22 std::num::NonZeroU32,
23};
24
25#[repr(C)]
28#[derive(Clone, Debug, PartialEq, BorshSerialize, BorshDeserialize, BorshSchema)]
29pub enum PreferredValidatorType {
30 Deposit,
32 Withdraw,
34}
35
36#[repr(C)]
39#[derive(Clone, Debug, PartialEq, BorshSerialize, BorshDeserialize, BorshSchema)]
40pub enum FundingType {
41 StakeDeposit,
43 SolDeposit,
45 SolWithdraw,
47}
48
49#[repr(C)]
51#[derive(Clone, Debug, PartialEq, BorshSerialize, BorshDeserialize)]
52pub enum StakePoolInstruction {
53 Initialize {
71 fee: Fee,
73 withdrawal_fee: Fee,
75 deposit_fee: Fee,
77 referral_fee: u8,
79 max_validators: u32,
81 },
82
83 AddValidatorToPool(u32),
110
111 RemoveValidatorFromPool,
127
128 DecreaseValidatorStake {
159 lamports: u64,
161 transient_stake_seed: u64,
163 },
164
165 IncreaseValidatorStake {
200 lamports: u64,
202 transient_stake_seed: u64,
204 },
205
206 SetPreferredValidator {
220 validator_type: PreferredValidatorType,
222 validator_vote_address: Option<Pubkey>,
225 },
226
227 UpdateValidatorListBalance {
245 start_index: u32,
247 no_merge: bool,
252 },
253
254 UpdateStakePoolBalance,
265
266 CleanupRemovedValidatorEntries,
271
272 DepositStake,
301
302 WithdrawStake(u64),
339
340 SetManager,
347
348 SetFee {
353 fee: FeeType,
355 },
356
357 SetStaker,
363
364 DepositSol(u64),
380
381 SetFundingAuthority(FundingType),
388
389 WithdrawSol(u64),
407
408 CreateTokenMetadata {
419 name: String,
421 symbol: String,
423 uri: String,
425 },
426 UpdateTokenMetadata {
435 name: String,
437 symbol: String,
439 uri: String,
441 },
442
443 IncreaseAdditionalValidatorStake {
480 lamports: u64,
482 transient_stake_seed: u64,
484 ephemeral_stake_seed: u64,
486 },
487
488 DecreaseAdditionalValidatorStake {
518 lamports: u64,
520 transient_stake_seed: u64,
522 ephemeral_stake_seed: u64,
524 },
525
526 DecreaseValidatorStakeWithReserve {
557 lamports: u64,
559 transient_stake_seed: u64,
561 },
562
563 #[deprecated(
614 since = "2.0.0",
615 note = "The stake redelegate instruction used in this will not be enabled."
616 )]
617 Redelegate {
618 #[allow(dead_code)] lamports: u64,
621 #[allow(dead_code)] source_transient_stake_seed: u64,
624 #[allow(dead_code)] ephemeral_stake_seed: u64,
627 #[allow(dead_code)] destination_transient_stake_seed: u64,
632 },
633
634 DepositStakeWithSlippage {
658 minimum_pool_tokens_out: u64,
660 },
661
662 WithdrawStakeWithSlippage {
688 pool_tokens_in: u64,
690 minimum_lamports_out: u64,
692 },
693
694 DepositSolWithSlippage {
711 lamports_in: u64,
713 minimum_pool_tokens_out: u64,
715 },
716
717 WithdrawSolWithSlippage {
736 pool_tokens_in: u64,
738 minimum_lamports_out: u64,
740 },
741}
742
743pub fn initialize(
745 program_id: &Pubkey,
746 stake_pool: &Pubkey,
747 manager: &Pubkey,
748 staker: &Pubkey,
749 stake_pool_withdraw_authority: &Pubkey,
750 validator_list: &Pubkey,
751 reserve_stake: &Pubkey,
752 pool_mint: &Pubkey,
753 manager_pool_account: &Pubkey,
754 token_program_id: &Pubkey,
755 deposit_authority: Option<Pubkey>,
756 fee: Fee,
757 withdrawal_fee: Fee,
758 deposit_fee: Fee,
759 referral_fee: u8,
760 max_validators: u32,
761) -> Instruction {
762 let init_data = StakePoolInstruction::Initialize {
763 fee,
764 withdrawal_fee,
765 deposit_fee,
766 referral_fee,
767 max_validators,
768 };
769 let data = borsh::to_vec(&init_data).unwrap();
770 let mut accounts = vec![
771 AccountMeta::new(*stake_pool, false),
772 AccountMeta::new_readonly(*manager, true),
773 AccountMeta::new_readonly(*staker, false),
774 AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
775 AccountMeta::new(*validator_list, false),
776 AccountMeta::new_readonly(*reserve_stake, false),
777 AccountMeta::new(*pool_mint, false),
778 AccountMeta::new(*manager_pool_account, false),
779 AccountMeta::new_readonly(*token_program_id, false),
780 ];
781 if let Some(deposit_authority) = deposit_authority {
782 accounts.push(AccountMeta::new_readonly(deposit_authority, true));
783 }
784 Instruction {
785 program_id: *program_id,
786 accounts,
787 data,
788 }
789}
790
791pub fn add_validator_to_pool(
794 program_id: &Pubkey,
795 stake_pool: &Pubkey,
796 staker: &Pubkey,
797 reserve: &Pubkey,
798 stake_pool_withdraw: &Pubkey,
799 validator_list: &Pubkey,
800 stake: &Pubkey,
801 validator: &Pubkey,
802 seed: Option<NonZeroU32>,
803) -> Instruction {
804 let accounts = vec![
805 AccountMeta::new(*stake_pool, false),
806 AccountMeta::new_readonly(*staker, true),
807 AccountMeta::new(*reserve, false),
808 AccountMeta::new_readonly(*stake_pool_withdraw, false),
809 AccountMeta::new(*validator_list, false),
810 AccountMeta::new(*stake, false),
811 AccountMeta::new_readonly(*validator, false),
812 AccountMeta::new_readonly(solana_sdk_ids::sysvar::rent::id(), false),
813 AccountMeta::new_readonly(solana_sdk_ids::sysvar::clock::id(), false),
814 AccountMeta::new_readonly(solana_sdk_ids::sysvar::stake_history::id(), false),
815 #[allow(deprecated)]
816 AccountMeta::new_readonly(solana_stake_interface::config::id(), false),
817 AccountMeta::new_readonly(solana_system_interface::program::id(), false),
818 AccountMeta::new_readonly(solana_stake_interface::program::id(), false),
819 ];
820 let data = borsh::to_vec(&StakePoolInstruction::AddValidatorToPool(
821 seed.map(|s| s.get()).unwrap_or(0),
822 ))
823 .unwrap();
824 Instruction {
825 program_id: *program_id,
826 accounts,
827 data,
828 }
829}
830
831pub fn remove_validator_from_pool(
834 program_id: &Pubkey,
835 stake_pool: &Pubkey,
836 staker: &Pubkey,
837 stake_pool_withdraw: &Pubkey,
838 validator_list: &Pubkey,
839 stake_account: &Pubkey,
840 transient_stake_account: &Pubkey,
841) -> Instruction {
842 let accounts = vec![
843 AccountMeta::new(*stake_pool, false),
844 AccountMeta::new_readonly(*staker, true),
845 AccountMeta::new_readonly(*stake_pool_withdraw, false),
846 AccountMeta::new(*validator_list, false),
847 AccountMeta::new(*stake_account, false),
848 AccountMeta::new(*transient_stake_account, false),
849 AccountMeta::new_readonly(solana_sdk_ids::sysvar::clock::id(), false),
850 AccountMeta::new_readonly(solana_stake_interface::program::id(), false),
851 ];
852 Instruction {
853 program_id: *program_id,
854 accounts,
855 data: borsh::to_vec(&StakePoolInstruction::RemoveValidatorFromPool).unwrap(),
856 }
857}
858
859#[deprecated(
862 since = "0.7.0",
863 note = "please use `decrease_validator_stake_with_reserve`"
864)]
865pub fn decrease_validator_stake(
866 program_id: &Pubkey,
867 stake_pool: &Pubkey,
868 staker: &Pubkey,
869 stake_pool_withdraw_authority: &Pubkey,
870 validator_list: &Pubkey,
871 validator_stake: &Pubkey,
872 transient_stake: &Pubkey,
873 lamports: u64,
874 transient_stake_seed: u64,
875) -> Instruction {
876 let accounts = vec![
877 AccountMeta::new_readonly(*stake_pool, false),
878 AccountMeta::new_readonly(*staker, true),
879 AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
880 AccountMeta::new(*validator_list, false),
881 AccountMeta::new(*validator_stake, false),
882 AccountMeta::new(*transient_stake, false),
883 AccountMeta::new_readonly(solana_sdk_ids::sysvar::clock::id(), false),
884 AccountMeta::new_readonly(solana_sdk_ids::sysvar::rent::id(), false),
885 AccountMeta::new_readonly(solana_system_interface::program::id(), false),
886 AccountMeta::new_readonly(solana_stake_interface::program::id(), false),
887 ];
888 Instruction {
889 program_id: *program_id,
890 accounts,
891 data: borsh::to_vec(&StakePoolInstruction::DecreaseValidatorStake {
892 lamports,
893 transient_stake_seed,
894 })
895 .unwrap(),
896 }
897}
898
899pub fn decrease_additional_validator_stake(
902 program_id: &Pubkey,
903 stake_pool: &Pubkey,
904 staker: &Pubkey,
905 stake_pool_withdraw_authority: &Pubkey,
906 validator_list: &Pubkey,
907 reserve_stake: &Pubkey,
908 validator_stake: &Pubkey,
909 ephemeral_stake: &Pubkey,
910 transient_stake: &Pubkey,
911 lamports: u64,
912 transient_stake_seed: u64,
913 ephemeral_stake_seed: u64,
914) -> Instruction {
915 let accounts = vec![
916 AccountMeta::new_readonly(*stake_pool, false),
917 AccountMeta::new_readonly(*staker, true),
918 AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
919 AccountMeta::new(*validator_list, false),
920 AccountMeta::new(*reserve_stake, false),
921 AccountMeta::new(*validator_stake, false),
922 AccountMeta::new(*ephemeral_stake, false),
923 AccountMeta::new(*transient_stake, false),
924 AccountMeta::new_readonly(solana_sdk_ids::sysvar::clock::id(), false),
925 AccountMeta::new_readonly(solana_sdk_ids::sysvar::stake_history::id(), false),
926 AccountMeta::new_readonly(solana_system_interface::program::id(), false),
927 AccountMeta::new_readonly(solana_stake_interface::program::id(), false),
928 ];
929 Instruction {
930 program_id: *program_id,
931 accounts,
932 data: borsh::to_vec(&StakePoolInstruction::DecreaseAdditionalValidatorStake {
933 lamports,
934 transient_stake_seed,
935 ephemeral_stake_seed,
936 })
937 .unwrap(),
938 }
939}
940
941pub fn decrease_validator_stake_with_reserve(
944 program_id: &Pubkey,
945 stake_pool: &Pubkey,
946 staker: &Pubkey,
947 stake_pool_withdraw_authority: &Pubkey,
948 validator_list: &Pubkey,
949 reserve_stake: &Pubkey,
950 validator_stake: &Pubkey,
951 transient_stake: &Pubkey,
952 lamports: u64,
953 transient_stake_seed: u64,
954) -> Instruction {
955 let accounts = vec![
956 AccountMeta::new_readonly(*stake_pool, false),
957 AccountMeta::new_readonly(*staker, true),
958 AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
959 AccountMeta::new(*validator_list, false),
960 AccountMeta::new(*reserve_stake, false),
961 AccountMeta::new(*validator_stake, false),
962 AccountMeta::new(*transient_stake, false),
963 AccountMeta::new_readonly(solana_sdk_ids::sysvar::clock::id(), false),
964 AccountMeta::new_readonly(solana_sdk_ids::sysvar::stake_history::id(), false),
965 AccountMeta::new_readonly(solana_system_interface::program::id(), false),
966 AccountMeta::new_readonly(solana_stake_interface::program::id(), false),
967 ];
968 Instruction {
969 program_id: *program_id,
970 accounts,
971 data: borsh::to_vec(&StakePoolInstruction::DecreaseValidatorStakeWithReserve {
972 lamports,
973 transient_stake_seed,
974 })
975 .unwrap(),
976 }
977}
978
979pub fn increase_validator_stake(
982 program_id: &Pubkey,
983 stake_pool: &Pubkey,
984 staker: &Pubkey,
985 stake_pool_withdraw_authority: &Pubkey,
986 validator_list: &Pubkey,
987 reserve_stake: &Pubkey,
988 transient_stake: &Pubkey,
989 validator_stake: &Pubkey,
990 validator: &Pubkey,
991 lamports: u64,
992 transient_stake_seed: u64,
993) -> Instruction {
994 let accounts = vec![
995 AccountMeta::new_readonly(*stake_pool, false),
996 AccountMeta::new_readonly(*staker, true),
997 AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
998 AccountMeta::new(*validator_list, false),
999 AccountMeta::new(*reserve_stake, false),
1000 AccountMeta::new(*transient_stake, false),
1001 AccountMeta::new_readonly(*validator_stake, false),
1002 AccountMeta::new_readonly(*validator, false),
1003 AccountMeta::new_readonly(solana_sdk_ids::sysvar::clock::id(), false),
1004 AccountMeta::new_readonly(solana_sdk_ids::sysvar::rent::id(), false),
1005 AccountMeta::new_readonly(solana_sdk_ids::sysvar::stake_history::id(), false),
1006 #[allow(deprecated)]
1007 AccountMeta::new_readonly(solana_stake_interface::config::id(), false),
1008 AccountMeta::new_readonly(solana_system_interface::program::id(), false),
1009 AccountMeta::new_readonly(solana_stake_interface::program::id(), false),
1010 ];
1011 Instruction {
1012 program_id: *program_id,
1013 accounts,
1014 data: borsh::to_vec(&StakePoolInstruction::IncreaseValidatorStake {
1015 lamports,
1016 transient_stake_seed,
1017 })
1018 .unwrap(),
1019 }
1020}
1021
1022pub fn increase_additional_validator_stake(
1025 program_id: &Pubkey,
1026 stake_pool: &Pubkey,
1027 staker: &Pubkey,
1028 stake_pool_withdraw_authority: &Pubkey,
1029 validator_list: &Pubkey,
1030 reserve_stake: &Pubkey,
1031 ephemeral_stake: &Pubkey,
1032 transient_stake: &Pubkey,
1033 validator_stake: &Pubkey,
1034 validator: &Pubkey,
1035 lamports: u64,
1036 transient_stake_seed: u64,
1037 ephemeral_stake_seed: u64,
1038) -> Instruction {
1039 let accounts = vec![
1040 AccountMeta::new_readonly(*stake_pool, false),
1041 AccountMeta::new_readonly(*staker, true),
1042 AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
1043 AccountMeta::new(*validator_list, false),
1044 AccountMeta::new(*reserve_stake, false),
1045 AccountMeta::new(*ephemeral_stake, false),
1046 AccountMeta::new(*transient_stake, false),
1047 AccountMeta::new_readonly(*validator_stake, false),
1048 AccountMeta::new_readonly(*validator, false),
1049 AccountMeta::new_readonly(solana_sdk_ids::sysvar::clock::id(), false),
1050 AccountMeta::new_readonly(solana_sdk_ids::sysvar::stake_history::id(), false),
1051 #[allow(deprecated)]
1052 AccountMeta::new_readonly(solana_stake_interface::config::id(), false),
1053 AccountMeta::new_readonly(solana_system_interface::program::id(), false),
1054 AccountMeta::new_readonly(solana_stake_interface::program::id(), false),
1055 ];
1056 Instruction {
1057 program_id: *program_id,
1058 accounts,
1059 data: borsh::to_vec(&StakePoolInstruction::IncreaseAdditionalValidatorStake {
1060 lamports,
1061 transient_stake_seed,
1062 ephemeral_stake_seed,
1063 })
1064 .unwrap(),
1065 }
1066}
1067
1068#[deprecated(
1071 since = "2.0.0",
1072 note = "The stake redelegate instruction used in this will not be enabled."
1073)]
1074pub fn redelegate(
1075 program_id: &Pubkey,
1076 stake_pool: &Pubkey,
1077 staker: &Pubkey,
1078 stake_pool_withdraw_authority: &Pubkey,
1079 validator_list: &Pubkey,
1080 reserve_stake: &Pubkey,
1081 source_validator_stake: &Pubkey,
1082 source_transient_stake: &Pubkey,
1083 ephemeral_stake: &Pubkey,
1084 destination_transient_stake: &Pubkey,
1085 destination_validator_stake: &Pubkey,
1086 validator: &Pubkey,
1087 lamports: u64,
1088 source_transient_stake_seed: u64,
1089 ephemeral_stake_seed: u64,
1090 destination_transient_stake_seed: u64,
1091) -> Instruction {
1092 let accounts = vec![
1093 AccountMeta::new_readonly(*stake_pool, false),
1094 AccountMeta::new_readonly(*staker, true),
1095 AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
1096 AccountMeta::new(*validator_list, false),
1097 AccountMeta::new(*reserve_stake, false),
1098 AccountMeta::new(*source_validator_stake, false),
1099 AccountMeta::new(*source_transient_stake, false),
1100 AccountMeta::new(*ephemeral_stake, false),
1101 AccountMeta::new(*destination_transient_stake, false),
1102 AccountMeta::new_readonly(*destination_validator_stake, false),
1103 AccountMeta::new_readonly(*validator, false),
1104 AccountMeta::new_readonly(solana_sdk_ids::sysvar::clock::id(), false),
1105 AccountMeta::new_readonly(solana_sdk_ids::sysvar::stake_history::id(), false),
1106 #[allow(deprecated)]
1107 AccountMeta::new_readonly(solana_stake_interface::config::id(), false),
1108 AccountMeta::new_readonly(solana_system_interface::program::id(), false),
1109 AccountMeta::new_readonly(solana_stake_interface::program::id(), false),
1110 ];
1111 Instruction {
1112 program_id: *program_id,
1113 accounts,
1114 data: borsh::to_vec(&StakePoolInstruction::Redelegate {
1115 lamports,
1116 source_transient_stake_seed,
1117 ephemeral_stake_seed,
1118 destination_transient_stake_seed,
1119 })
1120 .unwrap(),
1121 }
1122}
1123
1124pub fn set_preferred_validator(
1126 program_id: &Pubkey,
1127 stake_pool_address: &Pubkey,
1128 staker: &Pubkey,
1129 validator_list_address: &Pubkey,
1130 validator_type: PreferredValidatorType,
1131 validator_vote_address: Option<Pubkey>,
1132) -> Instruction {
1133 Instruction {
1134 program_id: *program_id,
1135 accounts: vec![
1136 AccountMeta::new(*stake_pool_address, false),
1137 AccountMeta::new_readonly(*staker, true),
1138 AccountMeta::new_readonly(*validator_list_address, false),
1139 ],
1140 data: borsh::to_vec(&StakePoolInstruction::SetPreferredValidator {
1141 validator_type,
1142 validator_vote_address,
1143 })
1144 .unwrap(),
1145 }
1146}
1147
1148pub fn add_validator_to_pool_with_vote(
1151 program_id: &Pubkey,
1152 stake_pool: &StakePool,
1153 stake_pool_address: &Pubkey,
1154 vote_account_address: &Pubkey,
1155 seed: Option<NonZeroU32>,
1156) -> Instruction {
1157 let pool_withdraw_authority =
1158 find_withdraw_authority_program_address(program_id, stake_pool_address).0;
1159 let (stake_account_address, _) =
1160 find_stake_program_address(program_id, vote_account_address, stake_pool_address, seed);
1161 add_validator_to_pool(
1162 program_id,
1163 stake_pool_address,
1164 &stake_pool.staker,
1165 &stake_pool.reserve_stake,
1166 &pool_withdraw_authority,
1167 &stake_pool.validator_list,
1168 &stake_account_address,
1169 vote_account_address,
1170 seed,
1171 )
1172}
1173
1174pub fn remove_validator_from_pool_with_vote(
1177 program_id: &Pubkey,
1178 stake_pool: &StakePool,
1179 stake_pool_address: &Pubkey,
1180 vote_account_address: &Pubkey,
1181 validator_stake_seed: Option<NonZeroU32>,
1182 transient_stake_seed: u64,
1183) -> Instruction {
1184 let pool_withdraw_authority =
1185 find_withdraw_authority_program_address(program_id, stake_pool_address).0;
1186 let (stake_account_address, _) = find_stake_program_address(
1187 program_id,
1188 vote_account_address,
1189 stake_pool_address,
1190 validator_stake_seed,
1191 );
1192 let (transient_stake_account, _) = find_transient_stake_program_address(
1193 program_id,
1194 vote_account_address,
1195 stake_pool_address,
1196 transient_stake_seed,
1197 );
1198 remove_validator_from_pool(
1199 program_id,
1200 stake_pool_address,
1201 &stake_pool.staker,
1202 &pool_withdraw_authority,
1203 &stake_pool.validator_list,
1204 &stake_account_address,
1205 &transient_stake_account,
1206 )
1207}
1208
1209pub fn increase_validator_stake_with_vote(
1212 program_id: &Pubkey,
1213 stake_pool: &StakePool,
1214 stake_pool_address: &Pubkey,
1215 vote_account_address: &Pubkey,
1216 lamports: u64,
1217 validator_stake_seed: Option<NonZeroU32>,
1218 transient_stake_seed: u64,
1219) -> Instruction {
1220 let pool_withdraw_authority =
1221 find_withdraw_authority_program_address(program_id, stake_pool_address).0;
1222 let (transient_stake_address, _) = find_transient_stake_program_address(
1223 program_id,
1224 vote_account_address,
1225 stake_pool_address,
1226 transient_stake_seed,
1227 );
1228 let (validator_stake_address, _) = find_stake_program_address(
1229 program_id,
1230 vote_account_address,
1231 stake_pool_address,
1232 validator_stake_seed,
1233 );
1234
1235 increase_validator_stake(
1236 program_id,
1237 stake_pool_address,
1238 &stake_pool.staker,
1239 &pool_withdraw_authority,
1240 &stake_pool.validator_list,
1241 &stake_pool.reserve_stake,
1242 &transient_stake_address,
1243 &validator_stake_address,
1244 vote_account_address,
1245 lamports,
1246 transient_stake_seed,
1247 )
1248}
1249
1250pub fn increase_additional_validator_stake_with_vote(
1253 program_id: &Pubkey,
1254 stake_pool: &StakePool,
1255 stake_pool_address: &Pubkey,
1256 vote_account_address: &Pubkey,
1257 lamports: u64,
1258 validator_stake_seed: Option<NonZeroU32>,
1259 transient_stake_seed: u64,
1260 ephemeral_stake_seed: u64,
1261) -> Instruction {
1262 let pool_withdraw_authority =
1263 find_withdraw_authority_program_address(program_id, stake_pool_address).0;
1264 let (ephemeral_stake_address, _) =
1265 find_ephemeral_stake_program_address(program_id, stake_pool_address, ephemeral_stake_seed);
1266 let (transient_stake_address, _) = find_transient_stake_program_address(
1267 program_id,
1268 vote_account_address,
1269 stake_pool_address,
1270 transient_stake_seed,
1271 );
1272 let (validator_stake_address, _) = find_stake_program_address(
1273 program_id,
1274 vote_account_address,
1275 stake_pool_address,
1276 validator_stake_seed,
1277 );
1278
1279 increase_additional_validator_stake(
1280 program_id,
1281 stake_pool_address,
1282 &stake_pool.staker,
1283 &pool_withdraw_authority,
1284 &stake_pool.validator_list,
1285 &stake_pool.reserve_stake,
1286 &ephemeral_stake_address,
1287 &transient_stake_address,
1288 &validator_stake_address,
1289 vote_account_address,
1290 lamports,
1291 transient_stake_seed,
1292 ephemeral_stake_seed,
1293 )
1294}
1295
1296pub fn decrease_validator_stake_with_vote(
1299 program_id: &Pubkey,
1300 stake_pool: &StakePool,
1301 stake_pool_address: &Pubkey,
1302 vote_account_address: &Pubkey,
1303 lamports: u64,
1304 validator_stake_seed: Option<NonZeroU32>,
1305 transient_stake_seed: u64,
1306) -> Instruction {
1307 let pool_withdraw_authority =
1308 find_withdraw_authority_program_address(program_id, stake_pool_address).0;
1309 let (validator_stake_address, _) = find_stake_program_address(
1310 program_id,
1311 vote_account_address,
1312 stake_pool_address,
1313 validator_stake_seed,
1314 );
1315 let (transient_stake_address, _) = find_transient_stake_program_address(
1316 program_id,
1317 vote_account_address,
1318 stake_pool_address,
1319 transient_stake_seed,
1320 );
1321 decrease_validator_stake_with_reserve(
1322 program_id,
1323 stake_pool_address,
1324 &stake_pool.staker,
1325 &pool_withdraw_authority,
1326 &stake_pool.validator_list,
1327 &stake_pool.reserve_stake,
1328 &validator_stake_address,
1329 &transient_stake_address,
1330 lamports,
1331 transient_stake_seed,
1332 )
1333}
1334
1335pub fn increase_additional_validator_stake_with_list(
1338 program_id: &Pubkey,
1339 stake_pool: &StakePool,
1340 validator_list: &ValidatorList,
1341 stake_pool_address: &Pubkey,
1342 vote_account_address: &Pubkey,
1343 lamports: u64,
1344 ephemeral_stake_seed: u64,
1345) -> Result<Instruction, ProgramError> {
1346 let validator_info = validator_list
1347 .find(vote_account_address)
1348 .ok_or(ProgramError::InvalidInstructionData)?;
1349 let transient_stake_seed = u64::from(validator_info.transient_seed_suffix);
1350 let validator_stake_seed = NonZeroU32::new(validator_info.validator_seed_suffix.into());
1351 Ok(increase_additional_validator_stake_with_vote(
1352 program_id,
1353 stake_pool,
1354 stake_pool_address,
1355 vote_account_address,
1356 lamports,
1357 validator_stake_seed,
1358 transient_stake_seed,
1359 ephemeral_stake_seed,
1360 ))
1361}
1362
1363pub fn decrease_additional_validator_stake_with_list(
1366 program_id: &Pubkey,
1367 stake_pool: &StakePool,
1368 validator_list: &ValidatorList,
1369 stake_pool_address: &Pubkey,
1370 vote_account_address: &Pubkey,
1371 lamports: u64,
1372 ephemeral_stake_seed: u64,
1373) -> Result<Instruction, ProgramError> {
1374 let validator_info = validator_list
1375 .find(vote_account_address)
1376 .ok_or(ProgramError::InvalidInstructionData)?;
1377 let transient_stake_seed = u64::from(validator_info.transient_seed_suffix);
1378 let validator_stake_seed = NonZeroU32::new(validator_info.validator_seed_suffix.into());
1379 Ok(decrease_additional_validator_stake_with_vote(
1380 program_id,
1381 stake_pool,
1382 stake_pool_address,
1383 vote_account_address,
1384 lamports,
1385 validator_stake_seed,
1386 transient_stake_seed,
1387 ephemeral_stake_seed,
1388 ))
1389}
1390
1391pub fn decrease_additional_validator_stake_with_vote(
1394 program_id: &Pubkey,
1395 stake_pool: &StakePool,
1396 stake_pool_address: &Pubkey,
1397 vote_account_address: &Pubkey,
1398 lamports: u64,
1399 validator_stake_seed: Option<NonZeroU32>,
1400 transient_stake_seed: u64,
1401 ephemeral_stake_seed: u64,
1402) -> Instruction {
1403 let pool_withdraw_authority =
1404 find_withdraw_authority_program_address(program_id, stake_pool_address).0;
1405 let (validator_stake_address, _) = find_stake_program_address(
1406 program_id,
1407 vote_account_address,
1408 stake_pool_address,
1409 validator_stake_seed,
1410 );
1411 let (ephemeral_stake_address, _) =
1412 find_ephemeral_stake_program_address(program_id, stake_pool_address, ephemeral_stake_seed);
1413 let (transient_stake_address, _) = find_transient_stake_program_address(
1414 program_id,
1415 vote_account_address,
1416 stake_pool_address,
1417 transient_stake_seed,
1418 );
1419 decrease_additional_validator_stake(
1420 program_id,
1421 stake_pool_address,
1422 &stake_pool.staker,
1423 &pool_withdraw_authority,
1424 &stake_pool.validator_list,
1425 &stake_pool.reserve_stake,
1426 &validator_stake_address,
1427 &ephemeral_stake_address,
1428 &transient_stake_address,
1429 lamports,
1430 transient_stake_seed,
1431 ephemeral_stake_seed,
1432 )
1433}
1434
1435#[deprecated(
1438 since = "1.1.0",
1439 note = "please use `update_validator_list_balance_chunk`"
1440)]
1441pub fn update_validator_list_balance(
1442 program_id: &Pubkey,
1443 stake_pool: &Pubkey,
1444 stake_pool_withdraw_authority: &Pubkey,
1445 validator_list_address: &Pubkey,
1446 reserve_stake: &Pubkey,
1447 validator_list: &ValidatorList,
1448 validator_vote_accounts: &[Pubkey],
1449 start_index: u32,
1450 no_merge: bool,
1451) -> Instruction {
1452 let mut accounts = vec![
1453 AccountMeta::new_readonly(*stake_pool, false),
1454 AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
1455 AccountMeta::new(*validator_list_address, false),
1456 AccountMeta::new(*reserve_stake, false),
1457 AccountMeta::new_readonly(solana_sdk_ids::sysvar::clock::id(), false),
1458 AccountMeta::new_readonly(solana_sdk_ids::sysvar::stake_history::id(), false),
1459 AccountMeta::new_readonly(solana_stake_interface::program::id(), false),
1460 ];
1461 accounts.append(
1462 &mut validator_vote_accounts
1463 .iter()
1464 .flat_map(|vote_account_address| {
1465 let validator_stake_info = validator_list.find(vote_account_address);
1466 if let Some(validator_stake_info) = validator_stake_info {
1467 let (validator_stake_account, _) = find_stake_program_address(
1468 program_id,
1469 vote_account_address,
1470 stake_pool,
1471 NonZeroU32::new(validator_stake_info.validator_seed_suffix.into()),
1472 );
1473 let (transient_stake_account, _) = find_transient_stake_program_address(
1474 program_id,
1475 vote_account_address,
1476 stake_pool,
1477 validator_stake_info.transient_seed_suffix.into(),
1478 );
1479 vec![
1480 AccountMeta::new(validator_stake_account, false),
1481 AccountMeta::new(transient_stake_account, false),
1482 ]
1483 } else {
1484 vec![]
1485 }
1486 })
1487 .collect::<Vec<AccountMeta>>(),
1488 );
1489 Instruction {
1490 program_id: *program_id,
1491 accounts,
1492 data: borsh::to_vec(&StakePoolInstruction::UpdateValidatorListBalance {
1493 start_index,
1494 no_merge,
1495 })
1496 .unwrap(),
1497 }
1498}
1499
1500pub fn update_validator_list_balance_chunk(
1508 program_id: &Pubkey,
1509 stake_pool: &Pubkey,
1510 stake_pool_withdraw_authority: &Pubkey,
1511 validator_list_address: &Pubkey,
1512 reserve_stake: &Pubkey,
1513 validator_list: &ValidatorList,
1514 len: usize,
1515 start_index: usize,
1516 no_merge: bool,
1517) -> Result<Instruction, ProgramError> {
1518 let mut accounts = vec![
1519 AccountMeta::new_readonly(*stake_pool, false),
1520 AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
1521 AccountMeta::new(*validator_list_address, false),
1522 AccountMeta::new(*reserve_stake, false),
1523 AccountMeta::new_readonly(solana_sdk_ids::sysvar::clock::id(), false),
1524 AccountMeta::new_readonly(solana_sdk_ids::sysvar::stake_history::id(), false),
1525 AccountMeta::new_readonly(solana_stake_interface::program::id(), false),
1526 ];
1527 let validator_list_subslice = validator_list
1528 .validators
1529 .get(start_index..start_index.saturating_add(len))
1530 .ok_or(ProgramError::InvalidInstructionData)?;
1531 accounts.extend(validator_list_subslice.iter().flat_map(
1532 |ValidatorStakeInfo {
1533 vote_account_address,
1534 validator_seed_suffix,
1535 transient_seed_suffix,
1536 ..
1537 }| {
1538 let (validator_stake_account, _) = find_stake_program_address(
1539 program_id,
1540 vote_account_address,
1541 stake_pool,
1542 NonZeroU32::new((*validator_seed_suffix).into()),
1543 );
1544 let (transient_stake_account, _) = find_transient_stake_program_address(
1545 program_id,
1546 vote_account_address,
1547 stake_pool,
1548 (*transient_seed_suffix).into(),
1549 );
1550 [
1551 AccountMeta::new(validator_stake_account, false),
1552 AccountMeta::new(transient_stake_account, false),
1553 ]
1554 },
1555 ));
1556 Ok(Instruction {
1557 program_id: *program_id,
1558 accounts,
1559 data: borsh::to_vec(&StakePoolInstruction::UpdateValidatorListBalance {
1560 start_index: start_index.try_into().unwrap(),
1561 no_merge,
1562 })
1563 .unwrap(),
1564 })
1565}
1566
1567pub fn update_stale_validator_list_balance_chunk(
1573 program_id: &Pubkey,
1574 stake_pool: &Pubkey,
1575 stake_pool_withdraw_authority: &Pubkey,
1576 validator_list_address: &Pubkey,
1577 reserve_stake: &Pubkey,
1578 validator_list: &ValidatorList,
1579 len: usize,
1580 start_index: usize,
1581 no_merge: bool,
1582 current_epoch: Epoch,
1583) -> Result<Option<Instruction>, ProgramError> {
1584 let validator_list_subslice = validator_list
1585 .validators
1586 .get(start_index..start_index.saturating_add(len))
1587 .ok_or(ProgramError::InvalidInstructionData)?;
1588 if validator_list_subslice.iter().all(|info| {
1589 let last_update_epoch: u64 = info.last_update_epoch.into();
1590 last_update_epoch >= current_epoch
1591 }) {
1592 return Ok(None);
1593 }
1594 update_validator_list_balance_chunk(
1595 program_id,
1596 stake_pool,
1597 stake_pool_withdraw_authority,
1598 validator_list_address,
1599 reserve_stake,
1600 validator_list,
1601 len,
1602 start_index,
1603 no_merge,
1604 )
1605 .map(Some)
1606}
1607
1608pub fn update_stake_pool_balance(
1611 program_id: &Pubkey,
1612 stake_pool: &Pubkey,
1613 withdraw_authority: &Pubkey,
1614 validator_list_storage: &Pubkey,
1615 reserve_stake: &Pubkey,
1616 manager_fee_account: &Pubkey,
1617 stake_pool_mint: &Pubkey,
1618 token_program_id: &Pubkey,
1619) -> Instruction {
1620 let accounts = vec![
1621 AccountMeta::new(*stake_pool, false),
1622 AccountMeta::new_readonly(*withdraw_authority, false),
1623 AccountMeta::new(*validator_list_storage, false),
1624 AccountMeta::new_readonly(*reserve_stake, false),
1625 AccountMeta::new(*manager_fee_account, false),
1626 AccountMeta::new(*stake_pool_mint, false),
1627 AccountMeta::new_readonly(*token_program_id, false),
1628 ];
1629 Instruction {
1630 program_id: *program_id,
1631 accounts,
1632 data: borsh::to_vec(&StakePoolInstruction::UpdateStakePoolBalance).unwrap(),
1633 }
1634}
1635
1636pub fn cleanup_removed_validator_entries(
1639 program_id: &Pubkey,
1640 stake_pool: &Pubkey,
1641 validator_list_storage: &Pubkey,
1642) -> Instruction {
1643 let accounts = vec![
1644 AccountMeta::new(*stake_pool, false),
1645 AccountMeta::new(*validator_list_storage, false),
1646 ];
1647 Instruction {
1648 program_id: *program_id,
1649 accounts,
1650 data: borsh::to_vec(&StakePoolInstruction::CleanupRemovedValidatorEntries).unwrap(),
1651 }
1652}
1653
1654pub fn update_stake_pool(
1657 program_id: &Pubkey,
1658 stake_pool: &StakePool,
1659 validator_list: &ValidatorList,
1660 stake_pool_address: &Pubkey,
1661 no_merge: bool,
1662) -> (Vec<Instruction>, Vec<Instruction>) {
1663 let (withdraw_authority, _) =
1664 find_withdraw_authority_program_address(program_id, stake_pool_address);
1665
1666 let update_list_instructions = validator_list
1667 .validators
1668 .chunks(MAX_VALIDATORS_TO_UPDATE)
1669 .enumerate()
1670 .map(|(i, chunk)| {
1671 update_validator_list_balance_chunk(
1673 program_id,
1674 stake_pool_address,
1675 &withdraw_authority,
1676 &stake_pool.validator_list,
1677 &stake_pool.reserve_stake,
1678 validator_list,
1679 chunk.len(),
1680 i.saturating_mul(MAX_VALIDATORS_TO_UPDATE),
1681 no_merge,
1682 )
1683 .unwrap()
1684 })
1685 .collect();
1686
1687 let final_instructions = vec![
1688 update_stake_pool_balance(
1689 program_id,
1690 stake_pool_address,
1691 &withdraw_authority,
1692 &stake_pool.validator_list,
1693 &stake_pool.reserve_stake,
1694 &stake_pool.manager_fee_account,
1695 &stake_pool.pool_mint,
1696 &stake_pool.token_program_id,
1697 ),
1698 cleanup_removed_validator_entries(
1699 program_id,
1700 stake_pool_address,
1701 &stake_pool.validator_list,
1702 ),
1703 ];
1704 (update_list_instructions, final_instructions)
1705}
1706
1707pub fn update_stale_stake_pool(
1714 program_id: &Pubkey,
1715 stake_pool: &StakePool,
1716 validator_list: &ValidatorList,
1717 stake_pool_address: &Pubkey,
1718 no_merge: bool,
1719 current_epoch: Epoch,
1720) -> (Vec<Instruction>, Vec<Instruction>) {
1721 let (withdraw_authority, _) =
1722 find_withdraw_authority_program_address(program_id, stake_pool_address);
1723
1724 let update_list_instructions = validator_list
1725 .validators
1726 .chunks(MAX_VALIDATORS_TO_UPDATE)
1727 .enumerate()
1728 .filter_map(|(i, chunk)| {
1729 update_stale_validator_list_balance_chunk(
1731 program_id,
1732 stake_pool_address,
1733 &withdraw_authority,
1734 &stake_pool.validator_list,
1735 &stake_pool.reserve_stake,
1736 validator_list,
1737 chunk.len(),
1738 i.saturating_mul(MAX_VALIDATORS_TO_UPDATE),
1739 no_merge,
1740 current_epoch,
1741 )
1742 .unwrap()
1743 })
1744 .collect();
1745
1746 let final_instructions = vec![
1747 update_stake_pool_balance(
1748 program_id,
1749 stake_pool_address,
1750 &withdraw_authority,
1751 &stake_pool.validator_list,
1752 &stake_pool.reserve_stake,
1753 &stake_pool.manager_fee_account,
1754 &stake_pool.pool_mint,
1755 &stake_pool.token_program_id,
1756 ),
1757 cleanup_removed_validator_entries(
1758 program_id,
1759 stake_pool_address,
1760 &stake_pool.validator_list,
1761 ),
1762 ];
1763 (update_list_instructions, final_instructions)
1764}
1765
1766fn deposit_stake_internal(
1767 program_id: &Pubkey,
1768 stake_pool: &Pubkey,
1769 validator_list_storage: &Pubkey,
1770 stake_pool_deposit_authority: Option<&Pubkey>,
1771 stake_pool_withdraw_authority: &Pubkey,
1772 deposit_stake_address: &Pubkey,
1773 deposit_stake_withdraw_authority: &Pubkey,
1774 validator_stake_account: &Pubkey,
1775 reserve_stake_account: &Pubkey,
1776 pool_tokens_to: &Pubkey,
1777 manager_fee_account: &Pubkey,
1778 referrer_pool_tokens_account: &Pubkey,
1779 pool_mint: &Pubkey,
1780 token_program_id: &Pubkey,
1781 minimum_pool_tokens_out: Option<u64>,
1782) -> Vec<Instruction> {
1783 let mut instructions = vec![];
1784 let mut accounts = vec![
1785 AccountMeta::new(*stake_pool, false),
1786 AccountMeta::new(*validator_list_storage, false),
1787 ];
1788 if let Some(stake_pool_deposit_authority) = stake_pool_deposit_authority {
1789 accounts.push(AccountMeta::new_readonly(
1790 *stake_pool_deposit_authority,
1791 true,
1792 ));
1793 instructions.extend_from_slice(&[
1794 solana_stake_interface::instruction::authorize(
1795 deposit_stake_address,
1796 deposit_stake_withdraw_authority,
1797 stake_pool_deposit_authority,
1798 solana_stake_interface::state::StakeAuthorize::Staker,
1799 None,
1800 ),
1801 solana_stake_interface::instruction::authorize(
1802 deposit_stake_address,
1803 deposit_stake_withdraw_authority,
1804 stake_pool_deposit_authority,
1805 solana_stake_interface::state::StakeAuthorize::Withdrawer,
1806 None,
1807 ),
1808 ]);
1809 } else {
1810 let stake_pool_deposit_authority =
1811 find_deposit_authority_program_address(program_id, stake_pool).0;
1812 accounts.push(AccountMeta::new_readonly(
1813 stake_pool_deposit_authority,
1814 false,
1815 ));
1816 instructions.extend_from_slice(&[
1817 solana_stake_interface::instruction::authorize(
1818 deposit_stake_address,
1819 deposit_stake_withdraw_authority,
1820 &stake_pool_deposit_authority,
1821 solana_stake_interface::state::StakeAuthorize::Staker,
1822 None,
1823 ),
1824 solana_stake_interface::instruction::authorize(
1825 deposit_stake_address,
1826 deposit_stake_withdraw_authority,
1827 &stake_pool_deposit_authority,
1828 solana_stake_interface::state::StakeAuthorize::Withdrawer,
1829 None,
1830 ),
1831 ]);
1832 };
1833
1834 accounts.extend_from_slice(&[
1835 AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
1836 AccountMeta::new(*deposit_stake_address, false),
1837 AccountMeta::new(*validator_stake_account, false),
1838 AccountMeta::new(*reserve_stake_account, false),
1839 AccountMeta::new(*pool_tokens_to, false),
1840 AccountMeta::new(*manager_fee_account, false),
1841 AccountMeta::new(*referrer_pool_tokens_account, false),
1842 AccountMeta::new(*pool_mint, false),
1843 AccountMeta::new_readonly(solana_sdk_ids::sysvar::clock::id(), false),
1844 AccountMeta::new_readonly(solana_sdk_ids::sysvar::stake_history::id(), false),
1845 AccountMeta::new_readonly(*token_program_id, false),
1846 AccountMeta::new_readonly(solana_stake_interface::program::id(), false),
1847 ]);
1848 instructions.push(
1849 if let Some(minimum_pool_tokens_out) = minimum_pool_tokens_out {
1850 Instruction {
1851 program_id: *program_id,
1852 accounts,
1853 data: borsh::to_vec(&StakePoolInstruction::DepositStakeWithSlippage {
1854 minimum_pool_tokens_out,
1855 })
1856 .unwrap(),
1857 }
1858 } else {
1859 Instruction {
1860 program_id: *program_id,
1861 accounts,
1862 data: borsh::to_vec(&StakePoolInstruction::DepositStake).unwrap(),
1863 }
1864 },
1865 );
1866 instructions
1867}
1868
1869pub fn deposit_stake(
1872 program_id: &Pubkey,
1873 stake_pool: &Pubkey,
1874 validator_list_storage: &Pubkey,
1875 stake_pool_withdraw_authority: &Pubkey,
1876 deposit_stake_address: &Pubkey,
1877 deposit_stake_withdraw_authority: &Pubkey,
1878 validator_stake_account: &Pubkey,
1879 reserve_stake_account: &Pubkey,
1880 pool_tokens_to: &Pubkey,
1881 manager_fee_account: &Pubkey,
1882 referrer_pool_tokens_account: &Pubkey,
1883 pool_mint: &Pubkey,
1884 token_program_id: &Pubkey,
1885) -> Vec<Instruction> {
1886 deposit_stake_internal(
1887 program_id,
1888 stake_pool,
1889 validator_list_storage,
1890 None,
1891 stake_pool_withdraw_authority,
1892 deposit_stake_address,
1893 deposit_stake_withdraw_authority,
1894 validator_stake_account,
1895 reserve_stake_account,
1896 pool_tokens_to,
1897 manager_fee_account,
1898 referrer_pool_tokens_account,
1899 pool_mint,
1900 token_program_id,
1901 None,
1902 )
1903}
1904
1905pub fn deposit_stake_with_slippage(
1907 program_id: &Pubkey,
1908 stake_pool: &Pubkey,
1909 validator_list_storage: &Pubkey,
1910 stake_pool_withdraw_authority: &Pubkey,
1911 deposit_stake_address: &Pubkey,
1912 deposit_stake_withdraw_authority: &Pubkey,
1913 validator_stake_account: &Pubkey,
1914 reserve_stake_account: &Pubkey,
1915 pool_tokens_to: &Pubkey,
1916 manager_fee_account: &Pubkey,
1917 referrer_pool_tokens_account: &Pubkey,
1918 pool_mint: &Pubkey,
1919 token_program_id: &Pubkey,
1920 minimum_pool_tokens_out: u64,
1921) -> Vec<Instruction> {
1922 deposit_stake_internal(
1923 program_id,
1924 stake_pool,
1925 validator_list_storage,
1926 None,
1927 stake_pool_withdraw_authority,
1928 deposit_stake_address,
1929 deposit_stake_withdraw_authority,
1930 validator_stake_account,
1931 reserve_stake_account,
1932 pool_tokens_to,
1933 manager_fee_account,
1934 referrer_pool_tokens_account,
1935 pool_mint,
1936 token_program_id,
1937 Some(minimum_pool_tokens_out),
1938 )
1939}
1940
1941pub fn deposit_stake_with_authority(
1945 program_id: &Pubkey,
1946 stake_pool: &Pubkey,
1947 validator_list_storage: &Pubkey,
1948 stake_pool_deposit_authority: &Pubkey,
1949 stake_pool_withdraw_authority: &Pubkey,
1950 deposit_stake_address: &Pubkey,
1951 deposit_stake_withdraw_authority: &Pubkey,
1952 validator_stake_account: &Pubkey,
1953 reserve_stake_account: &Pubkey,
1954 pool_tokens_to: &Pubkey,
1955 manager_fee_account: &Pubkey,
1956 referrer_pool_tokens_account: &Pubkey,
1957 pool_mint: &Pubkey,
1958 token_program_id: &Pubkey,
1959) -> Vec<Instruction> {
1960 deposit_stake_internal(
1961 program_id,
1962 stake_pool,
1963 validator_list_storage,
1964 Some(stake_pool_deposit_authority),
1965 stake_pool_withdraw_authority,
1966 deposit_stake_address,
1967 deposit_stake_withdraw_authority,
1968 validator_stake_account,
1969 reserve_stake_account,
1970 pool_tokens_to,
1971 manager_fee_account,
1972 referrer_pool_tokens_account,
1973 pool_mint,
1974 token_program_id,
1975 None,
1976 )
1977}
1978
1979pub fn deposit_stake_with_authority_and_slippage(
1984 program_id: &Pubkey,
1985 stake_pool: &Pubkey,
1986 validator_list_storage: &Pubkey,
1987 stake_pool_deposit_authority: &Pubkey,
1988 stake_pool_withdraw_authority: &Pubkey,
1989 deposit_stake_address: &Pubkey,
1990 deposit_stake_withdraw_authority: &Pubkey,
1991 validator_stake_account: &Pubkey,
1992 reserve_stake_account: &Pubkey,
1993 pool_tokens_to: &Pubkey,
1994 manager_fee_account: &Pubkey,
1995 referrer_pool_tokens_account: &Pubkey,
1996 pool_mint: &Pubkey,
1997 token_program_id: &Pubkey,
1998 minimum_pool_tokens_out: u64,
1999) -> Vec<Instruction> {
2000 deposit_stake_internal(
2001 program_id,
2002 stake_pool,
2003 validator_list_storage,
2004 Some(stake_pool_deposit_authority),
2005 stake_pool_withdraw_authority,
2006 deposit_stake_address,
2007 deposit_stake_withdraw_authority,
2008 validator_stake_account,
2009 reserve_stake_account,
2010 pool_tokens_to,
2011 manager_fee_account,
2012 referrer_pool_tokens_account,
2013 pool_mint,
2014 token_program_id,
2015 Some(minimum_pool_tokens_out),
2016 )
2017}
2018
2019fn deposit_sol_internal(
2021 program_id: &Pubkey,
2022 stake_pool: &Pubkey,
2023 stake_pool_withdraw_authority: &Pubkey,
2024 reserve_stake_account: &Pubkey,
2025 lamports_from: &Pubkey,
2026 pool_tokens_to: &Pubkey,
2027 manager_fee_account: &Pubkey,
2028 referrer_pool_tokens_account: &Pubkey,
2029 pool_mint: &Pubkey,
2030 token_program_id: &Pubkey,
2031 sol_deposit_authority: Option<&Pubkey>,
2032 lamports_in: u64,
2033 minimum_pool_tokens_out: Option<u64>,
2034) -> Instruction {
2035 let mut accounts = vec![
2036 AccountMeta::new(*stake_pool, false),
2037 AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
2038 AccountMeta::new(*reserve_stake_account, false),
2039 AccountMeta::new(*lamports_from, true),
2040 AccountMeta::new(*pool_tokens_to, false),
2041 AccountMeta::new(*manager_fee_account, false),
2042 AccountMeta::new(*referrer_pool_tokens_account, false),
2043 AccountMeta::new(*pool_mint, false),
2044 AccountMeta::new_readonly(solana_system_interface::program::id(), false),
2045 AccountMeta::new_readonly(*token_program_id, false),
2046 ];
2047 if let Some(sol_deposit_authority) = sol_deposit_authority {
2048 accounts.push(AccountMeta::new_readonly(*sol_deposit_authority, true));
2049 }
2050 if let Some(minimum_pool_tokens_out) = minimum_pool_tokens_out {
2051 Instruction {
2052 program_id: *program_id,
2053 accounts,
2054 data: borsh::to_vec(&StakePoolInstruction::DepositSolWithSlippage {
2055 lamports_in,
2056 minimum_pool_tokens_out,
2057 })
2058 .unwrap(),
2059 }
2060 } else {
2061 Instruction {
2062 program_id: *program_id,
2063 accounts,
2064 data: borsh::to_vec(&StakePoolInstruction::DepositSol(lamports_in)).unwrap(),
2065 }
2066 }
2067}
2068
2069pub fn deposit_sol(
2071 program_id: &Pubkey,
2072 stake_pool: &Pubkey,
2073 stake_pool_withdraw_authority: &Pubkey,
2074 reserve_stake_account: &Pubkey,
2075 lamports_from: &Pubkey,
2076 pool_tokens_to: &Pubkey,
2077 manager_fee_account: &Pubkey,
2078 referrer_pool_tokens_account: &Pubkey,
2079 pool_mint: &Pubkey,
2080 token_program_id: &Pubkey,
2081 lamports_in: u64,
2082) -> Instruction {
2083 deposit_sol_internal(
2084 program_id,
2085 stake_pool,
2086 stake_pool_withdraw_authority,
2087 reserve_stake_account,
2088 lamports_from,
2089 pool_tokens_to,
2090 manager_fee_account,
2091 referrer_pool_tokens_account,
2092 pool_mint,
2093 token_program_id,
2094 None,
2095 lamports_in,
2096 None,
2097 )
2098}
2099
2100pub fn deposit_sol_with_slippage(
2103 program_id: &Pubkey,
2104 stake_pool: &Pubkey,
2105 stake_pool_withdraw_authority: &Pubkey,
2106 reserve_stake_account: &Pubkey,
2107 lamports_from: &Pubkey,
2108 pool_tokens_to: &Pubkey,
2109 manager_fee_account: &Pubkey,
2110 referrer_pool_tokens_account: &Pubkey,
2111 pool_mint: &Pubkey,
2112 token_program_id: &Pubkey,
2113 lamports_in: u64,
2114 minimum_pool_tokens_out: u64,
2115) -> Instruction {
2116 deposit_sol_internal(
2117 program_id,
2118 stake_pool,
2119 stake_pool_withdraw_authority,
2120 reserve_stake_account,
2121 lamports_from,
2122 pool_tokens_to,
2123 manager_fee_account,
2124 referrer_pool_tokens_account,
2125 pool_mint,
2126 token_program_id,
2127 None,
2128 lamports_in,
2129 Some(minimum_pool_tokens_out),
2130 )
2131}
2132
2133pub fn deposit_sol_with_authority(
2137 program_id: &Pubkey,
2138 stake_pool: &Pubkey,
2139 sol_deposit_authority: &Pubkey,
2140 stake_pool_withdraw_authority: &Pubkey,
2141 reserve_stake_account: &Pubkey,
2142 lamports_from: &Pubkey,
2143 pool_tokens_to: &Pubkey,
2144 manager_fee_account: &Pubkey,
2145 referrer_pool_tokens_account: &Pubkey,
2146 pool_mint: &Pubkey,
2147 token_program_id: &Pubkey,
2148 lamports_in: u64,
2149) -> Instruction {
2150 deposit_sol_internal(
2151 program_id,
2152 stake_pool,
2153 stake_pool_withdraw_authority,
2154 reserve_stake_account,
2155 lamports_from,
2156 pool_tokens_to,
2157 manager_fee_account,
2158 referrer_pool_tokens_account,
2159 pool_mint,
2160 token_program_id,
2161 Some(sol_deposit_authority),
2162 lamports_in,
2163 None,
2164 )
2165}
2166
2167pub fn deposit_sol_with_authority_and_slippage(
2170 program_id: &Pubkey,
2171 stake_pool: &Pubkey,
2172 sol_deposit_authority: &Pubkey,
2173 stake_pool_withdraw_authority: &Pubkey,
2174 reserve_stake_account: &Pubkey,
2175 lamports_from: &Pubkey,
2176 pool_tokens_to: &Pubkey,
2177 manager_fee_account: &Pubkey,
2178 referrer_pool_tokens_account: &Pubkey,
2179 pool_mint: &Pubkey,
2180 token_program_id: &Pubkey,
2181 lamports_in: u64,
2182 minimum_pool_tokens_out: u64,
2183) -> Instruction {
2184 deposit_sol_internal(
2185 program_id,
2186 stake_pool,
2187 stake_pool_withdraw_authority,
2188 reserve_stake_account,
2189 lamports_from,
2190 pool_tokens_to,
2191 manager_fee_account,
2192 referrer_pool_tokens_account,
2193 pool_mint,
2194 token_program_id,
2195 Some(sol_deposit_authority),
2196 lamports_in,
2197 Some(minimum_pool_tokens_out),
2198 )
2199}
2200
2201fn withdraw_stake_internal(
2202 program_id: &Pubkey,
2203 stake_pool: &Pubkey,
2204 validator_list_storage: &Pubkey,
2205 stake_pool_withdraw: &Pubkey,
2206 stake_to_split: &Pubkey,
2207 stake_to_receive: &Pubkey,
2208 user_stake_authority: &Pubkey,
2209 user_transfer_authority: &Pubkey,
2210 user_pool_token_account: &Pubkey,
2211 manager_fee_account: &Pubkey,
2212 pool_mint: &Pubkey,
2213 token_program_id: &Pubkey,
2214 pool_tokens_in: u64,
2215 minimum_lamports_out: Option<u64>,
2216) -> Instruction {
2217 let accounts = vec![
2218 AccountMeta::new(*stake_pool, false),
2219 AccountMeta::new(*validator_list_storage, false),
2220 AccountMeta::new_readonly(*stake_pool_withdraw, false),
2221 AccountMeta::new(*stake_to_split, false),
2222 AccountMeta::new(*stake_to_receive, false),
2223 AccountMeta::new_readonly(*user_stake_authority, false),
2224 AccountMeta::new_readonly(*user_transfer_authority, true),
2225 AccountMeta::new(*user_pool_token_account, false),
2226 AccountMeta::new(*manager_fee_account, false),
2227 AccountMeta::new(*pool_mint, false),
2228 AccountMeta::new_readonly(solana_sdk_ids::sysvar::clock::id(), false),
2229 AccountMeta::new_readonly(*token_program_id, false),
2230 AccountMeta::new_readonly(solana_stake_interface::program::id(), false),
2231 ];
2232 if let Some(minimum_lamports_out) = minimum_lamports_out {
2233 Instruction {
2234 program_id: *program_id,
2235 accounts,
2236 data: borsh::to_vec(&StakePoolInstruction::WithdrawStakeWithSlippage {
2237 pool_tokens_in,
2238 minimum_lamports_out,
2239 })
2240 .unwrap(),
2241 }
2242 } else {
2243 Instruction {
2244 program_id: *program_id,
2245 accounts,
2246 data: borsh::to_vec(&StakePoolInstruction::WithdrawStake(pool_tokens_in)).unwrap(),
2247 }
2248 }
2249}
2250
2251pub fn withdraw_stake(
2253 program_id: &Pubkey,
2254 stake_pool: &Pubkey,
2255 validator_list_storage: &Pubkey,
2256 stake_pool_withdraw: &Pubkey,
2257 stake_to_split: &Pubkey,
2258 stake_to_receive: &Pubkey,
2259 user_stake_authority: &Pubkey,
2260 user_transfer_authority: &Pubkey,
2261 user_pool_token_account: &Pubkey,
2262 manager_fee_account: &Pubkey,
2263 pool_mint: &Pubkey,
2264 token_program_id: &Pubkey,
2265 pool_tokens_in: u64,
2266) -> Instruction {
2267 withdraw_stake_internal(
2268 program_id,
2269 stake_pool,
2270 validator_list_storage,
2271 stake_pool_withdraw,
2272 stake_to_split,
2273 stake_to_receive,
2274 user_stake_authority,
2275 user_transfer_authority,
2276 user_pool_token_account,
2277 manager_fee_account,
2278 pool_mint,
2279 token_program_id,
2280 pool_tokens_in,
2281 None,
2282 )
2283}
2284
2285pub fn withdraw_stake_with_slippage(
2287 program_id: &Pubkey,
2288 stake_pool: &Pubkey,
2289 validator_list_storage: &Pubkey,
2290 stake_pool_withdraw: &Pubkey,
2291 stake_to_split: &Pubkey,
2292 stake_to_receive: &Pubkey,
2293 user_stake_authority: &Pubkey,
2294 user_transfer_authority: &Pubkey,
2295 user_pool_token_account: &Pubkey,
2296 manager_fee_account: &Pubkey,
2297 pool_mint: &Pubkey,
2298 token_program_id: &Pubkey,
2299 pool_tokens_in: u64,
2300 minimum_lamports_out: u64,
2301) -> Instruction {
2302 withdraw_stake_internal(
2303 program_id,
2304 stake_pool,
2305 validator_list_storage,
2306 stake_pool_withdraw,
2307 stake_to_split,
2308 stake_to_receive,
2309 user_stake_authority,
2310 user_transfer_authority,
2311 user_pool_token_account,
2312 manager_fee_account,
2313 pool_mint,
2314 token_program_id,
2315 pool_tokens_in,
2316 Some(minimum_lamports_out),
2317 )
2318}
2319
2320fn withdraw_sol_internal(
2321 program_id: &Pubkey,
2322 stake_pool: &Pubkey,
2323 stake_pool_withdraw_authority: &Pubkey,
2324 user_transfer_authority: &Pubkey,
2325 pool_tokens_from: &Pubkey,
2326 reserve_stake_account: &Pubkey,
2327 lamports_to: &Pubkey,
2328 manager_fee_account: &Pubkey,
2329 pool_mint: &Pubkey,
2330 token_program_id: &Pubkey,
2331 sol_withdraw_authority: Option<&Pubkey>,
2332 pool_tokens_in: u64,
2333 minimum_lamports_out: Option<u64>,
2334) -> Instruction {
2335 let mut accounts = vec![
2336 AccountMeta::new(*stake_pool, false),
2337 AccountMeta::new_readonly(*stake_pool_withdraw_authority, false),
2338 AccountMeta::new_readonly(*user_transfer_authority, true),
2339 AccountMeta::new(*pool_tokens_from, false),
2340 AccountMeta::new(*reserve_stake_account, false),
2341 AccountMeta::new(*lamports_to, false),
2342 AccountMeta::new(*manager_fee_account, false),
2343 AccountMeta::new(*pool_mint, false),
2344 AccountMeta::new_readonly(solana_sdk_ids::sysvar::clock::id(), false),
2345 AccountMeta::new_readonly(solana_sdk_ids::sysvar::stake_history::id(), false),
2346 AccountMeta::new_readonly(solana_stake_interface::program::id(), false),
2347 AccountMeta::new_readonly(*token_program_id, false),
2348 ];
2349 if let Some(sol_withdraw_authority) = sol_withdraw_authority {
2350 accounts.push(AccountMeta::new_readonly(*sol_withdraw_authority, true));
2351 }
2352 if let Some(minimum_lamports_out) = minimum_lamports_out {
2353 Instruction {
2354 program_id: *program_id,
2355 accounts,
2356 data: borsh::to_vec(&StakePoolInstruction::WithdrawSolWithSlippage {
2357 pool_tokens_in,
2358 minimum_lamports_out,
2359 })
2360 .unwrap(),
2361 }
2362 } else {
2363 Instruction {
2364 program_id: *program_id,
2365 accounts,
2366 data: borsh::to_vec(&StakePoolInstruction::WithdrawSol(pool_tokens_in)).unwrap(),
2367 }
2368 }
2369}
2370
2371pub fn withdraw_sol(
2373 program_id: &Pubkey,
2374 stake_pool: &Pubkey,
2375 stake_pool_withdraw_authority: &Pubkey,
2376 user_transfer_authority: &Pubkey,
2377 pool_tokens_from: &Pubkey,
2378 reserve_stake_account: &Pubkey,
2379 lamports_to: &Pubkey,
2380 manager_fee_account: &Pubkey,
2381 pool_mint: &Pubkey,
2382 token_program_id: &Pubkey,
2383 pool_tokens_in: u64,
2384) -> Instruction {
2385 withdraw_sol_internal(
2386 program_id,
2387 stake_pool,
2388 stake_pool_withdraw_authority,
2389 user_transfer_authority,
2390 pool_tokens_from,
2391 reserve_stake_account,
2392 lamports_to,
2393 manager_fee_account,
2394 pool_mint,
2395 token_program_id,
2396 None,
2397 pool_tokens_in,
2398 None,
2399 )
2400}
2401
2402pub fn withdraw_sol_with_slippage(
2405 program_id: &Pubkey,
2406 stake_pool: &Pubkey,
2407 stake_pool_withdraw_authority: &Pubkey,
2408 user_transfer_authority: &Pubkey,
2409 pool_tokens_from: &Pubkey,
2410 reserve_stake_account: &Pubkey,
2411 lamports_to: &Pubkey,
2412 manager_fee_account: &Pubkey,
2413 pool_mint: &Pubkey,
2414 token_program_id: &Pubkey,
2415 pool_tokens_in: u64,
2416 minimum_lamports_out: u64,
2417) -> Instruction {
2418 withdraw_sol_internal(
2419 program_id,
2420 stake_pool,
2421 stake_pool_withdraw_authority,
2422 user_transfer_authority,
2423 pool_tokens_from,
2424 reserve_stake_account,
2425 lamports_to,
2426 manager_fee_account,
2427 pool_mint,
2428 token_program_id,
2429 None,
2430 pool_tokens_in,
2431 Some(minimum_lamports_out),
2432 )
2433}
2434
2435pub fn withdraw_sol_with_authority(
2439 program_id: &Pubkey,
2440 stake_pool: &Pubkey,
2441 sol_withdraw_authority: &Pubkey,
2442 stake_pool_withdraw_authority: &Pubkey,
2443 user_transfer_authority: &Pubkey,
2444 pool_tokens_from: &Pubkey,
2445 reserve_stake_account: &Pubkey,
2446 lamports_to: &Pubkey,
2447 manager_fee_account: &Pubkey,
2448 pool_mint: &Pubkey,
2449 token_program_id: &Pubkey,
2450 pool_tokens_in: u64,
2451) -> Instruction {
2452 withdraw_sol_internal(
2453 program_id,
2454 stake_pool,
2455 stake_pool_withdraw_authority,
2456 user_transfer_authority,
2457 pool_tokens_from,
2458 reserve_stake_account,
2459 lamports_to,
2460 manager_fee_account,
2461 pool_mint,
2462 token_program_id,
2463 Some(sol_withdraw_authority),
2464 pool_tokens_in,
2465 None,
2466 )
2467}
2468
2469pub fn withdraw_sol_with_authority_and_slippage(
2474 program_id: &Pubkey,
2475 stake_pool: &Pubkey,
2476 sol_withdraw_authority: &Pubkey,
2477 stake_pool_withdraw_authority: &Pubkey,
2478 user_transfer_authority: &Pubkey,
2479 pool_tokens_from: &Pubkey,
2480 reserve_stake_account: &Pubkey,
2481 lamports_to: &Pubkey,
2482 manager_fee_account: &Pubkey,
2483 pool_mint: &Pubkey,
2484 token_program_id: &Pubkey,
2485 pool_tokens_in: u64,
2486 minimum_lamports_out: u64,
2487) -> Instruction {
2488 withdraw_sol_internal(
2489 program_id,
2490 stake_pool,
2491 stake_pool_withdraw_authority,
2492 user_transfer_authority,
2493 pool_tokens_from,
2494 reserve_stake_account,
2495 lamports_to,
2496 manager_fee_account,
2497 pool_mint,
2498 token_program_id,
2499 Some(sol_withdraw_authority),
2500 pool_tokens_in,
2501 Some(minimum_lamports_out),
2502 )
2503}
2504
2505pub fn set_manager(
2507 program_id: &Pubkey,
2508 stake_pool: &Pubkey,
2509 manager: &Pubkey,
2510 new_manager: &Pubkey,
2511 new_fee_receiver: &Pubkey,
2512) -> Instruction {
2513 let accounts = vec![
2514 AccountMeta::new(*stake_pool, false),
2515 AccountMeta::new_readonly(*manager, true),
2516 AccountMeta::new_readonly(*new_manager, true),
2517 AccountMeta::new_readonly(*new_fee_receiver, false),
2518 ];
2519 Instruction {
2520 program_id: *program_id,
2521 accounts,
2522 data: borsh::to_vec(&StakePoolInstruction::SetManager).unwrap(),
2523 }
2524}
2525
2526pub fn set_fee(
2528 program_id: &Pubkey,
2529 stake_pool: &Pubkey,
2530 manager: &Pubkey,
2531 fee: FeeType,
2532) -> Instruction {
2533 let accounts = vec![
2534 AccountMeta::new(*stake_pool, false),
2535 AccountMeta::new_readonly(*manager, true),
2536 ];
2537 Instruction {
2538 program_id: *program_id,
2539 accounts,
2540 data: borsh::to_vec(&StakePoolInstruction::SetFee { fee }).unwrap(),
2541 }
2542}
2543
2544pub fn set_staker(
2546 program_id: &Pubkey,
2547 stake_pool: &Pubkey,
2548 set_staker_authority: &Pubkey,
2549 new_staker: &Pubkey,
2550) -> Instruction {
2551 let accounts = vec![
2552 AccountMeta::new(*stake_pool, false),
2553 AccountMeta::new_readonly(*set_staker_authority, true),
2554 AccountMeta::new_readonly(*new_staker, false),
2555 ];
2556 Instruction {
2557 program_id: *program_id,
2558 accounts,
2559 data: borsh::to_vec(&StakePoolInstruction::SetStaker).unwrap(),
2560 }
2561}
2562
2563pub fn set_funding_authority(
2565 program_id: &Pubkey,
2566 stake_pool: &Pubkey,
2567 manager: &Pubkey,
2568 new_sol_deposit_authority: Option<&Pubkey>,
2569 funding_type: FundingType,
2570) -> Instruction {
2571 let mut accounts = vec![
2572 AccountMeta::new(*stake_pool, false),
2573 AccountMeta::new_readonly(*manager, true),
2574 ];
2575 if let Some(auth) = new_sol_deposit_authority {
2576 accounts.push(AccountMeta::new_readonly(*auth, false))
2577 }
2578 Instruction {
2579 program_id: *program_id,
2580 accounts,
2581 data: borsh::to_vec(&StakePoolInstruction::SetFundingAuthority(funding_type)).unwrap(),
2582 }
2583}
2584
2585pub fn update_token_metadata(
2588 program_id: &Pubkey,
2589 stake_pool: &Pubkey,
2590 manager: &Pubkey,
2591 pool_mint: &Pubkey,
2592 name: String,
2593 symbol: String,
2594 uri: String,
2595) -> Instruction {
2596 let (stake_pool_withdraw_authority, _) =
2597 find_withdraw_authority_program_address(program_id, stake_pool);
2598 let (token_metadata, _) = find_metadata_account(pool_mint);
2599
2600 let accounts = vec![
2601 AccountMeta::new_readonly(*stake_pool, false),
2602 AccountMeta::new_readonly(*manager, true),
2603 AccountMeta::new_readonly(stake_pool_withdraw_authority, false),
2604 AccountMeta::new(token_metadata, false),
2605 AccountMeta::new_readonly(inline_mpl_token_metadata::id(), false),
2606 ];
2607
2608 Instruction {
2609 program_id: *program_id,
2610 accounts,
2611 data: borsh::to_vec(&StakePoolInstruction::UpdateTokenMetadata { name, symbol, uri })
2612 .unwrap(),
2613 }
2614}
2615
2616pub fn create_token_metadata(
2619 program_id: &Pubkey,
2620 stake_pool: &Pubkey,
2621 manager: &Pubkey,
2622 pool_mint: &Pubkey,
2623 payer: &Pubkey,
2624 name: String,
2625 symbol: String,
2626 uri: String,
2627) -> Instruction {
2628 let (stake_pool_withdraw_authority, _) =
2629 find_withdraw_authority_program_address(program_id, stake_pool);
2630 let (token_metadata, _) = find_metadata_account(pool_mint);
2631
2632 let accounts = vec![
2633 AccountMeta::new_readonly(*stake_pool, false),
2634 AccountMeta::new_readonly(*manager, true),
2635 AccountMeta::new_readonly(stake_pool_withdraw_authority, false),
2636 AccountMeta::new_readonly(*pool_mint, false),
2637 AccountMeta::new(*payer, true),
2638 AccountMeta::new(token_metadata, false),
2639 AccountMeta::new_readonly(inline_mpl_token_metadata::id(), false),
2640 AccountMeta::new_readonly(solana_system_interface::program::id(), false),
2641 ];
2642
2643 Instruction {
2644 program_id: *program_id,
2645 accounts,
2646 data: borsh::to_vec(&StakePoolInstruction::CreateTokenMetadata { name, symbol, uri })
2647 .unwrap(),
2648 }
2649}