From ac381006947c9181c0054453884f0277042153fa Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Mon, 5 Aug 2024 14:44:08 +0100 Subject: [PATCH 01/15] fix: frontend votes info copy and other minor spelling in copu --- CHANGELOG.md | 2 +- govtool/frontend/src/i18n/locales/en.ts | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5a7d62a5..b414a208f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ changes. ### Fixed -- +- Incorrect copy on DRep votes + other minor copy spelling mistakes ### Changed diff --git a/govtool/frontend/src/i18n/locales/en.ts b/govtool/frontend/src/i18n/locales/en.ts index 9d85b6baf..595ec7043 100644 --- a/govtool/frontend/src/i18n/locales/en.ts +++ b/govtool/frontend/src/i18n/locales/en.ts @@ -310,11 +310,11 @@ export const en = { dRep: { description: { notVerifiable: - "GovTool uses external sources for DRep data, and these sources are maintianed by the DReps themselves. This error means that the data stored by the DRep does not match the data supplied by the DRep when they originally registered", + "GovTool uses external sources for DRep data, and these sources are maintained by the DReps themselves. This error means that the data stored by the DRep does not match the data supplied by the DRep when they originally registered", dataMissing: - "GovTool uses external sources for DRep data, and these sources are maintianed by the DReps themselves. This error means that GovTool cannot locate the data on the URL specified when the DRep was originally registered.", + "GovTool uses external sources for DRep data, and these sources are maintained by the DReps themselves. This error means that GovTool cannot locate the data on the URL specified when the DRep was originally registered.", incorrectFormat: - "GovTool uses external sources for DRep data, and these sources are maintianed by the DReps themselves. This error means that the data stored by the DRep does not match the format defined by the DRep spec.", + "GovTool uses external sources for DRep data, and these sources are maintained by the DReps themselves. This error means that the data stored by the DRep does not match the format defined by the DRep spec.", }, message: { notVerifiable: @@ -440,15 +440,15 @@ export const en = { voteSubmitted: "Vote submitted", voteTransaction: "Vote transaction", votes: "Votes:", - votesSubmitted: "Votes submitted", + votesSubmitted: "DRep votes submitted", votesSubmittedOnChain: - "Votes submitted on-chain by DReps, SPOs and Constitutional Committee members.", + "Votes submitted on-chain by DReps and predefined voting options.", youCanProvideContext: "You can provide context about your vote. This information will be viewable by other users.", youHaventVotedYet: "You haven't voted on any Governance Actions yet. Check the 'To vote on' section to vote on Governance Actions.", withCategoryNotExist: { - partOne: "Governnance actions with category", + partOne: "Governance actions with category", optional: "and search phrase", partTwo: "don't exist.", }, From 88ddda6475511a4c3bfd62d4fefeb277a0315dd5 Mon Sep 17 00:00:00 2001 From: niraj Date: Mon, 5 Aug 2024 18:47:22 +0545 Subject: [PATCH 02/15] chore: add mock metadata with random value --- .../playwright/lib/_mock/index.ts | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/tests/govtool-frontend/playwright/lib/_mock/index.ts b/tests/govtool-frontend/playwright/lib/_mock/index.ts index c19ae407f..30c278935 100644 --- a/tests/govtool-frontend/playwright/lib/_mock/index.ts +++ b/tests/govtool-frontend/playwright/lib/_mock/index.ts @@ -113,4 +113,82 @@ export const valid = { return username; }, + metadata: () => { + return { + "@context": { + "@language": "en-us", + CIP100: + "https://github.com/cardano-foundation/CIPs/blob/master/CIP-0100/README.md#", + CIPQQQ: + "https://github.com/cardano-foundation/CIPs/blob/master/CIP-QQQ/README.md#", + hashAlgorithm: "CIP100:hashAlgorithm", + body: { + "@id": "CIPQQQ:body", + "@context": { + references: { + "@id": "CIPQQQ:references", + "@container": "@set", + "@context": { + GovernanceMetadata: "CIP100:GovernanceMetadataReference", + Other: "CIP100:OtherReference", + label: "CIP100:reference-label", + uri: "CIP100:reference-uri", + referenceHash: { + "@id": "CIPQQQ:referenceHash", + "@context": { + hashDigest: "CIPQQQ:hashDigest", + hashAlgorithm: "CIP100:hashAlgorithm", + }, + }, + }, + }, + dRepName: "CIPQQQ:dRepName", + bio: "CIPQQQ:bio", + email: "CIPQQQ:email", + }, + }, + authors: { + "@id": "CIP100:authors", + "@container": "@set", + "@context": { + name: "http://xmlns.com/foaf/0.1/name", + witness: { + "@id": "CIP100:witness", + "@context": { + witnessAlgorithm: "CIP100:witnessAlgorithm", + publicKey: "CIP100:publicKey", + signature: "CIP100:signature", + }, + }, + }, + }, + }, + authors: [], + hashAlgorithm: { + "@value": "blake2b-256", + }, + body: { + bio: { + "@value": faker.lorem.sentences(), + }, + dRepName: { + "@value": faker.person.firstName(), + }, + email: { + "@value": faker.internet.email(), + }, + references: [ + { + "@type": "Other", + label: { + "@value": "Label", + }, + uri: { + "@value": faker.internet.url(), + }, + }, + ], + }, + }; + }, }; From 82061bb9334db83e0fa17c0d2cad48f63ae23194 Mon Sep 17 00:00:00 2001 From: niraj Date: Mon, 5 Aug 2024 18:48:14 +0545 Subject: [PATCH 03/15] chore: add function to upload mock metadata and calculate hash --- .../playwright/lib/helpers/metadata.ts | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/govtool-frontend/playwright/lib/helpers/metadata.ts b/tests/govtool-frontend/playwright/lib/helpers/metadata.ts index 9c3657f95..80f929e4a 100644 --- a/tests/govtool-frontend/playwright/lib/helpers/metadata.ts +++ b/tests/govtool-frontend/playwright/lib/helpers/metadata.ts @@ -1,5 +1,11 @@ +import { faker } from "@faker-js/faker"; +import { valid as mockValid } from "@mock/index"; import { Download } from "@playwright/test"; +import metadataBucketService from "@services/metadataBucketService"; +const blake = require("blakejs"); + import * as fs from "fs"; +import path = require("path"); export async function downloadMetadata(download: Download): Promise<{ name: string; @@ -11,3 +17,29 @@ export async function downloadMetadata(download: Download): Promise<{ const jsonData = JSON.parse(fileContent); return { name: download.suggestedFilename(), data: jsonData }; } + +function calculateMetadataHash() { + try { + // Get the JSON data as a string + const data = JSON.stringify(mockValid.metadata()); + + // Convert the string to a buffer + const buffer = Buffer.from(data, "utf8"); + const hexDigest = blake.blake2bHex(buffer, null, 32); + + // Parse the JSON data + const jsonData = JSON.parse(data); + return { hexDigest, jsonData }; + } catch (error) { + console.error("Error reading file:", error); + } +} + +export async function uploadMetadataAndGetJsonHash() { + const { hexDigest: dataHash, jsonData } = calculateMetadataHash(); + const url = await metadataBucketService.uploadMetadata( + faker.person.firstName(), + jsonData + ); + return { dataHash, url }; +} From 3a9fe6eb2e3ca1fc2a1dac1e2d9bc29344d1bd69 Mon Sep 17 00:00:00 2001 From: niraj Date: Mon, 5 Aug 2024 18:51:25 +0545 Subject: [PATCH 04/15] chore: update register dRep anchor with uploaded metadata URL and generated data hash. --- .../playwright/lib/helpers/transaction.ts | 10 ++++- .../playwright/lib/services/kuberService.ts | 41 +++++++++++++------ .../govtool-frontend/playwright/lib/types.ts | 6 +++ .../playwright/tests/dRep.setup.ts | 22 ++++++++-- 4 files changed, 63 insertions(+), 16 deletions(-) diff --git a/tests/govtool-frontend/playwright/lib/helpers/transaction.ts b/tests/govtool-frontend/playwright/lib/helpers/transaction.ts index e8a04e3fc..5cc321295 100644 --- a/tests/govtool-frontend/playwright/lib/helpers/transaction.ts +++ b/tests/govtool-frontend/playwright/lib/helpers/transaction.ts @@ -5,6 +5,8 @@ import { LockInterceptor, LockInterceptorInfo } from "lib/lockInterceptor"; import { Logger } from "../../../cypress/lib/logger/logger"; import convertBufferToHex from "./convertBufferToHex"; import { ShelleyWallet } from "./crypto"; +import { uploadMetadataAndGetJsonHash } from "./metadata"; +import { WalletAndAnchorType } from "@types"; /** * Polls the transaction status until it's resolved or times out. @@ -112,9 +114,15 @@ export async function transferAdaForWallet( } export async function registerDRepForWallet(wallet: ShelleyWallet) { + const dataHashAndUrl = await uploadMetadataAndGetJsonHash(); + const metadataAnchorAndWallet: WalletAndAnchorType = { + ...dataHashAndUrl, + wallet: wallet.json(), + }; const registrationRes = await kuberService.dRepRegistration( convertBufferToHex(wallet.stakeKey.private), - convertBufferToHex(wallet.stakeKey.pkh) + convertBufferToHex(wallet.stakeKey.pkh), + metadataAnchorAndWallet ); await pollTransaction(registrationRes.txId, registrationRes.lockInfo); } diff --git a/tests/govtool-frontend/playwright/lib/services/kuberService.ts b/tests/govtool-frontend/playwright/lib/services/kuberService.ts index c0d4acf35..ceeff4714 100644 --- a/tests/govtool-frontend/playwright/lib/services/kuberService.ts +++ b/tests/govtool-frontend/playwright/lib/services/kuberService.ts @@ -1,5 +1,10 @@ import { faucetWallet } from "@constants/staticWallets"; -import { KuberValue, ProtocolParams, StaticWallet } from "@types"; +import { + KuberValue, + ProtocolParams, + StaticWallet, + WalletAndAnchorType, +} from "@types"; import * as blake from "blakejs"; import environments from "lib/constants/environments"; import { LockInterceptor, LockInterceptorInfo } from "lib/lockInterceptor"; @@ -37,7 +42,11 @@ class Kuber { this.version = version; } - static generateCert(type: CertificateType, key: string) { + static generateCert( + type: CertificateType, + key: string, + metadata?: WalletAndAnchorType + ) { if (type === "registerstake" || type === "deregisterdrep") { return { type: type, @@ -48,9 +57,8 @@ class Kuber { type: "registerdrep", key: key, anchor: { - url: "https://bit.ly/3zCH2HL", - dataHash: - "1111111111111111111111111111111111111111111111111111111111111111", + url: metadata?.url || "", + dataHash: metadata?.dataHash || "", }, }; } @@ -178,27 +186,36 @@ const kuberService = { return kuber.signAndSubmitTx(req); }, - multipleDRepRegistration: (wallets: StaticWallet[]) => { + multipleDRepRegistration: (metadatasAndWallets: WalletAndAnchorType[]) => { const kuber = new Kuber(faucetWallet.address, faucetWallet.payment.private); const req = { - certificates: wallets.map((wallet) => - Kuber.generateCert("registerdrep", wallet.stake.pkh) + certificates: metadatasAndWallets.map((metadataAndWallet) => + Kuber.generateCert( + "registerdrep", + metadataAndWallet.wallet.stake.pkh, + metadataAndWallet + ) ), - selections: wallets.map((wallet) => { + selections: metadatasAndWallets.map((metadata) => { return { type: "PaymentSigningKeyShelley_ed25519", description: "Stake Signing Key", - cborHex: `5820${wallet.stake.private}`, + cborHex: `5820${metadata.wallet.stake.private}`, }; }), }; return kuber.signAndSubmitTx(req); }, - dRepRegistration: (stakeSigningKey: string, pkh: string) => { + dRepRegistration: ( + stakeSigningKey: string, + pkh: string, + metadata: WalletAndAnchorType + ) => { const kuber = new Kuber(faucetWallet.address, faucetWallet.payment.private); + const req = { - certificates: [Kuber.generateCert("registerdrep", pkh)], + certificates: [Kuber.generateCert("registerdrep", pkh, metadata)], selections: [ { type: "PaymentSigningKeyShelley_ed25519", diff --git a/tests/govtool-frontend/playwright/lib/types.ts b/tests/govtool-frontend/playwright/lib/types.ts index 1b0cf3dfc..186d4dd7e 100644 --- a/tests/govtool-frontend/playwright/lib/types.ts +++ b/tests/govtool-frontend/playwright/lib/types.ts @@ -137,3 +137,9 @@ export type ProposedGovAction = { updatedAt: string; }; }; + +export type WalletAndAnchorType = { + url: string; + dataHash: string; + wallet: StaticWallet; +}; diff --git a/tests/govtool-frontend/playwright/tests/dRep.setup.ts b/tests/govtool-frontend/playwright/tests/dRep.setup.ts index 068ebaa6c..840e47d75 100644 --- a/tests/govtool-frontend/playwright/tests/dRep.setup.ts +++ b/tests/govtool-frontend/playwright/tests/dRep.setup.ts @@ -2,6 +2,7 @@ import environments from "@constants/environments"; import { dRepWallets } from "@constants/staticWallets"; import { setAllureEpic, setAllureStory } from "@helpers/allure"; import { ShelleyWallet } from "@helpers/crypto"; +import { uploadMetadataAndGetJsonHash } from "@helpers/metadata"; import { pollTransaction } from "@helpers/transaction"; import { expect, test as setup } from "@playwright/test"; import kuberService from "@services/kuberService"; @@ -34,7 +35,15 @@ setup("Register DRep of static wallets", async () => { setup.setTimeout(environments.txTimeOut); try { - const res = await kuberService.multipleDRepRegistration(dRepWallets); + // Submit metadata to obtain a URL and generate hash value. + const metadataPromises = dRepWallets.map(async (dRepWallet) => { + return { ...(await uploadMetadataAndGetJsonHash()), wallet: dRepWallet }; + }); + + const metadatasAndDRepWallets = await Promise.all(metadataPromises); + const res = await kuberService.multipleDRepRegistration( + metadatasAndDRepWallets + ); await pollTransaction(res.txId, res.lockInfo); } catch (err) { @@ -64,9 +73,16 @@ setup("Setup temporary DRep wallets", async () => { ]); await pollTransaction(initializeRes.txId, initializeRes.lockInfo); + // Submit metadata to obtain a URL and generate hash value. + const metadataPromises = dRepWallets.map(async (dRepWallet) => { + return { ...(await uploadMetadataAndGetJsonHash()), wallet: dRepWallet }; + }); + + const metadatasAndDRepWallets = await Promise.all(metadataPromises); // register dRep - const registrationRes = - await kuberService.multipleDRepRegistration(dRepWallets); + const registrationRes = await kuberService.multipleDRepRegistration( + metadatasAndDRepWallets + ); await pollTransaction(registrationRes.txId, registrationRes.lockInfo); // transfer 600 ADA for dRep registration From b850faf7f7fad7cd408103e03ab2b69cbf94efdb Mon Sep 17 00:00:00 2001 From: niraj Date: Tue, 6 Aug 2024 10:00:34 +0545 Subject: [PATCH 05/15] chore: refactor naming and valid matadata --- .../playwright/lib/_mock/index.ts | 132 +++++++++--------- .../playwright/lib/helpers/metadata.ts | 4 - .../playwright/lib/services/kuberService.ts | 6 +- .../playwright/tests/dRep.setup.ts | 4 +- 4 files changed, 70 insertions(+), 76 deletions(-) diff --git a/tests/govtool-frontend/playwright/lib/_mock/index.ts b/tests/govtool-frontend/playwright/lib/_mock/index.ts index 30c278935..d8f3a99c1 100644 --- a/tests/govtool-frontend/playwright/lib/_mock/index.ts +++ b/tests/govtool-frontend/playwright/lib/_mock/index.ts @@ -113,82 +113,80 @@ export const valid = { return username; }, - metadata: () => { - return { - "@context": { - "@language": "en-us", - CIP100: - "https://github.com/cardano-foundation/CIPs/blob/master/CIP-0100/README.md#", - CIPQQQ: - "https://github.com/cardano-foundation/CIPs/blob/master/CIP-QQQ/README.md#", - hashAlgorithm: "CIP100:hashAlgorithm", - body: { - "@id": "CIPQQQ:body", - "@context": { - references: { - "@id": "CIPQQQ:references", - "@container": "@set", - "@context": { - GovernanceMetadata: "CIP100:GovernanceMetadataReference", - Other: "CIP100:OtherReference", - label: "CIP100:reference-label", - uri: "CIP100:reference-uri", - referenceHash: { - "@id": "CIPQQQ:referenceHash", - "@context": { - hashDigest: "CIPQQQ:hashDigest", - hashAlgorithm: "CIP100:hashAlgorithm", - }, + metadata: () => ({ + "@context": { + "@language": "en-us", + CIP100: + "https://github.com/cardano-foundation/CIPs/blob/master/CIP-0100/README.md#", + CIPQQQ: + "https://github.com/cardano-foundation/CIPs/blob/master/CIP-QQQ/README.md#", + hashAlgorithm: "CIP100:hashAlgorithm", + body: { + "@id": "CIPQQQ:body", + "@context": { + references: { + "@id": "CIPQQQ:references", + "@container": "@set", + "@context": { + GovernanceMetadata: "CIP100:GovernanceMetadataReference", + Other: "CIP100:OtherReference", + label: "CIP100:reference-label", + uri: "CIP100:reference-uri", + referenceHash: { + "@id": "CIPQQQ:referenceHash", + "@context": { + hashDigest: "CIPQQQ:hashDigest", + hashAlgorithm: "CIP100:hashAlgorithm", }, }, }, - dRepName: "CIPQQQ:dRepName", - bio: "CIPQQQ:bio", - email: "CIPQQQ:email", }, + dRepName: "CIPQQQ:dRepName", + bio: "CIPQQQ:bio", + email: "CIPQQQ:email", }, - authors: { - "@id": "CIP100:authors", - "@container": "@set", - "@context": { - name: "http://xmlns.com/foaf/0.1/name", - witness: { - "@id": "CIP100:witness", - "@context": { - witnessAlgorithm: "CIP100:witnessAlgorithm", - publicKey: "CIP100:publicKey", - signature: "CIP100:signature", - }, + }, + authors: { + "@id": "CIP100:authors", + "@container": "@set", + "@context": { + name: "http://xmlns.com/foaf/0.1/name", + witness: { + "@id": "CIP100:witness", + "@context": { + witnessAlgorithm: "CIP100:witnessAlgorithm", + publicKey: "CIP100:publicKey", + signature: "CIP100:signature", }, }, }, }, - authors: [], - hashAlgorithm: { - "@value": "blake2b-256", + }, + authors: [], + hashAlgorithm: { + "@value": "blake2b-256", + }, + body: { + bio: { + "@value": faker.lorem.sentences(), }, - body: { - bio: { - "@value": faker.lorem.sentences(), - }, - dRepName: { - "@value": faker.person.firstName(), - }, - email: { - "@value": faker.internet.email(), - }, - references: [ - { - "@type": "Other", - label: { - "@value": "Label", - }, - uri: { - "@value": faker.internet.url(), - }, - }, - ], + dRepName: { + "@value": faker.person.firstName(), }, - }; - }, + email: { + "@value": faker.internet.email(), + }, + references: [ + { + "@type": "Other", + label: { + "@value": "Label", + }, + uri: { + "@value": faker.internet.url(), + }, + }, + ], + }, + }), }; diff --git a/tests/govtool-frontend/playwright/lib/helpers/metadata.ts b/tests/govtool-frontend/playwright/lib/helpers/metadata.ts index 80f929e4a..1f87d923b 100644 --- a/tests/govtool-frontend/playwright/lib/helpers/metadata.ts +++ b/tests/govtool-frontend/playwright/lib/helpers/metadata.ts @@ -5,7 +5,6 @@ import metadataBucketService from "@services/metadataBucketService"; const blake = require("blakejs"); import * as fs from "fs"; -import path = require("path"); export async function downloadMetadata(download: Download): Promise<{ name: string; @@ -20,14 +19,11 @@ export async function downloadMetadata(download: Download): Promise<{ function calculateMetadataHash() { try { - // Get the JSON data as a string const data = JSON.stringify(mockValid.metadata()); - // Convert the string to a buffer const buffer = Buffer.from(data, "utf8"); const hexDigest = blake.blake2bHex(buffer, null, 32); - // Parse the JSON data const jsonData = JSON.parse(data); return { hexDigest, jsonData }; } catch (error) { diff --git a/tests/govtool-frontend/playwright/lib/services/kuberService.ts b/tests/govtool-frontend/playwright/lib/services/kuberService.ts index ceeff4714..6ddc81a43 100644 --- a/tests/govtool-frontend/playwright/lib/services/kuberService.ts +++ b/tests/govtool-frontend/playwright/lib/services/kuberService.ts @@ -186,17 +186,17 @@ const kuberService = { return kuber.signAndSubmitTx(req); }, - multipleDRepRegistration: (metadatasAndWallets: WalletAndAnchorType[]) => { + multipleDRepRegistration: (metadataAndWallets: WalletAndAnchorType[]) => { const kuber = new Kuber(faucetWallet.address, faucetWallet.payment.private); const req = { - certificates: metadatasAndWallets.map((metadataAndWallet) => + certificates: metadataAndWallets.map((metadataAndWallet) => Kuber.generateCert( "registerdrep", metadataAndWallet.wallet.stake.pkh, metadataAndWallet ) ), - selections: metadatasAndWallets.map((metadata) => { + selections: metadataAndWallets.map((metadata) => { return { type: "PaymentSigningKeyShelley_ed25519", description: "Stake Signing Key", diff --git a/tests/govtool-frontend/playwright/tests/dRep.setup.ts b/tests/govtool-frontend/playwright/tests/dRep.setup.ts index 840e47d75..b872a7abe 100644 --- a/tests/govtool-frontend/playwright/tests/dRep.setup.ts +++ b/tests/govtool-frontend/playwright/tests/dRep.setup.ts @@ -40,9 +40,9 @@ setup("Register DRep of static wallets", async () => { return { ...(await uploadMetadataAndGetJsonHash()), wallet: dRepWallet }; }); - const metadatasAndDRepWallets = await Promise.all(metadataPromises); + const metadataAndDRepWallets = await Promise.all(metadataPromises); const res = await kuberService.multipleDRepRegistration( - metadatasAndDRepWallets + metadataAndDRepWallets ); await pollTransaction(res.txId, res.lockInfo); From 239bb4ee234080d7abb5ffd87ca47f161a6eb2ac Mon Sep 17 00:00:00 2001 From: niraj Date: Tue, 6 Aug 2024 12:11:58 +0545 Subject: [PATCH 06/15] chore: append a timestamp to valid username and remove unnecessary toLowercase. --- tests/govtool-frontend/playwright/lib/_mock/index.ts | 3 ++- .../tests/6-miscellaneous/miscellaneous.loggedin.spec.ts | 8 ++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/tests/govtool-frontend/playwright/lib/_mock/index.ts b/tests/govtool-frontend/playwright/lib/_mock/index.ts index d8f3a99c1..3fd311429 100644 --- a/tests/govtool-frontend/playwright/lib/_mock/index.ts +++ b/tests/govtool-frontend/playwright/lib/_mock/index.ts @@ -91,7 +91,8 @@ export const invalid = { export const valid = { username: () => { - let username = faker.internet.userName().toLowerCase(); + let timeStamp = Date.now(); + let username = `${faker.internet.userName().toLowerCase()}_${timeStamp}`; // Remove any invalid characters username = username.replace(/[^a-z0-9._]/g, ""); diff --git a/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.loggedin.spec.ts b/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.loggedin.spec.ts index 86722e193..d44d70a5b 100644 --- a/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.loggedin.spec.ts +++ b/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.loggedin.spec.ts @@ -139,9 +139,7 @@ test.describe("Temporary user", () => { test("6K. Should accept valid username.", async () => { for (let i = 0; i < 100; i++) { - await userPage - .getByTestId("username-input") - .fill(mockValid.username().toLowerCase()); + await userPage.getByTestId("username-input").fill(mockValid.username()); await expect( userPage.getByTestId("username-error-text") @@ -152,9 +150,7 @@ test.describe("Temporary user", () => { test("6L. Should reject invalid username.", async () => { for (let i = 0; i < 100; i++) { - await userPage - .getByTestId("username-input") - .fill(mockInvalid.username().toLowerCase()); + await userPage.getByTestId("username-input").fill(mockInvalid.username()); await expect(userPage.getByTestId("username-error-text")).toBeVisible(); await expect(userPage.getByTestId("proceed-button")).toBeDisabled(); From 63a5b0c2d057f9af2f7d23c8ccaa6d5462271fd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Wed, 31 Jul 2024 15:26:20 +0200 Subject: [PATCH 07/15] feat(#1644): add missing network metrics model to frontend service --- CHANGELOG.md | 1 + govtool/frontend/src/models/api.ts | 14 ++++++++++++++ .../src/services/requests/getNetworkMetrics.ts | 3 ++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b414a208f..7b2fca089 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ changes. ### Added - Add network name to GET /network/metrics [Issue 1644](https://github.com/IntersectMBO/govtool/issues/1644) +- Add network metrics model to frontend service ### Fixed diff --git a/govtool/frontend/src/models/api.ts b/govtool/frontend/src/models/api.ts index ed33d9199..d073459ac 100644 --- a/govtool/frontend/src/models/api.ts +++ b/govtool/frontend/src/models/api.ts @@ -1,5 +1,19 @@ import { MetadataValidationStatus } from "@models"; +export type NetworkMetrics = { + currentTime: string; + currentEpoch: number; + currentBlock: number; + uniqueDelegators: number; + totalDelegations: number; + totalGovernanceActions: number; + totalDRepVotes: number; + totalRegisteredDReps: number; + alwaysAbstainVotingPower: number; + alwaysNoConfidenceVotingPower: number; + networkName: string; +}; + export interface VoterInfo { isRegisteredAsDRep: boolean; wasRegisteredAsDRep: boolean; diff --git a/govtool/frontend/src/services/requests/getNetworkMetrics.ts b/govtool/frontend/src/services/requests/getNetworkMetrics.ts index 59fd0c674..33c30a108 100644 --- a/govtool/frontend/src/services/requests/getNetworkMetrics.ts +++ b/govtool/frontend/src/services/requests/getNetworkMetrics.ts @@ -1,7 +1,8 @@ +import { NetworkMetrics } from "@models"; import { API } from "../API"; export const getNetworkMetrics = async () => { - const response = await API.get("/network/metrics"); + const response = await API.get("/network/metrics"); return response.data; }; From 2f3d2f07bf3dc2c1af6c028c8ab44ec0c8f15596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Wed, 31 Jul 2024 14:54:12 +0200 Subject: [PATCH 08/15] chore: remove occurencies of sanchonet from contributing guide --- CONTRIBUTING.md | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b348e3850..ccc9e9126 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,6 +3,7 @@ ⚠️ This is a work in progress document, more instruction on how-to contribute to come! Contributing todo: + - [ ] Align with latest OSC policies - [ ] Refactor to reflect reality - [ ] Make more friendly to open source contributors @@ -21,9 +22,9 @@ This document contains guidelines to help you get started and how to make sure y - [Ask for Help](#ask-for-help) - [Roles and Responsibilities](#roles-and-responsibilities) - [I Want To Contribute](#i-want-to-contribute) - - [Before Submitting a Bug Report](#before-submitting-a-bug-report) - - [How Do I Submit a Good Bug Report?](#how-do-i-submit-a-good-bug-report) - - [Your First Code Contribution](#your-first-code-contribution) + - [Before Submitting a Bug Report](#before-submitting-a-bug-report) + - [How Do I Submit a Good Bug Report?](#how-do-i-submit-a-good-bug-report) + - [Your First Code Contribution](#your-first-code-contribution) - [Working Conventions](#working-conventions) - [Pull Requests](#pull-requests) - [Branch Naming](#branch-naming) @@ -38,8 +39,6 @@ This document contains guidelines to help you get started and how to make sure y - [CSS in Javascript](#css-in-javascript) - [CSS / SASS](#css--sass) - [Haskell](#haskell) - - [Bumping Node, DB-Sync, SanchoNet Versions](#bumping-node-db-sync-sanchonet-versions) - - [Steps to upgrade](#steps-to-upgrade) - [Development Processes](#development-processes) - [Developer workflow](#developer-workflow) - [QA Workflow](#qa-workflow) @@ -90,7 +89,7 @@ We use GitHub issues to track bugs and errors. If you run into an issue with the (Since we can't be sure at this point whether it is a bug or not, we ask you not to talk about a bug yet and not to label the issue.) - Explain the behavior you would expect and the actual behavior. - Please provide as much context as possible. - Describe the *reproduction steps* that someone else can follow to recreate the issue on their own. + Describe the _reproduction steps_ that someone else can follow to recreate the issue on their own. This usually includes your code. For good bug reports you should isolate the problem and create a reduced test case. - Provide the information you collected in the previous section. @@ -117,6 +116,7 @@ TODO Thank you for contributing your changes by opening a pull requests! To get something merged we usually require: + - Follow the Pull Request template - Description of the changes - if your commit messages are great, this is less important - Quality of changes is ensured - through new or updated automated tests @@ -133,6 +133,7 @@ Please reuse the branch naming for the pull request naming. - Using the related issue number after the prefix is required. Examples: + - `feat/123-added-ability-for-dreps-to-change-drep-id` - `fix/312-fixed-drep-ids-being-reversed` - `chore/567-bumped-cardano-node-version-to-9` @@ -151,6 +152,7 @@ Also, include any relevant meta-information, such as issue numbers. If a commit completely addresses a issue, you can put that in the headline if you want, but it’s fine to just put it in the body. Here are seven rules for great git commit messages: + 1. Separate subject from body with a blank line 2. Limit the subject line to 50 characters (soft limit) 3. Capitalize the subject line @@ -190,6 +192,7 @@ Releases that aren't stable will be released as pre-releases and will append a - ### Changelog During development, on every PR; + - Make sure `CHANGELOG.md` is kept up-to-date with high-level, technical, but user-focused list of changes according to [keepachangelog](https://keepachangelog.com/en/1.0.0/). - Bump `UNRELEASED` version in `CHANGELOG.md` according to [semver](https://semver.org/). @@ -211,25 +214,6 @@ Please see [CSS / SASS Style Guide](./docs/style-guides/css-sass/). Please see [stylish-haskell configuration](./govtool/backend/.stylish-haskell.yaml). -## Bumping Node, DB-Sync, SanchoNet Versions - -- SanchoNet periodically has to be respun, where all data is erased. -- This is normally to allow for the nodes to be upgraded to a new version, where the old chain may not be compatible with newer node implementation. -- So to go along with each respin GovTool's Node needs to upgraded to a newer version and it's local database must be dropped. -- New versions of DB-Sync are usually released alongside new Node versions, to ensure compatibility. -- Some new versions of DB-Sync will include revisions to the DB schema, if this is the case then we also need to upgrade the BE interface to work. - -### Steps to upgrade - -1. Coordinate and align with DB-Sync/Node teams to anticipate SanchoNet respins and version releases. Once network has been respun upgrade. -- Often a new node version is released a few days ahead of a Sanchonet respin, DB-Sync is normally a couple of days post node release. -2. Change the versions in the [docker-compose file](./src/docker-compose.sanchonet.yml), here the DB-Sync and Node docker versions can be incremented. Merge this change, following standard working conventions. -- IF the DB-Sync schema changed, then BE changes will have to be merged also. -3. Then the upgrade can be deployed using normal workflows, ensure to tick `resync_cardano_node_and_db` option of the workflow. This will wipe the existing Node and Db-Sync's data, to let the upgraded versions fully resync. -4. Wait for resync, depending on the size SanchoNet resycing will likely take over an hour. -5. Check successful resync, using the BE you are able to check transaction status. You can use the SanchoNet faucet to send transactions, then check faucet Tx id via GovTool BE. If GovTool sees the Tx then GovTool BE is on the same network as the faucet which is ideal. - - ## Development Processes ### Developer workflow From 35c14d71e313bf1b19c32b7973b55c4d0757f16f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Tue, 6 Aug 2024 12:53:44 +0200 Subject: [PATCH 09/15] feat: replace hardcoded sanchonet with the network from network metrics --- CHANGELOG.md | 4 +- README.md | 9 +- docs/operations/README.md | 45 +- govtool/frontend/.storybook/preview.tsx | 52 +- govtool/frontend/index.html | 2 +- govtool/frontend/maintenance-page/index.html | 10 +- .../molecules/AutomatedVotingCard.tsx | 5 +- .../molecules/DashboardActionCard.tsx | 4 +- .../molecules/GovernanceActionCardMyVote.tsx | 6 +- .../WhatRetirementMeans.tsx | 5 +- .../organisms/RegisterAsDirectVoterBox.tsx | 5 +- govtool/frontend/src/consts/images.ts | 2 +- govtool/frontend/src/consts/index.ts | 12 + govtool/frontend/src/context/appContext.tsx | 68 + .../frontend/src/context/contextProviders.tsx | 25 +- govtool/frontend/src/context/index.ts | 1 + govtool/frontend/src/context/wallet.tsx | 31 +- .../forms/useCreateGovernanceActionForm.ts | 5 +- .../src/hooks/forms/useEditDRepInfoForm.ts | 5 +- .../src/hooks/forms/useRegisterAsdRepForm.tsx | 5 +- .../src/hooks/queries/useGetNetworkMetrics.ts | 4 - govtool/frontend/src/i18n/locales/en.ts | 10 +- .../src/pages/RegisterAsDirectVoter.tsx | 5 +- .../src/pages/RetireAsDirectVoter.tsx | 5 +- govtool/frontend/src/utils/localStorage.ts | 2 +- govtool/frontend/yarn.lock | 10111 +++++++++++----- govtool/metadata-validation/src/main.ts | 1 + 27 files changed, 7595 insertions(+), 2844 deletions(-) create mode 100644 govtool/frontend/src/context/appContext.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b2fca089..a3d75643e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,8 @@ changes. ### Added -- +- Unsancho GovTool [Issue 1637](https://github.com/IntersectMBO/govtool/issues/1637) +- Add network metrics model to frontend service ### Fixed @@ -27,7 +28,6 @@ changes. ### Added - Add network name to GET /network/metrics [Issue 1644](https://github.com/IntersectMBO/govtool/issues/1644) -- Add network metrics model to frontend service ### Fixed diff --git a/README.md b/README.md index 71c40ecb1..ee04c954d 100644 --- a/README.md +++ b/README.md @@ -3,15 +3,14 @@

- Monorepo containing SanchoNet GovTool and supporting utilities + Monorepo containing Voltaire GovTool and supporting utilities

[![npm](https://img.shields.io/npm/v/npm.svg?style=flat-square)](https://www.npmjs.com/package/npm) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) - -[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=intersect-govtool&metric=ncloc)](https://sonarcloud.io/summary/overall?id=intersect-govtool) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=intersect-govtool&metric=coverage)](https://sonarcloud.io/summary/overall?id=intersect-govtool) [![Technical Debt](https://sonarcloud.io/api/project_badges/measure?project=intersect-govtool&metric=sqale_index)](https://sonarcloud.io/summary/overall?id=intersect-govtool) +[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=intersect-govtool&metric=ncloc)](https://sonarcloud.io/summary/overall?id=intersect-govtool) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=intersect-govtool&metric=coverage)](https://sonarcloud.io/summary/overall?id=intersect-govtool) [![Technical Debt](https://sonarcloud.io/api/project_badges/measure?project=intersect-govtool&metric=sqale_index)](https://sonarcloud.io/summary/overall?id=intersect-govtool)
@@ -19,8 +18,8 @@ ## 🌄 Purpose -The SanchoNet GovTool enables ada holders to experience some of the governance features described in [CIP-1694](https://github.com/cardano-foundation/CIPs/blob/master/CIP-1694/README.md) and to test governance features on [SanchoNet](https://sancho.network/) through a guided and straightforward experience. -The SanchoNet GovTool is currently open for beta testing and can be accessed at [sanchogov.tools](https://sanchogov.tools/). +The Voltaire GovTool enables ada holders to experience some of the governance features described in [CIP-1694](https://github.com/cardano-foundation/CIPs/blob/master/CIP-1694/README.md) and to test governance features. +The Voltaire GovTool is currently open for preview testing and can be accessed at [preview.gov.tools](https://preview.gov.tools/). Learn more; [docs.sanchogov.tools](https://docs.sanchogov.tools/). diff --git a/docs/operations/README.md b/docs/operations/README.md index 4b6ab139f..f14769304 100644 --- a/docs/operations/README.md +++ b/docs/operations/README.md @@ -1,12 +1,13 @@ # Overview The application is setup with the following tools: -* Terraform - for creating infrastructure in AWS for each environment -* Docker - to build and run application components -* Docker Compose - to connect the application components together and deploy them as a stack -* make - to simplify operations tasks -* Prometheus - to gather metrics from application host and Docker containers -* Grafana - to visualize metrics gathered from Prometheus and handle alerting + +- Terraform - for creating infrastructure in AWS for each environment +- Docker - to build and run application components +- Docker Compose - to connect the application components together and deploy them as a stack +- make - to simplify operations tasks +- Prometheus - to gather metrics from application host and Docker containers +- Grafana - to visualize metrics gathered from Prometheus and handle alerting # Environments @@ -14,11 +15,11 @@ The application is hosted on AWS, there are several application environments, ea Each environment consists of: -* VPC network (with subnets, route tables, IGW) -* Security Groups -* EC2 instance -* Elastic IPs associated with EC2 instance -* Route 53 record (only for environments using `govtool.byron.network` domain) +- VPC network (with subnets, route tables, IGW) +- Security Groups +- EC2 instance +- Elastic IPs associated with EC2 instance +- Route 53 record (only for environments using `govtool.byron.network` domain) For each environment, the frontend is hosted at root and the backend is at `/api`. @@ -26,25 +27,27 @@ For each environment, the frontend is hosted at root and the backend is at `/api ### beta -A beta environment connected to `sanchonet` Cardano network. +A beta environment connected to `preview` Cardano network. -Available at https://sanchogov.tools/. The DNS record for this domain is created manually. +Available at https://preview.gov.tools/. The DNS record for this domain is created manually. # Deployment Deployment is performed via GitHub Actions workflow (`.github/workflows/build-and-deploy.yml`). The workflow performs the following steps: -* check if the environment is defined in Terraform (to avoid deployment attempt to inexistant environment) -* build of frontend app -* build of backend app -* generate configuration files and upload them (over SSH) to the target environment -* setup the application compoments with Docker Compose on the target environment + +- check if the environment is defined in Terraform (to avoid deployment attempt to inexistant environment) +- build of frontend app +- build of backend app +- generate configuration files and upload them (over SSH) to the target environment +- setup the application compoments with Docker Compose on the target environment The workflow can be triggered directly from GitHub Actions panel. When ruuning the workflow, you need to specify: -* Cardano network to be used -* environment name -* optionally skip the build process (frontend and backend) - useful when there are plain configuration changes that do not require the application to be rebuild + +- Cardano network to be used +- environment name +- optionally skip the build process (frontend and backend) - useful when there are plain configuration changes that do not require the application to be rebuild # Monitoring diff --git a/govtool/frontend/.storybook/preview.tsx b/govtool/frontend/.storybook/preview.tsx index 87b01a7d2..9ee56bf7b 100644 --- a/govtool/frontend/.storybook/preview.tsx +++ b/govtool/frontend/.storybook/preview.tsx @@ -4,6 +4,8 @@ import React from "react"; import { I18nextProvider } from "react-i18next"; import { QueryClient, QueryClientProvider } from "react-query"; import { MemoryRouter, Route, Routes } from "react-router-dom"; + +import { AppContextProvider } from "../src/context/appContext"; import { ModalProvider } from "../src/context/modal"; import i18n from "../src/i18n"; import { theme } from "../src/theme"; @@ -23,30 +25,32 @@ const preview: Preview = { decorators: [ (Story) => ( - - - - - - - - - } - /> - - - - - + + + + + + + + + + } + /> + + + + + + ), ], diff --git a/govtool/frontend/index.html b/govtool/frontend/index.html index 9fa7c8404..e3ff67282 100644 --- a/govtool/frontend/index.html +++ b/govtool/frontend/index.html @@ -10,7 +10,7 @@ rel="stylesheet" /> - SanchoNet Govtool + Voltaire Govtool