From 52912f208f92b3ce7cf8c6d316a892ae8c025ead Mon Sep 17 00:00:00 2001 From: Andrew Plaza Date: Thu, 25 Jan 2024 14:07:10 -0500 Subject: [PATCH 1/5] create utilities for writing unit tests with a Mock Provider (no rpc requires) --- xps-gateway/src/lib.rs | 26 ++++++++++++++++++++++ xps-gateway/src/rpc/methods.rs | 40 ++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/xps-gateway/src/lib.rs b/xps-gateway/src/lib.rs index fa40437..8243135 100644 --- a/xps-gateway/src/lib.rs +++ b/xps-gateway/src/lib.rs @@ -22,3 +22,29 @@ pub async fn run(host: String, port: u16) -> Result<()> { handle.stopped().await; Ok(()) } + +#[cfg(test)] +mod test { + use std::str::FromStr; + + use ethers::{ + providers::{MockProvider, Provider}, + types::{Address, U64}, + }; + + use crate::types::GatewayContext; + + pub async fn create_mock_context() -> (GatewayContext>, MockProvider) { + let (provider, mock) = Provider::mocked(); + mock.push(U64::from(2)).unwrap(); + + let gateway = GatewayContext::new( + Address::from_str("0x0000000000000000000000000000000000000000").unwrap(), + provider, + ) + .await + .unwrap(); + + (gateway, mock) + } +} diff --git a/xps-gateway/src/rpc/methods.rs b/xps-gateway/src/rpc/methods.rs index a5d2a6a..90cd396 100644 --- a/xps-gateway/src/rpc/methods.rs +++ b/xps-gateway/src/rpc/methods.rs @@ -47,3 +47,43 @@ impl XpsServer for XpsMethods { Ok(self.wallet.address()) } } + +#[cfg(test)] +mod tests { + use ethers::types::{Block, Transaction, U64}; + use lib_didethresolver::types::{KeyEncoding, XmtpKeyPurpose}; + + use super::*; + + #[tokio::test] + async fn test_rpc_revoke_installation() { + let (context, mock) = crate::test::create_mock_context().await; + + mock.push(U64::from(0)).unwrap(); // transactioncount + mock.push(Block::::default()).unwrap(); // latest block + + let methods = XpsMethods::new(&context); + + let attr = XmtpAttribute { + encoding: KeyEncoding::Hex, + purpose: XmtpKeyPurpose::Installation, + }; + let value = vec![0x01, 0x02, 0x03]; + let res = methods + .revoke_installation( + "0x7e575682a8e450e33eb0493f9972821ae333cd7f".to_string(), + attr, + value, + Signature { + r: [0x01; 32].into(), + s: [0x02; 32].into(), + v: 0x01, + }, + ) + .await; + if let Err(e) = res { + println!("{:?}", e); + println!("{}", e); + } + } +} From 217c673c66efe2b02dd620442748bdcd03fe2a1a Mon Sep 17 00:00:00 2001 From: Andrew Plaza Date: Fri, 26 Jan 2024 17:01:59 -0500 Subject: [PATCH 2/5] use right order of requests in mock --- Cargo.lock | 401 ++++++++++++++++++++++++++++++--- xps-gateway/Cargo.toml | 5 +- xps-gateway/src/lib.rs | 51 ++++- xps-gateway/src/rpc/methods.rs | 28 +++ 4 files changed, 455 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index af6aa54..8671689 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -47,6 +47,21 @@ dependencies = [ "memchr", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anstream" version = "0.6.11" @@ -390,7 +405,12 @@ version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41daef31d7a747c5c847246f36de49ced6f7403b4cdabc807a97b5cc184cda7a" dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", "num-traits", + "wasm-bindgen", + "windows-targets 0.52.0", ] [[package]] @@ -913,20 +933,44 @@ dependencies = [ "uint", ] +[[package]] +name = "ethers" +version = "2.0.11" +dependencies = [ + "ethers-addressbook 2.0.11", + "ethers-contract 2.0.11", + "ethers-core 2.0.11", + "ethers-etherscan 2.0.11", + "ethers-middleware 2.0.11", + "ethers-providers 2.0.11", + "ethers-signers 2.0.11", + "ethers-solc 2.0.11", +] + [[package]] name = "ethers" version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a5344eea9b20effb5efeaad29418215c4d27017639fd1f908260f59cbbd226e" dependencies = [ - "ethers-addressbook", - "ethers-contract", - "ethers-core", - "ethers-etherscan", - "ethers-middleware", - "ethers-providers", - "ethers-signers", - "ethers-solc", + "ethers-addressbook 2.0.12", + "ethers-contract 2.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-core 2.0.12", + "ethers-etherscan 2.0.12", + "ethers-middleware 2.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-providers 2.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-signers 2.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-solc 2.0.12", +] + +[[package]] +name = "ethers-addressbook" +version = "2.0.11" +dependencies = [ + "ethers-core 2.0.11", + "once_cell", + "serde", + "serde_json", ] [[package]] @@ -935,10 +979,27 @@ version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bf35eb7d2e2092ad41f584951e08ec7c077b142dba29c4f1b8f52d2efddc49c" dependencies = [ - "ethers-core", + "ethers-core 2.0.12", + "once_cell", + "serde", + "serde_json", +] + +[[package]] +name = "ethers-contract" +version = "2.0.11" +dependencies = [ + "const-hex", + "ethers-contract-abigen 2.0.11", + "ethers-contract-derive 2.0.11", + "ethers-core 2.0.11", + "ethers-providers 2.0.11", + "futures-util", "once_cell", + "pin-project", "serde", "serde_json", + "thiserror", ] [[package]] @@ -948,10 +1009,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0111ead599d17a7bff6985fd5756f39ca7033edc79a31b23026a8d5d64fa95cd" dependencies = [ "const-hex", - "ethers-contract-abigen", - "ethers-contract-derive", - "ethers-core", - "ethers-providers", + "ethers-contract-abigen 2.0.12", + "ethers-contract-derive 2.0.12", + "ethers-core 2.0.12", + "ethers-providers 2.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures-util", "once_cell", "pin-project", @@ -960,6 +1021,28 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ethers-contract-abigen" +version = "2.0.11" +dependencies = [ + "Inflector", + "const-hex", + "dunce", + "ethers-core 2.0.11", + "ethers-etherscan 2.0.11", + "eyre", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "reqwest", + "serde", + "serde_json", + "syn 2.0.48", + "toml", + "walkdir", +] + [[package]] name = "ethers-contract-abigen" version = "2.0.12" @@ -969,8 +1052,8 @@ dependencies = [ "Inflector", "const-hex", "dunce", - "ethers-core", - "ethers-etherscan", + "ethers-core 2.0.12", + "ethers-etherscan 2.0.12", "eyre", "prettyplease", "proc-macro2", @@ -984,6 +1067,20 @@ dependencies = [ "walkdir", ] +[[package]] +name = "ethers-contract-derive" +version = "2.0.11" +dependencies = [ + "Inflector", + "const-hex", + "ethers-contract-abigen 2.0.11", + "ethers-core 2.0.11", + "proc-macro2", + "quote", + "serde_json", + "syn 2.0.48", +] + [[package]] name = "ethers-contract-derive" version = "2.0.12" @@ -992,14 +1089,42 @@ checksum = "7465c814a2ecd0de0442160da13584205d1cdc08f4717a6511cad455bd5d7dc4" dependencies = [ "Inflector", "const-hex", - "ethers-contract-abigen", - "ethers-core", + "ethers-contract-abigen 2.0.12", + "ethers-core 2.0.12", "proc-macro2", "quote", "serde_json", "syn 2.0.48", ] +[[package]] +name = "ethers-core" +version = "2.0.11" +dependencies = [ + "arrayvec", + "bytes", + "cargo_metadata", + "chrono", + "const-hex", + "elliptic-curve", + "ethabi", + "generic-array", + "k256", + "num_enum", + "once_cell", + "open-fastrlp", + "rand", + "rlp", + "serde", + "serde_json", + "strum", + "syn 2.0.48", + "tempfile", + "thiserror", + "tiny-keccak", + "unicode-xid", +] + [[package]] name = "ethers-core" version = "2.0.12" @@ -1030,6 +1155,20 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "ethers-etherscan" +version = "2.0.11" +dependencies = [ + "chrono", + "ethers-core 2.0.11", + "reqwest", + "semver", + "serde", + "serde_json", + "thiserror", + "tracing", +] + [[package]] name = "ethers-etherscan" version = "2.0.12" @@ -1037,7 +1176,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "facabf8551b4d1a3c08cb935e7fca187804b6c2525cc0dafb8e5a6dd453a24de" dependencies = [ "chrono", - "ethers-core", + "ethers-core 2.0.12", "reqwest", "semver", "serde", @@ -1046,6 +1185,31 @@ dependencies = [ "tracing", ] +[[package]] +name = "ethers-middleware" +version = "2.0.11" +dependencies = [ + "async-trait", + "auto_impl", + "ethers-contract 2.0.11", + "ethers-core 2.0.11", + "ethers-etherscan 2.0.11", + "ethers-providers 2.0.11", + "ethers-signers 2.0.11", + "futures-channel", + "futures-locks", + "futures-util", + "instant", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tokio", + "tracing", + "tracing-futures", + "url", +] + [[package]] name = "ethers-middleware" version = "2.0.11" @@ -1054,11 +1218,11 @@ checksum = "681ece6eb1d10f7cf4f873059a77c04ff1de4f35c63dd7bccde8f438374fcb93" dependencies = [ "async-trait", "auto_impl", - "ethers-contract", - "ethers-core", - "ethers-etherscan", - "ethers-providers", - "ethers-signers", + "ethers-contract 2.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-core 2.0.12", + "ethers-etherscan 2.0.12", + "ethers-providers 2.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-signers 2.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures-channel", "futures-locks", "futures-util", @@ -1073,6 +1237,41 @@ dependencies = [ "url", ] +[[package]] +name = "ethers-providers" +version = "2.0.11" +dependencies = [ + "async-trait", + "auto_impl", + "base64 0.21.7", + "bytes", + "const-hex", + "enr", + "ethers-core 2.0.11", + "futures-core", + "futures-timer", + "futures-util", + "hashers", + "http", + "instant", + "jsonwebtoken", + "once_cell", + "pin-project", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-tungstenite", + "tracing", + "tracing-futures", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "ws_stream_wasm", +] + [[package]] name = "ethers-providers" version = "2.0.11" @@ -1085,7 +1284,7 @@ dependencies = [ "bytes", "const-hex", "enr", - "ethers-core", + "ethers-core 2.0.12", "futures-core", "futures-timer", "futures-util", @@ -1110,6 +1309,23 @@ dependencies = [ "ws_stream_wasm", ] +[[package]] +name = "ethers-signers" +version = "2.0.11" +dependencies = [ + "async-trait", + "coins-bip32", + "coins-bip39", + "const-hex", + "elliptic-curve", + "eth-keystore", + "ethers-core 2.0.11", + "rand", + "sha2", + "thiserror", + "tracing", +] + [[package]] name = "ethers-signers" version = "2.0.11" @@ -1122,13 +1338,43 @@ dependencies = [ "const-hex", "elliptic-curve", "eth-keystore", - "ethers-core", + "ethers-core 2.0.12", "rand", "sha2", "thiserror", "tracing", ] +[[package]] +name = "ethers-solc" +version = "2.0.11" +dependencies = [ + "cfg-if", + "const-hex", + "dirs", + "dunce", + "ethers-core 2.0.11", + "glob", + "home", + "md-5", + "num_cpus", + "once_cell", + "path-slash", + "rayon", + "regex", + "semver", + "serde", + "serde_json", + "solang-parser", + "svm-rs", + "thiserror", + "tiny-keccak", + "tokio", + "tracing", + "walkdir", + "yansi", +] + [[package]] name = "ethers-solc" version = "2.0.12" @@ -1139,7 +1385,7 @@ dependencies = [ "const-hex", "dirs", "dunce", - "ethers-core", + "ethers-core 2.0.12", "glob", "home", "md-5", @@ -1620,6 +1866,29 @@ dependencies = [ "tokio-rustls 0.24.1", ] +[[package]] +name = "iana-time-zone" +version = "0.1.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "idna" version = "0.5.0" @@ -1999,6 +2268,33 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lib-didethresolver" +version = "0.1.0" +source = "git+https://github.com/xmtp/didethresolver?branch=main#4bf3d4b539b6090fdd46367d3a76863f3c449e7f" +dependencies = [ + "async-trait", + "base64 0.21.7", + "bs58", + "chrono", + "ethers 2.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "hex", + "jsonrpsee", + "log", + "peg", + "percent-encoding", + "rand", + "rustc-hex", + "serde", + "sha3", + "smart-default", + "thiserror", + "tiny-keccak", + "tokio", + "tracing", + "url", +] + [[package]] name = "libc" version = "0.2.152" @@ -2335,6 +2631,33 @@ dependencies = [ "hmac", ] +[[package]] +name = "peg" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "400bcab7d219c38abf8bd7cc2054eb9bbbd4312d66f6a5557d572a203f646f61" +dependencies = [ + "peg-macros", + "peg-runtime", +] + +[[package]] +name = "peg-macros" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46e61cce859b76d19090f62da50a9fe92bab7c2a5f09e183763559a2ac392c90" +dependencies = [ + "peg-runtime", + "proc-macro2", + "quote", +] + +[[package]] +name = "peg-runtime" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36bae92c60fa2398ce4678b98b2c4b5a7c61099961ca1fa305aec04a9ad28922" + [[package]] name = "pem" version = "1.1.1" @@ -3279,6 +3602,17 @@ version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +[[package]] +name = "smart-default" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "socket2" version = "0.5.5" @@ -3902,6 +4236,7 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -4085,6 +4420,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -4272,12 +4616,15 @@ dependencies = [ "async-trait", "clap", "ctor", - "ethers", + "ethers 2.0.11", "futures", + "hex", "jsonrpsee", + "lib-didethresolver", "log", "rand", "serde", + "serde_json", "thiserror", "tokio", "tokio-stream", diff --git a/xps-gateway/Cargo.toml b/xps-gateway/Cargo.toml index 890b394..39ba854 100644 --- a/xps-gateway/Cargo.toml +++ b/xps-gateway/Cargo.toml @@ -19,10 +19,13 @@ anyhow = "1" thiserror = "1" ctor = "0.2" clap = { version = "4.4.18", features = ["derive"] } -ethers = "2.0.11" +ethers = { path = "/Users/insipx/Projects/gakonst/ethers-rs/ethers" } rand = "0.8.5" [dev-dependencies] jsonrpsee = { version = "0.21", features = ["macros", "server", "client"] } futures = "0.3" tokio = { version = "1.34", features = ["macros", "rt", "time"] } +lib-didethresolver = { git = "https://github.com/xmtp/didethresolver", branch = "main" } +serde_json = "1.0" +hex = "0.4" diff --git a/xps-gateway/src/lib.rs b/xps-gateway/src/lib.rs index 8243135..db063d4 100644 --- a/xps-gateway/src/lib.rs +++ b/xps-gateway/src/lib.rs @@ -29,9 +29,13 @@ mod test { use ethers::{ providers::{MockProvider, Provider}, - types::{Address, U64}, + types::{Address, U64, H256, TxHash}, + prelude::{PendingTransaction, MockResponse, TransactionReceipt, Transaction} }; - + use serde_json::Value; + use std::borrow::Borrow; + use serde::Serialize; +/* use crate::types::GatewayContext; pub async fn create_mock_context() -> (GatewayContext>, MockProvider) { @@ -47,4 +51,47 @@ mod test { (gateway, mock) } + */ + + fn setup_mock_tx(mock: &mut MockProvider) { + mock.push(TransactionReceipt::default()).unwrap(); // eth_getTransactionReceipt + mock.push(Transaction { block_number: Some(1.into()), ..Transaction::default()}).unwrap(); // eth_getTransaction + mock.push(TxHash::default()).unwrap(); // eth_sendTransaction + mock.push(U64::from(0)).unwrap(); // eth_estimateGas + mock.push(U64::from(0)).unwrap(); // eth_GasPrice + } + + pub trait MockProviderExt { + /// Set the response for a call to a contract + /// This must be called for each transaction that a function might send. + /// + /// # Example + /// ``` + /// use ethers::{ + /// providers::{MockProvider, Provider}, + /// prelude::TransactionRequest, + /// types::{Address, Transaction} + /// }; + /// use std::time::Duration; + /// + /// let (mut provider, mut mock) = Provider::mocked(); + /// provider.set_interval(Duration::from_millis(1)); + /// + /// let to = Address::from_str("0x7e575682a8e450e33eb0493f9972821ae333cd7f").unwrap(); + /// let from = Address::from_str("0x0000000000000000000000000000000000000000").unwrap(); + /// let tx = TransactionRequest::new().to(to).value(1000).from(from); + /// mock.set_transaction_response(None::<()>); + /// let pending = provider.send_transaction(tx, None).await.unwrap().await.unwrap(); + /// ``` + fn set_transaction_response>(&mut self, response: Option); + } + + impl MockProviderExt for MockProvider { + fn set_transaction_response>(&mut self, response: Option) { + if let Some(r) = response { + self.push(r).unwrap(); + } + setup_mock_tx(self); + } + } } diff --git a/xps-gateway/src/rpc/methods.rs b/xps-gateway/src/rpc/methods.rs index 90cd396..a2e6dcf 100644 --- a/xps-gateway/src/rpc/methods.rs +++ b/xps-gateway/src/rpc/methods.rs @@ -52,9 +52,23 @@ impl XpsServer for XpsMethods { mod tests { use ethers::types::{Block, Transaction, U64}; use lib_didethresolver::types::{KeyEncoding, XmtpKeyPurpose}; + use std::str::FromStr; + use crate::test::MockProviderExt; use super::*; + + fn type_of(_: T) -> &'static str { + std::any::type_name::() + } + + #[tokio::test] + async fn test_rpc_wallet_address() { + let methods = XpsMethods::new(); + let res = methods.wallet_address().await.unwrap(); + assert_eq!(type_of(res), "primitive_types::H160"); + } +/* #[tokio::test] async fn test_rpc_revoke_installation() { let (context, mock) = crate::test::create_mock_context().await; @@ -86,4 +100,18 @@ mod tests { println!("{}", e); } } + */ + + #[tokio::test] + async fn test_eth_tx() { + let (mut provider, mut mock) = Provider::mocked(); + provider.set_interval(std::time::Duration::from_millis(1)); + + let to = Address::from_str("0x7e575682a8e450e33eb0493f9972821ae333cd7f").unwrap(); + let from = Address::from_str("0x0000000000000000000000000000000000000000").unwrap(); + let tx = TransactionRequest::new().to(to).value(1000).from(from); + mock.set_transaction_response(None::<()>); + let pending = provider.send_transaction(tx, None).await.unwrap().await.unwrap(); + + } } From ec7cfd742a9a8f466f34b0938c64c96b9c73661b Mon Sep 17 00:00:00 2001 From: Andrew Plaza Date: Tue, 30 Jan 2024 11:15:36 -0500 Subject: [PATCH 3/5] contract tx --- xps-gateway/src/lib.rs | 85 +++++++++++++++++++++++++++------- xps-gateway/src/rpc/methods.rs | 15 +++--- 2 files changed, 76 insertions(+), 24 deletions(-) diff --git a/xps-gateway/src/lib.rs b/xps-gateway/src/lib.rs index 2cb56b3..2ea218d 100644 --- a/xps-gateway/src/lib.rs +++ b/xps-gateway/src/lib.rs @@ -12,8 +12,8 @@ use jsonrpsee::server::Server; use std::str::FromStr; pub use crate::{ - rpc::{XpsMethods, XpsServer}, - types::GatewayContext + rpc::{XpsMethods, XpsServer}, + types::GatewayContext, }; /// Entrypoint for the xps Gateway @@ -30,7 +30,7 @@ pub async fn run(host: String, port: u16) -> Result<()> { let provider = Provider::::connect("wss://ethereum-sepolia.publicnode.com") .await .unwrap(); - + let context = GatewayContext::new(registry_contract, provider).await?; let xps_methods = rpc::XpsMethods::new(&context); let handle = server.start(xps_methods.into_rpc()); @@ -43,16 +43,20 @@ pub async fn run(host: String, port: u16) -> Result<()> { #[cfg(test)] mod test { use ethers::{ + prelude::{Transaction, TransactionReceipt}, providers::MockProvider, - types::{U64, TxHash}, - prelude::{TransactionReceipt, Transaction} + types::{Block, FeeHistory, TxHash, U256, U64}, }; - use std::borrow::Borrow; use serde::Serialize; + use std::borrow::Borrow; fn setup_mock_tx(mock: &mut MockProvider) { mock.push(TransactionReceipt::default()).unwrap(); // eth_getTransactionReceipt - mock.push(Transaction { block_number: Some(1.into()), ..Transaction::default()}).unwrap(); // eth_getTransaction + mock.push(Transaction { + block_number: Some(1.into()), + ..Transaction::default() + }) + .unwrap(); // eth_getTransaction mock.push(TxHash::default()).unwrap(); // eth_sendTransaction mock.push(U64::from(0)).unwrap(); // eth_estimateGas mock.push(U64::from(0)).unwrap(); // eth_GasPrice @@ -78,28 +82,77 @@ mod test { /// let from = Address::from_str("0x0000000000000000000000000000000000000000").unwrap(); /// let tx = TransactionRequest::new().to(to).value(1000).from(from); /// mock.set_transaction_response(None::<()>); - /// let pending = provider.send_transaction(tx, None).await.unwrap().await.unwrap(); + /// let pending = provider.send_transaction(tx, None).await.unwrap().await.unwrap(); /// ``` - fn set_transaction_response>(&mut self, response: Option); - + fn set_transaction_response>( + &mut self, + response: Option, + ); /// Set the response for a transaction to a Contract - fn set_contract_response>(&mut self, response: Option) { - todo!() - } - + fn set_contract_response>( + &mut self, + response: Option, + ); + /// Set the response for a call to a contract - fn set_call_response>(&mut self, response: Option) { + fn set_call_response>( + &mut self, + response: Option, + ) { todo!() } } impl MockProviderExt for MockProvider { - fn set_transaction_response>(&mut self, response: Option) { + fn set_transaction_response>( + &mut self, + response: Option, + ) { if let Some(r) = response { self.push(r).unwrap(); } setup_mock_tx(self); } + + fn set_contract_response>( + &mut self, + response: Option, + ) { + self.push(TransactionReceipt::default()).unwrap(); // eth_getTransactionReceipt + self.push(Transaction { + block_number: Some(1.into()), + ..Transaction::default() + }) + .unwrap(); // eth_getTransaction + self.push(TxHash::default()).unwrap(); // eth_sendRawTransaction + self.push(U64::from(0)).unwrap(); // estimateGas + self.push(fee_history()).unwrap(); // eth_feeHistory + self.push(Block { + //eth_getBlockByNumber + // base_fee_per_gas needs to be Some() for EIP-1559 + base_fee_per_gas: Some(U256::zero()), + ..Block::::default() + }) + .unwrap(); + self.push(U64::from(0)).unwrap(); // transactionCount + } + + fn set_call_response>( + &mut self, + response: Option, + ) { + todo!() + } + } + + // internal fn to return an empty fee history + fn fee_history() -> FeeHistory { + FeeHistory { + base_fee_per_gas: vec![U256::zero()], + gas_used_ratio: vec![0.0], + oldest_block: U256::zero(), + reward: Vec::new(), + } } } diff --git a/xps-gateway/src/rpc/methods.rs b/xps-gateway/src/rpc/methods.rs index f59b746..8e9f6ca 100644 --- a/xps-gateway/src/rpc/methods.rs +++ b/xps-gateway/src/rpc/methods.rs @@ -84,15 +84,15 @@ impl From> for ErrorObjectOwned { #[cfg(test)] mod tests { - use lib_didethresolver::types::{KeyEncoding, XmtpKeyPurpose}; use crate::test::MockProviderExt; + use lib_didethresolver::types::{KeyEncoding, XmtpKeyPurpose}; use super::*; - + fn type_of(_: T) -> &'static str { std::any::type_name::() } - + #[tokio::test] async fn test_rpc_wallet_address() { let (context, _) = GatewayContext::mocked().await; @@ -113,8 +113,8 @@ mod tests { purpose: XmtpKeyPurpose::Installation, }; let value = vec![0x01, 0x02, 0x03]; - - mock.set_transaction_response(None::<()>); + + mock.set_contract_response(None::<()>); methods .revoke_installation( @@ -127,8 +127,7 @@ mod tests { v: 0x01, }, ) - .await.unwrap(); - + .await + .unwrap(); } } - From 3c93b4de22a58e61fbd4783cf52680840922e8cd Mon Sep 17 00:00:00 2001 From: Andrew Plaza Date: Tue, 30 Jan 2024 12:14:33 -0500 Subject: [PATCH 4/5] contract tx --- xps-gateway/src/rpc/methods.rs | 6 +++--- xps-gateway/src/types.rs | 12 ++++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/xps-gateway/src/rpc/methods.rs b/xps-gateway/src/rpc/methods.rs index 8e9f6ca..8851613 100644 --- a/xps-gateway/src/rpc/methods.rs +++ b/xps-gateway/src/rpc/methods.rs @@ -116,7 +116,7 @@ mod tests { mock.set_contract_response(None::<()>); - methods + let res = methods .revoke_installation( "0x7e575682a8e450e33eb0493f9972821ae333cd7f".to_string(), attr, @@ -127,7 +127,7 @@ mod tests { v: 0x01, }, ) - .await - .unwrap(); + .await; + println!("{:?}", res); } } diff --git a/xps-gateway/src/types.rs b/xps-gateway/src/types.rs index 8342b95..3e12cf2 100644 --- a/xps-gateway/src/types.rs +++ b/xps-gateway/src/types.rs @@ -21,21 +21,25 @@ impl GatewayContext

{ let signer = Arc::new(SignerMiddleware::new_with_provider_chain(provider, wallet.clone()).await?); let registry = DIDRegistry::new(registry, signer.clone()); - Ok(Self { registry, signer, wallet }) + Ok(Self { + registry, + signer, + wallet, + }) } - } #[cfg(test)] mod tests { - use ethers::{providers::Provider, types::U64, prelude::MockProvider}; + use ethers::{prelude::MockProvider, providers::Provider, types::U64}; use std::str::FromStr; use super::*; impl GatewayContext> { pub async fn mocked() -> (Self, MockProvider) { - let (provider, mock) = Provider::mocked(); + let (mut provider, mock) = Provider::mocked(); + provider.set_interval(std::time::Duration::from_millis(1)); mock.push(U64::from(2)).unwrap(); let gateway = GatewayContext::new( From 5d68b62b1bd8377f3ab5c6298d273c30f80fa330 Mon Sep 17 00:00:00 2001 From: Andrew Plaza Date: Tue, 30 Jan 2024 13:45:01 -0500 Subject: [PATCH 5/5] how useful is this --- Cargo.lock | 34 ++--------- Cargo.toml | 6 +- registry/src/lib.rs | 24 ++++---- xps-gateway/src/lib.rs | 103 ++++++++++++++++++--------------- xps-gateway/src/rpc/methods.rs | 38 +++++++++++- xps-gateway/src/types.rs | 19 ++---- 6 files changed, 123 insertions(+), 101 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 28bd8c8..93d9bc2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -935,8 +935,6 @@ dependencies = [ [[package]] name = "ethers" version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5344eea9b20effb5efeaad29418215c4d27017639fd1f908260f59cbbd226e" dependencies = [ "ethers-addressbook", "ethers-contract", @@ -950,9 +948,7 @@ dependencies = [ [[package]] name = "ethers-addressbook" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bf35eb7d2e2092ad41f584951e08ec7c077b142dba29c4f1b8f52d2efddc49c" +version = "2.0.11" dependencies = [ "ethers-core", "once_cell", @@ -963,8 +959,6 @@ dependencies = [ [[package]] name = "ethers-contract" version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0111ead599d17a7bff6985fd5756f39ca7033edc79a31b23026a8d5d64fa95cd" dependencies = [ "const-hex", "ethers-contract-abigen", @@ -981,9 +975,7 @@ dependencies = [ [[package]] name = "ethers-contract-abigen" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbdfb952aafd385b31d316ed80d7b76215ce09743c172966d840e96924427e0c" +version = "2.0.11" dependencies = [ "Inflector", "const-hex", @@ -1005,9 +997,7 @@ dependencies = [ [[package]] name = "ethers-contract-derive" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7465c814a2ecd0de0442160da13584205d1cdc08f4717a6511cad455bd5d7dc4" +version = "2.0.11" dependencies = [ "Inflector", "const-hex", @@ -1021,9 +1011,7 @@ dependencies = [ [[package]] name = "ethers-core" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "918b1a9ba585ea61022647def2f27c29ba19f6d2a4a4c8f68a9ae97fd5769737" +version = "2.0.11" dependencies = [ "arrayvec", "bytes", @@ -1051,9 +1039,7 @@ dependencies = [ [[package]] name = "ethers-etherscan" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "facabf8551b4d1a3c08cb935e7fca187804b6c2525cc0dafb8e5a6dd453a24de" +version = "2.0.11" dependencies = [ "chrono", "ethers-core", @@ -1068,8 +1054,6 @@ dependencies = [ [[package]] name = "ethers-middleware" version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681ece6eb1d10f7cf4f873059a77c04ff1de4f35c63dd7bccde8f438374fcb93" dependencies = [ "async-trait", "auto_impl", @@ -1095,8 +1079,6 @@ dependencies = [ [[package]] name = "ethers-providers" version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25d6c0c9455d93d4990c06e049abf9b30daf148cf461ee939c11d88907c60816" dependencies = [ "async-trait", "auto_impl", @@ -1133,8 +1115,6 @@ dependencies = [ [[package]] name = "ethers-signers" version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cb1b714e227bbd2d8c53528adb580b203009728b17d0d0e4119353aa9bc5532" dependencies = [ "async-trait", "coins-bip32", @@ -1151,9 +1131,7 @@ dependencies = [ [[package]] name = "ethers-solc" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2e46e3ec8ef0c986145901fa9864205dc4dcee701f9846be2d56112d34bdea" +version = "2.0.11" dependencies = [ "cfg-if", "const-hex", diff --git a/Cargo.toml b/Cargo.toml index 48d79e8..d9c49e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,9 +25,13 @@ async-trait = "0.1" jsonrpsee = { version = "0.21", features = ["macros", "server", "client-core"] } anyhow = "1.0" thiserror = "1.0" -ethers = { version = "2.0.11", features = ["abigen"] } +ethers = { path = "../../../../gakonst/ethers-rs/ethers", features = ["abigen"] } ctor = "0.2" lib-didethresolver = { git = "https://github.com/xmtp/didethresolver", package = "lib-didethresolver", branch = "main" } gateway-types = { path = "./gateway-types" } rustc-hex = "2.1" hex = "0.4" + +[patch.crates-io] +ethers = { path = "../../../../gakonst/ethers-rs/ethers", features = ["abigen"] } + diff --git a/registry/src/lib.rs b/registry/src/lib.rs index 5b58f4c..e7d3485 100644 --- a/registry/src/lib.rs +++ b/registry/src/lib.rs @@ -81,18 +81,18 @@ where String::from_utf8_lossy(&attribute) ); - self.registry - .revoke_attribute_signed( - address, - signature.v.try_into()?, - signature.r.into(), - signature.s.into(), - attribute, - value.into(), - ) - .send() - .await? - .await?; + let res = self.registry.revoke_attribute_signed( + address, + signature.v.try_into()?, + signature.r.into(), + signature.s.into(), + attribute, + value.into(), + ); + + let res = res.send().await; + println!("{:?}", res); + res?.await?; Ok(()) } diff --git a/xps-gateway/src/lib.rs b/xps-gateway/src/lib.rs index 2ea218d..d25ac23 100644 --- a/xps-gateway/src/lib.rs +++ b/xps-gateway/src/lib.rs @@ -43,29 +43,18 @@ pub async fn run(host: String, port: u16) -> Result<()> { #[cfg(test)] mod test { use ethers::{ + abi::AbiEncode, prelude::{Transaction, TransactionReceipt}, providers::MockProvider, types::{Block, FeeHistory, TxHash, U256, U64}, }; use serde::Serialize; - use std::borrow::Borrow; - - fn setup_mock_tx(mock: &mut MockProvider) { - mock.push(TransactionReceipt::default()).unwrap(); // eth_getTransactionReceipt - mock.push(Transaction { - block_number: Some(1.into()), - ..Transaction::default() - }) - .unwrap(); // eth_getTransaction - mock.push(TxHash::default()).unwrap(); // eth_sendTransaction - mock.push(U64::from(0)).unwrap(); // eth_estimateGas - mock.push(U64::from(0)).unwrap(); // eth_GasPrice - } pub trait MockProviderExt { /// Set the response for a call to a contract /// This must be called for each transaction that a function might send. /// + /// /// # Example /// ``` /// use ethers::{ @@ -81,45 +70,69 @@ mod test { /// let to = Address::from_str("0x7e575682a8e450e33eb0493f9972821ae333cd7f").unwrap(); /// let from = Address::from_str("0x0000000000000000000000000000000000000000").unwrap(); /// let tx = TransactionRequest::new().to(to).value(1000).from(from); - /// mock.set_transaction_response(None::<()>); + /// mock.set_transaction_response(TransactionReceipt::default()); /// let pending = provider.send_transaction(tx, None).await.unwrap().await.unwrap(); /// ``` - fn set_transaction_response>( - &mut self, - response: Option, - ); + fn set_transaction_response(&mut self, response: TransactionReceipt); /// Set the response for a transaction to a Contract - fn set_contract_response>( - &mut self, - response: Option, - ); + /// + /// # Example + /// ``` + /// + /// let (context, mut mock) = GatewayContext::mocked().await; + /// let methods = XpsMethods::new(&context); + /// let attr = XmtpAttribute { + /// encoding: KeyEncoding::Hex, + /// purpose: XmtpKeyPurpose::Installation, + /// }; + /// let value = vec![0x01, 0x02, 0x03]; + /// mock.set_contract_response(Default::default()); + /// let res = methods + /// .revoke_installation( + /// Address::default().to_string(), + /// attr, + /// value, + /// Signature { + /// r: [0x01; 32].into(), + /// s: [0x02; 32].into(), + /// v: 0x01, + /// }, + /// ) + /// .await; + /// ``` + fn set_contract_response(&mut self, response: TransactionReceipt); /// Set the response for a call to a contract - fn set_call_response>( - &mut self, - response: Option, - ) { - todo!() - } + /// + /// # Example + /// + /// ``` + /// let (context, mut mock) = GatewayContext::mocked().await; + /// let registry = DIDRegistry::new(Address::default(), context.signer.clone()); + /// mock.set_call_response(ChangedReturn(U256::zero())); + /// registry.changed(Address::default()).call().await.unwrap(); + /// + /// ``` + /// + fn set_call_response(&mut self, response: T); } impl MockProviderExt for MockProvider { - fn set_transaction_response>( - &mut self, - response: Option, - ) { - if let Some(r) = response { - self.push(r).unwrap(); - } - setup_mock_tx(self); + fn set_transaction_response(&mut self, response: TransactionReceipt) { + self.push(response).unwrap(); + self.push(Transaction { + block_number: Some(1.into()), + ..Transaction::default() + }) + .unwrap(); // eth_getTransaction + self.push(TxHash::default()).unwrap(); // eth_sendTransaction + self.push(U64::from(0)).unwrap(); // eth_estimateGas + self.push(U64::from(0)).unwrap(); // eth_GasPrice } - fn set_contract_response>( - &mut self, - response: Option, - ) { - self.push(TransactionReceipt::default()).unwrap(); // eth_getTransactionReceipt + fn set_contract_response(&mut self, response: TransactionReceipt) { + self.push(response).unwrap(); self.push(Transaction { block_number: Some(1.into()), ..Transaction::default() @@ -138,11 +151,9 @@ mod test { self.push(U64::from(0)).unwrap(); // transactionCount } - fn set_call_response>( - &mut self, - response: Option, - ) { - todo!() + fn set_call_response(&mut self, response: T) { + self.push::(&response.encode_hex()) + .unwrap(); } } diff --git a/xps-gateway/src/rpc/methods.rs b/xps-gateway/src/rpc/methods.rs index 889daa7..520cf5b 100644 --- a/xps-gateway/src/rpc/methods.rs +++ b/xps-gateway/src/rpc/methods.rs @@ -11,6 +11,7 @@ use ethers::{core::types::Signature, providers::Middleware}; use gateway_types::GrantInstallationResult; use jsonrpsee::types::ErrorObjectOwned; use lib_didethresolver::types::XmtpAttribute; + use rand::{rngs::StdRng, SeedableRng}; use std::sync::Arc; use thiserror::Error; @@ -100,6 +101,7 @@ enum RpcError { impl From> for ErrorObjectOwned { fn from(error: RpcError) -> Self { + println!("{:?}", error); match error { RpcError::ContactOperation(c) => { ErrorObjectOwned::owned(-31999, c.to_string(), None::<()>) @@ -111,6 +113,7 @@ impl From> for ErrorObjectOwned { #[cfg(test)] mod tests { use crate::test::MockProviderExt; + use ethers::providers::MockResponse; use lib_didethresolver::types::{KeyEncoding, XmtpKeyPurpose}; use super::*; @@ -140,7 +143,40 @@ mod tests { }; let value = vec![0x01, 0x02, 0x03]; - mock.set_contract_response(None::<()>); + mock.set_contract_response(Default::default()); + + let res = methods + .revoke_installation( + "0x7e575682a8e450e33eb0493f9972821ae333cd7f".to_string(), + attr, + value, + Signature { + r: [0x01; 32].into(), + s: [0x02; 32].into(), + v: 0x01, + }, + ) + .await; + assert!(res.is_ok()); + } + + #[tokio::test] + async fn test_rpc_revoke_installation_error() { + let (context, mut mock) = GatewayContext::mocked().await; + + let methods = XpsMethods::new(&context); + + let attr = XmtpAttribute { + encoding: KeyEncoding::Hex, + purpose: XmtpKeyPurpose::Installation, + }; + let value = vec![0x01, 0x02, 0x03]; + + mock.push_response(MockResponse::Error(JsonRpcError { + code: -32000, + message: "VM Exception while processing transaction: revert".to_string(), + data: None, + })); let res = methods .revoke_installation( diff --git a/xps-gateway/src/types.rs b/xps-gateway/src/types.rs index 3e12cf2..01386b4 100644 --- a/xps-gateway/src/types.rs +++ b/xps-gateway/src/types.rs @@ -32,7 +32,6 @@ impl GatewayContext

{ #[cfg(test)] mod tests { use ethers::{prelude::MockProvider, providers::Provider, types::U64}; - use std::str::FromStr; use super::*; @@ -42,12 +41,9 @@ mod tests { provider.set_interval(std::time::Duration::from_millis(1)); mock.push(U64::from(2)).unwrap(); - let gateway = GatewayContext::new( - Address::from_str("0x0000000000000000000000000000000000000000").unwrap(), - provider, - ) - .await - .unwrap(); + let gateway = GatewayContext::new(Address::default(), provider) + .await + .unwrap(); (gateway, mock) } @@ -58,12 +54,9 @@ mod tests { let (provider, mock) = Provider::mocked(); mock.push(U64::from(2)).unwrap(); - let gateway = GatewayContext::new( - Address::from_str("0x0000000000000000000000000000000000000000").unwrap(), - provider, - ) - .await - .unwrap(); + let gateway = GatewayContext::new(Address::default(), provider) + .await + .unwrap(); assert!(gateway.registry.address().is_zero()); assert!(gateway.signer.is_signer().await);