Skip to content

Commit

Permalink
[wip] frenemies layout (MystenLabs#7339)
Browse files Browse the repository at this point in the history
  • Loading branch information
damirka authored Jan 19, 2023
1 parent 89d2141 commit 9741bc3
Show file tree
Hide file tree
Showing 25 changed files with 576 additions and 4 deletions.
13 changes: 13 additions & 0 deletions dapps/frenemies/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Example environment setting for the application.

# package ID
VITE_PKG=

# user registry object ID
VITE_REGISTRY=

# leaderboard object ID
VITE_LEADERBOARD=

# rpc to use (default http://localhost:9000/)
VITE_RPC=
1 change: 1 addition & 0 deletions dapps/frenemies/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"@fontsource/inter": "^4.5.14",
"@headlessui/react": "^1.7.7",
"@hookform/resolvers": "^2.9.10",
"@mysten/core": "workspace:*",
"@mysten/sui.js": "workspace:*",
"@mysten/wallet-kit": "workspace:*",
"@tanstack/react-query": "^4.22.0",
Expand Down
20 changes: 20 additions & 0 deletions dapps/frenemies/src/components/Layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import Header from "./header/Header";
import Footer from "./footer/Footer";
import { ReactElement } from "react";

function Layout({ children }: { children: ReactElement | ReactElement[] }) {
return (
<div className="container">
<Header />
<div className="mx-auto max-w-4xl container">
{children}
</div>
<Footer />
</div>
);
}

export default Layout;
19 changes: 19 additions & 0 deletions dapps/frenemies/src/components/block/Block.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

/**
* Round number.
*
* Requires reading the SuiSystem object to get current epoch
* minus the start round for the Frenemies game.
*/
function Block({ title, value }: { title: string, value: string }) {
return (
<div className="card flex-auto py-4 px-6 text-left">
<p>{title}</p>
<p>{value}</p>
</div>
);
}

export default Block;
14 changes: 14 additions & 0 deletions dapps/frenemies/src/components/footer/Footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

function Footer() {
return (
<footer className="container fixed bottom-0 w-full py-10 text-center">
<p className="text-center">
This is a footer, Mysten 2022
</p>
</footer>
);
}

export default Footer;
24 changes: 24 additions & 0 deletions dapps/frenemies/src/components/header/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { ConnectButton } from '@mysten/wallet-kit';

function Header() {
return (
<header className="py-5 bg-blue-700">
<div className="mx-auto flex h-full items-end px-5">
{/* Title + Description */}
<div className="h-full w-auto">
<h1 className="mx-1">Sui Frenemies</h1>
</div>

{/* Connect button on the right */}
<div className="w-full align-middle text-right">
<ConnectButton />
</div>
</div>
</header>
);
}

export default Header;
22 changes: 22 additions & 0 deletions dapps/frenemies/src/components/leaderboard/Leaderboard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import Row from './Row';
import TableHeader from "./TableHeader";
import type { Leaderboard as LeaderboardType } from '../../network/types';

/**
* Table representing a Leaderboard
*/
function Leaderboard({ board }: { board: LeaderboardType}) {
return (
<div className="leaderboard w-auto">
<table className="table-fixed w-auto">
<TableHeader />
{board.topScores.map((score) => <Row score={score} />)}
</table>
</div>
);
}

export default Leaderboard;
20 changes: 20 additions & 0 deletions dapps/frenemies/src/components/leaderboard/Row.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { Score } from "../../network/types";

/**
* A Single row in the Leaderboard table.
* Tightly coupled with the Leaderboard component.
*/
function Row({ score }: { score: Score }) {
return (
<tr>
<td>{ score.name }</td>
<td>{ score.score }</td>
<td>{ score.participation }</td>
</tr>
)
}

export default Row;
14 changes: 14 additions & 0 deletions dapps/frenemies/src/components/leaderboard/TableHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

function TableHeader() {
return (
<tr>
<th>Name</th>
<th>Score</th>
<th>Participation</th>
</tr>
);
}

export default TableHeader;
21 changes: 21 additions & 0 deletions dapps/frenemies/src/components/my-results/MyResults.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import Row, { Record } from './Row';
import TableHeader from "./TableHeader";

/**
* Table representing game score for the user.
*/
function MyResults({ records }: { records: Record[] }) {
return (
<div className="w-auto">
<table className="table-fixed w-auto">
<TableHeader />
{records.map((record) => <Row record={record} />)}
</table>
</div>
);
}

export default MyResults;
35 changes: 35 additions & 0 deletions dapps/frenemies/src/components/my-results/Row.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { SuiAddress } from "@mysten/sui.js";
import { formatAddress } from "./../../utils/format";

/**
* Leaderboard record.
*/
export type Record = {
round: number;
// todo: this should probably be a more general enum
role: "enemy" | "neutral" | "friend";
validator: SuiAddress;
objectiveAchieved: boolean;
score: number;
};

/**
* A Single row in the Leaderboard table.
* Tightly coupled with the Leaderboard component.
*/
function Row({ record }: { record: Record }) {
return (
<tr>
<td>{ record.round }</td>
<td>{ record.role }</td>
<td>{ formatAddress(record.validator) }</td>
<td>{ record.objectiveAchieved ? "Achieved" : "Failed" }</td>
<td>{ record.score > 0 ? ("+" + record.score) : record.score }</td>
</tr>
)
}

export default Row;
17 changes: 17 additions & 0 deletions dapps/frenemies/src/components/my-results/TableHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

function TableHeader() {
return (
<tr>
<th>Round</th>
<th>Role</th>
<th>Assigned Validator</th>
<th>Assigned Validator</th>
<th>Objective</th>
<th>Score</th>
</tr>
);
}

export default TableHeader;
18 changes: 18 additions & 0 deletions dapps/frenemies/src/components/round/Round.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

/**
* Round number.
*
* Requires reading the SuiSystem object to get current epoch
* minus the start round for the Frenemies game.
*/
function Round({ num }: { num: number }) {
return (
<div className="py-10">
<h2 className="round text-center">ROUND {num}</h2>
</div>
);
}

export default Round;
26 changes: 26 additions & 0 deletions dapps/frenemies/src/index.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,29 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

body {
background: #A0B6C3;
/* mix-blend-mode: saturation; */
}

.leaderboard {
background: linear-gradient(180deg, #768AF7 0%, #97A7FF 100%);
border-radius: 16px;
}

.card {
background: rgba(255, 255, 255, 0.9);
border-radius: 16px;
margin: 0 5px;
}

.round {
font-family: 'Inter', 'Helvetica Neue';
font-style: normal;
font-weight: 100;
font-size: 130px;
line-height: 194px;
text-align: center;
letter-spacing: 0.1em;
}
54 changes: 54 additions & 0 deletions dapps/frenemies/src/network/bcs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

/**
* Provides BCS schema for the used Move types.
* @module network/bcs
*/

import { bcs } from "@mysten/sui.js";

bcs.registerStructType('frenemies::Assignment', {
validator: 'address',
goal: 'u8',
epoch: 'u64'
});

bcs.registerStructType('frenemies::Scorecard', {
id: 'address',
name: 'string',
assignment: 'frenemies::Assignment',
score: 'u16',
participation: 'u16',
epoch: 'u64'
});

bcs.registerStructType('frenemies::ScorecardUpdateEvent', {
player: 'string',
assignment: 'frenemies::Assignment',
totalScore: 'u16',
epochScore: 'u16',
});

bcs.registerStructType('leaderboard::Leaderboard', {
id: 'address',
topScores: 'vector<Score>',
prevEpochStakes: 'table::Table',
epoch: 'u64',
startEpoch: 'u64'
});

bcs.registerStructType('leaderboard::Score', {
name: 'string',
score: 'u16',
participation: 'u16'
});

// This type only contains utility data;
// Other fields (based on generics) are attached as dynamic fields.
bcs.registerStructType('table::Table', {
id: 'address',
size: 'u64'
});

export default bcs;
9 changes: 9 additions & 0 deletions dapps/frenemies/src/network/provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { JsonRpcProvider, Network } from "@mysten/sui.js";

const rpc: string | Network = import.meta.env.VITE_RPC || Network.LOCAL;
const provider = new JsonRpcProvider(rpc);

export default provider;
21 changes: 21 additions & 0 deletions dapps/frenemies/src/network/queries/leaderboard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { Leaderboard } from "../types";
import { getRawObject, ObjectData } from "../rawObject";
import provider from "../provider";
import bcs from "../bcs";

/**
* Get a shared Leaderboard object's data.
* Its objectId should always be known and set in the environment.
*/
export async function getLeaderboard(objectId: string): Promise<ObjectData<Leaderboard> | null> {
const objectData = await getRawObject(provider, objectId);
const { reference, data: { bcs_bytes } } = objectData.details;

return {
reference,
data: bcs.de('leaderboard::Leaderboard', bcs_bytes, 'base64')
};
}
Loading

0 comments on commit 9741bc3

Please sign in to comment.