1use solana_program::pubkey::Pubkey;
4
5use super::types::{AmmCreatorFeeOn, VestingSchedule};
6
7#[derive(Clone, Debug)]
13pub struct PoolState {
14 pub epoch: u64,
15 pub auth_bump: u8,
16 pub status: u8,
17 pub base_decimals: u8,
18 pub quote_decimals: u8,
19 pub migrate_type: u8,
20 pub supply: u64,
21 pub total_base_sell: u64,
22 pub virtual_base: u64,
23 pub virtual_quote: u64,
24 pub real_base: u64,
25 pub real_quote: u64,
26 pub total_quote_fund_raising: u64,
27 pub quote_protocol_fee: u64,
28 pub platform_fee: u64,
29 pub migrate_fee: u64,
30 pub vesting_schedule: VestingSchedule,
31 pub global_config: Pubkey,
32 pub platform_config: Pubkey,
33 pub base_mint: Pubkey,
34 pub quote_mint: Pubkey,
35 pub base_vault: Pubkey,
36 pub quote_vault: Pubkey,
37 pub creator: Pubkey,
38 pub token_program_flag: u8,
39 pub amm_creator_fee_on: AmmCreatorFeeOn,
40 pub padding: [u8; 62],
41}
42
43impl Default for PoolState {
44 fn default() -> Self {
45 Self {
46 epoch: 0,
47 auth_bump: 0,
48 status: 0,
49 base_decimals: 0,
50 quote_decimals: 0,
51 migrate_type: 0,
52 supply: 0,
53 total_base_sell: 0,
54 virtual_base: 0,
55 virtual_quote: 0,
56 real_base: 0,
57 real_quote: 0,
58 total_quote_fund_raising: 0,
59 quote_protocol_fee: 0,
60 platform_fee: 0,
61 migrate_fee: 0,
62 vesting_schedule: VestingSchedule::default(),
63 global_config: Pubkey::default(),
64 platform_config: Pubkey::default(),
65 base_mint: Pubkey::default(),
66 quote_mint: Pubkey::default(),
67 base_vault: Pubkey::default(),
68 quote_vault: Pubkey::default(),
69 creator: Pubkey::default(),
70 token_program_flag: 0,
71 amm_creator_fee_on: AmmCreatorFeeOn::default(),
72 padding: [0u8; 62],
73 }
74 }
75}
76
77impl PoolState {
78 pub const DISCRIMINATOR: [u8; 8] = [247, 237, 227, 245, 215, 195, 222, 70];
79
80 pub fn try_from_bytes(data: &[u8]) -> Result<Self, std::io::Error> {
82 if data.len() < 8 {
83 return Err(std::io::Error::new(
84 std::io::ErrorKind::InvalidData,
85 "Data too short",
86 ));
87 }
88
89 let (discriminator, rest) = data.split_at(8);
90 if discriminator != Self::DISCRIMINATOR {
91 return Err(std::io::Error::new(
92 std::io::ErrorKind::InvalidData,
93 "Invalid discriminator",
94 ));
95 }
96
97 Self::deserialize(rest)
98 }
99
100 fn deserialize(data: &[u8]) -> Result<Self, std::io::Error> {
101 let mut offset = 0;
102
103 let epoch = read_u64(data, &mut offset)?;
104 let auth_bump = read_u8(data, &mut offset)?;
105 let status = read_u8(data, &mut offset)?;
106 let base_decimals = read_u8(data, &mut offset)?;
107 let quote_decimals = read_u8(data, &mut offset)?;
108 let migrate_type = read_u8(data, &mut offset)?;
109 let supply = read_u64(data, &mut offset)?;
110 let total_base_sell = read_u64(data, &mut offset)?;
111 let virtual_base = read_u64(data, &mut offset)?;
112 let virtual_quote = read_u64(data, &mut offset)?;
113 let real_base = read_u64(data, &mut offset)?;
114 let real_quote = read_u64(data, &mut offset)?;
115 let total_quote_fund_raising = read_u64(data, &mut offset)?;
116 let quote_protocol_fee = read_u64(data, &mut offset)?;
117 let platform_fee = read_u64(data, &mut offset)?;
118 let migrate_fee = read_u64(data, &mut offset)?;
119
120 let total_locked_amount = read_u64(data, &mut offset)?;
122 let cliff_period = read_u64(data, &mut offset)?;
123 let unlock_period = read_u64(data, &mut offset)?;
124 let start_time = read_u64(data, &mut offset)?;
125 let allocated_share_amount = read_u64(data, &mut offset)?;
126 let vesting_schedule = VestingSchedule {
127 total_locked_amount,
128 cliff_period,
129 unlock_period,
130 start_time,
131 allocated_share_amount,
132 };
133
134 let global_config = read_pubkey(data, &mut offset)?;
135 let platform_config = read_pubkey(data, &mut offset)?;
136 let base_mint = read_pubkey(data, &mut offset)?;
137 let quote_mint = read_pubkey(data, &mut offset)?;
138 let base_vault = read_pubkey(data, &mut offset)?;
139 let quote_vault = read_pubkey(data, &mut offset)?;
140 let creator = read_pubkey(data, &mut offset)?;
141 let token_program_flag = read_u8(data, &mut offset)?;
142 let amm_creator_fee_on_byte = read_u8(data, &mut offset)?;
143
144 let mut padding = [0u8; 62];
145 padding.copy_from_slice(&data[offset..offset + 62]);
146 let _ = offset + 62; Ok(Self {
149 epoch,
150 auth_bump,
151 status,
152 base_decimals,
153 quote_decimals,
154 migrate_type,
155 supply,
156 total_base_sell,
157 virtual_base,
158 virtual_quote,
159 real_base,
160 real_quote,
161 total_quote_fund_raising,
162 quote_protocol_fee,
163 platform_fee,
164 migrate_fee,
165 vesting_schedule,
166 global_config,
167 platform_config,
168 base_mint,
169 quote_mint,
170 base_vault,
171 quote_vault,
172 creator,
173 token_program_flag,
174 amm_creator_fee_on: AmmCreatorFeeOn::from_u8(amm_creator_fee_on_byte),
175 padding,
176 })
177 }
178
179 pub fn is_funding(&self) -> bool {
180 self.status == 0
181 }
182
183 pub fn is_migrate(&self) -> bool {
184 self.status == 1
185 }
186
187 pub fn is_trading(&self) -> bool {
188 self.status == 2
189 }
190
191 pub fn is_base_token_2022(&self) -> bool {
192 self.token_program_flag & 0x01 != 0
193 }
194
195 pub fn is_quote_token_2022(&self) -> bool {
196 self.token_program_flag & 0x02 != 0
197 }
198}
199
200pub struct GlobalConfig {
201 pub epoch: u64,
202 pub curve_type: u8,
203 pub index: u16,
204 pub migrate_fee: u64,
205 pub trade_fee_rate: u64,
206 pub max_share_fee_rate: u64,
207 pub min_base_supply: u64,
208 pub max_lock_rate: u64,
209 pub min_base_sell_rate: u64,
210 pub min_base_migrate_rate: u64,
211 pub min_quote_fund_raising: u64,
212 pub quote_mint: Pubkey,
213 pub protocol_fee_owner: Pubkey,
214 pub migrate_fee_owner: Pubkey,
215 pub migrate_to_amm_wallet: Pubkey,
216 pub migrate_to_cpswap_wallet: Pubkey,
217 pub padding: [u64; 16],
218}
219
220impl GlobalConfig {
221 pub const DISCRIMINATOR: [u8; 8] = [149, 8, 156, 202, 160, 252, 176, 217];
222
223 pub fn try_from_bytes(data: &[u8]) -> Result<Self, std::io::Error> {
224 if data.len() < 8 {
225 return Err(std::io::Error::new(
226 std::io::ErrorKind::InvalidData,
227 "Data too short",
228 ));
229 }
230
231 let (discriminator, rest) = data.split_at(8);
232 if discriminator != Self::DISCRIMINATOR {
233 return Err(std::io::Error::new(
234 std::io::ErrorKind::InvalidData,
235 "Invalid discriminator",
236 ));
237 }
238
239 let mut offset = 0;
240 let epoch = read_u64(rest, &mut offset)?;
241 let curve_type = read_u8(rest, &mut offset)?;
242 let index = read_u16(rest, &mut offset)?;
243 let migrate_fee = read_u64(rest, &mut offset)?;
244 let trade_fee_rate = read_u64(rest, &mut offset)?;
245 let max_share_fee_rate = read_u64(rest, &mut offset)?;
246 let min_base_supply = read_u64(rest, &mut offset)?;
247 let max_lock_rate = read_u64(rest, &mut offset)?;
248 let min_base_sell_rate = read_u64(rest, &mut offset)?;
249 let min_base_migrate_rate = read_u64(rest, &mut offset)?;
250 let min_quote_fund_raising = read_u64(rest, &mut offset)?;
251 let quote_mint = read_pubkey(rest, &mut offset)?;
252 let protocol_fee_owner = read_pubkey(rest, &mut offset)?;
253 let migrate_fee_owner = read_pubkey(rest, &mut offset)?;
254 let migrate_to_amm_wallet = read_pubkey(rest, &mut offset)?;
255 let migrate_to_cpswap_wallet = read_pubkey(rest, &mut offset)?;
256
257 let mut padding = [0u64; 16];
258 for i in 0..16 {
259 padding[i] = read_u64(rest, &mut offset)?;
260 }
261
262 Ok(Self {
263 epoch,
264 curve_type,
265 index,
266 migrate_fee,
267 trade_fee_rate,
268 max_share_fee_rate,
269 min_base_supply,
270 max_lock_rate,
271 min_base_sell_rate,
272 min_base_migrate_rate,
273 min_quote_fund_raising,
274 quote_mint,
275 protocol_fee_owner,
276 migrate_fee_owner,
277 migrate_to_amm_wallet,
278 migrate_to_cpswap_wallet,
279 padding,
280 })
281 }
282}
283
284fn read_u8(data: &[u8], offset: &mut usize) -> Result<u8, std::io::Error> {
285 if *offset >= data.len() {
286 return Err(std::io::Error::new(
287 std::io::ErrorKind::UnexpectedEof,
288 "Unexpected end of data",
289 ));
290 }
291 let value = data[*offset];
292 *offset += 1;
293 Ok(value)
294}
295
296fn read_u16(data: &[u8], offset: &mut usize) -> Result<u16, std::io::Error> {
297 if *offset + 2 > data.len() {
298 return Err(std::io::Error::new(
299 std::io::ErrorKind::UnexpectedEof,
300 "Unexpected end of data",
301 ));
302 }
303 let value = u16::from_le_bytes([data[*offset], data[*offset + 1]]);
304 *offset += 2;
305 Ok(value)
306}
307
308fn read_u64(data: &[u8], offset: &mut usize) -> Result<u64, std::io::Error> {
309 if *offset + 8 > data.len() {
310 return Err(std::io::Error::new(
311 std::io::ErrorKind::UnexpectedEof,
312 "Unexpected end of data",
313 ));
314 }
315 let bytes: [u8; 8] = data[*offset..*offset + 8].try_into().unwrap();
316 let value = u64::from_le_bytes(bytes);
317 *offset += 8;
318 Ok(value)
319}
320
321fn read_pubkey(data: &[u8], offset: &mut usize) -> Result<Pubkey, std::io::Error> {
322 if *offset + 32 > data.len() {
323 return Err(std::io::Error::new(
324 std::io::ErrorKind::UnexpectedEof,
325 "Unexpected end of data",
326 ));
327 }
328 let bytes: [u8; 32] = data[*offset..*offset + 32].try_into().unwrap();
329 let pubkey = Pubkey::new_from_array(bytes);
330 *offset += 32;
331 Ok(pubkey)
332}
333
334pub struct PlatformConfig {
335 pub epoch: u64,
336 pub platform_fee_wallet: Pubkey,
337 pub platform_nft_wallet: Pubkey,
338 pub platform_scale: u64,
339 pub creator_scale: u64,
340 pub burn_scale: u64,
341 pub fee_rate: u64,
342 pub name: [u8; 64],
343 pub web: [u8; 256],
344 pub img: [u8; 256],
345 pub cpswap_config: Pubkey,
346 pub creator_fee_rate: u64,
347 pub transfer_fee_extension_auth: Pubkey,
348}
349
350impl Default for PlatformConfig {
351 fn default() -> Self {
352 Self {
353 epoch: 0,
354 platform_fee_wallet: Pubkey::default(),
355 platform_nft_wallet: Pubkey::default(),
356 platform_scale: 0,
357 creator_scale: 0,
358 burn_scale: 0,
359 fee_rate: 0,
360 name: [0; 64],
361 web: [0; 256],
362 img: [0; 256],
363 cpswap_config: Pubkey::default(),
364 creator_fee_rate: 0,
365 transfer_fee_extension_auth: Pubkey::default(),
366 }
367 }
368}
369
370impl PlatformConfig {
371 pub const DISCRIMINATOR: [u8; 8] = [160, 78, 128, 0, 248, 83, 230, 160];
372
373 pub fn try_from_bytes(data: &[u8]) -> Result<Self, std::io::Error> {
374 if data.len() < 8 {
375 return Err(std::io::Error::new(
376 std::io::ErrorKind::InvalidData,
377 "Data too short",
378 ));
379 }
380
381 let (discriminator, rest) = data.split_at(8);
382 if discriminator != Self::DISCRIMINATOR {
383 return Err(std::io::Error::new(
384 std::io::ErrorKind::InvalidData,
385 "Invalid discriminator",
386 ));
387 }
388
389 let mut offset = 0;
390 let epoch = read_u64(rest, &mut offset)?;
391 let platform_fee_wallet = read_pubkey(rest, &mut offset)?;
392 let platform_nft_wallet = read_pubkey(rest, &mut offset)?;
393 let platform_scale = read_u64(rest, &mut offset)?;
394 let creator_scale = read_u64(rest, &mut offset)?;
395 let burn_scale = read_u64(rest, &mut offset)?;
396 let fee_rate = read_u64(rest, &mut offset)?;
397
398 let mut name = [0u8; 64];
399 name.copy_from_slice(&rest[offset..offset + 64]);
400 offset += 64;
401
402 let mut web = [0u8; 256];
403 web.copy_from_slice(&rest[offset..offset + 256]);
404 offset += 256;
405
406 let mut img = [0u8; 256];
407 img.copy_from_slice(&rest[offset..offset + 256]);
408 offset += 256;
409
410 let cpswap_config = read_pubkey(rest, &mut offset)?;
411 let creator_fee_rate = read_u64(rest, &mut offset)?;
412 let transfer_fee_extension_auth = read_pubkey(rest, &mut offset)?;
413
414 Ok(Self {
415 epoch,
416 platform_fee_wallet,
417 platform_nft_wallet,
418 platform_scale,
419 creator_scale,
420 burn_scale,
421 fee_rate,
422 name,
423 web,
424 img,
425 cpswap_config,
426 creator_fee_rate,
427 transfer_fee_extension_auth,
428 })
429 }
430}