Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a6ca482
chore: change convertDRepToCIP129 to convertDRep and use for both con…
kneerose Mar 18, 2025
3817a4a
test: add mock data and tests for converting script DRep to CIP-129/C…
kneerose Mar 18, 2025
6ac3128
chore: check conversion for both script/ non-script drep
kneerose Mar 18, 2025
c62cf0d
fix: vote assertion check issue on revote with updated context
kneerose Mar 19, 2025
30d2e5c
Merge pull request #3224 from IntersectMBO/tests/script-drep-conversion
kneerose Mar 19, 2025
472834c
fix: filtering drep votes
MSzalowski Mar 19, 2025
f510e4b
fix(#3242): fix redirection after vote
MSzalowski Mar 19, 2025
cb64984
Merge pull request #3248 from IntersectMBO/fix/3242-bug-incorrect-red…
MSzalowski Mar 20, 2025
d20d0c5
feat(#3230): redirect to outcomes from voting pillar
MSzalowski Mar 20, 2025
94683f8
Merge pull request #3254 from IntersectMBO/feat/3230-redirect-to-gove…
MSzalowski Mar 20, 2025
6628472
chore: update GovTool to v2.0.18
github-actions[bot] Mar 20, 2025
0278d0e
Merge pull request #3255 from IntersectMBO/chore/update-govtool-to-v2…
MSzalowski Mar 20, 2025
a2e795c
Merge pull request #3256 from IntersectMBO/develop
MSzalowski Mar 20, 2025
24cbf0f
chore(outcomes): add background color and upgrade to v1.3.0 with nece…
emmanuel-musau Mar 24, 2025
22bbd47
feat(#3263): add drep voting power list endpoint
MSzalowski Mar 25, 2025
f3835ce
Merge pull request #3266 from IntersectMBO/feat/add-drep-voting-power…
MSzalowski Mar 25, 2025
998f3c1
Merge pull request #3264 from emmanuel-musau/chore/outcomes-1.3.0
profd2004 Mar 25, 2025
a4d60ed
chore(#3037): Bump CSL to v14
MSzalowski Mar 25, 2025
0c32af3
Merge pull request #3267 from IntersectMBO/feat/3037-csl-versioning
MSzalowski Mar 25, 2025
ebdc0b9
chore: update govtool v2.0.18 release date
MSzalowski Mar 21, 2025
5d915d9
Merge pull request #3259 from IntersectMBO/chore/update-govtool-v2.0.…
MSzalowski Mar 25, 2025
f9383c3
Merge pull request #3268 from IntersectMBO/develop
MSzalowski Mar 25, 2025
97c355c
chore: add ipfs debug logs
MSzalowski Mar 25, 2025
3750329
Merge pull request #3272 from IntersectMBO/chore/dummy-rebuild-dev
MSzalowski Mar 25, 2025
783f372
fix: prevent publishing status when tests are skipped
kneerose Mar 26, 2025
c94ff7a
Merge pull request #3275 from IntersectMBO/fix/status-publish-on-depl…
mesudip Mar 26, 2025
324c9db
feat(#3273): add given name to drep voting power list endpoint
MSzalowski Mar 26, 2025
d99f342
Merge pull request #3276 from IntersectMBO/feat/3273-add-given-name-t…
MSzalowski Mar 26, 2025
7c2e9bc
chore: update GovTool v2.0.18 release date
MSzalowski Mar 26, 2025
af2e776
feat(#3277): handle drep voting power list on frontend
MSzalowski Mar 26, 2025
ce11d8d
Merge pull request #3281 from IntersectMBO/feat/3277-handle-drep-voti…
MSzalowski Mar 26, 2025
2c953c6
Merge pull request #3282 from IntersectMBO/chore/update-govtool-v2.0.…
MSzalowski Mar 26, 2025
15544c3
Merge pull request #3283 from IntersectMBO/develop
MSzalowski Mar 26, 2025
77c131c
Merge pull request #3257 from IntersectMBO/test
MSzalowski Mar 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test_backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ jobs:

publish-status:
runs-on: ubuntu-latest
if: always()
if: always() && needs.backend-tests.result != 'skipped'
needs: [backend-tests, publish-report]
steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test_integration_playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ jobs:

publish-status:
runs-on: ubuntu-latest
if: always()
if: always() && needs.integration-tests.result != 'skipped'
needs: [integration-tests, publish-report]
steps:
- uses: actions/checkout@v4
Expand Down
20 changes: 19 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,26 @@ changes.

### Removed

## [v2.0.17](https://github.com/IntersectMBO/govtool/releases/tag/v2.0.17) 2025-03-18
## [v2.0.18](https://github.com/IntersectMBO/govtool/releases/tag/v2.0.18) 2025-03-26

### Added

- Add redirection to outcomes when proposal is not found [Issue 3230](https://github.com/IntersectMBO/govtool/issues/3230)
- Add DRep voting power list endpoint [Issue 3263](https://github.com/IntersectMBO/govtool/issues/3263)
- Add DRep given name to the voting power list endpoint [Issue 3273](https://github.com/IntersectMBO/govtool/issues/3273)
- Add DRep voting power list query to PDF Pillar [Issue 3277](https://github.com/IntersectMBO/govtool/issues/3277)

### Fixed

- Fix post-vote navigation to governance action list [Issue 3242](https://github.com/IntersectMBO/govtool/issues/3242)

### Changed

- Bump CSL to v14 [Issue 3037](https://github.com/IntersectMBO/govtool/issues/3037)

### Removed

## [v2.0.17](https://github.com/IntersectMBO/govtool/releases/tag/v2.0.17) 2025-03-18

### Added

Expand Down
2 changes: 1 addition & 1 deletion govtool/backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ FROM $BASE_IMAGE_REPO:$BASE_IMAGE_TAG
WORKDIR /src
COPY . .
RUN cabal build
RUN cp dist-newstyle/build/x86_64-linux/ghc-9.2.7/vva-be-2.0.17/x/vva-be/build/vva-be/vva-be /usr/local/bin
RUN cp dist-newstyle/build/x86_64-linux/ghc-9.2.7/vva-be-2.0.18/x/vva-be/build/vva-be/vva-be /usr/local/bin
2 changes: 1 addition & 1 deletion govtool/backend/Dockerfile.qovery
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ FROM $BASE_IMAGE_REPO:$BASE_IMAGE_TAG
WORKDIR /src
COPY . .
RUN cabal build
RUN cp dist-newstyle/build/x86_64-linux/ghc-9.2.7/vva-be-2.0.17/x/vva-be/build/vva-be/vva-be /usr/local/bin
RUN cp dist-newstyle/build/x86_64-linux/ghc-9.2.7/vva-be-2.0.18/x/vva-be/build/vva-be/vva-be /usr/local/bin

# Expose the necessary port
EXPOSE 9876
Expand Down
2 changes: 2 additions & 0 deletions govtool/backend/app/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ startApp vvaConfig sentryService = do
networkMetricsCache <- newCache
networkInfoCache <- newCache
networkTotalStakeCache <- newCache
dRepVotingPowerListCache <- newCache
return $ CacheEnv
{ proposalListCache
, getProposalCache
Expand All @@ -137,6 +138,7 @@ startApp vvaConfig sentryService = do
, networkMetricsCache
, networkInfoCache
, networkTotalStakeCache
, dRepVotingPowerListCache
}

let connectionString = encodeUtf8 (dbSyncConnectionString $ getter vvaConfig)
Expand Down
37 changes: 37 additions & 0 deletions govtool/backend/sql/get-dreps-voting-power-list.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
WITH LatestExistingVotingAnchor AS (
SELECT
subquery.drep_registration_id,
subquery.drep_hash_id,
subquery.voting_anchor_id,
subquery.url,
subquery.metadata_hash,
subquery.ocvd_id
FROM (
SELECT
dr.id AS drep_registration_id,
dr.drep_hash_id,
va.id AS voting_anchor_id,
va.url,
encode(va.data_hash, 'hex') AS metadata_hash,
ocvd.id AS ocvd_id,
ROW_NUMBER() OVER (PARTITION BY dr.drep_hash_id ORDER BY dr.tx_id DESC) AS rn
FROM
drep_registration dr
JOIN voting_anchor va ON dr.voting_anchor_id = va.id
JOIN off_chain_vote_data ocvd ON va.id = ocvd.voting_anchor_id
WHERE
ocvd.voting_anchor_id IS NOT NULL
) subquery
WHERE
subquery.rn = 1
)
SELECT DISTINCT ON (raw)
view,
encode(raw, 'hex') AS hash_raw,
COALESCE(dd.amount, 0) AS voting_power,
ocvdd.given_name
FROM drep_hash dh
LEFT JOIN drep_distr dd ON dh.id = dd.hash_id AND dd.epoch_no = (SELECT MAX(no) from epoch)
LEFT JOIN LatestExistingVotingAnchor leva ON leva.drep_hash_id = dh.id
LEFT JOIN off_chain_vote_data ocvd ON ocvd.id = leva.ocvd_id
LEFT JOIN off_chain_vote_drep_data ocvdd ON ocvdd.off_chain_vote_data_id = ocvd.id
38 changes: 38 additions & 0 deletions govtool/backend/sql/get-filtered-dreps-voting-power.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
WITH LatestExistingVotingAnchor AS (
SELECT
subquery.drep_registration_id,
subquery.drep_hash_id,
subquery.voting_anchor_id,
subquery.url,
subquery.metadata_hash,
subquery.ocvd_id
FROM (
SELECT
dr.id AS drep_registration_id,
dr.drep_hash_id,
va.id AS voting_anchor_id,
va.url,
encode(va.data_hash, 'hex') AS metadata_hash,
ocvd.id AS ocvd_id,
ROW_NUMBER() OVER (PARTITION BY dr.drep_hash_id ORDER BY dr.tx_id DESC) AS rn
FROM
drep_registration dr
JOIN voting_anchor va ON dr.voting_anchor_id = va.id
JOIN off_chain_vote_data ocvd ON va.id = ocvd.voting_anchor_id
WHERE
ocvd.voting_anchor_id IS NOT NULL
) subquery
WHERE
subquery.rn = 1
)
SELECT DISTINCT ON (raw)
view,
encode(raw, 'hex') AS hash_raw,
COALESCE(dd.amount, 0) AS voting_power,
ocvdd.given_name
FROM drep_hash dh
LEFT JOIN drep_distr dd ON dh.id = dd.hash_id AND dd.epoch_no = (SELECT MAX(no) from epoch)
LEFT JOIN LatestExistingVotingAnchor leva ON leva.drep_hash_id = dh.id
LEFT JOIN off_chain_vote_data ocvd ON ocvd.id = leva.ocvd_id
LEFT JOIN off_chain_vote_drep_data ocvdd ON ocvdd.off_chain_vote_data_id = ocvd.id
WHERE view = ? OR encode(raw, 'hex') = ?
41 changes: 33 additions & 8 deletions govtool/backend/src/VVA/API.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import Control.Monad.Reader

import Data.Aeson (Value(..), Array, decode, encode, ToJSON, toJSON)
import Data.Bool (Bool)
import Data.List (sortOn)
import Data.List (sortOn, sort)
import qualified Data.Map as Map
import Data.Maybe (Maybe (Nothing), catMaybes, fromMaybe, mapMaybe)
import Data.Ord (Down (..))
Expand Down Expand Up @@ -64,6 +64,9 @@ type VVAApi =
:> QueryParam "search" Text
:> Get '[JSON] [VoteResponse]
:<|> "drep" :> "info" :> Capture "drepId" HexText :> Get '[JSON] DRepInfoResponse
:<|> "drep" :> "voting-power-list"
:> QueryParams "identifiers" Text
:> Get '[JSON] [DRepVotingPowerListResponse]
:<|> "ada-holder" :> "get-current-delegation" :> Capture "stakeKey" HexText :> Get '[JSON] (Maybe DelegationResponse)
:<|> "ada-holder" :> "get-voting-power" :> Capture "stakeKey" HexText :> Get '[JSON] Integer
:<|> "proposal" :> "list"
Expand All @@ -87,6 +90,7 @@ server = drepList
:<|> getVotingPower
:<|> getVotes
:<|> drepInfo
:<|> drepVotingPowerList
:<|> getCurrentDelegation
:<|> getStakeKeyVotingPower
:<|> listProposals
Expand Down Expand Up @@ -283,18 +287,20 @@ getVotes (unHexText -> dRepId) selectedTypes sortMode mSearch = do
CacheEnv {dRepGetVotesCache} <- asks vvaCache
(votes, proposals) <- cacheRequest dRepGetVotesCache dRepId $ DRep.getVotes dRepId []

let voteMap = Map.fromList $ map (\vote@Types.Vote {..} -> (voteProposalId, vote)) votes

processedProposals <- filter (isProposalSearchedFor mSearch) <$> mapSortAndFilterProposals selectedTypes sortMode proposals

let voteMapByTxHash = Map.fromList $
map (\vote -> (pack $ Prelude.takeWhile (/= '#') (unpack $ Types.voteGovActionId vote), vote)) votes

processedProposals <- filter (isProposalSearchedFor mSearch) <$>
mapSortAndFilterProposals selectedTypes sortMode proposals

return $
[ VoteResponse
{ voteResponseVote = voteToResponse vote
, voteResponseProposal = proposalResponse
}
| proposalResponse@ProposalResponse{proposalResponseId} <- processedProposals
, let proposalIdInt = read (unpack proposalResponseId) :: Int
, Just vote <- [Map.lookup (toInteger proposalIdInt) voteMap]
| proposalResponse <- processedProposals
, let txHash = unHexText (proposalResponseTxHash proposalResponse)
, Just vote <- [Map.lookup txHash voteMapByTxHash]
]

drepInfo :: App m => HexText -> m DRepInfoResponse
Expand Down Expand Up @@ -324,6 +330,25 @@ drepInfo (unHexText -> dRepId) = do
, dRepInfoResponseImageHash = HexText <$> dRepInfoImageHash
}

drepVotingPowerList :: App m => [Text] -> m [DRepVotingPowerListResponse]
drepVotingPowerList identifiers = do
CacheEnv {dRepVotingPowerListCache} <- asks vvaCache

let cacheKey = Text.intercalate "," (sort identifiers)

results <- cacheRequest dRepVotingPowerListCache cacheKey $
DRep.getDRepsVotingPowerList identifiers

return $ map toDRepVotingPowerListResponse results
where
toDRepVotingPowerListResponse Types.DRepVotingPowerList{..} =
DRepVotingPowerListResponse
{ drepVotingPowerListResponseView = drepView
, drepVotingPowerListResponseHashRaw = HexText drepHashRaw
, drepVotingPowerListResponseVotingPower = drepVotingPower
, drepVotingPowerListResponseGivenName = drepGivenName
}

getCurrentDelegation :: App m => HexText -> m (Maybe DelegationResponse)
getCurrentDelegation (unHexText -> stakeKey) = do
CacheEnv {adaHolderGetCurrentDelegationCache} <- asks vvaCache
Expand Down
31 changes: 31 additions & 0 deletions govtool/backend/src/VVA/API/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,37 @@ instance ToSchema DRepInfoResponse where
& example
?~ toJSON exampleDRepInfoResponse

data DRepVotingPowerListResponse
= DRepVotingPowerListResponse
{ drepVotingPowerListResponseView :: Text
, drepVotingPowerListResponseHashRaw :: HexText
, drepVotingPowerListResponseVotingPower :: Integer
, drepVotingPowerListResponseGivenName :: Maybe Text
}
deriving (Generic, Show)

deriveJSON (jsonOptions "drepVotingPowerListResponse") ''DRepVotingPowerListResponse

exampleDRepVotingPowerListResponse :: Text
exampleDRepVotingPowerListResponse =
"{\"view\": \"drep1qq5n7k0r0ff6lf4qvndw9t7vmdqa9y3q9qtjq879rrk9vcjcdy8a4xf92mqsajf9u3nrsh3r6zrp29kuydmfq45fz88qpzmjkc\","
<> "\"hashRaw\": \"9af10e89979e51b8cdc827c963124a1ef4920d1253eef34a1d5cfe76438e3f11\","
<> "\"votingPower\": 1000000,"
<> "\"givenName\": \"John Doe\"}"

instance ToSchema DRepVotingPowerListResponse where
declareNamedSchema proxy = do
NamedSchema name_ schema_ <-
genericDeclareNamedSchema
( fromAesonOptions $ jsonOptions "drepVotingPowerListResponse" )
proxy
return $
NamedSchema name_ $
schema_
& description ?~ "DRep Voting Power List Response"
& example
?~ toJSON exampleDRepVotingPowerListResponse

data GetProposalResponse
= GetProposalResponse
{ getProposalResponseVote :: Maybe VoteParams
Expand Down
68 changes: 47 additions & 21 deletions govtool/backend/src/VVA/DRep.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,33 @@

module VVA.DRep where

import Control.Monad.Except (MonadError)
import Control.Monad.Except (MonadError)
import Control.Monad.Reader

import Crypto.Hash

import Data.ByteString (ByteString)
import qualified Data.ByteString.Base16 as Base16
import qualified Data.ByteString.Char8 as C
import Data.FileEmbed (embedFile)
import Data.Foldable (Foldable (sum))
import Data.Has (Has)
import qualified Data.Map as M
import Data.Maybe (fromMaybe, isJust, isNothing)
import Data.ByteString (ByteString)
import qualified Data.ByteString.Base16 as Base16
import qualified Data.ByteString.Char8 as C
import Data.FileEmbed (embedFile)
import Data.Foldable (Foldable (sum))
import Data.Has (Has)
import qualified Data.Map as M
import Data.Maybe (fromMaybe, isJust, isNothing)
import Data.Scientific
import Data.String (fromString)
import Data.Text (Text, pack, unpack)
import qualified Data.Text.Encoding as Text
import Data.String (fromString)
import Data.Text (Text, pack, unpack, intercalate)
import qualified Data.Text.Encoding as Text
import Data.Time

import qualified Database.PostgreSQL.Simple as SQL
import qualified Database.PostgreSQL.Simple as SQL
import Database.PostgreSQL.Simple.Types (In(..))

import VVA.Config
import VVA.Pool (ConnectionPool, withPool)
import qualified VVA.Proposal as Proposal
import VVA.Types (AppError, DRepInfo (..), DRepRegistration (..), DRepStatus (..),
DRepType (..), Proposal (..), Vote (..))
import VVA.Pool (ConnectionPool, withPool)
import qualified VVA.Proposal as Proposal
import VVA.Types (AppError, DRepInfo (..), DRepRegistration (..), DRepStatus (..),
DRepType (..), Proposal (..), Vote (..), DRepVotingPowerList (..))

sqlFrom :: ByteString -> SQL.Query
sqlFrom bs = fromString $ unpack $ Text.decodeUtf8 bs
Expand Down Expand Up @@ -115,24 +117,22 @@ getVotes ::
m ([Vote], [Proposal])
getVotes drepId selectedProposals = withPool $ \conn -> do
results <- liftIO $ SQL.query conn getVotesSql (SQL.Only drepId)

if null results
then return ([], [])
else do
let proposalsToSelect = if null selectedProposals
then [ govActionId | (_, govActionId, _, _, _, _, _, _, _) <- results]
else selectedProposals

allProposals <- mapM (Proposal.getProposals . Just . (:[])) proposalsToSelect

let proposals = concat allProposals

let proposalMap = M.fromList $ map (\x -> (proposalId x, x)) proposals

timeZone <- liftIO getCurrentTimeZone

let votes =
[ Vote proposalId' drepId' vote' url' docHash' epochNo' (localTimeToUTC timeZone date') voteTxHash'
[ Vote proposalId' govActionId' drepId' vote' url' docHash' epochNo' (localTimeToUTC timeZone date') voteTxHash'
| (proposalId', govActionId', drepId', vote', url', docHash', epochNo', date', voteTxHash') <- results
, govActionId' `elem` proposalsToSelect
]
Expand Down Expand Up @@ -200,3 +200,29 @@ getDRepInfo drepId = withPool $ \conn -> do
}
[] -> return $ DRepInfo False False False False False Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
_ -> error "Unexpected result from database query in getDRepInfo"

getAllDRepsVotingPowerSql :: SQL.Query
getAllDRepsVotingPowerSql = sqlFrom $(embedFile "sql/get-dreps-voting-power-list.sql")

getFilteredDRepVotingPowerSql :: SQL.Query
getFilteredDRepVotingPowerSql = sqlFrom $(embedFile "sql/get-filtered-dreps-voting-power.sql")

getDRepsVotingPowerList ::
(Has ConnectionPool r, Has VVAConfig r, MonadReader r m, MonadIO m) =>
[Text] ->
m [DRepVotingPowerList]
getDRepsVotingPowerList identifiers = withPool $ \conn -> do
results <- if null identifiers
then do
liftIO $ SQL.query_ conn getAllDRepsVotingPowerSql
else do
resultsPerIdentifier <- forM identifiers $ \identifier -> do
liftIO $ SQL.query conn getFilteredDRepVotingPowerSql (identifier, identifier)

return $ concat resultsPerIdentifier

return
[ DRepVotingPowerList view hashRaw votingPower givenName
| (view, hashRaw, votingPower', givenName) <- results
, let votingPower = floor @Scientific votingPower'
]
Loading