Skip to content
This repository has been archived by the owner on Jan 2, 2025. It is now read-only.

Commit

Permalink
Fix collator power (#70)
Browse files Browse the repository at this point in the history
* Fix exposureCache index

* Adapt commission weighted power

* Power tooltips
  • Loading branch information
JayJay1024 authored Nov 28, 2023
1 parent b2c9ade commit 8119ab7
Show file tree
Hide file tree
Showing 14 changed files with 232 additions and 118 deletions.
15 changes: 10 additions & 5 deletions src/components/bond-more-deposit-modal.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { Key, useCallback, useMemo, useState } from "react";
import Modal from "./modal";
import CheckboxGroup from "./checkbox-group";
import { formatBlanace, getChainConfig, notifyTransaction } from "@/utils";
import { commissionWeightedPower, formatBlanace, getChainConfig, notifyTransaction } from "@/utils";
import { ExtraPower } from "./balance-input";
import { useApp, useStaking } from "@/hooks";
import { notification } from "./notification";
import { writeContract, waitForTransaction } from "@wagmi/core";

export default function BondMoreDepositModal({
commission,
isOpen,
onClose = () => undefined,
}: {
commission: string;
isOpen: boolean;
onClose?: () => void;
}) {
Expand All @@ -22,11 +24,14 @@ export default function BondMoreDepositModal({

const extraPower = useMemo(
() =>
calcExtraPower(
deposits.filter(({ id }) => checkedDeposits.includes(id)).reduce((acc, cur) => acc + cur.value, 0n),
0n
commissionWeightedPower(
calcExtraPower(
deposits.filter(({ id }) => checkedDeposits.includes(id)).reduce((acc, cur) => acc + cur.value, 0n),
0n
),
commission
),
[deposits, checkedDeposits, calcExtraPower]
[deposits, commission, checkedDeposits, calcExtraPower]
);

const availableDeposits = deposits.filter(({ id }) => !stakedDeposits.includes(id));
Expand Down
6 changes: 4 additions & 2 deletions src/components/bond-more-kton-modal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getChainConfig, notifyTransaction } from "@/utils";
import { commissionWeightedPower, getChainConfig, notifyTransaction } from "@/utils";
import BondMoreTokenModal from "./bond-more-token-modal";
import { useApp, useStaking } from "@/hooks";
import { useAccount, useBalance } from "wagmi";
Expand All @@ -7,9 +7,11 @@ import { notification } from "./notification";
import { writeContract, waitForTransaction } from "@wagmi/core";

export default function BondMoreKtonModal({
commission,
isOpen,
onClose = () => undefined,
}: {
commission: string;
isOpen: boolean;
onClose?: () => void;
}) {
Expand Down Expand Up @@ -60,7 +62,7 @@ export default function BondMoreKtonModal({
isOpen={isOpen}
symbol={ktonToken.symbol}
decimals={ktonToken.decimals}
power={calcExtraPower(0n, inputAmount)}
power={commissionWeightedPower(calcExtraPower(0n, inputAmount), commission)}
balance={ktonBalance?.value || 0n}
busy={busy}
disabled={inputAmount <= 0n}
Expand Down
6 changes: 4 additions & 2 deletions src/components/bond-more-ring-modal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getChainConfig, notifyTransaction } from "@/utils";
import { commissionWeightedPower, getChainConfig, notifyTransaction } from "@/utils";
import BondMoreTokenModal from "./bond-more-token-modal";
import { useAccount, useBalance } from "wagmi";
import { useApp, useStaking } from "@/hooks";
Expand All @@ -7,9 +7,11 @@ import { notification } from "./notification";
import { writeContract, waitForTransaction } from "@wagmi/core";

export default function BondMoreRingModal({
commission,
isOpen,
onClose = () => undefined,
}: {
commission: string;
isOpen: boolean;
onClose?: () => void;
}) {
Expand Down Expand Up @@ -58,7 +60,7 @@ export default function BondMoreRingModal({
isOpen={isOpen}
symbol={nativeToken.symbol}
decimals={nativeToken.decimals}
power={calcExtraPower(inputAmount, 0n)}
power={commissionWeightedPower(calcExtraPower(inputAmount, 0n), commission)}
balance={ringBalance?.value || 0n}
busy={busy}
disabled={inputAmount <= 0n}
Expand Down
35 changes: 32 additions & 3 deletions src/components/collator-select-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import Image from "next/image";
import { useAccount } from "wagmi";
import Table, { ColumnType } from "./table";
import Jazzicon from "./jazzicon";
import { prettyNumber } from "@/utils";
import { commissionWeightedPower, prettyNumber } from "@/utils";
import { notification } from "./notification";
import DisplayAccountName from "./display-account-name";
import { useStaking } from "@/hooks";
import Tooltip from "./tooltip";

type TabKey = "active" | "waiting";

Expand Down Expand Up @@ -59,10 +60,38 @@ const columns: ColumnType<DataSource>[] = [
title: (
<div className="inline-flex flex-col text-xs font-bold text-white">
<span>Total-staked</span>
<span>(Power)</span>
<div className="inline-flex items-center gap-small">
<span>(Power)</span>
<Tooltip
content={
<div className="inline-block text-xs font-light text-white">
{`The Collator's total-staked power is a dynamic value, inversely proportional to the commission set by
the Collator. Higher commission results in lower total-staked power and vice versa. `}
<a
rel="noopener noreferrer"
target="_blank"
className="text-primary hover:underline"
href="https://github.com/darwinia-network/DIPs/blob/main/DIPs/dip-1.md"
>
Learn More
</a>
</div>
}
enabledSafePolygon
contentClassName="w-80"
>
<Image
width={15}
height={14}
alt="Info"
src="/images/help.svg"
className="opacity-60 transition-opacity hover:opacity-100"
/>
</Tooltip>
</div>
</div>
),
render: (row) => <span>{prettyNumber(row.power)}</span>,
render: (row) => <span>{prettyNumber(commissionWeightedPower(row.power, row.commission))}</span>,
},
{
key: "commission",
Expand Down
37 changes: 28 additions & 9 deletions src/components/do-stake.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getChainConfig, notifyTransaction } from "@/utils";
import { commissionWeightedPower, getChainConfig, notifyTransaction } from "@/utils";
import ActiveDepositSelector from "./active-deposit-selector";
import CollatorSelector from "./collator-selector";
import BalanceInput, { ExtraPower } from "./balance-input";
Expand All @@ -11,8 +11,14 @@ import { ChainID } from "@/types";
import { notification } from "./notification";

export default function DoStake() {
const { deposits, nominatorCollators, isNominatorCollatorsLoading, calcExtraPower, updateNominatorCollators } =
useStaking();
const {
deposits,
nominatorCollators,
collatorCommission,
isNominatorCollatorsLoading,
calcExtraPower,
updateNominatorCollators,
} = useStaking();
const [delegateCollator, setDelegateCollator] = useState<string | undefined>(undefined);
const [delegateRing, setDelegateRing] = useState(0n);
const [delegateKton, setDelegateKton] = useState(0n);
Expand All @@ -28,15 +34,28 @@ export default function DoStake() {
const { data: ringBalance } = useBalance({ address, watch: true });
const { data: ktonBalance } = useBalance({ address, watch: true, token: ktonToken?.address });

const ringExtraPower = useMemo(() => calcExtraPower(delegateRing, 0n), [delegateRing, calcExtraPower]);
const ktonExtraPower = useMemo(() => calcExtraPower(0n, delegateKton), [delegateKton, calcExtraPower]);
const commission = useMemo(() => {
return (delegateCollator && collatorCommission[delegateCollator]) || "0.00%";
}, [delegateCollator, collatorCommission]);

const ringExtraPower = useMemo(
() => commissionWeightedPower(calcExtraPower(delegateRing, 0n), commission),
[commission, delegateRing, calcExtraPower]
);
const ktonExtraPower = useMemo(
() => commissionWeightedPower(calcExtraPower(0n, delegateKton), commission),
[commission, delegateKton, calcExtraPower]
);
const depositsExtraPower = useMemo(
() =>
calcExtraPower(
deposits.filter(({ id }) => delegateDeposits.includes(id)).reduce((acc, cur) => acc + cur.value, 0n),
0n
commissionWeightedPower(
calcExtraPower(
deposits.filter(({ id }) => delegateDeposits.includes(id)).reduce((acc, cur) => acc + cur.value, 0n),
0n
),
commission
),
[delegateDeposits, deposits, calcExtraPower]
[delegateDeposits, commission, deposits, calcExtraPower]
);

const handleStake = useCallback(async () => {
Expand Down
33 changes: 28 additions & 5 deletions src/components/power.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { GET_LATEST_STAKING_REWARDS } from "@/config";
import { useApp, useStaking } from "@/hooks";
import { formatBlanace, getChainConfig, prettyNumber } from "@/utils";
import { commissionWeightedPower, formatBlanace, getChainConfig, prettyNumber } from "@/utils";
import { formatDistanceStrict } from "date-fns";
import Image from "next/image";
import { getAddress } from "viem";
import { useAccount } from "wagmi";
import CountLoading from "./count-loading";
import { useRef } from "react";
import { useMemo, useRef } from "react";
import { CSSTransition } from "react-transition-group";
import { useQuery } from "@apollo/client";

Expand Down Expand Up @@ -36,7 +36,16 @@ interface QueryResult {

export default function Power() {
const loadingRef = useRef<HTMLDivElement>(null);
const { power, isLedgersInitialized, isRingPoolInitialized, isKtonPoolInitialized } = useStaking();
const {
power,
nominatorCollators,
collatorCommission,
isNominatorCollatorsInitialized,
isCollatorCommissionInitialized,
isLedgersInitialized,
isRingPoolInitialized,
isKtonPoolInitialized,
} = useStaking();
const { activeChain } = useApp();
const { address } = useAccount();
const { data: rewardData, loading: rewardLoading } = useQuery<QueryResult, QueryVariables>(
Expand All @@ -46,6 +55,16 @@ export default function Power() {
}
);

const thePower = useMemo(() => {
const isCollator =
address && Object.keys(collatorCommission).some((addr) => addr.toLowerCase() === address.toLowerCase())
? true
: false;
const collator = isCollator ? address : address ? nominatorCollators[address]?.at(0) : undefined;
const commission = collator ? collatorCommission[collator] : undefined;
return commissionWeightedPower(power, commission ?? "0.00%");
}, [address, power, collatorCommission, nominatorCollators]);

const chainConfig = getChainConfig(activeChain);

return (
Expand All @@ -56,8 +75,12 @@ export default function Power() {
<Image alt="Icon of Power" src="/images/power.svg" width={30} height={42} />
<span className="text-3xl font-bold text-white">Power</span>
</div>
{isLedgersInitialized && isRingPoolInitialized && isKtonPoolInitialized ? (
<span className="text-3xl font-bold text-white">{prettyNumber(power)}</span>
{isLedgersInitialized &&
isRingPoolInitialized &&
isKtonPoolInitialized &&
isNominatorCollatorsInitialized &&
isCollatorCommissionInitialized ? (
<span className="text-3xl font-bold text-white">{prettyNumber(thePower)}</span>
) : (
<CountLoading color="white" size="large" />
)}
Expand Down
36 changes: 18 additions & 18 deletions src/components/records-bonded-tokens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ export default function RecordsBondedTokens({ row }: { row: StakingRecordsDataSo
</span>
{row.collator.length > 0 && (
<>
<BondMoreRing />
<UnbondRing />
<BondMoreRing commission={row.commission} />
<UnbondRing commission={row.commission} />
</>
)}
</div>
Expand Down Expand Up @@ -155,8 +155,8 @@ export default function RecordsBondedTokens({ row }: { row: StakingRecordsDataSo
</span>
{row.collator.length > 0 && (
<>
<BondMoreDeposit />
<UnbondDeposit />
<BondMoreDeposit commission={row.commission} />
<UnbondDeposit commission={row.commission} />
</>
)}
</div>
Expand All @@ -183,71 +183,71 @@ export default function RecordsBondedTokens({ row }: { row: StakingRecordsDataSo
</span>
{row.collator.length > 0 && (
<>
<BondMoreKton />
<UnbondKton />
<BondMoreKton commission={row.commission} />
<UnbondKton commission={row.commission} />
</>
)}
</div>
</div>
);
}

function BondMoreRing() {
function BondMoreRing({ commission }: { commission: string }) {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<ChangeBondButton action="bond" onClick={() => setIsOpen(true)} />
<BondMoreRingModal isOpen={isOpen} onClose={() => setIsOpen(false)} />
<BondMoreRingModal commission={commission} isOpen={isOpen} onClose={() => setIsOpen(false)} />
</>
);
}

function BondMoreKton() {
function BondMoreKton({ commission }: { commission: string }) {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<ChangeBondButton action="bond" onClick={() => setIsOpen(true)} />
<BondMoreKtonModal isOpen={isOpen} onClose={() => setIsOpen(false)} />
<BondMoreKtonModal commission={commission} isOpen={isOpen} onClose={() => setIsOpen(false)} />
</>
);
}

function BondMoreDeposit() {
function BondMoreDeposit({ commission }: { commission: string }) {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<ChangeBondButton action="bond" onClick={() => setIsOpen(true)} />
<BondMoreDepositModal isOpen={isOpen} onClose={() => setIsOpen(false)} />
<BondMoreDepositModal commission={commission} isOpen={isOpen} onClose={() => setIsOpen(false)} />
</>
);
}

function UnbondRing() {
function UnbondRing({ commission }: { commission: string }) {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<ChangeBondButton action="unbond" onClick={() => setIsOpen(true)} />
<UnbondRingModal isOpen={isOpen} onClose={() => setIsOpen(false)} />
<UnbondRingModal commission={commission} isOpen={isOpen} onClose={() => setIsOpen(false)} />
</>
);
}

function UnbondKton() {
function UnbondKton({ commission }: { commission: string }) {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<ChangeBondButton action="unbond" onClick={() => setIsOpen(true)} />
<UnbondKtonModal isOpen={isOpen} onClose={() => setIsOpen(false)} />
<UnbondKtonModal commission={commission} isOpen={isOpen} onClose={() => setIsOpen(false)} />
</>
);
}

function UnbondDeposit() {
function UnbondDeposit({ commission }: { commission: string }) {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<ChangeBondButton action="unbond" onClick={() => setIsOpen(true)} />
<UnbondDepositModal isOpen={isOpen} onClose={() => setIsOpen(false)} />
<UnbondDepositModal commission={commission} isOpen={isOpen} onClose={() => setIsOpen(false)} />
</>
);
}
Expand Down
Loading

0 comments on commit 8119ab7

Please sign in to comment.