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::TOKEN_2022_PROGRAM_ID;
13pub use hopper_solana::mint::{
14 check_mint_authority, check_mint_initialized, mint_authority, mint_decimals,
15 mint_freeze_authority, mint_supply, MINT_LEN,
16};
17pub use hopper_solana::token::{
18 check_not_frozen, check_token_balance_gte, check_token_initialized, check_token_mint,
19 check_token_owner, token_account_amount, token_account_mint, token_account_owner,
20 token_account_state, TOKEN_ACCOUNT_LEN,
21};
22pub use hopper_solana::token2022_ext::{
23 check_no_confidential_transfer, check_no_permanent_delegate, check_no_transfer_fee,
24 check_no_transfer_hook, check_safe_token_2022_mint, check_transfer_hook_program,
25 check_transferable, find_extension_data, mint_has_extension, read_transfer_fee_config,
26 read_transfer_hook, token_has_extension, TransferFeeConfig, TransferHook, ACCOUNT_TYPE_MINT,
27 ACCOUNT_TYPE_OFFSET, ACCOUNT_TYPE_TOKEN, EXT_CONFIDENTIAL_TRANSFER_ACCOUNT,
28 EXT_CONFIDENTIAL_TRANSFER_MINT, EXT_CPI_GUARD, EXT_DEFAULT_ACCOUNT_STATE,
29 EXT_GROUP_MEMBER_POINTER, EXT_GROUP_POINTER, EXT_IMMUTABLE_OWNER, EXT_INTEREST_BEARING,
30 EXT_MEMO_TRANSFER, EXT_METADATA_POINTER, EXT_MINT_CLOSE_AUTHORITY, EXT_NON_TRANSFERABLE,
31 EXT_PERMANENT_DELEGATE, EXT_TOKEN_METADATA, EXT_TRANSFER_FEE_AMOUNT, EXT_TRANSFER_FEE_CONFIG,
32 EXT_TRANSFER_HOOK, MINT_BASE_SIZE, TLV_OFFSET, TOKEN_ACCOUNT_BASE_SIZE,
33};
34
35pub struct Transfer<'a> {
37 pub from: &'a AccountView,
38 pub to: &'a AccountView,
39 pub authority: &'a AccountView,
40 pub amount: u64,
41}
42
43impl Transfer<'_> {
44 #[inline]
45 pub fn invoke(&self) -> ProgramResult {
46 self.invoke_signed(&[])
47 }
48
49 #[inline]
50 pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
51 let mut data = [0u8; 9];
52 data[0] = 3;
53 data[1..9].copy_from_slice(&self.amount.to_le_bytes());
54
55 let accounts = [
56 InstructionAccount::writable(self.from.address()),
57 InstructionAccount::writable(self.to.address()),
58 InstructionAccount::readonly_signer(self.authority.address()),
59 ];
60 let views = [self.from, self.to, self.authority];
61 let instruction = InstructionView {
62 program_id: &TOKEN_2022_PROGRAM_ID,
63 data: &data,
64 accounts: &accounts,
65 };
66
67 hopper_runtime::cpi::invoke_signed(&instruction, &views, signers)
68 }
69}
70
71pub struct MintTo<'a> {
73 pub mint: &'a AccountView,
74 pub account: &'a AccountView,
75 pub mint_authority: &'a AccountView,
76 pub amount: u64,
77}
78
79impl MintTo<'_> {
80 #[inline]
81 pub fn invoke(&self) -> ProgramResult {
82 self.invoke_signed(&[])
83 }
84
85 #[inline]
86 pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
87 let mut data = [0u8; 9];
88 data[0] = 7;
89 data[1..9].copy_from_slice(&self.amount.to_le_bytes());
90
91 let accounts = [
92 InstructionAccount::writable(self.mint.address()),
93 InstructionAccount::writable(self.account.address()),
94 InstructionAccount::readonly_signer(self.mint_authority.address()),
95 ];
96 let views = [self.mint, self.account, self.mint_authority];
97 let instruction = InstructionView {
98 program_id: &TOKEN_2022_PROGRAM_ID,
99 data: &data,
100 accounts: &accounts,
101 };
102
103 hopper_runtime::cpi::invoke_signed(&instruction, &views, signers)
104 }
105}
106
107pub struct Burn<'a> {
109 pub account: &'a AccountView,
110 pub mint: &'a AccountView,
111 pub authority: &'a AccountView,
112 pub amount: u64,
113}
114
115impl Burn<'_> {
116 #[inline]
117 pub fn invoke(&self) -> ProgramResult {
118 self.invoke_signed(&[])
119 }
120
121 #[inline]
122 pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
123 let mut data = [0u8; 9];
124 data[0] = 8;
125 data[1..9].copy_from_slice(&self.amount.to_le_bytes());
126
127 let accounts = [
128 InstructionAccount::writable(self.account.address()),
129 InstructionAccount::writable(self.mint.address()),
130 InstructionAccount::readonly_signer(self.authority.address()),
131 ];
132 let views = [self.account, self.mint, self.authority];
133 let instruction = InstructionView {
134 program_id: &TOKEN_2022_PROGRAM_ID,
135 data: &data,
136 accounts: &accounts,
137 };
138
139 hopper_runtime::cpi::invoke_signed(&instruction, &views, signers)
140 }
141}
142
143pub struct CloseAccount<'a> {
145 pub account: &'a AccountView,
146 pub destination: &'a AccountView,
147 pub authority: &'a AccountView,
148}
149
150impl CloseAccount<'_> {
151 #[inline]
152 pub fn invoke(&self) -> ProgramResult {
153 self.invoke_signed(&[])
154 }
155
156 #[inline]
157 pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
158 let data = [9u8];
159 let accounts = [
160 InstructionAccount::writable(self.account.address()),
161 InstructionAccount::writable(self.destination.address()),
162 InstructionAccount::readonly_signer(self.authority.address()),
163 ];
164 let views = [self.account, self.destination, self.authority];
165 let instruction = InstructionView {
166 program_id: &TOKEN_2022_PROGRAM_ID,
167 data: &data,
168 accounts: &accounts,
169 };
170
171 hopper_runtime::cpi::invoke_signed(&instruction, &views, signers)
172 }
173}
174
175pub struct Approve<'a> {
177 pub source: &'a AccountView,
178 pub delegate: &'a AccountView,
179 pub authority: &'a AccountView,
180 pub amount: u64,
181}
182
183impl Approve<'_> {
184 #[inline]
185 pub fn invoke(&self) -> ProgramResult {
186 self.invoke_signed(&[])
187 }
188
189 #[inline]
190 pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
191 let mut data = [0u8; 9];
192 data[0] = 4;
193 data[1..9].copy_from_slice(&self.amount.to_le_bytes());
194
195 let accounts = [
196 InstructionAccount::writable(self.source.address()),
197 InstructionAccount::readonly(self.delegate.address()),
198 InstructionAccount::readonly_signer(self.authority.address()),
199 ];
200 let views = [self.source, self.delegate, self.authority];
201 let instruction = InstructionView {
202 program_id: &TOKEN_2022_PROGRAM_ID,
203 data: &data,
204 accounts: &accounts,
205 };
206
207 hopper_runtime::cpi::invoke_signed(&instruction, &views, signers)
208 }
209}
210
211pub struct Revoke<'a> {
213 pub source: &'a AccountView,
214 pub authority: &'a AccountView,
215}
216
217impl Revoke<'_> {
218 #[inline]
219 pub fn invoke(&self) -> ProgramResult {
220 self.invoke_signed(&[])
221 }
222
223 #[inline]
224 pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
225 let data = [5u8];
226 let accounts = [
227 InstructionAccount::writable(self.source.address()),
228 InstructionAccount::readonly_signer(self.authority.address()),
229 ];
230 let views = [self.source, self.authority];
231 let instruction = InstructionView {
232 program_id: &TOKEN_2022_PROGRAM_ID,
233 data: &data,
234 accounts: &accounts,
235 };
236
237 hopper_runtime::cpi::invoke_signed(&instruction, &views, signers)
238 }
239}
240
241pub struct InitializeAccount<'a> {
243 pub account: &'a AccountView,
244 pub mint: &'a AccountView,
245 pub owner: &'a AccountView,
246 pub rent_sysvar: &'a AccountView,
247}
248
249impl InitializeAccount<'_> {
250 #[inline]
251 pub fn invoke(&self) -> ProgramResult {
252 let data = [1u8];
253 let accounts = [
254 InstructionAccount::writable(self.account.address()),
255 InstructionAccount::readonly(self.mint.address()),
256 InstructionAccount::readonly(self.owner.address()),
257 InstructionAccount::readonly(self.rent_sysvar.address()),
258 ];
259 let views = [self.account, self.mint, self.owner, self.rent_sysvar];
260 let instruction = InstructionView {
261 program_id: &TOKEN_2022_PROGRAM_ID,
262 data: &data,
263 accounts: &accounts,
264 };
265
266 hopper_runtime::cpi::invoke(&instruction, &views)
267 }
268}
269
270pub mod instructions {
271 pub use super::{Approve, Burn, CloseAccount, InitializeAccount, MintTo, Revoke, Transfer};
272}