1#![allow(deprecated)]
5
6#[cfg(feature = "codama")]
7use codama_macros::{CodamaInstructions, CodamaType};
8use {
9 crate::state::{Authorized, Lockup, StakeAuthorize},
10 solana_clock::{Epoch, UnixTimestamp},
11 solana_pubkey::Pubkey,
12};
13#[cfg(feature = "bincode")]
14use {
15 crate::{config, program::ID, state::StakeStateV2},
16 solana_instruction::{AccountMeta, Instruction},
17};
18
19#[cfg(feature = "bincode")]
25const CLOCK_ID: Pubkey = Pubkey::from_str_const("SysvarC1ock11111111111111111111111111111111");
26
27#[cfg(feature = "bincode")]
28const RENT_ID: Pubkey = Pubkey::from_str_const("SysvarRent111111111111111111111111111111111");
29
30#[cfg(feature = "bincode")]
31const STAKE_HISTORY_ID: Pubkey =
32 Pubkey::from_str_const("SysvarStakeHistory1111111111111111111111111");
33
34#[cfg_attr(
39 feature = "serde",
40 derive(serde_derive::Deserialize, serde_derive::Serialize)
41)]
42#[cfg_attr(feature = "codama", derive(CodamaInstructions))]
43#[derive(Debug, PartialEq, Eq, Clone)]
44pub enum StakeInstruction {
45 #[cfg_attr(
55 feature = "codama",
56 codama(account(name = "stake", writable, docs = "Uninitialized stake account")),
57 codama(account(name = "rent_sysvar", docs = "Rent sysvar", default_value = sysvar("rent")))
58 )]
59 Initialize(Authorized, Lockup),
60
61 #[cfg_attr(
70 feature = "codama",
71 codama(account(name = "stake", writable, docs = "Stake account to be updated")),
72 codama(account(name = "clock_sysvar", docs = "Clock sysvar", default_value = sysvar("clock"))),
73 codama(account(name = "authority", signer, docs = "The stake or withdraw authority")),
74 codama(account(
75 name = "lockup_authority",
76 optional,
77 signer,
78 docs = "Lockup authority, if updating `StakeAuthorize::Withdrawer` before lockup expiration"
79 ))
80 )]
81 Authorize(Pubkey, StakeAuthorize),
82
83 #[cfg_attr(
96 feature = "codama",
97 codama(account(
98 name = "stake",
99 writable,
100 docs = "Initialized stake account to be delegated"
101 )),
102 codama(account(
103 name = "vote",
104 docs = "Vote account to which this stake will be delegated"
105 )),
106 codama(account(name = "clock_sysvar", docs = "Clock sysvar", default_value = sysvar("clock"))),
107 codama(account(
108 name = "stake_history",
109 docs = "Stake history sysvar that carries stake warmup/cooldown history",
110 default_value = sysvar("stake_history")
111 )),
112 codama(account(name = "unused", docs = "Unused account, formerly the stake config")),
113 codama(account(name = "stake_authority", signer, docs = "Stake authority"))
114 )]
115 DelegateStake,
116
117 #[cfg_attr(
124 feature = "codama",
125 codama(account(
126 name = "stake",
127 writable,
128 docs = "Stake account to be split; must be in the Initialized or Stake state"
129 )),
130 codama(account(
131 name = "split_stake",
132 writable,
133 docs = "Uninitialized stake account that will take the split-off amount"
134 )),
135 codama(account(name = "stake_authority", signer, docs = "Stake authority"))
136 )]
137 Split(#[cfg_attr(feature = "codama", codama(name = "args"))] u64),
140
141 #[cfg_attr(
154 feature = "codama",
155 codama(account(
156 name = "stake",
157 writable,
158 docs = "Stake account from which to withdraw"
159 )),
160 codama(account(name = "recipient", writable, docs = "Recipient account")),
161 codama(account(name = "clock_sysvar", docs = "Clock sysvar", default_value = sysvar("clock"))),
162 codama(account(
163 name = "stake_history",
164 docs = "Stake history sysvar that carries stake warmup/cooldown history",
165 default_value = sysvar("stake_history")
166 )),
167 codama(account(name = "withdraw_authority", signer, docs = "Withdraw authority")),
168 codama(account(
169 name = "lockup_authority",
170 optional,
171 signer,
172 docs = "Lockup authority, if before lockup expiration"
173 ))
174 )]
175 Withdraw(#[cfg_attr(feature = "codama", codama(name = "args"))] u64),
178
179 #[cfg_attr(
186 feature = "codama",
187 codama(account(
188 name = "stake",
189 writable,
190 docs = "Delegated stake account to be deactivated"
191 )),
192 codama(account(name = "clock_sysvar", docs = "Clock sysvar", default_value = sysvar("clock"))),
193 codama(account(name = "stake_authority", signer, docs = "Stake authority"))
194 )]
195 Deactivate,
196
197 #[cfg_attr(
206 feature = "codama",
207 codama(account(name = "stake", writable, docs = "Initialized stake account")),
208 codama(account(
209 name = "authority",
210 signer,
211 docs = "Lockup authority or withdraw authority"
212 ))
213 )]
214 SetLockup(LockupArgs),
215
216 #[cfg_attr(
241 feature = "codama",
242 codama(account(
243 name = "destination_stake",
244 writable,
245 docs = "Destination stake account for the merge"
246 )),
247 codama(account(
248 name = "source_stake",
249 writable,
250 docs = "Source stake account for to merge. This account will be drained"
251 )),
252 codama(account(name = "clock_sysvar", docs = "Clock sysvar", default_value = sysvar("clock"))),
253 codama(account(
254 name = "stake_history",
255 docs = "Stake history sysvar that carries stake warmup/cooldown history",
256 default_value = sysvar("stake_history")
257 )),
258 codama(account(name = "stake_authority", signer, docs = "Stake authority"))
259 )]
260 Merge,
261
262 #[cfg_attr(
271 feature = "codama",
272 codama(account(name = "stake", writable, docs = "Stake account to be updated")),
273 codama(account(
274 name = "base",
275 signer,
276 docs = "Base key of stake or withdraw authority"
277 )),
278 codama(account(name = "clock_sysvar", docs = "Clock sysvar", default_value = sysvar("clock"))),
279 codama(account(
280 name = "lockup_authority",
281 optional,
282 signer,
283 docs = "Lockup authority, if updating `StakeAuthorize::Withdrawer` before lockup expiration"
284 ))
285 )]
286 AuthorizeWithSeed(AuthorizeWithSeedArgs),
287
288 #[cfg_attr(
299 feature = "codama",
300 codama(account(name = "stake", writable, docs = "Uninitialized stake account")),
301 codama(account(name = "rent_sysvar", docs = "Rent sysvar", default_value = sysvar("rent"))),
302 codama(account(name = "stake_authority", docs = "The stake authority")),
303 codama(account(name = "withdraw_authority", signer, docs = "The withdraw authority"))
304 )]
305 InitializeChecked,
306
307 #[cfg_attr(
320 feature = "codama",
321 codama(account(name = "stake", writable, docs = "Stake account to be updated")),
322 codama(account(name = "clock_sysvar", docs = "Clock sysvar", default_value = sysvar("clock"))),
323 codama(account(name = "authority", signer, docs = "The stake or withdraw authority")),
324 codama(account(
325 name = "new_authority",
326 signer,
327 docs = "The new stake or withdraw authority"
328 )),
329 codama(account(
330 name = "lockup_authority",
331 optional,
332 signer,
333 docs = "Lockup authority, if updating `StakeAuthorize::Withdrawer` before lockup expiration"
334 ))
335 )]
336 AuthorizeChecked(
337 #[cfg_attr(feature = "codama", codama(name = "stakeAuthorize"))] StakeAuthorize,
338 ),
339
340 #[cfg_attr(
353 feature = "codama",
354 codama(account(name = "stake", writable, docs = "Stake account to be updated")),
355 codama(account(
356 name = "base",
357 signer,
358 docs = "Base key of stake or withdraw authority"
359 )),
360 codama(account(name = "clock_sysvar", docs = "Clock sysvar", default_value = sysvar("clock"))),
361 codama(account(
362 name = "new_authority",
363 signer,
364 docs = "The new stake or withdraw authority"
365 )),
366 codama(account(
367 name = "lockup_authority",
368 optional,
369 signer,
370 docs = "Lockup authority, if updating `StakeAuthorize::Withdrawer` before lockup expiration"
371 ))
372 )]
373 AuthorizeCheckedWithSeed(AuthorizeCheckedWithSeedArgs),
374
375 #[cfg_attr(
388 feature = "codama",
389 codama(account(name = "stake", writable, docs = "Initialized stake account")),
390 codama(account(
391 name = "authority",
392 signer,
393 docs = "Lockup authority or withdraw authority"
394 )),
395 codama(account(
396 name = "new_authority",
397 optional,
398 signer,
399 docs = "New lockup authority"
400 ))
401 )]
402 SetLockupChecked(LockupCheckedArgs),
403
404 GetMinimumDelegation,
415
416 #[cfg_attr(
428 feature = "codama",
429 codama(account(name = "stake", writable, docs = "Delegated stake account")),
430 codama(account(
431 name = "delinquent_vote",
432 docs = "Delinquent vote account for the delegated stake account"
433 )),
434 codama(account(
435 name = "reference_vote",
436 docs = "Reference vote account that has voted at least once in the last `MINIMUM_DELINQUENT_EPOCHS_FOR_DEACTIVATION` epochs"
437 ))
438 )]
439 DeactivateDelinquent,
440
441 #[deprecated(since = "2.1.0", note = "Redelegate will not be enabled")]
462 Redelegate,
464
465 #[cfg_attr(
485 feature = "codama",
486 codama(account(name = "sourceStake", writable, docs = "Active source stake account")),
487 codama(account(
488 name = "destinationStake",
489 writable,
490 docs = "Active or inactive destination stake account"
491 )),
492 codama(account(name = "stake_authority", signer, docs = "Stake authority"))
493 )]
494 MoveStake(#[cfg_attr(feature = "codama", codama(name = "args"))] u64),
496
497 #[cfg_attr(
511 feature = "codama",
512 codama(account(
513 name = "source_stake",
514 writable,
515 docs = "Active or inactive source stake account"
516 )),
517 codama(account(
518 name = "destination_stake",
519 writable,
520 docs = "Mergeable destination stake account"
521 )),
522 codama(account(name = "stake_authority", signer, docs = "Stake authority"))
523 )]
524 MoveLamports(#[cfg_attr(feature = "codama", codama(name = "args"))] u64),
526}
527
528#[cfg_attr(feature = "codama", derive(CodamaType), codama(name = "lockupParams"))]
529#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
530#[cfg_attr(
531 feature = "serde",
532 derive(serde_derive::Deserialize, serde_derive::Serialize)
533)]
534pub struct LockupArgs {
535 pub unix_timestamp: Option<UnixTimestamp>,
536 pub epoch: Option<Epoch>,
537 pub custodian: Option<Pubkey>,
538}
539
540#[cfg_attr(
541 feature = "codama",
542 derive(CodamaType),
543 codama(name = "lockupCheckedParams")
544)]
545#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
546#[cfg_attr(
547 feature = "serde",
548 derive(serde_derive::Deserialize, serde_derive::Serialize)
549)]
550pub struct LockupCheckedArgs {
551 pub unix_timestamp: Option<UnixTimestamp>,
552 pub epoch: Option<Epoch>,
553}
554
555#[cfg_attr(
556 feature = "codama",
557 derive(CodamaType),
558 codama(name = "authorizeWithSeedParams")
559)]
560#[derive(Debug, PartialEq, Eq, Clone)]
561#[cfg_attr(
562 feature = "serde",
563 derive(serde_derive::Deserialize, serde_derive::Serialize)
564)]
565pub struct AuthorizeWithSeedArgs {
566 pub new_authorized_pubkey: Pubkey,
567 pub stake_authorize: StakeAuthorize,
568 #[cfg_attr(feature = "codama", codama(size_prefix = number(u64)))]
569 pub authority_seed: String,
570 pub authority_owner: Pubkey,
571}
572
573#[cfg_attr(
574 feature = "codama",
575 derive(CodamaType),
576 codama(name = "authorizeCheckedWithSeedParams")
577)]
578#[derive(Debug, PartialEq, Eq, Clone)]
579#[cfg_attr(
580 feature = "serde",
581 derive(serde_derive::Deserialize, serde_derive::Serialize)
582)]
583pub struct AuthorizeCheckedWithSeedArgs {
584 pub stake_authorize: StakeAuthorize,
585 #[cfg_attr(feature = "codama", codama(size_prefix = number(u64)))]
586 pub authority_seed: String,
587 pub authority_owner: Pubkey,
588}
589
590#[cfg(feature = "bincode")]
591pub fn initialize(stake_pubkey: &Pubkey, authorized: &Authorized, lockup: &Lockup) -> Instruction {
592 Instruction::new_with_bincode(
593 ID,
594 &StakeInstruction::Initialize(*authorized, *lockup),
595 vec![
596 AccountMeta::new(*stake_pubkey, false),
597 AccountMeta::new_readonly(RENT_ID, false),
598 ],
599 )
600}
601
602#[cfg(feature = "bincode")]
603pub fn initialize_checked(stake_pubkey: &Pubkey, authorized: &Authorized) -> Instruction {
604 Instruction::new_with_bincode(
605 ID,
606 &StakeInstruction::InitializeChecked,
607 vec![
608 AccountMeta::new(*stake_pubkey, false),
609 AccountMeta::new_readonly(RENT_ID, false),
610 AccountMeta::new_readonly(authorized.staker, false),
611 AccountMeta::new_readonly(authorized.withdrawer, true),
612 ],
613 )
614}
615
616#[cfg(feature = "bincode")]
617pub fn create_account_with_seed(
618 from_pubkey: &Pubkey,
619 stake_pubkey: &Pubkey,
620 base: &Pubkey,
621 seed: &str,
622 authorized: &Authorized,
623 lockup: &Lockup,
624 lamports: u64,
625) -> Vec<Instruction> {
626 vec![
627 solana_system_interface::instruction::create_account_with_seed(
628 from_pubkey,
629 stake_pubkey,
630 base,
631 seed,
632 lamports,
633 StakeStateV2::size_of() as u64,
634 &ID,
635 ),
636 initialize(stake_pubkey, authorized, lockup),
637 ]
638}
639
640#[cfg(feature = "bincode")]
641pub fn create_account(
642 from_pubkey: &Pubkey,
643 stake_pubkey: &Pubkey,
644 authorized: &Authorized,
645 lockup: &Lockup,
646 lamports: u64,
647) -> Vec<Instruction> {
648 vec![
649 solana_system_interface::instruction::create_account(
650 from_pubkey,
651 stake_pubkey,
652 lamports,
653 StakeStateV2::size_of() as u64,
654 &ID,
655 ),
656 initialize(stake_pubkey, authorized, lockup),
657 ]
658}
659
660#[cfg(feature = "bincode")]
661pub fn create_account_with_seed_checked(
662 from_pubkey: &Pubkey,
663 stake_pubkey: &Pubkey,
664 base: &Pubkey,
665 seed: &str,
666 authorized: &Authorized,
667 lamports: u64,
668) -> Vec<Instruction> {
669 vec![
670 solana_system_interface::instruction::create_account_with_seed(
671 from_pubkey,
672 stake_pubkey,
673 base,
674 seed,
675 lamports,
676 StakeStateV2::size_of() as u64,
677 &ID,
678 ),
679 initialize_checked(stake_pubkey, authorized),
680 ]
681}
682
683#[cfg(feature = "bincode")]
684pub fn create_account_checked(
685 from_pubkey: &Pubkey,
686 stake_pubkey: &Pubkey,
687 authorized: &Authorized,
688 lamports: u64,
689) -> Vec<Instruction> {
690 vec![
691 solana_system_interface::instruction::create_account(
692 from_pubkey,
693 stake_pubkey,
694 lamports,
695 StakeStateV2::size_of() as u64,
696 &ID,
697 ),
698 initialize_checked(stake_pubkey, authorized),
699 ]
700}
701
702#[cfg(feature = "bincode")]
703fn _split(
704 stake_pubkey: &Pubkey,
705 authorized_pubkey: &Pubkey,
706 lamports: u64,
707 split_stake_pubkey: &Pubkey,
708) -> Instruction {
709 let account_metas = vec![
710 AccountMeta::new(*stake_pubkey, false),
711 AccountMeta::new(*split_stake_pubkey, false),
712 AccountMeta::new_readonly(*authorized_pubkey, true),
713 ];
714
715 Instruction::new_with_bincode(ID, &StakeInstruction::Split(lamports), account_metas)
716}
717
718#[cfg(feature = "bincode")]
719pub fn split(
720 stake_pubkey: &Pubkey,
721 authorized_pubkey: &Pubkey,
722 lamports: u64,
723 split_stake_pubkey: &Pubkey,
724) -> Vec<Instruction> {
725 vec![
726 solana_system_interface::instruction::allocate(
727 split_stake_pubkey,
728 StakeStateV2::size_of() as u64,
729 ),
730 solana_system_interface::instruction::assign(split_stake_pubkey, &ID),
731 _split(
732 stake_pubkey,
733 authorized_pubkey,
734 lamports,
735 split_stake_pubkey,
736 ),
737 ]
738}
739
740#[cfg(feature = "bincode")]
741pub fn split_with_seed(
742 stake_pubkey: &Pubkey,
743 authorized_pubkey: &Pubkey,
744 lamports: u64,
745 split_stake_pubkey: &Pubkey, base: &Pubkey, seed: &str, ) -> Vec<Instruction> {
749 vec![
750 solana_system_interface::instruction::allocate_with_seed(
751 split_stake_pubkey,
752 base,
753 seed,
754 StakeStateV2::size_of() as u64,
755 &ID,
756 ),
757 _split(
758 stake_pubkey,
759 authorized_pubkey,
760 lamports,
761 split_stake_pubkey,
762 ),
763 ]
764}
765
766#[cfg(feature = "bincode")]
767pub fn merge(
768 destination_stake_pubkey: &Pubkey,
769 source_stake_pubkey: &Pubkey,
770 authorized_pubkey: &Pubkey,
771) -> Vec<Instruction> {
772 let account_metas = vec![
773 AccountMeta::new(*destination_stake_pubkey, false),
774 AccountMeta::new(*source_stake_pubkey, false),
775 AccountMeta::new_readonly(CLOCK_ID, false),
776 AccountMeta::new_readonly(STAKE_HISTORY_ID, false),
777 AccountMeta::new_readonly(*authorized_pubkey, true),
778 ];
779
780 vec![Instruction::new_with_bincode(
781 ID,
782 &StakeInstruction::Merge,
783 account_metas,
784 )]
785}
786
787#[cfg(feature = "bincode")]
788pub fn create_account_and_delegate_stake(
789 from_pubkey: &Pubkey,
790 stake_pubkey: &Pubkey,
791 vote_pubkey: &Pubkey,
792 authorized: &Authorized,
793 lockup: &Lockup,
794 lamports: u64,
795) -> Vec<Instruction> {
796 let mut instructions = create_account(from_pubkey, stake_pubkey, authorized, lockup, lamports);
797 instructions.push(delegate_stake(
798 stake_pubkey,
799 &authorized.staker,
800 vote_pubkey,
801 ));
802 instructions
803}
804
805#[cfg(feature = "bincode")]
806#[allow(clippy::too_many_arguments)]
807pub fn create_account_with_seed_and_delegate_stake(
808 from_pubkey: &Pubkey,
809 stake_pubkey: &Pubkey,
810 base: &Pubkey,
811 seed: &str,
812 vote_pubkey: &Pubkey,
813 authorized: &Authorized,
814 lockup: &Lockup,
815 lamports: u64,
816) -> Vec<Instruction> {
817 let mut instructions = create_account_with_seed(
818 from_pubkey,
819 stake_pubkey,
820 base,
821 seed,
822 authorized,
823 lockup,
824 lamports,
825 );
826 instructions.push(delegate_stake(
827 stake_pubkey,
828 &authorized.staker,
829 vote_pubkey,
830 ));
831 instructions
832}
833
834#[cfg(feature = "bincode")]
835pub fn authorize(
836 stake_pubkey: &Pubkey,
837 authorized_pubkey: &Pubkey,
838 new_authorized_pubkey: &Pubkey,
839 stake_authorize: StakeAuthorize,
840 custodian_pubkey: Option<&Pubkey>,
841) -> Instruction {
842 let mut account_metas = vec![
843 AccountMeta::new(*stake_pubkey, false),
844 AccountMeta::new_readonly(CLOCK_ID, false),
845 AccountMeta::new_readonly(*authorized_pubkey, true),
846 ];
847
848 if let Some(custodian_pubkey) = custodian_pubkey {
849 account_metas.push(AccountMeta::new_readonly(*custodian_pubkey, true));
850 }
851
852 Instruction::new_with_bincode(
853 ID,
854 &StakeInstruction::Authorize(*new_authorized_pubkey, stake_authorize),
855 account_metas,
856 )
857}
858
859#[cfg(feature = "bincode")]
860pub fn authorize_checked(
861 stake_pubkey: &Pubkey,
862 authorized_pubkey: &Pubkey,
863 new_authorized_pubkey: &Pubkey,
864 stake_authorize: StakeAuthorize,
865 custodian_pubkey: Option<&Pubkey>,
866) -> Instruction {
867 let mut account_metas = vec![
868 AccountMeta::new(*stake_pubkey, false),
869 AccountMeta::new_readonly(CLOCK_ID, false),
870 AccountMeta::new_readonly(*authorized_pubkey, true),
871 AccountMeta::new_readonly(*new_authorized_pubkey, true),
872 ];
873
874 if let Some(custodian_pubkey) = custodian_pubkey {
875 account_metas.push(AccountMeta::new_readonly(*custodian_pubkey, true));
876 }
877
878 Instruction::new_with_bincode(
879 ID,
880 &StakeInstruction::AuthorizeChecked(stake_authorize),
881 account_metas,
882 )
883}
884
885#[cfg(feature = "bincode")]
886pub fn authorize_with_seed(
887 stake_pubkey: &Pubkey,
888 authority_base: &Pubkey,
889 authority_seed: String,
890 authority_owner: &Pubkey,
891 new_authorized_pubkey: &Pubkey,
892 stake_authorize: StakeAuthorize,
893 custodian_pubkey: Option<&Pubkey>,
894) -> Instruction {
895 let mut account_metas = vec![
896 AccountMeta::new(*stake_pubkey, false),
897 AccountMeta::new_readonly(*authority_base, true),
898 AccountMeta::new_readonly(CLOCK_ID, false),
899 ];
900
901 if let Some(custodian_pubkey) = custodian_pubkey {
902 account_metas.push(AccountMeta::new_readonly(*custodian_pubkey, true));
903 }
904
905 let args = AuthorizeWithSeedArgs {
906 new_authorized_pubkey: *new_authorized_pubkey,
907 stake_authorize,
908 authority_seed,
909 authority_owner: *authority_owner,
910 };
911
912 Instruction::new_with_bincode(
913 ID,
914 &StakeInstruction::AuthorizeWithSeed(args),
915 account_metas,
916 )
917}
918
919#[cfg(feature = "bincode")]
920pub fn authorize_checked_with_seed(
921 stake_pubkey: &Pubkey,
922 authority_base: &Pubkey,
923 authority_seed: String,
924 authority_owner: &Pubkey,
925 new_authorized_pubkey: &Pubkey,
926 stake_authorize: StakeAuthorize,
927 custodian_pubkey: Option<&Pubkey>,
928) -> Instruction {
929 let mut account_metas = vec![
930 AccountMeta::new(*stake_pubkey, false),
931 AccountMeta::new_readonly(*authority_base, true),
932 AccountMeta::new_readonly(CLOCK_ID, false),
933 AccountMeta::new_readonly(*new_authorized_pubkey, true),
934 ];
935
936 if let Some(custodian_pubkey) = custodian_pubkey {
937 account_metas.push(AccountMeta::new_readonly(*custodian_pubkey, true));
938 }
939
940 let args = AuthorizeCheckedWithSeedArgs {
941 stake_authorize,
942 authority_seed,
943 authority_owner: *authority_owner,
944 };
945
946 Instruction::new_with_bincode(
947 ID,
948 &StakeInstruction::AuthorizeCheckedWithSeed(args),
949 account_metas,
950 )
951}
952
953#[cfg(feature = "bincode")]
954pub fn delegate_stake(
955 stake_pubkey: &Pubkey,
956 authorized_pubkey: &Pubkey,
957 vote_pubkey: &Pubkey,
958) -> Instruction {
959 let account_metas = vec![
960 AccountMeta::new(*stake_pubkey, false),
961 AccountMeta::new_readonly(*vote_pubkey, false),
962 AccountMeta::new_readonly(CLOCK_ID, false),
963 AccountMeta::new_readonly(STAKE_HISTORY_ID, false),
964 AccountMeta::new_readonly(config::ID, false),
966 AccountMeta::new_readonly(*authorized_pubkey, true),
967 ];
968 Instruction::new_with_bincode(ID, &StakeInstruction::DelegateStake, account_metas)
969}
970
971#[cfg(feature = "bincode")]
972pub fn withdraw(
973 stake_pubkey: &Pubkey,
974 withdrawer_pubkey: &Pubkey,
975 to_pubkey: &Pubkey,
976 lamports: u64,
977 custodian_pubkey: Option<&Pubkey>,
978) -> Instruction {
979 let mut account_metas = vec![
980 AccountMeta::new(*stake_pubkey, false),
981 AccountMeta::new(*to_pubkey, false),
982 AccountMeta::new_readonly(CLOCK_ID, false),
983 AccountMeta::new_readonly(STAKE_HISTORY_ID, false),
984 AccountMeta::new_readonly(*withdrawer_pubkey, true),
985 ];
986
987 if let Some(custodian_pubkey) = custodian_pubkey {
988 account_metas.push(AccountMeta::new_readonly(*custodian_pubkey, true));
989 }
990
991 Instruction::new_with_bincode(ID, &StakeInstruction::Withdraw(lamports), account_metas)
992}
993
994#[cfg(feature = "bincode")]
995pub fn deactivate_stake(stake_pubkey: &Pubkey, authorized_pubkey: &Pubkey) -> Instruction {
996 let account_metas = vec![
997 AccountMeta::new(*stake_pubkey, false),
998 AccountMeta::new_readonly(CLOCK_ID, false),
999 AccountMeta::new_readonly(*authorized_pubkey, true),
1000 ];
1001 Instruction::new_with_bincode(ID, &StakeInstruction::Deactivate, account_metas)
1002}
1003
1004#[cfg(feature = "bincode")]
1005pub fn set_lockup(
1006 stake_pubkey: &Pubkey,
1007 lockup: &LockupArgs,
1008 custodian_pubkey: &Pubkey,
1009) -> Instruction {
1010 let account_metas = vec![
1011 AccountMeta::new(*stake_pubkey, false),
1012 AccountMeta::new_readonly(*custodian_pubkey, true),
1013 ];
1014 Instruction::new_with_bincode(ID, &StakeInstruction::SetLockup(*lockup), account_metas)
1015}
1016
1017#[cfg(feature = "bincode")]
1018pub fn set_lockup_checked(
1019 stake_pubkey: &Pubkey,
1020 lockup: &LockupArgs,
1021 custodian_pubkey: &Pubkey,
1022) -> Instruction {
1023 let mut account_metas = vec![
1024 AccountMeta::new(*stake_pubkey, false),
1025 AccountMeta::new_readonly(*custodian_pubkey, true),
1026 ];
1027
1028 let lockup_checked = LockupCheckedArgs {
1029 unix_timestamp: lockup.unix_timestamp,
1030 epoch: lockup.epoch,
1031 };
1032 if let Some(new_custodian) = lockup.custodian {
1033 account_metas.push(AccountMeta::new_readonly(new_custodian, true));
1034 }
1035 Instruction::new_with_bincode(
1036 ID,
1037 &StakeInstruction::SetLockupChecked(lockup_checked),
1038 account_metas,
1039 )
1040}
1041
1042#[cfg(feature = "bincode")]
1043pub fn get_minimum_delegation() -> Instruction {
1044 Instruction::new_with_bincode(ID, &StakeInstruction::GetMinimumDelegation, Vec::default())
1045}
1046
1047#[cfg(feature = "bincode")]
1048pub fn deactivate_delinquent_stake(
1049 stake_account: &Pubkey,
1050 delinquent_vote_account: &Pubkey,
1051 reference_vote_account: &Pubkey,
1052) -> Instruction {
1053 let account_metas = vec![
1054 AccountMeta::new(*stake_account, false),
1055 AccountMeta::new_readonly(*delinquent_vote_account, false),
1056 AccountMeta::new_readonly(*reference_vote_account, false),
1057 ];
1058 Instruction::new_with_bincode(ID, &StakeInstruction::DeactivateDelinquent, account_metas)
1059}
1060
1061#[cfg(feature = "bincode")]
1062fn _redelegate(
1063 stake_pubkey: &Pubkey,
1064 authorized_pubkey: &Pubkey,
1065 vote_pubkey: &Pubkey,
1066 uninitialized_stake_pubkey: &Pubkey,
1067) -> Instruction {
1068 let account_metas = vec![
1069 AccountMeta::new(*stake_pubkey, false),
1070 AccountMeta::new(*uninitialized_stake_pubkey, false),
1071 AccountMeta::new_readonly(*vote_pubkey, false),
1072 AccountMeta::new_readonly(config::ID, false),
1074 AccountMeta::new_readonly(*authorized_pubkey, true),
1075 ];
1076 Instruction::new_with_bincode(ID, &StakeInstruction::Redelegate, account_metas)
1077}
1078
1079#[cfg(feature = "bincode")]
1080#[deprecated(since = "2.1.0", note = "Redelegate will not be enabled")]
1081pub fn redelegate(
1082 stake_pubkey: &Pubkey,
1083 authorized_pubkey: &Pubkey,
1084 vote_pubkey: &Pubkey,
1085 uninitialized_stake_pubkey: &Pubkey,
1086) -> Vec<Instruction> {
1087 vec![
1088 solana_system_interface::instruction::allocate(
1089 uninitialized_stake_pubkey,
1090 StakeStateV2::size_of() as u64,
1091 ),
1092 solana_system_interface::instruction::assign(uninitialized_stake_pubkey, &ID),
1093 _redelegate(
1094 stake_pubkey,
1095 authorized_pubkey,
1096 vote_pubkey,
1097 uninitialized_stake_pubkey,
1098 ),
1099 ]
1100}
1101
1102#[cfg(feature = "bincode")]
1103#[deprecated(since = "2.1.0", note = "Redelegate will not be enabled")]
1104pub fn redelegate_with_seed(
1105 stake_pubkey: &Pubkey,
1106 authorized_pubkey: &Pubkey,
1107 vote_pubkey: &Pubkey,
1108 uninitialized_stake_pubkey: &Pubkey, base: &Pubkey, seed: &str, ) -> Vec<Instruction> {
1112 vec![
1113 solana_system_interface::instruction::allocate_with_seed(
1114 uninitialized_stake_pubkey,
1115 base,
1116 seed,
1117 StakeStateV2::size_of() as u64,
1118 &ID,
1119 ),
1120 _redelegate(
1121 stake_pubkey,
1122 authorized_pubkey,
1123 vote_pubkey,
1124 uninitialized_stake_pubkey,
1125 ),
1126 ]
1127}
1128
1129#[cfg(feature = "bincode")]
1130pub fn move_stake(
1131 source_stake_pubkey: &Pubkey,
1132 destination_stake_pubkey: &Pubkey,
1133 authorized_pubkey: &Pubkey,
1134 lamports: u64,
1135) -> Instruction {
1136 let account_metas = vec![
1137 AccountMeta::new(*source_stake_pubkey, false),
1138 AccountMeta::new(*destination_stake_pubkey, false),
1139 AccountMeta::new_readonly(*authorized_pubkey, true),
1140 ];
1141
1142 Instruction::new_with_bincode(ID, &StakeInstruction::MoveStake(lamports), account_metas)
1143}
1144
1145#[cfg(feature = "bincode")]
1146pub fn move_lamports(
1147 source_stake_pubkey: &Pubkey,
1148 destination_stake_pubkey: &Pubkey,
1149 authorized_pubkey: &Pubkey,
1150 lamports: u64,
1151) -> Instruction {
1152 let account_metas = vec![
1153 AccountMeta::new(*source_stake_pubkey, false),
1154 AccountMeta::new(*destination_stake_pubkey, false),
1155 AccountMeta::new_readonly(*authorized_pubkey, true),
1156 ];
1157
1158 Instruction::new_with_bincode(ID, &StakeInstruction::MoveLamports(lamports), account_metas)
1159}
1160
1161#[cfg(feature = "bincode")]
1162#[cfg(test)]
1163mod tests {
1164 use super::*;
1165
1166 #[allow(deprecated)]
1167 #[test]
1168 fn test_constants() {
1169 assert_eq!(CLOCK_ID, solana_sdk_ids::sysvar::clock::ID);
1171
1172 assert_eq!(STAKE_HISTORY_ID, solana_sdk_ids::sysvar::stake_history::ID);
1174
1175 assert_eq!(RENT_ID, solana_sdk_ids::sysvar::rent::ID);
1177 }
1178}