diff --git a/.github/scripts/set_commit_status.sh b/.github/scripts/set_commit_status.sh
new file mode 100644
index 000000000..01a822304
--- /dev/null
+++ b/.github/scripts/set_commit_status.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+
+# Ensure required environment variables are set
+if [ -z "$GITHUB_REPOSITORY" ] || [ -z "$GITHUB_SHA" ] || [ -z "$GITHUB_TOKEN" ] || [ -z "$GITHUB_RUN_ID" ]; then
+ echo "Missing required environment variables!"
+ exit 1
+fi
+
+# Retrieve necessary variables from workflow
+START_TIME=${START_TIME:-$(date +%s)}
+TEST_STATUS=${TEST_STATUS:-"failure"}
+REPORT_NUMBER=${REPORT_NUMBER:-1}
+REPORT_NAME=${REPORT_NAME:-"govtool-frontend"}
+HOST_URL=${HOST_URL:-"https://govtool.cardanoapi.io"}
+CONTEXT="Playwright Tests : $HOST_URL"
+
+if [[ "$REPORT_NAME" == "govtool-backend" ]]; then
+ CONTEXT="Backend Tests : $BASE_URL"
+fi
+
+# Parse Allure JSON results
+if [ -z "$(ls -A allure-results/*.json 2>/dev/null)" ]; then
+ echo "No Allure JSON results found!"
+ PASSED=0
+ FAILED=0
+ TOTAL=0
+else
+ PASSED=$(jq -s '[.[] | select(.status == "passed")] | length' allure-results/*.json)
+ FAILED=$(jq -s '[.[] | select(.status == "failed")] | length' allure-results/*.json)
+ TOTAL=$((PASSED + FAILED))
+fi
+
+
+
+# Calculate test duration
+CURRENT_TIME=$(date +%s)
+TEST_DURATION_SECONDS=$((CURRENT_TIME - START_TIME))
+TEST_DURATION_MINUTES=$((TEST_DURATION_SECONDS / 60))
+TEST_DURATION_HOURS=$((TEST_DURATION_MINUTES / 60))
+
+if [ "$TEST_DURATION_HOURS" -gt 0 ]; then
+ TEST_DURATION="${TEST_DURATION_HOURS} hour$( [ "$TEST_DURATION_HOURS" -ne 1 ] && echo "s"), $((TEST_DURATION_MINUTES % 60)) minute$( [ "$((TEST_DURATION_MINUTES % 60))" -ne 1 ] && echo "s"), and $((TEST_DURATION_SECONDS % 60)) second$( [ "$((TEST_DURATION_SECONDS % 60))" -ne 1 ] && echo "s")"
+elif [ "$TEST_DURATION_MINUTES" -gt 0 ]; then
+ TEST_DURATION="${TEST_DURATION_MINUTES} minute$( [ "$TEST_DURATION_MINUTES" -ne 1 ] && echo "s") and $((TEST_DURATION_SECONDS % 60)) second$( [ "$((TEST_DURATION_SECONDS % 60))" -ne 1 ] && echo "s")"
+else
+ TEST_DURATION="${TEST_DURATION_SECONDS} second$( [ "$TEST_DURATION_SECONDS" -ne 1 ] && echo "s")"
+fi
+
+# Determine target URL based on environment
+case "$GH_PAGES" in
+ "IntersectMBO/govtool-test-reports") TARGET_URL="https://intersectmbo.github.io/govtool-test-reports/${REPORT_NAME}/${REPORT_NUMBER}" ;;
+ "cardanoapi/govtool-test-reports") TARGET_URL="https://cardanoapi.github.io/govtool-test-reports/${REPORT_NAME}/${REPORT_NUMBER}" ;;
+ *) TARGET_URL="https://intersectmbo.github.io/govtool-test-reports/${REPORT_NAME}/${REPORT_NUMBER}" ;;
+esac
+
+# Determine test result message
+if [[ "$TEST_STATUS" == "success" ]]; then
+ DESCRIPTION="Tests passed in ${TEST_DURATION}"
+elif [[ "$TEST_STATUS" == "failure" && "$TOTAL" -ne 0 ]]; then
+ DESCRIPTION="Tests failed in ${TEST_DURATION}: Passed ${PASSED}, Failed ${FAILED} out of ${TOTAL}"
+else
+ DESCRIPTION="⚠️ Tests execution failed :$TEST_STATUS"
+ TEST_STATUS="error"
+ TARGET_URL="https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
+fi
+
+
+
+# Send commit status update to GitHub
+curl -X POST -H "Authorization: Bearer ${GITHUB_TOKEN}" \
+ -H "Accept: application/vnd.github+json" \
+ https://api.github.com/repos/${GITHUB_REPOSITORY}/statuses/${GITHUB_SHA} \
+ -d "{\"state\": \"${TEST_STATUS}\", \"context\": \"${CONTEXT}\", \"description\": \"${DESCRIPTION}\", \"target_url\": \"${TARGET_URL}\"}"
+
+echo "Commit status updated successfully!"
diff --git a/.github/workflows/test_backend.yml b/.github/workflows/test_backend.yml
index 22ccffaa0..59488d061 100644
--- a/.github/workflows/test_backend.yml
+++ b/.github/workflows/test_backend.yml
@@ -1,5 +1,10 @@
name: Backend Test
+permissions:
+ contents: read
+ checks: write
+ statuses: write
+
on:
workflow_dispatch:
inputs:
@@ -27,14 +32,31 @@ on:
workflows: ["Build and deploy GovTool test stack"]
types: [completed]
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: false
+
jobs:
backend-tests:
runs-on: ubuntu-latest
if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
+ outputs:
+ start_time: ${{ steps.set-pending-status.outputs.timestamp }}
+ status: ${{ steps.run-tests.outcome }}
steps:
- name: Checkout code
uses: actions/checkout@v4
+ - name: Set pending commit status
+ id: set-pending-status
+ run: |
+ echo "timestamp=$(date +%s)" >> $GITHUB_OUTPUT
+ curl -X POST -H "Authorization: Bearer ${{ github.token }}" \
+ -H "Accept: application/vnd.github+json" \
+ https://api.github.com/repos/${{ github.repository }}/statuses/${{ github.sha }} \
+ -d "{\"state\": \"pending\", \"context\": \"Backend Tests : ${{env.BASE_URL}}\", \"target_url\": \"https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\"}"
+
+
- name: Set up Python
uses: actions/setup-python@v4
with:
@@ -43,6 +65,7 @@ jobs:
- name: Run Backend Test
working-directory: tests/govtool-backend
+ id: run-tests
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
@@ -55,26 +78,27 @@ jobs:
fi
python ./setup.py
python -m pytest --alluredir allure-results
- env:
- BASE_URL: https://${{inputs.deployment || 'govtool.cardanoapi.io/api' }}
- NETWORK: ${{ inputs.network || vars.NETWORK }}
- KUBER_API_KEY: ${{ secrets.KUBER_API_KEY }}
- name: Upload report
if: always()
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: allure-results
path: tests/govtool-backend/allure-results
+ env:
+ NETWORK: ${{ inputs.network || vars.NETWORK }}
+ KUBER_API_KEY: ${{ secrets.KUBER_API_KEY }}
publish-report:
runs-on: ubuntu-latest
if: always() && needs.backend-tests.result != 'skipped'
needs: backend-tests
+ outputs:
+ report_number: ${{ steps.report-details.outputs.report_number }}
steps:
- uses: actions/checkout@v4
- name: Download results
- uses: actions/download-artifact@v3
+ uses: actions/download-artifact@v4
with:
name: allure-results
path: allure-results
@@ -134,6 +158,29 @@ jobs:
folder: build
target-folder: ${{ env.REPORT_NAME }}
- env:
- REPORT_NAME: govtool-backend
- GH_PAGES: ${{vars.GH_PAGES}}
+ publish-status:
+ runs-on: ubuntu-latest
+ if: always()
+ needs: [backend-tests, publish-report]
+ steps:
+ - uses: actions/checkout@v4
+ - name: Download results
+ uses: actions/download-artifact@v4
+ with:
+ name: allure-results
+ path: allure-results
+ - name: Set Commit Status
+ if: always()
+ run: |
+ chmod +x .github/scripts/set_commit_status.sh
+ .github/scripts/set_commit_status.sh
+ env:
+ START_TIME: ${{ needs.backend-tests.outputs.start_time }}
+ TEST_STATUS: ${{ needs.backend-tests.outputs.status }}
+ REPORT_NUMBER: ${{ needs.publish-report.outputs.report_number }}
+ GITHUB_TOKEN: ${{ github.token }}
+
+env:
+ BASE_URL: https://${{inputs.deployment || 'govtool.cardanoapi.io/api' }}
+ REPORT_NAME: govtool-backend
+ GH_PAGES: ${{vars.GH_PAGES}}
diff --git a/.github/workflows/test_integration_playwright.yml b/.github/workflows/test_integration_playwright.yml
index b00cee48f..b3c1591db 100644
--- a/.github/workflows/test_integration_playwright.yml
+++ b/.github/workflows/test_integration_playwright.yml
@@ -1,5 +1,10 @@
name: Integration Test [Playwright]
+permissions:
+ contents: read
+ checks: write
+ statuses: write
+
on:
workflow_dispatch:
inputs:
@@ -26,16 +31,32 @@ on:
workflow_run:
workflows: ["Build and deploy GovTool test stack"]
types: [completed]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: false
jobs:
integration-tests:
runs-on: ubuntu-latest
if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
+ outputs:
+ start_time: ${{ steps.set-pending-status.outputs.timestamp }}
+ status: ${{ steps.run-test.outcome }}
defaults:
run:
working-directory: tests/govtool-frontend/playwright
steps:
- uses: actions/checkout@v4
+ - name: Set pending commit status
+ id: set-pending-status
+ run: |
+ echo "timestamp=$(date +%s)" >> $GITHUB_OUTPUT
+ curl -X POST -H "Authorization: Bearer ${{ github.token }}" \
+ -H "Accept: application/vnd.github+json" \
+ https://api.github.com/repos/${{ github.repository }}/statuses/${{ github.sha }} \
+ -d "{\"state\": \"pending\", \"context\": \"Playwright Tests : ${{env.HOST_URL}}\", \"target_url\": \"https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\"}"
+
- uses: actions/setup-node@v4
with:
node-version: "18"
@@ -58,6 +79,7 @@ jobs:
run: npx playwright install --with-deps
- name: Run tests
+ id: run-test
run: |
mkdir -p ./lib/_mock
chmod +w ./lib/_mock
@@ -81,21 +103,20 @@ jobs:
npm test
- name: Upload report
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
if: always()
with:
name: allure-results
path: tests/govtool-frontend/playwright/allure-results
- name: Upload lock logs
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
if: always()
with:
name: lock-logs
path: tests/govtool-frontend/playwright/lock_logs.txt
env:
- HOST_URL: https://${{inputs.deployment || 'govtool.cardanoapi.io' }}
API_URL: https://${{inputs.deployment || 'govtool.cardanoapi.io' }}/api
DOCS_URL: ${{ vars.DOCS_URL }}
KUBER_API_KEY: ${{secrets.KUBER_API_KEY}}
@@ -111,10 +132,12 @@ jobs:
runs-on: ubuntu-latest
if: always() && needs.integration-tests.result != 'skipped'
needs: integration-tests
+ outputs:
+ report_number: ${{ steps.report-details.outputs.report_number }}
steps:
- uses: actions/checkout@v4
- name: Download report
- uses: actions/download-artifact@v3
+ uses: actions/download-artifact@v4
with:
name: allure-results
path: allure-results
@@ -175,6 +198,28 @@ jobs:
folder: build
target-folder: ${{ env.REPORT_NAME }}
- env:
- REPORT_NAME: govtool-frontend
- GH_PAGES: ${{vars.GH_PAGES}}
+ publish-status:
+ runs-on: ubuntu-latest
+ if: always()
+ needs: [integration-tests, publish-report]
+ steps:
+ - uses: actions/checkout@v4
+ - name: Download results
+ uses: actions/download-artifact@v4
+ with:
+ name: allure-results
+ path: allure-results
+ - name: Set Commit Status
+ if: always()
+ run: |
+ chmod +x .github/scripts/set_commit_status.sh
+ .github/scripts/set_commit_status.sh
+ env:
+ START_TIME: ${{ needs.integration-tests.outputs.start_time }}
+ TEST_STATUS: ${{ needs.integration-tests.outputs.status }}
+ REPORT_NUMBER: ${{ needs.publish-report.outputs.report_number }}
+ GITHUB_TOKEN: ${{ github.token }}
+env:
+ HOST_URL: https://${{inputs.deployment || 'govtool.cardanoapi.io' }}
+ REPORT_NAME: govtool-frontend
+ GH_PAGES: ${{vars.GH_PAGES}}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 36fae25f9..868a18f7c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,19 +12,22 @@ changes.
### Added
--
+- Add metadata url and hash to drep details [Issue 2911](https://github.com/IntersectMBO/govtool/issues/2911)
### Fixed
--
+- Fix calculating votes counting for governance actions
+- Fix crashing backend on unhandled missing proposal from vote [Issue 2920](https://github.com/IntersectMBO/govtool/issues/2920)
+- Remove abstain votes (not auto abstain) from total DRep stake
### Changed
- Change threshold visual representation in governance action votes
+- Resize governance action details columns
### Removed
--
+- Remove abstain from total DRep votes calculation
## [v2.0.11](https://github.com/IntersectMBO/govtool/releases/tag/v2.0.11) 2025-02-04
diff --git a/govtool/backend/sql/get-network-metrics.sql b/govtool/backend/sql/get-network-metrics.sql
index 17404faa7..ba668900f 100644
--- a/govtool/backend/sql/get-network-metrics.sql
+++ b/govtool/backend/sql/get-network-metrics.sql
@@ -10,222 +10,215 @@ WITH DRepActivity AS (
epoch_no DESC
LIMIT 1
),
-active_drep_boundary_epoch AS (
- SELECT
- epoch_no - drep_activity AS epoch_no
- FROM
- DRepActivity
-),
-RankedDRep AS (
+DRepDistr AS (
SELECT
- dh.raw AS drep_hash_raw,
- b.epoch_no,
- dr.deposit,
- dr.voting_anchor_id,
- ROW_NUMBER() OVER (PARTITION BY dh.raw ORDER BY dr.tx_id DESC) AS rank
+ drep_distr.*,
+ ROW_NUMBER() OVER (PARTITION BY drep_hash.id ORDER BY drep_distr.epoch_no DESC) AS rn
FROM
- drep_hash dh
- JOIN
- drep_registration dr ON dh.id = dr.drep_hash_id
- JOIN
- tx t ON dr.tx_id = t.id
- JOIN
- block b ON t.block_id = b.id
- WHERE
- dr.deposit >= 0
- GROUP BY
- dh.raw,
- b.epoch_no,
- dr.voting_anchor_id,
- dr.deposit,
- dr.tx_id
+ drep_distr
+ JOIN drep_hash ON drep_hash.id = drep_distr.hash_id
),
-current_epoch AS (
- SELECT
- Max(NO) AS no
- FROM
- epoch
+CurrentEpoch AS (
+ SELECT MAX(no) AS no FROM epoch
),
-current_block AS (
- SELECT
- Max(block_no) AS block_no
- FROM
- block
+ActiveDRepBoundaryEpoch AS (
+ SELECT epoch_no - drep_activity AS epoch_no FROM DRepActivity
),
-unique_delegators AS (
+LatestVotingProcedure AS (
SELECT
- count(DISTINCT (addr_id)) AS count
+ vp.*,
+ ROW_NUMBER() OVER (PARTITION BY drep_voter ORDER BY tx_id DESC) AS rn
FROM
- delegation_vote
+ voting_procedure vp
),
-total_delegations AS (
+LatestVoteEpoch AS (
SELECT
- count(*) AS count
+ block.epoch_no,
+ lvp.drep_voter AS drep_id
FROM
- delegation_vote
+ LatestVotingProcedure lvp
+ JOIN tx ON tx.id = lvp.tx_id
+ JOIN block ON block.id = tx.block_id
+ WHERE
+ lvp.rn = 1
),
-total_gov_action_proposals AS (
+RankedDRepRegistration AS (
SELECT
- count(DISTINCT (tx_id, INDEX)) AS count
+ 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
- gov_action_proposal
+ drep_registration dr
+ JOIN tx ON tx.id = dr.tx_id
+ JOIN block ON block.id = tx.block_id
+),
+TotalRegisteredDReps AS (
+ SELECT COUNT(DISTINCT dh.raw) AS unique_registrations
+ FROM drep_registration dr
+ JOIN drep_hash dh ON dr.drep_hash_id = dh.id
+ WHERE dr.deposit > 0
+),
+TotalActiveDReps AS (
+ SELECT COUNT(DISTINCT RankedDRepRegistration.drep_hash_id) AS unique_active_drep_registrations
+ FROM RankedDRepRegistration
+ LEFT JOIN LatestVoteEpoch lve ON lve.drep_id = RankedDRepRegistration.drep_hash_id
+ WHERE
+ (RankedDRepRegistration.epoch_no >= (SELECT epoch_no FROM ActiveDRepBoundaryEpoch))
+ OR (lve.epoch_no >= (SELECT epoch_no FROM ActiveDRepBoundaryEpoch))
),
-total_drep_votes AS (
+TotalInactiveDReps AS (
SELECT
- count(*) AS count
- FROM
- voting_procedure
- WHERE
- voter_role = 'DRep'
-),
-total_stake_controlled_by_dreps AS (
+ TotalRegisteredDReps.unique_registrations - TotalActiveDReps.unique_active_drep_registrations AS total_inactive_dreps
+ FROM TotalRegisteredDReps
+ CROSS JOIN TotalActiveDReps
+),
+TotalActiveCIP119CompliantDReps AS (
+ SELECT COUNT(DISTINCT RankedDRepRegistration.drep_hash_id) AS unique_active_cip119_compliant_drep_registrations
+ FROM RankedDRepRegistration
+ JOIN voting_anchor va ON va.id = RankedDRepRegistration.voting_anchor_id
+ JOIN off_chain_vote_data ocvd ON ocvd.voting_anchor_id = va.id
+ JOIN off_chain_vote_drep_data ocvdd ON ocvdd.off_chain_vote_data_id = ocvd.id
+ WHERE ocvdd.given_name IS NOT NULL
+ AND (RankedDRepRegistration.epoch_no >= (SELECT epoch_no FROM ActiveDRepBoundaryEpoch)
+ OR (EXISTS (
+ SELECT 1 FROM LatestVoteEpoch lve
+ WHERE lve.drep_id = RankedDRepRegistration.drep_hash_id
+ AND lve.epoch_no >= (SELECT epoch_no FROM ActiveDRepBoundaryEpoch)
+ )))
+),
+TotalStakeControlledByActiveDReps AS (
SELECT
- SUM(dd.amount)::bigint AS total
+ COALESCE(SUM(dd.amount), 0)::bigint AS total
FROM
- drep_distr dd
+ 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 current_epoch)
+ 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)
),
-total_stake_controlled_by_spos AS (
- SELECT
- SUM(ps.stake)::bigint AS total
- FROM
- pool_stat ps
- WHERE
- ps.epoch_no = (SELECT no FROM current_epoch)
+CurrentBlock AS (
+ SELECT MAX(block_no) AS block_no FROM block
),
-total_registered_direct_voters AS (
- SELECT
- COUNT(DISTINCT dh.raw) AS unique_direct_voters
- FROM
- drep_registration dr
- JOIN
- drep_hash dh
- ON
- dr.drep_hash_id = dh.id
- LEFT JOIN
- voting_anchor va
- ON
- dr.voting_anchor_id = va.id
- WHERE
- dr.deposit > 0
- AND va.url IS NULL
+UniqueDelegators AS (
+ SELECT COUNT(DISTINCT addr_id) AS count FROM delegation_vote
),
-total_registered_dreps AS (
- SELECT
- count(DISTINCT dh.raw) AS unique_registrations
- FROM
- drep_registration dr
- JOIN
- drep_hash dh
- ON
- dr.drep_hash_id = dh.id
- WHERE
- dr.deposit > 0
+TotalDelegations AS (
+ SELECT COUNT(*) AS count FROM delegation_vote
+),
+TotalGovActionProposals AS (
+ SELECT COUNT(DISTINCT (tx_id, INDEX)) AS count FROM gov_action_proposal
),
-total_active_dreps 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
- count(DISTINCT drep_hash_raw) AS unique_active_drep_registrations
- FROM
- RankedDRep
+ 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
- epoch_no >= (SELECT epoch_no FROM active_drep_boundary_epoch)
- AND rank = 1
+ subquery.rn = 1
),
-total_inactive_dreps AS (
+HasNonDeregisterVotingAnchor AS (
SELECT
- total_registered_dreps.unique_registrations - total_active_dreps.unique_active_drep_registrations AS total_inactive_dreps
+ dr.drep_hash_id,
+ EXISTS (
+ SELECT 1
+ FROM drep_registration dr_sub
+ WHERE
+ dr_sub.drep_hash_id = dr.drep_hash_id
+ AND dr_sub.voting_anchor_id IS NULL
+ AND COALESCE(dr_sub.deposit, 0) >= 0
+ ) AS value
FROM
- total_registered_dreps
- CROSS JOIN
- total_active_dreps
+ drep_registration dr
+ GROUP BY
+ dr.drep_hash_id
),
-total_active_cip119_compliant_dreps AS (
- SELECT
- count(DISTINCT drep_hash_raw) AS unique_active_cip119_compliant_drep_registrations
- FROM
- RankedDRep
- JOIN
- voting_anchor va on va.id = RankedDRep.voting_anchor_id
- JOIN off_chain_vote_data ocvd on ocvd.voting_anchor_id = va.id
- JOIN off_chain_vote_drep_data ocvdd on ocvdd.off_chain_vote_data_id = ocvd.id
- WHERE
- -- given_name is the only compulsory field in CIP-119
- ocvdd.given_name IS NOT NULL
- AND
- epoch_no >= (SELECT epoch_no FROM active_drep_boundary_epoch)
- AND
- rank = 1
-),
-always_abstain_voting_power AS (
- SELECT
- coalesce((
- SELECT
- amount
- FROM drep_hash
+TotalRegisteredDirectVoters AS (
+ SELECT COUNT(DISTINCT rdr.drep_hash_id) AS unique_direct_voters
+ FROM RankedDRepRegistration rdr
+ LEFT JOIN LatestExistingVotingAnchor leva ON leva.drep_hash_id = rdr.drep_hash_id
+ 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
+ WHERE drep_hash.view = 'drep_always_abstain'
+ ORDER BY epoch_no DESC LIMIT 1), 0) AS amount
),
-always_no_confidence_voting_power AS (
- SELECT
- coalesce((
- SELECT
- amount
- FROM drep_hash
+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
+ 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)
)
SELECT
- current_epoch.no as epoch_no,
- current_block.block_no,
- unique_delegators.count as unique_delegators,
- total_delegations.count as total_delegations,
- total_gov_action_proposals.count as total_gov_action_proposals,
- total_drep_votes.count as total_drep_votes,
- total_registered_dreps.unique_registrations as total_registered_dreps,
- COALESCE(total_stake_controlled_by_dreps.total, 0) as total_stake_controlled_by_dreps,
- COALESCE(total_stake_controlled_by_spos.total, 0) as total_stake_controlled_by_spos,
- total_active_dreps.unique_active_drep_registrations as total_active_dreps,
- total_inactive_dreps.total_inactive_dreps as total_inactive_dreps,
- total_active_cip119_compliant_dreps.unique_active_cip119_compliant_drep_registrations as total_active_cip119_compliant_dreps,
- total_registered_direct_voters.unique_direct_voters as total_registered_direct_voters,
- always_abstain_voting_power.amount as always_abstain_voting_power,
- always_no_confidence_voting_power.amount as always_no_confidence_voting_power,
- network_name
-FROM
- current_epoch
- CROSS JOIN current_block
- CROSS JOIN unique_delegators
- CROSS JOIN total_delegations
- CROSS JOIN total_gov_action_proposals
- CROSS JOIN total_drep_votes
- CROSS JOIN total_registered_dreps
- CROSS JOIN total_stake_controlled_by_dreps
- CROSS JOIN total_stake_controlled_by_spos
- CROSS JOIN total_active_dreps
- CROSS JOIN total_inactive_dreps
- CROSS JOIN total_active_cip119_compliant_dreps
- CROSS JOIN total_registered_direct_voters
- CROSS JOIN always_abstain_voting_power
- CROSS JOIN always_no_confidence_voting_power
- CROSS JOIN meta
-GROUP BY
- current_epoch.no,
- current_block.block_no,
- unique_delegators.count,
- total_delegations.count,
- total_gov_action_proposals.count,
- total_drep_votes.count,
- total_registered_dreps.unique_registrations,
- total_stake_controlled_by_dreps.total,
- total_stake_controlled_by_spos.total,
- total_active_dreps.unique_active_drep_registrations,
- total_inactive_dreps.total_inactive_dreps,
- total_active_cip119_compliant_dreps.unique_active_cip119_compliant_drep_registrations,
- total_registered_direct_voters.unique_direct_voters,
- always_abstain_voting_power.amount,
- always_no_confidence_voting_power.amount,
- network_name;
-
+ 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
+FROM CurrentEpoch
+CROSS JOIN CurrentBlock
+CROSS JOIN 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 meta;
diff --git a/govtool/backend/sql/list-proposals.sql b/govtool/backend/sql/list-proposals.sql
index ad66a5c7e..cedc4e86d 100644
--- a/govtool/backend/sql/list-proposals.sql
+++ b/govtool/backend/sql/list-proposals.sql
@@ -100,24 +100,38 @@ RankedPoolVotes AS (
voting_procedure vp
),
PoolVotes AS (
- SELECT
- rpv.gov_action_proposal_id,
- ps.epoch_no,
- COUNT(DISTINCT CASE WHEN vote = 'Yes' THEN rpv.pool_voter ELSE 0 END) AS total_unique_votes,
- COUNT(DISTINCT CASE WHEN vote = 'No' THEN rpv.pool_voter ELSE 0 END) AS total_unique_votes,
- COUNT(DISTINCT CASE WHEN vote = 'Abstain' THEN rpv.pool_voter ELSE 0 END) AS total_unique_votes,
- SUM(CASE WHEN rpv.vote = 'Yes' THEN ps.voting_power ELSE 0 END) AS poolYesVotes,
- SUM(CASE WHEN rpv.vote = 'No' THEN ps.voting_power ELSE 0 END) AS poolNoVotes,
- SUM(CASE WHEN rpv.vote = 'Abstain' THEN ps.voting_power ELSE 0 END) AS poolAbstainVotes
- FROM
- RankedPoolVotes rpv
- JOIN
- pool_stat ps
- ON rpv.pool_voter = ps.pool_hash_id
- WHERE
- rpv.rn = 1 AND ps.epoch_no = (SELECT MAX(no) FROM epoch)
- GROUP BY
- rpv.gov_action_proposal_id, ps.epoch_no
+ SELECT
+ rpv.gov_action_proposal_id,
+ ps.epoch_no,
+ COUNT(DISTINCT CASE WHEN vote = 'Yes' THEN rpv.pool_voter ELSE 0 END) AS total_unique_votes,
+ COUNT(DISTINCT CASE WHEN vote = 'No' THEN rpv.pool_voter ELSE 0 END) AS total_unique_votes,
+ COUNT(DISTINCT CASE WHEN vote = 'Abstain' THEN rpv.pool_voter ELSE 0 END) AS total_unique_votes,
+ SUM(CASE WHEN rpv.vote = 'Yes' THEN ps.voting_power ELSE 0 END) AS poolYesVotes,
+ SUM(CASE WHEN rpv.vote = 'No' THEN ps.voting_power ELSE 0 END) AS poolNoVotes,
+ SUM(CASE WHEN rpv.vote = 'Abstain' THEN ps.voting_power ELSE 0 END) AS poolAbstainVotes
+ FROM
+ RankedPoolVotes rpv
+ JOIN
+ pool_stat ps
+ ON rpv.pool_voter = ps.pool_hash_id
+ WHERE
+ rpv.rn = 1 AND ps.epoch_no = (SELECT MAX(no) FROM epoch)
+ GROUP BY
+ rpv.gov_action_proposal_id, ps.epoch_no
+),
+RankedDRepVotes AS (
+ SELECT
+ *,
+ ROW_NUMBER() OVER (PARTITION BY vp.drep_voter ORDER BY vp.tx_id DESC) AS rn
+ FROM
+ voting_procedure vp
+),
+RankedDRepRegistration AS (
+ SELECT
+ *,
+ ROW_NUMBER() OVER (PARTITION BY dr.drep_hash_id ORDER BY dr.tx_id DESC) AS rn
+ FROM
+ drep_registration dr
),
CommitteeVotes AS (
SELECT
@@ -225,19 +239,19 @@ SELECT
off_chain_vote_gov_action_data.abstract,
off_chain_vote_gov_action_data.motivation,
off_chain_vote_gov_action_data.rationale,
- COALESCE(SUM(ldd_drep.amount) FILTER (WHERE voting_procedure.vote::text = 'Yes'), 0) yes_votes,
- COALESCE(SUM(ldd_drep.amount) FILTER (WHERE voting_procedure.vote::text = 'No'), 0) + (
- CASE WHEN gov_action_proposal.type = 'NoConfidence' OR gov_action_proposal.type = 'HardForkInitiation' THEN
+ COALESCE(SUM(ldd_drep.amount) FILTER (WHERE rdv.vote::text = 'Yes'), 0) + (
+ CASE WHEN gov_action_proposal.type = 'NoConfidence' THEN
+ drep_voting_power.no_confidence
+ ELSE
+ 0
+ END) yes_votes,
+ COALESCE(SUM(ldd_drep.amount) FILTER (WHERE rdv.vote::text = 'No'), 0) + (
+ CASE WHEN gov_action_proposal.type = 'NoConfidence' THEN
0
ELSE
drep_voting_power.no_confidence
END) no_votes,
- COALESCE(SUM(ldd_drep.amount) FILTER (WHERE voting_procedure.vote::text = 'Abstain'), 0) + (
- CASE WHEN gov_action_proposal.type = 'NoConfidence' OR gov_action_proposal.type = 'HardForkInitiation' THEN
- 0
- ELSE
- drep_voting_power.abstain
- END) abstain_votes,
+ COALESCE(SUM(ldd_drep.amount) FILTER (WHERE rdv.vote::text = 'Abstain'), 0) abstain_votes,
COALESCE(ps.poolYesVotes, 0) pool_yes_votes,
COALESCE(ps.poolNoVotes, 0) pool_no_votes,
COALESCE(ps.poolAbstainVotes, 0) pool_abstain_votes,
@@ -260,8 +274,9 @@ FROM
LEFT JOIN cost_model AS cost_model ON proposal_params.cost_model_id = cost_model.id
LEFT JOIN PoolVotes ps ON gov_action_proposal.id = ps.gov_action_proposal_id
LEFT JOIN CommitteeVotes cv ON gov_action_proposal.id = cv.gov_action_proposal_id
- LEFT JOIN voting_procedure ON voting_procedure.gov_action_proposal_id = gov_action_proposal.id
- LEFT JOIN LatestDrepDistr ldd_drep ON ldd_drep.hash_id = voting_procedure.drep_voter
+ LEFT JOIN RankedDRepVotes rdv ON rdv.gov_action_proposal_id = gov_action_proposal.id AND rdv.rn = 1
+ LEFT JOIN RankedDRepRegistration rdr ON rdr.drep_hash_id = rdv.drep_voter AND COALESCE(rdr.deposit, 0) >= 0 AND rdr.rn = 1
+ LEFT JOIN LatestDrepDistr ldd_drep ON ldd_drep.hash_id = rdr.drep_hash_id
AND ldd_drep.epoch_no = latest_epoch.no
LEFT JOIN gov_action_proposal AS prev_gov_action ON gov_action_proposal.prev_gov_action_proposal = prev_gov_action.id
LEFT JOIN tx AS prev_gov_action_tx ON prev_gov_action.tx_id = prev_gov_action_tx.id
diff --git a/govtool/backend/src/VVA/API.hs b/govtool/backend/src/VVA/API.hs
index 89b37cc3c..5424b32e7 100644
--- a/govtool/backend/src/VVA/API.hs
+++ b/govtool/backend/src/VVA/API.hs
@@ -278,14 +278,19 @@ getVotes :: App m => HexText -> [GovernanceActionType] -> Maybe GovernanceAction
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
+
return $
[ VoteResponse
- { voteResponseVote = voteToResponse (voteMap Map.! read (unpack proposalResponseId))
+ { voteResponseVote = voteToResponse vote
, voteResponseProposal = proposalResponse
}
| proposalResponse@ProposalResponse{proposalResponseId} <- processedProposals
+ , let proposalIdInt = read (unpack proposalResponseId) :: Int
+ , Just vote <- [Map.lookup (toInteger proposalIdInt) voteMap]
]
drepInfo :: App m => HexText -> m DRepInfoResponse
@@ -436,6 +441,7 @@ getNetworkMetrics = do
, getNetworkMetricsResponseTotalGovernanceActions = networkMetricsTotalGovernanceActions
, getNetworkMetricsResponseTotalDRepVotes = networkMetricsTotalDRepVotes
, getNetworkMetricsResponseTotalRegisteredDReps = networkMetricsTotalRegisteredDReps
+ , getNetworkMetricsResponseTotalDRepDistr = networkMetricsTotalDRepDistr
, getNetworkMetricsResponseTotalStakeControlledByDReps = networkMetricsTotalStakeControlledByDReps
, getNetworkMetricsResponseTotalStakeControlledBySPOs = networkMetricsTotalStakeControlledBySPOs
, getNetworkMetricsResponseTotalActiveDReps = networkMetricsTotalActiveDReps
diff --git a/govtool/backend/src/VVA/API/Types.hs b/govtool/backend/src/VVA/API/Types.hs
index 2181bd676..947c7ac53 100644
--- a/govtool/backend/src/VVA/API/Types.hs
+++ b/govtool/backend/src/VVA/API/Types.hs
@@ -884,6 +884,7 @@ data GetNetworkMetricsResponse
, getNetworkMetricsResponseTotalGovernanceActions :: Integer
, getNetworkMetricsResponseTotalDRepVotes :: Integer
, getNetworkMetricsResponseTotalRegisteredDReps :: Integer
+ , getNetworkMetricsResponseTotalDRepDistr :: Integer
, getNetworkMetricsResponseTotalStakeControlledByDReps :: Integer
, getNetworkMetricsResponseTotalStakeControlledBySPOs :: Integer
, getNetworkMetricsResponseTotalActiveDReps :: Integer
@@ -907,6 +908,7 @@ exampleGetNetworkMetricsResponse =
<> "\"totalGovernanceActions\": 0,"
<> "\"totalDRepVotes\": 0,"
<> "\"totalRegisteredDReps\": 0,"
+ <> "\"totalDRepDistr\": 0,"
<> "\"totalStakeControlledByDReps\": 0,"
<> "\"totalStakeControlledBySPOs\": 0,"
<> "\"totalActiveDReps\": 0,"
diff --git a/govtool/backend/src/VVA/Network.hs b/govtool/backend/src/VVA/Network.hs
index 8b844d5d2..7187bb9b5 100644
--- a/govtool/backend/src/VVA/Network.hs
+++ b/govtool/backend/src/VVA/Network.hs
@@ -42,6 +42,7 @@ networkMetrics = withPool $ \conn -> do
, total_gov_action_proposals
, total_drep_votes
, total_registered_dreps
+ , total_drep_distr
, total_stake_controlled_by_dreps
, total_stake_controlled_by_spos
, total_active_dreps
@@ -60,6 +61,7 @@ networkMetrics = withPool $ \conn -> do
total_gov_action_proposals
total_drep_votes
total_registered_dreps
+ total_drep_distr
total_stake_controlled_by_dreps
total_stake_controlled_by_spos
total_active_dreps
diff --git a/govtool/backend/src/VVA/Types.hs b/govtool/backend/src/VVA/Types.hs
index 7a8fa3722..b07d87fcb 100644
--- a/govtool/backend/src/VVA/Types.hs
+++ b/govtool/backend/src/VVA/Types.hs
@@ -225,6 +225,7 @@ data NetworkMetrics
, networkMetricsTotalGovernanceActions :: Integer
, networkMetricsTotalDRepVotes :: Integer
, networkMetricsTotalRegisteredDReps :: Integer
+ , networkMetricsTotalDRepDistr :: Integer
, networkMetricsTotalStakeControlledByDReps :: Integer
, networkMetricsTotalStakeControlledBySPOs :: Integer
, networkMetricsTotalActiveDReps :: Integer
diff --git a/govtool/frontend/src/components/molecules/GovernanceActionDetailsCardVotes.tsx b/govtool/frontend/src/components/molecules/GovernanceActionDetailsCardVotes.tsx
index 5bd37ba6c..00b3dbe02 100644
--- a/govtool/frontend/src/components/molecules/GovernanceActionDetailsCardVotes.tsx
+++ b/govtool/frontend/src/components/molecules/GovernanceActionDetailsCardVotes.tsx
@@ -58,7 +58,7 @@ export const GovernanceActionDetailsCardVotes = ({
isInProgress={isInProgress}
/>
) : (
-
+
)}
);
diff --git a/govtool/frontend/src/components/molecules/VotesSubmitted.tsx b/govtool/frontend/src/components/molecules/VotesSubmitted.tsx
index c063d8887..b4c1afe53 100644
--- a/govtool/frontend/src/components/molecules/VotesSubmitted.tsx
+++ b/govtool/frontend/src/components/molecules/VotesSubmitted.tsx
@@ -10,12 +10,15 @@ import {
} from "@utils";
import { SubmittedVotesData } from "@models";
import { useFeatureFlag, useAppContext } from "@/context";
+import { GovernanceActionType } from "@/types/governanceAction";
type Props = {
+ type: GovernanceActionType;
votes: SubmittedVotesData;
};
export const VotesSubmitted = ({
+ type: govActionType,
votes: {
dRepYesVotes,
dRepAbstainVotes,
@@ -47,23 +50,38 @@ export const VotesSubmitted = ({
const { t } = useTranslation();
const { epochParams, networkMetrics } = useAppContext();
+ // Coming from be
+ // Equal to: total active drep stake + auto no-confidence stake
const totalStakeControlledByDReps =
- networkMetrics?.totalStakeControlledByDReps ?? 0;
+ (networkMetrics?.totalStakeControlledByDReps ?? 0) -
+ // As this being voted for the action becomes part of the total active stake
+ dRepAbstainVotes;
- const totalDRepVotes = totalStakeControlledByDReps
- ? totalStakeControlledByDReps - dRepAbstainVotes
- : undefined;
- const dRepYesVotesPercentage = totalDRepVotes
- ? (dRepYesVotes / totalDRepVotes) * 100
+ // Governance action abstain votesa + auto abstain votes
+ const totalAbstainVotes =
+ dRepAbstainVotes + (networkMetrics?.alwaysAbstainVotingPower ?? 0);
+
+ // TODO: Move this logic to backend
+ const dRepYesVotesPercentage = totalStakeControlledByDReps
+ ? (dRepYesVotes / totalStakeControlledByDReps) * 100
: undefined;
- const dRepNoVotesPercentage = totalDRepVotes
- ? (dRepNoVotes / totalDRepVotes) * 100
+
+ const dRepNoVotesPercentage = totalStakeControlledByDReps
+ ? (dRepNoVotes / totalStakeControlledByDReps) * 100
: undefined;
+
const dRepNotVotedVotes = totalStakeControlledByDReps
? totalStakeControlledByDReps -
- dRepYesVotes -
- dRepNoVotes -
- dRepAbstainVotes
+ (dRepYesVotes -
+ // As this is already added on backend
+ (govActionType === GovernanceActionType.NoConfidence
+ ? networkMetrics?.alwaysNoConfidenceVotingPower ?? 0
+ : 0)) -
+ (dRepNoVotes -
+ // As this is already added on backend
+ (govActionType === GovernanceActionType.NoConfidence
+ ? 0
+ : networkMetrics?.alwaysNoConfidenceVotingPower ?? 0))
: undefined;
const dRepNotVotedVotesPercentage =
100 - (dRepYesVotesPercentage ?? 0) - (dRepNoVotesPercentage ?? 0);
@@ -136,7 +154,7 @@ export const VotesSubmitted = ({
yesVotesPercentage={dRepYesVotesPercentage}
noVotes={dRepNoVotes}
noVotesPercentage={dRepNoVotesPercentage}
- abstainVotes={dRepAbstainVotes}
+ abstainVotes={totalAbstainVotes}
notVotedVotes={dRepNotVotedVotes}
notVotedPercentage={dRepNotVotedVotesPercentage}
threshold={(() => {
diff --git a/govtool/frontend/src/components/organisms/DRepDetailsCard.tsx b/govtool/frontend/src/components/organisms/DRepDetailsCard.tsx
index ac4c5b2fe..de812fd9a 100644
--- a/govtool/frontend/src/components/organisms/DRepDetailsCard.tsx
+++ b/govtool/frontend/src/components/organisms/DRepDetailsCard.tsx
@@ -48,6 +48,7 @@ export const DRepDetailsCard = ({
drepId,
votingPower,
isScriptBased,
+ metadataHash,
} = dRepData;
const groupedReferences = references?.reduce>(
@@ -235,6 +236,53 @@ export const DRepDetailsCard = ({
/>
)}
+ {url && (
+
+
+
+ {url}
+
+
+
+
+ )}
+ {metadataHash && (
+
+
+
+ )}
>
)}
{/* CIP-119 DATA END */}
diff --git a/govtool/frontend/src/components/organisms/GovernanceActionDetailsCard.tsx b/govtool/frontend/src/components/organisms/GovernanceActionDetailsCard.tsx
index ac0613661..1f204407b 100644
--- a/govtool/frontend/src/components/organisms/GovernanceActionDetailsCard.tsx
+++ b/govtool/frontend/src/components/organisms/GovernanceActionDetailsCard.tsx
@@ -36,7 +36,7 @@ export const GovernanceActionDetailsCard = ({
sx={{
borderRadius: "20px",
display: "grid",
- gridTemplateColumns: isOneColumn ? undefined : "0.6fr 0.4fr",
+ gridTemplateColumns: isOneColumn ? undefined : "0.55fr 0.45fr",
mt: "12px",
width: "100%",
position: "relative",
diff --git a/govtool/frontend/src/components/organisms/Modal/SubmittedVotesModal.tsx b/govtool/frontend/src/components/organisms/Modal/SubmittedVotesModal.tsx
index 1f3f7b6f5..32fb6889f 100644
--- a/govtool/frontend/src/components/organisms/Modal/SubmittedVotesModal.tsx
+++ b/govtool/frontend/src/components/organisms/Modal/SubmittedVotesModal.tsx
@@ -23,7 +23,7 @@ export const SubmittedVotesModal = forwardRef((_, ref) => {
>
-
+
diff --git a/govtool/frontend/src/i18n/locales/en.json b/govtool/frontend/src/i18n/locales/en.json
index 370a74adf..eb9926f8e 100644
--- a/govtool/frontend/src/i18n/locales/en.json
+++ b/govtool/frontend/src/i18n/locales/en.json
@@ -328,7 +328,9 @@
"references": "References",
"referenceDescription": "Description",
"referenceDescriptionHelpfulText": "Limit: 80 characters",
- "referenceURL": "URL"
+ "referenceURL": "URL",
+ "metadataUrl": "Metadata URL",
+ "metadataHash": "Metadata Hash"
},
"errors": {
"tooLongUrl": "Url must be less than 128 bytes",
diff --git a/govtool/frontend/src/models/api.ts b/govtool/frontend/src/models/api.ts
index 5deceeba3..bfa233d1e 100644
--- a/govtool/frontend/src/models/api.ts
+++ b/govtool/frontend/src/models/api.ts
@@ -87,6 +87,7 @@ export type NetworkMetrics = {
totalGovernanceActions: number;
totalDRepVotes: number;
totalRegisteredDReps: number;
+ totalDRepDistr: number;
totalStakeControlledByDReps: number;
totalStakeControlledBySPOs: number;
totalActiveDReps: number;
diff --git a/govtool/frontend/yarn.lock b/govtool/frontend/yarn.lock
index e0f4aac63..f24f8e693 100644
--- a/govtool/frontend/yarn.lock
+++ b/govtool/frontend/yarn.lock
@@ -1367,15 +1367,15 @@
resolved "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-asmjs/-/cardano-serialization-lib-asmjs-12.1.1.tgz"
integrity sha512-K3f28QUfLDJ7seO6MtKfMYtRm5ccf36TQ5yxyTmZqX1TA85MkriEdxqpgV9KLiLEA95emwnlvU2/WmlHMRPg1A==
-"@esbuild/darwin-arm64@0.21.5":
+"@esbuild/linux-x64@0.21.5":
version "0.21.5"
- resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz"
- integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==
+ resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz"
+ integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==
-"@esbuild/darwin-arm64@0.24.2":
+"@esbuild/linux-x64@0.24.2":
version "0.24.2"
- resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz"
- integrity sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==
+ resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz"
+ integrity sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
version "4.4.1"
@@ -2162,10 +2162,15 @@
resolved "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz"
integrity sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==
-"@parcel/watcher-darwin-arm64@2.5.0":
+"@parcel/watcher-linux-x64-glibc@2.5.0":
version "2.5.0"
- resolved "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz"
- integrity sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==
+ resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.0.tgz"
+ integrity sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==
+
+"@parcel/watcher-linux-x64-musl@2.5.0":
+ version "2.5.0"
+ resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.0.tgz"
+ integrity sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==
"@parcel/watcher@^2.4.1":
version "2.5.0"
@@ -2278,10 +2283,15 @@
estree-walker "^2.0.2"
picomatch "^4.0.2"
-"@rollup/rollup-darwin-arm64@4.27.4":
+"@rollup/rollup-linux-x64-gnu@4.27.4":
version "4.27.4"
- resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.27.4.tgz"
- integrity sha512-PlNiRQapift4LNS8DPUHuDX/IdXiLjf8mc5vdEmUR0fF/pyy2qWwzdLjB+iZquGr8LuN4LnUoSEvKRwjSVYz3Q==
+ resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.27.4.tgz"
+ integrity sha512-Ni8mMtfo+o/G7DVtweXXV/Ol2TFf63KYjTtoZ5f078AUgJTmaIJnj4JFU7TK/9SVWTaSJGxPi5zMDgK4w+Ez7Q==
+
+"@rollup/rollup-linux-x64-musl@4.27.4":
+ version "4.27.4"
+ resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.27.4.tgz"
+ integrity sha512-5AeeAF1PB9TUzD+3cROzFTnAJAcVUGLuR8ng0E0WXGkYhp6RD6L+6szYVX+64Rs0r72019KHZS1ka1q+zU/wUw==
"@rtsao/scc@^1.1.0":
version "1.1.0"
@@ -2860,10 +2870,15 @@
"@svgr/plugin-svgo" "^5.5.0"
loader-utils "^2.0.0"
-"@swc/core-darwin-arm64@1.9.3":
+"@swc/core-linux-x64-gnu@1.9.3":
version "1.9.3"
- resolved "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.9.3.tgz"
- integrity sha512-hGfl/KTic/QY4tB9DkTbNuxy5cV4IeejpPD4zo+Lzt4iLlDWIeANL4Fkg67FiVceNJboqg48CUX+APhDHO5G1w==
+ resolved "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.9.3.tgz"
+ integrity sha512-ivXXBRDXDc9k4cdv10R21ccBmGebVOwKXT/UdH1PhxUn9m/h8erAWjz5pcELwjiMf27WokqPgaWVfaclDbgE+w==
+
+"@swc/core-linux-x64-musl@1.9.3":
+ version "1.9.3"
+ resolved "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.9.3.tgz"
+ integrity sha512-ILsGMgfnOz1HwdDz+ZgEuomIwkP1PHT6maigZxaCIuC6OPEhKE8uYna22uU63XvYcLQvZYDzpR3ms47WQPuNEg==
"@swc/core@*", "@swc/core@^1.5.22", "@swc/core@^1.7.26":
version "1.9.3"
@@ -7169,16 +7184,6 @@ fs@^0.0.1-security:
resolved "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz"
integrity sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==
-fsevents@^2.3.2, fsevents@~2.3.2, fsevents@~2.3.3:
- version "2.3.3"
- resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz"
- integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
-
-fsevents@2.3.2:
- version "2.3.2"
- resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz"
- integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
-
function-bind@^1.1.2:
version "1.1.2"
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz"
diff --git a/tests/govtool-frontend/playwright/lib/_mock/treasuryProposedGAs.json b/tests/govtool-frontend/playwright/lib/_mock/treasuryProposedGAs.json
new file mode 100644
index 000000000..29c84a6c3
--- /dev/null
+++ b/tests/govtool-frontend/playwright/lib/_mock/treasuryProposedGAs.json
@@ -0,0 +1,1362 @@
+{
+ "data": [
+ {
+ "id": 17204,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "3316",
+ "createdAt": "2025-01-30T11:29:33.731Z",
+ "updatedAt": "2025-01-30T11:29:33.731Z",
+ "user_govtool_username": "korbin46_1738235936720",
+ "content": {
+ "id": 17183,
+ "attributes": {
+ "proposal_id": "17204",
+ "prop_rev_active": true,
+ "prop_abstract": "cura amoveo dedico complectus crastinus",
+ "prop_motivation": "tergeo amor volva aqua arma",
+ "prop_rationale": "pel ocer desidero blandior cultura",
+ "gov_action_type_id": "2",
+ "prop_name": "Statua cimentarius depraedor advenio alveus corrupti.",
+ "is_draft": false,
+ "user_id": "3316",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-30T11:29:33.760Z",
+ "updatedAt": "2025-01-30T11:29:33.760Z",
+ "proposal_links": [
+ {
+ "id": 17030,
+ "prop_link": "https://slight-clarity.org/",
+ "prop_link_text": "euphoric-barium"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15358,
+ "prop_receiving_address": "stake1uqqv758up00900wk9k7xlud8ljtj5zjw4hczht34034kyrgwcsvsk",
+ "prop_amount": 621
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 17183,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "3306",
+ "createdAt": "2025-01-30T09:52:59.102Z",
+ "updatedAt": "2025-01-30T09:52:59.102Z",
+ "user_govtool_username": "myah43_1738230167776",
+ "content": {
+ "id": 17162,
+ "attributes": {
+ "proposal_id": "17183",
+ "prop_rev_active": true,
+ "prop_abstract": "copia venia voluptates accusator varius",
+ "prop_motivation": "currus paulatim canto veritas cognatus",
+ "prop_rationale": "volutabrum comburo vitium cogito coniuratio",
+ "gov_action_type_id": "2",
+ "prop_name": "Verbera cubicularis acer argentum benevolentia laudantium.",
+ "is_draft": false,
+ "user_id": "3306",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-30T09:52:59.130Z",
+ "updatedAt": "2025-01-30T09:52:59.130Z",
+ "proposal_links": [
+ {
+ "id": 17009,
+ "prop_link": "https://playful-size.name/",
+ "prop_link_text": "bare-spiderling"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15337,
+ "prop_receiving_address": "stake1up6c3kuuf9ccy6nq5qr7j2k52m8csg54yhm50d5r5x8lg4q2vvhnc",
+ "prop_amount": 879
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 17181,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "1876",
+ "createdAt": "2025-01-30T09:43:38.887Z",
+ "updatedAt": "2025-01-30T09:43:38.887Z",
+ "user_govtool_username": "cordie_stark_1732618876964",
+ "content": {
+ "id": 17160,
+ "attributes": {
+ "proposal_id": "17181",
+ "prop_rev_active": true,
+ "prop_abstract": "desparatus arma speculum ver admoneo",
+ "prop_motivation": "adstringo ultio capto cado tertius",
+ "prop_rationale": "tergum stella depraedor tamen vigilo",
+ "gov_action_type_id": "2",
+ "prop_name": "Patruus articulus atqui temporibus curtus cernuus.",
+ "is_draft": false,
+ "user_id": "1876",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-30T09:43:38.914Z",
+ "updatedAt": "2025-01-30T09:43:38.914Z",
+ "proposal_links": [
+ {
+ "id": 17007,
+ "prop_link": "https://sore-channel.org/",
+ "prop_link_text": "enormous-summary"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15335,
+ "prop_receiving_address": "stake1up8xg8ur80nsymvefrlk4dshjyfrze4pep843l289f4n8fgynegq0",
+ "prop_amount": 883
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 17162,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "3294",
+ "createdAt": "2025-01-30T07:33:43.674Z",
+ "updatedAt": "2025-01-30T07:33:43.674Z",
+ "user_govtool_username": "albin_cormier42_1738221335719",
+ "content": {
+ "id": 17141,
+ "attributes": {
+ "proposal_id": "17162",
+ "prop_rev_active": true,
+ "prop_abstract": "sonitus decimus succedo aedificium repellendus",
+ "prop_motivation": "aetas verto capitulus copiose tabgo",
+ "prop_rationale": "nostrum desidero confero ambulo supellex",
+ "gov_action_type_id": "2",
+ "prop_name": "Crebro animadverto pecto trado alo alienus.",
+ "is_draft": false,
+ "user_id": "3294",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-30T07:33:43.699Z",
+ "updatedAt": "2025-01-30T07:33:43.699Z",
+ "proposal_links": [
+ {
+ "id": 16988,
+ "prop_link": "https://optimistic-bill.biz/",
+ "prop_link_text": "tedious-regulation"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15316,
+ "prop_receiving_address": "stake1uz924cfl9ag6ga4ah0c3mrgrley6pelvxrc30augvmqgwmqenqge9",
+ "prop_amount": 619
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 17160,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "1876",
+ "createdAt": "2025-01-30T07:16:26.480Z",
+ "updatedAt": "2025-01-30T07:16:26.480Z",
+ "user_govtool_username": "cordie_stark_1732618876964",
+ "content": {
+ "id": 17139,
+ "attributes": {
+ "proposal_id": "17160",
+ "prop_rev_active": true,
+ "prop_abstract": "cimentarius summopere voco natus quod",
+ "prop_motivation": "corporis solum constans amplus tertius",
+ "prop_rationale": "illum quasi cilicium debitis avaritia",
+ "gov_action_type_id": "2",
+ "prop_name": "Depono distinctio adhuc animi tres cum.",
+ "is_draft": false,
+ "user_id": "1876",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-30T07:16:26.514Z",
+ "updatedAt": "2025-01-30T07:16:26.514Z",
+ "proposal_links": [
+ {
+ "id": 16986,
+ "prop_link": "https://far-off-leaf.org",
+ "prop_link_text": "unconscious-plunger"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15314,
+ "prop_receiving_address": "stake1up8xg8ur80nsymvefrlk4dshjyfrze4pep843l289f4n8fgynegq0",
+ "prop_amount": 494
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 17158,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "1876",
+ "createdAt": "2025-01-30T07:07:07.606Z",
+ "updatedAt": "2025-01-30T07:07:07.606Z",
+ "user_govtool_username": "cordie_stark_1732618876964",
+ "content": {
+ "id": 17137,
+ "attributes": {
+ "proposal_id": "17158",
+ "prop_rev_active": true,
+ "prop_abstract": "curriculum in caste alioqui amoveo",
+ "prop_motivation": "substantia angustus subvenio argentum tum",
+ "prop_rationale": "acervus reiciendis fuga tenetur aedificium",
+ "gov_action_type_id": "2",
+ "prop_name": "Copia comprehendo cognomen quam conspergo absorbeo.",
+ "is_draft": false,
+ "user_id": "1876",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-30T07:07:07.632Z",
+ "updatedAt": "2025-01-30T07:07:07.632Z",
+ "proposal_links": [
+ {
+ "id": 16984,
+ "prop_link": "https://powerless-theology.net/",
+ "prop_link_text": "informal-bratwurst"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15312,
+ "prop_receiving_address": "stake1up8xg8ur80nsymvefrlk4dshjyfrze4pep843l289f4n8fgynegq0",
+ "prop_amount": 128
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 17157,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "3293",
+ "createdAt": "2025-01-30T07:05:45.314Z",
+ "updatedAt": "2025-01-30T07:05:45.314Z",
+ "user_govtool_username": "barney.kreiger_1738220473415",
+ "content": {
+ "id": 17136,
+ "attributes": {
+ "proposal_id": "17157",
+ "prop_rev_active": true,
+ "prop_abstract": "sulum charisma astrum tabernus coerceo",
+ "prop_motivation": "capitulus virgo spectaculum defendo voluntarius",
+ "prop_rationale": "denego tremo callide traho avaritia",
+ "gov_action_type_id": "2",
+ "prop_name": "Tendo ago dolores tandem ultra adaugeo.",
+ "is_draft": false,
+ "user_id": "3293",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-30T07:05:45.343Z",
+ "updatedAt": "2025-01-30T07:05:45.343Z",
+ "proposal_links": [
+ {
+ "id": 16983,
+ "prop_link": "https://utter-memo.net",
+ "prop_link_text": "thunderous-cofactor"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15311,
+ "prop_receiving_address": "stake1upmqsvunjaczvfyck7zqwptk56z2ty7smfmga5zvcduwz4cc9cq6v",
+ "prop_amount": 202
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 17147,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "3277",
+ "createdAt": "2025-01-29T16:43:47.743Z",
+ "updatedAt": "2025-01-29T16:43:47.743Z",
+ "user_govtool_username": "jacey45_1738168202436",
+ "content": {
+ "id": 17126,
+ "attributes": {
+ "proposal_id": "17147",
+ "prop_rev_active": true,
+ "prop_abstract": "averto vulariter absque tametsi thermae",
+ "prop_motivation": "pax aestivus aro causa cariosus",
+ "prop_rationale": "appositus beneficium avarus certus carpo",
+ "gov_action_type_id": "2",
+ "prop_name": "Amo aranea cibo alo vehemens tamquam.",
+ "is_draft": false,
+ "user_id": "3277",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-29T16:43:47.772Z",
+ "updatedAt": "2025-01-29T16:43:47.772Z",
+ "proposal_links": [
+ {
+ "id": 16974,
+ "prop_link": "https://polished-sideboard.name/",
+ "prop_link_text": "worthwhile-foodstuffs"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15301,
+ "prop_receiving_address": "stake1uqpsyvc8lcxvmt3xzrq09cmgv6hxmezdychhery9ctvt0xsw2zsvg",
+ "prop_amount": 441
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 17133,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "3277",
+ "createdAt": "2025-01-29T16:40:10.956Z",
+ "updatedAt": "2025-01-29T16:40:10.956Z",
+ "user_govtool_username": "jacey45_1738168202436",
+ "content": {
+ "id": 17112,
+ "attributes": {
+ "proposal_id": "17133",
+ "prop_rev_active": true,
+ "prop_abstract": "aeger cibus acer amaritudo incidunt",
+ "prop_motivation": "provident maiores quia deorsum suscipio",
+ "prop_rationale": "conatus culpa sulum alveus cum",
+ "gov_action_type_id": "2",
+ "prop_name": "Termes apostolus sonitus sustineo architecto demo.",
+ "is_draft": false,
+ "user_id": "3277",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-29T16:40:10.982Z",
+ "updatedAt": "2025-01-29T16:40:10.982Z",
+ "proposal_links": [
+ {
+ "id": 16960,
+ "prop_link": "https://functional-chick.net/",
+ "prop_link_text": "tasty-symbol"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15287,
+ "prop_receiving_address": "stake1uqpsyvc8lcxvmt3xzrq09cmgv6hxmezdychhery9ctvt0xsw2zsvg",
+ "prop_amount": 529
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 17131,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "1876",
+ "createdAt": "2025-01-29T16:30:52.083Z",
+ "updatedAt": "2025-01-29T16:30:52.083Z",
+ "user_govtool_username": "cordie_stark_1732618876964",
+ "content": {
+ "id": 17110,
+ "attributes": {
+ "proposal_id": "17131",
+ "prop_rev_active": true,
+ "prop_abstract": "uxor vulnus defendo dolorem vacuus",
+ "prop_motivation": "turbo quod eligendi veritas ait",
+ "prop_rationale": "apparatus ultra stabilis celo sol",
+ "gov_action_type_id": "2",
+ "prop_name": "Curriculum inventore patrocinor vaco similique solvo.",
+ "is_draft": false,
+ "user_id": "1876",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-29T16:30:52.111Z",
+ "updatedAt": "2025-01-29T16:30:52.111Z",
+ "proposal_links": [
+ {
+ "id": 16958,
+ "prop_link": "https://reflecting-gain.name/",
+ "prop_link_text": "repentant-oregano"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15285,
+ "prop_receiving_address": "stake1up8xg8ur80nsymvefrlk4dshjyfrze4pep843l289f4n8fgynegq0",
+ "prop_amount": 910
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 17112,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "3264",
+ "createdAt": "2025-01-29T16:17:23.432Z",
+ "updatedAt": "2025-01-29T16:17:23.432Z",
+ "user_govtool_username": "gilda26_1738166760447",
+ "content": {
+ "id": 17091,
+ "attributes": {
+ "proposal_id": "17112",
+ "prop_rev_active": true,
+ "prop_abstract": "pax iure carus ocer bellum",
+ "prop_motivation": "aqua vapulus demens cogo carus",
+ "prop_rationale": "tamdiu statua accusamus distinctio animus",
+ "gov_action_type_id": "2",
+ "prop_name": "Careo terreo careo odio carus temptatio.",
+ "is_draft": false,
+ "user_id": "3264",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-29T16:17:23.462Z",
+ "updatedAt": "2025-01-29T16:17:23.462Z",
+ "proposal_links": [
+ {
+ "id": 16939,
+ "prop_link": "https://palatable-grand.info",
+ "prop_link_text": "infinite-deviation"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15266,
+ "prop_receiving_address": "stake1uz7vg8mjrh8hnvsdsh4gzw3affghkpexfmzj69yra0mn5hqncy7kh",
+ "prop_amount": 682
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 17110,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "1876",
+ "createdAt": "2025-01-29T16:06:48.927Z",
+ "updatedAt": "2025-01-29T16:06:48.927Z",
+ "user_govtool_username": "cordie_stark_1732618876964",
+ "content": {
+ "id": 17089,
+ "attributes": {
+ "proposal_id": "17110",
+ "prop_rev_active": true,
+ "prop_abstract": "velum cito sperno adimpleo cruciamentum",
+ "prop_motivation": "adipisci vicinus eius copia debitis",
+ "prop_rationale": "illum deduco succedo coniuratio tamen",
+ "gov_action_type_id": "2",
+ "prop_name": "Censura vis utor aegrotatio vestrum tactus.",
+ "is_draft": false,
+ "user_id": "1876",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-29T16:06:48.953Z",
+ "updatedAt": "2025-01-29T16:06:48.953Z",
+ "proposal_links": [
+ {
+ "id": 16937,
+ "prop_link": "https://radiant-donut.name",
+ "prop_link_text": "chilly-earth"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15264,
+ "prop_receiving_address": "stake1up8xg8ur80nsymvefrlk4dshjyfrze4pep843l289f4n8fgynegq0",
+ "prop_amount": 436
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 17091,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "3249",
+ "createdAt": "2025-01-29T13:29:34.484Z",
+ "updatedAt": "2025-01-29T13:29:34.484Z",
+ "user_govtool_username": "jimmy_deckow21_1738156299677",
+ "content": {
+ "id": 17070,
+ "attributes": {
+ "proposal_id": "17091",
+ "prop_rev_active": true,
+ "prop_abstract": "trucido tolero amplitudo arcesso bellicus",
+ "prop_motivation": "cauda amita itaque dolorem expedita",
+ "prop_rationale": "bene denego patrocinor iusto baiulus",
+ "gov_action_type_id": "2",
+ "prop_name": "Barba adnuo repellat incidunt quas aufero.",
+ "is_draft": false,
+ "user_id": "3249",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-29T13:29:34.516Z",
+ "updatedAt": "2025-01-29T13:29:34.516Z",
+ "proposal_links": [
+ {
+ "id": 16918,
+ "prop_link": "https://admirable-prizefight.com",
+ "prop_link_text": "some-main"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15245,
+ "prop_receiving_address": "stake1urqlur423v8w95kle28ftm3mt3jpwg6vx2fmlh4xk0pyntq0t2x03",
+ "prop_amount": 716
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 17070,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "3242",
+ "createdAt": "2025-01-29T13:25:44.278Z",
+ "updatedAt": "2025-01-29T13:25:44.278Z",
+ "user_govtool_username": "felicity_johns_1738156022811",
+ "content": {
+ "id": 17049,
+ "attributes": {
+ "proposal_id": "17070",
+ "prop_rev_active": true,
+ "prop_abstract": "vis caelestis vir arcus venio",
+ "prop_motivation": "statua voluptates admoveo concedo turba",
+ "prop_rationale": "abutor acsi sollers nihil ara",
+ "gov_action_type_id": "2",
+ "prop_name": "Currus uxor carpo teres varius testimonium.",
+ "is_draft": false,
+ "user_id": "3242",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-29T13:25:44.305Z",
+ "updatedAt": "2025-01-29T13:25:44.305Z",
+ "proposal_links": [
+ {
+ "id": 16897,
+ "prop_link": "https://hollow-onset.info/",
+ "prop_link_text": "used-jacket"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15224,
+ "prop_receiving_address": "stake1urvcy7mtk5r509jejxxwz6ha80w646yxaxaeq32a6fm39fs48p22e",
+ "prop_amount": 649
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 17068,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "1876",
+ "createdAt": "2025-01-29T13:12:34.653Z",
+ "updatedAt": "2025-01-29T13:12:34.653Z",
+ "user_govtool_username": "cordie_stark_1732618876964",
+ "content": {
+ "id": 17047,
+ "attributes": {
+ "proposal_id": "17068",
+ "prop_rev_active": true,
+ "prop_abstract": "utrum debeo callide templum corona",
+ "prop_motivation": "aranea ventus verto pauci provident",
+ "prop_rationale": "laudantium placeat deputo vix tabernus",
+ "gov_action_type_id": "2",
+ "prop_name": "Repellat magnam conturbo comitatus pecco patior.",
+ "is_draft": false,
+ "user_id": "1876",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-29T13:12:34.691Z",
+ "updatedAt": "2025-01-29T13:12:34.691Z",
+ "proposal_links": [
+ {
+ "id": 16895,
+ "prop_link": "https://insistent-hypochondria.info/",
+ "prop_link_text": "raw-tamale"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15222,
+ "prop_receiving_address": "stake1up8xg8ur80nsymvefrlk4dshjyfrze4pep843l289f4n8fgynegq0",
+ "prop_amount": 779
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 17066,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "1876",
+ "createdAt": "2025-01-29T13:07:52.762Z",
+ "updatedAt": "2025-01-29T13:07:52.762Z",
+ "user_govtool_username": "cordie_stark_1732618876964",
+ "content": {
+ "id": 17045,
+ "attributes": {
+ "proposal_id": "17066",
+ "prop_rev_active": true,
+ "prop_abstract": "cernuus quam theologus denique aegre",
+ "prop_motivation": "admitto odit statua veritatis utilis",
+ "prop_rationale": "tum sui aurum speculum repellat",
+ "gov_action_type_id": "2",
+ "prop_name": "Curis tersus confero stella cerno celebrer.",
+ "is_draft": false,
+ "user_id": "1876",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-29T13:07:52.792Z",
+ "updatedAt": "2025-01-29T13:07:52.792Z",
+ "proposal_links": [
+ {
+ "id": 16893,
+ "prop_link": "https://previous-fisherman.info/",
+ "prop_link_text": "leafy-hobby"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15220,
+ "prop_receiving_address": "stake1up8xg8ur80nsymvefrlk4dshjyfrze4pep843l289f4n8fgynegq0",
+ "prop_amount": 807
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 17064,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "1876",
+ "createdAt": "2025-01-29T12:52:21.000Z",
+ "updatedAt": "2025-01-29T12:52:21.000Z",
+ "user_govtool_username": "cordie_stark_1732618876964",
+ "content": {
+ "id": 17043,
+ "attributes": {
+ "proposal_id": "17064",
+ "prop_rev_active": true,
+ "prop_abstract": "anser quibusdam ab conventus creator",
+ "prop_motivation": "acerbitas atrocitas commodo libero apto",
+ "prop_rationale": "vilitas nobis desidero trepide certe",
+ "gov_action_type_id": "2",
+ "prop_name": "Casso statua ad credo aurum curo.",
+ "is_draft": false,
+ "user_id": "1876",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-29T12:52:21.027Z",
+ "updatedAt": "2025-01-29T12:52:21.027Z",
+ "proposal_links": [
+ {
+ "id": 16891,
+ "prop_link": "https://mortified-faucet.info",
+ "prop_link_text": "super-sandbar"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15218,
+ "prop_receiving_address": "stake1up8xg8ur80nsymvefrlk4dshjyfrze4pep843l289f4n8fgynegq0",
+ "prop_amount": 581
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 17062,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "1876",
+ "createdAt": "2025-01-29T12:52:00.202Z",
+ "updatedAt": "2025-01-29T12:52:00.202Z",
+ "user_govtool_username": "cordie_stark_1732618876964",
+ "content": {
+ "id": 17041,
+ "attributes": {
+ "proposal_id": "17062",
+ "prop_rev_active": true,
+ "prop_abstract": "tabella aggredior basium ager summisse",
+ "prop_motivation": "blanditiis pax venio ter defaeco",
+ "prop_rationale": "ambitus coniuratio clementia complectus verto",
+ "gov_action_type_id": "2",
+ "prop_name": "Cerno tempora accusamus celo curvo iure.",
+ "is_draft": false,
+ "user_id": "1876",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-29T12:52:00.242Z",
+ "updatedAt": "2025-01-29T12:52:00.242Z",
+ "proposal_links": [
+ {
+ "id": 16889,
+ "prop_link": "https://parched-catalogue.name",
+ "prop_link_text": "inborn-middleman"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15216,
+ "prop_receiving_address": "stake1up8xg8ur80nsymvefrlk4dshjyfrze4pep843l289f4n8fgynegq0",
+ "prop_amount": 436
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 17043,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "3215",
+ "createdAt": "2025-01-29T11:48:35.324Z",
+ "updatedAt": "2025-01-29T11:48:35.324Z",
+ "user_govtool_username": "carter_padberg53_1738150702304",
+ "content": {
+ "id": 17022,
+ "attributes": {
+ "proposal_id": "17043",
+ "prop_rev_active": true,
+ "prop_abstract": "utique surgo validus consuasor esse",
+ "prop_motivation": "aetas despecto aiunt avaritia conturbo",
+ "prop_rationale": "anser labore est uterque comes",
+ "gov_action_type_id": "2",
+ "prop_name": "Doloremque vacuus tricesimus id approbo adopto.",
+ "is_draft": false,
+ "user_id": "3215",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-29T11:48:35.354Z",
+ "updatedAt": "2025-01-29T11:48:35.354Z",
+ "proposal_links": [
+ {
+ "id": 16870,
+ "prop_link": "https://heartfelt-economics.name/",
+ "prop_link_text": "gloomy-derby"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15197,
+ "prop_receiving_address": "stake1uz862u3nh7nldmeakemr3pkxdr8xz6n39xkq3wtu2ptxhcsfghatd",
+ "prop_amount": 805
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 17024,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "3206",
+ "createdAt": "2025-01-29T11:42:48.167Z",
+ "updatedAt": "2025-01-29T11:42:48.167Z",
+ "user_govtool_username": "ericka.ritchie_1738150365664",
+ "content": {
+ "id": 17003,
+ "attributes": {
+ "proposal_id": "17024",
+ "prop_rev_active": true,
+ "prop_abstract": "cicuta undique verto comparo vespillo",
+ "prop_motivation": "absorbeo videlicet cenaculum deprecator accusator",
+ "prop_rationale": "natus voco conicio baiulus condico",
+ "gov_action_type_id": "2",
+ "prop_name": "Undique subseco abundans aegre vulnus ambulo.",
+ "is_draft": false,
+ "user_id": "3206",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-29T11:42:48.193Z",
+ "updatedAt": "2025-01-29T11:42:48.193Z",
+ "proposal_links": [
+ {
+ "id": 16851,
+ "prop_link": "https://meaty-gate.net",
+ "prop_link_text": "orange-widow"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15178,
+ "prop_receiving_address": "stake1urf2xgpkh7u2kjee4uu5as2h24l2tefpc4xsnha8sdsj6uqhtgsyq",
+ "prop_amount": 722
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 17022,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "1876",
+ "createdAt": "2025-01-29T11:39:16.069Z",
+ "updatedAt": "2025-01-29T11:39:16.069Z",
+ "user_govtool_username": "cordie_stark_1732618876964",
+ "content": {
+ "id": 17001,
+ "attributes": {
+ "proposal_id": "17022",
+ "prop_rev_active": true,
+ "prop_abstract": "amet culpo vicissitudo arca adulatio",
+ "prop_motivation": "calcar agnitio succurro taedium ipsa",
+ "prop_rationale": "summa terebro minima bis sordeo",
+ "gov_action_type_id": "2",
+ "prop_name": "Beatae anser stillicidium quam aperio vallum.",
+ "is_draft": false,
+ "user_id": "1876",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-29T11:39:16.105Z",
+ "updatedAt": "2025-01-29T11:39:16.105Z",
+ "proposal_links": [
+ {
+ "id": 16849,
+ "prop_link": "https://good-spark.biz",
+ "prop_link_text": "surprised-identification"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15176,
+ "prop_receiving_address": "stake1up8xg8ur80nsymvefrlk4dshjyfrze4pep843l289f4n8fgynegq0",
+ "prop_amount": 961
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 17020,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "1876",
+ "createdAt": "2025-01-29T11:33:35.606Z",
+ "updatedAt": "2025-01-29T11:33:35.606Z",
+ "user_govtool_username": "cordie_stark_1732618876964",
+ "content": {
+ "id": 16999,
+ "attributes": {
+ "proposal_id": "17020",
+ "prop_rev_active": true,
+ "prop_abstract": "curtus capitulus tardus brevis vox",
+ "prop_motivation": "auditor et aduro aperio vulgivagus",
+ "prop_rationale": "conturbo tersus minus cubo aestivus",
+ "gov_action_type_id": "2",
+ "prop_name": "Cursus attonbitus deorsum tollo ciminatio villa.",
+ "is_draft": false,
+ "user_id": "1876",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-29T11:33:35.634Z",
+ "updatedAt": "2025-01-29T11:33:35.634Z",
+ "proposal_links": [
+ {
+ "id": 16847,
+ "prop_link": "https://silent-container.biz",
+ "prop_link_text": "tense-facelift"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15174,
+ "prop_receiving_address": "stake1up8xg8ur80nsymvefrlk4dshjyfrze4pep843l289f4n8fgynegq0",
+ "prop_amount": 447
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 16999,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "1876",
+ "createdAt": "2025-01-29T09:24:17.156Z",
+ "updatedAt": "2025-01-29T09:24:17.156Z",
+ "user_govtool_username": "cordie_stark_1732618876964",
+ "content": {
+ "id": 16978,
+ "attributes": {
+ "proposal_id": "16999",
+ "prop_rev_active": true,
+ "prop_abstract": "crustulum versus vapulus aliquam circumvenio",
+ "prop_motivation": "adhuc thalassinus arx dolores curvo",
+ "prop_rationale": "valde bene acquiro stabilis officiis",
+ "gov_action_type_id": "2",
+ "prop_name": "Curvo adsuesco depereo statua vulticulus thorax.",
+ "is_draft": false,
+ "user_id": "1876",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-29T09:24:17.191Z",
+ "updatedAt": "2025-01-29T09:24:17.191Z",
+ "proposal_links": [
+ {
+ "id": 16826,
+ "prop_link": "https://traumatic-eagle.org/",
+ "prop_link_text": "anchored-sake"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15153,
+ "prop_receiving_address": "stake1up8xg8ur80nsymvefrlk4dshjyfrze4pep843l289f4n8fgynegq0",
+ "prop_amount": 261
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 16958,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "1876",
+ "createdAt": "2025-01-28T17:48:59.554Z",
+ "updatedAt": "2025-01-28T17:48:59.554Z",
+ "user_govtool_username": "cordie_stark_1732618876964",
+ "content": {
+ "id": 16937,
+ "attributes": {
+ "proposal_id": "16958",
+ "prop_rev_active": true,
+ "prop_abstract": "complectus adflicto voro adipiscor volubilis",
+ "prop_motivation": "decimus quis adduco alo trans",
+ "prop_rationale": "ubi demitto crux trepide contego",
+ "gov_action_type_id": "2",
+ "prop_name": "Undique ambulo acerbitas ter tertius titulus.",
+ "is_draft": false,
+ "user_id": "1876",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-28T17:48:59.585Z",
+ "updatedAt": "2025-01-28T17:48:59.585Z",
+ "proposal_links": [
+ {
+ "id": 16785,
+ "prop_link": "https://testy-neuron.biz/",
+ "prop_link_text": "exemplary-selling"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15112,
+ "prop_receiving_address": "stake1up8xg8ur80nsymvefrlk4dshjyfrze4pep843l289f4n8fgynegq0",
+ "prop_amount": 563
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "id": 16957,
+ "attributes": {
+ "prop_likes": 0,
+ "prop_dislikes": 0,
+ "prop_comments_number": 0,
+ "user_id": "1876",
+ "createdAt": "2025-01-28T17:45:28.363Z",
+ "updatedAt": "2025-01-28T17:45:28.363Z",
+ "user_govtool_username": "cordie_stark_1732618876964",
+ "content": {
+ "id": 16936,
+ "attributes": {
+ "proposal_id": "16957",
+ "prop_rev_active": true,
+ "prop_abstract": "sol deprimo bonus adicio tamdiu",
+ "prop_motivation": "accusamus creta vir ara aetas",
+ "prop_rationale": "ultio degero exercitationem adfero vae",
+ "gov_action_type_id": "2",
+ "prop_name": "Animus virgo averto suscipio agnosco decerno.",
+ "is_draft": false,
+ "user_id": "1876",
+ "prop_submitted": false,
+ "prop_submission_tx_hash": null,
+ "prop_submission_date": null,
+ "createdAt": "2025-01-28T17:45:28.387Z",
+ "updatedAt": "2025-01-28T17:45:28.387Z",
+ "proposal_links": [
+ {
+ "id": 16784,
+ "prop_link": "https://klutzy-light.biz",
+ "prop_link_text": "boring-closing"
+ }
+ ],
+ "proposal_withdrawals": [
+ {
+ "id": 15111,
+ "prop_receiving_address": "stake1up8xg8ur80nsymvefrlk4dshjyfrze4pep843l289f4n8fgynegq0",
+ "prop_amount": 555
+ }
+ ],
+ "gov_action_type": {
+ "id": 2,
+ "attributes": {
+ "gov_action_type_name": "Treasury",
+ "createdAt": "2024-08-21T21:40:32.586Z",
+ "updatedAt": "2024-08-21T21:40:33.850Z",
+ "publishedAt": "2024-08-21T21:40:33.843Z"
+ }
+ }
+ }
+ }
+ }
+ }
+ ],
+ "meta": {
+ "pagination": {
+ "page": 1,
+ "pageSize": 25,
+ "pageCount": 138,
+ "total": 3437
+ }
+ }
+}
diff --git a/tests/govtool-frontend/playwright/lib/helpers/adaFormat.ts b/tests/govtool-frontend/playwright/lib/helpers/adaFormat.ts
index d9f7459b4..3f28e2eaf 100644
--- a/tests/govtool-frontend/playwright/lib/helpers/adaFormat.ts
+++ b/tests/govtool-frontend/playwright/lib/helpers/adaFormat.ts
@@ -2,13 +2,21 @@ const LOVELACE = 1000000;
export const correctVoteAdaFormat = (
lovelace: number | undefined,
- locale: string | undefined = undefined
+ precision = 2
) => {
if (lovelace) {
const ada = lovelace / LOVELACE;
- return ada.toLocaleString(locale, {
- maximumFractionDigits: 3,
- });
+ if (ada < 1000)
+ return ada.toLocaleString("en-us", {
+ maximumFractionDigits: precision,
+ });
+ const suffixes = ["k", "M", "B", "T"];
+ const divisors = [1000, 1000000, 1000000000, 1000000000000];
+ for (let i = 0; i < suffixes.length; i++) {
+ if (ada < divisors[i] * 1000) {
+ return (ada / divisors[i]).toFixed(precision) + suffixes[i];
+ }
+ }
}
return "0";
};
diff --git a/tests/govtool-frontend/playwright/lib/pages/dRepDirectoryPage.ts b/tests/govtool-frontend/playwright/lib/pages/dRepDirectoryPage.ts
index 6a0d78b28..0d2a28be2 100644
--- a/tests/govtool-frontend/playwright/lib/pages/dRepDirectoryPage.ts
+++ b/tests/govtool-frontend/playwright/lib/pages/dRepDirectoryPage.ts
@@ -79,6 +79,8 @@ export default class DRepDirectoryPage {
(filter) => !filters.includes(filter)
);
+ await this.page.waitForTimeout(4_000); // wait for the dRep list to render properly
+
const dRepList = await this.getAllListedDReps();
for (const filter of excludedFilters) {
diff --git a/tests/govtool-frontend/playwright/lib/pages/governanceActionDetailsPage.ts b/tests/govtool-frontend/playwright/lib/pages/governanceActionDetailsPage.ts
index 600d8818f..4199b7f99 100644
--- a/tests/govtool-frontend/playwright/lib/pages/governanceActionDetailsPage.ts
+++ b/tests/govtool-frontend/playwright/lib/pages/governanceActionDetailsPage.ts
@@ -1,7 +1,8 @@
import environments from "@constants/environments";
import { downloadMetadata } from "@helpers/metadata";
-import { Download, Page } from "@playwright/test";
+import { Download, Page, Response } from "@playwright/test";
import metadataBucketService from "@services/metadataBucketService";
+import { IProposal } from "@types";
import { withTxConfirmation } from "lib/transaction.decorator";
export default class GovernanceActionDetailsPage {
@@ -39,6 +40,9 @@ export default class GovernanceActionDetailsPage {
readonly dRepYesVotes = this.page.getByTestId("submitted-votes-dReps-yes");
readonly dRepNoVotes = this.page.getByTestId("submitted-votes-dReps-no");
+ readonly dRepNotVoted = this.page.getByTestId(
+ "submitted-votes-dReps-notVoted"
+ );
readonly dRepAbstainVotes = this.page.getByTestId(
"submitted-votes-dReps-abstain"
);
@@ -97,6 +101,29 @@ export default class GovernanceActionDetailsPage {
await this.voteBtn.click();
}
+ async getDRepNotVoted(
+ proposal: IProposal,
+ metricsResponsePromise: Promise
+ ): Promise {
+ const metricsResponses = await Promise.resolve(metricsResponsePromise);
+ const totalStakeControlledByDReps = await metricsResponses
+ .json()
+ .then((data) => data.totalStakeControlledByDReps);
+
+ if (
+ totalStakeControlledByDReps &&
+ typeof totalStakeControlledByDReps === "number"
+ ) {
+ const dRepNotVoted =
+ totalStakeControlledByDReps -
+ proposal.dRepYesVotes -
+ proposal.dRepAbstainVotes -
+ proposal.dRepNoVotes;
+
+ return dRepNotVoted;
+ }
+ }
+
async downloadVoteMetadata() {
const download: Download = await this.page.waitForEvent("download");
return downloadMetadata(download);
diff --git a/tests/govtool-frontend/playwright/lib/pages/proposalDiscussionPage.ts b/tests/govtool-frontend/playwright/lib/pages/proposalDiscussionPage.ts
index b44d9ca46..a8dbaaa12 100644
--- a/tests/govtool-frontend/playwright/lib/pages/proposalDiscussionPage.ts
+++ b/tests/govtool-frontend/playwright/lib/pages/proposalDiscussionPage.ts
@@ -92,10 +92,11 @@ export default class ProposalDiscussionPage {
filters: string[],
validateFunction: (proposalCard: any, filters: string[]) => Promise
) {
+ await this.page.waitForTimeout(4_000); // wait for the proposals to load
// single filter
for (const filter of filters) {
await this.filterProposalByNames([filter]);
- await this.validateFilters(filters, validateFunction);
+ await this.validateFilters([filter], validateFunction);
await this.unFilterProposalByNames([filter]);
}
diff --git a/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.dRep.spec.ts b/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.dRep.spec.ts
index e168afd2a..4036d80ba 100644
--- a/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.dRep.spec.ts
+++ b/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.dRep.spec.ts
@@ -150,6 +150,10 @@ test.describe("Check vote count", () => {
)
);
+ const metricsResponsePromise = page.waitForResponse((response) =>
+ response.url().includes(`network/metrics`)
+ );
+
const governanceActionsPage = new GovernanceActionsPage(page);
await governanceActionsPage.goto();
@@ -180,6 +184,11 @@ test.describe("Check vote count", () => {
`${proposalToCheck.txHash}#${proposalToCheck.index}`
);
+ const dRepNotVoted = await govActionDetailsPage.getDRepNotVoted(
+ proposalToCheck,
+ metricsResponsePromise
+ );
+
await govActionDetailsPage.showVotesBtn.click();
// check dRep votes
@@ -193,6 +202,12 @@ test.describe("Check vote count", () => {
await expect(govActionDetailsPage.dRepNoVotes).toHaveText(
`₳ ${correctVoteAdaFormat(proposalToCheck.dRepNoVotes)}`
);
+
+ if (dRepNotVoted) {
+ await expect(govActionDetailsPage.dRepNotVoted).toHaveText(
+ `₳ ${correctVoteAdaFormat(dRepNotVoted)}`
+ );
+ }
}
// check sPos votes
diff --git a/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.spec.ts b/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.spec.ts
index 8b08c93c0..9de7c222d 100644
--- a/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.spec.ts
+++ b/tests/govtool-frontend/playwright/tests/4-proposal-visibility/proposalVisibility.spec.ts
@@ -45,6 +45,10 @@ test("4K. Should display correct vote counts on governance details page for disc
)
);
+ const metricsResponsePromise = page.waitForResponse((response) =>
+ response.url().includes(`network/metrics`)
+ );
+
const governanceActionsPage = new GovernanceActionsPage(page);
await governanceActionsPage.goto();
const responses = await Promise.all(responsesPromise);
@@ -71,6 +75,11 @@ test("4K. Should display correct vote counts on governance details page for disc
`${proposalToCheck.txHash}#${proposalToCheck.index}`
);
+ const dRepNotVoted = await govActionDetailsPage.getDRepNotVoted(
+ proposalToCheck,
+ metricsResponsePromise
+ );
+
// check dRep votes
if (await areDRepVoteTotalsDisplayed(proposalToCheck)) {
await expect(govActionDetailsPage.dRepYesVotes).toHaveText(
@@ -82,6 +91,12 @@ test("4K. Should display correct vote counts on governance details page for disc
await expect(govActionDetailsPage.dRepNoVotes).toHaveText(
`₳ ${correctVoteAdaFormat(proposalToCheck.dRepNoVotes)}`
);
+
+ if (dRepNotVoted) {
+ await expect(govActionDetailsPage.dRepNotVoted).toHaveText(
+ `₳ ${correctVoteAdaFormat(dRepNotVoted)}`
+ );
+ }
}
// check sPos votes
if (await areSPOVoteTotalsDisplayed(proposalToCheck)) {
diff --git a/tests/govtool-frontend/playwright/tests/5-proposal-functionality/proposalFunctionality.dRep.spec.ts b/tests/govtool-frontend/playwright/tests/5-proposal-functionality/proposalFunctionality.dRep.spec.ts
index ac81002bf..1cfd89e32 100644
--- a/tests/govtool-frontend/playwright/tests/5-proposal-functionality/proposalFunctionality.dRep.spec.ts
+++ b/tests/govtool-frontend/playwright/tests/5-proposal-functionality/proposalFunctionality.dRep.spec.ts
@@ -96,13 +96,18 @@ test.describe("Proposal checks", () => {
});
test.describe("Validate provide context about vote", () => {
+ const characters =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
test("5D_1. Should accept valid data in provide context", async () => {
await govActionDetailsPage.contextBtn.click();
await expect(govActionDetailsPage.contextInput).toBeVisible();
for (let i = 0; i < 100; i++) {
- const randomContext = faker.lorem.paragraph(2);
+ const randomContext = faker.string.fromCharacters(characters, {
+ min: 1,
+ max: 9999,
+ });
await govActionDetailsPage.contextInput.fill(randomContext);
expect(await govActionDetailsPage.contextInput.textContent()).toEqual(
randomContext
@@ -118,7 +123,7 @@ test.describe("Proposal checks", () => {
await expect(govActionDetailsPage.contextInput).toBeVisible();
for (let i = 0; i < 100; i++) {
- const randomContext = faker.lorem.paragraph(40);
+ const randomContext = faker.string.fromCharacters(characters, 10001);
await govActionDetailsPage.contextInput.fill(randomContext);
expect(
await govActionDetailsPage.contextInput.textContent()
diff --git a/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.loggedin.spec.ts b/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.loggedin.spec.ts
index 36568db3b..bb35e0fbe 100644
--- a/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.loggedin.spec.ts
+++ b/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.loggedin.spec.ts
@@ -68,7 +68,7 @@ test.describe("Proposal created logged in state", () => {
await proposalDiscussionDetailsPage.addComment(randComment);
await proposalDiscussionDetailsPage.replyComment(randReply);
- await expect(page.getByText(randReply)).toBeVisible();
+ await expect(page.getByText(randReply)).toBeVisible({ timeout: 15_000 });
});
});
@@ -122,12 +122,12 @@ test.describe("Proposal created with poll enabled (user auth)", () => {
// vote must be changed
await expect(
page.getByTestId(`poll-${vote.toLowerCase()}-count`)
- ).not.toHaveText(`${vote}: (0%)`);
+ ).toHaveText(`${vote}: (0%)`, { timeout: 15_000 });
// opposite of random choice vote
const oppositeVote = pollVotes[pollVotes.length - 1 - choice];
await expect(
page.getByTestId(`poll-${oppositeVote.toLowerCase()}-count`)
- ).not.toHaveText(`${oppositeVote}: (100%)`);
+ ).toHaveText(`${oppositeVote}: (100%)`);
});
});
diff --git a/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.spec.ts b/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.spec.ts
index 4ad591246..c320cd668 100644
--- a/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.spec.ts
+++ b/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.spec.ts
@@ -6,11 +6,13 @@ import { isBootStrapingPhase, skipIfNotHardFork } from "@helpers/cardano";
import ProposalDiscussionDetailsPage from "@pages/proposalDiscussionDetailsPage";
import ProposalDiscussionPage from "@pages/proposalDiscussionPage";
import { expect } from "@playwright/test";
+import { ProposalType } from "@types";
const mockProposal = require("../../lib/_mock/proposal.json");
const mockPoll = require("../../lib/_mock/proposalPoll.json");
const mockComments = require("../../lib/_mock/proposalComments.json");
const mockInfoProposedGA = require("../../lib/_mock/infoProposedGAs.json");
+const mockTreasuryProposal = require("../../lib/_mock/treasuryProposedGAs.json");
const PROPOSAL_TYPE_FILTERS = ["Info", "Treasury"];
const BOOTSTRAP_PROPOSAL_TYPE_FILTERS = ["Info"];
@@ -92,27 +94,49 @@ test("8C. Should search the list of proposed governance actions.", async ({
}
});
-test("8D.Should show the view-all categorized proposed governance actions.", async ({
- page,
+test("8D. Should show the view-all categorized proposed governance actions.", async ({
+ browser,
}) => {
- await page.route("**/api/proposals?**", async (route) => {
- return route.fulfill({
- body: JSON.stringify(mockInfoProposedGA),
- });
- });
-
- const proposalDiscussionPage = new ProposalDiscussionPage(page);
- await proposalDiscussionPage.goto();
-
- await proposalDiscussionPage.showAllBtn.click();
-
- const proposalCards = await proposalDiscussionPage.getAllProposals();
-
- for (const proposalCard of proposalCards) {
- await expect(
- proposalCard.getByTestId("governance-action-type")
- ).toBeVisible();
- }
+ await Promise.all(
+ Object.entries({
+ [ProposalType.info]: mockInfoProposedGA,
+ [ProposalType.treasury]: mockTreasuryProposal,
+ }).map(async ([proposalType, mockData]) => {
+ const requestUrl = `**/api/proposals?**`;
+ let requestHandled = 0;
+
+ const context = await browser.newContext();
+ const page = await context.newPage();
+
+ await page.route(requestUrl, async (route) => {
+ if (requestHandled < 2) {
+ requestHandled = requestHandled + 1;
+ return route.fulfill({
+ body: JSON.stringify(mockData),
+ });
+ }
+ return route.continue();
+ });
+
+ const proposalDiscussionPage = new ProposalDiscussionPage(page);
+ await proposalDiscussionPage.goto();
+
+ await proposalDiscussionPage.filterBtn.click();
+ await proposalDiscussionPage.filterProposalByNames([proposalType]);
+ // to close the filter menu
+ await proposalDiscussionPage.filterBtn.click({ force: true });
+
+ proposalDiscussionPage.showAllBtn.click();
+
+ const proposalCards = await proposalDiscussionPage.getAllProposals();
+
+ for (const proposalCard of proposalCards) {
+ await expect(
+ proposalCard.getByTestId("governance-action-type")
+ ).toHaveText(proposalType, { timeout: 20_000 });
+ }
+ })
+ );
});
test("8H. Should disable proposal interaction on a disconnected state.", async ({