use chrono::{DateTime, Utc, Duration};
use serde::{Serialize, Deserialize};
use crate::errors::Result;
use libabieos_sys::ABIEOS;
pub(crate) mod eosio_datetime_format {
use chrono::{DateTime, Utc, TimeZone, NaiveDateTime};
use serde::{self, Deserialize, Serializer, Deserializer};
const FORMAT: &str = "%Y-%m-%dT%H:%M:%S";
pub fn serialize<S>(
date: &DateTime<Utc>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let s = format!("{}", date.format(FORMAT));
serializer.serialize_str(&s)
}
pub fn deserialize<'de, D>(
deserializer: D,
) -> Result<DateTime<Utc>, D::Error>
where
D: Deserializer<'de>,
{
let s: String = String::deserialize(deserializer)?;
let len = s.len();
let slice_len = if s.contains('.') {
len.saturating_sub(4)
} else {
len
};
let sliced = &s[0..slice_len];
match NaiveDateTime::parse_from_str(sliced, FORMAT) {
Err(_e) => {
eprintln!("DateTime Fail {} {:#?}", sliced, _e);
Err(serde::de::Error::custom(_e))
}
Ok(dt) => Ok(Utc.from_utc_datetime(&dt)),
}
}
}
fn byte_to_char(x: u8) -> char {
(if x <= 9 {
x + b'0'
} else {
x - 10 + b'a'
}) as char
}
pub fn vec_u8_to_hex(out: &[u8]) -> Result<String> {
let mut str = String::with_capacity(out.len());
for x in out {
str.push(byte_to_char((x & 0xf0).checked_shr(4).unwrap_or(0)));
str.push(byte_to_char(x & 0x0f));
}
Ok(str)
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ResourceLimit {
max: isize,
available: isize,
used: isize,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Key {
key: String,
weight: isize,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Permission {
permission: String,
actor: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Account {
weight: isize,
permission: Permission,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct RequiredAuth {
waits: Vec<String>,
threshold: isize,
accounts: Vec<Account>,
keys: Vec<Key>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Permissions {
parent: String,
perm_name: String,
required_auth: RequiredAuth,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct VoterInfo {
producers: Vec<String>,
is_proxy: isize,
owner: String,
proxy: String,
flags1: isize,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct GetAccount {
account_name: String,
head_block_num: usize,
privileged: bool,
#[serde(with = "eosio_datetime_format")]
last_code_update: DateTime<Utc>,
#[serde(with = "eosio_datetime_format")]
head_block_time: DateTime<Utc>,
#[serde(with = "eosio_datetime_format")]
created: DateTime<Utc>,
core_liquid_balance: Option<String>,
ram_quota: isize,
net_weight: isize,
cpu_weight: isize,
ram_usage: usize,
cpu_limit: ResourceLimit,
net_limit: ResourceLimit,
voter_info: Option<VoterInfo>,
refund_request: Option<String>,
permissions: Vec<Permissions>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AbiTypes {
new_type_name: String,
#[serde(rename = "type")]
abi_type: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AbiField {
name: String,
#[serde(rename = "type")]
abi_type: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AbiStruct {
name: String,
base: String,
fields: Vec<AbiField>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AbiAction {
name: String,
#[serde(rename = "type")]
abi_type: String,
ricardian_contract: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AbiTable {
name: String,
#[serde(rename = "type")]
abi_type: String,
index_type: String,
key_names: Vec<String>,
key_types: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AbiRicardianClauses {
id: String,
body: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AbiErrorMessages {
error_code: String,
error_msg: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AbiExtensions {
tag: String,
value: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AbiVariants {
name: String,
typea: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Abi {
version: String,
types: Vec<AbiTypes>,
structs: Vec<AbiStruct>,
actions: Vec<AbiAction>,
tables: Vec<AbiTable>,
ricardian_clauses: Vec<AbiRicardianClauses>,
error_messages: Vec<AbiErrorMessages>,
abi_extensions: Vec<AbiExtensions>,
variants: Vec<AbiVariants>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct GetAbi {
account_name: String,
abi: Abi,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct RequiredKeys {
pub required_keys: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct GetInfo {
server_version: String,
pub chain_id: String,
pub head_block_num: usize,
pub last_irreversible_block_num: usize,
pub last_irreversible_block_id: String,
pub head_block_id: String,
#[serde(with = "eosio_datetime_format")]
pub head_block_time: DateTime<Utc>,
head_block_producer: String,
virtual_block_cpu_limit: usize,
virtual_block_net_limit: usize,
block_cpu_limit: usize,
block_net_limit: usize,
server_version_string: String,
fork_db_head_block_num: usize,
fork_db_head_block_id: String,
server_full_version_string: Option<String>,
}
impl GetInfo {
pub fn set_exp_time(&self, duration: Duration) -> DateTime<Utc> {
self.head_block_time + duration
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AuthorizationIn {
pub actor: String,
pub permission: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct GetCodeHash {
pub account_name: String,
pub code_hash: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ActionIn {
pub account: String,
pub name: String,
pub authorization: Vec<AuthorizationIn>,
pub data: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct TransactionInSigned {
#[serde(with = "eosio_datetime_format")]
expiration: DateTime<Utc>,
ref_block_num: u16,
ref_block_prefix: u32,
max_net_usage_words: u32,
max_cpu_usage_ms: u8,
delay_sec: u32,
context_free_actions: Vec<String>,
pub actions: Vec<ActionIn>,
transaction_extensions: Vec<String>,
pub signatures: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct TransactionIn {
#[serde(with = "eosio_datetime_format")]
expiration: DateTime<Utc>,
ref_block_num: u16,
ref_block_prefix: u32,
max_net_usage_words: u32,
max_cpu_usage_ms: u8,
delay_sec: u32,
context_free_actions: Vec<String>,
pub actions: Vec<ActionIn>,
transaction_extensions: Vec<String>,
}
impl TransactionIn {
pub fn dummy() -> TransactionIn {
TransactionIn {
transaction_extensions: vec![],
ref_block_num: 0,
max_net_usage_words: 0,
expiration: Utc::now() + Duration::days(1),
delay_sec: 0,
max_cpu_usage_ms: 0,
actions: vec![],
ref_block_prefix: 0,
context_free_actions: vec![],
}
}
pub fn simple(actions: Vec<ActionIn>, ref_block_id: &str, expiration: DateTime<Utc>) -> Result<TransactionIn> {
let hash = TransactionIn::block_to_hash(ref_block_id)?;
let ref_block_num: u16 = (((hash[0] >> 32) & 0xffff_ffff) as u16).to_le();
let ref_block_prefix: u32 = ((hash[1] >> 32 & 0xffff_ffff) as u32).to_be();
Ok(TransactionIn {
transaction_extensions: vec![],
ref_block_num,
max_net_usage_words: 0,
expiration,
delay_sec: 0,
max_cpu_usage_ms: 0,
actions,
ref_block_prefix,
context_free_actions: vec![],
})
}
pub fn hex_to_u64(hex: &str) -> u64 {
let mut val: u64 = 0;
for char in hex.bytes() {
let digit = if char >= b'a' {
char + 10 - b'a'
} else {
char - b'0'
};
val = (val << 4) + digit as u64;
}
val
}
pub fn block_to_hash(ref_block_id: &str) -> Result<Vec<u64>> {
if ref_block_id.len() != 64 {
Err("Invalid ref_block id. expecting len of 64".into())
} else {
let v: Vec<u64> = vec![TransactionIn::hex_to_u64(&ref_block_id[0..16]),
TransactionIn::hex_to_u64(&ref_block_id[16..32]),
TransactionIn::hex_to_u64(&ref_block_id[33..48]),
TransactionIn::hex_to_u64(&ref_block_id[49..64])];
Ok(v)
}
}
}
#[derive(Debug, Deserialize, Serialize)]
pub struct ErrorDetails {
pub message: String,
pub file: String,
pub line_number: usize,
pub method: String,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct ErrorInt {
pub code: usize,
pub name: String,
pub what: String,
pub details: Vec<ErrorDetails>,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct ErrorReply {
pub code: usize,
pub message: String,
pub error: ErrorInt,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct PackedTransactionIn {
pub signatures: Vec<String>,
pub compression: String,
pub packed_context_free_data: String,
pub packed_trx: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct GetRawABI {
pub account_name: String,
pub code_hash: String,
pub abi_hash: String,
pub abi: String,
}
impl GetRawABI {
fn fix_padding(str: &str) -> String {
let mut bare: String = str.replacen('=', "", 4);
let len = bare.len();
let to_len = len + (4 - (len % 4));
for _i in len..to_len {
bare.push('=');
}
bare
}
pub fn decode_abi(&self) -> Result<Vec<u8>> {
let fixed = GetRawABI::fix_padding(&self.abi);
Ok(base64::decode(fixed)?)
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ActionSetcodeData {
pub(crate) account: String,
pub(crate) vmtype: u8,
pub(crate) vmversion: u8,
pub(crate) code: String,
}
impl ActionSetcodeData {
pub fn to_hex(&self, abieos: &ABIEOS) -> Result<String> {
let json = format!("{{ \"account\":\"{}\", \"vmtype\":{},\"vmversion\":{},\"code\":\"{}\" }}",
self.account, self.vmtype, self.vmversion, self.code);
unsafe {
let hex = abieos.json_to_hex("eosio", "setcode", &json)?;
Ok(String::from(hex))
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ActionSetData {
pub(crate) account: String,
pub(crate) abi: String,
}
impl ActionSetData {
pub fn to_hex(&self, abieos: &ABIEOS) -> Result<String> {
let json = format!("{{ \"account\":\"{}\", \"abi\":\"{}\"}}", self.account, self.abi);
unsafe {
let hex = abieos.json_to_hex("eosio", "setabi", &json);
Ok(String::from(hex?))
}
}
}
#[derive(Debug, Deserialize)]
pub struct TransactionResponse {
pub processed: TransactionProcessedResponse,
pub transaction_id: String,
}
#[derive(Debug, Deserialize)]
pub struct TransactionReceipt {
cpu_usage_us: usize,
net_usage_words: usize,
status: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AccountRamDelta {
account: String,
delta: isize,
}
#[derive(Debug, Deserialize)]
pub struct ActionReceipt {
receiver: String,
abi_sequence: usize,
recv_sequence: usize,
code_sequence: usize,
global_sequence: usize,
act_digest: String,
}
#[derive(Debug, Deserialize)]
#[serde(untagged)]
enum ActionACTData {
ActionACTDataSetCode {
code: Option<String>,
vmtype: usize,
account: String,
vmversion: usize,
},
String,
}
#[derive(Debug, Deserialize)]
pub struct ActionACT {
authorization: Vec<Permission>,
name: String,
account: String,
hex_data: String,
}
#[derive(Debug, Deserialize)]
pub struct ActionTrace {
account_ram_deltas: Vec<AccountRamDelta>,
console: Option<String>,
action_ordinal: isize,
receipt: ActionReceipt,
act: ActionACT,
context_free: bool,
producer_block_id: Option<String>,
except: Option<String>,
trx_id: String,
block_num: usize,
error_code: Option<String>,
#[serde(with = "eosio_datetime_format")]
block_time: DateTime<Utc>,
closest_unnotified_ancestor_action_ordinal: usize,
elapsed: usize,
receiver: String,
return_value: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct TransactionProcessedResponse {
scheduled: bool,
error_code: Option<String>,
action_traces: Vec<ActionTrace>,
pub block_num: usize,
producer_block_id: Option<String>,
except: Option<String>,
pub receipt: TransactionReceipt,
pub id: String,
elapsed: usize,
net_usage: usize,
#[serde(with = "eosio_datetime_format")]
block_time: DateTime<Utc>,
account_ram_delta: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct BlockTransactionAction {
pub account: String,
pub name: String,
pub authorization: Vec<AuthorizationIn>,
pub data: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct BlockTransaction {
#[serde(with = "eosio_datetime_format")]
expiration: DateTime<Utc>,
ref_block_num: u16,
ref_block_prefix: u32,
max_net_usage_words: u32,
max_cpu_usage_ms: u8,
delay_sec: u32,
context_free_actions: Vec<String>,
pub actions: Vec<BlockTransactionAction>,
}
#[derive(Debug, Deserialize)]
pub struct BlockTransactionTrx {
pub id: String,
signatures: Vec<String>,
compression: String,
packed_context_free_data: String,
packed_trx: String,
pub transaction: BlockTransaction,
}
#[derive(Debug, Deserialize)]
pub struct BlockTransactions {
status: String,
cpu_usage_us: usize,
net_usage_words: usize,
pub trx: BlockTransactionTrx,
}
#[derive(Debug, Deserialize)]
pub struct GetBlock {
#[serde(with = "eosio_datetime_format")]
timestamp: DateTime<Utc>,
producer: String,
confirmed: usize,
previous: String,
transaction_mroot: String,
action_mroot: String,
schedule_version: usize,
new_producers: Option<String>,
producer_signature: String,
pub transactions: Vec<BlockTransactions>,
pub id: String,
pub block_num: usize,
ref_block_prefix: usize,
}
#[derive(Debug, Deserialize)]
pub struct TableRow {
pub code: String,
pub scope: String,
pub table: String,
pub payer: String,
pub count: usize,
}
#[derive(Debug, Deserialize)]
pub struct GetTableByScope {
pub rows: Vec<TableRow>,
pub more: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct GetTableByScopeIn {
pub code: String,
pub table: String,
pub lower_bound: String,
pub upper_bound: String,
pub limit: usize,
pub reverse: bool,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct GetTableRowsIn {
pub json: bool,
pub code: String,
pub scope: String,
pub table: String,
pub table_key: String,
pub lower_bound: String,
pub upper_bound: String,
pub limit: usize,
pub key_type: String,
pub index_position: String,
pub encode_type: String,
pub reverse: bool,
pub show_payer: bool,
}
#[derive(Debug, Deserialize)]
pub struct GetTableRow {
pub data:String,
pub payer:Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct GetTableRows {
pub rows: Vec<GetTableRow>,
pub more: bool,
pub next_key:String,
}