gmsol/store/
store_ops.rs

1use std::{ops::Deref, sync::Arc};
2
3use anchor_client::{
4    anchor_lang::system_program,
5    solana_sdk::{pubkey::Pubkey, signer::Signer},
6};
7use gmsol_solana_utils::transaction_builder::TransactionBuilder;
8use gmsol_store::{
9    accounts, instruction,
10    states::{Factor, FactorKey},
11};
12
13/// Data Store management for GMSOL.
14pub trait StoreOps<C> {
15    /// Initialize [`Store`](gmsol_store::states::Store) account.
16    fn initialize_store<S: Signer + 'static>(
17        &self,
18        key: &str,
19        authority: Option<S>,
20        receiver: Option<S>,
21        holding: Option<S>,
22    ) -> TransactionBuilder<C>;
23
24    /// Transfer store authority.
25    fn transfer_store_authority(
26        &self,
27        store: &Pubkey,
28        new_authority: &Pubkey,
29    ) -> TransactionBuilder<C>;
30
31    /// Accept store authority.
32    fn accept_store_authority(&self, store: &Pubkey) -> TransactionBuilder<C>;
33
34    /// Transfer receiver.
35    fn transfer_receiver(&self, store: &Pubkey, new_receiver: &Pubkey) -> TransactionBuilder<C>;
36
37    /// Set new token map.
38    fn set_token_map(&self, store: &Pubkey, token_map: &Pubkey) -> TransactionBuilder<C>;
39
40    /// Insert factor.
41    fn insert_factor(
42        &self,
43        store: &Pubkey,
44        key: FactorKey,
45        factor: Factor,
46    ) -> TransactionBuilder<C>;
47}
48
49impl<C, S> StoreOps<C> for crate::Client<C>
50where
51    C: Deref<Target = S> + Clone,
52    S: Signer,
53{
54    fn initialize_store<S2: Signer + 'static>(
55        &self,
56        key: &str,
57        authority: Option<S2>,
58        receiver: Option<S2>,
59        holding: Option<S2>,
60    ) -> TransactionBuilder<C> {
61        let store = self.find_store_address(key);
62        let authority_address = authority.as_ref().map(|s| s.pubkey());
63        let receiver_address = receiver.as_ref().map(|s| s.pubkey());
64        let holding_address = holding.as_ref().map(|s| s.pubkey());
65        let mut rpc = self
66            .store_transaction()
67            .anchor_accounts(accounts::Initialize {
68                payer: self.payer(),
69                authority: authority_address,
70                receiver: receiver_address,
71                holding: holding_address,
72                store,
73                system_program: system_program::ID,
74            })
75            .anchor_args(instruction::Initialize {
76                key: key.to_string(),
77            });
78
79        for signer in authority.into_iter().chain(receiver).chain(holding) {
80            rpc = rpc.owned_signer(Arc::new(signer));
81        }
82
83        rpc
84    }
85
86    fn transfer_store_authority(
87        &self,
88        store: &Pubkey,
89        next_authority: &Pubkey,
90    ) -> TransactionBuilder<C> {
91        self.store_transaction()
92            .anchor_args(instruction::TransferStoreAuthority {})
93            .anchor_accounts(accounts::TransferStoreAuthority {
94                authority: self.payer(),
95                store: *store,
96                next_authority: *next_authority,
97            })
98    }
99
100    fn accept_store_authority(&self, store: &Pubkey) -> TransactionBuilder<C> {
101        self.store_transaction()
102            .anchor_args(instruction::AcceptStoreAuthority {})
103            .anchor_accounts(accounts::AcceptStoreAuthority {
104                next_authority: self.payer(),
105                store: *store,
106            })
107    }
108
109    fn transfer_receiver(&self, store: &Pubkey, new_receiver: &Pubkey) -> TransactionBuilder<C> {
110        self.store_transaction()
111            .anchor_args(instruction::TransferReceiver {})
112            .anchor_accounts(accounts::TransferReceiver {
113                authority: self.payer(),
114                store: *store,
115                next_receiver: *new_receiver,
116            })
117    }
118
119    fn set_token_map(&self, store: &Pubkey, token_map: &Pubkey) -> TransactionBuilder<C> {
120        self.store_transaction()
121            .anchor_args(instruction::SetTokenMap {})
122            .anchor_accounts(accounts::SetTokenMap {
123                authority: self.payer(),
124                store: *store,
125                token_map: *token_map,
126            })
127    }
128
129    fn insert_factor(
130        &self,
131        store: &Pubkey,
132        key: FactorKey,
133        factor: Factor,
134    ) -> TransactionBuilder<C> {
135        let rpc = self
136            .store_transaction()
137            .anchor_accounts(accounts::InsertConfig {
138                authority: self.payer(),
139                store: *store,
140            });
141        match key {
142            FactorKey::OrderFeeDiscountForReferredUser => {
143                rpc.anchor_args(instruction::InsertOrderFeeDiscountForReferredUser { factor })
144            }
145            _ => rpc.anchor_args(instruction::InsertFactor {
146                key: key.to_string(),
147                factor,
148            }),
149        }
150    }
151}