Signer
Introduction
Section titled “Introduction”@parity/product-sdk-signer handles account discovery, selection, and signing, decoupled from where the keys actually live. Your Product talks to one class, SignerManager, and the same call sites work whether signing routes to the user's Polkadot App in production or to local dev accounts in a test.
Every fallible method returns a typed Result, so you check .ok before reading .value rather than wrapping calls in try/catch.
When to Use It
Section titled “When to Use It”- Whenever your Product needs to discover accounts, select one, and obtain a
PolkadotSignerto sign transactions or raw bytes. - To manage the connection lifecycle: connect, disconnect, subscribe to state changes, and run once-per-session setup through the
onConnecthook (for example, requesting permissions). - Use the host provider for real signing on Polkadot Desktop and the Polkadot App; use the dev provider for tests with well-known accounts such as Alice and Bob.
- The product-account and Ring-VRF methods are Host-only; they return
HostUnavailableErrorunder the dev provider.
Core Concepts
Section titled “Core Concepts”SignerManager: The central class. It wraps one or more providers behind aResult-typed API and holds aSignerStatethat it pushes to subscribers.Result,ok,err: The return idiom across the package. Branch onres.ok, then readres.valueorres.error; only unexpected internal failures throw.SignerAccount: A signing-capable account. It exposes the SS58address, the EVM-derivedh160Address(forpallet-revive), thepublicKey, an optionalname, andgetSigner().- Host vs dev providers:
connect()defaults to the Host;connect('dev')loads well-known dev accounts locally, so no Host is needed for tests. onConnectandsubscribe:subscribefires on every state change;onConnectfires exactly once per transition into the connected state (and again after an auto-reconnect), which is where you request resources up front.- Product accounts:
getProductAccount(dotNsIdentifier, derivationIndex)returns a per-Product account the Host derives, so different Products get different addresses for the same user. This is a Host-only API.
Connect and Sign Raw Bytes
Section titled “Connect and Sign Raw Bytes”Construct the manager once, connect, select an account, and sign. Each step returns a Result:
import { SignerManager } from '@parity/product-sdk-signer';
async function signHello() { const manager = new SignerManager({ ss58Prefix: 0, dappName: 'my-product' });
const connectResult = await manager.connect(); if (!connectResult.ok) return; // HostUnavailableError outside a Host
const [account] = connectResult.value; if (!account) return; // connected, but the Host returned no accounts
manager.selectAccount(account.address);
const signature = await manager.signRaw(new TextEncoder().encode('hello')); if (signature.ok) { console.log(signature.value); // Uint8Array }}Request Permissions Once Per Session
Section titled “Request Permissions Once Per Session”Use the onConnect hook to request resource allocations as soon as the connection is established, before any signing call. Unlike the rest of the package, requestResourceAllocation throws rather than returning a Result, so guard it:
import { SignerManager } from '@parity/product-sdk-signer';
const manager = new SignerManager({ ss58Prefix: 0, dappName: 'my-product', onConnect: async (_account, { requestResourceAllocation, signal }) => { try { const outcomes = await requestResourceAllocation([ { tag: 'BulletinAllowance', value: undefined }, ]); if (signal.aborted) return; // user disconnected mid-request if (outcomes.some((outcome) => outcome !== 'Allocated')) { // Degrade gracefully: treat the capability as unavailable, not fatal. } } catch (cause) { // Typed host error — the connection itself is unaffected. } },});Three things that example is doing deliberately:
try/catch:requestResourceAllocationadapts the Host'sResult-returning call into a throwing one, so an unguardedawaitcan throw insideonConnect. Errors thrown here are logged and do not break the connected state, but you lose the chance to react.signal.aborted: TheAbortSignalfires if the user disconnects or the manager is destroyed while the request is still in flight. Check it before acting on the outcomes.- Checking the outcomes: Each is
'Allocated','Rejected', or'NotAvailable'— bare strings here, unlike the tagged objects theauthpackage returns. See Allowances and Permissions for what each resource authorizes.
Limitations
Section titled “Limitations”- Most methods return a
Result; branch on.ok. Only terminal conditions such as calling a destroyed manager surface as thrown errors. destroy()is terminal: later calls returnDestroyedError. Usedisconnect()for a reversible reset.subscribedoes not prime with the current state; callgetState()for the initial read, and useonConnectfor once-per-connect logic.getProductAccount,getProductAccountAlias,createRingVRFProof, andgetUserIdare Host-only.
Where to Go Next
Section titled “Where to Go Next”-
Sign and Submit Transactions
The task-focused recipe: derive a product account, sign, and submit a transaction end to end.
-
Transactions
Take the signer this package produces and submit and track a transaction to finality.
-
API Reference
The complete
signersurface:SignerManager,SignerAccount, providers, and the error hierarchy.