Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
akorchyn committed Jul 5, 2024
2 parents 33db4c2 + b5e9021 commit 52cf0ce
Show file tree
Hide file tree
Showing 14 changed files with 213 additions and 29 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

## [Unreleased]

## [0.10.1](https://github.com/near/near-workspaces-rs/compare/near-workspaces-v0.10.0...near-workspaces-v0.10.1) - 2024-06-26

### Added
- Exposes status RPC API method ([#308](https://github.com/near/near-workspaces-rs/pull/308))
- Fixed `dev_deploy` to use registrar account to create top-level accounts (nearcore 1.37.0+ forbidden to create top-level accounts by non-registrar accounts) ([#360](https://github.com/near/near-workspaces-rs/pull/360))
- Re-exported near-abi-client ([#303](https://github.com/near/near-workspaces-rs/pull/303))

### Other
- a way to get account with more than 100 near on sandbox ([#351](https://github.com/near/near-workspaces-rs/pull/351))
- Updated cargo-near to "0.5.2" ([#347](https://github.com/near/near-workspaces-rs/pull/347))

## [0.10.0](https://github.com/near/near-workspaces-rs/compare/near-workspaces-v0.9.0...near-workspaces-v0.10.0) - 2024-01-25

### Other
Expand Down
4 changes: 4 additions & 0 deletions examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,7 @@ path = "src/build_gen_abi.rs"
[[example]]
name = "macro_gen_abi"
path = "src/macro_gen_abi.rs"

[[example]]
name = "status"
path = "src/status.rs"
4 changes: 3 additions & 1 deletion examples/manually-spawned-sandbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ In workspaces, to connect to our manually launched node, all we have to do is ad
fn main() {
let worker = workspaces::sandbox()
.rpc_addr("http://localhost:3030")
.home_dir("/home/user/.near-sandbox-home")
.validator_key(workspaces::network::ValidatorKey::HomeDir(
"/.near/validator_key.json".into(),
))
.await?;

Ok(())
Expand Down
67 changes: 67 additions & 0 deletions examples/src/status.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let worker = near_workspaces::sandbox().await?;
let res = worker.status().await?;

// status: StatusResponse {
// version: Version {
// version: "trunk",
// build: "eb2bbe1",
// rustc_version: "1.72.0",
// },
// chain_id: "test-chain-vIC0E",
// protocol_version: 63,
// latest_protocol_version: 63,
// rpc_addr: Some(
// "0.0.0.0:3030",
// ),
// validators: [
// ValidatorInfo {
// account_id: AccountId(
// "test.near",
// ),
// is_slashed: false,
// },
// ],
// sync_info: StatusSyncInfo {
// latest_block_hash: GunSGsMD8fEmxsoyzdUGWBE4AiCUsBEefzxQJYMPdZoD,
// latest_block_height: 0,
// latest_state_root: 2tKZ7u2YU5GihxRveb2YMg5oxHBnCxNqgooUKfj9XSzh,
// latest_block_time: 2023-09-19T05:06:44.748482Z,
// syncing: false,
// earliest_block_hash: Some(
// GunSGsMD8fEmxsoyzdUGWBE4AiCUsBEefzxQJYMPdZoD,
// ),
// earliest_block_height: Some(
// 0,
// ),
// earliest_block_time: Some(
// 2023-09-19T05:06:44.748482Z,
// ),
// epoch_id: Some(
// EpochId(
// 11111111111111111111111111111111,
// ),
// ),
// epoch_start_height: Some(
// 0,
// ),
// },
// validator_account_id: Some(
// AccountId(
// "test.near",
// ),
// ),
// validator_public_key: Some(
// ed25519:FHvRfJv7WYoaQVSQD3AES98rTJMyk5wKYPFuLJKXb3nx,
// ),
// node_public_key: ed25519:7gUkJ6EQvSZmRp98hS5mUwojwU8fqQxHjrGcpsfn88um,
// node_key: Some(
// ed25519:FHvRfJv7WYoaQVSQD3AES98rTJMyk5wKYPFuLJKXb3nx,
// ),
// uptime_sec: 0,
// detailed_debug_status: None,
// }
println!("status: {res:#?}");
Ok(())
}
4 changes: 2 additions & 2 deletions workspaces/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "near-workspaces"
version = "0.10.0"
version = "0.10.1"
edition = "2018"
license = "MIT OR Apache-2.0"
readme = "README.md"
Expand Down Expand Up @@ -63,4 +63,4 @@ unstable = ["cargo_metadata"]
experimental = ["near-chain-configs"]

[package.metadata.docs.rs]
features = ["unstable"]
all-features = true
83 changes: 82 additions & 1 deletion workspaces/src/network/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
// churn if we were to.

use std::fs::File;
use std::io::BufReader;
use std::io::{BufReader, Write};
use std::path::Path;
use std::str::FromStr;

use serde_json::Value;

Expand Down Expand Up @@ -74,3 +75,83 @@ pub(crate) fn set_sandbox_configs(home_dir: impl AsRef<Path>) -> Result<()> {
}),
)
}

/// Overwrite the $home_dir/genesis.json file over a set of entries. `value` will be used per (key, value) pair
/// where value can also be another dict. This recursively sets all entry in `value` dict to the config
/// dict, and saves back into `home_dir` at the end of the day.
fn overwrite_genesis(home_dir: impl AsRef<Path>) -> Result<()> {
let home_dir = home_dir.as_ref();
let config_file =
File::open(home_dir.join("genesis.json")).map_err(|err| ErrorKind::Io.custom(err))?;
let config = BufReader::new(config_file);
let mut config: Value =
serde_json::from_reader(config).map_err(|err| ErrorKind::DataConversion.custom(err))?;

let config = config.as_object_mut().expect("expected to be object");
let mut total_supply = u128::from_str(
config
.get_mut("total_supply")
.expect("expected exist total_supply")
.as_str()
.unwrap_or_default(),
)
.unwrap_or_default();
let registrar_amount = 10_000_000_000_000_000_000_000_000_000_u128;
total_supply += registrar_amount;
config.insert(
"total_supply".to_string(),
Value::String(total_supply.to_string()),
);
let records = config.get_mut("records").expect("expect exist records");
records
.as_array_mut()
.expect("expected to be array")
.push(serde_json::json!(
{
"Account": {
"account_id": "registrar",
"account": {
"amount": registrar_amount.to_string(),
"locked": "0",
"code_hash": "11111111111111111111111111111111",
"storage_usage": 182
}
}
}
));
records
.as_array_mut()
.expect("expected to be array")
.push(serde_json::json!(
{
"AccessKey": {
"account_id": "registrar",
"public_key": "ed25519:5BGSaf6YjVm7565VzWQHNxoyEjwr3jUpRJSGjREvU9dB",
"access_key": {
"nonce": 0,
"permission": "FullAccess"
}
}
}
));

let config_file =
File::create(home_dir.join("genesis.json")).map_err(|err| ErrorKind::Io.custom(err))?;
serde_json::to_writer(config_file, &config).map_err(|err| ErrorKind::Io.custom(err))?;

Ok(())
}

pub fn set_sandbox_genesis(home_dir: impl AsRef<Path>) -> Result<()> {
overwrite_genesis(&home_dir)?;
let registrar_key = r#"{"account_id":"registrar","public_key":"ed25519:5BGSaf6YjVm7565VzWQHNxoyEjwr3jUpRJSGjREvU9dB","private_key":"ed25519:3tgdk2wPraJzT4nsTuf86UX41xgPNk3MHnq8epARMdBNs29AFEztAuaQ7iHddDfXG9F2RzV1XNQYgJyAyoW51UBB"}"#;
let mut registrar_wallet = File::create(home_dir.as_ref().join("registrar.json"))
.map_err(|err| ErrorKind::Io.custom(err))?;
registrar_wallet
.write_all(registrar_key.as_bytes())
.map_err(|err| ErrorKind::Io.custom(err))?;
registrar_wallet
.flush()
.map_err(|err| ErrorKind::Io.custom(err))?;
Ok(())
}
1 change: 1 addition & 0 deletions workspaces/src/network/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ pub use self::testnet::Testnet;
pub use self::variants::{
AllowDevAccountCreation, NetworkClient, NetworkInfo, TopLevelAccountCreator,
};
pub use config::set_sandbox_genesis;
18 changes: 16 additions & 2 deletions workspaces/src/network/sandbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,20 @@ impl Sandbox {
)),
}
}

pub(crate) fn registrar_signer(&self) -> Result<InMemorySigner> {
match &self.server.validator_key {
ValidatorKey::HomeDir(home_dir) => {
let path = home_dir.join("registrar.json");
InMemorySigner::from_file(&path)
}
ValidatorKey::Known(account_id, secret_key) => Ok(InMemorySigner::from_secret_key(
account_id.clone(),
secret_key.clone(),
)),
}
}

pub(crate) async fn from_builder_with_version<'a>(
build: NetworkBuilder<'a, Self>,
version: &str,
Expand Down Expand Up @@ -126,7 +140,7 @@ impl TopLevelAccountCreator for Sandbox {
id: AccountId,
sk: SecretKey,
) -> Result<Execution<Account>> {
let root_signer = self.root_signer()?;
let root_signer = self.registrar_signer()?;
let outcome = self
.client()
.create_account(&root_signer, &id, sk.public_key(), DEFAULT_DEPOSIT)
Expand All @@ -146,7 +160,7 @@ impl TopLevelAccountCreator for Sandbox {
sk: SecretKey,
wasm: &[u8],
) -> Result<Execution<Contract>> {
let root_signer = self.root_signer()?;
let root_signer = self.registrar_signer()?;
let outcome = self
.client()
.create_account_and_deploy(
Expand Down
2 changes: 2 additions & 0 deletions workspaces/src/network/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ impl SandboxServer {
// Configure `$home_dir/config.json` to our liking. Sandbox requires extra settings
// for the best user experience, and being able to offer patching large state payloads.
crate::network::config::set_sandbox_configs(&home_dir)?;
// Configure `$home_dir/genesis.json` to our liking.
crate::network::config::set_sandbox_genesis(&home_dir)?;

// Try running the server with the follow provided rpc_ports and net_ports
let (rpc_port, rpc_port_lock) = acquire_unused_port().await?;
Expand Down
12 changes: 12 additions & 0 deletions workspaces/src/network/variants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,18 @@ where
(id, sk)
}

/// Creates a top level developement account.
/// On sandbox network it has a balance of 100 Near.
/// If you need more Near for your tests in sandbox consider using `root_account()` method:
///
/// # Examples
/// ```
/// use near_workspaces::{result::Result, Account, network::Sandbox, Worker};
/// fn get_account_with_lots_of_near(worker: &Worker<Sandbox>) -> Result<Account> {
/// worker.root_account()
/// }
/// ```
///
pub async fn dev_create_account(&self) -> Result<Account> {
let (id, sk) = self.dev_generate().await;
let account = self.create_tla(id.clone(), sk).await?;
Expand Down
14 changes: 4 additions & 10 deletions workspaces/src/rpc/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use tokio_retry::strategy::{jitter, ExponentialBackoff};
use tokio_retry::Retry;

use near_jsonrpc_client::errors::{JsonRpcError, JsonRpcServerError};
use near_jsonrpc_client::methods::health::RpcStatusError;
use near_jsonrpc_client::methods::tx::{RpcTransactionError, RpcTransactionResponse};
use near_jsonrpc_client::{methods, JsonRpcClient, MethodCallResult};
use near_jsonrpc_primitives::types::query::QueryResponseKind;
Expand Down Expand Up @@ -292,18 +291,13 @@ impl Client {
.await
}

pub(crate) async fn status(&self) -> Result<StatusResponse, JsonRpcError<RpcStatusError>> {
pub(crate) async fn status(&self) -> Result<StatusResponse> {
let result = self
.rpc_client
.call(methods::status::RpcStatusRequest)
.await;

tracing::debug!(
target: "workspaces",
"Querying RPC with RpcStatusRequest resulted in {:?}",
result,
);
result
.await
.map_err(|e| RpcErrorCode::QueryFailure.custom(e))?;
Ok(result)
}

pub(crate) async fn tx_async_status(
Expand Down
6 changes: 6 additions & 0 deletions workspaces/src/worker/impls.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use near_jsonrpc_client::methods::tx::RpcTransactionResponse;
use near_primitives::views::StatusResponse;
use near_primitives::views::TxExecutionStatus;

use crate::network::{AllowDevAccountCreation, NetworkClient, NetworkInfo};
Expand Down Expand Up @@ -192,6 +193,11 @@ where
.map(ExecutionFinalResult::from_view)
.map_err(crate::error::Error::from)
}

/// Returns the status of the network.
pub async fn status(&self) -> Result<StatusResponse> {
self.client().status().await
}
}

#[cfg(feature = "experimental")]
Expand Down
15 changes: 2 additions & 13 deletions workspaces/tests/cross_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ async fn test_cross_contract_create_contract() -> anyhow::Result<()> {
let contract = worker.dev_deploy(FACTORY_CONTRACT).await?;
let status_amt = NearToken::from_near(35);

// Expect to fail for trying to create a new contract account with too short of a
// Expect to fail for trying to create a new contract account with a
// top level account name, such as purely just "status"
let status_id: AccountId = "status".parse().unwrap();
let outcome = cross_contract_create_contract(&status_id, &status_amt, &contract).await?;
Expand All @@ -40,17 +40,6 @@ async fn test_cross_contract_create_contract() -> anyhow::Result<()> {
failures.len()
);

// Expect to succeed after calling into the contract with expected length for a
// top level account.
let status_id: AccountId = "status-top-level-account-long-name".parse().unwrap();
let outcome = cross_contract_create_contract(&status_id, &status_amt, &contract).await?;
let failures = outcome.failures();
assert!(
failures.is_empty(),
"Expected no failures for creating a TLA, but got {} failures",
failures.len(),
);

Ok(())
}

Expand All @@ -60,7 +49,7 @@ async fn test_cross_contract_calls() -> anyhow::Result<()> {
let contract = worker.dev_deploy(FACTORY_CONTRACT).await?;
let status_amt = NearToken::from_near(35);

let status_id: AccountId = "status-top-level-account-long-name".parse().unwrap();
let status_id: AccountId = format!("status.{}", contract.id()).parse().unwrap();
cross_contract_create_contract(&status_id, &status_amt, &contract)
.await?
.into_result()?;
Expand Down
1 change: 1 addition & 0 deletions workspaces/tests/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ async fn test_manually_spawned_deploy() -> anyhow::Result<()> {
.await
.unwrap();
tracing::info!(target: "workspaces-test", "sandbox-init: {:?}", output);
near_workspaces::network::set_sandbox_genesis(&home_dir)?;

let mut child = near_sandbox_utils::run(&home_dir, rpc_port, net_port)?;

Expand Down

0 comments on commit 52cf0ce

Please sign in to comment.