How to Develop a Plugin?

In this guide, we will cover setting up your development environment, explain the structure of the plugins, and create our first custom plugin using a simple example.

This guide below describes how to develop your plugin from scratch. To get you up to speed we also prepared a template project:

Plugin Architecture

The architecture of plugins adheres to the default npm package structure, meaning it should have a package.json with your main file in which your code will reside.

To start a project, let’s create a directory with the mkdir command, open it and run yarn init, which will open an interactive session to create a package.json file. We then create a new file in the src directory named index.js.

1mkdir my-first-plugin && cd $_
2yarn init
3mkdir src && touch src/index.js

The structure of the plugin now looks like this:

1|-- src
2|---- index.js
3|-- package.json

Your main file is where you will interact with the plugin’s API. You must export an object containing the methods that will be called by the Desktop Wallet.

Writing Your First Plugin

As mentioned above, in the main file we have the lifecycle event **register**that is called when the plugin is loaded.

The getComponentPaths method should return a key-value object in which the key is the name of the component and the value is the relative path of the file to be rendered.

Now to reflect this we need to update our main file index.js:

index.js:

1module.exports = {
2 register() {
3 console.log(`I'm a plugin`)
4 },
5 getComponentPaths() {
6 return {
7 'my-first-plugin': './my-first-plugin.js'
8 }
9 }
10}

And the my-first-plugin.js file should be a valid Vue Component object, currently you can not write your plugin as a Single File Component , but instead of using the <template> tag you will write your HTML into the template field:

my-first-plugin.js:

1module.exports = {
2 template: `
3 
4 `,
5 data: () => ({
6 description: 'My first component'
7 })
8}

Running Your Plugin

Now that our definition file and component are ready, let’s check if it’s working:

  1. Clone the official desktop-wallet repository and prepare your environment:
1cd ..
2git clone https://github.com/ArkEcosystem/desktop-wallet
3cd desktop-wallet
4yarn install
  1. Move your project directory to the plugins folder:
1mv ../my-first-plugin/ ~/.ark-desktop/plugins/
  1. Now you are able to run it and test your plugin by running the wallet:
1yarn dev
  1. Open the Desktop Wallet and go to the Sidebar > Plugin Manager and enable it.

Well OK, but where is my component at?

In fact, the previous method only registers your component globally to be used at another time in your application. So to tackle this we’ll be adding a custom page and navigation icon.

Adding a Custom Page

If you need to add a custom page to your plugin, use the getRoutes method to link your component to the route path.

This should return an array of route configuration to be used by the vue-router .

Our main file will look like this after we add it:

index.js:

1module.exports = {
2 register() {
3 console.log(`I'm a plugin`)
4 },
5 getComponentPaths() {
6 return {
7 'my-first-plugin': './my-first-plugin.js'
8 }
9 },
10 getRoutes() {
11 return [
12 {
13 path: '/first-plugin',
14 name: 'first-plugin-route',
15 component: 'my-first-plugin'
16 }
17 ]
18 }
19}

Adding a Navigation Icon

You can add a link to your route in the sidebar using the **getMenuItems**method, which should return an array of objects containing the route name and title.

index.js:

1module.exports = {
2 register() {
3 console.log(`I'm a plugin`)
4 },
5 getComponentPaths() {
6 return {
7 'my-first-plugin': './my-first-plugin.js'
8 }
9 },
10 getRoutes() {
11 return [
12 {
13 path: '/first-plugin',
14 name: 'first-plugin-route',
15 component: 'my-first-plugin'
16 }
17 ]
18 },
19 getMenuItems() {
20 return [
21 {
22 routeName: 'first-plugin-route',
23 title: 'First Plugin'
24 }
25 ]
26 }
27}

Security

If you try to run this code, the wallet will throw an error because you are accessing features that need permissions. To define which permissions are allowed and you want to use you need to define them in your package.json:

package.json:

1{
2 "name": "my-first-plugin",
3 "version": "0.0.1",
4 "title": "My First Plugin",
5 "description": "Testing my first plugin on Ark Desktop Wallet",
6 "main": "src/index.js",
7 "permissions": [
8 "COMPONENTS",
9 "ROUTES",
10 "MENU_ITEMS"
11 ]
12}

Now you can finally access your component by clicking the side menu button.

Interacting With Data

Each component file can access the global walletApi object that contains some APIs that you can interact directly in the wallet.

Listening Events

Let’s start by watching new transactions (sent or received) on any imported wallet or contact.

To achieve this we need to use the eventBus API:

my-first-plugin.js:

1module.exports = {
2 template: `
3 
4 `,
5 data: () => ({
6 description: 'My first component'
7 }),
8 mounted () {
9 walletApi.eventBus.onAny(eventName => {
10 if (eventName.includes('transaction:new')) {
11 console.log('New transaction!')
12 }
13 })
14 }
15}

eventBus is an emittery instance. You can use its methods provided in the documentation. The wallet triggers an event similar to this wallet:<address>:transaction:new when identifying a new transaction.

Emitting Notifications

Instead of displaying a message on the console you can issue a notification using the alert API:

my-first-plugin.js:

1module.exports = {
2 template: `
3 
4 `,
5 data: () => ({
6 description: 'My first component'
7 }),
8 mounted () {
9 walletApi.eventBus.onAny(eventName => {
10 if (eventName.includes('transaction:new')) {
11 walletApi.alert.info('New transaction!')
12 }
13 })
14 }
15}

It has 4 notification types: info, success, warn and error.

You also need to set the permissions:

package.json:

1{
2 "name": "my-first-plugin",
3 "version": "0.0.1",
4 "title": "My First Plugin",
5 "description": "Testing my first plugin on Ark Desktop Wallet",
6 "main": "src/index.js",
7 "permissions": [
8 "COMPONENTS",
9 "ROUTES",
10 "MENU_ITEMS",
11 "EVENTS",
12 "ALERTS"
13 ]
14}

Limitations

At this point, you probably noticed that you can not run or import everything in your file, this includes the DOM, external packages, node builtin APIs. That is because your plugin is running through a sandbox, all thanks to the vm2 package we are using in Desktop Wallet.

Outro

Congrats you just developed your very first Desktop Wallet plugin! Now it is time to experiment on your own, and don’t forget we have our Development Bounty Program running, you are more than welcomed to jump in any time.

If you want to learn from already developed plugins for the Desktop Wallet, have a look in our official Desktop Plugins repository which currently consists of these plugins:

In the next tutorial we will look develop a custom desktop-wallet theme plugin.

Last updated 2 years ago
Edit Page
Share: