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
import Component from "flarum/Component"; import Dropdown from "flarum/components/Dropdown"; export default class Web3Dropdown extends Component view() return ( <Dropdown buttonClassName="Button" onclick=this.handleClick.bind(this) label="Add Web3 Account" > </Dropdown> ); handleClick(e) 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:
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(); console.log(accounts);
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
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.
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(); console.log(accounts); else window.location = "https://github.com/polkadot-js/extension";
Extending Flarum: Adding a Web3 Address to a User’s Profile