Cudos Blast is a Node.js CLI (command line interface) tool for working with the Cudos blockchain. You can scaffold, compile and test your Rust smart contracts. JavaScript and Rust testing is supported.
Utilizing blast.config.js
it provides a possibility for deploying and interacting with them on a specified network (local, test or public).
By using this tool you can also spin up a local Cudos node
and interact with it.
- Installation
- Help and version
- Initializing a project
- Compiling smart contracts
- Running Rust tests
- Testing contracts with JavaScript
- Interacting with a Cudos node
- Deploying smart contracts, interacting with them and running custom script files
- Network
- Managing accounts
- Development
Make sure you have Node.js installed. Docker is also required.
Prerequisite | Minimum version | Recommended version |
---|---|---|
Node.js | 12.5.0 | 16.10.0 |
npm | 6.9.0 | 7.24.0 |
Docker engine | 19.03.13 | 20.10.12 |
Docker compose | 1.27.4 | 1.29.2 |
For Windows users we recommend using Windows Subsystem for Linux (WSL). To avoid permission issues with
WSL
, you may have to changenpm
default directory.
Install Cudos Blast package:
npm install cudos-blast
Install Cudos Blast globally:
npm install -g cudos-blast
Run --help
or help
on any blast
command to show all available subcommands, parameters and additional information.
blast --help
blast help
blast node --help
blast node start help
You can display cudos-blast
version number using --version
.
blast --version
To scaffold a sample project navigate to empty directory and run
blast init
You can also specify the full directory of the project using optional parameter --dir
or -d
blast init --dir /Your/Location/Here
The project is now ready to work with the Cudos blockchain. It contains sample smart contracts and scripts to deploy or interact.
Make sure to initialize a new project in a directory other than the local repository folder, or else
cudos-blast
will break and the repository have to be cloned again.
Also, allblast
commands are designed to be executed from the project root directory.
To compile all smart contracts run
blast compile
The contracts have to be in {project_root}/contracts/
folder. Cudos Blast comes with sample contracts you can use. All contracts are compiled in alphabetical order and as a Rust workspace. If you want to add more folders to compile, all you have to do is edit the base {project_root}/Cargo.toml
file and add your folder under members
. The compilation is done using rust-optimizer and the artifacts in {project_root}/artifacts/
folder are optimized for deployment.
Rust tests are organized by the Rust convention for writing tests. You can check them in their corresponding contracts in {project_root}/contracts/{contract_name}/
. To run smart contracts' unit tests:
blast unittest
To run unit tests without printing cargo log messages use --quiet
or -q
blast unittest -q
Cudos Blast uses Jest framework for testing. Test files must be in {project_root}/tests/
folder. You can use the provided sample test as a template or make one or more tests of your own. You must have a local node running in order to deploy or interact with the smart contracts in your tests.
describe('alpha contract', () => {
const MSG_INIT = { count: 13 }
const MSG_INCREMENT = { increment: {} }
const MSG_RESET = { reset: { count: 1 } }
const QUERY_GET_COUNT = { get_count: {} }
let alice, bob, contract
// deploying alpha contract once before test cases
beforeAll(async () => {
// function 'getSigners' is available in global context
[alice, bob] = await getSigners()
contract = await getContractFactory('alpha')
await contract.deploy(MSG_INIT, bob)
})
// positive test case
test('increment count', async () => {
await contract.execute(MSG_INCREMENT, alice)
return expect(contract.query(QUERY_GET_COUNT))
.resolves.toEqual({ count: 14 })
})
// ...
// negative test case
test('reset count from user throws unauthorized', () => {
return expect(contract.execute(MSG_RESET, alice))
.rejects.toThrow('Unauthorized')
})
})
Run all test files with
blast test
You can interact with a local Cudos node
with blast node
command.
To start a fresh local Cudos node run
blast node start
or you can leave the current terminal window free by running the local node in background. To do this use --daemon
or -d
.
blast node start -d
To see how to manage local node accounts go here.
To stop a running node run
blast node stop
To check whether a Cudos node is online or offline run
blast node status
You are able to check the status of a non-local Cudos node by setting its URL in blast.config.js
under networkUrl:
.
You can use the supplied {project_root}/scripts/deploy.js
to deploy a sample smart contract.
async function main () {
// functions such as 'getSigners' and 'getContractFactory' are available in global context
const [alice, bob] = await getSigners()
// get contract object of 'alpha' contract in 'contracts/alpha'
const contract = await getContractFactory('alpha')
// define instantiate message for the contract
const MSG_INIT = { count: 13 }
// deploying the contract with bob as a signer
const contractAddress = await contract.deploy(MSG_INIT, bob)
// printing contract address so it can be copied and used in other scripts such as interact.js
console.log(`${contractAddress}`)
}
// ...
Run the contract with:
blast run scripts/deploy.js
When the contract is deployed, its address will be printed. Then you can edit {project_root}/scripts/interact.js
with the new address
async function main() {
const [alice, bob] = await getSigners()
// replace the address with the new one from your deployed smart contract
const contract = await getContractFromAddress('cudos1uul3yzm2lgskp3dxpj0zg558hppxk6pt8t00qe', bob)
// ...
and run the script to interact with the deployed smart contract.
blast run scripts/interact.js
You are free to use these files as templates or create your own custom .js
scripts. You can specify your own script file path.
blast run scripts/myCustomScript.js
blast run newFolder/anotherScripts/myCustomScript.js
Function | Descripton | Sample usage |
---|---|---|
getSigners() | set assigned objects as signers in order as in {project_root}/accounts.json |
const [alice, bob] = await getSigners() |
getContractFactory(contractName) | get a contract object from contract named contractName and sign it witn the first account in {project_root}/accounts.json |
const contract = await getContractFactory('alpha') |
getContractFromAddress(contractAddress, signer = null) | get a contract object by address. Default contract signer can be set. If omitted, signer becomes first account in {project_root}/accounts.json |
const contract = await getContractFromAddress('cudos1uul3yzm2lgskp3dxpj0zg558hppxk6pt8t00qe') |
You can run your scripts on a different node by setting its URL in blast.config.js
under networkUrl
. You can connect to the default local node as well as a public one or you can use your own Cudos node.
You can set a custom address prefix under addressPrefix
in blast.config.js
. Default is cudos
.
Here are public Cudos nodes you can use to connect to Cudos network:
Chain ID | URL |
---|---|
cudos-testnet-public-2 | https://sentry1.gcp-uscentral1.cudos.org:26657 |
Chain ID | URL |
---|---|
By default local Cudos node starts with 10 predefined accounts funded with acudos
. You can set how many additional random accounts to load when starting a local node in blast.config.js
under additionalAccounts
. In customAccountBalances
you can set the amount of tokens that these additional accounts will be funded with. Predefined and additionally generated accounts are written in {project_root}/accounts.json
. Another way to manage custom accounts is through blast keys
command.
You can put your private accounts in {project_root}/private-accounts.json
and add the file to .gitignore
to prevent exposing them.
To list all accounts in the local node key storage run
blast keys ls
To add a new account named myAccount1
to the local node key storage run
blast keys add myAccount1
After adding the new account, it is automatically funded with acudos
tokens from the default local node faucet.
To remove an account from the node key storage run
blast keys rm myAccount1
You can skip the delete confirmation with --force
or -f
blast keys rm myAccount1 -f
You can fund an account with additional tokens. To specify tokens amount use --tokens
or -t
.
blast keys fund myAccount1 --tokens 1000000
The tokens are funded from the default local node faucet in acudos
.
You can run tests that ensure blast
commands are working correctly.
npm test
You can also specify the test file name to run a single test. Test files are located in {repo_root}/packages/blast-tests/integration-tests/tests/
npm test init.test.sh
The following sample test contains a detailed explanation of the commands and syntax. It is recommended to execute npm test
first to get a general idea of the behavior. New tests should be placed in {repo_root}/packages/blast-tests/integration-tests/tests/
folder. Lets take a look at init.test.sh
. It covers blast init
command which should initialize a project inside the current directory. The tests follow the classic Arrange-Act-Assert pattern.
# our files start with "#!/bin/bash", which tells your terminal it should use bash to execute the file
#!/bin/bash
# "source" lets you use the contents of a file
source ./packages/blast-tests/integration-tests/vars.sh
# 'echo' prints out the string
# -n flag tells your terminal to stay on the same line after printing out the message
echo -n 'blast init...'
# ARRANGE
# "mkdir" creates a folder at the path specified in INIT_FOLDER variable
# "cd" navigates to the specified directory
# "&&" lets you execute the command that follows it only if the first command is successful
mkdir $INIT_FOLDER && cd $INIT_FOLDER
# ACT
# "&>" hides the output of the command
blast init &> /dev/null
# ASSERT
# "ls -R" lists directory content
# `` executes the command placed inside and provides its output
# we compare the output with the expected folder structure defined in TEMPLATE_FILES
if [[ ! `ls` == $TEMPLATE_FILES || ! `ls scripts` == $TEMPLATE_SCRIPTS_FILES ]]; then
# if the output doesn't match we print a fail message
# FAILED variable defines a red colored message
# -e flag escapes special characters, we need it in order to have colored messages
# 1>&2 redirects the output to stderr
echo -e "$FAILED\nGenerated folder is invalid!" 1>&2
# we are defining a variable with status 1
# in bash status code 1 means the script was not successful
exit_status=1
else
# otherwise we print pass message
echo -e $PASSED
fi
# we are cleaning up the files generated by the test
# "rm -r" removes the specified directory
rm -r ../$INIT_FOLDER &> /dev/null
# EXIT the script
# if the test fails and exit_status is assigned, the program will exit with status 1
# otherwise the exit_status will be undefined and the program will exit without a status, which means it was successful
exit $exit_status