EOS Local provides a really quick way to setup an EOS local network.
EOS local exposes all APIs provided by EOS Costa Rica and other BPs on the TestNet and MainNet.
It allows you to develop your application running the same APIs services you will use in production in your computer.
It has a companion project that serves as a starter boilerplate your dApp. https://github.com/eoscostarica/eos-dapp-boilerplate
EOS Local is a community-driven project led by EOS Costa Rica. We welcome contributions of all sorts. There are many ways to help, from reporting issues, proposing features, improving documentation, contributing code, design/ux proposals, etc.
Table of Contents generated with DocToc
- Architecture
- Technical Specs
- Getting started
- Aliases
- Chain Initialization
- Commands
- Directory Structure
- Services
- Using Cleos on EOS Local
- Testing accounts
- Contract Development
- Frequently Asked Questions
- Contributing
- About EOS Costa Rica
- License
- Contributors
Every service/process runs on a separate container.
You can develop multiple dApps using the same EOS Local Network, sharing testing users and machine resources.
- Virtualized local network with docker.
- Microservices architecture.
- Out-of-box services:
- EOSIO Nodeos deamon.
- HTTP RPC API with history db.
- Keosd wallet service.
- GraphQL API for complex data queries.
- Ngnix proxy.
- Services accessible through virtual host names both from host machine and within the docker network.
- Handy scripts for interacting with the local EOS services.
Important Disclaimer: This is a Work in Progress
Basic knowledge about Docker, Docker Compose, EOS and NodeJS is required.
- Video tutorial Docker Containers | Learn Docker Basics in 30 Mins
Global Dependencies
- Docker https://docs.docker.com/install/.
At least 10GB RAM (Docker -> Preferences -> Advanced -> Memory -> 10GB or above)
It is useful to have aliases for the docker
, docker-compose
and cleos
commands since they are used.
alias cleos='docker exec -i eoslocal_eosio cleos -u http://eosio:8888 --wallet-url http://wallet:8901'
alias eosio='docker exec -i eoslocal_eosio bash'
alias unlock_eoslocal='docker exec -i eoslocal_eosio ./scripts/unlock.sh'
alias dk='docker'
alias dc='docker-compose'
Execute make setup
for:
- Docker volumes creation.
- Chain initialization.
- Testing accounts creation.
Run the following command to verify afterwards
β docker network ls
NETWORK ID NAME DRIVER SCOPE
f72523603a2d bridge bridge local
113510307ce3 eoslocal bridge local
886afbf5db1a host host local
53d0d3f8d910 none null local
β docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------------------------------------------
eoslocal_eosio /bin/sh -c /wait && /opt/a ... Up 0.0.0.0:8888->8888/tcp, 0.0.0.0:9830->9876/tcp
eoslocal_ipfs /sbin/tini -- /usr/local/b ... Up 0.0.0.0:4001->4001/tcp, 0.0.0.0:5001->5001/tcp, 0.0.0.0:8081->8080/tcp, 8081/tcp
eoslocal_mongo docker-entrypoint.sh mongod Up 0.0.0.0:27017->27017/tcp
eoslocal_nginx /app/docker-entrypoint.sh ... Up 0.0.0.0:80->80/tcp
eoslocal_wallet /opt/eosio/bin/keosd --wal ... Up 0.0.0.0:8901->8901/tcp
β cleos wallet keys
[
"EOS5VdFvRRTtVQAPUJZQCYvpBekYV4nc1cFe7og9aYPTBMXZ38Koy",
"EOS5k6Jht1epqZ2mnRLFVDXDTosaTneR6xFhvenVLiFfz5Ue125dL",
"EOS6Jv4RykLZQQopCBdBHSwaGoMyFxyaxFNXimqFPdEXNWqgWbG1a",
"EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"EOS6TVQ6EmphCWavUuYiZMmDNYMRgbb96wgqWDncjrkvFPcpokgdD",
"EOS7CB47VMLWp49QhajE3uTuHuf9qoSeR6scUHMKGCD6LXYufRUDc",
"EOS84BLRbGbFahNJEpnnJHYCoW9QPbQEk2iHsHGGS6qcVUq9HhutG"
]
β cleos get info
{
"server_version": "59626f1e",
"chain_id": "cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f",
"head_block_num": 675,
"last_irreversible_block_num": 674,
"last_irreversible_block_id": "000002a2a6228780c7facc225ff53609ed072d57e7b6abb9a0ba92ab63b5d160",
"head_block_id": "000002a3b39afb5f16ac7a59f747e21ef6bcc060a856237016af48ad677c7f52",
"head_block_time": "2018-12-07T18:03:08.500",
"head_block_producer": "eosio",
"virtual_block_cpu_limit": 392064,
"virtual_block_net_limit": 2057598,
"block_cpu_limit": 199900,
"block_net_limit": 1048576,
"server_version_string": "v1.4.4"
}
β curl http://eosio.eoslocal.io/v1/chain/get_info | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 566 100 566 0 0 72554 0 --:--:-- --:--:-- --:--:-- 80857
{
"server_version": "59626f1e",
"chain_id": "cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f",
"head_block_num": 970,
"last_irreversible_block_num": 969,
"last_irreversible_block_id": "000003c9846265cddc9133024d9bd2adb1531378da8172318fe2a142b843c02a",
"head_block_id": "000003ca6e3448f540c36f70a176f5cc4769514f8018b07fbbf32b27f532fb6b",
"head_block_time": "2018-12-07T18:05:36.000",
"head_block_producer": "eosio",
"virtual_block_cpu_limit": 526492,
"virtual_block_net_limit": 2763849,
"block_cpu_limit": 199900,
"block_net_limit": 1048576,
"server_version_string": "v1.4.4"
}
β curl http://localhost:8888/v1/chain/get_info | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 568 100 568 0 0 78172 0 --:--:-- --:--:-- --:--:-- 81142
{
"server_version": "59626f1e",
"chain_id": "cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f",
"head_block_num": 1167,
"last_irreversible_block_num": 1166,
"last_irreversible_block_id": "0000048e64aedcb65234739ac489fe81f7b7d68e5c7ccb4c28bd8083b0e33213",
"head_block_id": "0000048ff0dcc3c4e65ec0de14f9d4ae9c8823bddad2bb19f73b0245514b138c",
"head_block_time": "2018-12-07T18:07:14.500",
"head_block_producer": "eosio",
"virtual_block_cpu_limit": 641088,
"virtual_block_net_limit": 3365893,
"block_cpu_limit": 199900,
"block_net_limit": 1048576,
"server_version_string": "v1.4.4"
}
make setup
run chain initialization.make flush
stops all services and removes all data.make fresh
stops all services and removes all data and run chain initialization again.docker-compose start
starts all containers.docker-compose exec [service_name] [bash | sh]
open bash or sh in a container.docker-compose stop
stops all containers.docker-compose down
stops and removes all containers.docker-compose restart
restarts all services.
.
βββ docs/ .............................................. documentation files and media
βββ services/ .......................................... microservices
| βββ graphql/ ....................................... graphql service
| |
| βββ history-api/ ................................... express/swagger history api
| |
| βββ ngnix/ ......................................... nginx service for routing
| |
| βββ mongo/ ......................................... mongodb data
| |
| βββ eosio/ ......................................... nodeos service
| βββ utils/ ..................................... service utilities
| βββ config/ .................................... eosio node configuration
| βββ scripts/ ................................... eosio scripts
| βββ contracts/ ................................. smart contracts
| βββ Dockerfile ................................. service image specification
|
βββ docker-compose.yaml ................................ docker compose for local dev
βββ contributing.md .................................... contributing guidelines
βββ license ............................................ project license
βββ makefile ........................................... make tasks manifest
βββ readme.md .......................................... project documentation
βββ .editorconfig ...................................... common text editor configs
The eosio node acts as block producer and history api node, this configuration is just for development. It's not recommended to for production. In production it's recommended to devide nodes responsibilities, you may want to configure a dedicate api node that stores you contracts data only or use one of the network block producers node as a service.
The docker image source code can be found at https://github.com/EOSIO/eos/blob/master/Docker/Dockerfile.
Learn more at https://developers.eos.io/eosio-nodeos/docs/
https://developers.eos.io/eosio-nodeos/reference
The eos rpc api is accesible through http://localhost:8888
MongoDB instance for to story hisotry. The eosio::mongo_db_plugin provides archiving of blockchain data into a MongoDB.
https://developers.eos.io/eosio-nodeos/docs/mongo_db_plugin
https://github.com/EOS-BP-Developers/eosio-graphql
https://github.com/CryptoLions/EOS-mongo-history-API
Nginx reverse proxy that allows accesing the services directly on the host machine the wildcard *.esolocal.io
that points to 127.0.0.1
, therefore as long as you can hit the dns server it will redirect all requests to your machine and nginx-proxy does the internal docker network routing to the right service.
Run ping {whatever}.eoslocal.io
to verify.
Optionally you can avoid the round trip and work offline maintaining virtual hosts by manually adding your dns to your hosts
file. https://en.wikipedia.org/wiki/Hosts_(file)
See the docker-compose.yml
for available virtual hosts for easier access without port shenanigans.
Cleos is a command line tool that interfaces with the API exposed by nodeos. In order to use cleos you will need to have the endpoint (IP address and port number) to a nodeos instance and also configure nodeos to load the 'eosio::chain_api_plugin'. cleos
contains documentation for all of its commands.
More at https://developers.eos.io/eosio-nodeos/docs/cleos-overview
EOS Local comes with 2 EOS nodes running in separate docker containers, you can interact with these nodes using cleos
in several ways:
You can execute commands on any container from you host machine using the docker exec
command.
Eg:
docker exec -i eoslocal_eosio cleos --url http://localhost:8888/ get info
We recomend using declaring alias on your shell configuration Eg (.bashrc or .zshrc)
alias cleos='docker exec -i eoslocal_eosio cleos -u http://eosio:8888 --wallet-url http://wallet:8901'
Notice it uses docker directly thru the container_name
insted of docker compose, this allows you to invoke it from any path in your computer, you don't have to be a the root dir of eoslocal.
After you have added those lines to your config you can open a new terminal window and run cleos --help
to test.
You can also login into the containers using the following docker-compose command
docker exec -it eoslocal_eosio bash
That will log you in and you will be able to execute cleos directly within the ubuntu server. Eg.
β docker exec -it eoslocal_eosio bash
root@b39ffe3c43c0:/opt/eosio/bin# cleos get info
{
"server_version": "f9a3d023",
"chain_id": "cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f",
"head_block_num": 4900,
"last_irreversible_block_num": 4899,
"last_irreversible_block_id": "000013232f7193f86a4edc59b6aa2b2a8ccd6c2060d24eb0e5c497beb97b76e5",
"head_block_id": "000013249772e5af12592d7d3eeb401276c09f781e3ed76faa75a49f53b481bd",
"head_block_time": "2018-11-05T20:27:45.000",
"head_block_producer": "eosio",
"virtual_block_cpu_limit": 26829884,
"virtual_block_net_limit": 140951435,
"block_cpu_limit": 199900,
"block_net_limit": 1048576,
"server_version_string": "v1.4.1"
}
The following accounts created automatically
account: eoslocalusra
private key: 5K4MHQN7sPdEURaxzjCnbynUwkEKRJzs8zVUf24ofaFiZNK815J
public key: EOS5k6Jht1epqZ2mnRLFVDXDTosaTneR6xFhvenVLiFfz5Ue125dL
account: eoslocalusrb
private key: 5JHCQDi7jsbnQnWdyxteRjT2DdNZHePiEG1DTaPQQDDP2X6aor6
public key: EOS6TVQ6EmphCWavUuYiZMmDNYMRgbb96wgqWDncjrkvFPcpokgdD
account: eoslocalusrc
private key: 5JXCt633pzYaUysn7exDHeVXwhwMjX2L231b37CdsSb7y1uvDH7
public key: EOS7CB47VMLWp49QhajE3uTuHuf9qoSeR6scUHMKGCD6LXYufRUDc
account: eoslocalusrd
private key: 5JdRgeRBriBDdxb3r76sLJaQmwGgXkMU8GReTAmy8xYppMSAAoZ
USER_D_PUBKEY="EOS6Jv4RykLZQQopCBdBHSwaGoMyFxyaxFNXimqFPdEXNWqgWbG1a
account: eoslocalusre
private key: 5Jdwjwto9wxy5ZNPnWSn965eb8ZtSrK1uRKUxhviLpr9gK79hmM
public key: EOS5VdFvRRTtVQAPUJZQCYvpBekYV4nc1cFe7og9aYPTBMXZ38Koy
All system accounts use the following keys
accounts: eosio.bpay, eosio.msig, eosio.names, eosio.ram, eosio.ramfee,
eosio.saving, eosio.stake, eosio.token, eosio.vpay
private key: 5KAVVPzPZnbAx8dHz6UWVPFDVFtU1P5ncUzwHGQFuTxnEbdHJL4
public key: OS84BLRbGbFahNJEpnnJHYCoW9QPbQEk2iHsHGGS6qcVUq9HhutG
The default folder for smart contracts is the services/eosio/contract
folder.
This folder is mounted to the ubuntu / eosio 1.4 container which also has the eosio.cdt for contract compilation on it. This means you can either compile from host machine or the within the container using eosio-cpp
command.
If you are starting off with eos contracts development make sure you read the official documentation at https://developers.eos.io. You can follow all instructions using EOS Local as alternative to the development environment proposed there.
This projects aims to be easily replicated across different operating systems with all the advantanges of containerized software and good practices for version control, so this is good fit for teams.
There other options:
- Installing eosio directly on your machine or a virtual machine https://developers.eos.io/eosio-home/docs/introduction.
- Using the simple boilerplate provide by Block One https://github.com/EOSIO/eosio-project-boilerplate-simple.
There 2 ways you can do this.
We'll use the hello world contract as example https://developers.eos.io/eosio-home/docs/your-first-contract
Make sure you install https://github.com/EOSIO/eosio.cdt.
β eosio-cpp --version
eosio-cpp version 1.4.1
β cd services/eosio/contracts/hello
β eosio-cpp -o hello.wasm hello.cpp --abigen
Warning, empty ricardian clause file
Warning, empty ricardian clause file
Warning, action <hi> does not have a ricardian contract
β docker exec -i eoslocal_eosio ./scripts/unlock.sh
+ cleos='cleos -u http://eosio:8888 --wallet-url http://wallet:8901'
+ unlock_wallet
+ echo 'unlocking default wallet...'
unlocking default wallet...
++ cat /opt/application/config/keys/eoslocal_wallet_password.txt
+ cleos -u http://eosio:8888 --wallet-url http://wallet:8901 wallet unlock --name eoslocal --password PW5JWU79n8sXuNSrd92mNG7TR69K7q1Ax3a37x1FfFSAQE9MgXosh
Unlocked: eoslocal
+ sleep .5
β cleos wallet keys
[
"EOS5VdFvRRTtVQAPUJZQCYvpBekYV4nc1cFe7og9aYPTBMXZ38Koy",
"EOS5k6Jht1epqZ2mnRLFVDXDTosaTneR6xFhvenVLiFfz5Ue125dL",
"EOS6Jv4RykLZQQopCBdBHSwaGoMyFxyaxFNXimqFPdEXNWqgWbG1a",
"EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"EOS6TVQ6EmphCWavUuYiZMmDNYMRgbb96wgqWDncjrkvFPcpokgdD",
"EOS7CB47VMLWp49QhajE3uTuHuf9qoSeR6scUHMKGCD6LXYufRUDc",
"EOS84BLRbGbFahNJEpnnJHYCoW9QPbQEk2iHsHGGS6qcVUq9HhutG"
]
β cleos create account eosio hello EOS5VdFvRRTtVQAPUJZQCYvpBekYV4nc1cFe7og9aYPTBMXZ38Koy -p eosio@active
executed transaction: 1b9a9b7d323542d4151ab9c8b6242c85272bc7ce7144772bb65b8633f7349389 200 bytes 517 us
warning: transaction executed locally, but may not be confirmed by the network yet ]
# eosio <= eosio::newaccount {"creator":"eosio","name":"hello","owner":{"threshold":1,"keys":[{"key":"EOS5VdFvRRTtVQAPUJZQCYvpBek...
β cleos set contract hello contracts/hello -p hello@active
Reading WASM from contracts/hello/hello.wasm...
Publishing contract...
executed transaction: 0af66be6acf1a40d5925ac95ac6673e87cde20b7d9dc07b355900d9a9f77ce11 1432 bytes 1133 us
warning: transaction executed locally, but may not be confirmed by the network yet ]
# eosio <= eosio::setcode {"account":"hello","vmtype":0,"vmversion":0,"code":"0061736d0100000001390b60027f7e006000017f60027f7f...
# eosio <= eosio::setabi {"account":"hello","abi":"0e656f73696f3a3a6162692f312e31000102686900010475736572046e616d650100000000...
β cleos push action hello hi '["eoslocalusra"]' -p eoslocalusra@active
executed transaction: a4c094be2ee7d614c3932dfd626e43c18eb0be5c8a70512bfbc9658e9ebbd030 104 bytes 3072 us
# hello <= hello::hi {"user":"eoslocalusra"}
>> Hello, eoslocalusra
warning: transaction executed locally, but may not be confirmed by the network yet ]
Important note: notice the contract folder path is actually the within the container, we're just invoking the command from the host machine contracts/hello
is relative to the container working directory which is /opt/application
. so the absolute path in the container would also work /opt/applicationcontracts/hello
.
# first get into the container, eosio is an alias of docker exec -i eoslocal_eosio bash
β eosio
root@cb008277a194:/opt/application#
# make sure the eoslocal wallet is unlocked
root@cb008277a194:/opt/application# ./scripts/unlock.sh
+ cleos='cleos -u http://eosio:8888 --wallet-url http://wallet:8901'
+ unlock_wallet
+ echo 'unlocking default wallet...'
unlocking default wallet...
++ cat /opt/application/config/keys/eoslocal_wallet_password.txt
+ cleos -u http://eosio:8888 --wallet-url http://wallet:8901 wallet unlock --name eoslocal --password PW5KjU3AFWFip8TqiJQHS3LnNupLnCCCDSi2ZHfaY3JHTVn7p3cah
Error 3120007: Already unlocked
Error Details:
Wallet is already unlocked: eoslocal
+ sleep .5
# get the keys listed and copy one of the those for the contract account
root@cb008277a194:/opt/application# ./scripts/cleos.sh wallet keys
[
"EOS5VdFvRRTtVQAPUJZQCYvpBekYV4nc1cFe7og9aYPTBMXZ38Koy",
"EOS5k6Jht1epqZ2mnRLFVDXDTosaTneR6xFhvenVLiFfz5Ue125dL",
"EOS6Jv4RykLZQQopCBdBHSwaGoMyFxyaxFNXimqFPdEXNWqgWbG1a",
"EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"EOS6TVQ6EmphCWavUuYiZMmDNYMRgbb96wgqWDncjrkvFPcpokgdD",
"EOS7CB47VMLWp49QhajE3uTuHuf9qoSeR6scUHMKGCD6LXYufRUDc",
"EOS84BLRbGbFahNJEpnnJHYCoW9QPbQEk2iHsHGGS6qcVUq9HhutG"
]
# create the account for the contract
root@cb008277a194:/opt/application# ./scripts/cleos.sh create account eosio hello EOS5VdFvRRTtVQAPUJZQCYvpBekYV4nc1cFe7og9aYPTBMXZ38Koy -p eosio@active
executed transaction: 17fec7f4557ab2bf9d1625dfe226de24c12cbb82c64e100fca6f7d5d11a32b1c 200 bytes 305 us
# eosio <= eosio::newaccount {"creator":"eosio","name":"hello","owner":{"threshold":1,"keys":[{"key":"EOS5VdFvRRTtVQAPUJZQCYvpBek...
warning: transaction executed locally, but may not be confirmed by the network yet ]
# deploy the contract
root@cb008277a194:/opt/application# ./scripts/cleos.sh set contract hello contracts/hello -p hello@active
Reading WASM from contracts/hello/hello.wasm...
Publishing contract...
executed transaction: 937f6fd6a4cfc8bc264ede7e43eb1a1ced9ffd20cd59c7c33adde665578c4de1 1432 bytes 495 us
# eosio <= eosio::setcode {"account":"hello","vmtype":0,"vmversion":0,"code":"0061736d0100000001390b60027f7e006000017f60027f7f...
# eosio <= eosio::setabi {"account":"hello","abi":"0e656f73696f3a3a6162692f312e31000102686900010475736572046e616d650100000000...
warning: transaction executed locally, but may not be confirmed by the network yet ]
# test the action
root@cb008277a194:/opt/application# ./scripts/cleos.sh push action hello hi '["eoslocalusra"]' -p eoslocalusra@active
executed transaction: a4c094be2ee7d614c3932dfd626e43c18eb0be5c8a70512bfbc9658e9ebbd030 104 bytes 3072 us
# hello <= hello::hi {"user":"eoslocalusra"}
>> Hello, eoslocalusra
warning: transaction executed locally, but may not be confirmed by the network yet ]
The primary benefits of containers are efficiency and agility. Containers are orders of magnitude faster to provision, and much lighter-weight to build and define versus methods like omnibus software builds and full Virtual Machine images. Containers in a single OS are also more efficient at resource utilization than running a Hypervisor and guest OSs.
Efficiency and agility are good for everyone, but they become game-changers at scale.
It also gives the ability to run distint versions of the different services like EOSIO on your laptop without conflicts.
Containers offer a logical packaging mechanism in which applications can be abstracted from the environment in which they actually run. This decoupling allows container-based applications to be deployed easily and consistently, regardless of whether the target environment is a private data center, the public cloud, or even a developerβs personal laptop. Containerization provides a clean separation of concerns, as developers focus on their application logic and dependencies, while IT operations teams can focus on deployment and management without bothering with application details such as specific software versions and configurations specific to the app.
For those coming from virtualized environments, containers are often compared with virtual machines (VMs). You might already be familiar with VMs: a guest operating system such as Linux or Windows runs on top of a host operating system with virtualized access to the underlying hardware. Like virtual machines, containers allow you to package your application together with libraries and other dependencies, providing isolated environments for running your software services. As youβll see below however, the similarities end here as containers offer a far more lightweight unit for developers and IT Ops teams to work with, carrying a myriad of benefits.
Learn more at https://cloud.google.com/containers/
We use a Kanban-style board. That's were we prioritize the work. Go to Project Board.
The main communication channels are github issues and EOS Costa Rica's Discord server. Feel to join and ask as many questions you may have.
Our weekly sync call is every Monday 1:00 AM UTC. meet.eoscostarica.io.
Contributing Guidelines https://developers.eoscostarica.io/docs/open-source-guidelines.
Please report bugs big and small by opening an issue
We challenge ourselves to provide the EOS platform with a strong geographical and political diversity by running the most robust EOS Block Producer possible from Costa Rica; We pledge to leverage our talent, experience, and sustainable internet resources to meet such an important challenge.
EOS Costa Rica supports the EOS.io community by maintaining and contributing to open source initiatives, meetups and workshops.
MIT Β© EOS Costa Rica
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!