Token Support
The SDK supports ETH and EMT stablecoins (zkUSD, zkEUR, zkPLN).
Supported Tokens
| Token | Decimals | Fiat Backing |
|---|---|---|
| ETH | 18 | - |
| zkUSD | 6 | US Dollar |
| zkEUR | 6 | Euro |
| zkPLN | 6 | Polish Zloty |
Token IDs
Tokens are identified by their contract address as a bigint:
typescript
const tokenId = BigInt(tokenAddress);
// ETH uses token ID 0
const ethTokenId = 0n;Getting Token Addresses
typescript
import { DEPLOYMENTS } from '@zkprivacy/sdk';
const { tokens } = DEPLOYMENTS.remote;
console.log('zkUSD:', tokens.zkUSD);
console.log('zkEUR:', tokens.zkEUR);
console.log('zkPLN:', tokens.zkPLN);Token Balances
Single Token
typescript
const tokenId = BigInt(DEPLOYMENTS.remote.tokens.zkUSD);
const balance = client.getBalanceByTokenId(tokenId);All Tokens
typescript
const balances = client.getAllBalances();
for (const [tokenId, balance] of balances) {
console.log(`Token ${tokenId}: ${balance}`);
}ETH Balance
typescript
// Shorthand for ETH (token ID 0)
const ethBalance = client.getBalance();
// Or explicitly
const ethBalance = client.getBalanceByTokenId(0n);Token Transfers
Always specify tokenId for non-ETH transfers:
typescript
import { parseUnits } from 'viem';
await client.transfer({
recipient: 'zks1...',
amount: parseUnits('100', 6), // 100 USDC
tokenId: BigInt(DEPLOYMENTS.remote.tokens.zkUSD),
});Token Utilities
Format for Display
typescript
import { formatTokenAmount } from '@zkprivacy/sdk';
formatTokenAmount(1000000n, 'zkUSD'); // "1.00"
formatTokenAmount(1234567n, 'zkUSD'); // "1.23"Parse User Input
typescript
import { parseTokenAmount } from '@zkprivacy/sdk';
parseTokenAmount('100.50', 'zkUSD'); // 100500000n
parseTokenAmount('1,234.56', 'zkUSD'); // 1234560000nToken Lookup
typescript
import { getTokenBySymbol, getTokenByAddress } from '@zkprivacy/sdk';
const token = getTokenBySymbol('zkUSD');
// { symbol: 'zkUSD', decimals: 6, name: 'ZK US Dollar', ... }
const token = getTokenByAddress('0x...');Shielding Tokens
Shield to Self
typescript
await client.shield({
amount: parseUnits('100', 6),
tokenId: BigInt(tokenAddress),
});Shield to Others
typescript
import { shieldTo } from '@zkprivacy/sdk';
await shieldTo(config, {
recipient: 'zks1...',
amount: '100',
tokenAddress: DEPLOYMENTS.remote.tokens.zkUSD,
walletClient,
});Unshielding Tokens
typescript
await client.unshield({
recipient: '0x...',
amount: parseUnits('100', 6),
tokenId: BigInt(DEPLOYMENTS.remote.tokens.zkUSD),
});EMT Token ABI
Use the EMT ABI for direct contract interaction:
typescript
import { EMT_ABI } from '@zkprivacy/sdk';
// Read balance
const balance = await publicClient.readContract({
address: tokenAddress,
abi: EMT_ABI,
functionName: 'balanceOf',
args: [account],
});
// Shield directly
await walletClient.writeContract({
address: tokenAddress,
abi: EMT_ABI,
functionName: 'shield',
args: [amount, commitment, encryptedNote],
});Working with Decimals
EMT tokens use 6 decimals (like USDC):
typescript
import { parseUnits, formatUnits } from 'viem';
// Parse: "100.50" → 100500000n
const amount = parseUnits('100.50', 6);
// Format: 100500000n → "100.50"
const display = formatUnits(100500000n, 6);ETH uses 18 decimals:
typescript
import { parseEther, formatEther } from 'viem';
const amount = parseEther('1.5'); // 1.5 ETH in wei
const display = formatEther(amount);Multi-Token Notes
Each note is tied to a specific token. You cannot:
- Transfer zkUSD with a zkEUR note
- Consolidate notes of different tokens
The SDK handles this automatically - it selects notes matching the transfer token.