Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(op receipt): implement wait_for_user_operation_receipt #23

Merged
merged 1 commit into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import Foundation

public struct UserOperationReceipt: Codable {

public struct Receipt: Codable {
public let transactionHash: String
public let transactionIndex: String
public let block_hash: String
public let block_number: String
public let from: String
public let to: String
public let cumulativeGasUsed: String
public let gas_used: String
public let contractAddress: String?
public let status: String
public let logsBloom: String
public let effectiveGasPrice: String

public init(
transactionHash: String,
transactionIndex: String,
block_hash: String,
block_number: String,
from: String,
to: String,
cumulativeGasUsed: String,
gas_used: String,
contractAddress: String?,
status: String,
logsBloom: String,
effectiveGasPrice: String
) {
self.transactionHash = transactionHash
self.transactionIndex = transactionIndex
self.block_hash = block_hash
self.block_number = block_number
self.from = from
self.to = to
self.cumulativeGasUsed = cumulativeGasUsed
self.gas_used = gas_used
self.contractAddress = contractAddress
self.status = status
self.logsBloom = logsBloom
self.effectiveGasPrice = effectiveGasPrice
}
}

public let userOpHash: String
public let entryPoint: String
public let sender: String
public let nonce: String
public let paymaster: String
public let actualGasCost: String
public let actualGasUsed: String
public let success: Bool
public let receipt: Receipt

public init(
userOpHash: String,
entryPoint: String,
sender: String,
nonce: String,
paymaster: String,
actualGasCost: String,
actualGasUsed: String,
success: Bool,
receipt: Receipt
) {
self.userOpHash = userOpHash
self.entryPoint = entryPoint
self.sender = sender
self.nonce = nonce
self.paymaster = paymaster
self.actualGasCost = actualGasCost
self.actualGasUsed = actualGasUsed
self.success = success
self.receipt = receipt
}
}
13 changes: 13 additions & 0 deletions crates/ffi/src/account_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,19 @@ impl FFIAccountClient {
.sign_message_with_mnemonic(message, mnemonic)
.map_err(|e| FFIError::Unknown(e.to_string()))
}

pub async fn wait_for_user_operation_receipt(
&self,
user_operation_hash: String,
) -> Result<String, FFIError> {
self.account_client
.wait_for_user_operation_receipt(user_operation_hash)
.await
.iter()
.map(serde_json::to_string)
.collect::<Result<String, serde_json::Error>>()
.map_err(|e| FFIError::Unknown(e.to_string()))
}
}

impl From<ffi::FFITransaction> for Transaction {
Expand Down
5 changes: 5 additions & 0 deletions crates/ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ mod ffi {
message: String,
mnemonic: String,
) -> Result<String, FFIError>;

pub async fn wait_for_user_operation_receipt(
&self,
user_operation_hash: String,
) -> Result<String, FFIError>;
}

extern "Rust" {
Expand Down
34 changes: 34 additions & 0 deletions crates/yttrium/src/account_client.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
use crate::bundler::{
client::BundlerClient, config::BundlerConfig,
models::user_operation_receipt::UserOperationReceipt,
};
use crate::config::Config;
use crate::private_key_service::PrivateKeyService;
use crate::sign_service::SignService;
Expand Down Expand Up @@ -161,6 +165,30 @@ impl AccountClient {

Ok(signature)
}

pub async fn wait_for_user_operation_receipt(
&self,
user_operation_hash: String,
) -> eyre::Result<UserOperationReceipt> {
println!("Querying for receipts...");

let bundler_base_url = self.config.clone().endpoints.bundler.base_url;

let bundler_client =
BundlerClient::new(BundlerConfig::new(bundler_base_url.clone()));
let receipt = bundler_client
.wait_for_user_operation_receipt(user_operation_hash.clone())
.await?;

println!("Received User Operation receipt: {:?}", receipt);

let tx_hash = receipt.clone().receipt.transaction_hash;
println!(
"UserOperation included: https://sepolia.etherscan.io/tx/{}",
tx_hash
);
Ok(receipt)
}
}

impl AccountClient {
Expand Down Expand Up @@ -268,6 +296,12 @@ mod tests {

println!("user_operation_hash: {:?}", user_operation_hash);

let receipt = account_client
.wait_for_user_operation_receipt(user_operation_hash)
.await?;

println!("receipt: {:?}", receipt);

Ok(())
}

Expand Down
4 changes: 2 additions & 2 deletions crates/yttrium/src/bundler/models/user_operation_receipt.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use alloy::primitives::Address;
use serde::{Deserialize, Serialize};

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UserOperationReceiptReceipt {
pub transaction_hash: String,
Expand All @@ -19,7 +19,7 @@ pub struct UserOperationReceiptReceipt {
pub effective_gas_price: String,
}

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UserOperationReceipt {
pub user_op_hash: String,
Expand Down
18 changes: 0 additions & 18 deletions crates/yttrium/src/transaction/send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,24 +349,6 @@ mod tests {

println!("Received User Operation hash: {:?}", user_operation_hash);

// let receipt = bundler_client
// .get_user_operation_receipt(user_operation_hash.clone())
// .await?;

// println!("Received User Operation receipt: {:?}", receipt);

// println!("Querying for receipts...");

// let receipt = bundler_client
// .wait_for_user_operation_receipt(user_operation_hash.clone())
// .await?;

// let tx_hash = receipt.receipt.transaction_hash;
// println!(
// "UserOperation included: https://sepolia.etherscan.io/tx/{}",
// tx_hash
// );

Ok(user_operation_hash)
}

Expand Down
22 changes: 0 additions & 22 deletions crates/yttrium/src/transaction/send/simple_account_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,28 +252,6 @@ pub async fn send_transaction_with_signer(

println!("Received User Operation hash: {:?}", user_operation_hash);

// TODO convert to polling
use std::time::Duration;
tokio::time::sleep(Duration::from_secs(2)).await;

let receipt = bundler_client
.get_user_operation_receipt(user_operation_hash.clone())
.await?;

println!("Received User Operation receipt: {:?}", receipt);

println!("Querying for receipts...");

let receipt = bundler_client
.wait_for_user_operation_receipt(user_operation_hash.clone())
.await?;

let tx_hash = receipt.receipt.transaction_hash;
println!(
"UserOperation included: https://sepolia.etherscan.io/tx/{}",
tx_hash
);

Ok(user_operation_hash)
}

Expand Down
16 changes: 16 additions & 0 deletions platforms/swift/Sources/Yttrium/AccountClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,22 @@ public final class AccountClient: AccountClientProtocol {
)
.toString()
}

public func waitForUserOperationReceipt(
userOperationHash: String
) async throws -> UserOperationReceipt {
let jsonString = try await coreAccountClient
.wait_for_user_operation_receipt(
userOperationHash.intoRustString()
)
.toString()
let jsonData = Data(jsonString.utf8)
let receipt = try JSONDecoder().decode(
UserOperationReceipt.self,
from: jsonData
)
return receipt
}
}

extension Transaction {
Expand Down
6 changes: 4 additions & 2 deletions platforms/swift/Tests/YttriumTests/AccountClientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ final class AccountClientTests: XCTestCase {
entryPoint: Self.entryPoint,
chainId: Self.chainId,
config: config,
signerType: .privateKey
signerType: .privateKey,
safe: false
Copy link
Contributor Author

@jackpooleywc jackpooleywc Sep 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

)
accountClient.register(privateKey: Self.privateKeyHex)

Expand All @@ -44,7 +45,8 @@ final class AccountClientTests: XCTestCase {
entryPoint: Self.entryPoint,
chainId: Self.chainId,
config: config,
signerType: .privateKey
signerType: .privateKey,
safe: false
)
accountClient.register(privateKey: Self.privateKeyHex)

Expand Down