Web3.py Patterns: External Modules

Build custom functionality or import a third-party plugin into your Web3 instance.

Available in the latest release of Web3.py (v5.29.0) is support for external modules! With external modules you can include custom functionality or import a third-party plugin into your Web3 instance. This feature may be an elegant way for Web3.py to integrate with one-off non-standard JSON-RPC methods, or an entire L2 API.

Usage

There are a couple of options for how to introduce external modules.

1) You may include them while instantiating a Web3.py instance:

from web3 import Web3, HTTPProvider
from my_custom_modules import ExampleModule

w3 = Web3(
   HTTPProvider(...),
   external_modules={'example': ExampleModule}
)

w3.example.example_method()

2) Or, utilize the attach_modules method on a Web3.py instance:

w3.attach_modules({'example': ExampleModule})

w3.example.example_method()

Creating an external module

External modules need only be a class. If you need to reference the parent Web3 instance, it is passed in as the first and only argument in the __init__ function. Here's a quick example that includes a module (HoopersModule) with one submodule (ShaqModule) that makes use of the Web3 instance:

import random

class HoopersModule():                       
    def set_strategy(self):
        print('foul!' if random.choice([True, False]) else 'flop!')

class ShaqModule():
    def __init__(self, w3):
        self.w3 = w3

    def print_balance(self):
        wei_balance = self.w3.eth.get_balance('shaq.eth')
        print(self.w3.fromWei(wei_balance, 'ether'))

w3.attach_modules({'hoopers': (HoopersModule, {'shaq': ShaqModule})})

w3.hoopers.set_strategy()
# flop!

w3.hoopers.shaq.print_balance()
# 0.271887362722036121

A note on middleware

As noted in the introduction, external modules are a great way to introduce new APIs to your Web3 instance. However, there is a subset of use cases which are better suited for middleware. If you are interested in adding some behavior to each existing RPC call, creating some custom middleware is likely the better fit.

Safety first!

When considering third-party modules, exercise caution, do your diligence, and only use those from parties you absolutely trust!