Setting Up a StarkNet Dev Environment with Python

David Barreto
Starknet Edu
Published in
5 min readSep 20, 2022

TL;DR; Commands to create a StarkNet dev environment using only Python.

# Install global dependencies (macOS)
$ brew install gmp python@3.9

# Create virtual environment
$ python3.9 -m venv env

# Activate virtual environment
$ source env/bin/activate

# Upgrade pip to latest version
(env) $ pip install --upgrade pip

# Install project dependencies inside virtual environment
(env) $ pip install cairo-lang openzeppelin-cairo-contracts pytest pytest-asyncio starknet-devnet starknet.py

# Track project dependencies in a file
(env) $ pip freeze > requirements.txt

File to set up the environment upon cloning (setup.sh).

#!/bin/bash
rm -rf env
python3.9 -m venv env
source env/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
deactivate

To use the script run bash setup.sh

The Problem We Want to Solve

Cairo docs provide instructions on how to configure your dev environment using Python’s built-in tools. This recommendation works well if it’s your first time using StarkNet or if you are working on a single project and on your own. As soon as you start maintaining a second project or start to collaborate with other people this setup will be insufficient because of improper dependency management.

In this article, we are going to explore how to make the most out of Python’s built-in tools for better collaboration and maintenance of your StarkNet projects without the overhead of having to learn new APIs and configuration files of advanced package managers and tooling.

Global Dependencies

Even though our goal is to isolate dependencies between StarkNet projects, there are two packages that must be available globally: gmp and python.

The release notes of Cairo 0.10.0 mentions that it depends on Python 3.9. On macOS, you can install both dependencies globally using Homebrew.

$ brew install gmp python@3.9

Installing a specific version of Python on Ubuntu in a way that plays nicely with pip is surprisingly difficult. If you are looking for a cross-platform alternative, take a look at this other article we wrote that uses Docker to create a StarkNet dev environment.

Project Scaffolding

We are going to name the root folder of our sample project as my-starknet-project but you can give it any name you want.

$ mkdir my-starknet-project && cd my-starknet-project

Inside this folder we are going to create four directories to better organize our code:

  • src: Where StarkNet smart contracts are stored
  • libs: Where Cairo functions for reusable functionality are stored
  • comp: Where the compiled version StarkNet smart contracts are stored
  • abis: Where the ABIs of StarkNet smart contracts are stored
  • tests: Where unit and integration tests (written in Python) are stored
$ mkdir src libs comp abis tests

The number of folders and their naming convention is only one of many possibilities. Different projects might use different conventions so feel free to come up with your own.

Finally, there are two files that are always needed for collaboration, .gitignore and README.md

$ touch .gitignore README.md

At the end you should end up with the following folder structure:

.
├── .gitignore
├── README.md
├── abis/
├── comp/
├── libs/
├── src/
└── tests/

Virtual Environment

Instead of having a single virtual environment shared with all projects, we are going to create a dedicated one inside the project’s root folder so packages can be managed in isolation.

Because this project is going to use Cairo 0.10.0 we should create the virtual environment using python3.9 binary.

$ python3.9 -m venv env

This will create a folder named env inside the project folder.

.
├── .gitignore
├── README.md
├── abis/
├── comp/
├── env/
├── libs/
├── src/
└── tests/

To activate the virtual environment we can run:

$ source env/bin/activate

Because the env folder stores python and pip binaries along with any package you install from pypi, it should not be added to your repository to avoid bloating.

$ echo “env” >> .gitignore

Instead, we can create a shell script to help recreate the virtual environment with the correct version of Python.

setup.sh

#!/bin/bash
rm -rf env
python3.9 -m venv env

This script can be executed by running:

$ bash setup.sh

Project Dependencies

With the project’s virtual environment activated we can install cairo-lang.

(env) $ pip install cairo-lang

To run unit tests on our Cairo files, we will need to install the packages pytest and pytest-asyncio.

(env) $ pip install pytest pytest-asyncio

To run integration tests with our smart contracts, we will need the packages starknet-devnet and starknet.py.

(env) $ pip install starknet-devnet starknet.py

starknet-devnet allows you to create a local version of StarkNet’s testnet to deploy and interact with your smart contracts (similar to Ganache) while starknet.py is an SDK to interact with this local testnet. starknet.py can also be used to create complex deployments to either Goerli or Mainnet.

Finally, install Open Zeppelin’s Cairo smart contracts to avoid reinventing the wheel for common use cases like ERC20 tokens and NFTs.

(env) $ pip install openzeppelin-cairo-contracts

To make our dependencies explicit to any other team member working on the project, we can create a requirements.txt file to list them.

(env) $ pip freeze > requirements.txt

At this point, our folder structure should look like this:

.
├── .gitignore
├── README.md
├── abis/
├── comp/
├── env/
├── libs/
├── requirements.txt
├── setup.sh
├── src/
└── tests/

Now when a team member clones the project they can install the same dependencies by running:

(env) $ pip install -r requirements.txt

We can further automate the project initialization by modifying setup.sh to also install the project dependencies.

setup.sh

#!/bin/bash
rm -rf env
python3.9 -m venv env
source env/bin/activate
pip install -r requirements.txt
deactivate

You can find the source code for this development environment here.

Conclusion

The development environment shown in this article aims at being functional while remaining simple using only what Python has to offer out of the box.

Unfortunately, Python’s built-in dependency manager (pip) has some shortcomings. It is not as feature complete as tools like npm (Javascript) or cargo (Rust); a lot more manual intervention is required to keep dependencies in sync and to create reusable commands.

If you are looking for a more robust dependency management solution you can use Poetry. If you want to also define global dependencies as code in your project you can use Docker but it might be overkill for most projects.

You can also setup a non-Python based development environment using Hardhat or Protostar as we discussed in our previous article “Choosing a StarkNet Development Tool”.

What other Python packages do you normally use with Cairo? Let us know in the comment section below.

--

--

David Barreto
Starknet Edu

Starknet Developer Advocate. Find me on Twitter as @barretodavid