shadow_drive_sdk/client/
refresh_stake.rs

1use anchor_lang::{system_program, InstructionData, ToAccountMetas};
2use shadow_drive_user_staking::accounts as shdw_drive_accounts;
3use shadow_drive_user_staking::instruction as shdw_drive_instructions;
4use solana_sdk::{
5    instruction::Instruction, pubkey::Pubkey, signer::Signer, transaction::Transaction,
6};
7use spl_associated_token_account::get_associated_token_address;
8
9use super::ShadowDriveClient;
10use crate::derived_addresses;
11use crate::{
12    constants::{PROGRAM_ADDRESS, STORAGE_CONFIG_PDA, TOKEN_MINT},
13    models::{
14        storage_acct::{StorageAccount, StorageAccountV2, StorageAcct},
15        *,
16    },
17};
18use spl_token::ID as TokenProgramID;
19
20impl<T> ShadowDriveClient<T>
21where
22    T: Signer,
23{
24    ///  Allows user to refresh stake account, and unmarks deletion.
25    /// * `storage_account_key` - The public key of the [`StorageAccount`](crate::models::StorageAccount) that you want to top up stake for.
26    /// # Example
27    ///
28    /// ```
29    /// # use shadow_drive_rust::{ShadowDriveClient, derived_addresses::storage_account};
30    /// # use solana_client::rpc_client::RpcClient;
31    /// # use solana_sdk::{
32    /// # pubkey::Pubkey,
33    /// # signature::Keypair,
34    /// # signer::{keypair::read_keypair_file, Signer},
35    /// # };
36    /// #
37    /// # let keypair = read_keypair_file(KEYPAIR_PATH).expect("failed to load keypair at path");
38    /// # let user_pubkey = keypair.pubkey();
39    /// # let rpc_client = RpcClient::new("https://ssc-dao.genesysgo.net");
40    /// # let shdw_drive_client = ShadowDriveClient::new(keypair, rpc_client);
41    /// # let (storage_account_key, _) = storage_account(&user_pubkey, 0);
42    /// #
43    /// let refresh_stake = shdw_drive_client
44    ///     .refresh_stake(&storage_account_key)
45    ///     .await?;
46    /// ```
47    pub async fn refresh_stake(
48        &self,
49        storage_account_key: &Pubkey,
50    ) -> ShadowDriveResult<ShdwDriveResponse> {
51        let selected_account = self.get_storage_account(storage_account_key).await?;
52
53        let txn = match selected_account {
54            StorageAcct::V1(storage_account) => {
55                self.refresh_stake_v1(storage_account_key, storage_account)
56                    .await?
57            }
58            StorageAcct::V2(storage_account) => {
59                self.refresh_stake_v2(storage_account_key, storage_account)
60                    .await?
61            }
62        };
63
64        let txn_result = self.rpc_client.send_and_confirm_transaction(&txn).await?;
65
66        Ok(ShdwDriveResponse {
67            txid: txn_result.to_string(),
68        })
69    }
70
71    async fn refresh_stake_v1(
72        &self,
73        storage_account_key: &Pubkey,
74        storage_account: StorageAccount,
75    ) -> ShadowDriveResult<Transaction> {
76        let wallet_pubkey = self.wallet.pubkey();
77        let owner_ata = get_associated_token_address(&wallet_pubkey, &TOKEN_MINT);
78        let (stake_account, _) = derived_addresses::stake_account(storage_account_key);
79        let accounts = shdw_drive_accounts::RefreshStakeV1 {
80            storage_config: *STORAGE_CONFIG_PDA,
81            storage_account: *storage_account_key,
82            stake_account: stake_account,
83            owner: storage_account.owner_1,
84            owner_ata,
85            token_mint: TOKEN_MINT,
86            system_program: system_program::ID,
87            token_program: TokenProgramID,
88        };
89
90        let args = shdw_drive_instructions::RefreshStake {};
91
92        let instruction = Instruction {
93            program_id: PROGRAM_ADDRESS,
94            accounts: accounts.to_account_metas(None),
95            data: args.data(),
96        };
97
98        let txn = Transaction::new_signed_with_payer(
99            &[instruction],
100            Some(&wallet_pubkey),
101            &[&self.wallet],
102            self.rpc_client.get_latest_blockhash().await?,
103        );
104
105        Ok(txn)
106    }
107
108    async fn refresh_stake_v2(
109        &self,
110        storage_account_key: &Pubkey,
111        storage_account: StorageAccountV2,
112    ) -> ShadowDriveResult<Transaction> {
113        let wallet_pubkey = self.wallet.pubkey();
114        let owner_ata = get_associated_token_address(&wallet_pubkey, &TOKEN_MINT);
115        let (stake_account, _) = derived_addresses::stake_account(storage_account_key);
116
117        let accounts = shdw_drive_accounts::RefreshStakeV2 {
118            storage_config: *STORAGE_CONFIG_PDA,
119            storage_account: *storage_account_key,
120            owner: storage_account.owner_1,
121            owner_ata,
122            stake_account: stake_account,
123            token_mint: TOKEN_MINT,
124            system_program: system_program::ID,
125            token_program: TokenProgramID,
126        };
127
128        let args = shdw_drive_instructions::RefreshStake2 {};
129
130        let instruction = Instruction {
131            program_id: PROGRAM_ADDRESS,
132            accounts: accounts.to_account_metas(None),
133            data: args.data(),
134        };
135
136        let txn = Transaction::new_signed_with_payer(
137            &[instruction],
138            Some(&wallet_pubkey),
139            &[&self.wallet],
140            self.rpc_client.get_latest_blockhash().await?,
141        );
142
143        Ok(txn)
144    }
145}