Skip to main content

CardanoProvider Context

The CardanoProvider provides a React Context for managing Cardano state across your entire application.

Overview

Instead of passing Lucid instances through props, use CardanoProvider to make Cardano state available anywhere in your component tree.

import { CardanoProvider, useCardano } from 'cardano-devkit';

function App() {
return (
<CardanoProvider network="Preprod" debug={true}>
<Header />
<Main />
<Footer />
</CardanoProvider>
);
}

Setup

CardanoProvider Props

interface CardanoProviderProps {
children: React.ReactNode;

// Network configuration
network?: NetworkType; // Default: 'Preprod'
provider?: ProviderConfig; // Custom provider config

// Features
autoConnect?: boolean; // Auto-connect on mount
persistWallet?: boolean; // Remember wallet connection
debug?: boolean; // Enable debug logging

// Callbacks
onConnect?: (address: string) => void;
onDisconnect?: () => void;
onError?: (error: Error) => void;
onNetworkChange?: (network: NetworkType) => void;
}

Basic Setup

import { CardanoProvider } from 'cardano-devkit';

function App() {
return (
<CardanoProvider
network="Preprod"
autoConnect={true}
persistWallet={true}
onConnect={(address) => console.log('Connected:', address)}
onError={(error) => console.error('Error:', error)}
>
<YourApp />
</CardanoProvider>
);
}

Context Hooks

useCardano()

Get the full Cardano context with all state and actions.

import { useCardano } from 'cardano-devkit';

function MyComponent() {
const {
// State
lucid,
network,
address,
balance,
isInitialized,
isConnected,
isLoading,
error,
availableWallets,

// Actions
connect,
disconnect,
switchNetwork,
refreshBalance,
signMessage,
signTransaction,
} = useCardano();

// Use context values...
}

useCardanoWallet()

Focused hook for wallet operations.

import { useCardanoWallet } from 'cardano-devkit';

function WalletButton() {
const {
address,
balance,
isConnected,
availableWallets,
connect,
disconnect,
} = useCardanoWallet();

if (isConnected) {
return (
<div>
<span>{truncateAddress(address)}</span>
<span>{formatLovelace(balance)} ADA</span>
<button onClick={disconnect}>Disconnect</button>
</div>
);
}

return (
<div>
<h3>Connect Wallet</h3>
{availableWallets.map(wallet => (
<button
key={wallet.name}
onClick={() => connect('browser', wallet.name)}
>
<img src={wallet.icon} alt={wallet.name} />
{wallet.name}
</button>
))}
</div>
);
}

useCardanoNetwork()

Focused hook for network operations.

import { useCardanoNetwork } from 'cardano-devkit';

function NetworkSelector() {
const {
network,
isLocalDevnet,
isTestnet,
isMainnet,
switchNetwork,
useLocalDevnet,
usePreprod,
usePreview,
useMainnet,
} = useCardanoNetwork();

return (
<div>
<p>Current: {network}</p>
<button onClick={() => usePreprod()}>Preprod</button>
<button onClick={() => usePreview()}>Preview</button>
<button onClick={() => useLocalDevnet()}>Local</button>
<button
onClick={() => useMainnet({ confirmMainnet: true })}
style={{ color: 'red' }}
>
Mainnet
</button>
</div>
);
}

useCardanoTx()

Focused hook for transaction operations.

import { useCardanoTx } from 'cardano-devkit';

function SendButton() {
const {
send,
sendMultiple,
sendWithMessage,
mint,
status,
lastTxHash,
error,
} = useCardanoTx();

const handleSend = async () => {
const txHash = await send("addr_test1...", 5000000n);
console.log("Sent:", txHash);
};

return (
<div>
<button onClick={handleSend} disabled={status === 'submitting'}>
Send 5 ADA
</button>
{status === 'submitted' && <p>TX: {lastTxHash}</p>}
{error && <p>Error: {error.message}</p>}
</div>
);
}

Type Definitions

CardanoContext

interface CardanoContext {
state: CardanoContextState;
actions: CardanoContextActions;
}

interface CardanoContextState {
lucid: LucidEvolution | null;
network: NetworkType;
address: string | null;
balance: bigint;
utxos: UTxO[];
isInitialized: boolean;
isConnected: boolean;
isLoading: boolean;
error: Error | null;
availableWallets: AvailableWallet[];
}

interface CardanoContextActions {
// Connection
connect: (method: WalletMethod, credential: string) => Promise<void>;
disconnect: () => void;

// Network
switchNetwork: (network: NetworkType) => Promise<void>;
useLocalDevnet: (port?: number) => Promise<void>;
usePreprod: () => Promise<void>;
usePreview: () => Promise<void>;
useMainnet: (options: MainnetSwitchOptions) => Promise<void>;

// Wallet operations
refreshBalance: () => Promise<void>;
signMessage: (message: string) => Promise<string>;
signTransaction: (tx: Transaction) => Promise<SignedTransaction>;

// Transaction helpers
send: (to: string, amount: bigint) => Promise<string>;
sendMultiple: (payments: SimplePayment[]) => Promise<string>;
sendWithMessage: (to: string, amount: bigint, message: string) => Promise<string>;
}

interface AvailableWallet {
name: string;
icon: string;
apiVersion: string;
isEnabled: boolean;
}

type TransactionStatus =
| 'idle'
| 'building'
| 'signing'
| 'submitting'
| 'submitted'
| 'confirmed'
| 'error';

Complete Example

import React from 'react';
import {
CardanoProvider,
useCardano,
useCardanoWallet,
useCardanoNetwork,
useCardanoTx,
formatLovelace,
truncateAddress,
} from 'cardano-devkit';

// Wallet connection component
function WalletConnect() {
const { address, balance, isConnected, availableWallets, connect, disconnect } = useCardanoWallet();

if (isConnected) {
return (
<div className="wallet-info">
<span>{truncateAddress(address!, 8, 6)}</span>
<span>{formatLovelace(balance)}</span>
<button onClick={disconnect}>Disconnect</button>
</div>
);
}

return (
<div className="wallet-connect">
{availableWallets.map(wallet => (
<button key={wallet.name} onClick={() => connect('browser', wallet.name)}>
Connect {wallet.name}
</button>
))}
</div>
);
}

// Network switcher component
function NetworkSwitcher() {
const { network, usePreprod, usePreview, useLocalDevnet } = useCardanoNetwork();

return (
<select value={network} onChange={e => {
switch (e.target.value) {
case 'Preprod': usePreprod(); break;
case 'Preview': usePreview(); break;
case 'LocalDevnet': useLocalDevnet(); break;
}
}}>
<option value="Preprod">Preprod</option>
<option value="Preview">Preview</option>
<option value="LocalDevnet">Local Devnet</option>
</select>
);
}

// Transaction form component
function SendForm() {
const [recipient, setRecipient] = React.useState('');
const [amount, setAmount] = React.useState('');
const { send, status, lastTxHash, error } = useCardanoTx();
const { isConnected } = useCardanoWallet();

const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
const lovelace = BigInt(parseFloat(amount) * 1_000_000);
await send(recipient, lovelace);
};

if (!isConnected) {
return <p>Connect wallet to send ADA</p>;
}

return (
<form onSubmit={handleSubmit}>
<input
placeholder="Recipient address"
value={recipient}
onChange={e => setRecipient(e.target.value)}
/>
<input
type="number"
placeholder="Amount (ADA)"
value={amount}
onChange={e => setAmount(e.target.value)}
/>
<button type="submit" disabled={status === 'submitting'}>
{status === 'submitting' ? 'Sending...' : 'Send ADA'}
</button>
{lastTxHash && <p>TX: {lastTxHash}</p>}
{error && <p className="error">{error.message}</p>}
</form>
);
}

// Main app
function App() {
return (
<CardanoProvider
network="Preprod"
autoConnect={true}
persistWallet={true}
debug={true}
>
<header>
<h1>My Cardano dApp</h1>
<NetworkSwitcher />
<WalletConnect />
</header>

<main>
<SendForm />
</main>
</CardanoProvider>
);
}

export default App;

Best Practices

  1. Wrap at the top level: Place CardanoProvider near the root of your app
  2. Use specific hooks: Prefer useCardanoWallet over useCardano when you only need wallet state
  3. Handle loading states: Always check isInitialized and isLoading before rendering
  4. Error boundaries: Wrap components in error boundaries to catch Cardano errors
  5. Persist wallet: Use persistWallet={true} for better UX across page reloads
// Error boundary example
import { ErrorBoundary } from 'react-error-boundary';

function App() {
return (
<ErrorBoundary fallback={<div>Something went wrong</div>}>
<CardanoProvider network="Preprod">
<YourApp />
</CardanoProvider>
</ErrorBoundary>
);
}