diff --git a/CHANGELOG.md b/CHANGELOG.md index 2186fff03..d2bae14cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,27 @@ changes. - +## [v2.0.4](https://github.com/IntersectMBO/govtool/releases/tag/v2.0.4) 2025-01-07 + +### Added + +- + +### Fixed + +- Fix CIP-129 DRep view identifier for script based DReps [Issue 2583](https://github.com/IntersectMBO/govtool/issues/2583) +- Fix fetching metadata from IPFS gateway +- Fix bad request on passing the random sorting to GA list request [Issue 2535](https://github.com/IntersectMBO/govtool/issues/2535) +- Fix wrong drep activity conditions + +### Changed + +- Reduce CSL version to 12.1.1 [Issue 2600](https://github.com/IntersectMBO/govtool/issues/2600) + +### Removed + +- + ## [v2.0.3](https://github.com/IntersectMBO/govtool/releases/tag/v2.0.3) 2024-12-30 ### Added diff --git a/govtool/backend/Dockerfile b/govtool/backend/Dockerfile index 3ee9f4e82..5cd5fac68 100644 --- a/govtool/backend/Dockerfile +++ b/govtool/backend/Dockerfile @@ -4,4 +4,4 @@ FROM $BASE_IMAGE_REPO:$BASE_IMAGE_TAG WORKDIR /src COPY . . RUN cabal build -RUN cp dist-newstyle/build/x86_64-linux/ghc-9.2.7/vva-be-2.0.3/x/vva-be/build/vva-be/vva-be /usr/local/bin +RUN cp dist-newstyle/build/x86_64-linux/ghc-9.2.7/vva-be-2.0.4/x/vva-be/build/vva-be/vva-be /usr/local/bin diff --git a/govtool/backend/Dockerfile.qovery b/govtool/backend/Dockerfile.qovery index 0dd9bc89d..7b442312f 100644 --- a/govtool/backend/Dockerfile.qovery +++ b/govtool/backend/Dockerfile.qovery @@ -4,7 +4,7 @@ FROM $BASE_IMAGE_REPO:$BASE_IMAGE_TAG WORKDIR /src COPY . . RUN cabal build -RUN cp dist-newstyle/build/x86_64-linux/ghc-9.2.7/vva-be-2.0.3/x/vva-be/build/vva-be/vva-be /usr/local/bin +RUN cp dist-newstyle/build/x86_64-linux/ghc-9.2.7/vva-be-2.0.4/x/vva-be/build/vva-be/vva-be /usr/local/bin # Expose the necessary port EXPOSE 9876 diff --git a/govtool/backend/sql/list-dreps.sql b/govtool/backend/sql/list-dreps.sql index 025764910..5872cd13a 100644 --- a/govtool/backend/sql/list-dreps.sql +++ b/govtool/backend/sql/list-dreps.sql @@ -17,6 +17,24 @@ DRepActivity AS ( ORDER BY epoch_no DESC LIMIT 1 +), +LatestVotingProcedure AS ( + SELECT + vp.*, + ROW_NUMBER() OVER (PARTITION BY drep_voter ORDER BY tx_id DESC) AS rn + FROM + voting_procedure vp +), +LatestVoteEpoch AS ( + SELECT + block.epoch_no, + lvp.drep_voter as drep_id + FROM + LatestVotingProcedure lvp + JOIN tx ON tx.id = lvp.tx_id + JOIN block ON block.id = tx.block_id + WHERE + lvp.rn = 1 ) SELECT DISTINCT ON (dh.raw) encode(dh.raw, 'hex'), @@ -26,7 +44,7 @@ SELECT DISTINCT ON (dh.raw) encode(va.data_hash, 'hex'), dr_deposit.deposit, DRepDistr.amount, - (DRepActivity.epoch_no - newestRegister.epoch_no) <= DRepActivity.drep_activity AS active, + (DRepActivity.epoch_no - GREATEST(MAX(COALESCE(block.epoch_no, block_first_register.epoch_no)), lve.epoch_no)) <= DRepActivity.drep_activity AS active, encode(dr_voting_anchor.tx_hash, 'hex') AS tx_hash, newestRegister.time AS last_register_time, COALESCE(latestDeposit.deposit, 0), @@ -143,6 +161,7 @@ FROM ) AS dr_first_register ON dr_first_register.drep_hash_id = dh.id AND dr_first_register.rn = 1 LEFT JOIN tx AS tx_first_register ON tx_first_register.id = dr_first_register.tx_id LEFT JOIN block AS block_first_register ON block_first_register.id = tx_first_register.block_id + LEFT JOIN LatestVoteEpoch lve ON lve.drep_id = dh.id WHERE ( COALESCE(?, '') = '' OR @@ -163,6 +182,7 @@ GROUP BY DRepDistr.amount, DRepActivity.epoch_no, DRepActivity.drep_activity, + lve.epoch_no, dr_voting_anchor.tx_hash, newestRegister.time, newestRegister.epoch_no, diff --git a/govtool/backend/vva-be.cabal b/govtool/backend/vva-be.cabal index f5d7bc5c5..396916205 100644 --- a/govtool/backend/vva-be.cabal +++ b/govtool/backend/vva-be.cabal @@ -1,6 +1,6 @@ cabal-version: 3.6 name: vva-be -version: 2.0.3 +version: 2.0.4 -- A short (one-line) description of the package. -- synopsis: diff --git a/govtool/frontend/package-lock.json b/govtool/frontend/package-lock.json index 4eea22d05..cb87c17d9 100644 --- a/govtool/frontend/package-lock.json +++ b/govtool/frontend/package-lock.json @@ -1,17 +1,17 @@ { "name": "@govtool/frontend", - "version": "2.0.3", + "version": "2.0.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@govtool/frontend", - "version": "2.0.3", + "version": "2.0.4", "hasInstallScript": true, "dependencies": { "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", - "@emurgo/cardano-serialization-lib-asmjs": "^13.1.0", + "@emurgo/cardano-serialization-lib-asmjs": "^12.1.1", "@hookform/resolvers": "^3.3.1", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", "@intersect.mbo/pdf-ui": "^0.5.5", @@ -2648,9 +2648,9 @@ "license": "MIT" }, "node_modules/@emurgo/cardano-serialization-lib-asmjs": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-asmjs/-/cardano-serialization-lib-asmjs-13.2.0.tgz", - "integrity": "sha512-sYj1GYG+TQ4XjMd9FFGFxr1I+IsMjD8GCJYw+X9N0T83OXH5kMLu1LxTmxrTmCa6PqJgLtZu8VXLGH7kAQbqLw==", + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-asmjs/-/cardano-serialization-lib-asmjs-12.1.1.tgz", + "integrity": "sha512-K3f28QUfLDJ7seO6MtKfMYtRm5ccf36TQ5yxyTmZqX1TA85MkriEdxqpgV9KLiLEA95emwnlvU2/WmlHMRPg1A==", "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { @@ -3382,12 +3382,6 @@ "sass": "^1.77.2" } }, - "node_modules/@intersect.mbo/pdf-ui/node_modules/@emurgo/cardano-serialization-lib-asmjs": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-asmjs/-/cardano-serialization-lib-asmjs-12.1.1.tgz", - "integrity": "sha512-K3f28QUfLDJ7seO6MtKfMYtRm5ccf36TQ5yxyTmZqX1TA85MkriEdxqpgV9KLiLEA95emwnlvU2/WmlHMRPg1A==", - "license": "MIT" - }, "node_modules/@intersect.mbo/pdf-ui/node_modules/@types/hast": { "version": "2.3.10", "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz", diff --git a/govtool/frontend/package.json b/govtool/frontend/package.json index 734961b1c..909459ad4 100644 --- a/govtool/frontend/package.json +++ b/govtool/frontend/package.json @@ -1,7 +1,7 @@ { "name": "@govtool/frontend", "private": true, - "version": "2.0.3", + "version": "2.0.4", "type": "module", "scripts": { "build": "vite build", @@ -25,7 +25,7 @@ "dependencies": { "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", - "@emurgo/cardano-serialization-lib-asmjs": "^13.1.0", + "@emurgo/cardano-serialization-lib-asmjs": "^12.1.1", "@hookform/resolvers": "^3.3.1", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", "@intersect.mbo/pdf-ui": "^0.5.5", @@ -112,6 +112,5 @@ "typescript": "^5.0.2", "nth-check": "^2.0.1", "postcss": "^8.4.31" - }, - "_id": "govtool@2.0.3" + } } diff --git a/govtool/frontend/patches/@emurgo+cardano-serialization-lib-asmjs+13.2.0.patch b/govtool/frontend/patches/@emurgo+cardano-serialization-lib-asmjs+12.1.1.patch similarity index 100% rename from govtool/frontend/patches/@emurgo+cardano-serialization-lib-asmjs+13.2.0.patch rename to govtool/frontend/patches/@emurgo+cardano-serialization-lib-asmjs+12.1.1.patch diff --git a/govtool/frontend/src/components/organisms/DRepCard.tsx b/govtool/frontend/src/components/organisms/DRepCard.tsx index 75f17b725..8a64f63d5 100644 --- a/govtool/frontend/src/components/organisms/DRepCard.tsx +++ b/govtool/frontend/src/components/organisms/DRepCard.tsx @@ -34,6 +34,7 @@ export const DRepCard = ({ metadataStatus, image, drepId, + isScriptBased, }, isConnected, isDelegationLoading, @@ -59,8 +60,8 @@ export const DRepCard = ({ }); const cip129Identifier = encodeCIP129Identifier({ - txID: `22${drepId}`, - bech32Prefix: "drep", + txID: `${isScriptBased ? "23" : "22"}${drepId}`, + bech32Prefix: isScriptBased ? "drep_script" : "drep", }); return ( diff --git a/govtool/frontend/src/components/organisms/DRepDetailsCard.tsx b/govtool/frontend/src/components/organisms/DRepDetailsCard.tsx index 196802c30..db673d200 100644 --- a/govtool/frontend/src/components/organisms/DRepDetailsCard.tsx +++ b/govtool/frontend/src/components/organisms/DRepDetailsCard.tsx @@ -47,6 +47,7 @@ export const DRepDetailsCard = ({ view, drepId, votingPower, + isScriptBased, } = dRepData; const groupedReferences = references?.reduce>( @@ -120,8 +121,8 @@ export const DRepDetailsCard = ({ > diff --git a/govtool/frontend/src/components/organisms/DashboardGovernanceActions.tsx b/govtool/frontend/src/components/organisms/DashboardGovernanceActions.tsx index 45b466475..3bcf8bb90 100644 --- a/govtool/frontend/src/components/organisms/DashboardGovernanceActions.tsx +++ b/govtool/frontend/src/components/organisms/DashboardGovernanceActions.tsx @@ -67,7 +67,8 @@ const StyledTab = styled((props: StyledTabProps) => ( })); export const DashboardGovernanceActions = () => { - const { debouncedSearchText, ...dataActionsBarProps } = useDataActionsBar(); + const { debouncedSearchText, isAdjusting, ...dataActionsBarProps } = + useDataActionsBar(); const { chosenFilters, chosenSorting } = dataActionsBarProps; const { voter } = useGetVoterInfo(); const { isMobile } = useScreenDimension(); @@ -81,6 +82,7 @@ export const DashboardGovernanceActions = () => { filters: queryFilters, sorting: chosenSorting, searchPhrase: debouncedSearchText, + enabled: !isAdjusting, }); const { state } = useLocation(); diff --git a/govtool/frontend/src/components/organisms/Footer.tsx b/govtool/frontend/src/components/organisms/Footer.tsx index 84b1e063d..984d12a54 100644 --- a/govtool/frontend/src/components/organisms/Footer.tsx +++ b/govtool/frontend/src/components/organisms/Footer.tsx @@ -63,7 +63,7 @@ export const Footer = () => { }} > - {t("footer.copyright")} + {t("footer.copyright", { year: new Date().getFullYear() })} = ({ children }) => { + const [isAdjusting, setIsAdjusting] = useState(true); const [searchText, setSearchText] = useState(""); const debouncedSearchText = useDebounce(searchText, 300); const [filtersOpen, setFiltersOpen] = useState(false); @@ -62,6 +64,7 @@ const DataActionsBarProvider: FC = ({ children }) => { setSearchText(""); setChosenFilters([]); setChosenSorting(""); + setIsAdjusting(false); }, []); const userMovedToDifferentAppArea = @@ -74,6 +77,7 @@ const DataActionsBarProvider: FC = ({ children }) => { pathname.includes("governance_actions/category"); useEffect(() => { + setIsAdjusting(true); if ( (!pathname.includes("drep_directory") && userMovedToDifferentAppArea && @@ -90,6 +94,7 @@ const DataActionsBarProvider: FC = ({ children }) => { const contextValue = useMemo( () => ({ + isAdjusting, chosenFilters, chosenFiltersLength: chosenFilters.length, chosenSorting, @@ -106,6 +111,7 @@ const DataActionsBarProvider: FC = ({ children }) => { sortOpen, }), [ + isAdjusting, chosenFilters, chosenSorting, debouncedSearchText, diff --git a/govtool/frontend/src/hooks/queries/useGetProposalsQuery.ts b/govtool/frontend/src/hooks/queries/useGetProposalsQuery.ts index f8f0ce857..6843f76af 100644 --- a/govtool/frontend/src/hooks/queries/useGetProposalsQuery.ts +++ b/govtool/frontend/src/hooks/queries/useGetProposalsQuery.ts @@ -10,6 +10,7 @@ export const useGetProposalsQuery = ({ filters = [], searchPhrase, sorting, + enabled, }: GetProposalsArguments) => { const { dRepID, pendingTransaction } = useCardano(); const { voter } = useGetVoterInfo(); @@ -42,6 +43,9 @@ export const useGetProposalsQuery = ({ pendingTransaction.vote?.transactionHash, ], fetchProposals, + { + enabled, + }, ); const proposals = Object.values(groupByType(data) ?? []); diff --git a/govtool/frontend/src/i18n/locales/en.json b/govtool/frontend/src/i18n/locales/en.json index 19bef3aeb..d3faf4074 100644 --- a/govtool/frontend/src/i18n/locales/en.json +++ b/govtool/frontend/src/i18n/locales/en.json @@ -292,7 +292,7 @@ } }, "footer": { - "copyright": "© 2024 Intersect MBO", + "copyright": "© {{year}} Intersect MBO", "privacyPolicy": "Privacy policy", "termOfService": "Terms of Use" }, diff --git a/govtool/frontend/src/services/requests/getDRepList.ts b/govtool/frontend/src/services/requests/getDRepList.ts index 835894481..b61707411 100644 --- a/govtool/frontend/src/services/requests/getDRepList.ts +++ b/govtool/frontend/src/services/requests/getDRepList.ts @@ -1,4 +1,3 @@ -import { bech32 } from "bech32"; import { type Infinite, type DRepStatus, @@ -7,11 +6,7 @@ import { DrepDataDTO, } from "@models"; import { API } from "../API"; -import { - decodeCIP129Identifier, - encodeCIP129Identifier, - mapDtoToDrep, -} from "@/utils"; +import { dRepSearchPhraseProcessor, mapDtoToDrep } from "@/utils"; export type GetDRepListArguments = { filters?: string[]; @@ -30,37 +25,7 @@ export const getDRepList = async ({ searchPhrase: rawSearchPhrase = "", status = [], }: GetDRepListArguments): Promise> => { - // DBSync contains wrong representation of DRep view for script based DReps, - // but it's still used by BE - const searchPhraseProcessor = async () => { - try { - if (rawSearchPhrase.startsWith("drep_script")) { - const { words } = bech32.decode(rawSearchPhrase); - return bech32.encode("drep", words); - } - if (rawSearchPhrase.startsWith("drep")) { - const decodedIdentifier = decodeCIP129Identifier(rawSearchPhrase); - if (decodedIdentifier) { - const isCIP129Identifier = decodedIdentifier.txID.startsWith("22"); - if (isCIP129Identifier) { - return encodeCIP129Identifier({ - txID: decodedIdentifier.txID.slice(2), - bech32Prefix: "drep", - }); - } - return encodeCIP129Identifier({ - txID: decodedIdentifier.txID, - bech32Prefix: "drep", - }); - } - } - return rawSearchPhrase; - } catch (e) { - return rawSearchPhrase; - } - }; - - const searchPhrase = await searchPhraseProcessor(); + const searchPhrase = await dRepSearchPhraseProcessor(rawSearchPhrase); const response = await API.get>("/drep/list", { params: { diff --git a/govtool/frontend/src/services/requests/getProposals.ts b/govtool/frontend/src/services/requests/getProposals.ts index 9e9fef4d0..9d09751be 100644 --- a/govtool/frontend/src/services/requests/getProposals.ts +++ b/govtool/frontend/src/services/requests/getProposals.ts @@ -14,6 +14,7 @@ export type GetProposalsArguments = { pageSize?: number; sorting?: string; searchPhrase?: string; + enabled?: boolean; }; export const getProposals = async ({ diff --git a/govtool/frontend/src/utils/drepSearchPhraseProcessor.ts b/govtool/frontend/src/utils/drepSearchPhraseProcessor.ts new file mode 100644 index 000000000..49befcb72 --- /dev/null +++ b/govtool/frontend/src/utils/drepSearchPhraseProcessor.ts @@ -0,0 +1,33 @@ +import { decodeCIP129Identifier } from "./cip129identifier"; + +/** + * Processes the search phrase for dRep and returns the dRep ID. + * If the phrase starts with "drep_script" or "drep", + * it decodes the CIP129 identifier and extracts the transaction ID. + * If the DRep ID starts with "22" or "23", it returns the ID without the prefix. + * If any error occurs during processing, it returns the original phrase. + * + * @param phrase - The search phrase to be processed. + * @returns The dRep ID extracted from the search phrase or the original phrase if an error occurs. + */ +export const dRepSearchPhraseProcessor = async (phrase: string) => { + let drepIDPhrase = phrase; + + try { + if ( + drepIDPhrase.startsWith("drep_script") || + drepIDPhrase.startsWith("drep") + ) { + const { txID } = decodeCIP129Identifier(drepIDPhrase); + + drepIDPhrase = txID; + } + if (drepIDPhrase.startsWith("22") || drepIDPhrase.startsWith("23")) { + return drepIDPhrase.slice(2); + } + + return drepIDPhrase; + } catch (e) { + return phrase; + } +}; diff --git a/govtool/frontend/src/utils/index.ts b/govtool/frontend/src/utils/index.ts index af99375d3..c2ee4a045 100644 --- a/govtool/frontend/src/utils/index.ts +++ b/govtool/frontend/src/utils/index.ts @@ -8,6 +8,7 @@ export * from "./checkIsMaintenanceOn"; export * from "./checkIsWalletConnected"; export * from "./cip129identifier"; export * from "./dRep"; +export * from "./drepSearchPhraseProcessor"; export * from "./ellipsizeText"; export * from "./filterOutNullParams"; export * from "./filterUpdatableProtocolParams"; @@ -33,5 +34,5 @@ export * from "./removeDuplicatedProposals"; export * from "./removeMarkdown"; export * from "./setProtocolParameterUpdate"; export * from "./testIdFromLabel"; -export * from "./wait"; export * from "./uniqBy"; +export * from "./wait"; diff --git a/govtool/frontend/src/utils/isValidFormat.ts b/govtool/frontend/src/utils/isValidFormat.ts index 96b6a6bd1..34ffb841a 100644 --- a/govtool/frontend/src/utils/isValidFormat.ts +++ b/govtool/frontend/src/utils/isValidFormat.ts @@ -1,5 +1,6 @@ import { Address, + DRep, RewardAddress, } from "@emurgo/cardano-serialization-lib-asmjs"; import i18n from "@/i18n"; @@ -52,3 +53,13 @@ export async function isReceivingAddress(address?: string) { return i18n.t("forms.errors.mustBeReceivingAddress"); } } + +export async function isDRepView(view?: string) { + if (!view) { + return true; + } + if (DRep.from_bech32(view)) { + return true; + } + return i18n.t("forms.errors.mustBeDRepView"); +} diff --git a/govtool/frontend/storybook.Dockerfile b/govtool/frontend/storybook.Dockerfile index d4eb64ffc..a12840ad9 100644 --- a/govtool/frontend/storybook.Dockerfile +++ b/govtool/frontend/storybook.Dockerfile @@ -16,6 +16,8 @@ FROM node:18-alpine as builder ARG NPMRC_TOKEN WORKDIR /src +ENV NODE_OPTIONS="--max-old-space-size=4096" + COPY --from=deps /src/node_modules ./node_modules COPY . . diff --git a/govtool/metadata-validation/package-lock.json b/govtool/metadata-validation/package-lock.json index 657acb1f5..2e591d76f 100644 --- a/govtool/metadata-validation/package-lock.json +++ b/govtool/metadata-validation/package-lock.json @@ -1,12 +1,12 @@ { "name": "@govtool/metadata-validation", - "version": "2.0.3", + "version": "2.0.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@govtool/metadata-validation", - "version": "2.0.3", + "version": "2.0.4", "license": "UNLICENSED", "dependencies": { "@nestjs/axios": "^3.0.2", diff --git a/govtool/metadata-validation/package.json b/govtool/metadata-validation/package.json index 90838c945..94e477b1a 100644 --- a/govtool/metadata-validation/package.json +++ b/govtool/metadata-validation/package.json @@ -1,6 +1,6 @@ { "name": "@govtool/metadata-validation", - "version": "2.0.3", + "version": "2.0.4", "description": "", "author": "", "private": true, diff --git a/govtool/metadata-validation/src/app.service.ts b/govtool/metadata-validation/src/app.service.ts index 8955db611..a44669a89 100644 --- a/govtool/metadata-validation/src/app.service.ts +++ b/govtool/metadata-validation/src/app.service.ts @@ -32,6 +32,8 @@ export class AppService { this.httpService .get(url, { headers: { + // Required to not being blocked by APIs that require a User-Agent + 'User-Agent': 'GovTool/Metadata-Validation-Tool', 'Content-Type': 'application/json', ...(isIPFS && process.env.IPFS_PROJECT_ID && { diff --git a/govtool/metadata-validation/src/main.ts b/govtool/metadata-validation/src/main.ts index f010743e6..b072c9977 100644 --- a/govtool/metadata-validation/src/main.ts +++ b/govtool/metadata-validation/src/main.ts @@ -13,7 +13,7 @@ async function bootstrap() { const config = new DocumentBuilder() .setTitle('Metadata Validation Tool') .setDescription('The Metadata Validation Tool API description') - .setVersion('2.0.3') + .setVersion('2.0.4') .build(); const document = SwaggerModule.createDocument(app, config); diff --git a/tests/govtool-frontend/playwright/lib/_mock/index.ts b/tests/govtool-frontend/playwright/lib/_mock/index.ts index 23c200604..3aff590cf 100644 --- a/tests/govtool-frontend/playwright/lib/_mock/index.ts +++ b/tests/govtool-frontend/playwright/lib/_mock/index.ts @@ -1,5 +1,6 @@ import { faker } from "@faker-js/faker"; import { generateExactLengthText } from "@helpers/string"; +import { imageObject } from "@types"; export const invalid = { url: (isSupportedGreaterThan128Words = true) => { @@ -139,8 +140,9 @@ export const valid = { return `ipfs://${randomCID}`; }, - metadata: (paymentAddress: string) => ({ + metadata: (paymentAddress: string, imageObject: imageObject) => ({ "@context": { + "@language": "en-us", CIP100: "https://github.com/cardano-foundation/CIPs/blob/master/CIP-0100/README.md#", CIP119: @@ -170,7 +172,12 @@ export const valid = { }, paymentAddress: "CIP119:paymentAddress", givenName: "CIP119:givenName", - image: "CIP119:image", + image: { + "@id": "CIP119:image", + "@context": { + ImageObject: "https://schema.org/ImageObject", + }, + }, objectives: "CIP119:objectives", motivations: "CIP119:motivations", qualifications: "CIP119:qualifications", @@ -197,6 +204,7 @@ export const valid = { hashAlgorithm: "blake2b-256", body: { givenName: faker.person.firstName(), + image: imageObject, motivations: faker.lorem.paragraph(2), objectives: faker.lorem.paragraph(2), paymentAddress: paymentAddress, diff --git a/tests/govtool-frontend/playwright/lib/helpers/dRep.ts b/tests/govtool-frontend/playwright/lib/helpers/dRep.ts index 33b6b1823..eab856f71 100644 --- a/tests/govtool-frontend/playwright/lib/helpers/dRep.ts +++ b/tests/govtool-frontend/playwright/lib/helpers/dRep.ts @@ -37,3 +37,26 @@ export async function fetchFirstActiveDRepDetails(page: Page) { await dRepDirectoryPage.searchInput.click(); return { dRepGivenName, dRepId, dRepDirectoryPage }; } + +export async function calculateImageSHA256(imageUrl: string) { + const toHex = (buffer: ArrayBuffer) => { + return Array.from(new Uint8Array(buffer)) + .map((byte) => byte.toString(16).padStart(2, "0")) + .join(""); + }; + try { + if (imageUrl == "") { + return ""; + } + const response = await fetch(imageUrl); + if (!response.ok) { + throw new Error(`Failed to fetch image: ${response.statusText}`); + } + const arrayBuffer = await response.arrayBuffer(); + const hashBuffer = await crypto.subtle.digest("SHA-256", arrayBuffer); + return toHex(hashBuffer); + } catch (error) { + console.error("Error calculating SHA256:", error); + return null; + } +} diff --git a/tests/govtool-frontend/playwright/lib/helpers/featureFlag.ts b/tests/govtool-frontend/playwright/lib/helpers/featureFlag.ts index 0a6f1576e..936b36bc0 100644 --- a/tests/govtool-frontend/playwright/lib/helpers/featureFlag.ts +++ b/tests/govtool-frontend/playwright/lib/helpers/featureFlag.ts @@ -18,11 +18,7 @@ export const areDRepVoteTotalsDisplayed = async (proposal: IProposal) => { ); } - return ![ - GovernanceActionType.NoConfidence, - GovernanceActionType.NewCommittee, - GovernanceActionType.UpdatetotheConstitution, - ].includes(proposal.type as GovernanceActionType); + return true; }; export const areSPOVoteTotalsDisplayed = async (proposal: IProposal) => { diff --git a/tests/govtool-frontend/playwright/lib/helpers/metadata.ts b/tests/govtool-frontend/playwright/lib/helpers/metadata.ts index 567b147f1..08eb1ee7d 100644 --- a/tests/govtool-frontend/playwright/lib/helpers/metadata.ts +++ b/tests/govtool-frontend/playwright/lib/helpers/metadata.ts @@ -6,6 +6,8 @@ const blake = require("blakejs"); import * as fs from "fs"; import { ShelleyWallet } from "./crypto"; +import { calculateImageSHA256 } from "./dRep"; +import { imageObject } from "@types"; export async function downloadMetadata(download: Download): Promise<{ name: string; @@ -21,7 +23,18 @@ export async function downloadMetadata(download: Download): Promise<{ async function calculateMetadataHash() { try { const paymentAddress = (await ShelleyWallet.generate()).addressBech32(0); - const data = JSON.stringify(mockValid.metadata(paymentAddress), null, 2); + const imageUrl = faker.image.avatarGitHub(); + const imageSHA256 = (await calculateImageSHA256(imageUrl)) || ""; + const imageObject: imageObject = { + "@type": "ImageObject", + contentUrl: imageUrl, + sha256: imageSHA256, + }; + const data = JSON.stringify( + mockValid.metadata(paymentAddress, imageObject), + null, + 2 + ); const buffer = Buffer.from(data, "utf8"); const hexDigest = blake.blake2bHex(buffer, null, 32); diff --git a/tests/govtool-frontend/playwright/lib/pages/governanceActionsPage.ts b/tests/govtool-frontend/playwright/lib/pages/governanceActionsPage.ts index 1bbb69179..6df0d4ef9 100644 --- a/tests/govtool-frontend/playwright/lib/pages/governanceActionsPage.ts +++ b/tests/govtool-frontend/playwright/lib/pages/governanceActionsPage.ts @@ -1,10 +1,6 @@ import removeAllSpaces from "@helpers/removeAllSpaces"; import { Locator, Page, expect } from "@playwright/test"; -import { - FullGovernanceDRepVoteActionsType, - GovernanceActionType, - IProposal, -} from "@types"; +import { GovernanceActionType, IProposal } from "@types"; import environments from "lib/constants/environments"; import GovernanceActionDetailsPage from "./governanceActionDetailsPage"; import { getEnumKeyByValue } from "@helpers/enum"; @@ -51,20 +47,6 @@ export default class GovernanceActionsPage { return new GovernanceActionDetailsPage(this.page); } - async viewFirstDRepVoteEnabledGovernanceAction(): Promise { - for (const governanceAction of Object.keys( - FullGovernanceDRepVoteActionsType - )) { - const result = await this.viewFirstProposalByGovernanceAction( - governanceAction as GovernanceActionType - ); - if (result) { - return result; - } - } - return null; - } - async viewFirstProposalByGovernanceAction( governanceAction: GovernanceActionType ): Promise { diff --git a/tests/govtool-frontend/playwright/lib/types.ts b/tests/govtool-frontend/playwright/lib/types.ts index 5c6853d2a..ed1c6b8bf 100644 --- a/tests/govtool-frontend/playwright/lib/types.ts +++ b/tests/govtool-frontend/playwright/lib/types.ts @@ -237,3 +237,9 @@ export type EpochParams = { pvtpp_security_group: number | null; treasury_growth_rate: number | null; }; + +export interface imageObject { + "@type": "ImageObject"; + contentUrl: string; + sha256: string; +} diff --git a/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.dRep.spec.ts b/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.dRep.spec.ts index 8e532d35f..c49773786 100644 --- a/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.dRep.spec.ts +++ b/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.dRep.spec.ts @@ -14,11 +14,7 @@ import { createNewPageWithWallet } from "@helpers/page"; import GovernanceActionsPage from "@pages/governanceActionsPage"; import { Page, expect } from "@playwright/test"; import { invalid as mockInvalid, valid as mockValid } from "@mock/index"; -import { - FullGovernanceDRepVoteActionsType, - GovernanceActionType, - IProposal, -} from "@types"; +import { GovernanceActionType, IProposal } from "@types"; import walletManager from "lib/walletManager"; import GovernanceActionDetailsPage from "@pages/governanceActionDetailsPage"; import { correctVoteAdaFormat } from "@helpers/adaFormat"; @@ -67,7 +63,7 @@ test.describe("Logged in DRep", () => { ? await govActionsPage.viewFirstProposalByGovernanceAction( GovernanceActionType.InfoAction ) - : await govActionsPage.viewFirstDRepVoteEnabledGovernanceAction(); + : await govActionsPage.viewFirstProposal(); await govActionDetailsPage.contextBtn.click(); await govActionDetailsPage.contextInput.fill(faker.lorem.sentence(200)); @@ -146,7 +142,7 @@ test.describe("Check vote count", () => { }) => { const voteWhiteListOption = (await isBootStrapingPhase()) ? { InfoAction: "InfoAction" } - : FullGovernanceDRepVoteActionsType; + : GovernanceActionType; const responsesPromise = Object.keys(voteWhiteListOption).map((filterKey) => page.waitForResponse((response) => response.url().includes(`&type[]=${voteWhiteListOption[filterKey]}`) diff --git a/tests/govtool-frontend/playwright/tests/5-proposal-functionality/proposalFunctionality.dRep.spec.ts b/tests/govtool-frontend/playwright/tests/5-proposal-functionality/proposalFunctionality.dRep.spec.ts index 1fb3059d6..505ddcb85 100644 --- a/tests/govtool-frontend/playwright/tests/5-proposal-functionality/proposalFunctionality.dRep.spec.ts +++ b/tests/govtool-frontend/playwright/tests/5-proposal-functionality/proposalFunctionality.dRep.spec.ts @@ -45,7 +45,7 @@ test.describe("Proposal checks", () => { ? await govActionsPage.viewFirstProposalByGovernanceAction( GovernanceActionType.InfoAction ) - : await govActionsPage.viewFirstDRepVoteEnabledGovernanceAction(); + : await govActionsPage.viewFirstProposal(); }); test("5A. Should show relevant details about governance action as DRep", async () => { @@ -157,7 +157,7 @@ test.describe("Perform voting", () => { ? await govActionsPage.viewFirstProposalByGovernanceAction( GovernanceActionType.InfoAction ) - : await govActionsPage.viewFirstDRepVoteEnabledGovernanceAction(); + : await govActionsPage.viewFirstProposal(); }); test("5E. Should re-vote with new data on a already voted governance action", async ({}, testInfo) => {