community_managed_token/
instruction.rs

1use borsh::{BorshDeserialize, BorshSerialize};
2use shank::ShankInstruction;
3use solana_program::{
4    instruction::{AccountMeta, Instruction},
5    program_error::ProgramError,
6    pubkey::Pubkey,
7    system_program,
8};
9use spl_associated_token_account::get_associated_token_address;
10
11use crate::get_authority;
12
13#[derive(Debug, Clone, ShankInstruction, BorshSerialize, BorshDeserialize)]
14#[rustfmt::skip]
15pub enum ManagedTokenInstruction {
16
17    #[account(0, writable, signer, name = "mint")]
18    #[account(1, writable, signer, name = "payer")]
19    #[account(2, name = "upstream_authority")]
20    #[account(3, name = "system_program", desc = "System program")]
21    #[account(4, name = "token_program", desc = "Token program")]
22    InitializeMint {
23        decimals: u8,
24    },
25
26    #[account(0, writable, name = "account")]
27    #[account(1, name = "owner")]
28    #[account(2, writable, signer, name = "payer")]
29    #[account(3, signer, name = "upstream_authority")]
30    #[account(4, name = "freeze_authority")]
31    #[account(5, name = "mint")]
32    #[account(6, name = "system_program", desc = "System program")]
33    #[account(
34        7,
35        name = "associated_token_program",
36        desc = "Associated Token program"
37    )]
38    #[account(8, name = "token_program", desc = "Token program")]
39    InitializeAccount,
40
41    #[account(0, writable, name = "src_account")]
42    #[account(1, writable, name = "dst_account")]
43    #[account(2, name = "mint")]
44    #[account(3, signer, name = "owner")]
45    #[account(4, signer, name = "upstream_authority")]
46    #[account(5, name = "freeze_authority")]
47    #[account(6, name = "token_program", desc = "Token program")]
48    Transfer { amount: u64 },
49
50    #[account(0, writable, name = "mint")]
51    #[account(1, writable, name = "account")]
52    #[account(2, signer, name = "upstream_authority")]
53    #[account(3, name = "freeze_authority")]
54    #[account(4, name = "token_program", desc = "Token program")]
55    MintTo { amount: u64 },
56
57    #[account(0, writable, name = "mint")]
58    #[account(1, writable, name = "account")]
59    #[account(2, signer, name = "owner")]
60    #[account(3, signer, name = "upstream_authority")]
61    #[account(4, name = "freeze_authority")]
62    #[account(5, name = "token_program", desc = "Token program")]
63    Burn { amount: u64 },
64
65    #[account(0, writable, name = "account")]
66    #[account(1, writable, name = "destination")]
67    #[account(2, name = "mint")]
68    #[account(3, signer, name = "owner")]
69    #[account(4, signer, name = "upstream_authority")]
70    #[account(5, name = "freeze_authority")]
71    #[account(6, name = "token_program", desc = "Token program")]
72    CloseAccount,
73
74    #[account(0, name = "mint")]
75    #[account(1, writable, name = "account")]
76    #[account(2, signer, name = "owner")]
77    #[account(3, signer, name = "upstream_authority")]
78    #[account(4, name = "delegate")]
79    #[account(5, name = "freeze_authority")]
80    #[account(6, name = "token_program", desc = "Token program")]
81    Approve { amount: u64 },
82
83    #[account(0, name = "mint")]
84    #[account(1, writable, name = "account")]
85    #[account(2, signer, name = "owner")]
86    #[account(3, signer, name = "upstream_authority")]
87    #[account(4, name = "freeze_authority")]
88    #[account(5, name = "token_program", desc = "Token program")]
89    Revoke,
90
91    #[account(0, writable, name = "mint")]
92    #[account(1, signer, name = "upstream_authority")]
93    #[account(2, name = "authority")]
94    #[account(3, name = "new_freeze_authority")]
95    #[account(4, name = "new_mint_authority")]
96    #[account(5, name = "token_program", desc = "Token program")]
97    MigrateAuthority,
98}
99
100pub fn create_initialize_mint_instruction(
101    mint: &Pubkey,
102    payer: &Pubkey,
103    upstream_authority: &Pubkey,
104    decimals: u8,
105) -> Result<Instruction, ProgramError> {
106    Ok(Instruction {
107        program_id: crate::id(),
108        accounts: vec![
109            AccountMeta::new(*mint, true),
110            AccountMeta::new(*payer, true),
111            AccountMeta::new_readonly(*upstream_authority, false),
112            AccountMeta::new_readonly(system_program::id(), false),
113            AccountMeta::new_readonly(spl_token::id(), false),
114        ],
115        data: ManagedTokenInstruction::InitializeMint { decimals }.try_to_vec()?,
116    })
117}
118
119pub fn create_initialize_account_instruction(
120    mint: &Pubkey,
121    owner: &Pubkey,
122    payer: &Pubkey,
123    upstream_authority: &Pubkey,
124) -> Result<Instruction, ProgramError> {
125    let account = get_associated_token_address(owner, mint);
126    let (freeze_authority, _) = get_authority(upstream_authority);
127    Ok(Instruction {
128        program_id: crate::id(),
129        accounts: vec![
130            AccountMeta::new(account, false),
131            AccountMeta::new_readonly(*owner, false),
132            AccountMeta::new(*payer, true),
133            AccountMeta::new_readonly(*upstream_authority, true),
134            AccountMeta::new_readonly(freeze_authority, false),
135            AccountMeta::new_readonly(*mint, false),
136            AccountMeta::new_readonly(system_program::id(), false),
137            AccountMeta::new_readonly(spl_associated_token_account::id(), false),
138            AccountMeta::new_readonly(spl_token::id(), false),
139        ],
140        data: ManagedTokenInstruction::InitializeAccount.try_to_vec()?,
141    })
142}
143
144pub fn create_mint_to_instruction(
145    mint: &Pubkey,
146    owner: &Pubkey,
147    upstream_authority: &Pubkey,
148    amount: u64,
149) -> Result<Instruction, ProgramError> {
150    let account = get_associated_token_address(owner, mint);
151    let (authority, _) = get_authority(upstream_authority);
152    Ok(Instruction {
153        program_id: crate::id(),
154        accounts: vec![
155            AccountMeta::new(*mint, false),
156            AccountMeta::new(account, false),
157            AccountMeta::new_readonly(*upstream_authority, true),
158            AccountMeta::new_readonly(authority, false),
159            AccountMeta::new_readonly(spl_token::id(), false),
160        ],
161        data: ManagedTokenInstruction::MintTo { amount }.try_to_vec()?,
162    })
163}
164
165pub fn create_transfer_instruction(
166    src: &Pubkey,
167    dst: &Pubkey,
168    mint: &Pubkey,
169    upstream_authority: &Pubkey,
170    amount: u64,
171) -> Result<Instruction, ProgramError> {
172    let src_account = get_associated_token_address(src, mint);
173    let dst_account = get_associated_token_address(dst, mint);
174    let (freeze_authority, _) = get_authority(upstream_authority);
175    Ok(Instruction {
176        program_id: crate::id(),
177        accounts: vec![
178            AccountMeta::new(src_account, false),
179            AccountMeta::new(dst_account, false),
180            AccountMeta::new_readonly(*mint, false),
181            AccountMeta::new_readonly(*src, true),
182            AccountMeta::new_readonly(*upstream_authority, true),
183            AccountMeta::new_readonly(freeze_authority, false),
184            AccountMeta::new_readonly(spl_token::id(), false),
185        ],
186        data: ManagedTokenInstruction::Transfer { amount }.try_to_vec()?,
187    })
188}
189
190pub fn create_transfer_with_delegate_instruction(
191    src: &Pubkey,
192    dst: &Pubkey,
193    delegate: &Pubkey,
194    mint: &Pubkey,
195    upstream_authority: &Pubkey,
196    amount: u64,
197) -> Result<Instruction, ProgramError> {
198    let src_account = get_associated_token_address(src, mint);
199    let dst_account = get_associated_token_address(dst, mint);
200    let (freeze_authority, _) = get_authority(upstream_authority);
201    Ok(Instruction {
202        program_id: crate::id(),
203        accounts: vec![
204            AccountMeta::new(src_account, false),
205            AccountMeta::new(dst_account, false),
206            AccountMeta::new_readonly(*mint, false),
207            AccountMeta::new_readonly(*delegate, true),
208            AccountMeta::new_readonly(*upstream_authority, true),
209            AccountMeta::new_readonly(freeze_authority, false),
210            AccountMeta::new_readonly(spl_token::id(), false),
211        ],
212        data: ManagedTokenInstruction::Transfer { amount }.try_to_vec()?,
213    })
214}
215
216pub fn create_burn_instruction(
217    mint: &Pubkey,
218    owner: &Pubkey,
219    upstream_authority: &Pubkey,
220    amount: u64,
221) -> Result<Instruction, ProgramError> {
222    let account = get_associated_token_address(owner, mint);
223    let (freeze_authority, _) = get_authority(upstream_authority);
224    Ok(Instruction {
225        program_id: crate::id(),
226        accounts: vec![
227            AccountMeta::new(*mint, false),
228            AccountMeta::new(account, false),
229            AccountMeta::new_readonly(*owner, true),
230            AccountMeta::new_readonly(*upstream_authority, true),
231            AccountMeta::new_readonly(freeze_authority, false),
232            AccountMeta::new_readonly(spl_token::id(), false),
233        ],
234        data: ManagedTokenInstruction::Burn { amount }.try_to_vec()?,
235    })
236}
237
238pub fn create_close_account_instruction(
239    mint: &Pubkey,
240    owner: &Pubkey,
241    upstream_authority: &Pubkey,
242) -> Result<Instruction, ProgramError> {
243    let account = get_associated_token_address(owner, mint);
244    let (freeze_authority, _) = get_authority(upstream_authority);
245    Ok(Instruction {
246        program_id: crate::id(),
247        accounts: vec![
248            AccountMeta::new(account, false),
249            AccountMeta::new(*owner, false),
250            AccountMeta::new_readonly(*mint, false),
251            AccountMeta::new_readonly(*owner, true),
252            AccountMeta::new_readonly(*upstream_authority, true),
253            AccountMeta::new_readonly(freeze_authority, false),
254            AccountMeta::new_readonly(spl_token::id(), false),
255        ],
256        data: ManagedTokenInstruction::CloseAccount.try_to_vec()?,
257    })
258}
259
260pub fn create_close_account_with_destination_instruction(
261    mint: &Pubkey,
262    owner: &Pubkey,
263    destination: &Pubkey,
264    upstream_authority: &Pubkey,
265) -> Result<Instruction, ProgramError> {
266    let account = get_associated_token_address(owner, mint);
267    let (freeze_authority, _) = get_authority(upstream_authority);
268    Ok(Instruction {
269        program_id: crate::id(),
270        accounts: vec![
271            AccountMeta::new(account, false),
272            AccountMeta::new(*destination, false),
273            AccountMeta::new_readonly(*mint, false),
274            AccountMeta::new_readonly(*owner, true),
275            AccountMeta::new_readonly(*upstream_authority, true),
276            AccountMeta::new_readonly(freeze_authority, false),
277            AccountMeta::new_readonly(spl_token::id(), false),
278        ],
279        data: ManagedTokenInstruction::CloseAccount.try_to_vec()?,
280    })
281}
282
283pub fn create_approve_instruction(
284    mint: &Pubkey,
285    owner: &Pubkey,
286    delegate: &Pubkey,
287    upstream_authority: &Pubkey,
288    amount: u64,
289) -> Result<Instruction, ProgramError> {
290    let (freeze_authority, _) = get_authority(upstream_authority);
291    let account = get_associated_token_address(owner, mint);
292    Ok(Instruction {
293        program_id: crate::id(),
294        accounts: vec![
295            AccountMeta::new_readonly(*mint, false),
296            AccountMeta::new(account, false),
297            AccountMeta::new_readonly(*owner, true),
298            AccountMeta::new_readonly(*upstream_authority, true),
299            AccountMeta::new_readonly(*delegate, false),
300            AccountMeta::new_readonly(freeze_authority, false),
301            AccountMeta::new_readonly(spl_token::id(), false),
302        ],
303        data: ManagedTokenInstruction::Approve { amount }.try_to_vec()?,
304    })
305}
306
307pub fn create_revoke_instruction(
308    mint: &Pubkey,
309    owner: &Pubkey,
310    upstream_authority: &Pubkey,
311) -> Result<Instruction, ProgramError> {
312    let (freeze_authority, _) = get_authority(upstream_authority);
313    let account = get_associated_token_address(owner, mint);
314    Ok(Instruction {
315        program_id: crate::id(),
316        accounts: vec![
317            AccountMeta::new_readonly(*mint, false),
318            AccountMeta::new(account, false),
319            AccountMeta::new_readonly(*owner, true),
320            AccountMeta::new_readonly(*upstream_authority, true),
321            AccountMeta::new_readonly(freeze_authority, false),
322            AccountMeta::new_readonly(spl_token::id(), false),
323        ],
324        data: ManagedTokenInstruction::Revoke.try_to_vec()?,
325    })
326}
327
328pub fn create_migrate_authority_instruction(
329    mint: &Pubkey,
330    upstream_authority: &Pubkey,
331    new_freeze_authority: &Pubkey,
332    new_mint_authority: &Pubkey,
333) -> Result<Instruction, ProgramError> {
334    let (authority, _) = get_authority(upstream_authority);
335    Ok(Instruction {
336        program_id: crate::id(),
337        accounts: vec![
338            AccountMeta::new(*mint, false),
339            AccountMeta::new_readonly(*upstream_authority, true),
340            AccountMeta::new_readonly(authority, false),
341            AccountMeta::new_readonly(*new_freeze_authority, false),
342            AccountMeta::new_readonly(*new_mint_authority, false),
343            AccountMeta::new_readonly(spl_token::id(), false),
344        ],
345        data: ManagedTokenInstruction::MigrateAuthority.try_to_vec()?,
346    })
347}