sememe 0.0.0-stage → 0.4.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2667 -2
  3. package/bin/sememe.mjs +556 -0
  4. package/index.mjs +48 -0
  5. package/interface/ata-ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL.json +62 -0
  6. package/interface/native-11111111111111111111111111111111.json +226 -0
  7. package/interface/native-ComputeBudget111111111111111111111111111111.json +72 -0
  8. package/interface/raydium-675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8.json +352 -0
  9. package/interface/token-TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA.json +334 -0
  10. package/interface/token-TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb.json +535 -0
  11. package/interface/token-metadata.json +132 -0
  12. package/package.json +71 -4
  13. package/src/account-list.mjs +308 -0
  14. package/src/account-union.mjs +523 -0
  15. package/src/account.mjs +199 -0
  16. package/src/acquire.mjs +145 -0
  17. package/src/adopt.mjs +205 -0
  18. package/src/ata-interface.mjs +276 -0
  19. package/src/ata.mjs +223 -0
  20. package/src/base58.mjs +96 -0
  21. package/src/canonical.mjs +24 -0
  22. package/src/cli-surface.mjs +300 -0
  23. package/src/codec.mjs +1069 -0
  24. package/src/conformance.mjs +431 -0
  25. package/src/corpus/harvest-compute-budget-2026-10-31.json +19122 -0
  26. package/src/corpus/harvest-system-2026-10-31.json +26090 -0
  27. package/src/decode.mjs +286 -0
  28. package/src/dialect.mjs +145 -0
  29. package/src/discriminators.mjs +177 -0
  30. package/src/drift.mjs +172 -0
  31. package/src/gap.mjs +205 -0
  32. package/src/lighthouse.mjs +168 -0
  33. package/src/lock.mjs +440 -0
  34. package/src/native-audit.mjs +56 -0
  35. package/src/native-corpus.mjs +57 -0
  36. package/src/native-interface.mjs +252 -0
  37. package/src/native.mjs +324 -0
  38. package/src/peer.mjs +95 -0
  39. package/src/program-id.mjs +74 -0
  40. package/src/pull.mjs +117 -0
  41. package/src/rawle.mjs +450 -0
  42. package/src/raydium-interface.mjs +747 -0
  43. package/src/raydium.mjs +391 -0
  44. package/src/receipt-digest.mjs +84 -0
  45. package/src/receipt-name.mjs +128 -0
  46. package/src/receipt-order.mjs +56 -0
  47. package/src/shank.mjs +73 -0
  48. package/src/short-forms.mjs +209 -0
  49. package/src/store-read.mjs +250 -0
  50. package/src/store-write.mjs +46 -0
  51. package/src/token-interface.mjs +394 -0
  52. package/src/token-metadata-interface.mjs +371 -0
  53. package/src/token-metadata.mjs +317 -0
  54. package/src/token.mjs +443 -0
  55. package/src/union.mjs +428 -0
  56. package/vendor/anza-solana-sdk/8db406e2edfafa25939ec782b77b5b6f30de164d/LICENSE.txt +201 -0
  57. package/vendor/anza-solana-sdk/8db406e2edfafa25939ec782b77b5b6f30de164d/compute-budget-interface/src/lib.rs +93 -0
  58. package/vendor/anza-solana-sdk/8db406e2edfafa25939ec782b77b5b6f30de164d/system-interface/src/instruction.rs +1899 -0
  59. package/vendor/lighthouse/4c579479c98635e419b1b167f08be02a71604a71/LICENSE +21 -0
  60. package/vendor/lighthouse/4c579479c98635e419b1b167f08be02a71604a71/lighthouse.json +2769 -0
  61. package/vendor/raydium-amm/91739d8d9f5cf347e0ce14ebe4d2bb7069fb31b6/LICENSE +201 -0
  62. package/vendor/raydium-amm/91739d8d9f5cf347e0ce14ebe4d2bb7069fb31b6/program/src/instruction.rs +1189 -0
  63. package/vendor/raydium-amm/91739d8d9f5cf347e0ce14ebe4d2bb7069fb31b6/program/src/state.rs +1348 -0
  64. package/vendor/spl-associated-token-account/fbf5379e7398ac8b231c73ee8a9ff677b43dd0ec/LICENSE +201 -0
  65. package/vendor/spl-associated-token-account/fbf5379e7398ac8b231c73ee8a9ff677b43dd0ec/interface/src/instruction.rs +169 -0
  66. package/vendor/spl-associated-token-account/fbf5379e7398ac8b231c73ee8a9ff677b43dd0ec/interface/src/lib.rs +12 -0
  67. package/vendor/spl-associated-token-account/fbf5379e7398ac8b231c73ee8a9ff677b43dd0ec/program/src/processor.rs +308 -0
  68. package/vendor/spl-token/737788ff5bcc3f1f44cfb222f25483187650be76/LICENSE.txt +176 -0
  69. package/vendor/spl-token/737788ff5bcc3f1f44cfb222f25483187650be76/interface/src/instruction.rs +1963 -0
  70. package/vendor/spl-token-2022/5251dcc07ecbcb721d6c4f0231090defadf00311/LICENSE.txt +176 -0
  71. package/vendor/spl-token-2022/5251dcc07ecbcb721d6c4f0231090defadf00311/interface/src/instruction.rs +2868 -0
  72. package/vendor/spl-token-metadata-interface/7038969ec74a89f1afdb9bc97c112d4d26fead9a/LICENSE +201 -0
  73. package/vendor/spl-token-metadata-interface/7038969ec74a89f1afdb9bc97c112d4d26fead9a/interface/src/error.rs +58 -0
  74. package/vendor/spl-token-metadata-interface/7038969ec74a89f1afdb9bc97c112d4d26fead9a/interface/src/instruction.rs +596 -0
  75. package/vendor/spl-token-metadata-interface/7038969ec74a89f1afdb9bc97c112d4d26fead9a/interface/src/lib.rs +21 -0
  76. package/vendor/spl-token-metadata-interface/7038969ec74a89f1afdb9bc97c112d4d26fead9a/interface/src/state.rs +229 -0
@@ -0,0 +1,1348 @@
1
+ //! State transition types
2
+
3
+ use crate::error::AmmError;
4
+ use solana_program::{
5
+ account_info::AccountInfo,
6
+ program_error::ProgramError,
7
+ program_pack::{IsInitialized, Pack, Sealed},
8
+ pubkey::Pubkey,
9
+ };
10
+
11
+ use arrayref::{array_mut_ref, array_ref, array_refs, mut_array_refs};
12
+ use bytemuck::{from_bytes, from_bytes_mut, Pod, Zeroable};
13
+ use safe_transmute::{self, trivial::TriviallyTransmutable};
14
+ use std::{
15
+ cell::{Ref, RefMut},
16
+ convert::TryInto,
17
+ mem::size_of,
18
+ };
19
+
20
+ pub const TEN_THOUSAND: u64 = 10000;
21
+ pub const MAX_ORDER_LIMIT: usize = 10;
22
+
23
+ #[cfg(not(test))]
24
+ pub fn get_recent_epoch() -> Result<u64, ProgramError> {
25
+ use solana_program::{clock::Clock, sysvar::Sysvar};
26
+ Ok(Clock::get()?.epoch)
27
+ }
28
+
29
+ #[cfg(test)]
30
+ pub fn get_recent_epoch() -> Result<u64, ProgramError> {
31
+ use std::time::{SystemTime, UNIX_EPOCH};
32
+ Ok(SystemTime::now()
33
+ .duration_since(UNIX_EPOCH)
34
+ .unwrap()
35
+ .as_secs()
36
+ / (2 * 24 * 3600))
37
+ }
38
+
39
+ pub trait Loadable: Pod {
40
+ fn load_mut<'a>(account: &'a AccountInfo) -> Result<RefMut<'a, Self>, ProgramError> {
41
+ // TODO verify if this checks for size
42
+ Ok(RefMut::map(account.try_borrow_mut_data()?, |data| {
43
+ from_bytes_mut(data)
44
+ }))
45
+ }
46
+ fn load<'a>(account: &'a AccountInfo) -> Result<Ref<'a, Self>, ProgramError> {
47
+ Ok(Ref::map(account.try_borrow_data()?, |data| {
48
+ from_bytes(data)
49
+ }))
50
+ }
51
+
52
+ fn load_from_bytes(data: &[u8]) -> Result<&Self, ProgramError> {
53
+ Ok(from_bytes(data))
54
+ }
55
+ }
56
+
57
+ macro_rules! impl_loadable {
58
+ ($type_name:ident) => {
59
+ unsafe impl Zeroable for $type_name {}
60
+ unsafe impl Pod for $type_name {}
61
+ unsafe impl TriviallyTransmutable for $type_name {}
62
+ impl Loadable for $type_name {}
63
+ };
64
+ }
65
+ #[cfg_attr(feature = "client", derive(Debug))]
66
+ #[repr(C, packed)]
67
+ #[derive(Clone, Copy, Default)]
68
+ pub struct TargetOrder {
69
+ pub price: u64,
70
+ pub vol: u64,
71
+ }
72
+ #[cfg(target_endian = "little")]
73
+ unsafe impl Zeroable for TargetOrder {}
74
+ #[cfg(target_endian = "little")]
75
+ unsafe impl Pod for TargetOrder {}
76
+ #[cfg(target_endian = "little")]
77
+ unsafe impl TriviallyTransmutable for TargetOrder {}
78
+
79
+ #[cfg_attr(feature = "client", derive(Debug))]
80
+ #[repr(C, packed)]
81
+ #[derive(Clone, Copy)]
82
+ pub struct TargetOrders {
83
+ pub owner: Pubkey,
84
+ pub buy_orders: [TargetOrder; 50],
85
+ pub padding1: [u64; 8],
86
+ pub target_x: u128,
87
+ pub target_y: u128,
88
+ pub plan_x_buy: u128,
89
+ pub plan_y_buy: u128,
90
+ pub plan_x_sell: u128,
91
+ pub plan_y_sell: u128,
92
+ pub placed_x: u128,
93
+ pub placed_y: u128,
94
+ pub calc_pnl_x: u128,
95
+ pub calc_pnl_y: u128,
96
+ pub sell_orders: [TargetOrder; 50],
97
+ pub padding2: [u64; 6],
98
+ pub replace_buy_client_id: [u64; MAX_ORDER_LIMIT],
99
+ pub replace_sell_client_id: [u64; MAX_ORDER_LIMIT],
100
+ pub last_order_numerator: u64,
101
+ pub last_order_denominator: u64,
102
+
103
+ pub plan_orders_cur: u64,
104
+ pub place_orders_cur: u64,
105
+
106
+ pub valid_buy_order_num: u64,
107
+ pub valid_sell_order_num: u64,
108
+
109
+ pub padding3: [u64; 10],
110
+
111
+ pub free_slot_bits: u128,
112
+ }
113
+ impl_loadable!(TargetOrders);
114
+
115
+ #[cfg(test)]
116
+ impl Default for TargetOrders {
117
+ #[inline]
118
+ fn default() -> TargetOrders {
119
+ TargetOrders {
120
+ owner: Pubkey::default(),
121
+ buy_orders: [TargetOrder::default(); 50],
122
+ padding1: [0; 8],
123
+ target_x: 0,
124
+ target_y: 0,
125
+ plan_x_buy: 0,
126
+ plan_y_buy: 0,
127
+ plan_x_sell: 0,
128
+ plan_y_sell: 0,
129
+ placed_x: 0,
130
+ placed_y: 0,
131
+ calc_pnl_x: 0,
132
+ calc_pnl_y: 0,
133
+ sell_orders: [TargetOrder::default(); 50],
134
+ padding2: [0; 6],
135
+ replace_buy_client_id: [0; MAX_ORDER_LIMIT],
136
+ replace_sell_client_id: [0; MAX_ORDER_LIMIT],
137
+ last_order_denominator: 0,
138
+ last_order_numerator: 0,
139
+ plan_orders_cur: 0,
140
+ place_orders_cur: 0,
141
+ valid_buy_order_num: 0,
142
+ valid_sell_order_num: 0,
143
+ padding3: [0; 10],
144
+ free_slot_bits: std::u128::MAX,
145
+ }
146
+ }
147
+ }
148
+
149
+ impl TargetOrders {
150
+ /// init
151
+ #[inline]
152
+ pub fn check_init(&mut self, x: u128, y: u128, owner: &Pubkey) -> Result<(), ProgramError> {
153
+ if self.owner != Pubkey::default() {
154
+ return Err(AmmError::AlreadyInUse.into());
155
+ }
156
+ self.owner = *owner;
157
+ self.last_order_numerator = 0; // 3
158
+ self.last_order_denominator = 0; // 1
159
+
160
+ self.plan_orders_cur = 0;
161
+ self.place_orders_cur = 0;
162
+
163
+ self.valid_buy_order_num = 0;
164
+ self.valid_sell_order_num = 0;
165
+
166
+ self.target_x = 0;
167
+ self.target_y = 0;
168
+ self.plan_x_buy = 0;
169
+ self.plan_y_buy = 0;
170
+ self.plan_x_sell = 0;
171
+ self.plan_y_sell = 0;
172
+ self.placed_x = 0;
173
+ self.placed_y = 0;
174
+ self.calc_pnl_x = x;
175
+ self.calc_pnl_y = y;
176
+ self.free_slot_bits = std::u128::MAX;
177
+ Ok(())
178
+ }
179
+
180
+ /// load_mut_checked
181
+ #[inline]
182
+ pub fn load_mut_checked<'a>(
183
+ account: &'a AccountInfo,
184
+ program_id: &Pubkey,
185
+ owner: &Pubkey,
186
+ ) -> Result<RefMut<'a, Self>, ProgramError> {
187
+ if account.owner != program_id {
188
+ return Err(AmmError::InvalidTargetAccountOwner.into());
189
+ }
190
+ if account.data_len() != size_of::<Self>() {
191
+ return Err(AmmError::ExpectedAccount.into());
192
+ }
193
+ let data = Self::load_mut(account)?;
194
+ if data.owner != *owner {
195
+ return Err(AmmError::InvalidTargetOwner.into());
196
+ }
197
+ Ok(data)
198
+ }
199
+
200
+ /// load_checked
201
+ #[inline]
202
+ pub fn load_checked<'a>(
203
+ account: &'a AccountInfo,
204
+ program_id: &Pubkey,
205
+ owner: &Pubkey,
206
+ ) -> Result<Ref<'a, Self>, ProgramError> {
207
+ if account.owner != program_id {
208
+ return Err(AmmError::InvalidTargetAccountOwner.into());
209
+ }
210
+ if account.data_len() != size_of::<Self>() {
211
+ return Err(AmmError::ExpectedAccount.into());
212
+ }
213
+ let data = Self::load(account)?;
214
+ if data.owner != *owner {
215
+ return Err(AmmError::InvalidTargetOwner.into());
216
+ }
217
+ Ok(data)
218
+ }
219
+ }
220
+
221
+ #[repr(u64)]
222
+ pub enum AmmStatus {
223
+ Uninitialized = 0u64,
224
+ Initialized = 1u64,
225
+ Disabled = 2u64,
226
+ WithdrawOnly = 3u64,
227
+ // pool only can add or remove liquidity, can't swap and plan orders
228
+ LiquidityOnly = 4u64,
229
+ // pool only can add or remove liquidity and plan orders, can't swap
230
+ OrderBookOnly = 5u64,
231
+ // pool only can add or remove liquidity and swap, can't plan orders
232
+ SwapOnly = 6u64,
233
+ // pool status after created and will auto update to SwapOnly during swap after open_time
234
+ WaitingTrade = 7u64,
235
+ }
236
+ impl AmmStatus {
237
+ pub fn from_u64(status: u64) -> Self {
238
+ match status {
239
+ 0u64 => AmmStatus::Uninitialized,
240
+ 1u64 => AmmStatus::Initialized,
241
+ 2u64 => AmmStatus::Disabled,
242
+ 3u64 => AmmStatus::WithdrawOnly,
243
+ 4u64 => AmmStatus::LiquidityOnly,
244
+ 5u64 => AmmStatus::OrderBookOnly,
245
+ 6u64 => AmmStatus::SwapOnly,
246
+ 7u64 => AmmStatus::WaitingTrade,
247
+ _ => unreachable!(),
248
+ }
249
+ }
250
+
251
+ pub fn into_u64(&self) -> u64 {
252
+ match self {
253
+ AmmStatus::Uninitialized => 0u64,
254
+ AmmStatus::Initialized => 1u64,
255
+ AmmStatus::Disabled => 2u64,
256
+ AmmStatus::WithdrawOnly => 3u64,
257
+ AmmStatus::LiquidityOnly => 4u64,
258
+ AmmStatus::OrderBookOnly => 5u64,
259
+ AmmStatus::SwapOnly => 6u64,
260
+ AmmStatus::WaitingTrade => 7u64,
261
+ }
262
+ }
263
+ pub fn valid_status(status: u64) -> bool {
264
+ match status {
265
+ 1u64 | 2u64 | 3u64 | 4u64 | 5u64 | 6u64 | 7u64 => return true,
266
+ _ => return false,
267
+ }
268
+ }
269
+
270
+ pub fn deposit_permission(&self) -> bool {
271
+ match self {
272
+ AmmStatus::Uninitialized => false,
273
+ AmmStatus::Initialized => true,
274
+ AmmStatus::Disabled => false,
275
+ AmmStatus::WithdrawOnly => false,
276
+ AmmStatus::LiquidityOnly => true,
277
+ AmmStatus::OrderBookOnly => true,
278
+ AmmStatus::SwapOnly => true,
279
+ AmmStatus::WaitingTrade => true,
280
+ }
281
+ }
282
+
283
+ pub fn withdraw_permission(&self) -> bool {
284
+ match self {
285
+ AmmStatus::Uninitialized => false,
286
+ AmmStatus::Initialized => true,
287
+ AmmStatus::Disabled => false,
288
+ AmmStatus::WithdrawOnly => true,
289
+ AmmStatus::LiquidityOnly => true,
290
+ AmmStatus::OrderBookOnly => true,
291
+ AmmStatus::SwapOnly => true,
292
+ AmmStatus::WaitingTrade => true,
293
+ }
294
+ }
295
+
296
+ pub fn swap_permission(&self) -> bool {
297
+ match self {
298
+ AmmStatus::Uninitialized => false,
299
+ AmmStatus::Initialized => true,
300
+ AmmStatus::Disabled => false,
301
+ AmmStatus::WithdrawOnly => false,
302
+ AmmStatus::LiquidityOnly => false,
303
+ AmmStatus::OrderBookOnly => false,
304
+ AmmStatus::SwapOnly => true,
305
+ AmmStatus::WaitingTrade => true,
306
+ }
307
+ }
308
+
309
+ pub fn orderbook_permission(&self) -> bool {
310
+ match self {
311
+ AmmStatus::Uninitialized => false,
312
+ AmmStatus::Initialized => true,
313
+ AmmStatus::Disabled => false,
314
+ AmmStatus::WithdrawOnly => false,
315
+ AmmStatus::LiquidityOnly => false,
316
+ AmmStatus::OrderBookOnly => true,
317
+ AmmStatus::SwapOnly => false,
318
+ AmmStatus::WaitingTrade => false,
319
+ }
320
+ }
321
+ }
322
+
323
+ #[repr(u64)]
324
+ pub enum AmmState {
325
+ InvalidState = 0u64,
326
+ IdleState = 1u64,
327
+ CancelAllOrdersState = 2u64,
328
+ PlanOrdersState = 3u64,
329
+ CancelOrderState = 4u64,
330
+ PlaceOrdersState = 5u64,
331
+ PurgeOrderState = 6u64,
332
+ }
333
+ impl AmmState {
334
+ pub fn from_u64(state: u64) -> Self {
335
+ match state {
336
+ 0u64 => AmmState::InvalidState,
337
+ 1u64 => AmmState::IdleState,
338
+ 2u64 => AmmState::CancelAllOrdersState,
339
+ 3u64 => AmmState::PlanOrdersState,
340
+ 4u64 => AmmState::CancelOrderState,
341
+ 5u64 => AmmState::PlaceOrdersState,
342
+ 6u64 => AmmState::PurgeOrderState,
343
+ _ => unreachable!(),
344
+ }
345
+ }
346
+
347
+ pub fn into_u64(&self) -> u64 {
348
+ match self {
349
+ AmmState::InvalidState => 0u64,
350
+ AmmState::IdleState => 1u64,
351
+ AmmState::CancelAllOrdersState => 2u64,
352
+ AmmState::PlanOrdersState => 3u64,
353
+ AmmState::CancelOrderState => 4u64,
354
+ AmmState::PlaceOrdersState => 5u64,
355
+ AmmState::PurgeOrderState => 6u64,
356
+ }
357
+ }
358
+ pub fn valid_state(state: u64) -> bool {
359
+ match state {
360
+ 0u64 | 1u64 | 2u64 | 3u64 | 4u64 | 5u64 | 6u64 => return true,
361
+ _ => return false,
362
+ }
363
+ }
364
+ }
365
+
366
+ #[cfg_attr(feature = "client", derive(Debug))]
367
+ #[derive(Copy, Clone)]
368
+ #[repr(u64)]
369
+ pub enum AmmParams {
370
+ Status = 0u64,
371
+ State = 1u64,
372
+ Fees = 2u64,
373
+ SetOpenTime = 3u64,
374
+ }
375
+ impl AmmParams {
376
+ pub fn from_u64(state: u64) -> Result<Self, ProgramError> {
377
+ match state {
378
+ 0u64 => Ok(AmmParams::Status),
379
+ 1u64 => Ok(AmmParams::State),
380
+ 2u64 => Ok(AmmParams::Fees),
381
+ 3u64 => Ok(AmmParams::SetOpenTime),
382
+ _ => return Err(ProgramError::InvalidInstructionData.into()),
383
+ }
384
+ }
385
+
386
+ pub fn into_u64(&self) -> u64 {
387
+ match self {
388
+ AmmParams::Status => 0u64,
389
+ AmmParams::State => 1u64,
390
+ AmmParams::Fees => 2u64,
391
+ AmmParams::SetOpenTime => 3u64,
392
+ }
393
+ }
394
+ }
395
+
396
+ #[cfg_attr(feature = "client", derive(Debug))]
397
+ #[derive(Copy, Clone, Eq, PartialEq)]
398
+ #[repr(u64)]
399
+ pub enum AmmResetFlag {
400
+ ResetYes = 0u64,
401
+ ResetNo = 1u64,
402
+ }
403
+ impl AmmResetFlag {
404
+ pub fn from_u64(flag: u64) -> Self {
405
+ match flag {
406
+ 0u64 => AmmResetFlag::ResetYes,
407
+ 1u64 => AmmResetFlag::ResetNo,
408
+ _ => unreachable!(),
409
+ }
410
+ }
411
+
412
+ pub fn into_u64(&self) -> u64 {
413
+ match self {
414
+ AmmResetFlag::ResetYes => 0u64,
415
+ AmmResetFlag::ResetNo => 1u64,
416
+ }
417
+ }
418
+ }
419
+
420
+ fn validate_fraction(numerator: u64, denominator: u64) -> Result<(), AmmError> {
421
+ if numerator >= denominator || denominator == 0 {
422
+ Err(AmmError::InvalidFee)
423
+ } else {
424
+ Ok(())
425
+ }
426
+ }
427
+
428
+ #[repr(C, packed)]
429
+ #[derive(Clone, Copy, Debug, Default, PartialEq)]
430
+ pub struct Fees {
431
+ /// numerator of the min_separate
432
+ pub min_separate_numerator: u64,
433
+ /// denominator of the min_separate
434
+ pub min_separate_denominator: u64,
435
+
436
+ /// numerator of the fee
437
+ pub trade_fee_numerator: u64,
438
+ /// denominator of the fee
439
+ /// and 'trade_fee_denominator' must be equal to 'min_separate_denominator'
440
+ pub trade_fee_denominator: u64,
441
+
442
+ /// numerator of the pnl
443
+ pub pnl_numerator: u64,
444
+ /// denominator of the pnl
445
+ pub pnl_denominator: u64,
446
+
447
+ /// numerator of the swap_fee
448
+ pub swap_fee_numerator: u64,
449
+ /// denominator of the swap_fee
450
+ pub swap_fee_denominator: u64,
451
+ }
452
+
453
+ impl Fees {
454
+ /// Validate that the fees are reasonable
455
+ pub fn validate(&self) -> Result<(), AmmError> {
456
+ validate_fraction(self.min_separate_numerator, self.min_separate_denominator)?;
457
+ validate_fraction(self.trade_fee_numerator, self.trade_fee_denominator)?;
458
+ validate_fraction(self.pnl_numerator, self.pnl_denominator)?;
459
+ validate_fraction(self.swap_fee_numerator, self.swap_fee_denominator)?;
460
+ Ok(())
461
+ }
462
+
463
+ pub fn initialize(&mut self) -> Result<(), AmmError> {
464
+ // min_separate = 5/10000
465
+ self.min_separate_numerator = 5;
466
+ self.min_separate_denominator = TEN_THOUSAND;
467
+ // trade_fee = 25/10000
468
+ self.trade_fee_numerator = 25;
469
+ self.trade_fee_denominator = TEN_THOUSAND;
470
+ // pnl = 12/100
471
+ self.pnl_numerator = 12;
472
+ self.pnl_denominator = 100;
473
+ // swap_fee = 25 / 10000
474
+ self.swap_fee_numerator = 25;
475
+ self.swap_fee_denominator = TEN_THOUSAND;
476
+ Ok(())
477
+ }
478
+ }
479
+
480
+ /// IsInitialized is required to use `Pack::pack` and `Pack::unpack`
481
+ impl IsInitialized for Fees {
482
+ fn is_initialized(&self) -> bool {
483
+ true
484
+ }
485
+ }
486
+
487
+ impl Sealed for Fees {}
488
+ impl Pack for Fees {
489
+ const LEN: usize = 64;
490
+ fn pack_into_slice(&self, output: &mut [u8]) {
491
+ let output = array_mut_ref![output, 0, 64];
492
+ let (
493
+ min_separate_numerator,
494
+ min_separate_denominator,
495
+ trade_fee_numerator,
496
+ trade_fee_denominator,
497
+ pnl_numerator,
498
+ pnl_denominator,
499
+ swap_fee_numerator,
500
+ swap_fee_denominator,
501
+ ) = mut_array_refs![output, 8, 8, 8, 8, 8, 8, 8, 8];
502
+ *min_separate_numerator = self.min_separate_numerator.to_le_bytes();
503
+ *min_separate_denominator = self.min_separate_denominator.to_le_bytes();
504
+ *trade_fee_numerator = self.trade_fee_numerator.to_le_bytes();
505
+ *trade_fee_denominator = self.trade_fee_denominator.to_le_bytes();
506
+ *pnl_numerator = self.pnl_numerator.to_le_bytes();
507
+ *pnl_denominator = self.pnl_denominator.to_le_bytes();
508
+ *swap_fee_numerator = self.swap_fee_numerator.to_le_bytes();
509
+ *swap_fee_denominator = self.swap_fee_denominator.to_le_bytes();
510
+ }
511
+
512
+ fn unpack_from_slice(input: &[u8]) -> Result<Fees, ProgramError> {
513
+ let input = array_ref![input, 0, 64];
514
+ #[allow(clippy::ptr_offset_with_cast)]
515
+ let (
516
+ min_separate_numerator,
517
+ min_separate_denominator,
518
+ trade_fee_numerator,
519
+ trade_fee_denominator,
520
+ pnl_numerator,
521
+ pnl_denominator,
522
+ swap_fee_numerator,
523
+ swap_fee_denominator,
524
+ ) = array_refs![input, 8, 8, 8, 8, 8, 8, 8, 8];
525
+ Ok(Self {
526
+ min_separate_numerator: u64::from_le_bytes(*min_separate_numerator),
527
+ min_separate_denominator: u64::from_le_bytes(*min_separate_denominator),
528
+ trade_fee_numerator: u64::from_le_bytes(*trade_fee_numerator),
529
+ trade_fee_denominator: u64::from_le_bytes(*trade_fee_denominator),
530
+ pnl_numerator: u64::from_le_bytes(*pnl_numerator),
531
+ pnl_denominator: u64::from_le_bytes(*pnl_denominator),
532
+ swap_fee_numerator: u64::from_le_bytes(*swap_fee_numerator),
533
+ swap_fee_denominator: u64::from_le_bytes(*swap_fee_denominator),
534
+ })
535
+ }
536
+ }
537
+
538
+ #[repr(C, packed)]
539
+ #[derive(Clone, Copy, Debug, Default, PartialEq)]
540
+ pub struct StateData {
541
+ /// delay to take pnl coin
542
+ pub need_take_pnl_coin: u64,
543
+ /// delay to take pnl pc
544
+ pub need_take_pnl_pc: u64,
545
+ /// Deprecated field.
546
+ /// No longer in use or updated.
547
+ pub total_pnl_pc: u64,
548
+ /// Deprecated field.
549
+ /// No longer in use or updated.
550
+ pub total_pnl_coin: u64,
551
+ /// pool open time
552
+ pub pool_open_time: u64,
553
+ /// padding for future updates
554
+ pub padding: [u64; 2],
555
+ /// Deprecated field.
556
+ /// No longer in use or updated.
557
+ pub orderbook_to_init_time: u64,
558
+
559
+ /// Deprecated field.
560
+ /// No longer in use or updated.
561
+ pub swap_coin_in_amount: u128,
562
+ /// Deprecated field.
563
+ /// No longer in use or updated.
564
+ pub swap_pc_out_amount: u128,
565
+ /// Deprecated field.
566
+ /// No longer in use or updated.
567
+ pub swap_acc_pc_fee: u64,
568
+
569
+ /// Deprecated field.
570
+ /// No longer in use or updated.
571
+ pub swap_pc_in_amount: u128,
572
+ /// Deprecated field.
573
+ /// No longer in use or updated.
574
+ pub swap_coin_out_amount: u128,
575
+ /// Deprecated field.
576
+ /// No longer in use or updated.
577
+ pub swap_acc_coin_fee: u64,
578
+ }
579
+
580
+ impl StateData {
581
+ pub fn initialize(&mut self, open_time: u64) -> Result<(), AmmError> {
582
+ self.need_take_pnl_coin = 0u64;
583
+ self.need_take_pnl_pc = 0u64;
584
+ self.total_pnl_pc = 0u64;
585
+ self.total_pnl_coin = 0u64;
586
+ self.pool_open_time = open_time;
587
+ self.padding = Zeroable::zeroed();
588
+ self.orderbook_to_init_time = 0u64;
589
+ self.swap_coin_in_amount = 0u128;
590
+ self.swap_pc_out_amount = 0u128;
591
+ self.swap_acc_pc_fee = 0u64;
592
+ self.swap_pc_in_amount = 0u128;
593
+ self.swap_coin_out_amount = 0u128;
594
+ self.swap_acc_coin_fee = 0u64;
595
+
596
+ Ok(())
597
+ }
598
+ }
599
+
600
+ #[cfg_attr(feature = "client", derive(Debug))]
601
+ #[repr(C, packed)]
602
+ #[derive(Clone, Copy, Default, PartialEq)]
603
+ pub struct AmmInfo {
604
+ /// Initialized status.
605
+ pub status: u64,
606
+ /// Nonce used in program address.
607
+ /// The program address is created deterministically with the nonce,
608
+ /// amm program id, and amm account pubkey. This program address has
609
+ /// authority over the amm's token coin account, token pc account, and pool
610
+ /// token mint.
611
+ pub nonce: u64,
612
+ /// max order count
613
+ pub order_num: u64,
614
+ /// within this range, 5 => 5% range
615
+ pub depth: u64,
616
+ /// coin decimal
617
+ pub coin_decimals: u64,
618
+ /// pc decimal
619
+ pub pc_decimals: u64,
620
+ /// amm machine state
621
+ pub state: u64,
622
+ /// amm reset_flag
623
+ pub reset_flag: u64,
624
+ /// min size 1->0.000001
625
+ pub min_size: u64,
626
+ /// vol_max_cut_ratio numerator, sys_decimal_value as denominator
627
+ pub vol_max_cut_ratio: u64,
628
+ /// amount wave numerator, sys_decimal_value as denominator
629
+ pub amount_wave: u64,
630
+ /// coinLotSize 1 -> 0.000001
631
+ pub coin_lot_size: u64,
632
+ /// pcLotSize 1 -> 0.000001
633
+ pub pc_lot_size: u64,
634
+ /// min_cur_price: (2 * amm.order_num * amm.pc_lot_size) * max_price_multiplier
635
+ pub min_price_multiplier: u64,
636
+ /// max_cur_price: (2 * amm.order_num * amm.pc_lot_size) * max_price_multiplier
637
+ pub max_price_multiplier: u64,
638
+ /// system decimal value, used to normalize the value of coin and pc amount
639
+ pub sys_decimal_value: u64,
640
+ /// All fee information
641
+ pub fees: Fees,
642
+ /// Statistical data
643
+ pub state_data: StateData,
644
+ /// Coin vault
645
+ pub coin_vault: Pubkey,
646
+ /// Pc vault
647
+ pub pc_vault: Pubkey,
648
+ /// Coin vault mint
649
+ pub coin_vault_mint: Pubkey,
650
+ /// Pc vault mint
651
+ pub pc_vault_mint: Pubkey,
652
+ /// lp mint
653
+ pub lp_mint: Pubkey,
654
+ /// open_orders key
655
+ pub open_orders: Pubkey,
656
+ /// market key
657
+ pub market: Pubkey,
658
+ /// market program key
659
+ pub market_program: Pubkey,
660
+ /// target_orders key
661
+ pub target_orders: Pubkey,
662
+ /// padding
663
+ pub padding1: [u64; 8],
664
+ /// amm owner key
665
+ pub amm_owner: Pubkey,
666
+ /// pool lp amount
667
+ pub lp_amount: u64,
668
+ /// client order id
669
+ pub client_order_id: u64,
670
+ /// recent epoch
671
+ pub recent_epoch: u64,
672
+ /// padding
673
+ pub padding2: u64,
674
+ }
675
+ impl_loadable!(AmmInfo);
676
+
677
+ impl AmmInfo {
678
+ /// Helper function to get the more efficient packed size of the struct
679
+ /// load_mut_checked
680
+ #[inline]
681
+ pub fn load_mut_checked<'a>(
682
+ account: &'a AccountInfo,
683
+ program_id: &Pubkey,
684
+ ) -> Result<RefMut<'a, Self>, ProgramError> {
685
+ if account.owner != program_id {
686
+ return Err(AmmError::InvalidAmmAccountOwner.into());
687
+ }
688
+ if account.data_len() != size_of::<Self>() {
689
+ return Err(AmmError::ExpectedAccount.into());
690
+ }
691
+ let data = Self::load_mut(account)?;
692
+ if data.status == AmmStatus::Uninitialized as u64 {
693
+ return Err(AmmError::InvalidStatus.into());
694
+ }
695
+ Ok(data)
696
+ }
697
+
698
+ /// load_checked
699
+ #[inline]
700
+ pub fn load_checked<'a>(
701
+ account: &'a AccountInfo,
702
+ program_id: &Pubkey,
703
+ ) -> Result<Ref<'a, Self>, ProgramError> {
704
+ if account.owner != program_id {
705
+ return Err(AmmError::InvalidAmmAccountOwner.into());
706
+ }
707
+ if account.data_len() != size_of::<Self>() {
708
+ return Err(AmmError::ExpectedAccount.into());
709
+ }
710
+ let data = Self::load(account)?;
711
+ if data.status == AmmStatus::Uninitialized as u64 {
712
+ return Err(AmmError::InvalidStatus.into());
713
+ }
714
+ Ok(data)
715
+ }
716
+
717
+ pub fn initialize(
718
+ &mut self,
719
+ nonce: u8,
720
+ open_time: u64,
721
+ coin_decimals: u8,
722
+ pc_decimals: u8,
723
+ _coin_lot_size: u64,
724
+ _pc_lot_size: u64,
725
+ ) -> Result<(), AmmError> {
726
+ self.fees.initialize()?;
727
+ self.state_data.initialize(open_time)?;
728
+
729
+ self.status = AmmStatus::Uninitialized.into_u64();
730
+ self.nonce = nonce as u64;
731
+ self.order_num = 7;
732
+ self.depth = 3;
733
+ self.coin_decimals = coin_decimals as u64;
734
+ self.pc_decimals = pc_decimals as u64;
735
+ self.state = AmmState::IdleState.into_u64();
736
+ self.reset_flag = AmmResetFlag::ResetNo.into_u64();
737
+ if pc_decimals > coin_decimals {
738
+ self.sys_decimal_value = (10 as u64)
739
+ .checked_pow(pc_decimals.try_into().unwrap())
740
+ .unwrap();
741
+ } else {
742
+ self.sys_decimal_value = (10 as u64)
743
+ .checked_pow(coin_decimals.try_into().unwrap())
744
+ .unwrap();
745
+ }
746
+
747
+ self.min_size = 0;
748
+
749
+ self.vol_max_cut_ratio = 500; // TEN_THOUSAND as denominator
750
+ self.amount_wave = self
751
+ .sys_decimal_value
752
+ .checked_mul(5)
753
+ .unwrap()
754
+ .checked_div(1000)
755
+ .unwrap();
756
+ self.coin_lot_size = 0;
757
+ self.pc_lot_size = 0;
758
+ self.min_price_multiplier = 1;
759
+ self.max_price_multiplier = 1000000000;
760
+ self.client_order_id = 0;
761
+ self.padding1 = Zeroable::zeroed();
762
+ self.recent_epoch = get_recent_epoch().unwrap();
763
+ self.padding2 = Zeroable::zeroed();
764
+
765
+ Ok(())
766
+ }
767
+
768
+ pub fn incr_client_order_id(&mut self) -> u64 {
769
+ self.client_order_id = self.client_order_id.wrapping_add(1);
770
+ if self.client_order_id == 0 {
771
+ self.client_order_id += 1;
772
+ }
773
+ self.client_order_id
774
+ }
775
+ }
776
+
777
+ /// State of amm config account
778
+ #[repr(C, packed)]
779
+ #[derive(Clone, Copy, Debug, Default, PartialEq)]
780
+ pub struct AmmConfig {
781
+ /// withdraw pnl owner
782
+ pub pnl_owner: Pubkey,
783
+ /// admin amm order owner
784
+ pub cancel_owner: Pubkey,
785
+ /// pending
786
+ pub pending_1: [u64; 28],
787
+ /// pending
788
+ pub pending_2: [u64; 31],
789
+ /// init amm pool fee amount
790
+ pub create_pool_fee: u64,
791
+ }
792
+ impl_loadable!(AmmConfig);
793
+
794
+ impl AmmConfig {
795
+ /// Helper function to get the more efficient packed size of the struct
796
+ /// load_mut_checked
797
+ #[inline]
798
+ pub fn load_mut_checked<'a>(
799
+ account: &'a AccountInfo,
800
+ program_id: &Pubkey,
801
+ ) -> Result<RefMut<'a, Self>, ProgramError> {
802
+ if account.owner != program_id {
803
+ return Err(AmmError::InvalidOwner.into());
804
+ }
805
+ if account.data_len() != size_of::<Self>() {
806
+ return Err(AmmError::ExpectedAccount.into());
807
+ }
808
+ let data = Self::load_mut(account)?;
809
+ Ok(data)
810
+ }
811
+
812
+ /// load_checked
813
+ #[inline]
814
+ pub fn load_checked<'a>(
815
+ account: &'a AccountInfo,
816
+ program_id: &Pubkey,
817
+ ) -> Result<Ref<'a, Self>, ProgramError> {
818
+ if account.owner != program_id {
819
+ return Err(AmmError::InvalidOwner.into());
820
+ }
821
+ if account.data_len() != size_of::<Self>() {
822
+ return Err(AmmError::ExpectedAccount.into());
823
+ }
824
+ let data = Self::load(account)?;
825
+ Ok(data)
826
+ }
827
+ }
828
+
829
+ #[cfg(test)]
830
+ mod test {
831
+ use super::*;
832
+
833
+ #[test]
834
+ fn test_amm_info_layout() {
835
+ let status: u64 = 0x123456789abcdef0;
836
+ let nonce: u64 = 0x123456789abcde0f;
837
+ let order_num: u64 = 0x123456789abcd0ef;
838
+ let depth: u64 = 0x123456789abc0def;
839
+ let coin_decimals: u64 = 0x123456789ab0cdef;
840
+ let pc_decimals: u64 = 0x123456789a0bcdef;
841
+ let state: u64 = 0x1234567890abcdef;
842
+ let reset_flag: u64 = 0x1234567809abcdef;
843
+ let min_size: u64 = 0x1234567089abcdef;
844
+ let vol_max_cut_ratio: u64 = 0x1234560789abcdef;
845
+ let amount_wave: u64 = 0x1234506789abcdef;
846
+ let coin_lot_size: u64 = 0x1234056789abcdef;
847
+ let pc_lot_size: u64 = 0x1230456789abcdef;
848
+ let min_price_multiplier: u64 = 0x1203456789abcdef;
849
+ let max_price_multiplier: u64 = 0x1023456789abcdef;
850
+ let sys_decimal_value: u64 = 0x123456789abcdfe0;
851
+
852
+ let min_separate_numerator: u64 = 0x123456789abcfde0;
853
+ let min_separate_denominator: u64 = 0x123456789abfcde0;
854
+ let trade_fee_numerator: u64 = 0x123456789afbcde0;
855
+ let trade_fee_denominator: u64 = 0x123456789fabcde0;
856
+ let pnl_numerator: u64 = 0x12345678f9abcde0;
857
+ let pnl_denominator: u64 = 0x1234567f89abcde0;
858
+ let swap_fee_numerator: u64 = 0x123456f789abcde0;
859
+ let swap_fee_denominator: u64 = 0x12345f6789abcde0;
860
+
861
+ let need_take_pnl_coin: u64 = 0x1234f56789abcde0;
862
+ let need_take_pnl_pc: u64 = 0x123f456789abcde0;
863
+ let total_pnl_pc: u64 = 0x12f3456789abcde0;
864
+ let total_pnl_coin: u64 = 0x1f23456789abcde0;
865
+ let pool_open_time: u64 = 0x123456789abcedf0;
866
+ let padding: [u64; 2] = [0x123456789abecdf0, 0x123456789aebcdf0];
867
+ let orderbook_to_init_time: u64 = 0x123456789eabcdf0;
868
+ let swap_coin_in_amount: u128 = 0x11002233445566778899aabbccddeeff;
869
+ let swap_pc_out_amount: u128 = 0x11220033445566778899aabbccddeeff;
870
+ let swap_acc_pc_fee: u64 = 0x12345678e9abcdf0;
871
+ let swap_pc_in_amount: u128 = 0x11223300445566778899aabbccddeeff;
872
+ let swap_coin_out_amount: u128 = 0x11223344005566778899aabbccddeeff;
873
+ let swap_acc_coin_fee: u64 = 0x1234567e89abcdf0;
874
+
875
+ let coin_vault = Pubkey::new_unique();
876
+ let pc_vault = Pubkey::new_unique();
877
+ let coin_vault_mint = Pubkey::new_unique();
878
+ let pc_vault_mint = Pubkey::new_unique();
879
+ let lp_mint = Pubkey::new_unique();
880
+ let open_orders = Pubkey::new_unique();
881
+ let market = Pubkey::new_unique();
882
+ let market_program = Pubkey::new_unique();
883
+ let target_orders = Pubkey::new_unique();
884
+
885
+ let mut padding1: [u64; 8] = [0u64; 8];
886
+ let mut padding1_data = [0u8; 8 * 8];
887
+ let mut offset = 0;
888
+ for i in 0..8 {
889
+ padding1[i] = u64::MAX - i as u64;
890
+ padding1_data[offset..offset + 8].copy_from_slice(&padding1[i].to_le_bytes());
891
+ offset += 8;
892
+ }
893
+ let amm_owner = Pubkey::new_unique();
894
+ let lp_amount: u64 = 0x123456e789abcdf0;
895
+ let client_order_id: u64 = 0x12345e6789abcdf0;
896
+ let recent_epoch: u64 = 0x1234e56789abcdf0;
897
+ let padding2: u64 = 0x123e456789abcdf0;
898
+
899
+ // serialize original data
900
+ let mut pool_data = [0u8; 752];
901
+ let mut offset = 0;
902
+ pool_data[offset..offset + 8].copy_from_slice(&status.to_le_bytes());
903
+ offset += 8;
904
+ pool_data[offset..offset + 8].copy_from_slice(&nonce.to_le_bytes());
905
+ offset += 8;
906
+ pool_data[offset..offset + 8].copy_from_slice(&order_num.to_le_bytes());
907
+ offset += 8;
908
+ pool_data[offset..offset + 8].copy_from_slice(&depth.to_le_bytes());
909
+ offset += 8;
910
+ pool_data[offset..offset + 8].copy_from_slice(&coin_decimals.to_le_bytes());
911
+ offset += 8;
912
+ pool_data[offset..offset + 8].copy_from_slice(&pc_decimals.to_le_bytes());
913
+ offset += 8;
914
+ pool_data[offset..offset + 8].copy_from_slice(&state.to_le_bytes());
915
+ offset += 8;
916
+ pool_data[offset..offset + 8].copy_from_slice(&reset_flag.to_le_bytes());
917
+ offset += 8;
918
+ pool_data[offset..offset + 8].copy_from_slice(&min_size.to_le_bytes());
919
+ offset += 8;
920
+ pool_data[offset..offset + 8].copy_from_slice(&vol_max_cut_ratio.to_le_bytes());
921
+ offset += 8;
922
+ pool_data[offset..offset + 8].copy_from_slice(&amount_wave.to_le_bytes());
923
+ offset += 8;
924
+ pool_data[offset..offset + 8].copy_from_slice(&coin_lot_size.to_le_bytes());
925
+ offset += 8;
926
+ pool_data[offset..offset + 8].copy_from_slice(&pc_lot_size.to_le_bytes());
927
+ offset += 8;
928
+ pool_data[offset..offset + 8].copy_from_slice(&min_price_multiplier.to_le_bytes());
929
+ offset += 8;
930
+ pool_data[offset..offset + 8].copy_from_slice(&max_price_multiplier.to_le_bytes());
931
+ offset += 8;
932
+ pool_data[offset..offset + 8].copy_from_slice(&sys_decimal_value.to_le_bytes());
933
+ offset += 8;
934
+
935
+ pool_data[offset..offset + 8].copy_from_slice(&min_separate_numerator.to_le_bytes());
936
+ offset += 8;
937
+ pool_data[offset..offset + 8].copy_from_slice(&min_separate_denominator.to_le_bytes());
938
+ offset += 8;
939
+ pool_data[offset..offset + 8].copy_from_slice(&trade_fee_numerator.to_le_bytes());
940
+ offset += 8;
941
+ pool_data[offset..offset + 8].copy_from_slice(&trade_fee_denominator.to_le_bytes());
942
+ offset += 8;
943
+ pool_data[offset..offset + 8].copy_from_slice(&pnl_numerator.to_le_bytes());
944
+ offset += 8;
945
+ pool_data[offset..offset + 8].copy_from_slice(&pnl_denominator.to_le_bytes());
946
+ offset += 8;
947
+ pool_data[offset..offset + 8].copy_from_slice(&swap_fee_numerator.to_le_bytes());
948
+ offset += 8;
949
+ pool_data[offset..offset + 8].copy_from_slice(&swap_fee_denominator.to_le_bytes());
950
+ offset += 8;
951
+
952
+ pool_data[offset..offset + 8].copy_from_slice(&need_take_pnl_coin.to_le_bytes());
953
+ offset += 8;
954
+ pool_data[offset..offset + 8].copy_from_slice(&need_take_pnl_pc.to_le_bytes());
955
+ offset += 8;
956
+ pool_data[offset..offset + 8].copy_from_slice(&total_pnl_pc.to_le_bytes());
957
+ offset += 8;
958
+ pool_data[offset..offset + 8].copy_from_slice(&total_pnl_coin.to_le_bytes());
959
+ offset += 8;
960
+ pool_data[offset..offset + 8].copy_from_slice(&pool_open_time.to_le_bytes());
961
+ offset += 8;
962
+ pool_data[offset..offset + 8].copy_from_slice(&padding[0].to_le_bytes());
963
+ offset += 8;
964
+ pool_data[offset..offset + 8].copy_from_slice(&padding[1].to_le_bytes());
965
+ offset += 8;
966
+ pool_data[offset..offset + 8].copy_from_slice(&orderbook_to_init_time.to_le_bytes());
967
+ offset += 8;
968
+ pool_data[offset..offset + 16].copy_from_slice(&swap_coin_in_amount.to_le_bytes());
969
+ offset += 16;
970
+ pool_data[offset..offset + 16].copy_from_slice(&swap_pc_out_amount.to_le_bytes());
971
+ offset += 16;
972
+ pool_data[offset..offset + 8].copy_from_slice(&swap_acc_pc_fee.to_le_bytes());
973
+ offset += 8;
974
+ pool_data[offset..offset + 16].copy_from_slice(&swap_pc_in_amount.to_le_bytes());
975
+ offset += 16;
976
+ pool_data[offset..offset + 16].copy_from_slice(&swap_coin_out_amount.to_le_bytes());
977
+ offset += 16;
978
+ pool_data[offset..offset + 8].copy_from_slice(&swap_acc_coin_fee.to_le_bytes());
979
+ offset += 8;
980
+
981
+ pool_data[offset..offset + 32].copy_from_slice(&coin_vault.to_bytes());
982
+ offset += 32;
983
+ pool_data[offset..offset + 32].copy_from_slice(&pc_vault.to_bytes());
984
+ offset += 32;
985
+ pool_data[offset..offset + 32].copy_from_slice(&coin_vault_mint.to_bytes());
986
+ offset += 32;
987
+ pool_data[offset..offset + 32].copy_from_slice(&pc_vault_mint.to_bytes());
988
+ offset += 32;
989
+ pool_data[offset..offset + 32].copy_from_slice(&lp_mint.to_bytes());
990
+ offset += 32;
991
+ pool_data[offset..offset + 32].copy_from_slice(&open_orders.to_bytes());
992
+ offset += 32;
993
+ pool_data[offset..offset + 32].copy_from_slice(&market.to_bytes());
994
+ offset += 32;
995
+ pool_data[offset..offset + 32].copy_from_slice(&market_program.to_bytes());
996
+ offset += 32;
997
+ pool_data[offset..offset + 32].copy_from_slice(&target_orders.to_bytes());
998
+ offset += 32;
999
+ pool_data[offset..offset + 8 * 8].copy_from_slice(&padding1_data);
1000
+ offset += 8 * 8;
1001
+ pool_data[offset..offset + 32].copy_from_slice(&amm_owner.to_bytes());
1002
+ offset += 32;
1003
+ pool_data[offset..offset + 8].copy_from_slice(&lp_amount.to_le_bytes());
1004
+ offset += 8;
1005
+ pool_data[offset..offset + 8].copy_from_slice(&client_order_id.to_le_bytes());
1006
+ offset += 8;
1007
+ pool_data[offset..offset + 8].copy_from_slice(&recent_epoch.to_le_bytes());
1008
+ offset += 8;
1009
+ pool_data[offset..offset + 8].copy_from_slice(&padding2.to_le_bytes());
1010
+ offset += 8;
1011
+
1012
+ // len check
1013
+ assert_eq!(offset, pool_data.len());
1014
+ assert_eq!(pool_data.len(), core::mem::size_of::<AmmInfo>());
1015
+
1016
+ // deserialize original data
1017
+ let unpack_data: &AmmInfo =
1018
+ bytemuck::from_bytes(&pool_data[0..core::mem::size_of::<AmmInfo>()]);
1019
+ // data check
1020
+ let unpack_status = unpack_data.status;
1021
+ assert_eq!(status, unpack_status);
1022
+ let unpack_nonce = unpack_data.nonce;
1023
+ assert_eq!(nonce, unpack_nonce);
1024
+ let unpack_order_num = unpack_data.order_num;
1025
+ assert_eq!(order_num, unpack_order_num);
1026
+ let unpack_depth = unpack_data.depth;
1027
+ assert_eq!(depth, unpack_depth);
1028
+ let unpack_coin_decimals = unpack_data.coin_decimals;
1029
+ assert_eq!(coin_decimals, unpack_coin_decimals);
1030
+ let unpack_pc_decimals = unpack_data.pc_decimals;
1031
+ assert_eq!(pc_decimals, unpack_pc_decimals);
1032
+ let unpack_state = unpack_data.state;
1033
+ assert_eq!(state, unpack_state);
1034
+ let unpack_reset_flag = unpack_data.reset_flag;
1035
+ assert_eq!(reset_flag, unpack_reset_flag);
1036
+ let unpack_min_size = unpack_data.min_size;
1037
+ assert_eq!(min_size, unpack_min_size);
1038
+ let unpack_vol_max_cut_ratio = unpack_data.vol_max_cut_ratio;
1039
+ assert_eq!(vol_max_cut_ratio, unpack_vol_max_cut_ratio);
1040
+ let unpack_amount_wave = unpack_data.amount_wave;
1041
+ assert_eq!(amount_wave, unpack_amount_wave);
1042
+ let unpack_coin_lot_size = unpack_data.coin_lot_size;
1043
+ assert_eq!(coin_lot_size, unpack_coin_lot_size);
1044
+ let unpack_pc_lot_size = unpack_data.pc_lot_size;
1045
+ assert_eq!(pc_lot_size, unpack_pc_lot_size);
1046
+ let unpack_min_price_multiplier = unpack_data.min_price_multiplier;
1047
+ assert_eq!(min_price_multiplier, unpack_min_price_multiplier);
1048
+ let unpack_max_price_multiplier = unpack_data.max_price_multiplier;
1049
+ assert_eq!(max_price_multiplier, unpack_max_price_multiplier);
1050
+ let unpack_sys_decimal_value = unpack_data.sys_decimal_value;
1051
+ assert_eq!(sys_decimal_value, unpack_sys_decimal_value);
1052
+ let unpack_min_separate_numerator = unpack_data.fees.min_separate_numerator;
1053
+ assert_eq!(min_separate_numerator, unpack_min_separate_numerator);
1054
+ let unpack_min_separate_denominator = unpack_data.fees.min_separate_denominator;
1055
+ assert_eq!(min_separate_denominator, unpack_min_separate_denominator);
1056
+ let unpack_trade_fee_numerator = unpack_data.fees.trade_fee_numerator;
1057
+ assert_eq!(trade_fee_numerator, unpack_trade_fee_numerator);
1058
+ let unpack_trade_fee_denominator = unpack_data.fees.trade_fee_denominator;
1059
+ assert_eq!(trade_fee_denominator, unpack_trade_fee_denominator);
1060
+ let unpack_pnl_numerator = unpack_data.fees.pnl_numerator;
1061
+ assert_eq!(pnl_numerator, unpack_pnl_numerator);
1062
+ let unpack_pnl_denominator = unpack_data.fees.pnl_denominator;
1063
+ assert_eq!(pnl_denominator, unpack_pnl_denominator);
1064
+ let unpack_swap_fee_numerator = unpack_data.fees.swap_fee_numerator;
1065
+ assert_eq!(swap_fee_numerator, unpack_swap_fee_numerator);
1066
+ let unpack_swap_fee_denominator = unpack_data.fees.swap_fee_denominator;
1067
+ assert_eq!(swap_fee_denominator, unpack_swap_fee_denominator);
1068
+ let unpack_need_take_pnl_coin = unpack_data.state_data.need_take_pnl_coin;
1069
+ assert_eq!(need_take_pnl_coin, unpack_need_take_pnl_coin);
1070
+ let unpack_need_take_pnl_pc = unpack_data.state_data.need_take_pnl_pc;
1071
+ assert_eq!(need_take_pnl_pc, unpack_need_take_pnl_pc);
1072
+ let unpack_total_pnl_pc = unpack_data.state_data.total_pnl_pc;
1073
+ assert_eq!(total_pnl_pc, unpack_total_pnl_pc);
1074
+ let unpack_total_pnl_coin = unpack_data.state_data.total_pnl_coin;
1075
+ assert_eq!(total_pnl_coin, unpack_total_pnl_coin);
1076
+ let unpack_pool_open_time = unpack_data.state_data.pool_open_time;
1077
+ assert_eq!(pool_open_time, unpack_pool_open_time);
1078
+ for i in 0..2 {
1079
+ let unpack_padding = unpack_data.state_data.padding[i];
1080
+ assert_eq!(padding[i], unpack_padding);
1081
+ }
1082
+ let unpack_orderbook_to_init_time = unpack_data.state_data.orderbook_to_init_time;
1083
+ assert_eq!(orderbook_to_init_time, unpack_orderbook_to_init_time);
1084
+ let unpack_swap_coin_in_amount = unpack_data.state_data.swap_coin_in_amount;
1085
+ assert_eq!(swap_coin_in_amount, unpack_swap_coin_in_amount);
1086
+ let unpack_swap_pc_out_amount = unpack_data.state_data.swap_pc_out_amount;
1087
+ assert_eq!(swap_pc_out_amount, unpack_swap_pc_out_amount);
1088
+ let unpack_swap_acc_pc_fee = unpack_data.state_data.swap_acc_pc_fee;
1089
+ assert_eq!(swap_acc_pc_fee, unpack_swap_acc_pc_fee);
1090
+ let unpack_swap_pc_in_amount = unpack_data.state_data.swap_pc_in_amount;
1091
+ assert_eq!(swap_pc_in_amount, unpack_swap_pc_in_amount);
1092
+ let unpack_swap_coin_out_amount = unpack_data.state_data.swap_coin_out_amount;
1093
+ assert_eq!(swap_coin_out_amount, unpack_swap_coin_out_amount);
1094
+ let unpack_swap_acc_coin_fee = unpack_data.state_data.swap_acc_coin_fee;
1095
+ assert_eq!(swap_acc_coin_fee, unpack_swap_acc_coin_fee);
1096
+ let unpack_coin_vault = unpack_data.coin_vault;
1097
+ assert_eq!(coin_vault, unpack_coin_vault);
1098
+ let unpack_pc_vault = unpack_data.pc_vault;
1099
+ assert_eq!(pc_vault, unpack_pc_vault);
1100
+ let unpack_coin_vault_mint = unpack_data.coin_vault_mint;
1101
+ assert_eq!(coin_vault_mint, unpack_coin_vault_mint);
1102
+ let unpack_pc_vault_mint = unpack_data.pc_vault_mint;
1103
+ assert_eq!(pc_vault_mint, unpack_pc_vault_mint);
1104
+ let unpack_lp_mint = unpack_data.lp_mint;
1105
+ assert_eq!(lp_mint, unpack_lp_mint);
1106
+ let unpack_open_orders = unpack_data.open_orders;
1107
+ assert_eq!(open_orders, unpack_open_orders);
1108
+ let unpack_market = unpack_data.market;
1109
+ assert_eq!(market, unpack_market);
1110
+ let unpack_market_program = unpack_data.market_program;
1111
+ assert_eq!(market_program, unpack_market_program);
1112
+ let unpack_target_orders = unpack_data.target_orders;
1113
+ assert_eq!(target_orders, unpack_target_orders);
1114
+ for i in 0..8 {
1115
+ let unpack_padding1 = unpack_data.padding1[i];
1116
+ assert_eq!(padding1[i], unpack_padding1);
1117
+ }
1118
+ let unpack_amm_owner = unpack_data.amm_owner;
1119
+ assert_eq!(amm_owner, unpack_amm_owner);
1120
+ let unpack_lp_amount = unpack_data.lp_amount;
1121
+ assert_eq!(lp_amount, unpack_lp_amount);
1122
+ let unpack_client_order_id = unpack_data.client_order_id;
1123
+ assert_eq!(client_order_id, unpack_client_order_id);
1124
+ let unpack_recent_epoch = unpack_data.recent_epoch;
1125
+ assert_eq!(recent_epoch, unpack_recent_epoch);
1126
+ let unpack_padding2 = unpack_data.padding2;
1127
+ assert_eq!(padding2, unpack_padding2);
1128
+ }
1129
+
1130
+ #[test]
1131
+ fn test_target_info_layout() {
1132
+ let owner: Pubkey = Pubkey::new_unique();
1133
+ let mut buy_orders: [TargetOrder; 50] = [TargetOrder::default(); 50];
1134
+ let mut buy_orders_data = [0u8; 8 * 2 * 50];
1135
+ let mut offset = 0;
1136
+ for i in 0..50 {
1137
+ buy_orders[i].price = u64::MAX - i as u64;
1138
+ buy_orders[i].vol = u64::MAX - 3 * i as u64;
1139
+ buy_orders_data[offset..offset + 8].copy_from_slice(&buy_orders[i].price.to_le_bytes());
1140
+ offset += 8;
1141
+ buy_orders_data[offset..offset + 8].copy_from_slice(&buy_orders[i].vol.to_le_bytes());
1142
+ offset += 8;
1143
+ }
1144
+ let mut padding1 = [0u64; 8];
1145
+ for i in 0..8 {
1146
+ padding1[i] = 1 << i;
1147
+ }
1148
+ let target_x: u128 = 0x11002233445566778899aabbccddeeff;
1149
+ let target_y: u128 = 0x11220033445566778899aabbccddeeff;
1150
+ let plan_x_buy: u128 = 0x11223300445566778899aabbccddeeff;
1151
+ let plan_y_buy: u128 = 0x11223344005566778899aabbccddeeff;
1152
+ let plan_x_sell: u128 = 0x11223344550066778899aabbccddeeff;
1153
+ let plan_y_sell: u128 = 0x11223344556600778899aabbccddeeff;
1154
+ let placed_x: u128 = 0x11223344556677008899aabbccddeeff;
1155
+ let placed_y: u128 = 0x11223344556677880099aabbccddeeff;
1156
+ let calc_pnl_x: u128 = 0x11223344556677889900aabbccddeeff;
1157
+ let calc_pnl_y: u128 = 0x112233445566778899aa00bbccddeeff;
1158
+ let mut sell_orders: [TargetOrder; 50] = [TargetOrder::default(); 50];
1159
+ let mut sell_orders_data = [0u8; 8 * 2 * 50];
1160
+ let mut offset = 0;
1161
+ for i in 0..50 {
1162
+ sell_orders[i].price = u64::MAX - (i + 50) as u64;
1163
+ sell_orders[i].vol = u64::MAX - 3 * (i + 50) as u64;
1164
+ sell_orders_data[offset..offset + 8]
1165
+ .copy_from_slice(&sell_orders[i].price.to_le_bytes());
1166
+ offset += 8;
1167
+ sell_orders_data[offset..offset + 8].copy_from_slice(&sell_orders[i].vol.to_le_bytes());
1168
+ offset += 8;
1169
+ }
1170
+ let mut padding2 = [0u64; 6];
1171
+ for i in 0..6 {
1172
+ padding2[i] = 1 << (i + 8);
1173
+ }
1174
+ let mut replace_buy_client_id = [0u64; MAX_ORDER_LIMIT];
1175
+ let mut replace_sell_client_id = [0u64; MAX_ORDER_LIMIT];
1176
+ for i in 0..MAX_ORDER_LIMIT {
1177
+ replace_buy_client_id[i] = 1 << (i + 8 + 6);
1178
+ replace_sell_client_id[i] = 1 << (i + 8 + 6 + MAX_ORDER_LIMIT);
1179
+ }
1180
+ let last_order_numerator: u64 = 0x123456789ab0cedf;
1181
+ let last_order_denominator: u64 = 0x123456789a0bcedf;
1182
+ let plan_orders_cur: u64 = 0x1234567890abcedf;
1183
+ let place_orders_cur: u64 = 0x1234567809abcedf;
1184
+ let valid_buy_order_num: u64 = 0x1234567089abcedf;
1185
+ let valid_sell_order_num: u64 = 0x1234560789abcedf;
1186
+ let mut padding3 = [0u64; 10];
1187
+ for i in 0..10 {
1188
+ padding3[i] = 1 << (i + 8 + 6 + MAX_ORDER_LIMIT + MAX_ORDER_LIMIT);
1189
+ }
1190
+ let free_slot_bits: u128 = 0x112233445566778899aabb00ccddeeff;
1191
+
1192
+ // serialize original data
1193
+ let mut target_orders_data = [0u8; 2208];
1194
+ let mut offset = 0;
1195
+
1196
+ target_orders_data[offset..offset + 32].copy_from_slice(&owner.to_bytes());
1197
+ offset += 32;
1198
+
1199
+ target_orders_data[offset..offset + 8 * 2 * 50].copy_from_slice(&buy_orders_data);
1200
+ offset += 8 * 2 * 50;
1201
+ for i in 0..8 {
1202
+ target_orders_data[offset..offset + 8].copy_from_slice(&padding1[i].to_le_bytes());
1203
+ offset += 8;
1204
+ }
1205
+ target_orders_data[offset..offset + 16].copy_from_slice(&target_x.to_le_bytes());
1206
+ offset += 16;
1207
+ target_orders_data[offset..offset + 16].copy_from_slice(&target_y.to_le_bytes());
1208
+ offset += 16;
1209
+ target_orders_data[offset..offset + 16].copy_from_slice(&plan_x_buy.to_le_bytes());
1210
+ offset += 16;
1211
+ target_orders_data[offset..offset + 16].copy_from_slice(&plan_y_buy.to_le_bytes());
1212
+ offset += 16;
1213
+ target_orders_data[offset..offset + 16].copy_from_slice(&plan_x_sell.to_le_bytes());
1214
+ offset += 16;
1215
+ target_orders_data[offset..offset + 16].copy_from_slice(&plan_y_sell.to_le_bytes());
1216
+ offset += 16;
1217
+ target_orders_data[offset..offset + 16].copy_from_slice(&placed_x.to_le_bytes());
1218
+ offset += 16;
1219
+ target_orders_data[offset..offset + 16].copy_from_slice(&placed_y.to_le_bytes());
1220
+ offset += 16;
1221
+ target_orders_data[offset..offset + 16].copy_from_slice(&calc_pnl_x.to_le_bytes());
1222
+ offset += 16;
1223
+ target_orders_data[offset..offset + 16].copy_from_slice(&calc_pnl_y.to_le_bytes());
1224
+ offset += 16;
1225
+ target_orders_data[offset..offset + 8 * 2 * 50].copy_from_slice(&sell_orders_data);
1226
+ offset += 8 * 2 * 50;
1227
+ for i in 0..6 {
1228
+ target_orders_data[offset..offset + 8].copy_from_slice(&padding2[i].to_le_bytes());
1229
+ offset += 8;
1230
+ }
1231
+ for i in 0..MAX_ORDER_LIMIT {
1232
+ target_orders_data[offset..offset + 8]
1233
+ .copy_from_slice(&replace_buy_client_id[i].to_le_bytes());
1234
+ offset += 8;
1235
+ }
1236
+ for i in 0..MAX_ORDER_LIMIT {
1237
+ target_orders_data[offset..offset + 8]
1238
+ .copy_from_slice(&replace_sell_client_id[i].to_le_bytes());
1239
+ offset += 8;
1240
+ }
1241
+ target_orders_data[offset..offset + 8].copy_from_slice(&last_order_numerator.to_le_bytes());
1242
+ offset += 8;
1243
+ target_orders_data[offset..offset + 8]
1244
+ .copy_from_slice(&last_order_denominator.to_le_bytes());
1245
+ offset += 8;
1246
+ target_orders_data[offset..offset + 8].copy_from_slice(&plan_orders_cur.to_le_bytes());
1247
+ offset += 8;
1248
+ target_orders_data[offset..offset + 8].copy_from_slice(&place_orders_cur.to_le_bytes());
1249
+ offset += 8;
1250
+ target_orders_data[offset..offset + 8].copy_from_slice(&valid_buy_order_num.to_le_bytes());
1251
+ offset += 8;
1252
+ target_orders_data[offset..offset + 8].copy_from_slice(&valid_sell_order_num.to_le_bytes());
1253
+ offset += 8;
1254
+ for i in 0..10 {
1255
+ target_orders_data[offset..offset + 8].copy_from_slice(&padding3[i].to_le_bytes());
1256
+ offset += 8;
1257
+ }
1258
+ target_orders_data[offset..offset + 16].copy_from_slice(&free_slot_bits.to_le_bytes());
1259
+ offset += 16;
1260
+
1261
+ // len check
1262
+ assert_eq!(offset, target_orders_data.len());
1263
+ assert_eq!(
1264
+ target_orders_data.len(),
1265
+ core::mem::size_of::<TargetOrders>()
1266
+ );
1267
+
1268
+ // deserialize original data
1269
+ let unpack_data: &TargetOrders =
1270
+ bytemuck::from_bytes(&target_orders_data[0..core::mem::size_of::<TargetOrders>()]);
1271
+ // data check
1272
+ let unpack_owner = unpack_data.owner;
1273
+ assert_eq!(owner, unpack_owner);
1274
+
1275
+ let unpack_buy_orders = unpack_data.buy_orders;
1276
+ for i in 0..50 {
1277
+ let price = buy_orders[i].price;
1278
+ let unpack_price = unpack_buy_orders[i].price;
1279
+ assert_eq!(price, unpack_price);
1280
+ let vol = buy_orders[i].vol;
1281
+ let unpack_vol = unpack_buy_orders[i].vol;
1282
+ assert_eq!(vol, unpack_vol);
1283
+ }
1284
+ let unpack_padding1 = unpack_data.padding1;
1285
+ for i in 0..8 {
1286
+ assert_eq!(padding1[i], unpack_padding1[i]);
1287
+ }
1288
+ let unpack_target_x = unpack_data.target_x;
1289
+ assert_eq!(target_x, unpack_target_x);
1290
+ let unpack_target_y = unpack_data.target_y;
1291
+ assert_eq!(target_y, unpack_target_y);
1292
+ let unpack_plan_x_buy = unpack_data.plan_x_buy;
1293
+ assert_eq!(plan_x_buy, unpack_plan_x_buy);
1294
+ let unpack_plan_y_buy = unpack_data.plan_y_buy;
1295
+ assert_eq!(plan_y_buy, unpack_plan_y_buy);
1296
+ let unpack_plan_x_sell = unpack_data.plan_x_sell;
1297
+ assert_eq!(plan_x_sell, unpack_plan_x_sell);
1298
+ let unpack_plan_y_sell = unpack_data.plan_y_sell;
1299
+ assert_eq!(plan_y_sell, unpack_plan_y_sell);
1300
+ let unpack_placed_x = unpack_data.placed_x;
1301
+ assert_eq!(placed_x, unpack_placed_x);
1302
+ let unpack_placed_y = unpack_data.placed_y;
1303
+ assert_eq!(placed_y, unpack_placed_y);
1304
+ let unpack_calc_pnl_x = unpack_data.calc_pnl_x;
1305
+ assert_eq!(calc_pnl_x, unpack_calc_pnl_x);
1306
+ let unpack_calc_pnl_y = unpack_data.calc_pnl_y;
1307
+ assert_eq!(calc_pnl_y, unpack_calc_pnl_y);
1308
+ let unpack_sell_orders = unpack_data.sell_orders;
1309
+ for i in 0..50 {
1310
+ let price = sell_orders[i].price;
1311
+ let unpack_price = unpack_sell_orders[i].price;
1312
+ assert_eq!(price, unpack_price);
1313
+ let vol = sell_orders[i].vol;
1314
+ let unpack_vol = unpack_sell_orders[i].vol;
1315
+ assert_eq!(vol, unpack_vol);
1316
+ }
1317
+ let unpack_padding2 = unpack_data.padding2;
1318
+ for i in 0..6 {
1319
+ assert_eq!(padding2[i], unpack_padding2[i]);
1320
+ }
1321
+ let unpack_replace_buy_client_id = unpack_data.replace_buy_client_id;
1322
+ for i in 0..MAX_ORDER_LIMIT {
1323
+ assert_eq!(replace_buy_client_id[i], unpack_replace_buy_client_id[i]);
1324
+ }
1325
+ let unpack_replace_sell_client_id = unpack_data.replace_sell_client_id;
1326
+ for i in 0..MAX_ORDER_LIMIT {
1327
+ assert_eq!(replace_sell_client_id[i], unpack_replace_sell_client_id[i]);
1328
+ }
1329
+ let unpack_last_order_numerator = unpack_data.last_order_numerator;
1330
+ assert_eq!(last_order_numerator, unpack_last_order_numerator);
1331
+ let unpack_last_order_denominator = unpack_data.last_order_denominator;
1332
+ assert_eq!(last_order_denominator, unpack_last_order_denominator);
1333
+ let unpack_plan_orders_cur = unpack_data.plan_orders_cur;
1334
+ assert_eq!(plan_orders_cur, unpack_plan_orders_cur);
1335
+ let unpack_place_orders_cur = unpack_data.place_orders_cur;
1336
+ assert_eq!(place_orders_cur, unpack_place_orders_cur);
1337
+ let unpack_valid_buy_order_num = unpack_data.valid_buy_order_num;
1338
+ assert_eq!(valid_buy_order_num, unpack_valid_buy_order_num);
1339
+ let unpack_valid_sell_order_num = unpack_data.valid_sell_order_num;
1340
+ assert_eq!(valid_sell_order_num, unpack_valid_sell_order_num);
1341
+ let unpack_padding3 = unpack_data.padding3;
1342
+ for i in 0..10 {
1343
+ assert_eq!(padding3[i], unpack_padding3[i]);
1344
+ }
1345
+ let unpack_free_slot_bits = unpack_data.free_slot_bits;
1346
+ assert_eq!(free_slot_bits, unpack_free_slot_bits);
1347
+ }
1348
+ }