Against live networks.
Contract resolution, FTSOv2 price feeds, Scaling anchor feeds with Merkle proofs, FDC attestations, FAssets, event log decoding, WebSocket subscriptions, arbitrary eth_call, and the transaction path above.
Open source · pure Dart · three dependencies
Flare publishes developer guides for JavaScript, React, Python, Rust and Go. There is no Dart guide: querying Flare's own documentation search for dart or flutter returns "No matching documents found". This repository is that missing piece.
import 'package:flare_network/flare_network.dart';
Future<void> main() async {
final client = FlareClient(FlareChain.coston2);
try {
final ftso = await FtsoV2.resolve(client);
final ids = [Feeds.flrUsd, Feeds.btcUsd];
for (final f in await ftso.getFeedsById(ids)) {
print('${f.feedId.name}: ${f.toDecimalString()}');
}
} finally {
client.close();
}
}
Output
FLR/USD: 0.00626973 BTC/USD: 62887.17
Because Flare is EVM compatible, and a reviewer will check.
A Flutter app could always reach Flare over JSON-RPC, and web3dart is a maintained, general purpose Dart EVM library that works against any Flare RPC. That has never been the gap.
What did not exist is anything Flare specific: typed, generated bindings for Flare's own contracts, so that FTSO feeds, FDC attestations, FAssets minting and Smart Accounts are reachable without hand-rolling ABIs against the registry.
That is the difference between a week of work and an import.
Generated from Flare's own ABI artifacts, so they do not drift by hand.
| Package | What it is |
|---|---|
flare_network | The core SDK. Pure Dart, three dependencies, no Flutter, no FFI |
flare_network_periphery | 164 generated bindings: 1,049 read methods, 513 transaction builders, 592 events, 168 custom errors |
flare_network_codegen | Dev-only CLI. Flare's ABI artifacts into typed Dart |
examples/developer-hub-dart | 17 runnable examples, mirroring Flare's own Go, Python and Rust sets |
A deliberate, permanent non-goal. It does everything on either side of the signature.
final wnat = await IWNatContract.resolve(client);
// Build. Only payable functions accept a value, so attaching one to a
// function that would reject it does not compile.
final tx = wnat.depositTx(value: BigInt.from(10).pow(18), from: user);
// Price. Simulates against current state, so a doomed action fails here,
// before the user is asked to approve it and before it costs anything.
final ready = await client.prepareTransaction(tx);
print(ready.maxCost); // worst case, in wei
// Sign, with your wallet library. Not this package.
final hash = await wallet.request('eth_sendTransaction', [ready.toWalletJson()]);
// Confirm. A mined transaction is not a successful one.
final receipt = await client.waitForReceipt(hash);
if (!receipt.succeeded) { /* reverted, and still cost gas */ }
If it reverts after it is mined, the receipt will not tell you why: it has no field for it. Replaying the call at its own block does.
if (!receipt.succeeded) {
final why = await client.explainRevert(receipt);
print(why?.description); // "ERC20: transfer amount exceeds balance"
}
When something reverts before signing, you get the reason directly. That matters on Flare specifically, because 168 of the custom errors in the published ABIs carry no message at all, so the node reports them as four opaque bytes.
try {
await client.prepareTransaction(tx);
} on FlareRpcException catch (e) {
print(IAssetManagerContract.decodeRevert(e)?.description);
// e.g. "InsufficientFundsForRedeem(1000000)"
}
Smart Accounts gives an XRP holder a Flare account they control from XRPL. No FLR for gas, no Flare key. Live on mainnet and on Coston2.
final accounts = await SmartAccountsClient.resolve(client);
final account = await accounts.accountFor('rLDkBYohbZw1AuFnpYtAcq8sbMjjBWKvE4');
// `address` is derived, not looked up. It is non-zero even for an XRPL
// address that has never existed. `isDeployed` is the field that matters.
if (account.isDeployed) {
final held = await accounts.balancesOf(account.address);
print(held.fXrp.balance);
print(held.heldVaults); // not `vaults`, which lists every vault, held or not
}
Those two naming choices are the whole point of a typed binding. An address that is derived
rather than looked up is non-zero for an account that does not exist, and a list called
vaults that means "all vaults" rather than "your vaults" is a bug waiting for
somebody's balance display.
isDeployed, never the address.
Runs on all six platforms Dart targets, including web, and pana reports the package WASM ready.
Contract resolution, FTSOv2 price feeds, Scaling anchor feeds with Merkle proofs, FDC attestations, FAssets, event log decoding, WebSocket subscriptions, arbitrary eth_call, and the transaction path above.
They are not EVM transactions. Hardware wallets that only sign are served by sendRawTransaction, which broadcasts for them.
dart test runs 240 hermetic, offline. dart test -P integration runs 91 against live Coston2.
cd packages/flare_network dart test # 240 tests, hermetic, offline dart test -P integration # 91 tests against live Coston2
Three projects, one build
Typed bindings for Flare's own contracts, so FTSO, FDC, FAssets and Smart Accounts are an import.
flaredart.trimmy.xyz The safety checkKnow what your XRPL payment will do on Flare before you sign it. It refuses the ones that lose money.
plimsoll.trimmy.xyz ↗ The productAI-friendly automation for XRP. One XRPL payment arms a standing rule on Flare that afterwards executes itself.
trimmy.xyz ↗