boundless_market/request_builder/
request_id_layer.rs1use super::{Adapt, Layer, RequestParams};
16use crate::{contracts::boundless_market::BoundlessMarketService, contracts::RequestId};
17use alloy::{network::Ethereum, providers::Provider};
18use derive_builder::Builder;
19
20#[non_exhaustive]
24#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
25pub enum RequestIdLayerMode {
26 #[default]
30 Rand,
31
32 Nonce,
36}
37
38#[non_exhaustive]
42#[derive(Clone, Builder)]
43pub struct RequestIdLayerConfig {
44 #[builder(default)]
46 pub mode: RequestIdLayerMode,
47}
48
49#[non_exhaustive]
54#[derive(Clone)]
55pub struct RequestIdLayer<P> {
56 pub boundless_market: BoundlessMarketService<P>,
58
59 pub config: RequestIdLayerConfig,
61}
62
63impl RequestIdLayerConfig {
64 pub fn builder() -> RequestIdLayerConfigBuilder {
68 Default::default()
69 }
70}
71
72impl<P: Clone> From<BoundlessMarketService<P>> for RequestIdLayer<P> {
73 fn from(boundless_market: BoundlessMarketService<P>) -> Self {
74 RequestIdLayer { boundless_market, config: Default::default() }
75 }
76}
77
78impl Default for RequestIdLayerConfig {
79 fn default() -> Self {
80 Self::builder().build().expect("implementation error in Default for RequestIdLayerConfig")
81 }
82}
83
84impl<P> RequestIdLayer<P> {
85 pub fn new(boundless_market: BoundlessMarketService<P>, config: RequestIdLayerConfig) -> Self {
90 Self { boundless_market, config }
91 }
92}
93
94impl<P> Layer<()> for RequestIdLayer<P>
95where
96 P: Provider<Ethereum> + 'static + Clone,
97{
98 type Output = RequestId;
99 type Error = anyhow::Error;
100
101 async fn process(&self, (): ()) -> Result<Self::Output, Self::Error> {
102 let id_u256 = match self.config.mode {
103 RequestIdLayerMode::Nonce => self.boundless_market.request_id_from_nonce().await?,
104 RequestIdLayerMode::Rand => self.boundless_market.request_id_from_rand().await?,
105 };
106 Ok(id_u256.try_into().expect("generated request ID should always be valid"))
107 }
108}
109
110impl<P> Adapt<RequestIdLayer<P>> for RequestParams
111where
112 P: Provider<Ethereum> + 'static + Clone,
113{
114 type Output = RequestParams;
115 type Error = anyhow::Error;
116
117 async fn process_with(self, layer: &RequestIdLayer<P>) -> Result<Self::Output, Self::Error> {
118 tracing::trace!("Processing {self:?} with RequestIdLayer");
119
120 if self.request_id.is_some() {
121 return Ok(self);
122 }
123
124 let request_id = layer.process(()).await?;
125 Ok(self.with_request_id(request_id))
126 }
127}