Skip to main content

Electrum Network Provider

The SolidCash SDK needs to connect to the BCH network to perform certain operations, like retrieving the contract's balance, or sending transactions. The recommended network provider is the ElectrumNetworkProvider.

Creating an ElectrumNetworkProvider​

The ElectrumNetworkProvider uses @electrum-cash/network library to connect to the configured electrum server. The connection uses a single, trusted electrum server so it does not have any fallback logic and does not validate SPV proofs for chain inclusion.

By default the ElectrumNetworkProvider creates a short-lived connection only when requests are pending. To configure this see the section on 'Manual Connection Management'.

Constructor​

Both network and options parameters are optional, and they default to mainnet with the bch.imaginary.cash Electrum server.

new ElectrumNetworkProvider(network?: Network, options?: Options)

Using the network parameter, you can specify the network to connect to. There's 4 networks supported by the ElectrumNetworkProvider:

type Network = 'mainnet' | 'chipnet' | 'testnet3' | 'testnet4';
NetworkDefault server
mainnetbch.imaginary.cash
chipnetchipnet.bch.ninja
testnet4testnet4.imaginary.cash
testnet3testnet.imaginary.cash

Any other network needs a hostname or a custom electrum client. The server must speak Electrum Cash protocol 1.5, which returns CashToken data with each UTXO.

Using the options parameter, you can specify a custom electrum client or hostname, enable manual connection management, and name the block-info oracle for contracts that read block data.

type Options = OptionsBase | CustomHostNameOptions | CustomElectrumOptions;

interface OptionsBase {
manualConnectionManagement?: boolean;
blockOracleCategory?: Uint8Array; // 32 bytes, display byte order
}

interface CustomHostNameOptions extends OptionsBase {
hostname: string;
}

interface CustomElectrumOptions extends OptionsBase {
electrum: ElectrumClient<ElectrumClientEvents>;
}

Example​

import { ElectrumNetworkProvider } from '@solidcash/solidcash/network/electrum';

const hostname = 'chipnet.bch.ninja';
const provider = new ElectrumNetworkProvider('chipnet', { hostname });

blockOracleCategory sets the provider's blockOracleCategory and derives its blockOracleLock. A contract that reads block.* values bakes that lock into its bytecode and co-spends the oracle; spending one built without a lock fails. See Block Data & Oracles.

ElectrumNetworkProvider Methods​

getUtxos()​

async provider.getUtxos(address: string): Promise<Utxo[]>;

Returns all UTXOs on specific address. Both confirmed and unconfirmed UTXOs are included.

interface Utxo {
txid: string;
vout: number;
satoshis: bigint;
token?: TokenDetails;
blockHeight?: number; // 0 while unconfirmed
}

interface TokenDetails {
amount: bigint;
category: string;
nft?: {
capability: 'none' | 'mutable' | 'minting';
commitment: string;
};
}

Example​

const userUtxos = await provider.getUtxos(userAddress)

getUtxosForLockingBytecode()​

async provider.getUtxosForLockingBytecode(lockingBytecode: Uint8Array | string): Promise<Utxo[]>;

Returns the UTXOs of a raw locking bytecode (a Uint8Array or a hex string), queried by its Electrum script hash. This also works for scripts that have no address.

getBlockHeight()​

async provider.getBlockHeight(): Promise<number>;

Get the current blockHeight.

Example​

const currentBlockHeight = await provider.getBlockHeight()

getRawTransaction()​

async provider.getRawTransaction(txid: string): Promise<string>;

Retrieve the Hex transaction details for a given transaction ID.

Example​

const rawTransaction = await provider.getRawTransaction(txid)

sendRawTransaction()​

async provider.sendRawTransaction(txHex: string): Promise<string>;

Broadcast a raw hex transaction to the network.

Example​

const txId = await provider.sendRawTransaction(txHex)

performRequest()​

Perform an arbitrary electrum request, refer to the docs at electrum-cash-protocol.

Example​

const verbose = true // get parsed transaction as json result
const txId = await provider.performRequest('blockchain.transaction.get', txid, verbose)

Manual Connection Management​

By default, the ElectrumNetworkProvider will automatically connect and disconnect to the electrum client as needed. However, you can enable manual connection management by setting the manualConnectionManagement option to true. This can be useful if you are passing a custom electrum client and are using that client for other purposes, such as subscribing to events.

const provider = new ElectrumNetworkProvider('chipnet', { manualConnectionManagement: true });
tip

If you're providing an ElectrumClient and using it to subscribe to address or block header events, you need to enable manualConnectionManagement to overwrite the default of connecting and disconnecting for each separate request.

connect()​

provider.connect(): Promise<void>;

Connects to the electrum client.

disconnect()​

provider.disconnect(): Promise<boolean>;

Disconnects from the electrum client, returns true if the client was connected, false if it was already disconnected.

Both methods throw when manualConnectionManagement is not enabled.

Using electrum-cash functionality​

To use more of the electrum-specific functionality which is not exposed in the ElectrumNetworkProvider you can simply call the methods on the electrum Client itself.

Custom Electrum Client​

When initializing an ElectrumNetworkProvider you have the option in the constructor to provide a custom electrum client. This way you can use one and the same indexer server for blockchain information but use it through two different interfaces. This allows you to access all underlying functionality of the @electrum-cash/network library like address and blockHeight subscriptions.

If intending to use electrum-cash subscriptions, make sure to set manualConnectionManagement to true, so the ElectrumNetworkProvider does not disconnect after each request.

Example​

import { ElectrumClient } from '@electrum-cash/network';
import { ElectrumNetworkProvider } from '@solidcash/solidcash/network/electrum';

const electrum = new ElectrumClient('SolidCash Application', '1.5.0', 'chipnet.bch.ninja');
const provider = new ElectrumNetworkProvider('chipnet', {
electrum, manualConnectionManagement: true
});
await electrum.connect();