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, chainType: chainTypeStr,
address: addressStr, address: addressStr,
balance: balance.usdtBalance, balance: balance.usdtBalance,
rawBalance: this.toRawBalance(balance.usdtBalance, this.getDecimals(chainTypeStr)), rawBalance: balance.usdtRawBalance,
decimals: this.getDecimals(chainTypeStr), decimals: balance.usdtDecimals,
}; };
if (chainTypeStr === ChainTypeEnum.KAVA) { if (chainTypeStr === ChainTypeEnum.KAVA) {
@ -99,25 +99,4 @@ export class DepositController {
return response; 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; chainType: string;
address: string; address: string;
usdtBalance: string; usdtBalance: string;
usdtRawBalance: string;
usdtDecimals: number;
nativeBalance: string; nativeBalance: string;
nativeSymbol: string; nativeSymbol: string;
} }
@ -39,6 +41,8 @@ export class BalanceQueryService {
chainType: chainType.toString(), chainType: chainType.toString(),
address, address,
usdtBalance: usdtBalance.formatted, usdtBalance: usdtBalance.formatted,
usdtRawBalance: usdtBalance.raw.toString(),
usdtDecimals: usdtBalance.decimals,
nativeBalance: nativeBalance.formatted, nativeBalance: nativeBalance.formatted,
nativeSymbol: config.nativeSymbol, nativeSymbol: config.nativeSymbol,
}; };

View File

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