fix(blockchain): read token decimals from contract instead of hardcoding

The balance display was incorrect because decimals were hardcoded to 18,
but USDT uses 6 decimals. Now reads decimals() from the ERC20 contract.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2025-12-09 06:10:36 -08:00
parent addcfa56e4
commit 2e6f22e9d8
3 changed files with 15 additions and 26 deletions

View File

@ -78,8 +78,8 @@ export class DepositController {
chainType: chainTypeStr,
address: addressStr,
balance: balance.usdtBalance,
rawBalance: this.toRawBalance(balance.usdtBalance, this.getDecimals(chainTypeStr)),
decimals: this.getDecimals(chainTypeStr),
rawBalance: balance.usdtRawBalance,
decimals: balance.usdtDecimals,
};
if (chainTypeStr === ChainTypeEnum.KAVA) {
@ -99,25 +99,4 @@ export class DepositController {
return response;
}
private getDecimals(chainType: string): number {
// USDT decimals by chain
switch (chainType) {
case ChainTypeEnum.KAVA:
return 18; // Our test USDT on KAVA uses 18 decimals
case ChainTypeEnum.BSC:
return 18; // Standard USDT on BSC
default:
return 18;
}
}
private toRawBalance(formattedBalance: string, decimals: number): string {
try {
const value = parseFloat(formattedBalance);
return BigInt(Math.floor(value * Math.pow(10, decimals))).toString();
} catch {
return '0';
}
}
}

View File

@ -8,6 +8,8 @@ export interface BalanceResult {
chainType: string;
address: string;
usdtBalance: string;
usdtRawBalance: string;
usdtDecimals: number;
nativeBalance: string;
nativeSymbol: string;
}
@ -39,6 +41,8 @@ export class BalanceQueryService {
chainType: chainType.toString(),
address,
usdtBalance: usdtBalance.formatted,
usdtRawBalance: usdtBalance.raw.toString(),
usdtDecimals: usdtBalance.decimals,
nativeBalance: nativeBalance.formatted,
nativeSymbol: config.nativeSymbol,
};

View File

@ -10,7 +10,10 @@ const ERC20_TRANSFER_EVENT_ABI = [
];
// ERC20 balanceOf ABI
const ERC20_BALANCE_ABI = ['function balanceOf(address owner) view returns (uint256)'];
const ERC20_BALANCE_ABI = [
'function balanceOf(address owner) view returns (uint256)',
'function decimals() view returns (uint8)',
];
export interface TransferEvent {
txHash: string;
@ -127,8 +130,11 @@ export class EvmProviderAdapter {
): Promise<TokenAmount> {
const provider = this.getProvider(chainType);
const contract = new Contract(tokenContract, ERC20_BALANCE_ABI, provider);
const balance = await contract.balanceOf(address);
return TokenAmount.fromRaw(balance, 18);
const [balance, decimals] = await Promise.all([
contract.balanceOf(address),
contract.decimals(),
]);
return TokenAmount.fromRaw(balance, Number(decimals));
}
/**