Afficher les tokens crypto d'un utilisateur dans Laravel Filament

December 28, 2025 Premium

Créez une page 'My Wallet' dans Filament pour afficher le solde ETH et les tokens ERC-20

Afficher les tokens crypto d'un utilisateur dans Laravel Filament

Apprenez à créer une page FilamentPHP qui affiche le solde crypto et les tokens ERC-20 d'un utilisateur connecté via son wallet Ethereum. Ce guide utilise ethers.js pour interroger la blockchain directement depuis le navigateur, sans backend ni clé API.

Prérequis

Avant de commencer, assurez-vous d'avoir :

  • Une application Laravel avec FilamentPHP v4
  • L'authentification wallet déjà configurée (voir article précédent)
  • Un champ eth_address sur le modèle User

Création de la Page Filament

Créez app/Filament/Pages/WalletTokens.php :

namespace App\Filament\Pages;

use BackedEnum;
use Filament\Pages\Page;
use Illuminate\Contracts\Support\Htmlable;

class WalletTokens extends Page
{
    protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-wallet';
    protected string $view = 'filament.pages.wallet-tokens';
    protected static ?int $navigationSort = 100;

    public static function canAccess(): bool
    {
        if (! config('metamask.enabled', true)) {
            return false;
        }

        $user = auth()->user();
        return $user && ! empty($user->eth_address);
    }

    public static function shouldRegisterNavigation(): bool
    {
        return static::canAccess();
    }

    public static function getNavigationLabel(): string
    {
        return __('wallet.navigation_label');
    }

    public function getTitle(): string|Htmlable
    {
        return __('wallet.page_title');
    }

    public function getEthAddress(): ?string
    {
        return auth()->user()?->eth_address;
    }
}

La page n'apparaît dans le menu que si :

  • La feature wallet est activée (METAMASK_AUTH_ENABLED=true)
  • L'utilisateur a un wallet lié à son compte

Configuration des réseaux

Dans la vue, définissez les réseaux supportés avec leurs RPC publics :

const networks = {
    mainnet: {
        rpc: 'https://eth.llamarpc.com',
        symbol: 'ETH',
        explorer: 'https://etherscan.io',
        coingeckoId: 'ethereum'
    },
    polygon: {
        rpc: 'https://polygon-rpc.com',
        symbol: 'MATIC',
        explorer: 'https://polygonscan.com',
        coingeckoId: 'matic-network'
    },
    arbitrum: {
        rpc: 'https://arb1.arbitrum.io/rpc',
        symbol: 'ETH',
        explorer: 'https://arbiscan.io',
        coingeckoId: 'ethereum'
    },
    base: {
        rpc: 'https://mainnet.base.org',
        symbol: 'ETH',
        explorer: 'https://basescan.org',
        coingeckoId: 'ethereum'
    },
    sepolia: {
        rpc: 'https://rpc.sepolia.org',
        symbol: 'SEP',
        explorer: 'https://sepolia.etherscan.io',
        coingeckoId: null // testnet
    }
};

Récupération du solde natif

Utilisez ethers.js pour lire le solde ETH/MATIC :

async function loadNativeBalance() {
    const provider = new ethers.JsonRpcProvider(networks[currentNetwork].rpc);
    const balance = await provider.getBalance(address);
    const formattedBalance = ethers.formatEther(balance);

    document.getElementById('native-balance').textContent =
        parseFloat(formattedBalance).toFixed(6);

    // Conversion USD via CoinGecko
    const coingeckoId = networks[currentNetwork].coingeckoId;
    if (coingeckoId) {
        const res = await fetch(
            `https://api.coingecko.com/api/v3/simple/price?ids=${coingeckoId}&vs_currencies=usd`
        );
        const data = await res.json();
        const usdValue = (parseFloat(formattedBalance) * data[coingeckoId].usd).toFixed(2);
        document.getElementById('native-balance-usd').textContent = `≈ $${usdValue} USD`;
    }
}

Lecture des tokens ERC-20

Définissez les tokens populaires à vérifier :

const popularTokens = {
    mainnet: [
        { address: '0xdAC17F958D2ee523a2206206994597C13D831ec7', symbol: 'USDT', decimals: 6 },
        { address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', symbol: 'USDC', decimals: 6 },
        { address: '0x6B175474E89094C44Da98b954EesC37d7B35C823', symbol: 'DAI', decimals: 18 },
    ],
    polygon: [
        { address: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F', symbol: 'USDT', decimals: 6 },
        { address: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', symbol: 'USDC', decimals: 6 },
    ],
    // ...
};

const ERC20_ABI = [
    'function balanceOf(address owner) view returns (uint256)',
    'function decimals() view returns (uint8)',
    'function symbol() view returns (string)'
];

Pour lire le solde d'un token :

async function loadTokens() {
    const provider = new ethers.JsonRpcProvider(networks[currentNetwork].rpc);
    const tokens = popularTokens[currentNetwork] || [];
    const tokenBalances = [];

    for (const token of tokens) {
        const contract = new ethers.Contract(token.address, ERC20_ABI, provider);
        const balance = await contract.balanceOf(address);

        if (balance > 0n) {
            const formattedBalance = ethers.formatUnits(balance, token.decimals);
            tokenBalances.push({
                symbol: token.symbol,
                balance: parseFloat(formattedBalance).toFixed(4),
            });
        }
    }

    // Afficher les tokens...
}

Vue Blade complète

Créez resources/views/filament/pages/wallet-tokens.blade.php :

<x-filament-panels::page>
    <div class="space-y-6">
        {{-- Adresse du wallet --}}
        <x-filament::section heading="Your Wallet">
            <p class="font-mono">{{ $this->getEthAddress() }}</p>
        </x-filament::section>

        {{-- Sélecteur de réseau --}}
        <x-filament::section heading="Network">
            <div class="flex gap-2">
                <button data-network="mainnet" class="network-btn ...">Ethereum</button>
                <button data-network="polygon" class="network-btn ...">Polygon</button>
                <button data-network="arbitrum" class="network-btn ...">Arbitrum</button>
            </div>
        </x-filament::section>

        {{-- Solde natif --}}
        <x-filament::section>
            <x-slot name="heading">
                <span id="native-token-name">ETH</span> Balance
            </x-slot>
            <div id="balance-loading">Loading...</div>
            <div id="balance-content" class="hidden">
                <span id="native-balance" class="text-3xl font-bold">0.00</span>
                <span id="native-symbol">ETH</span>
                <p id="native-balance-usd" class="text-sm text-gray-500"></p>
            </div>
        </x-filament::section>

        {{-- Tokens ERC-20 --}}
        <x-filament::section heading="Tokens">
            <div id="tokens-loading">Loading...</div>
            <div id="tokens-content" class="hidden space-y-2"></div>
            <div id="tokens-empty" class="hidden text-gray-500">No tokens found.</div>
        </x-filament::section>

        {{-- Lien explorateur --}}
        <a id="explorer-link" href="#" target="_blank" class="fi-btn ...">
            View on Block Explorer
        </a>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/ethers/6.7.0/ethers.umd.min.js"></script>
    <script>
        // Code JavaScript ici...
    </script>
</x-filament-panels::page>

Configuration optionnelle

Ajoutez dans config/metamask.php :

'default_network' => env('METAMASK_DEFAULT_NETWORK', 'mainnet'),

Et dans .env :

METAMASK_DEFAULT_NETWORK=mainnet

Avantages de cette approche

Pas de backend nécessaire : ethers.js interroge directement les nœuds RPC publics

Multi-chain : Support facile de plusieurs réseaux (Ethereum, Polygon, Arbitrum, Base...)

Temps réel : Les données sont toujours à jour depuis la blockchain

Gratuit : Utilise des RPC publics, pas besoin de clé API Alchemy/Infura

Privacy : Aucune donnée n'est envoyée à votre serveur

Limitations

  • Seuls les tokens populaires prédéfinis sont affichés
  • Les RPC publics peuvent avoir des limites de rate
  • Pour un usage intensif, envisagez Alchemy ou Infura

Conclusion

En quelques étapes, vous avez créé une page wallet complète dans Filament :

  • Affichage du solde natif (ETH, MATIC, etc.)
  • Liste des tokens ERC-20 détenus
  • Switch entre plusieurs réseaux blockchain
  • Conversion en USD via CoinGecko
  • Lien direct vers l'explorateur de blocs

Cette page offre à vos utilisateurs une vue d'ensemble de leurs actifs crypto directement dans votre application, sans quitter l'interface Filament.

Obtenez le Code Source Complet

Gagnez du temps et accédez à l'intégralité du projet.

Je veux le code source