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
92pub fn create_initialize_mint_instruction(
93 mint: &Pubkey,
94 payer: &Pubkey,
95 upstream_authority: &Pubkey,
96 decimals: u8,
97) -> Result<Instruction, ProgramError> {
98 Ok(Instruction {
99 program_id: crate::id(),
100 accounts: vec![
101 AccountMeta::new(*mint, true),
102 AccountMeta::new(*payer, true),
103 AccountMeta::new_readonly(*upstream_authority, false),
104 AccountMeta::new_readonly(system_program::id(), false),
105 AccountMeta::new_readonly(spl_token::id(), false),
106 ],
107 data: ManagedTokenInstruction::InitializeMint { decimals }.try_to_vec()?,
108 })
109}
110
111pub fn create_initialize_account_instruction(
112 mint: &Pubkey,
113 owner: &Pubkey,
114 payer: &Pubkey,
115 upstream_authority: &Pubkey,
116) -> Result<Instruction, ProgramError> {
117 let account = get_associated_token_address(owner, mint);
118 let (freeze_authority, _) = get_authority(upstream_authority);
119 Ok(Instruction {
120 program_id: crate::id(),
121 accounts: vec![
122 AccountMeta::new(account, false),
123 AccountMeta::new_readonly(*owner, false),
124 AccountMeta::new(*payer, true),
125 AccountMeta::new_readonly(*upstream_authority, true),
126 AccountMeta::new_readonly(freeze_authority, false),
127 AccountMeta::new_readonly(*mint, false),
128 AccountMeta::new_readonly(system_program::id(), false),
129 AccountMeta::new_readonly(spl_associated_token_account::id(), false),
130 AccountMeta::new_readonly(spl_token::id(), false),
131 ],
132 data: ManagedTokenInstruction::InitializeAccount.try_to_vec()?,
133 })
134}
135
136pub fn create_mint_to_instruction(
137 mint: &Pubkey,
138 owner: &Pubkey,
139 upstream_authority: &Pubkey,
140 amount: u64,
141) -> Result<Instruction, ProgramError> {
142 let account = get_associated_token_address(owner, mint);
143 let (authority, _) = get_authority(upstream_authority);
144 Ok(Instruction {
145 program_id: crate::id(),
146 accounts: vec![
147 AccountMeta::new(*mint, false),
148 AccountMeta::new(account, false),
149 AccountMeta::new_readonly(*upstream_authority, true),
150 AccountMeta::new_readonly(authority, false),
151 AccountMeta::new_readonly(spl_token::id(), false),
152 ],
153 data: ManagedTokenInstruction::MintTo { amount }.try_to_vec()?,
154 })
155}
156
157pub fn create_transfer_instruction(
158 src: &Pubkey,
159 dst: &Pubkey,
160 mint: &Pubkey,
161 upstream_authority: &Pubkey,
162 amount: u64,
163) -> Result<Instruction, ProgramError> {
164 let src_account = get_associated_token_address(src, mint);
165 let dst_account = get_associated_token_address(dst, mint);
166 let (freeze_authority, _) = get_authority(upstream_authority);
167 Ok(Instruction {
168 program_id: crate::id(),
169 accounts: vec![
170 AccountMeta::new(src_account, false),
171 AccountMeta::new(dst_account, false),
172 AccountMeta::new_readonly(*mint, false),
173 AccountMeta::new_readonly(*src, true),
174 AccountMeta::new_readonly(*upstream_authority, true),
175 AccountMeta::new_readonly(freeze_authority, false),
176 AccountMeta::new_readonly(spl_token::id(), false),
177 ],
178 data: ManagedTokenInstruction::Transfer { amount }.try_to_vec()?,
179 })
180}
181
182pub fn create_transfer_with_delegate_instruction(
183 src: &Pubkey,
184 dst: &Pubkey,
185 delegate: &Pubkey,
186 mint: &Pubkey,
187 upstream_authority: &Pubkey,
188 amount: u64,
189) -> Result<Instruction, ProgramError> {
190 let src_account = get_associated_token_address(src, mint);
191 let dst_account = get_associated_token_address(dst, mint);
192 let (freeze_authority, _) = get_authority(upstream_authority);
193 Ok(Instruction {
194 program_id: crate::id(),
195 accounts: vec![
196 AccountMeta::new(src_account, false),
197 AccountMeta::new(dst_account, false),
198 AccountMeta::new_readonly(*mint, false),
199 AccountMeta::new_readonly(*delegate, true),
200 AccountMeta::new_readonly(*upstream_authority, true),
201 AccountMeta::new_readonly(freeze_authority, false),
202 AccountMeta::new_readonly(spl_token::id(), false),
203 ],
204 data: ManagedTokenInstruction::Transfer { amount }.try_to_vec()?,
205 })
206}
207
208pub fn create_burn_instruction(
209 mint: &Pubkey,
210 owner: &Pubkey,
211 upstream_authority: &Pubkey,
212 amount: u64,
213) -> Result<Instruction, ProgramError> {
214 let account = get_associated_token_address(owner, mint);
215 let (freeze_authority, _) = get_authority(upstream_authority);
216 Ok(Instruction {
217 program_id: crate::id(),
218 accounts: vec![
219 AccountMeta::new(*mint, false),
220 AccountMeta::new(account, false),
221 AccountMeta::new_readonly(*owner, true),
222 AccountMeta::new_readonly(*upstream_authority, true),
223 AccountMeta::new_readonly(freeze_authority, false),
224 AccountMeta::new_readonly(spl_token::id(), false),
225 ],
226 data: ManagedTokenInstruction::Burn { amount }.try_to_vec()?,
227 })
228}
229
230pub fn create_close_account_instruction(
231 mint: &Pubkey,
232 owner: &Pubkey,
233 upstream_authority: &Pubkey,
234) -> Result<Instruction, ProgramError> {
235 let account = get_associated_token_address(owner, mint);
236 let (freeze_authority, _) = get_authority(upstream_authority);
237 Ok(Instruction {
238 program_id: crate::id(),
239 accounts: vec![
240 AccountMeta::new(account, false),
241 AccountMeta::new(*owner, false),
242 AccountMeta::new_readonly(*mint, false),
243 AccountMeta::new_readonly(*owner, true),
244 AccountMeta::new_readonly(*upstream_authority, true),
245 AccountMeta::new_readonly(freeze_authority, false),
246 AccountMeta::new_readonly(spl_token::id(), false),
247 ],
248 data: ManagedTokenInstruction::CloseAccount.try_to_vec()?,
249 })
250}
251
252pub fn create_approve_instruction(
253 mint: &Pubkey,
254 owner: &Pubkey,
255 delegate: &Pubkey,
256 upstream_authority: &Pubkey,
257 amount: u64,
258) -> Result<Instruction, ProgramError> {
259 let (freeze_authority, _) = get_authority(upstream_authority);
260 let account = get_associated_token_address(owner, mint);
261 Ok(Instruction {
262 program_id: crate::id(),
263 accounts: vec![
264 AccountMeta::new_readonly(*mint, false),
265 AccountMeta::new(account, false),
266 AccountMeta::new_readonly(*owner, true),
267 AccountMeta::new_readonly(*upstream_authority, true),
268 AccountMeta::new_readonly(*delegate, false),
269 AccountMeta::new_readonly(freeze_authority, false),
270 AccountMeta::new_readonly(spl_token::id(), false),
271 ],
272 data: ManagedTokenInstruction::Approve { amount }.try_to_vec()?,
273 })
274}
275
276pub fn create_revoke_instruction(
277 mint: &Pubkey,
278 owner: &Pubkey,
279 upstream_authority: &Pubkey,
280) -> Result<Instruction, ProgramError> {
281 let (freeze_authority, _) = get_authority(upstream_authority);
282 let account = get_associated_token_address(owner, mint);
283 Ok(Instruction {
284 program_id: crate::id(),
285 accounts: vec![
286 AccountMeta::new_readonly(*mint, false),
287 AccountMeta::new(account, false),
288 AccountMeta::new_readonly(*owner, true),
289 AccountMeta::new_readonly(*upstream_authority, true),
290 AccountMeta::new_readonly(freeze_authority, false),
291 AccountMeta::new_readonly(spl_token::id(), false),
292 ],
293 data: ManagedTokenInstruction::Revoke.try_to_vec()?,
294 })
295}