Skip to main content

Plugin Developer Guide

This guide intends to provide the necessary context for developing plugins for web3.js.

Feel free to explore some of the already built plugins and/or use this template to start with development of your Web3.js plugin.

caution

To provide type safety and IntelliSense for your plugin users, please refer to the Setting Up Module Augmentation section for how to augment the Web3Context module to enable typing features for your plugin.

Plugin Dependencies

At the minimum, your plugin should depend on web3 package version 4.0.2. This will allow your plugin class to extend the provided Web3PluginBase abstract class. However, web3 shouldn't be listed as a regular dependency, instead it should be listed in your plugin's package.json as a peer dependency.

important

It is important to note that the plugin name should be structured as @<organization>/web3-plugin-<name> or web3-plugin-<name>.

{
"name": "web3-plugin-custom-rpc-methods",
"version": "0.1.0",
"peerDependencies": {
"web3": ">= 4.0.2 < 5"
}
}

When your users install your plugin, this will allow the package manager to make use of the user installed web3 if available and if the version satisfies the version constraints instead of installing its own version of web3.

Add New Transaction Type

Furthermore, you have the flexibility to expand your range of transaction types, enhancing compatibility with the web3.js library.

// create new TransactionType class which extends BaseTransaction class
import { BaseTransaction } from 'web3-eth-accounts';
const TRANSACTION_TYPE = 15;
class SomeNewTxTypeTransaction extends BaseTransaction {
// ...
}

// create new plugin and add `SomeNewTxTypeTransaction` to the library
import { Web3EthPluginBase } from 'web3';

class SomeNewTxTypeTransactionPlugin extends Web3PluginBase {
public pluginNamespace = 'someNewTxTypeTransaction';
public constructor() {
super();
TransactionFactory.registerTransactionType(TRANSACTION_TYPE, SomeNewTxTypeTransaction);
}
}

Extending Web3PluginBase

Your plugin class should extend the Web3PluginBase abstract class. This class extends Web3Context and when the user registers your plugin with a class, your plugin's Web3Context will point to the module's Web3Context giving your plugin access to things such as user configured requestManager and accountProvider.

import { Web3PluginBase } from 'web3';

export class CustomRpcMethodsPlugin extends Web3PluginBase { ... }

Extending Web3EthPluginBase

In addition to Web3PluginBase, you can choose to extend Web3EthPluginBase which will provide the Ethereum JSON RPC API interface, which packages such as Web3Eth use, as a generic to your plugin's requestManager, giving it type support for the Ethereum JSON RPC spec. This would be the recommended approach if your plugin makes Ethereum JSON RPC calls directly to a provider using web3's provided requestManager.

import { Web3EthPluginBase } from 'web3';

export class CustomRpcMethodsPlugin extends Web3EthPluginBase { ... }

pluginNamespace

After extending the Web3PluginBase class, your plugin will need a public pluginNamespace property that configures how your plugin will be accessed on the class, which your plugin was registered with. In the following example, the pluginNamespace is set to customRpcMethods, so when the user registers the plugin they will access your plugin as follows:

The following represents your plugin code:

// custom_rpc_methods_plugin.ts
import { Web3PluginBase } from 'web3';

export class CustomRpcMethodsPlugin extends Web3PluginBase {
public pluginNamespace = 'customRpcMethods';

public someMethod() {
return 'someValue';
}
}

The following represents the plugin user's code:

// registering_a_plugin.ts
import { Web3Context } from 'web3';

import { CustomRpcMethodsPlugin } from './custom_rpc_methods_plugin';

const web3Context = new Web3Context('http://127.0.0.1:8545');
web3Context.registerPlugin(new CustomRpcMethodsPlugin());

await web3Context.customRpcMethods.someMethod();

Using the Inherited Web3Context

Below is an example of CustomRpcMethodsPlugin making use of this.requestManager which will have access to an Ethereum provider if one was configured by the user. In the event that no provider was set by the user, the below code will throw a ProviderError if customRpcMethod was to be called:

import { Web3PluginBase } from 'web3';

export class CustomRpcMethodsPlugin extends Web3PluginBase {
public pluginNamespace = 'customRpcMethods';

public async customRpcMethod() {
return this.requestManager.send({
method: 'custom_rpc_method',
params: [],
});
}
}

Below depicts a plugin user's code that does not configure an Ethereum provider, resulting in a thrown ProviderError when calling customRpcMethod:

// registering_a_plugin.ts
import { Web3Context } from 'web3';

import { CustomRpcMethodsPlugin } from './custom_rpc_methods_plugin'