1use std::collections::HashMap;
2use std::{io, io::Write};
3
4use borsh::schema::{Declaration, Definition};
5use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
6use solana_program::pubkey::Pubkey;
7
8#[repr(transparent)]
10#[derive(Clone, PartialEq, Eq)]
11pub struct Address(Pubkey);
12
13impl From<Address> for Pubkey {
14 fn from(address: Address) -> Self {
15 address.0
16 }
17}
18
19impl AsRef<Pubkey> for Address {
20 fn as_ref(&self) -> &Pubkey {
21 &self.0
22 }
23}
24
25impl AsMut<Pubkey> for Address {
26 fn as_mut(&mut self) -> &mut Pubkey {
27 &mut self.0
28 }
29}
30
31impl From<Pubkey> for Address {
32 fn from(pubkey: Pubkey) -> Self {
33 Self(pubkey)
34 }
35}
36
37impl From<&Pubkey> for Address {
38 fn from(pubkey: &Pubkey) -> Self {
39 Self(*pubkey)
40 }
41}
42
43#[macro_export]
44macro_rules! declare_tag {
45 ($name:ident, $type:ty, $tag:expr) => {
46 #[derive(Clone, PartialEq, Eq, BorshSerialize, BorshSchema, Debug)]
47 pub struct $name($type);
48 impl $name {
49 pub const TAG_VALUE: $type = $tag;
50 }
51
52 impl Default for $name {
53 fn default() -> Self {
54 Self(Self::TAG_VALUE)
55 }
56 }
57
58 impl BorshDeserialize for $name {
59 #[inline]
60 fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
61 let tag = <$type as BorshDeserialize>::deserialize(buf)?;
62 if tag != Self::TAG_VALUE {
63 return Err(std::io::Error::new(
64 std::io::ErrorKind::InvalidData,
65 "invalid tag",
66 ));
67 }
68 Ok($name(tag))
69 }
70 }
71 };
72}
73
74pub mod fee_owner {
75 use solana_program::declare_id;
76
77 declare_id!("3LTvJCPiPSMjX1kBJ6ZfEhn4G2hM46aJ1yEZsk8i12TK");
78}
79
80declare_tag!(PoolStateTag, u64, 0x16a7874c7fb2301b);
81
82#[derive(Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, BorshSchema)]
83pub struct PoolState {
84 pub tag: PoolStateTag,
85
86 pub pool_token_mint: Address,
88 pub assets: Vec<AssetInfo>,
90
91 pub vault_signer: Address,
93 pub vault_signer_nonce: u8,
95
96 pub account_params: Vec<ParamDesc>,
98
99 pub name: String,
101
102 pub lqd_fee_vault: Address,
104 pub initializer_fee_vault: Address,
106
107 pub fee_rate: u32,
109
110 pub admin_key: Option<Address>,
112
113 pub custom_state: Vec<u8>,
114}
115
116#[derive(Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, BorshSchema)]
117pub struct AssetInfo {
118 pub mint: Address,
119 pub vault_address: Address,
121}
122
123#[derive(Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, BorshSchema)]
124pub struct ParamDesc {
125 pub address: Address,
126 pub writable: bool,
127}
128
129pub const MIN_FEE_RATE: u32 = 150;
130pub const DEFAULT_FEE_RATE: u32 = 2500;
131pub const FEE_RATE_DENOMINATOR: u32 = 1_000_000;
132
133declare_tag!(PoolRequestTag, u64, 0x220a6cbdcd1cc4cf);
134
135#[derive(Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, BorshSchema)]
136pub struct PoolRequest {
137 pub tag: PoolRequestTag,
138 pub inner: PoolRequestInner,
139}
140
141#[derive(Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, BorshSchema)]
142pub enum PoolRequestInner {
143 Initialize(InitializePoolRequest),
156
157 GetBasket(PoolAction),
171
172 Execute(PoolAction),
189}
190
191#[derive(Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, BorshSchema)]
192pub struct InitializePoolRequest {
193 pub vault_signer_nonce: u8,
194 pub assets_length: u8,
195 pub pool_name: String,
196 pub fee_rate: u32,
197 pub custom_data: Vec<u8>,
198}
199
200#[derive(Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, BorshSchema)]
201pub enum PoolAction {
202 Create(u64),
204 Redeem(u64),
206 Swap(Vec<u64>),
208}
209
210#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, BorshSchema)]
211pub struct Basket {
212 pub quantities: Vec<i64>,
215}
216
217impl BorshSerialize for Address {
218 fn serialize<W: Write>(&self, writer: &mut W) -> io::Result<()> {
219 BorshSerialize::serialize(&self.0.to_bytes(), writer)
220 }
221}
222
223impl BorshDeserialize for Address {
224 fn deserialize(buf: &mut &[u8]) -> io::Result<Self> {
225 Ok(Self(Pubkey::new_from_array(BorshDeserialize::deserialize(
226 buf,
227 )?)))
228 }
229}
230
231impl BorshSchema for Address {
232 fn add_definitions_recursively(definitions: &mut HashMap<Declaration, Definition>) {
233 Self::add_definition(
234 Self::declaration(),
235 Definition::Struct {
236 fields: borsh::schema::Fields::UnnamedFields(vec![
237 <[u8; 32] as BorshSchema>::declaration(),
238 ]),
239 },
240 definitions,
241 );
242 <[u8; 32] as BorshSchema>::add_definitions_recursively(definitions);
243 }
244
245 fn declaration() -> Declaration {
246 "Address".to_string()
247 }
248}