1

I try to implement How do I get the Result of a Sudo event? in a function shown below. It's mostly an exact copy from the cookbook with some boilerplate.

export const sudo = async (
    api: ApiPromise,
    signer: KeyringPair,
    call: any,
): Promise<SubmittableResult> => {
    return new Promise(async (resolve, reject) => {
        const result = await api.tx.sudo.sudo(call).signAndSend(signer,
                                                           (result) =>
            {
                if (result.status.isInBlock || result.status.isFinalized) {
                  
                    //explain the error from the function executed by sudo
                    result.events
                        // We know this tx should result in `Sudid` event.
                        .filter(({ event }) => api.events.sudo.Sudid.is(event))
                        // We know that `Sudid` returns just a `Result`
                        .forEach(({ event : { data: [result] } }) => {
                            // Now we look to see if the extrinsic was actually successful or not...
                            if (result.isError) {
                                let error = result.asError;
                                if (error.isModule) {
                                    // for module errors, we have the section indexed, lookup
                                    const decoded = api.registry.findMetaError(error.asModule);
                                    const { docs, name, section } = decoded;

                                    console.log(`${section}.${name}: ${docs.join(' ')}`);
                                } else {
                                    // Other, CannotLookup, BadOrigin, no extra info
                                    console.log(error.toString());
                                }
                            }
                        });

                    resolve(result);
                } else if (result.status.isInvalid) {
                    reject(new Error(`Extrinsic isInvalid`));
                } else if (result.dispatchError) {
                    reject(new Error(`Dispatch error: ${result.dispatchError}`));
                } else if (result.internalError) {
                    reject(new Error(`Internal error: ${result.internalError}`));
                }
            });
    });
};

but get the following compilation error

 if (result.isError) {

 error TS2339: Property 'isError' does not exist on type 'Codec'.

When I use a similar construct for regular transactions, it works as expected.

1 Answer 1

2

Looking into it a bit, it seems that the Sudid event is not plainly a RuntimeError, maybe it was in the past but not anymore. It's an event with payload. You need to extract the actual RuntimeError from a payload called sudoResult from the Sudid events payload.

Sudid Event of the Events Enum of the pallet_sudo: https://github.com/paritytech/polkadot-sdk/blob/e2caa813bfd2973e7a7a74aa5292433397dbc787/substrate/frame/sudo/src/lib.rs#L302-L306

Here is an adapted piece of code how to do it.

const unsubscribe = await api.tx.sudo
  .sudo(api.tx.balances.forceTransfer(user1, user2, amount))
  .signAndSend(keyring.createFromUri("//Alice"), ({ status, events }) => {
    switch (status.type) {
      case "Finalized":
      case "InBlock":
        {
          if (status.isInBlock) {
            console.log("Transaction included at blockHash", status.asInBlock);
          }

          events.forEach((record) => {
            if (api.events.sudo.Sudid.is(record.event)) {

              // NEW PART:
              if (record.event.data.sudoResult.isErr) {

                // SAME PART AS IN DOCS:
                let error = record.event.data.sudoResult.asErr;
                if (error.isModule) {
                  // for module errors, we have the section indexed, lookup
                  const decoded = api.registry.findMetaError(error.asModule);
                  const { docs, name, section } = decoded;

                  console.log(`${section}.${name}: ${docs.join(" ")}`);
                } else {
                  // Other, CannotLookup, BadOrigin, no extra info
                  console.log(error.toString());
                }
              }
              return record.event;
            }
          });
        }
        break;
      default:
        break;
    }
  });

The docs are surely outdated here, I will create a PR to make it work again. Hope this helps.

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.