# Overview
Polar is development framework for building secret contracts. The aim of the project is to make Secret contracts development process simple, efficient and scalable. User can focus on logic of secret contract and not much about further steps in development. It facilitates features such as initiating project repo from contract templates, easy compilation of contracts, deployment and contract testing framework.
# Installation
Polar can be installed using npm
or yarn
using below commands:
- Using Yarn:
yarn global add secret-polar
- Using NPM:
npm install -g secret-polar
Polar requires a local rust environment available to be able to work. To install a rust environment, use command polar install
.
# Quick Start
This guide will explore the basics of creating a simple Polar project.
Polar allows you to compile your Rust code, generate schema for it, run your scripts, tests and deploy to network, interact with contract instance on the network.
To create your Polar project, run polar init <project-name>
:
$ polar init yellow
★ Welcome to polar v0.9.5
Initializing new project in /home/uditgulati/yellow.
★ Project created ★
You need to install these dependencies to run the sample project:
npm install --save-dev chai
Success! Created project at /home/uditgulati/yellow.
Begin by typing:
cd yellow
npx polar help
npx polar compile
The generated directory will have the following initial structure:
.
├── contracts
│ ├── Cargo.lock
│ ├── Cargo.toml
│ ├── examples
│ │ └── schema.rs
│ ├── src
│ │ ├── contract.rs
│ │ ├── lib.rs
│ │ ├── msg.rs
│ │ └── state.rs
│ └── tests
│ └── integration.rs
├── package.json
├── packages
│ └── cargo_common
│ ├── Cargo.lock
│ ├── Cargo.toml
│ └── src
│ ├── balances.rs
│ ├── cashmap.rs
│ ├── contract.rs
│ ├── lib.rs
│ ├── tokens.rs
│ └── voting.rs
├── polar.config.js
├── README.md
├── scripts
│ └── sample-script.js
└── test
└── sample-test.js
9 directories, 22 files
The contracts/
directory has all the rust files for the contract logic. scripts/
directory can contain .js
and .ts
scripts that user can write according to the use case, a sample script has been added to give some understanding of how a user script should look like. test/
directory can contain .js
and .ts
scripts to run tests for the deployed contracts.
# Listing tasks
To see the possible tasks (commands) that are available, run polar
in your project's folder:
$ polar
polar version 0.9.5
Usage: polar [GLOBAL OPTIONS] <TASK> [TASK OPTIONS]
GLOBAL OPTIONS:
--config Path to POLAR config file.
-h, --help Shows this message, or a task's help if its name is provided
--network The network to connect to. (default: "default")
--show-stack-traces Show stack traces.
--verbose Enables verbose logging
-v, --version Shows version and exit.
AVAILABLE TASKS:
clean Clears the cache and deletes specified artifacts files
compile Compile all secret contracts
help Prints this message
init Initializes a new project in the given directory
install Setup rust compiler
node-info Prints node info and status
repl Opens polar console
run Runs a user-defined script after compiling the project
test Runs a user-defined test script after compiling the project
To get help for a specific task run: polar help [task]
This is the list of built-in tasks. This is your starting point to find out what tasks are available to run.
If you take a look at the polar.config.js
file, you will find :
const accounts = [
{
name: 'account_0',
address: 'secret1l0g5czqw7vjvd20ezlk4x7ndgyn0rx5aumr8gk',
mnemonic: 'snack cable erode art lift better october drill hospital clown erase address'
},
{
name: 'account_1',
address: 'secret1ddfphwwzqtkp8uhcsc53xdu24y9gks2kug45zv',
mnemonic: 'sorry object nation also century glove small tired parrot avocado pulp purchase'
}
];
module.exports = {
networks: {
default: {
endpoint: 'http://localhost:1337/'
},
development: {
endpoint: 'tcp://0.0.0.0:26656',
nodeId: '115aa0a629f5d70dd1d464bc7e42799e00f4edae',
chainId: 'enigma-pub-testnet-3',
keyringBackend: 'test',
types: {}
},
// Supernova Testnet
testnet: {
endpoint: 'http://bootstrap.supernova.enigma.co:1317',
chainId: 'supernova-2',
trustNode: true,
keyringBackend: 'test',
accounts: accounts,
types: {},
fees: {
upload: {
amount: [{ amount: "500000", denom: "uscrt" }],
gas: "2000000",
},
init: {
amount: [{ amount: "125000", denom: "uscrt" }],
gas: "500000",
},
}
}
},
mocha: {
timeout: 60000
},
rust: {
version: "1.55.0"
}
};
Note that the accounts mentioned above are just a sample, don't use them in mainnet as it can lead to capital loss.
# Compiling contracts
To compile the contracts, use command polar compile
. This will compile all the contracts in the project. To compile only one contracts or a subset of all contracts in the project, use command polar compile <contract-source-dir>
. To skip schema generation while compiling use polar compile --skip-schema
.
$ polar compile
Compiling contract in directory: contracts
Compiling proc-macro2 v1.0.28
Compiling unicode-xid v0.2.2
Compiling syn v1.0.74
Compiling serde_derive v1.0.127
Compiling serde v1.0.127
Compiling ryu v1.0.5
Compiling serde_json v1.0.66
Compiling schemars v0.7.6
Compiling doc-comment v0.3.3
Compiling itoa v0.4.7
Compiling base64 v0.11.0
Compiling quote v1.0.9
Compiling serde_derive_internals v0.25.0
Compiling schemars_derive v0.7.6
Compiling snafu-derive v0.6.10
Compiling snafu v0.6.10
Compiling serde-json-wasm v0.2.3
Compiling cosmwasm-std v0.10.0 (https://github.com/enigmampc/SecretNetwork?tag=v1.0.4-debug-print#004c6bca)
Compiling cosmwasm-schema v0.10.0 (https://github.com/enigmampc/SecretNetwork?tag=v1.0.4-debug-print#004c6bca)
Compiling cosmwasm-storage v0.10.0 (https://github.com/enigmampc/SecretNetwork?tag=v1.0.4-debug-print#004c6bca)
Compiling sample-project v0.1.0 (/home/uditgulati/yellow/contracts)
Finished release [optimized] target(s) in 41.23s
Creating schema for contract in directory: contracts
Compiling proc-macro2 v1.0.28
Compiling unicode-xid v0.2.2
Compiling syn v1.0.74
Compiling serde_derive v1.0.127
Compiling serde v1.0.127
Compiling ryu v1.0.5
Compiling serde_json v1.0.66
Compiling schemars v0.7.6
Compiling doc-comment v0.3.3
Compiling itoa v0.4.7
Compiling base64 v0.11.0
Compiling quote v1.0.9
Compiling serde_derive_internals v0.25.0
Compiling schemars_derive v0.7.6
Compiling snafu-derive v0.6.10
Compiling snafu v0.6.10
Compiling serde-json-wasm v0.2.3
Compiling cosmwasm-std v0.10.0 (https://github.com/enigmampc/SecretNetwork?tag=v1.0.4-debug-print#004c6bca)
Compiling cosmwasm-schema v0.10.0 (https://github.com/enigmampc/SecretNetwork?tag=v1.0.4-debug-print#004c6bca)
Compiling cosmwasm-storage v0.10.0 (https://github.com/enigmampc/SecretNetwork?tag=v1.0.4-debug-print#004c6bca)
Compiling sample-project v0.1.0 (/home/uditgulati/yellow/contracts)
Finished dev [unoptimized + debuginfo] target(s) in 22.21s
Running `target/debug/examples/schema`
Created /home/uditgulati/yellow/contracts/schema/init_msg.json
Created /home/uditgulati/yellow/contracts/schema/handle_msg.json
Created /home/uditgulati/yellow/contracts/schema/query_msg.json
Created /home/uditgulati/yellow/contracts/schema/state.json
Created /home/uditgulati/yellow/contracts/schema/count_response.json
Copying file sample_project.wasm from contracts/target/wasm32-unknown-unknown/release/ to artifacts/contracts
Copying file count_response.json from contracts/schema to artifacts/schema/sample_project
Copying file handle_msg.json from contracts/schema to artifacts/schema/sample_project
Copying file init_msg.json from contracts/schema to artifacts/schema/sample_project
Copying file query_msg.json from contracts/schema to artifacts/schema/sample_project
Copying file state.json from contracts/schema to artifacts/schema/sample_project
This command will generate compiled .wasm
files in artifacts/contracts/
dir and schema .json
files in artifacts/schema/
dir.
# Running user scripts
User scripts are a way to define the flow of interacting with contracts on some network in form of a script. These scripts can be used to deploy a contract, query/transact with the contract.
A sample script scripts/sample-script.js
is available in the boilerplate. Contents of the script is as follows:
const { Contract, getAccountByName } = require("secret-polar");
async function run () {
const contract_owner = getAccountByName("account_0");
const contract = new Contract("sample-project");
await contract.parseSchema();
const deploy_response = await contract.deploy(
contract_owner,
{ // custom fees
amount: [{ amount: "750000", denom: "uscrt" }],
gas: "3000000",
}
);
console.log(deploy_response);
const contract_info = await contract.instantiate({"count": 102}, "deploy test", contract_owner);
console.log(contract_info);
const inc_response = await contract.tx.increment({account: contract_owner});
console.log(inc_response);
const response = await contract.query.get_count();
console.log(response);
const transferAmount = [{"denom": "uscrt", "amount": "15000000"}] // 15 SCRT
const customFees = { // custom fees
amount: [{ amount: "750000", denom: "uscrt" }],
gas: "3000000",
}
const ex_response = await contract.tx.increment(
{account: contract_owner, transferAmount: transferAmount}
);
// const ex_response = await contract.tx.increment(
// {account: contract_owner, transferAmount: transferAmount, customFees: customFees}
// );
console.log(ex_response);
}
module.exports = { default: run };
The script above deploys, inits contract sample-project
using account account_0
. It then increments the count value using transaction tx.increment()
and finally queries count using query query.get_count()
.
For the above script to be able to run, an account with name account_0
must be present in polar.config.js
and contract artifacts (compiled .wasm
and schema .json
files) in artifacts/
dir must be present for contract sample-project
.
# Running test scripts
Test scripts are used to test the contract after deploying it to the network and asserting on the interactions with the contract instance.
A sample test script test/sample-test.js
is available in the boilerplate. Contents of the script is as follows:
const { expect, use } = require("chai");
const { Contract, getAccountByName, polarChai } = require("secret-polar");
use(polarChai);
describe("sample_project", () => {
async function setup() {
const contract_owner = getAccountByName("account_1");
const other = getAccountByName("account_0");
const contract = new Contract("sample-project");
await contract.parseSchema();
return { contract_owner, other, contract };
}
it("deploy and init", async () => {
const { contract_owner, other, contract } = await setup();
const deploy_response = await contract.deploy(contract_owner);
const contract_info = await contract.instantiate({"count": 102}, "deploy test", contract_owner);
await expect(contract.query.get_count()).to.respondWith({ 'count': 102 });
});
it("unauthorized reset", async () => {
const { contract_owner, other, contract } = await setup();
const deploy_response = await contract.deploy(contract_owner);
const contract_info = await contract.instantiate({"count": 102}, "deploy test", contract_owner);
await expect(contract.tx.reset({account: other}, 100)).to.be.revertedWith("unauthorized");
await expect(contract.query.get_count()).not.to.respondWith({ 'count': 1000 });
});
it("increment", async () => {
const { contract_owner, other, contract } = await setup();
const deploy_response = await contract.deploy(contract_owner);
const contract_info = await contract.instantiate({"count": 102}, "deploy test", contract_owner);
const ex_response = await contract.tx.increment({account: contract_owner});
await expect(contract.query.get_count()).to.respondWith({ 'count': 103 });
});
});
Detailed overview of testing is given the Guides section.
# Using REPL
REPL (read–eval–print loop) gives the a console to do real time interactions with the network. Open the REPL using polar repl --network <network-name>
. Sample REPL interaction shown below as follows:
$ polar repl --network testnet
★★★ Welcome to polar REPL ★★★
Try typing: config
polar> config
{
name: 'testnet',
config: {
accounts: [ [Object], [Object], [Object], [Object] ],
endpoint: 'http://bootstrap.supernova.enigma.co:1317',
chainId: 'supernova-2',
trustNode: true,
keyringBackend: 'test',
types: {}
}
}
polar> const contract_owner = polar.getAccountByName("account_0");
Creating client for network: testnet
undefined
polar> const contract = new polar.Contract('sample-project');
Creating client for network: testnet
undefined
polar> const deploy_response = await contract.deploy(contract_owner);
Creating compressed .wasm file for sample_project...
When REPL is opened, polar
library is already imported, use polar.
to access classes and functions from the library. Polar Runtime Environment can be access using env
variable and polar.config.js
data can be accessed using config
variable.
# Get node information
Node information can be fetched using polar node-info --network <network-name>
as follows:
$ polar node-info --network testnet
Network: testnet
ChainId: supernova-2
Block height: 752832
Node Info: {
node_info: {
protocol_version: { p2p: '8', block: '11', app: '0' },
id: 'ab6394e953e0b570bb1deeb5a8b387aa0dc6188a',
listen_addr: 'tcp://0.0.0.0:26656',
network: 'supernova-2',
version: '0.34.12',
channels: '40202122233038606100',
moniker: 'sg-testnet-0',
other: { tx_index: 'on', rpc_address: 'tcp://0.0.0.0:26657' }
},
application_version: {
name: 'SecretNetwork',
server_name: 'secretd',
version: '1.2.0-beta1-79-g660cb1d9',
commit: '',
build_tags: 'netgo ledger hw production',
go: 'go version go1.15.5 linux/amd64',
build_deps: [
'filippo.io/edwards25519@v1.0.0-beta.2',
'github.com/99designs/keyring@v1.1.6',
...
'gopkg.in/ini.v1@v1.62.0',
'gopkg.in/yaml.v2@v2.4.0',
'gopkg.in/yaml.v3@v3.0.0-20210107192922-496545a6307b',
'nhooyr.io/websocket@v1.8.6'
],
cosmos_sdk_version: 'v0.44.1'
}
}
# Cleanup artifacts
To clear artifacts data, use polar clean
and to clean artifacts for only one contract, use polar clean <contract-name>
.