diff --git a/.github/workflows/test_backend.yml b/.github/workflows/test_backend.yml
index faf2cbb86..963405dfc 100644
--- a/.github/workflows/test_backend.yml
+++ b/.github/workflows/test_backend.yml
@@ -33,12 +33,26 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
+ if [[ "${{ env.NETWORK }}" == "preprod" ]]; then
+ export FAUCET_API_KEY="${{ secrets.FAUCET_API_KEY_PREPROD }}"
+ elif [[ "${{ env.NETWORK }}" == "sanchonet" ]]; then
+ export FAUCET_API_KEY="${{ secrets.FAUCET_API_KEY_SANCHONET }}"
+ else
+ export FAUCET_API_KEY="${{ secrets.FAUCET_API_KEY_PREVIEW }}"
+ fi
python ./setup.py
python -m pytest --alluredir allure-results
+ if [[ "${{ env.NETWORK }}" == "preprod" ]]; then
+ echo "FAUCET_API_KEY=${{ secrets.FAUCET_API_KEY_PREPROD }}" >> $GITHUB_ENV
+ elif [[ "${{ env.NETWORK }}" == "sanchonet" ]]; then
+ echo "FAUCET_API_KEY=${{ secrets.FAUCET_API_KEY_SANCHONET }}" >> $GITHUB_ENV
+ else
+ echo "FAUCET_API_KEY=${{ secrets.FAUCET_API_KEY_PREVIEW }}" >> $GITHUB_ENV
+ fi
env:
BASE_URL: https://${{inputs.deployment || 'govtool.cardanoapi.io/api' }}
- FAUCET_API_KEY: ${{ secrets.FAUCET_API_KEY }}
- KUBER_API_URL: https://kuber-govtool.cardanoapi.io
+ NETWORK: ${{ vars.NETWORK }}
+ KUBER_API_KEY: ${{ secrets.KUBER_API_KEY }}
- name: Upload report
if: always()
diff --git a/.github/workflows/test_integration_playwright.yml b/.github/workflows/test_integration_playwright.yml
index e6a3ff358..3f3c5fab1 100644
--- a/.github/workflows/test_integration_playwright.yml
+++ b/.github/workflows/test_integration_playwright.yml
@@ -54,7 +54,18 @@ jobs:
mkdir -p ./lib/_mock
chmod +w ./lib/_mock
npm run generate-wallets
+ if [[ "${{ env.NETWORK }}" == "preprod" ]]; then
+ export FAUCET_API_KEY="${{ secrets.FAUCET_API_KEY_PREPROD }}"
+ export BLOCKFROST_API_KEY="${{ secrets.BLOCKFROST_API_KEY_PREPROD }}"
+ elif [[ "${{ env.NETWORK }}" == "sanchonet" ]]; then
+ export FAUCET_API_KEY="${{ secrets.FAUCET_API_KEY_SANCHONET }}"
+ export BLOCKFROST_API_KEY="${{ secrets.BLOCKFROST_API_KEY_SANCHONET }}"
+ else
+ export FAUCET_API_KEY="${{ secrets.FAUCET_API_KEY_PREVIEW }}"
+ export BLOCKFROST_API_KEY="${{ secrets.BLOCKFROST_API_KEY_PREVIEW }}"
+ fi
npm test
+
- name: Upload report
uses: actions/upload-artifact@v3
@@ -74,9 +85,6 @@ jobs:
HOST_URL: https://${{inputs.deployment || 'govtool.cardanoapi.io' }}
API_URL: https://${{inputs.deployment || 'govtool.cardanoapi.io' }}/api
DOCS_URL: ${{ vars.DOCS_URL }}
- FAUCET_API_URL: ${{ vars.FAUCET_API_URL }}
- FAUCET_API_KEY: ${{secrets.FAUCET_API_KEY}}
- KUBER_API_URL: ${{vars.KUBER_API_URL}}
KUBER_API_KEY: ${{secrets.KUBER_API_KEY}}
TEST_WORKERS: ${{vars.TEST_WORKERS}}
CI: ${{vars.CI}}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 77b3ae685..f956c1c23 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,12 +16,35 @@ changes.
### Fixed
+-
+
+### Changed
+
+-
+
+### Removed
+
+-
+
+## [v1.0.29](https://github.com/IntersectMBO/govtool/releases/tag/v1.0.29) 2024-12-05
+
+### Added
+
+- Add support for displaying CIP-119 DRep images [Issue 1806](https://github.com/IntersectMBO/govtool/issues/1806)
+
+### Fixed
+
- Fix fetching voting power of newly registerd DRep [Issue 2407](https://github.com/IntersectMBO/govtool/issues/2407)
- Fix inconsistent voting status [Issue 1713](https://github.com/IntersectMBO/govtool/issues/1713)
+- Fix removing a child (link) when is not registed in DOM [Issue 2398](https://github.com/IntersectMBO/govtool/issues/2398)
+- Fix blank screen on DRep delegation when UTXos are missing [Issue 2408](https://github.com/IntersectMBO/govtool/issues/2408)
+- Fix broken guides links [Issue 2417](https://github.com/IntersectMBO/govtool/issues/2417)
### Changed
--
+- Bump cardano-db-sync to 13.6.0.4 [Issue 2411](https://github.com/IntersectMBO/govtool/issues/2411)
+- Bump @intersect.mbo/pdf-ui to v0.5.3
+- Bump @intersect.mbo/pdf-ui to v0.5.4
### Removed
diff --git a/README.md b/README.md
index db07e081c..27388fa33 100644
--- a/README.md
+++ b/README.md
@@ -36,7 +36,7 @@ The Cardano GovTool enables ada holders to experience the governance features de
### Documentation
-Learn more; [docs.gov.tools](https://docs.gov.tools/).
+Learn more; [docs.gov.tools](https://docs.gov.tools/cardano-govtool/using-govtool).
## 📍 Navigation
diff --git a/docs/architecture/README.md b/docs/architecture/README.md
index 66689da9c..8a74d4f8a 100644
--- a/docs/architecture/README.md
+++ b/docs/architecture/README.md
@@ -23,7 +23,7 @@ utility backend that serves validation of the governance actions metadata.
# Description
-Frontend is a React application using Vite as a built tool to enhance development speed and optimize production builds. Frontend interacts with the backend service via REST API and with the Cardano blockchain via cardano-serialization-lib and connected supported wallets (for the list of compatible wallets go [here](https://docs.gov.tools/how-to-use-the-govtool/getting-started/get-a-compatible-wallet)).
+Frontend is a React application using Vite as a built tool to enhance development speed and optimize production builds. Frontend interacts with the backend service via REST API and with the Cardano blockchain via cardano-serialization-lib and connected supported wallets (for the list of compatible wallets go [here](https://docs.gov.tools/cardano-govtool/using-govtool/getting-started/compatible-wallets)).
# Components
diff --git a/govtool/backend/Dockerfile b/govtool/backend/Dockerfile
index 9c1fabd7f..94b48a425 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-1.0.28/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-1.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 f7e8fd8ba..53e825921 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-1.0.28/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-1.0.29/x/vva-be/build/vva-be/vva-be /usr/local/bin
# Expose the necessary port
EXPOSE 9876
diff --git a/govtool/backend/app/Main.hs b/govtool/backend/app/Main.hs
index 91a743025..e0dd5d3b8 100644
--- a/govtool/backend/app/Main.hs
+++ b/govtool/backend/app/Main.hs
@@ -53,7 +53,7 @@ import System.Clock (TimeSpec (TimeSpec))
import System.IO (stderr)
import System.Log.Raven (initRaven, register, silentFallback)
import System.Log.Raven.Transport.HttpConduit (sendRecord)
-import System.Log.Raven.Types (SentryLevel (Error), SentryRecord (..))
+import System.Log.Raven.Types (SentryLevel (Error), SentryRecord (..), SentryService)
import System.TimeManager (TimeoutThread (..))
import VVA.API
@@ -71,12 +71,18 @@ main :: IO ()
main = do
commandLineConfig <- execParser cmdParser
vvaConfig <- loadVVAConfig (clcConfigPath commandLineConfig)
+ sentryService <-
+ initRaven
+ (sentryDSN vvaConfig)
+ id
+ sendRecord
+ silentFallback
case clcCommand commandLineConfig of
- StartApp -> startApp vvaConfig
+ StartApp -> startApp vvaConfig sentryService
ShowConfig -> Text.putStrLn $ vvaConfigToText vvaConfig
-startApp :: VVAConfig -> IO ()
-startApp vvaConfig = do
+startApp :: VVAConfig -> SentryService -> IO ()
+startApp vvaConfig sentryService = do
let vvaPort = serverPort vvaConfig
vvaHost = fromString (Text.unpack (serverHost vvaConfig))
settings =
@@ -92,7 +98,7 @@ startApp vvaConfig = do
++ show vvaPort
)
)
- $ setOnException (exceptionHandler vvaConfig) defaultSettings
+ $ setOnException (exceptionHandler vvaConfig sentryService) defaultSettings
cacheEnv <- do
let newCache = Cache.newCache (Just $ TimeSpec (fromIntegral (cacheDurationSeconds vvaConfig)) 0)
proposalListCache <- newCache
@@ -122,8 +128,8 @@ startApp vvaConfig = do
server' <- mkVVAServer appEnv
runSettings settings server'
-exceptionHandler :: VVAConfig -> Maybe Request -> SomeException -> IO ()
-exceptionHandler vvaConfig mRequest exception = do
+exceptionHandler :: VVAConfig -> SentryService -> Maybe Request -> SomeException -> IO ()
+exceptionHandler vvaConfig sentryService mRequest exception = do
print mRequest
print exception
let isNotTimeoutThread x = case fromException x of
@@ -135,12 +141,6 @@ exceptionHandler vvaConfig mRequest exception = do
guard . isNotTimeoutThread $ exception
guard . isNotConnectionClosedByPeer $ exception
let env = sentryEnv vvaConfig
- sentryService <-
- initRaven
- (sentryDSN vvaConfig)
- id
- sendRecord
- silentFallback
register
sentryService
"vva.be"
diff --git a/govtool/backend/vva-be.cabal b/govtool/backend/vva-be.cabal
index 14c7fcb34..bfc746013 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: 1.0.28
+version: 1.0.29
-- A short (one-line) description of the package.
-- synopsis:
diff --git a/govtool/frontend/.env.example b/govtool/frontend/.env.example
index 5fbb1a97f..2489d65a0 100644
--- a/govtool/frontend/.env.example
+++ b/govtool/frontend/.env.example
@@ -8,3 +8,5 @@ VITE_IS_DEV=true
VITE_USERSNAP_SPACE_API_KEY=""
VITE_IS_PROPOSAL_DISCUSSION_FORUM_ENABLED='true'
VITE_PDF_API_URL=""
+VITE_IPFS_GATEWAY=""
+VITE_IPFS_PROJECT_ID=""
\ No newline at end of file
diff --git a/govtool/frontend/Dockerfile b/govtool/frontend/Dockerfile
index 5186b390e..9a12dba06 100644
--- a/govtool/frontend/Dockerfile
+++ b/govtool/frontend/Dockerfile
@@ -10,6 +10,8 @@ ARG NPMRC_TOKEN
ARG VITE_USERSNAP_SPACE_API_KEY
ARG VITE_IS_PROPOSAL_DISCUSSION_FORUM_ENABLED='true'
ARG VITE_PDF_API_URL
+ARG VITE_IPFS_GATEWAY
+ARG VITE_IPFS_PROJECT_ID
# Ensure all required build arguments are set
RUN \
@@ -21,7 +23,9 @@ RUN \
: "${VITE_SENTRY_DSN:?Build argument VITE_SENTRY_DSN is not set}" && \
: "${NPMRC_TOKEN:?Build argument NPMRC_TOKEN is not set}" && \
: "${VITE_USERSNAP_SPACE_API_KEY:?Build argument VITE_USERSNAP_SPACE_API_KEY is not set}" && \
- : "${VITE_IS_PROPOSAL_DISCUSSION_FORUM_ENABLED:?Build argument VITE_IS_PROPOSAL_DISCUSSION_FORUM_ENABLED is not set}"
+ : "${VITE_IS_PROPOSAL_DISCUSSION_FORUM_ENABLED:?Build argument VITE_IS_PROPOSAL_DISCUSSION_FORUM_ENABLED is not set}" && \
+ : "${VITE_IPFS_GATEWAY:?Build argument VITE_IPFS_GATEWAY is not set}" && \
+ : "${VITE_IPFS_PROJECT_ID:?Build argument VITE_IPFS_PROJECT_ID is not set}"
ENV NODE_OPTIONS=--max_old_space_size=8192
diff --git a/govtool/frontend/Dockerfile.qovery b/govtool/frontend/Dockerfile.qovery
index ddc6c1288..f9b562ade 100644
--- a/govtool/frontend/Dockerfile.qovery
+++ b/govtool/frontend/Dockerfile.qovery
@@ -10,6 +10,8 @@ ARG NPMRC_TOKEN
ARG VITE_USERSNAP_SPACE_API_KEY
ARG VITE_IS_PROPOSAL_DISCUSSION_FORUM_ENABLED='true'
ARG VITE_PDF_API_URL
+ARG VITE_IPFS_GATEWAY
+ARG VITE_IPFS_PROJECT_ID
ENV NODE_OPTIONS=--max_old_space_size=8192
diff --git a/govtool/frontend/package-lock.json b/govtool/frontend/package-lock.json
index 200ada00e..a0b5f3816 100644
--- a/govtool/frontend/package-lock.json
+++ b/govtool/frontend/package-lock.json
@@ -14,7 +14,7 @@
"@emurgo/cardano-serialization-lib-asmjs": "^13.1.0",
"@hookform/resolvers": "^3.3.1",
"@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8",
- "@intersect.mbo/pdf-ui": "^0.5.2",
+ "@intersect.mbo/pdf-ui": "^0.5.4",
"@mui/icons-material": "^5.14.3",
"@mui/material": "^5.14.4",
"@rollup/plugin-babel": "^6.0.4",
@@ -3513,9 +3513,9 @@
"license": "ISC"
},
"node_modules/@intersect.mbo/pdf-ui": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.5.2.tgz",
- "integrity": "sha512-zKPL3p+rve8GKDlDd9EozvVs/TDnCP6dDOLySeNndaiXaRw32QBdAOt5pSHaE0NGymKahlVV2QwO2vFNiawopA==",
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.5.4.tgz",
+ "integrity": "sha512-QKaI+0C52/YAagkrRKzQQ/X2DwOHPovappEgeUXmVecvLzbVoJpKY9zGo5sNzmdu5qkYnE5/yIWbHZGVPpbvBA==",
"dependencies": {
"@emurgo/cardano-serialization-lib-asmjs": "^12.0.0-beta.2",
"@fontsource/poppins": "^5.0.14",
diff --git a/govtool/frontend/package.json b/govtool/frontend/package.json
index 3144989d1..3df53b084 100644
--- a/govtool/frontend/package.json
+++ b/govtool/frontend/package.json
@@ -1,7 +1,7 @@
{
"name": "@govtool/frontend",
"private": true,
- "version": "1.0.28",
+ "version": "1.0.29",
"type": "module",
"scripts": {
"build": "vite build",
@@ -28,7 +28,7 @@
"@emurgo/cardano-serialization-lib-asmjs": "^13.1.0",
"@hookform/resolvers": "^3.3.1",
"@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8",
- "@intersect.mbo/pdf-ui": "^0.5.2",
+ "@intersect.mbo/pdf-ui": "^0.5.4",
"@mui/icons-material": "^5.14.3",
"@mui/material": "^5.14.4",
"@rollup/plugin-babel": "^6.0.4",
@@ -108,5 +108,5 @@
"overrides": {
"typescript": "^5.0.2"
},
- "_id": "govtool@1.0.28"
+ "_id": "govtool@1.0.29"
}
diff --git a/govtool/frontend/public/icons/DefaultDRep.svg b/govtool/frontend/public/icons/DefaultDRep.svg
new file mode 100644
index 000000000..00557579b
--- /dev/null
+++ b/govtool/frontend/public/icons/DefaultDRep.svg
@@ -0,0 +1,5 @@
+
diff --git a/govtool/frontend/src/components/molecules/DataMissingHeader.tsx b/govtool/frontend/src/components/molecules/DataMissingHeader.tsx
index 6267d8742..ef6e278b4 100644
--- a/govtool/frontend/src/components/molecules/DataMissingHeader.tsx
+++ b/govtool/frontend/src/components/molecules/DataMissingHeader.tsx
@@ -1,19 +1,24 @@
-import { Box, SxProps } from "@mui/material";
+import { Avatar, Box, SxProps } from "@mui/material";
import { Typography } from "@atoms";
import { MetadataValidationStatus } from "@models";
import { getMetadataDataMissingStatusTranslation } from "@/utils";
+import { ICONS } from "@/consts";
type DataMissingHeaderProps = {
isDataMissing: MetadataValidationStatus | null;
title?: string;
titleStyle?: SxProps;
+ isDRep?: boolean;
+ image?: string | null;
};
export const DataMissingHeader = ({
title,
isDataMissing,
titleStyle,
+ isDRep,
+ image,
}: DataMissingHeaderProps) => (
+ {isDRep && (
+
+ )}
- openInNewTab(
- "https://docs.gov.tools/using-govtool/govtool-functions/dreps/drep-error-conditions",
- )
- }
+ onClick={() => openInNewTab(LINKS.DREP_ERROR_CONDITIONS)}
sx={{
fontFamily: "Poppins",
fontSize: "16px",
diff --git a/govtool/frontend/src/components/organisms/AutomatedVotingOptions.tsx b/govtool/frontend/src/components/organisms/AutomatedVotingOptions.tsx
index 4b84380e8..acfcf7c33 100644
--- a/govtool/frontend/src/components/organisms/AutomatedVotingOptions.tsx
+++ b/govtool/frontend/src/components/organisms/AutomatedVotingOptions.tsx
@@ -16,6 +16,7 @@ import {
AutomatedVotingOptionCurrentDelegation,
AutomatedVotingOptionDelegationId,
} from "@/types/automatedVotingOptions";
+import { LINKS } from "@/consts/links";
type AutomatedVotingOptionsProps = {
currentDelegation?: string | null;
@@ -118,11 +119,7 @@ export const AutomatedVotingOptions = ({
onClickDelegate={() =>
delegate(AutomatedVotingOptionDelegationId.abstain)
}
- onClickInfo={() =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/govtool-functions/delegating/abstain-from-every-vote",
- )
- }
+ onClickInfo={() => openInNewTab(LINKS.ABSTAIN_FROM_EVERY_VOTE)}
title={
isDelegatedToAbstain
? t("dRepDirectory.delegatedToAbstainTitle", {
@@ -162,9 +159,7 @@ export const AutomatedVotingOptions = ({
delegate(AutomatedVotingOptionDelegationId.no_confidence)
}
onClickInfo={() =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/govtool-functions/delegating/signal-no-confidence-on-every-vote",
- )
+ openInNewTab(LINKS.SIGNAL_NO_CONFIDENCE_ON_EVERY_VOTE)
}
title={
isDelegatedToNoConfidence
diff --git a/govtool/frontend/src/components/organisms/CreateGovernanceActionSteps/StorageInformation.tsx b/govtool/frontend/src/components/organisms/CreateGovernanceActionSteps/StorageInformation.tsx
index 0252327d0..7deecc45d 100644
--- a/govtool/frontend/src/components/organisms/CreateGovernanceActionSteps/StorageInformation.tsx
+++ b/govtool/frontend/src/components/organisms/CreateGovernanceActionSteps/StorageInformation.tsx
@@ -17,6 +17,7 @@ import {
isValidURLLength,
openInNewTab,
} from "@utils";
+import { LINKS } from "@/consts/links";
type StorageInformationProps = {
setStep: Dispatch>;
@@ -39,9 +40,7 @@ export const StorageInformation = ({ setStep }: StorageInformationProps) => {
const fileName = getValues("governance_action_type") as string;
const openGuideAboutStoringInformation = () =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/govtool-functions/storing-information-offline",
- );
+ openInNewTab(LINKS.STORING_INFORMATION_OFFLINE);
const isActionButtonDisabled = !watch("storingURL") || !!errors.storingURL;
diff --git a/govtool/frontend/src/components/organisms/CreateGovernanceActionSteps/StoreDataInfo.tsx b/govtool/frontend/src/components/organisms/CreateGovernanceActionSteps/StoreDataInfo.tsx
index 9beb1f9e1..1dc5da480 100644
--- a/govtool/frontend/src/components/organisms/CreateGovernanceActionSteps/StoreDataInfo.tsx
+++ b/govtool/frontend/src/components/organisms/CreateGovernanceActionSteps/StoreDataInfo.tsx
@@ -10,6 +10,7 @@ import {
import { CenteredBoxBottomButtons } from "@molecules";
import { ControlledField } from "@organisms";
import { openInNewTab } from "@utils";
+import { LINKS } from "@/consts/links";
type StoreDataInfoProps = {
setStep: Dispatch>;
@@ -20,10 +21,7 @@ export const StoreDataInfo = ({ setStep }: StoreDataInfoProps) => {
const { control, errors, watch } = useCreateGovernanceActionForm();
const { isMobile } = useScreenDimension();
- const openLink = () =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/govtool-functions/storing-information-offline",
- );
+ const openLink = () => openInNewTab(LINKS.STORING_INFORMATION_OFFLINE);
const isContinueDisabled = !watch("storeData");
diff --git a/govtool/frontend/src/components/organisms/DRepCard.tsx b/govtool/frontend/src/components/organisms/DRepCard.tsx
index d63d0b859..c396f8f46 100644
--- a/govtool/frontend/src/components/organisms/DRepCard.tsx
+++ b/govtool/frontend/src/components/organisms/DRepCard.tsx
@@ -1,5 +1,5 @@
import { useNavigate } from "react-router-dom";
-import { Box, ButtonBase, Divider } from "@mui/material";
+import { Box, ButtonBase, Divider, Avatar } from "@mui/material";
import { Button, StatusPill, Typography } from "@atoms";
import { ICONS, PATHS } from "@consts";
@@ -24,7 +24,7 @@ type DRepCardProps = {
};
export const DRepCard = ({
- dRep: { status, type, view, votingPower, givenName, metadataStatus },
+ dRep: { status, type, view, votingPower, givenName, metadataStatus, image },
isConnected,
isDelegationLoading,
isInProgress,
@@ -100,36 +100,47 @@ export const DRepCard = ({
containerType: "inline-size",
}}
>
-
-
- {metadataStatus
- ? getMetadataDataMissingStatusTranslation(metadataStatus)
- : ellipsizeText(givenName ?? "", 25)}
-
- {
- navigator.clipboard.writeText(view);
- addSuccessAlert(t("alerts.copiedToClipboard"));
- e.stopPropagation();
- }}
- sx={{
- gap: 1,
- width: "250px",
- maxWidth: "100%",
- "&:hover": {
- opacity: 0.6,
- transition: "opacity 0.3s",
- },
- }}
- >
-
- {view}
+
+
+
+
+ {metadataStatus
+ ? getMetadataDataMissingStatusTranslation(metadataStatus)
+ : ellipsizeText(givenName ?? "", 25)}
-
-
+ {
+ navigator.clipboard.writeText(view);
+ addSuccessAlert(t("alerts.copiedToClipboard"));
+ e.stopPropagation();
+ }}
+ sx={{
+ gap: 1,
+ width: "250px",
+ maxWidth: "100%",
+ "&:hover": {
+ opacity: 0.6,
+ transition: "opacity 0.3s",
+ },
+ }}
+ >
+
+ {view}
+
+
+
+
diff --git a/govtool/frontend/src/components/organisms/DRepDetailsCardHeader.tsx b/govtool/frontend/src/components/organisms/DRepDetailsCardHeader.tsx
index 77092b30f..ecbb61eba 100644
--- a/govtool/frontend/src/components/organisms/DRepDetailsCardHeader.tsx
+++ b/govtool/frontend/src/components/organisms/DRepDetailsCardHeader.tsx
@@ -32,7 +32,7 @@ export const DRepDetailsCardHeader = ({
const { votingPower: myVotingPower } =
useGetAdaHolderVotingPowerQuery(stakeKey);
- const { givenName, metadataStatus } = dRepData;
+ const { givenName, metadataStatus, image } = dRepData;
const navigateToEditDRep = () => {
navigate(PATHS.editDrepMetadata, {
@@ -121,7 +121,9 @@ export const DRepDetailsCardHeader = ({
)}
diff --git a/govtool/frontend/src/components/organisms/DashboardCards/DRepDashboardCard.tsx b/govtool/frontend/src/components/organisms/DashboardCards/DRepDashboardCard.tsx
index b9c4338f7..bd9908734 100644
--- a/govtool/frontend/src/components/organisms/DashboardCards/DRepDashboardCard.tsx
+++ b/govtool/frontend/src/components/organisms/DashboardCards/DRepDashboardCard.tsx
@@ -11,6 +11,7 @@ import {
DashboardActionCardProps,
} from "@molecules";
import { correctAdaFormat, openInNewTab } from "@utils";
+import { LINKS } from "@/consts/links";
type DRepDashboardCardProps = {
dRepID: string;
@@ -37,10 +38,7 @@ export const DRepDashboardCard = ({
const learnMoreButton = {
children: t("learnMore"),
dataTestId: "d-rep-learn-more-button",
- onClick: () =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/govtool-functions/dreps/register-as-a-drep",
- ),
+ onClick: () => openInNewTab(LINKS.REGISTER_AS_A_DREP),
};
const navigateToDrepDirectory = () => {
@@ -130,10 +128,7 @@ export const DRepDashboardCard = ({
? {
children: t("learnMore"),
dataTestId: "register-learn-more-button",
- onClick: () =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/govtool-functions/dreps/retire-as-a-drep",
- ),
+ onClick: () => openInNewTab(LINKS.RETIRE_AS_A_DREP),
}
: learnMoreButton,
];
diff --git a/govtool/frontend/src/components/organisms/DashboardCards/DelegateDashboardCard.tsx b/govtool/frontend/src/components/organisms/DashboardCards/DelegateDashboardCard.tsx
index 16459cd0b..b4a13d090 100644
--- a/govtool/frontend/src/components/organisms/DashboardCards/DelegateDashboardCard.tsx
+++ b/govtool/frontend/src/components/organisms/DashboardCards/DelegateDashboardCard.tsx
@@ -20,6 +20,7 @@ import {
AutomatedVotingOptionCurrentDelegation,
AutomatedVotingOptionDelegationId,
} from "@/types/automatedVotingOptions";
+import { LINKS } from "@/consts/links";
type DelegateDashboardCardProps = {
currentDelegation: CurrentDelegation;
@@ -45,10 +46,7 @@ export const DelegateDashboardCard = ({
const learnMoreButton = {
children: t("learnMore"),
dataTestId: "delegate-learn-more-button",
- onClick: () =>
- openInNewTab(
- "https://docs.gov.tools/how-to-use-the-govtool/using-govtool/delegating",
- ),
+ onClick: () => openInNewTab(LINKS.DELEGATING),
sx: { backgroundColor: "arcticWhite" },
};
diff --git a/govtool/frontend/src/components/organisms/DashboardCards/DirectVoterDashboardCard.tsx b/govtool/frontend/src/components/organisms/DashboardCards/DirectVoterDashboardCard.tsx
index a32e9a2f9..386aca6d4 100644
--- a/govtool/frontend/src/components/organisms/DashboardCards/DirectVoterDashboardCard.tsx
+++ b/govtool/frontend/src/components/organisms/DashboardCards/DirectVoterDashboardCard.tsx
@@ -8,6 +8,7 @@ import { useTranslation } from "@hooks";
import { VoterInfo } from "@models";
import { DashboardActionCard, DashboardActionCardProps } from "@molecules";
import { correctAdaFormat, openInNewTab } from "@utils";
+import { LINKS } from "@/consts/links";
type DirectVoterDashboardCardProps = {
pendingTransaction: PendingTransaction;
@@ -29,10 +30,7 @@ export const DirectVoterDashboardCard = ({
const learnMoreButton: LoadingButtonProps = {
children: t("learnMore"),
dataTestId: "direct-voter-learn-more-button",
- onClick: () =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/govtool-functions/direct-voting",
- ),
+ onClick: () => openInNewTab(LINKS.DIRECT_VOTING),
};
const cardProps: Partial = (() => {
@@ -96,10 +94,7 @@ export const DirectVoterDashboardCard = ({
{
children: t("learnMore"),
dataTestId: "learn-more-button",
- onClick: () =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/govtool-functions/direct-voting",
- ),
+ onClick: () => openInNewTab(LINKS.DIRECT_VOTING),
},
],
description: (
diff --git a/govtool/frontend/src/components/organisms/DashboardCards/ListGovActionsDashboardCard.tsx b/govtool/frontend/src/components/organisms/DashboardCards/ListGovActionsDashboardCard.tsx
index 00973c58d..eb59c26c5 100644
--- a/govtool/frontend/src/components/organisms/DashboardCards/ListGovActionsDashboardCard.tsx
+++ b/govtool/frontend/src/components/organisms/DashboardCards/ListGovActionsDashboardCard.tsx
@@ -4,6 +4,7 @@ import { IMAGES, PATHS } from "@consts";
import { useTranslation } from "@hooks";
import { DashboardActionCard } from "@molecules";
import { openInNewTab } from "@utils";
+import { LINKS } from "@/consts/links";
export const ListGovActionsDashboardCards = () => {
const navigate = useNavigate();
@@ -21,10 +22,7 @@ export const ListGovActionsDashboardCards = () => {
{
children: t("learnMore"),
dataTestId: "list-gov-actions-learn-more-button",
- onClick: () =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/govtool-functions/governance-actions/view-governance-actions",
- ),
+ onClick: () => openInNewTab(LINKS.VIEW_GOVERNANCE_ACTIONS),
variant: "outlined",
},
]}
diff --git a/govtool/frontend/src/components/organisms/DashboardCards/ProposeGovActionDashboardCard.tsx b/govtool/frontend/src/components/organisms/DashboardCards/ProposeGovActionDashboardCard.tsx
index 46191b137..165da2787 100644
--- a/govtool/frontend/src/components/organisms/DashboardCards/ProposeGovActionDashboardCard.tsx
+++ b/govtool/frontend/src/components/organisms/DashboardCards/ProposeGovActionDashboardCard.tsx
@@ -6,6 +6,7 @@ import { useTranslation } from "@hooks";
import { DashboardActionCard } from "@molecules";
import { openInNewTab } from "@utils";
import { useCallback } from "react";
+import { LINKS } from "@/consts/links";
type ProposeGovActionDashboardCardProps = {
createGovActionTx: PendingTransaction["createGovAction"];
@@ -52,10 +53,7 @@ export const ProposeGovActionDashboardCard = ({
{
children: t("learnMore"),
dataTestId: "propose-gov-action-learn-more-button",
- onClick: () =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/govtool-functions/governance-actions/propose-a-governance-action",
- ),
+ onClick: () => openInNewTab(LINKS.PROPOSE_A_GOVERNANCE_ACTION),
},
]}
description={t("dashboard.cards.proposeGovernanceAction.description")}
diff --git a/govtool/frontend/src/components/organisms/DrawerMobile.tsx b/govtool/frontend/src/components/organisms/DrawerMobile.tsx
index b2e107da9..dd48651a0 100644
--- a/govtool/frontend/src/components/organisms/DrawerMobile.tsx
+++ b/govtool/frontend/src/components/organisms/DrawerMobile.tsx
@@ -7,6 +7,7 @@ import { useFeatureFlag, useModal } from "@context";
import { openInNewTab } from "@utils";
import { DrawerMobileProps } from "./types";
+import { LINKS } from "@/consts/links";
const DRAWER_PADDING = 2;
const CALCULATED_DRAWER_PADDING = DRAWER_PADDING * 8 * 2;
@@ -21,10 +22,7 @@ export const DrawerMobile = ({
const { openModal } = useModal();
const { t } = useTranslation();
- const onClickHelp = () =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/support#for-support-you-can-reach-the-team-on-the-intersect-discord-server-at",
- );
+ const onClickHelp = () => openInNewTab(LINKS.SUPPORT);
return (
>;
@@ -35,9 +36,7 @@ export const EditDRepStorageInformation = ({
const fileName = getValues("givenName");
const openGuideAboutStoringInformation = () =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/govtool-functions/storing-information-offline",
- );
+ openInNewTab(LINKS.STORING_INFORMATION_OFFLINE);
const isActionButtonDisabled = !watch("storingURL") || !!errors.storingURL;
diff --git a/govtool/frontend/src/components/organisms/EditDRepInfoSteps/EditDRepStoreDataInfo.tsx b/govtool/frontend/src/components/organisms/EditDRepInfoSteps/EditDRepStoreDataInfo.tsx
index e7fe54d7e..065e8e9e8 100644
--- a/govtool/frontend/src/components/organisms/EditDRepInfoSteps/EditDRepStoreDataInfo.tsx
+++ b/govtool/frontend/src/components/organisms/EditDRepInfoSteps/EditDRepStoreDataInfo.tsx
@@ -11,6 +11,7 @@ import {
import { openInNewTab } from "@utils";
import { ControlledField } from "..";
+import { LINKS } from "@/consts/links";
export const EditDRepStoreDataInfo = ({
setStep,
@@ -27,10 +28,7 @@ export const EditDRepStoreDataInfo = ({
const isContinueDisabled = !watch("storeData");
- const openLink = () =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/govtool-functions/storing-information-offline",
- );
+ const openLink = () => openInNewTab(LINKS.STORING_INFORMATION_OFFLINE);
return (
<>
diff --git a/govtool/frontend/src/components/organisms/Footer.tsx b/govtool/frontend/src/components/organisms/Footer.tsx
index 79f037d8e..84b1e063d 100644
--- a/govtool/frontend/src/components/organisms/Footer.tsx
+++ b/govtool/frontend/src/components/organisms/Footer.tsx
@@ -5,6 +5,7 @@ import { ICONS } from "@consts";
import { useUsersnapApi } from "@context";
import { useScreenDimension, useTranslation } from "@hooks";
import { openInNewTab, testIdFromLabel } from "@utils";
+import { LINKS } from "@/consts/links";
type FooterLinkProps = {
label: string;
@@ -34,10 +35,7 @@ export const Footer = () => {
const { t } = useTranslation();
const { openFeedbackWindow } = useUsersnapApi();
- const onClickHelp = () =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/support#for-support-you-can-reach-the-team-on-the-intersect-discord-server-at",
- );
+ const onClickHelp = () => openInNewTab(LINKS.SUPPORT);
const onClickPrivacyPolicy = () =>
openInNewTab(
diff --git a/govtool/frontend/src/components/organisms/HomeCards.tsx b/govtool/frontend/src/components/organisms/HomeCards.tsx
index 59c97b252..8cc1e63f2 100644
--- a/govtool/frontend/src/components/organisms/HomeCards.tsx
+++ b/govtool/frontend/src/components/organisms/HomeCards.tsx
@@ -7,6 +7,7 @@ import { useFeatureFlag, useModal } from "@context";
import { ActionCard } from "@molecules";
import { useTranslation } from "@hooks";
import { openInNewTab } from "@utils";
+import { LINKS } from "@/consts/links";
export const HomeCards = () => {
const { isProposalDiscussionForumEnabled } = useFeatureFlag();
@@ -26,25 +27,16 @@ export const HomeCards = () => {
[openModal],
);
- const onClickLearnMoreAboutDelegation = () =>
- openInNewTab(
- "https://docs.gov.tools/how-to-use-the-govtool/using-govtool/delegating",
- );
+ const onClickLearnMoreAboutDelegation = () => openInNewTab(LINKS.DELEGATING);
const onClickLearnMoreAboutDRepRegistration = () =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/govtool-functions/dreps/register-as-a-drep",
- );
+ openInNewTab(LINKS.REGISTER_AS_A_DREP);
const onClickLearnMoreAboutDirectVoterRegistration = () =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/govtool-functions/direct-voting",
- );
+ openInNewTab(LINKS.DIRECT_VOTING);
const onClickLearnMoreAboutProposingGovAction = () =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/govtool-functions/governance-actions/governance-actions/propose-a-governance-action",
- );
+ openInNewTab(LINKS.PROPOSE_A_GOVERNANCE_ACTION);
const navigateToGovActions = useCallback(
() => navigate(PATHS.governanceActions),
diff --git a/govtool/frontend/src/components/organisms/Modal/ChooseWalletModal.tsx b/govtool/frontend/src/components/organisms/Modal/ChooseWalletModal.tsx
index 87a2ed712..16acd5cfa 100644
--- a/govtool/frontend/src/components/organisms/Modal/ChooseWalletModal.tsx
+++ b/govtool/frontend/src/components/organisms/Modal/ChooseWalletModal.tsx
@@ -8,6 +8,7 @@ import { WalletOptionButton } from "@molecules";
import { openInNewTab } from "@utils";
import { useTranslation } from "@hooks";
import { To } from "react-router-dom";
+import { LINKS } from "@/consts/links";
type ChooseWalletModalState = {
pathToNavigate?: To;
@@ -105,11 +106,7 @@ export const ChooseWalletModal = forwardRef((_, ref) => {
- openInNewTab(
- "https://docs.gov.tools/how-to-use-the-govtool/getting-started/get-a-compatible-wallet",
- )
- }
+ onClick={() => openInNewTab(LINKS.COMPATIBLE_WALLETS)}
sx={{ cursor: "pointer" }}
>
{t("here")}
diff --git a/govtool/frontend/src/components/organisms/RegisterAsDRepSteps/DRepStorageInformation.tsx b/govtool/frontend/src/components/organisms/RegisterAsDRepSteps/DRepStorageInformation.tsx
index c36e73667..ab52f9882 100644
--- a/govtool/frontend/src/components/organisms/RegisterAsDRepSteps/DRepStorageInformation.tsx
+++ b/govtool/frontend/src/components/organisms/RegisterAsDRepSteps/DRepStorageInformation.tsx
@@ -12,6 +12,7 @@ import {
import { CenteredBoxBottomButtons, Step } from "@molecules";
import { ControlledField } from "@organisms";
import { openInNewTab, ellipsizeText } from "@utils";
+import { LINKS } from "@/consts/links";
type StorageInformationProps = {
setStep: Dispatch>;
@@ -36,9 +37,7 @@ export const DRepStorageInformation = ({
const fileName = getValues("givenName");
const openGuideAboutStoringInformation = () =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/govtool-functions/storing-information-offline",
- );
+ openInNewTab(LINKS.STORING_INFORMATION_OFFLINE);
const isActionButtonDisabled = !watch("storingURL") || !!errors.storingURL;
diff --git a/govtool/frontend/src/components/organisms/RegisterAsDRepSteps/DRepStoreDataInfo.tsx b/govtool/frontend/src/components/organisms/RegisterAsDRepSteps/DRepStoreDataInfo.tsx
index a05696d7c..e8c31eff1 100644
--- a/govtool/frontend/src/components/organisms/RegisterAsDRepSteps/DRepStoreDataInfo.tsx
+++ b/govtool/frontend/src/components/organisms/RegisterAsDRepSteps/DRepStoreDataInfo.tsx
@@ -11,6 +11,7 @@ import {
import { openInNewTab } from "@utils";
import { ControlledField } from "..";
+import { LINKS } from "@/consts/links";
export const DRepStoreDataInfo = ({
setStep,
@@ -27,10 +28,7 @@ export const DRepStoreDataInfo = ({
const onClickContinue = () => setStep(4);
- const openLink = () =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/govtool-functions/storing-information-offline",
- );
+ const openLink = () => openInNewTab(LINKS.STORING_INFORMATION_OFFLINE);
return (
<>
diff --git a/govtool/frontend/src/components/organisms/RegisterAsDRepSteps/RolesAndResponsibilities.tsx b/govtool/frontend/src/components/organisms/RegisterAsDRepSteps/RolesAndResponsibilities.tsx
index a87883656..932bfe73f 100644
--- a/govtool/frontend/src/components/organisms/RegisterAsDRepSteps/RolesAndResponsibilities.tsx
+++ b/govtool/frontend/src/components/organisms/RegisterAsDRepSteps/RolesAndResponsibilities.tsx
@@ -11,6 +11,7 @@ import {
openInNewTab,
PROTOCOL_PARAMS_KEY,
} from "@utils";
+import { LINKS } from "@/consts/links";
export const RolesAndResponsibilities = ({
setStep,
@@ -24,10 +25,7 @@ export const RolesAndResponsibilities = ({
const onClickContinue = () => setStep(2);
- const openLearnMoreAboutDrep = () =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/govtool-functions/dreps",
- );
+ const openLearnMoreAboutDrep = () => openInNewTab(LINKS.DREPS);
return (
<>
diff --git a/govtool/frontend/src/components/organisms/TopBanners.tsx b/govtool/frontend/src/components/organisms/TopBanners.tsx
index 332a2c440..e27b8138d 100644
--- a/govtool/frontend/src/components/organisms/TopBanners.tsx
+++ b/govtool/frontend/src/components/organisms/TopBanners.tsx
@@ -1,6 +1,7 @@
import { Box, Link, Typography } from "@mui/material";
import { Trans, useTranslation } from "react-i18next";
import { useAppContext } from "@/context";
+import { LINKS } from "@/consts/links";
export const TopBanners = () => {
const { isMainnet, networkName, isInBootstrapPhase, isAppInitializing } =
@@ -60,7 +61,7 @@ export const TopBanners = () => {
components={{
docs: (
>;
@@ -35,9 +36,7 @@ export const VoteContextStoringInformation = ({
} = useVoteContextForm(setSavedHash, setStep, setErrorMessage);
const openGuideAboutStoringInformation = () =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/govtool-functions/storing-information-offline",
- );
+ openInNewTab(LINKS.STORING_INFORMATION_OFFLINE);
const isContinueDisabled = !watch("storingURL");
diff --git a/govtool/frontend/src/components/organisms/VoteContext/VoteContextTerms.tsx b/govtool/frontend/src/components/organisms/VoteContext/VoteContextTerms.tsx
index a98a948c8..d59d1af38 100644
--- a/govtool/frontend/src/components/organisms/VoteContext/VoteContextTerms.tsx
+++ b/govtool/frontend/src/components/organisms/VoteContext/VoteContextTerms.tsx
@@ -5,6 +5,7 @@ import { Spacer, Typography } from "@atoms";
import { useScreenDimension, useTranslation, useVoteContextForm } from "@hooks";
import { ControlledField, VoteContextWrapper } from "@organisms";
import { openInNewTab } from "@utils";
+import { LINKS } from "@/consts/links";
type StoreDataInfoProps = {
setStep: Dispatch>;
@@ -16,10 +17,7 @@ export const VoteContextTerms = ({ setStep, onCancel }: StoreDataInfoProps) => {
const { control, errors, watch } = useVoteContextForm();
const { isMobile } = useScreenDimension();
- const openLink = () =>
- openInNewTab(
- "https://docs.gov.tools/using-govtool/govtool-functions/storing-information-offline",
- );
+ const openLink = () => openInNewTab(LINKS.STORING_INFORMATION_OFFLINE);
const isContinueDisabled = !watch("terms");
diff --git a/govtool/frontend/src/consts/icons.ts b/govtool/frontend/src/consts/icons.ts
index bd70a2b06..4d8672516 100644
--- a/govtool/frontend/src/consts/icons.ts
+++ b/govtool/frontend/src/consts/icons.ts
@@ -13,6 +13,7 @@ export const ICONS = {
copyWhiteIcon: "/icons/CopyWhite.svg",
dashboardActiveIcon: "/icons/DashboardActive.svg",
dashboardIcon: "/icons/Dashboard.svg",
+ defaultDRepIcon: "/icons/DefaultDRep.svg",
download: "/icons/Download.svg",
drawerIcon: "/icons/DrawerIcon.svg",
dRepDirectoryActiveIcon: "/icons/DRepDirectoryActive.svg",
diff --git a/govtool/frontend/src/consts/links.ts b/govtool/frontend/src/consts/links.ts
new file mode 100644
index 000000000..c053c3001
--- /dev/null
+++ b/govtool/frontend/src/consts/links.ts
@@ -0,0 +1,29 @@
+export const LINKS = {
+ USING_GOVTOOL: "https://docs.gov.tools/cardano-govtool/using-govtool",
+ COMPATIBLE_WALLETS:
+ "https://docs.gov.tools/cardano-govtool/using-govtool/getting-started/compatible-wallets",
+ FAQS: "https://docs.gov.tools/cardano-govtool/faqs",
+ SUPPORT: "https://docs.gov.tools/cardano-govtool/support",
+ DREP_ERROR_CONDITIONS:
+ "https://docs.gov.tools/cardano-govtool/using-govtool/dreps/drep-error-conditions",
+ ABSTAIN_FROM_EVERY_VOTE:
+ "https://docs.gov.tools/cardano-govtool/using-govtool/delegating/abstain-from-every-vote",
+ SIGNAL_NO_CONFIDENCE_ON_EVERY_VOTE:
+ "https://docs.gov.tools/cardano-govtool/using-govtool/delegating/signal-no-confidence-on-every-vote",
+ REGISTER_AS_A_DREP:
+ "https://docs.gov.tools/cardano-govtool/using-govtool/dreps/register-as-a-drep",
+ PROPOSE_A_GOVERNANCE_ACTION:
+ "https://docs.gov.tools/cardano-govtool/using-govtool/governance-actions/propose-a-governance-action",
+ BOOTSTRAPPING_PHASE:
+ "https://docs.gov.tools/cardano-govtool/faqs/bootstrapping-phase",
+ STORING_INFORMATION_OFFLINE:
+ "https://docs.gov.tools/cardano-govtool/using-govtool/storing-information-offline",
+ DELEGATING: "https://docs.gov.tools/cardano-govtool/using-govtool/delegating",
+ DIRECT_VOTING:
+ "https://docs.gov.tools/cardano-govtool/using-govtool/direct-voting",
+ RETIRE_AS_A_DREP:
+ "https://docs.gov.tools/cardano-govtool/using-govtool/dreps/retire-as-a-drep",
+ VIEW_GOVERNANCE_ACTIONS:
+ "https://docs.gov.tools/cardano-govtool/using-govtool/governance-actions/view-governance-actions",
+ DREPS: "https://docs.gov.tools/cardano-govtool/using-govtool/dreps",
+};
diff --git a/govtool/frontend/src/consts/navItems.tsx b/govtool/frontend/src/consts/navItems.tsx
index c544fff52..74795d562 100644
--- a/govtool/frontend/src/consts/navItems.tsx
+++ b/govtool/frontend/src/consts/navItems.tsx
@@ -3,6 +3,7 @@ import i18n from "@/i18n";
import { theme } from "@/theme";
import { ICONS } from "./icons";
+import { LINKS } from "./links";
import { PATHS, PDF_PATHS } from "./paths";
export const NAV_ITEMS = [
@@ -33,13 +34,13 @@ export const NAV_ITEMS = [
dataTestId: "guides-link",
navTo: "",
label: i18n.t("menu.guides"),
- newTabLink: "https://docs.gov.tools/",
+ newTabLink: LINKS.USING_GOVTOOL,
},
{
dataTestId: "faqs-link",
navTo: "",
label: i18n.t("menu.faqs"),
- newTabLink: "https://docs.gov.tools/faqs",
+ newTabLink: LINKS.FAQS,
},
];
@@ -95,7 +96,7 @@ export const CONNECTED_NAV_ITEMS = [
navTo: "",
activeIcon: ICONS.guidesActiveIcon,
icon: ICONS.guidesIcon,
- newTabLink: "https://docs.gov.tools/",
+ newTabLink: LINKS.USING_GOVTOOL,
},
{
dataTestId: "faqs-link",
@@ -103,6 +104,6 @@ export const CONNECTED_NAV_ITEMS = [
navTo: "",
activeIcon: ICONS.faqsActiveIcon,
icon: ICONS.faqsIcon,
- newTabLink: "https://docs.gov.tools/faqs",
+ newTabLink: LINKS.FAQS,
},
];
diff --git a/govtool/frontend/src/hooks/useDelegateToDrep.ts b/govtool/frontend/src/hooks/useDelegateToDrep.ts
index 31509d14d..179e17457 100644
--- a/govtool/frontend/src/hooks/useDelegateToDrep.ts
+++ b/govtool/frontend/src/hooks/useDelegateToDrep.ts
@@ -52,8 +52,12 @@ export const useDelegateTodRep = () => {
voter,
});
} catch (error) {
+ console.error({ error });
openWalletErrorModal({
- error,
+ error:
+ typeof error === "string"
+ ? error
+ : (error as { message: string | null })?.message,
dataTestId: "delegate-transaction-error-modal",
});
Sentry.setTag("hook", "useDelegateTodRep");
diff --git a/govtool/frontend/src/models/api.ts b/govtool/frontend/src/models/api.ts
index fff33a0c0..32ef7bcc5 100644
--- a/govtool/frontend/src/models/api.ts
+++ b/govtool/frontend/src/models/api.ts
@@ -144,6 +144,9 @@ export type DrepDataDTO = {
url?: string;
view: string;
votingPower?: number;
+ imageUrl: string | null;
+ // either base64 for IPFS image or URL for regular image
+ image: string | null;
};
export type DRepData = DrepDataDTO & {
@@ -156,6 +159,9 @@ export type DRepData = DrepDataDTO & {
doNotList: boolean;
metadataStatus: MetadataValidationStatus | null;
metadataValid: boolean;
+ imageUrl: string | null;
+ // either base64 for IPFS image or URL for regular image
+ image: string | null;
};
export type Vote = "yes" | "no" | "abstain";
diff --git a/govtool/frontend/src/utils/jsonUtils.ts b/govtool/frontend/src/utils/jsonUtils.ts
index 04f499ed9..c73856bb0 100644
--- a/govtool/frontend/src/utils/jsonUtils.ts
+++ b/govtool/frontend/src/utils/jsonUtils.ts
@@ -24,8 +24,6 @@ export const downloadJson = (json: NodeObject, fileName?: string) => {
} else {
link.click();
}
-
- document.body.removeChild(link);
URL.revokeObjectURL(url);
};
@@ -52,6 +50,5 @@ export const downloadTextFile = (text: string, fileName?: string) => {
link.click();
}
- document.body.removeChild(link);
URL.revokeObjectURL(url);
};
diff --git a/govtool/frontend/src/utils/mapDtoToDrep.ts b/govtool/frontend/src/utils/mapDtoToDrep.ts
index 419973c14..4ab65d9fa 100644
--- a/govtool/frontend/src/utils/mapDtoToDrep.ts
+++ b/govtool/frontend/src/utils/mapDtoToDrep.ts
@@ -11,7 +11,7 @@ export const mapDtoToDrep = async (dto: DrepDataDTO): Promise => {
const emptyMetadata = {
paymentAddress: null,
givenName: "",
- image: null,
+ imageUrl: null,
objectives: null,
motivations: null,
qualifications: null,
@@ -24,6 +24,33 @@ export const mapDtoToDrep = async (dto: DrepDataDTO): Promise => {
// DBSync contains wrong representation of DRep view for script based DReps
const view = fixViewForScriptBasedDRep(dto.view, dto.isScriptBased);
+ // We need to prefetch the image, for the IPFS support
+ let base64Image = null;
+ const isIPFSImage = dto.imageUrl?.startsWith("ipfs://") || false;
+ if (dto.imageUrl) {
+ fetch(
+ isIPFSImage
+ ? `${process.env.VITE_IPFS_GATEWAY}/${dto.imageUrl?.slice(7)}`
+ : dto.imageUrl,
+ isIPFSImage
+ ? {
+ headers: { project_id: import.meta.env.VITE_IPFS_PROJECT_ID },
+ }
+ : {},
+ )
+ .then(async (res) => {
+ const blob = await res.blob();
+ const reader = new FileReader();
+ reader.readAsDataURL(blob);
+ reader.onloadend = () => {
+ base64Image = reader.result;
+ };
+ })
+ .catch((e) => {
+ console.error("Fetching the DRep image failed, reason: ", e);
+ });
+ }
+
if (dto.metadataHash && dto.url) {
const validationResponse = await postValidate({
url: dto.url,
@@ -36,6 +63,7 @@ export const mapDtoToDrep = async (dto: DrepDataDTO): Promise => {
...validationResponse.metadata,
metadataStatus: validationResponse.status || null,
metadataValid: validationResponse.valid,
+ image: isIPFSImage ? base64Image : dto.imageUrl,
view,
};
}
@@ -44,5 +72,6 @@ export const mapDtoToDrep = async (dto: DrepDataDTO): Promise => {
...dto,
...emptyMetadata,
view,
+ image: isIPFSImage ? base64Image : dto.imageUrl,
};
};
diff --git a/govtool/frontend/src/utils/tests/dRep.test.ts b/govtool/frontend/src/utils/tests/dRep.test.ts
index 104bfe019..66f41fe63 100644
--- a/govtool/frontend/src/utils/tests/dRep.test.ts
+++ b/govtool/frontend/src/utils/tests/dRep.test.ts
@@ -24,6 +24,8 @@ const EXAMPLE_DREP: DRepData = {
qualifications: null,
doNotList: false,
isScriptBased: false,
+ imageUrl: null,
+ image: null,
};
describe("isSameDRep function", () => {
diff --git a/govtool/frontend/yarn.lock b/govtool/frontend/yarn.lock
index dd3772103..b78223cc9 100644
--- a/govtool/frontend/yarn.lock
+++ b/govtool/frontend/yarn.lock
@@ -1536,10 +1536,10 @@
resolved "https://registry.npmjs.org/@intersect.mbo/intersectmbo.org-icons-set/-/intersectmbo.org-icons-set-1.1.0.tgz"
integrity sha512-sjKEtnK9eLYH/8kCD0YRQCms3byFA/tnSsei9NHTZbBYX9sBpeX6ErfR0sKYjOSxQOxl4FumX9D0X+vHIqxo8g==
-"@intersect.mbo/pdf-ui@^0.5.2":
- version "0.5.2"
- resolved "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.5.2.tgz"
- integrity sha512-zKPL3p+rve8GKDlDd9EozvVs/TDnCP6dDOLySeNndaiXaRw32QBdAOt5pSHaE0NGymKahlVV2QwO2vFNiawopA==
+"@intersect.mbo/pdf-ui@^0.5.4":
+ version "0.5.4"
+ resolved "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.5.4.tgz"
+ integrity sha512-QKaI+0C52/YAagkrRKzQQ/X2DwOHPovappEgeUXmVecvLzbVoJpKY9zGo5sNzmdu5qkYnE5/yIWbHZGVPpbvBA==
dependencies:
"@emurgo/cardano-serialization-lib-asmjs" "^12.0.0-beta.2"
"@fontsource/poppins" "^5.0.14"
diff --git a/govtool/metadata-validation/package.json b/govtool/metadata-validation/package.json
index 4e0da8c1e..5ada02dc8 100644
--- a/govtool/metadata-validation/package.json
+++ b/govtool/metadata-validation/package.json
@@ -1,6 +1,6 @@
{
"name": "@govtool/metadata-validation",
- "version": "1.0.28",
+ "version": "1.0.29",
"description": "",
"author": "",
"private": true,
diff --git a/govtool/metadata-validation/src/main.ts b/govtool/metadata-validation/src/main.ts
index 12ac1fcb2..c975ebc86 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('1.0.28')
+ .setVersion('1.0.29')
.build();
const document = SwaggerModule.createDocument(app, config);
diff --git a/scripts/govtool/Makefile b/scripts/govtool/Makefile
index 9a7e14f03..a4c9bb4cb 100644
--- a/scripts/govtool/Makefile
+++ b/scripts/govtool/Makefile
@@ -12,7 +12,7 @@ include config.mk
# image tags
cardano_node_image_tag := 10.1.2
-cardano_db_sync_image_tag := 13.6.0.1
+cardano_db_sync_image_tag := 13.6.0.4
.PHONY: all
all: deploy-stack notify
diff --git a/scripts/govtool/docker-compose.node+dbsync.yml b/scripts/govtool/docker-compose.node+dbsync.yml
index e72f09cfb..c88b4e037 100644
--- a/scripts/govtool/docker-compose.node+dbsync.yml
+++ b/scripts/govtool/docker-compose.node+dbsync.yml
@@ -65,7 +65,7 @@ services:
retries: 10
cardano-db-sync:
- image: ghcr.io/intersectmbo/cardano-db-sync:13.6.0.1
+ image: ghcr.io/intersectmbo/cardano-db-sync:13.6.0.4
environment:
- NETWORK=sanchonet
- POSTGRES_HOST=postgres
diff --git a/scripts/govtool/frontend.mk b/scripts/govtool/frontend.mk
index 64f5516e8..910cbd030 100644
--- a/scripts/govtool/frontend.mk
+++ b/scripts/govtool/frontend.mk
@@ -25,6 +25,8 @@ build-frontend: docker-login
--build-arg VITE_IS_PROPOSAL_DISCUSSION_FORUM_ENABLED="$${IS_PROPOSAL_DISCUSSION_FORUM_ENABLED}" \
--build-arg NPMRC_TOKEN="$${NPMRC_TOKEN}" \
--build-arg VITE_PDF_API_URL="$${PDF_API_URL}" \
+ --build-arg VITE_IPFS_GATEWAY="$${IPFS_GATEWAY}" \
+ --build-arg VITE_IPFS_PROJECT_ID="$${IPFS_PROJECT_ID}" \
$(root_dir)/govtool/frontend
.PHONY: push-frontend
diff --git a/tests/govtool-backend/.env.example b/tests/govtool-backend/.env.example
index 3bed52954..7e492cd11 100644
--- a/tests/govtool-backend/.env.example
+++ b/tests/govtool-backend/.env.example
@@ -5,4 +5,5 @@ METRICS_API_SECRET= `api_secret`
# required for setup
KUBER_API_URL = "https://kuber-govtool.cardanoapi.io"
KUBER_API_KEY = "" # optional
-FAUCET_API_KEY= """
\ No newline at end of file
+FAUCET_API_KEY= """
+NETWORK= preview
\ No newline at end of file
diff --git a/tests/govtool-backend/config.py b/tests/govtool-backend/config.py
index fb601c31b..e40af8b6d 100644
--- a/tests/govtool-backend/config.py
+++ b/tests/govtool-backend/config.py
@@ -11,5 +11,7 @@
RECORD_METRICS_API = os.getenv("RECORD_METRICS_API")
METRICS_API_SECRET = os.getenv("METRICS_API_SECRET")
-KUBER_API_URL = os.getenv("KUBER_API_URL")
+KUBER_API_URL = f'https://{os.getenv("NETWORK","preview")}.kuber.cardanoapi.io'
KUBER_API_KEY = os.getenv("KUBER_API_KEY")
+FAUCET_API_URL = f'https://faucet.${os.getenv("NETWORK","preview")}.world.dev.cardano.org'
+FACUET_API_KEY = os.getenv("FAUCET_API_KEY")
diff --git a/tests/govtool-backend/lib/faucet_api.py b/tests/govtool-backend/lib/faucet_api.py
index ed0150390..b6c63c9de 100644
--- a/tests/govtool-backend/lib/faucet_api.py
+++ b/tests/govtool-backend/lib/faucet_api.py
@@ -1,3 +1,4 @@
+from config import FAUCET_API_URL,FACUET_API_KEY
import os
from typing import TypedDict
@@ -21,8 +22,8 @@ def __init__(self, api_key: str, base_url: str = "https://faucet.sanchonet.world
@staticmethod
def from_env():
- api_key = os.getenv("FAUCET_API_KEY")
- base_url = os.getenv("FAUCET_API_URL", "https://faucet.sanchonet.world.dev.cardano.org")
+ api_key = FACUET_API_KEY
+ base_url = FAUCET_API_URL
if not api_key:
raise ValueError("FAUCET_API_KEY environment variable not set.")
return CardanoFaucet(api_key, base_url)
diff --git a/tests/govtool-backend/lib/kuber_api.py b/tests/govtool-backend/lib/kuber_api.py
index d70fedca2..788701d12 100644
--- a/tests/govtool-backend/lib/kuber_api.py
+++ b/tests/govtool-backend/lib/kuber_api.py
@@ -1,4 +1,5 @@
import json
+from config import KUBER_API_KEY,KUBER_API_URL
import sys
import time
from typing import Any, Optional
@@ -69,11 +70,12 @@ def wait_for_txout(self, txin: str, timeout=400, log: bool = False):
@staticmethod
def from_env() -> "KuberApi":
- api_url = os.environ.get("KUBER_API_URL")
+ api_url = KUBER_API_URL
+ print(f"KUBER_API_URL: {api_url}")
if api_url is not None:
api_url = api_url[:-1] if api_url.endswith("/") else api_url
print(f"KUBER_API_URL: {api_url}")
- api_key = os.environ.get("KUBER_API_KEY")
+ api_key = KUBER_API_KEY
return KuberApi(api_url, api_key)
else:
print("KUBER_API_URL environment variable is not set.", file=sys.stderr)
diff --git a/tests/govtool-backend/models/TestData.py b/tests/govtool-backend/models/TestData.py
index e4eb7e3ec..3f89f4149 100644
--- a/tests/govtool-backend/models/TestData.py
+++ b/tests/govtool-backend/models/TestData.py
@@ -18,13 +18,14 @@ class Proposal(TypedDict):
txHash: str
index: int
type: str
- details: Optional[dict]
+ details: Optional[dict] | Optional[list]
expiryDate: str
expiryEpochNo: int
createdDate: str
createdEpochNo: int
url: str
metadataHash: str
+ protocolParams: Optional[dict]
title: Optional[str]
abstract: Optional[str]
motivation: Optional[str]
@@ -38,6 +39,8 @@ class Proposal(TypedDict):
poolYesVotes: int
poolNoVotes: int
poolAbstainVotes: int
+ prevGovActionIndex: Optional[int]
+ prevGovActionTxHash: Optional[str]
class Drep(TypedDict):
diff --git a/tests/govtool-frontend/playwright/.env.example b/tests/govtool-frontend/playwright/.env.example
index 719692bbc..acd2110aa 100644
--- a/tests/govtool-frontend/playwright/.env.example
+++ b/tests/govtool-frontend/playwright/.env.example
@@ -10,11 +10,12 @@ PDF_URL=https://dev.api.pdf.gov.tools
NETWORK_ID=0
# Faucet
-FAUCET_API_URL=https://faucet.sanchonet.world.dev.cardano.org
FAUCET_API_KEY=
+#Blockfrost
+BLOCKFROST_API_KEY=XXXXXXXXXXXXXXXXXXXXXXXX
+
# Kuber
-KUBER_API_URL=https://sanchonet.kuber.cardanoapi.io
KUBER_API_KEY=
# Transaction timeout
diff --git a/tests/govtool-frontend/playwright/lib/constants/docsUrl.ts b/tests/govtool-frontend/playwright/lib/constants/docsUrl.ts
index b71d3b382..88953c3fa 100644
--- a/tests/govtool-frontend/playwright/lib/constants/docsUrl.ts
+++ b/tests/govtool-frontend/playwright/lib/constants/docsUrl.ts
@@ -1,15 +1,15 @@
import environments from "./environments";
-export const DELEGATION_DOC_URL = `${environments.docsUrl}/about/what-is-cardano-govtool/govtool-functions/delegating`;
-export const REGISTER_DREP_DOC_URL = `${environments.docsUrl}/using-govtool/govtool-functions/dreps/register-as-a-drep`;
-export const DIRECT_VOTER_DOC_URL = `${environments.docsUrl}/using-govtool/govtool-functions/direct-voting`;
-export const GOVERNANCE_ACTION_DOC_URL = `${environments.docsUrl}/using-govtool/govtool-functions/governance-actions/view-governance-actions`;
-export const PROPOSE_GOVERNANCE_ACTION_DOC_URL = `${environments.docsUrl}/using-govtool/govtool-functions/governance-actions/propose-a-governance-action`;
-export const ABSTAIN_VOTE_DOC_URL = `${environments.docsUrl}/using-govtool/govtool-functions/delegating/abstain-from-every-vote`;
-export const SIGNAL_NO_CONFIDENCE_VOTE_DOC_URL = `${environments.docsUrl}/using-govtool/govtool-functions/delegating/signal-no-confidence-on-every-vote`;
+export const DELEGATION_DOC_URL = `${environments.docsUrl}/using-govtool/delegating`;
+export const REGISTER_DREP_DOC_URL = `${environments.docsUrl}/using-govtool/dreps/register-as-a-drep`;
+export const DIRECT_VOTER_DOC_URL = `${environments.docsUrl}/using-govtool/direct-voting`;
+export const GOVERNANCE_ACTION_DOC_URL = `${environments.docsUrl}/using-govtool/governance-actions/view-governance-actions`;
+export const PROPOSE_GOVERNANCE_ACTION_DOC_URL = `${environments.docsUrl}/using-govtool/governance-actions/propose-a-governance-action`;
+export const ABSTAIN_VOTE_DOC_URL = `${environments.docsUrl}/using-govtool/delegating/abstain-from-every-vote`;
+export const SIGNAL_NO_CONFIDENCE_VOTE_DOC_URL = `${environments.docsUrl}/using-govtool/delegating/signal-no-confidence-on-every-vote`;
export const FAQS_DOC_URL = `${environments.docsUrl}/faqs`;
-export const GUIDES_DOC_URL = `${environments.docsUrl}`;
+export const GUIDES_DOC_URL = `${environments.docsUrl}/using-govtool`;
export const PRIVACY_POLICY = `https://docs.intersectmbo.org/legal/policies-and-conditions/privacy-policy`;
export const TERMS_AND_CONDITIONS = `https://docs.intersectmbo.org/legal/policies-and-conditions/terms-of-use`;
export const HELP_DOC_URL = `${environments.docsUrl}/support`;
-export const BOOTSTRAP_DOC_URL = `${environments.docsUrl}/about/bootstrapping-phase`;
+export const BOOTSTRAP_DOC_URL = `${environments.docsUrl}/faqs/bootstrapping-phase`;
diff --git a/tests/govtool-frontend/playwright/lib/constants/environments.ts b/tests/govtool-frontend/playwright/lib/constants/environments.ts
index 2982b74fa..13622c431 100644
--- a/tests/govtool-frontend/playwright/lib/constants/environments.ts
+++ b/tests/govtool-frontend/playwright/lib/constants/environments.ts
@@ -9,26 +9,21 @@ const NETWORK = process.env.NETWORK || "preview";
const environments = {
frontendUrl: SERVER_HOST_URL,
+ blockfrostApiKey: process.env.BLOCKFROST_API_KEY,
+ blockfrostApiUrl: "https://cardano-" + NETWORK + ".blockfrost.io/api",
apiUrl: `${SERVER_HOST_URL}/api`,
- docsUrl: process.env.DOCS_URL || "https://docs.gov.tools",
+ docsUrl: process.env.DOCS_URL || "https://docs.gov.tools/cardano-govtool",
pdfUrl: process.env.PDF_URL || "https://dev.api.pdf.gov.tools",
networkId: parseInt(process.env.NETWORK_ID) || 0,
faucet: {
- apiUrl:
- process.env.FAUCET_API_URL.replace("sanchonet", NETWORK) ||
- "https://faucet.sanchonet.world.dev.cardano.org".replace(
- "sanchonet",
- NETWORK
- ),
+ apiUrl:`https://faucet.${NETWORK}.world.dev.cardano.org`,
apiKey: process.env.FAUCET_API_KEY || "",
address:
process.env.FAUCET_ADDRESS ||
"addr_test1vz0ua2vyk7r4vufmpqh5v44awg8xff26hxlwyrt3uc67maqtql3kl",
},
kuber: {
- apiUrl:
- process.env.KUBER_API_URL.replace("sanchonet", NETWORK) ||
- "https://sanchonet.kuber.cardanoapi.io".replace("sanchonet", NETWORK),
+ apiUrl: `https://${NETWORK}.kuber.cardanoapi.io`,
apiKey: process.env.KUBER_API_KEY || "",
},
txTimeOut: parseInt(process.env.TX_TIMEOUT) || 240000,
diff --git a/tests/govtool-frontend/playwright/lib/fixtures/loadExtension.ts b/tests/govtool-frontend/playwright/lib/fixtures/loadExtension.ts
index 41ed3e722..34c508d5b 100644
--- a/tests/govtool-frontend/playwright/lib/fixtures/loadExtension.ts
+++ b/tests/govtool-frontend/playwright/lib/fixtures/loadExtension.ts
@@ -20,6 +20,8 @@ export default async function loadDemosExtension(
enableStakeSigning,
kuberApiUrl: environments.kuber.apiUrl,
kuberApiKey: environments.kuber.apiKey,
+ blockfrostApiKey: environments.blockfrostApiKey,
+ blockfrostApiUrl: environments.blockfrostApiUrl,
};
await page.addInitScript(
({ walletConfig, supportedExtensions }) => {
diff --git a/tests/govtool-frontend/playwright/lib/helpers/featureFlag.ts b/tests/govtool-frontend/playwright/lib/helpers/featureFlag.ts
index 6169bfcf5..0a6f1576e 100644
--- a/tests/govtool-frontend/playwright/lib/helpers/featureFlag.ts
+++ b/tests/govtool-frontend/playwright/lib/helpers/featureFlag.ts
@@ -1,4 +1,4 @@
-import { GrovernanceActionType, IProposal } from "@types";
+import { GovernanceActionType, IProposal } from "@types";
import { isBootStrapingPhase } from "./cardano";
import { SECURITY_RELEVANT_PARAMS_MAP } from "@constants/index";
@@ -12,17 +12,17 @@ export const areDRepVoteTotalsDisplayed = async (proposal: IProposal) => {
);
if (isInBootstrapPhase) {
return !(
- proposal.type === GrovernanceActionType.HardFork ||
- (proposal.type === GrovernanceActionType.ProtocolParameterChange &&
+ proposal.type === GovernanceActionType.HardFork ||
+ (proposal.type === GovernanceActionType.ProtocolParameterChange &&
!isSecurityGroup)
);
}
return ![
- GrovernanceActionType.NoConfidence,
- GrovernanceActionType.NewCommittee,
- GrovernanceActionType.UpdatetotheConstitution,
- ].includes(proposal.type as GrovernanceActionType);
+ GovernanceActionType.NoConfidence,
+ GovernanceActionType.NewCommittee,
+ GovernanceActionType.UpdatetotheConstitution,
+ ].includes(proposal.type as GovernanceActionType);
};
export const areSPOVoteTotalsDisplayed = async (proposal: IProposal) => {
@@ -34,22 +34,22 @@ export const areSPOVoteTotalsDisplayed = async (proposal: IProposal) => {
] !== null
);
if (isInBootstrapPhase) {
- return proposal.type !== GrovernanceActionType.ProtocolParameterChange;
+ return proposal.type !== GovernanceActionType.ProtocolParameterChange;
}
return !(
- proposal.type === GrovernanceActionType.UpdatetotheConstitution ||
- proposal.type === GrovernanceActionType.TreasuryWithdrawal ||
- (proposal.type === GrovernanceActionType.ProtocolParameterChange &&
+ proposal.type === GovernanceActionType.UpdatetotheConstitution ||
+ proposal.type === GovernanceActionType.TreasuryWithdrawal ||
+ (proposal.type === GovernanceActionType.ProtocolParameterChange &&
!isSecurityGroup)
);
};
-export const areCCVoteTotalsDisplayed = async (
- governanceActionType: GrovernanceActionType
+export const areCCVoteTotalsDisplayed = (
+ governanceActionType: GovernanceActionType
) => {
return ![
- GrovernanceActionType.NoConfidence,
- GrovernanceActionType.NewCommittee,
+ GovernanceActionType.NoConfidence,
+ GovernanceActionType.NewCommittee,
].includes(governanceActionType);
};
diff --git a/tests/govtool-frontend/playwright/lib/pages/governanceActionsPage.ts b/tests/govtool-frontend/playwright/lib/pages/governanceActionsPage.ts
index e12e92e07..1bbb69179 100644
--- a/tests/govtool-frontend/playwright/lib/pages/governanceActionsPage.ts
+++ b/tests/govtool-frontend/playwright/lib/pages/governanceActionsPage.ts
@@ -1,6 +1,10 @@
import removeAllSpaces from "@helpers/removeAllSpaces";
import { Locator, Page, expect } from "@playwright/test";
-import { GrovernanceActionType, IProposal } from "@types";
+import {
+ FullGovernanceDRepVoteActionsType,
+ GovernanceActionType,
+ IProposal,
+} from "@types";
import environments from "lib/constants/environments";
import GovernanceActionDetailsPage from "./governanceActionDetailsPage";
import { getEnumKeyByValue } from "@helpers/enum";
@@ -47,8 +51,22 @@ 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: GrovernanceActionType
+ governanceAction: GovernanceActionType
): Promise {
const proposalCard = this.page
.getByTestId(`govaction-${governanceAction}-card`)
@@ -121,7 +139,7 @@ export default class GovernanceActionsPage {
async sortAndValidate(
sortOption: string,
validationFn: (p1: IProposal, p2: IProposal) => boolean,
- filterKeys = Object.keys(GrovernanceActionType)
+ filterKeys = Object.keys(GovernanceActionType)
) {
const responsesPromise = Promise.all(
filterKeys.map((filterKey) =>
@@ -129,7 +147,7 @@ export default class GovernanceActionsPage {
response
.url()
.includes(
- `&type[]=${GrovernanceActionType[filterKey]}&sort=${sortOption}`
+ `&type[]=${GovernanceActionType[filterKey]}&sort=${sortOption}`
)
)
)
@@ -165,7 +183,7 @@ export default class GovernanceActionsPage {
for (let dIdx = 0; dIdx <= proposalsByType.length - 1; dIdx++) {
const proposals = proposalsByType[0] as IProposal[];
const filterOptionKey = getEnumKeyByValue(
- GrovernanceActionType,
+ GovernanceActionType,
proposals[0].type
);
diff --git a/tests/govtool-frontend/playwright/lib/services/blockfrostService.ts b/tests/govtool-frontend/playwright/lib/services/blockfrostService.ts
new file mode 100644
index 000000000..8e652d13f
--- /dev/null
+++ b/tests/govtool-frontend/playwright/lib/services/blockfrostService.ts
@@ -0,0 +1,37 @@
+import environments from "@constants/environments";
+
+export async function blockfrostSubmitTransaction(cborSignedTx: Buffer) {
+ const url = `${environments.blockfrostApiUrl}/v0/tx/submit`;
+ const res = await fetch(url, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/cbor",
+ project_id: environments.blockfrostApiKey,
+ },
+ body: cborSignedTx,
+ });
+ if (res.status === 200) {
+ return res.json();
+ } else {
+ return res.text().then((txt) => {
+ let err;
+ let json: any;
+ try {
+ json = JSON.parse(txt);
+ if (json) {
+ err = Error(
+ `BlockFrost [Status ${res.status}] : ${
+ json.message ? json.message : txt
+ }`
+ );
+ } else {
+ err = Error(`BlockFrost [Status ${res.status}] : ${txt}`);
+ }
+ } catch (e) {
+ err = Error(`BlockFrost [Status ${res.status}] : ${txt}`);
+ }
+ err.status = res.status;
+ throw err;
+ });
+ }
+}
diff --git a/tests/govtool-frontend/playwright/lib/services/kuberService.ts b/tests/govtool-frontend/playwright/lib/services/kuberService.ts
index 154b885e1..8de48ce41 100644
--- a/tests/govtool-frontend/playwright/lib/services/kuberService.ts
+++ b/tests/govtool-frontend/playwright/lib/services/kuberService.ts
@@ -6,11 +6,12 @@ import {
WalletAndAnchorType,
} from "@types";
import * as blake from "blakejs";
-import environments from "lib/constants/environments";
+import environments from "@constants/environments";
import { LockInterceptor, LockInterceptorInfo } from "lib/lockInterceptor";
import fetch, { BodyInit, RequestInit } from "node-fetch";
-import { cborxDecoder, cborxEncoder } from "../helpers/encodeDecode";
+import { cborxEncoder } from "@helpers/encodeDecode";
import { Logger } from "@helpers/logger";
+import { blockfrostSubmitTransaction } from "@services/blockfrostService";
type CertificateType = "registerstake" | "registerdrep" | "deregisterdrep";
@@ -99,20 +100,17 @@ class Kuber {
`Submitting tx: ${JSON.stringify({ lock_id: lockId, tx: signedTx })}`
);
- const res = (await callKuber(
- `/api/${this.version}/tx?submit=true`,
+ const response = (await callKuber(
+ `/api/${this.version}/tx?submit=false`,
"POST",
JSON.stringify(signedTx)
)) as any;
- let decodedTx = cborxDecoder.decode(Buffer.from(res.cborHex, "hex"));
- const submittedTxBody = Uint8Array.from(cborxEncoder.encode(decodedTx[0]));
- const submittedTxHash = Buffer.from(
- blake.blake2b(submittedTxBody, undefined, 32)
- ).toString("hex");
+ const cborSignedTx = Buffer.from(response.cborHex, "hex");
+ const submittedTxHash = await blockfrostSubmitTransaction(cborSignedTx);
Logger.success(`Tx submitted: ${submittedTxHash}`);
return {
- cbor: res.cborHex,
+ cbor: response.cborHex,
txId: submittedTxHash,
};
}
diff --git a/tests/govtool-frontend/playwright/lib/types.ts b/tests/govtool-frontend/playwright/lib/types.ts
index 2bde6027d..b20caf09c 100644
--- a/tests/govtool-frontend/playwright/lib/types.ts
+++ b/tests/govtool-frontend/playwright/lib/types.ts
@@ -74,7 +74,7 @@ export enum ProposalType {
treasury = "Treasury",
}
-export enum GrovernanceActionType {
+export enum GovernanceActionType {
ProtocolParameterChange = "ParameterChange",
InfoAction = "InfoAction",
TreasuryWithdrawal = "TreasuryWithdrawals",
diff --git a/tests/govtool-frontend/playwright/package-lock.json b/tests/govtool-frontend/playwright/package-lock.json
index 51252ad2e..74d2b854d 100644
--- a/tests/govtool-frontend/playwright/package-lock.json
+++ b/tests/govtool-frontend/playwright/package-lock.json
@@ -9,7 +9,7 @@
"version": "1.0.0",
"license": "MIT",
"dependencies": {
- "@cardanoapi/cardano-test-wallet": "^2.1.1",
+ "@cardanoapi/cardano-test-wallet": "^3.0.0",
"@faker-js/faker": "^8.4.1",
"@noble/curves": "^1.3.0",
"@noble/ed25519": "^2.0.0",
@@ -43,9 +43,9 @@
}
},
"node_modules/@cardanoapi/cardano-test-wallet": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@cardanoapi/cardano-test-wallet/-/cardano-test-wallet-2.1.1.tgz",
- "integrity": "sha512-K5HISR0GmWiJpZOaWT3PqfP7ez+Ht9+jrW8dSGwEXKfKPnj9g6uqUSnkUbuw3FmPeVRgNcB9EwkwmZzPcg7gZw==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@cardanoapi/cardano-test-wallet/-/cardano-test-wallet-3.0.0.tgz",
+ "integrity": "sha512-5cQPQPrsco8eeDBIQI74jiAVl48hI0E3u2JSmya9PvRL/D18LUPqanmhpDScD8fpWRzS7MKSAhqoqsxTlgWYOw==",
"license": "MIT"
},
"node_modules/@cbor-extract/cbor-extract-darwin-arm64": {
diff --git a/tests/govtool-frontend/playwright/package.json b/tests/govtool-frontend/playwright/package.json
index 9edc9eac5..b52c3e5f8 100644
--- a/tests/govtool-frontend/playwright/package.json
+++ b/tests/govtool-frontend/playwright/package.json
@@ -28,7 +28,7 @@
"generate-wallets": "ts-node ./generate_wallets.ts 17"
},
"dependencies": {
- "@cardanoapi/cardano-test-wallet": "^2.1.1",
+ "@cardanoapi/cardano-test-wallet": "^3.0.0",
"@faker-js/faker": "^8.4.1",
"@noble/curves": "^1.3.0",
"@noble/ed25519": "^2.0.0",
diff --git a/tests/govtool-frontend/playwright/tests/3-drep-registration/dRepRegistration.dRep.spec.ts b/tests/govtool-frontend/playwright/tests/3-drep-registration/dRepRegistration.dRep.spec.ts
index d4842d6ba..9f593c004 100644
--- a/tests/govtool-frontend/playwright/tests/3-drep-registration/dRepRegistration.dRep.spec.ts
+++ b/tests/govtool-frontend/playwright/tests/3-drep-registration/dRepRegistration.dRep.spec.ts
@@ -13,7 +13,7 @@ import GovernanceActionsPage from "@pages/governanceActionsPage";
import { expect } from "@playwright/test";
import walletManager from "lib/walletManager";
import DRepDirectoryPage from "@pages/dRepDirectoryPage";
-import { GrovernanceActionType } from "@types";
+import { GovernanceActionType } from "@types";
test.beforeEach(async () => {
await setAllureEpic("3. DRep registration");
@@ -37,12 +37,12 @@ test.describe("Logged in DReps", () => {
const governanceActionsPage = new GovernanceActionsPage(page);
await governanceActionsPage.goto();
-
+
await expect(page.getByText(/info action/i).first()).toBeVisible();
const governanceActionDetailsPage =
await governanceActionsPage.viewFirstProposalByGovernanceAction(
- GrovernanceActionType.InfoAction
+ GovernanceActionType.InfoAction
);
await expect(governanceActionDetailsPage.voteBtn).toBeVisible();
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 c4d2afbec..c066337ff 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
@@ -16,7 +16,7 @@ import { invalid as mockInvalid, valid as mockValid } from "@mock/index";
import {
BootstrapGovernanceActionType,
FullGovernanceDRepVoteActionsType,
- GrovernanceActionType,
+ GovernanceActionType,
IProposal,
} from "@types";
import walletManager from "lib/walletManager";
@@ -57,11 +57,16 @@ test.describe("Logged in DRep", () => {
const govActionsPage = new GovernanceActionsPage(page);
await govActionsPage.goto();
+ // assert to wait until the loading button is hidden
+ await expect(page.getByTestId("to-vote-tab")).toBeVisible({
+ timeout: 15_000,
+ });
+
govActionDetailsPage = (await isBootStrapingPhase())
? await govActionsPage.viewFirstProposalByGovernanceAction(
- GrovernanceActionType.InfoAction
+ GovernanceActionType.InfoAction
)
- : await govActionsPage.viewFirstProposal();
+ : await govActionsPage.viewFirstDRepVoteEnabledGovernanceAction();
await govActionDetailsPage.contextBtn.click();
await govActionDetailsPage.contextInput.fill(faker.lorem.sentence(200));
@@ -207,9 +212,7 @@ test.describe("Check vote count", () => {
// check ccCommittee votes
if (
- areCCVoteTotalsDisplayed(
- proposalToCheck.type as GrovernanceActionType
- )
+ areCCVoteTotalsDisplayed(proposalToCheck.type as GovernanceActionType)
) {
await expect(govActionDetailsPage.ccCommitteeYesVotes).toHaveText(
`${proposalToCheck.ccYesVotes}`
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 7918dc968..8b08c93c0 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
@@ -9,7 +9,7 @@ import {
import GovernanceActionDetailsPage from "@pages/governanceActionDetailsPage";
import GovernanceActionsPage from "@pages/governanceActionsPage";
import { expect, test } from "@playwright/test";
-import { GrovernanceActionType, IProposal } from "@types";
+import { GovernanceActionType, IProposal } from "@types";
test.beforeEach(async () => {
await setAllureEpic("4. Proposal visibility");
@@ -39,9 +39,9 @@ test("4K. Should display correct vote counts on governance details page for disc
page,
browser,
}) => {
- const responsesPromise = Object.keys(GrovernanceActionType).map((filterKey) =>
+ const responsesPromise = Object.keys(GovernanceActionType).map((filterKey) =>
page.waitForResponse((response) =>
- response.url().includes(`&type[]=${GrovernanceActionType[filterKey]}`)
+ response.url().includes(`&type[]=${GovernanceActionType[filterKey]}`)
)
);
@@ -98,7 +98,7 @@ test("4K. Should display correct vote counts on governance details page for disc
// check ccCommittee votes
if (
- areCCVoteTotalsDisplayed(proposalToCheck.type as GrovernanceActionType)
+ areCCVoteTotalsDisplayed(proposalToCheck.type as GovernanceActionType)
) {
await expect(govActionDetailsPage.ccCommitteeYesVotes).toHaveText(
`${proposalToCheck.ccYesVotes}`
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 a801a334d..989f9e661 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
@@ -12,7 +12,7 @@ import GovernanceActionDetailsPage from "@pages/governanceActionDetailsPage";
import GovernanceActionsPage from "@pages/governanceActionsPage";
import { Page, expect } from "@playwright/test";
import kuberService from "@services/kuberService";
-import { BootstrapGovernanceActionType, GrovernanceActionType } from "@types";
+import { BootstrapGovernanceActionType, GovernanceActionType } from "@types";
import walletManager from "lib/walletManager";
const invalidInfinityProposals = require("../../lib/_mock/invalidInfinityProposals.json");
@@ -32,12 +32,17 @@ test.describe("Proposal checks", () => {
const govActionsPage = new GovernanceActionsPage(page);
await govActionsPage.goto();
+ // assert to wait until the loading button is hidden
+ await expect(page.getByTestId("to-vote-tab")).toBeVisible({
+ timeout: 15_000,
+ });
+
currentPage = page;
govActionDetailsPage = (await isBootStrapingPhase())
? await govActionsPage.viewFirstProposalByGovernanceAction(
- GrovernanceActionType.InfoAction
+ GovernanceActionType.InfoAction
)
- : await govActionsPage.viewFirstProposal();
+ : await govActionsPage.viewFirstDRepVoteEnabledGovernanceAction();
});
test("5A. Should show relevant details about governance action as DRep", async () => {
@@ -181,11 +186,16 @@ test.describe("Perform voting", () => {
const govActionsPage = new GovernanceActionsPage(dRepPage);
await govActionsPage.goto();
+ // assert to wait until the loading button is hidden
+ await expect(dRepPage.getByTestId("to-vote-tab")).toBeVisible({
+ timeout: 15_000,
+ });
+
govActionDetailsPage = (await isBootStrapingPhase())
? await govActionsPage.viewFirstProposalByGovernanceAction(
- GrovernanceActionType.InfoAction
+ GovernanceActionType.InfoAction
)
- : await govActionsPage.viewFirstProposal();
+ : await govActionsPage.viewFirstDRepVoteEnabledGovernanceAction();
});
test("5E. Should re-vote with new data on a already voted governance action", async ({}, testInfo) => {
@@ -211,7 +221,7 @@ test.describe("Perform voting", () => {
await expect(
govActionDetailsPage.currentPage.getByTestId("my-vote").getByText("No")
- ).toBeVisible();
+ ).toBeVisible({ timeout: 15_000 });
});
test("5F. Should show notification of casted vote after vote", async ({}, testInfo) => {
@@ -271,77 +281,62 @@ test.describe("Check voting power", () => {
});
test.describe("Bootstrap phase", () => {
- test.use({ storageState: ".auth/dRep01.json", wallet: dRep01Wallet });
test("5L. Should restrict dRep votes to Info Governance actions During Bootstrapping Phase", async ({
- page,
- context,
+ browser,
}) => {
- await page.route("**/epoch/params", async (route) => {
- // Fetch the original response from the server
- const response = await route.fetch();
- const json = await response.json();
-
- // update protocol major version
- json["protocol_major"] = 9;
- await route.fulfill({
- status: 200,
- contentType: "application/json",
- body: JSON.stringify(json),
- });
- });
-
- const voteBlacklistOptions = Object.keys(GrovernanceActionType).filter(
+ const voteBlacklistOptions = Object.keys(GovernanceActionType).filter(
(option) => option !== BootstrapGovernanceActionType.InfoAction
);
- const govActionsPage = new GovernanceActionsPage(page);
- await govActionsPage.goto();
-
- // wait until the loading button is hidden
- await expect(
- page.getByRole("progressbar").getByRole("img")
- ).not.toBeVisible({ timeout: 10_000 });
-
- for (const voteBlacklistOption of voteBlacklistOptions) {
- const governanceActionDetailsPage =
- await govActionsPage.viewFirstProposalByGovernanceAction(
- voteBlacklistOption as GrovernanceActionType
- );
-
- if (governanceActionDetailsPage !== null) {
- // dRep vote
- await expect(governanceActionDetailsPage.dRepYesVotes).toBeVisible();
- await expect(
- governanceActionDetailsPage.dRepAbstainVotes
- ).toBeVisible();
- await expect(governanceActionDetailsPage.dRepNoVotes).toBeVisible();
-
- // sPos vote
- await expect(governanceActionDetailsPage.sPosYesVotes).toBeVisible();
- await expect(
- governanceActionDetailsPage.sPosAbstainVotes
- ).toBeVisible();
- await expect(governanceActionDetailsPage.sPosNoVotes).toBeVisible();
-
- // ccCommittee vote
- await expect(
- governanceActionDetailsPage.ccCommitteeYesVotes
- ).toBeVisible();
- await expect(
- governanceActionDetailsPage.ccCommitteeAbstainVotes
- ).toBeVisible();
- await expect(
- governanceActionDetailsPage.ccCommitteeNoVotes
- ).toBeVisible();
-
- await expect(
- governanceActionDetailsPage.yesVoteRadio
- ).not.toBeVisible();
- await expect(governanceActionDetailsPage.contextBtn).not.toBeVisible();
- await expect(governanceActionDetailsPage.voteBtn).not.toBeVisible();
-
- await governanceActionDetailsPage.backBtn.click();
- }
- }
+ await Promise.all(
+ voteBlacklistOptions.map(async (voteBlacklistOption) => {
+ const dRepPage = await createNewPageWithWallet(browser, {
+ storageState: ".auth/dRep01.json",
+ wallet: dRep01Wallet,
+ });
+
+ await dRepPage.route("**/epoch/params", async (route) => {
+ // Fetch the original response from the server
+ const response = await route.fetch();
+ const json = await response.json();
+
+ // update protocol major version
+ json["protocol_major"] = 9;
+ await route.fulfill({
+ status: 200,
+ contentType: "application/json",
+ body: JSON.stringify(json),
+ });
+ });
+
+ const governanceActionsPage = new GovernanceActionsPage(dRepPage);
+ await governanceActionsPage.goto();
+
+ // assert to wait until proposal cards are visible
+ await expect(dRepPage.getByTestId("voting-power-chips")).toBeVisible();
+ // wait until the loading button is hidden
+ await expect(dRepPage.getByTestId("to-vote-tab")).toBeVisible({
+ timeout: 15_000,
+ });
+
+ const governanceActionDetailsPage =
+ await governanceActionsPage.viewFirstProposalByGovernanceAction(
+ voteBlacklistOption as GovernanceActionType
+ );
+
+ if (governanceActionDetailsPage) {
+ await expect(
+ dRepPage.getByTestId("governance-action-details-card-header")
+ ).toBeVisible();
+ await expect(
+ governanceActionDetailsPage.yesVoteRadio
+ ).not.toBeVisible();
+ await expect(
+ governanceActionDetailsPage.contextBtn
+ ).not.toBeVisible();
+ await expect(governanceActionDetailsPage.voteBtn).not.toBeVisible();
+ }
+ })
+ );
});
});
diff --git a/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.loggedin.spec.ts b/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.loggedin.spec.ts
index b96e5e2dc..b61e6e3c4 100644
--- a/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.loggedin.spec.ts
+++ b/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.loggedin.spec.ts
@@ -9,7 +9,10 @@ import {
import { faker } from "@faker-js/faker";
import { test } from "@fixtures/proposal";
import { setAllureEpic } from "@helpers/allure";
-import { skipIfTreasuryAndBootstrapping, skipIfNotHardFork } from "@helpers/cardano";
+import {
+ skipIfTreasuryAndBootstrapping,
+ skipIfNotHardFork,
+} from "@helpers/cardano";
import { ShelleyWallet } from "@helpers/crypto";
import { createNewPageWithWallet } from "@helpers/page";
import { invalid, valid as mockValid } from "@mock/index";
@@ -261,7 +264,9 @@ test.describe("Proposal created logged state", () => {
}) => {
test.slow(); // Brute-force testing with 100 random data
for (let i = 0; i < 50; i++) {
- await proposalSubmissionPage.metadataUrlInput.fill(invalid.url(false));
+ await proposalSubmissionPage.metadataUrlInput.fill(
+ invalid.url(false)
+ );
await expect(page.getByTestId("url-input-error-text")).toBeVisible();
}