amm/
context.rs

1//! Context module includes information for instruction accounts
2
3use std::str::FromStr;
4
5use crate::curve::curve_type::CurveType;
6use crate::curve::fees::to_bps;
7use crate::error::PoolError;
8use crate::{state::Pool, vault_utils::MercurialVault};
9use anchor_lang::prelude::*;
10use anchor_spl::associated_token::AssociatedToken;
11use anchor_spl::token::{Mint, Token, TokenAccount};
12use mercurial_vault::state::Vault;
13
14/// get first key
15pub fn get_first_key(key1: Pubkey, key2: Pubkey) -> Pubkey {
16    if key1 > key2 {
17        return key1;
18    }
19    key2
20}
21/// get second key
22pub fn get_second_key(key1: Pubkey, key2: Pubkey) -> Pubkey {
23    if key1 > key2 {
24        return key2;
25    }
26    key1
27}
28
29/// get curve type
30pub fn get_curve_type(curve_type: CurveType) -> u8 {
31    match curve_type {
32        CurveType::ConstantProduct {} => 0,
33        _ => 1,
34    }
35}
36
37/// get admin
38pub fn get_admin(_payer: Pubkey) -> Pubkey {
39    Pubkey::from_str("5unTfT2kssBuNvHPY6LbJfJpLqEcdMxGYLWHwShaeTLi").unwrap()
40}
41
42/// get fee owner
43pub fn get_fee_owner() -> Pubkey {
44    Pubkey::from_str("6WaLrrRfReGKBYUSkmx2K6AuT21ida4j8at2SUiZdXu8").unwrap()
45}
46
47/// get_lp_mint
48pub fn get_lp_mint(token_a_mint_decimals: u8, token_b_mint_decimals: u8) -> u8 {
49    if token_a_mint_decimals > token_b_mint_decimals {
50        return token_a_mint_decimals;
51    }
52    token_b_mint_decimals
53}
54
55/// get trade fee bps seed for pool pda
56pub fn get_trade_fee_bps_bytes(curve_type: CurveType, trade_fee_bps: u64) -> Option<Vec<u8>> {
57    let default_fees = curve_type.get_default_fee();
58
59    let default_trade_fee_bps = to_bps(
60        default_fees.trade_fee_numerator.into(),
61        default_fees.trade_fee_denominator.into(),
62    )?;
63
64    if default_trade_fee_bps == trade_fee_bps {
65        return Some(vec![]);
66    }
67
68    Some(trade_fee_bps.to_le_bytes().to_vec())
69}
70
71/// Bootstrap pool with zero liquidity
72/// Accounts for bootstrap pool instruction
73#[derive(Accounts)]
74pub struct BootstrapLiquidity<'info> {
75    #[account(
76        mut,
77        has_one = a_vault @ PoolError::InvalidVaultAccount,
78        has_one = b_vault @ PoolError::InvalidVaultAccount,
79        has_one = a_vault_lp @ PoolError::InvalidVaultLpAccount,
80        has_one = b_vault_lp @ PoolError::InvalidVaultLpAccount,
81        has_one = lp_mint @ PoolError::InvalidPoolLpMintAccount,
82        constraint = a_vault_lp.mint == a_vault_lp_mint.key() @ PoolError::MismatchedLpMint,
83        constraint = b_vault_lp.mint == b_vault_lp_mint.key() @ PoolError::MismatchedLpMint,
84        constraint = pool.enabled @ PoolError::PoolDisabled
85    )]
86    /// Pool account (PDA)
87    pub pool: Box<Account<'info, Pool>>,
88    #[account(
89        mut,
90        constraint = lp_mint.supply == 0 @ PoolError::NonDepletedPool
91    )]
92    /// LP token mint of the pool
93    pub lp_mint: Account<'info, Mint>,
94    #[account(mut)]
95    /// user pool lp token account. lp will be burned from this account upon success liquidity removal.
96    pub user_pool_lp: Account<'info, TokenAccount>,
97
98    #[account(mut)]
99    /// LP token account of vault A. Used to receive/burn the vault LP upon deposit/withdraw from the vault.
100    pub a_vault_lp: Box<Account<'info, TokenAccount>>,
101    #[account(mut)]
102    /// LP token account of vault B. Used to receive/burn the vault LP upon deposit/withdraw from the vault.
103    pub b_vault_lp: Box<Account<'info, TokenAccount>>,
104
105    #[account(mut)]
106    /// Vault account for token a. token a of the pool will be deposit / withdraw from this vault account.
107    pub a_vault: Box<Account<'info, Vault>>,
108    #[account(mut)]
109    /// Vault account for token b. token b of the pool will be deposit / withdraw from this vault account.
110    pub b_vault: Box<Account<'info, Vault>>,
111
112    #[account(mut)]
113    /// LP token mint of vault a
114    pub a_vault_lp_mint: Box<Account<'info, Mint>>,
115    #[account(mut)]
116    /// LP token mint of vault b
117    pub b_vault_lp_mint: Box<Account<'info, Mint>>,
118
119    #[account(mut)]
120    /// Token vault account of vault A
121    pub a_token_vault: Box<Account<'info, TokenAccount>>,
122    #[account(mut)]
123    /// Token vault account of vault B
124    pub b_token_vault: Box<Account<'info, TokenAccount>>,
125    #[account(mut)]
126    /// User token A account. Token will be transfer from this account if it is add liquidity operation. Else, token will be transfer into this account.
127    pub user_a_token: Account<'info, TokenAccount>,
128    #[account(mut)]
129    /// User token B account. Token will be transfer from this account if it is add liquidity operation. Else, token will be transfer into this account.
130    pub user_b_token: Account<'info, TokenAccount>,
131    /// User account. Must be owner of user_a_token, and user_b_token.
132    pub user: Signer<'info>,
133
134    /// Vault program. the pool will deposit/withdraw liquidity from the vault.
135    pub vault_program: Program<'info, MercurialVault>,
136    /// Token program.
137    pub token_program: Program<'info, Token>,
138}
139
140/// Permissionless Initialize with customized fee tier
141/// Accounts for initialize new pool instruction
142#[derive(Accounts)]
143#[instruction(curve_type: CurveType, trade_fee_bps: u64)]
144pub struct InitializePermissionlessPoolWithFeeTier<'info> {
145    #[account(
146        init,
147        seeds = [
148            &get_curve_type(curve_type).to_le_bytes(),
149            get_first_key(token_a_mint.key(), token_b_mint.key()).as_ref(),
150            get_second_key(token_a_mint.key(), token_b_mint.key()).as_ref(),
151            get_trade_fee_bps_bytes(curve_type, trade_fee_bps).ok_or(PoolError::MathOverflow)?.as_ref(), // Do not include owner trade fee
152        ],
153        bump,
154        payer = payer,
155        // No point to rent for max 10 MB, as when deserialize it will hit stack limit
156        space = 8 + std::mem::size_of::<Pool>()
157    )]
158    /// Pool account (PDA address)
159    pub pool: Box<Account<'info, Pool>>,
160
161    /// LP token mint of the pool
162    #[account(
163        init,
164        seeds = [
165            "lp_mint".as_ref(),
166            pool.key().as_ref()
167        ],
168        bump,
169        payer = payer,
170        mint::decimals = get_lp_mint(token_a_mint.decimals, token_b_mint.decimals),
171        mint::authority = a_vault_lp
172    )]
173    pub lp_mint: Box<Account<'info, Mint>>,
174
175    /// Token A mint of the pool. Eg: USDT
176    pub token_a_mint: Box<Account<'info, Mint>>,
177    /// Token B mint of the pool. Eg: USDC
178    #[account(
179        constraint = token_b_mint.key() != token_a_mint.key() @ PoolError::MismatchedTokenMint
180    )]
181    pub token_b_mint: Box<Account<'info, Mint>>,
182
183    #[account(
184        mut,
185        constraint = a_vault.token_mint == token_a_mint.key() @ PoolError::MismatchedTokenMint
186    )]
187    /// Vault account for token A. Token A of the pool will be deposit / withdraw from this vault account.
188    pub a_vault: Box<Account<'info, Vault>>,
189    #[account(
190        mut,
191        constraint = b_vault.token_mint == token_b_mint.key() @ PoolError::MismatchedTokenMint
192    )]
193    /// Vault account for token B. Token B of the pool will be deposit / withdraw from this vault account.
194    pub b_vault: Box<Account<'info, Vault>>,
195
196    #[account(mut)]
197    /// Token vault account of vault A
198    pub a_token_vault: Box<Account<'info, TokenAccount>>,
199    #[account(mut)]
200    /// Token vault account of vault B
201    pub b_token_vault: Box<Account<'info, TokenAccount>>,
202
203    #[account(
204        mut,
205        constraint = a_vault_lp_mint.key() == a_vault.lp_mint @ PoolError::MismatchedLpMint
206    )]
207    /// LP token mint of vault A
208    pub a_vault_lp_mint: Box<Account<'info, Mint>>,
209    #[account(
210        mut,
211        constraint = b_vault_lp_mint.key() == b_vault.lp_mint @ PoolError::MismatchedLpMint
212    )]
213    /// LP token mint of vault B
214    pub b_vault_lp_mint: Box<Account<'info, Mint>>,
215    /// LP token account of vault A. Used to receive/burn the vault LP upon deposit/withdraw from the vault.
216    #[account(
217        init,
218        seeds = [
219            a_vault.key().as_ref(),
220            pool.key().as_ref()
221        ],
222        bump,
223        payer = payer,
224        token::mint = a_vault_lp_mint,
225        token::authority = a_vault_lp
226    )]
227    pub a_vault_lp: Box<Account<'info, TokenAccount>>,
228    /// LP token account of vault B. Used to receive/burn vault LP upon deposit/withdraw from the vault.
229    #[account(
230        init,
231        seeds = [
232            b_vault.key().as_ref(),
233            pool.key().as_ref()
234        ],
235        bump,
236        payer = payer,
237        token::mint = b_vault_lp_mint,
238        token::authority = a_vault_lp
239    )]
240    pub b_vault_lp: Box<Account<'info, TokenAccount>>,
241
242    #[account(
243        mut,
244        constraint = payer_token_a.mint == a_vault.token_mint @ PoolError::MismatchedTokenMint
245    )]
246    /// Payer token account for pool token A mint. Used to bootstrap the pool with initial liquidity.
247    pub payer_token_a: Box<Account<'info, TokenAccount>>,
248    #[account(
249        mut,
250        constraint = payer_token_b.mint == b_vault.token_mint @ PoolError::MismatchedTokenMint
251    )]
252    /// Admin token account for pool token B mint. Used to bootstrap the pool with initial liquidity.
253    pub payer_token_b: Box<Account<'info, TokenAccount>>,
254
255    /// CHECK: Payer pool LP token account. Used to receive LP during first deposit (initialize pool)
256    #[account(
257        init,
258        payer = payer,
259        associated_token::mint = lp_mint,
260        associated_token::authority = payer,
261    )]
262    pub payer_pool_lp: Box<Account<'info, TokenAccount>>,
263
264    #[account(
265        init,
266        seeds = [
267            "fee".as_ref(),
268            token_a_mint.key().as_ref(),
269            pool.key().as_ref()
270        ],
271        bump,
272        payer = payer,
273        token::mint = token_a_mint,
274        token::authority = fee_owner
275    )]
276    /// Admin fee token account for token A. Used to receive trading fee.
277    pub admin_token_a_fee: Box<Account<'info, TokenAccount>>,
278
279    /// Admin fee token account for token B. Used to receive trading fee.
280    #[account(
281        init,
282        seeds = [
283            "fee".as_ref(),
284            token_b_mint.key().as_ref(),
285            pool.key().as_ref()
286        ],
287        bump,
288        payer = payer,
289        token::mint = token_b_mint,
290        token::authority = fee_owner
291    )]
292    pub admin_token_b_fee: Box<Account<'info, TokenAccount>>,
293
294    /// Admin account. This account will be the admin of the pool, and the payer for PDA during initialize pool.
295    #[account(mut)]
296    pub payer: Signer<'info>,
297
298    /// CHECK: fee owner
299    #[account(constraint = fee_owner.key() == get_fee_owner() @ PoolError::InvalidFeeOwner)]
300    pub fee_owner: UncheckedAccount<'info>,
301
302    /// Rent account.
303    pub rent: Sysvar<'info, Rent>,
304
305    /// Vault program. The pool will deposit/withdraw liquidity from the vault.
306    pub vault_program: Program<'info, MercurialVault>,
307    /// Token program.
308    pub token_program: Program<'info, Token>,
309    /// Associated token program.
310    pub associated_token_program: Program<'info, AssociatedToken>,
311    /// System program.
312    pub system_program: Program<'info, System>,
313}
314
315/// Permissionless Initialize
316/// Accounts for initialize new pool instruction
317#[deprecated]
318#[derive(Accounts)]
319#[instruction(curve_type: CurveType)]
320pub struct InitializePermissionlessPool<'info> {
321    #[account(
322        init,
323        seeds = [
324            &get_curve_type(curve_type).to_le_bytes(),
325            get_first_key(token_a_mint.key(), token_b_mint.key()).as_ref(),
326            get_second_key(token_a_mint.key(), token_b_mint.key()).as_ref(),
327        ],
328        bump,
329        payer = payer,
330        // No point to rent for max 10 MB, as when deserialize it will hit stack limit
331        space = 8 + std::mem::size_of::<Pool>()
332    )]
333    /// Pool account (PDA address)
334    pub pool: Box<Account<'info, Pool>>,
335
336    /// LP token mint of the pool
337    #[account(
338        init,
339        seeds = [
340            "lp_mint".as_ref(),
341            pool.key().as_ref()
342        ],
343        bump,
344        payer = payer,
345        mint::decimals = get_lp_mint(token_a_mint.decimals, token_b_mint.decimals),
346        mint::authority = a_vault_lp
347    )]
348    pub lp_mint: Box<Account<'info, Mint>>,
349
350    /// Token A mint of the pool. Eg: USDT
351    pub token_a_mint: Box<Account<'info, Mint>>,
352    /// Token B mint of the pool. Eg: USDC
353    #[account(
354        constraint = token_b_mint.key() != token_a_mint.key() @ PoolError::MismatchedTokenMint
355    )]
356    pub token_b_mint: Box<Account<'info, Mint>>,
357
358    #[account(
359        mut,
360        constraint = a_vault.token_mint == token_a_mint.key() @ PoolError::MismatchedTokenMint
361    )]
362    /// Vault account for token A. Token A of the pool will be deposit / withdraw from this vault account.
363    pub a_vault: Box<Account<'info, Vault>>,
364    #[account(
365        mut,
366        constraint = b_vault.token_mint == token_b_mint.key() @ PoolError::MismatchedTokenMint
367    )]
368    /// Vault account for token B. Token B of the pool will be deposit / withdraw from this vault account.
369    pub b_vault: Box<Account<'info, Vault>>,
370
371    #[account(mut)]
372    /// Token vault account of vault A
373    pub a_token_vault: Box<Account<'info, TokenAccount>>,
374    #[account(mut)]
375    /// Token vault account of vault B
376    pub b_token_vault: Box<Account<'info, TokenAccount>>,
377
378    #[account(
379        mut,
380        constraint = a_vault_lp_mint.key() == a_vault.lp_mint @ PoolError::MismatchedLpMint
381    )]
382    /// LP token mint of vault A
383    pub a_vault_lp_mint: Box<Account<'info, Mint>>,
384    #[account(
385        mut,
386        constraint = b_vault_lp_mint.key() == b_vault.lp_mint @ PoolError::MismatchedLpMint
387    )]
388    /// LP token mint of vault B
389    pub b_vault_lp_mint: Box<Account<'info, Mint>>,
390    /// LP token account of vault A. Used to receive/burn the vault LP upon deposit/withdraw from the vault.
391    #[account(
392        init,
393        seeds = [
394            a_vault.key().as_ref(),
395            pool.key().as_ref()
396        ],
397        bump,
398        payer = payer,
399        token::mint = a_vault_lp_mint,
400        token::authority = a_vault_lp
401    )]
402    pub a_vault_lp: Box<Account<'info, TokenAccount>>,
403    /// LP token account of vault B. Used to receive/burn vault LP upon deposit/withdraw from the vault.
404    #[account(
405        init,
406        seeds = [
407            b_vault.key().as_ref(),
408            pool.key().as_ref()
409        ],
410        bump,
411        payer = payer,
412        token::mint = b_vault_lp_mint,
413        token::authority = a_vault_lp
414    )]
415    pub b_vault_lp: Box<Account<'info, TokenAccount>>,
416
417    #[account(
418        mut,
419        constraint = payer_token_a.mint == a_vault.token_mint @ PoolError::MismatchedTokenMint
420    )]
421    /// Payer token account for pool token A mint. Used to bootstrap the pool with initial liquidity.
422    pub payer_token_a: Box<Account<'info, TokenAccount>>,
423    #[account(
424        mut,
425        constraint = payer_token_b.mint == b_vault.token_mint @ PoolError::MismatchedTokenMint
426    )]
427    /// Admin token account for pool token B mint. Used to bootstrap the pool with initial liquidity.
428    pub payer_token_b: Box<Account<'info, TokenAccount>>,
429
430    /// CHECK: Payer pool LP token account. Used to receive LP during first deposit (initialize pool)
431    #[account(
432        init,
433        payer = payer,
434        associated_token::mint = lp_mint,
435        associated_token::authority = payer,
436    )]
437    pub payer_pool_lp: Box<Account<'info, TokenAccount>>,
438
439    #[account(
440        init,
441        seeds = [
442            "fee".as_ref(),
443            token_a_mint.key().as_ref(),
444            pool.key().as_ref()
445        ],
446        bump,
447        payer = payer,
448        token::mint = token_a_mint,
449        token::authority = fee_owner
450    )]
451    /// Admin fee token account for token A. Used to receive trading fee.
452    pub admin_token_a_fee: Box<Account<'info, TokenAccount>>,
453
454    /// Admin fee token account for token B. Used to receive trading fee.
455    #[account(
456        init,
457        seeds = [
458            "fee".as_ref(),
459            token_b_mint.key().as_ref(),
460            pool.key().as_ref()
461        ],
462        bump,
463        payer = payer,
464        token::mint = token_b_mint,
465        token::authority = fee_owner
466    )]
467    pub admin_token_b_fee: Box<Account<'info, TokenAccount>>,
468
469    /// Admin account. This account will be the admin of the pool, and the payer for PDA during initialize pool.
470    #[account(mut)]
471    pub payer: Signer<'info>,
472
473    /// CHECK: fee owner
474    #[account(constraint = fee_owner.key() == get_fee_owner() @ PoolError::InvalidFeeOwner)]
475    pub fee_owner: UncheckedAccount<'info>,
476
477    /// Rent account.
478    pub rent: Sysvar<'info, Rent>,
479
480    /// Vault program. The pool will deposit/withdraw liquidity from the vault.
481    pub vault_program: Program<'info, MercurialVault>,
482    /// Token program.
483    pub token_program: Program<'info, Token>,
484    /// Associated token program.
485    pub associated_token_program: Program<'info, AssociatedToken>,
486    /// System program.
487    pub system_program: Program<'info, System>,
488}
489
490/// Accounts for remove liquidity single sided instruction
491#[derive(Accounts)]
492pub struct RemoveLiquiditySingleSide<'info> {
493    #[account(
494        mut,
495        has_one = a_vault @ PoolError::InvalidVaultAccount,
496        has_one = b_vault @ PoolError::InvalidVaultAccount,
497        has_one = a_vault_lp @ PoolError::InvalidVaultLpAccount,
498        has_one = b_vault_lp @ PoolError::InvalidVaultLpAccount,
499        has_one = lp_mint @ PoolError::InvalidPoolLpMintAccount,
500        constraint = a_vault_lp.mint == a_vault_lp_mint.key() @ PoolError::MismatchedLpMint,
501        constraint = b_vault_lp.mint == b_vault_lp_mint.key() @ PoolError::MismatchedLpMint,
502        constraint = pool.enabled @ PoolError::PoolDisabled // user need to call remove liquidity in balanced ratio
503    )]
504    /// Pool account (PDA)
505    pub pool: Box<Account<'info, Pool>>,
506    #[account(mut)]
507    /// LP token mint of the pool
508    pub lp_mint: Account<'info, Mint>,
509    #[account(mut)]
510    /// User pool lp token account. LP will be burned from this account upon success liquidity removal.
511    pub user_pool_lp: Account<'info, TokenAccount>,
512
513    #[account(mut)]
514    /// LP token account of vault A. Used to receive/burn the vault LP upon deposit/withdraw from the vault.
515    pub a_vault_lp: Box<Account<'info, TokenAccount>>,
516    #[account(mut)]
517    /// LP token account of vault B. Used to receive/burn the vault LP upon deposit/withdraw from the vault.
518    pub b_vault_lp: Box<Account<'info, TokenAccount>>,
519
520    #[account(mut)]
521    /// Vault account for token A. Token A of the pool will be deposit / withdraw from this vault account.
522    pub a_vault: Box<Account<'info, Vault>>,
523    #[account(mut)]
524    /// Vault account for token B. Token B of the pool will be deposit / withdraw from this vault account.
525    pub b_vault: Box<Account<'info, Vault>>,
526
527    #[account(mut)]
528    /// LP token mint of vault A
529    pub a_vault_lp_mint: Box<Account<'info, Mint>>,
530    #[account(mut)]
531    /// LP token mint of vault B
532    pub b_vault_lp_mint: Box<Account<'info, Mint>>,
533
534    #[account(mut)]
535    /// Token vault account of vault A
536    pub a_token_vault: Box<Account<'info, TokenAccount>>,
537    #[account(mut)]
538    /// Token vault account of vault B
539    pub b_token_vault: Box<Account<'info, TokenAccount>>,
540    #[account(mut)]
541    /// User token account to receive token upon success liquidity removal.
542    pub user_destination_token: Account<'info, TokenAccount>,
543    /// User account. Must be owner of the user_pool_lp account.
544    pub user: Signer<'info>,
545
546    /// Vault program. The pool will deposit/withdraw liquidity from the vault.
547    pub vault_program: Program<'info, MercurialVault>,
548    /// Token program.
549    pub token_program: Program<'info, Token>,
550}
551
552/// Accounts for add or remove balanced liquidity instruction
553#[derive(Accounts)]
554pub struct AddOrRemoveBalanceLiquidity<'info> {
555    #[account(
556        mut,
557        has_one = a_vault @ PoolError::InvalidVaultAccount,
558        has_one = b_vault @ PoolError::InvalidVaultAccount,
559        has_one = a_vault_lp @ PoolError::InvalidVaultLpAccount,
560        has_one = b_vault_lp @ PoolError::InvalidVaultLpAccount,
561        has_one = lp_mint @ PoolError::InvalidPoolLpMintAccount,
562        constraint = a_vault_lp.mint == a_vault_lp_mint.key() @ PoolError::MismatchedLpMint,
563        constraint = b_vault_lp.mint == b_vault_lp_mint.key() @ PoolError::MismatchedLpMint,
564    )]
565    /// Pool account (PDA)
566    pub pool: Box<Account<'info, Pool>>,
567    #[account(mut)]
568    /// LP token mint of the pool
569    pub lp_mint: Account<'info, Mint>,
570    #[account(mut)]
571    /// user pool lp token account. lp will be burned from this account upon success liquidity removal.
572    pub user_pool_lp: Account<'info, TokenAccount>,
573
574    #[account(mut)]
575    /// LP token account of vault A. Used to receive/burn the vault LP upon deposit/withdraw from the vault.
576    pub a_vault_lp: Box<Account<'info, TokenAccount>>,
577    #[account(mut)]
578    /// LP token account of vault B. Used to receive/burn the vault LP upon deposit/withdraw from the vault.
579    pub b_vault_lp: Box<Account<'info, TokenAccount>>,
580
581    #[account(mut)]
582    /// Vault account for token a. token a of the pool will be deposit / withdraw from this vault account.
583    pub a_vault: Box<Account<'info, Vault>>,
584    #[account(mut)]
585    /// Vault account for token b. token b of the pool will be deposit / withdraw from this vault account.
586    pub b_vault: Box<Account<'info, Vault>>,
587
588    #[account(mut)]
589    /// LP token mint of vault a
590    pub a_vault_lp_mint: Box<Account<'info, Mint>>,
591    #[account(mut)]
592    /// LP token mint of vault b
593    pub b_vault_lp_mint: Box<Account<'info, Mint>>,
594
595    #[account(mut)]
596    /// Token vault account of vault A
597    pub a_token_vault: Box<Account<'info, TokenAccount>>,
598    #[account(mut)]
599    /// Token vault account of vault B
600    pub b_token_vault: Box<Account<'info, TokenAccount>>,
601    #[account(mut)]
602    /// User token A account. Token will be transfer from this account if it is add liquidity operation. Else, token will be transfer into this account.
603    pub user_a_token: Account<'info, TokenAccount>,
604    #[account(mut)]
605    /// User token B account. Token will be transfer from this account if it is add liquidity operation. Else, token will be transfer into this account.
606    pub user_b_token: Account<'info, TokenAccount>,
607    /// User account. Must be owner of user_a_token, and user_b_token.
608    pub user: Signer<'info>,
609
610    /// Vault program. the pool will deposit/withdraw liquidity from the vault.
611    pub vault_program: Program<'info, MercurialVault>,
612    /// Token program.
613    pub token_program: Program<'info, Token>,
614}
615
616/// Accounts for get pool info instruction
617#[derive(Accounts)]
618pub struct GetPoolInfo<'info> {
619    #[account(
620        has_one = a_vault_lp @ PoolError::InvalidVaultLpAccount,
621        has_one = b_vault_lp @ PoolError::InvalidVaultLpAccount,
622        has_one = a_vault @ PoolError::InvalidVaultAccount,
623        has_one = b_vault @ PoolError::InvalidVaultAccount,
624        has_one = lp_mint @ PoolError::InvalidPoolLpMintAccount,
625        constraint = a_vault_lp.mint == a_vault_lp_mint.key() @ PoolError::MismatchedLpMint,
626        constraint = b_vault_lp.mint == b_vault_lp_mint.key() @ PoolError::MismatchedLpMint,
627    )]
628    /// Pool account (PDA)
629    pub pool: Box<Account<'info, Pool>>,
630    /// LP token mint of the pool
631    pub lp_mint: Box<Account<'info, Mint>>,
632    /// LP token account of vault A. Used to receive/burn the vault LP upon deposit/withdraw from the vault.
633    pub a_vault_lp: Account<'info, TokenAccount>,
634    /// LP token account of vault B. Used to receive/burn the vault LP upon deposit/withdraw from the vault.
635    pub b_vault_lp: Account<'info, TokenAccount>,
636    /// Vault account for token a. token a of the pool will be deposit / withdraw from this vault account.
637    pub a_vault: Box<Account<'info, Vault>>,
638    /// Vault account for token b. token b of the pool will be deposit / withdraw from this vault account.
639    pub b_vault: Box<Account<'info, Vault>>,
640    /// LP token mint of vault a
641    pub a_vault_lp_mint: Box<Account<'info, Mint>>,
642    /// LP token mint of vault b
643    pub b_vault_lp_mint: Box<Account<'info, Mint>>,
644}
645/// Accounts for swap instruction
646#[derive(Accounts)]
647pub struct Swap<'info> {
648    #[account(
649        mut,
650        has_one = a_vault_lp @ PoolError::InvalidVaultLpAccount,
651        has_one = b_vault_lp @ PoolError::InvalidVaultLpAccount,
652        has_one = a_vault @ PoolError::InvalidVaultAccount,
653        has_one = b_vault @ PoolError::InvalidVaultAccount,
654        constraint = a_vault_lp.mint == a_vault_lp_mint.key() @ PoolError::MismatchedLpMint,
655        constraint = b_vault_lp.mint == b_vault_lp_mint.key() @ PoolError::MismatchedLpMint,
656        constraint = pool.enabled @ PoolError::PoolDisabled
657    )]
658    /// Pool account (PDA)
659    pub pool: Box<Account<'info, Pool>>,
660
661    #[account(
662        mut,
663        constraint = user_source_token.mint != user_destination_token.mint @ PoolError::IdenticalSourceDestination,
664        constraint = user_source_token.mint == a_vault.token_mint || user_source_token.mint == b_vault.token_mint @ PoolError::MismatchedTokenMint
665    )]
666    /// User token account. Token from this account will be transfer into the vault by the pool in exchange for another token of the pool.
667    pub user_source_token: Account<'info, TokenAccount>,
668    #[account(
669        mut,
670        constraint = user_destination_token.mint == a_vault.token_mint || user_destination_token.mint == b_vault.token_mint @ PoolError::MismatchedTokenMint
671    )]
672    /// User token account. The exchanged token will be transfer into this account from the pool.
673    pub user_destination_token: Account<'info, TokenAccount>,
674
675    #[account(mut)]
676    /// Vault account for token a. token a of the pool will be deposit / withdraw from this vault account.
677    pub a_vault: Box<Account<'info, Vault>>,
678    #[account(mut)]
679    /// Vault account for token b. token b of the pool will be deposit / withdraw from this vault account.
680    pub b_vault: Box<Account<'info, Vault>>,
681
682    #[account(mut)]
683    /// Token vault account of vault A
684    pub a_token_vault: Box<Account<'info, TokenAccount>>,
685    #[account(mut)]
686    /// Token vault account of vault B
687    pub b_token_vault: Box<Account<'info, TokenAccount>>,
688
689    #[account(mut)]
690    /// Lp token mint of vault a
691    pub a_vault_lp_mint: Box<Account<'info, Mint>>,
692    #[account(mut)]
693    /// Lp token mint of vault b
694    pub b_vault_lp_mint: Box<Account<'info, Mint>>,
695
696    #[account(mut)]
697    /// LP token account of vault A. Used to receive/burn the vault LP upon deposit/withdraw from the vault.
698    pub a_vault_lp: Account<'info, TokenAccount>,
699    #[account(mut)]
700    /// LP token account of vault B. Used to receive/burn the vault LP upon deposit/withdraw from the vault.
701    pub b_vault_lp: Account<'info, TokenAccount>,
702
703    #[account(mut)]
704    /// Admin fee token account. Used to receive trading fee. It's mint field must matched with user_source_token mint field.
705    pub admin_token_fee: Box<Account<'info, TokenAccount>>,
706
707    /// User account. Must be owner of user_source_token.
708    pub user: Signer<'info>,
709
710    /// Vault program. the pool will deposit/withdraw liquidity from the vault.
711    pub vault_program: Program<'info, MercurialVault>,
712    /// Token program.
713    pub token_program: Program<'info, Token>,
714}