You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Mar 5, 2025. It is now read-only.
@@ -13,26 +13,26 @@ To provide type safety and IntelliSense for your plugin users, please refer to t
13
13
14
14
## Plugin Dependencies
15
15
16
-
At the minimum, your plugin should depend on the `4.x` version of `web3-core`. This will allow your plugin class to extend the provided `Web3PluginBase` abstract class. However, `web3-core` shouldn't be listed as a regular dependency, instead it should be listed in your plugin's `package.json` as a [peer dependency](https://nodejs.org/en/blog/npm/peer-dependencies/):
16
+
At the minimum, your plugin should depend on the `4.x` version of `web3`. 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](https://nodejs.org/en/blog/npm/peer-dependencies/):
17
17
18
18
```json
19
19
{
20
20
"name": "web3-plugin-custom-rpc-methods",
21
21
"version": "0.1.0",
22
22
"peerDependencies": {
23
-
"web3-core": ">= 4.0.1-alpha.0 < 5"
23
+
"web3": ">= 4.0.1 < 5"
24
24
}
25
25
}
26
26
```
27
27
28
-
When your users install your plugin, this will allow the package manager to make use of the user installed `web3-core` if available and if the version satisfies the version constraints instead of installing it's own version of `web3-core`.
28
+
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 it's own version of `web3`.
29
29
30
30
## Extending `Web3PluginBase`
31
31
32
32
Your plugin class should `extend` the `Web3PluginBase` abstract class. This class `extends`[Web3Context](/api/web3-core/class/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](/api/web3-core/class/Web3Context#requestManager) and [accountProvider](/api/web3-core/class/Web3Context#accountProvider).
In addition to `Web3PluginBase`, you can choose to extend `Web3EthPluginBase` which will provide the [Ethereum JSON RPC API interface](/api/web3-types#EthExecutionAPI), which packages such as `Web3Eth` use, as a generic to your plugin's `requestManager`, giving it type support for the [Ethereum JSON RPC spec](https://ethereum.github.io/execution-apis/api-documentation/). This would be the recommended approach if your plugin makes Ethereum JSON RPC calls directly to a provider using web3's provided `requestManager`.
After extending the `Web3PluginBase` class, your plugin will need a `public``pluginNamespace` property that configures how your plugin will be accessed on the class 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:
52
+
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:
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](/api/web3-errors/class/ProviderError) if `customRpcMethod` was to be called:
@@ -126,7 +126,7 @@ ProviderError: Provider not available. Use `.setProvider` or `.provider=` to ini
126
126
If needed, you can provide an API type (that follows the [Web3ApiSpec](/api/web3-types#Web3APISpec) pattern) as a generic to `Web3PluginBase` that will add type hinting to the `requestManager` when developing your plugin. In the below code, this is the `CustomRpcApi` type that's being passed as `Web3PluginBase<CustomRpcApi>`
@@ -214,22 +210,17 @@ public link(parentContext: Web3Context) {
214
210
215
211
## Setting Up Module Augmentation
216
212
217
-
In order to provide type safety and IntelliSense for your plugin when it's registered by the user, you must [augment](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation) the `Web3Context` module. In simpler terms, you will be making TypeScript aware that you are modifying the interface of `Web3Context`, and any class that extends it, to include the interface of your plugin (i.e. your plugin's added methods, properties, etc.). A good tutorial that further explains the topic can be found [here](https://www.digitalocean.com/community/tutorials/typescript-module-augmentation).
213
+
To ensure type safety and enable IntelliSense for your plugin (which still needs to be registered by the user), you must augment the `Web3Context`class inside the `web3`module. In simpler terms, this is to modify the `Web3Context` class, and any inheriting classes, to make your plugin's functionality accessible from within. As a result, your plugin object will be accessible within a namespace of your choice, which will be available within any `Web3Context` object.
218
214
219
-
### A Quick Disclaimer
215
+
For a general understanding of Module Augmentation, you can refer to [this tutorial](https://www.digitalocean.com/community/tutorials/typescript-module-augmentation).
220
216
221
-
The `registerPlugin` method exists on the `Web3Context` class, so any class that `extends Web3Context` has the ability to add your plugin's additional functionality to its interface. By augmenting `Web3Context` to include your plugin's interface, you're essentially providing a blanket augmentation that adds your plugin's interface to **all** Web3 modules that extend `Web3Context` (i.e. `web3`, `web3-eth`, `web3-eth-contract`, etc.).
217
+
### Module Augmentation
222
218
223
-
:::warning
224
-
By augmenting `Web3Context` (and by extension all class interfaces that extend it), your plugin's interface will show up in things like IntelliSense for **all** Web3 modules that extend `Web3Context`, even if your plugin isn't registered - This is something worth making your users aware of, as they'll only be able to use your plugin if they register it with a Web3 class instance using `.registerPlugin`
225
-
226
-
For context, here is an example of your plugin's interface showing up in IntelliSense even though your plugin hasn't been registered (the code in this example is further explained in the subsequent sections):
219
+
When registering a plugin, you're adding additional methods and/or classes to the module's interface and TypeScript needs a little help understanding what's going to be available within the module after the plugin is registered.
The above screenshot shows IntelliSense thinking `.customRpcMethods.someMethod` is available to call on the instance of `Web3`, even though the plugin user hasn't registered `CustomRpcMethodsPlugin` - running this code would result in an error.
257
-
:::
258
-
259
-
### Re-exporting Web3Context
260
-
261
-
Currently TypeScript's module augmentation only supports named exports, so the first step in augmenting `Web3Context` is to re-export it as a named export. To do this you're going to create a `reexported_web3_context.ts` file (the name of this file can be whatever you prefer, but for the sake of this guide, it's going to be assumed it's named `reexported_web3_context.ts` and is located within the same directory as the `custom_rpc_methods_plugin.ts` file). The file contents should be as follows:
262
-
263
-
```typescript
264
-
// reexported_web3_context.ts
265
-
import { Web3Context } from'web3-core';
266
-
267
-
export { Web3Context };
268
-
```
269
-
270
-
### Re-declaring the Module
271
-
272
-
Now you're going to tell TypeScript that you're interested in re-defining a module's (in this case `reexported_web3_context`) interface. In simpler terms, TypeScript is already aware of what methods and classes exist for each web3.js module, but when registering a plugin, you're adding additional methods and/or classes to the module's interface and TypeScript needs a little help understanding what's going to be available within the module after the plugin is registered.
// Here is the declaration to TypeScript that you are
291
-
// augmenting the imported module (i.e. ./reexported_web3_context)
292
-
declaremodule'./reexported_web3_context' {...}
293
-
```
294
-
295
-
### Adding Your Plugin's Interface
296
-
297
-
Now that TypeScript is aware that the interface of the `reexport_web3_context` module is going to be augmented, you can add your plugin's interface. In this case, you're adding the interface of `CustomRpcMethodsPlugin` to the interface of `Web3Context` which is what the **plugin-user** is going to be calling `.registerPlugin` on:
The property name (i.e. `pluginNamespace`), `customRpcMethods` in
243
+
### Important points to consider
324
244
325
-
```typescript
326
-
{
327
-
customRpcMethods: CustomRpcMethodsPlugin;
328
-
}
329
-
```
245
+
1. By augmenting `Web3Context` (and, by extension, all the classes that extend it), your plugin's interface will show up in things like IntelliSense for **all** Web3 modules that extend `Web3Context`, even if your plugin isn't registered.
246
+
This is something worth making your users aware of, as they'll only be able to use your plugin if they register it with a Web3 class instance using `.registerPlugin`.
330
247
331
-
**MUST** be the same as the `pluginNamespace` set by the plugin.
248
+
:::warning
332
249
333
-
```typescript
334
-
import { Web3PluginBase } from'web3-core';
250
+
The following represent what your **plugin users** would see, when they use the plugin `CustomRpcMethodsPlugin`, without calling `.registerPlugin`:
The above screenshot shows IntelliSense thinking `.customRpcMethods.someMethod` is available to call on the instance of `Web3`, regardless if the plugin user registered or did not register `CustomRpcMethodsPlugin`.
255
+
But, the user who does not call `.registerPlugin`, before accessing your plugin, would face an error. And you need to make it clear for them that they need to call `.registerPlugin`, before they can access any plugin functionality.
342
256
343
-
This is because `.registerPlugin` will use the `pluginNamespace` property provided by the plugin as the property name when it registers the plugin with the class instance you call `.registerPlugin` on:
257
+
:::
344
258
345
-
```typescript
346
-
const web3 =newWeb3('http://127.0.0.1:8545');
347
-
web3.registerPlugin(newCustomRpcMethodsPlugin());
348
-
// Now customRpcMethods (i.e. the pluginNamespace) is available
349
-
// on the instance of Web3
350
-
web3.customRpcMethods;
351
-
```
259
+
2. The `registerPlugin` method exists on the `Web3Context` class, so any class that `extends Web3Context` has the ability to add your plugin's additional functionality to its interface. So, by augmenting `Web3Context` to include your plugin's interface, you're essentially providing a blanket augmentation that adds your plugin's interface to **all** Web3 modules that extend `Web3Context` (i.e. `web3`, `web3-eth`, `web3-eth-contract`, etc.).
352
260
353
-
:::
261
+
3. The value of the `pluginNamespace`, that we used `customRpcMethods` for it in our sample code, **MUST** have the exact same name at 2 places: The first place is in the augmentation. And the second is the value of the public `pluginNamespace` inside your plugin class.
354
262
355
-
### Exporting The Augmented Web3Context
263
+
So, for example, kindly notice using `customRpcMethods` in the next 2 snippets:
356
264
357
-
Lastly, you just need to export the augmented `Web3Context` by adding the following after the module re-declaration:
265
+
Module Augmentation:
358
266
359
-
```typescript
360
-
export { Web3Context };
361
-
```
267
+
```typescript
268
+
// code written by the plugin **developer**
362
269
363
-
The full code example is as follows:
270
+
declaremodule'web3' {
271
+
// Here is where you're adding your plugin inside Web3Context
0 commit comments