CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-polkadot--api

Promise and RxJS wrappers around the Polkadot JS RPC for interacting with Polkadot and Substrate-based blockchains

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

network-providers.mddocs/

Network Providers

Connection providers for different transport protocols and connection types. The @polkadot/api supports multiple provider implementations for connecting to blockchain nodes through various protocols.

Capabilities

WebSocket Provider

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 Provider

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;
}

Substrate Connect Provider

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;
}

Keyring Management

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;
}

Usage Examples

WebSocket Provider Setup

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();

HTTP Provider Setup

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 subscriptions

Substrate Connect Provider

import { 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'));

Keyring Management

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);

Secure Key Management

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);

Provider Error Handling

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);
}

Custom Provider Implementation

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

docs

api-initialization.md

blockchain-queries.md

events-metadata.md

index.md

network-providers.md

rpc-operations.md

transaction-submission.md

tile.json