fix: terminal papi native signer#81
Merged
Merged
Conversation
📦 Bundle size impactComparing No size changes detected. 🟢 |
TarikGul
approved these changes
May 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #80 (
PJS does not support this signed-extension: AsPgasindot init).Swaps
getPolkadotSignerFromPjsfor PAPI-nativegetPolkadotSignerinpackages/terminal/src/signer.ts. Transaction signing now routes throughsession.signRaw({ data: { tag: "Payload", value: hex(toSign) } })- an opaque-bytes wire route that already exists in@novasamatech/host-papp0.7.7. polkadot-api assemblescallData ‖ extras ‖ additionalSignedsfor every signed extension declared by the runtime, and the wallet just signs the resulting bytes. Any extension carried by the chain - including ones polkadot-api's PJS adapter doesn't have a built-in mapper for (AsPgason Paseo Next v2, future runtime extensions) - survives end-to-end.Root cause
Two stacked limitations on the previous path:
@polkadot-api/pjs-signerhard-throws on any signed extension without a built-in mapper. The mapper table covers eight extensions only (CheckGenesis,CheckNonce,CheckTxVersion,CheckMortality,CheckSpecVersion,ChargeAssetTxPayment,ChargeTransactionPayment,CheckMetadataHash).AsPgasisn't in that list.host-papp'sSigningPayloadRequestcodec has fixed slots (era,nonce,tip,assetId,metadataHash,mode, …) andsignedExtensions: Vector(str)- names only, no payload bytes. Even if PJS were patched to passAsPgasthrough, the wire format itself can't carry the extension'sextraandadditionalSignedbytes.The
Payload-tag route onsession.signRawis a tagged-bytes channel the upstream@novasamatech/product-sdkalready uses for non-bytes-typed raw requests, so the wallet code path is exercised in the field.Changes
packages/terminal/src/signer.ts- replaces PJS-bridged construction withgetPolkadotSigner(publicKey, "Sr25519", sign).signBytesis overridden post-construction to keep theBytes-tag route (so the wallet's<Bytes>...</Bytes>anti-phishing wrap applies exactly once to arbitrary-data signing, not to tx signing).packages/terminal/README.md- updates the Signing section to document the new wire path and the AsPgas fix.Two tiny helpers (
makeTxSignCallback,makeRawBytesSignCallback) replace the previous PJS field-translation glue and are unit-tested directly. Net diff: +150 / −288 lines (refactor reduces the file because the PJS field-translation glue is gone).What this does not fix (explicit scope)
This PR fixes the terminal/QR-paired flow only (
createSessionSigner/createSessionSignerForAccount). The in-host signer path -packages/signer/src/providers/host.tscallingaccountsProvider.getProductAccountSigner()from@novasamatech/product-sdk- stays PJS-bridged and will still throwPJS does not support this signed-extension: <name>for arbitrary extensions until two things happen upstream:paritytech/triangle-js-sdks#168merges - adds asignerType: 'createTransaction'option togetProductAccountSignerthat builds a PAPI-native signer routing through the newhost_create_transactionRPC.@novasamatech/product-sdkto the release containing that change and flip the option inpackages/signer/src/providers/host.ts.The upstream PR is currently OPEN, mergeable, awaiting review. The follow-up here is effectively one line per call site once it ships.
Consumer impact in the meantime: apps using
createSessionSigner(CLI/QR-paired) are unblocked by this PR. Apps reaching mobile signing via the in-hosthostprovider still hit the original error on AsPgas-bearing extrinsics.playground-cliusescreateSessionSignerForAccount, sodot initis covered.Validation
pnpm check(biome lint + format, 205 files) - cleanpnpm build(all packages + examples) - passpnpm test- 725 tests across 14 packages, 0 failurespackages/terminal/src/signer.tscovering the new wire path and regression guards against the legacysignPayloadcallpnpm exec tsc --noEmit(terminal package) - cleanTest plan
pnpm check(biome) — cleanpnpm build(all packages + examples) - passpnpm test— 725/725 across 14 packages