Docker Quickstart
The goal of this document is to get a development environment setup in as little time as possible.
Prerequisites
- Docker for Windows
- Docker for Linux
- Docker for Mac
- Git for Windows / Linux
- Ensure that you install Git Bash
Make sure docker engine is up on your system:
docker --version
Docker version 20.10.21, build baeda1f
Obtaining the Docker Image
Pull the docker image down from quay.io
docker pull quay.io/ultra.io/3rdparty-devtools:latest
The above image tag may be out of date. Visit our official quay.io repository to get the latest image tag.
Starting / Stopping Image
Open your terminal (on Windows use Git Bash
) and use the following command to create development tools container
docker run -dit --name ultra -p 8888:8888 -p 9876:9876 -v ~/ultra_workdir:/opt/ultra_workdir --name ultra quay.io/ultra.io/3rdparty-devtools:latest
WARNING
The above command will utilize ports 8888 and 9876. If those ports are occupied the docker will fail to create the container. You will have an option to change which ports will be used on your host machine later.
After you created the container you realistically won't need to create it again. Existing container will be accessible under the name of ultra
.
To stop the container without destroying it you can use the following command
docker stop ultra
Accessing the Image
After you created the container you will be able to attach to it using the following command. It will also start the container if it is currently stopped (for Windows keep in mind to use Git Bash
still).
docker start ultra && docker attach ultra
Accessing Docker Volume
The docker container has a shared directory located somewhere in your operating system.
Windows:
C:\\Users\\Username\\ultra_workdir
Linux:
~/ultra_workdir
Mac OS:
~/ultra_workdir
Docker Container:
/opt/ultra_workdir
Creating a Smart Contract
Create a directory in the ultra_workdir
directory called contracts
with a file inside called hello.cpp
.
- You can do it either on your host machine (Windows/Linux) or inside the docker image using your editor of choice (
nano
is preinstalled, other editors require manual installation) - You also have an option to use VSCode Environment
#include <eosio/eosio.hpp>
using namespace eosio;
class [[eosio::contract]] hello : public eosio::contract {
public:
using contract::contract;
[[eosio::action]]
void world( eosio::name name ) {
print("Hi, ", name);
}
};
Compiling a Smart Contract
Inside of the docker image (using the terminal that is attached to the ultra
container) navigate into the contracts
directory, and run the following command.
mkdir -p /opt/ultra_workdir/contracts && cd /opt/ultra_workdir/contracts
cdt-cpp -abigen -o hello.wasm hello.cpp
Writing your first test
Setup directory Structure
This directory structure should be reflected inside of the docker image.
/opt
/ultra_workdir
/contracts
|- hello.wasm
|- hello.abi
|- hello.cpp
/tests
|- hello.ultra_test.js
Write Tests
Test files are written in JavaScript and must have ultra_test.js
suffix (e.g. hello.ultra_test.js
).
Now try adding the following code snippet to hello.ultra_test.js
. You should place the file ultra_workdir/tests
directory like the file tree in the section above suggests
module.exports = class test {
constructor() {}
// Deploys ultra system contracts to the nodeos instance
requiresSystemContracts() {
return true;
}
// What account to create, and what contract to deploy on it
importContracts() {
return [{ account: 'smrtcntract1', path: '../contracts', contract: 'hello' }];
}
// Created after importing contracts
requiredAccounts() {
return ['account1', 'account2', 'account3', 'account4'];
}
tests({ assert, endpoint, cleos, rpc, api, ecc, keychain }) {
assert(true, "This will never trigger because it is true.");
// Should always return an object of async tests
return {
'should execute transaction': async () => {
const result = await api.transact({
actions: [{
account: 'smrtcntract1', // The smart contract account
name: 'world', // Name of the action
authorization: [
// actor -> The account performing the action
// permission -> Permission required for that account. Usually 'active'.
{ actor: 'account1', permission: 'active' },
],
// This is an exact match of the data to send to the 'action'.
// In the example below the 'hello' action will take a name parameter.
data: {
name: 'account1',
},
}],
},{ blocksBehind: 3, expireSeconds: 3600 });
},
};
}
};
Running Tests
Inside of the docker image run the following commands.
cd /opt/ultra_workdir
ultratest
If you did everything properly you should see the test line stating All Tests Passed
INFO
If the test run fails or gets stuck you can kill it using the ^C (Ctrl + C) termination command.