butr
API reference

@usebutr/polkadot

injectedWeb3 and Wallet Standard discovery, the adapter builders, and the Polkadot signer.

Discovery

discoverInjectedPolkadotAdapters(onAdapter, options?): () => void

Reads window.injectedWeb3 without prompting: adapters are built without calling enable(). It scans at once and again on a poll schedule for late-injecting extensions; the returned function cancels pending polls. It is a WalletSource as-is:

import type { WalletManagerConfig } from "@usebutr/core";
import { discoverInjectedPolkadotAdapters } from "@usebutr/polkadot";

const config: WalletManagerConfig = { sources: [discoverInjectedPolkadotAdapters] };

InjectedPolkadotDiscoveryOptions: pollMs?: ReadonlyArray<number> (offsets in milliseconds, default [250, 750]; [] for a single synchronous scan) and target? (overrides window).

discoverPolkadotWalletStandardAdapters(onAdapter, loadModule?): () => void

Discovers wallets advertising a polkadot: chain through Wallet Standard. Requires @wallet-standard/app; loadModule replaces that import (tests).

A wallet on both channels mints two unrelated ids, so passing both sources lists it twice. autoDiscovery(["polkadot"]) from @usebutr/wallets lists it once, including an extension that injects late, and keeps Wallet Standard wallets that no injectedWeb3 extension matches.

Adapter builders

buildInjectedPolkadotAdapter(extensionName, displayName, provider): PolkadotAdapter

provider is the window.injectedWeb3[extensionName] entry. The id is injected:polkadot:<extension-name>. connect() calls enable("butr"), which may prompt; construction does not. connect({ silent: true }) reuses only an existing in-memory session, otherwise it rejects with NotConnected before calling enable. A persisted connection stays dormant until an explicit connect grants access again. signMessage appears once connect() has enabled an extension that exposes signRaw, and subscribe once it exposes accounts.subscribe. There is no switchChain: an injected extension has no network to switch. An account pinned to a network through genesisHash carries that chain; others are labelled Polkadot.

buildPolkadotWalletStandardAdapter(wallet, registerDisconnector?): PolkadotAdapter | null

Wraps a Wallet Standard wallet, or returns null when it speaks no Polkadot. The id is slugify("polkadot", wallet.name). signMessage exists when the wallet advertises polkadot:signMessage, and switchChain when it advertises more than one Polkadot chain.

Neither adapter has sendTx, getBalance or getTransactionReceipt: building an extrinsic needs chain metadata over RPC, which butr does not ship.

Signers

Importing the package registers the polkadot-injected kind:

type PolkadotInjectedSigner = {
  extension: Injected; // the object `enable()` resolved: `accounts` and `signer`
  extensionName: string; // the `window.injectedWeb3` key
  kind: "polkadot-injected";
};

It carries no address: sign as the connected wallet's account. extensionName is what polkadot-api's connectInjectedExtension takes. On an injected adapter that is not connected, getSigner() rejects. Wallet Standard adapters resolve { kind: "wallet-standard", wallet }. See the PAPI integration.

Both transports wrap the message in <Bytes>…</Bytes> and hand the wallet those bytes: injected through signRaw, Wallet Standard through polkadot:signMessage. signedMessage is the wrapped bytes, or what a Wallet Standard wallet reports it signed; verify against it.

Types

InjectedPolkadotDiscoveryOptions, PolkadotSignMessageFeature, PolkadotSignMessageInput, PolkadotSignMessageOutput.

The Polkadot chain registry (POLKADOT_CHAINS, POLKADOT_CHAINS_LIST) lives in @usebutr/core. Chain ids are polkadot: plus the first 32 hex characters of the genesis hash.

Source: packages/polkadot/src/index.ts.