Extending Flarum: Adding a Web3 Address to a User's Profile

Flarum is incredibly fast, extensible, free and open-source forum software. In our first Flarum tutorial — “Writing a Flarum Extension: Building a Custom Field” — we covered how to add a new custom field to a user’s profile in a blazing fast and extremely extensible open-source forum software called Flarum. The field we added was web3address, the account of a user’s Web3 identity.

In this second tutorial, we take things a step further by allowing users to add a Web3 address to their profile.

Note ℹ: The Web3 ecosystem is a new internet of decentralized hosting, self-owned data, and censorship-resistant communication. For a primer on Web3, please see this 15 minute talk at FOSDEM.

Cryptographically Adding Web3

At this point, our custom field works, is settable by users, and is editable by administrators of the forum. Now let’s make sure users can add their address in a cryptographically sound way.

This means a user will only be able to add an address they have proven to own. You prove ownership of an address by signing a message with that address’ private key. Only the person who has the private key of a public–private keypair is considered to be the owner of that keypair. The public part of a public–private keypair is the base from which a Web3 address is mathematically derived.

To own some address(es), a user should install the Polkadot JS extension and create an account. The UI should be self-explanatory, but there’s a more detailed guide here if needed.

The field we added in the previous tutorial currently lets users manually set any value, but this means users can enter anyone’s address or even some gibberish. We want them to only add their own, so we’ll replace it with a button that will:

  • ask for permission to access the browser extension containing the account(s)
  • load the accounts and offer a dropdown to select one of them
  • ask the user to sign a message with that address and verify that signature
  • register that account as the user’s Web3 address

Let’s dive in.


First we need to change our Web3 input field into a Dropdown. Let’s create components/Web3Dropdown.js:

import Component from "flarum/Component";
import Dropdown from "flarum/components/Dropdown";

export default class Web3Dropdown extends Component 
    return (
        label="Add Web3 Account"

    console.log("Pick something");

We create a new component in the style of Web3Field.js we created earlier, but now we return an instance of the Dropdown component. The Dropdown component is one of several standard JS components in Flarum. You can find a full list here. We also give it the class “Button” to match its style with the rest of the forum. On click, we print a message.

The component is a button with the ability to summon a dropdown from passed-in items, much like the “Controls” menu that an admin of the forum can see on a user’s profile:

the simple button


In our extension’s JS folder, we’ll add two dependencies:

yarn add @polkadot/util-crypto @polkadot/util @polkadot/extension-dapp

Note ⚠: don’t forget to stop the process if you’re still running yarn dev and don’t forget to start it again after having installed these dependencies!

util-crypto contains some utility functions for cryptographic operations.util contains some basic utilities, like turning strings into bytes etc. (There are docs for both here.) extension-dapp is a helper layer that lets the JS we write interact with the Polkadot JS extension we’ve installed. (Visit the docs here.)

Asking Permission and Getting Accounts

Let’s modify our Dropdown now to ask the user for permission to access their Web3 accounts:

  import  web3Accounts, web3Enable  from "@polkadot/extension-dapp";

  // ...

  async handleClick(e) 
    await web3Enable("Flarum Web3 Address Extension");
    const accounts = await web3Accounts();

Notice that we changed the handleClick function to be async! We need this to be able to await promises in the code. Otherwise, we’d get stuck with nesting then calls.

First we call web3Enable, which asks us for permission to access the extension. Then we grab all of a user’s accounts and output them in the console. If you have the Polkadot JS extension installed and some accounts loaded, feel free to try this out now.

Authorize or reject

Output in the console

But what if someone doesn’t have the extension installed? We could have an admin-level setting which lets us choose whether to hide the button if the extension isn’t around or to redirect the user to its URL, but for now, let’s choose the latter:

  import  web3Accounts, web3Enable, isWeb3Injected  from "@polkadot/extension-dapp";

  // ...

  async handleClick(e) 
    await web3Enable("Flarum Web3 Address Extension");
    if (isWeb3Injected) 
      const accounts = await web3Accounts();
      window.location = "https://github.com/polkadot-js/extension";

Continue reading
Extending Flarum: Adding a Web3 Address to a User’s Profile
on SitePoint.