diff --git a/govtool/frontend/src/components/organisms/DashboardCards/DRepDashboardCard.tsx b/govtool/frontend/src/components/organisms/DashboardCards/DRepDashboardCard.tsx index 5afc070e..9fe20bbc 100644 --- a/govtool/frontend/src/components/organisms/DashboardCards/DRepDashboardCard.tsx +++ b/govtool/frontend/src/components/organisms/DashboardCards/DRepDashboardCard.tsx @@ -59,7 +59,15 @@ export const DRepDashboardCard = ({ title: t("dashboard.cards.drep.dRepRegistration"), }), ...(pendingTransaction.retireAsDrep && { - description: ( + description: voter?.givenName ? ( + + ) : ( { const hash = await createHash(jsonld!); expect(hash).toBeDefined(); expect(hash).toBe( - "bbdbbe163d1b8e4d6c10180df515cc7d58109412d90a42e898fc66850b3fc98c", + "72b37e2f5e64e7de57b85558ba00885c848f700fbb37fbed3197e603873fa976", ); }; test(); diff --git a/govtool/frontend/src/context/governanceAction.tsx b/govtool/frontend/src/context/governanceAction.tsx index 807a2260..d8f790b9 100644 --- a/govtool/frontend/src/context/governanceAction.tsx +++ b/govtool/frontend/src/context/governanceAction.tsx @@ -76,7 +76,11 @@ const GovernanceActionProvider = ({ children }: PropsWithChildren) => { */ const createHash = useCallback(async (jsonLD: NodeObject) => { try { - const jsonHash = blake2bHex(JSON.stringify(jsonLD), undefined, 32); + const jsonHash = blake2bHex( + JSON.stringify(jsonLD, null, 2), + undefined, + 32, + ); return jsonHash; } catch (error) { Sentry.captureException(error); diff --git a/govtool/frontend/src/hooks/forms/useCreateGovernanceActionForm.ts b/govtool/frontend/src/hooks/forms/useCreateGovernanceActionForm.ts index e6709a4a..73f05ec0 100644 --- a/govtool/frontend/src/hooks/forms/useCreateGovernanceActionForm.ts +++ b/govtool/frontend/src/hooks/forms/useCreateGovernanceActionForm.ts @@ -109,7 +109,7 @@ export const useCreateGovernanceActionForm = ( const jsonld = await generateJsonld(body, GOVERNANCE_ACTION_CONTEXT); - const jsonHash = blake2bHex(JSON.stringify(jsonld), undefined, 32); + const jsonHash = blake2bHex(JSON.stringify(jsonld, null, 2), undefined, 32); // That allows to validate metadata hash setHash(jsonHash); diff --git a/govtool/frontend/src/hooks/forms/useEditDRepInfoForm.ts b/govtool/frontend/src/hooks/forms/useEditDRepInfoForm.ts index 904d79ba..7dc1b634 100644 --- a/govtool/frontend/src/hooks/forms/useEditDRepInfoForm.ts +++ b/govtool/frontend/src/hooks/forms/useEditDRepInfoForm.ts @@ -100,7 +100,7 @@ export const useEditDRepInfoForm = ( const jsonld = await generateJsonld(body, DREP_CONTEXT, CIP_119); - const jsonHash = blake2bHex(JSON.stringify(jsonld), undefined, 32); + const jsonHash = blake2bHex(JSON.stringify(jsonld, null, 2), undefined, 32); setHash(jsonHash); setJson(jsonld); diff --git a/govtool/frontend/src/hooks/forms/useRegisterAsdRepForm.tsx b/govtool/frontend/src/hooks/forms/useRegisterAsdRepForm.tsx index b737eda5..df804559 100644 --- a/govtool/frontend/src/hooks/forms/useRegisterAsdRepForm.tsx +++ b/govtool/frontend/src/hooks/forms/useRegisterAsdRepForm.tsx @@ -109,10 +109,9 @@ export const useRegisterAsdRepForm = ( ], standardReference: CIP_119, }); - const jsonld = await generateJsonld(body, DREP_CONTEXT, CIP_119); - const jsonHash = blake2bHex(JSON.stringify(jsonld), undefined, 32); + const jsonHash = blake2bHex(JSON.stringify(jsonld, null, 2), undefined, 32); setHash(jsonHash); setJson(jsonld); diff --git a/govtool/frontend/src/hooks/forms/useVoteContextForm.tsx b/govtool/frontend/src/hooks/forms/useVoteContextForm.tsx index 9dc004a0..11779489 100644 --- a/govtool/frontend/src/hooks/forms/useVoteContextForm.tsx +++ b/govtool/frontend/src/hooks/forms/useVoteContextForm.tsx @@ -47,7 +47,7 @@ export const useVoteContextForm = ( }); const jsonld = await generateJsonld(body, CIP_100_CONTEXT, CIP_100); - const jsonHash = blake2bHex(JSON.stringify(jsonld), undefined, 32); + const jsonHash = blake2bHex(JSON.stringify(jsonld, null, 2), undefined, 32); // That allows to validate metadata hash setHash(jsonHash); diff --git a/govtool/frontend/src/i18n/locales/en.ts b/govtool/frontend/src/i18n/locales/en.ts index 44a8c57a..ad39c741 100644 --- a/govtool/frontend/src/i18n/locales/en.ts +++ b/govtool/frontend/src/i18n/locales/en.ts @@ -85,7 +85,9 @@ export const en = { reRegister: "Re-register as a DRep", retire: "Retire as a DRep", retirementInProgress: - "You are being retired as MrDRep. You will receive a refund of {{deposit}} ADA when the transaction completes.", + "You are being retired. You will receive a refund of {{deposit}} ADA when the transaction completes.", + retirementInProgressWithGivenName: + "You are being retired as {{givenName}}. You will receive a refund of {{deposit}} ADA when the transaction completes.", viewDetails: "View your DRep details", youAreRegistered: "You are Registered as a DRep", yourDRepId: "Your DRep ID", @@ -361,7 +363,8 @@ export const en = { }, dRepData: { givenName: "DRep Name", - givenNameHelpfulText: "This is the name that will be shown on your DRep profile", + givenNameHelpfulText: + "This is the name that will be shown on your DRep profile", objectives: "Objectives", objectivesHelpfulText: "What you believe and what you want to achieve as a DRep.", @@ -391,10 +394,9 @@ export const en = { }, references: "References", referenceDescription: "Description", - referenceDescriptionHelpfulText: - "Limit: 80 characters", + referenceDescriptionHelpfulText: "Limit: 80 characters", referenceURL: "URL", - }, + }, errors: { tooLongUrl: "Url must be less than 128 bytes", mustBeStakeAddress: "It must be reward address in bech32 format", diff --git a/govtool/metadata-validation/src/app.service.ts b/govtool/metadata-validation/src/app.service.ts index d1bdaa90..86c66e13 100644 --- a/govtool/metadata-validation/src/app.service.ts +++ b/govtool/metadata-validation/src/app.service.ts @@ -14,6 +14,7 @@ const axiosConfig: AxiosRequestConfig = { timeout: 5000, maxContentLength: 10 * 1024 * 1024, // Max content length 10MB maxBodyLength: 10 * 1024 * 1024, // Max body length 10MB + responseType: 'text', }; @Injectable() @@ -28,7 +29,7 @@ export class AppService { let metadata: Record; try { - const { data } = await firstValueFrom( + const { data: rawData } = await firstValueFrom( this.httpService.get(url, axiosConfig).pipe( timeout(5000), catchError(() => { @@ -37,38 +38,49 @@ export class AppService { ), ); - if (!data?.body) { + let parsedData; + try { + parsedData = JSON.parse(rawData); + } catch (error) { throw MetadataValidationStatus.INCORRECT_FORMAT; } - const standard = getStandard(data); + if (!parsedData?.body) { + throw MetadataValidationStatus.INCORRECT_FORMAT; + } + + const standard = getStandard(parsedData); if (standard) { - await validateMetadataStandard(data.body, standard); - metadata = parseMetadata(data.body); + await validateMetadataStandard(parsedData.body, standard); + metadata = parseMetadata(parsedData.body); } - const hashedMetadata = blake.blake2bHex( - JSON.stringify(data), - undefined, - 32, - ); + const hashedMetadata = blake.blake2bHex(rawData, undefined, 32); if (hashedMetadata !== hash) { - // Optional support for the canonized data hash - // Validate canonized data hash - const canonizedMetadata = await jsonld.canonize(data, { - safe: false, - }); - - const hashedCanonizedMetadata = blake.blake2bHex( - canonizedMetadata, + // Optionally validate on a parsed metadata + const hashedParsedMetadata = blake.blake2bHex( + JSON.stringify(parsedData), undefined, 32, ); + if (hashedParsedMetadata !== hash) { + // Optional support for the canonized data hash + // Validate canonized data hash + const canonizedMetadata = await jsonld.canonize(JSON.parse(rawData), { + safe: false, + }); + + const hashedCanonizedMetadata = blake.blake2bHex( + canonizedMetadata, + undefined, + 32, + ); - if (hashedCanonizedMetadata !== hash) { - throw MetadataValidationStatus.INVALID_HASH; + if (hashedCanonizedMetadata !== hash) { + throw MetadataValidationStatus.INVALID_HASH; + } } } } catch (error) { diff --git a/govtool/metadata-validation/src/utils/validateCIP108body.ts b/govtool/metadata-validation/src/utils/validateCIP108body.ts index a9bae715..abd8bc70 100644 --- a/govtool/metadata-validation/src/utils/validateCIP108body.ts +++ b/govtool/metadata-validation/src/utils/validateCIP108body.ts @@ -1,16 +1,7 @@ -import * as Joi from 'joi'; - import { MetadataValidationStatus } from '@/enums'; import { getFieldValue } from './getFieldValue'; -const CIP108FieldRules = { - title: Joi.string().allow('').max(80), - abstract: Joi.string().allow('').max(2500), - motivation: Joi.string().allow(''), - rationale: Joi.string().allow(''), -}; - /** * Validates the body of a CIP108 standard. * @@ -23,15 +14,12 @@ export const validateCIP108body = (body: Record) => { const abstract = getFieldValue(body, 'abstract'); const motivation = getFieldValue(body, 'motivation'); const rationale = getFieldValue(body, 'rationale'); - - try { - CIP108FieldRules.title.validate(title); - CIP108FieldRules.abstract.validate(abstract); - CIP108FieldRules.motivation.validate(motivation); - CIP108FieldRules.rationale.validate(rationale); - - return true; - } catch (error) { + if (!title || !abstract || !motivation || !rationale) { + throw MetadataValidationStatus.INCORRECT_FORMAT; + } + if (String(title).length > 80 || String(abstract).length > 2500) { throw MetadataValidationStatus.INCORRECT_FORMAT; } + + return true; };