2 · Install & initialize
In this step you create the program, add libspiffy, and start its actor system pointed at your local network.
Create the program
Section titled “Create the program”dart create -t console first_paymentcd first_paymentReplace the dependencies in pubspec.yaml:
environment: sdk: ^3.5.1
dependencies: libspiffy: ^5.0.0 isar_community: ^3.3.2 http: ^1.1.0Then 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.
Start libspiffy against localnet
Section titled “Start libspiffy against localnet”Put the localnet settings in one place:
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:
isaris your Isar instance, opened withLibSpiffySchemas.allSchemas. With it, libspiffy keeps both its event journal and its read models in Isar.secureStorageholds wallet keys.InMemorySecureStorageis 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'.peerAddressesare the nodes libspiffy syncs block headers from over P2P (enableP2Pdefaults totrue).arcConfigis where transactions are broadcast and where their status and merkle proofs come from.
Talking to the coordinator
Section titled “Talking to the coordinator”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.
The program’s skeleton
Section titled “The program’s skeleton”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:
LOCALNET_TERANODE=/path/to/localnet-teranode dart run bin/first_payment.dartlibspiffy is up; headers at 0The header chain starts at 0. libspiffy keeps syncing headers from Teranode in the background while your program carries on.