BluxBlux

useTokenMetadata

Read a SEP-41 token / Stellar Asset Contract's metadata in React, powered by TanStack Query.

useTokenMetadata is the React wrapper around getTokenMetadata. It reads a SEP-41 token / Stellar Asset Contract's decimals, name, symbol, and owner by simulating the contract's read-only entrypoints — no account, signing, or fees — and exposes the result as a TanStack Query, so you get caching, refetching, and loading states for free.

The read works for any contract id, deployed or not yet funded. owner is undefined for contracts without an owner() function (notably Stellar Asset Contracts, which expose admin() instead). The query stays disabled until a non-empty address is provided, which makes it easy to chain after useSacAddress.

Import

import { useTokenMetadata } from "@bluxcc/react";

Usage

Read a token contract directly:

import { useTokenMetadata } from "@bluxcc/react";

function TokenInfo() {
  const { data, isLoading, error } = useTokenMetadata(
    "CB64D3G7SM2RTH6JSGG34DDTFTQ5CFDKVDZJZSODMCX4NJ2HV2KN7OG",
  );

  if (isLoading) return <p>Loading…</p>;
  if (error) return <p>{error.message}</p>;

  // data → { decimals: 7, name: "USD Coin", symbol: "USDC", owner?: "G…" }
  return <p>{data?.name} ({data?.symbol})</p>;
}
root.render(
  <BluxProvider
    config={{
      appName: "MyApp",
      networks: [networks.testnet, networks.mainnet],
    }}
  >
    <App />
  </BluxProvider>
);

Derive a classic asset's SAC, then read it

Pair it with useSacAddress to read a classic asset's metadata. Keep the query disabled until the SAC id is known:

import { useSacAddress, useTokenMetadata } from "@bluxcc/react";

function ClassicAsset() {
  const { data: sac } = useSacAddress("USDC:GA5Z....KZVN");
  const { data: meta } = useTokenMetadata(sac ?? "", undefined, {
    enabled: Boolean(sac),
  });

  return <p>{meta?.symbol} · {meta?.decimals} decimals</p>;
}
root.render(
  <BluxProvider
    config={{
      appName: "MyApp",
      networks: [networks.testnet, networks.mainnet],
    }}
  >
    <App />
  </BluxProvider>
);

You can pass core options (currently just network) and TanStack Query options as the second and third arguments:

import { useTokenMetadata, networks } from "@bluxcc/react";

const { data } = useTokenMetadata(
  "CB64...N7OG",
  { network: networks.mainnet },        // core options
  { enabled: true, staleTime: 60000 },  // TanStack options
);

Always pass the address first, then core options, then TanStack Query options. The hook relies on this order to work correctly.

Parameters

address (required)

string

The token contract id (C…), e.g. a SAC from useSacAddress / getSacAddress. The query is disabled while this is empty.

network

string | undefined

Passed as { network } in the second argument. The network to read from. Import networks from @bluxcc/react to select one. Omit to use the active network.

Query Options

These are passed as the third argument and map directly to TanStack Query options.

OptionTypeDefaultDescription
enabledbooleantrueSet to false to disable automatic fetching. Also auto-disabled while address is empty.
staleTimenumber | Infinity0Time in ms before data is considered stale
gcTimenumber | Infinity300000Time in ms before inactive cache data is garbage collected
retryboolean | number3How many times to retry on failure
retryDelaynumber | functionDelay in ms between retry attempts
refetchIntervalnumber | false | functionContinuously refetch at this interval in ms
refetchOnMountboolean | 'always'trueRefetch on component mount if data is stale
refetchOnWindowFocusboolean | 'always'trueRefetch when the window regains focus
refetchOnReconnectboolean | 'always'trueRefetch when network reconnects
refetchIntervalInBackgroundbooleanKeep refetching even when tab is in background
placeholderDataTokenMetadata | functionPlaceholder data shown while query is pending (not persisted to cache)
initialDataTokenMetadata | functionInitial data for the cache (persisted)
initialDataUpdatedAtnumber | functionTimestamp of when initialData was last updated
selectfunctionTransform or select a subset of the returned data
notifyOnChangePropsstring[] | 'all'Limit re-renders to specific property changes
structuralSharingboolean | functiontrueRetain references from old data for performance
networkMode'online' | 'always' | 'offlineFirst''online'Controls when queries can run relative to network status
metaRecord<string, unknown>Attach arbitrary metadata to the query cache entry
queryClientQueryClientUse a custom QueryClient instead of the nearest context one

Return Type

data

TokenMetadata | undefined

type TokenMetadata = {
  decimals: number;     // number of decimal places the token uses
  name: string;         // human-readable token name
  symbol: string;       // token symbol / code
  owner?: string;       // owner() when present; undefined for a SAC
};

Status Booleans

PropertyTypeDescription
isPendingbooleanNo cached data and no completed fetch yet
isSuccessbooleanQuery resolved successfully
isErrorbooleanQuery failed
isLoadingbooleanFirst fetch in-flight (isFetching && isPending)
isFetchingbooleanQuery function is currently executing
isRefetchingbooleanBackground refetch in progress
isFetchedbooleanQuery has been fetched at least once
isFetchedAfterMountbooleanQuery fetched after component mounted
isStalebooleanCached data is stale or older than staleTime
isPlaceholderDatabooleanCurrently showing placeholder data
isLoadingErrorbooleanFailed on the first fetch
isRefetchErrorbooleanFailed during a background refetch
isPausedbooleanQuery wanted to fetch but was paused

Other Returns

PropertyTypeDescription
status'pending' | 'success' | 'error'Current query status
fetchStatus'fetching' | 'idle' | 'paused'Current fetch status
errornull | ErrorError object if the query failed
dataUpdatedAtnumberTimestamp of last successful fetch
errorUpdatedAtnumberTimestamp of last error
errorUpdateCountnumberTotal number of errors
failureCountnumberFailures since last success
failureReasonnull | ErrorReason for last retry failure
refetchfunctionManually trigger a refetch

This is a read-only simulation, so the user does not need to be connected. See getTokenMetadata for the BLUX: errors that surface on error.

On this page