diff --git a/protocol-units/bridge/chains/movement/src/lib.rs b/protocol-units/bridge/chains/movement/src/lib.rs index 580f8b193..f36262c85 100644 --- a/protocol-units/bridge/chains/movement/src/lib.rs +++ b/protocol-units/bridge/chains/movement/src/lib.rs @@ -1,15 +1,18 @@ +use aptos_api::accounts::Account; use aptos_sdk::{move_types::language_storage::TypeTag, rest_client::Client, types::LocalAccount}; use aptos_types::account_address::AccountAddress; use bridge_shared::{ + bridge_contracts::{ BridgeContractCounterparty, BridgeContractCounterpartyError, - BridgeContractCounterpartyResult, + BridgeContractCounterpartyResult, BridgeContractInitiator, BridgeContractInitiatorResult, BridgeContractInitiatorError }, types::{ Amount, BridgeTransferDetails, BridgeTransferId, HashLock, HashLockPreImage, InitiatorAddress, RecipientAddress, TimeLock, }, }; +use utils::send_view_request; use rand::prelude::*; use serde::Serialize; use std::str::FromStr; @@ -30,30 +33,45 @@ enum Call { GetDetails, } +#[derive(Clone, Debug)] pub struct Config { - pub rpc_url: Option, - pub ws_url: Option, - pub chain_id: String, - pub signer_private_key: String, - pub initiator_contract: MovementAddress, + pub rpc_url: Url, + pub ws_url: Option, + pub signer_private_key: Option, + pub initiator_contract: Option, + pub counterparty_contract: Option, pub gas_limit: u64, } +impl Config { + pub fn build_for_test() -> Self { + Config { + rpc_url: "http://localhost:30731".parse().unwrap(), + ws_url: Some(Url::parse("ws://localhost:30731").unwrap()), + signer_private_key: None, + initiator_contract: None, + counterparty_contract: None, + gas_limit: 10_000_000_000, + } + } +} + #[allow(dead_code)] #[derive(Clone)] pub struct MovementClient { ///Address of the counterparty moduke counterparty_address: AccountAddress, ///Address of the initiator module - initiator_address: Vec, + initiator_address: AccountAddress, ///The Apotos Rest Client rest_client: Client, ///The signer account signer: Arc, + config: Config, } impl MovementClient { - pub async fn new(config: Config) -> Result { + pub async fn new(config: impl Into) -> Result { let dot_movement = dot_movement::DotMovement::try_from_env().unwrap(); let suzuka_config = dot_movement.try_get_config_from_json::().unwrap(); @@ -75,13 +93,26 @@ impl MovementClient { let mut rng = rand::rngs::StdRng::from_seed(seed); let signer = LocalAccount::generate(&mut rng); + let initiator_address_bytes = signer.address().to_vec(); + let initiator_address_array: [u8; 32] = initiator_address_bytes.try_into().expect("Address must be 32 bytes"); + + let initiator_address = AccountAddress::new(initiator_address_array); Ok(MovementClient { - initiator_address: Vec::new(), //dummy for now + initiator_address, rest_client, counterparty_address: DUMMY_ADDRESS, signer: Arc::new(signer), + config: config.into(), }) } + + pub async fn get_signer_address(&self) -> AccountAddress { + self.signer.address() + } + + pub async fn get_block_number(&self) -> Result { + Ok(0) + } } #[async_trait::async_trait] @@ -170,12 +201,96 @@ impl BridgeContractCounterparty for MovementClient { _bridge_transfer_id: BridgeTransferId, ) -> BridgeContractCounterpartyResult>> { - // let _ = utils::send_view_request( - // self.rest_client, - // self.counterparty_address, - // "atomic_bridge_counterparty".to_string(), - // ); - todo!(); + send_view_request( + self.rest_client.clone() as &MovementClient, + self.counterparty_address, + COUNTERPARTY_MODULE_NAME, + "get_bridge_transfer_details", + self.counterparty_type_args(Call::GetDetails), + vec![], + ) + } +} + +#[async_trait::async_trait] +impl BridgeContractInitiator for MovementClient { + type Address = MovementAddress; + type Hash = [u8; 32]; + + async fn initiate_bridge_transfer( + &mut self, + initiator_address: InitiatorAddress, + recipient_address: RecipientAddress>, + hash_lock: HashLock, + time_lock: TimeLock, + amount: Amount, + ) -> BridgeContractInitiatorResult<()> { + let args = vec![ + to_bcs_bytes(&initiator_address.0).unwrap(), + to_bcs_bytes(&recipient_address.0).unwrap(), + to_bcs_bytes(&hash_lock.0).unwrap(), + to_bcs_bytes(&time_lock.0).unwrap(), + to_bcs_bytes(&amount.0).unwrap(), + ]; + let payload = utils::make_aptos_payload( + self.initiator_address, + "atomic_bridge_initiator", + "initiate_bridge_transfer", + self.counterparty_type_args(Call::Lock), + args, + ); + let _ = utils::send_aptos_transaction(&self.rest_client, self.signer.as_ref(), payload) + .await + .map_err(|_| BridgeContractInitiatorError::InitiateTransferError); + Ok(()) + } + + async fn complete_bridge_transfer( + &mut self, + bridge_transfer_id: BridgeTransferId, + preimage: HashLockPreImage, + ) -> BridgeContractInitiatorResult<()> { + let args = vec![ + to_bcs_bytes(&bridge_transfer_id.0).unwrap(), + to_bcs_bytes(&preimage.0).unwrap(), + ]; + let payload = utils::make_aptos_payload( + self.initiator_address, + "atomic_bridge_initiator", + "complete_bridge_transfer", + self.counterparty_type_args(Call::Complete), + args, + ); + let _ = utils::send_aptos_transaction(&self.rest_client, self.signer.as_ref(), payload) + .await + .map_err(|_| BridgeContractInitiatorError::CompleteTransferError); + Ok(()) + } + + async fn refund_bridge_transfer( + &mut self, + bridge_transfer_id: BridgeTransferId, + ) -> BridgeContractInitiatorResult<()> { + let args = vec![to_bcs_bytes(&bridge_transfer_id.0).unwrap()]; + let payload = utils::make_aptos_payload( + self.initiator_address, + "atomic_bridge_initiator", + "refund_bridge_transfer", + self.counterparty_type_args(Call::Abort), + args, + ); + let _ = utils::send_aptos_transaction(&self.rest_client, self.signer.as_ref(), payload) + .await + .map_err(|_| BridgeContractInitiatorError::GenericError(("Refund Transfer Error").to_string())); + Ok(()) + } + + async fn get_bridge_transfer_details( + &mut self, + bridge_transfer_id: BridgeTransferId, + ) -> BridgeContractInitiatorResult>> + { + let response = self.rest_client.view } }