1use std::{convert::TryFrom, fmt::Debug, hash::Hash};
2
3use anchor_lang::{
4 prelude::borsh::BorshSchema,
5 prelude::Pubkey,
6 prelude::*,
7 solana_program::{self, instruction::Instruction},
8 AnchorDeserialize,
9};
10use serde::{Deserialize, Serialize};
11use static_pubkey::static_pubkey;
12
13pub static PAYER_PUBKEY: Pubkey = static_pubkey!("C1ockworkPayer11111111111111111111111111111");
15
16#[derive(AnchorDeserialize, AnchorSerialize, BorshSchema, Clone, Debug, PartialEq)]
18pub struct ClockData {
19 pub slot: u64,
21 pub epoch: u64,
23 pub unix_timestamp: i64,
25}
26
27impl From<Clock> for ClockData {
28 fn from(clock: Clock) -> Self {
29 ClockData {
30 slot: clock.slot,
31 epoch: clock.epoch,
32 unix_timestamp: clock.unix_timestamp,
33 }
34 }
35}
36
37impl TryFrom<Vec<u8>> for ClockData {
38 type Error = Error;
39 fn try_from(data: Vec<u8>) -> std::result::Result<Self, Self::Error> {
40 Ok(
41 borsh::try_from_slice_with_schema::<ClockData>(data.as_slice())
42 .map_err(|_err| ErrorCode::AccountDidNotDeserialize)?,
43 )
44 }
45}
46
47#[derive(AnchorDeserialize, AnchorSerialize, Debug, Clone, PartialEq)]
49pub enum Trigger {
50 Account {
52 address: Pubkey,
54 offset: u64,
56 size: u64,
58 },
59
60 Cron {
62 schedule: String,
64
65 skippable: bool,
68 },
69
70 Now,
72
73 Slot {
75 slot: u64,
76 },
77
78 Epoch {
80 epoch: u64,
81 },
82
83 Timestamp {
84 unix_ts: i64,
85 },
86}
87
88#[derive(AnchorDeserialize, AnchorSerialize, Clone, Debug)]
90pub struct ThreadResponse {
91 pub close_to: Option<Pubkey>,
94 pub dynamic_instruction: Option<SerializableInstruction>,
97 pub trigger: Option<Trigger>,
99}
100
101impl Default for ThreadResponse {
102 fn default() -> Self {
103 return Self {
104 close_to: None,
105 dynamic_instruction: None,
106 trigger: None,
107 };
108 }
109}
110
111#[derive(
113 AnchorDeserialize,
114 AnchorSerialize,
115 Serialize,
116 Deserialize,
117 BorshSchema,
118 Clone,
119 Debug,
120 Hash,
121 PartialEq,
122)]
123pub struct SerializableInstruction {
124 pub program_id: Pubkey,
126 pub accounts: Vec<SerializableAccount>,
128 pub data: Vec<u8>,
130}
131
132impl From<Instruction> for SerializableInstruction {
133 fn from(instruction: Instruction) -> Self {
134 SerializableInstruction {
135 program_id: instruction.program_id,
136 accounts: instruction
137 .accounts
138 .iter()
139 .map(|a| SerializableAccount {
140 pubkey: a.pubkey,
141 is_signer: a.is_signer,
142 is_writable: a.is_writable,
143 })
144 .collect(),
145 data: instruction.data,
146 }
147 }
148}
149
150impl From<&SerializableInstruction> for Instruction {
151 fn from(instruction: &SerializableInstruction) -> Self {
152 Instruction {
153 program_id: instruction.program_id,
154 accounts: instruction
155 .accounts
156 .iter()
157 .map(|a| AccountMeta {
158 pubkey: a.pubkey,
159 is_signer: a.is_signer,
160 is_writable: a.is_writable,
161 })
162 .collect(),
163 data: instruction.data.clone(),
164 }
165 }
166}
167
168impl TryFrom<Vec<u8>> for SerializableInstruction {
169 type Error = Error;
170 fn try_from(data: Vec<u8>) -> std::result::Result<Self, Self::Error> {
171 Ok(
172 borsh::try_from_slice_with_schema::<SerializableInstruction>(data.as_slice())
173 .map_err(|_err| ErrorCode::AccountDidNotDeserialize)?,
174 )
175 }
176}
177
178#[derive(
180 AnchorDeserialize,
181 AnchorSerialize,
182 Serialize,
183 Deserialize,
184 BorshSchema,
185 Clone,
186 Debug,
187 Hash,
188 PartialEq,
189)]
190pub struct SerializableAccount {
191 pub pubkey: Pubkey,
193 pub is_signer: bool,
195 pub is_writable: bool,
197}
198
199impl SerializableAccount {
200 pub fn mutable(pubkey: Pubkey, signer: bool) -> Self {
202 Self {
203 pubkey,
204 is_signer: signer,
205 is_writable: true,
206 }
207 }
208
209 pub fn readonly(pubkey: Pubkey, signer: bool) -> Self {
211 Self {
212 pubkey,
213 is_signer: signer,
214 is_writable: false,
215 }
216 }
217}