Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
jankun4 committed Jun 3, 2024
1 parent bdd71eb commit 14ad2dc
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 42 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ changes.

### Changed

- `proposal.about` changed to `proposal.abstract`
- `drep/info` now returns 4 different tx hashes instead of one latest tx hash [Issue 688](https://github.com/IntersectMBO/govtool/issues/688)
- `proposal/list` allows user to search by tx hash [Issue 603](https://github.com/IntersectMBO/govtool/issues/603)
- `proposal/list` returns additional data such ass `expiryEpochNo`, `createdEpochNo`, `title`, `about`, `motivation`,
Expand Down
56 changes: 32 additions & 24 deletions govtool/backend/src/VVA/API.hs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ type VVAApi =
:<|> "transaction" :> "status" :> Capture "transactionId" HexText :> Get '[JSON] GetTransactionStatusResponse
:<|> "throw500" :> Get '[JSON] ()
:<|> "network" :> "metrics" :> Get '[JSON] GetNetworkMetricsResponse
:<|> "metadata" :> "validate" :> ReqBody '[JSON] MetadataValidationParams :> Post '[JSON] MetadataValidationResponse
:<|> "proposal" :> "metadata" :> "validate" :> ReqBody '[JSON] MetadataValidationParams :> Post '[JSON] MetadataValidationResponse

server :: App m => ServerT VVAApi m
server = drepList
Expand All @@ -89,7 +89,7 @@ server = drepList
:<|> getTransactionStatus
:<|> throw500
:<|> getNetworkMetrics
:<|> validateMetadata
:<|> getProposalMetadataValidationResponse


mapDRepType :: Types.DRepType -> DRepType
Expand Down Expand Up @@ -177,8 +177,10 @@ getVotingPower (unHexText -> dRepId) = do
cacheRequest dRepVotingPowerCache dRepId $ DRep.getVotingPower dRepId


proposalToResponse :: Types.Proposal -> MetadataValidationResponse -> ProposalResponse
proposalToResponse Types.Proposal {..} metadataValidationResponse =
proposalToResponse :: Types.Proposal -> Types.ProposalMetadataValidationResult -> ProposalResponse
proposalToResponse Types.Proposal {..} Types.ProposalMetadataValidationResult{..} =
let metadata = proposalMetadataValidationResultMetadata
in
ProposalResponse
{ proposalResponseId = pack $ show proposalId,
proposalResponseTxHash = HexText proposalTxHash,
Expand All @@ -191,16 +193,17 @@ proposalToResponse Types.Proposal {..} metadataValidationResponse =
proposalResponseCreatedEpochNo = proposalCreatedEpochNo,
proposalResponseUrl = proposalUrl,
proposalResponseMetadataHash = HexText proposalDocHash,
proposalResponseTitle = proposalTitle,
proposalResponseAbout = proposalAbout,
proposalResponseMotivation = proposalMotivaiton,
proposalResponseRationale = proposalRationale,
proposalResponseTitle = Types.proposalMetadataTitle <$> metadata,
proposalResponseAbstract = Types.proposalMetadataAbstract <$> metadata,
proposalResponseMotivation = Types.proposalMetadataMotivation <$> metadata,
proposalResponseRationale = Types.proposalMetadataRationale <$> metadata,
proposalResponseMetadata = GovernanceActionMetadata <$> proposalMetadata,
proposalResponseReferences = GovernanceActionReferences <$> proposalReferences,
proposalResponseReferences = maybe [] Types.proposalMetadataReferences metadata,
proposalResponseYesVotes = proposalYesVotes,
proposalResponseNoVotes = proposalNoVotes,
proposalResponseAbstainVotes = proposalAbstainVotes,
proposalResponseMetadataStatus = Just metadataValidationResponse
proposalResponseMetadataStatus = proposalMetadataValidationResultStatus,
proposalResponseMetadataValid = proposalMetadataValidationResultValid
}

voteToResponse :: Types.Vote -> VoteParams
Expand All @@ -226,7 +229,7 @@ mapSortAndFilterProposals
mapSortAndFilterProposals selectedTypes sortMode proposals = do
mappedProposals <-
mapM
(\proposal@Types.Proposal {proposalUrl, proposalDocHash} -> proposalToResponse proposal <$> validateMetadata (MetadataValidationParams proposalUrl $ HexText proposalDocHash))
(\proposal@Types.Proposal {proposalUrl, proposalDocHash} -> proposalToResponse proposal <$> validateProposalMetadata (MetadataValidationParams proposalUrl $ HexText proposalDocHash))
proposals
let filteredProposals =
if null selectedTypes
Expand Down Expand Up @@ -297,7 +300,7 @@ isProposalSearchedFor (Just searchQuery) (ProposalResponse{..}) = fromMaybe Fals
let valuesToCheck = catMaybes
[ Just govActionId
, proposalResponseTitle
, proposalResponseAbout
, proposalResponseAbstract
, proposalResponseMotivation
, proposalResponseRationale
]
Expand Down Expand Up @@ -351,8 +354,8 @@ 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)
metadataStatus <- validateMetadata $ MetadataValidationParams proposalUrl $ HexText proposalDocHash
let proposalResponse = proposalToResponse proposal metadataStatus
proposalMetadataValidationResult <- validateProposalMetadata $ MetadataValidationParams proposalUrl $ HexText proposalDocHash
let proposalResponse = proposalToResponse proposal proposalMetadataValidationResult
voteResponse <- case mDrepId of
Nothing -> return Nothing
Just drepId -> do
Expand Down Expand Up @@ -400,14 +403,19 @@ getNetworkMetrics = do
, getNetworkMetricsResponseAlwaysNoConfidenceVotingPower = networkMetricsAlwaysNoConfidenceVotingPower
}

validateMetadata :: App m => MetadataValidationParams -> m MetadataValidationResponse
validateMetadata MetadataValidationParams {..} = do
validateProposalMetadata :: App m => MetadataValidationParams -> m Types.ProposalMetadataValidationResult
validateProposalMetadata MetadataValidationParams {..} = do
CacheEnv {metadataValidationCache} <- asks vvaCache
result <- cacheRequest metadataValidationCache (metadataValidationParamsUrl, unHexText metadataValidationParamsHash)
$ Metadata.validateMetadata metadataValidationParamsUrl (unHexText metadataValidationParamsHash)

case fromJSON result of
Error e -> return $ MetadataValidationResponse Nothing False (AnyValue $ Just result)
Success (InternalMetadataValidationResponse {..}) -> return $ MetadataValidationResponse {metadataValidationResponseStatus=internalMetadataValidationResponseStatus, metadataValidationResponseValid=internalMmetadataValidationResponseValid, metadataValidationResponseRaw=AnyValue $ Just result}


cacheRequest metadataValidationCache (metadataValidationParamsUrl, unHexText metadataValidationParamsHash)
$ Metadata.getProposalMetadataValidationResult metadataValidationParamsUrl (unHexText metadataValidationParamsHash)

getProposalMetadataValidationResponse :: App m => MetadataValidationParams -> m MetadataValidationResponse
getProposalMetadataValidationResponse params = do
result <- validateProposalMetadata params
case result of
Types.ProposalMetadataValidationResult {..} -> do
let metadata = proposalMetadataValidationResultMetadata
return $ MetadataValidationResponse
{ metadataValidationResponseValid = proposalMetadataValidationResultValid
, metadataValidationResponseStatus = proposalMetadataValidationResultStatus
}
19 changes: 10 additions & 9 deletions govtool/backend/src/VVA/API/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,8 @@ instance ToSchema InternalMetadataValidationResponse where

data MetadataValidationResponse
= MetadataValidationResponse
{ metadataValidationResponseStatus :: Maybe MetadataValidationStatus
{ metadataValidationResponseStatus :: Maybe Text
, metadataValidationResponseValid :: Bool
, metadataValidationResponseRaw :: AnyValue
}
deriving (Generic, Show)

Expand Down Expand Up @@ -463,15 +462,16 @@ data ProposalResponse
, proposalResponseUrl :: Text
, proposalResponseMetadataHash :: HexText
, proposalResponseTitle :: Maybe Text
, proposalResponseAbout :: Maybe Text
, proposalResponseAbstract :: Maybe Text
, proposalResponseMotivation :: Maybe Text
, proposalResponseRationale :: Maybe Text
, proposalResponseMetadata :: Maybe GovernanceActionMetadata
, proposalResponseReferences :: Maybe GovernanceActionReferences
, proposalResponseReferences :: [Text]
, proposalResponseYesVotes :: Integer
, proposalResponseNoVotes :: Integer
, proposalResponseAbstainVotes :: Integer
, proposalResponseMetadataStatus :: Maybe MetadataValidationResponse
, proposalResponseMetadataStatus :: Maybe Text
, proposalResponseMetadataValid :: Bool
}
deriving (Generic, Show)

Expand All @@ -490,15 +490,16 @@ exampleProposalResponse = "{ \"id\": \"proposalId123\","
<> "\"url\": \"https://proposal.metadata.xyz\","
<> "\"metadataHash\": \"9af10e89979e51b8cdc827c963124a1ef4920d1253eef34a1d5cfe76438e3f11\","
<> "\"title\": \"Proposal Title\","
<> "\"about\": \"Proposal About\","
<> "\"abstract\": \"Proposal About\","
<> "\"motivation\": \"Proposal Motivation\","
<> "\"rationale\": \"Proposal Rationale\","
<> "\"metadata\": {\"key\": \"value\"},"
<> "\"references\": [{\"uri\": \"google.com\", \"@type\": \"Other\", \"label\": \"example label\"}],"
<> "\"references\": [\"google.com\"],"
<> "\"yesVotes\": 0,"
<> "\"noVotes\": 0,"
<> "\"abstainVotes\": 0"
<> "\"metadataStatus\": {\"status\": null, \"valid\": true}}"
<> "\"abstainVotes\": 0,"
<> "\"metadataStatus\": \"URL_NOT_FOUND\","
<> "\"metadataValid\": true}"

instance ToSchema ProposalResponse where
declareNamedSchema proxy = do
Expand Down
53 changes: 46 additions & 7 deletions govtool/backend/src/VVA/Metadata.hs
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}

module VVA.Metadata where

import Prelude hiding (lookup)
import Control.Monad.Except (MonadError, throwError)
import Control.Monad.Reader
import Control.Exception (try, Exception)

import Data.Aeson (Value, decode, encode, object, (.=))
import Data.Typeable (Typeable)
import Data.Vector (toList)
import Data.Aeson.KeyMap (lookup)
import Data.Aeson (Value(..), decode, encode, object, (.=))
import Data.Maybe (fromJust)
import Data.ByteString (ByteString)
import Data.FileEmbed (embedFile)
import Data.Has (Has, getter)
import Data.String (fromString)
import Data.Text (Text, unpack)
import Data.Text (Text, unpack, pack)
import qualified Data.Text.Encoding as Text
import Data.Time.Clock

Expand All @@ -29,17 +35,50 @@ validateMetadata
:: (Has VVAConfig r, Has Manager r, MonadReader r m, MonadIO m, MonadError AppError m)
=> Text
-> Text
-> m Value
validateMetadata url hash = do
-> Maybe Text
-> m (Either Text Value)
validateMetadata url hash standard = do
metadataHost <- getMetadataValidationHost
metadataPort <- getMetadataValidationPort
manager <- asks getter
let requestBody = encode $ object ["url" .= unpack url, "hash" .= unpack hash]
let requestBody = encode $ object (["url" .= unpack url, "hash" .= unpack hash] ++ maybe [] (\x -> ["standard" .= unpack x]) standard)
initialRequest <- liftIO $ parseRequest (unpack metadataHost <> ":" <> show metadataPort <> "/validate")
let request = initialRequest
{ method = "POST"
, requestBody = RequestBodyLBS requestBody
, requestHeaders = [("Content-Type", "application/json")]
}
response <- liftIO $ httpLbs request manager
return $ fromJust $ decode $ responseBody response
response <- liftIO $ try $ httpLbs request manager
case response of
Left (e :: HttpException) -> return $ Left (pack $ show e)
Right r -> case decode $ responseBody r of
Nothing -> throwError $ InternalError "Failed to validate metadata"
Just x -> return $ Right x

getProposalMetadataValidationResult ::
(Has ConnectionPool r, Has Manager r, Has VVAConfig r, MonadReader r m, MonadIO m, MonadFail m, MonadError AppError m) =>
Text ->
Text ->
m ProposalMetadataValidationResult
getProposalMetadataValidationResult url hash = do
result <- validateMetadata url hash (Just "CIPQQQ")
case result of
Left e -> return $ ProposalMetadataValidationResult False (Just e) Nothing
Right (Object r) -> case go r of
Nothing -> throwError $ InternalError "Failed to validate metadata"
Just x -> return x
where
go result = do
(Bool valid) <- lookup "valid" result
let status = case lookup "status" result of
Just (String s) -> Just s
_ -> Nothing
let proposalMetadata = do
(Object m) <- lookup "metadata" result
let abstract = (\(String s) -> s) <$> lookup "abstract" m
let motivation = (\(String s) -> s) <$> lookup "motivation" m
let rationale = (\(String s) -> s) <$> lookup "rationale" m
let title = (\(String s) -> s) <$> lookup "title" m
let references = (\(Array references') -> map (\(String x) -> x) $ toList references') <$> lookup "references" m
ProposalMetadata <$> abstract <*> motivation <*> rationale <*> title <*> references
return $ ProposalMetadataValidationResult valid status proposalMetadata
23 changes: 21 additions & 2 deletions govtool/backend/src/VVA/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,23 @@ data Proposal

data TransactionStatus = TransactionConfirmed | TransactionUnconfirmed


data ProposalMetadata =
ProposalMetadata
{ proposalMetadataAbstract :: Text
, proposalMetadataMotivation :: Text
, proposalMetadataRationale :: Text
, proposalMetadataTitle :: Text
, proposalMetadataReferences :: [Text]
}

data ProposalMetadataValidationResult =
ProposalMetadataValidationResult
{ proposalMetadataValidationResultValid :: Bool
, proposalMetadataValidationResultStatus :: Maybe Text
, proposalMetadataValidationResultMetadata :: Maybe ProposalMetadata
}

data CacheEnv
= CacheEnv
{ proposalListCache :: Cache.Cache () [Proposal]
Expand All @@ -145,7 +162,7 @@ data CacheEnv
, dRepVotingPowerCache :: Cache.Cache Text Integer
, dRepListCache :: Cache.Cache () [DRepRegistration]
, networkMetricsCache :: Cache.Cache () NetworkMetrics
, metadataValidationCache :: Cache.Cache (Text, Text) Value
, metadataValidationCache :: Cache.Cache (Text, Text) ProposalMetadataValidationResult
}

data NetworkMetrics
Expand Down Expand Up @@ -174,4 +191,6 @@ data MetadataValidationStatus
= IncorrectFormat
| IncorrectJSONLD
| IncorrectHash
| UrlNotFound
| UrlNotFound


1 change: 1 addition & 0 deletions govtool/backend/vva-be.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ library
, swagger2
, http-client
, http-client-tls
, vector

exposed-modules: VVA.Config
, VVA.CommandLine
Expand Down

0 comments on commit 14ad2dc

Please sign in to comment.