> ## Documentation Index
> Fetch the complete documentation index at: https://docs.chipipay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Reading State — Node.js

> Read-only operations every Chipi integration uses: token balances, the SKU catalog, and fiat-to-USD conversions. Zero gas, zero cost.

The reads on this page never touch a transaction. Use them whenever your app needs to display balances, browse the catalog, or quote a fiat amount in USD before charging the user.

## Token balances

`getTokenBalance` returns the on-chain balance of an ERC-20 token for a wallet. Look the wallet up by your own user identifier, or by the wallet's public address.

```ts theme={null}
import { Chain, ChainToken } from "@chipi-stack/backend";

// By externalUserId (the identifier you passed to createWallet)
const usdc = await sdk.getTokenBalance({
  externalUserId: "user-42",
  chainToken: ChainToken.USDC,
  chain: Chain.STARKNET,
});

// Or by raw public key
const eth = await sdk.getTokenBalance({
  walletPublicKey: "0x...",
  chainToken: ChainToken.ETH,
  chain: Chain.STARKNET,
});
```

The response shape is:

```ts theme={null}
{
  chain: Chain;             // "STARKNET"
  chainToken: ChainToken;   // "USDC" | "ETH" | "STRK" | ...
  chainTokenAddress: string;
  decimals: number;         // 6 for USDC, 18 for ETH/STRK
  balance: string;          // raw on-chain units, e.g. "1234567" = 1.234567 USDC
}
```

`balance` is a **string of raw token units** (not human-formatted). It's a string because raw balances exceed JavaScript's safe-integer range — a single ETH (`10^18` wei) is already past `Number.MAX_SAFE_INTEGER` (`2^53 − 1`). Parse with `BigInt`; only convert to `Number` at display time.

```ts theme={null}
// For display (acceptable for typical balances; loses precision past ~9 PB of USDC)
const display = Number(BigInt(usdc.balance)) / 10 ** usdc.decimals;
console.log(`USDC balance: ${display}`);

// For ledgers / arithmetic that must stay precise — keep it as BigInt
const balance = BigInt(usdc.balance);
const oneUsdc = 10n ** BigInt(usdc.decimals);
if (balance >= oneUsdc) {
  console.log("User has at least 1 USDC");
}
```

## Browse the SKU catalog

`getSkuList` returns paginated SKUs for the Bill Payments service. See the [Bills guide](/services/bills/node) for filtering by `category`, `chipiCategory`, `carrierName`, and `provider`.

```ts theme={null}
const result = await sdk.getSkuList({ page: 1, limit: 5 });

console.log(result.total);         // total matching SKUs
console.log(result.data[0].name);  // first SKU's display name
```

`getSku` fetches a single SKU by id:

```ts theme={null}
const sku = await sdk.getSku("sku-MI200");
console.log(sku.name, sku.fixedAmount, sku.currency);
```

## Fiat → USD conversion

`getUsdAmount` converts a local-currency amount to USD using Chipi's exchange rate. Useful for showing the user "you'll be charged \~$X USDC for a $200 MXN bill" before they confirm.

```ts theme={null}
import { Currency } from "@chipi-stack/backend";

const usd = await sdk.getUsdAmount(200, Currency.MXN);
console.log(`200 MXN ≈ $${usd.toFixed(2)} USD`);
```

`Currency` values today: `"MXN"` and `"USD"`.

## Putting it together

A common dashboard pattern: show the user their USDC balance and quote the cost of a recharge before they tap "buy".

```ts theme={null}
import { Chain, ChainToken, Currency } from "@chipi-stack/backend";

async function quotePurchase(sdk, externalUserId, skuId) {
  const [balance, sku] = await Promise.all([
    sdk.getTokenBalance({
      externalUserId,
      chainToken: ChainToken.USDC,
      chain: Chain.STARKNET,
    }),
    sdk.getSku(skuId),
  ]);

  const usdQuote = await sdk.getUsdAmount(sku.fixedAmount, sku.currency as Currency);

  const balanceHuman = Number(BigInt(balance.balance)) / 10 ** balance.decimals;

  return {
    balance: balanceHuman,                              // USDC the user holds
    cost: usdQuote,                                     // approx USDC needed
    canAfford: balanceHuman >= usdQuote,
  };
}
```

> ✅ Verified against the live API on **2026-05-11**.
