use std::ops::Deref;
use crate::{script, transaction};
use bitcoin::hashes::{sha256d, Hash};
use candid::CandidType;
use serde::{Deserialize, Serialize};
use serde_bytes::{ByteArray, ByteBuf};
use sha3::{Digest, Sha3_256};
mod agent;
pub use agent::*;
#[derive(CandidType, Clone, Debug, Default, Deserialize, Serialize)]
pub struct Txid(pub ByteN<32>);
impl std::str::FromStr for Txid {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let h = sha256d::Hash::from_str(s).map_err(|_| "invalid Txid")?;
Ok(Self(h.to_byte_array().into()))
}
}
impl std::fmt::Display for Txid {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
sha256d::Hash::from_bytes_ref(&self.0).fmt(f)
}
}
impl From<ByteN<32>> for Txid {
fn from(val: ByteN<32>) -> Self {
Self(val)
}
}
impl From<ByteArray<32>> for Txid {
fn from(val: ByteArray<32>) -> Self {
Self(ByteN(val))
}
}
impl From<[u8; 32]> for Txid {
fn from(val: [u8; 32]) -> Self {
Self(val.into())
}
}
impl From<transaction::Txid> for Txid {
fn from(txid: transaction::Txid) -> Self {
Self((*txid).into())
}
}
impl From<Txid> for transaction::Txid {
fn from(txid: Txid) -> Self {
Self::from_byte_array(*txid.0)
}
}
#[derive(CandidType, Clone, Debug, Default, Deserialize, Serialize)]
pub struct Address(pub ByteN<21>);
impl From<ByteN<21>> for Address {
fn from(val: ByteN<21>) -> Self {
Self(val)
}
}
impl From<ByteArray<21>> for Address {
fn from(val: ByteArray<21>) -> Self {
Self(ByteN(val))
}
}
impl From<[u8; 21]> for Address {
fn from(val: [u8; 21]) -> Self {
Self(val.into())
}
}
impl From<script::Address> for Address {
fn from(addr: script::Address) -> Self {
Self(addr.0.into())
}
}
impl From<Address> for script::Address {
fn from(addr: Address) -> Self {
Self(*addr.0)
}
}
impl std::str::FromStr for Address {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let addr = script::Address::from_str(s)?;
Ok(Self(addr.0.into()))
}
}
impl std::fmt::Display for Address {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
script::Address(*self.0).fmt(f)
}
}
#[derive(CandidType, Clone, Debug, Default, Deserialize, Serialize)]
pub struct OutPoint {
pub txid: Txid,
pub vout: u32,
}
impl From<transaction::OutPoint> for OutPoint {
fn from(val: transaction::OutPoint) -> Self {
Self {
txid: val.txid.into(),
vout: val.vout,
}
}
}
impl From<OutPoint> for transaction::OutPoint {
fn from(val: OutPoint) -> Self {
Self {
txid: val.txid.into(),
vout: val.vout,
}
}
}
#[derive(CandidType, Clone, Debug, Default, Deserialize, Serialize)]
pub struct Utxo {
pub height: u64, pub txid: Txid,
pub vout: u32,
pub value: u64,
}
impl From<Utxo> for transaction::TxIn {
fn from(val: Utxo) -> Self {
Self::with_outpoint(transaction::OutPoint {
txid: val.txid.into(),
vout: val.vout,
})
}
}
#[derive(CandidType, Clone, Debug, Default, Deserialize, Serialize)]
pub struct UnspentTx {
pub height: u64, pub output: Vec<ByteBuf>, pub spent: Vec<Option<Txid>>, }
#[derive(CandidType, Clone, Debug, Serialize, Deserialize)]
pub struct BlockRef {
pub hash: ByteN<32>,
pub height: u64,
}
pub fn sha3_256(data: &[u8]) -> [u8; 32] {
let mut hasher = Sha3_256::new();
hasher.update(data);
hasher.finalize().into()
}
#[derive(CandidType, Clone, Debug, Serialize, Deserialize)]
pub struct SendSignedTransactionInput {
pub tx: ByteBuf,
}
#[derive(CandidType, Clone, Debug, Serialize, Deserialize)]
pub struct SendSignedTransactionOutput {
pub txid: Txid,
pub tip_height: u64,
pub instructions: u64,
}
#[derive(CandidType, Clone, Debug, Serialize, Deserialize)]
pub struct CreateSignedTransactionInput {
pub address: String,
pub amount: u64,
pub fee_rate: u64, pub from_subaccount: Option<ByteN<32>>,
}
#[derive(CandidType, Clone, Debug, Serialize, Deserialize)]
pub struct CreateSignedTransactionOutput {
pub tx: ByteBuf,
pub tip_height: u64,
pub instructions: u64,
}
#[derive(CandidType, Clone, Debug, Serialize, Deserialize)]
pub struct UtxosOutput {
pub tip_height: u64,
pub tip_blockhash: ByteN<32>,
pub confirmed_height: u64,
pub utxos: Vec<Utxo>,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ByteN<const N: usize>(pub ByteArray<N>);
impl<const N: usize> Default for ByteN<N> {
fn default() -> Self {
Self(ByteArray::new([0u8; N]))
}
}
impl<const N: usize> CandidType for ByteN<N> {
fn _ty() -> candid::types::internal::Type {
candid::types::internal::TypeInner::Vec(candid::types::internal::TypeInner::Nat8.into())
.into()
}
fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
where
S: candid::types::Serializer,
{
serializer.serialize_blob(self.0.as_slice())
}
}
impl<const N: usize> Deref for ByteN<N> {
type Target = [u8; N];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<const N: usize> AsRef<[u8; N]> for ByteN<N> {
fn as_ref(&self) -> &[u8; N] {
&self.0
}
}
impl<const N: usize> From<[u8; N]> for ByteN<N> {
fn from(val: [u8; N]) -> Self {
Self(ByteArray::new(val))
}
}
impl<const N: usize> From<ByteArray<N>> for ByteN<N> {
fn from(val: ByteArray<N>) -> Self {
Self(val)
}
}
impl<const N: usize> From<ByteN<N>> for ByteArray<N> {
fn from(val: ByteN<N>) -> Self {
val.0
}
}