Local Development of Neo Smart Contracts in Python

Nevan Tan
Coinmonks
6 min readFeb 12, 2019

--

NOTE: This article was originally created for the City of Zion Competition #3 and was a runner-up entry. The original post was on Github, but I have since migrated it to Gitlab.

In this tutorial, we will use the neo-local project to setup a private chain for local development and testing of Neo smart contracts. Using a private chain gives us complete control over our environment, allowing us to work in isolation without dealing with external testnets.

In order to follow along, you will need access to a Unix-like terminal and a text editor of some sort. I will be working in a VM, using nano for text editing:

Ubuntu 18.04 (Minimal Install)
4GB RAM
50GB Disk

Note that you will probably want at least 20GB of disk space to store your private chain.

Docker, Docker Compose, and neo-local

The neo-local project requires Docker to run, so the first order of business will be to get that installed. Docker is a container engine that can run pre-configured setups, which is exactly what neo-local uses it for. We will be using Docker Community Edition (Docker CE).

Install Docker

You can find detailed installation instructions for your operating system of choice in the Docker docs. Here are direct links to the more common OS options:

Install Docker Compose

We will also need Docker Compose. For Windows and MacOS, it should already be included in the package you installed in the previous step. Linux users will need to follow the steps outlined in the compose section of the docs. Make sure you check the GitHub releases page for the latest version number as instructed in the guide — don’t just copy/paste the command without checking.

Testing Docker

Just as a quick test, you should now be able to run the following commands (the lines beginning in ‘$’) and see the corresponding output:

Your version numbers may not match mine exactly, that’s fine so long as you’re running the latest versions available to you.

Linux users should also be able to run the ‘hello-world’ docker container without sudo if the post-install steps worked. Note that you may have to restart your computer if you get a 'permission denied' error of some kind:

Setup neo-local

Finally, we’ll need to setup neo-local by cloning the repository and mounting the pre-configured wallet file so that we have GAS to work with on our private network.

In your terminal, navigate to the directory you want to store your Neo-related work, then clone the repository. For those unfamiliar with git, this will create a directory called ‘neo-local’ with the files we need inside. Navigate into the neo-local directory.

Most of the files in here are related to the neo-local project itself and we will not be modifying those at all. We will only be dealing with the wallets/ directory during setup in a moment. Most of our work will be in the smart-contracts/ directory once we're up and running.

The wallet file we’ll be using is a bit difficult to locate. You can find it on the neo-privatenet Docker hub page, or just grab it from this direct link. Place the downloaded wallet file in the wallets/ directory of the neo-local repository. For reference, the password for this wallet is coz.

Start the neo-local stack

Starting the stack is slightly different between operating systems. Both sets of commands will leave you in a neo-python command-line interface (CLI).

Windows (wiki)

MacOS (wiki) and Linux (wiki)

Install make if you don't already have it:

Start the stack:

Opening the wallet

The last setup step before working with smart contracts is opening the wallet we copied in earlier. Docker is set up to mount the wallets/ directory at root, so our wallet resides at /wallets/neo-privnet.wallet. The help command in neo-python will show a list of possible commands. The one we're looking for is open wallet {path}, which will then prompt for a password for the wallet (coz). The whole thing should look as follows:

A Basic Smart Contract

Since the neo-local stack uses neo-python, we’ll be writing a basic smart contract in Python. Create the file plus_one.py in the smart-contracts/ directory and add the following code:

As you can see, the contract takes an input number and returns that number plus one. Much like the wallets/ directory, smart-contracts/ is also mounted at root, so the path to our contract will be /smart-contracts/plus_one.py.

Neo smart contracts run on the NeoVM (Neo Virtual Machine) and must first be converted to bytecode, similar to Java, before they can be deployed. The build {path} command in neo-python does this for us, generating a .avm file alongside the .py file provided as input. However, this file on its own doesn't do us much good. We will want to start with the build..test variant of the command:

Let’s break the command down before we get to the output. The full signature for this command is:

The path to file is fairly self-explanatory. Types, however, are provided as a ContractParameterType where parameter and return types are each represented as a single byte:

The path to file is fairly self-explanatory. Types, however, are provided as a ContractParameterType where parameter and return types are each represented as a single byte:

In our case, the contract takes an integer (02) and also returns an integer (02). The next three arguments are properties that are set on the contract, we aren’t going to worry about those for now. The last argument is filling in the data that the contract will actually be called using. Running this command in the neo-python prompt should output something like the following:

The first output line is confirmation that the bytecode was built and where it was saved. The rest of the output describes the setup and result of the contract. We called it with the value of ‘5’, the invoke was successful, and we received the Integer ‘6’ back. Looks like our contract works!

Deploying a Smart Contract

Finally, once we’ve built and tested our smart contract, we need to deploy it to the network. This is actually a fairly simple process at this point, we just need to use the import contract command.

You will be prompted to fill in a few fields such as the Contract Name and Version, Author Name and Email, etc. Once those have been filled, some metadata about the contract will be printed and you will be prompted for your wallet password. Entering this password will deploy the contract and charge you the requisite quantity of GAS to do so. Since this is a private network, you should be fine to go ahead and deploy — the test wallet has plenty of GAS to work with.

Once the deployment goes through, grab the “hash” from the metadata that was printed and run a testinvoke command (substituting your own contract hash):

You should see the output with the expected result:

If you get a message about the contract not being found, you may need to wait for a minute or two for your contract to be mined into a block before it can be invoked. Once again, this will be a local invocation and entering your password will run the contract on the network for real, charging you GAS in the process.

Next Steps

As of the time of writing, Neo documentation is fairly fragmented. However, some of the following sites provide good info on smart contract development:

Additionally, neon-js can be used to interact with smart contracts from JavaScript environments.

Hopefully, this basic walkthrough of the development process will give you a starting point for your own projects to help enhance the NEO scene as a whole.

Get Best Software Deals Directly In Your Inbox

--

--