Баланс jetton: чтение через get-метод

Прочитаешь баланс Jetton через get_wallet_data и найдёшь wallet-адрес через get_wallet_address — без транзакции.

Где лежит баланс

Баланс jetton — поле storage jetton-wallet, не master и не TON-кошелька. Читаешь get-методом get_wallet_data (бесплатно через RPC). Сначала нужен адрес wallet: get_wallet_address на master.


Читаем баланс jUSDT

typescript
// @ton/ton ^15.1.0, @ton/core ^0.59.0
import { Address, TonClient, JettonMaster, fromNano } from "@ton/ton";

const client = new TonClient({
  endpoint: "https://toncenter.com/api/v2/jsonRPC",
});

// jUSDT master — mainnet, decimals = 6
const JUSDT = Address.parse(
  "EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs",
);
const DECIMALS = 6n;

const owner = Address.parse(
  "EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N",
);

async function getJettonBalance(ownerAddr: Address, masterAddr: Address) {
  const master = client.open(JettonMaster.create(masterAddr));
  const walletAddr = await master.getWalletAddress(ownerAddr);

  const state = await client.getContractState(walletAddr);
  if (state.state !== "active") {
    return 0n; // wallet ещё не задеплоен → баланса нет
  }

  const result = await client.runMethod(walletAddr, "get_wallet_data");
  const balance = result.stack.readBigNumber();
  const walletOwner = result.stack.readAddress();
  const jettonMaster = result.stack.readAddress();
  // дальше на стеке — cell с wallet_code

  if (!walletOwner.equals(ownerAddr)) {
    throw new Error("owner mismatch");
  }
  if (!jettonMaster.equals(masterAddr)) {
    throw new Error("master mismatch — чужой jetton-wallet");
  }

  return balance;
}

const raw = await getJettonBalance(owner, JUSDT);
const human = Number(raw) / Number(10n ** DECIMALS);
console.log({ raw: raw.toString(), human });
// fromNano тут не подходит: он делит на 1e9 (Gram), не на decimals токена
void fromNano;

Как это работает

  • getWalletAddress — детерминированный адрес; контракт может быть ещё uninit.
  • get_wallet_data(balance, owner, jetton, jetton_wallet_code).
  • Проверка jettonMaster.equals(masterAddr) защищает от поддельного wallet с тем же layout.
  • decimals бери из метаданных (get_jetton_data / JSON), не хардкодь «как у Gram».

Частые ошибки

Читаешь balance с master → у master нет баланса пользователя, только total_supply.

Делишь через fromNano → для токена с decimals=6 получишь неверный human-readable.

Не обработал uninit walletrunMethod падает; для UI это просто 0.


Что дальше

Материалы gramdocs.tech носят образовательный характер и не являются финансовой, юридической или инвестиционной рекомендацией. Работа с блокчейном TON и токеном Gram связана с рисками потери средств. Правовая информация