arc-units

Arc exposes one USDC balance through two interfaces at different scales. Get them confused and you are wrong by a factor of a trillion.

The two interfaces

nativeERC-20
read viagetBalance()balanceOf()
decimals186
address—0x3600…0000
truncatesnoyes

They are not two tokens. A precompile forwards ERC-20 calls to the account's native balance, so a UI showing both double-counts the same money.

Convert an amount

Type a USDC amount and watch what each interface reports.

Read a live account

Both reads are pinned to a single block. Arc produces one every ~500 ms, so reading them separately at latest can straddle a block and look like the invariant broke.

Use it

npm install arc-units viem
import { native, toErc20, toErc20Exact } from "arc-units";

const balance = native(1_234_567_890_123_456_789n);  // from getBalance()

const { value, dust } = toErc20(balance);
// value: 1234567n        what the recipient sees
// dust:  890123456789n   stays behind

toErc20Exact(balance);  // throws instead of losing it

Amounts carry their interface in the type, so a native amount and an ERC-20 amount cannot be added, compared, or passed to the wrong function — that is a compile error.