Writing tests against it
The local network is shared and it keeps growing. Every test we run adds to the same chain, and the autominer adds a block whenever it likes. A test that assumes it has the chain to itself works the first time and fails the tenth. These are the habits that keep our tests honest.
- Wait for a status, or anything after it. Never wait for one exact status. A block can be mined between two polls, so a test waiting for
SEEN_ON_NETWORKmust also acceptMINED. - Mine explicitly. Don’t wait on the autominer, which takes 10 minutes. For runs that must not see a block they didn’t ask for, set
MINE_INTERVAL=0in.envand run./scripts/start.shagain. - Don’t assume heights. Read the tip from the DataHub, and remember that the subsidy halves every 150 blocks.
- Use a fresh callback token per run. An
X-CallbackTokenthat is new for each run scopes the SSE stream and the webhooks to that run’s Transactions. - Fund through Arcade when the test needs a proof. That is
faucet.sh send … --arcade, as in Getting coins. - Check the health first.
curl -sf http://127.0.0.1:23012/healthchecks Arcade, and./scripts/status.shalso tells us whether Merkle Service is connected. Without that connection nothing gets pastACCEPTED_BY_NETWORK, and the test fails for a reason that has nothing to do with our code. - A wiped chain needs no other clean-up. After
reset.shandstart.sh, the faucet rescans from scratch and Arcade’s store is wiped with the rest.
The libtokensv
*_localnet_test.dartfiles are a working example of all of this. They broadcast and mine every kind of Lineage Token on this network, and are skipped when the network isn’t running.
Coming from SV Node or arc_regtest
Section titled “Coming from SV Node or arc_regtest”Before Teranode, our local setup was an SV Node in regtest mode, at first on its own and later behind ARC in arc_regtest. The two can run side by side with localnet-teranode, as they share no ports, containers or volumes. Moving a client across is mostly a change of addresses:
| SV Node and arc_regtest | localnet-teranode |
|---|---|
ARC at http://localhost:9090/v1 |
Arcade at http://127.0.0.1:23011, with no /v1 |
SV Node P2P on localhost:18333 |
Teranode’s wire protocol on 127.0.0.1:18444, with a user agent containing BSV |
SV Node RPC on localhost:18332 |
Teranode’s RPC on 127.0.0.1:19292, with no wallet methods |
bitcoin-cli sendtoaddress, or fund.sh <address> |
faucet.sh send <address> <satoshis> --arcade |
bitcoin-cli generate 101 |
mine.sh 101, although start.sh already does this |
ZeroMQ on localhost:28332 |
none: Arcade’s SSE stream and webhooks for our Transactions, or libp2p gossip for blocks |
| Chronicle at height 15,000 | Chronicle at height 200 |
The client code needs a few changes too:
POST /txanswers202 RECEIVEDstraight away, and there is noX-WaitFor. The client follows the status afterwards.- Transactions must be in Extended Format.
- There are new statuses (
SEEN_MULTIPLE_NODESandPENDING_RETRY), and a reorg moves aMINEDTransaction back toSEEN_ON_NETWORK. POST /txstakes the Transactions concatenated asapplication/octet-stream, not as a JSON array.
libspiffy 4.6.0 and later handle all of this. The repository’s CONSUMING.md has the full comparison.

