alloy-rs / alloy-rs/alloy

[Feature] Use of Provider Layers in the `PendingTransactionBuilder`

Offen
#3,517 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
enhancement
Vorherrschende Sprache
Rust
Sterne
1.3k
Forks
668
Ø Merge
2 T. 2 Std.
Gemergte PRs (30 T.)
29

Beschreibung

### Component

provider, pubsub

### Describe the feature you would like

I'm currently working with a number of RPCs where getting the transactions receipt can possibly fail even after the transaction has been confirmed. Geth is one of them where sometimes getting the receipt fails with `-32000: transaction indexing is in progress` even after the transaction has been confirmed.

To combat this I wrote a provider layer that would attempt to get the receipt for a given duration and timeout if we fail to get the receipt in that duration. The layer's primary code looks like the following:

```rust
impl Provider for ReceiptRetryProvider
where
P: Provider,
N: Network,
{
#[inline(always)]
fn root(&self) -> &RootProvider {
self.inner.root()
}

fn get_transaction_receipt(
&self,
hash: TxHash,
) -> ProviderCall<(TxHash,), Option<::ReceiptResponse>> {
tracing::info!("Inside the retry layer");

let client = self.inner.weak_client();
let polling_duration = self.polling_duration;
let polling_interval = self.polling_interval;

ProviderCall::BoxedFuture(Box::pin(async move {
let client = client
.upgrade()
.ok_or_else(|| TransportErrorKind::custom_str("RPC client dropped"))?;

let receipt = timeout(polling_duration, async move {
let mut interval = interval(polling_interval);

loop {
let result = client
.request::<(TxHash,), Option<::ReceiptResponse>>(
"eth_getTransactionReceipt",
(hash,),
)
.await;
if let Ok(Some(receipt)) = result {
return receipt;
}

interval.tick().await;
}
})
.await
.map_err(|_| {
RpcError::local_usage_str("Timeout when waiting for transaction receipt")
})?;

Ok(Some(receipt))
}))
}
}
```

In simple terms, attempt to get the receipt over a given duration and interval and throw a timeout error if we fail to get the receipt back within the allowed timeout.

The main problem that I have is that my added layer means that I can no longer make use of the `PendingTransactionBuilder` and the elegant API that it provides since it uses the `RootProvider` and not a generic `P: Provider` which means that all of the layers that I add to my provider are not used.

https://github.com/alloy-rs/alloy/blob/14835b09066edb36ccca778fc0d22bcdf2488145/crates/provider/src/heart.rs#L93-L96

I thought about pushing this layer further down the stack and into the client layers, but it would then mean that I need to JSON deserialize all (or most) my requests and responses in this layer which would be considerable overhead for the requests.

So, to make my feature request clear: Could the `PendingTransactionBuilder` have a generic `P` over any `Provider` to allow the requests made by the `PendingTransactionBuilder` to go through the layers I added to my provider?

### Additional context

_No response_

Beitragsleitfaden

Beitragsleitfaden öffnen

Bewertung

Dieses Issue wurde noch nicht bewertet.

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.