From bc73ac255b43fe3b19aef350bad044a91052fbae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Wed, 31 Jul 2024 18:39:35 +0200 Subject: [PATCH 1/9] fix!: remove usage of metadata validation service in Haskell Backend --- CHANGELOG.md | 1 + govtool/backend/app/Main.hs | 9 +- govtool/backend/src/VVA/API.hs | 126 +++++--------------------- govtool/backend/src/VVA/API/Types.hs | 22 +---- govtool/backend/src/VVA/Config.hs | 51 +---------- govtool/backend/src/VVA/Metadata.hs | 130 --------------------------- govtool/backend/src/VVA/Proposal.hs | 2 - govtool/backend/src/VVA/Types.hs | 43 --------- govtool/backend/vva-be.cabal | 1 - 9 files changed, 31 insertions(+), 354 deletions(-) delete mode 100644 govtool/backend/src/VVA/Metadata.hs diff --git a/CHANGELOG.md b/CHANGELOG.md index 17469c062..64b6d92bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ changes. - Change link to docs regarding DReps [Issue 1130](https://github.com/IntersectMBO/govtool/issues/1130) - Change link to view governance actions docs [Issue 1131](https://github.com/IntersectMBO/govtool/issues/1131) - Make all the frontend build arguments mandatory [Issue 1642](https://github.com/IntersectMBO/govtool/issues/1642), [Issue 1643](https://github.com/IntersectMBO/govtool/issues/1643) +- Remove usage of metadata validation service in Haskell Backend ## [sancho-v1.0.11](https://github.com/IntersectMBO/govtool/releases/tag/sancho-v1.0.11) 2024-07-30 diff --git a/govtool/backend/app/Main.hs b/govtool/backend/app/Main.hs index 9f057b91c..002a33668 100644 --- a/govtool/backend/app/Main.hs +++ b/govtool/backend/app/Main.hs @@ -8,7 +8,6 @@ module Main where -import Control.Concurrent.QSem (newQSem) import Control.Exception (Exception, SomeException, fromException, throw) import Control.Lens.Operators ((.~)) import Control.Monad @@ -85,6 +84,7 @@ startApp vvaConfig = do settings = setPort vvaPort $ setHost vvaHost + $ setTimeout 60 -- 60 seconds timeout $ setBeforeMainLoop ( Text.hPutStrLn stderr $ Text.pack @@ -107,8 +107,6 @@ startApp vvaConfig = do dRepVotingPowerCache <- newCache dRepListCache <- newCache networkMetricsCache <- newCache - proposalMetadataValidationCache <- newCache - dRepMetadataValidationCache <- newCache return $ CacheEnv { proposalListCache , getProposalCache @@ -120,13 +118,10 @@ startApp vvaConfig = do , dRepVotingPowerCache , dRepListCache , networkMetricsCache - , proposalMetadataValidationCache - , dRepMetadataValidationCache } connectionPool <- createPool (connectPostgreSQL (encodeUtf8 (dbSyncConnectionString $ getter vvaConfig))) close 1 1 60 vvaTlsManager <- newManager tlsManagerSettings - qsem <- newQSem (metadataValidationMaxConcurrentRequests vvaConfig) - let appEnv = AppEnv {vvaConfig=vvaConfig, vvaCache=cacheEnv, vvaConnectionPool=connectionPool, vvaTlsManager, vvaMetadataQSem=qsem} + let appEnv = AppEnv {vvaConfig=vvaConfig, vvaCache=cacheEnv, vvaConnectionPool=connectionPool, vvaTlsManager } server' <- mkVVAServer appEnv runSettings settings server' diff --git a/govtool/backend/src/VVA/API.hs b/govtool/backend/src/VVA/API.hs index da67e38bf..f78ea1e23 100644 --- a/govtool/backend/src/VVA/API.hs +++ b/govtool/backend/src/VVA/API.hs @@ -9,12 +9,11 @@ module VVA.API where import Control.Concurrent.Async (mapConcurrently) -import Control.Concurrent.QSem (signalQSem, waitQSem) import Control.Exception (throw, throwIO) import Control.Monad.Except (runExceptT, throwError) import Control.Monad.Reader -import Data.Aeson (Result (Error, Success), fromJSON) +import Data.Aeson (Result (Error, Success), fromJSON, Value) import Data.Bool (Bool) import Data.List (sortOn) import qualified Data.Map as Map @@ -36,7 +35,6 @@ import VVA.Cache (cacheRequest) import VVA.Config import qualified VVA.DRep as DRep import qualified VVA.Epoch as Epoch -import qualified VVA.Metadata as Metadata import VVA.Network as Network import qualified VVA.Proposal as Proposal import qualified VVA.Transaction as Transaction @@ -76,8 +74,6 @@ type VVAApi = :<|> "transaction" :> "status" :> Capture "transactionId" HexText :> Get '[JSON] GetTransactionStatusResponse :<|> "throw500" :> Get '[JSON] () :<|> "network" :> "metrics" :> Get '[JSON] GetNetworkMetricsResponse - :<|> "proposal" :> "metadata" :> "validate" :> ReqBody '[JSON] MetadataValidationParams :> Post '[JSON] MetadataValidationResponse - :<|> "drep" :> "metadata" :> "validate" :> ReqBody '[JSON] MetadataValidationParams :> Post '[JSON] MetadataValidationResponse server :: App m => ServerT VVAApi m server = drepList :<|> getVotingPower @@ -91,8 +87,6 @@ server = drepList :<|> getTransactionStatus :<|> throw500 :<|> getNetworkMetrics - :<|> getProposalMetadataValidationResponse - :<|> getDRepMetadataValidationResponse mapDRepType :: Types.DRepType -> DRepType @@ -104,10 +98,9 @@ mapDRepStatus Types.Retired = Retired mapDRepStatus Types.Active = Active mapDRepStatus Types.Inactive = Inactive -drepRegistrationToDrep :: Types.DRepRegistration -> Types.MetadataValidationResult Types.DRepMetadata -> DRep -drepRegistrationToDrep Types.DRepRegistration {..} Types.MetadataValidationResult{..} = - let metadata = metadataValidationResultMetadata - in DRep +drepRegistrationToDrep :: Types.DRepRegistration -> DRep +drepRegistrationToDrep Types.DRepRegistration {..} = + DRep { dRepDrepId = DRepHash dRepRegistrationDRepHash, dRepView = dRepRegistrationView, dRepUrl = dRepRegistrationUrl, @@ -117,13 +110,7 @@ drepRegistrationToDrep Types.DRepRegistration {..} Types.MetadataValidationResul dRepStatus = mapDRepStatus dRepRegistrationStatus, dRepType = mapDRepType dRepRegistrationType, dRepLatestTxHash = HexText <$> dRepRegistrationLatestTxHash, - dRepLatestRegistrationDate = dRepRegistrationLatestRegistrationDate, - dRepBio = Types.dRepMetadataBio <$> metadata, - dRepDRepName = Types.dRepMetadataDRepName <$> metadata, - dRepEmail = Types.dRepMetadataEmail <$> metadata, - dRepReferences = maybe [] Types.dRepMetadataReferences metadata, - dRepMetadataStatus = metadataValidationResultStatus, - dRepMetadataValid = metadataValidationResultValid + dRepLatestRegistrationDate = dRepRegistrationLatestRegistrationDate } delegationToResponse :: Types.Delegation -> DelegationResponse @@ -163,22 +150,13 @@ drepList mSearchQuery statuses mSortMode mPage mPageSize = do dRepRegistrationStatus appEnv <- ask - qsem <- asks vvaMetadataQSem allValidDReps <- liftIO $ mapConcurrently - (\d@Types.DRepRegistration{..} -> - drepRegistrationToDrep d - <$> do - waitQSem qsem - r <- either throwIO return =<< runExceptT (runReaderT (validateDRepMetadata - (MetadataValidationParams - (fromMaybe "" dRepRegistrationUrl) - $ HexText (fromMaybe "" dRepRegistrationDataHash))) appEnv) - signalQSem qsem - return r) + (\d@Types.DRepRegistration{..} -> do + let drep = drepRegistrationToDrep d + return drep) $ sortDReps $ filterDRepsByQuery $ filterDRepsByStatus dreps - let page = (fromIntegral $ fromMaybe 0 mPage) :: Int pageSize = (fromIntegral $ fromMaybe 10 mPageSize) :: Int @@ -199,11 +177,14 @@ getVotingPower (unHexText -> dRepId) = do CacheEnv {dRepVotingPowerCache} <- asks vvaCache cacheRequest dRepVotingPowerCache dRepId $ DRep.getVotingPower dRepId +decodeReferences :: Maybe Value -> Maybe [Text] +decodeReferences Nothing = Nothing +decodeReferences (Just val) = case fromJSON val of + Success texts -> Just texts + Error _ -> Nothing -proposalToResponse :: Types.Proposal -> Types.MetadataValidationResult Types.ProposalMetadata -> ProposalResponse -proposalToResponse Types.Proposal {..} Types.MetadataValidationResult{..} = - let metadata = metadataValidationResultMetadata - in +proposalToResponse :: Types.Proposal -> ProposalResponse +proposalToResponse Types.Proposal {..} = ProposalResponse { proposalResponseId = pack $ show proposalId, proposalResponseTxHash = HexText proposalTxHash, @@ -216,30 +197,15 @@ proposalToResponse Types.Proposal {..} Types.MetadataValidationResult{..} = proposalResponseCreatedEpochNo = proposalCreatedEpochNo, proposalResponseUrl = proposalUrl, proposalResponseMetadataHash = HexText proposalDocHash, - proposalResponseTitle = getTitle proposalTitle metadata, - proposalResponseAbstract = getAbstract proposalAbstract metadata, - proposalResponseMotivation = getMotivation proposalMotivation metadata, - proposalResponseRationale = getRationale proposalRationale metadata, - proposalResponseMetadata = GovernanceActionMetadata <$> proposalMetadata, - proposalResponseReferences = getReferences proposalReferences metadata, + proposalResponseTitle = proposalTitle, + proposalResponseAbstract = proposalAbstract, + proposalResponseMotivation = proposalMotivation, + proposalResponseRationale = proposalRationale, + proposalResponseReferences = fromMaybe [] (decodeReferences proposalReferences), proposalResponseYesVotes = proposalYesVotes, proposalResponseNoVotes = proposalNoVotes, - proposalResponseAbstainVotes = proposalAbstainVotes, - proposalResponseMetadataStatus = metadataValidationResultStatus, - proposalResponseMetadataValid = metadataValidationResultValid + proposalResponseAbstainVotes = proposalAbstainVotes } - where - getTitle p Nothing = p - getTitle _ m = Types.proposalMetadataTitle <$> m - getAbstract p Nothing = p - getAbstract _ m = Types.proposalMetadataAbstract <$> m - getMotivation p Nothing = p - getMotivation _ m = Types.proposalMetadataMotivation <$> m - getRationale p Nothing = p - getRationale _ m = Types.proposalMetadataRationale <$> m - -- TODO: convert aeson references to [Text] from database - --getReferences p Nothing = p - getReferences _ = maybe [] Types.proposalMetadataReferences voteToResponse :: Types.Vote -> VoteParams voteToResponse Types.Vote {..} = @@ -254,7 +220,6 @@ voteToResponse Types.Vote {..} = voteParamsTxHash = HexText voteTxHash } - mapSortAndFilterProposals :: App m => [GovernanceActionType] @@ -262,19 +227,7 @@ mapSortAndFilterProposals -> [Types.Proposal] -> m [ProposalResponse] mapSortAndFilterProposals selectedTypes sortMode proposals = do - - appEnv <- ask - qsem <- asks vvaMetadataQSem - - mappedProposals <- - liftIO $ mapConcurrently - (\proposal@Types.Proposal {proposalUrl, proposalDocHash} -> - do - waitQSem qsem - r <- either throwIO return =<< runExceptT (runReaderT (proposalToResponse proposal <$> validateProposalMetadata (MetadataValidationParams proposalUrl $ HexText proposalDocHash)) appEnv) - signalQSem qsem - return r) - proposals + let mappedProposals = map proposalToResponse proposals let filteredProposals = if null selectedTypes then mappedProposals @@ -398,8 +351,7 @@ getProposal g@(GovActionId govActionTxHash govActionIndex) mDrepId' = do let mDrepId = unHexText <$> mDrepId' CacheEnv {getProposalCache} <- asks vvaCache proposal@Types.Proposal {proposalUrl, proposalDocHash} <- cacheRequest getProposalCache (unHexText govActionTxHash, govActionIndex) (Proposal.getProposal (unHexText govActionTxHash) govActionIndex) - proposalMetadataValidationResult <- validateProposalMetadata $ MetadataValidationParams proposalUrl $ HexText proposalDocHash - let proposalResponse = proposalToResponse proposal proposalMetadataValidationResult + let proposalResponse = proposalToResponse proposal voteResponse <- case mDrepId of Nothing -> return Nothing Just drepId -> do @@ -447,35 +399,3 @@ getNetworkMetrics = do , getNetworkMetricsResponseAlwaysNoConfidenceVotingPower = networkMetricsAlwaysNoConfidenceVotingPower , getNetworkMetricsResponseNetworkName = networkMetricsNetworkName } - -validateProposalMetadata :: App m => MetadataValidationParams -> m (Types.MetadataValidationResult Types.ProposalMetadata) -validateProposalMetadata MetadataValidationParams {..} = do - CacheEnv {proposalMetadataValidationCache} <- asks vvaCache - cacheRequest proposalMetadataValidationCache (metadataValidationParamsUrl, unHexText metadataValidationParamsHash) - $ Metadata.getProposalMetadataValidationResult metadataValidationParamsUrl (unHexText metadataValidationParamsHash) - -getProposalMetadataValidationResponse :: App m => MetadataValidationParams -> m MetadataValidationResponse -getProposalMetadataValidationResponse params = do - result <- validateProposalMetadata params - case result of - Types.MetadataValidationResult {..} -> do - return $ MetadataValidationResponse - { metadataValidationResponseValid = metadataValidationResultValid - , metadataValidationResponseStatus = metadataValidationResultStatus - } - -validateDRepMetadata :: App m => MetadataValidationParams -> m (Types.MetadataValidationResult Types.DRepMetadata) -validateDRepMetadata MetadataValidationParams {..} = do - CacheEnv {dRepMetadataValidationCache} <- asks vvaCache - cacheRequest dRepMetadataValidationCache (metadataValidationParamsUrl, unHexText metadataValidationParamsHash) - $ Metadata.getDRepMetadataValidationResult metadataValidationParamsUrl (unHexText metadataValidationParamsHash) - -getDRepMetadataValidationResponse :: App m => MetadataValidationParams -> m MetadataValidationResponse -getDRepMetadataValidationResponse params = do - result <- validateDRepMetadata params - case result of - Types.MetadataValidationResult {..} -> do - return $ MetadataValidationResponse - { metadataValidationResponseValid = metadataValidationResultValid - , metadataValidationResponseStatus = metadataValidationResultStatus - } diff --git a/govtool/backend/src/VVA/API/Types.hs b/govtool/backend/src/VVA/API/Types.hs index 79f91fb3f..ecd44a665 100644 --- a/govtool/backend/src/VVA/API/Types.hs +++ b/govtool/backend/src/VVA/API/Types.hs @@ -454,13 +454,10 @@ data ProposalResponse , proposalResponseAbstract :: Maybe Text , proposalResponseMotivation :: Maybe Text , proposalResponseRationale :: Maybe Text - , proposalResponseMetadata :: Maybe GovernanceActionMetadata , proposalResponseReferences :: [Text] , proposalResponseYesVotes :: Integer , proposalResponseNoVotes :: Integer , proposalResponseAbstainVotes :: Integer - , proposalResponseMetadataStatus :: Maybe Text - , proposalResponseMetadataValid :: Bool } deriving (Generic, Show) @@ -482,13 +479,10 @@ exampleProposalResponse = "{ \"id\": \"proposalId123\"," <> "\"abstract\": \"Proposal About\"," <> "\"motivation\": \"Proposal Motivation\"," <> "\"rationale\": \"Proposal Rationale\"," - <> "\"metadata\": {\"key\": \"value\"}," <> "\"references\": [\"google.com\"]," <> "\"yesVotes\": 0," <> "\"noVotes\": 0," - <> "\"abstainVotes\": 0," - <> "\"metadataStatus\": \"URL_NOT_FOUND\"," - <> "\"metadataValid\": true}" + <> "\"abstainVotes\": 0}" instance ToSchema ProposalResponse where declareNamedSchema proxy = do @@ -831,12 +825,6 @@ data DRep , dRepType :: DRepType , dRepLatestTxHash :: Maybe HexText , dRepLatestRegistrationDate :: UTCTime - , dRepBio :: Maybe Text - , dRepDRepName :: Maybe Text - , dRepEmail :: Maybe Text - , dRepReferences :: [Text] - , dRepMetadataStatus :: Maybe Text - , dRepMetadataValid :: Bool } deriving (Generic, Show) @@ -854,13 +842,7 @@ exampleDrep = <> "\"status\": \"Active\"," <> "\"type\": \"DRep\"," <> "\"latestTxHash\": \"47c14a128cd024f1b990c839d67720825921ad87ed875def42641ddd2169b39c\"," - <> "\"latestRegistrationDate\": \"1970-01-01T00:00:00Z\"," - <> "\"bio\": \"DRep Bio\"," - <> "\"dRepName\": \"DRep Name\"," - <> "\"email\": \"google@gmail.com\"," - <> "\"references\": [\"google.com\"]," - <> "\"metadataStatus\": \"URL_NOT_FOUND\"," - <> "\"metadataValid\": true}" + <> "\"latestRegistrationDate\": \"1970-01-01T00:00:00Z\"}" -- ToSchema instance for DRep instance ToSchema DRep where diff --git a/govtool/backend/src/VVA/Config.hs b/govtool/backend/src/VVA/Config.hs index fd24a600a..cea9e3eb8 100644 --- a/govtool/backend/src/VVA/Config.hs +++ b/govtool/backend/src/VVA/Config.hs @@ -21,9 +21,6 @@ module VVA.Config , loadVVAConfig -- * Data type conversions , getDbSyncConnectionString - , getMetadataValidationEnabled - , getMetadataValidationHost - , getMetadataValidationPort , getServerHost , getServerPort , vvaConfigToText @@ -82,14 +79,6 @@ data VVAConfigInternal , vVAConfigInternalSentrydsn :: String -- | Sentry environment , vVAConfigInternalSentryEnv :: String - -- | Metadata validation service enabled - , vVAConfigInternalMetadataValidationEnabled :: Bool - -- | Metadata validation service host - , vVAConfigInternalMetadataValidationHost :: Text - -- | Metadata validation service port - , vVAConfigInternalMetadataValidationPort :: Int - -- | Maximum number of concurrent metadata requests - , vVAConfigInternalMetadataValidationMaxConcurrentRequests :: Int } deriving (FromConfig, Generic, Show) @@ -101,11 +90,7 @@ instance DefaultConfig VVAConfigInternal where vVAConfigInternalHost = "localhost", vVaConfigInternalCacheDurationSeconds = 20, vVAConfigInternalSentrydsn = "https://username:password@senty.host/id", - vVAConfigInternalSentryEnv = "development", - vVAConfigInternalMetadataValidationEnabled = True, - vVAConfigInternalMetadataValidationHost = "localhost", - vVAConfigInternalMetadataValidationPort = 3001, - vVAConfigInternalMetadataValidationMaxConcurrentRequests = 10 + vVAConfigInternalSentryEnv = "development" } -- | DEX configuration. @@ -123,14 +108,6 @@ data VVAConfig , sentryDSN :: String -- | Sentry environment , sentryEnv :: String - -- | Metadata validation service enabled - , metadataValidationEnabled :: Bool - -- | Metadata validation service host - , metadataValidationHost :: Text - -- | Metadata validation service port - , metadataValidationPort :: Int - -- | Maximum number of concurrent metadata requests - , metadataValidationMaxConcurrentRequests :: Int } deriving (Generic, Show, ToJSON) @@ -171,11 +148,7 @@ convertConfig VVAConfigInternal {..} = serverHost = vVAConfigInternalHost, cacheDurationSeconds = vVaConfigInternalCacheDurationSeconds, sentryDSN = vVAConfigInternalSentrydsn, - sentryEnv = vVAConfigInternalSentryEnv, - metadataValidationEnabled = vVAConfigInternalMetadataValidationEnabled, - metadataValidationHost = vVAConfigInternalMetadataValidationHost, - metadataValidationPort = vVAConfigInternalMetadataValidationPort, - metadataValidationMaxConcurrentRequests = vVAConfigInternalMetadataValidationMaxConcurrentRequests + sentryEnv = vVAConfigInternalSentryEnv } -- | Load configuration from a file specified on the command line. Load from @@ -212,22 +185,4 @@ getServerPort = asks (serverPort . getter) getServerHost :: (Has VVAConfig r, MonadReader r m) => m Text -getServerHost = asks (serverHost . getter) - --- | Access MetadataValidationService enabled -getMetadataValidationEnabled :: - (Has VVAConfig r, MonadReader r m) => - m Bool -getMetadataValidationEnabled = asks (metadataValidationEnabled . getter) - --- | Access MetadataValidationService host -getMetadataValidationHost :: - (Has VVAConfig r, MonadReader r m) => - m Text -getMetadataValidationHost = asks (metadataValidationHost . getter) - --- | Access MetadataValidationService port -getMetadataValidationPort :: - (Has VVAConfig r, MonadReader r m) => - m Int -getMetadataValidationPort = asks (metadataValidationPort . getter) +getServerHost = asks (serverHost . getter) \ No newline at end of file diff --git a/govtool/backend/src/VVA/Metadata.hs b/govtool/backend/src/VVA/Metadata.hs deleted file mode 100644 index 8c7f0306e..000000000 --- a/govtool/backend/src/VVA/Metadata.hs +++ /dev/null @@ -1,130 +0,0 @@ -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE ScopedTypeVariables #-} - -module VVA.Metadata where - -import Control.Exception (SomeException, Exception, try) -import Control.Monad.Except (MonadError, throwError) -import Control.Monad.Reader - -import Data.Aeson (Value (..), decode, encode, object, (.=)) -import Data.Aeson.KeyMap (KeyMap, lookup) -import Data.ByteString (ByteString) -import Data.FileEmbed (embedFile) -import Data.Has (Has, getter) -import Data.Maybe (fromJust) -import Data.String (fromString) -import Data.Text (Text, pack, unpack) -import qualified Data.Text.Encoding as Text -import Data.Time.Clock -import Data.Typeable (Typeable) -import Data.Vector (toList) - -import qualified Database.PostgreSQL.Simple as SQL - -import Network.HTTP.Client (httpLbs, parseRequest, Request(..), RequestBody(..), Response, Manager, newManager, managerResponseTimeout, responseTimeoutMicro, defaultManagerSettings, responseBody) -import Network.HTTP.Client.TLS - -import Prelude hiding (lookup) - -import VVA.Config -import VVA.Pool (ConnectionPool, withPool) -import VVA.Types - - -logException :: (MonadIO m) => Text -> SomeException -> m () -logException url ex = liftIO $ putStrLn $ "Failed to validate metadata for URL: " ++ unpack url ++ " with error: " ++ show ex - -validateMetadata - :: (Has VVAConfig r, Has Manager r, MonadReader r m, MonadIO m, MonadError AppError m) - => Text - -> Text - -> Maybe Text - -> m (MetadataValidationResult Value) -validateMetadata url hash standard = do - metadataEnabled <- getMetadataValidationEnabled - if not metadataEnabled - then return $ MetadataValidationResult True (Just "Metadata validation disabled") Nothing - else do - metadataHost <- getMetadataValidationHost - metadataPort <- getMetadataValidationPort - - let timeout = responseTimeoutMicro 1000 - manager <- liftIO $ newManager $ tlsManagerSettings { managerResponseTimeout = timeout } - - let requestBody = encode $ object $ - ["url" .= url, "hash" .= hash] ++ maybe [] (\x -> ["standard" .= x]) standard - requestUrl = unpack metadataHost ++ ":" ++ show metadataPort ++ "/validate" - - parsedRequestResult <- liftIO $ try $ parseRequest requestUrl - case parsedRequestResult of - Left (e :: SomeException) -> do - logException url e - return $ MetadataValidationResult False (Just "VALIDATION_FAILED") Nothing - Right initialRequest -> do - let request = initialRequest - { method = "POST" - , requestBody = RequestBodyLBS requestBody - , requestHeaders = [("Content-Type", "application/json")] - } - - responseResult <- liftIO $ try $ httpLbs request manager - case responseResult of - Left (e :: SomeException) -> do - logException url e - return $ MetadataValidationResult False (Just "VALIDATION_FAILED") Nothing - Right response -> case decode (responseBody response) of - Nothing -> return $ MetadataValidationResult False (Just "VALIDATION_FAILED") Nothing - Just x -> return $ MetadataValidationResult True (Just "VALIDATION_SUCCESS") (Just x) - -getProposalMetadataValidationResult :: - (Has ConnectionPool r, Has Manager r, Has VVAConfig r, MonadReader r m, MonadIO m, MonadFail m, MonadError AppError m) => - Text -> - Text -> - m (MetadataValidationResult ProposalMetadata) -getProposalMetadataValidationResult url hash = do - result <- validateMetadata url hash (Just "CIP108") - case result of - MetadataValidationResult False status _ -> return $ MetadataValidationResult False status Nothing - MetadataValidationResult True status (Just (Object r)) -> case go r of - Nothing -> throwError $ InternalError "Failed to validate metadata" - Just x -> return $ MetadataValidationResult True status (Just x) - _ -> return $ MetadataValidationResult False (Just "VALIDATION_FAILED") Nothing - where - go :: KeyMap Value -> Maybe ProposalMetadata - go result = do - (Bool valid) <- lookup "valid" result - (Object metadata) <- lookup "metadata" result - (String abstract) <- lookup "abstract" metadata - (String motivation) <- lookup "motivation" metadata - (String rationale) <- lookup "rationale" metadata - (String title) <- lookup "title" metadata - (Array references') <- lookup "references" metadata - let references = map (\(String x) -> x) (toList references') - return $ ProposalMetadata abstract motivation rationale title references - -getDRepMetadataValidationResult :: - (Has ConnectionPool r, Has Manager r, Has VVAConfig r, MonadReader r m, MonadIO m, MonadFail m, MonadError AppError m) => - Text -> - Text -> - m (MetadataValidationResult DRepMetadata) -getDRepMetadataValidationResult url hash = do - result <- validateMetadata url hash (Just "CIPQQQ") - case result of - MetadataValidationResult False status _ -> return $ MetadataValidationResult False status Nothing - MetadataValidationResult True status (Just (Object r)) -> case go r of - Nothing -> throwError $ InternalError "Failed to validate metadata" - Just x -> return $ MetadataValidationResult True status (Just x) - _ -> return $ MetadataValidationResult False (Just "VALIDATION_FAILED") Nothing - where - go :: KeyMap Value -> Maybe DRepMetadata - go result = do - (Bool valid) <- lookup "valid" result - (Object metadata) <- lookup "metadata" result - (String bio) <- lookup "bio" metadata - (String dRepName) <- lookup "dRepName" metadata - (String email) <- lookup "email" metadata - (Array references') <- lookup "references" metadata - let references = map (\(String x) -> x) (toList references') - return $ DRepMetadata bio dRepName email references \ No newline at end of file diff --git a/govtool/backend/src/VVA/Proposal.hs b/govtool/backend/src/VVA/Proposal.hs index 970ebde78..86aff74bc 100644 --- a/govtool/backend/src/VVA/Proposal.hs +++ b/govtool/backend/src/VVA/Proposal.hs @@ -86,7 +86,6 @@ getProposals mProposalIds = withPool $ \conn -> do , about' , motivation' , rationale' - , metadataJson' , references' , yesVotes' , noVotes' @@ -111,7 +110,6 @@ getProposals mProposalIds = withPool $ \conn -> do about' motivation' rationale' - metadataJson' references' (floor @Scientific yesVotes') (floor @Scientific noVotes') diff --git a/govtool/backend/src/VVA/Types.hs b/govtool/backend/src/VVA/Types.hs index c15bbb8c4..6e71b36cc 100644 --- a/govtool/backend/src/VVA/Types.hs +++ b/govtool/backend/src/VVA/Types.hs @@ -35,7 +35,6 @@ data AppEnv , vvaCache :: CacheEnv , vvaConnectionPool :: Pool Connection , vvaTlsManager :: Manager - , vvaMetadataQSem :: QSem } instance Has VVAConfig AppEnv where @@ -54,11 +53,6 @@ instance Has Manager AppEnv where getter AppEnv {vvaTlsManager} = vvaTlsManager modifier f a@AppEnv {vvaTlsManager} = a {vvaTlsManager = f vvaTlsManager} -instance Has QSem AppEnv where - getter AppEnv {vvaMetadataQSem} = vvaMetadataQSem - modifier f a@AppEnv {vvaMetadataQSem} = a {vvaMetadataQSem = f vvaMetadataQSem} - - data AppError = ValidationError Text | NotFoundError Text @@ -131,7 +125,6 @@ data Proposal , proposalAbstract :: Maybe Text , proposalMotivation :: Maybe Text , proposalRationale :: Maybe Text - , proposalMetadata :: Maybe Value , proposalReferences :: Maybe Value , proposalYesVotes :: Integer , proposalNoVotes :: Integer @@ -141,35 +134,6 @@ data Proposal data TransactionStatus = TransactionConfirmed | TransactionUnconfirmed - -data ProposalMetadata - = ProposalMetadata - { proposalMetadataAbstract :: Text - , proposalMetadataMotivation :: Text - , proposalMetadataRationale :: Text - , proposalMetadataTitle :: Text - , proposalMetadataReferences :: [Text] - } - deriving (Show) - -data DRepMetadata - = DRepMetadata - { dRepMetadataBio :: Text - , dRepMetadataDRepName :: Text - , dRepMetadataEmail :: Text - , dRepMetadataReferences :: [Text] - } - deriving (Show) - -data MetadataValidationResult a - = MetadataValidationResult - { metadataValidationResultValid :: Bool - , metadataValidationResultStatus :: Maybe Text - , metadataValidationResultMetadata :: Maybe a - } - deriving (Show) - - data CacheEnv = CacheEnv { proposalListCache :: Cache.Cache () [Proposal] @@ -182,8 +146,6 @@ data CacheEnv , dRepVotingPowerCache :: Cache.Cache Text Integer , dRepListCache :: Cache.Cache () [DRepRegistration] , networkMetricsCache :: Cache.Cache () NetworkMetrics - , proposalMetadataValidationCache :: Cache.Cache (Text, Text) (MetadataValidationResult ProposalMetadata) - , dRepMetadataValidationCache :: Cache.Cache (Text, Text) (MetadataValidationResult DRepMetadata) } data NetworkMetrics @@ -207,8 +169,3 @@ data Delegation , delegationDRepView :: Text , delegationTxHash :: Text } - - -data MetadataValidationStatus = IncorrectFormat | IncorrectJSONLD | IncorrectHash | UrlNotFound - - diff --git a/govtool/backend/vva-be.cabal b/govtool/backend/vva-be.cabal index f6d4dd4df..c72563025 100644 --- a/govtool/backend/vva-be.cabal +++ b/govtool/backend/vva-be.cabal @@ -118,5 +118,4 @@ library , VVA.Pool , VVA.Types , VVA.Network - , VVA.Metadata ghc-options: -threaded From cf57b4009de13ebfd3f050ec3e3371a07c7098a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Wed, 31 Jul 2024 18:46:28 +0200 Subject: [PATCH 2/9] chore: remove metadata validation config options for Haskell backend --- govtool/backend/example-config.json | 6 +----- scripts/govtool/config/templates/backend-config.json.tpl | 5 +---- .../configs_template/backend_config.json | 5 +---- 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/govtool/backend/example-config.json b/govtool/backend/example-config.json index dd99856ae..4960416a5 100644 --- a/govtool/backend/example-config.json +++ b/govtool/backend/example-config.json @@ -10,9 +10,5 @@ "host" : "localhost", "cachedurationseconds": 20, "sentrydsn": "https://username:password@senty.host/id", - "sentryenv": "dev", - "metadatavalidationenabled": true, - "metadatavalidationhost": "localhost", - "metadatavalidationport": 3001, - "metadatavalidationmaxconcurrentrequests": 10 + "sentryenv": "dev" } diff --git a/scripts/govtool/config/templates/backend-config.json.tpl b/scripts/govtool/config/templates/backend-config.json.tpl index 97a246773..a50b894f6 100644 --- a/scripts/govtool/config/templates/backend-config.json.tpl +++ b/scripts/govtool/config/templates/backend-config.json.tpl @@ -10,8 +10,5 @@ "host" : "0.0.0.0", "cachedurationseconds": 20, "sentrydsn": "", - "sentryenv": "", - "metadatavalidationhost": "http://metadata-validation", - "metadatavalidationport": "3000", - "metadatavalidationmaxconcurrentrequests": 10 + "sentryenv": "" } diff --git a/tests/test-infrastructure/configs_template/backend_config.json b/tests/test-infrastructure/configs_template/backend_config.json index 6f7256a1c..2079085a2 100644 --- a/tests/test-infrastructure/configs_template/backend_config.json +++ b/tests/test-infrastructure/configs_template/backend_config.json @@ -9,8 +9,5 @@ "port" : 8080, "host" : "0.0.0.0", "cachedurationseconds": 20, - "sentrydsn": "${SENTRY_DSN_BACKEND:-https://username:password@senty.host/id}", - "metadatavalidationhost": "${METADATA_VALIDATION_URL:-http://metadata-validation}", - "metadatavalidationport": 3000, - "metadatavalidationmaxconcurrentrequests": 10 + "sentrydsn": "${SENTRY_DSN_BACKEND:-https://username:password@senty.host/id}" } \ No newline at end of file From 8210586b869770721e15d73a80acad5b85214f9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Wed, 31 Jul 2024 19:40:26 +0200 Subject: [PATCH 3/9] chore: remove references from proposals --- govtool/backend/example-config.json | 2 +- govtool/backend/sql/list-proposals.sql | 2 -- govtool/backend/src/VVA/API.hs | 13 ++++--------- govtool/backend/src/VVA/API/Types.hs | 2 -- govtool/backend/src/VVA/Proposal.hs | 2 -- govtool/backend/src/VVA/Types.hs | 1 - 6 files changed, 5 insertions(+), 17 deletions(-) diff --git a/govtool/backend/example-config.json b/govtool/backend/example-config.json index 4960416a5..463fdc7df 100644 --- a/govtool/backend/example-config.json +++ b/govtool/backend/example-config.json @@ -3,7 +3,7 @@ "host" : "localhost", "dbname" : "cexplorer", "user" : "postgres", - "password" : "v8hlDV0yMAHHlIurYupj", + "password" : "postgres", "port" : 5432 }, "port" : 9999, diff --git a/govtool/backend/sql/list-proposals.sql b/govtool/backend/sql/list-proposals.sql index 2433b5990..dbebc2a73 100644 --- a/govtool/backend/sql/list-proposals.sql +++ b/govtool/backend/sql/list-proposals.sql @@ -59,8 +59,6 @@ SELECT off_chain_vote_gov_action_data.abstract, off_chain_vote_gov_action_data.motivation, off_chain_vote_gov_action_data.rationale, - off_chain_vote_data.json, - off_chain_vote_data.json#>'{body, references}' as references, coalesce(Sum(ldd.amount) FILTER (WHERE voting_procedure.vote::text = 'Yes'), 0) +( CASE WHEN gov_action_proposal.type = 'NoConfidence' THEN always_no_confidence_voting_power.amount diff --git a/govtool/backend/src/VVA/API.hs b/govtool/backend/src/VVA/API.hs index f78ea1e23..702af1b77 100644 --- a/govtool/backend/src/VVA/API.hs +++ b/govtool/backend/src/VVA/API.hs @@ -13,14 +13,16 @@ import Control.Exception (throw, throwIO) import Control.Monad.Except (runExceptT, throwError) import Control.Monad.Reader -import Data.Aeson (Result (Error, Success), fromJSON, Value) +import Data.Aeson (Value(..), Array, decode, encode, FromJSON, ToJSON) import Data.Bool (Bool) import Data.List (sortOn) import qualified Data.Map as Map -import Data.Maybe (Maybe (Nothing), catMaybes, fromMaybe) +import Data.Maybe (Maybe (Nothing), catMaybes, fromMaybe, mapMaybe) import Data.Ord (Down (..)) import Data.Text hiding (any, drop, elem, filter, length, map, null, take) import qualified Data.Text as Text +import qualified Data.Vector as V + import Numeric.Natural (Natural) @@ -177,12 +179,6 @@ getVotingPower (unHexText -> dRepId) = do CacheEnv {dRepVotingPowerCache} <- asks vvaCache cacheRequest dRepVotingPowerCache dRepId $ DRep.getVotingPower dRepId -decodeReferences :: Maybe Value -> Maybe [Text] -decodeReferences Nothing = Nothing -decodeReferences (Just val) = case fromJSON val of - Success texts -> Just texts - Error _ -> Nothing - proposalToResponse :: Types.Proposal -> ProposalResponse proposalToResponse Types.Proposal {..} = ProposalResponse @@ -201,7 +197,6 @@ proposalToResponse Types.Proposal {..} = proposalResponseAbstract = proposalAbstract, proposalResponseMotivation = proposalMotivation, proposalResponseRationale = proposalRationale, - proposalResponseReferences = fromMaybe [] (decodeReferences proposalReferences), proposalResponseYesVotes = proposalYesVotes, proposalResponseNoVotes = proposalNoVotes, proposalResponseAbstainVotes = proposalAbstainVotes diff --git a/govtool/backend/src/VVA/API/Types.hs b/govtool/backend/src/VVA/API/Types.hs index ecd44a665..a2c410d66 100644 --- a/govtool/backend/src/VVA/API/Types.hs +++ b/govtool/backend/src/VVA/API/Types.hs @@ -454,7 +454,6 @@ data ProposalResponse , proposalResponseAbstract :: Maybe Text , proposalResponseMotivation :: Maybe Text , proposalResponseRationale :: Maybe Text - , proposalResponseReferences :: [Text] , proposalResponseYesVotes :: Integer , proposalResponseNoVotes :: Integer , proposalResponseAbstainVotes :: Integer @@ -479,7 +478,6 @@ exampleProposalResponse = "{ \"id\": \"proposalId123\"," <> "\"abstract\": \"Proposal About\"," <> "\"motivation\": \"Proposal Motivation\"," <> "\"rationale\": \"Proposal Rationale\"," - <> "\"references\": [\"google.com\"]," <> "\"yesVotes\": 0," <> "\"noVotes\": 0," <> "\"abstainVotes\": 0}" diff --git a/govtool/backend/src/VVA/Proposal.hs b/govtool/backend/src/VVA/Proposal.hs index 86aff74bc..b68074e03 100644 --- a/govtool/backend/src/VVA/Proposal.hs +++ b/govtool/backend/src/VVA/Proposal.hs @@ -86,7 +86,6 @@ getProposals mProposalIds = withPool $ \conn -> do , about' , motivation' , rationale' - , references' , yesVotes' , noVotes' , abstainVotes' @@ -110,7 +109,6 @@ getProposals mProposalIds = withPool $ \conn -> do about' motivation' rationale' - references' (floor @Scientific yesVotes') (floor @Scientific noVotes') (floor @Scientific abstainVotes') diff --git a/govtool/backend/src/VVA/Types.hs b/govtool/backend/src/VVA/Types.hs index 6e71b36cc..dfcb1fb5f 100644 --- a/govtool/backend/src/VVA/Types.hs +++ b/govtool/backend/src/VVA/Types.hs @@ -125,7 +125,6 @@ data Proposal , proposalAbstract :: Maybe Text , proposalMotivation :: Maybe Text , proposalRationale :: Maybe Text - , proposalReferences :: Maybe Value , proposalYesVotes :: Integer , proposalNoVotes :: Integer , proposalAbstainVotes :: Integer From 23734336f8b10788ececf4b1c0e0d6ff2edb898a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Wed, 31 Jul 2024 22:04:05 +0200 Subject: [PATCH 4/9] chore: remove tls manager causing timeout errors --- govtool/backend/app/Main.hs | 5 +---- govtool/backend/sql/list-proposals.sql | 7 ++----- govtool/backend/src/VVA/Types.hs | 7 ------- 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/govtool/backend/app/Main.hs b/govtool/backend/app/Main.hs index 002a33668..fb2f7b524 100644 --- a/govtool/backend/app/Main.hs +++ b/govtool/backend/app/Main.hs @@ -37,8 +37,6 @@ import qualified Data.Text.Lazy.Encoding as LazyText import Database.PostgreSQL.Simple (close, connectPostgreSQL) -import Network.HTTP.Client hiding (Proxy, Request) -import Network.HTTP.Client.TLS import Network.Wai import Network.Wai.Handler.Warp import Network.Wai.Middleware.Cors @@ -120,8 +118,7 @@ startApp vvaConfig = do , networkMetricsCache } connectionPool <- createPool (connectPostgreSQL (encodeUtf8 (dbSyncConnectionString $ getter vvaConfig))) close 1 1 60 - vvaTlsManager <- newManager tlsManagerSettings - let appEnv = AppEnv {vvaConfig=vvaConfig, vvaCache=cacheEnv, vvaConnectionPool=connectionPool, vvaTlsManager } + let appEnv = AppEnv {vvaConfig=vvaConfig, vvaCache=cacheEnv, vvaConnectionPool=connectionPool } server' <- mkVVAServer appEnv runSettings settings server' diff --git a/govtool/backend/sql/list-proposals.sql b/govtool/backend/sql/list-proposals.sql index dbebc2a73..f09ec6f63 100644 --- a/govtool/backend/sql/list-proposals.sql +++ b/govtool/backend/sql/list-proposals.sql @@ -48,11 +48,10 @@ SELECT null end ) as description, - epoch_utils.last_epoch_end_time + epoch_utils.epoch_duration *(gov_action_proposal.expiration - epoch_utils.last_epoch_no), + epoch_utils.last_epoch_end_time + epoch_utils.epoch_duration * (gov_action_proposal.expiration - epoch_utils.last_epoch_no), gov_action_proposal.expiration, creator_block.time, creator_block.epoch_no, - /* created date */ voting_anchor.url, encode(voting_anchor.data_hash, 'hex'), off_chain_vote_gov_action_data.title, @@ -78,7 +77,6 @@ FROM on gov_action_proposal.id = treasury_withdrawal.gov_action_proposal_id LEFT JOIN stake_address on stake_address.id = treasury_withdrawal.stake_address_id - CROSS JOIN EpochUtils AS epoch_utils CROSS JOIN always_no_confidence_voting_power CROSS JOIN always_abstain_voting_power @@ -110,7 +108,6 @@ GROUP BY off_chain_vote_gov_action_data.abstract, off_chain_vote_gov_action_data.motivation, off_chain_vote_gov_action_data.rationale, - off_chain_vote_data.json, gov_action_proposal.index, creator_tx.hash, creator_block.time, @@ -120,4 +117,4 @@ GROUP BY voting_anchor.url, voting_anchor.data_hash, always_no_confidence_voting_power.amount, - always_abstain_voting_power.amount) + always_abstain_voting_power.amount) \ No newline at end of file diff --git a/govtool/backend/src/VVA/Types.hs b/govtool/backend/src/VVA/Types.hs index dfcb1fb5f..c23eae9fa 100644 --- a/govtool/backend/src/VVA/Types.hs +++ b/govtool/backend/src/VVA/Types.hs @@ -22,8 +22,6 @@ import Data.Time (UTCTime) import Database.PostgreSQL.Simple (Connection) -import Network.HTTP.Client (Manager) - import VVA.Cache import VVA.Config @@ -34,7 +32,6 @@ data AppEnv { vvaConfig :: VVAConfig , vvaCache :: CacheEnv , vvaConnectionPool :: Pool Connection - , vvaTlsManager :: Manager } instance Has VVAConfig AppEnv where @@ -49,10 +46,6 @@ instance Has (Pool Connection) AppEnv where getter AppEnv {vvaConnectionPool} = vvaConnectionPool modifier f a@AppEnv {vvaConnectionPool} = a {vvaConnectionPool = f vvaConnectionPool} -instance Has Manager AppEnv where - getter AppEnv {vvaTlsManager} = vvaTlsManager - modifier f a@AppEnv {vvaTlsManager} = a {vvaTlsManager = f vvaTlsManager} - data AppError = ValidationError Text | NotFoundError Text From 227e4ec794b1b363ff8e29d2f489f821e917e875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Wed, 31 Jul 2024 22:21:05 +0200 Subject: [PATCH 5/9] chore: make validate api adjustments --- .../src/hooks/forms/useVoteContextForm.tsx | 1 - .../frontend/src/models/metadataValidation.ts | 1 - .../metadata-validation/src/app.controller.ts | 24 +++++++++++++++++++ .../metadata-validation/src/app.service.ts | 13 +++------- .../src/dto/validateMetadata.dto.ts | 2 -- govtool/metadata-validation/src/main.ts | 9 ++++--- .../src/utils/parseMetadata.ts | 7 +----- 7 files changed, 32 insertions(+), 25 deletions(-) diff --git a/govtool/frontend/src/hooks/forms/useVoteContextForm.tsx b/govtool/frontend/src/hooks/forms/useVoteContextForm.tsx index 25fc2ef24..9dc004a0c 100644 --- a/govtool/frontend/src/hooks/forms/useVoteContextForm.tsx +++ b/govtool/frontend/src/hooks/forms/useVoteContextForm.tsx @@ -71,7 +71,6 @@ export const useVoteContextForm = ( const result = await validateMetadata({ hash: localHash, url, - noStandard: true, }); if (result.status) { diff --git a/govtool/frontend/src/models/metadataValidation.ts b/govtool/frontend/src/models/metadataValidation.ts index 7b085fe6b..9e2dcee18 100644 --- a/govtool/frontend/src/models/metadataValidation.ts +++ b/govtool/frontend/src/models/metadataValidation.ts @@ -22,5 +22,4 @@ export type MetadataValidationDTO = { url: string; hash: string; standard?: MetadataStandard; - noStandard?: boolean; }; diff --git a/govtool/metadata-validation/src/app.controller.ts b/govtool/metadata-validation/src/app.controller.ts index 13e2a7986..260ceb69b 100644 --- a/govtool/metadata-validation/src/app.controller.ts +++ b/govtool/metadata-validation/src/app.controller.ts @@ -4,12 +4,36 @@ import { ValidateMetadataDTO } from '@dto'; import { ValidateMetadataResult } from '@types'; import { AppService } from './app.service'; +import { ApiBody, ApiResponse } from '@nestjs/swagger'; @Controller() export class AppController { constructor(private readonly appService: AppService) {} @Post('validate') + @ApiBody({ + schema: { + type: 'object', + properties: { + url: { type: 'string' }, + hash: { type: 'string' }, + standard: { type: 'string' }, + }, + required: ['url', 'hash'], + }, + }) + @ApiResponse({ + status: 200, + description: 'Validation result', + schema: { + type: 'object', + properties: { + valid: { type: 'boolean' }, + status: { type: 'string' }, + metadata: { type: 'object' }, + }, + }, + }) validateMetadata( @Body() validateMetadataDto: ValidateMetadataDTO, ): Promise { diff --git a/govtool/metadata-validation/src/app.service.ts b/govtool/metadata-validation/src/app.service.ts index 6775e9d3f..04dd67976 100644 --- a/govtool/metadata-validation/src/app.service.ts +++ b/govtool/metadata-validation/src/app.service.ts @@ -6,7 +6,7 @@ import * as blake from 'blakejs'; import { ValidateMetadataDTO } from '@dto'; import { LoggerMessage, MetadataValidationStatus } from '@enums'; import { validateMetadataStandard, parseMetadata } from '@utils'; -import { MetadataStandard, ValidateMetadataResult } from '@types'; +import { ValidateMetadataResult } from '@types'; @Injectable() export class AppService { @@ -15,9 +15,7 @@ export class AppService { async validateMetadata({ hash, url, - standard = MetadataStandard.CIP108, - // workaround property to not break the haskell backend - noStandard = false, + standard, }: ValidateMetadataDTO): Promise { let status: MetadataValidationStatus; let metadata: any; @@ -30,13 +28,8 @@ export class AppService { ), ); - Logger.debug(LoggerMessage.METADATA_DATA, data); - - if (standard && !noStandard) { + if (standard) { await validateMetadataStandard(data, standard); - } - - if (!noStandard) { metadata = parseMetadata(data.body, standard); } diff --git a/govtool/metadata-validation/src/dto/validateMetadata.dto.ts b/govtool/metadata-validation/src/dto/validateMetadata.dto.ts index 7756806c3..69462cee0 100644 --- a/govtool/metadata-validation/src/dto/validateMetadata.dto.ts +++ b/govtool/metadata-validation/src/dto/validateMetadata.dto.ts @@ -6,6 +6,4 @@ export class ValidateMetadataDTO { url: string; standard?: MetadataStandard; - - noStandard?: boolean; } diff --git a/govtool/metadata-validation/src/main.ts b/govtool/metadata-validation/src/main.ts index 052a4c8bb..8163818cc 100644 --- a/govtool/metadata-validation/src/main.ts +++ b/govtool/metadata-validation/src/main.ts @@ -7,14 +7,13 @@ import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule, { cors: true, - logger: ['debug', 'error', 'log'], + logger: ['error', 'log'], }); const config = new DocumentBuilder() - .setTitle('Submission Tool') - .setDescription('The Submission Tool API description') - .setVersion('1.0') - .addTag('submission') + .setTitle('Metadata Validation Tool') + .setDescription('The Metadata Validation Tool API description') + .setVersion('1.0.11') .build(); const document = SwaggerModule.createDocument(app, config); diff --git a/govtool/metadata-validation/src/utils/parseMetadata.ts b/govtool/metadata-validation/src/utils/parseMetadata.ts index 0669d13e1..b606c50ce 100644 --- a/govtool/metadata-validation/src/utils/parseMetadata.ts +++ b/govtool/metadata-validation/src/utils/parseMetadata.ts @@ -22,9 +22,7 @@ export const parseMetadata = ( ); } } - Logger.debug(LoggerMessage.PARSED_METADATA_BODY, parsedMetadata, { - standard, - }); + return parsedMetadata; case MetadataStandard.CIPQQQ: @@ -38,9 +36,6 @@ export const parseMetadata = ( ); } } - Logger.debug(LoggerMessage.PARSED_METADATA_BODY, parsedMetadata, { - standard, - }); return parsedMetadata; default: Logger.warn(LoggerMessage.CANNOT_PARSE_METADATA_BODY, { standard }); From 8acaa8e6e22397529c03c7955bb4fde11be9984a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Thu, 1 Aug 2024 10:06:25 +0200 Subject: [PATCH 6/9] fix: move validation requests to frontend service fixing metadatas --- CHANGELOG.md | 4 +- govtool/backend/sql/list-proposals-my.sql | 113 ++++++++++++++++++ govtool/frontend/.env.example | 1 + govtool/frontend/src/pages/DRepDetails.tsx | 2 +- .../src/services/requests/getDRepList.ts | 45 ++++++- .../src/services/requests/getDRepVotes.ts | 38 +++++- .../src/services/requests/getProposal.ts | 27 ++++- .../src/services/requests/getProposals.ts | 42 ++++++- .../metadataValidation/postValidate.ts | 5 +- .../src/utils/validateMetadataStandard.ts | 5 +- 10 files changed, 264 insertions(+), 18 deletions(-) create mode 100644 govtool/backend/sql/list-proposals-my.sql diff --git a/CHANGELOG.md b/CHANGELOG.md index 64b6d92bb..1336ca98b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ changes. ### Fixed -- +- Fix displaying Governance Action & DRep metadatas ### Changed @@ -24,7 +24,7 @@ changes. - Change link to docs regarding DReps [Issue 1130](https://github.com/IntersectMBO/govtool/issues/1130) - Change link to view governance actions docs [Issue 1131](https://github.com/IntersectMBO/govtool/issues/1131) - Make all the frontend build arguments mandatory [Issue 1642](https://github.com/IntersectMBO/govtool/issues/1642), [Issue 1643](https://github.com/IntersectMBO/govtool/issues/1643) -- Remove usage of metadata validation service in Haskell Backend +- Breaking! Remove usage of metadata validation service in Haskell Backend ## [sancho-v1.0.11](https://github.com/IntersectMBO/govtool/releases/tag/sancho-v1.0.11) 2024-07-30 diff --git a/govtool/backend/sql/list-proposals-my.sql b/govtool/backend/sql/list-proposals-my.sql new file mode 100644 index 000000000..fd2454ae2 --- /dev/null +++ b/govtool/backend/sql/list-proposals-my.sql @@ -0,0 +1,113 @@ +WITH LatestDrepDistr AS ( + SELECT + *, + ROW_NUMBER() OVER (PARTITION BY hash_id ORDER BY epoch_no DESC) AS rn + FROM + drep_distr +), +EpochUtils AS ( + SELECT + (Max(end_time) - Min(end_time)) / (Max(NO) - Min(NO)) AS epoch_duration, + Max(NO) AS last_epoch_no, + Max(end_time) AS last_epoch_end_time + FROM + epoch +), +always_no_confidence_voting_power AS ( + SELECT + coalesce(( + SELECT + amount + FROM drep_hash + LEFT JOIN drep_distr ON drep_hash.id = drep_distr.hash_id + WHERE + drep_hash.view = 'drep_always_no_confidence' ORDER BY epoch_no DESC LIMIT 1), 0) AS amount +), +always_abstain_voting_power AS ( + SELECT + coalesce(( + SELECT + amount + FROM drep_hash + LEFT JOIN drep_distr ON drep_hash.id = drep_distr.hash_id + WHERE + drep_hash.view = 'drep_always_abstain' ORDER BY epoch_no DESC LIMIT 1), 0) AS amount +) +SELECT + gov_action_proposal.id AS proposal_id, + encode(creator_tx.hash, 'hex') AS tx_hash, + gov_action_proposal.index, + gov_action_proposal.type::text, + CASE + WHEN gov_action_proposal.type = 'TreasuryWithdrawals' THEN + json_build_object('Reward Address', stake_address.view, 'Amount', treasury_withdrawal.amount) + WHEN gov_action_proposal.type::text = 'InfoAction' THEN + json_build_object() + ELSE + NULL + END AS description, + epoch_utils.last_epoch_end_time + epoch_utils.epoch_duration * (gov_action_proposal.expiration - epoch_utils.last_epoch_no) AS expiry_date, + gov_action_proposal.expiration AS expiry_epoch_no, + creator_block.time AS created_date, + creator_block.epoch_no AS created_epoch_no, + voting_anchor.url, + encode(voting_anchor.data_hash, 'hex') AS metadata_hash, + off_chain_vote_gov_action_data.title, + off_chain_vote_gov_action_data.abstract, + off_chain_vote_gov_action_data.motivation, + off_chain_vote_gov_action_data.rationale, + coalesce(Sum(ldd.amount) FILTER (WHERE voting_procedure.vote::text = 'Yes'), 0) + + CASE + WHEN gov_action_proposal.type = 'NoConfidence' THEN always_no_confidence_voting_power.amount + ELSE 0 + END AS yes_votes, + coalesce(Sum(ldd.amount) FILTER (WHERE voting_procedure.vote::text = 'No'), 0) + + CASE + WHEN gov_action_proposal.type = 'NoConfidence' THEN 0 + ELSE always_no_confidence_voting_power.amount + END AS no_votes, + coalesce(Sum(ldd.amount) FILTER (WHERE voting_procedure.vote::text = 'Abstain'), 0) + always_abstain_voting_power.amount AS abstain_votes +FROM + gov_action_proposal + LEFT JOIN treasury_withdrawal ON gov_action_proposal.id = treasury_withdrawal.gov_action_proposal_id + LEFT JOIN stake_address ON stake_address.id = treasury_withdrawal.stake_address_id + CROSS JOIN EpochUtils AS epoch_utils + CROSS JOIN always_no_confidence_voting_power + CROSS JOIN always_abstain_voting_power + CROSS JOIN off_chain_vote_gov_action_data ON off_chain_vote_gov_action_data.off_chain_vote_data_id = off_chain_vote_data.id + JOIN tx AS creator_tx ON creator_tx.id = gov_action_proposal.tx_id + JOIN block AS creator_block ON creator_block.id = creator_tx.block_id + LEFT JOIN voting_anchor ON voting_anchor.id = gov_action_proposal.voting_anchor_id + LEFT JOIN off_chain_vote_data ON off_chain_vote_data.voting_anchor_id = voting_anchor.id + LEFT JOIN voting_procedure ON voting_procedure.gov_action_proposal_id = gov_action_proposal.id + LEFT JOIN LatestDrepDistr ldd ON ldd.hash_id = voting_procedure.drep_voter AND ldd.rn = 1 +WHERE (NOT ? + OR (concat(encode(creator_tx.hash, 'hex'), '#', gov_action_proposal.index) IN ?)) +AND gov_action_proposal.expiration > ( + SELECT + Max(NO) + FROM + epoch) + AND gov_action_proposal.ratified_epoch IS NULL + AND gov_action_proposal.enacted_epoch IS NULL + AND gov_action_proposal.expired_epoch IS NULL + AND gov_action_proposal.dropped_epoch IS NULL +GROUP BY + (gov_action_proposal.id, + stake_address.view, + treasury_withdrawal.amount, + creator_block.epoch_no, + off_chain_vote_gov_action_data.title, + off_chain_vote_gov_action_data.abstract, + off_chain_vote_gov_action_data.motivation, + off_chain_vote_gov_action_data.rationale, + gov_action_proposal.index, + creator_tx.hash, + creator_block.time, + epoch_utils.epoch_duration, + epoch_utils.last_epoch_no, + epoch_utils.last_epoch_end_time, + voting_anchor.url, + voting_anchor.data_hash, + always_no_confidence_voting_power.amount, + always_abstain_voting_power.amount) diff --git a/govtool/frontend/.env.example b/govtool/frontend/.env.example index 000fde760..5fbb1a97f 100644 --- a/govtool/frontend/.env.example +++ b/govtool/frontend/.env.example @@ -1,5 +1,6 @@ VITE_APP_ENV="development" VITE_BASE_URL="" +VITE_METADATA_API_URL="" VITE_NETWORK_FLAG=0 VITE_SENTRY_DSN="" VITE_GTM_ID="" diff --git a/govtool/frontend/src/pages/DRepDetails.tsx b/govtool/frontend/src/pages/DRepDetails.tsx index 326de2371..735d8683e 100644 --- a/govtool/frontend/src/pages/DRepDetails.tsx +++ b/govtool/frontend/src/pages/DRepDetails.tsx @@ -258,7 +258,7 @@ export const DRepDetails = ({ isConnected }: DRepDetailsProps) => { )} - {references.length > 0 && !metadataStatus && ( + {references?.length > 0 && !metadataStatus && ( => { - const response = await API.get("/drep/list", { + const response = await API.get("/drep/list", { params: { page, pageSize, @@ -28,5 +34,38 @@ export const getDRepList = async ({ ...(status.length && { status }), }, }); - return response.data; + + const validatedResponse = { + ...response.data, + elements: await Promise.all( + response.data.elements.map(async (drep) => { + if (drep.metadataStatus || drep.metadataValid) { + return { + ...drep, + metadataStatus: drep.metadataStatus, + metadataValid: drep.metadataValid, + }; + } + if (drep.url && drep.metadataHash) { + const validationResponse = await postValidate({ + url: drep.url, + hash: drep.metadataHash, + standard: MetadataStandard.CIPQQQ, + }); + return { + ...drep, + bio: validationResponse.metadata?.bio, + dRepName: validationResponse.metadata?.dRepName, + email: validationResponse.metadata?.email, + references: validationResponse.metadata?.references, + metadataStatus: validationResponse.status || null, + metadataValid: validationResponse.valid, + }; + } + return drep; + }), + ), + }; + + return validatedResponse; }; diff --git a/govtool/frontend/src/services/requests/getDRepVotes.ts b/govtool/frontend/src/services/requests/getDRepVotes.ts index 4d5c6fdaa..d672a6e6a 100644 --- a/govtool/frontend/src/services/requests/getDRepVotes.ts +++ b/govtool/frontend/src/services/requests/getDRepVotes.ts @@ -1,5 +1,6 @@ -import { VotedProposal } from "@models"; +import { MetadataStandard, VotedProposal } from "@models"; import { API } from "../API"; +import { postValidate } from "./metadataValidation"; type GetDRepVotesParams = { type?: string[]; @@ -18,5 +19,38 @@ export const getDRepVotes = async ({ const { data } = await API.get(urlBase, { params }); - return data; + const validatedData = await Promise.all( + data.map(async (votedProposal) => { + if ( + votedProposal.proposal.metadataStatus || + votedProposal.proposal.metadataValid + ) { + return votedProposal; + } + + if (votedProposal.proposal.url && votedProposal.proposal.metadataHash) { + const validationResponse = await postValidate({ + url: votedProposal.proposal.url, + hash: votedProposal.proposal.metadataHash, + standard: MetadataStandard.CIP108, + }); + + return { + ...votedProposal, + proposal: { + ...votedProposal.proposal, + abstract: validationResponse.metadata?.abstract, + motivation: validationResponse.metadata?.motivation, + title: validationResponse.metadata?.title, + rationale: validationResponse.metadata?.rationale, + references: validationResponse.metadata?.references, + metadataStatus: validationResponse.status || null, + metadataValid: validationResponse.valid, + }, + }; + } + }), + ); + + return validatedData; }; diff --git a/govtool/frontend/src/services/requests/getProposal.ts b/govtool/frontend/src/services/requests/getProposal.ts index 67044403d..bd0c5fafb 100644 --- a/govtool/frontend/src/services/requests/getProposal.ts +++ b/govtool/frontend/src/services/requests/getProposal.ts @@ -1,11 +1,34 @@ +import { ProposalData } from "@/models"; import { API } from "../API"; +import { postValidate } from "./metadataValidation"; export const getProposal = async (proposalId: string, drepId?: string) => { const encodedHash = encodeURIComponent(proposalId); - const { data } = await API.get( + const { data } = await API.get( `/proposal/get/${encodedHash}?drepId=${drepId}`, ); - return data; + if (data.metadataStatus || data.metadataValid) { + return data; + } + if (!data.url || !data.metadataHash) { + return data; + } + + const validationResponse = await postValidate({ + url: data.url, + hash: data.metadataHash, + }); + + return { + ...data, + title: validationResponse.metadata?.title, + abstract: validationResponse.metadata?.abstract, + motivation: validationResponse.metadata?.motivation, + rationale: validationResponse.metadata?.rationale, + references: validationResponse.metadata?.references, + metadataStatus: validationResponse.status || null, + metadataValid: validationResponse.valid, + }; }; diff --git a/govtool/frontend/src/services/requests/getProposals.ts b/govtool/frontend/src/services/requests/getProposals.ts index e5cd14b1f..f94fbfc96 100644 --- a/govtool/frontend/src/services/requests/getProposals.ts +++ b/govtool/frontend/src/services/requests/getProposals.ts @@ -1,4 +1,6 @@ -import { InfinityProposals } from "@models"; +import { InfinityProposals, MetadataStandard } from "@models"; + +import { postValidate } from "./metadataValidation"; import { API } from "../API"; export type GetProposalsArguments = { @@ -19,7 +21,7 @@ export const getProposals = async ({ searchPhrase = "", sorting = "", }: GetProposalsArguments): Promise => { - const response = await API.get("/proposal/list", { + const response = await API.get("/proposal/list", { params: { page, pageSize, @@ -29,5 +31,39 @@ export const getProposals = async ({ ...(dRepID && { drepId: dRepID }), }, }); - return response.data; + + const validatedResponse = { + ...response.data, + elements: await Promise.all( + response.data.elements.map(async (proposal) => { + if (proposal.metadataStatus || proposal.metadataValid) { + return { + ...proposal, + metadataStatus: proposal.metadataStatus, + metadataValid: proposal.metadataValid, + }; + } + if (proposal.url && proposal.metadataHash) { + const validationResponse = await postValidate({ + url: proposal.url, + hash: proposal.metadataHash, + standard: MetadataStandard.CIP108, + }); + return { + ...proposal, + abstract: validationResponse.metadata?.abstract, + motivation: validationResponse.metadata?.motivation, + title: validationResponse.metadata?.title, + rationale: validationResponse.metadata?.rationale, + references: validationResponse.metadata?.references, + metadataStatus: validationResponse.status || null, + metadataValid: validationResponse.valid, + }; + } + + return proposal; + }), + ), + }; + return validatedResponse; }; diff --git a/govtool/frontend/src/services/requests/metadataValidation/postValidate.ts b/govtool/frontend/src/services/requests/metadataValidation/postValidate.ts index 93eb8cc5a..7121ec472 100644 --- a/govtool/frontend/src/services/requests/metadataValidation/postValidate.ts +++ b/govtool/frontend/src/services/requests/metadataValidation/postValidate.ts @@ -5,10 +5,7 @@ const TIMEOUT_IN_SECONDS = 30 * 1000; // 1000 ms is 1 s then its 30 s const METADATA_API = axios.create({ // API address of the metadata-validation service is different from the main API - baseURL: import.meta.env?.VITE_BASE_URL?.replace( - "api", - "metadata-validation", - ), + baseURL: import.meta.env?.VITE_METADATA_API_URL, timeout: TIMEOUT_IN_SECONDS, }); diff --git a/govtool/metadata-validation/src/utils/validateMetadataStandard.ts b/govtool/metadata-validation/src/utils/validateMetadataStandard.ts index b2b285de2..390cd2fba 100644 --- a/govtool/metadata-validation/src/utils/validateMetadataStandard.ts +++ b/govtool/metadata-validation/src/utils/validateMetadataStandard.ts @@ -16,7 +16,10 @@ export const validateMetadataStandard = async ( try { await cipStandardSchema[standard]?.validateAsync(data); } catch (error) { - Logger.error(LoggerMessage.METADATA_VALIDATION_ERROR, error); + Logger.error( + LoggerMessage.METADATA_VALIDATION_ERROR, + MetadataValidationStatus.INCORRECT_FORMAT, + ); throw MetadataValidationStatus.INCORRECT_FORMAT; } }; From 95f216710298e2c5f08bf2632288b0b7d97b88ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Thu, 1 Aug 2024 10:10:11 +0200 Subject: [PATCH 7/9] chore: infrastructure adjustments of metadata-validation service usage --- govtool/frontend/Dockerfile | 2 ++ scripts/govtool/frontend.mk | 1 + 2 files changed, 3 insertions(+) diff --git a/govtool/frontend/Dockerfile b/govtool/frontend/Dockerfile index 0980b978b..cd86a854c 100644 --- a/govtool/frontend/Dockerfile +++ b/govtool/frontend/Dockerfile @@ -2,6 +2,7 @@ FROM node:18-alpine as builder ARG VITE_APP_ENV='beta' ARG VITE_BASE_URL +ARG METADATA_API_URL ARG VITE_GTM_ID ARG VITE_NETWORK_FLAG=0 ARG VITE_SENTRY_DSN @@ -14,6 +15,7 @@ ARG VITE_PDF_API_URL RUN \ : "${VITE_APP_ENV:?Build argument VITE_APP_ENV is not set}" && \ : "${VITE_BASE_URL:?Build argument VITE_BASE_URL is not set}" && \ + : "${METADATA_API_URL:?Build argument METADATA_API_URL is not set}" && \ : "${VITE_GTM_ID:?Build argument VITE_GTM_ID is not set}" && \ : "${VITE_NETWORK_FLAG:?Build argument VITE_NETWORK_FLAG is not set}" && \ : "${VITE_SENTRY_DSN:?Build argument VITE_SENTRY_DSN is not set}" && \ diff --git a/scripts/govtool/frontend.mk b/scripts/govtool/frontend.mk index 3881a2bcd..64f5516e8 100644 --- a/scripts/govtool/frontend.mk +++ b/scripts/govtool/frontend.mk @@ -17,6 +17,7 @@ build-frontend: docker-login $(docker) build --tag "$(repo_url)/frontend:$(frontend_image_tag)" \ --build-arg VITE_APP_ENV="$(env)" \ --build-arg VITE_BASE_URL="https://$(domain)/api" \ + --build-arg VITE_METADATA_API_URL="https://$(domain)/metadata-validation" \ --build-arg VITE_GTM_ID="$${GTM_ID}" \ --build-arg VITE_NETWORK_FLAG="$$NETWORK_FLAG" \ --build-arg VITE_SENTRY_DSN="$${SENTRY_DSN}" \ From e56f7efbcfbce0866494a686413cf6197ab1eabf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Thu, 1 Aug 2024 15:48:40 +0200 Subject: [PATCH 8/9] fix: fix ts erorrs --- .../DashboardGovernanceActionDetails.tsx | 1 - .../src/hooks/queries/useGetDRepVotesQuery.ts | 2 +- .../src/hooks/queries/useGetProposalQuery.ts | 2 +- .../src/services/requests/getDRepList.ts | 6 +--- .../src/services/requests/getProposal.ts | 35 +++++++++++-------- .../src/services/requests/getProposals.ts | 6 +--- 6 files changed, 25 insertions(+), 27 deletions(-) diff --git a/govtool/frontend/src/components/organisms/DashboardGovernanceActionDetails.tsx b/govtool/frontend/src/components/organisms/DashboardGovernanceActionDetails.tsx index 69d0ea764..7da26b623 100644 --- a/govtool/frontend/src/components/organisms/DashboardGovernanceActionDetails.tsx +++ b/govtool/frontend/src/components/organisms/DashboardGovernanceActionDetails.tsx @@ -33,7 +33,6 @@ export const DashboardGovernanceActionDetails = () => { const fullProposalId = proposalId + hash; const { data, isLoading } = useGetProposalQuery(fullProposalId ?? "", !state); - const shortenedGovActionId = getShortenedGovActionId( state ? state.txHash : data?.proposal.txHash ?? "", state ? state.index : data?.proposal.index ?? "", diff --git a/govtool/frontend/src/hooks/queries/useGetDRepVotesQuery.ts b/govtool/frontend/src/hooks/queries/useGetDRepVotesQuery.ts index 313823722..bec791c61 100644 --- a/govtool/frontend/src/hooks/queries/useGetDRepVotesQuery.ts +++ b/govtool/frontend/src/hooks/queries/useGetDRepVotesQuery.ts @@ -33,7 +33,7 @@ export const useGetDRepVotesQuery = ( }); const groupedByType = data?.reduce((groups, item) => { - const itemType = item.proposal.type; + const itemType = item?.proposal.type; // TODO: Provide better typing for groups // eslint-disable-next-line @typescript-eslint/ban-ts-comment diff --git a/govtool/frontend/src/hooks/queries/useGetProposalQuery.ts b/govtool/frontend/src/hooks/queries/useGetProposalQuery.ts index 2606d5690..e200e48e9 100644 --- a/govtool/frontend/src/hooks/queries/useGetProposalQuery.ts +++ b/govtool/frontend/src/hooks/queries/useGetProposalQuery.ts @@ -17,7 +17,7 @@ export const useGetProposalQuery = (proposalId: string, enabled?: boolean) => { ); return { - data, + data: data!, isLoading, refetch, isFetching: isRefetching, diff --git a/govtool/frontend/src/services/requests/getDRepList.ts b/govtool/frontend/src/services/requests/getDRepList.ts index d07f990fe..47ea64e30 100644 --- a/govtool/frontend/src/services/requests/getDRepList.ts +++ b/govtool/frontend/src/services/requests/getDRepList.ts @@ -40,11 +40,7 @@ export const getDRepList = async ({ elements: await Promise.all( response.data.elements.map(async (drep) => { if (drep.metadataStatus || drep.metadataValid) { - return { - ...drep, - metadataStatus: drep.metadataStatus, - metadataValid: drep.metadataValid, - }; + return drep; } if (drep.url && drep.metadataHash) { const validationResponse = await postValidate({ diff --git a/govtool/frontend/src/services/requests/getProposal.ts b/govtool/frontend/src/services/requests/getProposal.ts index bd0c5fafb..b45b98b30 100644 --- a/govtool/frontend/src/services/requests/getProposal.ts +++ b/govtool/frontend/src/services/requests/getProposal.ts @@ -1,34 +1,41 @@ -import { ProposalData } from "@/models"; +import { MetadataStandard, VotedProposal } from "@/models"; import { API } from "../API"; import { postValidate } from "./metadataValidation"; -export const getProposal = async (proposalId: string, drepId?: string) => { +export const getProposal = async ( + proposalId: string, + drepId?: string, +): Promise => { const encodedHash = encodeURIComponent(proposalId); - const { data } = await API.get( + const { data } = await API.get( `/proposal/get/${encodedHash}?drepId=${drepId}`, ); - if (data.metadataStatus || data.metadataValid) { + if (data.proposal.metadataStatus || data.proposal.metadataValid) { return data; } - if (!data.url || !data.metadataHash) { + if (!data.proposal.url || !data.proposal.metadataHash) { return data; } const validationResponse = await postValidate({ - url: data.url, - hash: data.metadataHash, + url: data.proposal.url, + hash: data.proposal.metadataHash, + standard: MetadataStandard.CIP108, }); return { ...data, - title: validationResponse.metadata?.title, - abstract: validationResponse.metadata?.abstract, - motivation: validationResponse.metadata?.motivation, - rationale: validationResponse.metadata?.rationale, - references: validationResponse.metadata?.references, - metadataStatus: validationResponse.status || null, - metadataValid: validationResponse.valid, + proposal: { + ...data.proposal, + title: validationResponse.metadata?.title, + abstract: validationResponse.metadata?.abstract, + motivation: validationResponse.metadata?.motivation, + rationale: validationResponse.metadata?.rationale, + references: validationResponse.metadata?.references, + metadataStatus: validationResponse.status || null, + metadataValid: validationResponse.valid, + }, }; }; diff --git a/govtool/frontend/src/services/requests/getProposals.ts b/govtool/frontend/src/services/requests/getProposals.ts index f94fbfc96..49b43082f 100644 --- a/govtool/frontend/src/services/requests/getProposals.ts +++ b/govtool/frontend/src/services/requests/getProposals.ts @@ -37,11 +37,7 @@ export const getProposals = async ({ elements: await Promise.all( response.data.elements.map(async (proposal) => { if (proposal.metadataStatus || proposal.metadataValid) { - return { - ...proposal, - metadataStatus: proposal.metadataStatus, - metadataValid: proposal.metadataValid, - }; + return proposal; } if (proposal.url && proposal.metadataHash) { const validationResponse = await postValidate({ From 7e01cad606ad97eed4f8e74978258412d20c71e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Thu, 1 Aug 2024 16:25:23 +0200 Subject: [PATCH 9/9] fix: fix argument name in dockerfile --- govtool/frontend/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/govtool/frontend/Dockerfile b/govtool/frontend/Dockerfile index cd86a854c..c1656099a 100644 --- a/govtool/frontend/Dockerfile +++ b/govtool/frontend/Dockerfile @@ -2,7 +2,7 @@ FROM node:18-alpine as builder ARG VITE_APP_ENV='beta' ARG VITE_BASE_URL -ARG METADATA_API_URL +ARG VITE_METADATA_API_URL ARG VITE_GTM_ID ARG VITE_NETWORK_FLAG=0 ARG VITE_SENTRY_DSN @@ -15,7 +15,7 @@ ARG VITE_PDF_API_URL RUN \ : "${VITE_APP_ENV:?Build argument VITE_APP_ENV is not set}" && \ : "${VITE_BASE_URL:?Build argument VITE_BASE_URL is not set}" && \ - : "${METADATA_API_URL:?Build argument METADATA_API_URL is not set}" && \ + : "${VITE_METADATA_API_URL:?Build argument VITE_METADATA_API_URL is not set}" && \ : "${VITE_GTM_ID:?Build argument VITE_GTM_ID is not set}" && \ : "${VITE_NETWORK_FLAG:?Build argument VITE_NETWORK_FLAG is not set}" && \ : "${VITE_SENTRY_DSN:?Build argument VITE_SENTRY_DSN is not set}" && \