Plugins

How To Create A Web3 Provider API Plugin Using Ape Framework

written by
Dalena Dang
Date Last Updated
October 25, 2022
Download Project Files

Ape Framework is a modular, dynamic, and easy-to-use set of Python tools that make building Web3 dApps easier. Now that you understand our framework's ecosystem let's customize a plugin. This tutorial will show you how to create a network plugin using Ape.

Getting Started Developing Plugins

This tutorial will walk you through how to create a plugin using `ape`. Today we will be focusing on developing a provider plugin. Provider plugins with the ApeWorX console to allow users to connect and interface with the blockchain.

We will be following the Developing Plugins guide, which you can find in the ApeWorX documentation here.

The initial step is to set up a directory for the project. We will use the ApeWorX project template to initialize this plugin. This example plugin we are developing today will be called LiveNode. We will discuss the methods you need to implement to create a working plugin.

Initializing a Plugin Project

To get started, let’s go to the template page and create a fork of the project. Then you can go to your project’s fork and select Use this Template to create a new repository. The benefit of setting up the project this way is that Github will know where this template is coming from and display that information, and it will also make it easier to reference in case you need to look back at it for anything. 

This project template is the standard template that ApeWorX uses when making our plugins, so it includes the `.github` and `.pre-commit-config.yaml` files standard for our workflow. While you do not have to keep and use these for your project, it will make reviewing and creating work at a certain standard easier.

The next step is to go ahead and clone the project into our terminal. Then rename the directory MODULE_NAME with the name of the plugin we are creating. We are going to name it `ape_livenode` for this example. The plugin’s name should begin with `ape_` so that the ape console will recognize the directory as a plugin package.

Then inside the main project directory, we will search for all instances of `<MODULE_NAME>` in the code and replace it with `ape_livenode`. You can use  `CTRL + SHIFT + H` in VSCode to search and replace all. Then you should do the same search for the package name `<PYPI_NAME>` and replace it with `ape-livenode`. The module name uses underscores, while the python package name uses dashes following the PEP guidelines.

The `ape_livenode` folder already contains an __init__.py (double underscore) and py.typed file, so you will not have to create it yourself. You will be registering the provider in the init.py file.

From there, we will create a file named `provider.py` (since we are making a provider plugin), and this will be where we implement the API classes needed for our plugin.

Implementing API Classes

For the plugin to work properly, you must implement all abstract methods from an API class. However, some mixing classes, such as Web3Provider, already implement some of the abstract methods. We can still override these methods, but it allows for shared code across EVM-based provider implementations.

So let’s go into the `provider.py` file, and we will go through what you must implement to create a general providers plugin.

First, we must import the API class from the `ape.api` namespace.

from ape.api import ProviderAPI

Then we will create the class for the provider:

class LiveNodeProvider(ProviderAPI): 

To connect to LiveNode, we will want to implement one of the abstract methods, `connect()`, from the api class.

class LiveNodeProvider(ProviderAPI):
		_is_connected: bool = False

		def connect(self):
			self._is_connected = True
      

Now let’s implement one more abstract method. Please note that any abstract method that includes `property` will need a property decorator as well before the function. Let’s implement this method `chain_id()`. 

@property
	def chain_id(self) -> int:
		return 50
    

Depending on what the provider needs, we can implement more API methods. You can view all the methods for the API in our docs linked here. If there is a missing method, you will see an error message in the terminal telling you what methods you are missing. We will only review some methods because they may differ between big releases. The best way to check what methods you need is to view the documentation for the plugin you are developing.

Registering API Classes

Once we have implemented the abstract methods, we will need to register the plugin so that the ape console recognizes it.

We will do this in the __init__.py file (double underscore). We will import plugins from ape to tell the console that this is a plugin for the console, and we will also be importing the plugin that we just created.

We are going to pretend that LiveNode is a local provider plugin for the Ethereum ecosystem, so we are going to yield “Ethereum”, “local” and `LiveNodeProvider

From ape import plugins

	From .provider import LiveNodeProvider

	@plugins.register(plugins.ProviderPlugin)
	Def provider():
		Yield “ethereum”, “local”, LiveNodeProvider

To make a mainnet provider plugin, you should yield “mainnet” instead of “local”. Also, if you are making a plugin for a different ecosystem, you should put that ecosystem name instead of “ethereum”.

Testing the Plugin

Once we have finished implementing and registering the plugin, they can now be a part of ape

To install the plugin in an editable environment, run `pip install -e .` This will allow us to change the plugin, which we will reflect in the python environment.

Since we did not implement all the abstract methods for the ProviderAPI class, we will get a warning message showing the methods that still need to be implemented. For now, we will insert these methods with no implementation to test that our plugin works.

Now let’s test our plugin. 

Open the ape console using our new provider.

ape console -network ethereum:local:livenode

Now let’s check out the chain ID implementation using: 

networks.active_provider.chain_id

And make sure that it returns the value from our implementation “50”.

Thank you for watching this video.

We hope this has cleared up any questions you may have had about developing plugins. If you have any questions, please feel free to come to our Discord server and ask. We are happy to help you with any questions or problems you may have.