I want to try out offchain minting feature in pallet_nfts. This extrinsic nfts.mintPreSigned(mintData, signature, signer) should be used to claim the NFT as a final step. Before that, mintData attribute should be signed upfront by the collection owner. How can I do this using polkadot.js UI?

2 Answers 2


In order to sign the mintData object, you would need to get its encoded version first. The easiest way to do this is to open the mintPreSigned extrinsic's form and fill it with the data:

mintPreSigned form

For the signature, select the Sr25519 type and put a dummy signature as the value: 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Now, in the encoded call data field you should see smth like this:


The next step would be to select and copy everything between 0x3425 and 01aaaaaaa.... (it's the encoded mintData object) and prefix that with 0x. If we take the example above that would be 0x7b000000c8010000040c6b65791476616c7565000000000000.

Now, you'll need to sign that string.
For that you could use a subkey sign command, or a simple JS script similar to this:

import { Keyring } from '@polkadot/api';
import { u8aToHex } from '@polkadot/util';

const keyring = new Keyring({ type: 'sr25519' });
const pair = keyring.addFromUri('//Alice');
const sig = pair.sign('0x7b000000c8010000040c6b65791476616c7565000000000000');
console.log('sig hex', u8aToHex(sig));

P.S. Unfortunately, it's not possible to sign that object by using the PolkadotJS Extension or PolkadotJS UI (Developer -> Sign message Page), since it wraps the string you enter with <Bytes></Bytes> which leads to an incorrect signature generated. This was discovered during the writing of this answer. We will try to add the support of both signing methods to the pallet and I will post an update here.

  • Thanks for the detailed answer! Not so obvious to me, but it works :) Looking forward to your updates!
    – Filk
    Apr 20 at 15:39
  • Yeah, that feature really requires a more detailed article :) Pls, let me know if you have more questions or ideas on how to improve the flow. Apr 20 at 16:32
  • P. S. The fix was merged to the master branch today (github.com/paritytech/substrate/pull/13960). If the node is launched locally, it is possible to sign the data object from the Developer -> Sign and verify page in PolkadotJS. For the Westmint, we would need to wait till that fix gets released. Apr 20 at 16:35

Offchain minting is a feature built into the NFTs pallet. It is the ability to mint NFTs by having the issuer of a collection sign encoded mint data offchain, this encoded mint data will either designate the account that can mint the NFT or if any account can mint it. Once signed by the issuer, the enduser can mint the NFT onchain via the mint_pre_signed extrinsic.

Okay.. so how do we do this in Substrate?

Follow these steps.

First we have to create an NFT collection.

Encoded call data:


Next we have to do three things:

  • create our mint data (this will be the NFT we want to be minted)
  • encode the mint data
  • sign the encoded mint data
    • the account that signs the encoded mint data should be an issuer for the collection, meaning, they have approval to mint

Note: when creating the mint data, if you only intend one account to have permission to mint that NFT then specify this in the only_account attribute otherwise, any account will be able to mint the NFT.

We can use PolkadotJs Apps to construct the mint data like so:

We are not going to submit this transaction. We are only using it to obtain the encoded mint data. You could also construct this using JavaScript and PolkadotJS API or similar.

Keep in mind that onlyAccount here is set to None. This means that any account that has access to this mint data, once it is signed, could mint this NFT.

For deadline specify the block number where this transaction will be valid for. The transaction will be valid up to this block number.

Notice the encoding details on the bottom right of the screen.

From that we can concatenate and construct our encoded mint data:


We now have to sign the encoded mint data.

Alternatively, here is a nice script:

import { Keyring } from '@polkadot/keyring';
import { u8aToHex } from '@polkadot/util';
import { cryptoWaitReady } from '@polkadot/util-crypto';

export const sign = async () => {
    await cryptoWaitReady();

    const keyring = new Keyring({ type: 'sr25519' });
    const pair = keyring.addFromUri('//Alice');
    const sig = pair.sign('0x000000000000000004106e616d65304272756e6f2047616c76616f0000d0070000');
    console.log('Signature: ', u8aToHex(sig));


Signature:  0x163b1eb3420cf2b78b4ffedca11e9618dd8528e6e7485cb343379d9db6aa84305f9995b6bf2120d4541d36a9056f6a158ccc5e8745794657073ae23cb3de838f

We can now create the mintPreSigned extrinsic and include our signature:

Click "Submit Transaction" and you have now minted a crisp, fresh NFT.

Success! Done.


Offchain Minting PR

Test for offchain minting (super useful to read):

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.