Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/config #396

Merged
merged 7 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .commitlintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"deployment",
"certificate",
"dx",
"config",
"stats"
]
]
Expand Down
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ apps/indexer/.env*
apps/landing/.env*
apps/provider-console/.env*
apps/provider-proxy/.env*
apps/stats-web/.env*

**/.next
*.md
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docker-build-stats-web.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ jobs:

- name: Build the Docker image
if: steps.filter.outputs.stats-web == 'true'
run: npm run dc:build -- stats-web
run: npm run dc:build -- --build-arg DEPLOYMENT_ENV=production stats-web
1 change: 1 addition & 0 deletions apps/stats-web/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

# production
/build
env-config.schema.js

# misc
.DS_Store
Expand Down
9 changes: 9 additions & 0 deletions apps/stats-web/env/.env.production
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
NEXT_PUBLIC_NODE_ENV=$NODE_ENV
NEXT_PUBLIC_BASE_API_MAINNET_URL=https://console-api.akash.network
NEXT_PUBLIC_BASE_API_SANDBOX_URL=https://console-api-sandbox.akash.network
NEXT_PUBLIC_BASE_API_TESTNET_URL=https://console-api-testnet.akash.network
NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_BASE_API_MAINNET_URL

BASE_API_MAINNET_URL=$NEXT_PUBLIC_BASE_API_MAINNET_URL
BASE_API_TESTNET_URL=$NEXT_PUBLIC_BASE_API_TESTNET_URL
BASE_API_SANDBOX_URL=$NEXT_PUBLIC_BASE_API_SANDBOX_URL
1 change: 1 addition & 0 deletions apps/stats-web/env/.env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NEXT_PUBLIC_API_BASE_URL=
9 changes: 9 additions & 0 deletions apps/stats-web/env/.env.staging
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
NEXT_PUBLIC_NODE_ENV=$NODE_ENV
NEXT_PUBLIC_BASE_API_MAINNET_URL=https://console-api-mainnet-staging.akash.network
NEXT_PUBLIC_BASE_API_SANDBOX_URL=https://console-api-sandbox-staging.akash.network
NEXT_PUBLIC_BASE_API_TESTNET_URL=$NEXT_PUBLIC_BASE_API_MAINNET_URL
NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_BASE_API_MAINNET_URL

BASE_API_MAINNET_URL=$NEXT_PUBLIC_BASE_API_MAINNET_URL
BASE_API_TESTNET_URL=$NEXT_PUBLIC_BASE_API_TESTNET_URL
BASE_API_SANDBOX_URL=$NEXT_PUBLIC_BASE_API_SANDBOX_URL
11 changes: 11 additions & 0 deletions apps/stats-web/next.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
require("@akashnetwork/env-loader");
const { version } = require("./package.json");

try {
const { browserEnvSchema } = require("./env-config.schema");

browserEnvSchema.parse(process.env);
} catch (error) {
if (error.message.includes("Cannot find module")) {
console.warn("No env-config.schema.js found, skipping env validation");
}
}

/** @type {import('next').NextConfig} */
const nextConfig = {
output: "standalone",
Expand Down
4 changes: 3 additions & 1 deletion apps/stats-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
"version": "0.20.0",
"private": true,
"scripts": {
"build": "next build",
"build": "npm run build-env-schemas && next build",
"build-env-schemas": "tsc src/config/env-config.schema.ts --outDir . --skipLibCheck",
"dev": "next dev",
"format": "prettier --write ./*.{ts,js,json} **/*.{ts,tsx,js,json}",
"lint": "eslint .",
"start": "next start"
},
"dependencies": {
"@akashnetwork/network-store": "*",
"@akashnetwork/ui": "*",
"@cosmjs/encoding": "^0.32.4",
"@json2csv/plainjs": "^7.0.4",
Expand Down
4 changes: 2 additions & 2 deletions apps/stats-web/src/app/(home)/DashboardContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import { Spinner } from "@akashnetwork/ui/components";
import { Dashboard } from "./Dashboard";

import { Title } from "@/components/Title";
import { useSelectedNetwork } from "@/hooks/useSelectedNetwork";
import { useMarketData } from "@/queries";
import { useDashboardData } from "@/queries/useDashboardData";
import { networkStore } from "@/store/network.store";

export const DashboardContainer: React.FunctionComponent = () => {
const { data: dashboardData, isLoading: isLoadingDashboardData } = useDashboardData();
const { data: marketData, isLoading: isLoadingMarketData } = useMarketData();
const selectedNetwork = useSelectedNetwork();
const selectedNetwork = networkStore.useSelectedNetwork();
const isLoading = isLoadingMarketData || isLoadingDashboardData;

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
import type { Network } from "@akashnetwork/network-store";
import { Metadata } from "next";
import { z } from "zod";

import { DeploymentInfo } from "./DeploymentInfo";

import PageContainer from "@/components/PageContainer";
import { Title } from "@/components/Title";
import { getNetworkBaseApiUrl } from "@/lib/constants";
import { networkId } from "@/config/env-config.schema";
import { UrlService } from "@/lib/urlUtils";
import { serverApiUrlService } from "@/services/api-url/server-api-url.service";
import { DeploymentDetail } from "@/types";

interface IProps {
params: { address: string; dseq: string };
searchParams: { [key: string]: string | string[] | undefined };
}
const DeploymentDetailPageSchema = z.object({
params: z.object({
address: z.string(),
dseq: z.string()
}),
searchParams: z.object({
network: networkId
})
});
type DeploymentDetailPageProps = z.infer<typeof DeploymentDetailPageSchema>;

export async function generateMetadata({ params: { address, dseq } }: IProps): Promise<Metadata> {
export async function generateMetadata({ params: { address, dseq } }: DeploymentDetailPageProps): Promise<Metadata> {
const url = `https://stats.akash.network${UrlService.deployment(address, dseq)}`;

return {
Expand All @@ -27,8 +36,8 @@ export async function generateMetadata({ params: { address, dseq } }: IProps): P
};
}

async function fetchDeploymentData(address: string, dseq: string, network: string): Promise<DeploymentDetail> {
const apiUrl = getNetworkBaseApiUrl(network);
async function fetchDeploymentData(address: string, dseq: string, network: Network["id"]): Promise<DeploymentDetail> {
const apiUrl = serverApiUrlService.getBaseApiUrlFor(network);
const response = await fetch(`${apiUrl}/v1/deployment/${address}/${dseq}`);

if (!response.ok) {
Expand All @@ -39,8 +48,12 @@ async function fetchDeploymentData(address: string, dseq: string, network: strin
return response.json();
}

export default async function DeploymentDetailPage({ params: { address, dseq }, searchParams: { network } }: IProps) {
const deployment = await fetchDeploymentData(address, dseq, network as string);
export default async function DeploymentDetailPage(props: DeploymentDetailPageProps) {
const {
params: { address, dseq },
searchParams: { network }
} = DeploymentDetailPageSchema.parse(props);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will throw an error if the props are not correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think network id should have a default value of mainnet.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so let's imagine someone implements a link to this page on the frontend. The one may notice that it works without the network params and not bother why it's needed. Thus we may get a bug when a mainnet link is opened from, say, staging.
I'd say it should fail in dev.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose yea, we do append the network param to the path everywhere is use it so it should be fine.

const deployment = await fetchDeploymentData(address, dseq, network);

return (
<PageContainer>
Expand Down
35 changes: 24 additions & 11 deletions apps/stats-web/src/app/addresses/[address]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Metadata } from "next";
import type { Network } from "@akashnetwork/network-store";
import type { Metadata } from "next";
import { z } from "zod";

import { AddressInfo } from "./AddressInfo";
import AddressLayout from "./AddressLayout";
Expand All @@ -7,16 +9,23 @@ import { AssetList } from "./AssetList";
import { LatestTransactions } from "./LatestTransactions";

import { Title } from "@/components/Title";
import { getNetworkBaseApiUrl } from "@/lib/constants";
import { networkId } from "@/config/env-config.schema";
import { UrlService } from "@/lib/urlUtils";
import { serverApiUrlService } from "@/services/api-url/server-api-url.service";
import { AddressDetail } from "@/types";

interface IProps {
params: { address: string };
searchParams: { [key: string]: string | string[] | undefined };
}
const AddressDetailPageSchema = z.object({
params: z.object({
address: z.string(),
dseq: z.string()
}),
searchParams: z.object({
network: networkId
})
});
type AddressDetailPageProps = z.infer<typeof AddressDetailPageSchema>;

export async function generateMetadata({ params: { address } }: IProps): Promise<Metadata> {
export async function generateMetadata({ params: { address } }: AddressDetailPageProps): Promise<Metadata> {
const url = `https://stats.akash.network${UrlService.address(address)}`;

return {
Expand All @@ -30,8 +39,8 @@ export async function generateMetadata({ params: { address } }: IProps): Promise
};
}

async function fetchAddressData(address: string, network: string): Promise<AddressDetail> {
const apiUrl = getNetworkBaseApiUrl(network);
async function fetchAddressData(address: string, network: Network["id"]): Promise<AddressDetail> {
const apiUrl = serverApiUrlService.getBaseApiUrlFor(network);
const response = await fetch(`${apiUrl}/v1/addresses/${address}`);

if (!response.ok) {
Expand All @@ -42,8 +51,12 @@ async function fetchAddressData(address: string, network: string): Promise<Addre
return response.json();
}

export default async function AddressDetailPage({ params: { address }, searchParams: { network } }: IProps) {
const addressDetail = await fetchAddressData(address, network as string);
export default async function AddressDetailPage(props: AddressDetailPageProps) {
const {
params: { address },
searchParams: { network }
} = AddressDetailPageSchema.parse(props);
const addressDetail = await fetchAddressData(address, network);

return (
<AddressLayout page="address" address={address}>
Expand Down
34 changes: 23 additions & 11 deletions apps/stats-web/src/app/blocks/[height]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,36 @@
import type { Network } from "@akashnetwork/network-store";
import { Card, CardContent, Table, TableBody, TableHead, TableHeader, TableRow } from "@akashnetwork/ui/components";
import { SearchX } from "lucide-react";
import { Metadata } from "next";
import type { Metadata } from "next";
import { z } from "zod";

import { BlockInfo } from "./BlockInfo";

import { TransactionRow } from "@/components/blockchain/TransactionRow";
import PageContainer from "@/components/PageContainer";
import { Title } from "@/components/Title";
import { getNetworkBaseApiUrl } from "@/lib/constants";
import { networkId } from "@/config/env-config.schema";
import { serverApiUrlService } from "@/services/api-url/server-api-url.service";
import { BlockDetail } from "@/types";

interface IProps {
params: { height: string };
searchParams: { [key: string]: string | string[] | undefined };
}
const BlockDetailPageSchema = z.object({
params: z.object({
height: z.string()
}),
searchParams: z.object({
network: networkId
})
});
type BlockDetailPageProps = z.infer<typeof BlockDetailPageSchema>;

export async function generateMetadata({ params: { height } }: IProps): Promise<Metadata> {
export async function generateMetadata({ params: { height } }: BlockDetailPageProps): Promise<Metadata> {
return {
title: `Block #${height}`
};
}

async function fetchBlockData(height: string, network: string): Promise<BlockDetail> {
const apiUrl = getNetworkBaseApiUrl(network);
async function fetchBlockData(height: string, network: Network["id"]): Promise<BlockDetail> {
const apiUrl = serverApiUrlService.getBaseApiUrlFor(network);
const response = await fetch(`${apiUrl}/v1/blocks/${height}`);

if (!response.ok) {
Expand All @@ -33,8 +41,12 @@ async function fetchBlockData(height: string, network: string): Promise<BlockDet
return response.json();
}

export default async function BlockDetailPage({ params: { height }, searchParams: { network } }: IProps) {
const block = await fetchBlockData(height, network as string);
export default async function BlockDetailPage(props: BlockDetailPageProps) {
const {
params: { height },
searchParams: { network }
} = BlockDetailPageSchema.parse(props);
const block = await fetchBlockData(height, network);

return (
<PageContainer>
Expand Down
6 changes: 3 additions & 3 deletions apps/stats-web/src/app/graph/[snapshot]/GraphContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import dynamic from "next/dynamic";
import { DiffNumber } from "@/components/DiffNumber";
import { DiffPercentageChip } from "@/components/DiffPercentageChip";
import { TimeRange } from "@/components/graph/TimeRange";
import { selectedRangeValues } from "@/lib/constants";
import { SELECTED_RANGE_VALUES } from "@/config/date.config";
import { percIncrease, udenomToDenom } from "@/lib/mathHelpers";
import { SNAPSHOT_NOT_FOUND } from "@/lib/snapshotsUrlHelpers";
import { bytesToShrink } from "@/lib/unitUtils";
Expand All @@ -25,7 +25,7 @@ export interface IGraphProps {
}

export default function GraphContainer({ snapshot }: IGraphProps) {
const [selectedRange, setSelectedRange] = useState(selectedRangeValues["7D"]);
const [selectedRange, setSelectedRange] = useState(SELECTED_RANGE_VALUES["7D"]);
const { data: snapshotData, status } = useGraphSnapshot(snapshot);
const snapshotMetadata = snapshotData && getSnapshotMetadata(snapshot as Snapshots);
const rangedData = snapshotData && snapshotData.snapshots.slice(Math.max(snapshotData.snapshots.length - selectedRange, 0), snapshotData.snapshots.length);
Expand All @@ -50,7 +50,7 @@ export default function GraphContainer({ snapshot }: IGraphProps) {
const csvContent = parser.parse(rangedData.map(d => ({ date: d.date, value: snapshotMetadata.unitFn(d.value).value })));

const datePart = new Date().toISOString().substring(0, 10).replaceAll("-", "");
const rangePart = Object.keys(selectedRangeValues).find(key => selectedRangeValues[key] === selectedRange);
const rangePart = Object.keys(SELECTED_RANGE_VALUES).find(key => SELECTED_RANGE_VALUES[key] === selectedRange);
const fileName = `${snapshot}-${datePart}-${rangePart}.csv`;

const encodedUri = encodeURI("data:text/csv;charset=utf-8," + csvContent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import dynamic from "next/dynamic";
import { DiffNumber } from "@/components/DiffNumber";
import { DiffPercentageChip } from "@/components/DiffPercentageChip";
import { TimeRange } from "@/components/graph/TimeRange";
import { selectedRangeValues } from "@/lib/constants";
import { SELECTED_RANGE_VALUES } from "@/config/date.config";
import { percIncrease } from "@/lib/mathHelpers";
import { getProviderSnapshotMetadata } from "@/lib/providerUtils";
import { SNAPSHOT_NOT_FOUND } from "@/lib/snapshotsUrlHelpers";
Expand All @@ -25,7 +25,7 @@ export interface IGraphProps {
}

export default function GraphContainer({ snapshot }: IGraphProps) {
const [selectedRange, setSelectedRange] = useState(selectedRangeValues["7D"]);
const [selectedRange, setSelectedRange] = useState(SELECTED_RANGE_VALUES["7D"]);
const { data: snapshotData, status } = useProviderGraphSnapshot(snapshot);
const snapshotMetadata = snapshotData && getProviderSnapshotMetadata(snapshot as ProviderSnapshots);
const rangedData = snapshotData && snapshotData.snapshots.slice(Math.max(snapshotData.snapshots.length - selectedRange, 0), snapshotData.snapshots.length);
Expand All @@ -50,7 +50,7 @@ export default function GraphContainer({ snapshot }: IGraphProps) {
const csvContent = parser.parse(rangedData.map(d => ({ date: d.date, value: snapshotMetadata.unitFn(d.value).value })));

const datePart = new Date().toISOString().substring(0, 10).replaceAll("-", "");
const rangePart = Object.keys(selectedRangeValues).find(key => selectedRangeValues[key] === selectedRange);
const rangePart = Object.keys(SELECTED_RANGE_VALUES).find(key => SELECTED_RANGE_VALUES[key] === selectedRange);
const fileName = `${snapshot}-${datePart}-${rangePart}.csv`;

const encodedUri = encodeURI("data:text/csv;charset=utf-8," + csvContent);
Expand Down
Loading
Loading