Promise and RxJS wrappers around the Polkadot JS RPC for interacting with Polkadot and Substrate-based blockchains
npx @tessl/cli install tessl/npm-polkadot--api@16.4.0@polkadot/api provides comprehensive JavaScript/TypeScript wrappers around the Polkadot and Substrate blockchain RPC interfaces. It offers clean abstractions for querying blockchain state, submitting transactions, subscribing to chain events, and interacting with smart contracts through both Promise-based and RxJS Observable patterns.
npm install @polkadot/apiimport { ApiPromise, WsProvider } from "@polkadot/api";For RxJS-based API:
import { ApiRx, WsProvider } from "@polkadot/api";For CommonJS:
const { ApiPromise, WsProvider } = require("@polkadot/api");import { ApiPromise, WsProvider } from "@polkadot/api";
// Connect to a Polkadot node
const provider = new WsProvider("wss://rpc.polkadot.io");
const api = await ApiPromise.create({ provider });
// Query chain state
const [chain, nodeName, nodeVersion] = await Promise.all([
api.rpc.system.chain(),
api.rpc.system.name(),
api.rpc.system.version()
]);
console.log(`Connected to chain ${chain} using ${nodeName} v${nodeVersion}`);
// Query account balance
const account = "1FRMM8PEiWXYax7rpS6X4XZX1aAAxSWx1CrKTyrVYhV24fg";
const { data: balance } = await api.query.system.account(account);
console.log(`Account balance: ${balance.free.toHuman()}`);
// Subscribe to new blocks
const unsubscribe = await api.rpc.chain.subscribeNewHeads((header) => {
console.log(`New block #${header.number} has hash ${header.hash}`);
});@polkadot/api is built around several key components:
ApiPromise for Promise-based async operations and ApiRx for RxJS Observable streamsWsProvider, HttpProvider, ScProvider) for different connection typesCore API creation and connection management for both Promise and RxJS patterns.
class ApiPromise {
static create(options?: ApiOptions): Promise<ApiPromise>;
constructor(options?: ApiOptions);
get isReady(): Promise<ApiPromise>;
get isReadyOrError(): Promise<ApiPromise>;
clone(): ApiPromise;
connect(): Promise<void>;
disconnect(): Promise<void>;
setSigner(signer?: Signer): void;
combineLatest<T>(fns: CombinatorFunction[], callback: CombinatorCallback<T>): Promise<() => void>;
/**
* Query blockchain state at a specific block hash
* @param blockHash - Block hash to query at
* @param knownVersion - Optional runtime version for optimization
* @returns Promise resolving to query interface bound to the block
*/
queryAt(blockHash: Uint8Array | string, knownVersion?: RuntimeVersion): Promise<QueryableStorage<'promise'>>;
/**
* Make runtime calls at a specific block hash
* @param blockHash - Block hash to query at
* @param knownVersion - Optional runtime version for optimization
* @returns Promise resolving to call interface bound to the block
*/
callAt(blockHash: Uint8Array | string, knownVersion?: RuntimeVersion): Promise<QueryableCalls<'promise'>>;
/**
* Sign raw data using keyring pair or external signer
* @param address - KeyringPair or address string for signing
* @param data - Raw data to sign
* @param options - Signing options including external signer
* @returns Promise resolving to hex signature
*/
sign(address: KeyringPair | string, data: SignerPayloadRawBase, options?: { signer?: Signer }): Promise<string>;
}
class ApiRx {
static create(options?: ApiOptions): Observable<ApiRx>;
constructor(options?: ApiOptions);
get isReady(): Observable<ApiRx>;
clone(): ApiRx;
connect(): Promise<void>;
disconnect(): Promise<void>;
setSigner(signer?: Signer): void;
/**
* Query blockchain state at a specific block hash
* @param blockHash - Block hash to query at
* @param knownVersion - Optional runtime version for optimization
* @returns Observable emitting query interface bound to the block
*/
queryAt(blockHash: Uint8Array | string, knownVersion?: RuntimeVersion): Observable<QueryableStorage<'rxjs'>>;
/**
* Make runtime calls at a specific block hash
* @param blockHash - Block hash to query at
* @param knownVersion - Optional runtime version for optimization
* @returns Observable emitting call interface bound to the block
*/
callAt(blockHash: Uint8Array | string, knownVersion?: RuntimeVersion): Observable<QueryableCalls<'rxjs'>>;
/**
* Sign raw data using keyring pair or external signer
* @param address - KeyringPair or address string for signing
* @param data - Raw data to sign
* @param options - Signing options including external signer
* @returns Promise resolving to hex signature
*/
sign(address: KeyringPair | string, data: SignerPayloadRawBase, options?: { signer?: Signer }): Promise<string>;
}
interface ApiOptions {
provider?: ProviderInterface;
types?: RegistryTypes;
rpc?: Record<string, Record<string, DefinitionRpc | DefinitionRpcSub>>;
derives?: DeriveCustom;
metadata?: Record<string, HexString>;
noInitWarn?: boolean;
throwOnConnect?: boolean;
throwOnUnknown?: boolean;
signer?: Signer;
registry?: Registry;
initWasm?: boolean;
isPedantic?: boolean;
rpcCacheCapacity?: number;
runtime?: DefinitionsCall;
signedExtensions?: ExtDef;
source?: ApiBase<any>;
}Query blockchain state, constants, and runtime information through dynamic interfaces.
interface QueryableStorage<ApiType> {
[section: string]: {
[method: string]: (...args: any[]) => QueryableStorageEntry<ApiType>;
};
}
interface QueryableConsts<ApiType> {
[section: string]: {
[constant: string]: any;
};
}
interface QueryableStorageMulti<ApiType> {
<T extends any[]>(
queries: (QueryableStorageEntry<'rxjs'> | [QueryableStorageEntry<'rxjs'>, ...any[]])[],
callback?: (values: T) => void
): ApiType extends 'rxjs' ? Observable<T> : Promise<T>;
}
interface AllDerives<ApiType> {
[section: string]: {
[method: string]: (...args: any[]) => ApiType extends 'rxjs' ? Observable<any> : Promise<any>;
};
}Direct access to node RPC methods for chain information, state queries, and system operations.
interface DecoratedRpc<ApiType, RpcInterface> {
chain: {
getBlock: (hash?: Hash) => ApiType extends 'rxjs' ? Observable<SignedBlock> : Promise<SignedBlock>;
subscribeNewHeads: (callback?: (header: Header) => void) => ApiType extends 'rxjs' ? Observable<Header> : UnsubscribePromise;
};
state: {
getStorage: (key: StorageKey, at?: Hash) => ApiType extends 'rxjs' ? Observable<StorageData> : Promise<StorageData>;
subscribeStorage: (keys: StorageKey[], callback?: (changes: StorageChangeSet) => void) => ApiType extends 'rxjs' ? Observable<StorageChangeSet> : UnsubscribePromise;
};
system: {
chain: () => ApiType extends 'rxjs' ? Observable<Text> : Promise<Text>;
name: () => ApiType extends 'rxjs' ? Observable<Text> : Promise<Text>;
version: () => ApiType extends 'rxjs' ? Observable<Text> : Promise<Text>;
};
}Create, sign, and submit transactions with full lifecycle tracking and event monitoring.
interface SubmittableExtrinsics<ApiType> {
[section: string]: {
[method: string]: (...args: any[]) => SubmittableExtrinsic<ApiType>;
};
}
interface SubmittableExtrinsic<ApiType> {
sign(account: AddressOrPair, options?: Partial<SignerOptions>): SubmittableExtrinsic<ApiType>;
signAndSend(account: AddressOrPair, callback?: (result: SubmittableResult) => void): ApiType extends 'rxjs' ? Observable<SubmittableResult> : Promise<Hash>;
signAndSend(account: AddressOrPair, options?: Partial<SignerOptions>, callback?: (result: SubmittableResult) => void): ApiType extends 'rxjs' ? Observable<SubmittableResult> : Promise<Hash>;
}
class SubmittableResult {
readonly status: ExtrinsicStatus;
readonly events: EventRecord[];
readonly dispatchError?: DispatchError;
readonly txHash: Hash;
get isCompleted(): boolean;
get isError(): boolean;
get isFinalized(): boolean;
get isInBlock(): boolean;
}Connection providers for different transport protocols and connection types.
class WsProvider implements ProviderInterface {
constructor(endpoint?: string | string[], autoConnectMs?: number, headers?: Record<string, string>);
connect(): Promise<void>;
disconnect(): Promise<void>;
send(method: string, params: unknown[]): Promise<any>;
}
class HttpProvider implements ProviderInterface {
constructor(endpoint?: string, headers?: Record<string, string>);
send(method: string, params: unknown[]): Promise<any>;
}
class ScProvider implements ProviderInterface {
constructor(spec: string | ChainSpec, config?: ScProviderConfig);
connect(): Promise<void>;
disconnect(): Promise<void>;
send(method: string, params: unknown[]): Promise<any>;
}
class Keyring {
constructor(options?: KeyringOptions);
addFromUri(suri: string, meta?: KeyringPair$Meta, type?: KeypairType): KeyringPair;
getPairs(): KeyringPair[];
}Access runtime events, errors, and metadata for dynamic API behavior.
interface DecoratedEvents<ApiType> {
[section: string]: {
[event: string]: EventMetadata;
};
}
interface DecoratedErrors<ApiType> {
[section: string]: {
[error: string]: RegistryError;
};
}type ApiTypes = 'promise' | 'rxjs';
type AddressOrPair = string | KeyringPair;
type UnsubscribePromise = Promise<() => void>;
type CombinatorCallback<T> = (...args: T) => void;
type CombinatorFunction = (callback: (value: any) => void) => UnsubscribePromise;
interface ChainSpec {
chainSpec: string;
database?: string;
}
interface ScProviderConfig {
config?: any;
database?: string;
}
interface StorageChangeSet {
block: Hash;
changes: [StorageKey, StorageData | null][];
}
interface EventRecord {
phase: Phase;
event: Event;
topics: Vec<Hash>;
}
interface RegistryTypes {
[typeName: string]: any;
}
interface KeyringPair {
address: string;
publicKey: Uint8Array;
sign(message: Uint8Array): Uint8Array;
}
interface Signer {
signPayload(payload: SignerPayload): Promise<SignerResult>;
signRaw?(raw: SignerPayloadRaw): Promise<SignerResult>;
}
interface SignerPayloadRawBase {
data: string | Uint8Array;
type?: 'bytes' | 'payload';
}
type DecorateFn<T> = (...args: any[]) => Observable<T>;
type CodecReturnType<T extends (...args: unknown[]) => Observable<Codec>> =
T extends (...args: any) => infer R
? R extends Observable<Codec>
? ObsInnerType<R>
: never
: never;
interface DecorateMethodOptions {
methodName?: string;
overrideNoSub?: any;
}
type StorageEntryPromiseOverloads = (...args: unknown[]) => Promise<any> | UnsubscribePromise;
type ObsInnerType<T> = T extends Observable<infer U> ? U : never;Both ApiPromise and ApiRx instances provide utility methods for working with runtime metadata:
interface ApiUtilityMethods {
/**
* Find call definition by index
* @param callIndex - Call index bytes
* @returns Call function definition
*/
findCall(callIndex: Uint8Array | string): CallFunction;
/**
* Find error definition by index
* @param errorIndex - Error index bytes
* @returns Registry error definition
*/
findError(errorIndex: Uint8Array | string): RegistryError;
/** Access multi-query interface */
get queryMulti(): QueryableStorageMulti<ApiType>;
/** Access derived query interface */
get derive(): AllDerives<ApiType>;
/** Runtime metadata */
get runtimeMetadata(): Metadata;
/** Runtime version information */
get runtimeVersion(): RuntimeVersion;
/** Chain name */
get runtimeChain(): Text;
/** Genesis hash */
get genesisHash(): Hash;
/** Connection status */
get isConnected(): boolean;
}Beyond the main API classes, @polkadot/api exports several utility functions and constants:
/**
* Package information containing name, version, and type
*/
const packageInfo: {
name: string;
version: string;
path: string;
type: string;
};
/**
* Decorator function that converts RxJS observables to Promise-based methods
* @param method - The method to convert from Observable to Promise
* @param options - Decoration options for method behavior
* @returns Promise-based version of the method
*/
function toPromiseMethod<M extends DecorateFn<CodecReturnType<M>>>(
method: M,
options?: DecorateMethodOptions
): StorageEntryPromiseOverloads;
/**
* Decorator function for RxJS-based methods (identity function)
* @param method - The method to return as-is for RxJS usage
* @returns The same method for RxJS compatibility
*/
function toRxMethod<M extends DecorateFn<Codec>>(method: M): M;