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}