mod types;
use itertools::Itertools;
pub use types::*;
use std::any::Any;
use std::str::FromStr;
use crate::libp2p::{NetRPCMethods, NetworkMessage, PeerId};
use crate::rpc::{ApiPaths, Ctx, Permission, RpcMethod, ServerError};
use anyhow::{Context as _, Result};
use cid::multibase;
use fvm_ipld_blockstore::Blockstore;
pub enum NetAddrsListen {}
impl RpcMethod<0> for NetAddrsListen {
const NAME: &'static str = "Filecoin.NetAddrsListen";
const PARAM_NAMES: [&'static str; 0] = [];
const API_PATHS: ApiPaths = ApiPaths::V1;
const PERMISSION: Permission = Permission::Read;
type Params = ();
type Ok = AddrInfo;
async fn handle(ctx: Ctx<impl Blockstore>, (): Self::Params) -> Result<Self::Ok, ServerError> {
let (tx, rx) = flume::bounded(1);
let req = NetworkMessage::JSONRPCRequest {
method: NetRPCMethods::AddrsListen(tx),
};
ctx.network_send.send_async(req).await?;
let (id, addrs) = rx.recv_async().await?;
Ok(AddrInfo::new(id, addrs))
}
}
pub enum NetPeers {}
impl RpcMethod<0> for NetPeers {
const NAME: &'static str = "Filecoin.NetPeers";
const PARAM_NAMES: [&'static str; 0] = [];
const API_PATHS: ApiPaths = ApiPaths::V1;
const PERMISSION: Permission = Permission::Read;
type Params = ();
type Ok = Vec<AddrInfo>;
async fn handle(ctx: Ctx<impl Blockstore>, (): Self::Params) -> Result<Self::Ok, ServerError> {
let (tx, rx) = flume::bounded(1);
let req = NetworkMessage::JSONRPCRequest {
method: NetRPCMethods::Peers(tx),
};
ctx.network_send.send_async(req).await?;
let peer_addresses = rx.recv_async().await?;
let connections = peer_addresses
.into_iter()
.map(|(id, addrs)| AddrInfo::new(id, addrs))
.collect();
Ok(connections)
}
}
pub enum NetFindPeer {}
impl RpcMethod<1> for NetFindPeer {
const NAME: &'static str = "Filecoin.NetFindPeer";
const PARAM_NAMES: [&'static str; 1] = ["peer_id"];
const API_PATHS: ApiPaths = ApiPaths::V1;
const PERMISSION: Permission = Permission::Read;
type Params = (String,);
type Ok = AddrInfo;
async fn handle(
ctx: Ctx<impl Blockstore>,
(peer_id,): Self::Params,
) -> Result<Self::Ok, ServerError> {
let peer_id = PeerId::from_str(&peer_id)?;
let (tx, rx) = flume::bounded(1);
ctx.network_send
.send_async(NetworkMessage::JSONRPCRequest {
method: NetRPCMethods::Peer(tx, peer_id),
})
.await?;
let addrs = rx
.recv_async()
.await?
.with_context(|| format!("peer {peer_id} not found"))?;
Ok(AddrInfo::new(peer_id, addrs))
}
}
pub enum NetListening {}
impl RpcMethod<0> for NetListening {
const NAME: &'static str = "Filecoin.NetListening";
const PARAM_NAMES: [&'static str; 0] = [];
const API_PATHS: ApiPaths = ApiPaths::V1;
const PERMISSION: Permission = Permission::Read;
type Params = ();
type Ok = bool;
async fn handle(_: Ctx<impl Any>, (): Self::Params) -> Result<Self::Ok, ServerError> {
Ok(true)
}
}
pub enum NetInfo {}
impl RpcMethod<0> for NetInfo {
const NAME: &'static str = "Forest.NetInfo";
const PARAM_NAMES: [&'static str; 0] = [];
const API_PATHS: ApiPaths = ApiPaths::V1;
const PERMISSION: Permission = Permission::Read;
type Params = ();
type Ok = NetInfoResult;
async fn handle(ctx: Ctx<impl Blockstore>, (): Self::Params) -> Result<Self::Ok, ServerError> {
let (tx, rx) = flume::bounded(1);
let req = NetworkMessage::JSONRPCRequest {
method: NetRPCMethods::Info(tx),
};
ctx.network_send.send_async(req).await?;
Ok(rx.recv_async().await?)
}
}
pub enum NetConnect {}
impl RpcMethod<1> for NetConnect {
const NAME: &'static str = "Filecoin.NetConnect";
const PARAM_NAMES: [&'static str; 1] = ["info"];
const API_PATHS: ApiPaths = ApiPaths::V1;
const PERMISSION: Permission = Permission::Write;
type Params = (AddrInfo,);
type Ok = ();
async fn handle(
ctx: Ctx<impl Blockstore>,
(AddrInfo { id, addrs },): Self::Params,
) -> Result<Self::Ok, ServerError> {
let (_, id) = multibase::decode(format!("{}{}", "z", id))?;
let peer_id = PeerId::from_bytes(&id)?;
let (tx, rx) = flume::bounded(1);
let req = NetworkMessage::JSONRPCRequest {
method: NetRPCMethods::Connect(tx, peer_id, addrs),
};
ctx.network_send.send_async(req).await?;
let success = rx.recv_async().await?;
if success {
Ok(())
} else {
Err(anyhow::anyhow!("Peer could not be dialed from any address provided").into())
}
}
}
pub enum NetDisconnect {}
impl RpcMethod<1> for NetDisconnect {
const NAME: &'static str = "Filecoin.NetDisconnect";
const PARAM_NAMES: [&'static str; 1] = ["id"];
const API_PATHS: ApiPaths = ApiPaths::V1;
const PERMISSION: Permission = Permission::Write;
type Params = (String,);
type Ok = ();
async fn handle(
ctx: Ctx<impl Blockstore>,
(id,): Self::Params,
) -> Result<Self::Ok, ServerError> {
let peer_id = PeerId::from_str(&id)?;
let (tx, rx) = flume::bounded(1);
let req = NetworkMessage::JSONRPCRequest {
method: NetRPCMethods::Disconnect(tx, peer_id),
};
ctx.network_send.send_async(req).await?;
rx.recv_async().await?;
Ok(())
}
}
pub enum NetAgentVersion {}
impl RpcMethod<1> for NetAgentVersion {
const NAME: &'static str = "Filecoin.NetAgentVersion";
const PARAM_NAMES: [&'static str; 1] = ["id"];
const API_PATHS: ApiPaths = ApiPaths::V1;
const PERMISSION: Permission = Permission::Read;
type Params = (String,);
type Ok = String;
async fn handle(
ctx: Ctx<impl Blockstore>,
(id,): Self::Params,
) -> Result<Self::Ok, ServerError> {
let peer_id = PeerId::from_str(&id)?;
let (tx, rx) = flume::bounded(1);
ctx.network_send
.send_async(NetworkMessage::JSONRPCRequest {
method: NetRPCMethods::AgentVersion(tx, peer_id),
})
.await?;
Ok(rx.recv_async().await?.context("item not found")?)
}
}
pub enum NetAutoNatStatus {}
impl RpcMethod<0> for NetAutoNatStatus {
const NAME: &'static str = "Filecoin.NetAutoNatStatus";
const PARAM_NAMES: [&'static str; 0] = [];
const API_PATHS: ApiPaths = ApiPaths::V1;
const PERMISSION: Permission = Permission::Read;
type Params = ();
type Ok = NatStatusResult;
async fn handle(ctx: Ctx<impl Blockstore>, (): Self::Params) -> Result<Self::Ok, ServerError> {
let (tx, rx) = flume::bounded(1);
let req = NetworkMessage::JSONRPCRequest {
method: NetRPCMethods::AutoNATStatus(tx),
};
ctx.network_send.send_async(req).await?;
let nat_status = rx.recv_async().await?;
Ok(nat_status.into())
}
}
pub enum NetVersion {}
impl RpcMethod<0> for NetVersion {
const NAME: &'static str = "Filecoin.NetVersion";
const PARAM_NAMES: [&'static str; 0] = [];
const API_PATHS: ApiPaths = ApiPaths::V1;
const PERMISSION: Permission = Permission::Read;
type Params = ();
type Ok = String;
async fn handle(ctx: Ctx<impl Blockstore>, (): Self::Params) -> Result<Self::Ok, ServerError> {
Ok(ctx.chain_config().eth_chain_id.to_string())
}
}
pub enum NetProtectAdd {}
impl RpcMethod<1> for NetProtectAdd {
const NAME: &'static str = "Filecoin.NetProtectAdd";
const PARAM_NAMES: [&'static str; 1] = ["peer_ids"];
const API_PATHS: ApiPaths = ApiPaths::V1;
const PERMISSION: Permission = Permission::Admin;
type Params = (Vec<String>,);
type Ok = ();
async fn handle(
ctx: Ctx<impl Blockstore>,
(peer_ids,): Self::Params,
) -> Result<Self::Ok, ServerError> {
let peer_ids = peer_ids
.iter()
.map(String::as_str)
.map(PeerId::from_str)
.try_collect()?;
let (tx, rx) = flume::bounded(1);
ctx.network_send
.send_async(NetworkMessage::JSONRPCRequest {
method: NetRPCMethods::ProtectPeer(tx, peer_ids),
})
.await?;
rx.recv_async().await?;
Ok(())
}
}
pub enum NetProtectList {}
impl RpcMethod<0> for NetProtectList {
const NAME: &'static str = "Filecoin.NetProtectList";
const PARAM_NAMES: [&'static str; 0] = [];
const API_PATHS: ApiPaths = ApiPaths::Both;
const PERMISSION: Permission = Permission::Read;
type Params = ();
type Ok = Vec<String>;
async fn handle(_: Ctx<impl Blockstore>, (): Self::Params) -> Result<Self::Ok, ServerError> {
Err(ServerError::stubbed_for_openrpc())
}
}
pub enum NetProtectRemove {}
impl RpcMethod<1> for NetProtectRemove {
const NAME: &'static str = "Filecoin.NetProtectRemove";
const PARAM_NAMES: [&'static str; 1] = ["peer_ids"];
const API_PATHS: ApiPaths = ApiPaths::Both;
const PERMISSION: Permission = Permission::Admin;
type Params = (Vec<String>,);
type Ok = ();
async fn handle(
ctx: Ctx<impl Blockstore>,
(peer_ids,): Self::Params,
) -> Result<Self::Ok, ServerError> {
let peer_ids = peer_ids
.iter()
.map(String::as_str)
.map(PeerId::from_str)
.try_collect()?;
let (tx, rx) = flume::bounded(1);
ctx.network_send
.send_async(NetworkMessage::JSONRPCRequest {
method: NetRPCMethods::UnprotectPeer(tx, peer_ids),
})
.await?;
rx.recv_async().await?;
Ok(())
}
}