Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: api key and custom network object #306

Merged
merged 8 commits into from Oct 4, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Added

- RPC API Keys used to interact with services such as Pagoda Console.
- [Import a couple functions over from near_crypto for PublicKey](https://github.com/near/workspaces-rs/pull/265)
- Impl `Ord`, `PartialOrd`, `Hash`, `BorshSerialize`, `BorshDeserialize`, `Display`, and `FromStr` for `PublicKey`
- NOTE: Borsh bytes format is the same as near-sdk, where it is in the form of [bytes_len, key_type, key_data..]
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -344,5 +344,7 @@ These environment variables will be useful if there was ever a snag hit:

- `NEAR_RPC_TIMEOUT_SECS`: The default is 10 seconds, but this is the amount of time before timing out waiting for a RPC service when talking to the sandbox or any other network such as testnet.
- `NEAR_SANDBOX_BIN_PATH`: Set this to our own prebuilt `neard-sandbox` bin path if we want to use a non-default version of the sandbox or configure nearcore with our own custom features that we want to test in workspaces.
<<<<<<< HEAD
frol marked this conversation as resolved.
Show resolved Hide resolved
- `NEAR_SANDBOX_MAX_PAYLOAD_SIZE`: Sets the max payload size for sending transaction commits to sandbox. The default is 1gb and is necessary for patching large states.
- `NEAR_SANDBOX_MAX_FILES`: Set the max amount of files that can be opened at a time in the sandbox. If none is specified, the default size of 4096 will be used. The actual near chain will use over 10,000 in practice, but for testing this should be much lower since we do not have a constantly running blockchain unless our tests take up that much time.
- `NEAR_RPC_API_KEY`: This is the API key necessary for communicating with RPC nodes. This is useful when interacting with services such as Pagoda Console or a service that can access RPC metrics.
7 changes: 5 additions & 2 deletions examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ serde_json = { version = "1.0" }
tokio = { version = "1.10.0", features = ["full"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3.5", features = ["env-filter"] }
workspaces = { path = "../workspaces", features = ["experimental"] }

workspaces = { path = "../workspaces", features = ["experimental", "unstable"] }

[[example]]
name = "async_transaction"
Expand Down Expand Up @@ -83,3 +82,7 @@ path = "src/tx_status.rs"
[[example]]
name = "noop"
path = "src/noop.rs"

[[example]]
name = "custom_network"
path = "src/custom_network.rs"
20 changes: 20 additions & 0 deletions examples/src/custom_network.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/// URL to the Pagoda API to use for testnet.
pub const PAGODA_TESTNET_RPC_URL: &str = "https://near-testnet.api.pagoda.co/rpc/v1/";

#[tokio::main]
async fn main() -> anyhow::Result<()> {
// `NEAR_RPC_API_KEY="xxxx" cargo test --package workspaces --test custom_network -- test_custom_network --exact --nocapture`
if std::env::var("NEAR_RPC_API_KEY").is_err() {
// skip the test
println!("NEAR_RPC_API_KEY is not set, skipping the example");
return Ok(());
}

// Reference to what can be called by this network: https://docs.pagoda.co/endpoints
let worker = workspaces::custom(PAGODA_TESTNET_RPC_URL).await?;
let res = worker.view_block().await?;

assert!(res.height() > 0);

Ok(())
}
3 changes: 3 additions & 0 deletions workspaces/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,6 @@ pub use worker::{
betanet, mainnet, mainnet_archival, sandbox, testnet, testnet_archival, with_betanet,
with_mainnet, with_mainnet_archival, with_sandbox, with_testnet, with_testnet_archival, Worker,
};

#[cfg(feature = "unstable")]
pub use worker::{custom, with_custom};
2 changes: 1 addition & 1 deletion workspaces/src/network/betanet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub struct Betanet {
impl FromNetworkBuilder for Betanet {
async fn from_builder<'a>(build: NetworkBuilder<'a, Self>) -> crate::result::Result<Self> {
let rpc_url = build.rpc_addr.unwrap_or_else(|| RPC_URL.into());
let client = Client::new(&rpc_url);
let client = Client::new(&rpc_url)?;
client.wait_for_rpc().await?;

Ok(Self {
Expand Down
54 changes: 54 additions & 0 deletions workspaces/src/network/custom.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use crate::network::{Info, NetworkClient, NetworkInfo};
use crate::result::Result;
use crate::rpc::client::Client;
use std::path::PathBuf;

use super::builder::{FromNetworkBuilder, NetworkBuilder};

/// Holds information about a custom network.
pub struct Custom {
client: Client,
info: Info,
}

#[async_trait::async_trait]
impl FromNetworkBuilder for Custom {
async fn from_builder<'a>(build: NetworkBuilder<'a, Self>) -> Result<Self> {
let rpc_url = build
.rpc_addr
.expect("rpc address should be provided for custom network");
let client = Client::new(&rpc_url)?;
client.wait_for_rpc().await?;

Ok(Self {
client,
info: Info {
name: build.name.into(),
root_id: "near".parse().unwrap(),
keystore_path: PathBuf::from(".near-credentials/mainnet/"),
rpc_url: url::Url::parse(&rpc_url).expect("custom provided url should be valid"),
},
})
}
}

impl std::fmt::Debug for Custom {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Custom")
.field("root_id", &self.info.root_id)
.field("rpc_url", &self.info.rpc_url)
.finish()
}
}

impl NetworkClient for Custom {
fn client(&self) -> &Client {
&self.client
}
}

impl NetworkInfo for Custom {
fn info(&self) -> &Info {
&self.info
}
}
2 changes: 1 addition & 1 deletion workspaces/src/network/mainnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub struct Mainnet {
impl FromNetworkBuilder for Mainnet {
async fn from_builder<'a>(build: NetworkBuilder<'a, Self>) -> Result<Self> {
let rpc_url = build.rpc_addr.unwrap_or_else(|| RPC_URL.into());
let client = Client::new(&rpc_url);
let client = Client::new(&rpc_url)?;
client.wait_for_rpc().await?;

Ok(Self {
Expand Down
2 changes: 2 additions & 0 deletions workspaces/src/network/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ pub(crate) mod builder;
pub(crate) mod variants;

pub mod betanet;
pub mod custom;
pub mod mainnet;
pub mod testnet;

pub(crate) use variants::DEV_ACCOUNT_SEED;

pub use self::betanet::Betanet;
pub use self::custom::Custom;
pub use self::info::Info;
pub use self::mainnet::Mainnet;
pub use self::sandbox::Sandbox;
Expand Down
2 changes: 1 addition & 1 deletion workspaces/src/network/sandbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl FromNetworkBuilder for Sandbox {
}
};

let client = Client::new(&server.rpc_addr());
let client = Client::new(&server.rpc_addr())?;
client.wait_for_rpc().await?;

// Server locks some ports on startup due to potential port collision, so we need
Expand Down
2 changes: 1 addition & 1 deletion workspaces/src/network/testnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub struct Testnet {
impl FromNetworkBuilder for Testnet {
async fn from_builder<'a>(build: NetworkBuilder<'a, Self>) -> Result<Self> {
let rpc_url = build.rpc_addr.unwrap_or_else(|| RPC_URL.into());
let client = Client::new(&rpc_url);
let client = Client::new(&rpc_url)?;
client.wait_for_rpc().await?;

Ok(Self {
Expand Down
13 changes: 9 additions & 4 deletions workspaces/src/rpc/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,20 @@ pub struct Client {
}

impl Client {
pub(crate) fn new(rpc_addr: &str) -> Self {
pub(crate) fn new(rpc_addr: &str) -> Result<Self> {
let connector = JsonRpcClient::new_client();
let rpc_client = connector.connect(rpc_addr);
let mut rpc_client = connector.connect(rpc_addr);
if let Ok(api_key) = std::env::var("NEAR_RPC_API_KEY") {
frol marked this conversation as resolved.
Show resolved Hide resolved
let api_key = near_jsonrpc_client::auth::ApiKey::new(api_key)
.map_err(|e| ErrorKind::DataConversion.custom(e))?;
rpc_client = rpc_client.header(api_key);
}

Self {
Ok(Self {
rpc_client,
rpc_addr: rpc_addr.into(),
access_key_nonces: RwLock::new(HashMap::new()),
}
})
}

pub(crate) async fn query_broadcast_tx(
Expand Down
15 changes: 14 additions & 1 deletion workspaces/src/worker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::fmt;
use std::sync::Arc;

use crate::network::builder::NetworkBuilder;
use crate::network::{Betanet, Mainnet, Sandbox, Testnet};
use crate::network::{Betanet, Custom, Mainnet, Sandbox, Testnet};
use crate::{Network, Result};

/// The `Worker` type allows us to interact with any NEAR related networks, such
Expand Down Expand Up @@ -76,6 +76,10 @@ pub fn betanet<'a>() -> NetworkBuilder<'a, Betanet> {
NetworkBuilder::new("betanet")
}

pub fn custom<'a>(rpc_url: &str) -> NetworkBuilder<'a, Custom> {
NetworkBuilder::new("custom").rpc_addr(rpc_url)
}

/// Run a locally scoped task where a [`sandbox`] instanced [`Worker`] is supplied.
pub async fn with_sandbox<F, T>(task: F) -> Result<T::Output>
where
Expand Down Expand Up @@ -129,3 +133,12 @@ where
{
Ok(task(betanet().await?).await)
}

#[allow(dead_code)]
pub async fn with_custom<F, T>(task: F, rpc_url: &str) -> Result<T::Output>
where
F: Fn(Worker<Custom>) -> T,
T: core::future::Future,
{
Ok(task(custom(rpc_url).await?).await)
}
Loading