Skip to Content
API Reference@parity/product-sdk-signerOverview

@parity/product-sdk-signer

Account connection and signing, decoupled from where the keys actually live.

SignerManager wraps one or more SignerProvider implementations behind a Result-typed API for connecting, listing accounts, and reacting to status or account changes. The two built-in providers — HostProvider (Polkadot Desktop/Mobile) and DevProvider (the well-known Alice/Bob accounts) — let the same call sites work in production and in tests.

npm install @parity/product-sdk-signer

Exports

Classes

NameSummary
AccountNotFoundErrorAn account was not found by address.
DestroyedErrorThe SignerManager has been destroyed and is no longer usable.
DevProviderProvider for Substrate development accounts.
HostDisconnectedErrorThe host connection was lost.
HostProviderProvider for the Host API (Polkadot Desktop / Android).
HostRejectedErrorThe host rejected the account or signing request.
HostUnavailableErrorThe Host API is not available (product-sdk not installed or not inside a container).
NoAccountsErrorNo accounts available from the provider.
SignerErrorBase class for all signer errors. Use instanceof SignerError to catch any signer-related error.
SignerManagerCore orchestrator for signer management.
SigningFailedErrorA signing operation failed.
TimeoutErrorAn operation timed out.

Functions

NameSummary
err()Create a failed Result.
isHostError()Check if a SignerError is a host-related error.
ok()Create a successful Result.
sleep()Sleep for a given duration, cancellable via AbortSignal.
withRetry()Retry an async operation with exponential backoff.

Interfaces

NameSummary
AccountPersistenceAdapter for persisting the selected account address across sessions.
ConnectContextContext passed to the onConnect callback.
ContextualAliasA contextual alias obtained from Ring VRF.
DevProviderOptionsOptions for the dev account provider.
HostProviderOptionsOptions for the Host API provider.
ProductAccountA product account — an app-scoped derived account managed by the host wallet.
RetryOptionsOptions for retry with exponential backoff.
RingLocationLocation of a Ring VRF ring on-chain.
SignerAccountA signing-capable account from any provider.
SignerManagerOptionsOptions for SignerManager construction.
SignerProviderInterface that all signer providers must implement.
SignerStateFull state snapshot emitted to subscribers.

Type Aliases

NameSummary
ConnectionStatusConnection status for a signer provider.
DevAccountNameA well-known Substrate development account name (Alice, Bob, …) used to derive deterministic dev accounts from the standard Substrate dev mnemonic.
DevKeyTypeSupported key types for dev account derivation.
OnConnectCallback signature for SignerManagerOptions.onConnect.
ProviderFactoryFactory function that creates a SignerProvider for a given type.
ProviderTypeIdentifies the source of an account.
ResultLightweight Result type for operations that can fail expectedly.
UnsubscribeFunction that unsubscribes a listener when called.

Classes

class AccountNotFoundError

An account was not found by address.

Extends: SignerError

Constructors

constructor
new AccountNotFoundError(address: string): AccountNotFoundError

Properties

address
propertyreadonlystring

class DestroyedError

The SignerManager has been destroyed and is no longer usable.

Extends: SignerError

Constructors

constructor
new DestroyedError(): DestroyedError

class DevProvider

Provider for Substrate development accounts.

Uses the well-known DEV_PHRASE with hard derivation paths (//Alice, //Bob, etc.) to create deterministic accounts for local development and testing.

Implements: SignerProvider

Constructors

constructor
new DevProvider(options?: DevProviderOptions): DevProvider

Properties

type
propertyreadonly"dev"

Unique identifier for this provider type.

Methods

connect

Attempt to connect and discover accounts.

connect(): Promise<Result<SignerAccount[], SignerError>>
Returns

Accounts on success, typed error on failure.

disconnect

Disconnect and clean up resources. Safe to call multiple times.

disconnect(): void
onAccountsChange

Subscribe to account list changes.

Emitted when the set of available accounts changes (e.g., user connects/disconnects in the host wallet).

onAccountsChange(_callback: (accounts: SignerAccount[]) => void): Unsubscribe
Returns

Unsubscribe function.

onStatusChange

Subscribe to connection status changes.

Not all providers emit status changes — for example, dev accounts are always “connected” and never emit.

onStatusChange(_callback: (status: "disconnected" | "connecting" | "connected") => void): Unsubscribe
Returns

Unsubscribe function.

class HostDisconnectedError

The host connection was lost.

Extends: SignerError

Constructors

constructor
new HostDisconnectedError(message: string = "Host connection lost"): HostDisconnectedError

class HostProvider

Provider for the Host API (Polkadot Desktop / Android).

Dynamically imports @novasamatech/host-api-wrapper at runtime so it remains an optional peer dependency. Apps running outside a host container will gracefully get a HOST_UNAVAILABLE error.

Supports both non-product accounts (user’s external wallets) and product accounts (app-scoped derived accounts managed by the host).

Implements: SignerProvider

Constructors

constructor
new HostProvider(options?: HostProviderOptions): HostProvider

Properties

type
propertyreadonlyProviderType

Unique identifier for this provider type.

Methods

connect

Attempt to connect and discover accounts.

connect(signal?: AbortSignal): Promise<Result<SignerAccount[], SignerError>>
Parameters
  • signal: Optional AbortSignal to cancel the connection attempt.
Returns

Accounts on success, typed error on failure.

createRingVRFProof

Create a Ring VRF proof for anonymous operations.

Proves that the signer is a member of the ring at the given location without revealing which member. Used for privacy-preserving protocols.

Requires a prior successful connect() call.

createRingVRFProof(dotNsIdentifier: string, derivationIndex: number, location: RingLocation, message: Uint8Array): Promise<Result<Uint8Array<ArrayBufferLike>, SignerError>>
disconnect

Disconnect and clean up resources. Safe to call multiple times.

disconnect(): void
getProductAccount

Get an app-scoped product account from the host.

Product accounts are derived by the host wallet for each app, identified by dotNsIdentifier (e.g., “mark3t.dot”). The user controls these accounts but they are scoped to the requesting app.

Requires a prior successful connect() call.

getProductAccount(dotNsIdentifier: string, derivationIndex: number = 0): Promise<Result<SignerAccount, SignerError>>
getProductAccountAlias

Get a contextual alias for a product account via Ring VRF.

Aliases prove account membership in a ring without revealing which account produced the alias.

Requires a prior successful connect() call.

getProductAccountAlias(dotNsIdentifier: string, derivationIndex: number = 0): Promise<Result<ContextualAlias, SignerError>>
getProductAccountSigner

Get a PolkadotSigner for a product account.

Convenience method for when you already have the product account details. Requires a prior successful connect() call.

Routing is pinned to signerType: "createTransaction" via PRODUCT_SIGNER_TYPE so unknown signed extensions (e.g. AsPgas on Paseo Next) are forwarded to the host as opaque bytes for metadata-driven decoding, rather than going through the PJS bridge that throws on unknown extensions.

getProductAccountSigner(account: ProductAccount): PolkadotSigner
onAccountsChange

Subscribe to account list changes.

Emitted when the set of available accounts changes (e.g., user connects/disconnects in the host wallet).

onAccountsChange(callback: (accounts: SignerAccount[]) => void): Unsubscribe
Returns

Unsubscribe function.

onStatusChange

Subscribe to connection status changes.

Not all providers emit status changes — for example, dev accounts are always “connected” and never emit.

onStatusChange(callback: (status: ConnectionStatus) => void): Unsubscribe
Returns

Unsubscribe function.

class HostRejectedError

The host rejected the account or signing request.

Extends: SignerError

Constructors

constructor
new HostRejectedError(message: string = "Host rejected the request"): HostRejectedError

class HostUnavailableError

The Host API is not available (product-sdk not installed or not inside a container).

Extends: SignerError

Constructors

constructor
new HostUnavailableError(message: string = "Host API is not available"): HostUnavailableError

class NoAccountsError

No accounts available from the provider.

Extends: SignerError

Constructors

constructor
new NoAccountsError(provider: ProviderType, message?: string): NoAccountsError

Properties

provider
propertyreadonlyProviderType

class SignerError

Base class for all signer errors. Use instanceof SignerError to catch any signer-related error.

Extends: Error

Constructors

constructor
new SignerError(message: string, options?: ErrorOptions): SignerError

class SignerManager

Core orchestrator for signer management.

Manages account discovery and signer creation via the Host API. Framework-agnostic — use the subscribe() pattern to integrate with React, Vue, or any framework.

Lifecycle

disconnected → connecting → connected ──── selectAccount / signRaw / … ▲ │ │ │ ▼ ▼ └── disconnect() provider drops → auto-reconnect → connected (onConnect re-fires) ┌─ destroy() ──► (terminal — manager unusable)

Callbacks

  • subscribe(cb) fires synchronously on every state mutation, in registration order, inside the call stack that mutated state. It does not fire with the initial state — call getState() if you need a priming read. Multiple mutations during the same operation produce multiple notifications.

  • onConnect(account, ctx) (from SignerManagerOptions) fires exactly when the manager transitions from non-connected to "connected" with a selected account. It fires on a microtask after the subscribe notification, so subscribers always observe state.status === "connected" before onConnect’s side effects run. It re-fires after auto-reconnect (the SDK reconnects automatically when the provider drops), and re-fires after a fresh connect().

  • Internal onAccountsChange wiring is worth a behavioral note: when the provider reports an updated account list, the manager preserves the current selection if its address is still present, or sets selectedAccount to null if it isn’t — it does not fall back to accounts[0]. The fallback-to-first only applies on connect-success, where there is no prior selection to preserve.

disconnect() vs destroy()

  • disconnect() resets state to initial. Subsequent connect() calls work normally. Reversible.
  • destroy() is terminal: the instance is marked unusable, all subscribers are cleared, and any further call returns DestroyedError. Use in framework teardown (React useEffect cleanup, HMR dispose).

Both methods cancel any in-flight connect, reconnect attempt, and onConnect callback (the ctx.signal becomes aborted).

Examples

const manager = new SignerManager({ onConnect: async (_account, { requestResourceAllocation }) => { await requestResourceAllocation([{ tag: "AutoSigning", value: undefined }]); }, }); manager.subscribe(state => console.log(state.status)); await manager.connect(); // host provider (default) await manager.connect("dev"); // Alice / Bob / … for testing manager.selectAccount("5GrwvaEF…"); const signer = manager.getSigner();

Constructors

constructor
new SignerManager(options?: SignerManagerOptions): SignerManager

Methods

connect

Connect to a provider.

If no provider type is specified, connects to the Host API. The SDK is designed to run exclusively inside a host container.

When connecting to a specific provider type:

  • "host": Connect to the Host API (default, recommended)
  • "dev": Connect using dev accounts (for testing)
connect(providerType?: ProviderType): Promise<Result<SignerAccount[], SignerError>>
createRingVRFProof

Create a Ring VRF proof for anonymous operations.

Proves that the signer is a member of the ring at the given location without revealing which member. Only available when connected via the host provider — returns HOST_UNAVAILABLE otherwise.

createRingVRFProof(dotNsIdentifier: string, derivationIndex: number, location: RingLocation, message: Uint8Array): Promise<Result<Uint8Array<ArrayBufferLike>, SignerError>>
destroy

Destroy the manager and release all resources.

Terminal — clears all subscribers, cancels in-flight work, and marks the instance unusable. Any subsequent method returns DestroyedError. Idempotent. Use in framework teardown (React useEffect cleanup, HMR dispose). For a reversible reset, use disconnect instead.

destroy(): void
disconnect

Disconnect from the current provider and reset state to initial.

Reversible — subsequent connect() calls work normally. Cancels any in-flight connect, reconnect attempt, or onConnect callback (ctx.signal becomes aborted).

disconnect(): void
getProductAccount

Get an app-scoped product account from the host.

Product accounts are derived by the host wallet for each app, identified by dotNsIdentifier (e.g., “mark3t.dot”). Only available when connected via the host provider — returns HOST_UNAVAILABLE otherwise.

getProductAccount(dotNsIdentifier: string, derivationIndex: number = 0): Promise<Result<SignerAccount, SignerError>>
Examples
const result = await manager.getProductAccount("myapp.dot"); if (result.ok) { const signer = result.value.getSigner(); }
getProductAccountAlias

Get a contextual alias for a product account via Ring VRF.

Aliases prove account membership in a ring without revealing which account produced the alias. Only available when connected via the host provider — returns HOST_UNAVAILABLE otherwise.

getProductAccountAlias(dotNsIdentifier: string, derivationIndex: number = 0): Promise<Result<ContextualAlias, SignerError>>
getSigner

Get the PolkadotSigner for the currently selected account. Returns null if no account is selected or manager is disconnected.

getSigner(): PolkadotSigner | null
getState

Get a snapshot of the current state.

getState(): SignerState
selectAccount

Select an account by address. Returns the account on success, or ACCOUNT_NOT_FOUND error.

selectAccount(address: string): Result<SignerAccount, SignerError>
signRaw

Sign arbitrary bytes with the currently selected account.

Convenience wrapper around PolkadotSigner.signBytes — useful for master key derivation, message signing, and proof generation without constructing a full transaction.

Returns a SIGNING_FAILED error if no account is selected or signing fails.

signRaw(data: Uint8Array): Promise<Result<Uint8Array<ArrayBufferLike>, SignerError>>
subscribe

Subscribe to state changes.

The callback fires synchronously on every state mutation, in registration order, inside the call stack that mutated state. It does not fire with the current state at subscription time — call getState if you need a priming read.

For “fired once when the user connects” semantics, prefer the SignerManagerOptions.onConnect option instead of gating on state.status inside this callback — subscribe will fire many times while connected (selectAccount, account swaps, etc.).

subscribe(callback: (state: SignerState) => void): () => void
Returns

an unsubscribe function.

class SigningFailedError

A signing operation failed.

Extends: SignerError

Constructors

constructor
new SigningFailedError(cause: unknown, message?: string): SigningFailedError

class TimeoutError

An operation timed out.

Extends: SignerError

Constructors

constructor
new TimeoutError(operation: string, ms: number): TimeoutError

Properties

ms
propertyreadonlynumber
operation
propertyreadonlystring

Functions

err()

Create a failed Result.

err(error: E): Result<never, E>

isHostError()

Check if a SignerError is a host-related error.

isHostError(e: SignerError): e is HostUnavailableError | HostRejectedError | HostDisconnectedError

ok()

Create a successful Result.

ok(value: T): Result<T, never>

sleep()

Sleep for a given duration, cancellable via AbortSignal.

Resolves immediately if the signal is already aborted. Cleans up the abort listener when the timer fires naturally to prevent listener accumulation in retry loops.

sleep(ms: number, signal?: AbortSignal): Promise<void>

withRetry()

Retry an async operation with exponential backoff.

Calls fn up to maxAttempts times. If fn returns an error result, waits with exponential backoff before the next attempt. Returns the first successful result or the last error.

withRetry(fn: (attempt: number) => Promise<Result<T, E>>, options?: RetryOptions): Promise<Result<T, E>>

Interfaces

interface AccountPersistence

Adapter for persisting the selected account address across sessions.

globalThis.localStorage satisfies this interface. Pass a custom implementation for container environments (e.g., hostLocalStorage) or for testing.

Methods

getItem
getItem(key: string): string | Promise<string | null> | null
removeItem
removeItem(key: string): void | Promise<void>
setItem
setItem(key: string, value: string): void | Promise<void>

interface ConnectContext

Context passed to the onConnect callback.

Properties

requestResourceAllocation
property(resources: { tag: "StatementStoreAllowance"; value: undefined } | { tag: "BulletinAllowance"; value: undefined } | { tag: "SmartContractAllowance"; value: number } | { tag: "AutoSigning"; value: undefined }[]) => Promise<{ tag: "Rejected"; value: undefined } | { tag: "Allocated"; value: undefined } | { tag: "NotAvailable"; value: undefined }[]>

Request a batch of host resource allocations. Bound shorthand for requestResourceAllocation from @parity/product-sdk-host — throws on failure, returns the unwrapped outcomes on success.

signal
propertyAbortSignal

Aborted when the manager disconnects or is destroyed while the callback is still running. Pass through to fetch / cancellation primitives so mid-flight work stops promptly.

interface ContextualAlias

A contextual alias obtained from Ring VRF.

Proves account membership in a ring without revealing which account.

Properties

alias
propertyUint8Array

The Ring VRF alias bytes.

context
propertyUint8Array

Ring context (32 bytes).

interface DevProviderOptions

Options for the dev account provider.

Properties

keyType
propertyoptionalDevKeyType

Key type for account derivation. Default: “sr25519”

mnemonic
propertyoptionalstring

Custom mnemonic phrase instead of DEV_PHRASE.

names
propertyoptionalreadonly string[]

Which dev accounts to create. Default: all 6 standard accounts.

ss58Prefix
propertyoptionalnumber

SS58 prefix for address encoding. Default: 42

interface HostProviderOptions

Options for the Host API provider.

Properties

loadHostApiEnum
propertyoptional() => Promise<HostApiEnumHelper>

Custom loader for @novasamatech/host-api (used to construct the ChainSubmit permission request). Defaults to dynamic import.

loadSdk
propertyoptional() => Promise<ProductSdkModule>

Custom SDK loader. Defaults to import("@novasamatech/host-api-wrapper"). Override this for testing or custom SDK setups.

maxRetries
propertyoptionalnumber

Max retry attempts for initial connection. Default: 3

productAccount
propertyoptional{ derivationIndex?: number; dotNsIdentifier: string }

If set, connect() returns a single product account for the given dotNsIdentifier, skipping the legacy fetch entirely. For apps that sign exclusively with a per-dapp derived account.

SignerAccount.name is populated best-effort from accounts.getUserId().primaryUsername; failures leave it null. Signing is pinned to createTransaction (see PR #96).

requestChainSubmitPermission
propertyoptionalboolean

Whether to request the host’s ChainSubmit permission after a successful connect(). Without this, subsequent signing requests are rejected by the host with PermissionDenied. Default: true.

Set to false if your app needs to defer the permission prompt or drives it manually.

(Previously named requestTransactionSubmitPermission — alias kept for backwards compatibility but the new wire format uses ChainSubmit.)

requestTransactionSubmitPermission
propertyoptionalboolean
retryDelay
propertyoptionalnumber

Initial retry delay in ms. Default: 500

ss58Prefix
propertyoptionalnumber

SS58 prefix for address encoding. Default: 42

interface ProductAccount

A product account — an app-scoped derived account managed by the host wallet.

The host derives a unique keypair for each app (identified by dotNsIdentifier) so apps get their own account that the user controls but is scoped to the app.

Properties

derivationIndex
propertynumber

Derivation index within the app scope. Default: 0

dotNsIdentifier
propertystring

App identifier (e.g., “mark3t.dot”).

publicKey
propertyUint8Array

Raw public key (32 bytes).

interface RetryOptions

Options for retry with exponential backoff.

Properties

backoffMultiplier
propertyoptionalnumber

Multiplier applied to delay after each attempt. Default: 2

initialDelay
propertyoptionalnumber

Initial delay in ms before first retry. Default: 500

maxAttempts
propertyoptionalnumber

Maximum number of attempts. Default: 3

maxDelay
propertyoptionalnumber

Maximum delay cap in ms. Default: 10_000

signal
propertyoptionalAbortSignal

AbortSignal to cancel retries early.

interface RingLocation

Location of a Ring VRF ring on-chain.

Matches the product-sdk’s RingLocation codec shape.

Properties

genesisHash
propertystring
hints
propertyoptional{ palletInstance?: number }
ringRootHash
propertystring

interface SignerAccount

A signing-capable account from any provider.

Properties

address
propertySS58String

SS58 address (generic prefix 42 by default).

h160Address
property`0x${string}`

H160 EVM address derived from the public key.

For native Substrate accounts: keccak256(publicKey), last 20 bytes. For EVM-derived accounts: strips the 0xEE padding. Used for pallet-revive / Asset Hub EVM contract interactions.

name
propertystring | null

Human-readable name if available from the provider.

publicKey
propertyUint8Array

Raw public key (32 bytes). May be sr25519, ed25519, or ecdsa depending on the provider.

source
propertyProviderType

Which provider supplied this account.

Methods

getSigner

Get the PolkadotSigner for this account.

getSigner(): PolkadotSigner

interface SignerManagerOptions

Options for SignerManager construction.

Properties

createProvider
propertyoptionalProviderFactory

Custom provider factory. Override to inject test doubles or custom providers.

dappName
propertyoptionalstring

App name used for storage key namespacing. Default: “product-sdk” The selected account is persisted under product-sdk:signer:{dappName}:selectedAccount.

hostTimeout
propertyoptionalnumber

Maximum time in ms to wait for the Host API. Applied as an AbortSignal timeout on the host provider connection. Default: 10_000

maxRetries
propertyoptionalnumber

Maximum retry attempts for provider connection. Default: 3

onConnect
propertyoptionalOnConnect

Callback fired exactly when the manager transitions to connected with a selected account — not on subsequent state mutations while still connected. Fires again after auto-reconnect, so a fresh host session re-runs the callback.

Common use: request product resource allocations once per session. The ctx exposes a pre-bound requestResourceAllocation helper plus an AbortSignal that fires if the user disconnects or destroys the manager mid-flight.

requestResourceAllocation throws on failure (matches the @parity/product-sdk-host export of the same name); errors thrown from onConnect are logged but do not affect the connected state — the next reconnect retries.

persistence
propertyoptionalAccountPersistence | null

Storage adapter for persisting selected account. Uses host localStorage when inside a container. Set to null to disable persistence entirely.

ss58Prefix
propertyoptionalnumber

SS58 prefix for address encoding. Default: 42

interface SignerProvider

Interface that all signer providers must implement.

Providers are responsible for discovering accounts and creating signers from a specific source (Host API or dev accounts).

Properties

type
propertyreadonlyProviderType

Unique identifier for this provider type.

Methods

connect

Attempt to connect and discover accounts.

connect(signal?: AbortSignal): Promise<Result<SignerAccount[], SignerError>>
Parameters
  • signal: Optional AbortSignal to cancel the connection attempt.
Returns

Accounts on success, typed error on failure.

disconnect

Disconnect and clean up resources. Safe to call multiple times.

disconnect(): void
onAccountsChange

Subscribe to account list changes.

Emitted when the set of available accounts changes (e.g., user connects/disconnects in the host wallet).

onAccountsChange(callback: (accounts: SignerAccount[]) => void): Unsubscribe
Returns

Unsubscribe function.

onStatusChange

Subscribe to connection status changes.

Not all providers emit status changes — for example, dev accounts are always “connected” and never emit.

onStatusChange(callback: (status: ConnectionStatus) => void): Unsubscribe
Returns

Unsubscribe function.

interface SignerState

Full state snapshot emitted to subscribers.

Properties

accounts
propertyreadonly SignerAccount[]

All available accounts across all connected providers.

activeProvider
propertyProviderType | null

Which provider is active (null if disconnected).

error
propertySignerError | null

Last error (null if no error).

selectedAccount
propertySignerAccount | null

Currently selected account (null if none selected).

status
propertyConnectionStatus

Current connection status.

Type Aliases

type ConnectionStatus

Connection status for a signer provider.

type ConnectionStatus = "disconnected" | "connecting" | "connected"

type DevAccountName

A well-known Substrate development account name (Alice, Bob, …) used to derive deterministic dev accounts from the standard Substrate dev mnemonic.

type DevAccountName = typeof DEFAULT_DEV_NAMES[number]

type DevKeyType

Supported key types for dev account derivation.

type DevKeyType = "sr25519" | "ed25519"

type OnConnect

Callback signature for SignerManagerOptions.onConnect.

type OnConnect = (account: SignerAccount, ctx: ConnectContext) => void | Promise<void>

type ProviderFactory

Factory function that creates a SignerProvider for a given type.

type ProviderFactory = (type: ProviderType) => SignerProvider

type ProviderType

Identifies the source of an account.

  • "host": Host API provider (Polkadot Desktop / Mobile) — the primary provider
  • "dev": Development accounts (Alice, Bob, etc.) — for testing only
type ProviderType = "host" | "dev"

type Result

Lightweight Result type for operations that can fail expectedly.

type Result = { ok: true; value: T } | { error: E; ok: false }

type Unsubscribe

Function that unsubscribes a listener when called.

type Unsubscribe = () => void
Last updated on