Documentation/Searchers
Filler
Build an order filler bot using the signet-orders crate
The Filler struct from signet-orders
orchestrates the full order-filling pipeline: fetching pending orders from a
source, signing Permit2
fills, and submitting them as bundles. It is the main building block for writing
a Signet filler bot.
Setup
cargo add signet-orders signet-types signet-constants signet-tx-cache
cargo add alloy --features provider-http,signers
cargo add futures-utilArchitecture
Filler is generic over three type parameters:
Sign: Any alloySigner— signs Permit2 fill messagesSource: AnOrderSource— provides a stream of pending orders (e.g. from the tx cache)Submit: AFillSubmitter— handles transaction construction, gas pricing, and bundle submission
OrderSource ──▶ Filler ──▶ FillSubmitter ──▶ BundleSubmitter
(fetch) (sign) (build txs) (submit bundle)The crate provides TxCache
as a ready-made OrderSource and BundleSubmitter, and
FeePolicySubmitter
as a FillSubmitter that handles gas pricing and bundle construction.
Creating a Filler
use alloy::providers::ProviderBuilder;
use signet_constants::parmigiana;
use signet_orders::{FeePolicySubmitter, Filler, FillerOptions};
use signet_tx_cache::TxCache;
let signer = /* your alloy Signer */;
let wallet = /* EthereumWallet wrapping the same key */;
// Connect providers with gas estimation and wallet signing
let ru_provider = ProviderBuilder::new()
.wallet(wallet.clone())
.connect("https://rpc.parmigiana.signet.sh")
.await?;
let host_provider = ProviderBuilder::new()
.wallet(wallet)
.connect("https://eth.llamarpc.com")
.await?;
let tx_cache = TxCache::parmigiana();
let constants = parmigiana::system_constants();
// FeePolicySubmitter builds fill + initiate transactions and wraps them in a
// SignetEthBundle before forwarding to the BundleSubmitter (here, the tx cache).
let submitter = FeePolicySubmitter::new(
ru_provider,
host_provider,
tx_cache.clone(),
constants.clone(),
);
let filler = Filler::new(
signer,
tx_cache,
submitter,
constants,
FillerOptions::new(),
);FillerOptions
FillerOptions lets you tune fill signing behavior:
deadline_offset— seconds from now until the Permit2 signature expires. WhenNone(default), defaults to 12 seconds.nonce— explicit Permit2 nonce. WhenNone(default), a fresh nonce is generated from the current timestamp in microseconds.
let options = FillerOptions::new()
.with_deadline_offset(30) // 30 second deadline
.with_nonce(42); // explicit nonce
Fetching and Filling Orders
Fetch orders as a stream
get_orders() returns a Stream of SignedOrders. You can filter, collect,
or process them however you like:
use futures_util::{StreamExt, TryStreamExt};
let orders: Vec<_> = filler
.get_orders()
.try_filter(|order| {
// Apply your own filtering logic
std::future::ready(is_profitable(order))
})
.try_collect()
.await?;Fill a batch of orders
fill() signs Permit2 fills for the orders, builds transactions, and submits
the bundle in one call:
match filler.fill(orders).await {
Ok(response) => println!("Bundle submitted: {}", response.id),
Err(error) => eprintln!("Fill failed: {error}"),
}Sign fills without submitting
For more control, use sign_fills() to get back an OrdersAndFills struct
that pairs orders with their signed fills:
let orders_and_fills = filler.sign_fills(orders).await?;
// Inspect before submitting
println!("Signer: {}", orders_and_fills.signer_address());
println!("Orders: {}", orders_and_fills.orders().len());
println!("Fills per chain: {}", orders_and_fills.fills().len());Implementing Custom Traits
OrderSource
Provide orders from a custom source:
use futures_util::Stream;
use signet_orders::OrderSource;
use signet_types::SignedOrder;
struct MyOrderSource;
impl OrderSource for MyOrderSource {
type Error = MyError;
fn get_orders(&self) -> impl Stream<Item = Result<SignedOrder, Self::Error>> + Send {
// Return a stream of orders from your source
todo!()
}
}FillSubmitter
Handle fill submission with custom transaction construction or fee logic:
use signet_orders::{FillSubmitter, OrdersAndFills};
struct MySubmitter;
impl FillSubmitter for MySubmitter {
type Response = ();
type Error = MyError;
async fn submit_fills(&self, orders_and_fills: OrdersAndFills) -> Result<(), Self::Error> {
// Build and submit transactions your way
todo!()
}
}FeePolicySubmitter
FeePolicySubmitter
is the provided FillSubmitter implementation. It:
- Builds rollup transactions (fill + order initiate calls)
- Builds host transactions (fill calls for orders targeting Ethereum)
- Signs and encodes all transactions using the configured providers
- Wraps everything in a
SignetEthBundleand submits via aBundleSubmitter
It requires two providers (rollup and host) configured with gas estimation and
wallet fillers, plus any BundleSubmitter (e.g. TxCache).
Next Steps
- signet-filler source — example filler service built on
signet-orders - Off-chain Orders in Rust — submit orders (the other side of the market)
- Simulating Bundles — test bundles before submission
- Working with Orders — overview of the orders system