sememe 0.0.0-stage → 0.4.22
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.
- package/LICENSE +21 -0
- package/README.md +2777 -2
- package/bin/sememe.mjs +556 -0
- package/index.mjs +48 -0
- package/interface/ata-ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL.json +62 -0
- package/interface/native-11111111111111111111111111111111.json +226 -0
- package/interface/native-ComputeBudget111111111111111111111111111111.json +72 -0
- package/interface/raydium-675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8.json +352 -0
- package/interface/token-TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA.json +334 -0
- package/interface/token-TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb.json +535 -0
- package/interface/token-metadata.json +132 -0
- package/package.json +71 -4
- package/src/account-list.mjs +308 -0
- package/src/account-union.mjs +523 -0
- package/src/account.mjs +199 -0
- package/src/acquire.mjs +145 -0
- package/src/adopt.mjs +206 -0
- package/src/ata-interface.mjs +276 -0
- package/src/ata.mjs +223 -0
- package/src/base58.mjs +96 -0
- package/src/canonical.mjs +24 -0
- package/src/cli-surface.mjs +300 -0
- package/src/codec.mjs +1118 -0
- package/src/conformance.mjs +431 -0
- package/src/corpus/harvest-compute-budget-2026-10-31.json +19122 -0
- package/src/corpus/harvest-system-2026-10-31.json +26090 -0
- package/src/decode.mjs +286 -0
- package/src/dialect.mjs +180 -0
- package/src/discriminators.mjs +192 -0
- package/src/drift.mjs +172 -0
- package/src/gap.mjs +205 -0
- package/src/lighthouse.mjs +168 -0
- package/src/lock.mjs +440 -0
- package/src/native-audit.mjs +56 -0
- package/src/native-corpus.mjs +57 -0
- package/src/native-interface.mjs +252 -0
- package/src/native.mjs +324 -0
- package/src/peer.mjs +95 -0
- package/src/program-id.mjs +74 -0
- package/src/pull.mjs +117 -0
- package/src/rawle.mjs +454 -0
- package/src/raydium-interface.mjs +747 -0
- package/src/raydium.mjs +391 -0
- package/src/receipt-digest.mjs +84 -0
- package/src/receipt-name.mjs +128 -0
- package/src/receipt-order.mjs +56 -0
- package/src/shank.mjs +73 -0
- package/src/short-forms.mjs +209 -0
- package/src/store-read.mjs +253 -0
- package/src/store-write.mjs +46 -0
- package/src/token-interface.mjs +394 -0
- package/src/token-metadata-interface.mjs +371 -0
- package/src/token-metadata.mjs +317 -0
- package/src/token.mjs +443 -0
- package/src/union.mjs +428 -0
- package/vendor/anza-solana-sdk/8db406e2edfafa25939ec782b77b5b6f30de164d/LICENSE.txt +201 -0
- package/vendor/anza-solana-sdk/8db406e2edfafa25939ec782b77b5b6f30de164d/compute-budget-interface/src/lib.rs +93 -0
- package/vendor/anza-solana-sdk/8db406e2edfafa25939ec782b77b5b6f30de164d/system-interface/src/instruction.rs +1899 -0
- package/vendor/lighthouse/4c579479c98635e419b1b167f08be02a71604a71/LICENSE +21 -0
- package/vendor/lighthouse/4c579479c98635e419b1b167f08be02a71604a71/lighthouse.json +2769 -0
- package/vendor/raydium-amm/91739d8d9f5cf347e0ce14ebe4d2bb7069fb31b6/LICENSE +201 -0
- package/vendor/raydium-amm/91739d8d9f5cf347e0ce14ebe4d2bb7069fb31b6/program/src/instruction.rs +1189 -0
- package/vendor/raydium-amm/91739d8d9f5cf347e0ce14ebe4d2bb7069fb31b6/program/src/state.rs +1348 -0
- package/vendor/spl-associated-token-account/fbf5379e7398ac8b231c73ee8a9ff677b43dd0ec/LICENSE +201 -0
- package/vendor/spl-associated-token-account/fbf5379e7398ac8b231c73ee8a9ff677b43dd0ec/interface/src/instruction.rs +169 -0
- package/vendor/spl-associated-token-account/fbf5379e7398ac8b231c73ee8a9ff677b43dd0ec/interface/src/lib.rs +12 -0
- package/vendor/spl-associated-token-account/fbf5379e7398ac8b231c73ee8a9ff677b43dd0ec/program/src/processor.rs +308 -0
- package/vendor/spl-token/737788ff5bcc3f1f44cfb222f25483187650be76/LICENSE.txt +176 -0
- package/vendor/spl-token/737788ff5bcc3f1f44cfb222f25483187650be76/interface/src/instruction.rs +1963 -0
- package/vendor/spl-token-2022/5251dcc07ecbcb721d6c4f0231090defadf00311/LICENSE.txt +176 -0
- package/vendor/spl-token-2022/5251dcc07ecbcb721d6c4f0231090defadf00311/interface/src/instruction.rs +2868 -0
- package/vendor/spl-token-metadata-interface/7038969ec74a89f1afdb9bc97c112d4d26fead9a/LICENSE +201 -0
- package/vendor/spl-token-metadata-interface/7038969ec74a89f1afdb9bc97c112d4d26fead9a/interface/src/error.rs +58 -0
- package/vendor/spl-token-metadata-interface/7038969ec74a89f1afdb9bc97c112d4d26fead9a/interface/src/instruction.rs +596 -0
- package/vendor/spl-token-metadata-interface/7038969ec74a89f1afdb9bc97c112d4d26fead9a/interface/src/lib.rs +21 -0
- 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
|
+
}
|