diff --git a/Cargo.lock b/Cargo.lock index 26a09ab..1fbcad8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -660,6 +660,16 @@ dependencies = [ "cipher", ] +[[package]] +name = "ctrlc" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b" +dependencies = [ + "nix", + "windows-sys 0.52.0", +] + [[package]] name = "data-encoding" version = "2.5.0" @@ -2296,6 +2306,17 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.4.2", + "cfg-if", + "libc", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -2946,6 +2967,20 @@ dependencies = [ "xps-types", ] +[[package]] +name = "registry-localnet" +version = "0.1.0" +dependencies = [ + "anyhow", + "ctrlc", + "ethers", + "hex", + "lib-didethresolver", + "tokio", + "tracing", + "tracing-subscriber", +] + [[package]] name = "reqwest" version = "0.11.24" diff --git a/Cargo.toml b/Cargo.toml index 52c9eab..93a50f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ members = [ "messaging", "inbox", "registry", - "xps-types", + "xps-types", "bin/registry-localnet", ] exclude = [] diff --git a/bin/registry-localnet/Cargo.toml b/bin/registry-localnet/Cargo.toml new file mode 100644 index 0000000..63f9e88 --- /dev/null +++ b/bin/registry-localnet/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "registry-localnet" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +ethers.workspace = true +anyhow.workspace = true +tokio.workspace = true +tracing.workspace = true +tracing-subscriber.workspace = true +ctrlc = "3.4.2" +lib-didethresolver.workspace = true +hex.workspace = true diff --git a/bin/registry-localnet/src/main.rs b/bin/registry-localnet/src/main.rs new file mode 100644 index 0000000..825fdcc --- /dev/null +++ b/bin/registry-localnet/src/main.rs @@ -0,0 +1,97 @@ +use anyhow::Error; +use ethers::{ + abi::Address, + core::utils::Anvil, + middleware::SignerMiddleware, + providers::{Provider, Ws}, + signers::{LocalWallet, Signer as _}, + utils::AnvilInstance, +}; +use lib_didethresolver::did_registry::DIDRegistry; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; + +#[tokio::main] +async fn main() -> Result<(), Error> { + let running = Arc::new(AtomicBool::new(true)); + let r = running.clone(); + + ctrlc::set_handler(move || { + r.store(false, Ordering::SeqCst); + }) + .expect("Error setting Ctrl-C handler"); + + let anvil = deploy().await?; + + println!("Waiting for Ctrl-C..."); + while running.load(Ordering::SeqCst) {} + drop(anvil); + println!("Shutting down..."); + Ok(()) +} + +async fn deploy() -> Result { + let anvil = Anvil::new() + .port(8545_u16) + .args(vec![ + "--base-fee", + "35", + "--gas-price", + "50", + "--disable-block-gas-limit", + ]) + .spawn(); + let registry_address = deploy_to_anvil(&anvil).await?; + println!( + "Registry deployed at {}, at endpoint {}", + hex::encode(registry_address), + anvil.ws_endpoint() + ); + + println!("Chain ID: {}", anvil.chain_id()); + println!("Endpoint: {}", anvil.endpoint()); + println!("WS Endpoint: {}", anvil.ws_endpoint()); + + println!("\n\n"); + println!("Private Keys -------------------------------------"); + for key in anvil.keys() { + println!("0x{}", hex::encode(key.to_bytes())); + } + println!("\n\n"); + println!("Addresses -------------------------------------"); + for address in anvil.addresses() { + println!("0x{}", hex::encode(address)); + } + + Ok(anvil) +} + +async fn deploy_to_anvil(anvil: &AnvilInstance) -> Result { + println!("Deploying Registry to local anvil"); + + let wallet: LocalWallet = anvil.keys()[0].clone().into(); + let client = client(anvil, wallet).await; + + let registry = DIDRegistry::deploy(client.clone(), ()) + .unwrap() + .gas_price(100) + .send() + .await + .unwrap(); + + Ok(registry.address()) +} + +async fn client( + anvil: &AnvilInstance, + wallet: LocalWallet, +) -> Arc, LocalWallet>> { + let provider = Provider::::connect(anvil.ws_endpoint()) + .await + .unwrap() + .interval(std::time::Duration::from_millis(10u64)); + Arc::new(SignerMiddleware::new( + provider, + wallet.with_chain_id(anvil.chain_id()), + )) +} diff --git a/lib-xps/src/lib.rs b/lib-xps/src/lib.rs index 3fd478e..1cde25c 100644 --- a/lib-xps/src/lib.rs +++ b/lib-xps/src/lib.rs @@ -15,7 +15,7 @@ pub use crate::rpc::{XpsClient, XpsMethods, XpsServer}; use crate::types::GatewayContext; /// Entrypoint for the xps Gateway -pub async fn run(host: String, port: u16) -> Result<()> { +pub async fn run>(host: String, port: u16, provider: P) -> Result<()> { crate::util::init_logging(); let server_addr = format!("{}:{}", host, port); @@ -26,9 +26,7 @@ pub async fn run(host: String, port: u16) -> Result<()> { let registry_contract = Address::from_str(DID_ETH_REGISTRY)?; let conversation_contract = Address::from_str(CONVERSATION)?; - let provider = Provider::::connect("wss://ethereum-sepolia.publicnode.com") - .await - .unwrap(); + let provider = Provider::::connect(provider.as_ref()).await.unwrap(); let context = GatewayContext::new(registry_contract, conversation_contract, provider).await?; let xps_methods = rpc::XpsMethods::new(&context); diff --git a/lib-xps/src/rpc/methods.rs b/lib-xps/src/rpc/methods.rs index 89aa19e..efab4a6 100644 --- a/lib-xps/src/rpc/methods.rs +++ b/lib-xps/src/rpc/methods.rs @@ -13,7 +13,6 @@ use ethers::{ use jsonrpsee::types::ErrorObjectOwned; use lib_didethresolver::types::XmtpAttribute; use messaging::MessagingOperations; -use rand::{rngs::StdRng, SeedableRng}; use std::sync::Arc; use thiserror::Error; use xps_types::{ @@ -31,7 +30,6 @@ pub const DEFAULT_ATTRIBUTE_VALIDITY: u64 = 60 * 60 * 24 * 365; pub struct XpsMethods { message_operations: MessagingOperations>, contact_operations: ContactOperations>, - pub wallet: LocalWallet, pub signer: Arc>, } @@ -40,7 +38,6 @@ impl XpsMethods

{ Self { message_operations: MessagingOperations::new(context.conversation.clone()), contact_operations: ContactOperations::new(context.registry.clone()), - wallet: LocalWallet::new(&mut StdRng::from_entropy()), signer: context.signer.clone(), } } @@ -81,8 +78,10 @@ impl XpsServer for XpsMethods

{ signature, U256::from(DEFAULT_ATTRIBUTE_VALIDITY), ) - .await - .map_err(RpcError::from)?; + .await; + + log::debug!("{:?}", result); + let result = result.map_err(RpcError::from)?; Ok(result) } @@ -104,7 +103,8 @@ impl XpsServer for XpsMethods

{ } async fn wallet_address(&self) -> Result { - Ok(self.wallet.address()) + log::debug!("xps_walletAddress called"); + Ok(self.signer.signer().address()) } /// Fetches the current balance of the wallet in Ether. @@ -120,11 +120,12 @@ impl XpsServer for XpsMethods

{ /// balance could not be fetched or converted. /// async fn balance(&self) -> Result { + log::debug!("xps_balance called"); // Fetch the balance in wei (the smallest unit of Ether) from the blockchain. let wei_balance: U256 = self .signer .provider() - .get_balance(self.wallet.address(), None) + .get_balance(self.signer.signer().address(), None) .await .map_err::, _>(RpcError::from)?; diff --git a/registry/src/lib.rs b/registry/src/lib.rs index 2744b0e..a816789 100644 --- a/registry/src/lib.rs +++ b/registry/src/lib.rs @@ -108,10 +108,20 @@ where .send() .await? .await?; + + if let Some(ref receipt) = transaction_receipt { + log::debug!( + "Gas Used by transaction {}, Gas used in block {}, effective_price {}", + receipt.gas_used.unwrap_or(0.into()), + receipt.cumulative_gas_used, + receipt.effective_gas_price.unwrap_or(0.into()) + ); + } + Ok(GrantInstallationResult { status: Status::Success, message: "Installation request complete.".to_string(), - transaction: transaction_receipt.unwrap().transaction_hash.to_string(), + transaction: transaction_receipt.map(|r| r.transaction_hash), }) } diff --git a/xps-types/src/lib.rs b/xps-types/src/lib.rs index 952c578..f4307fb 100644 --- a/xps-types/src/lib.rs +++ b/xps-types/src/lib.rs @@ -2,8 +2,8 @@ pub mod error; -use ethers::types::U256; use ethers::types::{Address, Bytes as EthersBytes, Signature}; +use ethers::types::{H256, U256}; use ethers::utils::format_units; use std::fmt; @@ -11,8 +11,9 @@ use serde::{Deserialize, Serialize}; use std::fmt::Display; /// Address of the did:ethr Registry on Sepolia -pub const DID_ETH_REGISTRY: &str = "0xd1D374DDE031075157fDb64536eF5cC13Ae75000"; -// Address of the Converstion on Sepolia +// pub const DID_ETH_REGISTRY: &str = "0xd1D374DDE031075157fDb64536eF5cC13Ae75000"; +pub const DID_ETH_REGISTRY: &str = "0x5fbdb2315678afecb367f032d93f642f64180aa3"; +// Address of the Conversation on Sepolia pub const CONVERSATION: &str = "0x15aE865d0645816d8EEAB0b7496fdd24227d1801"; /// A message sent to a conversation @@ -49,7 +50,7 @@ pub type Bytes = Vec; pub struct GrantInstallationResult { pub status: Status, pub message: String, - pub transaction: String, + pub transaction: Option, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] diff --git a/xps/src/main.rs b/xps/src/main.rs index ebde1bc..ebbe998 100644 --- a/xps/src/main.rs +++ b/xps/src/main.rs @@ -9,12 +9,18 @@ struct Args { port: u16, #[arg(short = 's', long = "host", default_value = "127.0.0.1")] host: String, + #[arg( + short = 'e', + long = "endpoint", + default_value = "wss://ethereum-sepolia.publicnode.com" + )] + endpoint: String, } #[tokio::main] async fn main() -> Result<()> { let args = Args::parse(); - crate::run(args.host, args.port).await?; + crate::run(args.host, args.port, args.endpoint).await?; Ok(()) } @@ -60,6 +66,15 @@ mod tests { let args = Args::parse_from(arg_list); assert_eq!(args.port, 0); assert_eq!(args.host, "127.0.0.1"); + assert_eq!(args.endpoint, "wss://ethereum-sepolia.publicnode.com"); + Ok(()) + } + + #[test] + fn test_endpoint() -> Result<()> { + let arg_list = vec!["xps", "--endpoint", "http://localhost:8545"]; + let args = Args::parse_from(arg_list); + assert_eq!(args.endpoint, "http://localhost:8545"); Ok(()) } }