From 85a55aa5e7f46b1bc56d3e76f3fd92ea755aa519 Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Tue, 17 Dec 2024 15:46:36 -0500 Subject: [PATCH] chore: remove old code --- crates/kotlin-ffi/src/lib.rs | 61 +-- crates/yttrium/src/account_client.rs | 341 +------------ crates/yttrium/src/lib.rs | 3 - crates/yttrium/src/private_key_service.rs | 35 -- crates/yttrium/src/sign_service.rs | 83 ---- crates/yttrium/src/signer.rs | 250 ---------- crates/yttrium/src/smart_accounts.rs | 2 - crates/yttrium/src/smart_accounts/deployed.rs | 92 ---- .../src/smart_accounts/simple_account.rs | 52 -- .../simple_account/create_account.rs | 28 -- .../smart_accounts/simple_account/factory.rs | 115 ----- .../simple_account/sender_address.rs | 83 ---- crates/yttrium/src/transaction/send.rs | 375 +------------- .../yttrium/src/transaction/send/safe_test.rs | 5 +- .../src/transaction/send/send_tests.rs | 1 - .../send/send_tests/test_send_pimlico_v07.rs | 264 ---------- .../transaction/send/simple_account_test.rs | 470 ------------------ crates/yttrium/tests/shared/mod.rs | 0 crates/yttrium/tests/test_send_transaction.rs | 9 - crates/yttrium_dart/rust/src/lib.rs | 62 +-- justfile | 5 +- 21 files changed, 62 insertions(+), 2274 deletions(-) delete mode 100644 crates/yttrium/src/private_key_service.rs delete mode 100644 crates/yttrium/src/sign_service.rs delete mode 100644 crates/yttrium/src/signer.rs delete mode 100644 crates/yttrium/src/smart_accounts/deployed.rs delete mode 100644 crates/yttrium/src/smart_accounts/simple_account.rs delete mode 100644 crates/yttrium/src/smart_accounts/simple_account/create_account.rs delete mode 100644 crates/yttrium/src/smart_accounts/simple_account/factory.rs delete mode 100644 crates/yttrium/src/smart_accounts/simple_account/sender_address.rs delete mode 100644 crates/yttrium/src/transaction/send/send_tests.rs delete mode 100644 crates/yttrium/src/transaction/send/send_tests/test_send_pimlico_v07.rs delete mode 100644 crates/yttrium/src/transaction/send/simple_account_test.rs delete mode 100644 crates/yttrium/tests/shared/mod.rs delete mode 100644 crates/yttrium/tests/test_send_transaction.rs diff --git a/crates/kotlin-ffi/src/lib.rs b/crates/kotlin-ffi/src/lib.rs index ff82d045..85a70b01 100644 --- a/crates/kotlin-ffi/src/lib.rs +++ b/crates/kotlin-ffi/src/lib.rs @@ -12,7 +12,7 @@ use { relay_rpc::domain::ProjectId, std::time::Duration, yttrium::{ - account_client::{AccountClient as YAccountClient, SignerType}, + account_client::AccountClient as YAccountClient, chain_abstraction::{ api::{ prepare::{PrepareResponse, RouteResponseAvailable}, @@ -24,8 +24,6 @@ use { ui_fields::UiFields, }, config::Config, - private_key_service::PrivateKeyService, - sign_service::address_from_string, transaction::{ send::safe_test::{ Address as FFIAddress, OwnerSignature as YOwnerSignature, @@ -41,9 +39,6 @@ pub struct FFIAccountClientConfig { pub owner_address: String, pub chain_id: u64, pub config: Config, - pub signer_type: String, - pub safe: bool, - pub private_key: String, } #[derive(uniffi::Record)] @@ -225,25 +220,15 @@ impl ChainAbstractionClient { impl FFIAccountClient { #[uniffi::constructor] pub fn new(config: FFIAccountClientConfig) -> Self { - let owner_address = config.owner_address.clone(); - let signer_type = config.signer_type.clone(); - let signer = SignerType::from(signer_type).unwrap(); - let account_client = match signer { - SignerType::PrivateKey => { - let private_key_fn = - Box::new(move || Ok(config.private_key.clone())); - let owner = address_from_string(&owner_address).unwrap(); - let service = PrivateKeyService::new(private_key_fn, owner); - YAccountClient::new_with_private_key_service( - config.owner_address.clone(), - config.chain_id, - config.config, - service, - config.safe, - ) - } - SignerType::Native => todo!(), - }; + let account_client = YAccountClient::new( + config + .owner_address + .parse::() + .unwrap() + .into(), + config.chain_id, + config.config, + ); Self { owner_address: config.owner_address.clone(), @@ -260,24 +245,10 @@ impl FFIAccountClient { self.account_client .get_address() .await + .map(|address| address.to_string()) .map_err(|e| FFIError::General(e.to_string())) } - pub async fn send_transactions( - &self, - transactions: Vec, - ) -> Result { - let ytransactions: Vec = - transactions.into_iter().map(YTransaction::from).collect(); - - Ok(self - .account_client - .send_transactions(ytransactions) - .await - .map_err(|e| FFIError::General(e.to_string()))? - .to_string()) - } - pub async fn prepare_send_transactions( &self, transactions: Vec, @@ -333,16 +304,6 @@ impl FFIAccountClient { .to_string()) } - pub fn sign_message_with_mnemonic( - &self, - message: String, - mnemonic: String, - ) -> Result { - self.account_client - .sign_message_with_mnemonic(message, mnemonic) - .map_err(|e| FFIError::General(e.to_string())) - } - pub async fn wait_for_user_operation_receipt( &self, user_operation_hash: String, diff --git a/crates/yttrium/src/account_client.rs b/crates/yttrium/src/account_client.rs index 3710277d..ced154d7 100644 --- a/crates/yttrium/src/account_client.rs +++ b/crates/yttrium/src/account_client.rs @@ -6,11 +6,12 @@ use { pimlico::paymaster::client::PaymasterClient, }, config::Config, - private_key_service::PrivateKeyService, - sign_service::SignService, - smart_accounts::safe::{ - prepare_sign, sign, sign_step_3, Owners, PreparedSignature, - SignOutputEnum, SignStep3Params, + smart_accounts::{ + account_address::AccountAddress, + safe::{ + prepare_sign, sign, sign_step_3, Owners, PreparedSignature, + SignOutputEnum, SignStep3Params, + }, }, transaction::{ send::{ @@ -19,151 +20,45 @@ use { self, DoSendTransactionParams, OwnerSignature, PreparedSendTransaction, }, - send_transactions, }, Transaction, }, }, alloy::{ network::Ethereum, - primitives::{Address, Bytes, B256, U256, U64}, + primitives::{Bytes, B256, U256, U64}, providers::ReqwestProvider, - signers::local::PrivateKeySigner, }, - std::sync::Arc, - tokio::sync::Mutex, }; -#[derive(Clone)] -pub enum SignerType { - PrivateKey, - Native, -} - -impl SignerType { - pub fn from(string: String) -> eyre::Result { - match string.as_str() { - "PrivateKey" => Ok(SignerType::PrivateKey), - "Native" => Ok(SignerType::Native), - _ => Err(eyre::Report::msg("Invalid signer type")), - } - } -} - -#[derive(Clone)] -pub enum Signer { - PrivateKey(Arc>), - Native(Arc>), - None, -} - -impl Signer { - pub fn new_with_sign_service(sign_service: SignService) -> Self { - Self::Native(Arc::new(Mutex::new(sign_service))) - } - - pub fn new_with_private_key_service( - private_key_service: PrivateKeyService, - ) -> Self { - Self::PrivateKey(Arc::new(Mutex::new(private_key_service))) - } -} - -#[allow(dead_code)] #[cfg_attr(feature = "uniffi", derive(uniffi_macros::Object))] pub struct AccountClient { - owner: String, + owner: AccountAddress, chain_id: u64, pub config: Config, - signer: Signer, - safe: bool, } impl AccountClient { - pub fn new_with_sign_service( - owner: String, - chain_id: u64, - config: Config, - sign_service: SignService, - ) -> Self { - Self { - owner, - chain_id, - config: config.clone(), - signer: Signer::Native(Arc::new(Mutex::new(sign_service))), - safe: false, - } - } - - pub fn new_with_private_key_service( - owner: String, - chain_id: u64, - config: Config, - private_key_service: PrivateKeyService, - safe: bool, - ) -> Self { - Self { - owner, - chain_id, - config: config.clone(), - signer: Signer::PrivateKey(Arc::new(Mutex::new( - private_key_service, - ))), - safe, - } - } - - pub fn new_with_private_key( - owner: String, - chain_id: u64, - config: Config, - private_key: String, - ) -> Self { - let owner_address: Address = owner.parse().unwrap(); - let private_key_service = PrivateKeyService::new( - Box::new(move || Ok(private_key.clone())), - owner_address, - ); - Self { - owner, - chain_id, - config: config.clone(), - signer: Signer::PrivateKey(Arc::new(Mutex::new( - private_key_service, - ))), - safe: false, - } + pub fn new(owner: AccountAddress, chain_id: u64, config: Config) -> Self { + Self { owner, chain_id, config } } pub fn chain_id(&self) -> u64 { self.chain_id } - pub async fn get_address(&self) -> eyre::Result { - get_address_with_signer( - self.owner.clone(), - self.chain_id, - self.config.clone(), - self.signer.clone(), - self.safe, - ) - .await + pub async fn get_address(&self) -> eyre::Result { + safe_test::get_address(self.owner, self.config.clone()).await } pub fn prepare_sign_message( &self, message_hash: B256, ) -> PreparedSignature { - if !self.safe { - unimplemented!( - "sign_message is not supported for non-safe accounts" - ); - } - prepare_sign( // TODO refactor class to parse Address on AccountClient // initialization instead of lazily - self.owner.parse::
().unwrap().into(), + self.owner, U256::from(U64::from(self.chain_id)), message_hash, ) @@ -173,12 +68,6 @@ impl AccountClient { &self, signatures: Vec, ) -> eyre::Result { - if !self.safe { - unimplemented!( - "sign_message is not supported for non-safe accounts" - ); - } - // TODO refactor class to create Provider on AccountClient // initialization instead of lazily let provider = ReqwestProvider::::new_http( @@ -186,16 +75,8 @@ impl AccountClient { ); sign( - Owners { - owners: vec![self.owner.parse::
().unwrap()], - threshold: 1, - }, - self.get_address() - .await - .unwrap() - .parse::
() - .unwrap() - .into(), + Owners { owners: vec![self.owner.into()], threshold: 1 }, + self.get_address().await?, signatures, &provider, PaymasterClient::new(BundlerConfig::new( @@ -213,31 +94,15 @@ impl AccountClient { sign_step_3(signatures, sign_step_3_params).await } - pub async fn send_transactions( - &self, - transactions: Vec, - ) -> eyre::Result { - send_transactions( - transactions, - self.owner.clone(), - self.chain_id, - self.config.clone(), - self.signer.clone(), - self.safe, - ) - .await - } - pub async fn prepare_send_transactions( &self, transactions: Vec, ) -> eyre::Result { prepare_send_transaction( transactions, - self.owner.clone(), + self.owner, self.chain_id, self.config.clone(), - self.safe, ) .await } @@ -252,25 +117,10 @@ impl AccountClient { do_send_transaction_params, self.chain_id, self.config.clone(), - self.safe, ) .await } - pub fn sign_message_with_mnemonic( - &self, - message: String, - mnemonic: String, - ) -> eyre::Result { - let sign_service = crate::sign_service::SignService::new_with_mnemonic( - mnemonic.clone(), - ); - - let signature = sign_service.sign(message)?; - - Ok(signature) - } - pub async fn wait_for_user_operation_receipt( &self, user_operation_hash: B256, @@ -295,162 +145,3 @@ impl AccountClient { Ok(receipt) } } - -impl AccountClient { - pub fn mock() -> Self { - AccountClient { - owner: "".to_string(), - chain_id: 0, - config: Config::local(), - signer: Signer::Native(Arc::new(Mutex::new(SignService::mock()))), - safe: false, - } - } -} - -pub async fn get_address_with_signer( - owner_address: String, - chain_id: u64, - config: Config, - signer: Signer, - safe: bool, -) -> eyre::Result { - match signer { - Signer::PrivateKey(private_key_service) => { - let private_key_service = private_key_service.clone(); - let private_key_service = private_key_service.lock().await; - let private_key_signer_key = - private_key_service.private_key().unwrap(); - let private_key_signer: PrivateKeySigner = - private_key_signer_key.parse().unwrap(); - get_address_with_private_key_signer( - owner_address, - chain_id, - config, - private_key_signer, - safe, - ) - .await - } - Signer::Native(_sign_service) => { - todo!("Implement native signer support") - } - Signer::None => { - todo!("get_address_with_signer doesn't work with None signer") - } - } -} - -pub async fn get_address_with_private_key_signer( - owner_address: String, - chain_id: u64, - config: Config, - signer: PrivateKeySigner, - safe: bool, -) -> eyre::Result { - use crate::smart_accounts::simple_account::sender_address::get_sender_address_with_signer; - - let sender_address = if safe { - safe_test::get_address(owner_address, config).await? - } else { - get_sender_address_with_signer(config, chain_id, signer).await? - }; - - Ok(sender_address.to_string()) -} - -#[cfg(test)] -mod tests { - use { - super::*, - crate::{config::Config, private_key_service::PrivateKeyService}, - }; - - // mnemonic:`"test test test test test test test test test test test junk"` - // derived at `m/44'/60'/0'/0/0` - const PRIVATE_KEY_HEX: &str = - "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"; - - #[tokio::test] - async fn test_send_transaction_local() -> eyre::Result<()> { - let config = Config::local(); - - let owner_address = - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266".to_string(); - let chain_id = 11155111; - - let private_key_hex = PRIVATE_KEY_HEX.to_string(); - - let private_key_service = PrivateKeyService::new( - Box::new(move || Ok(private_key_hex.clone())), - owner_address.parse().unwrap(), - ); - - let account_client = AccountClient::new_with_private_key_service( - owner_address, - chain_id, - config, - private_key_service, - false, - ); - - let transaction = Transaction::new_from_strings( - "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045".to_string(), - "0".to_string(), - "0x68656c6c6f".to_string(), - )?; - - let user_operation_hash = - account_client.send_transactions(vec![transaction]).await?; - - println!("user_operation_hash: {:?}", user_operation_hash); - - let receipt = account_client - .wait_for_user_operation_receipt(user_operation_hash) - .await?; - - println!("receipt: {:?}", receipt); - - Ok(()) - } - - #[tokio::test] - async fn test_get_address_local() -> eyre::Result<()> { - let expected_address = - "0x75BD33d92EEAC5Fe41446fcF5953050d691E7fc9".to_string(); - - let config = Config::local(); - - let owner_address = - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266".to_string(); - let chain_id = 11155111; - - let private_key_hex = PRIVATE_KEY_HEX.to_string(); - - let private_key_service = PrivateKeyService::new( - Box::new(move || Ok(private_key_hex.clone())), - owner_address.parse().unwrap(), - ); - - let account_client = AccountClient::new_with_private_key_service( - owner_address, - chain_id, - config, - private_key_service, - false, - ); - - let sender_address = account_client.get_address().await?; - - println!("sender_address: {:?}", sender_address); - - eyre::ensure!( - sender_address == expected_address, - "Sender address {} does not match expected address {}", - sender_address, - expected_address - ); - - Ok(()) - } -} diff --git a/crates/yttrium/src/lib.rs b/crates/yttrium/src/lib.rs index 0aa9e5a3..d463bda1 100644 --- a/crates/yttrium/src/lib.rs +++ b/crates/yttrium/src/lib.rs @@ -16,9 +16,6 @@ pub mod erc6492_client; pub mod erc7579; pub mod error; pub mod jsonrpc; -pub mod private_key_service; -pub mod sign_service; -pub mod signer; pub mod smart_accounts; pub mod test_helpers; pub mod transaction; diff --git a/crates/yttrium/src/private_key_service.rs b/crates/yttrium/src/private_key_service.rs deleted file mode 100644 index 0dc0f8c2..00000000 --- a/crates/yttrium/src/private_key_service.rs +++ /dev/null @@ -1,35 +0,0 @@ -use { - crate::error::YttriumError, alloy::primitives::Address, std::sync::Arc, - tokio::sync::Mutex, -}; - -pub type PrivateKeyFN = - dyn Fn() -> Result + Send + 'static; - -pub type BoxPrivateKeyFN = Box; - -pub struct PrivateKeyService { - private_key_fn: Arc>, - owner: Address, -} - -impl PrivateKeyService { - pub fn new(private_key_fn: BoxPrivateKeyFN, owner: Address) -> Self { - PrivateKeyService { - private_key_fn: Arc::new(Mutex::new(private_key_fn)), - owner, - } - } - - pub fn owner(&self) -> Address { - self.owner - } - - pub fn private_key(&self) -> Result { - let private_key_fn = self.private_key_fn.clone(); - let private_key_fn = private_key_fn - .try_lock() - .map_err(|e| YttriumError { message: e.to_string() })?; - (private_key_fn)() - } -} diff --git a/crates/yttrium/src/sign_service.rs b/crates/yttrium/src/sign_service.rs deleted file mode 100644 index 0923b00d..00000000 --- a/crates/yttrium/src/sign_service.rs +++ /dev/null @@ -1,83 +0,0 @@ -use { - crate::error::YttriumError, - alloy::{ - primitives::Address, - signers::{ - local::{coins_bip39::English, MnemonicBuilder, PrivateKeySigner}, - SignerSync, - }, - }, - std::sync::Arc, - tokio::sync::Mutex, -}; - -pub type SignFN = - dyn Fn(String) -> Result + Send + 'static; - -pub type BoxSignFN = Box; - -pub struct SignService { - sign_fn: Arc>, - owner: Address, -} - -impl SignService { - pub fn new(sign_fn: BoxSignFN, owner: Address) -> Self { - SignService { sign_fn: Arc::new(Mutex::new(sign_fn)), owner } - } - - pub fn owner(&self) -> Address { - self.owner - } - - pub fn sign(&self, message: String) -> Result { - let sign_fn = self.sign_fn.clone(); - let sign_fn = sign_fn - .try_lock() - .map_err(|e| YttriumError { message: e.to_string() })?; - (sign_fn)(message) - } -} - -impl SignService { - pub fn mock() -> Self { - SignService { - sign_fn: Arc::new(Mutex::new(Box::new(|_| Ok("".to_string())))), - owner: Address::ZERO, - } - } - - pub fn new_with_mnemonic(mnemonic: String) -> Self { - let phrase = mnemonic.clone(); - let index: u32 = 0; - - let wallet = MnemonicBuilder::::default() - .phrase(phrase.to_string()) - .index(index) - .unwrap() - .build() - .unwrap(); - - let alloy_signer = PrivateKeySigner::from(wallet.clone()); - - let owner = alloy_signer.address(); - - SignService { - sign_fn: Arc::new(Mutex::new(Box::new(move |msg: String| { - let message_bytes = hex::decode(msg).unwrap(); - let signature = - alloy_signer.sign_message_sync(&message_bytes)?; - let sig_vec: Vec = signature.into(); - let sig_vec_hex = hex::encode(sig_vec.clone()); - println!("sig_vec_hex: {:?}", sig_vec_hex); - Ok(sig_vec_hex) - }))), - owner, - } - } -} - -pub fn address_from_string(address: &str) -> eyre::Result
{ - let address = address.parse::
()?; - Ok(address) -} diff --git a/crates/yttrium/src/signer.rs b/crates/yttrium/src/signer.rs deleted file mode 100644 index 91a9b58e..00000000 --- a/crates/yttrium/src/signer.rs +++ /dev/null @@ -1,250 +0,0 @@ -use { - crate::{ - error::YttriumError, sign_service::SignService, - user_operation::UserOperationV07, - }, - alloy::{ - primitives::Address, - signers::{ - local::{coins_bip39::English, MnemonicBuilder, PrivateKeySigner}, - SignerSync, - }, - }, - eyre, - std::sync::Arc, - tokio::sync::{Mutex, MutexGuard}, -}; - -pub struct Signer { - sign_service: Arc>, -} - -impl Signer { - pub fn new(sign_service: Arc>) -> Self { - Self { sign_service } - } - - pub fn signer_from_phrase( - phrase: &str, - _chain_id: u64, - ) -> eyre::Result { - let index = 0; - let local_signer = MnemonicBuilder::::default() - .phrase(phrase) - .index(index)? - .build()?; - let signer = Self::from(local_signer); - Ok(signer) - } - - pub async fn owner(&self) -> Address { - let sign_service_clone = Arc::clone(&self.sign_service); - let sign_service = sign_service_clone.lock().await; - sign_service.owner() - } - - pub async fn sign_message(&self, message: String) -> eyre::Result> { - let sign_service_clone = Arc::clone(&self.sign_service); - let sign_service = sign_service_clone.lock().await; - let result = Self::sign_message_impl(message, &sign_service)?; - Ok(result) - } - - pub fn sign_user_operation_sync_v07( - &self, - uo: &crate::user_operation::UserOperationV07, - ep: &Address, - chain_id: u64, - ) -> eyre::Result { - let sign_service_clone = Arc::clone(&self.sign_service); - let sign_service = sign_service_clone.try_lock()?; - let result = Self::sign_user_operation_impl_v07( - uo, - ep, - chain_id, - &sign_service, - )?; - Ok(result) - } - - pub fn sign_message_sync(&self, message: String) -> eyre::Result> { - let sign_service_clone = Arc::clone(&self.sign_service); - let sign_service = sign_service_clone.try_lock()?; - let result = Self::sign_message_impl(message, &sign_service)?; - Ok(result) - } - - pub fn sign_message_string_sync( - &self, - message: String, - ) -> eyre::Result { - let sign_service_clone = Arc::clone(&self.sign_service); - let sign_service = sign_service_clone.try_lock()?; - let result = Self::sign_message_as_string_impl(message, &sign_service)?; - Ok(result) - } - - fn sign_user_operation_impl_v07( - uo: &UserOperationV07, - ep: &Address, - chain_id: u64, - sign_service: &MutexGuard, - ) -> eyre::Result { - let hash = uo.hash(ep, chain_id); - let message_bytes = hash.0.to_vec(); - println!("message_bytes: {:?}", message_bytes.clone()); - - let message = hex::encode(message_bytes); - println!("message: {:?}", message.clone()); - - let signature = sign_service.sign(message)?; - let sig_vec: Vec<_> = signature.into(); - let mut user_operation = uo.clone(); - user_operation.signature = sig_vec.into(); - Ok(user_operation) - } - - fn sign_message_impl( - message: String, - sign_service: &MutexGuard, - ) -> eyre::Result> { - let signature = - Self::sign_message_as_string_impl(message, sign_service)?; - let signature_bytes: Vec = signature.into(); - Ok(signature_bytes) - } - - fn sign_message_as_string_impl( - message: String, - sign_service: &MutexGuard, - ) -> eyre::Result { - let signature = sign_service.sign(message)?; - Ok(signature) - } -} - -impl From for Signer -where - S: alloy::signers::SignerSync - + Send - + Sync - + 'static, - S: alloy::signers::Signer - + Send - + Sync - + 'static, -{ - fn from(signer: S) -> Self { - let owner = signer.address(); - let sign_fn = Box::new(move |msg: String| { - signer - .sign_message_sync(msg.as_bytes()) - .map(|sig| sig.as_bytes().to_vec()) - .map(hex::encode) - .map_err(YttriumError::from) - }); - let sign_service_s = SignService::new(sign_fn, owner); - let sign_service = Arc::new(Mutex::new(sign_service_s)); - Signer::new(sign_service) - } -} - -pub fn sign_user_operation_v07_with_ecdsa_and_sign_service( - uo: &UserOperationV07, - ep: &Address, - chain_id: u64, - signer: PrivateKeySigner, - sign_service: &Arc>, -) -> eyre::Result { - let hash = uo.hash(ep, chain_id); - - println!("hash: {:?}", hash.clone()); - - let message = hash.0; - - println!("message: {:?}", message.clone()); - - let message_bytes = message.to_vec(); - - println!("message_bytes: {:?}", message_bytes.clone()); - - let sign_service = Arc::clone(sign_service); - let sign_service = sign_service.try_lock()?; - - let message_hex = hex::encode(message_bytes.clone()); - - let signature_native = sign_service.sign(message_hex)?; - - println!("signature_native: {:?}", signature_native); - - let signature_native_bytes = hex::decode(signature_native.clone())?; - - { - let signature = signer.sign_message_sync(&message_bytes)?; - println!("signature: {:?}", signature); - let sig_vec: Vec = signature.into(); - let sig_vec_hex = hex::encode(sig_vec.clone()); - println!("sig_vec_hex: {:?}", sig_vec_hex); - - assert_eq!( - sig_vec, signature_native_bytes, - "sig_vec != signature_native_bytes" - ); - assert_eq!( - sig_vec_hex, signature_native, - "sig_vec_hex != signature_native" - ); - } - let sig_vec = signature_native_bytes; - - let mut user_operation = uo.clone(); - user_operation.signature = sig_vec.into(); - Ok(user_operation) -} - -pub fn sign_user_operation_v07_with_ecdsa( - uo: &UserOperationV07, - ep: &Address, - chain_id: u64, - signer: PrivateKeySigner, -) -> eyre::Result { - let hash = uo.hash(ep, chain_id); - - println!("hash: {:?}", hash.clone()); - - let message = hash.0; - - println!("message: {:?}", message.clone()); - - let message_bytes = message.to_vec(); - - println!("message_bytes: {:?}", message_bytes.clone()); - - let signature = signer.sign_message_sync(&message_bytes)?; - println!("signature: {:?}", signature); - let sig_vec: Vec = signature.into(); - println!("hex::encode(sig_vec): {:?}", hex::encode(sig_vec.clone())); - - let mut user_operation = uo.clone(); - user_operation.signature = sig_vec.into(); - Ok(user_operation) -} - -#[cfg(test)] -mod tests { - use {super::*, eyre::ensure}; - - pub const ETHERIEUM_MAINNET_CHAIN_ID: u64 = 1; - pub const MNEMONIC_PHRASE: &str = - "test test test test test test test test test test test junk"; - pub const CHAIN_ID: u64 = ETHERIEUM_MAINNET_CHAIN_ID; - - #[tokio::test] - async fn test_sign_message_sync() -> eyre::Result<()> { - let signer = Signer::signer_from_phrase(MNEMONIC_PHRASE, CHAIN_ID)?; - let message = "Hello, world!".to_string(); - let signature = signer.sign_message_sync(message)?; - ensure!(!signature.is_empty(), "Signature is empty"); - Ok(()) - } -} diff --git a/crates/yttrium/src/smart_accounts.rs b/crates/yttrium/src/smart_accounts.rs index cecb0e86..eff74e84 100644 --- a/crates/yttrium/src/smart_accounts.rs +++ b/crates/yttrium/src/smart_accounts.rs @@ -1,5 +1,3 @@ pub mod account_address; -pub mod deployed; pub mod nonce; pub mod safe; -pub mod simple_account; diff --git a/crates/yttrium/src/smart_accounts/deployed.rs b/crates/yttrium/src/smart_accounts/deployed.rs deleted file mode 100644 index 2c216494..00000000 --- a/crates/yttrium/src/smart_accounts/deployed.rs +++ /dev/null @@ -1,92 +0,0 @@ -use { - super::account_address::AccountAddress, - alloy::contract::private::{Network, Provider, Transport}, - core::clone::Clone, -}; - -pub async fn is_smart_account_deployed( - provider: &P, - sender_address: AccountAddress, -) -> eyre::Result -where - T: Transport + Clone, - P: Provider, - N: Network, -{ - let contract_code = - provider.get_code_at(sender_address.to_address()).await?; - - if contract_code.len() > 2 { - return Ok(true); - } - - Ok(false) -} - -#[cfg(test)] -mod tests { - use { - super::*, - alloy::{ - network::EthereumWallet, - providers::ProviderBuilder, - signers::local::{coins_bip39::English, MnemonicBuilder}, - }, - }; - - const MNEMONIC_PHRASE: &str = - "test test test test test test test test test test test junk"; - - #[tokio::test] - async fn test_is_smart_account_deployed() -> eyre::Result<()> { - let config = crate::config::Config::local(); - let chain = crate::chain::Chain::ETHEREUM_SEPOLIA_V07; - let entry_point_config = chain.entry_point_config(); - // let chain_id = chain.id.eip155_chain_id(); - let entry_point_address = entry_point_config.address(); - - let (owner_address, _local_signer, provider) = { - let phrase = MNEMONIC_PHRASE; - let index: u32 = 0; - let local_signer = MnemonicBuilder::::default() - .phrase(phrase) - .index(index)? - .build()?; - let ethereum_wallet = EthereumWallet::from(local_signer.clone()); - let rpc_url_string = config.endpoints.rpc.base_url; - let rpc_url: reqwest::Url = rpc_url_string.parse()?; - let provider = ProviderBuilder::new() - .with_recommended_fillers() - .wallet(ethereum_wallet.clone()) - .on_http(rpc_url); - let owner = ethereum_wallet.clone().default_signer(); - let owner_address = owner.address(); - eyre::Ok((owner_address, local_signer, provider)) - }?; - - use crate::smart_accounts::simple_account::factory::FactoryAddress; - let simple_account_factory_address = FactoryAddress::local_v07(); - use crate::{ - entry_point::get_sender_address::get_sender_address_v07, - smart_accounts::simple_account::create_account::SimpleAccountCreate, - }; - - let factory_data_call = SimpleAccountCreate::new_u64(owner_address, 0); - let factory_data_value = factory_data_call.encode(); - - let sender_address = get_sender_address_v07( - &provider, - simple_account_factory_address.into(), - factory_data_value.into(), - entry_point_address, - ) - .await?; - - let is_deployed = - is_smart_account_deployed(&provider, sender_address).await?; - - println!("is_deployed: {:?}", is_deployed); - - Ok(()) - } -} diff --git a/crates/yttrium/src/smart_accounts/simple_account.rs b/crates/yttrium/src/smart_accounts/simple_account.rs deleted file mode 100644 index fddd2444..00000000 --- a/crates/yttrium/src/smart_accounts/simple_account.rs +++ /dev/null @@ -1,52 +0,0 @@ -use alloy::{sol, sol_types::SolCall}; - -sol!( - #[allow(missing_docs)] - function execute(address dest, uint256 value, bytes calldata func); -); - -pub mod create_account; -pub mod factory; -pub mod sender_address; - -pub struct SimpleAccountExecute(executeCall); - -impl SimpleAccountExecute { - pub fn new( - address: alloy::primitives::Address, - value: alloy::primitives::U256, - func: alloy::primitives::Bytes, - ) -> Self { - Self(executeCall { dest: address, value, func }) - } - - pub fn encode(&self) -> Vec { - executeCall::abi_encode(&self.0) - } -} - -sol! { - #[sol(rpc)] - contract SimpleAccount {} -} - -pub const DUMMY_SIGNATURE_HEX: &str = "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c"; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct OwnerAddress(alloy::primitives::Address); - -impl OwnerAddress { - pub fn new(address: alloy::primitives::Address) -> Self { - Self(address) - } - - pub fn to_address(&self) -> alloy::primitives::Address { - self.0 - } -} - -impl From for alloy::primitives::Address { - fn from(val: OwnerAddress) -> Self { - val.0 - } -} diff --git a/crates/yttrium/src/smart_accounts/simple_account/create_account.rs b/crates/yttrium/src/smart_accounts/simple_account/create_account.rs deleted file mode 100644 index 71f6e8db..00000000 --- a/crates/yttrium/src/smart_accounts/simple_account/create_account.rs +++ /dev/null @@ -1,28 +0,0 @@ -use alloy::{primitives::U256, sol, sol_types::SolCall}; - -sol!( - #[allow(missing_docs)] - #[derive(Debug, PartialEq, Eq)] - type SimpleAccount is address; - function createAccount(address owner,uint256 salt) public returns (SimpleAccount ret); -); - -pub struct SimpleAccountCreate(createAccountCall); - -impl SimpleAccountCreate { - pub fn new( - owner: alloy::primitives::Address, - salt: alloy::primitives::U256, - ) -> Self { - Self(createAccountCall { owner, salt }) - } - - pub fn new_u64(owner: alloy::primitives::Address, salt: u64) -> Self { - let salt = U256::from(salt); - Self(createAccountCall { owner, salt }) - } - - pub fn encode(&self) -> Vec { - createAccountCall::abi_encode(&self.0) - } -} diff --git a/crates/yttrium/src/smart_accounts/simple_account/factory.rs b/crates/yttrium/src/smart_accounts/simple_account/factory.rs deleted file mode 100644 index a04c1cee..00000000 --- a/crates/yttrium/src/smart_accounts/simple_account/factory.rs +++ /dev/null @@ -1,115 +0,0 @@ -use { - crate::{chain::ChainId, entry_point::EntryPointVersion}, - alloy::{ - contract::private::{Network, Provider, Transport}, - primitives::Address, - sol, - }, - std::marker::PhantomData, -}; - -pub struct FactoryInstance { - address: Address, - provider: P, - _network_transport: PhantomData<(N, T)>, -} - -impl + Clone, N: Network> - FactoryInstance -{ - pub fn new(address: Address, provider: P) -> Self { - Self { address, provider, _network_transport: PhantomData } - } - - pub fn local_v07(provider: P) -> Self { - let address = FactoryAddress::local_v07().to_address(); - Self::new(address, provider) - } - - pub fn instance( - self, - ) -> SimpleAccountFactory::SimpleAccountFactoryInstance { - SimpleAccountFactory::new(self.address, self.provider) - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct FactoryAddress(alloy::primitives::Address); - -impl FactoryAddress { - pub const V06: &'static str = ""; // TODO - - pub const V07: &'static str = "0x91E60e0613810449d098b0b5Ec8b51A0FE8c8985"; - - pub const SEPOLIA_V06: &'static str = - "0x9406Cc6185a346906296840746125a0E44976454"; - - pub const SEPOLIA_V07: &'static str = - "0x91E60e0613810449d098b0b5Ec8b51A0FE8c8985"; - - pub const LOCAL_V06: &'static str = - "0x9406Cc6185a346906296840746125a0E44976454"; - - pub const LOCAL_V07: &'static str = - "0x91E60e0613810449d098b0b5Ec8b51A0FE8c8985"; - - pub fn new(address: alloy::primitives::Address) -> Self { - Self(address) - } - - pub fn v06() -> Self { - Self(Self::V06.parse().unwrap()) - } - - pub fn v07() -> Self { - Self(Self::V07.parse().unwrap()) - } - - pub fn local_v06() -> Self { - Self(Self::LOCAL_V06.parse().unwrap()) - } - - pub fn local_v07() -> Self { - Self(Self::LOCAL_V07.parse().unwrap()) - } - - pub fn to_address(self) -> alloy::primitives::Address { - self.into() - } -} - -impl From for Address { - fn from(factory_address: FactoryAddress) -> Self { - factory_address.0 - } -} - -pub fn factory_address_from_chain_id(chain_id: ChainId) -> FactoryAddress { - factory_address_from_chain_id_and_version(chain_id, EntryPointVersion::V07) -} - -pub fn factory_address_from_chain_id_and_version( - chain_id: ChainId, - entry_point_version: EntryPointVersion, -) -> FactoryAddress { - match chain_id { - ChainId::ETHEREUM_MAINNET => match entry_point_version { - EntryPointVersion::V06 => FactoryAddress::v06(), - EntryPointVersion::V07 => FactoryAddress::v07(), - }, - ChainId::ETHEREUM_SEPOLIA => match entry_point_version { - EntryPointVersion::V06 => FactoryAddress::v06(), - EntryPointVersion::V07 => FactoryAddress::v07(), - }, - ChainId::LOCAL_FOUNDRY_ETHEREUM_SEPOLIA => match entry_point_version { - EntryPointVersion::V06 => FactoryAddress::local_v06(), - EntryPointVersion::V07 => FactoryAddress::local_v07(), - }, - _ => panic!("Unsupported chain ID"), - } -} - -sol! { - #[sol(rpc)] - contract SimpleAccountFactory {} -} diff --git a/crates/yttrium/src/smart_accounts/simple_account/sender_address.rs b/crates/yttrium/src/smart_accounts/simple_account/sender_address.rs deleted file mode 100644 index 866b7c9f..00000000 --- a/crates/yttrium/src/smart_accounts/simple_account/sender_address.rs +++ /dev/null @@ -1,83 +0,0 @@ -use { - crate::{ - chain::ChainId, - config::Config, - entry_point::{ - get_sender_address::get_sender_address_v07, EntryPointVersion, - }, - smart_accounts::{ - account_address::AccountAddress, - simple_account::{ - create_account::SimpleAccountCreate, factory::FactoryAddress, - }, - }, - }, - alloy::{ - network::EthereumWallet, primitives::Address, - providers::ProviderBuilder, signers::local::PrivateKeySigner, - }, -}; - -pub async fn get_sender_address_with_signer( - config: Config, - chain_id: u64, - signer: PrivateKeySigner, -) -> eyre::Result { - let _bundler_base_url = config.clone().endpoints.bundler.base_url; - let _paymaster_base_url = config.clone().endpoints.paymaster.base_url; - let rpc_base_url = config.clone().endpoints.rpc.base_url; - - let chain_id = ChainId::new_eip155(chain_id); - let chain = crate::chain::Chain::new(chain_id, EntryPointVersion::V07); - - let entry_point_config = chain.entry_point_config(); - - let entry_point_address = entry_point_config.address(); - - // Create a provider - - let alloy_signer = signer; - let ethereum_wallet = EthereumWallet::new(alloy_signer.clone()); - - let owner = ethereum_wallet.clone().default_signer(); - let owner_address = owner.address(); - - let rpc_url = rpc_base_url.parse()?; - let provider = ProviderBuilder::new() - .with_recommended_fillers() - .wallet(ethereum_wallet.clone()) - .on_http(rpc_url); - - let simple_account_factory_address_primitives: Address = - "0x91E60e0613810449d098b0b5Ec8b51A0FE8c8985".parse()?; - let simple_account_factory_address = - FactoryAddress::new(simple_account_factory_address_primitives); - - let factory_data_call = SimpleAccountCreate::new_u64(owner_address, 2); - - let factory_data_value = factory_data_call.encode(); - - let factory_data_value_hex = hex::encode(factory_data_value.clone()); - - let factory_data_value_hex_prefixed = - format!("0x{}", factory_data_value_hex); - - println!( - "Generated factory_data: {:?}", - factory_data_value_hex_prefixed.clone() - ); - - // 5. Calculate the sender address - - let sender_address = get_sender_address_v07( - &provider, - simple_account_factory_address.into(), - factory_data_value.clone().into(), - entry_point_address, - ) - .await?; - - println!("Calculated sender address: {:?}", sender_address); - - Ok(sender_address) -} diff --git a/crates/yttrium/src/transaction/send.rs b/crates/yttrium/src/transaction/send.rs index 7ead4798..934a56bb 100644 --- a/crates/yttrium/src/transaction/send.rs +++ b/crates/yttrium/src/transaction/send.rs @@ -1,13 +1,9 @@ use { crate::{ - config::Config, - transaction::{ - send::simple_account_test::send_transaction_with_signer, - Transaction, - }, - user_operation::UserOperationV07, + config::Config, smart_accounts::account_address::AccountAddress, + transaction::Transaction, user_operation::UserOperationV07, }, - alloy::{primitives::B256, signers::local::PrivateKeySigner}, + alloy::primitives::B256, core::fmt, safe_test::{ DoSendTransactionParams, OwnerSignature, PreparedSendTransaction, @@ -15,8 +11,6 @@ use { }; pub mod safe_test; -pub mod send_tests; -pub mod simple_account_test; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct UserOperationEstimated(UserOperationV07); @@ -51,91 +45,20 @@ impl fmt::Display for SentUserOperationHash { } } -use crate::account_client::Signer; - -pub async fn send_transactions( - transaction: Vec, - owner: String, - chain_id: u64, - config: Config, - signer: Signer, - safe: bool, -) -> eyre::Result { - match signer { - Signer::PrivateKey(private_key_service) => { - let private_key_service = private_key_service.clone(); - let private_key_service = private_key_service.lock().await; - let private_key_signer_key = - private_key_service.private_key().unwrap(); - let private_key_signer: PrivateKeySigner = - private_key_signer_key.parse().unwrap(); - send_transactions_with_private_key_signer( - transaction, - owner, - chain_id, - config, - private_key_signer, - safe, - ) - .await - } - Signer::Native(_sign_service) => { - todo!("Implement native signer support") - } - Signer::None => { - todo!("send_transaction doesn't work with None signer") - } - } -} - -pub async fn send_transactions_with_private_key_signer( - transactions: Vec, - _owner: String, - chain_id: u64, - config: Config, - private_key_signer: PrivateKeySigner, - safe: bool, -) -> eyre::Result { - let signer = private_key_signer; - - let user_operation_hash = if safe { - safe_test::send_transactions(transactions, signer, None, None, config) - .await? - .user_op_hash - } else { - send_transaction_with_signer( - transactions.first().unwrap().clone(), - config, - chain_id, - signer, - ) - .await? - }; - - println!("user_operation_hash: {:?}", user_operation_hash); - - Ok(user_operation_hash) -} - pub async fn prepare_send_transaction( transactions: Vec, - owner: String, + owner: AccountAddress, _chain_id: u64, config: Config, - safe: bool, ) -> eyre::Result { - let user_operation_hash = if safe { - safe_test::prepare_send_transactions( - transactions, - owner.parse()?, - None, - None, - config, - ) - .await? - } else { - return Err(eyre::eyre!("Only Safe is implemented")); - }; + let user_operation_hash = safe_test::prepare_send_transactions( + transactions, + owner.into(), + None, + None, + config, + ) + .await?; Ok(user_operation_hash) } @@ -145,275 +68,13 @@ pub async fn do_send_transactions( do_send_transaction_params: DoSendTransactionParams, _chain_id: u64, config: Config, - safe: bool, ) -> eyre::Result { - let user_operation_hash = if safe { - safe_test::do_send_transactions( - signatures, - do_send_transaction_params, - config, - ) - .await? - } else { - return Err(eyre::eyre!("Only Safe is implemented")); - }; + let user_operation_hash = safe_test::do_send_transactions( + signatures, + do_send_transaction_params, + config, + ) + .await?; Ok(user_operation_hash) } - -#[cfg(test)] -mod tests { - use { - super::*, - crate::{ - bundler::{ - client::BundlerClient, - config::BundlerConfig, - pimlico::{ - client::BundlerClient as PimlicoBundlerClient, - paymaster::client::PaymasterClient, - }, - }, - entry_point::get_sender_address::get_sender_address_v07, - sign_service::SignService, - signer::sign_user_operation_v07_with_ecdsa, - smart_accounts::{ - nonce::get_nonce, - simple_account::{ - create_account::SimpleAccountCreate, - factory::FactoryAddress, SimpleAccountExecute, - }, - }, - user_operation::UserOperationV07, - }, - alloy::{ - network::EthereumWallet, - primitives::{Address, Bytes, B256, U256}, - providers::ProviderBuilder, - signers::local::{ - coins_bip39::English, MnemonicBuilder, PrivateKeySigner, - }, - }, - std::{str::FromStr, sync::Arc}, - tokio::sync::Mutex, - }; - - const MNEMONIC_PHRASE: &str = - "test test test test test test test test test test test junk"; - - async fn send_transaction_alt( - sign_service: Arc>, - transaction: Transaction, - ) -> eyre::Result { - let sign_service = sign_service.clone(); - let sign_service = sign_service.lock().await; - - let config = crate::config::Config::pimlico(); - - let bundler_base_url = config.endpoints.bundler.base_url; - - let bundler_client = - BundlerClient::new(BundlerConfig::new(bundler_base_url.clone())); - - let pimlico_client: PimlicoBundlerClient = PimlicoBundlerClient::new( - BundlerConfig::new(bundler_base_url.clone()), - ); - - let chain = crate::chain::Chain::ETHEREUM_SEPOLIA_V07; - let entry_point_config = chain.entry_point_config(); - - let chain_id = chain.id.eip155_chain_id(); - - let entry_point_address = entry_point_config.address(); - - let rpc_url = config.endpoints.rpc.base_url; - - // Create a provider - - let (ethereum_wallet, alloy_signer) = { - let phrase = MNEMONIC_PHRASE.to_string(); - let index: u32 = 0; - - let local_signer = { - let local_signer_result = MnemonicBuilder::::default() - .phrase(phrase.clone()) - .index(index)? - .build(); - match local_signer_result { - Ok(signer) => signer, - Err(e) => { - println!("Error creating signer: {}", e); - let local_signer: PrivateKeySigner = phrase.parse()?; - local_signer - } - } - }; - let ethereum_wallet = EthereumWallet::from(local_signer.clone()); - (ethereum_wallet, local_signer) - }; - - let rpc_url: reqwest::Url = rpc_url.parse()?; - let provider = ProviderBuilder::new() - .with_recommended_fillers() - .wallet(ethereum_wallet.clone()) - .on_http(rpc_url); - - let simple_account_factory_address_primitives: Address = - "0x91E60e0613810449d098b0b5Ec8b51A0FE8c8985".parse()?; - let simple_account_factory_address = - FactoryAddress::new(simple_account_factory_address_primitives); - - let owner = ethereum_wallet.clone().default_signer(); - let owner_address = owner.address(); - let sign_service_owner = sign_service.owner(); - assert_eq!( - owner_address, sign_service_owner, - "Owner addresses don't match, should be {:?}, is {:?}", - owner_address, sign_service_owner - ); - - let factory_data_call = SimpleAccountCreate::new_u64(owner_address, 0); - - let factory_data_value = factory_data_call.encode(); - - let factory_data_value_hex = hex::encode(factory_data_value.clone()); - - let factory_data_value_hex_prefixed = - format!("0x{}", factory_data_value_hex); - - println!( - "Generated factory_data: {:?}", - factory_data_value_hex_prefixed.clone() - ); - - // 5. Calculate the sender address - - let sender_address = get_sender_address_v07( - &provider, - simple_account_factory_address.into(), - factory_data_value.clone().into(), - entry_point_address, - ) - .await?; - - println!("Calculated sender address: {:?}", sender_address); - - let to = transaction.to; - let value = transaction.value; - let data = transaction.data; - - let call_data = SimpleAccountExecute::new(to, value, data); - let call_data_encoded = call_data.encode(); - let call_data_value_hex = hex::encode(call_data_encoded.clone()); - let call_data_value_hex_prefixed = format!("0x{}", call_data_value_hex); - - println!("Generated callData: {:?}", call_data_value_hex_prefixed); - - // Fill out remaining UserOperation values - - let gas_price = - pimlico_client.estimate_user_operation_gas_price().await?; - - assert!(gas_price.fast.max_fee_per_gas > U256::from(1)); - - println!("Gas price: {:?}", gas_price); - - let nonce = - get_nonce(&provider, sender_address, &entry_point_address).await?; - - let user_op = UserOperationV07 { - sender: sender_address, - nonce, - factory: None, - factory_data: None, - call_data: Bytes::from_str(&call_data_value_hex)?, - call_gas_limit: U256::from(0), - verification_gas_limit: U256::from(0), - pre_verification_gas: U256::from(0), - max_fee_per_gas: gas_price.fast.max_fee_per_gas, - max_priority_fee_per_gas: gas_price.fast.max_priority_fee_per_gas, - paymaster: None, - paymaster_verification_gas_limit: None, - paymaster_post_op_gas_limit: None, - paymaster_data: None, - // authorization_list: None, - signature: Bytes::from_str( - crate::smart_accounts::simple_account::DUMMY_SIGNATURE_HEX - .strip_prefix("0x") - .unwrap(), - )?, - }; - - let paymaster_client = - PaymasterClient::new(BundlerConfig::new(bundler_base_url.clone())); - - let sponsor_user_op_result = paymaster_client - .sponsor_user_operation_v07( - &user_op.clone().into(), - &entry_point_address, - None, - ) - .await?; - - println!("sponsor_user_op_result: {:?}", sponsor_user_op_result); - - let sponsored_user_op = { - let s = sponsor_user_op_result.clone(); - let mut op = user_op.clone(); - - op.call_gas_limit = s.call_gas_limit; - op.verification_gas_limit = s.verification_gas_limit; - op.pre_verification_gas = s.pre_verification_gas; - op.paymaster = Some(s.paymaster); - op.paymaster_verification_gas_limit = - Some(s.paymaster_verification_gas_limit); - op.paymaster_post_op_gas_limit = - Some(s.paymaster_post_op_gas_limit); - op.paymaster_data = Some(s.paymaster_data); - - op - }; - - println!("Received paymaster sponsor result: {:?}", sponsored_user_op); - - // Sign the UserOperation - - let signed_user_op = sign_user_operation_v07_with_ecdsa( - &sponsored_user_op.clone(), - &entry_point_address.to_address(), - chain_id, - alloy_signer, - )?; - - println!("Generated signature: {:?}", signed_user_op.signature); - - let user_operation_hash = bundler_client - .send_user_operation(entry_point_address, signed_user_op.clone()) - .await?; - - println!("Received User Operation hash: {:?}", user_operation_hash); - - Ok(user_operation_hash) - } - - #[tokio::test] - #[ignore = "TODO: rewrite against local infrastructure"] - async fn test_send_transaction_alt() -> eyre::Result<()> { - let transaction = Transaction::mock(); - - let mnemonic = MNEMONIC_PHRASE.to_string(); - - let sign_service = crate::sign_service::SignService::new_with_mnemonic( - mnemonic.clone(), - ); - - let sign_service_arc = Arc::new(Mutex::new(sign_service)); - - let transaction_hash = - send_transaction_alt(sign_service_arc, transaction).await?; - - println!("Transaction sent: {}", transaction_hash); - - Ok(()) - } -} diff --git a/crates/yttrium/src/transaction/send/safe_test.rs b/crates/yttrium/src/transaction/send/safe_test.rs index 35312fb0..05f88c01 100644 --- a/crates/yttrium/src/transaction/send/safe_test.rs +++ b/crates/yttrium/src/transaction/send/safe_test.rs @@ -75,15 +75,14 @@ impl fmt::Display for SentUserOperationHash { } pub async fn get_address( - owner_address: String, + owner_address: AccountAddress, config: Config, ) -> eyre::Result { let rpc_url = config.endpoints.rpc.base_url; let rpc_url: reqwest::Url = rpc_url.parse()?; let provider = ReqwestProvider::::new_http(rpc_url); - let owners = - Owners { owners: vec![owner_address.parse().unwrap()], threshold: 1 }; + let owners = Owners { owners: vec![owner_address.into()], threshold: 1 }; Ok(get_account_address(provider, owners).await) } diff --git a/crates/yttrium/src/transaction/send/send_tests.rs b/crates/yttrium/src/transaction/send/send_tests.rs deleted file mode 100644 index 23edfa97..00000000 --- a/crates/yttrium/src/transaction/send/send_tests.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod test_send_pimlico_v07; diff --git a/crates/yttrium/src/transaction/send/send_tests/test_send_pimlico_v07.rs b/crates/yttrium/src/transaction/send/send_tests/test_send_pimlico_v07.rs deleted file mode 100644 index 64d892d8..00000000 --- a/crates/yttrium/src/transaction/send/send_tests/test_send_pimlico_v07.rs +++ /dev/null @@ -1,264 +0,0 @@ -#[cfg(test)] -mod tests { - use { - crate::{ - bundler::{ - client::BundlerClient, - config::BundlerConfig, - pimlico::{ - client::BundlerClient as PimlicoBundlerClient, - paymaster::client::PaymasterClient, - }, - }, - entry_point::get_sender_address::get_sender_address_v07, - smart_accounts::simple_account::{ - create_account::SimpleAccountCreate, SimpleAccountExecute, - }, - user_operation::UserOperationV07, - }, - alloy::{ - network::EthereumWallet, - primitives::{Address, Bytes, U256}, - providers::ProviderBuilder, - signers::local::{coins_bip39::English, MnemonicBuilder}, - }, - std::{str::FromStr, sync::Arc}, - tokio::sync::Mutex, - }; - - const SIMPLE_ACCOUNT_FACTORY_ADDRESS: &str = - "0x91E60e0613810449d098b0b5Ec8b51A0FE8c8985"; - - const MNEMONIC_PHRASE: &str = - "test test test test test test test test test test test junk"; - - #[tokio::test] - #[ignore = "TODO: rewrite against local infrastructure"] - async fn test_send_transaction_pimlico_v07() -> eyre::Result<()> { - let expected_factory_data_hex = "0x5fbfb9cf000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000000000000000000000000000000000000000000000"; - - let expected_call_data_hex = "0xb61d27f6000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa9604500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000"; - - let config = crate::config::Config::pimlico(); - - // 3. Create the clients - - let bundler_base_url = config.endpoints.bundler.base_url; - - let bundler_client = - BundlerClient::new(BundlerConfig::new(bundler_base_url.clone())); - - let pimlico_client: PimlicoBundlerClient = PimlicoBundlerClient::new( - BundlerConfig::new(bundler_base_url.clone()), - ); - - let phrase = MNEMONIC_PHRASE; - let index: u32 = 0; - let chain = crate::chain::Chain::ETHEREUM_SEPOLIA_V07; - let entry_point_config = chain.entry_point_config(); - - let chain_id = chain.id.eip155_chain_id(); - - let wallet = MnemonicBuilder::::default() - .phrase(phrase) - .index(index)? - .build()?; - - let alloy_signer = - alloy::signers::local::PrivateKeySigner::from(wallet.clone()); - - let ethereum_wallet = EthereumWallet::from(wallet.clone()); - - let mnemonic = phrase.to_string(); - - let sign_service = crate::sign_service::SignService::new_with_mnemonic( - mnemonic.clone(), - ); - - let rpc_url = config.endpoints.rpc.base_url; - - // Create a provider with the wallet. - let rpc_url: reqwest::Url = rpc_url.parse()?; - let provider = ProviderBuilder::new() - .with_recommended_fillers() - .wallet(ethereum_wallet.clone()) - .on_http(rpc_url); - - // 4.Generate the factory and factoryData - - let _simple_account_factory_address: Address = - SIMPLE_ACCOUNT_FACTORY_ADDRESS.parse()?; - let simple_account_factory_address = - crate::smart_accounts::simple_account::factory::FactoryAddress::new( - _simple_account_factory_address, - ); - - let entry_point_address = entry_point_config.address(); - - let owner = ethereum_wallet.clone().default_signer(); - let owner_address = owner.address(); - - let factory_data_call = SimpleAccountCreate::new_u64(owner_address, 0); - - let factory_data_value = factory_data_call.encode(); - - let factory_data_value_hex = hex::encode(factory_data_value.clone()); - - let factory_data_value_hex_prefixed = - format!("0x{}", factory_data_value_hex); - - assert_eq!( - factory_data_value_hex_prefixed.clone(), - expected_factory_data_hex, - "Factory data value hex does not match expected factory data hex" - ); - - println!( - "Generated factory_data: {:?}", - factory_data_value_hex_prefixed.clone() - ); - - // 5. Calculate the sender address - - let sender_address = get_sender_address_v07( - &provider, - simple_account_factory_address.into(), - factory_data_value.clone().into(), - entry_point_address, - ) - .await?; - - println!("Calculated sender address: {:?}", sender_address); - - // 6. Generate the callData - - let to: Address = - "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045".parse()?; // vitalik - let value = alloy::primitives::Uint::<256, 4>::from(0); - - let data: Bytes = - Bytes::from_str("0x68656c6c6f".strip_prefix("0x").unwrap())?; // "hello" encoded to utf-8 bytes - - let call_data = SimpleAccountExecute::new(to, value, data); - let call_data_encoded = call_data.encode(); - let call_data_value_hex = hex::encode(call_data_encoded.clone()); - let call_data_value_hex_prefixed = format!("0x{}", call_data_value_hex); - - println!("Generated callData: {:?}", call_data_value_hex_prefixed); - - assert_eq!( - call_data_value_hex_prefixed, expected_call_data_hex, - "Call data value hex does not match expected call data hex" - ); - - // 7. Fill out remaining UserOperation values - - let gas_price = - pimlico_client.estimate_user_operation_gas_price().await?; - - assert!(gas_price.fast.max_fee_per_gas > U256::from(1)); - - println!("Gas price: {:?}", gas_price); - - let nonce = crate::smart_accounts::nonce::get_nonce( - &provider, - sender_address, - &entry_point_address, - ) - .await?; - - let user_op = UserOperationV07 { - sender: sender_address, - nonce, - factory: None, - factory_data: None, - call_data: Bytes::from_str(&call_data_value_hex).unwrap(), - call_gas_limit: U256::from(0), - verification_gas_limit: U256::from(0), - pre_verification_gas: U256::from(0), - max_fee_per_gas: gas_price.fast.max_fee_per_gas, - max_priority_fee_per_gas: gas_price.fast.max_priority_fee_per_gas, - paymaster: None, - paymaster_verification_gas_limit: None, - paymaster_post_op_gas_limit: None, - paymaster_data: None, - // authorization_list: None, - signature: Bytes::from_str( - crate::smart_accounts::simple_account::DUMMY_SIGNATURE_HEX - .strip_prefix("0x") - .unwrap(), - )?, - }; - - // 8. Request Pimlico verifying paymaster sponsorship - - let paymaster_client = - PaymasterClient::new(BundlerConfig::new(bundler_base_url.clone())); - let sponsor_user_op_result = paymaster_client - .sponsor_user_operation_v07( - &user_op.clone().into(), - &entry_point_address, - None, - ) - .await?; - - println!("sponsor_user_op_result: {:?}", sponsor_user_op_result); - - let sponsored_user_op = { - let s = sponsor_user_op_result.clone(); - let mut op = user_op.clone(); - - op.call_gas_limit = s.call_gas_limit; - op.verification_gas_limit = s.verification_gas_limit; - op.pre_verification_gas = s.pre_verification_gas; - op.paymaster = Some(s.paymaster); - op.paymaster_verification_gas_limit = - Some(s.paymaster_verification_gas_limit); - op.paymaster_post_op_gas_limit = - Some(s.paymaster_post_op_gas_limit); - op.paymaster_data = Some(s.paymaster_data); - - op - }; - - println!("Received paymaster sponsor result: {:?}", sponsored_user_op); - - // 9. Sign the UserOperation - - let signed_user_op = - crate::signer::sign_user_operation_v07_with_ecdsa_and_sign_service( - &sponsored_user_op.clone(), - &entry_point_address.to_address(), - chain_id, - alloy_signer, - &Arc::new(Mutex::new(sign_service)), - )?; - - println!("Generated signature: {:?}", signed_user_op.signature); - - // 10. Submit the UserOperation to be bundled - - let user_operation_hash = bundler_client - .send_user_operation(entry_point_address, signed_user_op.clone()) - .await?; - - println!("Received User Operation hash: {:?}", user_operation_hash); - - // let's also wait for the userOperation to be included, by continually - // querying for the receipts - - // println!("Querying for receipts..."); - - // let receipt = bundler_client - // .wait_for_user_operation_receipt(user_operation_hash) - // .await?; - - // let tx_hash = receipt.receipt.transaction_hash; - // println!( - // "UserOperation included: https://sepolia.etherscan.io/tx/{}", - // tx_hash - // ); - - Ok(()) - } -} diff --git a/crates/yttrium/src/transaction/send/simple_account_test.rs b/crates/yttrium/src/transaction/send/simple_account_test.rs deleted file mode 100644 index 38cdfbfb..00000000 --- a/crates/yttrium/src/transaction/send/simple_account_test.rs +++ /dev/null @@ -1,470 +0,0 @@ -use { - crate::{ - bundler::{ - client::BundlerClient, - config::BundlerConfig, - pimlico::{ - client::BundlerClient as PimlicoBundlerClient, - paymaster::client::PaymasterClient, - }, - }, - chain::ChainId, - config::Config, - entry_point::get_sender_address::get_sender_address_v07, - signer::sign_user_operation_v07_with_ecdsa, - smart_accounts::{ - nonce::get_nonce, - simple_account::{ - create_account::SimpleAccountCreate, factory::FactoryAddress, - SimpleAccountExecute, - }, - }, - transaction::Transaction, - user_operation::UserOperationV07, - }, - alloy::{ - network::EthereumWallet, - primitives::{Address, Bytes, B256, U256}, - providers::ProviderBuilder, - signers::local::PrivateKeySigner, - }, - core::fmt, - std::str::FromStr, -}; - -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct UserOperationEstimated(UserOperationV07); - -impl From for UserOperationV07 { - fn from(val: UserOperationEstimated) -> Self { - val.0 - } -} - -#[derive(Debug, Clone)] -pub struct SignedUserOperation(UserOperationV07); - -impl From for UserOperationV07 { - fn from(val: SignedUserOperation) -> Self { - val.0 - } -} - -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct SentUserOperationHash(String); - -impl From for String { - fn from(user_operation_hash: SentUserOperationHash) -> Self { - user_operation_hash.0 - } -} - -impl fmt::Display for SentUserOperationHash { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -pub async fn send_transaction_with_signer( - transaction: Transaction, - config: Config, - chain_id: u64, - signer: PrivateKeySigner, -) -> eyre::Result { - let bundler_base_url = config.clone().endpoints.bundler.base_url; - let paymaster_base_url = config.clone().endpoints.paymaster.base_url; - let rpc_base_url = config.clone().endpoints.rpc.base_url; - - let bundler_client = - BundlerClient::new(BundlerConfig::new(bundler_base_url.clone())); - - let pimlico_client: PimlicoBundlerClient = - PimlicoBundlerClient::new(BundlerConfig::new(bundler_base_url.clone())); - - use crate::entry_point::EntryPointVersion; - let chain_id = ChainId::new_eip155(chain_id); - let chain = crate::chain::Chain::new(chain_id, EntryPointVersion::V07); - let entry_point_config = chain.entry_point_config(); - - let entry_point_address = entry_point_config.address(); - - // Create a provider - - let alloy_signer = signer; - let ethereum_wallet = EthereumWallet::new(alloy_signer.clone()); - - let owner = ethereum_wallet.clone().default_signer(); - let owner_address = owner.address(); - - let rpc_url = rpc_base_url.parse()?; - let provider = ProviderBuilder::new() - .with_recommended_fillers() - .wallet(ethereum_wallet.clone()) - .on_http(rpc_url); - - let simple_account_factory_address_primitives: Address = - "0x91E60e0613810449d098b0b5Ec8b51A0FE8c8985".parse()?; - let simple_account_factory_address = - FactoryAddress::new(simple_account_factory_address_primitives); - - let factory_data_call = SimpleAccountCreate::new_u64(owner_address, 2); - - let factory_data_value = factory_data_call.encode(); - - let factory_data_value_hex = hex::encode(factory_data_value.clone()); - - let factory_data_value_hex_prefixed = - format!("0x{}", factory_data_value_hex); - - println!( - "Generated factory_data: {:?}", - factory_data_value_hex_prefixed.clone() - ); - - // 5. Calculate the sender address - - let sender_address = get_sender_address_v07( - &provider, - simple_account_factory_address.into(), - factory_data_value.clone().into(), - entry_point_address, - ) - .await?; - - println!("Calculated sender address: {:?}", sender_address); - - let to: Address = transaction.to; - let value: alloy::primitives::Uint<256, 4> = transaction.value; - let data = transaction.data; - - let call_data = SimpleAccountExecute::new(to, value, data); - let call_data_encoded = call_data.encode(); - let call_data_value_hex = hex::encode(call_data_encoded.clone()); - let call_data_value_hex_prefixed = format!("0x{}", call_data_value_hex); - - println!("Generated callData: {:?}", call_data_value_hex_prefixed); - - let is_deployed = - crate::smart_accounts::deployed::is_smart_account_deployed( - &provider, - sender_address, - ) - .await?; - - println!("is_deployed: {:?}", is_deployed); - - let factory: Option
= if !is_deployed { - Some(simple_account_factory_address.to_address()) - } else { - None - }; - - let factory_data: Option = - if !is_deployed { Some(factory_data_value.into()) } else { None }; - - // Fill out remaining UserOperation values - - let gas_price = pimlico_client.estimate_user_operation_gas_price().await?; - - assert!(gas_price.fast.max_fee_per_gas > U256::from(1)); - - println!("Gas price: {:?}", gas_price); - - let nonce = - get_nonce(&provider, sender_address, &entry_point_address).await?; - - let user_op = UserOperationV07 { - sender: sender_address, - nonce, - factory, - factory_data, - call_data: Bytes::from_str(&call_data_value_hex)?, - call_gas_limit: U256::from(0), - verification_gas_limit: U256::from(0), - pre_verification_gas: U256::from(0), - max_fee_per_gas: gas_price.fast.max_fee_per_gas, - max_priority_fee_per_gas: gas_price.fast.max_priority_fee_per_gas, - paymaster: None, - paymaster_verification_gas_limit: None, - paymaster_post_op_gas_limit: None, - paymaster_data: None, - signature: Bytes::from_str( - crate::smart_accounts::simple_account::DUMMY_SIGNATURE_HEX - .strip_prefix("0x") - .unwrap(), - )?, - }; - - let paymaster_client = - PaymasterClient::new(BundlerConfig::new(paymaster_base_url.clone())); - - let sponsor_user_op_result = paymaster_client - .sponsor_user_operation_v07( - &user_op.clone().into(), - &entry_point_address, - None, - ) - .await?; - - println!("sponsor_user_op_result: {:?}", sponsor_user_op_result); - - let sponsored_user_op = { - let s = sponsor_user_op_result.clone(); - let mut op = user_op.clone(); - - op.call_gas_limit = s.call_gas_limit; - op.verification_gas_limit = s.verification_gas_limit; - op.pre_verification_gas = s.pre_verification_gas; - op.paymaster = Some(s.paymaster); - op.paymaster_verification_gas_limit = - Some(s.paymaster_verification_gas_limit); - op.paymaster_post_op_gas_limit = Some(s.paymaster_post_op_gas_limit); - op.paymaster_data = Some(s.paymaster_data); - - op - }; - - println!("Received paymaster sponsor result: {:?}", sponsored_user_op); - - // Sign the UserOperation - - let signed_user_op = sign_user_operation_v07_with_ecdsa( - &sponsored_user_op.clone(), - &entry_point_address.to_address(), - chain_id.eip155_chain_id(), - alloy_signer, - )?; - - println!("Generated signature: {:?}", signed_user_op.signature); - - let user_operation_hash = bundler_client - .send_user_operation(entry_point_address, signed_user_op.clone()) - .await?; - - println!("Received User Operation hash: {:?}", user_operation_hash); - - Ok(user_operation_hash) -} - -#[cfg(test)] -mod tests { - use { - crate::{ - bundler::{ - client::BundlerClient, - config::BundlerConfig, - pimlico::{ - client::BundlerClient as PimlicoBundlerClient, - paymaster::client::PaymasterClient, - }, - }, - entry_point::get_sender_address::get_sender_address_v07, - signer::sign_user_operation_v07_with_ecdsa, - smart_accounts::{ - nonce::get_nonce, - simple_account::{ - create_account::SimpleAccountCreate, - factory::FactoryAddress, SimpleAccountExecute, - }, - }, - transaction::Transaction, - user_operation::UserOperationV07, - }, - alloy::{ - network::EthereumWallet, - primitives::{Address, Bytes, B256, U256}, - providers::ProviderBuilder, - signers::local::LocalSigner, - }, - std::str::FromStr, - }; - - async fn send_transaction(transaction: Transaction) -> eyre::Result { - let config = crate::config::Config::local(); - - let bundler_base_url = config.endpoints.bundler.base_url; - let paymaster_base_url = config.endpoints.paymaster.base_url; - - let bundler_client = - BundlerClient::new(BundlerConfig::new(bundler_base_url.clone())); - - let pimlico_client: PimlicoBundlerClient = PimlicoBundlerClient::new( - BundlerConfig::new(bundler_base_url.clone()), - ); - - let chain = crate::chain::Chain::ETHEREUM_SEPOLIA_V07; - let entry_point_config = chain.entry_point_config(); - - let chain_id = chain.id.eip155_chain_id(); - - let entry_point_address = entry_point_config.address(); - - let rpc_url = config.endpoints.rpc.base_url; - - // Create a provider - - let alloy_signer = LocalSigner::random(); - let ethereum_wallet = EthereumWallet::new(alloy_signer.clone()); - - let owner = ethereum_wallet.clone().default_signer(); - let owner_address = owner.address(); - - let rpc_url: reqwest::Url = rpc_url.parse()?; - let provider = ProviderBuilder::new() - .with_recommended_fillers() - .wallet(ethereum_wallet.clone()) - .on_http(rpc_url); - - let simple_account_factory_address_primitives: Address = - "0x91E60e0613810449d098b0b5Ec8b51A0FE8c8985".parse()?; - let simple_account_factory_address = - FactoryAddress::new(simple_account_factory_address_primitives); - - let factory_data_call = SimpleAccountCreate::new_u64(owner_address, 2); - - let factory_data_value = factory_data_call.encode(); - - let factory_data_value_hex = hex::encode(factory_data_value.clone()); - - let factory_data_value_hex_prefixed = - format!("0x{}", factory_data_value_hex); - - println!( - "Generated factory_data: {:?}", - factory_data_value_hex_prefixed.clone() - ); - - // 5. Calculate the sender address - - let sender_address = get_sender_address_v07( - &provider, - simple_account_factory_address.into(), - factory_data_value.clone().into(), - entry_point_address, - ) - .await?; - - println!("Calculated sender address: {:?}", sender_address); - - let to = transaction.to; - let value = transaction.value; - let data = transaction.data; - - let call_data = SimpleAccountExecute::new(to, value, data); - let call_data_encoded = call_data.encode(); - let call_data_value_hex = hex::encode(call_data_encoded.clone()); - let call_data_value_hex_prefixed = format!("0x{}", call_data_value_hex); - - println!("Generated callData: {:?}", call_data_value_hex_prefixed); - - // Fill out remaining UserOperation values - - let gas_price = - pimlico_client.estimate_user_operation_gas_price().await?; - - assert!(gas_price.fast.max_fee_per_gas > U256::from(1)); - - println!("Gas price: {:?}", gas_price); - - let nonce = - get_nonce(&provider, sender_address, &entry_point_address).await?; - - let user_op = UserOperationV07 { - sender: sender_address, - nonce, - factory: Some(simple_account_factory_address.to_address()), - factory_data: Some(factory_data_value.into()), - call_data: Bytes::from_str(&call_data_value_hex)?, - call_gas_limit: U256::from(0), - verification_gas_limit: U256::from(0), - pre_verification_gas: U256::from(0), - max_fee_per_gas: gas_price.fast.max_fee_per_gas, - max_priority_fee_per_gas: gas_price.fast.max_priority_fee_per_gas, - paymaster: None, - paymaster_verification_gas_limit: None, - paymaster_post_op_gas_limit: None, - paymaster_data: None, - // authorization_list: None, - signature: Bytes::from_str( - crate::smart_accounts::simple_account::DUMMY_SIGNATURE_HEX - .strip_prefix("0x") - .unwrap(), - )?, - }; - - let paymaster_client = PaymasterClient::new(BundlerConfig::new( - paymaster_base_url.clone(), - )); - - let sponsor_user_op_result = paymaster_client - .sponsor_user_operation_v07( - &user_op.clone().into(), - &entry_point_address, - None, - ) - .await?; - - println!("sponsor_user_op_result: {:?}", sponsor_user_op_result); - - let sponsored_user_op = { - let s = sponsor_user_op_result.clone(); - let mut op = user_op.clone(); - - op.call_gas_limit = s.call_gas_limit; - op.verification_gas_limit = s.verification_gas_limit; - op.pre_verification_gas = s.pre_verification_gas; - op.paymaster = Some(s.paymaster); - op.paymaster_verification_gas_limit = - Some(s.paymaster_verification_gas_limit); - op.paymaster_post_op_gas_limit = - Some(s.paymaster_post_op_gas_limit); - op.paymaster_data = Some(s.paymaster_data); - - op - }; - - println!("Received paymaster sponsor result: {:?}", sponsored_user_op); - - // Sign the UserOperation - - let signed_user_op = sign_user_operation_v07_with_ecdsa( - &sponsored_user_op.clone(), - &entry_point_address.to_address(), - chain_id, - alloy_signer, - )?; - - println!("Generated signature: {:?}", signed_user_op.signature); - - let user_operation_hash = bundler_client - .send_user_operation(entry_point_address, signed_user_op.clone()) - .await?; - - println!("Querying for receipts..."); - - let receipt = bundler_client - .wait_for_user_operation_receipt(user_operation_hash) - .await?; - - println!("Received User Operation receipt: {:?}", receipt); - - let tx_hash = receipt.receipt.transaction_hash; - println!( - "UserOperation included: https://sepolia.etherscan.io/tx/{}", - tx_hash - ); - - Ok(user_operation_hash) - } - - #[tokio::test] - async fn test_send_transaction() -> eyre::Result<()> { - let transaction = Transaction::mock(); - - let transaction_hash = send_transaction(transaction).await?; - - println!("Transaction sent: {}", transaction_hash); - - Ok(()) - } -} diff --git a/crates/yttrium/tests/shared/mod.rs b/crates/yttrium/tests/shared/mod.rs deleted file mode 100644 index e69de29b..00000000 diff --git a/crates/yttrium/tests/test_send_transaction.rs b/crates/yttrium/tests/test_send_transaction.rs deleted file mode 100644 index 2ce871f0..00000000 --- a/crates/yttrium/tests/test_send_transaction.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub const ETHERIEUM_MAINNET_CHAIN_ID: u64 = 1; -pub const MNEMONIC_PHRASE: &str = - "test test test test test test test test test test test junk"; -pub const CHAIN_ID: u64 = ETHERIEUM_MAINNET_CHAIN_ID; - -#[tokio::test] -async fn test_send_transaction_on_sepolia() -> eyre::Result<()> { - Ok(()) -} diff --git a/crates/yttrium_dart/rust/src/lib.rs b/crates/yttrium_dart/rust/src/lib.rs index 4318f776..84f516e6 100644 --- a/crates/yttrium_dart/rust/src/lib.rs +++ b/crates/yttrium_dart/rust/src/lib.rs @@ -9,7 +9,7 @@ use { serde::{Deserialize, Serialize}, std::time::Duration, yttrium::{ - account_client::{AccountClient as YAccountClient, SignerType}, + account_client::AccountClient as YAccountClient, chain_abstraction::{ api::{ prepare::PrepareResponse, @@ -19,8 +19,6 @@ use { client::Client, }, config::Config, - private_key_service::PrivateKeyService, - sign_service::address_from_string, transaction::{ send::safe_test::{ Address, OwnerSignature as YOwnerSignature, PrimitiveSignature, @@ -147,9 +145,6 @@ pub struct AccountClientConfig { pub owner_address: String, pub chain_id: u64, pub config: Config, - pub signer_type: String, - pub safe: bool, - pub private_key: String, } #[frb] @@ -163,25 +158,15 @@ pub struct AccountClient { impl AccountClient { // #[frb(constructor)] pub fn new(config: AccountClientConfig) -> Self { - let owner_address = config.owner_address.clone(); - let signer_type = config.signer_type.clone(); - let signer = SignerType::from(signer_type).unwrap(); - let account_client = match signer { - SignerType::PrivateKey => { - let private_key_fn = - Box::new(move || Ok(config.private_key.clone())); - let owner = address_from_string(&owner_address).unwrap(); - let service = PrivateKeyService::new(private_key_fn, owner); - YAccountClient::new_with_private_key_service( - config.owner_address.clone(), - config.chain_id, - config.config, - service, - config.safe, - ) - } - SignerType::Native => todo!(), - }; + let account_client = YAccountClient::new( + config + .owner_address + .parse::() + .unwrap() + .into(), + config.chain_id, + config.config, + ); Self { owner_address: config.owner_address.clone(), @@ -200,25 +185,10 @@ impl AccountClient { self.account_client .get_address() .await + .map(|address| address.to_string()) .map_err(|e| Error::General(e.to_string())) } - #[frb] - pub async fn send_transactions( - &self, - transactions: Vec, - ) -> Result { - let ytransactions: Vec = - transactions.into_iter().map(YTransaction::from).collect(); - - Ok(self - .account_client - .send_transactions(ytransactions) - .await - .map_err(|e| Error::General(e.to_string()))? - .to_string()) - } - #[frb] pub async fn prepare_send_transactions( &self, @@ -276,16 +246,6 @@ impl AccountClient { .to_string()) } - pub fn sign_message_with_mnemonic( - &self, - message: String, - mnemonic: String, - ) -> Result { - self.account_client - .sign_message_with_mnemonic(message, mnemonic) - .map_err(|e| Error::General(e.to_string())) - } - #[frb] pub async fn wait_for_user_operation_receipt( &self, diff --git a/justfile b/justfile index 659c45fd..fbdefc1d 100644 --- a/justfile +++ b/justfile @@ -24,7 +24,7 @@ devloop-ci: check env-tests _ci _pass devloop-ci-costly: check env-tests _ci costly-tests _pass full: devloop-ci-costly -_ci: udeps swift kotlin +_ci: udeps swift kotlin flutter # Run all checks that CI does; helpful to autofix and help debug most CI errors ci: check _ci _pass @@ -72,3 +72,6 @@ swift: kotlin: # TODO + +flutter: + cd crates/yttrium_dart && flutter_rust_bridge_codegen generate --config-file flutter_rust_bridge.yaml