In today’s digital era, decentralized applications (dApps) are reshaping how users interact with financial systems. One of the most critical components of any Web3 application is the crypto wallet—a gateway that enables users to manage assets across multiple blockchains. In this guide, we’ll walk through building a multi-chain wallet in Flutter, supporting Bitcoin, Ethereum, and Tron, while also demonstrating how to generate addresses and sign transactions using Dart.
We’ll maintain a clean, developer-focused tone, using proper Markdown formatting for clarity and SEO optimization. Whether you're building your first Web3 app or expanding into cross-chain functionality, this tutorial delivers practical insights with real-world code examples.
Understanding Multi-Chain Wallets
A multi-chain wallet allows users to manage assets on different blockchains from a single interface. Instead of juggling multiple wallets for Bitcoin, Ethereum, and Tron, developers can leverage Hierarchical Deterministic (HD) Wallets to derive keys across chains using a single mnemonic phrase.
This approach aligns with the BIP-44 standard, which defines a universal structure for deriving keys based on purpose, coin type, and account index. By adhering to BIP-44, your app ensures compatibility and security across ecosystems.
👉 Discover how seamless blockchain integration powers next-gen apps
Generating a Multi-Chain HD Wallet
To create a wallet supporting Bitcoin, Ethereum, and Tron, we use the bip39 and flutter_bitcoin packages in Dart. These libraries allow us to generate a mnemonic, derive a seed, and compute private/public key pairs for each chain.
According to BIP-44:
- Bitcoin uses coin type
0 - Ethereum uses coin type
60 - Tron uses coin type
195
Here’s how to derive wallets for all three chains:
import 'package:bip39/bip39.dart' as bip39;
import 'package:flutter_bitcoin/flutter_bitcoin.dart';
final mnemonic = bip39.generateMnemonic(strength: 128);
final seed = bip39.mnemonicToSeed(mnemonic);
final hdWallet = HDWallet.fromSeed(seed);
final btcWallet = hdWallet.derivePath("m/44'/0'/0'/0/0");
final ethWallet = hdWallet.derivePath("m/44'/60'/0'/0/0");
final tronWallet = hdWallet.derivePath("m/44'/195'/0'/0/0");Each derived wallet contains a private key (privKey) and public key, but generating the final address requires chain-specific encoding.
Converting Keys to Addresses
Despite sharing the same derivation logic, each blockchain uses unique rules to convert public keys into human-readable addresses.
Bitcoin Address Generation
The flutter_bitcoin package simplifies this process:
final btcAddress = btcWallet.address; // Automatically formattedUnder the hood, it applies SHA256 + RIPEMD160 hashing and Base58Check encoding. Most Bitcoin addresses start with 1, 3, or bc1 (for SegWit).
Ethereum Address Generation
Using the web3dart package:
import 'package:web3dart/web3dart.dart';
final ethPriKey = EthPrivateKey.fromHex(ethWallet.privKey!);
final ethAddress = ethPriKey.address.hex;Ethereum takes the last 20 bytes of the Keccak-256 hash of the public key—resulting in addresses starting with 0x.
Tron Address Generation
With the wallet package:
import 'package:wallet/wallet.dart' as wallet;
final tronPrivateKey = wallet.PrivateKey(BigInt.parse(tronWallet.privKey!, radix: 16));
final tronPubKey = wallet.tron.createPublicKey(tronPrivateKey);
final tronAddress = wallet.tron.createAddress(tronPubKey);Tron uses SHA256 + RIPEMD160 like Bitcoin but encodes with Base58Check and prefixes with T.
💡 Pro Tip: Chain-specific prefixes make it easy to identify which network an address belongs to—enhancing user safety and reducing errors.
Signing Transactions Across Chains
Once addresses are generated, the next step is sending value. However, transaction models differ significantly between chains.
Ethereum: Account-Based Model
Ethereum uses an account-based model, where each address has a balance and nonce. To send ETH:
const alchemyApiKey = 'your_api_key';
final web3Client = Web3Client('https://eth-sepolia.g.alchemy.com/v2/$alchemyApiKey', Client());
Future<String> signTransaction({
required EthPrivateKey privateKey,
required Transaction transaction,
}) async {
try {
final signedTx = await web3Client.signTransaction(privateKey, transaction, chainId: 11155111);
return HEX.encode(signedTx);
} catch (e) {
rethrow;
}
}
// Build and send
final tx = Transaction(
from: ethPriKey.address,
to: EthereumAddress.fromHex("0xE2Dc3214f7096a94077E71A3E218243E289F1067"),
value: EtherAmount.fromBase10String(EtherUnit.gwei, "10000"),
);
final rawTx = await signTransaction(privateKey: ethPriKey, transaction: tx);
final txHash = await web3Client.sendRawTransaction(Uint8List.fromList(HEX.decode(rawTx)));
print("Transaction hash: $txHash");The client automatically fetches gas price, gas limit, and nonce—streamlining the process.
Bitcoin: UTXO Model
Bitcoin operates on an Unspent Transaction Output (UTXO) model. You don’t have a “balance”—you have inputs from previous transactions.
To send BTC:
- Identify valid UTXOs
- Construct inputs and outputs
- Sign each input with the corresponding private key
Example:
String createBitcoinTransaction(HDWallet wallet) {
final txb = TransactionBuilder();
txb.setVersion(1);
txb.addInput('previous_tx_id', 0); // UTXO reference
txb.addOutput('recipient_address', 12000); // in satoshis
txb.sign(vin: 0, keyPair: ECPair.fromWIF(wallet.wif!));
return txb.build().toHex();
}⚠️ Note: You need external APIs like Blockchair or QuickNode to query UTXOs—this step isn’t handled natively in most Dart libraries yet.
Frequently Asked Questions
Q: Can one mnemonic securely control multiple blockchains?
Yes. HD wallets follow BIP-44 standards, allowing secure derivation of keys across chains using isolated paths. As long as the mnemonic is protected, all derived assets remain safe.
Q: Why do address formats differ so much between chains?
Each blockchain evolved independently with distinct design goals. Ethereum prioritized simplicity; Bitcoin focused on security and compression; Tron borrowed from Bitcoin but adapted for smart contracts.
Q: Is it possible to send tokens (not just native coins) in Flutter?
Yes—using libraries like web3dart, you can build ERC-20 or TRC-20 token transfers by interacting with smart contract ABIs. We’ll cover this in upcoming sections.
Q: How are transaction fees calculated on each chain?
- Ethereum: Gas price × gas limit (dynamic under EIP-1559)
- Bitcoin: Fee per byte × transaction size (in satoshis/byte)
- Tron: Bandwidth and energy system; often free for small transactions
Q: Can I broadcast Bitcoin transactions directly from Flutter?
Not easily. Most mobile implementations rely on third-party services (e.g., Blockchair API) to push raw transactions to the network due to node connectivity limitations.
Q: What about Tron transaction signing in Dart?
Currently, there's no mature Dart library for full Tron transaction signing. Developers often bridge to JavaScript via flutter_js or use REST APIs provided by TronGrid.
👉 Explore tools that simplify blockchain interactions in mobile apps
Building a Complete Flutter Application
With the above logic, you can now build a functional multi-chain wallet UI in Flutter:
- Input field for mnemonic recovery
- Display derived addresses for BTC, ETH, TRX
- Transaction signing forms for Ethereum and Bitcoin
- Option to broadcast Ethereum transactions via Alchemy or Infura
While sending Bitcoin requires additional backend support for UTXO lookup and broadcasting, Ethereum integration is largely self-contained thanks to robust Dart libraries.
You can extend this further by:
- Adding QR code scanning for addresses
- Supporting testnets for safer development
- Implementing biometric authentication for private key access
Final Thoughts
Creating a multi-chain wallet in Flutter opens doors to powerful Web3 experiences. By understanding core concepts like HD derivation, address generation, and transaction signing, you lay the foundation for more advanced features like token swaps, staking interfaces, and decentralized identity.
As interoperability becomes central to blockchain evolution, mastering cross-chain development will set your apps apart.
Whether you're building for innovation or user empowerment, integrating secure, intuitive wallet functionality is essential—and entirely achievable with Dart and modern SDKs.