Skip to content

Commit

Permalink
[#617] feat: integrate frontend with metadata validation service
Browse files Browse the repository at this point in the history
  • Loading branch information
MSzalowski committed Apr 8, 2024
1 parent f585328 commit 82c80b6
Show file tree
Hide file tree
Showing 22 changed files with 146 additions and 156 deletions.
22 changes: 11 additions & 11 deletions .github/workflows/lighthouse.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,23 @@ jobs:
- name: Run build and lighthouse task
working-directory: ./govtool/frontend
run: |
npm install
VITE_BASE_URL=https://staging.govtool.byron.network/api npm run build
lhci collect
npm install
VITE_BASE_URL=https://staging.govtool.byron.network/ npm run build
lhci collect
- name: Evaluate reports
if: github.repository_owner != 'IntersectMBO'
run: |
lhci assert --preset "lighthouse:recommended"
lhci assert --preset "lighthouse:recommended"
- name: Publish reports
working-directory: ./govtool/frontend
if: github.repository_owner == 'IntersectMBO'
run: |
lhci assert --preset lighthouse:recommended || echo "LightHouse Assertion error ignored ..."
lhci upload --githubAppToken="${{ secrets.LHCI_GITHUB_APP_TOKEN }}" --token="${{ secrets.LHCI_SERVER_TOKEN }}" --serverBaseUrl=https://lighthouse.cardanoapi.io --ignoreDuplicateBuildFailure
curl -X POST https://ligththouse.cardanoapi.io/api/metrics/build-reports \
-d "@./lighthouseci/$(ls ./.lighthouseci |grep 'lhr.*\.json' | head -n 1)" \
-H "commit-hash: $(git rev-parse HEAD)" \
-H "secret-token: ${{ secrets.METRICS_SERVER_SECRET_TOKEN }}" \
-H 'Content-Type: application/json' || echo "Metric Upload error ignored ..."
lhci assert --preset lighthouse:recommended || echo "LightHouse Assertion error ignored ..."
lhci upload --githubAppToken="${{ secrets.LHCI_GITHUB_APP_TOKEN }}" --token="${{ secrets.LHCI_SERVER_TOKEN }}" --serverBaseUrl=https://lighthouse.cardanoapi.io --ignoreDuplicateBuildFailure
curl -X POST https://ligththouse.cardanoapi.io/api/metrics/build-reports \
-d "@./lighthouseci/$(ls ./.lighthouseci |grep 'lhr.*\.json' | head -n 1)" \
-H "commit-hash: $(git rev-parse HEAD)" \
-H "secret-token: ${{ secrets.METRICS_SERVER_SECRET_TOKEN }}" \
-H 'Content-Type: application/json' || echo "Metric Upload error ignored ..."
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ changes.

## [Unreleased]

- Integrate frontend with metadata validation service [Issue 617](https://github.com/IntersectMBO/govtool/issues/617)

### Added

- added `epochNo` and `date` to `drep/getVotes` and `proposal/get`
Expand Down
2 changes: 1 addition & 1 deletion govtool/frontend/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ build-frontend: docker-login
if [[ "$(cardano_network)" = "mainnet" ]]; then NETWORK_FLAG=1; else NETWORK_FLAG=0; fi; \
$(call check_image_on_ecr,frontend,$(frontend_image_tag)) || \
$(docker) build --tag "$(repo_url)/frontend:$(frontend_image_tag)" \
--build-arg VITE_BASE_URL="https://$(domain)/api" \
--build-arg VITE_BASE_URL="https://$(domain)" \
--build-arg VITE_GTM_ID="$${GTM_ID}" \
--build-arg VITE_NETWORK_FLAG="$$NETWORK_FLAG" \
--build-arg VITE_SENTRY_DSN="$${SENTRY_DSN}" \
Expand Down
10 changes: 5 additions & 5 deletions govtool/frontend/src/consts/externalDataModalConfig.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ModalState } from "@/context";
import I18n from "@/i18n";
import { MetadataValidationStatus } from "@/models";

export enum MetadataHashValidationErrors {
INVALID_URL = "Invalid URL",
Expand Down Expand Up @@ -29,13 +30,12 @@ const urlCannotBeFound = {
};

export const storageInformationErrorModals: Record<
MetadataHashValidationErrors,
MetadataValidationStatus,
ModalState<
typeof externalDataDoesntMatchModal | typeof urlCannotBeFound
>["state"]
> = {
[MetadataHashValidationErrors.INVALID_URL]: urlCannotBeFound,
[MetadataHashValidationErrors.FETCH_ERROR]: urlCannotBeFound,
[MetadataHashValidationErrors.INVALID_JSON]: externalDataDoesntMatchModal,
[MetadataHashValidationErrors.INVALID_HASH]: externalDataDoesntMatchModal,
[MetadataValidationStatus.URL_NOT_FOUND]: urlCannotBeFound,
[MetadataValidationStatus.INVALID_JSONLD]: externalDataDoesntMatchModal,
[MetadataValidationStatus.INVALID_HASH]: externalDataDoesntMatchModal,
};
4 changes: 4 additions & 0 deletions govtool/frontend/src/consts/queryKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ export const QUERY_KEYS = {
useGetDRepInfoKey: "useGetDRepInfoKey",
useGetVoteContextFromFile: "useGetVoteContextFromFile",
};

export const MUTATION_KEYS = {
postValidateKey: "postValidateKey",
};
32 changes: 18 additions & 14 deletions govtool/frontend/src/hooks/forms/useCreateGovernanceActionForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,19 @@ import {
CIP_100,
CIP_108,
GOVERNANCE_ACTION_CONTEXT,
MetadataHashValidationErrors,
PATHS,
storageInformationErrorModals,
} from "@consts";
import { useCardano, useModal } from "@context";
import {
canonizeJSON,
downloadJson,
generateJsonld,
validateMetadataHash,
} from "@utils";
import { canonizeJSON, downloadJson, generateJsonld } from "@utils";
import { MetadataValidationStatus } from "@models";
import {
GovernanceActionFieldSchemas,
GovernanceActionType,
} from "@/types/governanceAction";

import { useValidateMutation } from "../mutations";

export type CreateGovernanceActionValues = {
links?: { link: string }[];
storeData?: boolean;
Expand All @@ -48,6 +45,7 @@ export const useCreateGovernanceActionForm = (
buildTreasuryGovernanceAction,
buildSignSubmitConwayCertTx,
} = useCardano();
const { validateMetadata } = useValidateMutation();
const { t } = useTranslation();
const [isLoading, setIsLoading] = useState<boolean>(false);
const [hash, setHash] = useState<string | null>(null);
Expand Down Expand Up @@ -120,22 +118,27 @@ export const useCreateGovernanceActionForm = (
}, [govActionType, json]);

const validateHash = useCallback(
async (storingUrl: string, localHash: string | null) => {
async (url: string, localHash: string | null) => {
try {
if (!localHash) {
throw new Error(MetadataHashValidationErrors.INVALID_HASH);
throw new Error(MetadataValidationStatus.INVALID_HASH);
}
await validateMetadataHash(storingUrl, localHash);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
const result = await validateMetadata({ url, hash: localHash });

if (result.status) {
throw result.status;
}
} catch (error) {
if (
Object.values(MetadataHashValidationErrors).includes(error.message)
Object.values(MetadataValidationStatus).includes(
error as MetadataValidationStatus,
)
) {
openModal({
type: "statusModal",
state: {
...storageInformationErrorModals[
error.message as MetadataHashValidationErrors
error as MetadataValidationStatus
],
onSubmit: backToForm,
onCancel: backToDashboard,
Expand Down Expand Up @@ -214,6 +217,7 @@ export const useCreateGovernanceActionForm = (
setIsLoading(true);

await validateHash(data.storingURL, hash);

const govActionBuilder = await buildTransaction(data);
await buildSignSubmitConwayCertTx({
govActionBuilder,
Expand Down
25 changes: 13 additions & 12 deletions govtool/frontend/src/hooks/forms/useEditDRepInfoForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,10 @@ import {
storageInformationErrorModals,
} from "@consts";
import { useCardano, useModal } from "@context";
import {
canonizeJSON,
downloadJson,
generateJsonld,
validateMetadataHash,
} from "@utils";
import { canonizeJSON, downloadJson, generateJsonld } from "@utils";
import { MetadataValidationStatus } from "@models";

import { useValidateMutation } from "../mutations";

export type EditDRepInfoValues = {
bio?: string;
Expand All @@ -43,6 +41,7 @@ export const defaultEditDRepInfoValues: EditDRepInfoValues = {
export const useEditDRepInfoForm = (
setStep?: Dispatch<SetStateAction<number>>,
) => {
const { validateMetadata } = useValidateMutation();
const { t } = useTranslation();
const navigate = useNavigate();
const [isLoading, setIsLoading] = useState<boolean>(false);
Expand Down Expand Up @@ -113,21 +112,23 @@ export const useEditDRepInfoForm = (
};

const validateHash = useCallback(
async (storingUrl: string) => {
async (url: string) => {
try {
if (!hash) throw new Error(MetadataHashValidationErrors.INVALID_HASH);

await validateMetadataHash(storingUrl, hash);
const result = await validateMetadata({ url, hash });

if (result.status) {
throw result.status;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
if (
Object.values(MetadataHashValidationErrors).includes(error.message)
) {
if (Object.values(MetadataValidationStatus).includes(error)) {
openModal({
type: "statusModal",
state: {
...storageInformationErrorModals[
error.message as MetadataHashValidationErrors
error as MetadataValidationStatus
],
onSubmit: backToForm,
onCancel: backToDashboard,
Expand Down
28 changes: 16 additions & 12 deletions govtool/frontend/src/hooks/forms/useRegisterAsdRepForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,15 @@ import {
CIP_100,
CIP_QQQ,
DREP_CONTEXT,
MetadataHashValidationErrors,
PATHS,
storageInformationErrorModals,
} from "@consts";
import { useCardano, useModal } from "@context";
import {
canonizeJSON,
downloadJson,
generateJsonld,
validateMetadataHash,
} from "@utils";
import { MetadataValidationStatus } from "@models";
import { canonizeJSON, downloadJson, generateJsonld } from "@utils";

import { useGetVoterInfo } from "..";
import { useValidateMutation } from "../mutations";

export type RegisterAsDRepValues = {
bio?: string;
Expand All @@ -44,6 +41,7 @@ export const defaultRegisterAsDRepValues: RegisterAsDRepValues = {
export const useRegisterAsdRepForm = (
setStep?: Dispatch<SetStateAction<number>>,
) => {
const { validateMetadata } = useValidateMutation();
const { t } = useTranslation();
const navigate = useNavigate();
const [isLoading, setIsLoading] = useState<boolean>(false);
Expand Down Expand Up @@ -116,21 +114,27 @@ export const useRegisterAsdRepForm = (
};

const validateHash = useCallback(
async (storingUrl: string) => {
async (url: string) => {
try {
if (!hash) throw new Error(MetadataHashValidationErrors.INVALID_HASH);
if (!hash) throw new Error(MetadataValidationStatus.INVALID_HASH);

await validateMetadataHash(storingUrl, hash);
const result = await validateMetadata({ url, hash });

if (result.status) {
throw result.status;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
if (
Object.values(MetadataHashValidationErrors).includes(error.message)
Object.values(MetadataValidationStatus).includes(
error as MetadataValidationStatus,
)
) {
openModal({
type: "statusModal",
state: {
...storageInformationErrorModals[
error.message as MetadataHashValidationErrors
error as MetadataValidationStatus
],
onSubmit: backToForm,
onCancel: backToDashboard,
Expand Down
34 changes: 15 additions & 19 deletions govtool/frontend/src/hooks/forms/useVoteContextForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,14 @@ import { Dispatch, SetStateAction, useCallback, useState } from "react";
import { NodeObject } from "jsonld";
import { useFormContext } from "react-hook-form";
import { blake2bHex } from "blakejs";

import {
CIP_108,
MetadataHashValidationErrors,
VOTE_TEST_CONTEXT,
} from "@consts";
import {
canonizeJSON,
downloadJson,
generateJsonld,
validateMetadataHash,
} from "@utils";
import { captureException } from "@sentry/react";

import { CIP_108, VOTE_TEST_CONTEXT } from "@consts";
import { canonizeJSON, downloadJson, generateJsonld } from "@utils";
import { MetadataValidationStatus } from "@models";

import { useValidateMutation } from "../mutations";

export type VoteContextFormValues = {
voteContextText: string;
terms?: boolean;
Expand All @@ -27,6 +21,7 @@ export const useVoteContextForm = (
setStep?: Dispatch<SetStateAction<number>>,
setErrorMessage?: Dispatch<SetStateAction<string | undefined>>,
) => {
const { validateMetadata } = useValidateMutation();
const [hash, setHash] = useState<string | null>(null);
const [json, setJson] = useState<NodeObject | null>(null);

Expand Down Expand Up @@ -71,18 +66,19 @@ export const useVoteContextForm = (
}, [json]);

const validateHash = useCallback(
async (storingUrl: string, localHash: string | null) => {
async (url: string, localHash: string | null) => {
try {
if (!localHash) {
throw new Error(MetadataHashValidationErrors.INVALID_HASH);
throw new Error(MetadataValidationStatus.INVALID_HASH);
}
const result = await validateMetadata({ url, hash: localHash });
if (result.status) {
throw result.status;
}
await validateMetadataHash(storingUrl, localHash);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
if (
Object.values(MetadataHashValidationErrors).includes(error.message)
) {
if (setErrorMessage) setErrorMessage(error.message);
if (Object.values(MetadataValidationStatus).includes(error)) {
if (setErrorMessage) setErrorMessage(error);
if (setStep) setStep(4);
}
throw error;
Expand Down
1 change: 1 addition & 0 deletions govtool/frontend/src/hooks/mutations/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./metadataValidation";
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./useValidateMutation";
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useMutation } from "react-query";

import { postValidate } from "@services";
import { MUTATION_KEYS } from "@consts";
import { MetadataValidationDTO } from "@models";

export const useValidateMutation = () => {
const { data, isLoading, mutateAsync } = useMutation({
mutationFn: (body: MetadataValidationDTO) => postValidate(body),
mutationKey: [MUTATION_KEYS.postValidateKey],
});

return {
validateMetadata: mutateAsync,
validationStatus: data,
isValidating: isLoading,
};
};
1 change: 1 addition & 0 deletions govtool/frontend/src/models/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./api";
export * from "./snackbar";
export * from "./wallet";
export * from "./metadataValidation";
16 changes: 16 additions & 0 deletions govtool/frontend/src/models/metadataValidation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// TODO: Should be taken from @govtool/metadata-validation
export enum MetadataValidationStatus {
URL_NOT_FOUND = "URL_NOT_FOUND",
INVALID_JSONLD = "INVALID_JSONLD",
INVALID_HASH = "INVALID_HASH",
}

export type ValidateMetadataResult = {
status?: MetadataValidationStatus;
valid: boolean;
};

export type MetadataValidationDTO = {
url: string;
hash: string;
};
Loading

0 comments on commit 82c80b6

Please sign in to comment.