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
129
130
use anchor_lang::AccountDeserialize;
use clockwork_client::{
    network::state::{Config, Delegation, Worker},
    Client,
};
use spl_associated_token_account::get_associated_token_address;

use crate::errors::CliError;

pub fn create(client: &Client, worker_id: u64) -> Result<(), CliError> {
    // Get config data
    let config_pubkey = Config::pubkey();
    let config_data = client
        .get_account_data(&config_pubkey)
        .map_err(|_err| CliError::AccountNotFound(config_pubkey.to_string()))?;
    let config = Config::try_deserialize(&mut config_data.as_slice())
        .map_err(|_err| CliError::AccountDataNotParsable(config_pubkey.to_string()))?;

    // Get worker
    let worker_pubkey = Worker::pubkey(worker_id);
    let worker_data = client
        .get_account_data(&worker_pubkey)
        .map_err(|_err| CliError::AccountNotFound(worker_pubkey.to_string()))?;
    let worker = Worker::try_deserialize(&mut worker_data.as_slice())
        .map_err(|_err| CliError::AccountDataNotParsable(worker_pubkey.to_string()))?;

    // Build ix
    let delegation_pubkey = Delegation::pubkey(worker_pubkey, worker.total_delegations);
    let ix = clockwork_client::network::instruction::delegation_create(
        client.payer_pubkey(),
        delegation_pubkey,
        config.mint,
        worker_pubkey,
    );
    client.send_and_confirm(&[ix], &[client.payer()]).unwrap();

    Ok(())
}

pub fn deposit(
    client: &Client,
    amount: u64,
    delegation_id: u64,
    worker_id: u64,
) -> Result<(), CliError> {
    // Get config data
    let config_pubkey = Config::pubkey();
    let config_data = client
        .get_account_data(&config_pubkey)
        .map_err(|_err| CliError::AccountNotFound(config_pubkey.to_string()))?;
    let config = Config::try_deserialize(&mut config_data.as_slice())
        .map_err(|_err| CliError::AccountDataNotParsable(config_pubkey.to_string()))?;

    // TODO Map the amount using the mint's decimals.

    // Build ix
    let worker_pubkey = Worker::pubkey(worker_id);
    let delegation_pubkey = Delegation::pubkey(worker_pubkey, delegation_id);
    let ix = clockwork_client::network::instruction::delegation_deposit(
        amount,
        client.payer_pubkey(),
        delegation_pubkey,
        config.mint,
    );
    client.send_and_confirm(&[ix], &[client.payer()]).unwrap();

    Ok(())
}

pub fn withdraw(
    client: &Client,
    amount: u64,
    delegation_id: u64,
    worker_id: u64,
) -> Result<(), CliError> {
    // Get config data
    let config_pubkey = Config::pubkey();
    let config_data = client
        .get_account_data(&config_pubkey)
        .map_err(|_err| CliError::AccountNotFound(config_pubkey.to_string()))?;
    let config = Config::try_deserialize(&mut config_data.as_slice())
        .map_err(|_err| CliError::AccountDataNotParsable(config_pubkey.to_string()))?;

    // TODO Map the amount using the mint's decimals.

    // Build ix
    let worker_pubkey = Worker::pubkey(worker_id);
    let delegation_pubkey = Delegation::pubkey(worker_pubkey, delegation_id);
    let ix = clockwork_client::network::instruction::delegation_withdraw(
        amount,
        client.payer_pubkey(),
        delegation_pubkey,
        config.mint,
    );
    client.send_and_confirm(&[ix], &[client.payer()]).unwrap();

    Ok(())
}

pub fn get(client: &Client, delegation_id: u64, worker_id: u64) -> Result<(), CliError> {
    // Get config account
    let config_pubkey = Config::pubkey();
    let config_data = client
        .get_account_data(&config_pubkey)
        .map_err(|_err| CliError::AccountNotFound(config_pubkey.to_string()))?;
    let config = Config::try_deserialize(&mut config_data.as_slice())
        .map_err(|_err| CliError::AccountDataNotParsable(config_pubkey.to_string()))?;

    // Get the delegation account.
    let worker_pubkey = Worker::pubkey(worker_id);
    let delegation_pubkey = Delegation::pubkey(worker_pubkey, delegation_id);
    let delegation_data = client
        .get_account_data(&delegation_pubkey)
        .map_err(|_err| CliError::AccountNotFound(delegation_pubkey.to_string()))?;
    let delegation = Delegation::try_deserialize(&mut delegation_data.as_slice())
        .map_err(|_err| CliError::AccountDataNotParsable(delegation_pubkey.to_string()))?;

    // Get the delegation's token account.
    let delegation_tokens_pubkey = get_associated_token_address(&delegation_pubkey, &config.mint);
    let token_balance = client
        .get_token_account_balance(&delegation_tokens_pubkey)
        .map_err(|_err| CliError::AccountDataNotParsable(delegation_pubkey.to_string()))?;

    println!(
        "Address: {}\n{:#?}\nLiquid balance: {}",
        delegation_pubkey, delegation, token_balance.ui_amount_string
    );

    Ok(())
}