Merge pull request 'fix: Extract duplicated formatTokenAmount to helper.ts (#209)' (#228) from fix/issue-209 into master

This commit is contained in:
johba 2026-02-24 20:46:16 +01:00
commit 1bc01c0555
4 changed files with 22 additions and 33 deletions

3
package-lock.json generated
View file

@ -1,5 +1,5 @@
{ {
"name": "harb-worktree-150", "name": "harb-worktree-209",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
@ -21831,7 +21831,6 @@
"name": "harb-staking", "name": "harb-staking",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@harb/ui-shared": "*",
"@harb/web3": "*", "@harb/web3": "*",
"@tanstack/vue-query": "^5.64.2", "@tanstack/vue-query": "^5.64.2",
"@vue/test-utils": "^2.4.6", "@vue/test-utils": "^2.4.6",

View file

@ -2,6 +2,7 @@ import { ref, computed, onMounted, onUnmounted, type Ref } from 'vue';
import axios from 'axios'; import axios from 'axios';
import { DEFAULT_CHAIN_ID } from '@/config'; import { DEFAULT_CHAIN_ID } from '@/config';
import { resolveGraphqlEndpoint, formatGraphqlError } from '@/utils/graphqlRetry'; import { resolveGraphqlEndpoint, formatGraphqlError } from '@/utils/graphqlRetry';
import { parseTokenAmount } from '@/utils/helper';
import logger from '@/utils/logger'; import logger from '@/utils/logger';
const GRAPHQL_TIMEOUT_MS = 15_000; const GRAPHQL_TIMEOUT_MS = 15_000;
@ -39,16 +40,6 @@ export interface ActivePositionShort {
kraikenDeposit: string; kraikenDeposit: string;
} }
function formatTokenAmount(rawWei: string, decimals = 18): number {
try {
const big = BigInt(rawWei);
const divisor = 10 ** decimals;
return Number(big) / divisor;
} catch {
return 0;
}
}
function formatDate(ts: string | null): string { function formatDate(ts: string | null): string {
if (!ts) return 'N/A'; if (!ts) return 'N/A';
try { try {
@ -178,13 +169,13 @@ export function usePositionDashboard(positionId: Ref<string>) {
} }
// Derived values // Derived values
const depositKrk = computed(() => formatTokenAmount(position.value?.kraikenDeposit ?? '0')); const depositKrk = computed(() => parseTokenAmount(position.value?.kraikenDeposit ?? '0'));
const taxPaidKrk = computed(() => formatTokenAmount(position.value?.taxPaid ?? '0')); const taxPaidKrk = computed(() => parseTokenAmount(position.value?.taxPaid ?? '0'));
const currentValueKrk = computed(() => { const currentValueKrk = computed(() => {
if (!position.value || !stats.value) return 0; if (!position.value || !stats.value) return 0;
const share = Number(position.value.share); const share = Number(position.value.share);
const outstanding = formatTokenAmount(stats.value.outstandingStake); const outstanding = parseTokenAmount(stats.value.outstandingStake);
return share * outstanding; return share * outstanding;
}); });
@ -245,7 +236,7 @@ export function usePositionDashboard(positionId: Ref<string>) {
return { count: lower, level, color }; return { count: lower, level, color };
}); });
const payoutKrk = computed(() => formatTokenAmount(position.value?.payout ?? '0')); const payoutKrk = computed(() => parseTokenAmount(position.value?.payout ?? '0'));
const netPnlKrk = computed(() => { const netPnlKrk = computed(() => {
if (!position.value) return 0; if (!position.value) return 0;

View file

@ -2,6 +2,7 @@ import { ref, computed, onMounted, onUnmounted, type Ref } from 'vue';
import axios from 'axios'; import axios from 'axios';
import { DEFAULT_CHAIN_ID } from '@/config'; import { DEFAULT_CHAIN_ID } from '@/config';
import { resolveGraphqlEndpoint, formatGraphqlError } from '@/utils/graphqlRetry'; import { resolveGraphqlEndpoint, formatGraphqlError } from '@/utils/graphqlRetry';
import { parseTokenAmount } from '@/utils/helper';
import logger from '@/utils/logger'; import logger from '@/utils/logger';
const GRAPHQL_TIMEOUT_MS = 15_000; const GRAPHQL_TIMEOUT_MS = 15_000;
@ -36,16 +37,6 @@ export interface WalletStats {
holderCount: number; holderCount: number;
} }
function formatTokenAmount(rawWei: string, decimals = 18): number {
try {
const big = BigInt(rawWei);
const divisor = 10 ** decimals;
return Number(big) / divisor;
} catch {
return 0;
}
}
export function useWalletDashboard(address: Ref<string>) { export function useWalletDashboard(address: Ref<string>) {
const holderBalance = ref<string>('0'); const holderBalance = ref<string>('0');
const holderTotalEthSpent = ref<string>('0'); const holderTotalEthSpent = ref<string>('0');
@ -145,13 +136,13 @@ export function useWalletDashboard(address: Ref<string>) {
} }
// Derived values // Derived values
const balanceKrk = computed(() => formatTokenAmount(holderBalance.value)); const balanceKrk = computed(() => parseTokenAmount(holderBalance.value));
const ethBacking = computed(() => { const ethBacking = computed(() => {
if (!stats.value) return 0; if (!stats.value) return 0;
const balance = balanceKrk.value; const balance = balanceKrk.value;
const reserve = formatTokenAmount(stats.value.lastEthReserve); const reserve = parseTokenAmount(stats.value.lastEthReserve);
const totalSupply = formatTokenAmount(stats.value.kraikenTotalSupply); const totalSupply = parseTokenAmount(stats.value.kraikenTotalSupply);
if (totalSupply === 0) return 0; if (totalSupply === 0) return 0;
return balance * (reserve / totalSupply); return balance * (reserve / totalSupply);
}); });
@ -160,21 +151,21 @@ export function useWalletDashboard(address: Ref<string>) {
if (!stats.value) return 0; if (!stats.value) return 0;
const balance = balanceKrk.value; const balance = balanceKrk.value;
// floorPriceWei is price per token in wei → convert to ETH // floorPriceWei is price per token in wei → convert to ETH
const floorPriceEth = formatTokenAmount(stats.value.floorPriceWei); const floorPriceEth = parseTokenAmount(stats.value.floorPriceWei);
return balance * floorPriceEth; return balance * floorPriceEth;
}); });
// Cost basis & P&L // Cost basis & P&L
const avgCostBasis = computed(() => { const avgCostBasis = computed(() => {
const spent = formatTokenAmount(holderTotalEthSpent.value); const spent = parseTokenAmount(holderTotalEthSpent.value);
const acquired = formatTokenAmount(holderTotalTokensAcquired.value); const acquired = parseTokenAmount(holderTotalTokensAcquired.value);
if (acquired === 0) return 0; if (acquired === 0) return 0;
return spent / acquired; return spent / acquired;
}); });
const currentPriceEth = computed(() => { const currentPriceEth = computed(() => {
if (!stats.value?.currentPriceWei) return 0; if (!stats.value?.currentPriceWei) return 0;
return formatTokenAmount(stats.value.currentPriceWei); return parseTokenAmount(stats.value.currentPriceWei);
}); });
const unrealizedPnlEth = computed(() => { const unrealizedPnlEth = computed(() => {

View file

@ -68,6 +68,14 @@ export function formatTokenAmount(raw: string, decimals: number = 18, digits: nu
} }
} }
export function parseTokenAmount(rawWei: string, decimals = 18): number {
try {
return Number(formatUnits(BigInt(rawWei), decimals));
} catch {
return 0;
}
}
export function formatBigIntDivision(nominator: bigint, denominator: bigint, _digits: number = 2) { export function formatBigIntDivision(nominator: bigint, denominator: bigint, _digits: number = 2) {
if (!nominator) { if (!nominator) {
return 0; return 0;