diff --git a/.changeset/large-drinks-carry.md b/.changeset/large-drinks-carry.md new file mode 100644 index 000000000..b023f3981 --- /dev/null +++ b/.changeset/large-drinks-carry.md @@ -0,0 +1,5 @@ +--- +'website': minor +--- + +Binary downloads are now the latest stable version. diff --git a/.changeset/quick-cobras-cross.md b/.changeset/quick-cobras-cross.md new file mode 100644 index 000000000..9652a510d --- /dev/null +++ b/.changeset/quick-cobras-cross.md @@ -0,0 +1,5 @@ +--- +'explorer': minor +--- + +The explorer now shows average prices on the home page. diff --git a/.changeset/witty-eggs-fail.md b/.changeset/witty-eggs-fail.md index 6581572c3..f5508ee93 100644 --- a/.changeset/witty-eggs-fail.md +++ b/.changeset/witty-eggs-fail.md @@ -2,4 +2,4 @@ 'explorer': minor --- -The explorer has been revamped and not supports searching for and viewing hosts. +The explorer has been revamped and now supports searching for and viewing hosts. diff --git a/apps/explorer/app/host/[id]/opengraph-image.tsx b/apps/explorer/app/host/[id]/opengraph-image.tsx index 4e315f7c4..da9873b6c 100644 --- a/apps/explorer/app/host/[id]/opengraph-image.tsx +++ b/apps/explorer/app/host/[id]/opengraph-image.tsx @@ -41,15 +41,24 @@ export default async function Image({ params }) { const values = [ { label: 'storage', - value: getStorageCost({ host: h.host, rates: r.rates }), + value: getStorageCost({ + price: h.host.settings.storage_price, + rates: r.rates, + }), }, { label: 'download', - value: getDownloadCost({ host: h.host, rates: r.rates }), + value: getDownloadCost({ + price: h.host.settings.download_price, + rates: r.rates, + }), }, { label: 'upload', - value: getUploadCost({ host: h.host, rates: r.rates }), + value: getUploadCost({ + price: h.host.settings.upload_price, + rates: r.rates, + }), }, ] diff --git a/apps/explorer/app/layout.tsx b/apps/explorer/app/layout.tsx index 49ebf1ae0..df195194d 100644 --- a/apps/explorer/app/layout.tsx +++ b/apps/explorer/app/layout.tsx @@ -2,6 +2,26 @@ import { Layout } from '../components/Layout' import '../config/style.css' import { NextAppSsrAppRouter } from '@siafoundation/design-system' import { appLink } from '../config' +import { IBM_Plex_Sans, IBM_Plex_Mono } from '@next/font/google' +import { cx } from 'class-variance-authority' + +const sans = IBM_Plex_Sans({ + weight: ['100', '200', '300', '400', '500', '600', '700'], + style: ['normal', 'italic'], + subsets: ['latin'], + variable: '--font-sans', + display: 'swap', + preload: true, +}) + +const mono = IBM_Plex_Mono({ + weight: ['100', '200', '300', '400', '500', '600', '700'], + style: ['normal', 'italic'], + subsets: ['latin'], + variable: '--font-mono', + display: 'swap', + preload: true, +}) export const metadata = { title: 'Explorer', @@ -19,7 +39,11 @@ export default function RootLayout({ children: React.ReactNode }) { return ( - + {children} diff --git a/apps/explorer/app/page.tsx b/apps/explorer/app/page.tsx index 8b763a521..180cac304 100644 --- a/apps/explorer/app/page.tsx +++ b/apps/explorer/app/page.tsx @@ -4,6 +4,7 @@ import { Home } from '../components/Home' import { getSiaCentralBlockLatest, getSiaCentralBlocks, + getSiaCentralExchangeRates, getSiaCentralHosts, getSiaCentralHostsNetworkMetrics, } from '@siafoundation/sia-central' @@ -30,7 +31,7 @@ export function generateMetadata(): Metadata { export const revalidate = 60 export default async function HomePage() { - const [metrics, lastestBlock] = await Promise.all([ + const [m, lb, r, h] = await Promise.all([ getSiaCentralHostsNetworkMetrics({ config: { api: siaCentralApi, @@ -41,9 +42,23 @@ export default async function HomePage() { api: siaCentralApi, }, }), + getSiaCentralExchangeRates({ + config: { + api: siaCentralApi, + }, + }), + getSiaCentralHosts({ + params: { + limit: 5, + }, + config: { + api: siaCentralApi, + }, + }), ]) - const lastBlockHeight = lastestBlock?.block.height || 0 - const blocks = await getSiaCentralBlocks({ + + const lastBlockHeight = lb?.block.height || 0 + const bs = await getSiaCentralBlocks({ payload: { heights: range(lastBlockHeight - 5, lastBlockHeight), }, @@ -51,20 +66,14 @@ export default async function HomePage() { api: siaCentralApi, }, }) - const hosts = await getSiaCentralHosts({ - params: { - limit: 5, - }, - config: { - api: siaCentralApi, - }, - }) + return ( ) } diff --git a/apps/explorer/components/Home/index.tsx b/apps/explorer/components/Home/index.tsx index 755a4d718..8fc95f3c4 100644 --- a/apps/explorer/components/Home/index.tsx +++ b/apps/explorer/components/Home/index.tsx @@ -11,21 +11,25 @@ import { ContentLayout } from '../ContentLayout' import { reverse, sortBy } from 'lodash' import { SiaCentralBlock, + SiaCentralExchangeRates, SiaCentralHost, SiaCentralHostsNetworkMetricsResponse, } from '@siafoundation/sia-central' import { hashToAvatar } from '../../lib/avatar' +import { getDownloadCost, getStorageCost, getUploadCost } from '../../lib/host' export function Home({ metrics, blockHeight, blocks, hosts, + rates, }: { metrics: SiaCentralHostsNetworkMetricsResponse blockHeight: number blocks: SiaCentralBlock[] hosts: SiaCentralHost[] + rates: SiaCentralExchangeRates }) { const values = useMemo(() => { const list = [ @@ -120,9 +124,60 @@ export function Home({ ), }, + { + label: 'Average storage price', + value: ( + + + {getStorageCost({ + price: metrics?.average.settings.storage_price, + rates, + })} + + + ), + }, + { + label: 'Average download price', + value: ( + + + {getDownloadCost({ + price: metrics?.average.settings.download_price, + rates, + })} + + + ), + }, + { + label: 'Average upload price', + value: ( + + + {getUploadCost({ + price: metrics?.average.settings.upload_price, + rates, + })} + + + ), + }, ] return list - }, [metrics, blockHeight]) + }, [metrics, blockHeight, rates]) return ( + + + } > diff --git a/apps/explorer/components/Host/HostPricing.tsx b/apps/explorer/components/Host/HostPricing.tsx index 2918c22e3..b0873b90d 100644 --- a/apps/explorer/components/Host/HostPricing.tsx +++ b/apps/explorer/components/Host/HostPricing.tsx @@ -20,17 +20,17 @@ type Props = { export function HostPricing({ host, rates }: Props) { const storageCost = useMemo( - () => getStorageCost({ host, rates }), + () => getStorageCost({ price: host.settings.storage_price, rates }), [rates, host] ) const downloadCost = useMemo( - () => getDownloadCost({ host, rates }), + () => getDownloadCost({ price: host.settings.download_price, rates }), [rates, host] ) const uploadCost = useMemo( - () => getUploadCost({ host, rates }), + () => getUploadCost({ price: host.settings.upload_price, rates }), [rates, host] ) diff --git a/apps/explorer/lib/host.ts b/apps/explorer/lib/host.ts index 172f4b9cf..b75b1c5fc 100644 --- a/apps/explorer/lib/host.ts +++ b/apps/explorer/lib/host.ts @@ -1,54 +1,47 @@ import { TBToBytes, monthsToBlocks } from '@siafoundation/design-system' -import { - SiaCentralExchangeRates, - SiaCentralHost, -} from '@siafoundation/sia-central' +import { SiaCentralExchangeRates } from '@siafoundation/sia-central' import BigNumber from 'bignumber.js' import { humanSiacoin } from '@siafoundation/sia-js' type Props = { - host: SiaCentralHost + price: string rates: SiaCentralExchangeRates } -export function getStorageCost({ host, rates }: Props) { +export function getStorageCost({ price, rates }: Props) { return rates - ? `$${new BigNumber(host.settings.storage_price) + ? `$${new BigNumber(price) .times(TBToBytes(1)) .times(monthsToBlocks(1)) .div(1e24) .times(rates.sc.usd || 1) .toFixed(2)}/TB` : `${humanSiacoin( - new BigNumber(host.settings.storage_price) - .times(TBToBytes(1)) - .times(monthsToBlocks(1)), + new BigNumber(price).times(TBToBytes(1)).times(monthsToBlocks(1)), { fixed: 0 } )}/TB` } -export function getDownloadCost({ host, rates }: Props) { +export function getDownloadCost({ price, rates }: Props) { return rates - ? `$${new BigNumber(host.settings.download_price) + ? `$${new BigNumber(price) .times(TBToBytes(1)) .div(1e24) .times(rates.sc.usd || 1) .toFixed(2)}/TB` - : `${humanSiacoin( - new BigNumber(host.settings.download_price).times(TBToBytes(1)), - { fixed: 0 } - )}/TB` + : `${humanSiacoin(new BigNumber(price).times(TBToBytes(1)), { + fixed: 0, + })}/TB` } -export function getUploadCost({ host, rates }: Props) { +export function getUploadCost({ price, rates }: Props) { return rates - ? `$${new BigNumber(host.settings.upload_price) + ? `$${new BigNumber(price) .times(TBToBytes(1)) .div(1e24) .times(rates.sc.usd || 1) .toFixed(2)}/TB` - : `${humanSiacoin( - new BigNumber(host.settings.upload_price).times(TBToBytes(1)), - { fixed: 0 } - )}/TB` + : `${humanSiacoin(new BigNumber(price).times(TBToBytes(1)), { + fixed: 0, + })}/TB` } diff --git a/apps/explorer/project.json b/apps/explorer/project.json index 27090f690..0a0509307 100644 --- a/apps/explorer/project.json +++ b/apps/explorer/project.json @@ -10,7 +10,7 @@ "defaultConfiguration": "production", "options": { "outputPath": "dist/apps/explorer", - "postcssConfig": "apps/website/postcss.config.js", + "postcssConfig": "apps/explorer/postcss.config.js", "assets": [ { "glob": "**/*", diff --git a/apps/explorer/tailwind.config.js b/apps/explorer/tailwind.config.js index f927defea..758f1d1a1 100644 --- a/apps/explorer/tailwind.config.js +++ b/apps/explorer/tailwind.config.js @@ -5,7 +5,7 @@ module.exports = { content: [ join( __dirname, - '{src,pages,components}/**/*!(*.stories|*.spec).{ts,tsx,html}' + '{app,pages,components,config,hooks}/**/*!(*.stories|*.spec).{ts,tsx,html}' ), ...createGlobPatternsForDependencies(__dirname), ], diff --git a/apps/website/components/DownloadWidgetSelect.tsx b/apps/website/components/DownloadWidgetSelect.tsx index cfaf06dd9..2e7605ffd 100644 --- a/apps/website/components/DownloadWidgetSelect.tsx +++ b/apps/website/components/DownloadWidgetSelect.tsx @@ -7,7 +7,11 @@ import { Download16, } from '@siafoundation/design-system' import { useState } from 'react' -import { getLinks, getLinksRuntimeNetwork } from '../content/downloads' +import { + getHostdDownloadLinks, + getRenterdDownloadLinks, + getWalletDownloadLinks, +} from '../content/downloads' type Daemon = 'renterd' | 'hostd' | 'walletd' type Props = { @@ -17,9 +21,12 @@ type Props = { export function DownloadWidgetSelect({ daemon, version }: Props) { const downloadLinks = - daemon === 'walletd' - ? getLinksRuntimeNetwork(daemon, version) - : getLinks(daemon, version) + daemon === 'renterd' + ? getRenterdDownloadLinks(version) + : daemon === 'hostd' + ? getHostdDownloadLinks(version) + : getWalletDownloadLinks(version) + const [download, setDownload] = useState(downloadLinks[0]) const combined = downloadLinks.filter((i) => i.group === 'combined') diff --git a/apps/website/components/HostMap/HostItem.tsx b/apps/website/components/HostMap/HostItem.tsx index d5b79f9d4..77daf8171 100644 --- a/apps/website/components/HostMap/HostItem.tsx +++ b/apps/website/components/HostMap/HostItem.tsx @@ -141,7 +141,6 @@ export function HostItem({ { } export type GitHubRelease = { + name: string tag_name: string } @@ -191,10 +192,10 @@ export async function getGitHubRenterdLatestRelease(): Promise { try { const response = await axios.get( - 'https://api.github.com/repos/SiaFoundation/hostd/releases?per_page=1' + 'https://api.github.com/repos/SiaFoundation/hostd/releases/latest' ) - if (response.data.length) { - return response.data[0] + if (response.data) { + return response.data } else { return null } diff --git a/libs/design-system/src/app/AppAuthedLayout/SidenavItem.tsx b/libs/design-system/src/app/AppAuthedLayout/SidenavItem.tsx index 9dd8c262d..9a23c5190 100644 --- a/libs/design-system/src/app/AppAuthedLayout/SidenavItem.tsx +++ b/libs/design-system/src/app/AppAuthedLayout/SidenavItem.tsx @@ -15,7 +15,7 @@ type Props = { export function SidenavItem({ title, children, route, onClick }: Props) { const pathname = usePathname() const state = - route && (route === '/' ? pathname === route : pathname.startsWith(route)) + route && (route === '/' ? pathname === route : pathname?.startsWith(route)) if (!route) { return ( diff --git a/libs/design-system/src/index.ts b/libs/design-system/src/index.ts index b10e8b58b..468906f2f 100644 --- a/libs/design-system/src/index.ts +++ b/libs/design-system/src/index.ts @@ -131,7 +131,6 @@ export * from './site/PatternedPanel' export * from './site/Callout' export * from './site/Links' export * from './site/SitePageHead' -export * from './site/NextAppSsr' export * from './site/NextAppSsrAppRouter' export * from './site/NextAppCsr' export * from './site/NextDocument' @@ -200,3 +199,4 @@ export * from './lib/getOs' export * from './lib/countryEmoji' export { colors } from './config/colors' +export * from './config/css' diff --git a/libs/design-system/src/site/NextAppSsrAppRouter.tsx b/libs/design-system/src/site/NextAppSsrAppRouter.tsx index cdb96fad5..3e43b485c 100644 --- a/libs/design-system/src/site/NextAppSsrAppRouter.tsx +++ b/libs/design-system/src/site/NextAppSsrAppRouter.tsx @@ -3,7 +3,6 @@ import { TooltipProvider } from '../hooks/tooltip' import { Toaster } from '../lib/toast' import { AppSettingsProvider, CoreProvider } from '@siafoundation/react-core' -import { rootClasses } from '../config/css' import { ThemeProvider } from 'next-themes' export function NextAppSsrAppRouter({ @@ -16,7 +15,7 @@ export function NextAppSsrAppRouter({ -
+
{children}