buddy_link/instruction/
transfer_reward.rs

1use crate::constants::BL_PROGRAM_ID;
2use borsh::{BorshDeserialize, BorshSerialize};
3use solana_program::instruction::{AccountMeta, Instruction};
4use solana_program::pubkey::Pubkey;
5use crate::utils::{get_account_meta_or_read_default, get_instruction_name_data};
6
7#[repr(C)]
8#[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Debug, Clone)]
9pub struct GeneralTransferRewardArgs {
10    /// The amount of tokens to be transferred
11    pub amount: u64,
12}
13
14#[repr(C)]
15#[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Debug, Clone)]
16pub struct TransferUncheckedLocalSharedRewardArgs {
17    /// The amount of tokens to be split and transferred
18    pub total_amount: u64,
19    /// How the token will be split in bps
20    pub shares_in_bps: Vec<u16>,
21    /// If the referrer members are included in the remaining accounts.
22    /// Is needed if you want to use the on-chain analytics system
23    pub members_included: bool,
24}
25
26///# Transfer Unchecked Local Shared Reward (SPL & SOL)
27///
28/// Transfer referral rewards to multiple user based on their share in bps
29///
30/// UNCHECKED: does not validate any accounts
31/// LOCAL: does not use the global referral system of Buddylink
32///
33/// 1. `[writable, signer]` Authority of the account sending the funds.
34/// 2. `[optional]` Only used if sending SOL, None if sending SPL.
35/// 3. `[optional]` Mint, None if sending SOL.
36/// 4. `[optional]` Token program, None if sending SOL.
37/// 5. `[writable, optional]` None if sending SOL (will send from authority), else is Token Account
38/// 7. `[writable]` Combination of referrer treasury / token account AND referrer member (if you want analytics on-chain).
39/// 8. Transfer arguments
40pub fn transfer_unchecked_local_shared_reward(
41    authority: Pubkey,
42    system_program: Option<Pubkey>,
43    mint: Option<Pubkey>,
44    token_program: Option<Pubkey>,
45    from_account: Option<Pubkey>,
46    remaining_accounts: &[Pubkey],
47    transfer_args: &TransferUncheckedLocalSharedRewardArgs,
48) -> Instruction {
49    let mut instruction_data = get_instruction_name_data("transfer_reward_unchecked_multiple");
50    instruction_data.extend_from_slice(&transfer_args.try_to_vec().unwrap());
51
52    let mut accounts = vec![
53        AccountMeta::new(authority, true),
54        AccountMeta::new_readonly(system_program.unwrap_or(BL_PROGRAM_ID), false),
55        AccountMeta::new_readonly(mint.unwrap_or(BL_PROGRAM_ID), false),
56        AccountMeta::new_readonly(token_program.unwrap_or(BL_PROGRAM_ID), false),
57        get_account_meta_or_read_default(&from_account),
58    ];
59
60    accounts.extend_from_slice(
61        &remaining_accounts
62            .iter()
63            .map(|account| AccountMeta {
64                pubkey: *account,
65                is_signer: false,
66                is_writable: true,
67            })
68            .collect::<Vec<AccountMeta>>(),
69    );
70
71    Instruction {
72        program_id: BL_PROGRAM_ID,
73        accounts,
74        data: instruction_data,
75    }
76}
77
78///# Transfer Secure Local Reward (SPL)
79///
80/// Transfer referral rewards to a single user, where validation is done.
81///
82/// SECURE: validation is done on the seeds, the owners of the accounts, the referral tree, the buddy doing the action is the same of the one in your system.
83/// LOCAL: does not use the global referral system of Buddylink
84///
85/// 1. `[writable, signer]` Authority of the account sending the funds.
86/// 2. `[]` Mint
87/// 3. `[]` Token program
88/// 4. `[writable]` Account sending the funds.
89/// 5. `[writable]` Account receiving the funds (buddy link owned).
90/// 6. `[writable]` Referrer member (account of the referrer within your organization).
91/// 7. `[writable]` Referrer treasury (treasury that owns the referrer member #6).
92/// 8. `[writable]` Referrer treasury for reward (treasury that is linked to the current mint, could be the same as #7).
93/// 9. `[writable]` Buddy Link Profile of the referee.
94/// 10. `[writable]` Buddy Link Paid buddy of the referee (could be the same as #9).
95/// 11. `[writable]` Referee treasury (is owned by #10).
96/// 12. `[writable]` Referee member (account of the referee within your organization).
97/// 13. Transfer arguments
98#[allow(clippy::too_many_arguments)]
99pub fn transfer_secure_local_reward(
100    authority: Pubkey,
101    mint: Pubkey,
102    token_program: Pubkey,
103    from_token_account: Pubkey,
104    referrer_token_account: Pubkey,
105    referrer_member: Pubkey,
106    referrer_treasury: Pubkey,
107    referrer_treasury_for_reward: Pubkey,
108    referee_buddy_profile: Pubkey,
109    referee_buddy: Pubkey,
110    referee_treasury: Pubkey,
111    referee_member: Pubkey,
112    transfer_args: &GeneralTransferRewardArgs,
113) -> Instruction {
114    let mut instruction_data = get_instruction_name_data("transfer_reward_secure_no_global");
115    instruction_data.extend_from_slice(&transfer_args.try_to_vec().unwrap());
116
117    Instruction {
118        program_id: BL_PROGRAM_ID,
119        accounts: vec![
120            AccountMeta::new(authority, true),
121            AccountMeta::new_readonly(mint, false),
122            AccountMeta::new_readonly(token_program, false),
123            AccountMeta::new(from_token_account, false),
124            AccountMeta::new(referrer_member, false),
125            AccountMeta::new(referrer_treasury, false),
126            AccountMeta::new(referrer_treasury_for_reward, false),
127            AccountMeta::new(referee_buddy_profile, false),
128            AccountMeta::new(referee_buddy, false),
129            AccountMeta::new(referee_treasury, false),
130            AccountMeta::new(referee_member, false),
131            AccountMeta::new(referrer_token_account, false),
132        ],
133        data: instruction_data,
134    }
135}
136
137///# Transfer Checked Global Reward (SPL)
138///
139/// Transfer referral rewards to a single user, where validation is done.
140///
141/// CHECKED: validation is done on the seeds, the owners of the accounts, the referral tree.
142/// GLOBAL: option to also use the global referral system of buddylink
143///
144/// 1. `[writable, signer]` Authority of the account sending the funds.
145/// 2. `[]` Mint
146/// 3. `[]` Token program
147/// 4. `[writable]` Account sending the funds.
148/// 5. `[writable]` Account receiving the funds (buddy link owned).
149/// 6. `[writable, optional]` Referrer member (account of the referrer within your organization) (None if don't want on-chain analytics).
150/// 7. `[writable]` Referrer treasury (treasury that owns the referrer member #6).
151/// 8. `[writable]` Referrer treasury for reward (treasury that is linked to the current mint, could be the same as #7).
152/// 9. `[writable]` Referee member (account of the referee within your organization).
153/// 10. `[writable]` Global referrer treasury (treasury of the global referrer of current referee) (None if user doesn't have global referrer).
154/// 11. `[writable]` Global referrer treasury for reward (treasury of the global referrer of current referee that is linked to the current mint, could be same as #10) (None if user doesn't have global referrer).
155/// 12. Transfer arguments
156#[allow(clippy::too_many_arguments)]
157pub fn transfer_checked_global_reward(
158    authority: Pubkey,
159    mint: Pubkey,
160    token_program: Pubkey,
161    from_token_account: Pubkey,
162    referrer_token_account: Pubkey,
163    referrer_member: Option<Pubkey>,
164    referrer_treasury: Pubkey,
165    referrer_treasury_for_reward: Pubkey,
166    referee_member: Pubkey,
167    buddy_global_referrer_treasury: Option<Pubkey>,
168    buddy_global_referrer_token_account: Option<Pubkey>,
169    transfer_args: &GeneralTransferRewardArgs,
170) -> Instruction {
171    let mut instruction_data = get_instruction_name_data("transfer_reward_spl");
172    instruction_data.extend_from_slice(&transfer_args.try_to_vec().unwrap());
173
174    Instruction {
175        program_id: BL_PROGRAM_ID,
176        accounts: vec![
177            AccountMeta::new(authority, true),
178            get_account_meta_or_read_default(&buddy_global_referrer_treasury),
179            get_account_meta_or_read_default(&buddy_global_referrer_token_account),
180            get_account_meta_or_read_default(&referrer_member),
181            AccountMeta::new(referrer_treasury, false),
182            AccountMeta::new(referrer_treasury_for_reward, false),
183            AccountMeta::new(referee_member, false),
184            AccountMeta::new_readonly(mint, false),
185            AccountMeta::new_readonly(token_program, false),
186            AccountMeta::new(from_token_account, false),
187            AccountMeta::new(referrer_token_account, false),
188        ],
189        data: instruction_data,
190    }
191}
192
193///# Transfer Checked Global Only Reward (SPL & SOL)
194///
195/// Transfer referral rewards within the global referral buddy link system.
196/// If you're an organization, you probably won't use this.
197///
198/// CHECKED: validation is done on the seeds, the owners of the accounts, the referral tree.
199/// GLOBAL ONLY: using only the global referral system of buddylink
200///
201/// 1. `[writable, signer]` Authority of the account sending the funds.
202/// 2. `[optional]` Only used if sending SOL, None if sending SPL.
203/// 3. `[optional]` Mint, None if sending SOL.
204/// 4. `[optional]` Token program, None if sending SOL.
205/// 5. `[writable, optional]` None if sending SOL (will send from authority), else is Token Account
206/// 6. `[writable, optional]` None if receiving SOL (will send to treasury), else is Token Account
207/// 7. `[writable]` Global referrer treasury (treasury of the global referrer of current referee).
208/// 8. `[writable]` Global referrer treasury for reward (treasury of the global referrer of current referee that is linked to the current mint, could be same as #10).
209/// 9. `[writable]` Buddy Link Profile of the referee.
210/// 10. `[writable]` Buddy Link Paid buddy of the referee (could be the same as #9).
211/// 11. Transfer arguments
212#[allow(clippy::too_many_arguments)]
213pub fn transfer_checked_global_only_reward(
214    authority: Pubkey,
215    system_program: Option<Pubkey>,
216    mint: Option<Pubkey>,
217    token_program: Option<Pubkey>,
218    from_token_account: Option<Pubkey>,
219    referrer_token_account: Option<Pubkey>,
220    buddy_global_referrer_treasury: Pubkey,
221    buddy_global_referrer_treasury_for_reward: Pubkey,
222    referee_buddy_profile: Pubkey,
223    referee_buddy: Pubkey,
224    transfer_args: &GeneralTransferRewardArgs,
225) -> Instruction {
226    let mut instruction_data = get_instruction_name_data("transfer_reward_global");
227    instruction_data.extend_from_slice(&transfer_args.try_to_vec().unwrap());
228
229    Instruction {
230        program_id: BL_PROGRAM_ID,
231        accounts: vec![
232            AccountMeta::new(authority, true),
233            AccountMeta::new(buddy_global_referrer_treasury, false),
234            AccountMeta::new(buddy_global_referrer_treasury_for_reward, false),
235            AccountMeta::new_readonly(referee_buddy_profile, false),
236            AccountMeta::new_readonly(referee_buddy, false),
237            AccountMeta::new_readonly(system_program.unwrap_or(BL_PROGRAM_ID), false),
238            AccountMeta::new_readonly(mint.unwrap_or(BL_PROGRAM_ID), false),
239            AccountMeta::new_readonly(token_program.unwrap_or(BL_PROGRAM_ID), false),
240            get_account_meta_or_read_default(&referrer_token_account),
241            get_account_meta_or_read_default(&from_token_account),
242        ],
243        data: instruction_data,
244    }
245}