alloy-rs / alloy-rs/alloy

[Feature] Getting tx hash before sending is too hard

Ouverte
#2,404 5 commentaires 0 réactions 0 personnes assignées Voir sur GitHub
enhancement
Langage dominant
Rust
Étoiles
1.3k
Forks
668
Merge moyen
2 j 1 h
PR mergées (30 j)
29

Description

### Component

provider, pubsub

### Describe the feature you would like

**[Feature] Getting tx hash before sending is too hard**

I need a way to get tx hash before sending. Currently this is too hard. (In the end of this issue I will describe why I need this.)

Let's assume we want to send tx to contract on Sepolia. Using `PrivateKeySigner`, with default fillers. This is how I can do this:
```rust
// alloy 0.15.9
// alloy-core 1.1.0

// https://sepolia.etherscan.io/address/0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14
alloy::sol!(
#[sol(rpc)]
interface IWETH9 {
function deposit() public payable;
}
);

use alloy::signers::local::PrivateKeySigner;
use alloy::primitives::b256;
use alloy::providers::ProviderBuilder;
use alloy::primitives::address;
use alloy::primitives::U256;

#[tokio::main]
async fn main() {
// https://sepolia.etherscan.io/address/0x1D56416a0b4B0ac6eB07bA47ecc881de056d6Efb
let signer = PrivateKeySigner::from_bytes(&b256!("0xa110aaaaaaaaaaaaaaa110aaaaaaaaaaaaaaaaaaaaaaa110aaaaaaaaaaaa110a")).unwrap();
let provider = ProviderBuilder::new().wallet(signer).connect_http("https://rpc.sepolia.ethpandaops.io".parse().unwrap());
let weth9 = IWETH9::new(address!("0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14"), provider);
println!("{}", weth9.deposit().value(U256::from(1)).send().await.unwrap().watch().await.unwrap());
}
```

So far, so good. Now let's assume we want to do the same thing, but we want to get tx hash before sending tx. With default fillers, of course, I don't want to manually fill nonce, etc.

I was unable to find such use case in docs. There is no info in alloy book or in examples. I even thought that this is not possible. After a lot of tries I was able to come up with this:
```rust
// alloy 0.15.9
// alloy-core 1.1.0

// https://sepolia.etherscan.io/address/0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14
alloy::sol!(
#[sol(rpc)]
interface IWETH9 {
function deposit() public payable;
}
);

use alloy::providers::Provider;
use alloy::signers::local::PrivateKeySigner;
use alloy::primitives::b256;
use alloy::providers::ProviderBuilder;
use alloy::primitives::address;
use alloy::primitives::U256;
use alloy::providers::SendableTx;

#[tokio::main]
async fn main() {
// https://sepolia.etherscan.io/address/0x1D56416a0b4B0ac6eB07bA47ecc881de056d6Efb
let signer = PrivateKeySigner::from_bytes(&b256!("0xa110aaaaaaaaaaaaaaa110aaaaaaaaaaaaaaaaaaaaaaa110aaaaaaaaaaaa110a")).unwrap();
let provider = ProviderBuilder::new().wallet(signer).connect_http("https://rpc.sepolia.ethpandaops.io".parse().unwrap());
let weth9 = IWETH9::new(address!("0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14"), provider.clone());
let SendableTx::Envelope(envelope) = provider.fill(weth9.deposit().value(U256::from(1)).into_transaction_request()).await.unwrap() else {
unreachable!();
};
println!("{}", envelope.hash());
println!("{}", provider.send_tx_envelope(envelope).await.unwrap().watch().await.unwrap());
}
```
If there is a simpler way to do this, please, let me know.

So, please, make this use case simpler.

If you think that current API is okay, then, at least, include this example to docs.

Now let me explain why I need this.

I want to write trading bot. The bot will write every its operation to my accounting system. I want the following rule to always hold: "Operation should be in accounting if and only if it was actually executed on chain". The rule should be true even in presence of crashes, panics, etc.

Unfortunately, I was unable to create scheme, which will allow me to enforce this rule fully automatically. So I created scheme, which will enforce the rule mostly automatically with occasional manual intervention.

My scheme is so: when my bot needs to perform some operation (i. e. Ethereum transaction), it does these steps:
- The bot writes transaction hash to log
- The bot sends transaction and waits for confirmations
- The bot writes operation to accounting

If bot crashes, then I intervene manually. I look into logs. I find last transaction present in logs. I see whether it was executed on-chain and whether it is present in accounting. If it was executed, but is not present in accounting, then I manually add it to accounting.

Okay, so this system works.

But this system requires me to know tx hash before sending transaction! And this is why I need this.

### Additional context

_No response_

Guide de contribution

Ouvrir le guide de contribution

Évaluation

Cette issue n'a pas encore été évaluée.

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.