Skip to content

Commit 22bbd47

Browse files
committed
feat(#3263): add drep voting power list endpoint
1 parent 0278d0e commit 22bbd47

File tree

9 files changed

+125
-19
lines changed

9 files changed

+125
-19
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ changes.
1212

1313
### Added
1414

15+
- Add drep voting power list endpoint [Issue 3263](https://github.com/IntersectMBO/govtool/issues/3263)
16+
1517
### Fixed
1618

1719
### Changed
@@ -20,7 +22,6 @@ changes.
2022

2123
## [v2.0.18](https://github.com/IntersectMBO/govtool/releases/tag/v2.0.18) 2025-03-20
2224

23-
2425
### Added
2526

2627
- Add redirection to outcomes when proposal is not found [Issue 3230](https://github.com/IntersectMBO/govtool/issues/3230)

govtool/backend/app/Main.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ startApp vvaConfig sentryService = do
124124
networkMetricsCache <- newCache
125125
networkInfoCache <- newCache
126126
networkTotalStakeCache <- newCache
127+
dRepVotingPowerListCache <- newCache
127128
return $ CacheEnv
128129
{ proposalListCache
129130
, getProposalCache
@@ -137,6 +138,7 @@ startApp vvaConfig sentryService = do
137138
, networkMetricsCache
138139
, networkInfoCache
139140
, networkTotalStakeCache
141+
, dRepVotingPowerListCache
140142
}
141143

142144
let connectionString = encodeUtf8 (dbSyncConnectionString $ getter vvaConfig)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
SELECT DISTINCT ON (raw)
2+
view,
3+
encode(raw, 'hex') AS hash_raw,
4+
COALESCE(dd.amount, 0) AS voting_power
5+
FROM drep_hash dh
6+
LEFT JOIN drep_distr dd ON dh.id = dd.hash_id AND dd.epoch_no = (SELECT MAX(no) from epoch)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
SELECT DISTINCT ON (raw)
2+
view,
3+
encode(raw, 'hex') AS hash_raw,
4+
COALESCE(dd.amount, 0) AS voting_power
5+
FROM drep_hash dh
6+
LEFT JOIN drep_distr dd ON dh.id = dd.hash_id AND dd.epoch_no = (SELECT MAX(no) from epoch)
7+
WHERE view = ? OR encode(raw, 'hex') = ?

govtool/backend/src/VVA/API.hs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import Control.Monad.Reader
1515

1616
import Data.Aeson (Value(..), Array, decode, encode, ToJSON, toJSON)
1717
import Data.Bool (Bool)
18-
import Data.List (sortOn)
18+
import Data.List (sortOn, sort)
1919
import qualified Data.Map as Map
2020
import Data.Maybe (Maybe (Nothing), catMaybes, fromMaybe, mapMaybe)
2121
import Data.Ord (Down (..))
@@ -64,6 +64,9 @@ type VVAApi =
6464
:> QueryParam "search" Text
6565
:> Get '[JSON] [VoteResponse]
6666
:<|> "drep" :> "info" :> Capture "drepId" HexText :> Get '[JSON] DRepInfoResponse
67+
:<|> "drep" :> "voting-power-list"
68+
:> QueryParams "identifiers" Text
69+
:> Get '[JSON] [DRepVotingPowerListResponse]
6770
:<|> "ada-holder" :> "get-current-delegation" :> Capture "stakeKey" HexText :> Get '[JSON] (Maybe DelegationResponse)
6871
:<|> "ada-holder" :> "get-voting-power" :> Capture "stakeKey" HexText :> Get '[JSON] Integer
6972
:<|> "proposal" :> "list"
@@ -87,6 +90,7 @@ server = drepList
8790
:<|> getVotingPower
8891
:<|> getVotes
8992
:<|> drepInfo
93+
:<|> drepVotingPowerList
9094
:<|> getCurrentDelegation
9195
:<|> getStakeKeyVotingPower
9296
:<|> listProposals
@@ -326,6 +330,24 @@ drepInfo (unHexText -> dRepId) = do
326330
, dRepInfoResponseImageHash = HexText <$> dRepInfoImageHash
327331
}
328332

333+
drepVotingPowerList :: App m => [Text] -> m [DRepVotingPowerListResponse]
334+
drepVotingPowerList identifiers = do
335+
CacheEnv {dRepVotingPowerListCache} <- asks vvaCache
336+
337+
let cacheKey = Text.intercalate "," (sort identifiers)
338+
339+
results <- cacheRequest dRepVotingPowerListCache cacheKey $
340+
DRep.getDRepsVotingPowerList identifiers
341+
342+
return $ map toDRepVotingPowerListResponse results
343+
where
344+
toDRepVotingPowerListResponse Types.DRepVotingPowerList{..} =
345+
DRepVotingPowerListResponse
346+
{ drepVotingPowerListResponseView = drepView
347+
, drepVotingPowerListResponseHashRaw = HexText drepHashRaw
348+
, drepVotingPowerListResponseVotingPower = drepVotingPower
349+
}
350+
329351
getCurrentDelegation :: App m => HexText -> m (Maybe DelegationResponse)
330352
getCurrentDelegation (unHexText -> stakeKey) = do
331353
CacheEnv {adaHolderGetCurrentDelegationCache} <- asks vvaCache

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,35 @@ instance ToSchema DRepInfoResponse where
622622
& example
623623
?~ toJSON exampleDRepInfoResponse
624624

625+
data DRepVotingPowerListResponse
626+
= DRepVotingPowerListResponse
627+
{ drepVotingPowerListResponseView :: Text
628+
, drepVotingPowerListResponseHashRaw :: HexText
629+
, drepVotingPowerListResponseVotingPower :: Integer
630+
}
631+
deriving (Generic, Show)
632+
633+
deriveJSON (jsonOptions "drepVotingPowerListResponse") ''DRepVotingPowerListResponse
634+
635+
exampleDRepVotingPowerListResponse :: Text
636+
exampleDRepVotingPowerListResponse =
637+
"{\"view\": \"drep1qq5n7k0r0ff6lf4qvndw9t7vmdqa9y3q9qtjq879rrk9vcjcdy8a4xf92mqsajf9u3nrsh3r6zrp29kuydmfq45fz88qpzmjkc\","
638+
<> "\"hashRaw\": \"9af10e89979e51b8cdc827c963124a1ef4920d1253eef34a1d5cfe76438e3f11\","
639+
<> "\"votingPower\": 1000000}"
640+
641+
instance ToSchema DRepVotingPowerListResponse where
642+
declareNamedSchema proxy = do
643+
NamedSchema name_ schema_ <-
644+
genericDeclareNamedSchema
645+
( fromAesonOptions $ jsonOptions "drepVotingPowerListResponse" )
646+
proxy
647+
return $
648+
NamedSchema name_ $
649+
schema_
650+
& description ?~ "DRep Voting Power List Response"
651+
& example
652+
?~ toJSON exampleDRepVotingPowerListResponse
653+
625654
data GetProposalResponse
626655
= GetProposalResponse
627656
{ getProposalResponseVote :: Maybe VoteParams

govtool/backend/src/VVA/DRep.hs

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,33 @@
66

77
module VVA.DRep where
88

9-
import Control.Monad.Except (MonadError)
9+
import Control.Monad.Except (MonadError)
1010
import Control.Monad.Reader
1111

1212
import Crypto.Hash
1313

14-
import Data.ByteString (ByteString)
15-
import qualified Data.ByteString.Base16 as Base16
16-
import qualified Data.ByteString.Char8 as C
17-
import Data.FileEmbed (embedFile)
18-
import Data.Foldable (Foldable (sum))
19-
import Data.Has (Has)
20-
import qualified Data.Map as M
21-
import Data.Maybe (fromMaybe, isJust, isNothing)
14+
import Data.ByteString (ByteString)
15+
import qualified Data.ByteString.Base16 as Base16
16+
import qualified Data.ByteString.Char8 as C
17+
import Data.FileEmbed (embedFile)
18+
import Data.Foldable (Foldable (sum))
19+
import Data.Has (Has)
20+
import qualified Data.Map as M
21+
import Data.Maybe (fromMaybe, isJust, isNothing)
2222
import Data.Scientific
23-
import Data.String (fromString)
24-
import Data.Text (Text, pack, unpack)
25-
import qualified Data.Text.Encoding as Text
23+
import Data.String (fromString)
24+
import Data.Text (Text, pack, unpack, intercalate)
25+
import qualified Data.Text.Encoding as Text
2626
import Data.Time
2727

28-
import qualified Database.PostgreSQL.Simple as SQL
28+
import qualified Database.PostgreSQL.Simple as SQL
29+
import Database.PostgreSQL.Simple.Types (In(..))
30+
2931
import VVA.Config
30-
import VVA.Pool (ConnectionPool, withPool)
31-
import qualified VVA.Proposal as Proposal
32-
import VVA.Types (AppError, DRepInfo (..), DRepRegistration (..), DRepStatus (..),
33-
DRepType (..), Proposal (..), Vote (..))
32+
import VVA.Pool (ConnectionPool, withPool)
33+
import qualified VVA.Proposal as Proposal
34+
import VVA.Types (AppError, DRepInfo (..), DRepRegistration (..), DRepStatus (..),
35+
DRepType (..), Proposal (..), Vote (..), DRepVotingPowerList (..))
3436

3537
sqlFrom :: ByteString -> SQL.Query
3638
sqlFrom bs = fromString $ unpack $ Text.decodeUtf8 bs
@@ -198,3 +200,29 @@ getDRepInfo drepId = withPool $ \conn -> do
198200
}
199201
[] -> return $ DRepInfo False False False False False Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
200202
_ -> error "Unexpected result from database query in getDRepInfo"
203+
204+
getAllDRepsVotingPowerSql :: SQL.Query
205+
getAllDRepsVotingPowerSql = sqlFrom $(embedFile "sql/get-dreps-voting-power-list.sql")
206+
207+
getFilteredDRepVotingPowerSql :: SQL.Query
208+
getFilteredDRepVotingPowerSql = sqlFrom $(embedFile "sql/get-filtered-dreps-voting-power.sql")
209+
210+
getDRepsVotingPowerList ::
211+
(Has ConnectionPool r, Has VVAConfig r, MonadReader r m, MonadIO m) =>
212+
[Text] ->
213+
m [DRepVotingPowerList]
214+
getDRepsVotingPowerList identifiers = withPool $ \conn -> do
215+
results <- if null identifiers
216+
then do
217+
liftIO $ SQL.query_ conn getAllDRepsVotingPowerSql
218+
else do
219+
resultsPerIdentifier <- forM identifiers $ \identifier -> do
220+
liftIO $ SQL.query conn getFilteredDRepVotingPowerSql (identifier, identifier)
221+
222+
return $ concat resultsPerIdentifier
223+
224+
return
225+
[ DRepVotingPowerList view hashRaw votingPower
226+
| (view, hashRaw, votingPower') <- results
227+
, let votingPower = floor @Scientific votingPower'
228+
]

govtool/backend/src/VVA/Types.hs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ data DRepInfo
9696
, dRepInfoImageHash :: Maybe Text
9797
}
9898

99+
data DRepVotingPowerList
100+
= DRepVotingPowerList
101+
{ drepView :: Text
102+
, drepHashRaw :: Text
103+
, drepVotingPower :: Integer
104+
}
105+
deriving (Show, Eq)
106+
99107
data DRepStatus = Active | Inactive | Retired deriving (Show, Eq, Ord)
100108

101109
data DRepType = DRep | SoleVoter deriving (Show, Eq)
@@ -216,6 +224,7 @@ data CacheEnv
216224
, networkMetricsCache :: Cache.Cache () NetworkMetrics
217225
, networkInfoCache :: Cache.Cache () NetworkInfo
218226
, networkTotalStakeCache :: Cache.Cache () NetworkTotalStake
227+
, dRepVotingPowerListCache :: Cache.Cache Text [DRepVotingPowerList]
219228
}
220229

221230
data NetworkInfo

govtool/backend/vva-be.cabal

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ extra-source-files:
3434
sql/get-network-metrics.sql
3535
sql/get-network-info.sql
3636
sql/get-network-total-stake.sql
37+
sql/get-dreps-voting-power-list.sql
38+
sql/get-filtered-dreps-voting-power.sql
3739
executable vva-be
3840
main-is: Main.hs
3941

0 commit comments

Comments
 (0)