Skip to main content
Jettons are fungible tokens on TON, similar to ERC-20 tokens on Ethereum. Unlike Toncoin, which is the native TON currency used in all transfers, each jetton has a separate master (minter) contract and an individual wallet contract for each holder. For example, USDT on TON is implemented as a jetton, and its minter contract address is EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs. By providing this address and the recipient’s TON wallet contract address, AppKit knows which tokens to send and to whom.

Metadata

Retrieve metadata about a specific jetton, such as its name, symbol, and decimals:
import { useJettonInfo } from '@ton/appkit-react';

export const JettonCard = ({ jettonAddress }) => {
  const {
    data: info,
    isLoading,
    error,
  } = useJettonInfo({
    // Jetton master (minter) contract address
    address: jettonAddress,
  });

  if (isLoading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>Error: {error.message}</div>;
  }

  return (
    <div>
      <p><em>Jetton info</em></p>
      <p>Name: {info?.name}</p>
      <p>Symbol: {info?.symbol}</p>
      <p>Decimals: {info?.decimals}</p>
    </div>
  );
};

Jetton wallet address

Each jetton holder has a dedicated jetton wallet contract. To resolve its address for a given owner:
import {
  useJettonWalletAddress,
  useAddress,
} from '@ton/appkit-react';

export const JettonWalletAddressCard = ({ jettonAddress }) => {
  const ownerAddress = useAddress();
  const {
    data: walletAddress,
    isLoading,
    error,
  } = useJettonWalletAddress({
    // TON wallet address of the jetton holder
    ownerAddress: ownerAddress ?? '<TON_WALLET_ADDRESS>',

    // Jetton master (minter) contract address
    jettonAddress,
  });

  if (isLoading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>Error: {error.message}</div>;
  }

  return <div>Jetton wallet address: {walletAddress?.toString()}</div>;
};

Balance

Similar to Toncoin balance checks, discrete one-off checks have limited value on their own and continuous monitoring should be used for UI display. Unlike Toncoin, the balance units and decimal places vary between jettons — use the decimals field from the jetton’s metadata to interpret raw amounts correctly. USDT has a decimal precision of 6, meaning that the fractional balance string '0.1' represents a balance of 0.1 USDT, or 100000 micro USDT (raw units).

On-demand balance check

Single jetton

Check the balance of a specific jetton for the connected TON wallet or an arbitrary address:
import {
  useJettonBalanceByAddress,
  useAddress,
} from '@ton/appkit-react';

export const JettonBalanceCard = ({ jettonAddress }) => {
  const ownerAddress = useAddress();
  const {
    data: balance,
    isLoading,
    error,
  } = useJettonBalanceByAddress({
    // TON wallet address of the jetton holder
    ownerAddress: ownerAddress ?? '<TON_WALLET_ADDRESS>',

    // Jetton master (minter) contract address
    jettonAddress,

    // Jetton decimals to calculate raw unit amounts
    jettonDecimals: 6,
  });

  if (isLoading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>Error: {error.message}</div>;
  }

  return <div>Jetton balance: {balance ?? '0'}</div>;
};

All jettons

Retrieve every jetton held by the connected TON wallet or an arbitrary address:
import {
  useJettonsByAddress,
  useAddress,
  // Helper function targeting the connected wallet
  useJettons,
} from '@ton/appkit-react';

export const JettonListByAddress = () => {
  const address = useAddress();
  const {
    data: jettons,
    isLoading,
    error,
  } = useJettonsByAddress({
    // TON wallet address of the jetton holder
    address: address ?? '<TON_WALLET_ADDRESS>',
  });

  // Alternatively, query the connected wallet directly
  // const { data: jettons, isLoading, error } = useJettons();

  if (isLoading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>Error: {error.message}</div>;
  }

  return (
    <div>
      <p>Jettons</p>
      <ul>
        {jettons?.jettons.map((jetton) => (
          <li key={jetton.walletAddress}>
            {jetton.info.name}: {jetton.balance ?? '0'}
          </li>
        ))}
      </ul>
    </div>
  );
};

Continuous balance monitoring

Poll the balance at regular intervals to keep the displayed value up to date. Use an appropriate interval based on UX requirements — shorter intervals provide fresher data but increase API usage. Modify the following example according to the application logic:
import {
  useJettonBalanceByAddress,
  useAddress,
} from '@ton/appkit-react';

export const JettonBalanceCard = ({ jettonAddress }) => {
  const ownerAddress = useAddress();
  const {
    data: balance,
    isLoading,
    error,
    refetch,
  } = useJettonBalanceByAddress({
    // TON wallet address of the jetton holder
    ownerAddress: ownerAddress ?? '<TON_WALLET_ADDRESS>',

    // Jetton master (minter) contract address
    jettonAddress,
  });

  if (isLoading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return (
      <div>
        <p>Error: {error.message}</p>
        <button onClick={() => refetch()}>Try again</button>
      </div>
    );
  }

  return <div>Jetton balance: {balance ?? '0'}</div>;
};

Transfers

Before making a transfer, make sure there is enough Toncoin in the balance to cover the fees. Modify the following examples according to the application logic:
// Pre-built UI component for sending jetton transactions by clicking a button.
// It handles success and error states while being customizable.
import { SendJettonButton } from '@ton/appkit-react';

export const SendJetton = () => {
  // For example: 'UQ...'
  const recipientAddress = '<TON_WALLET_ADDRESS>';
  // For example, '0.1' or '1' jetton
  const jettonAmount = '<FRACTIONAL_JETTON_AMOUNT>';
  // For example, 'EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs'
  const jettonAddress = '<JETTON_MINTER_ADDRESS>';

  return (
    <SendJettonButton
      // New owner of the sent jettons
      recipientAddress={recipientAddress}

      // Jetton amount in fractional units
      amount={jettonAmount}

      // What kind of jettons to send
      jetton={{
        // Jetton master (minter) contract address
        address: jettonAddress,

        // Short ticker name
        symbol: 'USDT',

        // Jetton decimals to calculate raw unit amounts
        // For example, USDT defaults to 6, while Toncoin to 9:
        decimals: 6,
      }}

      // (optional) Comment
      comment="Hello from AppKit!"

      // (optional) Add custom button title
      text="Send some jetton"

      // (optional) Handle successes
      onSuccess={(result) => console.log('Transaction sent:', result)}

      // (optional) Handle errors
      onError={(error) => console.error('Transaction failed:', error)}

      // (optional) Add custom CSS classes
      className=''

      // (optional) When set to `true`, the button is disabled
      disabled={false}
    />
  );
};

Next steps

Work with NFTs

See also

Jettons: General: