Promise and RxJS wrappers around the Polkadot JS RPC for interacting with Polkadot and Substrate-based blockchains
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Connection providers for different transport protocols and connection types. The @polkadot/api supports multiple provider implementations for connecting to blockchain nodes through various protocols.
WebSocket-based provider for real-time bidirectional communication with blockchain nodes.
class WsProvider implements ProviderInterface {
/**
* Create WebSocket provider
* @param endpoint - WebSocket endpoint URL or array of URLs
* @param autoConnectMs - Auto-connect delay in milliseconds or false to disable
* @param headers - Additional WebSocket headers
* @param timeout - Connection timeout in milliseconds
* @param cacheCapacity - RPC response cache capacity
* @param cacheTtl - Cache TTL in milliseconds or null to disable
*/
constructor(
endpoint?: string | string[],
autoConnectMs?: number | false,
headers?: Record<string, string>,
timeout?: number,
cacheCapacity?: number,
cacheTtl?: number | null
);
/**
* Connect to WebSocket endpoint
* @returns Promise resolving when connected
*/
connect(): Promise<void>;
/**
* Disconnect from WebSocket endpoint
* @returns Promise resolving when disconnected
*/
disconnect(): Promise<void>;
/**
* Check if provider is connected
*/
get isConnected(): boolean;
/**
* Send RPC request
* @param method - RPC method name
* @param params - Method parameters
* @param subscription - Subscription callback
* @returns Promise resolving to result
*/
send<T = any>(
method: string,
params: unknown[],
subscription?: ProviderInterfaceCallback
): Promise<T>;
/**
* Subscribe to provider events
* @param type - Event type
* @param callback - Event callback
* @returns Unsubscribe function
*/
on(type: ProviderInterfaceEmitType, callback: ProviderInterfaceEmitted): () => void;
/**
* Clone provider with same configuration
* @returns New WsProvider instance
*/
clone(): WsProvider;
/** Current endpoint URL */
readonly endpoint: string;
/** Connection timeout setting */
readonly timeout: number;
}HTTP-based provider for stateless request-response communication with blockchain nodes.
class HttpProvider implements ProviderInterface {
/**
* Create HTTP provider
* @param endpoint - HTTP endpoint URL
* @param headers - Additional HTTP headers
* @param timeout - Request timeout in milliseconds
* @param cacheCapacity - RPC response cache capacity
*/
constructor(
endpoint?: string,
headers?: Record<string, string>,
timeout?: number,
cacheCapacity?: number
);
/**
* Connect (no-op for HTTP)
* @returns Promise resolving immediately
*/
connect(): Promise<void>;
/**
* Disconnect (no-op for HTTP)
* @returns Promise resolving immediately
*/
disconnect(): Promise<void>;
/**
* HTTP is always "connected"
*/
get isConnected(): boolean;
/**
* Send HTTP RPC request
* @param method - RPC method name
* @param params - Method parameters
* @returns Promise resolving to result
*/
send<T = any>(method: string, params: unknown[]): Promise<T>;
/**
* Subscribe to provider events
* @param type - Event type
* @param callback - Event callback
* @returns Unsubscribe function
*/
on(type: ProviderInterfaceEmitType, callback: ProviderInterfaceEmitted): () => void;
/**
* Clone provider with same configuration
* @returns New HttpProvider instance
*/
clone(): HttpProvider;
/** Current endpoint URL */
readonly endpoint: string;
/** Request timeout setting */
readonly timeout: number;
}Light client provider using Substrate Connect for browser-based blockchain access.
class ScProvider implements ProviderInterface {
/**
* Create Substrate Connect provider
* @param Sc - Substrate Connect interface with WellKnownChain and createScClient
* @param spec - Chain specification string or well-known chain name
* @param sharedSandbox - Optional shared ScProvider instance for sandbox mode
*/
constructor(
Sc: SubstrateConnect,
spec: string | WellKnownChain,
sharedSandbox?: ScProvider
);
/**
* Connect to light client
* @returns Promise resolving when connected
*/
connect(): Promise<void>;
/**
* Disconnect from light client
* @returns Promise resolving when disconnected
*/
disconnect(): Promise<void>;
/**
* Check if provider is connected
*/
get isConnected(): boolean;
/**
* Send RPC request through light client
* @param method - RPC method name
* @param params - Method parameters
* @param subscription - Subscription callback
* @returns Promise resolving to result
*/
send<T = any>(
method: string,
params: unknown[],
subscription?: ProviderInterfaceCallback
): Promise<T>;
/**
* Subscribe to provider events
* @param type - Event type
* @param callback - Event callback
* @returns Unsubscribe function
*/
on(type: ProviderInterfaceEmitType, callback: ProviderInterfaceEmitted): () => void;
/**
* Clone provider with same configuration
* @returns New ScProvider instance
*/
clone(): ScProvider;
/** Chain specification */
readonly spec: string | ChainSpec;
}
interface SubstrateConnect {
/** Well-known chain constants */
WellKnownChain: typeof WellKnownChain;
/** Create Substrate Connect client */
createScClient: (config?: any) => ScClient;
}
type WellKnownChain = string;
interface ScClient {
/** Add a well-known chain */
addWellKnownChain: (spec: WellKnownChain, onResponse: (response: string) => void) => Promise<Chain>;
/** Add a custom chain */
addChain: (spec: string, onResponse: (response: string) => void) => Promise<Chain>;
}
interface Chain {
/** Send JSON-RPC request */
sendJsonRpc: (request: string) => void;
/** Add a chain to existing client */
addChain: (spec: string, onResponse: (response: string) => void) => Promise<Chain>;
/** Remove the chain */
remove: () => void;
}
interface ScProviderConfig {
/** Light client configuration */
config?: any;
/** Database name */
database?: string;
}
interface ChainSpec {
/** Chain specification JSON */
chainSpec: string;
/** Optional database configuration */
database?: string;
}Cryptographic key management for transaction signing.
class Keyring {
/**
* Create keyring instance
* @param options - Keyring configuration options
*/
constructor(options?: KeyringOptions);
/**
* Add keypair from URI
* @param suri - Secret URI (mnemonic, hex seed, or derivation path)
* @param meta - Key metadata
* @param type - Cryptographic algorithm type
* @returns KeyringPair instance
*/
addFromUri(
suri: string,
meta?: KeyringPair$Meta,
type?: KeypairType
): KeyringPair;
/**
* Add keypair from seed
* @param seed - Raw seed bytes
* @param meta - Key metadata
* @param type - Cryptographic algorithm type
* @returns KeyringPair instance
*/
addFromSeed(
seed: Uint8Array,
meta?: KeyringPair$Meta,
type?: KeypairType
): KeyringPair;
/**
* Add keypair from mnemonic
* @param mnemonic - BIP39 mnemonic phrase
* @param meta - Key metadata
* @param type - Cryptographic algorithm type
* @returns KeyringPair instance
*/
addFromMnemonic(
mnemonic: string,
meta?: KeyringPair$Meta,
type?: KeypairType
): KeyringPair;
/**
* Add keypair from JSON backup
* @param json - Keyring JSON backup
* @param passphrase - Decryption passphrase
* @returns KeyringPair instance
*/
addFromJson(json: KeyringPair$Json, passphrase?: string): KeyringPair;
/**
* Get all keypairs
* @returns Array of KeyringPair instances
*/
getPairs(): KeyringPair[];
/**
* Get keypair by address
* @param address - Account address
* @returns KeyringPair instance or undefined
*/
getPair(address: string): KeyringPair;
/**
* Remove keypair
* @param address - Account address to remove
*/
removePair(address: string): void;
/**
* Set address format
* @param ss58Format - SS58 address format number
*/
setSS58Format(ss58Format: number): void;
}
interface KeyringOptions {
/** Default cryptographic algorithm */
type?: 'ed25519' | 'sr25519' | 'ecdsa';
/** SS58 address format */
ss58Format?: number;
}
interface KeyringPair {
/** Account address */
readonly address: string;
/** Public key bytes */
readonly publicKey: Uint8Array;
/** Key metadata */
readonly meta: KeyringPair$Meta;
/** Cryptographic algorithm type */
readonly type: KeypairType;
/**
* Sign message
* @param message - Message to sign
* @param options - Signing options
* @returns Signature bytes
*/
sign(message: Uint8Array, options?: SignOptions): Uint8Array;
/**
* Verify signature
* @param message - Original message
* @param signature - Signature to verify
* @returns Verification result
*/
verify(message: Uint8Array, signature: Uint8Array): boolean;
/**
* Export to JSON
* @param passphrase - Encryption passphrase
* @returns JSON backup
*/
toJson(passphrase?: string): KeyringPair$Json;
/**
* Lock keypair (remove private key from memory)
*/
lock(): void;
/**
* Unlock keypair
* @param passphrase - Unlock passphrase
*/
unlock(passphrase?: string): void;
/**
* Check if keypair is locked
*/
get isLocked(): boolean;
}import { ApiPromise, WsProvider } from "@polkadot/api";
// Basic WebSocket connection
const provider = new WsProvider('wss://rpc.polkadot.io');
const api = await ApiPromise.create({ provider });
// Multiple endpoints with failover
const provider = new WsProvider([
'wss://rpc.polkadot.io',
'wss://polkadot-rpc.dwellir.com',
'wss://1rpc.io/dot'
]);
const api = await ApiPromise.create({ provider });
// Custom headers and timeout
const provider = new WsProvider(
'wss://rpc.polkadot.io',
1000, // Auto-connect delay
{ 'User-Agent': 'MyApp/1.0' }, // Custom headers
30000, // 30 second timeout
1024 // Cache capacity
);
// Listen to provider events
provider.on('connected', () => console.log('Connected to node'));
provider.on('disconnected', () => console.log('Disconnected from node'));
provider.on('error', (error) => console.error('Provider error:', error));
// Manual connection management
await provider.connect();
console.log('Connected:', provider.isConnected);
await provider.disconnect();import { ApiPromise, HttpProvider } from "@polkadot/api";
// Basic HTTP connection
const provider = new HttpProvider('https://rpc.polkadot.io');
const api = await ApiPromise.create({ provider });
// Custom headers and timeout
const provider = new HttpProvider(
'https://rpc.polkadot.io',
{
'Authorization': 'Bearer token123',
'User-Agent': 'MyApp/1.0'
},
30000 // 30 second timeout
);
// HTTP provider limitations
console.log('Always connected:', provider.isConnected); // true
// Note: HTTP providers don't support subscriptionsimport { ApiPromise, ScProvider } from "@polkadot/api";
// Well-known chain connection
const provider = new ScProvider('polkadot');
const api = await ApiPromise.create({ provider });
// Custom chain spec
const chainSpec = {
chainSpec: JSON.stringify({
name: "My Custom Chain",
id: "my-chain",
// ... full chain specification
})
};
const provider = new ScProvider(chainSpec, {
database: 'my-chain-db'
});
// Light client connection
await provider.connect();
console.log('Light client connected');
// Provider events
provider.on('connected', () => console.log('Light client ready'));
provider.on('disconnected', () => console.log('Light client stopped'));import { Keyring } from "@polkadot/keyring";
// Create keyring with SR25519 keys
const keyring = new Keyring({ type: 'sr25519' });
// Add development accounts
const alice = keyring.addFromUri('//Alice');
const bob = keyring.addFromUri('//Bob');
const charlie = keyring.addFromUri('//Charlie');
console.log('Alice address:', alice.address);
console.log('Bob address:', bob.address);
// Add from mnemonic
const account = keyring.addFromMnemonic(
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about',
{ name: 'Test Account' }
);
// Add from seed
const seed = new Uint8Array(32).fill(1); // Don't use this in production!
const seedAccount = keyring.addFromSeed(seed, { name: 'Seed Account' });
// Get all accounts
const pairs = keyring.getPairs();
console.log(`Keyring has ${pairs.length} accounts`);
// Sign message
const message = new TextEncoder().encode('Hello Polkadot');
const signature = alice.sign(message);
console.log('Signature:', signature);
// Verify signature
const isValid = alice.verify(message, signature);
console.log('Signature valid:', isValid);import { Keyring } from "@polkadot/keyring";
const keyring = new Keyring({ type: 'sr25519' });
// Generate new mnemonic (in production, use @polkadot/util-crypto)
import { mnemonicGenerate } from "@polkadot/util-crypto";
const mnemonic = mnemonicGenerate();
console.log('Generated mnemonic:', mnemonic);
// Add account with encryption
const account = keyring.addFromMnemonic(mnemonic, { name: 'Secure Account' });
// Export to encrypted JSON
const json = account.toJson('strong-passphrase');
console.log('Encrypted JSON:', json);
// Lock account (remove private key from memory)
account.lock();
console.log('Account locked:', account.isLocked);
// Unlock account
account.unlock('strong-passphrase');
console.log('Account unlocked:', !account.isLocked);
// Import from JSON
const keyring2 = new Keyring({ type: 'sr25519' });
const imported = keyring2.addFromJson(json, 'strong-passphrase');
console.log('Imported address:', imported.address);import { ApiPromise, WsProvider } from "@polkadot/api";
// Robust connection with error handling
async function connectWithRetry(endpoints: string[], maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
for (const endpoint of endpoints) {
try {
console.log(`Attempting connection to ${endpoint}...`);
const provider = new WsProvider(endpoint, 1000, {}, 10000);
const api = await ApiPromise.create({
provider,
throwOnConnect: true
});
console.log(`Connected to ${endpoint}`);
return api;
} catch (error) {
console.warn(`Failed to connect to ${endpoint}:`, error.message);
}
}
if (i < maxRetries - 1) {
console.log(`Retry ${i + 1}/${maxRetries} in 5 seconds...`);
await new Promise(resolve => setTimeout(resolve, 5000));
}
}
throw new Error('Failed to connect to any endpoint');
}
// Usage
const endpoints = [
'wss://rpc.polkadot.io',
'wss://polkadot-rpc.dwellir.com',
'wss://1rpc.io/dot'
];
try {
const api = await connectWithRetry(endpoints);
console.log('Successfully connected');
// Set up reconnection on disconnect
api.provider.on('disconnected', async () => {
console.log('Connection lost, attempting to reconnect...');
try {
await api.connect();
console.log('Reconnected successfully');
} catch (error) {
console.error('Reconnection failed:', error);
}
});
} catch (error) {
console.error('All connection attempts failed:', error);
}import { ProviderInterface, ProviderInterfaceCallback } from "@polkadot/rpc-provider/types";
// Example custom provider implementation
class CustomProvider implements ProviderInterface {
private _isConnected = false;
private _eventemitter = new EventTarget();
constructor(private endpoint: string) {}
get isConnected(): boolean {
return this._isConnected;
}
async connect(): Promise<void> {
// Custom connection logic
this._isConnected = true;
this._eventemitter.dispatchEvent(new CustomEvent('connected'));
}
async disconnect(): Promise<void> {
// Custom disconnection logic
this._isConnected = false;
this._eventemitter.dispatchEvent(new CustomEvent('disconnected'));
}
async send(method: string, params: unknown[]): Promise<any> {
if (!this._isConnected) {
throw new Error('Provider not connected');
}
// Custom RPC request logic
const response = await fetch(this.endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: Date.now(),
method,
params
})
});
const result = await response.json();
if (result.error) {
throw new Error(result.error.message);
}
return result.result;
}
on(type: string, callback: (...args: any[]) => void): () => void {
this._eventemitter.addEventListener(type, callback);
return () => this._eventemitter.removeEventListener(type, callback);
}
clone(): CustomProvider {
return new CustomProvider(this.endpoint);
}
}
// Usage
const customProvider = new CustomProvider('https://my-custom-node.com');
const api = await ApiPromise.create({ provider: customProvider });Install with Tessl CLI
npx tessl i tessl/npm-polkadot--api