4

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, 2023 at 10:23

1 Answer 1

0

I solved this by manually constructing the payload in JS and creating a signed extrinsic to then pass back to subxt. There seems to be an issue between the partial extrinsic format and what polkadot.js expects.

For reference, here's an example where most of the work is still done in subxt:

https://github.com/paritytech/subxt/blob/tadeo-hepperle-browser-extension-signing-example/examples/wasm-example/src/services.rs#L130

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.