1#![no_std]
7#![deny(unsafe_op_in_unsafe_fn)]
8
9use hopper_runtime::instruction::{InstructionAccount, InstructionView, Signer};
10use hopper_runtime::{AccountView, ProgramResult};
11
12pub use hopper_solana::constants::ATA_PROGRAM_ID;
13
14#[cfg(target_os = "solana")]
15pub use hopper_solana::ata::{
16 derive_ata, derive_ata_2022, derive_ata_for_program, verify_ata, verify_ata_2022,
17 verify_ata_any,
18};
19
20pub struct Create<'a> {
22 pub payer: &'a AccountView,
23 pub associated_account: &'a AccountView,
24 pub wallet: &'a AccountView,
25 pub mint: &'a AccountView,
26 pub system_program: &'a AccountView,
27 pub token_program: &'a AccountView,
28}
29
30impl Create<'_> {
31 #[inline]
32 pub fn invoke(&self) -> ProgramResult {
33 self.invoke_signed(&[])
34 }
35
36 #[inline]
37 pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
38 let data = [0u8];
39 let accounts = [
40 InstructionAccount::writable_signer(self.payer.address()),
41 InstructionAccount::writable(self.associated_account.address()),
42 InstructionAccount::readonly(self.wallet.address()),
43 InstructionAccount::readonly(self.mint.address()),
44 InstructionAccount::readonly(self.system_program.address()),
45 InstructionAccount::readonly(self.token_program.address()),
46 ];
47 let views = [
48 self.payer,
49 self.associated_account,
50 self.wallet,
51 self.mint,
52 self.system_program,
53 self.token_program,
54 ];
55 let instruction = InstructionView {
56 program_id: &ATA_PROGRAM_ID,
57 data: &data,
58 accounts: &accounts,
59 };
60
61 hopper_runtime::cpi::invoke_signed(&instruction, &views, signers)
62 }
63}
64
65pub struct CreateIdempotent<'a> {
67 pub payer: &'a AccountView,
68 pub associated_account: &'a AccountView,
69 pub wallet: &'a AccountView,
70 pub mint: &'a AccountView,
71 pub system_program: &'a AccountView,
72 pub token_program: &'a AccountView,
73}
74
75impl CreateIdempotent<'_> {
76 #[inline]
77 pub fn invoke(&self) -> ProgramResult {
78 self.invoke_signed(&[])
79 }
80
81 #[inline]
82 pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
83 let data = [1u8];
84 let accounts = [
85 InstructionAccount::writable_signer(self.payer.address()),
86 InstructionAccount::writable(self.associated_account.address()),
87 InstructionAccount::readonly(self.wallet.address()),
88 InstructionAccount::readonly(self.mint.address()),
89 InstructionAccount::readonly(self.system_program.address()),
90 InstructionAccount::readonly(self.token_program.address()),
91 ];
92 let views = [
93 self.payer,
94 self.associated_account,
95 self.wallet,
96 self.mint,
97 self.system_program,
98 self.token_program,
99 ];
100 let instruction = InstructionView {
101 program_id: &ATA_PROGRAM_ID,
102 data: &data,
103 accounts: &accounts,
104 };
105
106 hopper_runtime::cpi::invoke_signed(&instruction, &views, signers)
107 }
108}
109
110pub struct RecoverNested<'a> {
112 pub nested_associated_account: &'a AccountView,
113 pub nested_token_mint: &'a AccountView,
114 pub destination_associated_account: &'a AccountView,
115 pub owner_associated_account: &'a AccountView,
116 pub owner_token_mint: &'a AccountView,
117 pub wallet: &'a AccountView,
118 pub token_program: &'a AccountView,
119}
120
121impl RecoverNested<'_> {
122 #[inline]
123 pub fn invoke(&self) -> ProgramResult {
124 self.invoke_signed(&[])
125 }
126
127 #[inline]
128 pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
129 let data = [2u8];
130 let accounts = [
131 InstructionAccount::writable(self.nested_associated_account.address()),
132 InstructionAccount::readonly(self.nested_token_mint.address()),
133 InstructionAccount::writable(self.destination_associated_account.address()),
134 InstructionAccount::readonly(self.owner_associated_account.address()),
135 InstructionAccount::readonly(self.owner_token_mint.address()),
136 InstructionAccount::writable_signer(self.wallet.address()),
137 InstructionAccount::readonly(self.token_program.address()),
138 ];
139 let views = [
140 self.nested_associated_account,
141 self.nested_token_mint,
142 self.destination_associated_account,
143 self.owner_associated_account,
144 self.owner_token_mint,
145 self.wallet,
146 self.token_program,
147 ];
148 let instruction = InstructionView {
149 program_id: &ATA_PROGRAM_ID,
150 data: &data,
151 accounts: &accounts,
152 };
153
154 hopper_runtime::cpi::invoke_signed(&instruction, &views, signers)
155 }
156}
157
158pub mod instructions {
159 pub use super::{Create, CreateIdempotent, RecoverNested};
160}