Skip to content

Commit

Permalink
[frenemies] Optimize + offline (MystenLabs#8201)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jordan-Mysten authored Feb 9, 2023
1 parent 8cc013d commit c3fc012
Show file tree
Hide file tree
Showing 17 changed files with 271 additions and 193 deletions.
29 changes: 12 additions & 17 deletions dapps/frenemies/src/components/Assignment/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import { useWalletKit } from "@mysten/wallet-kit";
import { useScorecard } from "../../network/queries/scorecard";
import { useSuiSystem } from "../../network/queries/sui-system";
import { convertToString, useValidators } from "../../network/queries/sui-system";
import { Goal } from "../../network/types";
import { formatBalance } from "../../utils/format";
import { Card } from "../Card";
Expand Down Expand Up @@ -33,16 +33,15 @@ function getIsInRank(goal: Goal, index: number) {

export function Assignment() {
const { currentAccount } = useWalletKit();
const { data: system } = useSuiSystem();
const { data: validators } = useValidators();
const { data: scorecard } = useScorecard(currentAccount);

const unsortedValidators = system?.validators.fields.active_validators;

const sortedValidators = unsortedValidators
? [...unsortedValidators].sort((a, b) =>
const sortedValidators = validators
? [...validators].sort((a, b) =>
Number(
BigInt(b.fields.voting_power || "0") -
BigInt(a.fields.voting_power || "0")
BigInt(b.next_epoch_stake) +
BigInt(b.next_epoch_delegation) -
(BigInt(a.next_epoch_stake) + BigInt(a.next_epoch_delegation))
)
)
: null;
Expand All @@ -52,10 +51,7 @@ export function Assignment() {
if (!assignment) return null;

const assignedValidatorIndex = sortedValidators?.findIndex((validator) => {
return (
validator.fields.metadata.fields.sui_address.replace("0x", "") ===
assignment.validator
);
return validator.sui_address.replace("0x", "") === assignment.validator;
});

const assignedValidator =
Expand All @@ -65,10 +61,9 @@ export function Assignment() {

if (!assignedValidator) return null;

const name = assignedValidator.fields.metadata.fields.name as string;
const selfStake = BigInt(assignedValidator.fields.metadata.fields.next_epoch_stake);
const delegatedStake =
BigInt(assignedValidator.fields.metadata.fields.next_epoch_delegation);
const name = convertToString(assignedValidator.name);
const selfStake = BigInt(assignedValidator.next_epoch_stake);
const delegatedStake = BigInt(assignedValidator.next_epoch_delegation);
const totalStake = selfStake + delegatedStake;

const isInRank = getIsInRank(assignment.goal, assignedValidatorIndex!);
Expand Down Expand Up @@ -108,7 +103,7 @@ export function Assignment() {

{/* TODO: Validate copy states: */}
<div className="mt-1 max-w-xs text-steel-dark text-p1">
Move your Validator to the assigned rank by allocating Sui Stake
Move your Validator to the assigned rank by allocating SUI Stake
to them.
</div>
</div>
Expand Down
47 changes: 47 additions & 0 deletions dapps/frenemies/src/components/TimeRemaining.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { useEffect, useState } from "react";
import { useEpoch } from "../network/queries/epoch";
import { formatTimeRemaining } from "../utils/format";
import { Stat } from "./Stat";


/**
* Calculate time left until the next epoch based on the last two timestamps
* for epoch changes (`timestamp` and `prevTimestamp`).
*/
function getTime(timestamp?: number, prevTimestamp?: number): number | null {
if (!timestamp || !prevTimestamp) return null;

const prevEpochLength = timestamp - prevTimestamp;
const timePassed = Date.now() - timestamp;
const timeLeft = prevEpochLength - timePassed;
return timeLeft <= 0 ? 0 : timeLeft;
}

export function TimeRemaining() {
const { data: epoch } = useEpoch();

const [timer, setTime] = useState(() =>
getTime(epoch?.timestamp, epoch?.prevTimestamp)
);

useEffect(() => {
if (!epoch) return;

const interval = setInterval(
() => setTime(getTime(epoch.timestamp, epoch.prevTimestamp)),
1000
);
return () => clearInterval(interval);
}, [epoch]);

return (
<Stat label="Time Remaining">
<div className="text-steel-dark font-light">
{formatTimeRemaining(timer || 0)}
</div>
</Stat>
);
}
25 changes: 11 additions & 14 deletions dapps/frenemies/src/components/Validators/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import { useWalletKit } from "@mysten/wallet-kit";
import { useMyType } from "../../network/queries/use-raw";
import { GridItem } from "./GridItem";
import { ValidatorItem } from "./Validator";
import { MoveActiveValidator, normalizeSuiAddress } from "@mysten/sui.js";
import { normalizeSuiAddress } from "@mysten/sui.js";
import { useValidators } from "../../network/queries/sui-system";

function Header({ children }: { children: ReactNode }) {
return (
Expand All @@ -23,26 +24,22 @@ function Header({ children }: { children: ReactNode }) {
);
}

interface Props {
/** Set of 40 currently active validators */
validators: MoveActiveValidator[];
}

export function Table({ validators }: Props) {
export function Table() {
const { currentAccount } = useWalletKit();
const { data: stakes } = useMyType<StakedSui>(STAKED_SUI, currentAccount);
const { data: delegations } = useMyType<Delegation>(
DELEGATION,
currentAccount
);

const { data: validators } = useValidators();

// sort validators by their live stake info in DESC order
const sorted = [...validators].sort((a, b) =>
const sorted = [...(validators || [])].sort((a, b) =>
Number(
BigInt(b.fields.metadata.fields.next_epoch_stake) +
BigInt(b.fields.metadata.fields.next_epoch_delegation) -
(BigInt(a.fields.metadata.fields.next_epoch_stake) +
BigInt(a.fields.metadata.fields.next_epoch_delegation))
BigInt(b.next_epoch_stake) +
BigInt(b.next_epoch_delegation) -
(BigInt(a.next_epoch_stake) + BigInt(a.next_epoch_delegation))
)
);

Expand All @@ -69,13 +66,13 @@ export function Table({ validators }: Props) {
<GridItem className="px-5 py-4">
<Header>Rank</Header>
<Header>Validator</Header>
<Header>Your Sui Stake</Header>
<Header>Your SUI Stake</Header>
</GridItem>

<div className="flex flex-col gap-1">
{sorted.map((validator, index) => {
const address = normalizeSuiAddress(
validator.fields.metadata.fields.sui_address
validator.sui_address
);

return (
Expand Down
29 changes: 15 additions & 14 deletions dapps/frenemies/src/components/Validators/Validator.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { MoveActiveValidator } from "@mysten/sui.js";
import { ValidatorMetaData } from "@mysten/sui.js";
import { useWalletKit } from "@mysten/wallet-kit";
import clsx from "clsx";
import { FormEvent, useState } from "react";
import { useScorecard } from "../../network/queries/scorecard";
import { convertToString } from "../../network/queries/sui-system";
import { ObjectData } from "../../network/rawObject";
import { Delegation, StakedSui } from "../../network/types";
import { formatBalance } from "../../utils/format";
Expand All @@ -18,7 +19,7 @@ import { Target } from "./Target";

interface Props {
index: number;
validator: MoveActiveValidator;
validator: ValidatorMetaData;
stake: ObjectData<StakedSui>;
delegation?: ObjectData<Delegation>;
}
Expand All @@ -28,17 +29,14 @@ const DEC = 9;
export function ValidatorItem({ index, validator, stake, delegation }: Props) {
const { currentAccount } = useWalletKit();
const { data: scorecard } = useScorecard(currentAccount);
const metadata = validator.fields.metadata.fields;
const [amount, setAmount] = useState("");

const onInputAmount = (evt: FormEvent<HTMLInputElement>) => {
setAmount(evt.currentTarget.value);
};

const delegatedStake = BigInt(
validator.fields.metadata.fields.next_epoch_delegation
);
const selfStake = BigInt(validator.fields.metadata.fields.next_epoch_stake);
const delegatedStake = BigInt(validator.next_epoch_delegation);
const selfStake = BigInt(validator.next_epoch_stake);
const totalStake = selfStake + delegatedStake;

return (
Expand All @@ -50,20 +48,20 @@ export function ValidatorItem({ index, validator, stake, delegation }: Props) {
: "bg-[#F5FAFA]"
)}
>
<div>{index + 1}</div>
<div id={`validator-${validator.sui_address}`}>{index + 1}</div>
<div className="flex items-center gap-2.5">
<div>
<Logo
size="md"
src={metadata.image_url as string}
fallback={metadata.name as string}
label={metadata.name as string}
src={convertToString(validator.image_url)}
fallback={convertToString(validator.name) || ""}
label={convertToString(validator.name) || ""}
circle
/>
</div>
<div className="space-y-0.5">
<div className="text-gray-90 text-body font-semibold">
{metadata.name}
{convertToString(validator.name)}
</div>
<div>
<span className="text-gray-90 font-semibold text-body">
Expand Down Expand Up @@ -102,13 +100,16 @@ export function ValidatorItem({ index, validator, stake, delegation }: Props) {
) : stake ? (
<CancelDelegation stake={stake} />
) : (
<AddDelegation validator={metadata.sui_address} amount={amount} />
<AddDelegation
validator={validator.sui_address}
amount={amount}
/>
)}
</div>
</div>
</div>

{metadata.sui_address.replace("0x", "") ===
{validator.sui_address.replace("0x", "") ===
scorecard?.data.assignment.validator && (
<Target goal={scorecard.data.assignment.goal} />
)}
Expand Down
11 changes: 5 additions & 6 deletions dapps/frenemies/src/components/Validators/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import { useWalletKit } from "@mysten/wallet-kit";
import { useScorecard } from "../../network/queries/scorecard";
import { useSuiSystem } from "../../network/queries/sui-system";
import { formatGoal } from "../../utils/format";
import { Goal } from "../../network/types";
import { Balance } from "./Balance";
Expand All @@ -12,15 +11,13 @@ import { Card } from "../Card";

export function Validators({ hasAssignment }: { hasAssignment: boolean }) {
const { currentAccount } = useWalletKit();
const { data: system } = useSuiSystem();
const { data: scorecard } = useScorecard(currentAccount);

// At this point there's no way it errors out.
if (!system || !currentAccount) {
if (!currentAccount) {
return null;
}

const validators = system.validators.fields.active_validators;
const assignment = scorecard?.data.assignment;

return (
Expand All @@ -32,11 +29,13 @@ export function Validators({ hasAssignment }: { hasAssignment: boolean }) {
{assignment.goal === Goal.Enemy ? "an " : "a "}
<span className="font-bold">{formatGoal(assignment.goal)}</span>.
</h2>
): <div />}
) : (
<div />
)}

<Balance />
</div>
<Table validators={validators} />
<Table />
</Card>
);
}
1 change: 1 addition & 0 deletions dapps/frenemies/src/components/leaderboard/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const Cell = ({
);

export function Table({ data }: Props) {
console.log(data.topScores);
return (
<div className="overflow-y-scroll max-h-60">
<table className="table-fixed w-full">
Expand Down
8 changes: 4 additions & 4 deletions dapps/frenemies/src/components/round/Round.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import { config } from "../../config";
import { useSuiSystem } from "../../network/queries/sui-system";
import { useEpoch } from "../../network/queries/epoch";
import { useRawObject } from "../../network/queries/use-raw";
import { LEADERBOARD, Leaderboard } from "../../network/types";

Expand All @@ -13,17 +13,17 @@ import { LEADERBOARD, Leaderboard } from "../../network/types";
* minus the start round for the Frenemies game.
*/
export function Round() {
const { data: system } = useSuiSystem();
const { data: epoch } = useEpoch();
const { data: leaderboard } = useRawObject<Leaderboard>(
config.VITE_LEADERBOARD,
LEADERBOARD
);

if (!system || !leaderboard) {
if (!epoch || !leaderboard) {
return null;
}

const round = BigInt(system.epoch) - leaderboard.data.startEpoch;
const round = BigInt(epoch.epoch) - leaderboard.data.startEpoch;

return (
<h2 className="uppercase text-steel-dark font-thin text-6xl sm:text-8xl md:text-9xl lg:text-9xl xl:text-[160px] leading-tight text-center tracking-widest">
Expand Down
Loading

0 comments on commit c3fc012

Please sign in to comment.