#![no_std]
extern crate alloc;
pub use alloc::boxed::Box;
pub use alloc::string::String;
pub use alloc::vec::Vec;
pub use dharitri_codec;
pub mod abi;
pub mod err_msg;
pub mod hex_call_data;
pub mod io;
pub mod non_zero_util;
mod proxy;
pub mod storage;
pub mod types;
pub use hex_call_data::*;
pub use io::*;
pub use proxy::OtherContractHandle;
pub use storage::{storage_get, storage_set};
pub use types::*;
use core::ops::{Add, Div, Mul, Neg, Rem, Sub};
use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign};
use core::ops::{BitAnd, BitOr, BitXor, Shl, Shr};
use core::ops::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign};
pub trait ContractHookApi<BigInt, BigUint>: Sized
where
	BigInt: dharitri_codec::NestedEncode + 'static,
	BigUint: dharitri_codec::NestedEncode + 'static,
{
	fn get_sc_address(&self) -> Address;
	fn get_owner_address(&self) -> Address;
	fn get_caller(&self) -> Address;
	fn get_balance(&self, address: &Address) -> BigUint;
	fn get_sc_balance(&self) -> BigUint {
		self.get_balance(&self.get_sc_address())
	}
	fn storage_store_slice_u8(&self, key: &[u8], value: &[u8]);
	fn storage_load_len(&self, key: &[u8]) -> usize;
	fn storage_load_vec_u8(&self, key: &[u8]) -> Vec<u8>;
	fn storage_load_boxed_bytes(&self, key: &[u8]) -> BoxedBytes {
		self.storage_load_vec_u8(key).into()
	}
	fn storage_store_bytes32(&self, key: &[u8], value: &[u8; 32]);
	fn storage_load_bytes32(&self, key: &[u8]) -> [u8; 32];
	fn storage_store_big_uint(&self, key: &[u8], value: &BigUint);
	fn storage_load_big_uint(&self, key: &[u8]) -> BigUint;
	fn storage_store_big_uint_raw(&self, key: &[u8], handle: i32);
	fn storage_load_big_uint_raw(&self, key: &[u8]) -> i32;
	fn storage_store_big_int(&self, key: &[u8], value: &BigInt);
	fn storage_load_big_int(&self, key: &[u8]) -> BigInt;
	fn storage_store_u64(&self, key: &[u8], value: u64);
	fn storage_store_i64(&self, key: &[u8], value: i64);
	fn storage_load_u64(&self, key: &[u8]) -> u64;
	fn storage_load_i64(&self, key: &[u8]) -> i64;
	#[inline]
	fn storage_load_cumulated_validator_reward(&self) -> BigUint {
		self.storage_load_big_uint(storage::protected_keys::DHARITRI_REWARD_KEY)
	}
	fn get_call_value_big_uint(&self) -> BigUint;
	fn get_dct_value_big_uint(&self) -> BigUint;
	fn get_dct_token_name(&self) -> Vec<u8>;
	fn send_tx(&self, to: &Address, amount: &BigUint, data: &[u8]);
	fn async_call(&self, to: &Address, amount: &BigUint, data: &[u8]);
	fn deploy_contract(
		&self,
		gas: u64,
		amount: &BigUint,
		code: &BoxedBytes,
		code_metadata: CodeMetadata,
		arg_buffer: &ArgBuffer,
	) -> Address;
	fn get_tx_hash(&self) -> H256;
	fn get_gas_left(&self) -> u64;
	fn get_block_timestamp(&self) -> u64;
	fn get_block_nonce(&self) -> u64;
	fn get_block_round(&self) -> u64;
	fn get_block_epoch(&self) -> u64;
	fn get_block_random_seed(&self) -> Box<[u8; 48]>;
	fn get_prev_block_timestamp(&self) -> u64;
	fn get_prev_block_nonce(&self) -> u64;
	fn get_prev_block_round(&self) -> u64;
	fn get_prev_block_epoch(&self) -> u64;
	fn get_prev_block_random_seed(&self) -> Box<[u8; 48]>;
	fn sha256(&self, data: &[u8]) -> H256;
	fn keccak256(&self, data: &[u8]) -> H256;
}
pub trait ContractIOApi<BigInt, BigUint>: Clone {
	fn get_num_arguments(&self) -> i32;
	#[inline(never)] fn check_num_arguments(&self, expected: i32) {
		let nr_args = self.get_num_arguments();
		if nr_args != expected {
			self.signal_error(err_msg::ARG_WRONG_NUMBER);
		}
	}
	fn check_not_payable(&self);
	fn get_argument_len(&self, arg_index: i32) -> usize;
	fn copy_argument_to_slice(&self, arg_index: i32, slice: &mut [u8]);
	fn get_argument_vec_u8(&self, arg_index: i32) -> Vec<u8>;
	fn get_argument_boxed_bytes(&self, arg_index: i32) -> BoxedBytes {
		self.get_argument_vec_u8(arg_index).into()
	}
	fn get_argument_big_int(&self, arg_id: i32) -> BigInt;
	fn get_argument_big_uint(&self, arg_id: i32) -> BigUint;
	fn get_argument_big_int_raw(&self, arg_id: i32) -> i32;
	fn get_argument_big_uint_raw(&self, arg_id: i32) -> i32;
	fn get_argument_u64(&self, arg_id: i32) -> u64;
	fn get_argument_i64(&self, arg_id: i32) -> i64;
	fn finish_slice_u8(&self, slice: &[u8]);
	fn finish_big_int(&self, b: &BigInt);
	fn finish_big_uint(&self, b: &BigUint);
	fn finish_big_int_raw(&self, handle: i32);
	fn finish_big_uint_raw(&self, handle: i32);
	fn finish_u64(&self, value: u64);
	fn finish_i64(&self, value: i64);
	fn signal_error(&self, message: &[u8]) -> !;
	fn write_log(&self, topics: &[[u8; 32]], data: &[u8]);
}
pub trait BigUintApi:
	Sized
	+ From<u64>
	+ From<u32>
	+ From<usize>
	+ Clone
	+ Add<Output = Self>
	+ AddAssign
	+ Sub<Output = Self>
	+ SubAssign
	+ Mul<Output = Self>
	+ MulAssign
	+ Div<Output = Self>
	+ DivAssign
	+ Rem<Output = Self>
	+ RemAssign
	+ BitAnd<Output = Self>
	+ BitAndAssign
	+ BitOr<Output = Self>
	+ BitOrAssign
	+ BitXor<Output = Self>
	+ BitXorAssign
	+ Shr<usize, Output = Self>
	+ ShrAssign<usize>
	+ Shl<usize, Output = Self>
	+ ShlAssign<usize>
	+ PartialEq<Self>
	+ Eq
	+ PartialOrd<Self>
	+ Ord
	+ PartialEq<u64>
	+ PartialOrd<u64>
	+ dharitri_codec::NestedEncode
	+ dharitri_codec::TopEncode
	+ dharitri_codec::NestedDecode
	+ dharitri_codec::TopDecode
	+ abi::TypeAbi
{
	fn zero() -> Self {
		0u64.into()
	}
	fn byte_length(&self) -> i32;
	fn copy_to_slice_big_endian(&self, slice: &mut [u8]) -> i32;
	fn copy_to_array_big_endian_pad_right(&self, target: &mut [u8; 32]);
	fn to_bytes_be(&self) -> Vec<u8>;
	fn to_bytes_be_pad_right(&self, nr_bytes: usize) -> Option<Vec<u8>>;
	fn from_bytes_be(bytes: &[u8]) -> Self;
}
pub enum Sign {
	Minus,
	NoSign,
	Plus,
}
pub trait BigIntApi<BigUint>:
	Sized
	+ From<BigUint>
	+ From<i64>
	+ From<i32>
	+ Clone
	+ Add<Output = Self>
	+ AddAssign
	+ Sub<Output = Self>
	+ SubAssign
	+ Mul<Output = Self>
	+ MulAssign
	+ Div<Output = Self>
	+ DivAssign
	+ Rem<Output = Self>
	+ RemAssign
	+ Neg
	+ PartialEq<Self>
	+ Eq
	+ PartialOrd<Self>
	+ Ord
	+ PartialEq<i64>
	+ PartialOrd<i64>
	+ dharitri_codec::NestedEncode
	+ dharitri_codec::TopEncode
	+ dharitri_codec::NestedDecode
	+ dharitri_codec::TopDecode
	+ abi::TypeAbi
{
	fn zero() -> Self {
		0i64.into()
	}
	fn abs_uint(&self) -> BigUint;
	fn sign(&self) -> Sign;
	fn to_signed_bytes_be(&self) -> Vec<u8>;
	fn from_signed_bytes_be(bytes: &[u8]) -> Self;
}
pub trait CallableContract<A> {
	fn call(&self, fn_name: &[u8]) -> bool;
	fn abi(&self, include_modules: bool) -> abi::ContractAbi;
	fn clone_contract(&self) -> Box<dyn CallableContract<A>>;
	fn into_api(self: Box<Self>) -> A;
}
#[macro_export]
macro_rules! contract_proxy {
	($s:expr, $address:expr, $proxy_trait:ident) => {
		$s.contract_proxy($address) as Box<dyn $proxy_trait<BigInt, BigUint>>
	};
}
#[macro_export]
macro_rules! imports {
	() => {
		use core::ops::{Add, Div, Mul, Rem, Sub};
		use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign};
		use core::ops::{BitAnd, BitOr, BitXor, Shl, Shr};
		use core::ops::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign};
		use dharitri_wasm::dharitri_codec::{DecodeError, NestedDecode, NestedEncode, TopDecode};
		use dharitri_wasm::err_msg;
		use dharitri_wasm::io::*;
		use dharitri_wasm::non_zero_util::*;
		use dharitri_wasm::types::*;
		use dharitri_wasm::{Address, H256};
		use dharitri_wasm::{
			AsyncCallError, AsyncCallResult, BigIntApi, BigUintApi, ContractHookApi, ContractIOApi,
			OtherContractHandle,
		};
		use dharitri_wasm::{BorrowedMutStorage, Box, BoxedBytes, Queue, VarArgs, Vec};
		use dharitri_wasm::{SCError, SCResult, SCResult::Err, SCResult::Ok};
	};
}
#[macro_export]
macro_rules! derive_imports {
	() => {
		use dharitri_wasm::dharitri_codec;
		use dharitri_wasm::dharitri_codec::dharitri_codec_derive::{
			NestedDecode, NestedEncode, TopDecode, TopEncode,
		};
		use dharitri_wasm_derive::TypeAbi;
	};
}
#[macro_export]
macro_rules! sc_error {
	($s:expr) => {
		dharitri_wasm::SCResult::Err(dharitri_wasm::SCError::from($s.as_bytes()))
	};
}
#[macro_export]
macro_rules! sc_try {
	($s:expr) => {
		match $s {
			dharitri_wasm::SCResult::Ok(t) => t,
			dharitri_wasm::SCResult::Err(e) => {
				return dharitri_wasm::SCResult::Err(e);
			},
		}
	};
}
#[macro_export]
macro_rules! require {
	($expression:expr, $error_msg:expr) => {
		if (!($expression)) {
			return sc_error!($error_msg);
		}
	};
}
#[macro_export]
macro_rules! only_owner {
	($trait_self: expr, $error_msg:expr) => {
		if ($trait_self.get_caller() != $trait_self.get_owner_address()) {
			return sc_error!($error_msg);
		}
	};
}
#[macro_export]
macro_rules! mut_storage (
    ($t:ty) => (
        BorrowedMutStorage<T, BigInt, BigUint, $t>
    )
);
#[macro_export]
macro_rules! non_zero_usize {
	($input: expr, $error_msg:expr) => {
		if let Some(nz) = NonZeroUsize::new($input) {
			nz
		} else {
			return sc_error!($error_msg);
		}
	};
}