Release notes
Release notes and unreleased changes can be found in the CHANGELOG
Requirements
- Rust v1.60.0 and up
- MacOS (x86 and M1) or Linux (x86) for sandbox tests.
WASM compilation not supported
workspaces-rs, the library itself, does not currently compile to WASM. Best to put this dependency in [dev-dependencies] section of Cargo.toml if we were trying to run this library alongside something that already does compile to WASM, such as near-sdk-rs.
Simple Testing Case
A simple test to get us going and familiar with workspaces framework. Here, we will be going through the NFT contract and how we can test it with workspaces-rs.
Setup -- Imports
First, we need to declare some imports for convenience.
// macro allowing us to convert human readable units to workspace units.
use parse_near;
// macro allowing us to convert args into JSON bytes to be read by the contract.
use json;
// Additional convenient imports that allows workspaces to function readily.
use *;
We will need to have our pre-compiled WASM contract ahead of time and know its path. In this showcase, we will be pointing to the example's NFT contract:
const NFT_WASM_FILEPATH: &str = "./examples/res/non_fungible_token.wasm";
NOTE: there is an unstable feature that will allow us to compile our projects during testing time as well. Take a look at the feature section Compiling Contracts During Test Time
Setup -- Setting up Sandbox and Deploying NFT Contract
This includes launching our sandbox, loading our wasm file and deploying that wasm file to the sandbox environment.
async
Where
anyhow- A crate that deals with error handling, making it more robust for developers.worker- Our gateway towards interacting with our sandbox environment.contract- The deployed contract on sandbox the developer interacts with.
Then we'll go directly into making a call into the contract, and initialize the NFT contract's metadata:
let outcome = contract
.call
.args_json?
.transact
.await?;
// outcome contains data like logs, receipts and transaction outcomes.
println!;
Afterwards, let's mint an NFT via nft_mint. This showcases some extra arguments we can supply, such as deposit and gas:
let deposit = 10000000000000000000000;
let outcome = contract
.call
.args_json?
.deposit
// nft_mint might consume more than default gas, so supply our own gas value:
.gas
.transact
.await?;
println!;
Then later on, we can view our minted NFT's metadata via our view call into nft_metadata:
let result: Value = contract
.call
.view
.await?
.json?;
println!;
println!;
Ok
}
Common Usage
One advantage of using NEAR Workspaces-rs instead of a unit test is that Workspaces allows you to check balances after a transfer (unit tests don't).
Here is an example:
async
Examples
More standalone examples can be found in examples/src/*.rs.
To run the above NFT example, execute:
cargo run --example nft
Features
Choosing a network
// or whatever runtime we want
async
Helper Functions
Need to make a helper function regardless of whatever Network?
use *;
use ;
// Helper function that calls into a contract we give it
async
Spooning - Pulling Existing State and Contracts from Mainnet/Testnet
This example will showcase spooning state from a testnet contract into our local sandbox environment.
We will first start with the usual imports:
use ;
use Sandbox;
use *;
use ;
Then specify the contract name from testnet we want to be pulling:
const CONTRACT_ACCOUNT: &str = "contract_account_name_on_testnet.testnet";
Let's also specify a specific block ID referencing back to a specific time. Just in case our contract or the one we're referencing has been changed or updated:
const BLOCK_HEIGHT: BlockHeight = 12345;
Create a function called pull_contract which will pull the contract's .wasm file from the chain and deploy it onto our local sandbox. We'll have to re-initialize it with all the data to run tests.
async
This next line will actually pull down the relevant contract from testnet and set an initial balance on it with 1000 NEAR.
Following that we will have to init the contract again with our own metadata. This is because the contract's data is to big for the RPC service to pull down, who's limits are set to 50mb.
let contract = worker
.import_contract
.initial_balance
.block_height
.transact
.await?;
owner
.call
.args_json?
.transact
.await?;
Ok
}
Time Traveling
workspaces testing offers support for forwarding the state of the blockchain to the future. This means contracts which require time sensitive data do not need to sit and wait the same amount of time for blocks on the sandbox to be produced. We can simply just call worker.fast_forward to get us further in time:
async
For a full example, take a look at examples/src/fast_forward.rs.
Compiling Contracts During Test Time
Note, this is an unstable feature and will very likely change. To enable it, add the unstable feature flag to workspaces dependency in Cargo.toml:
[]
= { = "...", = ["unstable"] }
Then, in our tests right before we call into deploy or dev_deploy, we can compile our projects:
async
For a full example, take a look at workspaces/tests/deploy_project.rs.
Environment Variables
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 beforing 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 prebuiltneard-sandboxbin 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.