Skip to content

2 · Install & initialize

In this step you create the program, add libspiffy, and start its actor system pointed at your local network.

Terminal window
dart create -t console first_payment
cd first_payment

Replace the dependencies in pubspec.yaml:

pubspec.yaml
environment:
sdk: ^3.5.1
dependencies:
libspiffy: ^5.0.0
isar_community: ^3.3.2
http: ^1.1.0

Then run dart pub get. libspiffy stores its event journal and read models in Isar, so your program depends on Isar too. You’ll use http to talk to Arcade in step 4.

Put the localnet settings in one place:

lib/localnet.dart
import 'dart:io';
import 'package:isar_community/isar.dart';
import 'package:libspiffy/libspiffy.dart';
/// Arcade, localnet-teranode's ARC-compatible API. No `/v1`.
const arcadeUrl = 'http://127.0.0.1:23011';
/// Teranode's Bitcoin wire protocol, where libspiffy syncs block headers.
const nodePeer = '127.0.0.1:18444';
/// Your localnet-teranode checkout. Set LOCALNET_TERANODE to change it.
final localnetDir =
Platform.environment['LOCALNET_TERANODE'] ?? '../localnet-teranode';
/// Starts libspiffy against localnet-teranode, storing everything under
/// [dataDir].
Future<LibSpiffyActorSystem> startLocalnet(String dataDir) async {
// A plain Dart program loads Isar's native library itself.
// (A Flutter app gets it from isar_community_flutter_libs instead.)
await Isar.initializeIsarCore(download: true);
final isar = await Isar.open(
LibSpiffySchemas.allSchemas,
directory: dataDir,
name: 'tutorial',
);
final libspiffy = LibSpiffyActorSystem();
await libspiffy.initialize(
isar: isar,
dataDirectory: dataDir,
// Development only: keys live in memory and are gone when the program
// exits. A real app passes a SecureStorage backed by the platform
// keystore.
secureStorage: InMemorySecureStorage(),
networkType: 'regtest',
enableP2P: true,
peerAddresses: [nodePeer],
arcConfig: ArcServiceConfig(baseUrl: arcadeUrl),
);
return libspiffy;
}

What each argument does:

  • isar is your Isar instance, opened with LibSpiffySchemas.allSchemas. With it, libspiffy keeps both its event journal and its read models in Isar.
  • secureStorage holds wallet keys. InMemorySecureStorage is for development only: it keeps keys in plain memory. Because of that, the program uses a fresh data directory on every run.
  • networkType: 'regtest' selects regtest network parameters. The other values are 'test' (the default) and 'main'.
  • peerAddresses are the nodes libspiffy syncs block headers from over P2P (enableP2P defaults to true).
  • arcConfig is where transactions are broadcast and where their status and merkle proofs come from.

libspiffy.coordinator is a WalletCoordinator, your app’s one entry point. It does three things:

Method What it does
ask(request) Sends a command or query and completes with its own reply, even when other requests of the same kind are running. If the request failed, it throws CoordinatorFailure.
on<E>({walletId}) A stream of one kind of event, optionally for one wallet. Use it for events nobody asked for: balance changes, confirmations, incoming payments.
tell(command) Sends without waiting. The reply, if any, arrives on libspiffy.coordinatorEvents.

Each request has a default reply timeout suited to what it does. For example, ask waits up to 1 minute for most requests, 3 minutes for building a payment, and 5 minutes for receiving one. You can pass timeout: to change it.

bin/first_payment.dart
import 'dart:io';
import 'package:first_payment/localnet.dart';
import 'package:libspiffy/coordinator.dart';
import 'package:libspiffy/libspiffy.dart';
Future<void> main() async {
// Step 2: initialize libspiffy against the local network.
final dataDir = await Directory.systemTemp.createTemp('first_payment_');
final libspiffy = await startLocalnet(dataDir.path);
final coordinator = libspiffy.coordinator;
print('libspiffy is up; headers at ${libspiffy.headerChain.bestHeight}');
// Steps 3–8 go here.
await libspiffy.shutdown();
await dataDir.delete(recursive: true);
}

Run it:

Terminal window
LOCALNET_TERANODE=/path/to/localnet-teranode dart run bin/first_payment.dart
libspiffy is up; headers at 0

The header chain starts at 0. libspiffy keeps syncing headers from Teranode in the background while your program carries on.

Next: create wallets →