> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mirador.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Web3 Demo App

> A complete interactive demo app showing SDK integration with Web3 wallets, transactions, and trace lifecycle management

## Overview

The [Web3 Demo App](https://github.com/miradorlabs/web-client/tree/main/example) is a fully interactive example that showcases the Mirador Web SDK end-to-end. It connects to browser wallets, sends real blockchain transactions, and tracks the entire lifecycle with Mirador traces.

All code snippets below are extracted from the actual demo source code.

## What It Demonstrates

* **Trace creation** with descriptive names and structured metadata
* **Attributes** for wallet, network, and transaction context
* **Tags** for categorization and filtering
* **Events** at each stage of the transaction lifecycle
* **Transaction hints** via `web3.evm.addTxHint()` and `web3.evm.addTx()` for cross-chain correlation
* **Provider integration** via `Web3Plugin` for automatic chain detection
* **Flush** to send trace data immediately
* **Error handling** and trace closure on success, failure, or rejection

## SDK Integration Walkthrough

The core SDK integration lives in a single `sendTransaction()` function. Here's how it works step by step.

### 1. Initialize the Client

The client is created once when the user provides their API key:

```typescript theme={null}
import { Client, Web3Plugin } from '@miradorlabs/web-sdk';

const client = new Client(apiKey, { apiUrl: 'https://ingest-gateway.mirador.org' });
```

### 2. Create a Trace with Metadata

When a transaction is initiated, a new trace is created and enriched with attributes and tags:

```typescript theme={null}
// Create the trace
const trace = client.trace({ name: 'web3_transfer' });

// Add wallet and transaction attributes
trace
  .addAttribute('wallet.address', walletAddress)
  .addAttribute('wallet.type', 'injected')
  .addAttribute('network.name', networkInfo.name)
  .addAttribute('network.chainId', chainId.toString())
  .addAttribute('transaction.type', 'transfer')
  .addAttribute('transaction.to', recipient)
  .addAttribute('transaction.value', amount)
  .addAttribute('transaction.valueWei', amountWei.toString());

// Add tags for categorization
trace.addTags(['web3', 'transfer', 'sepolia-testnet']);
```

### 3. Track Events Through the Transaction Lifecycle

Events are added at each significant step, capturing relevant data:

```typescript theme={null}
// When the user initiates the transaction
trace.addEvent('transaction_initiated', {
  from: walletAddress,
  to: recipient,
  value: amount,
});

// After the wallet submits the transaction
trace.addEvent('transaction_sent', { txHash });

// When the transaction confirms on-chain
trace.addEvent('transaction_confirmed', {
  success: true,
  blockNumber: 12345678,
  txHash,
});
```

### 4. Send Transaction and Link with `web3.evm.addTxHint()`

The demo uses ethers.js to send transactions and links them to the trace:

```typescript theme={null}
import { BrowserProvider, parseEther } from 'ethers';
import { Client, Web3Plugin, ChainName } from '@miradorlabs/web-sdk';

const ethersProvider = new BrowserProvider(walletState.provider);
const signer = await ethersProvider.getSigner();
const tx = await signer.sendTransaction({
  to: recipient,
  value: parseEther(amount),
});

const chainName: ChainName = 'ethereum';
trace.web3.evm.addTxHint(tx.hash, chainName, 'ETH Transfer');
trace.web3.evm.addTxInputData(tx.data);
```

You can also capture transaction input data. When `input` is provided, it is emitted as a `"Tx input data"` event:

```typescript theme={null}
trace.web3.evm.addTxHint(txHash, 'ethereum', {
  input: txData,       // emitted as a "Tx input data" event
  details: 'ETH Transfer'
});

// Or capture input data explicitly
trace.web3.evm.addTxHint(txHash, chainName, 'ETH Transfer');
trace.web3.evm.addTxInputData(tx.data);
```

Or use `web3.evm.addTx()` to extract hash, input data, and chain from a transaction object automatically:

```typescript theme={null}
const tx = await signer.sendTransaction(txData);
trace.web3.evm.addTx(tx);  // extracts tx.hash, tx.data, tx.chainId
```

This enables Mirador to correlate on-chain data with your trace across any of the supported networks.

### Alternative: Using MiradorProvider

Instead of manually adding transaction hints, you can wrap your wallet provider with `MiradorProvider` to capture all transactions automatically:

```typescript theme={null}
import { Client, MiradorProvider } from '@miradorlabs/web-sdk';

const client = new Client(apiKey);
const provider = new MiradorProvider(window.ethereum, client);

// Use `provider` instead of window.ethereum — transactions are auto-traced
const txHash = await provider.request({
  method: 'eth_sendTransaction',
  params: [{ from: walletAddress, to: recipient, value: amountHex }]
});
```

See the [Provider guide](/concepts/provider) for more details on using `MiradorProvider` with ethers.js and viem.

### 5. Flush and Retrieve the Trace ID

After adding the transaction hint, flush the trace to send data to Mirador and retrieve the trace ID:

```typescript theme={null}
trace.flush();

// Poll for the trace ID (available after flush completes)
let traceId = trace.getTraceId();
let attempts = 0;
while (!traceId && attempts < 50) {
  await new Promise(resolve => setTimeout(resolve, 100));
  traceId = trace.getTraceId();
  attempts++;
}
```

### 6. Handle Errors and Close the Trace

Always close the trace when the operation completes, whether it succeeds or fails:

```typescript theme={null}
// On success
trace.addEvent('transaction_confirmed', { success: true, blockNumber, txHash });
await trace.close(`Transaction confirmed in block ${blockNumber}`);

// On user rejection
trace.addEvent('transaction_rejected', { reason: 'User rejected' });
await trace.close('Transaction rejected by user');

// On error
trace.addEvent('transaction_error', { error: err.message });
await trace.close(`Transaction error: ${err.message}`);
```

## Example Trace Output

When you send a transaction through the demo, the SDK captures the following data:

```json theme={null}
{
  "name": "web3_transfer",
  "attributes": {
    "wallet.address": "0x742d...0bEb",
    "wallet.type": "injected",
    "network.name": "Sepolia Testnet",
    "network.chainId": "11155111",
    "transaction.type": "transfer",
    "transaction.to": "0x1234...7890",
    "transaction.value": "0.001",
    "transaction.valueWei": "1000000000000000"
  },
  "tags": ["web3", "transfer", "sepolia-testnet"],
  "events": [
    { "name": "trace init" },
    { "name": "transaction_initiated", "data": { "from": "0x742d...0bEb", "to": "0x1234...7890", "value": "0.001" } },
    { "name": "transaction_sent", "data": { "txHash": "0xabc...def" } },
    { "name": "transaction_confirmed", "data": { "success": true, "blockNumber": 12345678, "txHash": "0xabc...def" } }
  ],
  "txHashHints": [
    { "txHash": "0xabc...def", "chain": "ethereum", "details": "ETH Transfer" }
  ]
}
```

## Supported Networks

The demo supports 12 networks (6 mainnets and 6 testnets):

| Network          | Chain ID | Symbol | Mirador Chain |
| ---------------- | -------- | ------ | ------------- |
| Ethereum         | 1        | ETH    | `ethereum`    |
| Sepolia          | 11155111 | ETH    | `ethereum`    |
| Polygon          | 137      | MATIC  | `polygon`     |
| Polygon Amoy     | 80002    | MATIC  | `polygon`     |
| Arbitrum One     | 42161    | ETH    | `arbitrum`    |
| Arbitrum Sepolia | 421614   | ETH    | `arbitrum`    |
| Optimism         | 10       | ETH    | `optimism`    |
| Optimism Sepolia | 11155420 | ETH    | `optimism`    |
| Base             | 8453     | ETH    | `base`        |
| Base Sepolia     | 84532    | ETH    | `base`        |
| BNB Chain        | 56       | BNB    | `bsc`         |
| BNB Testnet      | 97       | BNB    | `bsc`         |

## Running the Demo

<Steps>
  <Step title="Clone the repo and install dependencies">
    ```bash theme={null}
    git clone https://github.com/miradorlabs/web-client.git
    cd web-client/example
    npm install
    ```
  </Step>

  <Step title="Start the development server">
    ```bash theme={null}
    npm run dev
    ```

    This builds the SDK, bundles the demo, starts a CORS proxy, and serves the app at `http://localhost:8000`.
  </Step>

  <Step title="Connect and send a transaction">
    Enter your Mirador API key, connect a browser wallet (MetaMask, Coinbase Wallet, etc.), switch to a testnet, and send a transaction to see the full trace lifecycle in action.
  </Step>
</Steps>

## Next Steps

<CardGroup cols={2}>
  <Card title="API Reference" icon="book" href="/api-reference/client">
    Complete Client and Trace API documentation
  </Card>

  <Card title="Traces" icon="route" href="/concepts/traces">
    Learn about trace lifecycle, flushing, and closing
  </Card>

  <Card title="Transaction Hints" icon="link" href="/concepts/transaction-hints">
    Deep dive into cross-chain transaction correlation
  </Card>

  <Card title="Transaction Tracking" icon="ethereum" href="/examples/transaction-tracking">
    More SDK integration patterns for DeFi operations
  </Card>
</CardGroup>
