+ {/*
*/}
+
+
+
- )}
-
Total Supply
{
-
- Validators
-
- {validatorSet ? validatorSet.active_validators.length : null}
-
-
-
Next Epoch
@@ -159,7 +153,7 @@ const Stats: FC = () => {
- {dev && (
+ {false && (
<>
{/* @TODO: DUMMY DATA */}
diff --git a/web-app/src/modules/core/routes/Home/Stats/PriceStats.tsx b/web-app/src/modules/core/routes/Home/Stats/PriceStats.tsx
index feef5d2..0b008a1 100644
--- a/web-app/src/modules/core/routes/Home/Stats/PriceStats.tsx
+++ b/web-app/src/modules/core/routes/Home/Stats/PriceStats.tsx
@@ -7,6 +7,9 @@ import { OL_COINGECKO_URL } from '../../../../../contants';
import CoingeckoLogo from '../../../../assets/images/coingecko.png';
const PriceStats: FC = () => {
+
+ const dev = location.search.includes('dev=true');
+
const priceIsIncreasing = true;
const upIcon = (
@@ -63,41 +66,47 @@ const PriceStats: FC = () => {
{/* @TODO: DUMMY DATA */}
-
- $0.00000
- {priceIsIncreasing ? upIcon : downIcon}
-
- 2.57%
-
-
- {/* @TODO: DUMMY DATA */}
-
-
- Marketcap
- $000,000,000
-
-
-
Trading Volume (24hrs)
-
$000,000
+ {dev && (
+
+ $0.00000
+ {priceIsIncreasing ? upIcon : downIcon}
+
+ 2.57%
+
-
+ )}
{/* @TODO: DUMMY DATA */}
-
-
- Marketcap
- $000,000,000
-
-
- Trading Volume (24hrs)
- $000,000
-
-
+ {dev && (
+ <>
+
+
+ Marketcap
+ $000,000,000
+
+
+ Trading Volume (24hrs)
+ $000,000
+
+
+ {/* @TODO: DUMMY DATA */}
+
+
+ Marketcap
+ $000,000,000
+
+
+ Trading Volume (24hrs)
+ $000,000
+
+
+ >
+ )}
);
};
diff --git a/web-app/src/modules/core/routes/Test/MessageForm.tsx b/web-app/src/modules/core/routes/Test/MessageForm.tsx
deleted file mode 100644
index 6c9ae5f..0000000
--- a/web-app/src/modules/core/routes/Test/MessageForm.tsx
+++ /dev/null
@@ -1,120 +0,0 @@
-import { FC, useState } from "react";
-import {
- AptosAccount, BCS, TxnBuilderTypes,
- HexString,
-} from "aptos";
-
-import useAptos from "../../../aptos";
-import axios from "axios";
-import { sha3_256 as sha3Hash } from "@noble/hashes/sha3";
-
-const {
- AccountAddress,
- EntryFunction,
- TransactionPayloadEntryFunction,
- RawTransaction,
- ChainId,
- TransactionAuthenticatorEd25519,
- Ed25519PublicKey,
- Ed25519Signature,
- SignedTransaction
-} = TxnBuilderTypes;
-
-const MessageForm: FC = () => {
- const aptos = useAptos();
- const [message, setMessage] = useState('');
-
- const onSubmit = async (event: React.FormEvent
) => {
- event.preventDefault();
-
- const entryFunctionPayload = new TransactionPayloadEntryFunction(
- EntryFunction.natural(
- // Fully qualified module name, `AccountAddress::ModuleName`
- "0x00000000000000000000000000000000d0383924341821f9e43a6cff46f0a74e::message",
- // Module function
- "set_message",
- // The coin type to transfer
- [],
- // Arguments for function `transfer`: receiver account address and amount to transfer
- [
- BCS.bcsSerializeStr(message)
- ],
- ),
- );
-
- const chainId = await aptos.getChainId();
-
- const walletAddress = 'D0383924341821F9E43A6CFF46F0A74E';
- const account = await aptos.getAccount(walletAddress);
-
- const rawTxn = new RawTransaction(
- // Transaction sender account address
- AccountAddress.fromHex(walletAddress),
-
- BigInt(account.sequence_number),
- entryFunctionPayload,
- // Max gas unit to spend
- BigInt(2000000),
- // Gas price per unit
- BigInt(200),
- // Expiration timestamp. Transaction is discarded if it is not executed within 10 seconds from now.
- BigInt(Math.floor(Date.now() / 1000) + 10),
- // BigInt(1699656761),
- new ChainId(chainId),
- );
-
- const privateKey = new HexString("0x60b9b1bcc7f9af9011d7fb26466cb00fd35a21db22f373f085b3bc0604aca78c");
-
- const signer = new AptosAccount(privateKey.toUint8Array());
-
- const hash = sha3Hash.create();
- hash.update("DIEM::RawTransaction");
- const prefix = hash.digest();
- const body = BCS.bcsToBytes(rawTxn);
- const mergedArray = new Uint8Array(prefix.length + body.length);
- mergedArray.set(prefix);
- mergedArray.set(body, prefix.length);
-
- const signingMessage = mergedArray;
-
- const signature = signer.signBuffer(signingMessage);
- const sig = new Ed25519Signature(signature.toUint8Array());
-
- const authenticator = new TransactionAuthenticatorEd25519(
- new Ed25519PublicKey(signer.pubKey().toUint8Array()),
- sig
- );
- const signedTx = new SignedTransaction(rawTxn, authenticator);
-
- const bcsTxn = BCS.bcsToBytes(signedTx);
-
- const res = await axios({
- method: 'POST',
- url: 'https://rpc.0l.fyi./v1/transactions',
- headers: {
- "content-type": "application/x.diem.signed_transaction+bcs",
- },
- data: bcsTxn,
- });
- console.log(res);
- };
-
- return (
-
-
Set Message
-
-
- );
-};
-
-export default MessageForm;
\ No newline at end of file
diff --git a/web-app/src/modules/core/routes/Test/Test.tsx b/web-app/src/modules/core/routes/Test/Test.tsx
deleted file mode 100644
index 977bf9a..0000000
--- a/web-app/src/modules/core/routes/Test/Test.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import { FC, useEffect, useState } from "react";
-import useAptos from "../../../aptos";
-import MessageForm from "./MessageForm";
-
-const Test: FC = () => {
- const [message, setMessage] = useState('');
- const aptos = useAptos();
-
- useEffect(() => {
- const load = async () => {
- const res = await aptos.getAccountResource(
- '0xD0383924341821F9E43A6CFF46F0A74E', '0xD0383924341821F9E43A6CFF46F0A74E::message::MessageHolder');
- console.log(res);
- setMessage((res.data as any).message);
- };
- load();
- }, []);
-
- return (
-
-
Test
-
{`message = ${message}`}
-
-
-
-
- );
-};
-
-export default Test;
diff --git a/web-app/src/modules/core/routes/Test/index.ts b/web-app/src/modules/core/routes/Test/index.ts
deleted file mode 100644
index ef09c7b..0000000
--- a/web-app/src/modules/core/routes/Test/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from "./Test";
diff --git a/web-app/src/modules/core/routes/Validators/Validators.tsx b/web-app/src/modules/core/routes/Validators/Validators.tsx
index 9c47b5b..b413630 100644
--- a/web-app/src/modules/core/routes/Validators/Validators.tsx
+++ b/web-app/src/modules/core/routes/Validators/Validators.tsx
@@ -1,8 +1,10 @@
import { FC } from 'react';
import { gql, useQuery } from '@apollo/client';
+
import Page from '../../../ui/Page';
import ValidatorsTable from './components/ValidatorsTable';
import ValidatorsStats from './components/ValidatorsStats';
+import { IValidator } from '../../../interface/Validator.interface';
const GET_VALIDATORS = gql`
query GetValidators {
@@ -37,36 +39,13 @@ const GET_VALIDATORS = gql`
const Validators: FC = () => {
const { data, error } = useQuery<{
- validators: {
- address: string;
- inSet: boolean;
- index: number;
- votingPower: number;
- account: {
- balance: number;
- slowWallet: {
- unlocked: number;
- } | null;
- };
- vouches: {
- epoch: number;
- }[];
- grade: {
- compliant: boolean;
- failedBlocks: number;
- proposedBlocks: number;
- };
- currentBid: {
- currentBid: number;
- expirationEpoch: number;
- };
- }[];
+ validators: IValidator[];
}>(GET_VALIDATORS);
if (error) {
console.log('error', error);
return (
-
+
{`Error: ${error.message}`}
);
@@ -83,8 +62,6 @@ const Validators: FC = () => {
);
-
- return null;
};
export default Validators;
diff --git a/web-app/src/modules/core/routes/Validators/components/ValidatorsStats.tsx b/web-app/src/modules/core/routes/Validators/components/ValidatorsStats.tsx
index 8065e51..bc4b747 100644
--- a/web-app/src/modules/core/routes/Validators/components/ValidatorsStats.tsx
+++ b/web-app/src/modules/core/routes/Validators/components/ValidatorsStats.tsx
@@ -1,7 +1,8 @@
import { FC } from 'react';
-import { IValidator } from '../../../../interface/Validator.interface';
+
import Money from '../../../../ui/Money';
import StatsCard from '../../../../ui/StatsCard';
+import { IValidator } from '../../../../interface/Validator.interface';
interface ValidatorsStatsProps {
validators?: IValidator[];
diff --git a/web-app/src/modules/core/routes/Validators/components/ValidatorsTable.tsx b/web-app/src/modules/core/routes/Validators/components/ValidatorsTable.tsx
index 1a5e2ca..b737408 100644
--- a/web-app/src/modules/core/routes/Validators/components/ValidatorsTable.tsx
+++ b/web-app/src/modules/core/routes/Validators/components/ValidatorsTable.tsx
@@ -196,11 +196,7 @@ const ValidatorsTable: FC = ({ validators }) => {
{cumulativeValidators
? cumulativeValidators.map((validator) => (
-
+
))
: Array.from({ length: 10 }).map((_, index) => (
diff --git a/web-app/src/modules/interface/Validator.interface.ts b/web-app/src/modules/interface/Validator.interface.ts
index f9ba36d..bb6f1de 100644
--- a/web-app/src/modules/interface/Validator.interface.ts
+++ b/web-app/src/modules/interface/Validator.interface.ts
@@ -4,9 +4,9 @@ export interface IValidator {
index: number;
votingPower: number;
account: {
- balance: number;
+ balance: string;
slowWallet: {
- unlocked: number;
+ unlocked: string;
} | null;
};
vouches: {
diff --git a/web-app/src/modules/ui/AccountAddress/AccountAddress.tsx b/web-app/src/modules/ui/AccountAddress/AccountAddress.tsx
index 8a0348f..d28dac3 100644
--- a/web-app/src/modules/ui/AccountAddress/AccountAddress.tsx
+++ b/web-app/src/modules/ui/AccountAddress/AccountAddress.tsx
@@ -27,7 +27,9 @@ const AccountAddress: FC = ({ address }) => {
return (
-
+
= ({ address }) => {
- const canvasRef = useRef
(null);
-
- // Function to convert hexadecimal to binary
- const hexToBinary = (hex: string): string => {
- return hex.split('').reduce((binary, hexChar) => {
- return binary + parseInt(hexChar, 16).toString(2).padStart(4, '0');
- }, '');
- };
-
- // Function to generate an avatar 16x16 from a hexadecimal address
- const generateAvatar = (hexAddress: string) => {
- const binaryData = hexToBinary(hexAddress);
- const canvas = canvasRef.current;
- if (canvas) {
- const ctx = canvas.getContext('2d');
- if (ctx) {
- // Base colors determined by the first 4 characters of the address
- const baseColors = [
- parseInt(hexAddress[0], 16),
- parseInt(hexAddress[1], 16),
- parseInt(hexAddress[2], 16),
- parseInt(hexAddress[3], 16),
- ];
-
- // Color palette (example colors, can be customized)
- const colors = [
- '#FF0000',
- '#00FF00',
- '#0000FF',
- '#FFFF00', // Red, Green, Blue, Yellow
- '#FF00FF',
- '#00FFFF',
- '#FFFFFF',
- '#000000', // Magenta, Cyan, White, Black
- ];
-
- // Map base colors to the color palette
- const selectedColors = baseColors.map((baseColor) => colors[baseColor % colors.length]);
-
- // Use the rest of the address to determine the color shades
- for (let y = 0; y < 8; y++) {
- for (let x = 0; x < 8; x++) {
- const index = (y * 8 + x) * 2;
- const bit = binaryData.slice(index, index + 2);
- const colorIndex = parseInt(bit, 2) % selectedColors.length;
- const color = selectedColors[colorIndex];
- ctx.fillStyle = color;
- ctx.fillRect(x * 2, y * 2, 2, 2); // Each color block is 2x2 pixels
- }
- }
- }
- }
- };
-
- useEffect(() => {
- if (address) {
- generateAvatar(address);
- }
+ const icon = useMemo(() => {
+ return createIcon({
+ seed: address,
+ size: 8,
+ scale: 2,
+ }).toDataURL();
}, [address]);
-
- return (
-
-
-
- );
+ return ;
};
export default AddressAvatar;
diff --git a/web-app/src/modules/ui/AddressAvatar/blockies.ts b/web-app/src/modules/ui/AddressAvatar/blockies.ts
new file mode 100644
index 0000000..29937ea
--- /dev/null
+++ b/web-app/src/modules/ui/AddressAvatar/blockies.ts
@@ -0,0 +1,121 @@
+// Copied from https://github.com/download13/blockies/blob/master/src/blockies.mjs
+
+// The random number is a js implementation of the Xorshift PRNG
+const randseed = new Array(4); // Xorshift: [x, y, z, w] 32 bit values
+
+interface Options {
+ seed: string;
+ size: number;
+ scale: number;
+ color: string;
+ bgcolor: string;
+ spotcolor: string;
+}
+
+function seedrand(seed: string) {
+ randseed.fill(0);
+
+ for (let i = 0; i < seed.length; i++) {
+ randseed[i % 4] = (randseed[i % 4] << 5) - randseed[i % 4] + seed.charCodeAt(i);
+ }
+}
+
+function rand() {
+ // based on Java's String.hashCode(), expanded to 4 32bit values
+ const t = randseed[0] ^ (randseed[0] << 11);
+
+ randseed[0] = randseed[1];
+ randseed[1] = randseed[2];
+ randseed[2] = randseed[3];
+ randseed[3] = randseed[3] ^ (randseed[3] >> 19) ^ t ^ (t >> 8);
+
+ return (randseed[3] >>> 0) / ((1 << 31) >>> 0);
+}
+
+function createColor(): string {
+ //saturation is the whole color spectrum
+ const h = Math.floor(rand() * 360);
+ //saturation goes from 40 to 100, it avoids greyish colors
+ const s = rand() * 60 + 40 + '%';
+ //lightness can be anything from 0 to 100, but probabilities are a bell curve around 50%
+ const l = (rand() + rand() + rand() + rand()) * 25 + '%';
+
+ return `hsl(${h},${s},${l})`;
+}
+
+function createImageData(size: number) {
+ const width = size; // Only support square icons for now
+ const height = size;
+
+ const dataWidth = Math.ceil(width / 2);
+ const mirrorWidth = width - dataWidth;
+
+ const data = [];
+ for (let y = 0; y < height; y++) {
+ let row = [];
+ for (let x = 0; x < dataWidth; x++) {
+ // this makes foreground and background color to have a 43% (1/2.3) probability
+ // spot color has 13% chance
+ row[x] = Math.floor(rand() * 2.3);
+ }
+ const r = row.slice(0, mirrorWidth);
+ r.reverse();
+ row = row.concat(r);
+
+ for (let i = 0; i < row.length; i++) {
+ data.push(row[i]);
+ }
+ }
+
+ return data;
+}
+
+function buildOpts(opts: Partial): Options {
+ const newOpts = {
+ size: opts.size || 8,
+ scale: opts.scale || 4,
+ color: opts.color || createColor(),
+ bgcolor: opts.bgcolor || createColor(),
+ spotcolor: opts.spotcolor || createColor(),
+ seed: opts.seed || Math.floor(Math.random() * Math.pow(10, 16)).toString(16),
+ };
+
+ seedrand(newOpts.seed);
+
+ return newOpts;
+}
+
+export function renderIcon(options: Partial, canvas: HTMLCanvasElement) {
+ let opts = buildOpts(options);
+
+ const imageData = createImageData(opts.size);
+ const width = Math.sqrt(imageData.length);
+
+ canvas.width = canvas.height = opts.size * opts.scale;
+
+ const cc = canvas.getContext('2d')!;
+ cc.fillStyle = opts.bgcolor;
+ cc.fillRect(0, 0, canvas.width, canvas.height);
+ cc.fillStyle = opts.color;
+
+ for (let i = 0; i < imageData.length; i++) {
+ // if data is 0, leave the background
+ if (imageData[i]) {
+ const row = Math.floor(i / width);
+ const col = i % width;
+
+ // if data is 2, choose spot color, if 1 choose foreground
+ cc.fillStyle = imageData[i] == 1 ? opts.color : opts.spotcolor;
+
+ cc.fillRect(col * opts.scale, row * opts.scale, opts.scale, opts.scale);
+ }
+ }
+
+ return canvas;
+}
+
+export function createIcon(opts: Partial) {
+ const canvas = document.createElement('canvas');
+ renderIcon(opts, canvas);
+ return canvas;
+}
diff --git a/web-app/src/modules/ui/Layout/Footer/Footer.tsx b/web-app/src/modules/ui/Layout/Footer/Footer.tsx
index 98c2126..4941986 100644
--- a/web-app/src/modules/ui/Layout/Footer/Footer.tsx
+++ b/web-app/src/modules/ui/Layout/Footer/Footer.tsx
@@ -1,7 +1,5 @@
import React from 'react';
-import { Link } from 'react-router-dom';
-import Logo from '../../Logo/Logo';
-import { SOCIAL_LINKS } from '../../../../contants';
+import Logo from '../../Logo';
const CI_COMMIT_SHA: string = import.meta.env.VITE_CI_COMMIT_SHA;
@@ -17,33 +15,90 @@ const Footer: React.FC = () => {
Join the most open, transparent and community driven network today.
-
Join our discord
-
+
- © {new Date().getFullYear()} 0L Network. All rights reserved.
+ © 2024 0L Network. All rights reserved.
- {CI_COMMIT_SHA}
- {Object.keys(SOCIAL_LINKS).map((socialKey) => {
- const socialLink = SOCIAL_LINKS[socialKey];
- return (
-
- {socialLink.logoSvg}
-
- );
- })}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/web-app/src/modules/ui/Logo/index.ts b/web-app/src/modules/ui/Logo/index.ts
new file mode 100644
index 0000000..f252704
--- /dev/null
+++ b/web-app/src/modules/ui/Logo/index.ts
@@ -0,0 +1 @@
+export { default } from "./Logo";
diff --git a/web-app/src/modules/ui/NodeMap/NodeMap.tsx b/web-app/src/modules/ui/NodeMap/NodeMap.tsx
index 564e715..dc83efc 100644
--- a/web-app/src/modules/ui/NodeMap/NodeMap.tsx
+++ b/web-app/src/modules/ui/NodeMap/NodeMap.tsx
@@ -76,6 +76,7 @@ function NodeMap(): ReactNode {
left: point[0] - 5,
width: 6,
height: 6,
+ borderRadius: 2,
}}
/>
))}
diff --git a/web-app/src/modules/ui/Page/Page.tsx b/web-app/src/modules/ui/Page/Page.tsx
index 1306391..6a5848e 100644
--- a/web-app/src/modules/ui/Page/Page.tsx
+++ b/web-app/src/modules/ui/Page/Page.tsx
@@ -1,13 +1,12 @@
-import clsx from 'clsx';
import { FC, PropsWithChildren, ReactNode } from 'react';
+import clsx from 'clsx';
type Props = PropsWithChildren<{
title?: string | ReactNode;
__deprecated_grayBg?: boolean;
- mainClassName?: string;
}>;
-const Page: FC = ({ title, children, __deprecated_grayBg: grayBg, mainClassName = '' }) => {
+const Page: FC = ({ title, children, __deprecated_grayBg: grayBg }) => {
return (
<>
{title && (
@@ -24,13 +23,7 @@ const Page: FC = ({ title, children, __deprecated_grayBg: grayBg, mainCla
)}
-