Flare Transaction SDK
Flare Transaction SDK (@flarenetwork/flare-tx-sdk
) is the official Node.js Software Development Kit for performing common actions on Flare's networks:
- Retrieving account and balance information
- Transferring native and wrapped coins
- Claiming rewards from FlareDrops, staking, and FTSO delegation
- Delegating to FTSO providers
- Interacting with the C-chain contracts
- Staking on the P-chain
This guide will walk you through installation, core concepts, and cookbook for all major features.
You can raise an issue on the flare-foundation/flare-tx-sdk GitHub repository.
Prerequisites
Before you start, ensure you have the following:
- Node.js
- An EIP-1193 (e.g. MetaMask, WalletConnect), or a hardware wallet like Ledger or Trezor.
Installation
To get started, install the SDK into your Node.js project:
- npm
- yarn
npm install @flarenetwork/flare-tx-sdk
yarn add @flarenetwork/flare-tx-sdk
Core concepts
Before you write code, it's helpful to understand two key components of the SDK:
-
Network
Object: This is your main entry point for all on-chain actions. It represents the network you want to connect to (FLARE
,COSTON2
,SONGBIRD
orCOSTON
) and provides all the methods for querying balances, sending transactions, and interacting with contracts. -
Wallet
Object: This object represents the user's account. It's responsible for providing a public key to identify the account and for signing transactions. The SDK doesn't handle private keys directly; instead, it defines aWallet
interface that you can implement using standard wallets like MetaMask, Ledger, or your own custom signer.
Quick start
Here's a simple example of how to use the SDK to connect to Flare Mainnet with a MetaMask wallet and check an account's balance.
import { Network, EIP1193WalletController } from "@flarenetwork/flare-tx-sdk";
async function main() {
console.log("Connecting to the Flare Mainnet...");
// 1. Initialize the Network object for Flare Mainnet
const network = Network.FLARE;
// 2. Connect to the active wallet in MetaMask
const controller = new EIP1193WalletController(window.ethereum);
const wallet = await controller.getActiveWallet();
// 3. Get the public key from the wallet
const publicKey = await wallet.getPublicKey();
// 4. Derive the C-Chain and P-Chain addresses
const cAddress = network.getCAddress(publicKey);
const pAddress = network.getPAddress(publicKey);
console.log(`C-Chain Address: ${cAddress}, P-Chain Address: ${pAddress}`);
// 5. Fetch the account's complete balance overview
console.log("Fetching balance...");
const balance = await network.getBalance(publicKey);
console.log("✅ Balance retrieved successfully!");
// All amounts are returned as wei
console.log(` - Available on C-Chain: ${balance.availableOnC} wei`);
console.log(` - Wrapped on C-Chain: ${balance.wrappedOnC} wei`);
console.log(` - Available on P-Chain: ${balance.availableOnP} wei`);
console.log(` - Staked on P-Chain: ${balance.stakedOnP} wei`);
}
main().catch(console.error);
Cookbook
This section provides practical guides for each major feature of the SDK.
Get account balances
The Flare network uses two chains: the C-Chain (Contract Chain) for EVM smart contracts and the P-Chain (Platform Chain) for staking. Both chains derive their addresses from a single public key.
// Get the public key from your wallet
const publicKey = await wallet.getPublicKey();
// Derive the addresses for each chain
const cAddress = network.getCAddress(publicKey);
const pAddress = network.getPAddress(publicKey);
// Get a full balance overview
const balance = await network.getBalance(publicKey);
// Or, query for specific balances
const cBalance = await network.getBalanceOnC(cAddress);
const cWrappedBalance = await network.getBalanceWrappedOnC(publicKeyOrCAddress);
const pBalance = await network.getBalanceOnP(publicKey);
const stakedBalance = await network.getBalanceStakedOnP(publicKey);
Wrap and transfer
Transfer native FLR and its wrapped equivalent WFLR on the C-Chain.
import { Amount } from "@flarenetwork/flare-tx-sdk";
// Transfer 1 FLR
await network.transferNative(wallet, recipientAddress, Amount.nats(1)); // Amount.nats handles the conversion to wei
// Wrap 1 FLR -> 1 WFLR
await network.wrapNative(wallet, Amount.nats(1));
// Transfer 1 WFLR
await network.transferWrapped(wallet, recipientAddress, Amount.wnats(1));
// Unwrap 1 WFLR -> 1 FLR
await network.unwrapToNative(wallet, Amount.wnats(1));
Claim Flaredrops rewards
// Check claimable FlareDrop rewards
const flareDropAmount = await network.getClaimableFlareDropReward(cAddress);
if (flareDropAmount > 0) {
// Claim the reward and send it to the wallet's C-Chain address
await network.claimFlareDropReward(wallet);
}
You can also pass additional parameters to modify:
rewardOwner
(address) - C-chain address of the reward ownerrecipient
(address) - C-chain address of where the reward should be transferredwrap
(boolean) - transfer reward as native (default) or wrapped.
await network.claimFlareDropReward(wallet, rewardOwner, recipient, wrap);
Claim staking rewards
// Check and claim staking rewards
const stakingRewardAmount = await network.getClaimableStakingReward(cAddress);
if (stakingRewardAmount > 0) {
await network.claimStakingReward(wallet);
}
You can also pass additional parameters to modify:
rewardOwner
(address) - C-chain address of the reward ownerrecipient
(address) - C-chain address of where the reward should be transferredwrap
(boolean) - transfer reward as native (default) or wrapped.
await network.claimStakingReward(wallet, rewardOwner, recipient, wrap);
Claim FTSO delegation rewards
// Check and claim FTSO delegation rewards
const ftsoRewardAmount = await network.getClaimableFtsoReward(cAddress);
if (ftsoRewardAmount > 0) {
await network.claimFtsoReward(wallet);
}
You can also pass additional parameters to modify:
rewardOwner
(address) - C-chain address of the reward ownerrecipient
(address) - C-chain address of where the reward should be transferredwrap
(boolean) - transfer reward as native (default) or wrapped.
await network.claimFtsoReward(wallet, rewardOwner, recipient, wrap);
Detailed rewards
let states = await network.getStateOfFtsoRewards(cAddress);
The method returns an array of reward-epoch arrays.
It can be empty or it consists of objects of type FtsoRewardState
with properties:
rewardEpochId
(int) - The reward epoch id.beneficiary
(string) - The reward owner (C-chain address orNodeID
if claimType isMIRROR
).amount
(int) - The reward amount in wei.claimType
(string) - The type of claim (DIRECT
,FEE
,WNAT
,MIRROR
, orCCHAIN
).initialised
(boolean) - flag indicating if the reward can be claimed without providing proofs.
Claim with proofs
Rewards that are not initialized can be claimed using Merkle proofs available in the flare-foundation/fsp-rewards repository.
await network.claimFtsoReward(wallet, rewardOwner, recipient, wrap, proofs);
where proofs is an array of objects of type FtsoRewardClaimWithProof
with properties:
merkleProof
(array of string) - The Merkle proof in hexadecimal encoding.body
(FtsoRewardClaim
) - Same structure asFtsoRewardState
without theinitialised
parameter.
Delegate to FTSO providers
Delegate your wrapped token vote power to one or two FTSO data providers to earn rewards.
import { Amount } from "@flarenetwork/flare-tx-sdk";
// Get current delegations
const delegations = await network.getFtsoDelegatesOf(cAddress);
console.log(delegations);
which returns an array of FtsoDelegate
:
address
- C-chain address of the delegate.shareBP
- The delegation share in base points units, a unit corresponds to 0.01%.
Delegate to one provider
const share = Amount.percentages(100);
await network.delegateToFtso(wallet, providerAddress, share);
Delegate to two providers
// Delegate 50% to provider1 and 50% to provider2
const share = Amount.percentages(50);
await network.delegateToFtso(
wallet,
provider1Address,
share,
provider2Address,
share,
);
Undelegate
// Undelegate all vote power
await network.undelegateFromFtso(wallet);
Interact with C-Chain contracts
Interact with any smart contract on the C-Chain by providing its address and ABI.
// Call a read-only contract method
const result = await network.invokeContractCallOnC(contractAddress, abi, "methodName", [param1, param2]);
// Execute a transaction method that changes state
// The `value` parameter is for payable methods
await network.invokeContractMethodOnC(wallet, contractAddress, abi, "methodName", value, [param1, param2]);
// You can also use contract names for official Flare contracts
const contractNames = await network.getFlareContracts(); // See available names
await network.invokeContractMethodOnC(wallet, "FtsoRewardManager", abi, "claimReward", ...);
Stake on P-Chain
Staking requires moving funds from the C-Chain to the P-Chain, delegating them to a validator, and then moving them back. The SDK streamlines this cross-chain process.
-
Transfer Funds from C-Chain to P-Chain: This operation performs a C-Chain export followed by a P-Chain import automatically.
// Transfer 100 FLR from C-Chain to P-Chain
const amountToTransfer = Amount.nats(100);
await network.transferToP(wallet, amountToTransfer); -
Delegate to a Validator: Once funds are on the P-Chain, you can delegate them.
const amountToDelegate = Amount.nats(50);
const nodeId = "NodeID-P73B..."; // The ID of the validator
const startTime = Math.floor(Date.now() / 1000); // Start now
const endTime = startTime + 14 * 24 * 60 * 60; // End in 14 days
await network.delegateOnP(
wallet,
amountToDelegate,
nodeId,
startTime,
endTime,
); -
Transfer Funds Back to C-Chain: After your delegation period ends, move your funds back to the C-Chain.
// Transfer all available funds from P-Chain back to C-Chain
await network.transferToC(wallet);
Wallet controllers
A controller is a helper class that wraps a standard wallet library (like EIP-1193 for MetaMask or Zondax for Ledger) and produces SDK-compatible Wallet
objects.
The SDK includes controllers for popular wallet standards to make this easy.
EIP-1193 Wallets
Use the EIP1193WalletController
for any browser-based wallet that exposes an EIP-1193 provider (window.ethereum
) such as MetaMask or WalletConnect.
import { EIP1193WalletController } from "@flarenetwork/flare-tx-sdk";
// `provider` is the object from your Web3 wallet (e.g., window.ethereum)
const controller = new EIP1193WalletController(provider);
// Get a wallet for the currently active account in MetaMask
const wallet = await controller.getActiveWallet();
// Listen for account changes
controller.onWalletChange((newWallet) => {
console.log("Wallet account changed to:", await newWallet.getCAddress());
// Update your application state with the new wallet
});
Ledger
Use the LedgerWalletController
with either @zondax/ledger-flare
or @ledgerHQ/hw-app-eth
libraries to sign with a Ledger device.
import { LedgerWalletController } from "@flarenetwork/flare-tx-sdk";
// Option 1: Setup with Zondax
import { FlareApp } from "@zondax/ledger-flare"
flrApp = FlareApp(...)
const controller = new LedgerWalletController(flrApp, null);
// Option 2: Setup with LedgerHQ
// import { Eth } from "@ledgerHQ/hw-app-eth"
// ethApp = Eth(...)
// const controller = new LedgerWalletController(null, ethApp);
// Get a wallet for a specific BIP-44 path
const wallet = await controller.getWallet("m/44'/60'/0'/0/0");
Trezor
Use the TrezorWalletController
to integrate with a Trezor device via the Trezor Connect SDK.
import { TrezorConnect } from '@trezor/connect';
import { TrezorWalletController } from "@flarenetwork/flare-tx-sdk";
TrezorConnect.init(...)
const controller = new TrezorWalletController(TrezorConnect);
// Get a wallet for a specific BIP-44 path
const wallet = await controller.getWallet("m/44'/60'/0'/0/0");
Advanced
Transaction tracking
For fine-grained control and monitoring, you can register callbacks that fire at different stages of a transaction's lifecycle. All This is useful for UI updates, logging, or offline signing workflows.
// The transaction lifecycle looks like:
// [Unsigned] → [Before Signature] → [Signed] → [Before Submission] → [Submitted] → [After Submission] → [Confirmed]
// 1. Before Signing: Inspect the unsigned transaction.
// Returning `false` will cancel the signing request.
network.setBeforeTxSignatureCallback(async (data) => {
console.log("Transaction to be signed:", data.unsignedTxHex);
console.log("Transaction ID:", data.txType); // https://github.com/flare-foundation/flare-tx-sdk/blob/main/src/network/txtype.ts
return true; // Allow signing
});
// 2. Before Submission: Inspect the signed transaction.
// Returning `false` will prevent it from being sent to the network.
network.setBeforeTxSubmissionCallback(async (data) => {
console.log("Transaction to be submitted:", data.signedTxHex);
console.log("Transaction ID:", data.txId);
console.log("Transaction type:", data.txType); // https://github.com/flare-foundation/flare-tx-sdk/blob/main/src/network/txtype.ts
return true; // Allow submission
});
// 3. After Submission: Get the transaction ID immediately after sending.
network.setAfterTxSubmissionCallback(async (data) => {
console.log(`Transaction ${data.txId} submitted. Awaiting confirmation...`);
console.log("Transaction type:", data.txType); // https://github.com/flare-foundation/flare-tx-sdk/blob/main/src/network/txtype.ts
return true; // Wait for confirmation
});
// 4. After Confirmation: Get the final status of the transaction.
network.setAfterTxConfirmationCallback(async (data) => {
console.log(
`Transaction ${data.txId} confirmed with status: ${data.txStatus}`,
);
});
Change network RPC
When creating the Network
object, the SDK utilizes Flare's public RPCs by default.
To specify a custom RPC endpoint:
// Initialize the Network object for Flare Mainnet
const network = Network.FLARE;
// Change the RPC endpoint to a custom one
// You can use any public or private RPC, or your own node
network.setRpc(
"https://stylish-light-theorem.flare-mainnet.quiknode.pro/ext/bc/C/rpc",
);
Custom wallets
If you are not using a standard wallet, you can create your own Wallet
object.
Your wallet will need to implement a few required methods:
Supporting only C-Chain
getCAddress(): Promise<string>
signCTransaction(tx: string): Promise<string>
signAndSubmitCTransaction(tx: string): Promise<string>
signDigest(digest: string): Promise<string>
Supporting both P-Chain and C-Chain
getPublicKey(): Promise<string>
signCTransaction(tx: string): Promise<string>
signAndSubmitCTransaction(tx: string): Promise<string>
signDigest(digest: string): Promise<string>
signPTransaction(tx: string): Promise<string>
signEthMessage(message: string): Promise<string>