Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ changes.

### Added

### Fixed
- Add support for preprod in matomo analytics [Issue 3173](https://github.com/IntersectMBO/govtool/issues/3173)

- hotfix for ada handle and payment address validation order [Issue 3155](https://github.com/IntersectMBO/govtool/issues/3155)
### Fixed

### Changed

- Exclude network total stake and info from network metrics [Issue 3189](https://github.com/IntersectMBO/govtool/issues/3189)

### Removed

## [v2.0.15](https://github.com/IntersectMBO/govtool/releases/tag/v2.0.15) 2025-03-11
Expand Down
34 changes: 17 additions & 17 deletions govtool/backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ This is a backend application of GovTool project.

In order to run `backend` your host machine will need access to the `cardano-db-sync` postgres database. To have this database running locally you'll need:

- `cardano-node`
- `cardano-db-sync`
- PostgreSQL database
- [cardano-node](https://github.com/IntersectMBO/cardano-node)
- [cardano-db-sync](https://github.com/IntersectMBO/cardano-db-sync)
- [PostgreSQL database](https://www.postgresql.org/download/) (psql needs to be installed on your machine in order to compile the project)

You will need your `cardano-node` and `cardano-db-sync` to be compatible with Sancho testnet. Until these features will be merged to the master branch the new Sancho compatible versions are available as releases on [github](https://github.com/IntersectMBO/cardano-db-sync/releases). You will also need a correct `cardano-node` version. The release notes for `cardano-db-sync` usualy specify that.

Expand All @@ -30,44 +30,44 @@ Due to problems with openapi3 package it's hard to build this project with plain

2. Get [direnv](https://direnv.net/).

3. Set GHC version to 9.10.1:
3. Set GHC version to 9.2.8:

```sh
ghcup install ghc 9.10.1
ghcup install ghc 9.2.8

ghcup set ghc 9.10.1
ghcup set ghc 9.2.8
```

4. Install cabal

```sh
ghcup install cabal
ghcup set cabal
```
```sh
ghcup install cabal
ghcup set cabal
```

5. Enter `govtool/backend` directory:

```sh
cd govtool/backend
cd govtool/backend
```

6. Allow direnv to setup your environment:

```sh
direnv allow
direnv allow
```

7. Update cabal & build project
```sh
cabal update
cabal build all
cabal update
cabal build all
```
8. Create a config file. You can use `example-config.json` as a template.

9. Run project
`sh
cabal run vva-be -- --config <YOUR CONFIG FILE> start-app
`
```sh
cabal run vva-be -- --config <YOUR CONFIG FILE> start-app
```
> [!WARNING]
> In the context of our ongoing project enhancements, it is assumed that the executable previously known as 'vva-be' should be now officially renamed to 'govtool-backend'. This change is necessary for aligning with the updated branding and functional scope of the application and it has to be implemented in the near future as a chore and refactoring ticket. Make sure that the documentation matches the actual name of the executable.

Expand Down
5 changes: 5 additions & 0 deletions govtool/backend/app/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ startApp vvaConfig sentryService = do
dRepVotingPowerCache <- newCache
dRepListCache <- newCache
networkMetricsCache <- newCache
networkInfoCache <- newCache
networkTotalStakeCache <- newCache
return $ CacheEnv
{ proposalListCache
, getProposalCache
Expand All @@ -133,6 +135,8 @@ startApp vvaConfig sentryService = do
, dRepVotingPowerCache
, dRepListCache
, networkMetricsCache
, networkInfoCache
, networkTotalStakeCache
}

let connectionString = encodeUtf8 (dbSyncConnectionString $ getter vvaConfig)
Expand All @@ -144,6 +148,7 @@ startApp vvaConfig sentryService = do

exceptionHandler :: VVAConfig -> SentryService -> Maybe Request -> SomeException -> IO ()
exceptionHandler vvaConfig sentryService mRequest exception = do
print exception
let isNotTimeoutThread x = case fromException x of
Just TimeoutThread -> False
_ -> True
Expand Down
6 changes: 6 additions & 0 deletions govtool/backend/sql/get-network-info.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
SELECT
(SELECT MAX(no) FROM epoch) AS current_epoch,
(SELECT MAX(block_no) FROM block) AS current_block,
network_name
FROM
meta;
48 changes: 1 addition & 47 deletions govtool/backend/sql/get-network-metrics.sql
Original file line number Diff line number Diff line change
Expand Up @@ -110,23 +110,6 @@ TotalActiveCIP119CompliantDReps AS (
AND lve.epoch_no >= (SELECT epoch_no FROM ActiveDRepBoundaryEpoch)
)))
),
TotalStakeControlledByActiveDReps AS (
SELECT
COALESCE(SUM(dd.amount), 0)::bigint AS total
FROM
drep_hash dh
LEFT JOIN DRepDistr dd ON dd.hash_id = dh.id AND dd.rn = 1
LEFT JOIN RankedDRepRegistration rd ON dd.hash_id = rd.drep_hash_id AND rd.rn = 1
LEFT JOIN LatestVoteEpoch lve ON lve.drep_id = dh.id
CROSS JOIN DRepActivity
WHERE
dd.epoch_no = (SELECT no FROM CurrentEpoch)
AND COALESCE(rd.deposit, 0) >= 0
AND ((DRepActivity.epoch_no - GREATEST(COALESCE(lve.epoch_no, 0), COALESCE(rd.epoch_no, 0))) <= DRepActivity.drep_activity)
),
CurrentBlock AS (
SELECT MAX(block_no) AS block_no FROM block
),
UniqueDelegators AS (
SELECT COUNT(DISTINCT addr_id) AS count FROM delegation_vote
),
Expand All @@ -139,9 +122,6 @@ TotalGovActionProposals AS (
TotalDRepVotes AS (
SELECT COUNT(*) AS count FROM voting_procedure WHERE voter_role = 'DRep'
),
TotalStakeControlledBySPOs AS (
SELECT SUM(ps.stake)::bigint AS total FROM pool_stat ps WHERE ps.epoch_no = (SELECT no FROM CurrentEpoch)
),
LatestExistingVotingAnchor AS (
SELECT
subquery.drep_registration_id,
Expand Down Expand Up @@ -192,18 +172,6 @@ TotalRegisteredDirectVoters AS (
LEFT JOIN HasNonDeregisterVotingAnchor hndva ON hndva.drep_hash_id = rdr.drep_hash_id
WHERE rdr.rn = 1 AND COALESCE(rdr.deposit, 0) >= 0 AND (leva.url IS NULL OR hndva.value = true)
),
AlwaysAbstainVotingPower 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
),
AlwaysNoConfidenceVotingPower 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
),
TotalDRepDistr AS (
SELECT SUM(COALESCE(amount, 0))::bigint total_drep_distr FROM drep_distr where epoch_no = (SELECT no from CurrentEpoch)
),
Expand All @@ -223,42 +191,28 @@ CommitteeThreshold AS (
OR (c.gov_action_proposal_id IS NULL)
)
SELECT
CurrentEpoch.no AS epoch_no,
CurrentBlock.block_no,
UniqueDelegators.count AS unique_delegators,
TotalDelegations.count AS total_delegations,
TotalGovActionProposals.count AS total_gov_action_proposals,
TotalDRepVotes.count AS total_drep_votes,
TotalRegisteredDReps.unique_registrations AS total_registered_dreps,
TotalDRepDistr.total_drep_distr,
COALESCE(TotalStakeControlledByActiveDReps.total, 0) + COALESCE(AlwaysNoConfidenceVotingPower.amount, 0) AS total_stake_controlled_by_active_dreps,
COALESCE(TotalStakeControlledBySPOs.total, 0) AS total_stake_controlled_by_spos,
TotalActiveDReps.unique_active_drep_registrations AS total_active_dreps,
TotalInactiveDReps.total_inactive_dreps AS total_inactive_dreps,
TotalActiveCIP119CompliantDReps.unique_active_cip119_compliant_drep_registrations AS total_active_cip119_compliant_dreps,
TotalRegisteredDirectVoters.unique_direct_voters AS total_registered_direct_voters,
AlwaysAbstainVotingPower.amount AS always_abstain_voting_power,
AlwaysNoConfidenceVotingPower.amount AS always_no_confidence_voting_power,
meta.network_name,
NoOfCommitteeMembers.total no_of_committee_members,
CommitteeThreshold.quorum_numerator,
CommitteeThreshold.quorum_denominator
FROM CurrentEpoch
CROSS JOIN CurrentBlock
CROSS JOIN UniqueDelegators
FROM UniqueDelegators
CROSS JOIN TotalDRepDistr
CROSS JOIN TotalDelegations
CROSS JOIN TotalGovActionProposals
CROSS JOIN TotalDRepVotes
CROSS JOIN TotalRegisteredDReps
CROSS JOIN TotalStakeControlledByActiveDReps
CROSS JOIN TotalStakeControlledBySPOs
CROSS JOIN TotalActiveDReps
CROSS JOIN TotalInactiveDReps
CROSS JOIN TotalActiveCIP119CompliantDReps
CROSS JOIN TotalRegisteredDirectVoters
CROSS JOIN AlwaysAbstainVotingPower
CROSS JOIN AlwaysNoConfidenceVotingPower
CROSS JOIN NoOfCommitteeMembers
CROSS JOIN CommitteeThreshold
CROSS JOIN meta;
93 changes: 93 additions & 0 deletions govtool/backend/sql/get-network-total-stake.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
WITH DRepActivity AS (
SELECT
drep_activity AS drep_activity,
epoch_no AS epoch_no
FROM
epoch_param
WHERE
epoch_no IS NOT NULL
ORDER BY
epoch_no DESC
LIMIT 1
),
LatestVotingProcedure AS (
SELECT
vp.*,
ROW_NUMBER() OVER (PARTITION BY drep_voter ORDER BY tx_id DESC) AS rn
FROM
voting_procedure vp
),
DRepDistr AS (
SELECT
drep_distr.*,
ROW_NUMBER() OVER (PARTITION BY drep_hash.id ORDER BY drep_distr.epoch_no DESC) AS rn
FROM
drep_distr
JOIN drep_hash ON drep_hash.id = drep_distr.hash_id
),
CurrentEpoch AS (
SELECT MAX(no) AS no FROM epoch
),
LatestVoteEpoch AS (
SELECT
block.epoch_no,
lvp.drep_voter AS drep_id
FROM
LatestVotingProcedure lvp
JOIN tx ON tx.id = lvp.tx_id
JOIN block ON block.id = tx.block_id
WHERE
lvp.rn = 1
),
RankedDRepRegistration AS (
SELECT
dr.id,
dr.drep_hash_id,
dr.deposit,
dr.voting_anchor_id,
ROW_NUMBER() OVER (PARTITION BY dr.drep_hash_id ORDER BY dr.tx_id DESC) AS rn,
encode(tx.hash, 'hex') AS tx_hash,
block.epoch_no
FROM
drep_registration dr
JOIN tx ON tx.id = dr.tx_id
JOIN block ON block.id = tx.block_id
),
TotalStakeControlledByActiveDReps AS (
SELECT
COALESCE(SUM(dd.amount), 0)::bigint AS total
FROM
drep_hash dh
LEFT JOIN DRepDistr dd ON dd.hash_id = dh.id AND dd.rn = 1
LEFT JOIN RankedDRepRegistration rd ON dd.hash_id = rd.drep_hash_id AND rd.rn = 1
LEFT JOIN LatestVoteEpoch lve ON lve.drep_id = dh.id
CROSS JOIN DRepActivity
WHERE
dd.epoch_no = (SELECT no FROM CurrentEpoch)
AND COALESCE(rd.deposit, 0) >= 0
AND ((DRepActivity.epoch_no - GREATEST(COALESCE(lve.epoch_no, 0), COALESCE(rd.epoch_no, 0))) <= DRepActivity.drep_activity)
),
TotalStakeControlledBySPOs AS (
SELECT SUM(ps.stake)::bigint AS total FROM pool_stat ps WHERE ps.epoch_no = (SELECT no FROM CurrentEpoch)
),
AlwaysAbstainVotingPower 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
),
AlwaysNoConfidenceVotingPower 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
)
SELECT
COALESCE(TotalStakeControlledByActiveDReps.total, 0) + COALESCE(AlwaysNoConfidenceVotingPower.amount, 0) AS total_stake_controlled_by_active_dreps,
COALESCE(TotalStakeControlledBySPOs.total, 0) AS total_stake_controlled_by_spos,
AlwaysAbstainVotingPower.amount AS always_abstain_voting_power,
AlwaysNoConfidenceVotingPower.amount AS always_no_confidence_voting_power
FROM TotalStakeControlledByActiveDReps
LEFT JOIN TotalStakeControlledBySPOs ON TRUE
LEFT JOIN AlwaysAbstainVotingPower ON TRUE
LEFT JOIN AlwaysNoConfidenceVotingPower ON TRUE
38 changes: 28 additions & 10 deletions govtool/backend/src/VVA/API.hs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ type VVAApi =
:<|> "transaction" :> "status" :> Capture "transactionId" HexText :> Get '[JSON] GetTransactionStatusResponse
:<|> "throw500" :> Get '[JSON] ()
:<|> "network" :> "metrics" :> Get '[JSON] GetNetworkMetricsResponse
:<|> "network" :> "info" :> Get '[JSON] GetNetworkInfoResponse
:<|> "network" :> "total-stake" :> Get '[JSON] GetNetworkTotalStakeResponse

server :: App m => ServerT VVAApi m
server = drepList
:<|> getVotingPower
Expand All @@ -92,7 +95,8 @@ server = drepList
:<|> getTransactionStatus
:<|> throw500
:<|> getNetworkMetrics

:<|> getNetworkInfo
:<|> getNetworkTotalStake

mapDRepType :: Types.DRepType -> DRepType
mapDRepType Types.DRep = NormalDRep
Expand Down Expand Up @@ -428,29 +432,43 @@ getTransactionStatus (unHexText -> transactionId) = do
throw500 :: App m => m ()
throw500 = throwError $ CriticalError "intentional system break for testing purposes"

getNetworkInfo :: App m => m GetNetworkInfoResponse
getNetworkInfo = do
CacheEnv {networkInfoCache} <- asks vvaCache
Types.NetworkInfo {..} <- Network.networkInfo
return $ GetNetworkInfoResponse
{ getNetworkInfoResponseCurrentTime = networkInfoCurrentTime
, getNetworkInfoResponseEpochNo = networkInfoEpochNo
, getNetworkInfoResponseBlockNo = networkInfoBlockNo
, getNetworkInfoResponseNetworkName = networkInfoNetworkName
}

getNetworkTotalStake :: App m => m GetNetworkTotalStakeResponse
getNetworkTotalStake = do
CacheEnv {networkTotalStakeCache} <- asks vvaCache
Types.NetworkTotalStake {..} <- Network.networkTotalStake
return $ GetNetworkTotalStakeResponse
{ getNetworkTotalStakeResponseTotalStakeControlledByDReps = networkTotalStakeControlledByDReps
, getNetworkTotalStakeResponseTotalStakeControlledBySPOs = networkTotalStakeControlledBySPOs
, getNetworkTotalStakeResponseAlwaysAbstainVotingPower = networkTotalAlwaysAbstainVotingPower
, getNetworkTotalStakeResponseAlwaysNoConfidenceVotingPower = networkTotalAlwaysNoConfidenceVotingPower
}

getNetworkMetrics :: App m => m GetNetworkMetricsResponse
getNetworkMetrics = do
CacheEnv {networkMetricsCache} <- asks vvaCache
Types.NetworkMetrics {..} <- Network.networkMetrics
return $ GetNetworkMetricsResponse
{ getNetworkMetricsResponseCurrentTime = networkMetricsCurrentTime
, getNetworkMetricsResponseCurrentEpoch = networkMetricsCurrentEpoch
, getNetworkMetricsResponseCurrentBlock = networkMetricsCurrentBlock
, getNetworkMetricsResponseUniqueDelegators = networkMetricsUniqueDelegators
{ getNetworkMetricsResponseUniqueDelegators = networkMetricsUniqueDelegators
, getNetworkMetricsResponseTotalDelegations = networkMetricsTotalDelegations
, getNetworkMetricsResponseTotalGovernanceActions = networkMetricsTotalGovernanceActions
, getNetworkMetricsResponseTotalDRepVotes = networkMetricsTotalDRepVotes
, getNetworkMetricsResponseTotalRegisteredDReps = networkMetricsTotalRegisteredDReps
, getNetworkMetricsResponseTotalDRepDistr = networkMetricsTotalDRepDistr
, getNetworkMetricsResponseTotalStakeControlledByDReps = networkMetricsTotalStakeControlledByDReps
, getNetworkMetricsResponseTotalStakeControlledBySPOs = networkMetricsTotalStakeControlledBySPOs
, getNetworkMetricsResponseTotalActiveDReps = networkMetricsTotalActiveDReps
, getNetworkMetricsResponseTotalInactiveDReps = networkMetricsTotalInactiveDReps
, getNetworkMetricsResponseTotalActiveCIP119CompliantDReps = networkMetricsTotalActiveCIP119CompliantDReps
, getNetworkMetricsResponseTotalRegisteredDirectVoters = networkMetricsTotalRegisteredDirectVoters
, getNetworkMetricsResponseAlwaysAbstainVotingPower = networkMetricsAlwaysAbstainVotingPower
, getNetworkMetricsResponseAlwaysNoConfidenceVotingPower = networkMetricsAlwaysNoConfidenceVotingPower
, getNetworkMetricsResponseNetworkName = networkMetricsNetworkName
, getNetworkMetricsResponseNoOfCommitteeMembers = networkMetricsNoOfCommitteeMembers
, getNetworkMetricsResponseQuorumNumerator = networkMetricsQuorumNumerator
, getNetworkMetricsResponseQuorumDenominator = networkMetricsQuorumDenominator
Expand Down
Loading