Skip to main content

xenith_core/
transport.rs

1use crate::{ChainId, KeyMetadata, MessageId, MessageStatus, Result, StateKey, StateValue};
2use async_trait::async_trait;
3use bytes::Bytes;
4
5/// Options that fine-tune how a message is sent over the transport.
6///
7/// All fields are optional; unset values let the transport pick sensible defaults.
8///
9/// # Example
10///
11/// ```
12/// use xenith_core::SendOptions;
13/// let opts = SendOptions { gas_limit: Some(200_000), max_fee_per_gas: Some(50_000_000_000), ..Default::default() };
14/// ```
15#[derive(Debug, Clone, Default)]
16pub struct SendOptions {
17    /// Override the destination gas limit for message execution.
18    pub gas_limit: Option<u64>,
19    /// Override the nonce used by the sending contract.
20    pub nonce: Option<u64>,
21    /// Address to receive any fee refund on the source chain.
22    pub refund_address: Option<[u8; 20]>,
23    /// EIP-1559 maximum fee per gas in wei.
24    pub max_fee_per_gas: Option<u128>,
25    /// EIP-1559 maximum priority fee per gas in wei.
26    pub max_priority_fee_per_gas: Option<u128>,
27    /// Native token value (in wei) to attach to the transaction.
28    pub value: Option<u128>,
29}
30
31/// Abstraction over a cross-chain messaging protocol.
32///
33/// All implementations must be `Send + Sync` so they can be shared across async
34/// tasks and stored behind `Arc<dyn MessagingTransport>`.
35///
36/// # Example
37///
38/// ```rust,no_run
39/// use xenith_core::{MessagingTransport, ChainId, SendOptions};
40/// use bytes::Bytes;
41/// use std::sync::Arc;
42///
43/// async fn send_to_arbitrum(transport: Arc<dyn MessagingTransport>) {
44///     let id = transport
45///         .send_message(ChainId::from(42161), Bytes::from("payload"), Default::default())
46///         .await
47///         .unwrap();
48/// }
49/// ```
50#[async_trait]
51pub trait MessagingTransport: Send + Sync {
52    /// Submit a message to the destination chain and return its tracking ID.
53    async fn send_message(
54        &self,
55        destination: ChainId,
56        payload: Bytes,
57        options: SendOptions,
58    ) -> Result<MessageId>;
59
60    /// Estimate the native-token fee for sending `payload` to `destination`.
61    async fn estimate_fee(&self, destination: ChainId, payload: Bytes) -> Result<u128>;
62
63    /// Poll the current delivery status of a previously sent message.
64    async fn message_status(&self, id: MessageId) -> Result<MessageStatus>;
65
66    /// Returns the address this transport will submit transactions from, if applicable.
67    ///
68    /// Stub transports that do not submit on-chain transactions return `None`.
69    /// Live transports backed by a [`crate::TransactionSigner`] return `Some(address)`.
70    fn sender_address(&self) -> Option<[u8; 20]>;
71
72    /// Poll for messages received by this transport since the last call.
73    ///
74    /// Returns a vec of `(StateKey, StateValue, Option<KeyMetadata>)` decoded from
75    /// incoming wire-format payloads. Implementations should track a cursor (block
76    /// number or nonce) so repeated calls return new messages only, not all
77    /// historical messages.
78    ///
79    /// Returns an empty vec if no new messages are available.
80    async fn poll_incoming(&self) -> Result<Vec<(StateKey, StateValue, Option<KeyMetadata>)>>;
81}