假设我是Alice,我的任务是通过部署在Avalache子网上的智能合约将N个ERC20令牌从我的地址转移到我的客户端Bob。我想用Rust程序来执行我的智能合约transfer
函数。假设我使用ethers-rs
,并具有以下代码:
let tx = self.contract.transfer(addr_to, amount).tx;
let _res: TypedTransaction = tx;
if let Some(receipt) = self
.contract
.transfer(addr_to, amount)
.send()
.await
.map_err(|e| EthersTransferError(e.to_string()))?
.await
.map_err(|e| EthersTransferError(e.to_string()))?
{
return Ok(receipt);
}
此代码完成交易并返回包含交易哈希,状态和其他重要信息的收据大约需要5秒。但问题是:如果我的程序在收到收据之前的5秒内崩溃了怎么办?所以我的交易可能成功,也可能不成功,我无法检查,因为除了from address
,to address
,amount
和smart-contract address
,我没有收据和其他任何信息。但是我需要知道我的交易是否成功,我应该转移令牌exactly once
。那么在这种情况下我能做什么呢?我的想法是从最后的块中获取事件,并在其中找到我的事务,所以我这样做:
async fn find_tx(&self, to: Address, amount: U256, from_block: BlockNumber) -> Result<()> {
let filter = Filter::new()
.address(self.contract_addr)
.event("Transfer(address,address,uint256)")
.topic2(H256::from(to))
.from_block(from_block);
let mut interval = time::interval(time::Duration::from_secs(600));
loop {
interval.tick().await;
let logs = self
.client
.get_logs(&filter)
.await
.map_err(|e| AvalancheGetLogsError(e.to_string()))?;
for log in logs.iter() {
if self.client.address() == Address::from(log.topics[1])
&& to == Address::from(log.topics[2])
&& amount == U256::from(log.data.as_bytes_ref())
{
return Ok(());
}
}
}
}
这个解决方案的问题是a)一些链设置了要过滤的最大区块数量(如Fuji testnet - 2048个区块),而我的交易可能远远超过了这个限制,b)它可以检查交易是否失败,代码将在无限循环中堆叠,我将不得不等待几天来确保交易没有到达。
所以,我需要用有限的信息找到我的交易状态。你认为最好的方案是什么?我相信我不是第一个遇到这个问题的人。我必须依赖承载我的子网的服务的API吗?索引器,浏览器?以某种方式扩展智能合约功能以进行额外检查?Geth
是否有足够的功能来解决这个问题?我有点迷糊了。提前感谢
-
将事务哈希值存储到数据库
-
您可以使用eth_getTransactionReceipt
通过交易哈希查询交易收据,状态和日志 -
如果您的节点没有存储旧收据,或者正在修剪
-
自己运行节点
-
切换到更高质量的付费节点提供商
-