1use borsh::BorshDeserialize;
9use borsh::BorshSerialize;
10use solana_program::pubkey::Pubkey;
11
12pub struct CreateAccount {
14 pub from: solana_program::pubkey::Pubkey,
16 pub to: solana_program::pubkey::Pubkey,
18 pub base: Option<solana_program::pubkey::Pubkey>,
20 pub system_program: solana_program::pubkey::Pubkey,
22}
23
24impl CreateAccount {
25 pub fn instruction(
26 &self,
27 args: CreateAccountInstructionArgs,
28 ) -> solana_program::instruction::Instruction {
29 self.instruction_with_remaining_accounts(args, &[])
30 }
31 #[allow(clippy::vec_init_then_push)]
32 pub fn instruction_with_remaining_accounts(
33 &self,
34 args: CreateAccountInstructionArgs,
35 remaining_accounts: &[solana_program::instruction::AccountMeta],
36 ) -> solana_program::instruction::Instruction {
37 let mut accounts = Vec::with_capacity(4 + remaining_accounts.len());
38 accounts.push(solana_program::instruction::AccountMeta::new(
39 self.from, true,
40 ));
41 accounts.push(solana_program::instruction::AccountMeta::new(
42 self.to, false,
43 ));
44 if let Some(base) = self.base {
45 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
46 base, false,
47 ));
48 } else {
49 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
50 crate::LIMESTONE_ID,
51 false,
52 ));
53 }
54 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
55 self.system_program,
56 false,
57 ));
58 accounts.extend_from_slice(remaining_accounts);
59 let mut data = CreateAccountInstructionData::new().try_to_vec().unwrap();
60 let mut args = args.try_to_vec().unwrap();
61 data.append(&mut args);
62
63 solana_program::instruction::Instruction {
64 program_id: crate::LIMESTONE_ID,
65 accounts,
66 data,
67 }
68 }
69}
70
71#[derive(BorshDeserialize, BorshSerialize)]
72pub struct CreateAccountInstructionData {
73 discriminator: u8,
74}
75
76impl CreateAccountInstructionData {
77 pub fn new() -> Self {
78 Self { discriminator: 0 }
79 }
80}
81
82impl Default for CreateAccountInstructionData {
83 fn default() -> Self {
84 Self::new()
85 }
86}
87
88#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)]
89#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
90pub struct CreateAccountInstructionArgs {
91 pub slot: u64,
92 pub lamports: u64,
93 pub space: u64,
94 pub owner: Pubkey,
95}
96
97#[derive(Clone, Debug, Default)]
106pub struct CreateAccountBuilder {
107 from: Option<solana_program::pubkey::Pubkey>,
108 to: Option<solana_program::pubkey::Pubkey>,
109 base: Option<solana_program::pubkey::Pubkey>,
110 system_program: Option<solana_program::pubkey::Pubkey>,
111 slot: Option<u64>,
112 lamports: Option<u64>,
113 space: Option<u64>,
114 owner: Option<Pubkey>,
115 __remaining_accounts: Vec<solana_program::instruction::AccountMeta>,
116}
117
118impl CreateAccountBuilder {
119 pub fn new() -> Self {
120 Self::default()
121 }
122 #[inline(always)]
124 pub fn from(&mut self, from: solana_program::pubkey::Pubkey) -> &mut Self {
125 self.from = Some(from);
126 self
127 }
128 #[inline(always)]
130 pub fn to(&mut self, to: solana_program::pubkey::Pubkey) -> &mut Self {
131 self.to = Some(to);
132 self
133 }
134 #[inline(always)]
137 pub fn base(&mut self, base: Option<solana_program::pubkey::Pubkey>) -> &mut Self {
138 self.base = base;
139 self
140 }
141 #[inline(always)]
144 pub fn system_program(&mut self, system_program: solana_program::pubkey::Pubkey) -> &mut Self {
145 self.system_program = Some(system_program);
146 self
147 }
148 #[inline(always)]
149 pub fn slot(&mut self, slot: u64) -> &mut Self {
150 self.slot = Some(slot);
151 self
152 }
153 #[inline(always)]
154 pub fn lamports(&mut self, lamports: u64) -> &mut Self {
155 self.lamports = Some(lamports);
156 self
157 }
158 #[inline(always)]
159 pub fn space(&mut self, space: u64) -> &mut Self {
160 self.space = Some(space);
161 self
162 }
163 #[inline(always)]
164 pub fn owner(&mut self, owner: Pubkey) -> &mut Self {
165 self.owner = Some(owner);
166 self
167 }
168 #[inline(always)]
170 pub fn add_remaining_account(
171 &mut self,
172 account: solana_program::instruction::AccountMeta,
173 ) -> &mut Self {
174 self.__remaining_accounts.push(account);
175 self
176 }
177 #[inline(always)]
179 pub fn add_remaining_accounts(
180 &mut self,
181 accounts: &[solana_program::instruction::AccountMeta],
182 ) -> &mut Self {
183 self.__remaining_accounts.extend_from_slice(accounts);
184 self
185 }
186 #[allow(clippy::clone_on_copy)]
187 pub fn instruction(&self) -> solana_program::instruction::Instruction {
188 let accounts = CreateAccount {
189 from: self.from.expect("from is not set"),
190 to: self.to.expect("to is not set"),
191 base: self.base,
192 system_program: self
193 .system_program
194 .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")),
195 };
196 let args = CreateAccountInstructionArgs {
197 slot: self.slot.clone().expect("slot is not set"),
198 lamports: self.lamports.clone().expect("lamports is not set"),
199 space: self.space.clone().expect("space is not set"),
200 owner: self.owner.clone().expect("owner is not set"),
201 };
202
203 accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts)
204 }
205}
206
207pub struct CreateAccountCpiAccounts<'a, 'b> {
209 pub from: &'b solana_program::account_info::AccountInfo<'a>,
211 pub to: &'b solana_program::account_info::AccountInfo<'a>,
213 pub base: Option<&'b solana_program::account_info::AccountInfo<'a>>,
215 pub system_program: &'b solana_program::account_info::AccountInfo<'a>,
217}
218
219pub struct CreateAccountCpi<'a, 'b> {
221 pub __program: &'b solana_program::account_info::AccountInfo<'a>,
223 pub from: &'b solana_program::account_info::AccountInfo<'a>,
225 pub to: &'b solana_program::account_info::AccountInfo<'a>,
227 pub base: Option<&'b solana_program::account_info::AccountInfo<'a>>,
229 pub system_program: &'b solana_program::account_info::AccountInfo<'a>,
231 pub __args: CreateAccountInstructionArgs,
233}
234
235impl<'a, 'b> CreateAccountCpi<'a, 'b> {
236 pub fn new(
237 program: &'b solana_program::account_info::AccountInfo<'a>,
238 accounts: CreateAccountCpiAccounts<'a, 'b>,
239 args: CreateAccountInstructionArgs,
240 ) -> Self {
241 Self {
242 __program: program,
243 from: accounts.from,
244 to: accounts.to,
245 base: accounts.base,
246 system_program: accounts.system_program,
247 __args: args,
248 }
249 }
250 #[inline(always)]
251 pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult {
252 self.invoke_signed_with_remaining_accounts(&[], &[])
253 }
254 #[inline(always)]
255 pub fn invoke_with_remaining_accounts(
256 &self,
257 remaining_accounts: &[(
258 &'b solana_program::account_info::AccountInfo<'a>,
259 bool,
260 bool,
261 )],
262 ) -> solana_program::entrypoint::ProgramResult {
263 self.invoke_signed_with_remaining_accounts(&[], remaining_accounts)
264 }
265 #[inline(always)]
266 pub fn invoke_signed(
267 &self,
268 signers_seeds: &[&[&[u8]]],
269 ) -> solana_program::entrypoint::ProgramResult {
270 self.invoke_signed_with_remaining_accounts(signers_seeds, &[])
271 }
272 #[allow(clippy::clone_on_copy)]
273 #[allow(clippy::vec_init_then_push)]
274 pub fn invoke_signed_with_remaining_accounts(
275 &self,
276 signers_seeds: &[&[&[u8]]],
277 remaining_accounts: &[(
278 &'b solana_program::account_info::AccountInfo<'a>,
279 bool,
280 bool,
281 )],
282 ) -> solana_program::entrypoint::ProgramResult {
283 let mut accounts = Vec::with_capacity(4 + remaining_accounts.len());
284 accounts.push(solana_program::instruction::AccountMeta::new(
285 *self.from.key,
286 true,
287 ));
288 accounts.push(solana_program::instruction::AccountMeta::new(
289 *self.to.key,
290 false,
291 ));
292 if let Some(base) = self.base {
293 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
294 *base.key, false,
295 ));
296 } else {
297 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
298 crate::LIMESTONE_ID,
299 false,
300 ));
301 }
302 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
303 *self.system_program.key,
304 false,
305 ));
306 remaining_accounts.iter().for_each(|remaining_account| {
307 accounts.push(solana_program::instruction::AccountMeta {
308 pubkey: *remaining_account.0.key,
309 is_signer: remaining_account.1,
310 is_writable: remaining_account.2,
311 })
312 });
313 let mut data = CreateAccountInstructionData::new().try_to_vec().unwrap();
314 let mut args = self.__args.try_to_vec().unwrap();
315 data.append(&mut args);
316
317 let instruction = solana_program::instruction::Instruction {
318 program_id: crate::LIMESTONE_ID,
319 accounts,
320 data,
321 };
322 let mut account_infos = Vec::with_capacity(4 + 1 + remaining_accounts.len());
323 account_infos.push(self.__program.clone());
324 account_infos.push(self.from.clone());
325 account_infos.push(self.to.clone());
326 if let Some(base) = self.base {
327 account_infos.push(base.clone());
328 }
329 account_infos.push(self.system_program.clone());
330 remaining_accounts
331 .iter()
332 .for_each(|remaining_account| account_infos.push(remaining_account.0.clone()));
333
334 if signers_seeds.is_empty() {
335 solana_program::program::invoke(&instruction, &account_infos)
336 } else {
337 solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds)
338 }
339 }
340}
341
342#[derive(Clone, Debug)]
351pub struct CreateAccountCpiBuilder<'a, 'b> {
352 instruction: Box<CreateAccountCpiBuilderInstruction<'a, 'b>>,
353}
354
355impl<'a, 'b> CreateAccountCpiBuilder<'a, 'b> {
356 pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self {
357 let instruction = Box::new(CreateAccountCpiBuilderInstruction {
358 __program: program,
359 from: None,
360 to: None,
361 base: None,
362 system_program: None,
363 slot: None,
364 lamports: None,
365 space: None,
366 owner: None,
367 __remaining_accounts: Vec::new(),
368 });
369 Self { instruction }
370 }
371 #[inline(always)]
373 pub fn from(&mut self, from: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self {
374 self.instruction.from = Some(from);
375 self
376 }
377 #[inline(always)]
379 pub fn to(&mut self, to: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self {
380 self.instruction.to = Some(to);
381 self
382 }
383 #[inline(always)]
386 pub fn base(
387 &mut self,
388 base: Option<&'b solana_program::account_info::AccountInfo<'a>>,
389 ) -> &mut Self {
390 self.instruction.base = base;
391 self
392 }
393 #[inline(always)]
395 pub fn system_program(
396 &mut self,
397 system_program: &'b solana_program::account_info::AccountInfo<'a>,
398 ) -> &mut Self {
399 self.instruction.system_program = Some(system_program);
400 self
401 }
402 #[inline(always)]
403 pub fn slot(&mut self, slot: u64) -> &mut Self {
404 self.instruction.slot = Some(slot);
405 self
406 }
407 #[inline(always)]
408 pub fn lamports(&mut self, lamports: u64) -> &mut Self {
409 self.instruction.lamports = Some(lamports);
410 self
411 }
412 #[inline(always)]
413 pub fn space(&mut self, space: u64) -> &mut Self {
414 self.instruction.space = Some(space);
415 self
416 }
417 #[inline(always)]
418 pub fn owner(&mut self, owner: Pubkey) -> &mut Self {
419 self.instruction.owner = Some(owner);
420 self
421 }
422 #[inline(always)]
424 pub fn add_remaining_account(
425 &mut self,
426 account: &'b solana_program::account_info::AccountInfo<'a>,
427 is_writable: bool,
428 is_signer: bool,
429 ) -> &mut Self {
430 self.instruction
431 .__remaining_accounts
432 .push((account, is_writable, is_signer));
433 self
434 }
435 #[inline(always)]
440 pub fn add_remaining_accounts(
441 &mut self,
442 accounts: &[(
443 &'b solana_program::account_info::AccountInfo<'a>,
444 bool,
445 bool,
446 )],
447 ) -> &mut Self {
448 self.instruction
449 .__remaining_accounts
450 .extend_from_slice(accounts);
451 self
452 }
453 #[inline(always)]
454 pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult {
455 self.invoke_signed(&[])
456 }
457 #[allow(clippy::clone_on_copy)]
458 #[allow(clippy::vec_init_then_push)]
459 pub fn invoke_signed(
460 &self,
461 signers_seeds: &[&[&[u8]]],
462 ) -> solana_program::entrypoint::ProgramResult {
463 let args = CreateAccountInstructionArgs {
464 slot: self.instruction.slot.clone().expect("slot is not set"),
465 lamports: self
466 .instruction
467 .lamports
468 .clone()
469 .expect("lamports is not set"),
470 space: self.instruction.space.clone().expect("space is not set"),
471 owner: self.instruction.owner.clone().expect("owner is not set"),
472 };
473 let instruction = CreateAccountCpi {
474 __program: self.instruction.__program,
475
476 from: self.instruction.from.expect("from is not set"),
477
478 to: self.instruction.to.expect("to is not set"),
479
480 base: self.instruction.base,
481
482 system_program: self
483 .instruction
484 .system_program
485 .expect("system_program is not set"),
486 __args: args,
487 };
488 instruction.invoke_signed_with_remaining_accounts(
489 signers_seeds,
490 &self.instruction.__remaining_accounts,
491 )
492 }
493}
494
495#[derive(Clone, Debug)]
496struct CreateAccountCpiBuilderInstruction<'a, 'b> {
497 __program: &'b solana_program::account_info::AccountInfo<'a>,
498 from: Option<&'b solana_program::account_info::AccountInfo<'a>>,
499 to: Option<&'b solana_program::account_info::AccountInfo<'a>>,
500 base: Option<&'b solana_program::account_info::AccountInfo<'a>>,
501 system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>,
502 slot: Option<u64>,
503 lamports: Option<u64>,
504 space: Option<u64>,
505 owner: Option<Pubkey>,
506 __remaining_accounts: Vec<(
508 &'b solana_program::account_info::AccountInfo<'a>,
509 bool,
510 bool,
511 )>,
512}