Skip to content
Logo

parse()

The parse() utility creates transports from URL-like one-liner strings. It dynamically loads the required transport packages at runtime.

Installation

npm i @rpckit/core

You must also install the transport packages you want to use:

npm i @rpckit/websocket @rpckit/tcp @rpckit/http @rpckit/fallback @rpckit/cluster

Basic Usage

import { parse } from '@rpckit/core'
 
const transport = await parse('wss://example.com')
await transport.connect()
 
const result = await transport.request('method', param1, param2)

Supported Schemes

SchemeTransportPackage
ws://, wss://WebSocket@rpckit/websocket
tcp://, tcp+tls://TCP@rpckit/tcp
http://, https://HTTP@rpckit/http
fallback(...)Fallback@rpckit/fallback
cluster(quorum,...)Cluster@rpckit/cluster

Simple Transports

WebSocket

const ws = await parse('wss://example.com')
const wss = await parse('wss://example.com:8443/path')

TCP

const tcp = await parse('tcp://example.com:50001')
const tcpTls = await parse('tcp+tls://example.com:50002')

HTTP

const http = await parse('https://example.com/rpc')

Meta-Transports

Fallback

Creates a fallback transport that tries transports in order:

const fb = await parse('fallback(wss://primary.com,wss://backup.com)')

With health ranking enabled:

const ranked = await parse('fallback(wss://a.com,wss://b.com)?rank=true')

Cluster

Creates a cluster transport requiring quorum consensus. The first argument is the quorum number:

// Require 2-of-3 agreement
const cluster = await parse('cluster(2,wss://node1.com,wss://node2.com,wss://node3.com)')

Options

Options are specified as query parameters:

const transport = await parse('wss://example.com?timeout=10000&keepAlive=30000')

Supported Options

OptionTypeDescription
timeoutnumberRequest timeout in milliseconds
keepAlivenumberKeep-alive ping interval in milliseconds
batchbooleanEnable/disable batching
batchSizenumberMaximum requests per batch
batchWaitnumberMaximum wait time before flushing batch (ms)
rankbooleanEnable health ranking for fallback transport
eagerConnectbooleanConnect all fallback transports in parallel
retryCountnumberNumber of retry attempts
retryDelaynumberBase delay between retries (ms)
clientNamestringClient name for electrum-cash handshake (default: 'rpckit')
protocolVersionstringProtocol version for electrum-cash handshake (default: '1.6')

Batching Options

// Enable batching with custom settings
const transport = await parse('wss://example.com?batchSize=10&batchWait=50')

Fallback Options

// Ranked fallback with eager connection
const transport = await parse('fallback(wss://a.com,wss://b.com)?rank=true&eagerConnect=true')

Cluster Options

// Cluster with custom timeout
const transport = await parse('cluster(2,wss://a.com,wss://b.com,wss://c.com)?timeout=5000')

Nested Transports

Meta-transports can be nested:

// Fallback with a cluster as backup
const nested = await parse('fallback(wss://primary.com,cluster(2,wss://a.com,wss://b.com,wss://c.com))')

Protocol-Specific Parse

createParse

Use createParse to create a parse function that uses different packages for transport creation:

import { createParse } from '@rpckit/core'
 
const electrumParse = createParse({
  websocket: '@rpckit/websocket/electrum-cash',
  tcp: '@rpckit/tcp/electrum-cash',
  http: '@rpckit/http/electrum-cash',
})
 
// Transports created by electrumParse have Electrum Cash defaults
const transport = await electrumParse('wss://electrum.example.com')

createParseSync

Use createParseSync to create a synchronous parse function using pre-imported factory functions. Unlike createParse which uses dynamic imports, this accepts already-loaded factories:

import { createParseSync } from '@rpckit/core'
import { webSocket } from '@rpckit/websocket/electrum-cash'
import { fallback } from '@rpckit/fallback'
 
const parse = createParseSync({ webSocket, fallback })
const transport = parse('fallback(wss://a.com,wss://b.com)?eagerConnect=true')

Factory keys are normalized automatically (webSocket maps to websocket).

Pre-Built Electrum Cash Parse

A pre-configured parse for Electrum Cash is available:

import { parse } from '@rpckit/core/electrum-cash'
 
const transport = await parse('wss://electrum.example.com')
// Handshake, keepAlive method, and unsubscribe conventions are pre-configured
 
// Custom client name and protocol version
const custom = await parse('wss://electrum.example.com?clientName=myapp&protocolVersion=1.5')

Pre-Built Ethereum Parse

A pre-configured parse for Ethereum is available:

import { parse } from '@rpckit/core/ethereum'
 
const transport = await parse('wss://ethereum-rpc.publicnode.com')
// Uses Ethereum transport variants with eth_subscription routing

Type Safety

Use generics to type the transport:

import { parse } from '@rpckit/core/electrum-cash'
import type { ElectrumCashSchema } from '@rpckit/core/electrum-cash'
 
const transport = await parse<ElectrumCashSchema>('wss://electrum.example.com')
 
// Typed request
const balance = await transport.request('blockchain.address.get_balance', address)

Error Handling

If a required package is not installed, parse() throws an error:

try {
  const transport = await parse('wss://example.com')
} catch (error) {
  // Error: Package @rpckit/websocket is not installed. Run: npm install @rpckit/websocket
}

Invalid URLs also throw errors:

await parse('invalid://example.com')
// Error: Unknown scheme: invalid

Example: Configuration-Driven Setup

import { parse } from '@rpckit/core'
 
// Configuration from environment or config file
const config = {
  transport: process.env.RPC_TRANSPORT || 'wss://localhost:8080'
}
 
async function createClient() {
  const transport = await parse(config.transport)
  await transport.connect()
  return transport
}
 
// Switch between transports without code changes
// RPC_TRANSPORT='fallback(wss://primary.com,wss://backup.com)?rank=true'
// RPC_TRANSPORT='cluster(2,wss://a.com,wss://b.com,wss://c.com)'
// RPC_TRANSPORT='tcp+tls://electrum.example.com:50002'