eCash for Flutter
Package for interacting with eCash (XEC) blockchain.
eCashAddr
Set of functions for encoding, decoding and validating eCash Addresses.
import 'package:ecash/ecashaddr.dart';
// Encode a hash into an eCash address
final address = encodeCashAddress('ecash', AddressType.p2pkh, '76a04053bda5c88f2db1002ad94f303ab715f0eda');
// ecash:qpm2qsznhks23z7629mms6s4cwef74vcwva87rkuu2
// Decode an address into its components
final decoded = decodeCashAddress('ecash:qpm2qsznhks23z7629mms6s4cwef74vcwva87rkuu2');
// DecodedAddress(prefix: 'ecash', type: p2pkh, hash: '76a04053bda5c88f2db1002ad94f303ab715f0eda')
eCash Chronik Client
A comprehensive Dart port of the JavaScript chronik-client library for accessing the Chronik blockchain indexer on eCash (XEC).
Quick Start
import 'package:ecash/ecash.dart';
void main() async {
// Create a client using connection strategy
final chronik = await ChronikClient.useStrategy(
ConnectionStrategy.closestFirst,
[
'https://chronik1.e.cash',
'https://chronik2.e.cash',
],
);
// Get blockchain info
final info = await chronik.blockchainInfo();
print('Tip height: ${info.tipHeight}');
// Get a transaction
final tx = await chronik.tx('0f3c...');
print('TX: ${tx.txid}');
// Query script history
final history = await chronik
.script('p2pkh', 'hash160...')
.history(page: 0, pageSize: 10);
// Get UTXOs for an address
final utxos = await chronik.address('ecash:...').utxos();
// WebSocket subscriptions
final ws = chronik.ws(WsConfig(
onMessage: (msg) {
if (msg is WsMsgBlockClient) {
print('Block: ${msg.blockHash}');
}
},
));
ws.subscribeToBlocks();
chronik.close();
}
API Overview
Blockchain Info
// Get blockchain information
final blockchainInfo = await chronik.blockchainInfo();
// Get server information
final chronikInfo = await chronik.chronikInfo();
Blocks
// Get a block by hash or height
final block = await chronik.block('hashOrHeight');
// Get multiple blocks
final blocks = await chronik.blocks(startHeight, endHeight);
// Get transactions in a block
final blockTxs = await chronik.blockTxs('hashOrHeight', page: 0, pageSize: 25);
Transactions
// Get transaction details
final tx = await chronik.tx('txid...');
// Get raw transaction bytes
final rawBytes = await chronik.rawTx('txid...');
// Broadcast a transaction
final response = await chronik.broadcastTx(txBytes);
// Broadcast and wait for finalization
final finalResponse = await chronik.broadcastAndFinalizeTx(txBytes);
// Validate a transaction without broadcasting
final validation = await chronik.validateRawTx(txBytes);
Scripts and Addresses
// Query by script
final scriptEndpoint = chronik.script('p2pkh', 'payload...');
final history = await scriptEndpoint.history(page: 0, pageSize: 10);
final utxos = await scriptEndpoint.utxos();
final confirmed = await scriptEndpoint.confirmedTxs();
final unconfirmed = await scriptEndpoint.unconfirmedTxs();
// Query by eCash address
final addressEndpoint = chronik.address('ecash:...');
Tokens
// Get token information
final tokenInfo = await chronik.token('tokenId...');
// Get token endpoint for queries
final tokenEndpoint = chronik.tokenId('tokenId...');
final tokenHistory = await tokenEndpoint.history();
final tokenUtxos = await tokenEndpoint.utxos();
Lokad IDs
// Get lokad ID endpoint
final lokadEndpoint = chronik.lokadId('lokadId...');
final history = await lokadEndpoint.history();
Plugins
// Get plugin endpoint
final pluginEndpoint = chronik.plugin('pluginName');
final groups = await pluginEndpoint.groups();
final utxos = await pluginEndpoint.utxos('groupHex');
final history = await pluginEndpoint.history('groupHex');
WebSocket
final ws = chronik.ws(WsConfig(
onMessage: (msg) {
switch (msg) {
case WsMsgBlockClient():
print('Block update: ${msg.blockHash}');
case WsMsgTxClient():
print('TX update: ${msg.tx.txid}');
case WsErrorMsg():
print('Error: ${msg.error}');
}
},
onConnect: () {
print('Connected');
},
onReconnect: (error) {
print('Reconnecting due to: $error');
},
keepAlive: true,
));
// Wait for connection
await ws.waitForOpen();
// Subscribe/unsubscribe
ws.subscribeToBlocks();
ws.subscribeToScript('p2pkh', 'payload...');
ws.subscribeToAddress('ecash:...');
ws.subscribeToTokenId('tokenId...');
ws.subscribeToLokadId('lokadId...');
ws.subscribeToTxid('txid...');
ws.subscribeToTxs(); // All transactions
ws.subscribeToPlugin('pluginName', 'groupHex');
// Unsubscribe
ws.unsubscribeFromBlocks();
ws.unsubscribeFromScript('p2pkh', 'payload...');
// Mobile apps can pause/resume
ws.pause(); // Stop reconnecting
ws.resume(); // Resume reconnecting
// Close
ws.close();
Connection Strategies
ClosestFirst (Recommended)
Selects the fastest server based on WebSocket latency measurement:
final chronik = await ChronikClient.useStrategy(
ConnectionStrategy.closestFirst,
['https://chronik1.e.cash', 'https://chronik2.e.cash'],
);
The client will:
- Measure latency to all servers
- Sort by latency (fastest first)
- Use the fastest server
- Failover to the next fastest on connection failure
AsOrdered
Uses servers in the provided order:
final chronik = await ChronikClient.useStrategy(
ConnectionStrategy.asOrdered,
['https://primary.e.cash', 'https://backup.e.cash'],
);
Error Handling
The client throws strongly-typed exceptions:
try {
final tx = await chronik.tx('invalid');
} on ValidationException catch (e) {
print('Validation error: ${e.message}');
} on ServerException catch (e) {
print('Server error: ${e.message}');
} on AllServersFailedException catch (e) {
print('All servers failed: ${e.failedServers}');
} catch (e) {
print('Unknown error: $e');
}
Libraries
- chronik
- chronik/chronik.pb
- chronik/chronik.pbenum
- chronik/chronik.pbjson
- chronik/client
- Main Chronik client class
- chronik/endpoints
- chronik/failover_proxy
- chronik/types
- chronik/utils
- chronik/validation
- chronik/ws_endpoint
- ecash
- ecashaddr
- ecashaddr/base32
- ecashaddr/cashaddr
- ecashaddr/convert_bits
- ecashaddr/types
- ecashaddr/validation