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

Commit

Permalink
Adapt kton staking with isStakingV2
Browse files Browse the repository at this point in the history
  • Loading branch information
JayJay1024 committed Mar 14, 2024
1 parent 458179f commit de81198
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 28 deletions.
70 changes: 67 additions & 3 deletions src/components/bond-more-kton-modal.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,82 @@
import { getChainConfig } from "@/utils";
import { commissionWeightedPower, getChainConfig, notifyTransaction } from "@/utils";
import BondMoreTokenModal from "./bond-more-token-modal";
import { useApp } from "@/hooks";
import { useApp, useStaking } from "@/hooks";
import { useAccount, useBalance, usePublicClient, useWalletClient } from "wagmi";
import { useCallback, useState } from "react";
import { notification } from "./notification";

export default function BondMoreKtonModal({
commission,
isOpen,
onClose = () => undefined,
}: {
commission: string;
isOpen: boolean;
onClose?: () => void;
}) {
const { activeChain } = useApp();
const { address } = useAccount();
const { isStakingV2, calcExtraPower } = useStaking();

const { data: walletClient } = useWalletClient();
const publicClient = usePublicClient();

const [inputAmount, setInputAmount] = useState(0n);
const [busy, setBusy] = useState(false);

const { ktonToken } = getChainConfig(activeChain);
const { data: ktonBalance } = useBalance({ address, token: ktonToken?.address, query: { refetchInterval: 3000 } });

const handleBond = useCallback(async () => {
if ((ktonBalance?.value || 0n) < inputAmount) {
notification.warn({ description: "Your balance is insufficient." });
} else if (walletClient && publicClient) {
setBusy(true);
const { contract, explorer } = getChainConfig(activeChain);

try {
const abi = isStakingV2
? (await import("@/config/abi/staking-v2.json")).default
: (await import("@/config/abi/staking.json")).default;

const hash = await walletClient.writeContract({
address: contract.staking.address,
abi,
functionName: "stake",
args: [0n, inputAmount, []],
});
const receipt = await publicClient.waitForTransactionReceipt({ hash });

if (receipt.status === "success") {
setInputAmount(0n);
onClose();
}
notifyTransaction(receipt, explorer);
} catch (err) {
console.error(err);
notification.error({ description: (err as Error).message });
}

setBusy(false);
}
}, [activeChain, inputAmount, ktonBalance?.value, isStakingV2, walletClient, publicClient, onClose]);

return (
ktonToken && <BondMoreTokenModal isOpen={isOpen} symbol={ktonToken.symbol} onClose={onClose} onCancel={onClose} />
ktonToken && (
<BondMoreTokenModal
isOpen={isOpen}
symbol={ktonToken.symbol}
decimals={ktonToken.decimals}
power={commissionWeightedPower(calcExtraPower(0n, inputAmount), commission)}
balance={ktonBalance?.value || 0n}
busy={busy}
disabled={inputAmount <= 0n}
isReset={inputAmount <= 0}
onClose={onClose}
onBond={handleBond}
onCancel={onClose}
onChange={setInputAmount}
/>
)
);
}
58 changes: 47 additions & 11 deletions src/components/bond-more-token-modal.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,72 @@
import { useStaking } from "@/hooks";
import BalanceInput from "./balance-input";
import Modal from "./modal";

export default function BondMoreTokenModal({
isOpen,
symbol,
decimals,
balance,
power,
busy,
disabled,
isReset,
onCancel = () => undefined,
onBond = () => undefined,
onClose = () => undefined,
onChange = () => undefined,
}: {
isOpen: boolean;
symbol: string;
decimals: number;
balance: bigint;
power: bigint;
busy?: boolean;
disabled?: boolean;
isReset?: boolean;
onCancel?: () => void;
onBond?: () => void;
onClose?: () => void;
onChange?: (amount: bigint) => void;
}) {
const { isStakingV2 } = useStaking();
return (
<Modal
title={`Bond More ${symbol}`}
isOpen={isOpen}
onCancel={onCancel}
onClose={onClose}
onOk={isStakingV2 ? undefined : onBond}
maskClosable={false}
okText="Bond"
className="lg:w-[25rem]"
busy={busy}
disabled={disabled}
>
<div className="flex flex-col gap-small text-xs font-bold lg:text-sm lg:font-light">
<span className="text-white">{`Please stake ${symbol} in`}</span>
<a
href="https://kton-staking.darwinia.network/"
rel="noopener noreferrer"
target="_blank"
className="text-primary underline transition-opacity hover:opacity-80"
>
https://kton-staking.darwinia.network
</a>
</div>
{isStakingV2 ? (
<div className="flex flex-col gap-small text-xs font-bold lg:text-sm lg:font-light">
<span className="text-white">{`Please stake ${symbol} in`}</span>
<a
href="https://kton-staking.darwinia.network/"
rel="noopener noreferrer"
target="_blank"
className="text-primary underline transition-opacity hover:opacity-80"
>
https://kton-staking.darwinia.network
</a>
</div>
) : (
<BalanceInput
label="Amount"
boldLabel
decimals={decimals}
symbol={symbol}
balance={balance}
power={power}
isReset={isReset}
onChange={onChange}
/>
)}
</Modal>
);
}
26 changes: 22 additions & 4 deletions src/components/collator-selector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Jazzicon from "./jazzicon";
import Image from "next/image";
import CollatorSelectModal from "./collator-select-modal";
import { useCallback, useState } from "react";
import { useAccountName } from "@/hooks";
import { useAccountName, useStaking } from "@/hooks";
import { toShortAdrress } from "@/utils";

interface Props {
Expand All @@ -12,6 +12,7 @@ interface Props {

export default function CollatorSelector({ collator, onSelect }: Props) {
const [isOpen, setIsOpen] = useState(false);
const { isStakingV2 } = useStaking();

const handleConfirm = useCallback(
(collator: string) => {
Expand All @@ -24,7 +25,11 @@ export default function CollatorSelector({ collator, onSelect }: Props) {
return (
<>
{collator ? (
<div className="flex h-10 items-center gap-middle border border-white px-large transition-opacity">
<div
className={`flex items-center gap-middle border px-large transition-opacity ${
isStakingV2 ? "h-10 border-white" : "border-primary py-middle"
}`}
>
<Collator collator={collator} />
<button
className="shrink-0 transition-transform hover:scale-105 active:scale-95"
Expand All @@ -35,7 +40,9 @@ export default function CollatorSelector({ collator, onSelect }: Props) {
</div>
) : (
<button
className="h-10 border border-white text-sm font-light text-white transition-opacity hover:opacity-80 active:opacity-60"
className={`border text-sm text-white transition-opacity hover:opacity-80 active:opacity-60 ${
isStakingV2 ? "h-10 border-white font-light" : "border-primary py-middle font-bold"
}`}
onClick={() => setIsOpen(true)}
>
Select a collator
Expand All @@ -49,13 +56,24 @@ export default function CollatorSelector({ collator, onSelect }: Props) {

function Collator({ collator }: { collator: string }) {
const { accountName } = useAccountName(collator);
const { isStakingV2 } = useStaking();

return (
return isStakingV2 ? (
<>
<Jazzicon address={collator} size={22} />
<span className="truncate text-sm font-bold text-white">
{accountName === collator ? toShortAdrress(collator) : accountName}
</span>
</>
) : (
<>
<Jazzicon address={collator} size={30} />
<div className="flex min-w-0 flex-col gap-small">
<span className="text-sm font-bold text-white">
{accountName === collator ? toShortAdrress(collator) : accountName}
</span>
<span className="break-words text-xs font-light text-white">{collator}</span>
</div>
</>
);
}
37 changes: 32 additions & 5 deletions src/components/do-stake.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { notification } from "./notification";

export default function DoStake() {
const {
isStakingV2,
deposits,
nominatorCollators,
collatorCommission,
Expand All @@ -26,12 +27,13 @@ export default function DoStake() {
const [busy, setBusy] = useState(false);

const { activeChain } = useApp();
const { nativeToken, explorer } = getChainConfig(activeChain);
const { nativeToken, ktonToken, explorer } = getChainConfig(activeChain);

const publicClient = usePublicClient();
const { data: walletClient } = useWalletClient();
const { address } = useAccount();
const { data: ringBalance } = useBalance({ address, query: { refetchInterval: 3000 } });
const { data: ktonBalance } = useBalance({ address, query: { refetchInterval: 3000 }, token: ktonToken?.address });

const commission = useMemo(() => {
return (delegateCollator && collatorCommission[delegateCollator]) || "0.00%";
Expand All @@ -41,6 +43,10 @@ export default function DoStake() {
() => commissionWeightedPower(calcExtraPower(delegateRing, 0n), commission),
[commission, delegateRing, calcExtraPower]
);
const ktonExtraPower = useMemo(
() => commissionWeightedPower(calcExtraPower(0n, delegateKton), commission),
[commission, delegateKton, calcExtraPower]
);
const depositsExtraPower = useMemo(
() =>
commissionWeightedPower(
Expand Down Expand Up @@ -109,6 +115,9 @@ export default function DoStake() {

<div className="h-[1px] bg-white/20" />

{/* collator */}
{!isStakingV2 && <CollatorSelector collator={delegateCollator} onSelect={setDelegateCollator} />}

<div className="flex flex-col gap-middle lg:flex-row">
{/* ring */}
<BalanceInput
Expand All @@ -122,17 +131,35 @@ export default function DoStake() {
isReset={delegateRing <= 0}
/>

{/* kton */}
{ktonToken && !isStakingV2 && (
<>
<BalanceInput
balance={ktonBalance?.value || 0n}
symbol={ktonToken.symbol}
logoPath={ktonToken.logoPath}
decimals={ktonToken.decimals}
power={ktonExtraPower}
className="lg:flex-1"
onChange={setDelegateKton}
isReset={delegateKton <= 0}
/>
</>
)}

{/* active deposit */}
<div className="flex flex-col gap-middle lg:flex-1">
<ActiveDepositSelector checkedDeposits={delegateDeposits} onChange={setDelegateDeposits} />
<ExtraPower power={depositsExtraPower} />
</div>

{/* collator */}
<div className="flex flex-col gap-middle lg:flex-1">
<CollatorSelector collator={delegateCollator} onSelect={setDelegateCollator} />
<ExtraPower power={0n} className="invisible" />
</div>
{isStakingV2 && (
<div className="flex flex-col gap-middle lg:flex-1">
<CollatorSelector collator={delegateCollator} onSelect={setDelegateCollator} />
<ExtraPower power={0n} className="invisible" />
</div>
)}
</div>

<div className="h-[1px] bg-white/20" />
Expand Down
6 changes: 3 additions & 3 deletions src/components/records-bonded-tokens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ export default function RecordsBondedTokens({ row }: { row: StakingRecordsDataSo
</span>
{row.collator.length > 0 && (
<>
<BondMoreKton />
<BondMoreKton commission={row.commission} />
<UnbondKton commission={row.commission} />
</>
)}
Expand All @@ -211,12 +211,12 @@ function BondMoreRing({ commission }: { commission: string }) {
);
}

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)} />
</>
);
}
Expand Down
9 changes: 7 additions & 2 deletions src/components/unbond-token-modal.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useStaking } from "@/hooks";
import BalanceInput from "./balance-input";
import Modal from "./modal";

Expand Down Expand Up @@ -28,6 +29,8 @@ export default function UnbondTokenModal({
onClose?: () => void;
onChange?: (amount: bigint) => void;
}) {
const { isStakingV2 } = useStaking();

return (
<Modal
title={`Unbond ${symbol}`}
Expand All @@ -42,10 +45,12 @@ export default function UnbondTokenModal({
disabled={disabled}
>
<>
<p className="text-xs font-light text-white line-through">
<p className={`text-xs font-light text-white ${isStakingV2 ? "line-through" : ""}`}>
This unbonding process will take 14 days to complete.
</p>
<p className="text-xs font-light text-white">{`There is no longer a 14-day period for unbonding ${symbol}.`}</p>
{isStakingV2 && (
<p className="text-xs font-light text-white">{`There is no longer a 14-day period for unbonding ${symbol}.`}</p>
)}
<div className="h-[1px] bg-white/20" />
<BalanceInput
label="Amount"
Expand Down

0 comments on commit de81198

Please sign in to comment.