Skip to content

Commit aab4260

Browse files
committed
fix(sequencer): Send layer-2 transaction
1 parent 6695578 commit aab4260

File tree

7 files changed

+84
-27
lines changed

7 files changed

+84
-27
lines changed

metabased-sequencer/interceptor/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ hyper-util = "0.1.8"
3535
alloy-primitives = "0.8.7"
3636
url = { version = "2", features = ["serde"] }
3737
prometheus-client = "0.22"
38+

metabased-sequencer/interceptor/src/application/send_raw_transaction.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,5 @@ where
4646
)?;
4747
}
4848

49-
chain.process_transaction(encoded).await?;
50-
51-
Ok(tx.tx_hash().to_owned())
49+
Ok(chain.process_transaction(encoded).await?)
5250
}

metabased-sequencer/interceptor/src/domain/chain.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
use super::primitives::Bytes;
1+
use super::primitives::{Bytes, TxHash};
22
use jsonrpsee::core::async_trait;
33
use std::error::Error;
44

55
#[async_trait]
66
pub trait MetabasedSequencerChainService {
77
type Error: Error;
88

9-
async fn process_transaction(&self, tx: Bytes) -> Result<(), Self::Error>;
9+
async fn process_transaction(&self, tx: Bytes) -> Result<TxHash, Self::Error>;
1010

11-
async fn process_bulk_transactions(&self, tx: Vec<Bytes>) -> Result<(), Self::Error>;
11+
async fn process_bulk_transactions(&self, tx: Vec<Bytes>) -> Result<TxHash, Self::Error>;
1212
}
1313

1414
#[cfg(test)]
@@ -36,16 +36,16 @@ mod tests {
3636
impl MetabasedSequencerChainService for InMemoryMetabasedSequencerChain {
3737
type Error = Infallible;
3838

39-
async fn process_transaction(&self, tx: Bytes) -> Result<(), Infallible> {
39+
async fn process_transaction(&self, tx: Bytes) -> Result<TxHash, Infallible> {
4040
self.transactions.write().await.push(tx);
4141

42-
Ok(())
42+
Ok(TxHash::ZERO)
4343
}
4444

45-
async fn process_bulk_transactions(&self, tx: Vec<Bytes>) -> Result<(), Infallible> {
45+
async fn process_bulk_transactions(&self, tx: Vec<Bytes>) -> Result<TxHash, Infallible> {
4646
self.transactions.write().await.extend(tx);
4747

48-
Ok(())
48+
Ok(TxHash::ZERO)
4949
}
5050
}
5151
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
pub use alloy::primitives::{Address, Bytes};
1+
pub use alloy::primitives::{Address, Bytes, TxHash, B256};

metabased-sequencer/interceptor/src/infrastructure/sol.rs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
use crate::domain::primitives::{Address, Bytes};
1+
use crate::domain::primitives::{Address, Bytes, TxHash};
22
use crate::domain::MetabasedSequencerChainService;
33
use crate::infrastructure::sol::MetabasedSequencerChain::MetabasedSequencerChainInstance;
44
use alloy::network::Network;
55
use alloy::providers::Provider;
6-
use alloy::sol;
76
use alloy::transports::Transport;
7+
use alloy::sol;
88
use async_trait::async_trait;
99
use std::marker::PhantomData;
10+
use std::time::Duration;
1011

1112
sol! {
1213
#[derive(Debug, PartialEq, Eq)]
@@ -51,15 +52,27 @@ impl<P: Provider<T, N>, T: Transport + Clone, N: Network> MetabasedSequencerChai
5152
{
5253
type Error = alloy::contract::Error;
5354

54-
async fn process_transaction(&self, tx: Bytes) -> Result<(), Self::Error> {
55-
self.contract().processTransaction(tx).call().await?;
56-
57-
Ok(())
55+
async fn process_transaction(&self, tx: Bytes) -> Result<TxHash, Self::Error> {
56+
Ok(self
57+
.contract()
58+
.processTransaction(tx)
59+
.send()
60+
.await?
61+
.with_required_confirmations(2)
62+
.with_timeout(Some(Duration::from_secs(60)))
63+
.watch()
64+
.await?)
5865
}
5966

60-
async fn process_bulk_transactions(&self, tx: Vec<Bytes>) -> Result<(), Self::Error> {
61-
self.contract().processBulkTransactions(tx).call().await?;
62-
63-
Ok(())
67+
async fn process_bulk_transactions(&self, tx: Vec<Bytes>) -> Result<TxHash, Self::Error> {
68+
Ok(self
69+
.contract()
70+
.processBulkTransactions(tx)
71+
.send()
72+
.await?
73+
.with_required_confirmations(2)
74+
.with_timeout(Some(Duration::from_secs(60)))
75+
.watch()
76+
.await?)
6477
}
6578
}

metabased-sequencer/interceptor/src/presentation/cli.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::domain::primitives::Address;
22
use crate::presentation::server;
3+
use alloy_primitives::B256;
34
use clap::{Parser, ValueEnum};
45
use figment::providers::{Env, Serialized};
56
use figment::Figment;
@@ -23,6 +24,7 @@ pub async fn run() -> anyhow::Result<()> {
2324
args.port,
2425
args.chain_contract_address,
2526
args.chain_rpc_address,
27+
args.private_key,
2628
)
2729
.await?;
2830

@@ -96,6 +98,10 @@ struct CliArgs {
9698
#[arg(short = 'p', long)]
9799
port: Option<u16>,
98100

101+
/// Private key to sign layer-2 transactions with.
102+
#[arg(short = 'k', long)]
103+
private_key: B256,
104+
99105
/// Profile that chooses which .env file to load
100106
#[arg(short = 'o', long)]
101107
profile: Option<Profile>,
@@ -104,6 +110,7 @@ struct CliArgs {
104110
struct Args {
105111
chain_contract_address: Address,
106112
chain_rpc_address: Url,
113+
private_key: B256,
107114
port: u16,
108115
}
109116

@@ -112,6 +119,7 @@ impl From<CliArgs> for Args {
112119
Self {
113120
chain_contract_address: value.chain_contract_address,
114121
chain_rpc_address: value.chain_rpc_address,
122+
private_key: value.private_key,
115123
port: value.port.expect("port should be set by a default value"),
116124
}
117125
}

metabased-sequencer/interceptor/src/presentation/server.rs

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@ use crate::domain::MetabasedSequencerChainService;
44
use crate::infrastructure::SolMetabasedSequencerChainService;
55
use crate::presentation::json_rpc_errors::Error;
66
use crate::presentation::jsonrpc;
7-
use alloy::providers::ProviderBuilder;
7+
use alloy::network::{Ethereum, EthereumWallet};
8+
use alloy::primitives::B256;
9+
use alloy::providers::fillers::{
10+
CachedNonceManager, ChainIdFiller, FillProvider, GasFiller, JoinFill, NonceFiller, WalletFiller,
11+
};
12+
use alloy::providers::{ReqwestProvider, RootProvider};
13+
use alloy::signers::local::PrivateKeySigner;
814
use jsonrpsee::server::{RpcServiceBuilder, Server, ServerHandle};
915
use jsonrpsee::RpcModule;
1016
use std::net::SocketAddr;
@@ -14,30 +20,57 @@ pub async fn run(
1420
port: u16,
1521
chain_contract_address: Address,
1622
chain_rpc_address: Url,
23+
private_key: B256,
1724
) -> anyhow::Result<(SocketAddr, ServerHandle)> {
25+
let chain = create_chain_service(chain_contract_address, chain_rpc_address, private_key)?;
26+
let metrics = PrometheusMetrics::new();
27+
let services = Services::new(chain, metrics);
28+
1829
let rpc_middleware = RpcServiceBuilder::new();
1930
let server = Server::builder()
2031
.set_rpc_middleware(rpc_middleware)
2132
.build(format!("127.0.0.1:{port}"))
2233
.await?;
34+
2335
let addr = server.local_addr()?;
24-
let rpc = ProviderBuilder::new().on_http(chain_rpc_address);
25-
let chain = SolMetabasedSequencerChainService::new(chain_contract_address, rpc);
26-
let metrics = PrometheusMetrics::new();
27-
let services = Services { chain, metrics };
2836
let module = create_eth_module(services)?;
2937
let handle = server.start(module);
3038

3139
Ok((addr, handle))
3240
}
3341

42+
fn create_chain_service(
43+
chain_contract_address: Address,
44+
chain_rpc_address: Url,
45+
private_key: B256,
46+
) -> anyhow::Result<
47+
impl MetabasedSequencerChainService<Error = alloy::contract::Error> + Send + Sync + 'static,
48+
> {
49+
let signer = PrivateKeySigner::from_bytes(&private_key)?;
50+
let wallet = EthereumWallet::from(signer);
51+
let filler = JoinFill::new(
52+
NonceFiller::new(CachedNonceManager::default()),
53+
JoinFill::new(
54+
WalletFiller::new(wallet),
55+
JoinFill::new(GasFiller, ChainIdFiller::new(None)),
56+
),
57+
);
58+
let rpc: RootProvider<_, Ethereum> = ReqwestProvider::new_http(chain_rpc_address);
59+
let rpc = FillProvider::new(rpc, filler);
60+
61+
Ok(SolMetabasedSequencerChainService::new(
62+
chain_contract_address,
63+
rpc,
64+
))
65+
}
66+
3467
fn create_eth_module<Chain, M>(
3568
services: Services<Chain, M>,
3669
) -> anyhow::Result<RpcModule<Services<Chain, M>>>
3770
where
3871
Chain: MetabasedSequencerChainService + Send + Sync + 'static,
39-
M: Metrics + Send + Sync + 'static,
4072
Error: From<<Chain as MetabasedSequencerChainService>::Error>,
73+
M: Metrics + Send + Sync + 'static,
4174
{
4275
let mut module = RpcModule::new(services);
4376
module.register_async_method("eth_sendRawTransaction", jsonrpc::send_raw_transaction)?;
@@ -52,6 +85,10 @@ pub struct Services<Chain, M> {
5285
}
5386

5487
impl<Chain: MetabasedSequencerChainService, M: Metrics> Services<Chain, M> {
88+
pub fn new(chain: Chain, metrics: M) -> Self {
89+
Self { chain, metrics }
90+
}
91+
5592
pub fn chain_service(&self) -> &Chain {
5693
&self.chain
5794
}

0 commit comments

Comments
 (0)