Mesh LogoMesh

Browser Wallet

Connect to CIP-30 compatible browser wallets like Eternl, Nami, Lace, and Flint.

Overview

MeshCardanoBrowserWallet enables your dApp to connect with users' browser extension wallets following the CIP-30 standard. This provides a consistent interface for wallet discovery, connection, transaction signing, and data queries across all compatible wallets.

Supported wallets include: Eternl, Nami, Lace, Flint, Typhon, GeroWallet, and any CIP-30 compliant wallet.

Quick Start

import { MeshCardanoBrowserWallet } from "@meshsdk/wallet";

// 1. Get installed wallets on user's device
const wallets = MeshCardanoBrowserWallet.getInstalledWallets();

// 2. Connect to a wallet
const wallet = await MeshCardanoBrowserWallet.enable("eternl");

// 3. Get wallet balance
const balance = await wallet.getBalanceMesh();

// 4. Get wallet address
const address = await wallet.getChangeAddressBech32();

Wallet Discovery

getInstalledWallets

Retrieve all CIP-30 compatible wallets installed on the user's device.

const wallets = MeshCardanoBrowserWallet.getInstalledWallets();

Returns:

[
  {
    id: "eternl",
    name: "Eternl",
    icon: "data:image/png;base64,...",
    version: "0.1.0"
  },
  {
    id: "nami",
    name: "Nami",
    icon: "data:image/png;base64,...",
    version: "3.0.0"
  }
]
PropertyTypeDescription
idstringWallet identifier used for connection
namestringDisplay name of the wallet
iconstringBase64-encoded wallet icon for UI display
versionstringWallet extension version

Connection

enable

Connect to a specific wallet. This prompts the user to grant permission.

const wallet = await MeshCardanoBrowserWallet.enable("eternl");

With CIP extensions:

// Enable CIP-95 (governance) support
const wallet = await MeshCardanoBrowserWallet.enable("eternl", [{ cip: 95 }]);
ParameterTypeRequiredDescription
walletNamestringYesWallet identifier from getInstalledWallets()
extensionsExtension[]NoCIP extensions to enable (e.g., [{ cip: 95 }])

Account Information

getNetworkId

Get the network the wallet is connected to.

const networkId = await wallet.getNetworkId();
// 0 = Testnet, 1 = Mainnet

getChangeAddressBech32

Get the address where transaction change should be sent.

const changeAddress = await wallet.getChangeAddressBech32();
// "addr_test1qz..."

getUsedAddressesBech32

Get all addresses that have received funds.

const usedAddresses = await wallet.getUsedAddressesBech32();
// ["addr_test1qz...", "addr_test1qr..."]

getUnusedAddressesBech32

Get addresses that have never received funds.

const unusedAddresses = await wallet.getUnusedAddressesBech32();

getRewardAddressesBech32

Get stake addresses associated with the wallet.

const stakeAddresses = await wallet.getRewardAddressesBech32();
// ["stake_test1uz..."]

Balance & Assets

getBalanceMesh

Get the complete balance including ADA and all native assets.

const balance = await wallet.getBalanceMesh();

Returns:

[
  { unit: "lovelace", quantity: "796105407" },
  { unit: "d9312da562da182b02322fd8acb536f37eb9d29fba7c49dc172555274d657368546f6b656e", quantity: "1" }
]

UTXOs & Collateral

getUtxosMesh

Get all unspent transaction outputs controlled by the wallet.

const utxos = await wallet.getUtxosMesh();

Returns:

[
  {
    input: {
      txHash: "16dcbb1f93b4f9d5e...",
      outputIndex: 0
    },
    output: {
      address: "addr_test1qz...",
      amount: [
        { unit: "lovelace", quantity: "1314550" },
        { unit: "d9312da562da182b...", quantity: "1" }
      ]
    }
  }
]

getCollateralMesh

Get UTXOs suitable for use as collateral in Plutus script transactions.

const collateral = await wallet.getCollateralMesh();

Collateral UTXOs must contain only ADA (no native assets) and meet minimum value requirements.

Transaction Operations

signTx

Sign a transaction with the wallet's private keys. Returns a witness set in CBOR hex format.

// Single signature
const witnessSet = await wallet.signTx(unsignedTx, false);

// Partial signing (for multi-sig transactions)
const witnessSet = await wallet.signTx(unsignedTx, true);
ParameterTypeRequiredDescription
txstringYesUnsigned transaction CBOR hex
partialSignbooleanYesSet true for multi-signature transactions

signTxReturnFullTx

Sign a transaction and return the full signed transaction with witnesses merged.

const signedTx = await wallet.signTxReturnFullTx(unsignedTx, false);

This is useful when you need the complete transaction CBOR rather than just the witness set.


submitTx

Submit a signed transaction to the network.

const txHash = await wallet.submitTx(signedTx);
// "f4ec9833a3bf95403d395f699bc564938f3419537e7fb5084425d3838a4b6159"

signData

Sign arbitrary data using CIP-8 message signing. Useful for authentication and proof of wallet ownership.

const address = await wallet.getChangeAddressBech32();
const signature = await wallet.signData(address, "Hello, Mesh!");

Returns:

{
  signature: "845846a2012...",
  key: "a4010103272006215..."
}

See Prove Wallet Ownership to verify signatures server-side.

Complete Example

import { MeshCardanoBrowserWallet } from "@meshsdk/wallet";
import { MeshTxBuilder, BlockfrostProvider } from "@meshsdk/core";

// Setup provider
const provider = new BlockfrostProvider("<YOUR_API_KEY>");

// Check installed wallets
const installedWallets = MeshCardanoBrowserWallet.getInstalledWallets();
console.log("Installed wallets:", installedWallets.map(w => w.name));

// Connect to wallet
const wallet = await MeshCardanoBrowserWallet.enable("eternl");

// Check connection
const networkId = await wallet.getNetworkId();
console.log("Connected to:", networkId === 0 ? "Testnet" : "Mainnet");

// Get wallet info
const address = await wallet.getChangeAddressBech32();
const balance = await wallet.getBalanceMesh();
const lovelace = balance.find(a => a.unit === 'lovelace')?.quantity || '0';
console.log(`Address: ${address}`);
console.log(`Balance: ${Number(lovelace) / 1_000_000} ADA`);

// Build and send transaction
const txBuilder = new MeshTxBuilder({
  fetcher: provider,
  verbose: true,
});

const utxos = await wallet.getUtxosMesh();

const unsignedTx = await txBuilder
  .txOut("addr_test1qz...", [{ unit: "lovelace", quantity: "5000000" }])
  .changeAddress(address)
  .selectUtxosFrom(utxos)
  .complete();

const signedTx = await wallet.signTxReturnFullTx(unsignedTx, false);
const txHash = await wallet.submitTx(signedTx);

console.log(`Transaction submitted: ${txHash}`);

React Integration

For React applications, use the @meshsdk/react package for built-in wallet components and hooks.

import { CardanoWallet, useWallet } from "@meshsdk/react";

function App() {
  const { connected, wallet } = useWallet();

  return (
    <div>
      <CardanoWallet />
      {connected && <p>Connected!</p>}
    </div>
  );
}

See React Getting Started for full integration details.

API Reference

MethodReturnsDescription
getInstalledWallets()Wallet[]Static - Get installed wallets
enable(walletName, extensions?)Promise<MeshCardanoBrowserWallet>Static - Connect to wallet
getNetworkId()Promise<number>Network ID (0=testnet, 1=mainnet)
getUtxos()Promise<string[]>UTXOs in CBOR hex format
getUtxosMesh()Promise<UTxO[]>UTXOs in Mesh format
getCollateral()Promise<string[]>Collateral UTXOs in CBOR hex format
getCollateralMesh()Promise<UTxO[]>Collateral UTXOs in Mesh format
getBalance()Promise<string>Balance in CBOR hex format
getBalanceMesh()Promise<Asset[]>Balance as Asset array
getUsedAddresses()Promise<string[]>Used addresses in hex format
getUsedAddressesBech32()Promise<string[]>Used addresses in Bech32
getUnusedAddresses()Promise<string[]>Unused addresses in hex format
getUnusedAddressesBech32()Promise<string[]>Unused addresses in Bech32
getChangeAddress()Promise<string>Change address in hex format
getChangeAddressBech32()Promise<string>Change address in Bech32
getRewardAddresses()Promise<string[]>Reward addresses in hex format
getRewardAddressesBech32()Promise<string[]>Reward addresses in Bech32
signTx(tx, partialSign)Promise<string>Sign transaction, return witness set
signTxReturnFullTx(tx, partialSign)Promise<string>Sign and return full transaction
signData(address, data)Promise<DataSignature>Sign arbitrary data
submitTx(tx)Promise<string>Submit transaction

Troubleshooting

Wallet not appearing in getInstalledWallets()

  • Ensure the wallet extension is installed and enabled
  • Refresh the page after installing a new wallet
  • Check that the wallet is unlocked

"User rejected the request" error

The user declined the connection or signing prompt. Handle this gracefully:

try {
  const wallet = await MeshCardanoBrowserWallet.enable("eternl");
} catch (error) {
  if (error.message.includes("rejected")) {
    console.log("User declined connection");
  }
}

"Account not set" error

The wallet is locked or no account is selected. Prompt the user to unlock their wallet.

Transaction signing fails

  • Ensure UTXOs are up to date (call getUtxosMesh() before building)
  • Verify the transaction has sufficient funds for outputs + fees
  • For Plutus transactions, ensure collateral is set

Multi-signature transaction issues

  • Set partialSign: true when calling signTx()
  • Each signer must sign the transaction in sequence
  • The final signer can use partialSign: false

On this page