This package implements CIP-30 and CIP-95 APIs which allow the Flutter web app to communicate with the Cardano wallet extension.

In short, the package exposes window.{walletName} JS api taking away all the complexities of using js_interop.


  • Dart: 3.3.4+
  • Flutter: 3.22.1+


    catalyst_cardano_serialization: any # or the latest version on Pub
    catalyst_cardano: any # or the latest version on Pub
    catalyst_cardano_web: any # or the latest version on Pub

Web setup

Add the following line at the end of <head> section in web/index.html:

<script type="module" src="/assets/packages/catalyst_cardano_web/assets/js/catalyst_cardano.js"></script>


Import package:catalyst_cardano_serialization/catalyst_cardano_serialization.dart and package:catalyst_cardano/catalyst_cardano.dart, instantiate TransactionBuilder, provide transaction inputs, outputs, add change address for any remaining unspent UTXOs and build the transaction body.

To obtain the witnessSet call api.signTx(transaction: unsignedTx);. Finally, create a signed transaction and submit it to the blockchain with api.submitTx(transaction: signedTx);

import 'dart:async';

import 'package:catalyst_cardano/catalyst_cardano.dart';
import 'package:catalyst_cardano_serialization/catalyst_cardano_serialization.dart';

Future<void> main() async {
  final wallets = await CatalystCardano.instance.getWallets();
  if (wallets.isEmpty) {
    // no wallet extension found, please install in your browser

  final wallet = wallets.first;

  final api = await wallet.enable();
  assert(await wallet.isEnabled(), 'wallet is enabled');

  print(await api.getBalance());
  print(await api.getExtensions());
  print(await api.getNetworkId());
  print(await api.getRewardAddresses());
  print(await api.getUnusedAddresses());
  print(await api.getUsedAddresses());

  final unsignedTx = _buildUnsignedTx(
    utxos: await api.getUtxos(amount: const Coin(1000000)),
    changeAddress: await api.getChangeAddress(),

  final witnessSet = await api.signTx(transaction: unsignedTx);
  final signedTx = Transaction(
    body: unsignedTx.body,
    isValid: true,
    witnessSet: witnessSet,
  await api.submitTx(transaction: signedTx);

Transaction _buildUnsignedTx({
  required List<TransactionUnspentOutput> utxos,
  required ShelleyAddress changeAddress,
}) {
  const txBuilderConfig = TransactionBuilderConfig(
    feeAlgo: LinearFee(
      constant: Coin(155381),
      coefficient: Coin(44),
    maxTxSize: 16384,
    maxValueSize: 5000,
    coinsPerUtxoByte: Coin(4310),

  /* cSpell:disable */
  final preprodFaucetAddress = ShelleyAddress.fromBech32(
  /* cSpell:enable */

  final txOutput = TransactionOutput(
    address: preprodFaucetAddress,
    amount: const Value(coin: Coin(1000000)),

  final txBuilder = TransactionBuilder(
    config: txBuilderConfig,
    inputs: utxos,
    networkId: NetworkId.testnet,

  final txBody = txBuilder

  return Transaction(
    body: txBody,
    isValid: true,
    witnessSet: const TransactionWitnessSet(vkeyWitnesses: {}),


This package supports a minimal TransactionBuilder that does not yet work with Smart Contracts or scripts. However AuxiliaryMetadata is already supported thus it's possible to fulfill some of the use cases. NFTs are partially supported, i.e. to transfer them in a transaction.

Only Shelley era bech32 base and stake addresses are supported. Byron era addresses are not supported.

Reference documentation


Post issues and feature requests on the GitHub issue tracker. Please read our CONTRIBUTING for guidelines on how to contribute.


Licensed under either of Apache License, Version 2.0 or MIT license at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.