use super::*;
use crate::keystore::backend::GenericKeyStore;
#[cfg(any(feature = "std", feature = "wasm"))]
use crate::keystore::BackendExt;
#[cfg(any(feature = "std", feature = "wasm"))]
use crate::keystore::TanglePairSigner;
use crate::network::setup::NetworkConfig;
use crate::utils::test_utils::get_client;
use alloc::string::{String, ToString};
use core::fmt::Debug;
use core::net::IpAddr;
use eigensdk::crypto_bls;
use libp2p::Multiaddr;
use protocol::TangleInstanceSettings;
use std::path::PathBuf;
#[cfg(feature = "std")]
pub type StdGadgetConfiguration = GadgetConfiguration<parking_lot::RawRwLock>;
#[non_exhaustive]
pub struct GadgetConfiguration<RwLock: lock_api::RawRwLock> {
pub http_rpc_endpoint: String,
pub ws_rpc_endpoint: String,
pub keystore_uri: String,
pub data_dir: Option<PathBuf>,
pub bootnodes: Vec<Multiaddr>,
pub is_registration: bool,
pub skip_registration: bool,
pub protocol: Protocol,
pub protocol_specific: ProtocolSpecificSettings,
pub target_port: u16,
pub target_addr: IpAddr,
pub use_secure_url: bool,
pub span: tracing::Span,
pub test_mode: bool,
pub(crate) _lock: core::marker::PhantomData<RwLock>,
}
impl<RwLock: lock_api::RawRwLock> Debug for GadgetConfiguration<RwLock> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("GadgetConfiguration")
.field("http_rpc_endpoint", &self.http_rpc_endpoint)
.field("ws_rpc_endpoint", &self.ws_rpc_endpoint)
.field("keystore_uri", &self.keystore_uri)
.field("data_dir", &self.data_dir)
.field("bootnodes", &self.bootnodes)
.field("is_registration", &self.is_registration)
.field("skip_registration", &self.skip_registration)
.field("protocol", &self.protocol)
.field("protocol_specific", &self.protocol_specific)
.field("bind_port", &self.target_port)
.field("bind_addr", &self.target_addr)
.field("test_mode", &self.test_mode)
.finish()
}
}
impl<RwLock: lock_api::RawRwLock> Clone for GadgetConfiguration<RwLock> {
fn clone(&self) -> Self {
Self {
http_rpc_endpoint: self.http_rpc_endpoint.clone(),
ws_rpc_endpoint: self.ws_rpc_endpoint.clone(),
keystore_uri: self.keystore_uri.clone(),
data_dir: self.data_dir.clone(),
bootnodes: self.bootnodes.clone(),
is_registration: self.is_registration,
skip_registration: self.skip_registration,
protocol: self.protocol,
protocol_specific: self.protocol_specific,
target_port: self.target_port,
target_addr: self.target_addr,
use_secure_url: self.use_secure_url,
span: self.span.clone(),
test_mode: self.test_mode,
_lock: core::marker::PhantomData,
}
}
}
impl<RwLock: lock_api::RawRwLock> Default for GadgetConfiguration<RwLock> {
fn default() -> Self {
Self {
http_rpc_endpoint: "http://localhost:9944".to_string(),
ws_rpc_endpoint: "ws://localhost:9944".to_string(),
keystore_uri: "file::memory:".to_string(),
data_dir: None,
bootnodes: Vec::new(),
is_registration: false,
skip_registration: false,
protocol: Protocol::Tangle,
protocol_specific: ProtocolSpecificSettings::Tangle(TangleInstanceSettings {
blueprint_id: 0,
service_id: Some(0),
}),
target_port: 0,
target_addr: core::net::IpAddr::V4(core::net::Ipv4Addr::new(127, 0, 0, 1)),
use_secure_url: false,
span: tracing::Span::current(),
test_mode: true,
_lock: core::marker::PhantomData,
}
}
}
impl<RwLock: lock_api::RawRwLock> GadgetConfiguration<RwLock> {
pub fn libp2p_identity(&self) -> Result<libp2p::identity::Keypair, Error> {
let ed25519 = *self.first_ed25519_signer()?.signer();
let keypair = libp2p::identity::Keypair::ed25519_from_bytes(ed25519.seed())
.map_err(|err| Error::ConfigurationError(err.to_string()))?;
Ok(keypair)
}
pub fn libp2p_network_config<T: Into<String>>(
&self,
network_name: T,
) -> Result<NetworkConfig, Error> {
let network_identity = self.libp2p_identity()?;
let my_ecdsa_key = self.first_ecdsa_signer()?;
let network_config = NetworkConfig::new_service_network(
network_identity,
my_ecdsa_key.signer().clone(),
self.bootnodes.clone(),
self.target_port,
network_name,
);
Ok(network_config)
}
pub fn keystore(&self) -> Result<GenericKeyStore<RwLock>, Error> {
#[cfg(feature = "std")]
use crate::keystore::backend::fs::FilesystemKeystore;
use crate::keystore::backend::{mem::InMemoryKeystore, GenericKeyStore};
match self.keystore_uri.as_str() {
uri if uri == "file::memory:" || uri == ":memory:" => {
Ok(GenericKeyStore::Mem(InMemoryKeystore::new()))
}
#[cfg(feature = "std")]
uri if uri.starts_with("file:") || uri.starts_with("file://") => {
let path = uri
.trim_start_matches("file://")
.trim_start_matches("file:");
Ok(GenericKeyStore::Fs(FilesystemKeystore::open(path)?))
}
otherwise => Err(Error::UnsupportedKeystoreUri(otherwise.to_string())),
}
}
#[doc(alias = "sr25519_signer")]
#[cfg(any(feature = "std", feature = "wasm"))]
pub fn first_sr25519_signer(&self) -> Result<TanglePairSigner<sp_core::sr25519::Pair>, Error> {
self.keystore()?.sr25519_key().map_err(Error::Keystore)
}
#[doc(alias = "ecdsa_signer")]
#[cfg(any(feature = "std", feature = "wasm"))]
pub fn first_ecdsa_signer(&self) -> Result<TanglePairSigner<sp_core::ecdsa::Pair>, Error> {
self.keystore()?.ecdsa_key().map_err(Error::Keystore)
}
#[doc(alias = "ed25519_signer")]
#[cfg(any(feature = "std", feature = "wasm"))]
pub fn first_ed25519_signer(&self) -> Result<TanglePairSigner<sp_core::ed25519::Pair>, Error> {
self.keystore()?.ed25519_key().map_err(Error::Keystore)
}
#[doc(alias = "bls_bn254_signer")]
#[cfg(any(feature = "std", feature = "wasm"))]
pub fn first_bls_bn254_signer(&self) -> Result<crypto_bls::BlsKeyPair, Error> {
self.keystore()?.bls_bn254_key().map_err(Error::Keystore)
}
#[must_use]
pub const fn should_run_registration(&self) -> bool {
self.is_registration
}
#[cfg(any(feature = "std", feature = "wasm"))]
pub async fn client(&self) -> Result<crate::clients::tangle::runtime::TangleClient, Error> {
match self.protocol {
Protocol::Tangle => get_client(&self.ws_rpc_endpoint, &self.http_rpc_endpoint)
.await
.map_err(|err| Error::BadRpcConnection(err.to_string())),
_ => {
get_client(&self.target_endpoint_ws(), &self.target_endpoint_http())
.await
.map_err(|err| Error::BadRpcConnection(err.to_string()))
}
}
}
pub fn target_endpoint_http(&self) -> String {
let base = match self.use_secure_url {
true => "https",
false => "http",
};
format!("{base}://{}:{}", self.target_addr, self.target_port)
}
pub fn target_endpoint_ws(&self) -> String {
let base = match self.use_secure_url {
true => "wss",
false => "ws",
};
format!("{base}://{}:{}", self.target_addr, self.target_port)
}
pub fn service_id(&self) -> Option<u64> {
let tangle_settings = self.protocol_specific.tangle().ok()?;
let TangleInstanceSettings { service_id, .. } = tangle_settings;
*service_id
}
}