Cookbook

A set of code snippets ready to be used.

Get all extensions accounts

A dapp will not be aware whether or not the user has the extension installed on their browser until the web3Enable function is called. Calling this function returns the amount of extensions installed and for which the user has accepted to share their accounts. Using web3Accounts, you can then retrieve the visible accounts. See below for web3AccountsSubscribe usage.

import { web3Accounts, web3Enable } from '@polkadot/extension-dapp';
// this call fires up the authorization popup
const extensions = await web3Enable('my cool dapp');
if (extensions.length === 0) {
// no extension installed, or the user did not accept the authorization
// in this case we should inform the use and give a link to the extension
return;
}
// we are now informed that the user has at least one extension and that we
// will be able to show and use accounts
const allAccounts = await web3Accounts();

Sign a message

Here is an example on how to sign a message with an account that was injected by the extension.

// We arbitraily select the first account returned from the above snippet
// `account` is of type InjectedAccountWithMeta
const account = allAccount[0];
// to be able to retrieve the signer interface from this account
// we can use web3FromSource which will return an InjectedExtension type
const injector = await web3FromSource(account.meta.source);
// this injector object has a signer and a signRaw method
// to be able to sign raw bytes
const signRaw = injector?.signer?.signRaw;
if (!!signRaw) {
// after making sure that signRaw is defined
// we can use it to sign our message
const { signature } = await signRaw({
account.address,
data: stringToHex('message to sign'),
type: 'bytes'
});
}

Head to the relevant util-crypto example to see how to verify a signature.

Sign and send a transaction

The api is able to retrieve the signer when signAndSend is called with the address from an account retrieved from the extension.

// We arbitraily select the first account returned from the above snippet
// `account` is of type InjectedAccountWithMeta
const account = allAccount[0];
// here we use the api to create a balance transfer to some account of a value of 12344
const transferExtrinsic = api.tx.balances.transfer('5C5555yEXUcmEJ5kkcCMvdZjUo7NGJiQJMS7vZXEeoMhj3VQ', 123456)
// to be able to retrieve the signer interface from this account
// we can use web3FromSource which will return an InjectedExtension type
const injector = await web3FromSource(account.meta.source);
// passing the injected account address as the first argument of signAndSend
// will allow the api to retrieve the signer and the user will see the extension
// popup asking to sign the balance transfer transaction
transferExtrinsic.signAndSend(account.address, { signer: injector.signer }, ({ status }) => {
if (status.isInBlock) {
console.log(`Completed at block hash #${status.asInBlock.toString()}`);
} else {
console.log(`Current status: ${status.type}`);
}
}).catch((error: any) => {
console.log(':( transaction failed', error);
});

Subscription to extensions' accounts

Using web3AccountsSubscribe similarly as what we did above with web3Accounts allows to get all injected accounts, in this case though because we use a subscription, we will be aware of any account change.

import { web3AccountsSubscribe, web3Enable } from '@polkadot/extension-dapp';
// this call fires up the authorization popup
const extensions = await web3Enable('my cool dapp');
if (extensions.length === 0) {
// no extension installed, or the user did not accept the authorization
// in this case we should inform the use and give a link to the extension
return;
}
// we are now informed that the user has at least one extension and that we
// will be able to show and use accounts
let unsubscribe; // this is the function of type `() => void` that should be called to unsubscribe
// we subscribe to any account change and log the new list.
// note that `web3AccountsSubscribe` returns the function to unsubscribe
unsubscribe = await web3AccountsSubscribe(( injectedAccounts ) => {
injectedAccounts.map(( accounts ) => {
console.log(account.address);
})
});
// don't forget to unsubscribe when needed, e.g when unmounting a component
unsubscribe && unsubscribe();