59 lines
1.7 KiB
TypeScript
59 lines
1.7 KiB
TypeScript
import { ref, watch, type Ref } from 'vue';
|
|
import { useAccount, useChainId } from '@wagmi/vue';
|
|
import { createPublicClient, erc20Abi, formatUnits, http } from 'viem';
|
|
import { getHarbConfig, KRAIKEN_LOCAL_CHAIN } from '../config';
|
|
|
|
/**
|
|
* Read-only KRK token balance for the connected wallet.
|
|
* Lightweight — no contract writes, no staking, just balanceOf.
|
|
*/
|
|
export function useTokenBalance(tokenAddress: Ref<`0x${string}` | undefined> | `0x${string}`) {
|
|
const { address, isConnected } = useAccount();
|
|
const chainId = useChainId();
|
|
|
|
const balance = ref(0n);
|
|
const formatted = ref('0');
|
|
const loading = ref(false);
|
|
|
|
async function refresh() {
|
|
const token = typeof tokenAddress === 'string' ? tokenAddress : tokenAddress.value;
|
|
if (!address.value || !token) {
|
|
balance.value = 0n;
|
|
formatted.value = '0';
|
|
return;
|
|
}
|
|
|
|
loading.value = true;
|
|
try {
|
|
const config = getHarbConfig();
|
|
const chain = config.chains.find(c => c.id === chainId.value) ?? KRAIKEN_LOCAL_CHAIN;
|
|
const rpcUrl = chain.rpcUrls.default.http[0];
|
|
const client = createPublicClient({ chain, transport: http(rpcUrl) });
|
|
|
|
const result = await client.readContract({
|
|
abi: erc20Abi,
|
|
address: token,
|
|
functionName: 'balanceOf',
|
|
args: [address.value],
|
|
});
|
|
balance.value = result;
|
|
formatted.value = formatUnits(result, 18);
|
|
} catch {
|
|
balance.value = 0n;
|
|
formatted.value = '0';
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
}
|
|
|
|
watch([address, isConnected], () => {
|
|
if (isConnected.value) {
|
|
void refresh();
|
|
} else {
|
|
balance.value = 0n;
|
|
formatted.value = '0';
|
|
}
|
|
}, { immediate: true });
|
|
|
|
return { balance, formatted, loading, refresh };
|
|
}
|