Skip to content

Commit c5b959b

Browse files
committed
Adding new feature - Catalyst VotingPower query
09a_catalystVote.sh / 09a_vatalystVoteF10.sh: Added a query feature so you can now verify your registered Voting-Power. This works on MainNet and on TestNet, because its a combined API at the moment. The result is the currently registered total Voting-Power, and all the Delegators/Delegations that are done to that Voting-Key. Queries can be done by providing the name of the Voting-Key file, by providing a bech encoded Voting-Key or by directly providing a hex encoded Voting-Key like: - 09a_catalystVoteF10.sh query myvote-test - 09a_catalystVoteF10.sh query cvote_vk1lca8dhe30dtmuk4yq3c9f20af0jk7ne9vhzhemheczjtpy3dq85qcdzn3e - 09a_catalystVoteF10.sh query fe3a76df317b57be5aa4047054a9fd4be56f4f2565c57ceef9c0a4b0922d01e8
1 parent 78c6aaa commit c5b959b

File tree

4 files changed

+351
-13
lines changed

4 files changed

+351
-13
lines changed

cardano/mainnet/00_common.sh

+8-1
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ case "${network,,}" in
154154
_transactionExplorer="https://cardanoscan.io/transaction/" #URLS for the Transaction-Explorers -> autoresolve into ${transactionExplorer}/
155155
_koiosAPI="https://api.koios.rest/api/v0" #Koios-API URLs -> autoresolve into ${koiosAPI}
156156
_adahandlePolicyID="f0ff48bbb7bbe9d59a40f1ce90e9e9d0ff5002ec48f232b49ca0fb9a" #PolicyIDs for the adaHandles -> autoresolve into ${adahandlePolicyID}
157+
_catalystAPI="https://api.testnet.projectcatalyst.io/api/v1" #Catalyst-API URLs -> autoresolve into ${catalystAPI}
157158
;;
158159

159160

@@ -166,6 +167,7 @@ case "${network,,}" in
166167
_transactionExplorer="https://preprod.cardanoscan.io/transaction"
167168
_koiosAPI="https://preprod.koios.rest/api/v0"
168169
_adahandlePolicyID="f0ff48bbb7bbe9d59a40f1ce90e9e9d0ff5002ec48f232b49ca0fb9a" #PolicyIDs for the adaHandles -> autoresolve into ${adahandlePolicyID}
170+
_catalystAPI="https://api.testnet.projectcatalyst.io/api/v1" #Catalyst-API URLs -> autoresolve into ${catalystAPI}
169171
;;
170172

171173

@@ -178,6 +180,7 @@ case "${network,,}" in
178180
_transactionExplorer="https://preview.cardanoscan.io/transaction"
179181
_koiosAPI="https://preview.koios.rest/api/v0"
180182
_adahandlePolicyID="f0ff48bbb7bbe9d59a40f1ce90e9e9d0ff5002ec48f232b49ca0fb9a" #PolicyIDs for the adaHandles -> autoresolve into ${adahandlePolicyID}
183+
_catalystAPI="https://api.testnet.projectcatalyst.io/api/v1" #Catalyst-API URLs -> autoresolve into ${catalystAPI}
181184
;;
182185

183186

@@ -190,6 +193,7 @@ case "${network,,}" in
190193
_transactionExplorer=
191194
_koiosAPI="https://guild.koios.rest/api/v0"
192195
_adahandlePolicyID="f0ff48bbb7bbe9d59a40f1ce90e9e9d0ff5002ec48f232b49ca0fb9a" #PolicyIDs for the adaHandles -> autoresolve into ${adahandlePolicyID}
196+
_catalystAPI= #Catalyst-API URLs -> autoresolve into ${catalystAPI}
193197
;;
194198

195199

@@ -202,6 +206,7 @@ case "${network,,}" in
202206
_transactionExplorer="https://testnet.cexplorer.io/tx"
203207
_koiosAPI=
204208
_adahandlePolicyID="8d18d786e92776c824607fd8e193ec535c79dc61ea2405ddf3b09fe3"
209+
_catalystAPI= #Catalyst-API URLs -> autoresolve into ${catalystAPI}
205210
;;
206211

207212
esac
@@ -215,12 +220,14 @@ tokenMetaServer=${tokenMetaServer:-"${_tokenMetaServer}"}
215220
transactionExplorer=${transactionExplorer:-"${_transactionExplorer}"}
216221
koiosAPI=${koiosAPI:-"${_koiosAPI}"}
217222
adahandlePolicyID=${adahandlePolicyID:-"${_adahandlePolicyID}"}
223+
catalystAPI=${catalystAPI:-"${_catalystAPI}"}
218224

219225

220226
#Check about the / at the end of the URLs
221227
if [[ "${tokenMetaServer: -1}" == "/" ]]; then tokenMetaServer=${tokenMetaServer%?}; fi #make sure the last char is not a /
222228
if [[ "${koiosAPI: -1}" == "/" ]]; then koiosAPI=${koiosAPI%?}; fi #make sure the last char is not a /
223229
if [[ "${transactionExplorer: -1}" == "/" ]]; then transactionExplorer=${transactionExplorer%?}; fi #make sure the last char is not a /
230+
if [[ "${catalystAPI: -1}" == "/" ]]; then catalystAPI=${catalystAPI%?}; fi #make sure the last char is not a /
224231

225232

226233
#Check about the needed chain params
@@ -558,7 +565,7 @@ if [[ ! "${tmpEra}" == "auto" ]]; then nodeEraParam="--${tmpEra}-era"; else node
558565

559566
#Temporary fix to lock the transaction build-raw to alonzo era for
560567
#Hardware-Wallet operations. Babbage-Era is not yet supported, so we will lock this for now
561-
#if [[ "${nodeEraParam}" == "" ]] || [[ "${nodeEraParam}" == "--babbage-era" ]]; then nodeEraParam="--alonzo-era"; fi
568+
if [[ "${nodeEraParam}" == "" ]] || [[ "${nodeEraParam}" == "--conway-era" ]]; then nodeEraParam="--babbage-era"; fi
562569

563570

564571
#-------------------------------------------------------

cardano/mainnet/09a_catalystVote.sh

+172-6
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ Usage: $(basename $0) new cli <voteKeyName> ... Generat
2424
2525
$(basename $0) qrcode <voteKeyName> <4-Digit-PinCode> ... Shows the QR code for the Catalyst-Voting-App protected via a 4-digit PinCode
2626
27+
$(basename $0) query <voteKeyName|voteBechPublicKey> ... Queries the Catalyst-API for the Voting-Power and Delegations for a VotingKey
28+
2729
2830
Examples:
2931
@@ -53,13 +55,13 @@ payPath=0 #set default paymentPath
5355
paramCnt=$#;
5456
allParameters=( "$@" )
5557

56-
if [[ ${paramCnt} -lt 3 ]]; then showUsage; exit 1; fi
57-
5858
case ${1,,} in
5959

6060
### Generate the QR code from the vote secret key for the mobile voting app
6161
qrcode )
6262

63+
if [[ ${paramCnt} -lt 3 ]]; then showUsage; exit 1; fi
64+
6365
#Check the catalyst-toolbox binary existance and version
6466
if ! exists "${catalyst_toolbox_bin}"; then
6567
#Try the one in the scripts folder
@@ -70,7 +72,7 @@ case ${1,,} in
7072
if [[ $? -ne 0 ]]; then echo -e "\e[35mERROR - This script needs a working 'catalyst-toolbox' binary. Please make sure you have it present with with the right path in '00_common.sh' !\e[0m\n\n"; exit 1; fi
7173
catalystToolboxVersion=$(echo ${catalystToolboxCheck} | cut -d' ' -f 2)
7274
versionCheck "${minCatalystToolboxVersion}" "${catalystToolboxVersion}"
73-
if [[ $? -ne 0 ]]; then majorError "Version ${catalystToolboxVersion} ERROR - Please use a cardano-toolbox version ${minCatalystToolboxVersion} or higher !\nOld versions are not compatible, please upgrade - thx."; exit 1; fi
75+
if [[ $? -ne 0 ]]; then majorError "Version ${catalystToolboxVersion} ERROR - Please use a catalyst-toolbox version ${minCatalystToolboxVersion} or higher !\nOld versions are not compatible, please upgrade - thx."; exit 1; fi
7476

7577
voteKeyName="${allParameters[1]}"; voteKeyName=${voteKeyName/#.\//};
7678
pinCode="${allParameters[2]}";
@@ -112,7 +114,9 @@ case ${1,,} in
112114

113115
### Generate new Voting Keys
114116
new )
115-
if [[ ${paramCnt} -ge 3 ]]; then
117+
118+
if [[ ${paramCnt} -lt 3 ]]; then showUsage; exit 1;
119+
elif [[ ${paramCnt} -ge 3 ]]; then
116120
method="${allParameters[1]}";
117121
voteKeyName="${allParameters[2]}"; voteKeyName=${voteKeyName/#.\//};
118122
else echo -e "\e[35mMissing parameters!\e[0m\n"; showUsage; exit 1; fi
@@ -203,7 +207,7 @@ case ${1,,} in
203207
hw )
204208

205209
#We need a voting keypair with vkey and hwsfile from a Hardware-Key, so lets create them
206-
start_HwWallet; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi
210+
start_HwWallet "" "6.0.3" ""; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi
207211
tmp=$(${cardanohwcli} address key-gen --path 1694H/1815H/${accountNo}H/${payPath}/${indexNo} --verification-key-file "${voteKeyName}.voting.vkey" --hw-signing-file "${voteKeyName}.voting.hwsfile" 2> /dev/stdout)
208212
if [[ "${tmp^^}" =~ (ERROR|DISCONNECT) ]]; then echo -e "\e[35m${tmp}\e[0m\n"; exit 1; else echo -e "\e[32mDONE\e[0m\n"; fi
209213
checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi
@@ -400,7 +404,7 @@ case ${1,,} in
400404
echo -e "\e[0mNonce (current slotHeight): \e[32m${currentTip}\e[0m"
401405
echo
402406

403-
start_HwWallet; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi
407+
start_HwWallet "" "6.0.3" ""; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi
404408
tmp=$(${cardanohwcli} vote registration-metadata ${cardanoHwCliParameters} --stake-signing-key-hwsfile "${stakeAcct}.hwsfile" --metadata-cbor-out-file "${votingMetaFile}" 2> /dev/stdout)
405409
if [[ "${tmp^^}" =~ (ERROR|DISCONNECT) ]]; then echo -e "\e[35m${tmp}\e[0m\n"; exit 1; else echo -e "\e[32mDONE\e[0m\n"; fi
406410
checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi
@@ -456,6 +460,168 @@ case ${1,,} in
456460
;;
457461

458462

463+
### Query the Catalyst-API for the voteKey -> VotingPower and Delegations
464+
query )
465+
466+
#Query only possible if not offline mode
467+
if ${offlineMode}; then
468+
echo -e "\e[35mYou have to be in ONLINE MODE to do this!\e[0m\n"; exit 1;
469+
fi
470+
471+
#Check that there is actually a catalystAPI available for this network
472+
if [[ ${catalystAPI} == "" ]]; then
473+
echo -e "\e[35mThere is no Catalyst-API available for this network, i am sorry!\e[0m\n"; exit 1;
474+
fi
475+
476+
#Check about 1 input parameters
477+
if [[ ${paramCnt} -ne 2 ]]; then echo -e "\e[35mIncorrect parameter count!\e[0m\n"; showUsage; exit 1; fi
478+
479+
echo -e "\e[0mQuery the Catalyst-API (${catalystAPI}) for the following Voting-Key\e[0m"
480+
echo
481+
482+
#Read the votePublicKey information
483+
voteKeyName="${allParameters[1]}"
484+
485+
#check the voteKeyName entry if it is a .pkey file (contains the bech pubKey), or if is a .vkey file (contains the key in hex format) or if it is a direct bech or hex key
486+
if [ -f "${voteKeyName}.voting.pkey" ]; then #the .pkey file exists so lets read the value in it and check it if its a bech key
487+
inputKey=$(cat "${voteKeyName}.voting.pkey")
488+
tmp=$(${bech32_bin} <<< "${inputKey}" 2> /dev/null)
489+
if [ $? -ne 0 ]; then echo -e "\e[35mError - ${voteKeyName}.voting.pkey contains an invalid bech votePublicKey !\e[0m\n"; exit 1; fi
490+
votePubKey=$(${bech32_bin} "cvote_vk" <<< "${inputKey}" 2> /dev/null) #make sure it is a bechKey "cvote_vk"
491+
checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi
492+
voteKeySource="${voteKeyName}.voting.pkey"
493+
elif [ -f "${voteKeyName}.voting.vkey" ]; then #the .vkey file exists so lets read the value in it and check it
494+
cborVoteKey=$(jq -r ".cborHex" "${voteKeyName}.voting.vkey" 2> /dev/null);
495+
if [[ $? -ne 0 ]]; then echo -e "\e[35mERROR - ${voteKeyName}.voting.vkey is not a valid json file. Please make sure to use the new voting key format, you can generate it with the subcommand 'new' !\e[0m\n\n"; exit 1; fi
496+
#Generate the voting key bech format
497+
inputKey=${cborVoteKey:4}
498+
votePubKey=$(${bech32_bin} "cvote_vk" <<< ${inputKey:0:64} 2> /dev/null) #only use the first 64chars (32 bytes) in case an extended key was provided
499+
checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi
500+
voteKeySource="${voteKeyName}.voting.vkey"
501+
502+
elif [[ "${voteKeyName//[![:xdigit:]]}" == "${voteKeyName}" ]] && [[ ${#voteKeyName} -eq 64 || ${#voteKeyName} -eq 128 ]]; then #lets use a hex key as the voteKeyName with length of 32 or 64 bytes
503+
#Generate the voting key from hex input
504+
inputKey=${voteKeyName,,}
505+
votePubKey=$(${bech32_bin} "cvote_vk" <<< ${inputKey:0:64} 2> /dev/null) #only use the first 64chars (32 bytes) in case an extended key was provided
506+
checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi
507+
voteKeySource="direct"
508+
voteKeyName="Hex-VotePublicKey"
509+
510+
else #ok lets try to read in the voteKeyName as a direct bech key
511+
inputKey="${voteKeyName}"
512+
tmp=$(${bech32_bin} <<< "${inputKey}" 2> /dev/null)
513+
if [ $? -ne 0 ]; then echo -e "\e[35mError - ${voteKeyName}.voting.pkey/vkey file not found. Also it is not a direct valid bech or hex votePublicKey !\e[0m\n"; exit 1; fi
514+
votePubKey=$(${bech32_bin} "cvote_vk" <<< "${inputKey}" 2> /dev/null) #make sure it is a bechKey "cvote_vk"
515+
checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi
516+
voteKeySource="direct"
517+
voteKeyName="Bech-VotePublicKey"
518+
fi
519+
520+
echo -e "\e[0m Name: \e[32m${voteKeyName}\n\e[0m Source: \e[32m${voteKeySource}\n\e[0m inputKey: \e[32m${inputKey}\n\e[0m votePubKey: \e[32m${votePubKey}\e[0m\n"
521+
522+
523+
524+
#votePubKey is always in bech format at this point, so lets get the hex format for the api query
525+
voteKeyHex=$(${bech32_bin} <<< "${votePubKey}" 2> /dev/null) #convert the displayed votePubKey(Bech) into the Hex-Representation
526+
527+
#query the voteKeyHex via the catalyst-api, try it 5 times
528+
retrycnt=5
529+
while [[ ${retrycnt} -gt 0 ]]; do
530+
echo -n "Requesting information via the Catalyst-API ... "
531+
response=$(curl -s -m 10 -X GET "${catalystAPI}/registration/voter/0x${voteKeyHex}?with_delegators=true" -H "accept: application/json" 2> /dev/null)
532+
if [[ $? -ne 0 ]]; then #curl existed with an error
533+
echo -e "\e[31mError - Bad response!\e[0m";
534+
retrycnt=$(( ${retrycnt} - 1 ));
535+
else #curl exited ok, so lets check the response content
536+
voter_info=$(jq -r ".voter_info" 2> /dev/null <<< ${response})
537+
if [[ "${voter_info}" == "" || "${voter_info}" == "null" ]]; then #no data available
538+
echo -e "\e[35mThere is no data available (yet) for this Voting-Key!\e[0m\n\n";
539+
exit 1;
540+
else
541+
break; #good answer found
542+
fi
543+
fi
544+
done
545+
546+
#exit if all retries were used to get an answer
547+
if [[ ${retrycnt} -eq 0 ]]; then
548+
echo -e "\n\e[35mError - Something went wrong, the Catalyst-API server is not reachable correctly!\e[0m\n\n";
549+
exit 1;
550+
fi
551+
552+
#entry for the 'voter_info' found
553+
echo -e "\e[32mDONE\e[0m\n"
554+
555+
#get the values
556+
voting_power=$(jq -r ".voting_power" <<< ${voter_info})
557+
delegator_count=$(jq -r ".delegator_addresses | length" <<< ${voter_info})
558+
delegator_addresses=(); readarray -t delegator_addresses <<< $(jq -r ".delegator_addresses | .[]" <<< ${voter_info})
559+
registration_lastupdated=$(jq -r ".last_updated" <<< ${response})
560+
registration_finalized=$(jq -r ".final" <<< ${response})
561+
562+
echo -e "\e[0m Last updated: \e[32m$(date --date="${registration_lastupdated}")\e[0m"
563+
echo -e "\e[0m Is Finalized: \e[32m${registration_finalized}\e[0m"
564+
echo
565+
echo -e "\e[0m Voting-Power: \e[33m$(convertToADA ${voting_power}) ADA\e[0m"
566+
echo -e "\e[0m Delegator-Count: \e[32m${delegator_count}\e[0m"
567+
echo
568+
echo -e "\e[0m ---------------- \e[0m"
569+
echo
570+
571+
#list all addresses(vkeys -> resolve to stakeaddresses -> get detailed infos again via the api)
572+
for (( tmpCnt=0; tmpCnt<${delegator_count}; tmpCnt++ ))
573+
do
574+
delegator_vkey=${delegator_addresses[${tmpCnt}]:2};
575+
576+
#get the stakeaddress from the vkey hash
577+
if [[ "${magicparam}" == *"mainnet"* ]]; then
578+
delegator_stakeaddress=$(echo -n "e1$(xxd -r -ps <<< "${delegator_vkey}" | b2sum -l 224 -b | cut -d' ' -f 1)" | ./bech32 "stake");
579+
else
580+
delegator_stakeaddress=$(echo -n "e0$(xxd -r -ps <<< "${delegator_vkey}" | b2sum -l 224 -b | cut -d' ' -f 1)" | ./bech32 "stake_test");
581+
fi
582+
583+
echo -e "\e[0m Delegator: $(( ${tmpCnt} + 1))\e[0m"
584+
echo -e "\e[0m Public-Key: \e[32m${delegator_vkey}\e[0m"
585+
echo -e "\e[0m Stake-Address: \e[32m${delegator_stakeaddress}\e[0m"
586+
587+
#get details about the current delegator
588+
#query the delegator publicKey (vkey) via the catalyst-api, try it 5 times
589+
retrycnt=5
590+
delegator_rewardaddress="\e[35mquery error\e[0m";
591+
delegator_rawpower=0;
592+
showProcessAnimation "Requesting information via the Catalyst-API: " &
593+
while [[ ${retrycnt} -gt 0 ]]; do
594+
response=$(curl -s -m 10 -X GET "${catalystAPI}/registration/delegations/0x${delegator_vkey}" -H "accept: application/json" 2> /dev/null)
595+
if [[ $? -ne 0 ]]; then #curl existed with an error
596+
retrycnt=$(( ${retrycnt} - 1 ));
597+
else #curl exited ok, so lets check the response content
598+
delegator_rewardaddress=$(jq -r ".reward_address" 2> /dev/null <<< ${response})
599+
if [[ "${delegator_rewardaddress}" != "" && "${delegator_rewardaddress}" != "null" ]]; then #valid data found
600+
delegator_rawpower=$(jq -r ".raw_power" 2> /dev/null <<< ${response})
601+
break;
602+
else #no valid data found
603+
delegator_rewardaddress="\e[35mquery error\e[0m";
604+
break;
605+
fi
606+
fi
607+
done
608+
stopProcessAnimation;
609+
610+
#if we used all retry counts, we failed to get data
611+
if [[ ${retrycnt} -eq 0 ]]; then delegator_rewardaddress="\e[35mquery error\e[0m"; fi
612+
613+
echo -e "\e[0m Rewards-Address: \e[32m${delegator_rewardaddress}\e[0m"
614+
echo -e "\e[0m Raw-Power: \e[33m$(convertToADA ${delegator_rawpower}) ADA\e[0m"
615+
echo
616+
617+
done
618+
619+
echo
620+
621+
exit 0;
622+
;;
623+
624+
459625
* ) showUsage; exit 1;
460626
;;
461627
esac

0 commit comments

Comments
 (0)