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
use anchor_lang::AccountDeserialize;
use clockwork_client::{
    network::state::{
        Config, Fee, Penalty, Registry, Snapshot, SnapshotFrame, Worker, WorkerSettings,
    },
    Client,
};
use solana_sdk::signature::{Keypair, Signer};

use crate::errors::CliError;

pub fn get(client: &Client, id: u64) -> Result<(), CliError> {
    let worker_pubkey = Worker::pubkey(id);
    let worker = client
        .get::<Worker>(&worker_pubkey)
        .map_err(|_err| CliError::AccountDataNotParsable(worker_pubkey.to_string()))?;

    // Get fee balance
    let fee_pubkey = Fee::pubkey(worker_pubkey);
    let fee_data = client
        .get_account_data(&fee_pubkey)
        .map_err(|_err| CliError::AccountNotFound(fee_pubkey.to_string()))?;
    let fees_min_rent = client
        .get_minimum_balance_for_rent_exemption(fee_data.len())
        .unwrap();
    let fees_balance = client.get_balance(&fee_pubkey).unwrap();
    let fees_total = fees_balance - fees_min_rent;

    // Get penalty balance
    let penalty_pubkey = Penalty::pubkey(worker_pubkey);
    let penalty_data = client
        .get_account_data(&penalty_pubkey)
        .map_err(|_err| CliError::AccountNotFound(penalty_pubkey.to_string()))?;
    let penalty_min_rent = client
        .get_minimum_balance_for_rent_exemption(penalty_data.len())
        .unwrap();
    let penalty_balance = client.get_balance(&penalty_pubkey).unwrap();
    let penalty_total = penalty_balance - penalty_min_rent;

    println!(
        "Address: {}\nFees: {}\nFee account: {}\nPenalty: {}\nPenalty account: {}\n{:#?}",
        worker_pubkey, fees_total, fee_pubkey, penalty_total, penalty_pubkey, worker
    );

    // Get registry
    let registry_pubkey = Registry::pubkey();
    let registry_data = client
        .get_account_data(&registry_pubkey)
        .map_err(|_err| CliError::AccountNotFound(registry_pubkey.to_string()))?;
    let registry = Registry::try_deserialize(&mut registry_data.as_slice())
        .map_err(|_err| CliError::AccountDataNotParsable(registry_pubkey.to_string()))?;

    // Get snapshot frame
    let snapshot_pubkey = Snapshot::pubkey(registry.current_epoch);
    let snapshot_frame_pubkey = SnapshotFrame::pubkey(snapshot_pubkey, worker.id);
    match client.get_account_data(&snapshot_frame_pubkey) {
        Err(_err) => {}
        Ok(snapshot_frame_data) => {
            let snapshot_frame = SnapshotFrame::try_deserialize(
                &mut snapshot_frame_data.as_slice(),
            )
            .map_err(|_err| CliError::AccountDataNotParsable(registry_pubkey.to_string()))?;
            println!("{:#?}", snapshot_frame);
        }
    }

    Ok(())
}

pub fn create(client: &Client, signatory: Keypair, silent: bool) -> 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 registry
    let registry_pubkey = Registry::pubkey();
    let registry_data = client
        .get_account_data(&registry_pubkey)
        .map_err(|_err| CliError::AccountNotFound(registry_pubkey.to_string()))?;
    let registry = Registry::try_deserialize(&mut registry_data.as_slice())
        .map_err(|_err| CliError::AccountDataNotParsable(registry_pubkey.to_string()))?;

    // Build ix
    let worker_id = registry.total_workers;
    let worker_pubkey = Worker::pubkey(worker_id);
    let ix = clockwork_client::network::instruction::worker_create(
        client.payer_pubkey(),
        config.mint,
        signatory.pubkey(),
        worker_pubkey,
    );
    client
        .send_and_confirm(&[ix], &[client.payer(), &signatory])
        .unwrap();
    if !silent {
        get(client, worker_id)?;
    }
    Ok(())
}

pub fn update(client: &Client, id: u64, signatory: Option<Keypair>) -> Result<(), CliError> {
    // Derive worker keypair.
    let worker_pubkey = Worker::pubkey(id);
    let worker = client
        .get::<Worker>(&worker_pubkey)
        .map_err(|_err| CliError::AccountDataNotParsable(worker_pubkey.to_string()))?;

    // Build and submit tx.
    let settings = WorkerSettings {
        commission_rate: 0,
        signatory: signatory.map_or(worker.signatory, |v| v.pubkey()),
    };
    let ix = clockwork_client::network::instruction::worker_update(
        client.payer_pubkey(),
        settings,
        worker_pubkey,
    );
    client.send_and_confirm(&[ix], &[client.payer()]).unwrap();
    get(client, worker.id)?;
    Ok(())
}