1use borsh::{BorshDeserialize, BorshSerialize};
8
9pub struct CreateTokenMetadata {
11 pub vault: solana_program::pubkey::Pubkey,
12
13 pub admin: solana_program::pubkey::Pubkey,
14
15 pub vrt_mint: solana_program::pubkey::Pubkey,
16
17 pub payer: solana_program::pubkey::Pubkey,
18
19 pub metadata: solana_program::pubkey::Pubkey,
20
21 pub mpl_token_metadata_program: solana_program::pubkey::Pubkey,
22
23 pub system_program: solana_program::pubkey::Pubkey,
24}
25
26impl CreateTokenMetadata {
27 pub fn instruction(
28 &self,
29 args: CreateTokenMetadataInstructionArgs,
30 ) -> solana_program::instruction::Instruction {
31 self.instruction_with_remaining_accounts(args, &[])
32 }
33 #[allow(clippy::vec_init_then_push)]
34 pub fn instruction_with_remaining_accounts(
35 &self,
36 args: CreateTokenMetadataInstructionArgs,
37 remaining_accounts: &[solana_program::instruction::AccountMeta],
38 ) -> solana_program::instruction::Instruction {
39 let mut accounts = Vec::with_capacity(7 + remaining_accounts.len());
40 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
41 self.vault, false,
42 ));
43 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
44 self.admin, true,
45 ));
46 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
47 self.vrt_mint,
48 false,
49 ));
50 accounts.push(solana_program::instruction::AccountMeta::new(
51 self.payer, true,
52 ));
53 accounts.push(solana_program::instruction::AccountMeta::new(
54 self.metadata,
55 false,
56 ));
57 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
58 self.mpl_token_metadata_program,
59 false,
60 ));
61 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
62 self.system_program,
63 false,
64 ));
65 accounts.extend_from_slice(remaining_accounts);
66 let mut data = CreateTokenMetadataInstructionData::new()
67 .try_to_vec()
68 .unwrap();
69 let mut args = args.try_to_vec().unwrap();
70 data.append(&mut args);
71
72 solana_program::instruction::Instruction {
73 program_id: crate::JITO_VAULT_ID,
74 accounts,
75 data,
76 }
77 }
78}
79
80#[derive(BorshDeserialize, BorshSerialize)]
81pub struct CreateTokenMetadataInstructionData {
82 discriminator: u8,
83}
84
85impl CreateTokenMetadataInstructionData {
86 pub fn new() -> Self {
87 Self { discriminator: 29 }
88 }
89}
90
91impl Default for CreateTokenMetadataInstructionData {
92 fn default() -> Self {
93 Self::new()
94 }
95}
96
97#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)]
98#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
99pub struct CreateTokenMetadataInstructionArgs {
100 pub name: String,
101 pub symbol: String,
102 pub uri: String,
103}
104
105#[derive(Clone, Debug, Default)]
117pub struct CreateTokenMetadataBuilder {
118 vault: Option<solana_program::pubkey::Pubkey>,
119 admin: Option<solana_program::pubkey::Pubkey>,
120 vrt_mint: Option<solana_program::pubkey::Pubkey>,
121 payer: Option<solana_program::pubkey::Pubkey>,
122 metadata: Option<solana_program::pubkey::Pubkey>,
123 mpl_token_metadata_program: Option<solana_program::pubkey::Pubkey>,
124 system_program: Option<solana_program::pubkey::Pubkey>,
125 name: Option<String>,
126 symbol: Option<String>,
127 uri: Option<String>,
128 __remaining_accounts: Vec<solana_program::instruction::AccountMeta>,
129}
130
131impl CreateTokenMetadataBuilder {
132 pub fn new() -> Self {
133 Self::default()
134 }
135 #[inline(always)]
136 pub fn vault(&mut self, vault: solana_program::pubkey::Pubkey) -> &mut Self {
137 self.vault = Some(vault);
138 self
139 }
140 #[inline(always)]
141 pub fn admin(&mut self, admin: solana_program::pubkey::Pubkey) -> &mut Self {
142 self.admin = Some(admin);
143 self
144 }
145 #[inline(always)]
146 pub fn vrt_mint(&mut self, vrt_mint: solana_program::pubkey::Pubkey) -> &mut Self {
147 self.vrt_mint = Some(vrt_mint);
148 self
149 }
150 #[inline(always)]
151 pub fn payer(&mut self, payer: solana_program::pubkey::Pubkey) -> &mut Self {
152 self.payer = Some(payer);
153 self
154 }
155 #[inline(always)]
156 pub fn metadata(&mut self, metadata: solana_program::pubkey::Pubkey) -> &mut Self {
157 self.metadata = Some(metadata);
158 self
159 }
160 #[inline(always)]
162 pub fn mpl_token_metadata_program(
163 &mut self,
164 mpl_token_metadata_program: solana_program::pubkey::Pubkey,
165 ) -> &mut Self {
166 self.mpl_token_metadata_program = Some(mpl_token_metadata_program);
167 self
168 }
169 #[inline(always)]
171 pub fn system_program(&mut self, system_program: solana_program::pubkey::Pubkey) -> &mut Self {
172 self.system_program = Some(system_program);
173 self
174 }
175 #[inline(always)]
176 pub fn name(&mut self, name: String) -> &mut Self {
177 self.name = Some(name);
178 self
179 }
180 #[inline(always)]
181 pub fn symbol(&mut self, symbol: String) -> &mut Self {
182 self.symbol = Some(symbol);
183 self
184 }
185 #[inline(always)]
186 pub fn uri(&mut self, uri: String) -> &mut Self {
187 self.uri = Some(uri);
188 self
189 }
190 #[inline(always)]
192 pub fn add_remaining_account(
193 &mut self,
194 account: solana_program::instruction::AccountMeta,
195 ) -> &mut Self {
196 self.__remaining_accounts.push(account);
197 self
198 }
199 #[inline(always)]
201 pub fn add_remaining_accounts(
202 &mut self,
203 accounts: &[solana_program::instruction::AccountMeta],
204 ) -> &mut Self {
205 self.__remaining_accounts.extend_from_slice(accounts);
206 self
207 }
208 #[allow(clippy::clone_on_copy)]
209 pub fn instruction(&self) -> solana_program::instruction::Instruction {
210 let accounts = CreateTokenMetadata {
211 vault: self.vault.expect("vault is not set"),
212 admin: self.admin.expect("admin is not set"),
213 vrt_mint: self.vrt_mint.expect("vrt_mint is not set"),
214 payer: self.payer.expect("payer is not set"),
215 metadata: self.metadata.expect("metadata is not set"),
216 mpl_token_metadata_program: self.mpl_token_metadata_program.unwrap_or(
217 solana_program::pubkey!("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"),
218 ),
219 system_program: self
220 .system_program
221 .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")),
222 };
223 let args = CreateTokenMetadataInstructionArgs {
224 name: self.name.clone().expect("name is not set"),
225 symbol: self.symbol.clone().expect("symbol is not set"),
226 uri: self.uri.clone().expect("uri is not set"),
227 };
228
229 accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts)
230 }
231}
232
233pub struct CreateTokenMetadataCpiAccounts<'a, 'b> {
235 pub vault: &'b solana_program::account_info::AccountInfo<'a>,
236
237 pub admin: &'b solana_program::account_info::AccountInfo<'a>,
238
239 pub vrt_mint: &'b solana_program::account_info::AccountInfo<'a>,
240
241 pub payer: &'b solana_program::account_info::AccountInfo<'a>,
242
243 pub metadata: &'b solana_program::account_info::AccountInfo<'a>,
244
245 pub mpl_token_metadata_program: &'b solana_program::account_info::AccountInfo<'a>,
246
247 pub system_program: &'b solana_program::account_info::AccountInfo<'a>,
248}
249
250pub struct CreateTokenMetadataCpi<'a, 'b> {
252 pub __program: &'b solana_program::account_info::AccountInfo<'a>,
254
255 pub vault: &'b solana_program::account_info::AccountInfo<'a>,
256
257 pub admin: &'b solana_program::account_info::AccountInfo<'a>,
258
259 pub vrt_mint: &'b solana_program::account_info::AccountInfo<'a>,
260
261 pub payer: &'b solana_program::account_info::AccountInfo<'a>,
262
263 pub metadata: &'b solana_program::account_info::AccountInfo<'a>,
264
265 pub mpl_token_metadata_program: &'b solana_program::account_info::AccountInfo<'a>,
266
267 pub system_program: &'b solana_program::account_info::AccountInfo<'a>,
268 pub __args: CreateTokenMetadataInstructionArgs,
270}
271
272impl<'a, 'b> CreateTokenMetadataCpi<'a, 'b> {
273 pub fn new(
274 program: &'b solana_program::account_info::AccountInfo<'a>,
275 accounts: CreateTokenMetadataCpiAccounts<'a, 'b>,
276 args: CreateTokenMetadataInstructionArgs,
277 ) -> Self {
278 Self {
279 __program: program,
280 vault: accounts.vault,
281 admin: accounts.admin,
282 vrt_mint: accounts.vrt_mint,
283 payer: accounts.payer,
284 metadata: accounts.metadata,
285 mpl_token_metadata_program: accounts.mpl_token_metadata_program,
286 system_program: accounts.system_program,
287 __args: args,
288 }
289 }
290 #[inline(always)]
291 pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult {
292 self.invoke_signed_with_remaining_accounts(&[], &[])
293 }
294 #[inline(always)]
295 pub fn invoke_with_remaining_accounts(
296 &self,
297 remaining_accounts: &[(
298 &'b solana_program::account_info::AccountInfo<'a>,
299 bool,
300 bool,
301 )],
302 ) -> solana_program::entrypoint::ProgramResult {
303 self.invoke_signed_with_remaining_accounts(&[], remaining_accounts)
304 }
305 #[inline(always)]
306 pub fn invoke_signed(
307 &self,
308 signers_seeds: &[&[&[u8]]],
309 ) -> solana_program::entrypoint::ProgramResult {
310 self.invoke_signed_with_remaining_accounts(signers_seeds, &[])
311 }
312 #[allow(clippy::clone_on_copy)]
313 #[allow(clippy::vec_init_then_push)]
314 pub fn invoke_signed_with_remaining_accounts(
315 &self,
316 signers_seeds: &[&[&[u8]]],
317 remaining_accounts: &[(
318 &'b solana_program::account_info::AccountInfo<'a>,
319 bool,
320 bool,
321 )],
322 ) -> solana_program::entrypoint::ProgramResult {
323 let mut accounts = Vec::with_capacity(7 + remaining_accounts.len());
324 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
325 *self.vault.key,
326 false,
327 ));
328 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
329 *self.admin.key,
330 true,
331 ));
332 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
333 *self.vrt_mint.key,
334 false,
335 ));
336 accounts.push(solana_program::instruction::AccountMeta::new(
337 *self.payer.key,
338 true,
339 ));
340 accounts.push(solana_program::instruction::AccountMeta::new(
341 *self.metadata.key,
342 false,
343 ));
344 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
345 *self.mpl_token_metadata_program.key,
346 false,
347 ));
348 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
349 *self.system_program.key,
350 false,
351 ));
352 remaining_accounts.iter().for_each(|remaining_account| {
353 accounts.push(solana_program::instruction::AccountMeta {
354 pubkey: *remaining_account.0.key,
355 is_signer: remaining_account.1,
356 is_writable: remaining_account.2,
357 })
358 });
359 let mut data = CreateTokenMetadataInstructionData::new()
360 .try_to_vec()
361 .unwrap();
362 let mut args = self.__args.try_to_vec().unwrap();
363 data.append(&mut args);
364
365 let instruction = solana_program::instruction::Instruction {
366 program_id: crate::JITO_VAULT_ID,
367 accounts,
368 data,
369 };
370 let mut account_infos = Vec::with_capacity(7 + 1 + remaining_accounts.len());
371 account_infos.push(self.__program.clone());
372 account_infos.push(self.vault.clone());
373 account_infos.push(self.admin.clone());
374 account_infos.push(self.vrt_mint.clone());
375 account_infos.push(self.payer.clone());
376 account_infos.push(self.metadata.clone());
377 account_infos.push(self.mpl_token_metadata_program.clone());
378 account_infos.push(self.system_program.clone());
379 remaining_accounts
380 .iter()
381 .for_each(|remaining_account| account_infos.push(remaining_account.0.clone()));
382
383 if signers_seeds.is_empty() {
384 solana_program::program::invoke(&instruction, &account_infos)
385 } else {
386 solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds)
387 }
388 }
389}
390
391#[derive(Clone, Debug)]
403pub struct CreateTokenMetadataCpiBuilder<'a, 'b> {
404 instruction: Box<CreateTokenMetadataCpiBuilderInstruction<'a, 'b>>,
405}
406
407impl<'a, 'b> CreateTokenMetadataCpiBuilder<'a, 'b> {
408 pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self {
409 let instruction = Box::new(CreateTokenMetadataCpiBuilderInstruction {
410 __program: program,
411 vault: None,
412 admin: None,
413 vrt_mint: None,
414 payer: None,
415 metadata: None,
416 mpl_token_metadata_program: None,
417 system_program: None,
418 name: None,
419 symbol: None,
420 uri: None,
421 __remaining_accounts: Vec::new(),
422 });
423 Self { instruction }
424 }
425 #[inline(always)]
426 pub fn vault(&mut self, vault: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self {
427 self.instruction.vault = Some(vault);
428 self
429 }
430 #[inline(always)]
431 pub fn admin(&mut self, admin: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self {
432 self.instruction.admin = Some(admin);
433 self
434 }
435 #[inline(always)]
436 pub fn vrt_mint(
437 &mut self,
438 vrt_mint: &'b solana_program::account_info::AccountInfo<'a>,
439 ) -> &mut Self {
440 self.instruction.vrt_mint = Some(vrt_mint);
441 self
442 }
443 #[inline(always)]
444 pub fn payer(&mut self, payer: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self {
445 self.instruction.payer = Some(payer);
446 self
447 }
448 #[inline(always)]
449 pub fn metadata(
450 &mut self,
451 metadata: &'b solana_program::account_info::AccountInfo<'a>,
452 ) -> &mut Self {
453 self.instruction.metadata = Some(metadata);
454 self
455 }
456 #[inline(always)]
457 pub fn mpl_token_metadata_program(
458 &mut self,
459 mpl_token_metadata_program: &'b solana_program::account_info::AccountInfo<'a>,
460 ) -> &mut Self {
461 self.instruction.mpl_token_metadata_program = Some(mpl_token_metadata_program);
462 self
463 }
464 #[inline(always)]
465 pub fn system_program(
466 &mut self,
467 system_program: &'b solana_program::account_info::AccountInfo<'a>,
468 ) -> &mut Self {
469 self.instruction.system_program = Some(system_program);
470 self
471 }
472 #[inline(always)]
473 pub fn name(&mut self, name: String) -> &mut Self {
474 self.instruction.name = Some(name);
475 self
476 }
477 #[inline(always)]
478 pub fn symbol(&mut self, symbol: String) -> &mut Self {
479 self.instruction.symbol = Some(symbol);
480 self
481 }
482 #[inline(always)]
483 pub fn uri(&mut self, uri: String) -> &mut Self {
484 self.instruction.uri = Some(uri);
485 self
486 }
487 #[inline(always)]
489 pub fn add_remaining_account(
490 &mut self,
491 account: &'b solana_program::account_info::AccountInfo<'a>,
492 is_writable: bool,
493 is_signer: bool,
494 ) -> &mut Self {
495 self.instruction
496 .__remaining_accounts
497 .push((account, is_writable, is_signer));
498 self
499 }
500 #[inline(always)]
505 pub fn add_remaining_accounts(
506 &mut self,
507 accounts: &[(
508 &'b solana_program::account_info::AccountInfo<'a>,
509 bool,
510 bool,
511 )],
512 ) -> &mut Self {
513 self.instruction
514 .__remaining_accounts
515 .extend_from_slice(accounts);
516 self
517 }
518 #[inline(always)]
519 pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult {
520 self.invoke_signed(&[])
521 }
522 #[allow(clippy::clone_on_copy)]
523 #[allow(clippy::vec_init_then_push)]
524 pub fn invoke_signed(
525 &self,
526 signers_seeds: &[&[&[u8]]],
527 ) -> solana_program::entrypoint::ProgramResult {
528 let args = CreateTokenMetadataInstructionArgs {
529 name: self.instruction.name.clone().expect("name is not set"),
530 symbol: self.instruction.symbol.clone().expect("symbol is not set"),
531 uri: self.instruction.uri.clone().expect("uri is not set"),
532 };
533 let instruction = CreateTokenMetadataCpi {
534 __program: self.instruction.__program,
535
536 vault: self.instruction.vault.expect("vault is not set"),
537
538 admin: self.instruction.admin.expect("admin is not set"),
539
540 vrt_mint: self.instruction.vrt_mint.expect("vrt_mint is not set"),
541
542 payer: self.instruction.payer.expect("payer is not set"),
543
544 metadata: self.instruction.metadata.expect("metadata is not set"),
545
546 mpl_token_metadata_program: self
547 .instruction
548 .mpl_token_metadata_program
549 .expect("mpl_token_metadata_program is not set"),
550
551 system_program: self
552 .instruction
553 .system_program
554 .expect("system_program is not set"),
555 __args: args,
556 };
557 instruction.invoke_signed_with_remaining_accounts(
558 signers_seeds,
559 &self.instruction.__remaining_accounts,
560 )
561 }
562}
563
564#[derive(Clone, Debug)]
565struct CreateTokenMetadataCpiBuilderInstruction<'a, 'b> {
566 __program: &'b solana_program::account_info::AccountInfo<'a>,
567 vault: Option<&'b solana_program::account_info::AccountInfo<'a>>,
568 admin: Option<&'b solana_program::account_info::AccountInfo<'a>>,
569 vrt_mint: Option<&'b solana_program::account_info::AccountInfo<'a>>,
570 payer: Option<&'b solana_program::account_info::AccountInfo<'a>>,
571 metadata: Option<&'b solana_program::account_info::AccountInfo<'a>>,
572 mpl_token_metadata_program: Option<&'b solana_program::account_info::AccountInfo<'a>>,
573 system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>,
574 name: Option<String>,
575 symbol: Option<String>,
576 uri: Option<String>,
577 __remaining_accounts: Vec<(
579 &'b solana_program::account_info::AccountInfo<'a>,
580 bool,
581 bool,
582 )>,
583}