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