3

I am generating a partial unsigned extrinsic via subxt however cannot figure how to how to sign it using the polkadot.js api. For example:


#[subxt::subxt(runtime_metadata_path = "polkadot_metadata.scale")]
pub mod polkadot {}

...

let dest = AccountId32::from([0; 32]);

let api = OnlineClient::<PolkadotConfig>::from_url("wss://rpc.polkadot.io:443").await?;

let tx = polkadot::tx()
    .balances()
    .transfer(MultiAddress::Address32([1; 32]), 123_456_789_012_345);

let partial_extrinsic = api
    .tx()
    .create_partial_signed(&tx, &dest, Default::default())
    .await
    .unwrap();

let signer_payload: Vec<u8> = partial_extrinsic.signer_payload();

// hand signer_payload off to browser

The signer_payload being:

[5, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 11, 121, 223, 13, 134, 72, 112, 0, 0, 0, 154, 36, 0, 0, 20, 0, 0, 0, 145, 177, 113, 187, 21, 142, 45, 56, 72, 250, 35, 169, 241, 194, 81, 130, 251, 142, 32, 49, 59, 44, 30, 180, 146, 25, 218, 122, 112, 206, 144, 195, 145, 177, 113, 187, 21, 142, 45, 56, 72, 250, 35, 169, 241, 194, 81, 130, 251, 142, 32, 49, 59, 44, 30, 180, 146, 25, 218, 122, 112, 206, 144, 195]

And in the browser:

let api = await ApiPromise.create({
  provider: new WsProvider("wss://rpc.polkadot.io:443"),
});
let injector = await web3FromAddress(address);
const signerPayload = api.createType("SignerPayload", u8aToHex(signer_payload));
await injector.signer.signPayload(signerPayload.toPayload());

Js is erroring with:

Error: createType(SignerPayload):: decodeU8aStruct: failed at 0x70ce90c391b171bb158e2d3848fa23a9… on address (index 8/13): {"_enum":{"Id":"AccountId","Index":"Compact<AccountIndex>","Raw":"Bytes","Address32":"H256","Address20":"H160"}}:: Unable to create Enum via index 112, in Id, Index, Raw, Address32, Address20

If I instead use this tx (as a simpler example):

let tx = polkadot::tx().system().remark("hello".into());

The signer_payload is correctly parsed, however the address is unusable and errors when trying to sign.

{
  "era": {
    "immortalEra": "0x00"
  },
  "nonce": 0,
  "tip": 5,
  "specVersion": 1819043176,
  "transactionVersion": 111,
  "genesisHash": "0x9a2400001400000091b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb4",
  "blockHash": "0x9219da7a70ce90c391b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb4",
  "address": {
    "index": "1HV2wGCy"
  },
  "blockNumber": 50064,
  "method": {
    "callIndex": "0x0000",
    "args": {
      "remark": "0x"
    }
  },
  "runtimeVersion": {
    "specName": "",
    "implName": "",
    "authoringVersion": 0,
    "specVersion": 0,
    "implVersion": 0,
    "apis": [],
    "transactionVersion": 0,
    "stateVersion": 0
  },
  "signedExtensions": [],
  "version": 0
}

How do I correctly use the generated signer_payload from subxt with polkadot.js? I've tried manually overriding some of the values in the payload:

let payload = signerPayload.toPayload();
payload.address = "15LzmxXr1rztdAzVq5mMWjoFSdFZfrbXSKsASqEaKP3qHnbE";     
payload.version = 4;

But the polkadot extension errors with Cannot read properties of undefined (reading 'isImmortalEra')

1
  • I'm not super familiar with the Polkadot.js interface so I can't be much help there I'm afraid, but I note that the "signer_payload" JSON you printed doesn't look to be correctly parsed; it looks like almost everything is just at some default value (and your remark itself is lost).
    – jsdw
    May 2 at 10:23

0

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.