Skip to main content

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

bash
cargo add signet-orders signet-types signet-constants signet-tx-cache
cargo add alloy --features provider-http,signers
cargo add futures-util

Architecture

Filler is generic over three type parameters:

  • Sign: Any alloy Signer — signs Permit2 fill messages
  • Source: An OrderSource — provides a stream of pending orders (e.g. from the tx cache)
  • Submit: A FillSubmitter — handles transaction construction, gas pricing, and bundle submission
text
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

rust
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. When None (default), defaults to 12 seconds.
  • nonce — explicit Permit2 nonce. When None (default), a fresh nonce is generated from the current timestamp in microseconds.
rust
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:

rust
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:

rust
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:

rust
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:

rust
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:

rust
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:

  1. Builds rollup transactions (fill + order initiate calls)
  2. Builds host transactions (fill calls for orders targeting Ethereum)
  3. Signs and encodes all transactions using the configured providers
  4. Wraps everything in a SignetEthBundle and submits via a BundleSubmitter

It requires two providers (rollup and host) configured with gas estimation and wallet fillers, plus any BundleSubmitter (e.g. TxCache).

Next Steps

ESC

Start typing to search documentation...

Navigate Select ⌘K Open