Toward an Interoperable Transaction Interface: Introducing `createTransaction`

TL;DR

The Polkadot.js (PJS onwards) signPayload interface has repeatedly caused ecosystem-wide breakages and friction, it’s tightly coupled to the internals of PJS and can’t fully leverage Extrinsic V5.

We’re proposing a new, documented, library-agnostic function: createTransaction that lives alongside signPayload and enables interoperable tooling across wallets, extensions, DApps, and libraries. RFC here.


Introduction

In this post I’ll explain why the Polkadot.js signer interface that became our ecosystem standard is problematic, especially in the context of Extrinsic V5. I will also propose a practical way forward that preserves backward compatibility while unlocking interoperability.

The status quo

A major issue with PolkadotJS is that its public-facing APIs are tightly coupled to its internal implementation details. This tight coupling makes them non-interoperable.

The two most problematic areas are:

  • The JSON-RPC Provider: for communicating with the network.
  • The PolkadotJS Signers: for creating signed extrinsics.

When we designed PAPI, we made sure that these public interfaces are simple, well-documented, and decoupled from our internals. That way, other tools and libraries can adhere to them, without needing to understand how PAPI works under the hood. This minimalistic approach has proven extremely beneficial for the JSON-RPC Provider, and now it’s time to apply the same thinking to signing.

If we want a healthy and diverse ecosystem, we need new tools and libraries to adhere to clear, interoperable interfaces, and we should gradually migrate PolkadotJS towards those standards.

Why the current interface is problematic

The signPayload interface has been fragile for years. Every time a new extension is added or changed, things break across wallets and dApps. Some concrete issues:

  1. Pre-metadata design
    Its design predates Metadata V14 and only supports a handful of extensions.
  • Adding new signed-extensions (e.g. CheckMetadataHash) has broken nearly every dApp at some point.
  • Parachains cannot realistically define custom extensions.
  • It cannot model versioned extensions, a necessity with Extrinsic V5.
  1. Undocumented and inconsistent
    The payload fields are tied to internal quirks of PolkadotJS, with behaviors that aren’t documented.
  • Example: the blockNumber field is required even for immortal transactions, and must be encoded in big-endian, unlike SCALE which is little-endian.
  • These details aren’t documented anywhere outside the code, forcing developers to guess.
  1. Not ready for Extrinsic V5
    Extrinsic V5 introduces general transactions and versioned extension. signPayload simply cannot handle this evolution, making it a blocker for progress.

Two paths forward

  • Option 1: Patch signPayload again, break dApps again, scramble to fix things again… until the next crisis.
  • Option 2: Define a new, well-documented interface that works for both Extrinsic V4 and V5, leverages metadata, and allows parachains to define their own extensions without hacks.

The PAPI team is committed to Option 2, and we hope the broader ecosystem (Parity, W3F, wallet developers, parachains) will join us.

The proposed solution: createTransaction

When we created PAPI, we didn’t adopt PJS signers, instead we used a simple, SCALE-based interface. This design allows us to:

  • Work with any metadata-defined extensions.
  • Create a wrapper that uses PJS signers behind the scenes while hiding its quirks.
  • Support cutting-edge chains like Proof-of-Personhood and Paseo Kreivo, which already use custom extensions in the case of PoP and general v5 transactions in the case of Paseo Kreivo. It’s worth pointing out that, as of today, no other JS/TS library facilitates the creation of these kinds of extrinsics.

This approach proved robust and inspired the proposal for a broader, ecosystem-wide interface: createTransaction.

The idea is for PolkadotJS Signers to expose a new method alongside signPayload, as detailed in this RFC. Over time, we can encourage DApps and tools to adopt the new method.

Why this matters

Adopting createTransaction gives us:

  • Library-agnostic interoperability: DApps, wallets, and libraries can work together without depending on PolkadotJS internals.
  • Extrinsic V5 support: Including general transactions and versioned extensions (RFC-0099).
  • Metadata-driven flexibility: Parachains can define their own extensions cleanly.
  • Future-proofing: We avoid repeating the painful breakage cycles caused by signPayload.

Call to action

We’re committed (as the PAPI team) to help land this interface and to collaborate with wallets, extensions, and libraries to implement it. We’re happy to implement it in the Polkadot.js extension and provide the necessary libraries to make adoption easy.

Discussion & spec: RFC: Deprecate `signPayload` in favour of new `createTransaction` · Issue #6213 · polkadot-js/api · GitHub
If you maintain a wallet/extension/library or a runtime with custom extensions, we’d love your input.

10 Likes