diff --git a/.github/images/cardano-govtool-header.png b/.github/images/cardano-govtool-header.png new file mode 100644 index 000000000..f7a7ded9c Binary files /dev/null and b/.github/images/cardano-govtool-header.png differ diff --git a/.github/workflows/build-and-deploy-test-stack.yml b/.github/workflows/build-and-deploy-test-stack.yml index e735e2c0c..a4d3c07a2 100644 --- a/.github/workflows/build-and-deploy-test-stack.yml +++ b/.github/workflows/build-and-deploy-test-stack.yml @@ -75,3 +75,4 @@ jobs: USERSNAP_SPACE_API_KEY: ${{ secrets.USERSNAP_SPACE_API_KEY }} APP_ENV: test PDF_API_URL: ${{ secrets.PDF_API_URL }} + KUBER_API_KEY: ${{secrets.KUBER_API_KEY}} diff --git a/.gitignore b/.gitignore index 05f1097fb..ccd0c617b 100644 --- a/.gitignore +++ b/.gitignore @@ -62,7 +62,7 @@ node_storage/ # MSVC Windows builds of rustc generate these, which store debugging information *.pdb - +.venv ### Windows ### # Windows thumbnail cache files Thumbs.db diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ec1ed241..9981d01ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,26 @@ changes. - +## [sancho-v1.0.18](https://github.com/IntersectMBO/govtool/releases/tag/sancho-v1.0.18) 2024-09-12 + +### Added + +- Add script for Matomo Analytics [Issue 1817](https://github.com/IntersectMBO/govtool/issues/1817) + +### Fixed + +- Correctly show all kinds of votes in the modal showing vote numbers [Issue 1941](https://github.com/IntersectMBO/govtool/issues/1941) +- Fixed terms and conditions link [Issue 1968](https://github.com/IntersectMBO/govtool/issues/1968) +- Hide Delegate button in DRep list and details if user has already delegated to this DRep [Issue 1982](https://github.com/IntersectMBO/govtool/issues/1982) +- Fix condition for disabling voting on different GA types [Issue 2008](https://github.com/IntersectMBO/govtool/issues/2008) +- Fix incorrect copy (ex. github) to (e.g. github) [Issue 1748](https://github.com/IntersectMBO/govtool/issues/1748) + +### Changed + +- Bump @intersect.mbo/pdf-ui to v0.3.9 +- Changed misleading text for direct voter registration [Issue 1976](https://github.com/IntersectMBO/govtool/issues/1976) +- Change base repo README header image to have correct branding and reflect mainnet launch. + ## [sancho-v1.0.17](https://github.com/IntersectMBO/govtool/releases/tag/sancho-v1.0.17) 2024-09-05 ### Added diff --git a/README.md b/README.md index 8a8aea50b..db07e081c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- +

@@ -24,7 +24,7 @@ The Cardano GovTool enables ada holders to experience the governance features de #### Mainnet -- _Coming soon_ +- [gov.tools](https://gov.tools/) #### SanchoNet diff --git a/gov-action-loader/backend/.env.example b/gov-action-loader/backend/.env.example index 8997b5adf..d0868c32f 100644 --- a/gov-action-loader/backend/.env.example +++ b/gov-action-loader/backend/.env.example @@ -1,2 +1,4 @@ -KUBER_API_URL=https://sanchonet.kuber.cardanoapi.io +KUBER_API_URL_SANCHO=https://sanchonet.kuber.cardanoapi.io +KUBER_API_URL_PREVIEW=https://preview.kuber.cardanoapi.io +KUBER_API_URL_PREPROD=https://preprod.kuber.cardanoapi.io KUBER_API_KEY=xxxxxxxxxxxxx diff --git a/gov-action-loader/backend/app/data/gov-script.plutus b/gov-action-loader/backend/app/data/gov-script.plutus new file mode 100644 index 000000000..b6af50acb --- /dev/null +++ b/gov-action-loader/backend/app/data/gov-script.plutus @@ -0,0 +1,5 @@ +{ + "type": "PlutusScriptV3", + "description": "", + "cborHex": "5908545908510101003232323232323232323232323232323232323232323232323232323232323232323232323232323232259323255333573466e1d20000011180098111bab357426ae88d55cf00104554ccd5cd19b87480100044600422c6aae74004dd51aba1357446ae88d55cf1baa3255333573466e1d200a35573a002226ae84d5d11aab9e00111637546ae84d5d11aba235573c6ea800642b26006003149a2c8a4c301f801c0052000c00e0070018016006901e4070c00e003000c00d20d00fc000c0003003800a4005801c00e003002c00d20c09a0c80e1801c006001801a4101b5881380018000600700148013003801c006005801a410100078001801c006001801a4101001f8001800060070014801b0038018096007001800600690404002600060001801c0052008c00e006025801c006001801a41209d8001800060070014802b003801c006005801a410112f501c3003800c00300348202b7881300030000c00e00290066007003800c00b003482032ad7b806038403060070014803b00380180960003003800a4021801c00e003002c00d20f40380e1801c006001801a41403f800100a0c00e0029009600f0030078040c00e002900a600f003800c00b003301a483403e01a600700180060066034904801e00060001801c0052016c01e00600f801c006001801980c2402900e30000c00e002901060070030128060c00e00290116007003800c00b003483c0ba03860070018006006906432e00040283003800a40498003003800a404d802c00e00f003800c00b003301a480cb0003003800c003003301a4802b00030001801c01e0070018016006603490605c0160006007001800600660349048276000600030000c00e0029014600b003801c00c04b003800c00300348203a2489b00030001801c00e006025801c006001801a4101b11dc2df80018000c0003003800a4055802c00e007003012c00e003000c00d2080b8b872c000c0006007003801809600700180060069040607e4155016000600030000c00e00290166007003012c00e003000c00d2080c001c000c0003003800a405d801c00e003002c00d20c80180e1801c006001801a412007800100a0c00e00290186007003013c0006007001480cb005801801e006003801800e00600500403003800a4069802c00c00f003001c00c007003803c00e003002c00c05300333023480692028c0004014c00c00b003003c00c00f003003c00e00f003800c00b00301480590052008003003800a406d801c00e003002c00d2000c00d2006c00060070018006006900a600060001801c0052038c00e007001801600690006006901260003003800c003003483281300020141801c005203ac00e006027801c006001801a403d800180006007001480f3003801804e00700180060069040404af3c4e302600060001801c005203ec00e006013801c006001801a4101416f0fd20b80018000600700148103003801c006005801a403501c3003800c0030034812b00030000c00e0029021600f003800c00a01ac00e003000c00ccc08d20d00f4800b00030000c0000000000803c00c016008401e006009801c006001801807e0060298000c000401e006007801c0060018018074020c000400e00f003800c00b003010c000802180020070018006006019801805e0003000400600580180760060138000800c00b00330134805200c400e00300080330004006005801a4001801a410112f58000801c00600901260008019806a40118002007001800600690404a75ee01e00060008018046000801801e000300c4832004c025201430094800a0030028052003002c00d2002c000300648010c0092002300748028c0312000300b48018c0292012300948008c0212066801a40018000c0192008300a2233335573e00250002801994004d55ce800cd55cf0008d5d08014c00cd5d10011263009222532900389800a4d2219002912c80344c01526910c80148964cc04cdd68010034564cc03801400626601800e0071801226601800e01518010096400a3000910c008600444002600244004a664600200244246466004460044460040064600444600200646a660080080066a00600224446600644b20051800484ccc02600244666ae68cdc3801000c00200500a91199ab9a33710004003000801488ccd5cd19b89002001800400a44666ae68cdc4801000c00a00122333573466e20008006005000912a999ab9a3371200400222002220052255333573466e2400800444008440040026eb400a42660080026eb000a4264666015001229002914801c8954ccd5cd19b8700400211333573466e1c00c006001002118011229002914801c88cc044cdc100200099b82002003245200522900391199ab9a3371066e08010004cdc1001001c002004403245200522900391199ab9a3371266e08010004cdc1001001c00a00048a400a45200722333573466e20cdc100200099b820020038014000912c99807001000c40062004912c99807001000c400a2002001199919ab9a357466ae880048cc028dd69aba1003375a6ae84008d5d1000934000dd60010a40064666ae68d5d1800c0020052225933006003357420031330050023574400318010600a444aa666ae68cdc3a400000222c22aa666ae68cdc4000a4000226600666e05200000233702900000088994004cdc2001800ccdc20010008cc010008004c01088954ccd5cd19b87480000044400844cc00c004cdc300100091119803112c800c60012219002911919806912c800c4c02401a442b26600a004019130040018c008002590028c804c8888888800d1900991111111002a244b267201722222222008001000c600518000001112a999ab9a3370e004002230001155333573466e240080044600823002229002914801c88ccd5cd19b893370400800266e0800800e00100208c8c0040048c0088cc008008005" +} \ No newline at end of file diff --git a/gov-action-loader/backend/app/funds.py b/gov-action-loader/backend/app/funds.py index 6899ddc3c..015f0c511 100644 --- a/gov-action-loader/backend/app/funds.py +++ b/gov-action-loader/backend/app/funds.py @@ -2,13 +2,15 @@ from fastapi import HTTPException +from app.network import get_api_url from app.settings import settings from app.transaction import (default_proposal_deposit_ada, main_wallet, submit_tx) -async def get_ada_balance(address, client): - utxo_url = settings.kuber_api_url + "/api/v3/utxo" +async def get_ada_balance(address, client, network): + + utxo_url = get_api_url(network) + "/api/v3/utxo" kuber_response = await client.get( utxo_url, params={"address": address}, @@ -25,8 +27,8 @@ async def get_ada_balance(address, client): ) -async def get_protocol_params(client): - pParamsQuery = settings.kuber_api_url + "/api/v3/protocol-params" +async def get_protocol_params(client, network): + pParamsQuery = get_api_url(network) + "/api/v3/protocol-params" kuber_response = await client.get( pParamsQuery, headers={"api-key": settings.kuber_api_key}, @@ -41,7 +43,7 @@ async def get_protocol_params(client): async def check_balance_and_fund_wallets( - wallets, supported_proposals_in_single_tx, per_proposal_deposit, client + wallets, supported_proposals_in_single_tx, per_proposal_deposit, client, network ): wallets_with_balance = await asyncio.gather( *[get_ada_balance(wallet["address"], client) for wallet in wallets] @@ -82,7 +84,7 @@ async def check_balance_and_fund_wallets( for wallet in low_balance_wallets ], } - tx = await submit_tx(fund_from_main_tx, client) + tx = await submit_tx(fund_from_main_tx, client, network) raise HTTPException( status_code=412, detail="This action required multiple transaction and wallet setup TX:" diff --git a/gov-action-loader/backend/app/main.py b/gov-action-loader/backend/app/main.py index 268ee1b3d..34bd1ffbc 100644 --- a/gov-action-loader/backend/app/main.py +++ b/gov-action-loader/backend/app/main.py @@ -1,21 +1,24 @@ import asyncio import json import math -from typing import Any, Dict +from typing import Any, Dict, Literal import httpx -from fastapi import Depends, FastAPI, HTTPException +from fastapi import Depends, FastAPI, HTTPException, Header from app.cors import add_cors from app.funds import (check_balance_and_fund_wallets, get_ada_balance, get_protocol_params) from app.http_utils import get_client from app.models import MultipleProposal +from app.network import get_api_url from app.settings import settings from app.transaction import (get_base_proposal_for_multiple, get_default_transaction, get_proposal_data_from_type, - main_wallet, submit_proposal_tx) + main_wallet, submit_proposal_tx, + get_gov_script + ) app = FastAPI() add_cors(app) @@ -25,13 +28,14 @@ async def submit_multiple_proposals( multi_proposal: MultipleProposal, client: httpx.AsyncClient = Depends(get_client), + network: str = Header(...) ): required_proposals = multi_proposal.no_of_proposals base_proposal = get_base_proposal_for_multiple() supported_proposals_in_single_tx = 50 maximum_supported_proposals = 10000 - pparams = await get_protocol_params(client) + pparams = await get_protocol_params(client, network) if required_proposals <= supported_proposals_in_single_tx: tx = await submit_proposal_tx( @@ -40,6 +44,7 @@ async def submit_multiple_proposals( | get_proposal_data_from_type(multi_proposal.proposal_type, pparams), required_proposals, client, + network ) return [{"proposal_count": required_proposals, "tx_hash": tx}] elif required_proposals <= maximum_supported_proposals: @@ -73,6 +78,7 @@ async def submit_multiple_proposals( supported_proposals_in_single_tx, per_proposal_deposit, client, + network ) proposals_numbers_in_last_tx = ( @@ -93,6 +99,7 @@ async def submit_multiple_proposals( if wallet != required_wallets[-1] else proposals_numbers_in_last_tx, client, + network ) for wallet in required_wallets ] @@ -111,21 +118,26 @@ async def submit_multiple_proposals( @app.get("/api/balance") -async def getWalletBalance(client: httpx.AsyncClient = Depends(get_client)): - return await get_ada_balance(main_wallet["address"], client) +async def getWalletBalance(client: httpx.AsyncClient = Depends(get_client), + network: str = Header(...)): + return await get_ada_balance(main_wallet["address"], client, network) @app.post("/api/load/single") async def submit_single_proposal( proposal: Dict[str, Any], client: httpx.AsyncClient = Depends(get_client), + network: str = Header(...) ): default_transaction = get_default_transaction() default_proposal_data = default_transaction["proposals"][0] combined_proposal = default_proposal_data | proposal default_transaction["proposals"][0] = combined_proposal - tx_url = settings.kuber_api_url + "/api/v1/tx?submit=true" + if "withdraw" in combined_proposal or "parameterupdate" in combined_proposal: + if combined_proposal["script"]["cborHex"] == "": + combined_proposal["script"] = get_gov_script() + tx_url = get_api_url(network) + "/api/v1/tx?submit=true" kuber_response = await client.post( tx_url, json=default_transaction, @@ -141,22 +153,3 @@ async def submit_single_proposal( raise HTTPException( status_code=kuber_response.status_code, detail=kuber_response.text ) - - -@app.get("/api/blockfrost/transaction/{tx_hash}") -async def get_transaction_from_blockfrost( - tx_hash: str, - client: httpx.AsyncClient = Depends(get_client), -): - tx_url = settings.blockfrost_api_url + "/txs/" + tx_hash - tx_response = await client.get( - tx_url, - headers={"project_id": settings.blockfrost_project_id}, - ) - if tx_response.status_code == 200: - return tx_response.json() - else: - print(tx_response.text) - raise HTTPException( - status_code=tx_response.status_code, detail=tx_response.json() - ) diff --git a/gov-action-loader/backend/app/models.py b/gov-action-loader/backend/app/models.py index 8a124a885..01bfa4c09 100644 --- a/gov-action-loader/backend/app/models.py +++ b/gov-action-loader/backend/app/models.py @@ -4,3 +4,4 @@ class MultipleProposal(BaseModel): proposal_type: str no_of_proposals: int + \ No newline at end of file diff --git a/gov-action-loader/backend/app/network.py b/gov-action-loader/backend/app/network.py new file mode 100644 index 000000000..5c9fbaa84 --- /dev/null +++ b/gov-action-loader/backend/app/network.py @@ -0,0 +1,15 @@ +from fastapi import HTTPException +from app.settings import settings + +NETWORKS = {"preview", "preprod", "sanchonet"} + +def get_api_url (network): + network_l_case = network.lower() + if network_l_case == "sancho" or network_l_case == "sanchonet": + return settings.kuber_api_url_sancho + elif network_l_case == "preview": + return settings.kuber_api_url_preview + elif network_l_case == "preprod": + return settings.kuber_api_url_preprod + else: + raise HTTPException(status_code=400, detail=f"Invalid network: {network}. Expected: {NETWORKS}") \ No newline at end of file diff --git a/gov-action-loader/backend/app/settings.py b/gov-action-loader/backend/app/settings.py index 02095e720..fa1eff63c 100644 --- a/gov-action-loader/backend/app/settings.py +++ b/gov-action-loader/backend/app/settings.py @@ -2,7 +2,9 @@ class Settings(BaseSettings): - kuber_api_url: str + kuber_api_url_sancho: str + kuber_api_url_preview: str + kuber_api_url_preprod: str kuber_api_key: str = '' settings = Settings() diff --git a/gov-action-loader/backend/app/transaction.py b/gov-action-loader/backend/app/transaction.py index 8b980f5aa..0d9027960 100644 --- a/gov-action-loader/backend/app/transaction.py +++ b/gov-action-loader/backend/app/transaction.py @@ -10,6 +10,7 @@ from fastapi import HTTPException +from app.network import get_api_url from app.settings import settings main_wallet = { @@ -90,12 +91,16 @@ def generate_quorom(): return {"numerator": numerator, "denominator": denomintor} -def generate_hardfork(): - majorProtocolNum = random.randint(1, 9) - minorProtocolNum = random.randint(1, 9) +def generate_hardfork(current_pParams): + protocol_version = [current_pParams["protocolVersion"]["major"], + current_pParams["protocolVersion"]["minor"]] + + # Randomly select an index (0 for major, 1 for minor) and increment it + protocol_version[random.randint(0, 1)] += 1 + return { "hardfork": { - "protocolVersion": {"major": majorProtocolNum, "minor": minorProtocolNum} + "protocolVersion": {"major": protocol_version[0], "minor": protocol_version[1]} } } @@ -115,6 +120,13 @@ def change_pp_value(random_parameter): return random_parameter +def get_gov_script(): + with open("app/data/gov-script.plutus", "r") as script_file: + script_str = script_file.read() + script_json = json.loads(script_str) + return script_json + + def get_proposal_data_from_type(proposal_type, current_pParams): match proposal_type: case "constitution": @@ -126,7 +138,10 @@ def get_proposal_data_from_type(proposal_type, current_pParams): } case "withdrawal": number_of_addresses = random.randint(1, 5) - return {"withdraw": generate_withdraw(number_of_addresses)} + return { + "script": get_gov_script(), + "withdraw": generate_withdraw(number_of_addresses), + } case "no-confidence": return {"noconfidence": True} case "update-committee": @@ -138,7 +153,7 @@ def get_proposal_data_from_type(proposal_type, current_pParams): } } case "hardfork": - return generate_hardfork() + return generate_hardfork(current_pParams) case "update-parameters": # read current protocol parameters from json # get one of the keys of the pp @@ -146,7 +161,10 @@ def get_proposal_data_from_type(proposal_type, current_pParams): keys = pParams.keys() rand_key = random.choice(filter_updatable_paramKeys(list(keys))) # recurse into the innermost element of that key and change it by +-1, all protocol parameter value is either float or int - return {"parameterupdate": {rand_key: change_pp_value(pParams[rand_key])}} + return { + "script": get_gov_script(), + "parameterupdate": {rand_key: change_pp_value(pParams[rand_key])}, + } # added_proposal = case "info": return {} @@ -160,17 +178,42 @@ def get_proposal_data_from_type(proposal_type, current_pParams): def filter_updatable_paramKeys(keys): - updatable_keys = {"maxBlockSize", "maxBBSize", "maxTxSize", "maxBHSize", "keyDeposit", "poolDeposit", "eMax", - "nOpt", "a0", "rho", "tau", "minPoolCost", "coinsPerUTxOByte", "costModels", "prices", - "maxTxExUnits", "maxBlockExUnits", "maxValSize", "collateralPercentage", "maxCollateralInputs", - "poolVotingThresholds", "dRepVotingThresholds", "committeeMinSize", "committeeMaxTermLength", - "govActionLifetime", "govActionDeposit", "dRepDeposit", "dRepActivity"} + updatable_keys = { + "maxBlockSize", + "maxBBSize", + "maxTxSize", + "maxBHSize", + "keyDeposit", + "poolDeposit", + "eMax", + "nOpt", + "a0", + "rho", + "tau", + "minPoolCost", + "coinsPerUTxOByte", + "costModels", + "prices", + "maxTxExUnits", + "maxBlockExUnits", + "maxValSize", + "collateralPercentage", + "maxCollateralInputs", + "poolVotingThresholds", + "dRepVotingThresholds", + "committeeMinSize", + "committeeMaxTermLength", + "govActionLifetime", + "govActionDeposit", + "dRepDeposit", + "dRepActivity", + } return [x for x in keys if x in updatable_keys] -async def submit_tx(tx, client, submit=True): +async def submit_tx(tx, client, network, submit=True): submit_query = "?submit=true" if submit else "" - tx_url = settings.kuber_api_url + "/api/v1/tx" + submit_query + tx_url = get_api_url(network) + "/api/v1/tx" + submit_query response = await client.post( tx_url, json=tx, @@ -187,7 +230,7 @@ async def submit_tx(tx, client, submit=True): raise HTTPException(status_code=response.status_code, detail=response.text) -async def submit_proposal_tx(wallet, proposal, proposal_numbers, client): +async def submit_proposal_tx(wallet, proposal, proposal_numbers, client, network): proposals = [ { **proposal, @@ -202,4 +245,4 @@ async def submit_proposal_tx(wallet, proposal, proposal_numbers, client): "selections": [wallet["address"], wallet["skey"]], "proposals": proposals, } - return await submit_tx(tx, client) + return await submit_tx(tx, client, network) diff --git a/gov-action-loader/frontend/src/App.vue b/gov-action-loader/frontend/src/App.vue index 4a1d5a291..889b6c540 100644 --- a/gov-action-loader/frontend/src/App.vue +++ b/gov-action-loader/frontend/src/App.vue @@ -7,7 +7,8 @@ - + @@ -18,13 +19,19 @@ Bulk Load -

+
-
+ +
+ Loading Balance ... +
+ + +
{{ walletInfo.balance }} Ada
@@ -53,21 +60,7 @@ export default { SpecificLoad, }, mounted() { - const fetchInterval = 7000 - const updateBalance = async () => { - getBalance() - .then((response) => { - if (response.data?.address) { - this.walletInfo.address = response.data.address - this.walletInfo.balance = response.data.totalValue - } - console.log('Wallet balance', response) - }) - .finally(() => { - this.timoutId = setTimeout(updateBalance, fetchInterval) - }) - } - Promise.resolve(updateBalance()) + this.updateBalance() }, unmounted() { if (this.timeoutId) { @@ -78,14 +71,43 @@ export default { return { tab: null, selectedNetwork: 'Sanchonet', // Default selection - networkOptions: ['Mock Database', 'Sanchonet'], + networkOptions: ['Sanchonet', 'Preview', 'Preprod'], walletInfo: { address: null, balance: null, }, timeoutId: null, + fetchInterval: 7000, + loading: true } }, + methods: { + async updateBalance() { + try { + const response = await getBalance(this.selectedNetwork) + if (response.data?.address) { + this.walletInfo.address = response.data.address + this.walletInfo.balance = response.data.totalValue + } + console.log('Wallet balance', response) + } catch (error) { + console.error('Error updating balance:', error) + } finally { + this.timeoutId = setTimeout(this.updateBalance, this.fetchInterval) + this.loading = false; + } + }, + }, + watch: { + selectedNetwork() { + if (this.timeoutId) { + clearTimeout(this.timeoutId) + } + this.loading = true; + this.updateBalance() + + }, + }, } diff --git a/gov-action-loader/frontend/src/api.ts b/gov-action-loader/frontend/src/api.ts index 9d3584daa..5417b587c 100644 --- a/gov-action-loader/frontend/src/api.ts +++ b/gov-action-loader/frontend/src/api.ts @@ -1,24 +1,28 @@ import axios from 'axios' import config from './config' - axios.defaults.headers.common['Content-Type'] = 'application/json' +let NETWORK: string = '' + + export async function submitMultipleProposals(proposalType: string, noOfProposals: number) { const loadMultipleUrl = config.dataLoaderApi + '/api/load/multiple' const data = { proposal_type: proposalType, no_of_proposals: noOfProposals, } - return await axios.post(loadMultipleUrl, data) + return await axios.post(loadMultipleUrl, data, {headers:{network: NETWORK}}) } -export async function getBalance() { +export async function getBalance(selectedNetwork: string) { const loadSingleUrl = config.dataLoaderApi + '/api/balance' - return await axios.get(loadSingleUrl) + NETWORK = selectedNetwork + return await axios.get(loadSingleUrl, {headers:{network: selectedNetwork}}) } export async function submitSingleProposal(data?: any) { const loadSingleUrl = config.dataLoaderApi + '/api/load/single' - return await axios.post(loadSingleUrl, data) + console.log("data: ", data); + return await axios.post(loadSingleUrl, data, {headers:{network: NETWORK}}) } function generateRandomId(length: number) { @@ -61,7 +65,7 @@ export async function submitSingleProposalMock(action: String, data?: any) { url: data['anchor'].url, } break - case 'Withdrawl': + case 'Withdrawal': let withdrawAddress = Object.keys(data['withdraw'])[0] payload = { @@ -116,5 +120,5 @@ export async function submitSingleProposalMock(action: String, data?: any) { break } console.log(payload) - return await axios.post(singleProposalendpoint, payload) + return await axios.post(singleProposalendpoint, payload, {headers:{network: NETWORK}}) } diff --git a/gov-action-loader/frontend/src/views/SpecificLoad.vue b/gov-action-loader/frontend/src/views/SpecificLoad.vue index 9d1181bf4..05fd0507f 100644 --- a/gov-action-loader/frontend/src/views/SpecificLoad.vue +++ b/gov-action-loader/frontend/src/views/SpecificLoad.vue @@ -12,17 +12,13 @@ import config from '../config'
- +
-
-
Previous Gov Action ID (optional)
+
+
Previous Gov Action ID (optional) +
@@ -30,13 +26,8 @@ import config from '../config'
Proposal deposit (optional)
- +
@@ -61,10 +52,11 @@ import config from '../config' - +
- +
- - - - + + + -
+ + + +
+
@@ -101,38 +91,20 @@ import config from '../config' * - - + +
Add To Committee
- - - - + + + -
+ @@ -144,12 +116,10 @@ import config from '../config'
Remove From Committee
- - - + + -
+ @@ -164,20 +134,10 @@ import config from '../config' * - - + +
@@ -188,75 +148,35 @@ import config from '../config' * - - - - - - - - - + + + + + + + + + - - + + - + @@ -289,47 +209,31 @@ import config from '../config' - + - + Copy - - - + + + - + - + Copy @@ -337,66 +241,40 @@ import config from '../config' - + - + Copy - - - - - - + + + + + + + + + +
- + Submitting... Submit @@ -416,7 +294,8 @@ import config from '../config'
Transaction submitted successfully.
@@ -433,6 +312,11 @@ export default { props: { selectedNetwork: String, }, + // watch: { + // selectedNetwork(newValue) { + // setNetwork(newValue); + // } + // }, data() { return { // Data related to governance action form @@ -456,6 +340,8 @@ export default { majorProtocol: '', minorProtocol: '', + guardrailScript: '', + maxblocksize: null, minFeeA: null, MaxBBSize: null, @@ -956,11 +842,17 @@ export default { break case 'Info': break - case 'Withdrawl': + case 'Withdrawal': proposal_data['withdraw'] = this.treasuryWithdrawalAddresses.reduce((obj, key, index) => { obj[key] = parseInt(this.treasuryAmounts[index]) return obj }, {}) + proposal_data['script'] = + { + type: "PlutusScriptV3", + description: "", + cborHex: this.guardrailScript + } break case 'No Confidence': proposal_data['noconfidence'] = true @@ -1015,8 +907,8 @@ export default { ...(this.CommitteeMinSize != null ? { CommitteeMinSize: parseInt(this.CommitteeMinSize) } : {}), ...(this.CommitteeMaxTermLength != null ? { - CommitteeMaxTermLength: parseInt(this.CommitteeMaxTermLength), - } + CommitteeMaxTermLength: parseInt(this.CommitteeMaxTermLength), + } : {}), ...(this.GovActionLifetime != null ? { GovActionLifetime: parseInt(this.GovActionLifetime) } : {}), ...(this.GovActionDeposit != null ? { GovActionDeposit: parseInt(this.GovActionDeposit) } : {}), @@ -1025,12 +917,8 @@ export default { } break } - if (this.selectedNetwork == 'Mock Database') { - console.log('Mock database') - this.submitProposalToMock(this.selectedAction, proposal_data) - } else { - this.submitProposalViaKuber(proposal_data) - } + + this.submitProposalViaKuber(proposal_data) }, submitProposalViaKuber(proposal_data) { this.loading = true diff --git a/govtool/backend/Dockerfile b/govtool/backend/Dockerfile index 38c09931d..c6c0d2827 100644 --- a/govtool/backend/Dockerfile +++ b/govtool/backend/Dockerfile @@ -4,4 +4,4 @@ FROM $BASE_IMAGE_REPO:$BASE_IMAGE_TAG WORKDIR /src COPY . . RUN cabal build -RUN cp dist-newstyle/build/x86_64-linux/ghc-9.2.7/vva-be-1.0.17/x/vva-be/build/vva-be/vva-be /usr/local/bin +RUN cp dist-newstyle/build/x86_64-linux/ghc-9.2.7/vva-be-1.0.18/x/vva-be/build/vva-be/vva-be /usr/local/bin diff --git a/govtool/backend/Dockerfile.qovery b/govtool/backend/Dockerfile.qovery index cdf1acc79..94d4c4fa4 100644 --- a/govtool/backend/Dockerfile.qovery +++ b/govtool/backend/Dockerfile.qovery @@ -4,7 +4,7 @@ FROM $BASE_IMAGE_REPO:$BASE_IMAGE_TAG WORKDIR /src COPY . . RUN cabal build -RUN cp dist-newstyle/build/x86_64-linux/ghc-9.2.7/vva-be-1.0.17/x/vva-be/build/vva-be/vva-be /usr/local/bin +RUN cp dist-newstyle/build/x86_64-linux/ghc-9.2.7/vva-be-1.0.18/x/vva-be/build/vva-be/vva-be /usr/local/bin # Expose the necessary port EXPOSE 9876 diff --git a/govtool/backend/vva-be.cabal b/govtool/backend/vva-be.cabal index 97e5c5692..b269c0e52 100644 --- a/govtool/backend/vva-be.cabal +++ b/govtool/backend/vva-be.cabal @@ -1,6 +1,6 @@ cabal-version: 3.6 name: vva-be -version: 1.0.17 +version: 1.0.18 -- A short (one-line) description of the package. -- synopsis: diff --git a/govtool/frontend/index.html b/govtool/frontend/index.html index 8032b4a36..cb8734a1b 100644 --- a/govtool/frontend/index.html +++ b/govtool/frontend/index.html @@ -24,6 +24,21 @@ +
diff --git a/govtool/frontend/package-lock.json b/govtool/frontend/package-lock.json index fdb9a75d1..43293d7e5 100644 --- a/govtool/frontend/package-lock.json +++ b/govtool/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "@govtool/frontend", - "version": "1.0.17", + "version": "1.0.18", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@govtool/frontend", - "version": "1.0.17", + "version": "1.0.18", "hasInstallScript": true, "dependencies": { "@emotion/react": "^11.11.1", @@ -14,7 +14,7 @@ "@emurgo/cardano-serialization-lib-asmjs": "12.0.0-beta.2", "@hookform/resolvers": "^3.3.1", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "^0.3.8", + "@intersect.mbo/pdf-ui": "^0.3.9", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@rollup/plugin-babel": "^6.0.4", @@ -3551,9 +3551,9 @@ "license": "ISC" }, "node_modules/@intersect.mbo/pdf-ui": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.3.8.tgz", - "integrity": "sha512-eI8Uo2b6Byi7kQKOYA7TGCj3h96P4WP+kv0ZHKCPs/yVR6w1IGQHrXmBM9B0SlXh/gAQvW/kzTeZyL+nnL5ZOg==", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.3.9.tgz", + "integrity": "sha512-KL2bd3Q7EuG0iYCdw19k8uABfr0NYmEaFkgwiXxNOAubGmUeZW/uognbfSl5hWdJIbJ3XZ68GCIW1JhrskgCHg==", "dependencies": { "@emurgo/cardano-serialization-lib-asmjs": "^12.0.0-beta.2", "@fontsource/poppins": "^5.0.14", diff --git a/govtool/frontend/package.json b/govtool/frontend/package.json index 541024da5..7a3b7cc66 100644 --- a/govtool/frontend/package.json +++ b/govtool/frontend/package.json @@ -1,7 +1,7 @@ { "name": "@govtool/frontend", "private": true, - "version": "1.0.17", + "version": "1.0.18", "type": "module", "scripts": { "build": "vite build", @@ -28,7 +28,7 @@ "@emurgo/cardano-serialization-lib-asmjs": "12.0.0-beta.2", "@hookform/resolvers": "^3.3.1", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "^0.3.8", + "@intersect.mbo/pdf-ui": "^0.3.9", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@rollup/plugin-babel": "^6.0.4", @@ -109,5 +109,5 @@ "typescript": "^5.0.2" }, "readme": "ERROR: No README data found!", - "_id": "govtool@1.0.17" + "_id": "govtool@1.0.18" } diff --git a/govtool/frontend/src/components/atoms/StakeRadio.tsx b/govtool/frontend/src/components/atoms/StakeRadio.tsx index c7360ca62..8c7e4c57f 100644 --- a/govtool/frontend/src/components/atoms/StakeRadio.tsx +++ b/govtool/frontend/src/components/atoms/StakeRadio.tsx @@ -2,8 +2,13 @@ import { Dispatch, FC, SetStateAction } from "react"; import { Box, IconButton, Typography } from "@mui/material"; import { ICONS } from "@consts"; -import { useScreenDimension } from "@hooks"; +import { + useGetAdaHolderVotingPowerQuery, + useScreenDimension, + useTranslation, +} from "@hooks"; import { theme } from "@/theme"; +import { correctAdaFormat } from "@/utils"; type StakeRadioProps = { isChecked?: boolean; @@ -18,9 +23,9 @@ export const StakeRadio: FC = ({ ...props }) => { palette: { boxShadow1 }, } = theme; const { isMobile } = useScreenDimension(); - // const { powerIsLoading, votingPower } = - // useGetAdaHolderVotingPowerQuery(stakeKey); - // const { t } = useTranslation(); + const { powerIsLoading, votingPower } = + useGetAdaHolderVotingPowerQuery(stakeKey); + const { t } = useTranslation(); return ( = ({ ...props }) => { /> - {/* TODO uncomment when voting power value s correct */} - {/* + - {t("votingPower")} - : + {t("votingPower")}: {powerIsLoading ? ( @@ -82,7 +85,7 @@ export const StakeRadio: FC = ({ ...props }) => { ₳ {correctAdaFormat(votingPower) ?? 0} )} - */} + ); diff --git a/govtool/frontend/src/components/atoms/modal/ModalWrapper.tsx b/govtool/frontend/src/components/atoms/modal/ModalWrapper.tsx index 807cded95..772063fc5 100644 --- a/govtool/frontend/src/components/atoms/modal/ModalWrapper.tsx +++ b/govtool/frontend/src/components/atoms/modal/ModalWrapper.tsx @@ -32,6 +32,8 @@ export const BaseWrapper = styled("div")>` width: 80vw; max-width: 510px; padding: 52px 24px 34px 24px; + max-height: 80vh; + overflow: auto; `; } if (variant === "popup") { diff --git a/govtool/frontend/src/components/molecules/AutomatedVotingCard.tsx b/govtool/frontend/src/components/molecules/AutomatedVotingCard.tsx index 855631938..729a02523 100644 --- a/govtool/frontend/src/components/molecules/AutomatedVotingCard.tsx +++ b/govtool/frontend/src/components/molecules/AutomatedVotingCard.tsx @@ -1,4 +1,4 @@ -import { Box } from "@mui/material"; +import { Box, Divider } from "@mui/material"; import { Button, Typography } from "@atoms"; import { primaryBlue } from "@consts"; @@ -20,6 +20,7 @@ export const AutomatedVotingCard = ({ onClickInfo, title, transactionId, + votingPower, }: AutomatedVotingCardProps) => { const { cExplorerBaseUrl } = useAppContext(); const { isMobile, screenWidth } = useScreenDimension(); @@ -83,8 +84,7 @@ export const AutomatedVotingCard = ({ {!inProgress && !isSelected && ( <> - {/* TODO uncomment when voting power value s correct */} - {/* */} + /> { const { isVotingOnGovernanceActionEnabled } = useFeatureFlag(); const { screenWidth } = useScreenDimension(); @@ -52,29 +39,15 @@ export const GovernanceActionDetailsCardVotes = ({ p: `40px ${isModifiedPadding ? "24px" : "80px"}`, }} > - {isVoter && isVotingOnGovernanceActionEnabled(type) ? ( + {isVoter && isVotingOnGovernanceActionEnabled(proposal.type) ? ( ) : ( - + )} ); diff --git a/govtool/frontend/src/components/molecules/VoteActionForm.tsx b/govtool/frontend/src/components/molecules/VoteActionForm.tsx index 964edcf5c..79e13120b 100644 --- a/govtool/frontend/src/components/molecules/VoteActionForm.tsx +++ b/govtool/frontend/src/components/molecules/VoteActionForm.tsx @@ -13,28 +13,22 @@ import { useGetVoteContextTextFromFile, } from "@hooks"; import { formatDisplayDate } from "@utils"; -import { ProposalVote } from "@/models"; +import { ProposalData, ProposalVote } from "@/models"; +import { VoteContextModalState, SubmittedVotesModalState } from "../organisms"; type VoteActionFormProps = { setIsVoteSubmitted: Dispatch>; - expiryDate: string | undefined; - expiryEpochNo: number | undefined; isInProgress?: boolean; previousVote?: ProposalVote; - dRepYesVotes: number; - dRepNoVotes: number; - dRepAbstainVotes: number; + proposal: ProposalData; }; export const VoteActionForm = ({ setIsVoteSubmitted, - expiryDate, - expiryEpochNo, previousVote, - dRepAbstainVotes, - dRepNoVotes, - dRepYesVotes, isInProgress, + proposal, + proposal: { expiryDate, expiryEpochNo }, }: VoteActionFormProps) => { const [voteContextHash, setVoteContextHash] = useState(); const [voteContextUrl, setVoteContextUrl] = useState(); @@ -59,9 +53,9 @@ export const VoteActionForm = ({ canVote, } = useVoteActionForm({ previousVote, voteContextHash, voteContextUrl }); - const setVoteContextData = (url: string, hash: string) => { + const setVoteContextData = (url: string, hash: string | null) => { setVoteContextUrl(url); - setVoteContextHash(hash); + setVoteContextHash(hash ?? undefined); }; useEffect(() => { @@ -215,13 +209,11 @@ export const VoteActionForm = ({ }} onClick={() => { openModal({ - type: "votingPower", + type: "submittedVotes", state: { - dRepYesVotes, - dRepNoVotes, - dRepAbstainVotes, + ...proposal, vote: previousVote?.vote, - }, + } satisfies SubmittedVotesModalState, }); }} > @@ -309,7 +301,7 @@ export const VoteActionForm = ({ type: "voteContext", state: { onSubmit: setVoteContextData, - }, + } satisfies VoteContextModalState, }); }} sx={{ diff --git a/govtool/frontend/src/components/molecules/VotesSubmitted.tsx b/govtool/frontend/src/components/molecules/VotesSubmitted.tsx index d148a49a9..8edd31219 100644 --- a/govtool/frontend/src/components/molecules/VotesSubmitted.tsx +++ b/govtool/frontend/src/components/molecules/VotesSubmitted.tsx @@ -4,17 +4,10 @@ import { IMAGES } from "@consts"; import { VotePill } from "@atoms"; import { useTranslation } from "@hooks"; import { correctAdaFormat } from "@utils"; +import { SubmittedVotesData } from "@models"; type Props = { - dRepYesVotes: number; - dRepNoVotes: number; - dRepAbstainVotes: number; - poolYesVotes: number; - poolNoVotes: number; - poolAbstainVotes: number; - ccYesVotes: number; - ccNoVotes: number; - ccAbstainVotes: number; + votes: SubmittedVotesData; }; const Vote = ({ @@ -39,15 +32,17 @@ const Vote = ({ ); export const VotesSubmitted = ({ - dRepAbstainVotes, - dRepNoVotes, - dRepYesVotes, - poolAbstainVotes, - poolNoVotes, - poolYesVotes, - ccAbstainVotes, - ccNoVotes, - ccYesVotes, + votes: { + dRepYesVotes, + dRepAbstainVotes, + dRepNoVotes, + poolYesVotes, + poolAbstainVotes, + poolNoVotes, + ccYesVotes, + ccAbstainVotes, + ccNoVotes, + }, }: Props) => { const { t } = useTranslation(); diff --git a/govtool/frontend/src/components/organisms/DRepCard.tsx b/govtool/frontend/src/components/organisms/DRepCard.tsx index 8391f3f1c..95e611c2e 100644 --- a/govtool/frontend/src/components/organisms/DRepCard.tsx +++ b/govtool/frontend/src/components/organisms/DRepCard.tsx @@ -19,6 +19,7 @@ type DRepCardProps = { isDelegationLoading?: boolean; isInProgress?: boolean; isMe?: boolean; + isMyDrep?: boolean; onDelegate?: () => void; }; @@ -28,6 +29,7 @@ export const DRepCard = ({ isDelegationLoading, isInProgress, isMe, + isMyDrep, onDelegate, }: DRepCardProps) => { const navigate = useNavigate(); @@ -209,6 +211,7 @@ export const DRepCard = ({ {status === "Active" && isConnected && onDelegate && + !isMyDrep && !isInProgress && (