use std::{convert::TryFrom, fmt::Debug, hash::Hash};
use anchor_lang::{
prelude::borsh::BorshSchema,
prelude::Pubkey,
prelude::*,
solana_program::{self, instruction::Instruction},
AnchorDeserialize,
};
use serde::{Deserialize, Serialize};
use static_pubkey::static_pubkey;
pub static PAYER_PUBKEY: Pubkey = static_pubkey!("C1ockworkPayer11111111111111111111111111111");
#[derive(AnchorDeserialize, AnchorSerialize, BorshSchema, Clone, Debug, PartialEq)]
pub struct ClockData {
pub slot: u64,
pub epoch: u64,
pub unix_timestamp: i64,
}
impl From<Clock> for ClockData {
fn from(clock: Clock) -> Self {
ClockData {
slot: clock.slot,
epoch: clock.epoch,
unix_timestamp: clock.unix_timestamp,
}
}
}
impl TryFrom<Vec<u8>> for ClockData {
type Error = Error;
fn try_from(data: Vec<u8>) -> std::result::Result<Self, Self::Error> {
Ok(
borsh::try_from_slice_with_schema::<ClockData>(data.as_slice())
.map_err(|_err| ErrorCode::AccountDidNotDeserialize)?,
)
}
}
#[derive(AnchorDeserialize, AnchorSerialize, Debug, Clone, PartialEq)]
pub enum Trigger {
Account {
address: Pubkey,
offset: u64,
size: u64,
},
Cron {
schedule: String,
skippable: bool,
},
Now,
Slot { slot: u64 },
Epoch { epoch: u64 },
Timestamp { unix_ts: i64 },
Pyth {
price_feed: Pubkey,
equality: Equality,
limit: i64,
},
}
#[repr(u8)]
#[derive(AnchorDeserialize, AnchorSerialize, Clone, Debug, Eq, PartialEq, Hash)]
pub enum Equality {
GreaterThanOrEqual,
LessThanOrEqual,
}
#[derive(AnchorDeserialize, AnchorSerialize, Clone, Debug)]
pub struct ThreadResponse {
pub close_to: Option<Pubkey>,
pub dynamic_instruction: Option<SerializableInstruction>,
pub trigger: Option<Trigger>,
}
impl Default for ThreadResponse {
fn default() -> Self {
return Self {
close_to: None,
dynamic_instruction: None,
trigger: None,
};
}
}
#[derive(
AnchorDeserialize,
AnchorSerialize,
Serialize,
Deserialize,
BorshSchema,
Clone,
Debug,
Hash,
PartialEq,
)]
pub struct SerializableInstruction {
pub program_id: Pubkey,
pub accounts: Vec<SerializableAccount>,
pub data: Vec<u8>,
}
impl From<Instruction> for SerializableInstruction {
fn from(instruction: Instruction) -> Self {
SerializableInstruction {
program_id: instruction.program_id,
accounts: instruction
.accounts
.iter()
.map(|a| SerializableAccount {
pubkey: a.pubkey,
is_signer: a.is_signer,
is_writable: a.is_writable,
})
.collect(),
data: instruction.data,
}
}
}
impl From<&SerializableInstruction> for Instruction {
fn from(instruction: &SerializableInstruction) -> Self {
Instruction {
program_id: instruction.program_id,
accounts: instruction
.accounts
.iter()
.map(|a| AccountMeta {
pubkey: a.pubkey,
is_signer: a.is_signer,
is_writable: a.is_writable,
})
.collect(),
data: instruction.data.clone(),
}
}
}
impl TryFrom<Vec<u8>> for SerializableInstruction {
type Error = Error;
fn try_from(data: Vec<u8>) -> std::result::Result<Self, Self::Error> {
Ok(
borsh::try_from_slice_with_schema::<SerializableInstruction>(data.as_slice())
.map_err(|_err| ErrorCode::AccountDidNotDeserialize)?,
)
}
}
#[derive(
AnchorDeserialize,
AnchorSerialize,
Serialize,
Deserialize,
BorshSchema,
Clone,
Debug,
Hash,
PartialEq,
)]
pub struct SerializableAccount {
pub pubkey: Pubkey,
pub is_signer: bool,
pub is_writable: bool,
}
impl SerializableAccount {
pub fn mutable(pubkey: Pubkey, signer: bool) -> Self {
Self {
pubkey,
is_signer: signer,
is_writable: true,
}
}
pub fn readonly(pubkey: Pubkey, signer: bool) -> Self {
Self {
pubkey,
is_signer: signer,
is_writable: false,
}
}
}