From b8b625e8bf9f43d8d7f6823fc80d6b246c1757a9 Mon Sep 17 00:00:00 2001 From: Steven Yi Date: Mon, 30 Sep 2024 17:24:18 -0400 Subject: [PATCH 01/14] fix: ArNS assessment pass evaluation should check dataHashDigest and status code match with reference gateway --- src/utils/observations.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/utils/observations.ts b/src/utils/observations.ts index 159cd407..85454977 100644 --- a/src/utils/observations.ts +++ b/src/utils/observations.ts @@ -107,7 +107,9 @@ const assessArNSName = async ( expectedStatusCode: referenceRes.statusCode, pass: referenceRes.resolvedId === gatewayRes?.resolvedId && - referenceRes.resolvedId !== null, + referenceRes.resolvedId !== null && + referenceRes.dataHashDigest == gatewayRes?.dataHashDigest && + referenceRes.statusCode == gatewayRes?.statusCode, resolvedDataHash: gatewayRes?.dataHashDigest ?? '', resolvedId: gatewayRes?.resolvedId ?? '', resolvedStatusCode: gatewayRes?.statusCode ?? 0, From 028a862a39bba03348a2ac5009b4b5a799dacaaf Mon Sep 17 00:00:00 2001 From: Steven Yi Date: Tue, 1 Oct 2024 13:56:08 -0400 Subject: [PATCH 02/14] feat: add version number to app UI --- .vscode/settings.json | 3 +- package.json | 2 +- src/layout/Sidebar.tsx | 8 +- yarn.lock | 2820 ++++++++++++++++++++-------------------- 4 files changed, 1420 insertions(+), 1413 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index d5d00188..430048d0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,4 @@ { - "files.insertFinalNewline": true + "files.insertFinalNewline": true, + "npm.packageManager": "yarn" } diff --git a/package.json b/package.json index acb6866b..a4794e37 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@ar-io/network-portal", "private": true, - "version": "0.0.0", + "version": "1.0.0", "type": "module", "scripts": { "build": "yarn clean && tsc --build tsconfig.build.json && NODE_OPTIONS=--max-old-space-size=32768 vite build", diff --git a/src/layout/Sidebar.tsx b/src/layout/Sidebar.tsx index ae00f33a..4c6f8b6a 100644 --- a/src/layout/Sidebar.tsx +++ b/src/layout/Sidebar.tsx @@ -106,8 +106,14 @@ const Sidebar = () => {
+ {sidebarOpen && ( +
+ v{process.env.npm_package_version}- + {process.env.VITE_GITHUB_HASH?.slice(0, 6)} +
+ )}
{blockHeight ? blockHeight.toLocaleString('en-US') : NBSP}
-
- ARWEAVE BLOCK -
+
ARWEAVE BLOCK
{gatewaysLoading ? ( - + ) : gateways ? ( - Object.values(gateways).filter((g) => g.status === "joined").length + Object.values(gateways).filter((g) => g.status === 'joined').length ) : ( NBSP )}
-
- TOTAL GATEWAYS +
TOTAL GATEWAYS
+
+ +
+
+ {protocolBalance == undefined ? ( + + ) : ( +
+ {formatWithCommas(new mIOToken(protocolBalance).toIO().valueOf())} {ticker} +
+ )}
+
TOTAL PROTOCOL BALANCE
diff --git a/src/pages/Staking/ConnectedLandingPage.tsx b/src/pages/Staking/ConnectedLandingPage.tsx index 44015697..356372f2 100644 --- a/src/pages/Staking/ConnectedLandingPage.tsx +++ b/src/pages/Staking/ConnectedLandingPage.tsx @@ -3,7 +3,6 @@ import Placeholder from '@src/components/Placeholder'; import { PinkArrowIcon } from '@src/components/icons'; import StakingModal from '@src/components/modals/StakingModal'; import useGateways from '@src/hooks/useGateways'; -import useProtocolBalance from '@src/hooks/useProtocolBalance'; import { useGlobalState } from '@src/store'; import { formatWithCommas } from '@src/utils'; import { useEffect, useState } from 'react'; @@ -17,7 +16,6 @@ const ConnectedLandingPage = () => { const [isStakingModalOpen, setIsStakingModalOpen] = useState(false); - const { data: protocolBalance } = useProtocolBalance(); const { data: gateways } = useGateways(); const balances = useGlobalState((state) => state.balances); @@ -35,13 +33,6 @@ const ConnectedLandingPage = () => { }, [gateways, walletAddress]); const topPanels = [ - { - title: 'Total Protocol Balance', - balance: - protocolBalance !== undefined - ? formatWithCommas(new mIOToken(protocolBalance).toIO().valueOf()) - : undefined, - }, { title: 'Your Balance', balance: formatWithCommas(balances.io), @@ -57,7 +48,7 @@ const ConnectedLandingPage = () => { return (
-
+
{topPanels.map((panel, index) => (
Date: Tue, 1 Oct 2024 16:52:17 -0400 Subject: [PATCH 04/14] feat: remove CTA quick stake button and add as smaller button to Active Stake table --- src/pages/Staking/ActiveStakes.tsx | 23 +++++++++++++++----- src/pages/Staking/ConnectedLandingPage.tsx | 25 ---------------------- 2 files changed, 18 insertions(+), 30 deletions(-) diff --git a/src/pages/Staking/ActiveStakes.tsx b/src/pages/Staking/ActiveStakes.tsx index c2e0b8a9..e0d23991 100644 --- a/src/pages/Staking/ActiveStakes.tsx +++ b/src/pages/Staking/ActiveStakes.tsx @@ -22,7 +22,7 @@ const columnHelper = createColumnHelper(); const ActiveStakes = () => { const walletAddress = useGlobalState((state) => state.walletAddress); - const ticker = useGlobalState((state) => state.ticker); + const ticker = useGlobalState((state) => state.ticker); const { isLoading, data: gateways } = useGateways(); const [activeStakes, setActiveStakes] = useState>([]); @@ -30,6 +30,7 @@ const ActiveStakes = () => { const [showUnstakeAllModal, setShowUnstakeAllModal] = useState(false); const [stakingModalWalletAddress, setStakingModalWalletAddress] = useState(); + const [showQuickStake, setShowQuickStake] = useState(false); const navigate = useNavigate(); @@ -74,7 +75,7 @@ const ActiveStakes = () => { href={`https://${row.getValue('domain')}`} target="_blank" rel="noreferrer" - onClick={(e) => e.stopPropagation()} + onClick={(e) => e.stopPropagation()} > {row.getValue('domain')} {' '} @@ -133,9 +134,10 @@ const ActiveStakes = () => { const hasDelegatedStake = activeStakes?.some((v) => v.delegatedStake > 0) ?? false; + console.log(activeStakes); return (
-
+
Active Stakes
{hasDelegatedStake && (
{ onClose={() => setShowUnstakeAllModal(false)} /> )} - {stakingModalWalletAddress && ( + {(stakingModalWalletAddress || showQuickStake) && ( setStakingModalWalletAddress(undefined)} + onClose={() => { + setStakingModalWalletAddress(undefined); + setShowQuickStake(false); + }} ownerWallet={stakingModalWalletAddress} /> )} diff --git a/src/pages/Staking/ConnectedLandingPage.tsx b/src/pages/Staking/ConnectedLandingPage.tsx index 356372f2..741fefad 100644 --- a/src/pages/Staking/ConnectedLandingPage.tsx +++ b/src/pages/Staking/ConnectedLandingPage.tsx @@ -1,6 +1,5 @@ import { mIOToken } from '@ar.io/sdk/web'; import Placeholder from '@src/components/Placeholder'; -import { PinkArrowIcon } from '@src/components/icons'; import StakingModal from '@src/components/modals/StakingModal'; import useGateways from '@src/hooks/useGateways'; import { useGlobalState } from '@src/store'; @@ -64,30 +63,6 @@ const ConnectedLandingPage = () => {
))}
- - {isStakingModalOpen && ( From c1ebb180a943b557a1500e2d5113b6972fdcd900 Mon Sep 17 00:00:00 2001 From: Steven Yi Date: Tue, 1 Oct 2024 17:20:52 -0400 Subject: [PATCH 05/14] feat: remove time from Join Date column on Gateways page --- src/hooks/useGatewayInfo.ts | 4 ++-- src/pages/Gateway/index.tsx | 4 ++-- src/pages/Observe/ObservationsTable.tsx | 4 ++-- src/pages/Report/ReportHeader.tsx | 4 ++-- src/pages/Reports/ReportsTable.tsx | 4 ++-- src/utils/index.ts | 11 ++++++++++- 6 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/hooks/useGatewayInfo.ts b/src/hooks/useGatewayInfo.ts index 99dd5061..b9ff6047 100644 --- a/src/hooks/useGatewayInfo.ts +++ b/src/hooks/useGatewayInfo.ts @@ -1,6 +1,6 @@ import { mIOToken } from '@ar.io/sdk/web'; import { useGlobalState } from '@src/store'; -import { formatDate, formatWalletAddress, formatWithCommas } from '@src/utils'; +import { formatDateTime, formatWalletAddress, formatWithCommas } from '@src/utils'; import useGateway from './useGateway'; export enum GatewayStatus { @@ -26,7 +26,7 @@ export const useGatewayInfo = () => { `${gateway.settings.protocol}://${gateway.settings.fqdn}:${gateway.settings.port}`, ], ['Observer Wallet', formatWalletAddress(gateway.observerAddress)], - ['Joined at', formatDate(new Date(gateway.startTimestamp))], + ['Joined at', formatDateTime(new Date(gateway.startTimestamp))], [ `Stake (${ticker})`, formatWithCommas(new mIOToken(gateway.operatorStake).toIO().valueOf()), diff --git a/src/pages/Gateway/index.tsx b/src/pages/Gateway/index.tsx index 6b1b2c49..58b9e249 100644 --- a/src/pages/Gateway/index.tsx +++ b/src/pages/Gateway/index.tsx @@ -34,7 +34,7 @@ import useGateways from '@src/hooks/useGateways'; import useHealthcheck from '@src/hooks/useHealthCheck'; import useProtocolBalance from '@src/hooks/useProtocolBalance'; import { useGlobalState } from '@src/store'; -import { formatDate } from '@src/utils'; +import { formatDateTime } from '@src/utils'; import { calculateOperatorRewards } from '@src/utils/rewards'; import { showErrorToast } from '@src/utils/toast'; import { useQueryClient } from '@tanstack/react-query'; @@ -424,7 +424,7 @@ const Gateway = () => { title="Join Date" value={ gateway?.startTimestamp - ? formatDate(new Date(gateway?.startTimestamp)) + ? formatDateTime(new Date(gateway?.startTimestamp)) : undefined } /> diff --git a/src/pages/Observe/ObservationsTable.tsx b/src/pages/Observe/ObservationsTable.tsx index 91d33767..b5d58b1f 100644 --- a/src/pages/Observe/ObservationsTable.tsx +++ b/src/pages/Observe/ObservationsTable.tsx @@ -2,7 +2,7 @@ import Bubble from '@src/components/Bubble'; import TableView from '@src/components/TableView'; import { observationsDB } from '@src/store/observationsDB'; import { Assessment } from '@src/types'; -import { formatDate } from '@src/utils'; +import { formatDateTime } from '@src/utils'; import { ColumnDef, createColumnHelper } from '@tanstack/react-table'; import { useLiveQuery } from 'dexie-react-hooks'; import { useEffect, useState } from 'react'; @@ -64,7 +64,7 @@ const ObservationsTable = ({ id: 'timestamp', header: 'Timestamp', sortDescFirst: true, - cell: ({ row }) => formatDate(new Date(row.original.timestamp)), + cell: ({ row }) => formatDateTime(new Date(row.original.timestamp)), }), columnHelper.accessor('arnsNames', { id: 'arnsNames', diff --git a/src/pages/Report/ReportHeader.tsx b/src/pages/Report/ReportHeader.tsx index ba70cb8b..c04b0ad8 100644 --- a/src/pages/Report/ReportHeader.tsx +++ b/src/pages/Report/ReportHeader.tsx @@ -3,7 +3,7 @@ import Placeholder from '@src/components/Placeholder'; import Profile from '@src/components/Profile'; import { HeaderSeparatorIcon, ReportsIcon } from '@src/components/icons'; import { ReportData } from '@src/types'; -import { formatDate } from '@src/utils'; +import { formatDateTime } from '@src/utils'; import { Link, useParams } from 'react-router-dom'; const ReportHeader = ({ @@ -66,7 +66,7 @@ const ReportHeader = ({ )}
Generated At:
{reportData ? ( -
{formatDate(new Date(reportData.epochStartTimestamp))}
+
{formatDateTime(new Date(reportData.epochStartTimestamp))}
) : ( )} diff --git a/src/pages/Reports/ReportsTable.tsx b/src/pages/Reports/ReportsTable.tsx index 9f566e4c..8aad090a 100644 --- a/src/pages/Reports/ReportsTable.tsx +++ b/src/pages/Reports/ReportsTable.tsx @@ -2,7 +2,7 @@ import { AoGateway } from '@ar.io/sdk'; import Placeholder from '@src/components/Placeholder'; import TableView from '@src/components/TableView'; import useReports, { ReportTransactionData } from '@src/hooks/useReports'; -import { formatDate } from '@src/utils'; +import { formatDateTime } from '@src/utils'; import { ColumnDef, createColumnHelper } from '@tanstack/react-table'; import { useNavigate } from 'react-router-dom'; @@ -36,7 +36,7 @@ const ReportsTable = ({ id: 'generatedAt', header: 'Generated At', sortDescFirst: false, - cell: ({ row }) => formatDate(new Date(row.original.timestamp)), + cell: ({ row }) => formatDateTime(new Date(row.original.timestamp)), }), columnHelper.accessor('size', { id: 'size', diff --git a/src/utils/index.ts b/src/utils/index.ts index e4ea0354..78c13b25 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -56,12 +56,21 @@ export const formatAddress = (address: string) => { )}`; }; -/** Convert Date object to format of YYYY-MM-DD HH:MM:SS AM/PM */ +/** Convert Date object to format of YYYY-MM-DD */ export function formatDate(date: Date): string { const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); // Months are 0-indexed const day = String(date.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; +} + +/** Convert Date object to format of YYYY-MM-DD HH:MM:SS AM/PM */ +export function formatDateTime(date: Date): string { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); // Months are 0-indexed + const day = String(date.getDate()).padStart(2, '0'); + let hours = date.getHours(); const minutes = String(date.getMinutes()).padStart(2, '0'); const seconds = String(date.getSeconds()).padStart(2, '0'); From 78607f1b11d3d15d025d47d127844bc8e2884b43 Mon Sep 17 00:00:00 2001 From: Steven Yi Date: Wed, 2 Oct 2024 10:26:49 -0400 Subject: [PATCH 06/14] chore: remove "Total" from header items --- src/components/Header.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 81fb69d2..9aa48c2c 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -41,7 +41,7 @@ const Header = () => { NBSP )}
-
TOTAL GATEWAYS
+
GATEWAYS
@@ -54,7 +54,7 @@ const Header = () => {
)}
-
TOTAL PROTOCOL BALANCE
+
PROTOCOL BALANCE
From 20d51a1e2a2f439d5c55680422e9cadfe8d34b0c Mon Sep 17 00:00:00 2001 From: Steven Yi Date: Wed, 2 Oct 2024 10:39:45 -0400 Subject: [PATCH 07/14] Update src/pages/Staking/ActiveStakes.tsx Co-authored-by: Dylan Fiedler --- src/pages/Staking/ActiveStakes.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/Staking/ActiveStakes.tsx b/src/pages/Staking/ActiveStakes.tsx index e0d23991..64b29f23 100644 --- a/src/pages/Staking/ActiveStakes.tsx +++ b/src/pages/Staking/ActiveStakes.tsx @@ -134,7 +134,6 @@ const ActiveStakes = () => { const hasDelegatedStake = activeStakes?.some((v) => v.delegatedStake > 0) ?? false; - console.log(activeStakes); return (
From 06c7d9078109f1fa0535286a67997f4838671e5e Mon Sep 17 00:00:00 2001 From: Steven Yi Date: Wed, 2 Oct 2024 11:48:23 -0400 Subject: [PATCH 08/14] feat: updated to use warning triangle icon for unstaking callout --- src/components/icons/index.ts | 2 ++ src/components/icons/warning_triangle.svg | 9 +++++++++ src/components/modals/UnstakeWarning.tsx | 4 ++-- 3 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 src/components/icons/warning_triangle.svg diff --git a/src/components/icons/index.ts b/src/components/icons/index.ts index 74f73121..aa94ebd9 100644 --- a/src/components/icons/index.ts +++ b/src/components/icons/index.ts @@ -45,6 +45,7 @@ import TimerIcon from './timer.svg?react'; import ToastCloseIcon from './toast_close.svg?react'; import WalletIcon from './wallet.svg?react'; import WarningIcon from './warning.svg?react'; +import WarningTriangleIcon from './warning_triangle.svg?react'; export { ArConnectIcon, @@ -93,4 +94,5 @@ export { ToastCloseIcon, WalletIcon, WarningIcon, + WarningTriangleIcon, }; diff --git a/src/components/icons/warning_triangle.svg b/src/components/icons/warning_triangle.svg new file mode 100644 index 00000000..8f7b1666 --- /dev/null +++ b/src/components/icons/warning_triangle.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/components/modals/UnstakeWarning.tsx b/src/components/modals/UnstakeWarning.tsx index 375108ab..26b5696b 100644 --- a/src/components/modals/UnstakeWarning.tsx +++ b/src/components/modals/UnstakeWarning.tsx @@ -1,10 +1,10 @@ -import { WarningIcon } from '../icons'; +import { WarningTriangleIcon } from '../icons'; const UnstakeWarning = () => { return (
- +
30 days is the standard unstaking period. During this withdrawal time your tokens will be locked and will not be accruing rewards. From c3ae83f2988093e4f4a5eb3906d8302085bf3347 Mon Sep 17 00:00:00 2001 From: Steven Yi Date: Wed, 2 Oct 2024 11:54:15 -0400 Subject: [PATCH 09/14] feat: reduce vertical padding in places to get more of modal to fit on screen without scrolling --- src/components/modals/StakingModal.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/modals/StakingModal.tsx b/src/components/modals/StakingModal.tsx index 910fc259..b99c50f8 100644 --- a/src/components/modals/StakingModal.tsx +++ b/src/components/modals/StakingModal.tsx @@ -158,7 +158,7 @@ const StakingModal = ({ ? balances.io - parseFloat(amountToStake) : '-'; - const baseTabClassName = 'text-center py-6'; + const baseTabClassName = 'text-center py-3'; const selectedTabClassNames = `${baseTabClassName} bg-grey-700 border-b border-red-400`; const nonSelectedTabClassNames = `${baseTabClassName} bg-grey-1000 text-low`; @@ -250,7 +250,7 @@ const StakingModal = ({ Unstaking
-
+
Gateway Owner:
{ownerWallet ? (
From 3e49af3221a3da7d1c1df019d03dbfa237d76bf5 Mon Sep 17 00:00:00 2001 From: Steven Yi Date: Wed, 2 Oct 2024 15:49:35 -0400 Subject: [PATCH 10/14] feat: change withdraw all button to use red gradient --- src/index.css | 3 +++ src/pages/Staking/ActiveStakes.tsx | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/index.css b/src/index.css index f5d03324..b6e7b3d3 100644 --- a/src/index.css +++ b/src/index.css @@ -12,4 +12,7 @@ .text-gradient { @apply bg-gradient-to-r from-gradient-primary-start to-gradient-primary-end bg-clip-text text-transparent; } + .text-gradient-red { + @apply bg-gradient-to-r from-gradient-red-start to-gradient-red-end bg-clip-text text-transparent; + } } diff --git a/src/pages/Staking/ActiveStakes.tsx b/src/pages/Staking/ActiveStakes.tsx index 64b29f23..d64eec41 100644 --- a/src/pages/Staking/ActiveStakes.tsx +++ b/src/pages/Staking/ActiveStakes.tsx @@ -141,7 +141,7 @@ const ActiveStakes = () => { {hasDelegatedStake && (
} > - + } /> From 3f4661a699972f40bb75a2ed272f3ea77f0365fe Mon Sep 17 00:00:00 2001 From: Steven Yi Date: Wed, 2 Oct 2024 15:56:34 -0400 Subject: [PATCH 12/14] feat: adjusted version string and drawer icon colors --- src/components/icons/close_drawer.svg | 6 +++--- src/components/icons/open_drawer.svg | 6 +++--- src/layout/Sidebar.tsx | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/icons/close_drawer.svg b/src/components/icons/close_drawer.svg index 32b8df1c..c8681909 100644 --- a/src/components/icons/close_drawer.svg +++ b/src/components/icons/close_drawer.svg @@ -1,7 +1,7 @@ - - - + + + diff --git a/src/components/icons/open_drawer.svg b/src/components/icons/open_drawer.svg index aebdca60..3a09a15a 100644 --- a/src/components/icons/open_drawer.svg +++ b/src/components/icons/open_drawer.svg @@ -1,7 +1,7 @@ - - - + + + diff --git a/src/layout/Sidebar.tsx b/src/layout/Sidebar.tsx index 4c6f8b6a..65688f2e 100644 --- a/src/layout/Sidebar.tsx +++ b/src/layout/Sidebar.tsx @@ -109,14 +109,14 @@ const Sidebar = () => { className={sidebarOpen ? 'flex items-center justify-end' : 'flex items-center justify-center'} > {sidebarOpen && ( -
+
v{process.env.npm_package_version}- {process.env.VITE_GITHUB_HASH?.slice(0, 6)}
)}
); }, }), @@ -136,7 +138,7 @@ const ActiveStakes = () => { return (
-
+
Active Stakes
{hasDelegatedStake && (
Date: Fri, 4 Oct 2024 10:29:38 -0400 Subject: [PATCH 14/14] fix: ensure for number range that value is not empty string --- src/components/forms/validation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/forms/validation.ts b/src/components/forms/validation.ts index 0e19e8f0..220ccc98 100644 --- a/src/components/forms/validation.ts +++ b/src/components/forms/validation.ts @@ -80,7 +80,7 @@ export const validateNumberRange = ( return (v: string) => { const value = +v; - return value < min || value > max || isNaN(value) + return v.length == 0 || value < min || value > max || isNaN(value) ? `${propertyName} must be a number from ${min} to ${max}.` : undefined; };