Skip to content

Commit 9338a35

Browse files
authored
Merge pull request #3693 from IntersectMBO/fix/3490-off-chain-data-references-are-missing-for-dreps
fix(#3490): add missing DRep references
2 parents e1a8db7 + 7260f0b commit 9338a35

File tree

12 files changed

+237
-92
lines changed

12 files changed

+237
-92
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ changes.
1616

1717
### Fixed
1818

19+
- Fix missing off chain references in DRep details [Issue 3490](https://github.com/IntersectMBO/govtool/issues/3490)
20+
1921
### Changed
2022

2123
### Removed

govtool/backend/sql/list-dreps.sql

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,35 @@ DRepData AS (
126126
off_chain_vote_drep_data.motivations,
127127
off_chain_vote_drep_data.qualifications,
128128
off_chain_vote_drep_data.image_url,
129-
off_chain_vote_drep_data.image_hash
129+
off_chain_vote_drep_data.image_hash,
130+
COALESCE(
131+
(
132+
SELECT jsonb_agg(ref)
133+
FROM jsonb_array_elements(
134+
CASE
135+
WHEN (ocvd.json::jsonb)->'body'->'references' IS NOT NULL
136+
THEN (ocvd.json::jsonb)->'body'->'references'
137+
ELSE '[]'::jsonb
138+
END
139+
) AS ref
140+
WHERE ref->>'@type' = 'Identity'
141+
),
142+
'[]'::jsonb
143+
) AS identity_references,
144+
COALESCE(
145+
(
146+
SELECT jsonb_agg(ref)
147+
FROM jsonb_array_elements(
148+
CASE
149+
WHEN (ocvd.json::jsonb)->'body'->'references' IS NOT NULL
150+
THEN (ocvd.json::jsonb)->'body'->'references'
151+
ELSE '[]'::jsonb
152+
END
153+
) AS ref
154+
WHERE ref->>'@type' = 'Link'
155+
),
156+
'[]'::jsonb
157+
) AS link_references
130158
FROM
131159
drep_hash dh
132160
JOIN RankedDRepRegistration ON RankedDRepRegistration.drep_hash_id = dh.id
@@ -212,7 +240,29 @@ DRepData AS (
212240
off_chain_vote_drep_data.motivations,
213241
off_chain_vote_drep_data.qualifications,
214242
off_chain_vote_drep_data.image_url,
215-
off_chain_vote_drep_data.image_hash
243+
off_chain_vote_drep_data.image_hash,
244+
(
245+
SELECT jsonb_agg(ref)
246+
FROM jsonb_array_elements(
247+
CASE
248+
WHEN (ocvd.json::jsonb)->'body'->'references' IS NOT NULL
249+
THEN (ocvd.json::jsonb)->'body'->'references'
250+
ELSE '[]'::jsonb
251+
END
252+
) AS ref
253+
WHERE ref->>'@type' = 'Identity'
254+
),
255+
(
256+
SELECT jsonb_agg(ref)
257+
FROM jsonb_array_elements(
258+
CASE
259+
WHEN (ocvd.json::jsonb)->'body'->'references' IS NOT NULL
260+
THEN (ocvd.json::jsonb)->'body'->'references'
261+
ELSE '[]'::jsonb
262+
END
263+
) AS ref
264+
WHERE ref->>'@type' = 'Link'
265+
)
216266
)
217267
SELECT * FROM DRepData
218268
WHERE

govtool/backend/src/VVA/API.hs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,9 @@ drepRegistrationToDrep Types.DRepRegistration {..} =
134134
dRepMotivations = dRepRegistrationMotivations,
135135
dRepQualifications = dRepRegistrationQualifications,
136136
dRepImageUrl = dRepRegistrationImageUrl,
137-
dRepImageHash = HexText <$> dRepRegistrationImageHash
137+
dRepImageHash = HexText <$> dRepRegistrationImageHash,
138+
dRepIdentityReferences = DRepReferences <$> dRepRegistrationIdentityReferences,
139+
dRepLinkReferences = DRepReferences <$> dRepRegistrationLinkReferences
138140
}
139141

140142
delegationToResponse :: Types.Delegation -> DelegationResponse

govtool/backend/src/VVA/API/Types.hs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ instance ToParamSchema GovernanceActionSortMode where
273273

274274

275275
newtype GovernanceActionDetails
276-
= GovernanceActionDetails { getValue :: Value }
276+
= GovernanceActionDetails { getGovernanceActionValue :: Value }
277277
deriving newtype (Show)
278278

279279
instance FromJSON GovernanceActionDetails where
@@ -593,6 +593,7 @@ instance ToSchema VoteResponse where
593593
& example
594594
?~ toJSON exampleVoteResponse
595595

596+
596597
data DRepInfoResponse
597598
= DRepInfoResponse
598599
{ dRepInfoResponseIsScriptBased :: Bool
@@ -612,7 +613,7 @@ data DRepInfoResponse
612613
, dRepInfoResponseGivenName :: Maybe Text
613614
, dRepInfoResponseObjectives :: Maybe Text
614615
, dRepInfoResponseMotivations :: Maybe Text
615-
, dRepInfoResponseQualifications :: Maybe Text
616+
, dRepInfoResponseQualifications :: Maybe Text
616617
, dRepInfoResponseImageUrl :: Maybe Text
617618
, dRepInfoResponseImageHash :: Maybe HexText
618619
}
@@ -820,6 +821,27 @@ instance ToSchema DRepType where
820821
& description ?~ "DRep Type"
821822
& enum_ ?~ map toJSON [NormalDRep, SoleVoter]
822823

824+
newtype DRepReferences
825+
= DRepReferences { getDRepReferencesValue :: Value }
826+
deriving newtype (Show)
827+
828+
instance FromJSON DRepReferences where
829+
parseJSON v = return $ DRepReferences v
830+
831+
instance ToJSON DRepReferences where
832+
toJSON (DRepReferences d) = d
833+
834+
instance ToSchema DRepReferences where
835+
declareNamedSchema _ = pure $ NamedSchema (Just "DRepReferences") $ mempty
836+
& type_ ?~ OpenApiObject
837+
& description ?~ "A JSON value that can include nested objects and arrays"
838+
& example ?~ toJSON
839+
(Aeson.object
840+
[ "some_key" .= ("some value" :: String)
841+
, "nested_key" .= Aeson.object ["inner_key" .= (1 :: Int)]
842+
, "array_key" .= [1, 2, 3 :: Int]
843+
])
844+
823845
data DRep
824846
= DRep
825847
{ dRepIsScriptBased :: Bool
@@ -838,9 +860,11 @@ data DRep
838860
, dRepGivenName :: Maybe Text
839861
, dRepObjectives :: Maybe Text
840862
, dRepMotivations :: Maybe Text
841-
, dRepQualifications :: Maybe Text
863+
, dRepQualifications :: Maybe Text
842864
, dRepImageUrl :: Maybe Text
843865
, dRepImageHash :: Maybe HexText
866+
, dRepIdentityReferences :: Maybe DRepReferences
867+
, dRepLinkReferences :: Maybe DRepReferences
844868
}
845869
deriving (Generic, Show)
846870

govtool/backend/src/VVA/DRep.hs

Lines changed: 73 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,41 +11,74 @@ import Control.Monad.Reader
1111

1212
import Crypto.Hash
1313

14+
import Data.Aeson (Value)
1415
import Data.ByteString (ByteString)
15-
import qualified Data.ByteString.Base16 as Base16
16-
import qualified Data.ByteString.Char8 as C
16+
import qualified Data.ByteString.Base16 as Base16
17+
import qualified Data.ByteString.Char8 as C
1718
import Data.FileEmbed (embedFile)
1819
import Data.Foldable (Foldable (sum))
1920
import Data.Has (Has)
20-
import qualified Data.Map as M
21+
import qualified Data.Map as M
2122
import Data.Maybe (fromMaybe, isJust, isNothing)
2223
import Data.Scientific
2324
import Data.String (fromString)
2425
import Data.Text (Text, pack, unpack, intercalate)
25-
import qualified Data.Text.Encoding as Text
26+
import qualified Data.Text.Encoding as Text
2627
import Data.Time
2728

28-
import qualified Database.PostgreSQL.Simple as SQL
29+
import qualified Database.PostgreSQL.Simple as SQL
2930
import Database.PostgreSQL.Simple.Types (In(..))
31+
import Database.PostgreSQL.Simple.FromRow
3032

3133
import VVA.Config
3234
import VVA.Pool (ConnectionPool, withPool)
33-
import qualified VVA.Proposal as Proposal
35+
import qualified VVA.Proposal as Proposal
3436
import VVA.Types (AppError, DRepInfo (..), DRepRegistration (..), DRepStatus (..),
3537
DRepType (..), Proposal (..), Vote (..), DRepVotingPowerList (..))
3638

39+
data DRepQueryResult = DRepQueryResult
40+
{ queryDrepHash :: Text
41+
, queryDrepView :: Text
42+
, queryIsScriptBased :: Bool
43+
, queryUrl :: Maybe Text
44+
, queryDataHash :: Maybe Text
45+
, queryDeposit :: Scientific
46+
, queryVotingPower :: Maybe Integer
47+
, queryIsActive :: Bool
48+
, queryTxHash :: Maybe Text
49+
, queryDate :: LocalTime
50+
, queryLatestDeposit :: Scientific
51+
, queryLatestNonDeregisterVotingAnchorWasNotNull :: Bool
52+
, queryMetadataError :: Maybe Text
53+
, queryPaymentAddress :: Maybe Text
54+
, queryGivenName :: Maybe Text
55+
, queryObjectives :: Maybe Text
56+
, queryMotivations :: Maybe Text
57+
, queryQualifications :: Maybe Text
58+
, queryImageUrl :: Maybe Text
59+
, queryImageHash :: Maybe Text
60+
, queryIdentityReferences :: Maybe Value
61+
, queryLinkReferences :: Maybe Value
62+
} deriving (Show)
63+
64+
instance FromRow DRepQueryResult where
65+
fromRow = DRepQueryResult
66+
<$> field <*> field <*> field <*> field <*> field <*> field
67+
<*> field <*> field <*> field <*> field <*> field <*> field
68+
<*> field <*> field <*> field <*> field <*> field <*> field
69+
<*> field <*> field <*> field <*> field
70+
3771
sqlFrom :: ByteString -> SQL.Query
3872
sqlFrom bs = fromString $ unpack $ Text.decodeUtf8 bs
3973

4074
listDRepsSql :: SQL.Query
4175
listDRepsSql = sqlFrom $(embedFile "sql/list-dreps.sql")
42-
4376
listDReps ::
4477
(Has ConnectionPool r, Has VVAConfig r, MonadReader r m, MonadIO m) =>
4578
Maybe Text -> m [DRepRegistration]
4679
listDReps mSearchQuery = withPool $ \conn -> do
4780
let searchParam = fromMaybe "" mSearchQuery
48-
results <- liftIO $ SQL.query conn listDRepsSql
81+
results <- liftIO (SQL.query conn listDRepsSql
4982
( searchParam -- COALESCE(?, '')
5083
, searchParam -- LENGTH(?)
5184
, searchParam -- AND ?
@@ -56,44 +89,45 @@ listDReps mSearchQuery = withPool $ \conn -> do
5689
, "%" <> searchParam <> "%" -- objectives
5790
, "%" <> searchParam <> "%" -- motivations
5891
, "%" <> searchParam <> "%" -- qualifications
59-
)
92+
) :: IO [DRepQueryResult])
6093

6194
timeZone <- liftIO getCurrentTimeZone
6295
return
63-
[ DRepRegistration drepHash drepView isScriptBased url dataHash (floor @Scientific deposit) votingPower status drepType txHash (localTimeToUTC timeZone date) metadataError paymentAddress givenName objectives motivations qualifications imageUrl imageHash
64-
| ( drepHash
65-
, drepView
66-
, isScriptBased
67-
, url
68-
, dataHash
69-
, deposit
70-
, votingPower
71-
, isActive
72-
, txHash
73-
, date
74-
, latestDeposit
75-
, latestNonDeregisterVotingAnchorWasNotNull
76-
, metadataError
77-
, paymentAddress
78-
, givenName
79-
, objectives
80-
, motivations
81-
, qualifications
82-
, imageUrl
83-
, imageHash
84-
) <- results
85-
, let status = case (isActive, deposit) of
96+
[ DRepRegistration
97+
(queryDrepHash result)
98+
(queryDrepView result)
99+
(queryIsScriptBased result)
100+
(queryUrl result)
101+
(queryDataHash result)
102+
(floor @Scientific $ queryDeposit result)
103+
(queryVotingPower result)
104+
status
105+
drepType
106+
(queryTxHash result)
107+
(localTimeToUTC timeZone $ queryDate result)
108+
(queryMetadataError result)
109+
(queryPaymentAddress result)
110+
(queryGivenName result)
111+
(queryObjectives result)
112+
(queryMotivations result)
113+
(queryQualifications result)
114+
(queryImageUrl result)
115+
(queryImageHash result)
116+
(queryIdentityReferences result)
117+
(queryLinkReferences result)
118+
| result <- results
119+
, let status = case (queryIsActive result, queryDeposit result) of
86120
(_, d) | d < 0 -> Retired
87121
(isActive, d) | d >= 0 && isActive -> Active
88122
| d >= 0 && not isActive -> Inactive
89-
, let latestDeposit' = floor @Scientific latestDeposit :: Integer
90-
, let drepType | latestDeposit' >= 0 && isNothing url = SoleVoter
91-
| latestDeposit' >= 0 && isJust url = DRep
92-
| latestDeposit' < 0 && not latestNonDeregisterVotingAnchorWasNotNull = SoleVoter
93-
| latestDeposit' < 0 && latestNonDeregisterVotingAnchorWasNotNull = DRep
94-
| Data.Maybe.isJust url = DRep
123+
, let latestDeposit' = floor @Scientific (queryLatestDeposit result) :: Integer
124+
, let drepType | latestDeposit' >= 0 && isNothing (queryUrl result) = SoleVoter
125+
| latestDeposit' >= 0 && isJust (queryUrl result) = DRep
126+
| latestDeposit' < 0 && not (queryLatestNonDeregisterVotingAnchorWasNotNull result) = SoleVoter
127+
| latestDeposit' < 0 && queryLatestNonDeregisterVotingAnchorWasNotNull result = DRep
128+
| Data.Maybe.isJust (queryUrl result) = DRep
95129
]
96-
130+
97131
getVotingPowerSql :: SQL.Query
98132
getVotingPowerSql = sqlFrom $(embedFile "sql/get-voting-power.sql")
99133

0 commit comments

Comments
 (0)