From 9f69308950a999ecbf16c9e7a797768e4740c4f4 Mon Sep 17 00:00:00 2001 From: Ciabas Date: Mon, 7 Jul 2025 17:10:59 +0200 Subject: [PATCH 01/16] (fix) Hotfix for duplicated entries for pools for epoch 568 on mainnet in pool_stat table --- govtool/backend/sql/list-proposals.sql | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/govtool/backend/sql/list-proposals.sql b/govtool/backend/sql/list-proposals.sql index dfb54e12d..a0f3f97e1 100644 --- a/govtool/backend/sql/list-proposals.sql +++ b/govtool/backend/sql/list-proposals.sql @@ -113,15 +113,23 @@ RankedPoolVotes AS ( vp.vote FROM voting_procedure vp - WHERE + WHERE vp.pool_voter IS NOT NULL AND vp.gov_action_proposal_id IN (SELECT id FROM ActiveProposals) - ORDER BY - vp.pool_voter, - vp.gov_action_proposal_id, + ORDER BY + vp.pool_voter, + vp.gov_action_proposal_id, vp.tx_id DESC, vp.id DESC ), +-- it's a hotfix for duplication issue https://github.com/IntersectMBO/cardano-db-sync/issues/1986 +LatestPoolStat AS ( + SELECT DISTINCT ON (pool_hash_id) * + FROM + pool_stat + WHERE + epoch_no = (SELECT MAX(no) FROM epoch) +), PoolVotes AS ( SELECT rpv.gov_action_proposal_id, @@ -132,10 +140,10 @@ PoolVotes AS ( SUM(CASE WHEN rpv.vote = 'Yes' THEN ps.voting_power ELSE 0 END) AS poolYesVotes, SUM(CASE WHEN rpv.vote = 'No' THEN ps.voting_power ELSE 0 END) AS poolNoVotes, SUM(CASE WHEN rpv.vote = 'Abstain' THEN ps.voting_power ELSE 0 END) AS poolAbstainVotes - FROM + FROM RankedPoolVotes rpv - JOIN - pool_stat ps + JOIN + LatestPoolStat ps ON rpv.pool_voter = ps.pool_hash_id WHERE ps.epoch_no = (SELECT MAX(no) FROM epoch) From c8e01fd5a3dbf7b29c9c4e27732ecc449ce58c51 Mon Sep 17 00:00:00 2001 From: Ciabas Date: Tue, 8 Jul 2025 13:08:19 +0200 Subject: [PATCH 02/16] (fix) Hotfix for calculations on SPOs on gov actions --- govtool/backend/sql/get-network-total-stake.sql | 10 +++++++++- .../src/components/molecules/VotesSubmitted.tsx | 17 ++++++++++------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/govtool/backend/sql/get-network-total-stake.sql b/govtool/backend/sql/get-network-total-stake.sql index 9399df5c3..80e29d06c 100644 --- a/govtool/backend/sql/get-network-total-stake.sql +++ b/govtool/backend/sql/get-network-total-stake.sql @@ -67,8 +67,16 @@ TotalStakeControlledByActiveDReps AS ( AND COALESCE(rd.deposit, 0) >= 0 AND ((DRepActivity.epoch_no - GREATEST(COALESCE(lve.epoch_no, 0), COALESCE(rd.epoch_no, 0))) <= DRepActivity.drep_activity) ), +-- it's a hotfix for duplication issue https://github.com/IntersectMBO/cardano-db-sync/issues/1986 +LatestPoolStat AS ( + SELECT DISTINCT ON (pool_hash_id) * + FROM + pool_stat + WHERE + epoch_no = (SELECT MAX(no) FROM epoch) +), TotalStakeControlledBySPOs AS ( - SELECT SUM(ps.stake)::bigint AS total FROM pool_stat ps WHERE ps.epoch_no = (SELECT no FROM CurrentEpoch) + SELECT SUM(ps.stake)::bigint AS total FROM LatestPoolStat ps WHERE ps.epoch_no = (SELECT no FROM CurrentEpoch) ), AlwaysAbstainVotingPower AS ( SELECT COALESCE((SELECT amount FROM drep_hash diff --git a/govtool/frontend/src/components/molecules/VotesSubmitted.tsx b/govtool/frontend/src/components/molecules/VotesSubmitted.tsx index 87f3ab8a0..7b81cd370 100644 --- a/govtool/frontend/src/components/molecules/VotesSubmitted.tsx +++ b/govtool/frontend/src/components/molecules/VotesSubmitted.tsx @@ -109,14 +109,17 @@ export const VotesSubmitted = ({ 100 - (dRepYesVotesPercentage ?? 0) - (dRepNoVotesPercentage ?? 0); const poolYesVotesPercentage = - poolYesVotes + poolNoVotes - ? (poolYesVotes / (poolYesVotes + poolNoVotes)) * 100 + typeof poolYesVotes === "number" && + typeof networkTotalStake?.totalStakeControlledBySPOs === "number" && + networkTotalStake.totalStakeControlledBySPOs > 0 + ? (poolYesVotes / networkTotalStake.totalStakeControlledBySPOs) * 100 + : undefined; + const poolNoVotesPercentage = + typeof poolNoVotes === "number" && + typeof networkTotalStake?.totalStakeControlledBySPOs === "number" && + networkTotalStake.totalStakeControlledBySPOs > 0 + ? (poolNoVotes / networkTotalStake.totalStakeControlledBySPOs) * 100 : undefined; - const poolNoVotesPercentage = poolYesVotesPercentage - ? 100 - poolYesVotesPercentage - : poolNoVotes - ? 100 - : undefined; const ccYesVotesPercentage = noOfCommitteeMembers ? (ccYesVotes / noOfCommitteeMembers) * 100 From 897a21adbb4f72a8cc86811e5522cad50362829b Mon Sep 17 00:00:00 2001 From: Ciabas Date: Wed, 9 Jul 2025 14:04:03 +0200 Subject: [PATCH 03/16] (fix#3879): broken parameters on Live Voting page --- ...rnanceActionNewCommitteeDetailsTabContent.tsx | 16 +++++++++++++--- .../src/components/organisms/DrawerMobile.tsx | 1 + 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/govtool/frontend/src/components/molecules/GovernanceActionNewCommitteeDetailsTabContent.tsx b/govtool/frontend/src/components/molecules/GovernanceActionNewCommitteeDetailsTabContent.tsx index fc244db2f..e3a2a286a 100644 --- a/govtool/frontend/src/components/molecules/GovernanceActionNewCommitteeDetailsTabContent.tsx +++ b/govtool/frontend/src/components/molecules/GovernanceActionNewCommitteeDetailsTabContent.tsx @@ -13,6 +13,12 @@ type CCMember = { newExpirationEpoch?: number; }; +function isArrayOfStrings(value: unknown): value is string[] { + return ( + Array.isArray(value) && value.every((item) => typeof item === "string") + ); +} + export const GovernanceActionNewCommitteeDetailsTabContent = ({ details, }: Pick) => { @@ -38,6 +44,10 @@ export const GovernanceActionNewCommitteeDetailsTabContent = ({ newExpirationEpoch: member.newExpirationEpoch, })); + const membersToBeRemoved = isArrayOfStrings(details?.membersToBeRemoved) + ? details.membersToBeRemoved + : []; + return ( {membersToBeAdded.length > 0 && ( @@ -78,7 +88,7 @@ export const GovernanceActionNewCommitteeDetailsTabContent = ({ ))} )} - {(details?.membersToBeRemoved as string[]).length > 0 && ( + {membersToBeRemoved.length > 0 && ( {t("govActions.membersToBeRemoved")} - {(details?.membersToBeRemoved as string[]).map((hash) => ( - + {membersToBeRemoved.map((hash) => ( + setIsDrawerOpen(false)} navItem={navItem} + key={navItem.label} /> ); } From fc4ae545a04536f0ebc79b0db2f563f2cd7c450d Mon Sep 17 00:00:00 2001 From: "Artur W." Date: Wed, 9 Jul 2025 14:51:24 +0200 Subject: [PATCH 04/16] Revert "(fix) Hotfix for calculations on SPOs on gov actions" --- govtool/backend/sql/get-network-total-stake.sql | 10 +--------- .../src/components/molecules/VotesSubmitted.tsx | 17 +++++++---------- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/govtool/backend/sql/get-network-total-stake.sql b/govtool/backend/sql/get-network-total-stake.sql index 80e29d06c..9399df5c3 100644 --- a/govtool/backend/sql/get-network-total-stake.sql +++ b/govtool/backend/sql/get-network-total-stake.sql @@ -67,16 +67,8 @@ TotalStakeControlledByActiveDReps AS ( AND COALESCE(rd.deposit, 0) >= 0 AND ((DRepActivity.epoch_no - GREATEST(COALESCE(lve.epoch_no, 0), COALESCE(rd.epoch_no, 0))) <= DRepActivity.drep_activity) ), --- it's a hotfix for duplication issue https://github.com/IntersectMBO/cardano-db-sync/issues/1986 -LatestPoolStat AS ( - SELECT DISTINCT ON (pool_hash_id) * - FROM - pool_stat - WHERE - epoch_no = (SELECT MAX(no) FROM epoch) -), TotalStakeControlledBySPOs AS ( - SELECT SUM(ps.stake)::bigint AS total FROM LatestPoolStat ps WHERE ps.epoch_no = (SELECT no FROM CurrentEpoch) + SELECT SUM(ps.stake)::bigint AS total FROM pool_stat ps WHERE ps.epoch_no = (SELECT no FROM CurrentEpoch) ), AlwaysAbstainVotingPower AS ( SELECT COALESCE((SELECT amount FROM drep_hash diff --git a/govtool/frontend/src/components/molecules/VotesSubmitted.tsx b/govtool/frontend/src/components/molecules/VotesSubmitted.tsx index 7b81cd370..87f3ab8a0 100644 --- a/govtool/frontend/src/components/molecules/VotesSubmitted.tsx +++ b/govtool/frontend/src/components/molecules/VotesSubmitted.tsx @@ -109,17 +109,14 @@ export const VotesSubmitted = ({ 100 - (dRepYesVotesPercentage ?? 0) - (dRepNoVotesPercentage ?? 0); const poolYesVotesPercentage = - typeof poolYesVotes === "number" && - typeof networkTotalStake?.totalStakeControlledBySPOs === "number" && - networkTotalStake.totalStakeControlledBySPOs > 0 - ? (poolYesVotes / networkTotalStake.totalStakeControlledBySPOs) * 100 - : undefined; - const poolNoVotesPercentage = - typeof poolNoVotes === "number" && - typeof networkTotalStake?.totalStakeControlledBySPOs === "number" && - networkTotalStake.totalStakeControlledBySPOs > 0 - ? (poolNoVotes / networkTotalStake.totalStakeControlledBySPOs) * 100 + poolYesVotes + poolNoVotes + ? (poolYesVotes / (poolYesVotes + poolNoVotes)) * 100 : undefined; + const poolNoVotesPercentage = poolYesVotesPercentage + ? 100 - poolYesVotesPercentage + : poolNoVotes + ? 100 + : undefined; const ccYesVotesPercentage = noOfCommitteeMembers ? (ccYesVotes / noOfCommitteeMembers) * 100 From ed0e0297836eda405a9f2ce46e96da0807164059 Mon Sep 17 00:00:00 2001 From: "Artur W." Date: Wed, 9 Jul 2025 14:51:40 +0200 Subject: [PATCH 05/16] Revert "(fix) Hotfix for duplicated entries for pools for epoch 568 on mainnet in pool_stat table" --- govtool/backend/sql/list-proposals.sql | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/govtool/backend/sql/list-proposals.sql b/govtool/backend/sql/list-proposals.sql index a0f3f97e1..dfb54e12d 100644 --- a/govtool/backend/sql/list-proposals.sql +++ b/govtool/backend/sql/list-proposals.sql @@ -113,23 +113,15 @@ RankedPoolVotes AS ( vp.vote FROM voting_procedure vp - WHERE + WHERE vp.pool_voter IS NOT NULL AND vp.gov_action_proposal_id IN (SELECT id FROM ActiveProposals) - ORDER BY - vp.pool_voter, - vp.gov_action_proposal_id, + ORDER BY + vp.pool_voter, + vp.gov_action_proposal_id, vp.tx_id DESC, vp.id DESC ), --- it's a hotfix for duplication issue https://github.com/IntersectMBO/cardano-db-sync/issues/1986 -LatestPoolStat AS ( - SELECT DISTINCT ON (pool_hash_id) * - FROM - pool_stat - WHERE - epoch_no = (SELECT MAX(no) FROM epoch) -), PoolVotes AS ( SELECT rpv.gov_action_proposal_id, @@ -140,10 +132,10 @@ PoolVotes AS ( SUM(CASE WHEN rpv.vote = 'Yes' THEN ps.voting_power ELSE 0 END) AS poolYesVotes, SUM(CASE WHEN rpv.vote = 'No' THEN ps.voting_power ELSE 0 END) AS poolNoVotes, SUM(CASE WHEN rpv.vote = 'Abstain' THEN ps.voting_power ELSE 0 END) AS poolAbstainVotes - FROM + FROM RankedPoolVotes rpv - JOIN - LatestPoolStat ps + JOIN + pool_stat ps ON rpv.pool_voter = ps.pool_hash_id WHERE ps.epoch_no = (SELECT MAX(no) FROM epoch) From f72812aa77150f52527c1c78f79017e4680f0ff2 Mon Sep 17 00:00:00 2001 From: Ciabas Date: Wed, 9 Jul 2025 15:42:09 +0200 Subject: [PATCH 06/16] (fix#3881): add not voted to SPOs counting on gov actions --- .../frontend/src/components/molecules/VotesSubmitted.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/govtool/frontend/src/components/molecules/VotesSubmitted.tsx b/govtool/frontend/src/components/molecules/VotesSubmitted.tsx index 87f3ab8a0..8bd2bd0ee 100644 --- a/govtool/frontend/src/components/molecules/VotesSubmitted.tsx +++ b/govtool/frontend/src/components/molecules/VotesSubmitted.tsx @@ -117,6 +117,11 @@ export const VotesSubmitted = ({ : poolNoVotes ? 100 : undefined; + const poolNotVotedVotes = + typeof networkTotalStake?.totalStakeControlledBySPOs === "number" + ? networkTotalStake.totalStakeControlledBySPOs - + (poolYesVotes + poolNoVotes + poolAbstainVotes) + : undefined; const ccYesVotesPercentage = noOfCommitteeMembers ? (ccYesVotes / noOfCommitteeMembers) * 100 @@ -200,6 +205,7 @@ export const VotesSubmitted = ({ noVotes={poolNoVotes} noVotesPercentage={poolNoVotesPercentage} abstainVotes={poolAbstainVotes} + notVotedVotes={poolNotVotedVotes} threshold={ (() => { const votingThresholdKey = getGovActionVotingThresholdKey({ From 0f4d315d652d379053424b13a0d27ddd3a869124 Mon Sep 17 00:00:00 2001 From: Ciabas Date: Thu, 10 Jul 2025 12:37:01 +0200 Subject: [PATCH 07/16] (fix#3881): calculate SPO % based on the whole group (yes/no/abstain/not-voted) --- .../src/components/molecules/VotesSubmitted.tsx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/govtool/frontend/src/components/molecules/VotesSubmitted.tsx b/govtool/frontend/src/components/molecules/VotesSubmitted.tsx index 8bd2bd0ee..63443c212 100644 --- a/govtool/frontend/src/components/molecules/VotesSubmitted.tsx +++ b/govtool/frontend/src/components/molecules/VotesSubmitted.tsx @@ -109,14 +109,17 @@ export const VotesSubmitted = ({ 100 - (dRepYesVotesPercentage ?? 0) - (dRepNoVotesPercentage ?? 0); const poolYesVotesPercentage = - poolYesVotes + poolNoVotes - ? (poolYesVotes / (poolYesVotes + poolNoVotes)) * 100 + typeof poolYesVotes === "number" && + typeof networkTotalStake?.totalStakeControlledBySPOs === "number" && + networkTotalStake.totalStakeControlledBySPOs > 0 + ? (poolYesVotes / networkTotalStake.totalStakeControlledBySPOs) * 100 + : undefined; + const poolNoVotesPercentage = + typeof poolNoVotes === "number" && + typeof networkTotalStake?.totalStakeControlledBySPOs === "number" && + networkTotalStake.totalStakeControlledBySPOs > 0 + ? (poolNoVotes / networkTotalStake.totalStakeControlledBySPOs) * 100 : undefined; - const poolNoVotesPercentage = poolYesVotesPercentage - ? 100 - poolYesVotesPercentage - : poolNoVotes - ? 100 - : undefined; const poolNotVotedVotes = typeof networkTotalStake?.totalStakeControlledBySPOs === "number" ? networkTotalStake.totalStakeControlledBySPOs - From 52692b5f5f912b95af019dcb103c8da5f0c58e5e Mon Sep 17 00:00:00 2001 From: Ciabas Date: Tue, 8 Jul 2025 14:58:21 +0200 Subject: [PATCH 08/16] (fix) Add SPOs not voted values to gov actions --- .../components/molecules/VotesSubmitted.tsx | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/govtool/frontend/src/components/molecules/VotesSubmitted.tsx b/govtool/frontend/src/components/molecules/VotesSubmitted.tsx index 63443c212..9c193a285 100644 --- a/govtool/frontend/src/components/molecules/VotesSubmitted.tsx +++ b/govtool/frontend/src/components/molecules/VotesSubmitted.tsx @@ -84,6 +84,8 @@ export const VotesSubmitted = ({ dRepAbstainVotes + (networkTotalStake?.alwaysAbstainVotingPower ?? 0); // TODO: Move this logic to backend + + // DRep votes const dRepYesVotesPercentage = totalStakeControlledByDReps ? (dRepYesVotes / totalStakeControlledByDReps) * 100 : undefined; @@ -108,33 +110,45 @@ export const VotesSubmitted = ({ const dRepNotVotedVotesPercentage = 100 - (dRepYesVotesPercentage ?? 0) - (dRepNoVotesPercentage ?? 0); + // SPO/Pool votes const poolYesVotesPercentage = typeof poolYesVotes === "number" && typeof networkTotalStake?.totalStakeControlledBySPOs === "number" && networkTotalStake.totalStakeControlledBySPOs > 0 ? (poolYesVotes / networkTotalStake.totalStakeControlledBySPOs) * 100 : undefined; + const poolNoVotesPercentage = typeof poolNoVotes === "number" && typeof networkTotalStake?.totalStakeControlledBySPOs === "number" && networkTotalStake.totalStakeControlledBySPOs > 0 ? (poolNoVotes / networkTotalStake.totalStakeControlledBySPOs) * 100 : undefined; + const poolNotVotedVotes = typeof networkTotalStake?.totalStakeControlledBySPOs === "number" ? networkTotalStake.totalStakeControlledBySPOs - (poolYesVotes + poolNoVotes + poolAbstainVotes) : undefined; + const poolNotVotedVotesPercentage = + 100 - + (typeof poolYesVotesPercentage === "number" ? poolYesVotesPercentage : 0) - + (typeof poolNoVotesPercentage === "number" ? poolNoVotesPercentage : 0); + + // Constitutional Commission votes const ccYesVotesPercentage = noOfCommitteeMembers ? (ccYesVotes / noOfCommitteeMembers) * 100 : undefined; - const ccNoVotesPercentage = noOfCommitteeMembers + + const ccNoVotesPercentage = noOfCommitteeMembers ? (ccNoVotes / noOfCommitteeMembers) * 100 : undefined; - const ccNotVotedVotes = + + const ccNotVotedVotes = noOfCommitteeMembers - ccYesVotes - ccNoVotes - ccAbstainVotes; - const ccNotVotedVotesPercentage = + + const ccNotVotedVotesPercentage = 100 - (ccYesVotesPercentage ?? 0) - (ccNoVotesPercentage ?? 0); return ( @@ -209,6 +223,7 @@ export const VotesSubmitted = ({ noVotesPercentage={poolNoVotesPercentage} abstainVotes={poolAbstainVotes} notVotedVotes={poolNotVotedVotes} + notVotedPercentage={poolNotVotedVotesPercentage} threshold={ (() => { const votingThresholdKey = getGovActionVotingThresholdKey({ From e792251fd91538532542c1172c4563196541558c Mon Sep 17 00:00:00 2001 From: kneerose Date: Tue, 15 Jul 2025 15:53:59 +0545 Subject: [PATCH 09/16] chore: disable hardfork proposal test --- .../govtool-frontend/playwright/.env.example | 2 ++ .../playwright/lib/constants/environments.ts | 2 ++ .../playwright/lib/helpers/index.ts | 19 ++++++++++++++ .../lib/pages/proposalSubmissionPage.ts | 5 ++-- .../proposalSubmission.ga.spec.ts | 4 +-- .../proposalSubmission.loggedin.pd.spec.ts | 26 ++++++++----------- .../proposalDiscussion.spec.ts | 7 +++-- .../playwright/tests/proposal.setup.ts | 7 +++-- 8 files changed, 47 insertions(+), 25 deletions(-) diff --git a/tests/govtool-frontend/playwright/.env.example b/tests/govtool-frontend/playwright/.env.example index c68929567..b2d1e6c52 100644 --- a/tests/govtool-frontend/playwright/.env.example +++ b/tests/govtool-frontend/playwright/.env.example @@ -20,5 +20,7 @@ FAUCET_ADDRESS= FAUCET_PAYMENT_PRIVATE= FAUCET_STAKE_PRIVATE= +IS_HARDFORK_PROPOSAL_ENABLED=false + CI=true TEST_WORKERS=6 // Number of workers to run in parallel \ No newline at end of file diff --git a/tests/govtool-frontend/playwright/lib/constants/environments.ts b/tests/govtool-frontend/playwright/lib/constants/environments.ts index c382c358b..8c1563d30 100644 --- a/tests/govtool-frontend/playwright/lib/constants/environments.ts +++ b/tests/govtool-frontend/playwright/lib/constants/environments.ts @@ -34,6 +34,8 @@ const environments = { (process.env.SCHEDULED_WORKFLOW && process.env.SCHEDULED_WORKFLOW == "true") || false, + isHardforkProposalEnabled: + process.env.IS_HARDFORK_PROPOSAL_ENABLED === "true" || false, }; export default environments; diff --git a/tests/govtool-frontend/playwright/lib/helpers/index.ts b/tests/govtool-frontend/playwright/lib/helpers/index.ts index 86fc90cc3..56c16331a 100644 --- a/tests/govtool-frontend/playwright/lib/helpers/index.ts +++ b/tests/govtool-frontend/playwright/lib/helpers/index.ts @@ -1,4 +1,5 @@ import environments from "@constants/environments"; +import { ProposalType } from "@types"; export const parseVotingPowerAndPercentage = ( combinedString: string ): { votingPower: string; percentage: string } => { @@ -27,3 +28,21 @@ export const getWalletConfigForFaucet = () => { address: environments.faucet.address || "", }; }; + + +export const getProposalType = () => { + return Object.values(ProposalType).filter( + (type) => + !( + environments.isHardforkProposalEnabled === false && + type === ProposalType.hardFork + ) + ); +}; + +export const getProposalWalletCount = (): number => { + if (environments.isScheduled) { + return 1; + } + return environments.isHardforkProposalEnabled ? 6 : 5; +}; \ No newline at end of file diff --git a/tests/govtool-frontend/playwright/lib/pages/proposalSubmissionPage.ts b/tests/govtool-frontend/playwright/lib/pages/proposalSubmissionPage.ts index a7c327f93..94874ee50 100644 --- a/tests/govtool-frontend/playwright/lib/pages/proposalSubmissionPage.ts +++ b/tests/govtool-frontend/playwright/lib/pages/proposalSubmissionPage.ts @@ -5,6 +5,7 @@ import { faker } from "@faker-js/faker"; import { isBootStrapingPhase } from "@helpers/cardano"; import { ShelleyWallet } from "@helpers/crypto"; import { expectWithInfo } from "@helpers/exceptionHandler"; +import { getProposalType } from "@helpers/index"; import { downloadMetadata, uploadScriptAndGenerateUrl, @@ -615,8 +616,8 @@ export default class ProposalSubmissionPage { async createProposal( receivingAddress: string, - proposalType: ProposalType = Object.values(ProposalType)[ - Math.floor(Math.random() * Object.values(ProposalType).length) + proposalType: ProposalType = getProposalType()[ + Math.floor(Math.random() * getProposalType().length) ] ): Promise { await this.addLinkBtn.click(); diff --git a/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.ga.spec.ts b/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.ga.spec.ts index 7cd57efc1..e45681fde 100644 --- a/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.ga.spec.ts +++ b/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.ga.spec.ts @@ -16,7 +16,7 @@ import { ProposalType } from "@types"; import walletManager from "lib/walletManager"; import { valid as mockValid, invalid as mockInvalid } from "@mock/index"; import { rewardAddressBech32 } from "@helpers/shellyWallet"; -import { getWalletConfigForFaucet } from "@helpers/index"; +import { getProposalType, getWalletConfigForFaucet } from "@helpers/index"; import { faker } from "@faker-js/faker"; import { proposalSubmissionAuthFile } from "@constants/auth"; import ProposalDiscussionDetailsPage from "@pages/proposalDiscussionDetailsPage"; @@ -28,7 +28,7 @@ test.beforeEach(async () => { await skipIfTemporyWalletIsNotAvailable("proposalSubmissionWallets.json"); }); -Object.values(ProposalType).forEach((proposalType, index) => { +getProposalType().forEach((proposalType, index) => { test(`7H_${index + 1}. Should submit a ${proposalType.toLocaleLowerCase()} proposal as governance action`, async ({ page, browser, diff --git a/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.loggedin.pd.spec.ts b/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.loggedin.pd.spec.ts index 879d01beb..ad227a7de 100644 --- a/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.loggedin.pd.spec.ts +++ b/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.loggedin.pd.spec.ts @@ -21,6 +21,7 @@ import { skipIfMainnet, } from "@helpers/cardano"; import { ShelleyWallet } from "@helpers/crypto"; +import { getProposalType } from "@helpers/index"; import { createNewPageWithWallet } from "@helpers/page"; import { rewardAddressBech32 } from "@helpers/shellyWallet"; import ProposalDiscussionDetailsPage from "@pages/proposalDiscussionDetailsPage"; @@ -42,12 +43,13 @@ test.describe("Proposal created logged state", () => { }); test.describe("Accept valid data", () => { - Object.values(ProposalType).map((type: ProposalType, index) => { + getProposalType().map((type: ProposalType, index) => { test(`7E_${index + 1}. Should accept valid data in ${type.toLowerCase()} proposal form`, async ({ page, }) => { await skipIfNotInfoAndBootstrapping(type); + test.slow(); // Brute-force testing with 50 random data const proposalSubmissionPage = new ProposalSubmissionPage(page); @@ -99,7 +101,7 @@ test.describe("Proposal created logged state", () => { }); test.describe("Reject invalid data", () => { - Object.values(ProposalType).map((type: ProposalType, index) => { + getProposalType().map((type: ProposalType, index) => { test(`7F_${index + 1}. Should reject invalid data in ${type.toLowerCase()} Proposal form`, async ({ page, }) => { @@ -128,7 +130,7 @@ test.describe("Proposal created logged state", () => { }); test.describe("Create a proposal with proper data", () => { - Object.values(ProposalType).map((type: ProposalType, index) => { + getProposalType().map((type: ProposalType, index) => { test(`7G_${index + 1}. Should create a proposal with proper ${type.toLowerCase()} data`, async ({ page, wallet, @@ -203,7 +205,7 @@ test.describe("Proposal created logged state", () => { }); test.describe("Review fillup form", () => { - Object.values(ProposalType).map((type: ProposalType, index) => { + getProposalType().map((type: ProposalType, index) => { test(`7I_${index + 1}. Should valid review submission in ${type.toLowerCase()} Proposal form`, async ({ page, }) => { @@ -278,7 +280,7 @@ test.describe("Proposal created logged state", () => { }); test.describe("Verify Proposal form", () => { - Object.values(ProposalType).map((type: ProposalType, index) => { + getProposalType().map((type: ProposalType, index) => { test(`7D_${index + 1}. Verify ${type.toLocaleLowerCase()} proposal form`, async ({ page, }) => { @@ -378,9 +380,7 @@ test.describe("Proposal Draft", () => { }); const proposalSubmissionPage = new ProposalSubmissionPage(page); const proposalType = - Object.values(ProposalType)[ - Math.floor(Math.random() * Object.values(ProposalType).length) - ]; + getProposalType()[Math.floor(Math.random() * getProposalType().length)]; await proposalSubmissionPage.createDraft(proposalType); const getAllDrafts = await proposalSubmissionPage.getAllDrafts(); @@ -395,9 +395,7 @@ test.describe("Proposal Draft", () => { }); const proposalType = - Object.values(ProposalType)[ - Math.floor(Math.random() * Object.values(ProposalType).length) - ]; + getProposalType()[Math.floor(Math.random() * getProposalType().length)]; const proposalSubmissionPage = new ProposalSubmissionPage(page); const createProposalType = (await isBootStrapingPhase()) @@ -470,7 +468,7 @@ test.describe("Proposal Draft", () => { ); }); - Object.values(ProposalType).map((proposalType, index) => { + getProposalType().map((proposalType, index) => { test(`7M_${index + 1}. Should edit a ${proposalType.toLowerCase()} proposal draft`, async ({ browser, }) => { @@ -567,9 +565,7 @@ test.describe("Proposal Draft", () => { test.slow(); const proposalType = - Object.values(ProposalType)[ - Math.floor(Math.random() * Object.values(ProposalType).length) - ]; + getProposalType()[Math.floor(Math.random() * getProposalType().length)]; const proposalSubmissionPage = new ProposalSubmissionPage(page); const { proposalFormValue } = diff --git a/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.spec.ts b/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.spec.ts index 011627afa..babf72fce 100644 --- a/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.spec.ts +++ b/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.spec.ts @@ -7,6 +7,7 @@ import { faker } from "@faker-js/faker"; import { test } from "@fixtures/proposal"; import { setAllureEpic } from "@helpers/allure"; import { isBootStrapingPhase } from "@helpers/cardano"; +import { getProposalType } from "@helpers/index"; import { injectLogger } from "@helpers/page"; import { extractProposalIdFromUrl } from "@helpers/string"; import { functionWaitedAssert } from "@helpers/waitedLoop"; @@ -55,9 +56,7 @@ test.describe("Filter and sort proposals", () => { // proposal type filter await proposalDiscussionPage.applyAndValidateFilters( - isBootStraping - ? BOOTSTRAP_PROPOSAL_TYPE_FILTERS - : Object.values(ProposalType), + isBootStraping ? BOOTSTRAP_PROPOSAL_TYPE_FILTERS : getProposalType(), proposalDiscussionPage._validateTypeFiltersInProposalCard ); @@ -171,7 +170,7 @@ test("8D. Should show the view-all categorized proposed governance actions.", as browser, }) => { await Promise.all( - Object.values(ProposalType).map(async (proposalType: string) => { + getProposalType().map(async (proposalType: string) => { const context = await browser.newContext(); const page = await context.newPage(); injectLogger(page); diff --git a/tests/govtool-frontend/playwright/tests/proposal.setup.ts b/tests/govtool-frontend/playwright/tests/proposal.setup.ts index 0c7a714fa..751c6992f 100644 --- a/tests/govtool-frontend/playwright/tests/proposal.setup.ts +++ b/tests/govtool-frontend/playwright/tests/proposal.setup.ts @@ -7,10 +7,13 @@ import { test as setup } from "@fixtures/walletExtension"; import kuberService from "@services/kuberService"; import walletManager from "lib/walletManager"; import { functionWaitedAssert } from "@helpers/waitedLoop"; -import { getWalletConfigForFaucet } from "@helpers/index"; +import { + getProposalWalletCount, + getWalletConfigForFaucet, +} from "@helpers/index"; import { createKeyFromPrivateKeyHex } from "@helpers/crypto"; -const PROPOSAL_WALLETS_COUNT = environments.isScheduled ? 1 : 6; +const PROPOSAL_WALLETS_COUNT = getProposalWalletCount(); let govActionDeposit: number; From 56c5a8921a4a03e93115d7a15f5121ce798613bc Mon Sep 17 00:00:00 2001 From: kneerose Date: Tue, 15 Jul 2025 16:10:45 +0545 Subject: [PATCH 10/16] fix: update governance actions test to ensure correct navigation and visibility for live voting --- .../proposalVisibility.loggedin.spec.ts | 4 ++-- .../tests/4-proposal-visibility/proposalVisibility.spec.ts | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.loggedin.spec.ts b/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.loggedin.spec.ts index afc6b5f5d..37b5bf379 100644 --- a/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.loggedin.spec.ts +++ b/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.loggedin.spec.ts @@ -20,8 +20,8 @@ test("4A_1. Should access Governance Actions page with connecting wallet", async await openDrawer(page); } - await page.getByTestId("governance-actions-link").click(); - await expect(page.getByText(/Governance Actions/i)).toHaveCount(2); + await page.getByTestId("governance-actions-live-voting-link").click(); + await expect(page.getByText(/Live Voting/i)).toHaveCount(2); }); test("4B_1. Should restrict voting for users who are not registered as DReps (with wallet connected)", async ({ diff --git a/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.spec.ts b/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.spec.ts index 333176391..adab72a92 100644 --- a/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.spec.ts +++ b/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.spec.ts @@ -15,6 +15,7 @@ import removeAllSpaces from "@helpers/removeAllSpaces"; import { functionWaitedAssert } from "@helpers/waitedLoop"; import extractExpiryDateFromText from "@helpers/extractExpiryDateFromText"; import { InvalidMetadata } from "@constants/index"; +import { isMobile } from "@helpers/mobile"; test.beforeEach(async () => { await setAllureEpic("4. Proposal visibility"); @@ -44,7 +45,11 @@ test("4A_2. Should access Governance Actions page without connecting wallet", as await page.goto("/"); await page.getByTestId("move-to-governance-actions-button").click(); - await expect(page.getByText(/Governance actions/i)).toHaveCount(2); + if (!isMobile(page)) { + await page.getByTestId("governance-actions").click(); + } + + await expect(page.getByText(/Live Voting/i)).toHaveCount(2); }); test("4B_2. Should restrict voting for users who are not registered as DReps (without wallet connected)", async ({ From bd0f7fff5003995ed477c07fa49e9f19e80c91c5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 16 Jul 2025 08:15:49 +0000 Subject: [PATCH 11/16] chore: update GovTool to v2.0.29 --- CHANGELOG.md | 11 +++++++++++ govtool/backend/Dockerfile | 2 +- govtool/backend/Dockerfile.qovery | 2 +- govtool/backend/vva-be.cabal | 2 +- govtool/frontend/package-lock.json | 4 ++-- govtool/frontend/package.json | 2 +- govtool/metadata-validation/package-lock.json | 4 ++-- govtool/metadata-validation/package.json | 2 +- govtool/metadata-validation/src/main.ts | 2 +- 9 files changed, 21 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba69e3a67..25bb40f23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,17 @@ changes. ## [Unreleased] +### Added + +### Fixed + +### Changed + +### Removed + +## [v2.0.29](https://github.com/IntersectMBO/govtool/releases/tag/v2.0.29) 2025-07-16 + + ### Added - Preserve maintenance ending banner state on the wallet connection change [Issue 3681](https://github.com/IntersectMBO/govtool/issues/3681) diff --git a/govtool/backend/Dockerfile b/govtool/backend/Dockerfile index 88b71c171..e77613ae9 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.23/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.29/x/vva-be/build/vva-be/vva-be /usr/local/bin diff --git a/govtool/backend/Dockerfile.qovery b/govtool/backend/Dockerfile.qovery index 925a0a670..6f14bfb83 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.23/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.29/x/vva-be/build/vva-be/vva-be /usr/local/bin # Expose the necessary port EXPOSE 9876 diff --git a/govtool/backend/vva-be.cabal b/govtool/backend/vva-be.cabal index 9ae62c3dd..b644dad9a 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.23 +version: 2.0.29 -- A short (one-line) description of the package. -- synopsis: diff --git a/govtool/frontend/package-lock.json b/govtool/frontend/package-lock.json index 612ed8faa..7d3a360d6 100644 --- a/govtool/frontend/package-lock.json +++ b/govtool/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "@govtool/frontend", - "version": "2.0.23", + "version": "2.0.29", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@govtool/frontend", - "version": "2.0.23", + "version": "2.0.29", "hasInstallScript": true, "dependencies": { "@emotion/react": "^11.11.1", diff --git a/govtool/frontend/package.json b/govtool/frontend/package.json index 5afca7323..710d20de4 100644 --- a/govtool/frontend/package.json +++ b/govtool/frontend/package.json @@ -1,7 +1,7 @@ { "name": "@govtool/frontend", "private": true, - "version": "2.0.23", + "version": "2.0.29", "type": "module", "scripts": { "build": "vite build", diff --git a/govtool/metadata-validation/package-lock.json b/govtool/metadata-validation/package-lock.json index 59f24cd09..af93db9c9 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.23", + "version": "2.0.29", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@govtool/metadata-validation", - "version": "2.0.23", + "version": "2.0.29", "license": "UNLICENSED", "dependencies": { "@nestjs/axios": "^3.0.2", diff --git a/govtool/metadata-validation/package.json b/govtool/metadata-validation/package.json index 865f15b43..2d82069ad 100644 --- a/govtool/metadata-validation/package.json +++ b/govtool/metadata-validation/package.json @@ -1,6 +1,6 @@ { "name": "@govtool/metadata-validation", - "version": "2.0.23", + "version": "2.0.29", "description": "", "author": "", "private": true, diff --git a/govtool/metadata-validation/src/main.ts b/govtool/metadata-validation/src/main.ts index 5dd0961fb..1140bba4a 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.23") + .setVersion("2.0.29") .build(); const document = SwaggerModule.createDocument(app, config); From d1d76ca3f1d9faf2279bae32918d9f4489f3f8d4 Mon Sep 17 00:00:00 2001 From: Ciabas Date: Thu, 17 Jul 2025 16:34:19 +0200 Subject: [PATCH 12/16] [hotfix] Add info box to authors section on gov actions explaining the special case of MLabs withdrawal --- .../GovernanceActionDetailsCardData.tsx | 60 ++++++++++++++++++- govtool/frontend/src/i18n/locales/en.json | 6 ++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/govtool/frontend/src/components/organisms/GovernanceActionDetailsCardData.tsx b/govtool/frontend/src/components/organisms/GovernanceActionDetailsCardData.tsx index b38a2b2d0..b8adba8e1 100644 --- a/govtool/frontend/src/components/organisms/GovernanceActionDetailsCardData.tsx +++ b/govtool/frontend/src/components/organisms/GovernanceActionDetailsCardData.tsx @@ -1,5 +1,5 @@ import { useMemo, useState, useEffect } from "react"; -import { Box, Tabs, Tab, styled, Skeleton } from "@mui/material"; +import { Box, Tabs, Tab, styled, Skeleton, Link } from "@mui/material"; import { useLocation } from "react-router-dom"; import CheckCircleOutlineIcon from "@mui/icons-material/CheckCircleOutline"; import CancelOutlinedIcon from "@mui/icons-material/CancelOutlined"; @@ -29,9 +29,11 @@ import { validateSignature, } from "@utils"; import { MetadataValidationStatus, ProposalData } from "@models"; +import { Trans } from "react-i18next"; import { errorRed, successGreen } from "@/consts"; import { GovernanceActionType } from "@/types/governanceAction"; import { useAppContext } from "@/context"; +import { theme } from "@/theme"; type TabPanelProps = { children?: React.ReactNode; @@ -165,6 +167,11 @@ export const GovernanceActionDetailsCardData = ({ hash ?? "" }`; + const isItMLabsWithdrawal = + type === GovernanceActionType.TreasuryWithdrawals && + cip129GovernanceActionId === + "gov_action18nefry4qacd80xzs2srjahxm2e4vz3c8wvrr03rrtk8mdqfuknysq66459t"; + const tabs = useMemo( () => [ @@ -390,6 +397,7 @@ export const GovernanceActionDetailsCardData = ({ publicKey={author.publicKey} algorithm={author.witnessAlgorithm} jsonContent={jsonContent} + forceValidStatus={isItMLabsWithdrawal} /> {author.name} ))} + {isItMLabsWithdrawal && authors && authors.length > 0 && } @@ -520,13 +529,16 @@ const AuthorSignatureStatus = ({ publicKey, signature, jsonContent, + forceValidStatus = false, }: { algorithm?: string; publicKey?: string; signature?: string; jsonContent?: Record; + forceValidStatus: boolean; }) => { const { t } = useTranslation(); + const [isSignatureValid, setIsSignatureValid] = useState( null, ); @@ -543,6 +555,9 @@ const AuthorSignatureStatus = ({ const result = await validateSignature(args); if (!cancelled) setIsSignatureValid(result); } + if (forceValidStatus) { + return setIsSignatureValid(true); + } checkSignature(); return () => { cancelled = true; @@ -573,3 +588,46 @@ const AuthorSignatureStatus = ({ ); }; + +const AuthorsVerificationInfoBox = () => { + const { t } = useTranslation(); + const { + palette: { lightBlue, secondaryBlue }, + } = theme; + + return ( + + + + + {t("govActions.safeModeInfoBox.title")} + + + {t("govActions.safeModeInfoBox.line1")} + + + ]} + /> + + + {t("govActions.safeModeInfoBox.link")} + + + + ); +}; diff --git a/govtool/frontend/src/i18n/locales/en.json b/govtool/frontend/src/i18n/locales/en.json index 4ecbc2ea9..4e89f3fb1 100644 --- a/govtool/frontend/src/i18n/locales/en.json +++ b/govtool/frontend/src/i18n/locales/en.json @@ -482,6 +482,12 @@ "additionalInformationAboutYourVote": "Additional information about your vote", "provideNewContextAboutYourVote": "Provide new context about your vote", "rationale": "Rationale", + "safeModeInfoBox": { + "title": "How this Author got verified?", + "line1": "A metadata formatting issue caused only part of the data to be signed, preventing automatic verification — the signature is valid and can be manually confirmed.", + "line2": "<0>Govtool have manually verified the signature confirming this Treasury action is genuinely coming from Intersect and has marked it accordingly to make it explicit to DReps.", + "link": "More details" + }, "seeExternalData": "See external data", "selectDifferentOption": "Select a different option to change your vote", "showVotes": "Show votes", From f115d816a36a6acf01822cc08e9707723a55d9b2 Mon Sep 17 00:00:00 2001 From: Sudip Bhattarai Date: Thu, 17 Jul 2025 21:36:22 +0545 Subject: [PATCH 13/16] Fix CommitteeThreshold query in network-metrics --- govtool/backend/sql/get-network-metrics.sql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/govtool/backend/sql/get-network-metrics.sql b/govtool/backend/sql/get-network-metrics.sql index 4aa9c8cbb..3d0844d49 100644 --- a/govtool/backend/sql/get-network-metrics.sql +++ b/govtool/backend/sql/get-network-metrics.sql @@ -186,9 +186,9 @@ CommitteeThreshold AS ( SELECT c.* FROM committee c - LEFT JOIN LatestGovAction lga ON c.gov_action_proposal_id = lga.id - WHERE (c.gov_action_proposal_id IS NOT NULL AND lga.id IS NOT NULL) - OR (c.gov_action_proposal_id IS NULL) + where + ( c.gov_action_proposal_id = (Select id from LatestGovAction)) + OR ( c.gov_action_proposal_id IS NULL) ) SELECT UniqueDelegators.count AS unique_delegators, From dae191e6e78ce0c9a179117b4463b48253ea74ad Mon Sep 17 00:00:00 2001 From: Sudip Bhattarai Date: Thu, 17 Jul 2025 23:09:56 +0545 Subject: [PATCH 14/16] Solve get-network-metrics returning 500 on preview --- govtool/backend/sql/get-network-metrics.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/govtool/backend/sql/get-network-metrics.sql b/govtool/backend/sql/get-network-metrics.sql index 3d0844d49..f5f821bc3 100644 --- a/govtool/backend/sql/get-network-metrics.sql +++ b/govtool/backend/sql/get-network-metrics.sql @@ -189,6 +189,7 @@ CommitteeThreshold AS ( where ( c.gov_action_proposal_id = (Select id from LatestGovAction)) OR ( c.gov_action_proposal_id IS NULL) + order by gov_action_proposal_id nulls last ) SELECT UniqueDelegators.count AS unique_delegators, From 4982aaf48778608006ee4b5d117ca94dff64e1cd Mon Sep 17 00:00:00 2001 From: Sudip Bhattarai Date: Fri, 18 Jul 2025 02:43:36 +0545 Subject: [PATCH 15/16] Fix Duplicate row in get-network-metrics query --- govtool/backend/sql/get-network-metrics.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/govtool/backend/sql/get-network-metrics.sql b/govtool/backend/sql/get-network-metrics.sql index f5f821bc3..73ddabc95 100644 --- a/govtool/backend/sql/get-network-metrics.sql +++ b/govtool/backend/sql/get-network-metrics.sql @@ -189,7 +189,7 @@ CommitteeThreshold AS ( where ( c.gov_action_proposal_id = (Select id from LatestGovAction)) OR ( c.gov_action_proposal_id IS NULL) - order by gov_action_proposal_id nulls last + order by gov_action_proposal_id nulls last limit 1 ) SELECT UniqueDelegators.count AS unique_delegators, From 4da521571f75e398e25652c21b92f9547a3d615e Mon Sep 17 00:00:00 2001 From: Aaron Boyle Date: Fri, 18 Jul 2025 11:05:56 +0100 Subject: [PATCH 16/16] updates copy --- govtool/frontend/src/i18n/locales/en.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/govtool/frontend/src/i18n/locales/en.json b/govtool/frontend/src/i18n/locales/en.json index 4e89f3fb1..73836a465 100644 --- a/govtool/frontend/src/i18n/locales/en.json +++ b/govtool/frontend/src/i18n/locales/en.json @@ -484,8 +484,8 @@ "rationale": "Rationale", "safeModeInfoBox": { "title": "How this Author got verified?", - "line1": "A metadata formatting issue caused only part of the data to be signed, preventing automatic verification — the signature is valid and can be manually confirmed.", - "line2": "<0>Govtool have manually verified the signature confirming this Treasury action is genuinely coming from Intersect and has marked it accordingly to make it explicit to DReps.", + "line1": "Due to a metadata formatting issue, only a part of the data was signed, which prevented GovTool's automatic verification. However, the signature is valid and can be confirmed manually.", + "line2": "<0>Govtool Builders have manually verified the signature, confirming that this Treasury action genuinely originates from Intersect. It has been marked accordingly to make this clear to DReps.", "link": "More details" }, "seeExternalData": "See external data",