Files
agnostic_orderbook
ahash
aho_corasick
arrayref
arrayvec
atty
base64
bincode
blake3
block_buffer
block_padding
borsh
borsh_derive
borsh_derive_internal
borsh_schema_derive_internal
bs58
bv
bytemuck
byteorder
cfg_if
constant_time_eq
cpufeatures
crunchy
crypto_mac
curve25519_dalek
derivative
dex_v3
digest
either
enumflags2
enumflags2_derive
env_logger
generic_array
getrandom
hashbrown
hex
hmac
hmac_drbg
humantime
itertools
keccak
lazy_static
libc
libm
libsecp256k1
libsecp256k1_core
log
memchr
memmap2
num_derive
num_enum
num_enum_derive
num_traits
opaque_debug
ppv_lite86
proc_macro2
quote
rand
rand_chacha
rand_core
rand_pcg
regex
regex_syntax
rustversion
serde
serde_bytes
serde_derive
sha2
sha3
solana_frozen_abi
solana_frozen_abi_macro
solana_logger
solana_program
solana_sdk_macro
spin
spl_token
subtle
syn
synstructure
termcolor
thiserror
thiserror_impl
typenum
unicode_xid
zeroize
zeroize_derive
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use borsh::{BorshDeserialize, BorshSerialize};
use solana_program::{
    account_info::{next_account_info, AccountInfo},
    entrypoint::ProgramResult,
    msg,
    program_error::ProgramError,
    pubkey::Pubkey,
};

use crate::{
    error::DexError,
    state::{AccountTag, UserAccount},
    utils::{check_account_owner, check_signer},
};

#[derive(BorshDeserialize, BorshSerialize)]
/**
The required arguments for a initialize_account instruction.
*/
pub struct Params {}

struct Accounts<'a, 'b: 'a> {
    user: &'a AccountInfo<'b>,
    user_owner: &'a AccountInfo<'b>,
    target_lamports_account: &'a AccountInfo<'b>,
}

impl<'a, 'b: 'a> Accounts<'a, 'b> {
    pub fn parse(
        _program_id: &Pubkey,
        accounts: &'a [AccountInfo<'b>],
    ) -> Result<Self, ProgramError> {
        let accounts_iter = &mut accounts.iter();
        let a = Self {
            user: next_account_info(accounts_iter)?,
            user_owner: next_account_info(accounts_iter)?,
            target_lamports_account: next_account_info(accounts_iter)?,
        };
        check_signer(&a.user_owner).unwrap();
        check_account_owner(a.user, &_program_id).unwrap();

        Ok(a)
    }

    pub fn load_user_account(&self) -> Result<UserAccount<'b>, ProgramError> {
        let user_account =
            match AccountTag::deserialize(&mut (&self.user.data.borrow() as &[u8])).unwrap() {
                AccountTag::UserAccount => {
                    let u = UserAccount::parse(&self.user)?;
                    if &u.header.owner != self.user_owner.key {
                        msg!("Invalid user account owner provided!");
                        return Err(ProgramError::InvalidArgument);
                    }
                    u
                }
                AccountTag::Uninitialized => {
                    msg!("Invalid user account!");
                    return Err(ProgramError::InvalidArgument);
                }
                _ => return Err(ProgramError::InvalidArgument),
            };
        Ok(user_account)
    }
}

pub(crate) fn process(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
    let accounts = Accounts::parse(program_id, accounts)?;

    let user_account = accounts.load_user_account()?;

    if user_account.header.number_of_orders != 0
        || user_account.header.quote_token_free != 0
        || user_account.header.base_token_free != 0
    {
        msg!("The user account cannot be closed as it has pending orders or unsettled funds");
        return Err(DexError::UserAccountStillActive.into());
    }

    let mut lamports = accounts.user.lamports.borrow_mut();
    let mut target_lamports = accounts.target_lamports_account.lamports.borrow_mut();

    **target_lamports += **lamports;
    **lamports = 0;

    Ok(())
}