I am trying to programatically construct the hash as used for multisig transactions, basically the approveAsMulti which taking a call hash.

So my code is along the following form,

/* create the tx */
const inner = api.tx.balances.transfer('1G...', 100000000)

/* generate the hash */
const hash = inner.hash

/* generate the approval */
const multi = api.tx.multisig.approveAsMulti(2, ['1G...', ...], null, hash, weight)

/* send it here ... */

However the hash I generate is not the same hash as what I can see in the UI, so right at the end I cannot actually seem to approve the final step via the UI. So I'm not sure what goes wrong, the hashes should match?

1 Answer 1


The short version: for the call-only part, use inner.method.hash.

(I'll use your same inner naming throughout.)

The longer version: The api.tx construct is representative of an extrinsic, initially when it is created, it is unsigned, once we use inner.signAsync(...) (or inner.signAndSubmit(...)), it is signed. So when you call inner.hash, you actually retrieve the (initially unsigned) extrinsic hash.

Internally an extrinsic represented here has two major parts,

  • the signature (comprising the signing address, actual cryptographic signature and all data from the signed extensions as per the metadata definition)
  • the call (pallet/method index and call data as per metadata)

So after all of this: For the hash of the call-only, access the call via the .method getter and then the .hash on that will return the hash for the call only.

  • Thank you for the detail. Commented Mar 26, 2022 at 5:25

Your Answer

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

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