Skip to main content

Mock, Regtest & Legacy Providers

Use ElectrumNetworkProvider for ordinary token-aware public-network access. The SDK also includes a deterministic in-process provider, a live BCHN regtest adapter, and two narrower legacy backends.

MockNetworkProvider​

MockNetworkProvider evaluates and indexes transactions locally with the BCH 2026 VM. It is intended for unit and e2e tests, not as a public network emulator or persistence layer. Every accepted transaction is mined into a block at once.

import { MockNetworkProvider } from 'solidcash/network/mock';

const provider = new MockNetworkProvider();
const [owner, user] = await provider.getSigners(2, {
fundingUtxos: 5,
satoshis: 1_000_000n,
});

The provider returns CashToken details, queries raw locking bytecode, records raw transactions, and updates its UTXO set after successful broadcasts by default. The signers use the public Hardhat test mnemonic; never use them outside isolated test networks.

getSigners(count = 20, options) returns HDSigners, each funded once with a genesis-valid coin. The options are satoshis per coin (default 1_000_000n), fundingUtxos (coins per signer, default 1), genesisFundingUtxos (how many of those coins sit at vout: 0 of their own transaction, default 1), mnemonic and path. getSigner(index) returns one funded signer.

Consensus and policy profile​

const productionShape = new MockNetworkProvider({
consensusLimits: {
maximumInputBytes: 10_000,
maximumStackItemBytes: 10_000,
maximumTransactionBytes: 100_000,
maximumNftCommitmentBytes: 128,
},
policy: { enforceDust: true },
});

Mock defaults relax size ceilings so large protocol tests can execute, but retain the real operation-cost density budget. The default MOCK_CONSENSUS_LIMITS allow 1,000,000-byte inputs, stack items and NFT commitments, 10,000,000-byte transactions and relaxed hash iterations, keep 800 operation-cost units per byte, and apply no dust rule. Override fields deliberately when testing a boundary; each option object is merged over the defaults. The mock accepts only whole-number hash-iteration limits, so the real fractional allowances (0.5 per byte for relay, 3.5 for consensus) cannot be set on it. Pass operationCostBudgetPerByte: MOCK_RELAXED_OPERATION_COST only in a harness that tests the relaxed profile itself. A green relaxed mock test is not evidence that the transaction satisfies production script, transaction, standardness, or relay limits.

updateUtxoSet: false records submitted transactions without validating them or applying their outputs, and is useful for isolated debug evaluation.

UTXO and token fixtures​

import { randomUtxo } from 'solidcash';

await provider.addUtxo(addressOrLockingBytecode, randomUtxo({
vout: 0,
satoshis: 100_000n,
}));

const { categoryId, utxos } = await provider.addTokenUtxos([
{ address, satoshis: 1_200n, token: { amount: 100n } },
]);

const dynamic = await provider.addTokenUtxosDynamic((createdCategory) => [
{ address, satoshis: 1_200n, token: { amount: 0n, nft: {
capability: 'mutable',
commitment: deriveCommitment(createdCategory),
} } },
]);

addUtxo() is asynchronous; it takes an address or a hex locking bytecode and preserves the supplied outpoint and token record. Use a distinct vout: 0 transaction when a fixture must be a valid CashToken genesis input. addTokenUtxos() creates one coherent category for its output list; addTokenUtxosDynamic(factory) also exposes that category while building category-dependent commitments. Both return { categoryId, utxos }: the category is a random txid, and output i of the list is the UTXO categoryId:i.

Height, time, and snapshots​

provider.setBlockHeight(900_000);
await provider.mine(3);
await provider.mineUpTo(900_010);

provider.setNextBlockTimestamp(1_900_000_000);
provider.increaseTime(3600);

const snapshot = await provider.takeSnapshot();
// ... mutate provider state
await snapshot.restore();

mine() advances the height, increaseTime() moves the tip timestamp at once and returns it, and setNextBlockTimestamp() applies to the next mined block. takeSnapshot() captures the chain, the height and the time; its restore() rewinds to that point and can be called repeatedly.

The EIP-1193-style send(method, params) surface implements the Hardhat-compatible network helpers used by SolidHat: evm_snapshot, evm_revert, evm_mine, hardhat_mine, evm_increaseTime, evm_setNextBlockTimestamp, eth_blockNumber and eth_chainId; evm_setAutomine is accepted and ignored. reset() clears the UTXO set, accepted transactions and signer funding, resets the block time and re-creates the block oracle; the block height stays.

The mock mints its own block-info oracle and writes its height and time into it as it mines, so contracts that read block.* values work without setup. See Block Data & Oracles.

RegtestNetworkProvider​

RegtestNetworkProvider drives a real BCHN regtest node and mines after broadcasts. It is the integration-test bridge between relaxed in-memory evaluation and real node admission.

import { RegtestNetworkProvider } from 'solidcash';

const provider = new RegtestNetworkProvider({
rpcUrl: 'http://localhost:18443',
rpcUser: 'user',
rpcPassword: 'password',
});

await provider.mine(1);

The values shown are the defaults, so new RegtestNetworkProvider() connects to the same node. The provider reads no environment variables; a project created by SolidHat passes REGTEST_RPC_URL, REGTEST_RPC_USER and REGTEST_RPC_PASSWORD to it from its config. The consensusLimits and policy options publish limits for SDK preflight; configure the node to match them.

It imports addresses into the node wallet as needed, returns token-aware listunspent records, deduplicates token and ordinary CashAddress views of the same script, and supports raw-locking-bytecode lookup where the script can be converted to an address, plus outputs it broadcast itself. Its addUtxo(address, utxo) and token fixture helpers create actual transactions and preserve genuine genesis categories rather than silently substituting labels. Each broadcast is mined into a block at once, and the provider mints and updates its own block-info oracle as the mock does.

increaseTime(seconds) is asynchronous: it sets the node's mock clock and mines a median-time window of blocks, so that the node's median-time-past reaches the new time. takeSnapshot() returns a restore() that rewinds the chain, and send() maps the same Hardhat helpers as the mock except hardhat_mine.

Run it only against a disposable regtest wallet. reset() clears the provider's caches and mock clock but does not rewind the chain; use a snapshot, or reset the BCHN data directory, when test isolation requires it.

FullStackNetworkProvider​

import BCHJS from '@psf/bch-js';
import { FullStackNetworkProvider } from 'solidcash';

const bchjs = new BCHJS({
restURL: 'https://api.fullstack.cash/v3/',
apiToken: process.env.FULLSTACK_TOKEN,
});
const provider = new FullStackNetworkProvider('mainnet', bchjs);

This adapter uses BCHJS ElectrumX and raw-transaction endpoints. It does not return CashToken metadata and does not support getUtxosForLockingBytecode(). Do not use it for stateful contracts, token transactions, or any builder which must avoid accidentally treating token-bearing UTXOs as BCH-only inputs.

BitcoinRpcNetworkProvider​

import { BitcoinRpcNetworkProvider } from 'solidcash';

const provider = new BitcoinRpcNetworkProvider(
'mainnet',
'http://localhost:8332',
{ rpcUser: process.env.BCH_RPC_USER!, rpcPassword: process.env.BCH_RPC_PASSWORD! },
);

The generic RPC adapter uses wallet listunspent, so addresses must be imported before funds arrive or otherwise be known to the node wallet. It does not return CashToken metadata and cannot query arbitrary locking bytecode. getClient() returns its RPC client for other node calls. Use RegtestNetworkProvider for token-aware BCHN tests and Electrum for public stateful deployments.

Capability summary​

ProviderCashTokensRaw script lookupLocal mutation helpersIntended use
ElectrumYesYesNoPublic stateful/stateless applications
MockYesYesYesFast deterministic tests
RegtestYesAddressable scripts and its own broadcastsYes, on real BCHNNode-level integration tests
FullStackNoNoNoLegacy BCH-only access
Bitcoin RPCNoNoNoWallet-known BCH-only access

See Network Provider for the shared interface and Testing Setup for fixture patterns.