The Para Modal provides comprehensive balance display capabilities, allowing users to view their wallet balances across multiple assets and networks. You can configure how balances are displayed and aggregated, and programmatically access balance data using the useProfileBalance hook.

Balance Display Configuration

You can customize how balances are displayed and calculated through the paraModalConfig.balances property in your ParaProvider configuration. This setting will impact both the Para Modal’s balance display and instances where you use the useProfileBalance hook. Para supports two primary balance display modes, AGGREGATED and CUSTOM_ASSET.

Defining Custom Networks and Assets

To include custom assets when fetching connected wallet balances, you will need to supply implementation metadata for each asset, including:
  • Each asset must include basic metadata, including name, symbol, and logoUrl (optional).
  • Each asset must include an implementations array for each network you wish to query for balances.
    • Each implementation object must include:
      • Price data:
        • For a fixed price:
          • Include a price object with the asset’s price in the format { value: number; currency: 'USD' }.
        • For a volatile price:
          • Include a priceUrl string. This endpoint must respond to GET requests with a JSON object with the asset’s current price in the format { value: number; currency: 'USD' }.
      • Network information:
        • For a custom EVM network:
          • Include a network object specifying the network’s name, evmChainId, and an rpcUrl where asset balances can be queried.
          • If the asset is the network’s native token:
            • No additional configuration is needed.
          • If the asset is an ERC-20 token:
            • Include a contractAddress string.
        • For a standard EVM or Solana network:
          • Include a network string, matching one of the networks enumerated in the TNetwork type. For example, 'ETHEREUM' or 'SOLANA'.
          • Include a contractAddress string.
Refer to the code snippets below for example configurations.

Aggregated Mode (Default)

Aggregated mode automatically aggregates balances across all detected chains and assets and displays them in USD value. If you supply additional assets and price data, these totals will be included in the calculation.
The aggregated total will include most commonly used assets across many networks. If you want to only include totals from your customized tokens, set excludeStandardAssets to true.
An example configuration with additional assets is below:
<ParaProvider
  // ... other config
  paraModalConfig={{
    // ... other config
    balances: {
      displayType: "AGGREGATED",
      // Include only balances for your custom assets:
      excludeStandardAssets: true,
      additionalAssets: [
        {
          name: 'Custom Token',
          symbol: 'CUSTOM',
          logoUrl: '<logo-url>',
          // A price endpoint for the asset:
          priceUrl: '<price-url-endpoint>',
          implementations: [
            // A custom EVM network where the asset is the native token:
            {
              network: {
                name: 'Custom Chain',
                evmChainId: '12345',
                rpcUrl: '<rpc-url>',
              },
            },
            // A custom EVM network where the asset is an ERC-20 token:
            {
              network: {
                name: 'Custom Chain',
                evmChainId: '12345',
                rpcUrl: '<rpc-url>',
              },
              contractAddress: '0x...',
            },
            // An implementation of the token on Solana:
            {
              network: 'SOLANA',
              contractAddress: 'Ep4r...',
            },
          ],
        },
        {
          name: 'Custom Stablecoin',
          symbol: 'CSTABLE',
          logoUrl: '<logo-url.png>',
          // A fixed price for the asset
          price: {
            value: 1,
            currency: 'USD',
          },
          networks: [
            // A custom network where the asset is an ERC-20 token:
            {
              network: {
                name: 'Custom Chain',
                evmChainId: '12345',
                rpcUrl: '<rpc-url>',
              },
              contractAddress: '0x...',
            },
          ],
        },
      ]
    }
  }}
>
  {children}
</ParaProvider>

Custom Token Mode

In Custom Token mode, the Para Modal will only display balances of a chosen asset, with no fiat currency conversion. This is ideal for cases where your app uses a particular token that may not have price information available. Like in Aggregated mode, you will need to supply implementation metadata for the asset, including any custom network definitions so that its balances can be queried for the session’s connected wallets. However, in this mode, you do not need to include a price object or a price URL.
<ParaProvider
  // ... other config
  paraModalConfig={{
    // ... other config
    balances: {
      displayType: 'CUSTOM_ASSET',
      asset: {
        name: 'Custom Token',
        symbol: 'CUSTOM',
        logoUrl: '<logo-url>',
        networks: [
          // A custom network where the asset is the native token:
          {
            network: {
              name: 'Custom Chain',
              evmChainId: '12345',
              rpcUrl: '<rpc-url>',
            },
          },
          // A known network where the asset is an ERC-20 token:
          {
            contractAddress: '0x...',
            network: 'ETHEREUM',
          }
        ],
      },
    },
  }}
>
  {children}
</ParaProvider>

useProfileBalance Hook

The useProfileBalance hook allows you to query the current aggregated or custom token balance of all wallets in the current session. Balances are normally cached on the server for five minutes. You can supply a refetchTrigger to the hook to manually refetch balances when desired, using a unique number or string.
import { useProfileBalance } from "@getpara/react-sdk";

function BalanceDisplay() {
  const [refetchTrigger, setRefetchTrigger] = useState(0);

  const { data: profileBalance, isLoading, error } = useProfileBalance({
    // Balances will be refetched whenever `refetchTrigger` changes
    refetchTrigger,
  });

  if (isLoading) return <div>Loading balances...</div>;
  if (error) return <div>Error loading balances: {error.message}</div>;
  if (!profileBalance) return <div>No balance data available</div>;

  return (
    <div>
      <h2>Total Balance: ${profileBalance.value.value.toFixed(2)}</h2>
      <div>
        {profileBalance.wallets.map((wallet) => (
          <div key={wallet.address}>
            <h3>Wallet: {wallet.address}</h3>
            {wallet.assets.map((asset) => (
              <div key={asset.symbol}>
                <span>{asset.symbol}: ${asset.balance}</span>
                <span>(${asset.value.value.toFixed(2)})</span>
              </div>
            ))}
          </div>
        ))}
      </div>
      <button onClick={() => setRefetchTrigger(prev => prev + 1)}>Refresh Balances</button>
    </div>
  );
}
Depending on the display type, the ProfileBalance object returned by useProfileBalance has the following structure:
{
  value: {
    value: 200,
    currency: 'USD',
  },
  wallets: [
    {
      type: 'EVM',
      address: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
      value: {
        value: 200,
        currency: 'USD',
      },
      assets: [
        {
          metadata: {
            internalId: 'ETHEREUM',
            zerionId: 'eth',
            name: 'Ethereum',
            price: {
              value: 4000,
              currency: 'USD',
            }
          },
          quantity: 0.03,
          value: {
            value: 120,
            currency: 'USD',
          },
          networks: [
            {
              metadata: {
                internalId: 'ETHEREUM',
                zerionId: 'ethereum',
                evmChainId: '1',
                name: 'Ethereum',
              },
              quantity: 0.02,
              value: {
                value: 80,
                currency: 'USD',
              },
            },
            {
              metadata: {
                internalId: 'BASE',
                zerionId: 'base',
                evmChainId: '8453',
                name: 'Base',
              },
              quantity: 0.01,
              value: {
                value: 40,
                currency: 'USD',
              },
            }
          ]
        },
        {
          metadata: {
            internalId: 'USDC',
            zerionId: 'usdc',
            name: 'USD Coin',
            price: {
              value: 1,
              currency: 'USD',
            }
          },
          quantity: 80,
          value: {
            value: 80,
            currency: 'USD',
          },
          networks: [
            {
              metadata: {
                internalId: 'ETHEREUM',
                zerionId: 'ethereum',
                evmChainId: '1',
                name: 'Ethereum',
              },
              quantity: 50,
              value: {
                value: 50,
                currency: 'USD',
              },
            },
            {
              metadata: {
                internalId: 'BASE',
                zerionId: 'base',
                evmChainId: '8453',
                name: 'Base',
              },
              quantity: 20,
              value: {
                value: 20,
                currency: 'USD',
              },
            },
            {
              metadata: {
                internalId: 'SOLANA',
                name: 'Solana',
              },
              quantity: 10,
              value: {
                value: 10,
                currency: 'USD',
              },
            }
          ]
        }
      ],
      networks: [
        {
          metadata: {
            internalId: 'ETHEREUM',
            zerionId: 'ethereum',
            evmChainId: '1',
            name: 'Ethereum',
          },
          value: {
            value: 130,
            currency: 'USD',
          },
          assets: [
            {
              metadata: {
                internalId: 'ETHEREUM',
                zerionId: 'ethereum',
                evmChainId: '1',
                name: 'Ethereum',
              },
              quantity: 0.02,
              value: {
                value: 80,
                currency: 'USD',
              },
            },
            {
              metadata: {
                internalId: 'USDC',
                zerionId: 'usdc',
                name: 'USD Coin',
                price: {
                  value: 1,
                  currency: 'USD',
                },
              },
              quantity: 50,
              value: {
                value: 50,
                currency: 'USD',
              },
            }
          ]
        },
        {
          metadata: {
            internalId: 'BASE',
            zerionId: 'base',
            evmChainId: '8453',
            name: 'Base',
          },
          value: {
            value: 60,
            currency: 'USD',
          },
          assets: [
            {
              metadata: {
                internalId: 'ETHEREUM',
                zerionId: 'eth',
                evmChainId: '1',
                name: 'Ethereum',
              },
              quantity: 0.01,
              value: {
                value: 40,
                currency: 'USD',
              },
            },
            {
              metadata: {
                internalId: 'USDC',
                zerionId: 'usdc',
                name: 'USD Coin',
                price: {
                  value: 1,
                  currency: 'USD',
                },
              },
              quantity: 20,
              value: {
                value: 20,
                currency: 'USD',
              },
            }
          ]
        },
        {
          metadata: {
            internalId: 'SOLANA',
            name: 'Solana',
          },
          value: {
            value: 10,
            currency: 'USD',
          },
          assets: [
            {
              metadata: {
                internalId: 'USDC',
                zerionId: 'usdc',
                name: 'USD Coin',
                price: {
                  value: 1,
                  currency: 'USD',
                },
              },
              quantity: 10,
              value: {
                value: 10,
                currency: 'USD',
              },
            }
          ]
        }
      ]
    }
  ]
}