use async_trait::async_trait;
use primitive_types::H160;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use crate::{
neo_builder::{AccountSigner, TransactionBuilder},
neo_clients::{JsonRpcProvider, RpcClient},
neo_contract::{ContractError, SmartContractTrait},
neo_protocol::Account,
neo_types::{
serde_with_utils::{deserialize_script_hash, serialize_script_hash},
ScriptHash,
},
ContractParameter,
};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NeoXBridgeContract<'a, P: JsonRpcProvider> {
#[serde(deserialize_with = "deserialize_script_hash")]
#[serde(serialize_with = "serialize_script_hash")]
script_hash: ScriptHash,
#[serde(skip)]
provider: Option<&'a RpcClient<P>>,
}
impl<'a, P: JsonRpcProvider + 'static> NeoXBridgeContract<'a, P> {
pub const CONTRACT_HASH: &'static str = "74f2dc36a68fdc4682034178eb2220729231db76";
pub const DEPOSIT: &'static str = "deposit";
pub const WITHDRAW: &'static str = "withdraw";
pub const GET_FEE: &'static str = "getFee";
pub const GET_CAP: &'static str = "getCap";
pub fn new(provider: Option<&'a RpcClient<P>>) -> Result<Self, ContractError> {
Ok(Self {
script_hash: ScriptHash::from_str(Self::CONTRACT_HASH).map_err(|e| {
ContractError::InvalidScriptHash(format!("Invalid contract hash: {}", e))
})?,
provider,
})
}
pub fn with_script_hash(script_hash: ScriptHash, provider: Option<&'a RpcClient<P>>) -> Self {
Self { script_hash, provider }
}
pub async fn deposit(
&self,
token: &ScriptHash,
amount: i64,
destination: &str,
account: &Account,
) -> Result<TransactionBuilder<'_, P>, ContractError> {
let params = vec![
token.into(),
ContractParameter::integer(amount),
ContractParameter::string(destination.to_string()),
];
let mut builder = self.invoke_function(Self::DEPOSIT, params).await?;
let _ = builder.set_signers(vec![AccountSigner::called_by_entry(account)
.map_err(|e| {
ContractError::InvalidAccount(format!("Failed to create account signer: {}", e))
})?
.into()]);
Ok(builder)
}
pub async fn withdraw(
&self,
token: &ScriptHash,
amount: i64,
destination: &str,
account: &Account,
) -> Result<TransactionBuilder<'_, P>, ContractError> {
let params = vec![
token.into(),
ContractParameter::integer(amount),
ContractParameter::string(destination.to_string()),
];
let mut builder = self.invoke_function(Self::WITHDRAW, params).await?;
let _ = builder.set_signers(vec![AccountSigner::called_by_entry(account)
.map_err(|e| {
ContractError::InvalidAccount(format!("Failed to create account signer: {}", e))
})?
.into()]);
Ok(builder)
}
pub async fn get_fee(&self, token: &ScriptHash) -> Result<u64, ContractError> {
let result = self.call_function_returning_int(Self::GET_FEE, vec![token.into()]).await?;
Ok(result as u64)
}
pub async fn get_cap(&self, token: &ScriptHash) -> Result<u64, ContractError> {
let result = self.call_function_returning_int(Self::GET_CAP, vec![token.into()]).await?;
Ok(result as u64)
}
}
#[async_trait]
impl<'a, P: JsonRpcProvider> SmartContractTrait<'a> for NeoXBridgeContract<'a, P> {
type P = P;
fn script_hash(&self) -> H160 {
self.script_hash
}
fn set_script_hash(&mut self, script_hash: H160) {
self.script_hash = script_hash;
}
fn provider(&self) -> Option<&RpcClient<P>> {
self.provider
}
}