Skip to main content

tuktuk_cli/cmd/
cron_transaction.rs

1use clap::{Args, Subcommand};
2use serde::Serialize;
3use solana_sdk::{pubkey::Pubkey, signer::Signer};
4use tuktuk_program::cron::{
5    accounts::{CronJobTransactionV0, CronJobV0},
6    types::{AddCronTransactionArgsV0, RemoveCronTransactionArgsV0, TransactionSourceV0},
7};
8use tuktuk_sdk::prelude::*;
9
10use super::{cron::CronArg, TransactionSource};
11use crate::{
12    client::send_instructions,
13    cmd::Opts,
14    result::Result,
15    serde::{print_json, serde_pubkey},
16};
17
18#[derive(Debug, Args)]
19pub struct CronTransactionCmd {
20    #[command(subcommand)]
21    pub cmd: Cmd,
22}
23
24#[derive(Debug, Subcommand)]
25pub enum Cmd {
26    CreateRemote {
27        #[command(flatten)]
28        cron_job: CronArg,
29        #[arg(long)]
30        index: u32,
31        #[arg(long)]
32        url: String,
33        #[arg(long)]
34        signer: Pubkey,
35    },
36    Close {
37        #[command(flatten)]
38        cron_job: CronArg,
39        #[arg(long)]
40        id: u32,
41    },
42    Get {
43        #[command(flatten)]
44        cron_job: CronArg,
45        #[arg(long)]
46        id: u32,
47    },
48    List {
49        #[command(flatten)]
50        cron_job: CronArg,
51    },
52}
53
54impl CronTransactionCmd {
55    pub async fn run(&self, opts: Opts) -> Result<()> {
56        match &self.cmd {
57            Cmd::CreateRemote {
58                cron_job,
59                index,
60                url,
61                signer,
62            } => {
63                let client = opts.client().await?;
64                let cron_job_key = cron_job.get_pubkey(&client).await?.ok_or_else(|| {
65                    anyhow::anyhow!("Must provide cron-name, cron-id, or cron-pubkey")
66                })?;
67                let (cron_job_transaction_key, ix) = tuktuk::cron_job_transaction::add_transaction(
68                    client.payer.pubkey(),
69                    cron_job_key,
70                    AddCronTransactionArgsV0 {
71                        index: *index,
72                        transaction_source: TransactionSourceV0::RemoteV0 {
73                            url: url.to_string(),
74                            signer: *signer,
75                        },
76                    },
77                )?;
78                send_instructions(
79                    client.rpc_client.clone(),
80                    &client.payer,
81                    client.opts.ws_url().as_str(),
82                    &[ix],
83                    &[],
84                )
85                .await?;
86                print_json(&CronTransaction {
87                    pubkey: cron_job_transaction_key,
88                    id: *index,
89                    cron_job: cron_job_key,
90                    transaction_source: Some(TransactionSource::RemoteV0 {
91                        url: url.to_string(),
92                        signer: *signer,
93                    }),
94                })?;
95            }
96            Cmd::Close {
97                cron_job,
98                id: index,
99            } => {
100                let client = opts.client().await?;
101                let cron_job_key = cron_job.get_pubkey(&client).await?.ok_or_else(|| {
102                    anyhow::anyhow!("Must provide cron-name, cron-id, or cron-pubkey")
103                })?;
104                let cron_job_transaction_key =
105                    tuktuk::cron_job_transaction::key(&cron_job_key, *index);
106                let cron_job_transaction: CronJobTransactionV0 = client
107                    .rpc_client
108                    .anchor_account(&cron_job_transaction_key)
109                    .await?
110                    .ok_or_else(|| {
111                        anyhow::anyhow!(
112                            "Cron job transaction not found: {}",
113                            cron_job_transaction_key
114                        )
115                    })?;
116                let ix = tuktuk::cron_job_transaction::remove_transaction(
117                    client.payer.pubkey(),
118                    cron_job_key,
119                    RemoveCronTransactionArgsV0 { index: *index },
120                )?;
121                send_instructions(
122                    client.rpc_client.clone(),
123                    &client.payer,
124                    client.opts.ws_url().as_str(),
125                    &[ix],
126                    &[],
127                )
128                .await?;
129                print_json(&CronTransaction {
130                    pubkey: cron_job_transaction_key,
131                    id: *index,
132                    cron_job: cron_job_key,
133                    transaction_source: Some(TransactionSource::from(to_transaction_source(
134                        cron_job_transaction.transaction,
135                    ))),
136                })?;
137            }
138            Cmd::Get {
139                cron_job,
140                id: index,
141            } => {
142                let client = opts.client().await?;
143                let cron_job_key = cron_job.get_pubkey(&client).await?.ok_or_else(|| {
144                    anyhow::anyhow!("Must provide cron-name, cron-id, or cron-pubkey")
145                })?;
146                let cron_job_transaction_key =
147                    tuktuk::cron_job_transaction::key(&cron_job_key, *index);
148                let cron_job_transaction: CronJobTransactionV0 = client
149                    .rpc_client
150                    .anchor_account(&cron_job_transaction_key)
151                    .await?
152                    .ok_or_else(|| {
153                        anyhow::anyhow!(
154                            "Cron job transaction not found: {}",
155                            cron_job_transaction_key
156                        )
157                    })?;
158                print_json(&CronTransaction {
159                    pubkey: cron_job_transaction_key,
160                    id: *index,
161                    cron_job: cron_job_key,
162                    transaction_source: Some(TransactionSource::from(to_transaction_source(
163                        cron_job_transaction.transaction,
164                    ))),
165                })?;
166            }
167            Cmd::List { cron_job } => {
168                let client = opts.client().await?;
169                let cron_job_key = cron_job.get_pubkey(&client).await?.ok_or_else(|| {
170                    anyhow::anyhow!("Must provide cron-name, cron-id, or cron-pubkey")
171                })?;
172                let cron_job: CronJobV0 = client
173                    .rpc_client
174                    .anchor_account(&cron_job_key)
175                    .await?
176                    .ok_or_else(|| anyhow::anyhow!("Cron job not found: {}", cron_job_key))?;
177                let cron_job_transaction_keys =
178                    tuktuk::cron_job_transaction::keys(&cron_job_key, &cron_job)?;
179                let cron_job_transactions = client
180                    .as_ref()
181                    .anchor_accounts::<CronJobTransactionV0>(&cron_job_transaction_keys)
182                    .await?;
183                print_json(
184                    &cron_job_transactions
185                        .iter()
186                        .map(|(pubkey, maybe_t)| {
187                            maybe_t.as_ref().map(|t| CronTransaction {
188                                pubkey: *pubkey,
189                                id: t.id,
190                                cron_job: cron_job_key,
191                                transaction_source: Some(TransactionSource::from(
192                                    to_transaction_source(t.transaction.clone()),
193                                )),
194                            })
195                        })
196                        .collect::<Vec<_>>(),
197                )?;
198            }
199        }
200        Ok(())
201    }
202}
203
204fn to_transaction_source(source: TransactionSourceV0) -> tuktuk_program::TransactionSourceV0 {
205    match source {
206        TransactionSourceV0::RemoteV0 { url, signer } => {
207            tuktuk_program::TransactionSourceV0::RemoteV0 { url, signer }
208        }
209        TransactionSourceV0::CompiledV0(transaction) => {
210            tuktuk_program::TransactionSourceV0::CompiledV0(tuktuk_program::CompiledTransactionV0 {
211                num_rw_signers: transaction.num_rw_signers,
212                num_ro_signers: transaction.num_ro_signers,
213                num_rw: transaction.num_rw,
214                accounts: transaction.accounts,
215                instructions: transaction
216                    .instructions
217                    .into_iter()
218                    .map(|i| tuktuk_program::CompiledInstructionV0 {
219                        program_id_index: i.program_id_index,
220                        accounts: i.accounts,
221                        data: i.data,
222                    })
223                    .collect(),
224                signer_seeds: transaction.signer_seeds,
225            })
226        }
227    }
228}
229
230#[derive(Serialize)]
231pub struct CronTransaction {
232    #[serde(with = "serde_pubkey")]
233    pub pubkey: Pubkey,
234    pub id: u32,
235    #[serde(with = "serde_pubkey")]
236    pub cron_job: Pubkey,
237    pub transaction_source: Option<TransactionSource>,
238}