fix: Fix collapse component formatting: taxPaid display, string coercion, BigInt precision (#260)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
openhands 2026-02-25 08:06:49 +00:00
parent f3383dce01
commit ca8e4737fe
4 changed files with 21 additions and 25 deletions

View file

@ -5,6 +5,8 @@
* This aligns with the Harberger tax economic model where stakers earn from protocol growth. * This aligns with the Harberger tax economic model where stakers earn from protocol growth.
*/ */
import { formatUnits } from 'viem';
/** /**
* Calculate profit for an active position. * Calculate profit for an active position.
* *
@ -31,8 +33,8 @@ export function calculateActivePositionProfit(totalSupplyInit: bigint, currentTo
} }
// Convert to token units (assuming 18 decimals) // Convert to token units (assuming 18 decimals)
const initSupply = Number(totalSupplyInit) / 1e18; const initSupply = Number(formatUnits(totalSupplyInit, 18));
const currentSupply = Number(currentTotalSupply) / 1e18; const currentSupply = Number(formatUnits(currentTotalSupply, 18));
// Calculate new issuance since position creation // Calculate new issuance since position creation
const newIssuance = currentSupply - initSupply; const newIssuance = currentSupply - initSupply;
@ -67,8 +69,8 @@ export function calculateClosedPositionProfit(totalSupplyInit: bigint, totalSupp
} }
// Convert to token units (assuming 18 decimals) // Convert to token units (assuming 18 decimals)
const initSupply = Number(totalSupplyInit) / 1e18; const initSupply = Number(formatUnits(totalSupplyInit, 18));
const endSupply = Number(totalSupplyEnd) / 1e18; const endSupply = Number(formatUnits(totalSupplyEnd, 18));
// Calculate new issuance during position lifetime // Calculate new issuance during position lifetime
const newIssuance = endSupply - initSupply; const newIssuance = endSupply - initSupply;

View file

@ -84,7 +84,7 @@ import FButton from '@/components/fcomponents/FButton.vue';
import FTag from '@/components/fcomponents/FTag.vue'; import FTag from '@/components/fcomponents/FTag.vue';
import FSelect from '@/components/fcomponents/FSelect.vue'; import FSelect from '@/components/fcomponents/FSelect.vue';
import FCollapse from '@/components/fcomponents/FCollapse.vue'; import FCollapse from '@/components/fcomponents/FCollapse.vue';
import { compactNumber, formatWei } from 'kraiken-lib/format'; import { compactNumber, weiToNumber } from 'kraiken-lib/format';
import { useUnstake } from '@/composables/useUnstake'; import { useUnstake } from '@/composables/useUnstake';
import { useAdjustTaxRate } from '@/composables/useAdjustTaxRates'; import { useAdjustTaxRate } from '@/composables/useAdjustTaxRates';
import { computed, ref, onMounted } from 'vue'; import { computed, ref, onMounted } from 'vue';
@ -114,7 +114,7 @@ const props = defineProps<{
const showTaxMenu = ref(false); const showTaxMenu = ref(false);
const newTaxRateIndex = ref<number | null>(null); const newTaxRateIndex = ref<number | null>(null);
const taxDue = ref<bigint>(); const taxDue = ref<bigint>();
const taxPaidGes = ref<string>(); const taxPaidGes = ref<number>();
const profit = ref<number>(); const profit = ref<number>();
const loading = ref<boolean>(false); const loading = ref<boolean>(false);
@ -127,22 +127,22 @@ const tag = computed(() => {
return ''; return '';
}); });
const total = computed(() => props.amount + profit.value! + -taxPaidGes.value!); const total = computed(() => props.amount + profit.value! - taxPaidGes.value!);
// P&L calculations (FIXED: Use BigInt math to preserve precision) // P&L calculations (FIXED: Use BigInt math to preserve precision)
const grossReturn = computed(() => { const grossReturn = computed(() => {
try { try {
const currentSupply = BigInt(statCollection.kraikenTotalSupply); const currentSupply = BigInt(statCollection.kraikenTotalSupply);
const initSupply = BigInt(props.position.totalSupplyInit); const initSupply = BigInt(props.position.totalSupplyInit);
if (initSupply === 0n) return 0; if (initSupply === 0n) return 0;
// Calculate percentage change using BigInt to avoid precision loss // Calculate percentage change using BigInt to avoid precision loss
// Formula: ((current - init) / init) * 100 // Formula: ((current - init) / init) * 100
// To maintain precision, multiply by 10000 first, then divide by 100 for display // To maintain precision, multiply by 10000 first, then divide by 100 for display
const diff = currentSupply - initSupply; const diff = currentSupply - initSupply;
const percentBigInt = (diff * 10000n) / initSupply; const percentBigInt = (diff * 10000n) / initSupply;
return Number(percentBigInt) / 100; return Number(percentBigInt) / 100;
} catch (error) { } catch (error) {
void error; // suppress lint void error; // suppress lint
@ -154,12 +154,12 @@ const taxCostPercent = computed(() => {
try { try {
const taxPaid = BigInt(props.position.taxPaid); const taxPaid = BigInt(props.position.taxPaid);
const deposit = BigInt(props.position.harbDeposit); const deposit = BigInt(props.position.harbDeposit);
if (deposit === 0n) return 0; if (deposit === 0n) return 0;
// Calculate percentage using BigInt precision // Calculate percentage using BigInt precision
const percentBigInt = (taxPaid * 10000n) / deposit; const percentBigInt = (taxPaid * 10000n) / deposit;
return Number(percentBigInt) / 100; return Number(percentBigInt) / 100;
} catch (error) { } catch (error) {
void error; // suppress lint void error; // suppress lint
@ -216,16 +216,12 @@ async function unstakePosition() {
async function loadActivePositionData() { async function loadActivePositionData() {
//loadTaxDue //loadTaxDue
taxDue.value = await getTaxDue(props.id); taxDue.value = await getTaxDue(props.id);
taxPaidGes.value = formatWei(taxDue.value + BigInt(props.position.taxPaid), 18); taxPaidGes.value = weiToNumber(taxDue.value + BigInt(props.position.taxPaid));
//loadTotalSupply //loadTotalSupply
// Calculate issuance earned using kraiken-lib profit calculation // Calculate issuance earned using kraiken-lib profit calculation
profit.value = calculateActivePositionProfit( profit.value = calculateActivePositionProfit(props.position.totalSupplyInit, statCollection.kraikenTotalSupply, props.position.share);
props.position.totalSupplyInit,
statCollection.kraikenTotalSupply,
props.position.share
);
} }
onMounted(() => { onMounted(() => {

View file

@ -20,7 +20,7 @@
</template> </template>
<div class="history-body"> <div class="history-body">
<div> <div>
<span class="subheader2">Tax paid</span><span class="number-small">{{ props.taxPaid }}</span <span class="subheader2">Tax paid</span><span class="number-small">{{ compactNumber(props.taxPaid) }}</span
><span class="caption"> $KRK</span> ><span class="caption"> $KRK</span>
</div> </div>
<div> <div>
@ -53,8 +53,7 @@ import { computed } from 'vue';
const props = defineProps<{ const props = defineProps<{
taxRate: number; taxRate: number;
taxPaid: string; taxPaid: number;
treshold: number;
id: bigint; id: bigint;
amount: number; amount: number;
position: Position; position: Position;

View file

@ -93,8 +93,7 @@
v-for="position in myClosedPositions" v-for="position in myClosedPositions"
:key="position.id" :key="position.id"
:taxRate="position.taxRatePercentage" :taxRate="position.taxRatePercentage"
:taxPaid="position.taxPaid.toString()" :taxPaid="weiToNumber(position.taxPaid)"
:treshold="tresholdValue"
:id="position.positionId" :id="position.positionId"
:amount="position.amount" :amount="position.amount"
:position="position" :position="position"
@ -129,7 +128,7 @@ import { usePositions } from '@/composables/usePositions';
const { status } = useAccount(); const { status } = useAccount();
const showPanel = inject('showPanel'); const showPanel = inject('showPanel');
import { commaNumber } from 'kraiken-lib/format'; import { commaNumber, weiToNumber } from 'kraiken-lib/format';
const wallet = useWallet(); const wallet = useWallet();
const initialChainId = wallet.account.chainId ?? DEFAULT_CHAIN_ID; const initialChainId = wallet.account.chainId ?? DEFAULT_CHAIN_ID;
const { myActivePositions, myClosedPositions, tresholdValue, activePositions } = usePositions(initialChainId); const { myActivePositions, myClosedPositions, tresholdValue, activePositions } = usePositions(initialChainId);