Skip to content
This repository was archived by the owner on Feb 13, 2025. It is now read-only.

Commit 46a18d4

Browse files
committed
Added batch instruction
1 parent f4b8d7e commit 46a18d4

File tree

3 files changed

+134
-0
lines changed

3 files changed

+134
-0
lines changed

program/src/entrypoint.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use batch::process_batch;
12
use pinocchio::{
23
account_info::AccountInfo, default_panic_handler, no_allocator, program_entrypoint,
34
program_error::ProgramError, pubkey::Pubkey, ProgramResult,
@@ -81,6 +82,13 @@ pub fn process_instruction(
8182

8283
process_initialize_mint2(accounts, instruction_data)
8384
}
85+
// 255 - Batch
86+
255 => {
87+
#[cfg(feature = "logging")]
88+
pinocchio::msg!("Instruction: Batch");
89+
90+
process_batch(accounts, instruction_data)
91+
}
8492
_ => process_remaining_instruction(accounts, instruction_data, *discriminator),
8593
}
8694
}

program/src/processor/batch.rs

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
use core::mem::size_of;
2+
use pinocchio::{
3+
account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey, ProgramResult,
4+
};
5+
6+
use crate::processor::{
7+
process_close_account, process_initialize_account3, process_initialize_mint,
8+
process_initialize_mint2, process_mint_to, process_transfer,
9+
};
10+
11+
macro_rules! map_accounts {
12+
// For 1 account
13+
($accounts:expr, $instruction_data:expr, 1) => {{
14+
let (account_idx, rest) = $instruction_data
15+
.split_first()
16+
.ok_or(ProgramError::InvalidInstructionData)?;
17+
*$instruction_data = rest;
18+
let batch_accounts = [$accounts[*account_idx as usize].clone()];
19+
batch_accounts
20+
}};
21+
22+
// For 2 accounts
23+
($accounts:expr, $instruction_data:expr, 2) => {{
24+
let (account_indices, rest) = $instruction_data.split_at(2);
25+
*$instruction_data = rest;
26+
let batch_accounts = [
27+
$accounts[account_indices[0] as usize].clone(),
28+
$accounts[account_indices[1] as usize].clone(),
29+
];
30+
batch_accounts
31+
}};
32+
33+
// For 3 accounts
34+
($accounts:expr, $instruction_data:expr, 3) => {{
35+
let (account_indices, rest) = $instruction_data.split_at(3);
36+
*$instruction_data = rest;
37+
let batch_accounts = [
38+
$accounts[account_indices[0] as usize].clone(),
39+
$accounts[account_indices[1] as usize].clone(),
40+
$accounts[account_indices[2] as usize].clone(),
41+
];
42+
batch_accounts
43+
}};
44+
}
45+
46+
#[inline(always)]
47+
pub fn process_batch(accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResult {
48+
// Validates the instruction data.
49+
let (counter, mut instruction_data) = instruction_data
50+
.split_first()
51+
.ok_or(ProgramError::InvalidInstructionData)?;
52+
53+
let mut discriminator;
54+
for _ in 0..*counter {
55+
(discriminator, instruction_data) = instruction_data
56+
.split_first()
57+
.ok_or(ProgramError::InvalidInstructionData)?;
58+
match discriminator {
59+
// 0 - InitializeMint
60+
0 => {
61+
#[cfg(feature = "logging")]
62+
pinocchio::msg!("Batch Instruction: InitializeMint");
63+
64+
let batch_accounts = map_accounts!(accounts, &mut instruction_data, 2);
65+
process_initialize_mint(&batch_accounts, instruction_data, true)?;
66+
if instruction_data[size_of::<(u8, Pubkey)>()] == 0 {
67+
instruction_data = &instruction_data[size_of::<(u8, Pubkey, u8)>()..];
68+
} else {
69+
instruction_data = &instruction_data[size_of::<(u8, Pubkey, u8, Pubkey)>()..];
70+
}
71+
}
72+
// 3 - Transfer
73+
3 => {
74+
#[cfg(feature = "logging")]
75+
pinocchio::msg!("Batch Instruction: Transfer");
76+
77+
let batch_accounts = map_accounts!(accounts, &mut instruction_data, 3);
78+
process_transfer(&batch_accounts, instruction_data)?;
79+
instruction_data = &instruction_data[size_of::<u64>()..];
80+
}
81+
// 7 - MintTo
82+
7 => {
83+
#[cfg(feature = "logging")]
84+
pinocchio::msg!("Batch Instruction: MintTo");
85+
86+
let batch_accounts = map_accounts!(accounts, &mut instruction_data, 3);
87+
process_mint_to(&batch_accounts, instruction_data)?;
88+
instruction_data = &instruction_data[size_of::<u64>()..];
89+
}
90+
// 9 - CloseAccount
91+
9 => {
92+
#[cfg(feature = "logging")]
93+
pinocchio::msg!("Batch Instruction: CloseAccount");
94+
95+
let batch_accounts = map_accounts!(accounts, &mut instruction_data, 2);
96+
process_close_account(&batch_accounts)?;
97+
}
98+
18 => {
99+
#[cfg(feature = "logging")]
100+
pinocchio::msg!("Batch Instruction: InitializeAccount3");
101+
102+
let batch_accounts = map_accounts!(accounts, &mut instruction_data, 3);
103+
process_initialize_account3(&batch_accounts, instruction_data)?;
104+
instruction_data = &instruction_data[size_of::<Pubkey>()..];
105+
}
106+
// 20 - InitializeMint2
107+
20 => {
108+
#[cfg(feature = "logging")]
109+
pinocchio::msg!("Instruction: InitializeMint2");
110+
111+
let batch_accounts = map_accounts!(accounts, &mut instruction_data, 1);
112+
process_initialize_mint2(&batch_accounts, instruction_data)?;
113+
if instruction_data[size_of::<(u8, Pubkey)>()] == 0 {
114+
instruction_data = &instruction_data[size_of::<(u8, Pubkey, u8)>()..];
115+
} else {
116+
instruction_data = &instruction_data[size_of::<(u8, Pubkey, u8, Pubkey)>()..];
117+
}
118+
}
119+
_ => {
120+
return Err(ProgramError::InvalidInstructionData);
121+
}
122+
}
123+
}
124+
Ok(())
125+
}

program/src/processor/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use token_interface::{
2121
pub mod amount_to_ui_amount;
2222
pub mod approve;
2323
pub mod approve_checked;
24+
pub mod batch;
2425
pub mod burn;
2526
pub mod burn_checked;
2627
pub mod close_account;

0 commit comments

Comments
 (0)