use alloy_network::Ethereum;
use alloy_primitives::{Address, Bytes};
use alloy_provider::Provider;
use alloy_rpc_types::TransactionRequest;
use alloy_sol_types::sol;
use tracing::{debug, info};
use crate::protocol::DomainId;
use MessageTransmitterV2::MessageTransmitterV2Instance;
pub struct MessageTransmitterV2Contract<P: Provider<Ethereum>> {
instance: MessageTransmitterV2Instance<P>,
}
impl<P: Provider<Ethereum>> MessageTransmitterV2Contract<P> {
pub fn new(address: Address, provider: P) -> Self {
debug!(
contract_address = %address,
event = "message_transmitter_v2_contract_initialized"
);
Self {
instance: MessageTransmitterV2Instance::<P>::new(address, provider),
}
}
pub fn receive_message_transaction(
&self,
message: Bytes,
attestation: Bytes,
from_address: Address,
) -> TransactionRequest {
info!(
message_len = message.len(),
attestation_len = attestation.len(),
from_address = %from_address,
contract_address = %self.instance.address(),
version = "v2",
event = "receive_message_v2_transaction_created"
);
self.instance
.receiveMessage(message, attestation)
.from(from_address)
.into_transaction_request()
}
pub fn send_message_transaction(
&self,
from_address: Address,
destination_domain: DomainId,
recipient: Address,
message_body: Bytes,
destination_caller: Address,
min_finality_threshold: u32,
) -> TransactionRequest {
info!(
from_address = %from_address,
destination_domain = %destination_domain,
recipient = %recipient,
message_len = message_body.len(),
destination_caller = %destination_caller,
finality_threshold = min_finality_threshold,
contract_address = %self.instance.address(),
version = "v2",
event = "send_message_v2_transaction_created"
);
self.instance
.sendMessage(
destination_domain.as_u32(),
recipient.into_word(),
destination_caller.into_word(),
min_finality_threshold,
message_body,
)
.from(from_address)
.into_transaction_request()
}
pub async fn is_message_received(
&self,
message_hash: [u8; 32],
) -> Result<bool, alloy_contract::Error> {
let nonce_status = self.instance.usedNonces(message_hash.into()).call().await?;
debug!(
message_hash = ?message_hash,
nonce_status = %nonce_status,
is_received = !nonce_status.is_zero(),
event = "is_message_received_checked"
);
Ok(!nonce_status.is_zero())
}
pub fn address(&self) -> Address {
*self.instance.address()
}
}
sol!(
#[allow(clippy::too_many_arguments)]
#[allow(missing_docs)]
#[sol(rpc)]
MessageTransmitterV2,
"abis/v2/message_transmitter_v2.json"
);