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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use std::fs;
use std::io::Write;
use std::str::FromStr;

use serde::{Deserialize, Serialize};
use solana_client::rpc_client::RpcClient;
use solana_program::instruction::Instruction;
use solana_program::pubkey::Pubkey;
use spl_associated_token_account::get_associated_token_address;
use tabled::Tabled;

use common::command::{CliConfig, ProcessResult};
use common::contract::instructions::create_clmmpools::new_create_clmmpool;
use common::contract::instructions::create_tick_array_map::new_create_tick_array_map;
use common::contract::state::fee_tier::FeeTier;
use common::program::SWAP_PROGRAM_ID;
use common::utils::file::{read_for_str};
use common::utils::send::send_tx;

pub const TEMPLATE_DIR: &str = "./clmmpool-template.yaml";

#[derive(Debug, Serialize, Deserialize, Tabled)]
pub struct ClmmpoolTemplate {
    /// `clmm_config` provide the protocol_fee_rate and control the pool.
    pub clmm_config: String,

    /// `fee_tier` provide the tick_spacing and fee_rate to the pool.
    pub fee_tier: String,

    /// pool token_a mint address.
    pub token_a: String,
    /// pool token_b mint address.
    pub token_b: String,

    /// `init_sqrt_price` is pool init price.
    pub init_sqrt_price: u128,
}

pub fn process_create_pool(
    rpc_client: &RpcClient,
    config: &CliConfig,
    output: &str,
) -> ProcessResult {
    let pool: ClmmpoolTemplate = read_for_str(output);

    let fee_tier_info = FeeTier::get_info(
        rpc_client,
        &Pubkey::from_str(pool.fee_tier.as_str()).unwrap(),
    );

    let (clmmpool_pubkey, _) = Pubkey::find_program_address(
        &[
            b"clmmpool",
            Pubkey::from_str(pool.clmm_config.as_str())
                .unwrap()
                .as_ref(),
            Pubkey::from_str(pool.token_a.as_str()).unwrap().as_ref(),
            Pubkey::from_str(pool.token_b.as_str()).unwrap().as_ref(),
            fee_tier_info.tick_spacing.to_le_bytes().as_ref(),
        ],
        &SWAP_PROGRAM_ID,
    );

    let token_a_vault = get_associated_token_address(
        &clmmpool_pubkey,
        &Pubkey::from_str(pool.token_a.as_str()).unwrap(),
    );
    let token_b_vault = get_associated_token_address(
        &clmmpool_pubkey,
        &Pubkey::from_str(pool.token_b.as_str()).unwrap(),
    );

    let mut ixs: Vec<Instruction> = Vec::new();
    ixs.push(new_create_clmmpool(
        Pubkey::from_str(pool.clmm_config.as_str()).unwrap(),
        Pubkey::from_str(pool.fee_tier.as_str()).unwrap(),
        Pubkey::from_str(pool.token_a.as_str()).unwrap(),
        Pubkey::from_str(pool.token_b.as_str()).unwrap(),
        pool.init_sqrt_price,
        clmmpool_pubkey,
        token_a_vault,
        token_b_vault,
        config.pubkey().unwrap(),
    ));

    let (tick_array_map_pubkey, _) = Pubkey::find_program_address(
        &[b"tick_array_map", clmmpool_pubkey.as_ref()],
        &SWAP_PROGRAM_ID,
    );
    ixs.push(new_create_tick_array_map(
        clmmpool_pubkey,
        tick_array_map_pubkey,
        config.pubkey().unwrap(),
    ));

    let res = send_tx(rpc_client, config, &ixs)?;
    println!("pool key: {}", clmmpool_pubkey.to_string());

    Ok("signers : ".to_owned() + res.to_string().as_str())
}

pub fn process_create_pool_template(output: &str) -> ProcessResult {
    let clmmpool_template = ClmmpoolTemplate {
        clmm_config: Pubkey::from_str("BPFLoaderUpgradeab1e11111111111111111111111")
            .unwrap()
            .to_string(),
        fee_tier: Pubkey::from_str("BPFLoaderUpgradeab1e11111111111111111111111")
            .unwrap()
            .to_string(),
        token_a: Pubkey::from_str("BPFLoaderUpgradeab1e11111111111111111111111")
            .unwrap()
            .to_string(),
        token_b: Pubkey::from_str("BPFLoaderUpgradeab1e11111111111111111111111")
            .unwrap()
            .to_string(),
        init_sqrt_price: 0,
    };

    let mut file = fs::File::create(output).expect("create failed");
    file.write_all(
        serde_yaml::to_string(&clmmpool_template)
            .unwrap()
            .as_bytes(),
    )
        .expect("write failed");

    Ok(output.to_string() + " file create success".to_string().as_str())
}