diff --git a/cardano/mainnet/00_common.sh b/cardano/mainnet/00_common.sh index 1dd72068..8a4eda44 100755 --- a/cardano/mainnet/00_common.sh +++ b/cardano/mainnet/00_common.sh @@ -1,4 +1,4 @@ -#!/bin/bash +##!/bin/bash unset magicparam network addrformat ############################################################################################################################## @@ -12,47 +12,55 @@ unset magicparam network addrformat ############################################################################################################################## -#--------- Set the Path to your node socket file and to your genesis files here --------- -socket="db-mainnet/node.socket" #Path to your cardano-node socket for machines in online-mode. Another example would be "$HOME/cnode/sockets/node.socket" -genesisfile="configuration-mainnet/mainnet-shelley-genesis.json" #Shelley-Genesis path, you can also use the placeholder $HOME to specify your home directory -genesisfile_byron="configuration-mainnet/mainnet-byron-genesis.json" #Byron-Genesis path, you can also use the placeholder $HOME to specify your home directory +#--------- Workmode: online, light, offline --- please read the instructions on the github repo README :-) +workMode="online" #change this to "online" if your machine is online and you run a local node with, this is also know as full-mode + #change this to "light" if your machine is online but you don't run a local node (all requests are done via online APIs like koios, adahandle, etc.) + #change this to "offline" if you run these scripts on a cold machine, needs a counterpart with is set to "online" or "light" on a hot machine #--------- Set the Path to your main binaries here --------- -cardanocli="./cardano-cli" #Path to your cardano-cli binary you wanna use. If your binary is present in the Path just set it to "cardano-cli" without the "./" infront -cardanonode="./cardano-node" #Path to your cardano-node binary you wanna use. If your binary is present in the Path just set it to "cardano-node" without the "./" infront -bech32_bin="./bech32" #Path to your bech32 binary you wanna use. If your binary is present in the Path just set it to "bech32" without the "./" infront - +cardanocli="./cardano-cli" #Path to your cardano-cli binary you wanna use. If your binary is present in the Path just set it to "cardano-cli" without the "./" infront +cardanosigner="./cardano-signer" #Path to your cardano-signer binary you wanna use. If your binary is present in the Path just set it to "cardano-signer" without the "./" infront +bech32_bin="./bech32" #Path to your bech32 binary you wanna use. If your binary is present in the Path just set it to "bech32" without the "./" infront -#--------- You can work in offline mode too, please read the instructions on the github repo README :-) -offlineMode="no" #change this to "yes" if you run these scripts on a cold machine, it need a counterpart with set to "no" on a hot machine -offlineFile="./offlineTransfer.json" #path to the filename (JSON) that will be used to transfer the data between a hot and a cold machine #------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -#--------- Only needed if you wanna do catalyst voting or include your itn witness for your pool-ticker -cardanosigner="./cardano-signer" #Path to your cardano-signer binary you wanna use. If your binary is present in the Path just set it to "cardano-signer" without the "./" infront +#--------- Only needed if you run in online mode with a local node (aka FullMode) +cardanonode="./cardano-node" #Path to your cardano-node binary you wanna use. If your binary is present in the Path just set it to "cardano-node" without the "./" infront +socket="db/node.socket" #Path to your cardano-node socket for machines in online-mode. Another example would be "$HOME/cnode/sockets/node.socket" -#--------- Only needed if you wanna do catalyst voting -catalyst_toolbox_bin="./catalyst-toolbox" #Path to your catalyst-toolbox binary you wanna use. If your binary is present in the Path just set it to "catalyst-toolbox" without the "./" infront +#--------- Only needed for offline mode and pool-operations --------- +genesisfile="$HOME/cardano/mainnet-shelley-genesis.json" #Shelley-Genesis path, you can also use the placeholder $HOME to specify your home directory +genesisfile_byron="$HOME/cardano/mainnet-byron-genesis.json" #Byron-Genesis path, you can also use the placeholder $HOME to specify your home directory #--------- Only needed if you wanna use a hardware key (Ledger/Trezor) too, please read the instructions on the github repo README :-) cardanohwcli="cardano-hw-cli" #Path to your cardano-hw-cli binary you wanna use. If your binary is present in the Path just set it to "cardano-hw-cli" without the "./" infront +#--------- Only needed if you wanna do online/offline hot/cold machine transfers +offlineFile="./offlineTransfer.json" #path to the filename (JSON) that will be used to transfer the data between a hot and a cold machine + + +#--------- Only needed if you wanna do catalyst voting +catalyst_toolbox_bin="./catalyst-toolbox" #Path to your catalyst-toolbox binary you wanna use. If your binary is present in the Path just set it to "catalyst-toolbox" without the "./" infront + + #--------- Only needed if you wanna generate the right format for the NativeAsset Metadata Registry cardanometa="./token-metadata-creator" #Path to your token-metadata-creator binary you wanna use. If present in the Path just set it to "token-metadata-creator" without the "./" infront + #--------- Only needed if you wanna change the BlockChain from the Mainnet to a Testnet Chain Setup, uncomment the network you wanna use by removing the leading # # Using a preconfigured network name automatically loads and sets the magicparam, addrformat and byronToShelleyEpochs parameters, also API-URLs, etc. #network="Mainnet" #Mainnet (Default) #network="PreProd" #PreProd Testnet (new default Testnet) #network="Preview" #Preview Testnet (new fast Testnet) +#network="Sancho" #SanchoNet Testnet (new governance Testnet) #network="Legacy" #Legacy TestChain (formally known as Public-Testnet) #network="GuildNet" #GuildNet Testnet @@ -124,10 +132,11 @@ echo -e "\e[35m${1}\n\nIf you think all is right at your side, please check the } #------------------------------------------------------- + #API Endpoints and Network-Settings for the various chains network=${network:-mainnet} #sets the default network to mainnet, if not set otherwise -unset _magicparam _addrformat _byronToShelleyEpochs _tokenMetaServer _transactionExplorer _koiosAPI _adahandlePolicyID +unset _magicparam _addrformat _byronToShelleyEpochs _tokenMetaServer _transactionExplorer _koiosAPI _adahandlePolicyID _adahandleAPI _lightModeParametersURL #Load and overwrite variables via env files if present scriptDir=$(dirname "$0" 2> /dev/null) @@ -135,26 +144,30 @@ if [[ -f "${scriptDir}/common.inc" ]]; then source "${scriptDir}/common.inc"; fi if [[ -f "$HOME/.common.inc" ]]; then source "$HOME/.common.inc"; fi if [[ -f "common.inc" ]]; then source "common.inc"; fi +#Also check about a lowercase "workmode" entry +workMode=${workmode:-"${workMode}"} + #Set the list of preconfigured networknames -networknames="mainnet, preprod, preview, legacy, vasildev" +networknames="mainnet, preprod, preview, sancho" #Check if there are testnet parameters set but network is still "mainnet" if [[ "${magicparam}${addrformat}" == *"testnet"* && "${network,,}" == "mainnet" ]]; then majorError "Mainnet selected, but magicparam(${magicparam})/addrformat(${addrformat}) have testnet settings!\n\nPlease select the right chain in the '00_common.sh', '${scriptDir}/common.inc', '$HOME/.common.inc' or './common.inc' file by setting the value for the parameter network to one of the preconfiged networknames:\n${networknames}\n\nThere is no need anymore, to set the parameters magicparam/addrformat/byronToShelleyEpochs for the preconfigured networks. Its enough to specify it for example with: network=\"preprod\"\nOf course you can still set them and also set a custom networkname like: network=\"vasil-dev\""; exit 1; fi - #Preload the variables, based on the "network" name case "${network,,}" in "mainnet" ) - network="Mainnet" #nicer name for info-display - _magicparam="--mainnet" #MagicParameter Extension --mainnet / --testnet-magic xxx - _addrformat="--mainnet" #Addressformat for the address generation, normally the same as magicparam + network="Mainnet" #nicer name for info-display + _magicparam="--mainnet" #MagicParameter Extension --mainnet / --testnet-magic xxx + _addrformat="--mainnet" #Addressformat for the address generation, normally the same as magicparam _byronToShelleyEpochs=208 #The number of Byron Epochs before the Chain forks to Shelley-Era _tokenMetaServer="https://tokens.cardano.org/metadata/" #Token Metadata API URLs -> autoresolve into ${tokenMetaServer}/ _transactionExplorer="https://cardanoscan.io/transaction/" #URLS for the Transaction-Explorers -> autoresolve into ${transactionExplorer}/ - _koiosAPI="https://api.koios.rest/api/v0" #Koios-API URLs -> autoresolve into ${koiosAPI} + _koiosAPI="https://api.koios.rest/api/v1" #Koios-API URLs -> autoresolve into ${koiosAPI} _adahandlePolicyID="f0ff48bbb7bbe9d59a40f1ce90e9e9d0ff5002ec48f232b49ca0fb9a" #PolicyIDs for the adaHandles -> autoresolve into ${adahandlePolicyID} + _adahandleAPI="https://api.handle.me" #Adahandle-API URLs -> autoresolve into ${adahandleAPI} _catalystAPI="https://api.testnet.projectcatalyst.io/api/v1" #Catalyst-API URLs -> autoresolve into ${catalystAPI} + _lightModeParametersURL="https://uptime.live/data/cardano/parms/mainnet-parameters.json" #Parameters-JSON-File with current informations about cardano-cli version, tip, era, protocol-parameters ;; @@ -165,9 +178,11 @@ case "${network,,}" in _byronToShelleyEpochs=4 _tokenMetaServer="https://metadata.cardano-testnet.iohkdev.io/metadata" _transactionExplorer="https://preprod.cardanoscan.io/transaction" - _koiosAPI="https://preprod.koios.rest/api/v0" + _koiosAPI="https://preprod.koios.rest/api/v1" _adahandlePolicyID="f0ff48bbb7bbe9d59a40f1ce90e9e9d0ff5002ec48f232b49ca0fb9a" #PolicyIDs for the adaHandles -> autoresolve into ${adahandlePolicyID} + _adahandleAPI="https://preprod.api.handle.me" #Adahandle-API URLs -> autoresolve into ${adahandleAPI} _catalystAPI="https://api.testnet.projectcatalyst.io/api/v1" #Catalyst-API URLs -> autoresolve into ${catalystAPI} + _lightModeParametersURL="https://uptime.live/data/cardano/parms/preprod-parameters.json" #Parameters-JSON-File with current informations about cardano-cli version, tip, era, protocol-parameters ;; @@ -178,9 +193,11 @@ case "${network,,}" in _byronToShelleyEpochs=0 _tokenMetaServer="https://metadata.cardano-testnet.iohkdev.io/metadata" _transactionExplorer="https://preview.cardanoscan.io/transaction" - _koiosAPI="https://preview.koios.rest/api/v0" + _koiosAPI="https://preview.koios.rest/api/v1" _adahandlePolicyID="f0ff48bbb7bbe9d59a40f1ce90e9e9d0ff5002ec48f232b49ca0fb9a" #PolicyIDs for the adaHandles -> autoresolve into ${adahandlePolicyID} - _catalystAPI= #Catalyst-API URLs -> autoresolve into ${catalystAPI} + _adahandleAPI="https://preview.api.handle.me" #Adahandle-API URLs -> autoresolve into ${adahandleAPI} + _catalystAPI= #Catalyst-API URLs -> autoresolve into ${catalystAPI} + _lightModeParametersURL="https://uptime.live/data/cardano/parms/preview-parameters.json" #Parameters-JSON-File with current informations about cardano-cli version, tip, era, protocol-parameters ;; @@ -191,9 +208,26 @@ case "${network,,}" in _byronToShelleyEpochs=2 _tokenMetaServer="https://metadata.cardano-testnet.iohkdev.io/metadata" _transactionExplorer= - _koiosAPI="https://guild.koios.rest/api/v0" + _koiosAPI="https://guild.koios.rest/api/v1" + _adahandlePolicyID="f0ff48bbb7bbe9d59a40f1ce90e9e9d0ff5002ec48f232b49ca0fb9a" #PolicyIDs for the adaHandles -> autoresolve into ${adahandlePolicyID} + _adahandleAPI= + _catalystAPI= #Catalyst-API URLs -> autoresolve into ${catalystAPI} + _lightModeParametersURL= #Parameters-JSON-File with current informations about cardano-cli version, tip, era, protocol-parameters + ;; + + + "sancho"|"sancho-net"|"sanchonet" ) + network="SanchoNet" + _magicparam="--testnet-magic 4" + _addrformat="--testnet-magic 4" + _byronToShelleyEpochs=0 + _tokenMetaServer="https://metadata.cardano-testnet.iohkdev.io/metadata" + _transactionExplorer= + _koiosAPI= _adahandlePolicyID="f0ff48bbb7bbe9d59a40f1ce90e9e9d0ff5002ec48f232b49ca0fb9a" #PolicyIDs for the adaHandles -> autoresolve into ${adahandlePolicyID} - _catalystAPI= #Catalyst-API URLs -> autoresolve into ${catalystAPI} + _adahandleAPI= + _catalystAPI= #Catalyst-API URLs -> autoresolve into ${catalystAPI} + _lightModeParametersURL= #Parameters-JSON-File with current informations about cardano-cli version, tip, era, protocol-parameters ;; @@ -206,7 +240,9 @@ case "${network,,}" in _transactionExplorer= _koiosAPI= _adahandlePolicyID="8d18d786e92776c824607fd8e193ec535c79dc61ea2405ddf3b09fe3" - _catalystAPI= #Catalyst-API URLs -> autoresolve into ${catalystAPI} + _adahandleAPI= + _catalystAPI= #Catalyst-API URLs -> autoresolve into ${catalystAPI} + _lightModeParametersURL= #Parameters-JSON-File with current informations about cardano-cli version, tip, era, protocol-parameters ;; esac @@ -220,7 +256,9 @@ tokenMetaServer=${tokenMetaServer:-"${_tokenMetaServer}"} transactionExplorer=${transactionExplorer:-"${_transactionExplorer}"} koiosAPI=${koiosAPI:-"${_koiosAPI}"} adahandlePolicyID=${adahandlePolicyID:-"${_adahandlePolicyID}"} +adahandleAPI=${adahandleAPI:-"${_adahandleAPI}"} catalystAPI=${catalystAPI:-"${_catalystAPI}"} +lightModeParametersURL=${lightModeParametersURL:-"${_lightModeParametersURL}"} #Check about the / at the end of the URLs @@ -228,54 +266,247 @@ if [[ "${tokenMetaServer: -1}" == "/" ]]; then tokenMetaServer=${tokenMetaServer if [[ "${koiosAPI: -1}" == "/" ]]; then koiosAPI=${koiosAPI%?}; fi #make sure the last char is not a / if [[ "${transactionExplorer: -1}" == "/" ]]; then transactionExplorer=${transactionExplorer%?}; fi #make sure the last char is not a / if [[ "${catalystAPI: -1}" == "/" ]]; then catalystAPI=${catalystAPI%?}; fi #make sure the last char is not a / +if [[ "${adahandleAPI: -1}" == "/" ]]; then adahandleAPI=${adahandleAPI%?}; fi #make sure the last char is not a / #Check about the needed chain params if [[ "${magicparam}" == "" || ${addrformat} == "" || ${byronToShelleyEpochs} == "" ]]; then majorError "The 'magicparam', 'addrformat' or 'byronToShelleyEpochs' is not set!\nOr maybe you have set the wrong parameter network=\"${network}\" ?\nList of preconfigured network-names: ${networknames}"; exit 1; fi #Don't allow to overwrite the needed Versions, so we set it after the overwrite part -minNodeVersion="1.35.5" #minimum allowed node version for this script-collection version +minCliVersion="8.17.0" #minimum allowed cli version for this script-collection version +maxCliVersion="99.99.9" #maximum allowed cli version, 99.99.9 = no limit so far +minNodeVersion="8.7.2" #minimum allowed node version for this script-collection version maxNodeVersion="99.99.9" #maximum allowed node version, 99.99.9 = no limit so far minLedgerCardanoAppVersion="5.0.0" #minimum version for the cardano-app on the Ledger HW-Wallet minTrezorCardanoAppVersion="2.6.0" #minimum version for the firmware on the Trezor HW-Wallet minHardwareCliVersion="1.12.0" #minimum version for the cardano-hw-cli -minCardanoSignerVersion="1.13.0" #minimum version for the cardano-signer binary +minCardanoSignerVersion="1.14.0" #minimum version for the cardano-signer binary minCatalystToolboxVersion="0.5.0" #minimum version for the catalyst-toolbox binary +#Defaults - Variables and Constants +defEra="" #Era for non era related cardano-cli commands +defTTL=100000 #Default seconds for transactions to be valid +addrTypePayment="payment" +addrTypeStake="stake" +lightModeParametersJSON="" #will be updated with the latest parameters json if scripts are running in light mode -#Set the CARDANO_NODE_SOCKET_PATH for all cardano-cli operations +#Set the CARDANO_NODE_SOCKET_PATH for all cardano-cli operations which are interacting with a local node export CARDANO_NODE_SOCKET_PATH=${socket} +#set the CARDANO_NODE_NETWORK_ID for all cardano-cli operations, the ${magicparam} stays active in the background +if [[ "${magicparam,,}" == *"mainnet"* ]]; then + export CARDANO_NODE_NETWORK_ID="mainnet"; #set it to mainnet + else + export CARDANO_NODE_NETWORK_ID="${magicparam#* }"; #set it to the number behind the space (e.g. '--testnet-magic 1234' -> '1234'} +fi + #Set the bc linebreak to a big number so we can work with really biiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiig numbers export BC_LINE_LENGTH=1000 -#Setting online/offline variables and offlineFile default value, versionInfo, tokenRegistryquery, tx output cropping to boolean values -if [[ "${offlineMode^^}" == "YES" ]]; then offlineMode=true; onlineMode=false; else offlineMode=false; onlineMode=true; fi + + +#------------------------------------------------------- +#queryLight_protocolParameters function +# +# makes an online query via the hosted service to get the current protocolParameters file +# which also includes the used cardano-cli version, era, tip, lastupdate +# +queryLight_protocolParameters() { + + local queryData=${1,,} + local errorcnt=0 + local error=-1 + while [[ ${errorcnt} -lt 5 && ${error} -ne 0 ]]; do #try a maximum of 5 times to request the information + error=0 + response=$(curl --compressed -sL -m 30 -X GET -w "---spo-scripts---%{http_code}" -H "Cache-Control: no-cache, no-store" "${lightModeParametersURL}?rnd=$(date +%s 2> /dev/null)" 2> /dev/null) + if [[ $? -ne 0 ]]; then error=1; sleep 1; fi; #if there is an error, wait for a second and repeat + errorcnt=$(( ${errorcnt} + 1 )) + done + if [[ ${error} -ne 0 ]]; then echo -e "Query of the Light-Mode Protocol-Parameters-JSON via curl failed, tried 5 times."; exit 1; fi; #curl query failed + + #Split the response string into JSON content and the HTTP-ResponseCode + if [[ "${response}" =~ (.*)---spo-scripts---([0-9]*)* ]]; then + local responseJSON="${BASH_REMATCH[1]}" + local responseCode="${BASH_REMATCH[2]}" + else + echo -e "Query of the Light-Mode Protocol-Paramters-JSON curl failed. Could not separate Content and ResponseCode."; exit 1; #curl query failed + fi + + #Check the responseCode + case ${responseCode} in + "200" ) ;; #all good, continue + * ) echo -e "Query of the Light-Mode Protocol-Parameters-JSON failed\nHTTP Request File: ${lightModeParametersURL}\nHTTP Response Code: ${responseCode}"; exit 1; #exit with a failure and the http response code + esac; + parametersJSON=$(jq -r . <<< "${responseJSON}" 2> /dev/null) + if [[ $? -ne 0 ]]; then echo -e "Query of the Light-Mode Protocol-Parameters-JSON failed, not a JSON response."; exit 1; fi; #reponse is not a json file + + #return the response + printf "${parametersJSON}" + unset response error errorcnt parametersJSON + +} +#------------------------------------------------------- + + +#------------------------------------------------------- +#queryLight_tip function +# +# makes an online query via koios API and returns the current tip +# +queryLight_tip() { + + local errorcnt=0 + local error=-1 + while [[ ${errorcnt} -lt 5 && ${error} -ne 0 ]]; do #try a maximum of 5 times to request the information via koios API + error=0 + response=$(curl -sL -m 30 -X GET -w "---spo-scripts---%{http_code}" "${koiosAPI}/tip" -H "Accept: application/json" -H "Content-Type: application/json" 2> /dev/null) + if [ $? -ne 0 ]; then error=1; fi; + errorcnt=$(( ${errorcnt} + 1 )) + done + if [[ ${error} -ne 0 ]]; then echo -e "Query-Tip of the Koios-API via curl failed, tried 5 times."; exit 1; fi; #curl query failed + + #Split the response string into JSON content and the HTTP-ResponseCode + if [[ "${response}" =~ (.*)---spo-scripts---([0-9]*)* ]]; then + local responseJSON="${BASH_REMATCH[1]}" + local responseCode="${BASH_REMATCH[2]}" + else + echo -e "Query of the Koios-API via curl failed. Could not separate Content and ResponseCode."; exit 1; #curl query failed + fi + + #Check the responseCode + case ${responseCode} in + "200" ) ;; #all good, continue + * ) echo -e "HTTP Response code: ${responseCode}"; exit 1; #exit with a failure and the http response code + esac; + tipRet=$(jq -r ".[0].abs_slot" <<< "${responseJSON}" 2> /dev/null) + if [ $? -ne 0 ]; then echo -e "Query-Tip via Koios-API (${koiosAPI}) failed, not a JSON response."; exit 1; fi; #reponse is not a json file + + #return the tip + printf "${tipRet}" + unset tipRet response responseCode responseJSON error errorcnt + +} +#------------------------------------------------------- + +#------------------------------------------------------- +#queryLight_epoch function +# +# makes an online query via koios API and returns the current epoch +# +queryLight_epoch() { + + local errorcnt=0 + local error=-1 + while [[ ${errorcnt} -lt 5 && ${error} -ne 0 ]]; do #try a maximum of 5 times to request the information via koios API + error=0 + response=$(curl -sL -m 30 -X GET -w "---spo-scripts---%{http_code}" "${koiosAPI}/tip" -H "Accept: application/json" -H "Content-Type: application/json" 2> /dev/null) + if [ $? -ne 0 ]; then error=1; fi; + errorcnt=$(( ${errorcnt} + 1 )) + done + if [[ ${error} -ne 0 ]]; then echo -e "Query-Epoch of the Koios-API via curl failed, tried 5 times."; exit 1; fi; #curl query failed + + #Split the response string into JSON content and the HTTP-ResponseCode + if [[ "${response}" =~ (.*)---spo-scripts---([0-9]*)* ]]; then + local responseJSON="${BASH_REMATCH[1]}" + local responseCode="${BASH_REMATCH[2]}" + else + echo -e "Query of the Koios-API via curl failed. Could not separate Content and ResponseCode."; exit 1; #curl query failed + fi + + #Check the responseCode + case ${responseCode} in + "200" ) ;; #all good, continue + * ) echo -e "HTTP Response code: ${responseCode}"; exit 1; #exit with a failure and the http response code + esac; + epochRet=$(jq -r ".[0].epoch_no" <<< "${responseJSON}" 2> /dev/null) + if [ $? -ne 0 ]; then echo -e "Query-Tip via Koios-API (${koiosAPI}) failed, not a JSON response."; exit 1; fi; #reponse is not a json file + + #return the tip + printf "${epochRet}" + unset epochRet response responseCode responseJSON error errorcnt + +} +#------------------------------------------------------- + +#------------------------------------------------------- +#Setting offlineFile default value, versionInfo, tokenRegistryquery, tx output cropping to boolean values if [[ "${offlineFile}" == "" ]]; then offlineFile="./offlineTransfer.json"; fi if [[ "${showVersionInfo^^}" == "NO" ]]; then showVersionInfo=false; else showVersionInfo=true; fi if [[ "${queryTokenRegistry^^}" == "NO" ]]; then queryTokenRegistry=false; else queryTokenRegistry=true; fi if [[ "${cropTxOutput^^}" == "NO" ]]; then cropTxOutput=false; else cropTxOutput=true; fi +#------------------------------------------------------- - -#------------------------------------------------------------- -#Do a cli and node version check +#------------------------------------------------------- versionCheck() { printf '%s\n%s' "${1}" "${2}" | sort -C -V; } #$1=minimal_needed_version, $2=current_node_version +#------------------------------------------------------- +#------------------------------------------------------- exists() { command -v "$1" >/dev/null 2>&1 } +#------------------------------------------------------- +#------------------------------------------------------- #Check cardano-cli if ! exists "${cardanocli}"; then majorError "Path ERROR - Path to cardano-cli is not correct or cardano-cli binaryfile is missing!\nYour current set path is: ${cardanocli}"; exit 1; fi versionCLI=$(${cardanocli} version 2> /dev/null |& head -n 1 |& awk {'print $2'}) -versionCheck "${minNodeVersion}" "${versionCLI}" -if [[ $? -ne 0 ]]; then majorError "Version ${versionCLI} ERROR - Please use a cardano-cli version ${minNodeVersion} or higher !\nOld versions are not supported for security reasons, please upgrade - thx."; exit 1; fi -versionCheck "${versionCLI}" "${maxNodeVersion}" -if [[ $? -ne 0 ]]; then majorError "Version ${versionCLI} ERROR - Please use a cardano-cli version between ${minNodeVersion} and ${maxNodeVersion} !\nOther versions are not supported for compatibility issues, please check if newer scripts are available - thx."; exit 1; fi +versionCheck "${minCliVersion}" "${versionCLI}" +if [[ $? -ne 0 ]]; then majorError "Version ${versionCLI} ERROR - Please use a cardano-cli version ${minCliVersion} or higher !\nOlder versions are not supported for compatibility issues, please upgrade - thx."; exit 1; fi +versionCheck "${versionCLI}" "${maxCliVersion}" +if [[ $? -ne 0 ]]; then majorError "Version ${versionCLI} ERROR - Please use a cardano-cli version between ${minCliVersion} and ${maxCliVersion} !\nOther versions are not supported for compatibility issues, please check if newer scripts are available - thx."; exit 1; fi +#------------------------------------------------------- + + +#------------------------------------------------------- +#Set the workMode for the scripts and additional variables according to it +workMode=${workMode,,} #convert it to lowercase +case ${workMode} in + "online") #Online-Mode(Full-Mode) - The machine is online and a local running node is present + onlineMode=true; fullMode=true; lightMode=false; offlineMode=false; + ;; + + "light") #Light-Mode - The machine is online, but without a local node + onlineMode=true; fullMode=false; lightMode=true; offlineMode=false; + + #Check if there are needed entries for the light mode + if [[ "${lightModeParametersURL}" == "" || "${koiosAPI}" == "" ]]; then majorError "There is no Light-Mode available for this network!"; exit 1; fi + + #Get the latest lightModeParametersJSON so it does not need to be requested multiple times + lightModeParametersJSON=$(queryLight_protocolParameters); + if [[ $? -ne 0 ]]; then majorError "${lightModeParametersJSON}"; exit 1; fi + + #Read all values at once + { read lightModeParametersDate; read lightModeParametersMagic; read lightModeParametersVersionCLI; } <<< $(jq -r ".sposcriptsLightMode.lastUpdate, .sposcriptsLightMode.magic, .sposcriptsLightMode.versionCLI" 2> /dev/null <<< "${lightModeParametersJSON}") + + #Check if the lightModeParametersJSON is not older than a few hours + lightModeParametersTimeDiff=$(( $(date -u +%s) - $(date --date="${lightModeParametersDate}" +%s) )) + if [[ ${lightModeParametersTimeDiff} -gt 21600 ]]; then majorError "The time difference from your local time to the online Light-Mode-Parameters file\nis bigger than 6 hours! Its currently ${lightModeParametersTimeDiff} seconds.\nThis means that either your local time is off, or that the LightMode parameters-file hosting service is not up2date.\nIn that case, please retry a bit later and/or report the issue - thx!"; exit 1; fi + + #Check if the online lightModeParametersFile contains the same network magic + if [[ "${lightModeParametersMagic}" != "${CARDANO_NODE_NETWORK_ID}" ]]; then majorError "The online version of the parameters-file has a network-magic ${lightModeParametersMagic},\nbut the scripts are locally configured for network-magic ${CARDANO_NODE_NETWORK_ID} !"; exit 1; fi + + #Check that the local CLI version is not lower than the lightModeParametersVersionCLI + versionCheck "${lightModeParametersVersionCLI}" "${versionCLI}" + if [[ $? -ne 0 ]]; then majorError "For working in LightMode, please use at least a local cardano-cli version ${lightModeParametersVersionCLI} or higher!\nYou are currently using version ${versionCLI}, please upgrade - thx."; exit 1; fi + ;; + + "offline") #Offline-Mode - The machine is offline (airgapped) + onlineMode=false; fullMode=false; lightMode=false; offlineMode=true; + ;; + + *) #Unknown workMode + majorError "Unknown workMode '${workMode}'\n\nPlease set it to 'online', 'light' or 'offline'"; + exit 1; +esac +#------------------------------------------------------- + +#------------------------------------------------------- if ${showVersionInfo}; then echo -ne "\n\e[0mVersion-Info: \e[32mcli ${versionCLI}\e[0m"; fi +#------------------------------------------------------- -#Check cardano-node only in online mode -if ${onlineMode}; then +#------------------------------------------------------- +#Check cardano-node only in workMode="online" (FullMode) +if ${fullMode}; then if ! exists "${cardanonode}"; then majorError "Path ERROR - Path to cardano-node is not correct or cardano-node binaryfile is missing!\nYour current set path is: ${cardanonode}"; exit 1; fi versionNODE=$(${cardanonode} version 2> /dev/null |& head -n 1 |& awk {'print $2'}) versionCheck "${minNodeVersion}" "${versionNODE}" @@ -284,7 +515,10 @@ if ${onlineMode}; then if [[ $? -ne 0 ]]; then majorError "Version ${versionNODE} ERROR - Please use a cardano-node version between ${minNodeVersion} and ${maxNodeVersion} !\nOther versions are not supported for compatibility issues, please check if newer scripts are available - thx."; exit 1; fi if ${showVersionInfo}; then echo -ne " / \e[32mnode ${versionNODE}\e[0m"; fi fi +#------------------------------------------------------- + +#------------------------------------------------------- #Check bech32 tool if given path is ok, if not try to use the one in the scripts folder if ! exists "${bech32_bin}"; then #Try the one in the scripts folder @@ -292,43 +526,81 @@ if ! exists "${bech32_bin}"; then else majorError "Path ERROR - Path to the 'bech32' binary is not correct or 'bech32' binaryfile is missing!\nYou can find it here: https://github.com/input-output-hk/bech32/releases/latest\nThis is needed to calculate the correct Bech32-Assetformat like 'asset1ee0u29k4xwauf0r7w8g30klgraxw0y4rz2t7xs'."; exit 1; fi fi -#Display current Mode (online or offline) + +#------------------------------------------------------------- +#Check if curl, jq, bc and xxd is installed +if ! exists curl; then echo -e "\e[33mYou need the little tool 'curl', its needed to fetch online data !\n\nInstall it on Ubuntu/Debian like:\n\e[97msudo apt update && sudo apt -y install curl\n\n\e[33mThx! :-)\e[0m\n"; exit 2; fi +if ! exists jq; then echo -e "\e[33mYou need the little tool 'jq', its needed to do the json processing !\n\nInstall it on Ubuntu/Debian like:\n\e[97msudo apt update && sudo apt -y install jq\n\n\e[33mThx! :-)\e[0m\n"; exit 2; fi +if ! exists bc; then echo -e "\e[33mYou need the little tool 'bc', its needed to do larger number calculations !\n\nInstall it on Ubuntu/Debian like:\n\e[97msudo apt update && sudo apt -y install bc\n\n\e[33mThx! :-)\e[0m\n"; exit 2; fi +if ! exists xxd; then echo -e "\e[33mYou need the little tool 'xxd', its needed to convert hex strings !\n\nInstall it on Ubuntu/Debian like:\n\e[97msudo apt update && sudo apt -y install xxd\n\n\e[33mThx! :-)\e[0m\n"; exit 2; fi + + +#------------------------------------------------------------- +#Searching for the temp directory (used for transactions files) +tempDir=$(dirname $(mktemp -ut tmp.XXXX)) + + +#------------------------------------------------------- +#Return the era the chain is currently in +get_NodeEra() { + case ${workMode} in + "online") local tmpEra=$(${cardanocli} query tip ${magicparam} 2> /dev/null | jq -r ".era | select (.!=null)" 2> /dev/null);; + "offline") local tmpEra=$(jq -r ".protocol.era" 2> /dev/null < ${offlineFile});; + "light") local tmpEra=$(jq -r ".sposcriptsLightMode.lastTip.era" 2> /dev/null <<< "${lightModeParametersJSON}");; + esac +if [[ ! "${tmpEra}" == "" ]]; then tmpEra=${tmpEra,,}; else tmpEra="auto"; fi +echo "${tmpEra}"; return 0; #return era in lowercase +} + +##Set nodeEra parameter ( --byron-era, --shelley-era, --allegra-era, --mary-era, --alonzo-era, --babbage-era or empty) +tmpEra=$(get_NodeEra); +if [[ ! "${tmpEra}" == "auto" ]]; then + nodeEraParam="--${tmpEra}-era"; #for cli commands before 8.12.0 + cliEra="${tmpEra,,}" #new era selection parameter for cardano cli 8.12.0+ + else + nodeEraParam=""; + cliEra="${defEra}"; +fi + +#Temporary fix to lock the transaction build-raw to alonzo era for +#Hardware-Wallet operations. Babbage-Era is not yet supported, so we will lock this for now +#if [[ "${nodeEraParam}" == "" ]] || [[ "${nodeEraParam}" == "--conway-era" ]]; then nodeEraParam="--babbage-era"; cliEra="babbage"; fi +#------------------------------------------------------- + + +#Display current Mode if ${showVersionInfo}; then - if ${offlineMode}; then - echo -ne "\t\tScripts-Mode: \e[32moffline\e[0m"; - else - echo -ne "\t\tScripts-Mode: \e[36monline\e[0m"; + + case ${workMode} in + "online") echo -ne "\t\tMode: \e[36monline(full)\e[0m"; if [ ! -e "${socket}" ]; then echo -ne "\n\n\e[35mWarning: Node-Socket does not exist !\e[0m"; fi + ;; + + "light") echo -ne "\t\tMode: \e[93monline(light)\e[0m" + ;; + + "offline") echo -ne "\t\tMode: \e[32moffline\e[0m" + ;; + esac + + if [[ "${cliEra}" != "${defEra}" ]]; then + echo -ne "\tEra: \e[32m${cliEra}\e[0m"; + else + echo -ne "\tEra: \e[36mdefault\e[0m"; fi if [[ "${magicparam}" == *"mainnet"* ]]; then - echo -ne "\t\t\e[32mMainnet\e[0m"; + echo -ne "\tNetwork: \e[32mMainnet\e[0m"; else - echo -ne "\t\t\e[91mTestnet: ${network} (magic $(echo ${magicparam} | awk {'print $2'}))\e[0m"; + echo -ne "\tTestnet: \e[91m${network} (magic $(echo ${magicparam} | awk {'print $2'}))\e[0m"; fi echo + if ${offlineMode}; then echo -e "\n\e[0mLocal-Time:\e[32m $(date)\e[0m (\e[33mverify correct offline-time\e[0m)"; fi #show the local time in offline mode as an extra information echo fi -#------------------------------------------------------------- -#Check path to genesis files -if [[ ! -f "${genesisfile}" ]]; then majorError "Path ERROR - Path to the shelley genesis file '${genesisfile}' is wrong or the file is missing!"; exit 1; fi -if [[ ! -f "${genesisfile_byron}" ]]; then majorError "Path ERROR - Path to the byron genesis file '${genesisfile_byron}' is wrong or the file is missing!"; exit 1; fi - - - -#------------------------------------------------------------- -#Check if curl, jq, bc and xxd is installed -if ! exists curl; then echo -e "\e[33mYou need the little tool 'curl', its needed to fetch online data !\n\nInstall it on Ubuntu/Debian like:\n\e[97msudo apt update && sudo apt -y install curl\n\n\e[33mThx! :-)\e[0m\n"; exit 2; fi -if ! exists jq; then echo -e "\e[33mYou need the little tool 'jq', its needed to do the json processing !\n\nInstall it on Ubuntu/Debian like:\n\e[97msudo apt update && sudo apt -y install jq\n\n\e[33mThx! :-)\e[0m\n"; exit 2; fi -if ! exists bc; then echo -e "\e[33mYou need the little tool 'bc', its needed to do larger number calculations !\n\nInstall it on Ubuntu/Debian like:\n\e[97msudo apt update && sudo apt -y install bc\n\n\e[33mThx! :-)\e[0m\n"; exit 2; fi -if ! exists xxd; then echo -e "\e[33mYou need the little tool 'xxd', its needed to convert hex strings !\n\nInstall it on Ubuntu/Debian like:\n\e[97msudo apt update && sudo apt -y install xxd\n\n\e[33mThx! :-)\e[0m\n"; exit 2; fi - -#------------------------------------------------------------- -#Searching for the temp directory (used for transactions files) -tempDir=$(dirname $(mktemp -ut tmp.XXXX)) @@ -338,7 +610,7 @@ tempDir=$(dirname $(mktemp -ut tmp.XXXX)) check_address() { tmp=$(${cardanocli} address info --address $1 2> /dev/null) if [[ $? -ne 0 ]]; then echo -e "\e[35mERROR - Unknown address format for address: $1 !\e[0m"; exit 1; fi -era=$(jq -r .era <<< ${tmp} 2> /dev/null) +local era=$(jq -r .era <<< ${tmp} 2> /dev/null) if [[ "${era^^}" == "BYRON" ]]; then echo -e "\e[33mINFO - Byron addresses are only supported as a destination address!\e[0m\n"; fi } @@ -350,21 +622,25 @@ get_addressEra() { ${cardanocli} address info --address $1 2> /dev/null | jq -r .era } -addrTypePayment="payment" -addrTypeStake="stake" #------------------------------------------------------- #AdaHandle Format checks (exits with true or false) checkAdaRootHandleFormat() { - #AdaHandles with optional SubHandles + #AdaHandles without SubHandles if [[ "${1,,}" =~ ^\$[a-z0-9_.-]{1,15}$ ]]; then true; else false; fi } checkAdaSubHandleFormat() { - #AdaHandles with optional SubHandles + #AdaHandles with SubHandles if [[ "${1,,}" =~ ^\$[a-z0-9_.-]{1,15}@[a-z0-9_.-]{1,15}$ ]]; then true; else false; fi } +checkAdaHandleFormat() { + #All AdaHandles formats - root and sub/virtual ones + if [[ "${1,,}" =~ ^\$[a-z0-9_.-]{1,15}(@[a-z0-9_.-]{1,15})?$ ]]; then true; else false; fi +} + + #------------------------------------------------------------- #Subroutine for user interaction @@ -405,6 +681,7 @@ ask() { } #------------------------------------------------------- + #------------------------------------------------------- #Subroutine for password interaction ask_pass() { @@ -419,8 +696,6 @@ ask_pass() { #------------------------------------------------------- - - #------------------------------------------------------- #Subroutines to set read/write flags for important files file_lock() @@ -434,39 +709,75 @@ if [ -f "$1" ]; then chmod 600 "$1"; fi } #------------------------------------------------------- + #------------------------------------------------------- -#Subroutines to calculate current epoch from genesis.json offline +#Subroutines to calculate current slotHeight(tip) depending on online/light/offline mode get_currentEpoch() { -local startTimeGenesis=$(cat ${genesisfile} | jq -r .systemStart) -local startTimeSec=$(date --date=${startTimeGenesis} +%s) #in seconds (UTC) -local currentTimeSec=$(date -u +%s) #in seconds (UTC) -local epochLength=$(cat ${genesisfile} | jq -r .epochLength) -local currentEPOCH=$(( (${currentTimeSec}-${startTimeSec}) / ${epochLength} )) #returns a integer number, we like that -echo ${currentEPOCH} +case ${workMode} in + + "online") #Full-OnlineMode, query the local node + local currentEpoch=$(${cardanocli} query tip ${magicparam} 2> /dev/null | jq -r .epoch 2> /dev/null); + + #if the return is blank (bug in the cli), then retry 2 times. if failing again, exit with a majorError + if [[ "${currentEpoch}" == "" ]]; then local currentEpoch=$(${cardanocli} query tip ${magicparam} 2> /dev/null | jq -r .epoch 2> /dev/null); + if [[ "${currentEpoch}" == "" ]]; then local currentEpoch=$(${cardanocli} query tip ${magicparam} 2> /dev/null | jq -r .epoch 2> /dev/null); + if [[ "${currentEpoch}" == "" ]]; then majorError "query tip/epoch return from cardano-cli failed"; exit 1; fi + fi + fi + ;; + + "light") #Light-Mode, query koios about the tip + currentEpoch=$(queryLight_epoch); + if [[ $? -ne 0 ]]; then majorError "${currentEpoch}"; exit 1; fi + ;; + + "offline") #Offline-Mode, calculate the tip from the genesis file + #Static + + #Check path to genesis files + if [[ ! -f "${genesisfile}" ]]; then majorError "Path ERROR - Path to the shelley genesis file '${genesisfile}' is wrong or the file is missing!"; exit 1; fi + + local startTimeGenesis; local epochLength; + { read startTimeGenesis; read epochLength; } <<< $( jq -r ".systemStart // \"null\", .epochLength // \"null\"" < ${genesisfile} 2> /dev/null) + local startTimeSec=$(date --date=${startTimeGenesis} +%s) #in seconds (UTC) + local currentTimeSec=$(date -u +%s) #in seconds (UTC) + local currentEpoch=$(( (${currentTimeSec}-${startTimeSec}) / ${epochLength} )) #returns a integer number, we like that + ;; +esac + +echo ${currentEpoch} } #------------------------------------------------------- + #------------------------------------------------------- -#Subroutines to calculate time until next epoch from genesis.json offline +#Subroutines to calculate time until next epoch from genesis.json get_timeUntilNextEpoch() { -local startTimeGenesis=$(cat ${genesisfile} | jq -r .systemStart) -local startTimeSec=$(date --date=${startTimeGenesis} +%s) #in seconds (UTC) -local currentTimeSec=$(date -u +%s) #in seconds (UTC) -local epochLength=$(cat ${genesisfile} | jq -r .epochLength) -local currentEPOCH=$(( (${currentTimeSec}-${startTimeSec}) / ${epochLength} )) #returns a integer number, we like that -local timeUntilNextEpoch=$(( ${epochLength} - (${currentTimeSec}-${startTimeSec}) + (${currentEPOCH}*${epochLength}) )) -echo ${timeUntilNextEpoch} + + #Check path to genesis files + if [[ ! -f "${genesisfile}" ]]; then majorError "Path ERROR - Path to the shelley genesis file '${genesisfile}' is wrong or the file is missing!"; exit 1; fi + + local startTimeGenesis; local epochLength; + { read startTimeGenesis; read epochLength; } <<< $( jq -r ".systemStart // \"null\", .epochLength // \"null\"" < ${genesisfile} 2> /dev/null) + local startTimeSec=$(date --date=${startTimeGenesis} +%s) #in seconds (UTC) + local currentTimeSec=$(date -u +%s) #in seconds (UTC) + local currentEPOCH=$(( (${currentTimeSec}-${startTimeSec}) / ${epochLength} )) #returns a integer number, we like that + local timeUntilNextEpoch=$(( ${epochLength} - (${currentTimeSec}-${startTimeSec}) + (${currentEPOCH}*${epochLength}) )) + echo ${timeUntilNextEpoch} + } #------------------------------------------------------- #------------------------------------------------------- -#Subroutines to calculate current slotHeight(tip) depending on online/offline mode +#Subroutines to calculate current slotHeight(tip) depending on online/light/offline mode get_currentTip() { -if ${onlineMode}; then +case ${workMode} in + + "online") #Full-OnlineMode, query the local node local currentTip=$(${cardanocli} query tip ${magicparam} 2> /dev/null | jq -r .slot 2> /dev/null); #only "slot" instead of "slotNo" since 1.26.0 #if the return is blank (bug in the cli), then retry 2 times. if failing again, exit with a majorError @@ -475,13 +786,25 @@ if ${onlineMode}; then if [[ "${currentTip}" == "" ]]; then majorError "query tip return from cardano-cli failed"; exit 1; fi fi fi - else + ;; + + "light") #Light-Mode, query koios about the tip + currentTip=$(queryLight_tip); + if [[ $? -ne 0 ]]; then majorError "${currentTip}"; exit 1; fi + ;; + + "offline") #Offline-Mode, calculate the tip from the genesis file #Static - local slotLength=$(cat ${genesisfile} | jq -r .slotLength) #In Secs - local epochLength=$(cat ${genesisfile} | jq -r .epochLength) #In Secs - local slotsPerKESPeriod=$(cat ${genesisfile} | jq -r .slotsPerKESPeriod) #Number - local startTimeByron=$(cat ${genesisfile_byron} | jq -r .startTime) #In Secs(abs) - local startTimeGenesis=$(cat ${genesisfile} | jq -r .systemStart) #In Text + + if [[ ! -f "${genesisfile}" ]]; then majorError "Path ERROR - Path to the shelley genesis file '${genesisfile}' is wrong or the file is missing!"; exit 1; fi + if [[ ! -f "${genesisfile_byron}" ]]; then majorError "Path ERROR - Path to the byron genesis file '${genesisfile_byron}' is wrong or the file is missing!"; exit 1; fi + + local slotLength; #In Secs + local epochLength; #In Secs + local slotsPerKESPeriod; #Number + local startTimeGenesis; #In Text + { read slotLength; read epochLength; read slotsPerKESPeriod; read startTimeGenesis; } <<< $(jq -r ".slotLength // \"null\", .epochLength // \"null\", .slotsPerKESPeriod // \"null\", .systemStart // \"null\"" < ${genesisfile} 2> /dev/null) + local startTimeByron=$(jq -r .startTime < ${genesisfile_byron} 2> /dev/null) #In Secs(abs) local startTimeSec=$(date --date=${startTimeGenesis} +%s) #In Secs(abs) local transTimeEnd=$(( ${startTimeSec}+(${byronToShelleyEpochs}*${epochLength}) )) #In Secs(abs) End of the TransitionPhase local byronSlots=$(( (${startTimeSec}-${startTimeByron}) / 20 )) #NumSlots between ByronChainStart and ShelleyGenesisStart(TransitionStart) @@ -497,26 +820,33 @@ if ${onlineMode}; then else #After Transition Phase local currentTip=$(( ${byronSlots} + ${transSlots} + ((${currentTimeSec}-${transTimeEnd}) / ${slotLength}) )) fi + ;; + +esac - fi echo ${currentTip} } #------------------------------------------------------- #------------------------------------------------------- -#Subroutines to calculate current TTL +#Subroutines to calculate current TTL - SHOULD NOT BE USED ANYMORE, DIRECTLY CALCULATE THE NEW TTL FROM THE CURRENT TIP IN EACH SCRIPT get_currentTTL() { -echo $(( $(get_currentTip) + 100000 )) #100000 so a little over a day to have time to collect witnesses and transmit the transaction + currentTip=$(get_currentTip); + if [[ $? -ne 0 ]]; then majorError "${currentTip}"; exit 1; fi + echo $(( ${currentTip} + ${defTTL} )) #100000(defTTL) so a little over a day to have time to collect witnesses and transmit the transaction } #------------------------------------------------------- + #------------------------------------------------------- #Subroutines to check the syncState of the node get_currentSync() { -if ${onlineMode}; then +case ${workMode} in + + "online") #Full-OnlineMode, query the local node local currentSync=$(${cardanocli} query tip ${magicparam} 2> /dev/null | jq -r .syncProgress 2> /dev/null); #if the return is blank (bug in the cli), then retry 2 times. if failing again, exit with a majorError @@ -527,15 +857,21 @@ if ${onlineMode}; then fi if [[ ${currentSync} == "100.00" ]]; then echo "synced"; else echo "unsynced"; fi + ;; + + "light") #Light-Mode, query koios about the tip - we pretend that if koios api responds with a tip without an error, that the database is also synced + local currentTip=$(queryLight_tip); + if [[ $? -eq 0 ]]; then echo "synced"; else echo "unsynced"; fi + ;; - else + "offline") #Offline-Mode, calculate the tip from the genesis file echo "offline" -fi + ;; +esac } #------------------------------------------------------- - #------------------------------------------------------- #Displays an Errormessage if parameter is not 0 checkError() @@ -544,6 +880,7 @@ if [[ $1 -ne 0 ]]; then echo -e "\n\n\e[35mERROR (Code $1) !\e[0m\n"; exit $1; f } #------------------------------------------------------- + #------------------------------------------------------- #TrimString function trimString @@ -552,25 +889,6 @@ function trimString } #------------------------------------------------------- -#------------------------------------------------------- -#Return the era the online node is in -get_NodeEra() { -local tmpEra=$(${cardanocli} query tip ${magicparam} 2> /dev/null | jq -r ".era | select (.!=null)" 2> /dev/null) -if [[ ! "${tmpEra}" == "" ]]; then tmpEra=${tmpEra,,}; else tmpEra="auto"; fi -echo "${tmpEra}"; return 0; #return era in lowercase -} -##Set nodeEra parameter ( --byron-era, --shelley-era, --allegra-era, --mary-era, --alonzo-era, --babbage-era or empty) -if ${onlineMode}; then tmpEra=$(get_NodeEra); else tmpEra=$(jq -r ".protocol.era" 2> /dev/null < ${offlineFile}); fi -if [[ ! "${tmpEra}" == "auto" ]]; then nodeEraParam="--${tmpEra}-era"; else nodeEraParam=""; fi - -#Temporary fix to lock the transaction build-raw to alonzo era for -#Hardware-Wallet operations. Babbage-Era is not yet supported, so we will lock this for now -if [[ "${nodeEraParam}" == "" ]] || [[ "${nodeEraParam}" == "--conway-era" ]]; then nodeEraParam="--babbage-era"; fi - - -#------------------------------------------------------- - - #------------------------------------------------------- #Converts a raw UTXO query output into the new UTXO JSON style since 1.26.0, but with stringnumbers @@ -660,7 +978,7 @@ generate_UTXO() #Parameter1=RawUTXO, Parameter2=Address #close the utxo part local utxoJSON+="}," #the last char "," will be deleted at the end -done < <(printf "${1}\n" | tail -n +3) #read in from parameter 1 (raw utxo) but cut first two lines +done < <(printf "%s\n" "${1}" | tail -n +3) #read in from parameter 1 (raw utxo) but cut first two lines. printf must be used with format %s, otherwise utxo content like \000 would be automatically decoded. #close the whole json but delete the last char "," before that. do it only if there are entries present (length>1), else return an empty json if [[ ${#utxoJSON} -gt 1 ]]; then echo "${utxoJSON%?}}"; else echo "{}"; fi; @@ -669,7 +987,6 @@ done < <(printf "${1}\n" | tail -n +3) #read in from parameter 1 (raw utxo) but #------------------------------------------------------- - #------------------------------------------------------- #Cuts out all UTXOs in a mary style UTXO JSON that are not the given UTXO hash ($2) #The given UTXO hash can be multiple UTXO hashes with the or separator | for egrep @@ -689,6 +1006,7 @@ echo "${outJSON}" } #------------------------------------------------------- + #------------------------------------------------------- #Cuts out all UTXOs in a mary style UTXO JSON that are not the given UTXO hash ($2) #The given UTXO hash can be multiple UTXO hashes with the separator | @@ -710,6 +1028,7 @@ echo "${outJSON}" } #------------------------------------------------------- + #------------------------------------------------------- #Convert PolicyID|assetName TokenName into Bech32 format "token1....." convert_tokenName2BECH() { @@ -724,6 +1043,7 @@ echo -n "${tmp_policyID}${tmp_assetName}" | xxd -r -ps | b2sum -l 160 -b | awk { } #------------------------------------------------------- + #------------------------------------------------------- #Convert ASCII assetName into HEX assetName convert_assetNameASCII2HEX() { @@ -731,6 +1051,7 @@ echo -n "${1}" | xxd -b -ps -c 80 | tr -d '\n' } #------------------------------------------------------- + #------------------------------------------------------- #Convert HEX assetName into ASCII assetName convert_assetNameHEX2ASCII() { @@ -738,6 +1059,7 @@ echo -n "${1}" | xxd -r -ps } #------------------------------------------------------- + #------------------------------------------------------- #Convert HEX assetName into ASCII assetName. If possible return ".assetName" else return just the HEX assetName without a leading point'.' convert_assetNameHEX2ASCII_ifpossible() { @@ -763,6 +1085,7 @@ tmp=$(${cardanocli} transaction calculate-min-required-utxo ${nodeEraParam} --pr if [[ $? -ne 0 ]]; then echo -e "\e[35mERROR - Can't calculate minValue for the given tx-out string: ${2} !\e[0m"; exit 1; fi echo ${tmp} | cut -d' ' -f 2 #Output is "Lovelace xxxxxx", so return the second part } +#------------------------------------------------------- #------------------------------------------------------- @@ -781,7 +1104,7 @@ local protocolVersionMajor=$(jq -r ".protocolVersion.major | select (.!=null)" < ### switch the method of the minOutUTXO calculation depending on the current era, starting with protocolVersionMajor>=7 (babbage) -if [[ ${protocolVersionMajor} -ge 7 ]]; then #7=Babbage and above, new since babbage: CIP-0055 -> minOutUTXO depends on the cbor bytes length +if [[ ${protocolVersionMajor} -ge 7 ]]; then #7=Babbage, 8=Conway ..., new since babbage: CIP-0055 -> minOutUTXO depends on the cbor bytes length #chain constants for babbage local constantOverhead=160 #constantOverhead=160 bytes set for babbage-era, 158 for mary/alonzo transactions in babbage era @@ -793,24 +1116,23 @@ if [[ ${protocolVersionMajor} -ge 7 ]]; then #7=Babbage and above, new since bab if [[ ${#asset_entry[@]} -eq 2 ]]; then #only lovelaces, no assets - case ${nodeEraParam,,} in - *"babbage"* ) #Build the tx-out cbor in babbage-tx format with maps - local cborStr="" #setup a clear new cbor string variable, will hold the tx-out cbor part - local cborStr+=$(to_cbor "map" 2) #map 2 - local cborStr+=$(to_cbor "unsigned" 0) #unsigned 0 - local cborStr+=$(to_cbor "bytes" "${toAddrHex}") #toAddr in hex - local cborStr+=$(to_cbor "unsigned" 1) #unsigned 1 - local cborStr+=$(to_cbor "unsigned" ${toLovelaces}) #amount of lovelaces - ;; - - * ) #Build the tx-out cbor in alonzo/shelley format with array - local cborStr="" #setup a clear new cbor string variable, will hold the tx-out cbor part - local cborStr+=$(to_cbor "array" 2) #array 2 - local cborStr+=$(to_cbor "bytes" "${toAddrHex}") #toAddr in hex - local cborStr+=$(to_cbor "unsigned" ${toLovelaces}) #amount of lovelaces - ;; + *"babbage"* | *"conway"* ) #Build the tx-out cbor in babbage-tx format with maps + local cborStr="" #setup a clear new cbor string variable, will hold the tx-out cbor part + local cborStr+=$(to_cbor "map" 2) #map 2 + local cborStr+=$(to_cbor "unsigned" 0) #unsigned 0 + local cborStr+=$(to_cbor "bytes" "${toAddrHex}") #toAddr in hex + local cborStr+=$(to_cbor "unsigned" 1) #unsigned 1 + local cborStr+=$(to_cbor "unsigned" ${toLovelaces}) #amount of lovelaces + ;; + + * ) #Build the tx-out cbor in alonzo/shelley format with array + local cborStr="" #setup a clear new cbor string variable, will hold the tx-out cbor part + local cborStr+=$(to_cbor "array" 2) #array 2 + local cborStr+=$(to_cbor "bytes" "${toAddrHex}") #toAddr in hex + local cborStr+=$(to_cbor "unsigned" ${toLovelaces}) #amount of lovelaces + ;; esac @@ -847,20 +1169,20 @@ if [[ ${protocolVersionMajor} -ge 7 ]]; then #7=Babbage and above, new since bab case ${nodeEraParam,,} in - *"babbage"* ) #Build the tx-out cbor in babbage-tx format with maps + *"babbage"* | *"conway"* ) #Build the tx-out cbor in babbage-tx format with maps - local cborStr="" #setup a clear new cbor string variable, will hold the tx-out cbor part - local cborStr+=$(to_cbor "map" 2) #map 2 - local cborStr+=$(to_cbor "unsigned" 0) #unsigned 0 - local cborStr+=$(to_cbor "bytes" "${toAddrHex}") #toAddr in hex - local cborStr+=$(to_cbor "unsigned" 1) #unsigned 1 - ;; + local cborStr="" #setup a clear new cbor string variable, will hold the tx-out cbor part + local cborStr+=$(to_cbor "map" 2) #map 2 + local cborStr+=$(to_cbor "unsigned" 0) #unsigned 0 + local cborStr+=$(to_cbor "bytes" "${toAddrHex}") #toAddr in hex + local cborStr+=$(to_cbor "unsigned" 1) #unsigned 1 + ;; - * ) #Build the tx-out cbor in alonzo/shelley format with array - local cborStr="" #setup a clear new cbor string variable, will hold the tx-out cbor part - local cborStr+=$(to_cbor "array" 2) #array 2 - local cborStr+=$(to_cbor "bytes" "${toAddrHex}") #toAddr in hex - ;; + * ) #Build the tx-out cbor in alonzo/shelley format with array + local cborStr="" #setup a clear new cbor string variable, will hold the tx-out cbor part + local cborStr+=$(to_cbor "array" 2) #array 2 + local cborStr+=$(to_cbor "bytes" "${toAddrHex}") #toAddr in hex + ;; esac @@ -982,6 +1304,419 @@ echo ${minOutUTXO} #return the minOutUTXO value for the txOut-String with or wit +#------------------------------------------------------- +#queryLight_UTXO function +# +# makes an online query via koios API and returns and output like a cli utxo query +# +queryLight_UTXO() { #${1} = address to query + + local addr=${1} + local errorcnt=0 + local error=-1 + while [[ ${errorcnt} -lt 5 && ${error} -ne 0 ]]; do #try a maximum of 5 times to request the information via koios API + error=0 + response=$(curl -sL -m 120 -X POST -w "---spo-scripts---%{http_code}" "${koiosAPI}/address_utxos?select=tx_hash,tx_index,value,asset_list" -H "Accept: application/json" -H "Content-Type: application/json" -d "{\"_addresses\":[\"${addr}\"], \"_extended\": true}" 2> /dev/null) + if [ $? -ne 0 ]; then error=1; fi; + errorcnt=$(( ${errorcnt} + 1 )) + done + if [[ ${error} -ne 0 ]]; then echo -e "Query of the Koios-API via curl failed, tried 5 times."; exit 1; fi; #curl query failed + + if [[ "${response}" =~ (.*)---spo-scripts---([0-9]*)* ]]; then #split the response string into JSON content and the HTTP-ResponseCode + local responseJSON="${BASH_REMATCH[1]}" + local responseCode="${BASH_REMATCH[2]}" + else + echo -e "Query of the Koios-API via curl failed. Could not separate Content and ResponseCode."; exit 1; #curl query failed + fi + + #Check the responseCode + case ${responseCode} in + "200" ) ;; #all good, continue + "504" ) echo -e "HTTP Response code: ${responseCode} - Koios API took too long to query the request. You might use the normal 'online' mode instead."; exit 1;; #exit with a failure and the http response code + * ) echo -e "HTTP Response code: ${responseCode}"; exit 1; #exit with a failure and the http response code + esac; + utxoRet=$(jq -r "(\"TxHash TxIx Amount---\"), ( . | sort_by(.tx_hash) | .[] | \"\(.tx_hash) \(.tx_index) \(.value) lovelace \", (.asset_list[] | \"+ \(.quantity) \(.policy_id).\(.asset_name) \"), \"\")" <<< "${responseJSON}" 2> /dev/null) + if [ $? -ne 0 ]; then echo -e "Query via Koios-API (${koiosAPI}) failed, not a JSON response."; exit 1; fi; #reponse is not a json file + utxoRet=$(tr -d '\n' <<< "${utxoRet}" | sed 's//\n/g' | sed 's/\. / /g') #reformat the utxo output so it is like the cli output + + #return the utxo + printf "${utxoRet}" + unset utxoRet response responseCode responseJSON addr error errorcnt + +} +#------------------------------------------------------- + + + +#------------------------------------------------------- +#queryLight_stakeAddressInfo function +# +# makes an online query via koios API and returns and output like a cli stake-address-info query +# +queryLight_stakeAddressInfo() { #${1} = address to query + + local addr=${1} + local errorcnt=0 + local error=-1 + while [[ ${errorcnt} -lt 5 && ${error} -ne 0 ]]; do #try a maximum of 5 times to request the information via koios API + error=0 + response=$(curl -sL -m 30 -X POST -w "---spo-scripts---%{http_code}" "${koiosAPI}/account_info" -H "Accept: application/json" -H "Content-Type: application/json" -d "{\"_stake_addresses\":[\"${addr}\"]}" 2> /dev/null) + if [ $? -ne 0 ]; then error=1; fi; + errorcnt=$(( ${errorcnt} + 1 )) + done + if [[ ${error} -ne 0 ]]; then echo -e "Query of the Koios-API via curl failed, tried 5 times."; exit 1; fi; #curl query failed + + #Split the response string into JSON content and the HTTP-ResponseCode + if [[ "${response}" =~ (.*)---spo-scripts---([0-9]*)* ]]; then + local responseJSON="${BASH_REMATCH[1]}" + local responseCode="${BASH_REMATCH[2]}" + else + echo -e "Query of the Koios-API via curl failed. Could not separate Content and ResponseCode."; exit 1; #curl query failed + fi + + #Check the responseCode + case ${responseCode} in + "200" ) ;; #all good, continue + * ) echo -e "HTTP Response code: ${responseCode}"; exit 1; #exit with a failure and the http response code + esac; + + jsonRet=$(jq -r . <<< "${responseJSON}" 2> /dev/null) + if [ $? -ne 0 ]; then echo -e "Query via Koios-API (${koiosAPI}) failed, not a JSON response."; exit 1; fi; #reponse is not a json file + + #check if the stakeAddress is registered, if not, return an empty array + if [[ $(jq -r ".[0].status" <<< "${responseJSON}" 2> /dev/null) != "registered" ]]; then + printf "[]"; #stakeAddress not registered on chain, return an empty array + else +# local delegation=$(jq -r ".[0].delegated_pool" <<< "${responseJSON}" 2> /dev/null) +# local rewardAccountBalance=$(jq -r ".[0].rewards_available" <<< "${responseJSON}" 2> /dev/null) + local delegation; local rewardAccountBalance; local delegationDeposit; #define local variables so we can read it in one go with the next jq command + { read delegation; read rewardAccountBalance; read delegationDeposit; } <<< $(jq -r ".[0].delegated_pool // \"null\", .[0].rewards_available // \"null\", .[0].deposit // \"null\"" <<< "${responseJSON}" 2> /dev/null) + + #deposit value, always 2000000 lovelaces until conway +# local delegationDeposit=$(jq -r ".[0].deposit" <<< "${responseJSON}" 2> /dev/null) + if [[ ${delegationDeposit} == null ]]; then delegationDeposit=2000000; fi + + jsonRet="[ { \"address\": \"${addr}\", \"stakeDelegation\": \"${delegation}\", \"delegationDeposit\": ${delegationDeposit}, \"rewardAccountBalance\": ${rewardAccountBalance} } ]" #compose a json like the cli output + #return the composed json + printf "${jsonRet}" + fi + + unset jsonRet response responseCode responseJSON addr error errorcnt + +} +#------------------------------------------------------- + + + +#------------------------------------------------------- +#submitLight function +# +# submits a given TxFile via koios API and returns the corresponding txID +# +submitLight() { #${1} = path to txFile + + local txFile=${1} + + cborStr=$(jq -r ".cborHex" < "${txFile}" 2> /dev/null) + if [ $? -ne 0 ]; then echo -e "Submit via Koios-API (${koiosAPI}) failed, could not read the 'cborHex' from '${txFile}'."; exit 1; fi; #jq readout failed + + local errorcnt=0 + local error=-1 + while [[ ${errorcnt} -lt 5 && ${error} -ne 0 ]]; do #try a maximum of 5 times to submit via koios API + error=0 + response=$(xxd -p -r <<< "${cborStr}" | curl -sL -m 120 -X POST -w "---spo-scripts---%{http_code}" -H "Content-Type: application/cbor" --data-binary @- "${koiosAPI}/submittx" 2> /dev/null) + if [ $? -ne 0 ]; then error=1; fi; + errorcnt=$(( ${errorcnt} + 1 )) + done + if [[ ${error} -ne 0 ]]; then echo -e "Submit to the Koios-API via curl failed, tried 5 times."; exit 1; fi; #curl call failed + + if [[ "${response}" =~ (.*)---spo-scripts---([0-9]*)* ]]; then #split the response string into JSON content and the HTTP-ResponseCode + local responseTxID="${BASH_REMATCH[1]}" + local responseCode="${BASH_REMATCH[2]}" + else + echo -e "Submit to the Koios-API via curl failed. Could not separate Content and ResponseCode."; exit 1; #curl call failed + fi + + #Check the responseCode + case ${responseCode} in + "202" ) ;; #all good, continue + "400" ) echo -e "HTTP Response code: ${responseCode} - Koios API reported back an error. Maybe you have to wait for the next block - please retry later.\nIf you have issues further on, please report back, thx!"; exit 1;; #exit with a failure and the http response code + * ) echo -e "HTTP Response code: ${responseCode}"; exit 1; #exit with a failure and the http response code + esac; + + local txID=${responseTxID//\"/} #remove any quote symbol + + #Check if the responseTxID is actually a valid one + if [[ "${txID//[![:xdigit:]]}" != "${txID}" || ${#txID} -ne 64 ]]; then #returned txID is not a valid one + echo -e "Submit via Koios-API (${koiosAPI}) failed, returned TxID is not a valid one.\nI've got back: ${responseTxID}"; exit 1; + fi; + + #return the txID + printf "${txID}" + unset response responseCode responseTxID txID txFile error errorcnt + +} +#------------------------------------------------------- + + + +#------------------------------------------------------- +#resolveAdahandle function +# +# this function resolves a given adahandle (cip25, cip68, virtual) into a payment address +# +# inputs +# ${1} = name of the adahandle +# ${2} = name of the variable that should be filled with the resolved address +# +# outputs +# variable '${2}' will be filled with the resolved address +# variable 'utxo' will hold the utxo query of a resolved adahandle if possible, so no further query needed in the calling script +resolveAdahandle() { + + #Adahandles will only work in online or light mode, exit with an error if in offline mode + if ${offlineMode}; then echo -e "\n\e[35mERROR - Adahandles are only supported in online & light mode.\n\e[0m"; exit 1; fi + + #If there is no koiosAPI available for this network, exit with an error + if [[ "${koiosAPI}" == "" ]]; then echo -e "\n\e[35mERROR - Adahandles are not supported on this network yet.\n\e[0m"; exit 1; fi; + + local adahandle="${1,,}" #lowercase the incoming adahandle + local outputVar="${2}" #hold the name of the output variable + local resolvedAddr="" + + #ROOT HANDLES + #check if its an root adahandle (without a @ char) -> do a lookup for the CIP-25 asset format, if not found do a lookup for the CIP-68 format + if checkAdaRootHandleFormat "${adahandle}"; then + + assetNameHex=$(convert_assetNameASCII2HEX ${adahandle:1}) + + #query classic cip-25 adahandle asset holding address via koios + local errorcnt=0 + local error=-1 + showProcessAnimation "Query Adahandle(CIP-25) into holding address: " & + while [[ ${errorcnt} -lt 5 && ${error} -ne 0 ]]; do #try a maximum of 5 times to request the information via koios API + error=0 + response=$(curl -sL -m 30 -X GET -w "---spo-scripts---%{http_code}" "${koiosAPI}/asset_addresses?_asset_policy=${adahandlePolicyID}&_asset_name=${assetNameHex}" -H "Accept: application/json" -H "Content-Type: application/json" 2> /dev/null) + if [ $? -ne 0 ]; then error=1; fi; + errorcnt=$(( ${errorcnt} + 1 )) + done + stopProcessAnimation; + if [[ ${error} -ne 0 ]]; then echo -e "\n\e[35mQuery of the Koios-API via curl failed, tried 5 times.\n\e[0m"; exit 1; fi; #curl query failed + + if [[ "${response}" =~ (.*)---spo-scripts---([0-9]*)* ]]; then #split the response string into JSON content and the HTTP-ResponseCode + local responseJSON="${BASH_REMATCH[1]}" + local responseCode="${BASH_REMATCH[2]}" + else + echo -e "Query of the Koios-API via curl failed. Could not separate Content and ResponseCode."; exit 1; #curl query failed + fi + + #check the responseCode + case ${responseCode} in + "200" ) ;; #all good, continue + * ) echo -e "\n\e[35mERROR - HTTP Response code: ${responseCode}\n\e[0m"; exit 1;; #exit with a failure and the http response code + esac; + tmpCheck=$(jq -r . <<< "${responseJSON}" 2> /dev/null) + if [ $? -ne 0 ]; then echo -e "\n\e[35mQuery via Koios-API (${koiosAPI}) failed, not a JSON response.\n\e[0m"; exit 1; fi; #reponse is not a json file + + #check if the received json only contains one entry in the array(=resolved), if not -> continue to check the cip-68 format + if [[ $(jq ". | length" 2> /dev/null <<< ${responseJSON}) -ne 1 ]]; then + + assetNameHex="000de140${assetNameHex}" + + #query CIP-68 adahandle asset holding address via koios + errorcnt=0;error=-1; + showProcessAnimation "Query Adahandle(CIP-68) into holding address: " & + while [[ ${errorcnt} -lt 5 && ${error} -ne 0 ]]; do #try a maximum of 5 times to request the information via koios API + error=0 + response=$(curl -sL -m 30 -X GET -w "---spo-scripts---%{http_code}" "${koiosAPI}/asset_addresses?_asset_policy=${adahandlePolicyID}&_asset_name=${assetNameHex}" -H "Accept: application/json" -H "Content-Type: application/json" 2> /dev/null) + if [ $? -ne 0 ]; then error=1; fi; + errorcnt=$(( ${errorcnt} + 1 )) + done + stopProcessAnimation; + if [[ ${error} -ne 0 ]]; then echo -e "\n\e[35mERROR - Query of the Koios-API via curl failed, tried 5 times.\n\e[0m"; exit 1; fi; #curl query failed + + if [[ "${response}" =~ (.*)---spo-scripts---([0-9]*)* ]]; then #split the response string into JSON content and the HTTP-ResponseCode + responseJSON="${BASH_REMATCH[1]}" + responseCode="${BASH_REMATCH[2]}" + else + echo -e "Query of the Koios-API via curl failed. Could not separate Content and ResponseCode."; exit 1; #curl query failed + fi + + #check the responseCode + case ${responseCode} in + "200" ) ;; #all good, continue + * ) echo -e "\n\e[35mERROR - HTTP Response code: ${responseCode}\n\e[0m"; exit 1;; #exit with a failure and the http response code + esac; + tmpCheck=$(jq -r . <<< "${responseJSON}" 2> /dev/null) + if [ $? -ne 0 ]; then echo -e "\n\e[35mERROR - Query via Koios-API (${koiosAPI}) failed, not a JSON response.\n\e[0m"; exit 1; fi; #reponse is not a json file + + #check if the received json only contains one entry in the array + if [[ $(jq ". | length" 2> /dev/null <<< ${responseJSON}) -ne 1 ]]; then echo -e "\n\e[33mCould not resolve Adahandle to an address.\n\e[0m"; exit 1; fi + + fi + + #we have a valid responseJSON from a CIP-25 or CIP-68 request + resolvedAddr=$(jq -r ".[0].payment_address" <<< ${responseJSON} 2> /dev/null) + + #lets check if the resolved address is actually a valid payment address + local typeOfAddr=$(get_addressType "${resolvedAddr}"); + if [[ ${typeOfAddr} != ${addrTypePayment} ]]; then echo -e "\n\e[35mERROR - Resolved address '${resolvedAddr}' is not a valid payment address.\n\e[0m"; exit 1; fi; + + #in fullmode -> check that the node is fully synced, otherwise the query would mabye return a false state + if [[ ${fullMode} == true && $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced or not running, please let your node sync to 100% first !\e[0m\n"; exit 1; fi + + #now lets verify that the adahandle native asset is actually on an utxo of that resolved address + showProcessAnimation "Verify Adahandle is on resolved address: " & + case ${workMode} in + "online") utxo=$(${cardanocli} ${cliEra} query utxo --address ${resolvedAddr} 2> /dev/stdout); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit 1; else stopProcessAnimation; fi;; + "light") utxo=$(queryLight_UTXO "${resolvedAddr}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit 1; else stopProcessAnimation; fi;; + esac + + #exit with an error if the adahandle is not on the address + if [[ $(grep "${adahandlePolicyID}.${assetNameHex} " <<< ${utxo} | wc -l) -ne 1 ]]; then echo -e "\n\e[35mERROR - Resolved address '${resolvedAddr}' does not hold the \$adahandle '${adahandle}' !\n\e[0m"; exit 1; fi; + + #ok, we found it + echo -e "\e[0mFound \$adahandle '${adahandle}' on Address:\e[32m ${resolvedAddr}\e[0m\n" + + + #SUBHANDLES/VIRTUALHANDLES + #check if its a sub-adahandle or a virtual-adahandle (with a @ char) -> do a lookup via the Adahandle-API, verify via utxo check or Koios + elif checkAdaSubHandleFormat "${adahandle}"; then + + + #query virtual subHandle via adahandleAPI + if [[ "${adahandleAPI}" == "" ]]; then echo -e "\n\e[33mERROR - There is no Adahandle-API available for this network.\n\e[0m"; exit 1; fi + + local errorcnt=0 + local error=-1 + showProcessAnimation "Query sub/virtual Adahandle via the Adahandle-API (${adahandleAPI}): " & + while [[ ${errorcnt} -lt 5 && ${error} -ne 0 ]]; do #try a maximum of 5 times to request the information via koios API + error=0 + response=$(curl -sL -m 30 -X GET -w "---spo-scripts---%{http_code}" "${adahandleAPI}/handles/${adahandle:1}" -H "Accept: application/json" -H "Content-Type: application/json" 2> /dev/null) + if [ $? -ne 0 ]; then error=1; fi; + errorcnt=$(( ${errorcnt} + 1 )) + done + stopProcessAnimation; + if [[ ${error} -ne 0 ]]; then echo -e "\n\e[35mQuery via Adahandle-API (${adahandleAPI}) failed, tried 5 times.\n\e[0m"; exit 1; fi; #curl query failed + + if [[ "${response}" =~ (.*)---spo-scripts---([0-9]*)* ]]; then #split the response string into JSON content and the HTTP-ResponseCode + local responseJSON="${BASH_REMATCH[1]}" + local responseCode="${BASH_REMATCH[2]}" + else + echo -e "Query via Adahandle-API via curl failed. Could not separate Content and ResponseCode."; exit 1; #curl query failed + fi + + #Check the responseCode + case ${responseCode} in + "200" ) ;; #all good, continue + "202" ) echo -e "\n\e[33mAdahandle was found, but the API sync is not on tip with the network status. Please try again later.\n\e[0m"; exit 1;; + "404" ) echo -e "\n\e[33mAdahandle '${adahandleName}' was not found, cannot resolve it to an address.\n\e[0m"; exit 1;; + * ) echo -e "\n\e[33m$(jq -r .message <<< ${responseJSON})\nAdahandle-API response code: ${responseCode}"; + echo -e "\nIf you think this is an issue, please report this via the SPO-Scripts Github-Repository https://github.com/gitmachtl/scripts\n\e[0m"; exit 1;; + esac; + + #query was successful, get the address + resolvedAddr=$(jq -r ".\"resolved_addresses\".ada" <<< ${responseJSON} 2> /dev/null) + if [ $? -ne 0 ]; then echo -e "\n\e[35mERROR - The received data from the Adahandle-API is not a valid JSON.\n\e[0m"; exit 1; fi; + + #lets check if the resolved address is actually a valid payment address + local typeOfAddr=$(get_addressType "${resolvedAddr}"); + if [[ ${typeOfAddr} != ${addrTypePayment} ]]; then echo -e "\n\e[35mERROR - Resolved address '${resolvedAddr}' is not a valid payment address.\n\e[0m"; exit 1; fi; + + #lets check the resolved address. if its a cip-68 subhandle (starting with hex 000de140) than it lives on an utxo which resolves to the address + #if its a virtual subhandle (strting with hex 00000000) than the resolved address is within the inline_datum + #check that the node is fully synced, otherwise the query would mabye return a false state + assetNameHex=$(jq -r ".hex" <<< ${responseJSON}); + case "${assetNameHex}" in + + "000de140"* ) #its a cip-68 subhandle, lets verify it is actually on the resolved address + + #in fullmode -> check that the node is fully synced, otherwise the query would mabye return a false state + if [[ ${fullMode} == true && $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced or not running, please let your node sync to 100% first !\e[0m\n"; exit 1; fi + + #now lets verify that the adahandle native asset is actually on an utxo of that resolved address + showProcessAnimation "Verify Adahandle is on resolved address: " & + case ${workMode} in + "online") utxo=$(${cardanocli} ${cliEra} query utxo --address ${resolvedAddr} 2> /dev/stdout); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit 1; else stopProcessAnimation; fi;; + "light") utxo=$(queryLight_UTXO "${resolvedAddr}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit 1; else stopProcessAnimation; fi;; + esac + + #exit with an error if the adahandle is not on the address + if [[ $(grep "${adahandlePolicyID}.${assetNameHex} " <<< ${utxo} | wc -l) -ne 1 ]]; then echo -e "\n\e[35mERROR - Resolved address '${resolvedAddr}' does not hold the \$adahandle '${adahandle}' !\n\e[0m"; exit 1; fi; + + #ok, we found it + echo -e "\e[0mFound \$subhandle '${adahandle}' on Address:\e[32m ${resolvedAddr}\e[0m\n" + ;; + + "00000000"* ) #its a virtual subhandle, lets check a second opinion by doing a koios api query too + + #query cip-68 adahandle asset utxo, and check the inline_datum + errorcnt=0;error=-1; + showProcessAnimation "Query Virtualhandle into holding address: " & + while [[ ${errorcnt} -lt 5 && ${error} -ne 0 ]]; do #try a maximum of 5 times to request the information via koios API + error=0 + response=$(curl -sL -m 30 -X POST -w "---spo-scripts---%{http_code}" "${koiosAPI}/asset_utxos?select=inline_datum" -H "Accept: application/json" -H "Content-Type: application/json" -d "{\"_asset_list\":[[\"${adahandlePolicyID}\",\"${assetNameHex}\"]],\"_extended\":true}" 2> /dev/null) + if [ $? -ne 0 ]; then error=1; fi; + errorcnt=$(( ${errorcnt} + 1 )) + done + stopProcessAnimation; + if [[ ${error} -ne 0 ]]; then echo -e "\n\e[35mERROR - Query of the Koios-API via curl failed, tried 5 times.\n\e[0m"; exit 1; fi; #curl query failed + + if [[ "${response}" =~ (.*)---spo-scripts---([0-9]*)* ]]; then #split the response string into JSON content and the HTTP-ResponseCode + responseJSON="${BASH_REMATCH[1]}" + responseCode="${BASH_REMATCH[2]}" + else + echo -e "Query of the Koios-API via curl failed. Could not separate Content and ResponseCode."; exit 1; #curl query failed + fi + + #check the responseCode + case ${responseCode} in + "200" ) ;; #all good, continue + * ) echo -e "\n\e[35mERROR - HTTP Response code: ${responseCode}\n\e[0m"; exit 1;; #exit with a failure and the http response code + esac; + tmpCheck=$(jq -r . <<< "${responseJSON}" 2> /dev/null) + if [ $? -ne 0 ]; then echo -e "\n\e[35mQuery via Koios-API (${koiosAPI}) failed, not a JSON response.\n\e[0m"; exit 1; fi; #reponse is not a json file + + #check if the received json only contains one entry in the array (will also not be 1 if not a valid json) + if [[ $(jq ". | length" 2> /dev/null <<< ${responseJSON}) -ne 1 ]]; then echo -e "\n\e[33mCould not query Koios-API about 'asset_utxos'.\n\e[0m"; exit 1; fi + + #lets extract the resolved address from the inline_datum into resolvedAddrCheckHex + local resolvedAddrCheckHex=$(jq -r ".[0].inline_datum.bytes" <<< ${responseJSON} | sed -n "s/.*7265736f6c7665645f616464726573736573.*\(436164615839.*\)/\1/p" | cut -c 13-126) + + #get the bech address for mainnet/testnets + if [[ "${magicparam}" == *"mainnet"* ]]; then local resolvedAddrCheck=$(${bech32_bin} "addr" <<< "${resolvedAddrCheckHex}" 2> /dev/null); + else local resolvedAddrCheck=$(${bech32_bin} "addr_test" <<< "${resolvedAddrCheckHex}" 2> /dev/null); + fi + + #exit with an error if the adahandle is not on the address + if [[ "${resolvedAddr}" != "${resolvedAddrCheck}" ]]; then + echo -e "\n\e[35mERROR - Adahandle-API resolved address '${resolvedAddr}' does not\nmatch with Koios-API resolved address '${resolvedAddrCheck}' !\n\e[0m"; exit 1; fi; + + #ok, we found it + echo -e "\e[0mThis \e[33mvirtual\e[0m \$adahandle '${adahandle}' resolves to Address:\e[32m ${resolvedAddr}\n\e[0m" + ;; + + + esac + + else echo -e "\n\e[35mERROR - Thats strange, you should not have landed here with the Adahandle '${adahandle}'. Please report this issue, thx !\n\e[0m"; exit 1; + + fi #roothandle or subhandle + + +#RESOLVED - exit the function and give back the resolved address to the given variable name +printf -v ${outputVar} "%s" "${resolvedAddr}" + +unset outputVar error errorcnt response responseCode responseJSON resolvedAddr resolvedAddrCheck resolvedAddrCheckHex typeOfAddr tmpCheck +} +#------------------------------------------------------- + + + #------------------------------------------------------- #to_cbor function # @@ -1082,6 +1817,40 @@ echo -n "${cbor^^}" #return the cbor in uppercase #------------------------------------------------------- +#------------------------------------------------------- +#int_from_cbor function +# +# decodes an unsigned integer from a given cborHexString +# maximum supported number is a 8 byte long unsigned int +# +int_from_cbor() { + + # ${1} string: cbor encoded hex string starting at the integer position + # ${2} count: optional number of entry count -> 0 = the number at that position, 1 = the next number, 2 = the number after the next number + # + local cborHexString="${1^^}" #convert the given string into an uppercase one + local entryCnt="${2:- 0}" #number of interations left + local value="${cborHexString:0:2}" #get the first two chars + local charLen=0 #number of chars the current number used in the cborHexString + + + if [[ "0x${value}" < "0x18" ]]; then printf -v intVal "%d" "0x${cborHexString:0:2}" 2> /dev/null; retCode=$?; charLen=2; #1byte total value below 0x18 (24dec) + elif [[ "${value}" == "18" ]]; then printf -v intVal "%d" "0x${cborHexString:2:2}" 2> /dev/null; retCode=$?; charLen=4; #2bytes total: first 0x1800 + 1 lower byte value + elif [[ "${value}" == "19" ]]; then printf -v intVal "%d" "0x${cborHexString:2:4}" 2> /dev/null; retCode=$?; charLen=6; #3bytes total: first 0x190000 + 2 lowerbytes value + elif [[ "${value}" == "1A" ]]; then printf -v intVal "%d" "0x${cborHexString:2:8}" 2> /dev/null; retCode=$?; charLen=10; #5bytes total: 0x1A00000000 + 4 lower bytes value + elif [[ "${value}" == "1B" ]]; then printf -v intVal "%d" "0x${cborHexString:2:16}" 2> /dev/null; retCode=$?; charLen=18; #9bytes total: first 0x1B0000000000000000 + 8 lower bytes value + else local intVal=-1; retCode=1 + fi + + if [[ ${retCode} -eq 0 && ${entryCnt} -eq 0 ]]; then + echo -n "${intVal}"; exit 0; #no further work to do, return the number + elif [[ ${retCode} -eq 0 && ${entryCnt} -ne 0 ]]; then + entryCnt=$(( ${entryCnt} -1 )); tmp=$(int_from_cbor "${cborHexString:${charLen} }" "${entryCnt}"); retCode=$?; echo -n "${tmp}"; exit ${retCode}; #itteration, go to the next number + else + echo -n "error"; exit 1; #an error occured + fi + +} @@ -1216,7 +1985,7 @@ if [ -f "${offlineFile}" ]; then if [[ ! $(jq ".protocol.parameters | length" <<< ${offlineJSON}) -gt 0 ]]; then echo -e "\e[35mERROR - '$(basename ${offlineFile})' contains no protocol parameters. Please generate a valid offlineJSON first in onlinemode.\e[0m\n"; exit 1; fi else offileJSON=null - echo -e "\e[35mERROR - '$(basename ${offlineFile})' is not present, please generate a valid offlineJSON first in onlinemode.\e[0m\n"; exit 1; + echo -e "\e[35mERROR - '$(basename ${offlineFile})' is not present, please generate a valid offlineJSON first in onlinemode.\nYou can do so by running \e[33m01_workOffline.sh new\e[0m\n"; exit 1; fi } diff --git a/cardano/mainnet/01_claimRewards.sh b/cardano/mainnet/01_claimRewards.sh index c33994f9..d7bb7c38 100755 --- a/cardano/mainnet/01_claimRewards.sh +++ b/cardano/mainnet/01_claimRewards.sh @@ -174,37 +174,17 @@ if [ ! -f "${toAddr}.addr" ]; then typeOfAddr=$(get_addressType "${toAddr}"); if [[ ${typeOfAddr} == ${addrTypePayment} ]]; then echo "$(basename ${toAddr})" > ${tempDir}/tempTo.addr; toAddr="${tempDir}/tempTo"; - #check if its an root adahandle (without a @ char) - elif checkAdaRootHandleFormat "${toAddr}"; then - if ${offlineMode}; then echo -e "\n\e[35mERROR - Adahandles are only supported in Online mode.\n\e[0m"; exit 1; fi + #check if its an adahandle (root/sub/virtual) + elif checkAdaHandleFormat "${toAddr}"; then + adahandleName=${toAddr,,} - assetNameHex=$(convert_assetNameASCII2HEX ${adahandleName:1}) - #query classic cip-25 adahandle asset holding address via koios - showProcessAnimation "Query Adahandle(CIP-25) into holding address: " & - response=$(curl -s -m 10 -X GET "${koiosAPI}/asset_address_list?_asset_policy=${adahandlePolicyID}&_asset_name=${assetNameHex}" -H "Accept: application/json" 2> /dev/null) - stopProcessAnimation; - #check if the received json only contains one entry in the array (will also not be 1 if not a valid json) - if [[ $(jq ". | length" 2> /dev/null <<< ${response}) -ne 1 ]]; then - #query classic cip-68 adahandle asset holding address via koios - showProcessAnimation "Query Adahandle(CIP-68) into holding address: " & - response=$(curl -s -m 10 -X GET "${koiosAPI}/asset_address_list?_asset_policy=${adahandlePolicyID}&_asset_name=000de140${assetNameHex}" -H "Accept: application/json" 2> /dev/null) - stopProcessAnimation; - #check if the received json only contains one entry in the array (will also not be 1 if not a valid json) - if [[ $(jq ". | length" 2> /dev/null <<< ${response}) -ne 1 ]]; then echo -e "\n\e[35mCould not resolve Adahandle to an address.\n\e[0m"; exit 1; fi - assetNameHex="000de140${assetNameHex}" - fi - toAddr=$(jq -r ".[0].payment_address" <<< ${response} 2> /dev/null) - typeOfAddr=$(get_addressType "${toAddr}"); - if [[ ${typeOfAddr} != ${addrTypePayment} ]]; then echo -e "\n\e[35mERROR - Resolved address '${toAddr}' is not a valid payment address.\n\e[0m"; exit 1; fi; - showProcessAnimation "Verify Adahandle is on resolved address: " & - utxo=$(${cardanocli} query utxo --address ${toAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; - if [[ $(grep "${adahandlePolicyID}.${assetNameHex} " <<< ${utxo} | wc -l) -ne 1 ]]; then - echo -e "\n\e[35mERROR - Resolved address '${toAddr}' does not hold the \$adahandle '${adahandleName}' !\n\e[0m"; exit 1; fi; - echo -e "\e[0mFound \$adahandle '${adahandleName}' on Address:\e[32m ${toAddr}\e[0m\n" - echo "$(basename ${toAddr})" > ${tempDir}/adahandle-resolve.addr; toAddr="${tempDir}/adahandle-resolve"; - - elif checkAdaSubHandleFormat "${toAddr}"; then - echo -e "\n\e[33mINFO - AdaSubHandles are not supported yet.\n\e[0m"; exit 1; + + #resolve given adahandle into address + resolveAdahandle "${adahandleName}" "toAddr" #if successful, it resolves the adahandle and writes it out into the variable 'toAddr'. also sets the variable 'utxo' if possible + unset utxo #remove utxo information from the adahandle lookup, because we only use it as a destination target + + #resolveAdahandle did not exit with an error, so we resolved it + echo "${toAddr}" > ${tempDir}/adahandle-resolve.addr; toAddr="${tempDir}/adahandle-resolve"; #otherwise post an error message else echo -e "\n\e[35mERROR - Destination Address can't be resolved. Maybe filename wrong, or not a payment-address.\n\e[0m"; exit 1; @@ -262,9 +242,8 @@ echo -e "\e[0mClaim Staking Rewards from Address\e[32m ${stakeAddr}.addr\e[0m to echo #get live values -currentTip=$(get_currentTip) -ttl=$(get_currentTTL) -currentEPOCH=$(get_currentEpoch) +currentTip=$(get_currentTip); checkError "$?"; +ttl=$(( ${currentTip} + ${defTTL} )) echo -e "Current Slot-Height:\e[32m ${currentTip}\e[0m (setting TTL[invalid_hereafter] to ${ttl})" echo @@ -277,14 +256,27 @@ if [[ "${sendFromAddr}" == "${sendToAddr}" ]]; then rxcnt="1"; else rxcnt="2"; e echo - #Get rewards state data for the address. When in online mode of course from the node and the chain, in offlinemode from the transferFile - if ${onlineMode}; then - rewardsJSON=$(${cardanocli} query stake-address-info --address ${stakingAddr} ${magicparam} | jq -rc .) - else - rewardsJSON=$(cat ${offlineFile} | jq -r ".address.\"${stakingAddr}\".rewardsJSON" 2> /dev/null) - if [[ "${rewardsJSON}" == null ]]; then echo -e "\e[35mStake-Address not included in the offline transferFile, please include it first online!\e[0m\n"; exit; fi - fi - checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi + #Get rewards state data for the address. When in online mode of course from the node and the chain, in light mode via koios, in offlinemode from the transferFile + case ${workMode} in + + "online") showProcessAnimation "Query-StakeAddress-Info: " & + rewardsJSON=$(${cardanocli} ${cliEra} query stake-address-info --address ${stakingAddr} 2> /dev/null ) + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${rewardsJSON}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + rewardsJSON=$(jq -rc . <<< "${rewardsJSON}") + ;; + + "light") showProcessAnimation "Query-StakeAddress-Info-LightMode: " & + rewardsJSON=$(queryLight_stakeAddressInfo "${stakingAddr}") + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${rewardsJSON}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + + "offline") readOfflineFile; #Reads the offlinefile into the offlineJSON variable + rewardsJSON=$(jq -r ".address.\"${stakingAddr}\".rewardsJSON" <<< ${offlineJSON} 2> /dev/null) + if [[ "${rewardsJSON}" == null ]]; then echo -e "\e[35mAddress not included in the offline transferFile, please include it first online!\e[0m\n"; exit; fi + ;; + + esac + rewardsEntryCnt=$(jq -r 'length' <<< ${rewardsJSON}) if [[ ${rewardsEntryCnt} == 0 ]]; then echo -e "\e[35mStaking Address is not on the chain, register it first !\e[0m\n"; exit 1; @@ -297,7 +289,7 @@ echo do rewardsAmount=$(jq -r ".[${tmpCnt}].rewardAccountBalance" <<< ${rewardsJSON}) - delegationPoolID=$(jq -r ".[${tmpCnt}].delegation" <<< ${rewardsJSON}) + delegationPoolID=$(jq -r ".[${tmpCnt}].delegation // .[${tmpCnt}].stakeDelegation" <<< ${rewardsJSON}) rewardsSum=$((${rewardsSum}+${rewardsAmount})) @@ -309,7 +301,46 @@ echo fi #If delegated to a pool, show the current pool ID - if [[ ! ${delegationPoolID} == null ]]; then echo -e " \tAccount is delegated to a Pool with ID: \e[32m${delegationPoolID}\e[0m"; fi + if [[ ! ${delegationPoolID} == null ]]; then + echo -e " \tAccount is delegated to a Pool with ID: \e[32m${delegationPoolID}\e[0m"; + + if [[ ${onlineMode} == true && ${koiosAPI} != "" ]]; then + + #query poolinfo via poolid on koios + errorcnt=0; error=-1; + showProcessAnimation "Query Pool-Info via Koios: " & + while [[ ${errorcnt} -lt 5 && ${error} -ne 0 ]]; do #try a maximum of 5 times to request the information + error=0 + response=$(curl -sL -m 30 -X POST -w "---spo-scripts---%{http_code}" "${koiosAPI}/pool_info" -H "Accept: application/json" -H "Content-Type: application/json" -d "{\"_pool_bech32_ids\":[\"${delegationPoolID}\"]}" 2> /dev/null) + if [[ $? -ne 0 ]]; then error=1; sleep 1; fi; #if there is an error, wait for a second and repeat + errorcnt=$(( ${errorcnt} + 1 )) + done + stopProcessAnimation; + + #if no error occured, split the response string into JSON content and the HTTP-ResponseCode + if [[ ${error} -eq 0 && "${response}" =~ (.*)---spo-scripts---([0-9]*)* ]]; then + + responseJSON="${BASH_REMATCH[1]}" + responseCode="${BASH_REMATCH[2]}" + + #if the responseCode is 200 (OK) and the received json only contains one entry in the array (will also not be 1 if not a valid json) + if [[ ${responseCode} -eq 200 && $(jq ". | length" 2> /dev/null <<< ${responseJSON}) -eq 1 ]]; then + { read poolNameInfo; read poolTickerInfo; read poolStatusInfo; } <<< $(jq -r ".[0].meta_json.name // \"-\", .[0].meta_json.ticker // \"-\", .[0].pool_status // \"-\"" 2> /dev/null <<< ${responseJSON}) + echo -e " \t\e[0mInformation about the Pool: \e[32m${poolNameInfo} (${poolTickerInfo})\e[0m" + echo -e " \t\e[0m Status: \e[32m${poolStatusInfo}\e[0m" + echo + fi #responseCode & jsoncheck + + fi #error & response + unset errorcnt error + + fi #onlineMode & koiosAPI + + else + + echo -e " \tAccount is not delegated to a Pool !"; + + fi echo @@ -322,24 +353,45 @@ echo #------------------------------------- +echo -e "\n--------------------------------------------\n" + + # # Checking UTXO Data of the source address and gathering data about total lovelaces and total assets # - #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in offlinemode from the transferFile - if ${onlineMode}; then + #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in lightmode via API requests, in offlinemode from the transferFile + case ${workMode} in + "online") + #check that the node is fully synced, otherwise the query would mabye return a false state + if [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced or not running, please let your node sync to 100% first !\e[0m\n"; exit 1; fi showProcessAnimation "Query-UTXO: " & - utxo=$(${cardanocli} query utxo --address ${sendFromAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + utxo=$(${cardanocli} ${cliEra} query utxo --address ${sendFromAddr} 2> /dev/stdout); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + if [[ ${skipUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep -v "${skipUtxoWithAsset}" ); fi #if its set to keep utxos that contains certain policies, filter them out + if [[ ${onlyUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep "${onlyUtxoWithAsset}" ); utxo=$(echo -e "Header\n-----\n${utxo}"); fi #only use given utxos. rebuild the two header lines + if [[ ${utxoLimitCnt} -gt 0 ]]; then utxo=$(echo "${utxo}" | head -n $(( ${utxoLimitCnt} + 2 )) ); fi #if there was a utxo cnt limit set, reduce it (+2 for the header) + showProcessAnimation "Convert-UTXO: " & + utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; + ;; + + "light") + showProcessAnimation "Query-UTXO-LightMode: " & + utxo=$(queryLight_UTXO "${sendFromAddr}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; if [[ ${skipUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep -v "${skipUtxoWithAsset}" ); fi #if its set to keep utxos that contains certain policies, filter them out if [[ ${onlyUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep "${onlyUtxoWithAsset}" ); utxo=$(echo -e "Header\n-----\n${utxo}"); fi #only use given utxos. rebuild the two header lines if [[ ${utxoLimitCnt} -gt 0 ]]; then utxo=$(echo "${utxo}" | head -n $(( ${utxoLimitCnt} + 2 )) ); fi #if there was a utxo cnt limit set, reduce it (+2 for the header) showProcessAnimation "Convert-UTXO: " & utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; - else - readOfflineFile; #Reads the offlinefile into the offlineJSON variable - utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON}) + ;; + + + "offline") readOfflineFile; #Reads the offlinefile into the offlineJSON variable + utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON} 2> /dev/null) if [[ "${utxoJSON}" == null ]]; then echo -e "\e[35mPayment-Address not included in the offline transferFile, please include it first online!\e[0m\n"; exit 1; fi - fi + ;; + esac #Only use UTXOs specied in the extra parameter if present if [[ ! "${filterForUTXO}" == "" ]]; then echo -e "\e[0mUTXO-Mode: \e[32mOnly using the UTXO with Hash ${filterForUTXO}\e[0m\n"; utxoJSON=$(filterFor_UTXO "${utxoJSON}" "${filterForUTXO}"); fi @@ -400,8 +452,20 @@ echo totalAssetsJSON=$( jq ". += {\"${assetHash}${point}${assetName}\":{amount: \"${newValue}\", name: \"${assetTmpName}\", bech: \"${assetBech}\"}}" <<< ${totalAssetsJSON}) if [[ "${assetTmpName:0:1}" == "." ]]; then assetTmpName=${assetTmpName:1}; else assetTmpName="{${assetTmpName}}"; fi - case ${assetHash} in - "${adahandlePolicyID}" ) #$adahandle + case "${assetHash}${assetTmpName:1:8}" in + "${adahandlePolicyID}000de140" ) #$adahandle cip-68 + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Own): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}00000000" ) #$adahandle virtual + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Vir): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}000643b0" ) #$adahandle reference + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Ref): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}"* ) #$adahandle cip-25 echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle: \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" ;; * ) #default @@ -463,12 +527,13 @@ if [[ ! "${transactionMessage}" == "{}" ]]; then echo -e "\e[0mInclude Transaction-Message-Metadata-File:\e[32m ${transactionMessageMetadataFile}\n\e[90m"; cat ${transactionMessageMetadataFile}; echo -e "\e[0m"; fi + #Read ProtocolParameters -if ${onlineMode}; then - protocolParametersJSON=$(${cardanocli} query protocol-parameters ${magicparam} ); #onlinemode - else - protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON}); #offlinemode - fi +case ${workMode} in + "online") protocolParametersJSON=$(${cardanocli} ${cliEra} query protocol-parameters );; #onlinemode + "light") protocolParametersJSON=${lightModeParametersJSON};; #lightmode + "offline") protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON});; #offlinemode +esac checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi minOutUTXO=$(calc_minOutUTXO "${protocolParametersJSON}" "${sendToAddr}+1000000${assetsOutString}") @@ -482,13 +547,13 @@ withdrawal="${stakingAddr}+${rewardsSum}" txBodyFile="${tempDir}/dummy.txbody" rm ${txBodyFile} 2> /dev/null if [[ ${rxcnt} == 1 ]]; then - ${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --withdrawal ${withdrawal} --out-file ${txBodyFile} + ${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --withdrawal ${withdrawal} --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi else - ${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendFromAddr}+1000000${assetsOutString}" --tx-out ${sendToAddr}+1000000 --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --withdrawal ${withdrawal} --out-file ${txBodyFile} + ${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendFromAddr}+1000000${assetsOutString}" --tx-out ${sendToAddr}+1000000 --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --withdrawal ${withdrawal} --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi fi -fee=$(${cardanocli} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} ${magicparam} --witness-count 2 --byron-witness-count 0 | awk '{ print $1 }') +fee=$(${cardanocli} ${cliEra} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} --witness-count 2 --byron-witness-count 0 | awk '{ print $1 }') echo -e "\e[0mMimimum transfer Fee for ${txcnt}x TxIn & ${rxcnt}x TxOut & Withdrawal: \e[32m $(convertToADA ${fee}) ADA / ${fee} lovelaces \e[90m" @@ -526,9 +591,9 @@ echo #Building unsigned transaction body if [[ ${rxcnt} == 1 ]]; then - ${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+${lovelacesToReturn}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --withdrawal ${withdrawal} --out-file ${txBodyFile} + ${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+${lovelacesToReturn}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --withdrawal ${withdrawal} --out-file ${txBodyFile} else - ${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendFromAddr}+${lovelacesToReturn}${assetsOutString}" --tx-out ${sendToAddr}+${rewardsSum} --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --withdrawal ${withdrawal} --out-file ${txBodyFile} + ${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendFromAddr}+${lovelacesToReturn}${assetsOutString}" --tx-out ${sendToAddr}+${rewardsSum} --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --withdrawal ${withdrawal} --out-file ${txBodyFile} fi dispFile=$(cat ${txBodyFile}); if ${cropTxOutput} && [[ ${#dispFile} -gt 4000 ]]; then echo "${dispFile:0:4000} ... (cropped)"; else echo "${dispFile}"; fi @@ -555,7 +620,7 @@ if [[ -f "${fromAddr}.hwsfile" && -f "${stakeAddr}.hwsfile" && "${paymentName}" if [[ "${tmp^^}" =~ (ERROR|DISCONNECT) ]]; then echo -e "\e[35m${tmp}\e[0m\n"; exit 1; else echo -ne "\e[0mWitnessed ... "; fi checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - ${cardanocli} transaction assemble --tx-body-file ${txBodyFile} --witness-file ${txWitnessFile}-payment --witness-file ${txWitnessFile}-staking --out-file ${txFile} + ${cardanocli} ${cliEra} transaction assemble --tx-body-file ${txBodyFile} --witness-file ${txWitnessFile}-payment --witness-file ${txWitnessFile}-staking --out-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "Assembled ... \e[32mDONE\e[0m\n"; @@ -569,7 +634,7 @@ elif [[ -f "${stakeAddr}.skey" && -f "${fromAddr}.skey" ]]; then #with the norma echo -e "\e[0mSign the unsigned transaction body with the \e[32m${fromAddr}.skey\e[0m & \e[32m${stakeAddr}.skey\e[0m: \e[32m ${txFile} \e[90m" echo - ${cardanocli} transaction sign --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON1}") --signing-key-file <(echo "${skeyJSON2}") ${magicparam} --out-file ${txFile} + ${cardanocli} ${cliEra} transaction sign --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON1}") --signing-key-file <(echo "${skeyJSON2}") --out-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #forget the signing keys @@ -590,18 +655,31 @@ echo if [ "${ENV_SKIP_PROMPT}" == "YES" ] || ask "\n\e[33mDoes this look good for you, continue ?" N; then echo - if ${onlineMode}; then #onlinesubmit + case ${workMode} in + "online") + #onlinesubmit echo -ne "\e[0mSubmitting the transaction via the node... " - ${cardanocli} transaction submit --tx-file ${txFile} ${magicparam} + ${cardanocli} ${cliEra} transaction submit --tx-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "\e[32mDONE\n" - #Show the TxID - txID=$(${cardanocli} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" + #Show the TxID + txID=$(${cardanocli} ${cliEra} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; + + "light") + #lightmode submit + showProcessAnimation "Submit-Transaction-LightMode: " & + txID=$(submitLight "${txFile}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${txID}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + echo -e "\e[0mSubmit-Transaction-LightMode: \e[32mDONE\n" + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; - else #offlinestore + "offline") + #offlinestore txFileJSON=$(cat ${txFile} | jq .) offlineJSON=$( jq ".transactions += [ { date: \"$(date -R)\", type: \"Withdrawal\", @@ -616,7 +694,6 @@ if [ "${ENV_SKIP_PROMPT}" == "YES" ] || ask "\n\e[33mDoes this look good for you #Write the new offileFile content offlineJSON=$( jq ".history += [ { date: \"$(date -R)\", action: \"signed rewards withdrawal from '${stakeAddr}' to '${toAddr}', payment via '${fromAddr}'\" } ]" <<< ${offlineJSON}) offlineJSON=$( jq ".general += {offlineCLI: \"${versionCLI}\" }" <<< ${offlineJSON}) - offlineJSON=$( jq ".general += {offlineNODE: \"${versionNODE}\" }" <<< ${offlineJSON}) echo "${offlineJSON}" > ${offlineFile} #Readback the tx content and compare it to the current one readback=$(cat ${offlineFile} | jq -r ".transactions[-1].txJSON") @@ -626,8 +703,9 @@ if [ "${ENV_SKIP_PROMPT}" == "YES" ] || ask "\n\e[33mDoes this look good for you else echo -e "\e[35mERROR - Could not verify the written data in the '$(basename ${offlineFile})'. Retry again or generate a new '$(basename ${offlineFile})'.\e[0m\n"; fi + ;; - fi + esac fi diff --git a/cardano/mainnet/01_protectKey.sh b/cardano/mainnet/01_protectKey.sh index e24d7171..6ea8e0eb 100755 --- a/cardano/mainnet/01_protectKey.sh +++ b/cardano/mainnet/01_protectKey.sh @@ -24,6 +24,7 @@ Example: $(basename $0) enc mywallet ... Encrypts the mywallet.skey fi EOF } + #Check commandline parameters if [[ $# -lt 2 ]]; then showUsage; exit 1; fi #check about two given parameters case ${1^^} in diff --git a/cardano/mainnet/01_queryAddress.sh b/cardano/mainnet/01_queryAddress.sh index 66476707..6d005196 100755 --- a/cardano/mainnet/01_queryAddress.sh +++ b/cardano/mainnet/01_queryAddress.sh @@ -5,7 +5,6 @@ #load variables and functions from common.sh . "$(dirname "$0")"/00_common.sh - #Check the commandline parameter if [[ $# -eq 1 && ! $1 == "" ]]; then addrName="$(dirname $1)/$(basename $1 .addr)"; addrName=${addrName/#.\//}; else echo "ERROR - Usage: $0 "; exit 2; fi @@ -18,41 +17,19 @@ if [ ! -f "${addrName}.addr" ]; then typeOfAddr=$(get_addressType "${addrName}"); if [[ ${typeOfAddr} == ${addrTypePayment} || ${typeOfAddr} == ${addrTypeStake} ]]; then echo "$(basename ${addrName})" > ${tempDir}/tempAddr.addr; addrName="${tempDir}/tempAddr"; - #check if its an root adahandle (without a @ char) - elif checkAdaRootHandleFormat "${addrName}"; then - if ${offlineMode}; then echo -e "\n\e[35mERROR - Adahandles are only supported in Online mode.\n\e[0m"; exit 1; fi + #check if its an adahandle (root/sub/virtual) + elif checkAdaHandleFormat "${addrName}"; then + adahandleName=${addrName,,} - assetNameHex=$(convert_assetNameASCII2HEX ${adahandleName:1}) - #query classic cip-25 adahandle asset holding address via koios - showProcessAnimation "Query Adahandle(CIP-25) into holding address: " & - response=$(curl -s -m 10 -X GET "${koiosAPI}/asset_address_list?_asset_policy=${adahandlePolicyID}&_asset_name=${assetNameHex}" -H "Accept: application/json" 2> /dev/null) - stopProcessAnimation; - #check if the received json only contains one entry in the array (will also not be 1 if not a valid json) - if [[ $(jq ". | length" 2> /dev/null <<< ${response}) -ne 1 ]]; then - #query classic cip-68 adahandle asset holding address via koios - showProcessAnimation "Query Adahandle(CIP-68) into holding address: " & - response=$(curl -s -m 10 -X GET "${koiosAPI}/asset_address_list?_asset_policy=${adahandlePolicyID}&_asset_name=000de140${assetNameHex}" -H "Accept: application/json" 2> /dev/null) - stopProcessAnimation; - #check if the received json only contains one entry in the array (will also not be 1 if not a valid json) - if [[ $(jq ". | length" 2> /dev/null <<< ${response}) -ne 1 ]]; then echo -e "\n\e[35mCould not resolve Adahandle to an address.\n\e[0m"; exit 1; fi - assetNameHex="000de140${assetNameHex}" - fi - addrName=$(jq -r ".[0].payment_address" <<< ${response} 2> /dev/null) - typeOfAddr=$(get_addressType "${addrName}"); - if [[ ${typeOfAddr} != ${addrTypePayment} ]]; then echo -e "\n\e[35mERROR - Resolved address '${addrName}' is not a valid payment address.\n\e[0m"; exit 1; fi; - showProcessAnimation "Verify Adahandle is on resolved address: " & - utxo=$(${cardanocli} query utxo --address ${addrName} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; - if [[ $(grep "${adahandlePolicyID}.${assetNameHex} " <<< ${utxo} | wc -l) -ne 1 ]]; then - echo -e "\n\e[35mERROR - Resolved address '${addrName}' does not hold the \$adahandle '${adahandleName}' !\n\e[0m"; exit 1; fi; - echo -e "\e[0mFound \$adahandle '${adahandleName}' on Address:\e[32m ${addrName}\e[0m\n" - echo "$(basename ${addrName})" > ${tempDir}/adahandle-resolve.addr; addrName="${tempDir}/adahandle-resolve"; - - elif checkAdaSubHandleFormat "${addrName}"; then - echo -e "\n\e[33mINFO - AdaSubHandles are not supported yet.\n\e[0m"; exit 1; - #otherwise post an error message - else echo -e "\n\e[35mERROR - Destination Address can't be resolved. Maybe filename wrong, or not a payment-address.\n\e[0m"; exit 1; + #resolve given adahandle into address + resolveAdahandle "${adahandleName}" "addrName" #if successful, it resolves the adahandle and writes it out into the variable 'addrName'. also sets the variable 'utxo' if possible + + #resolveAdahandle did not exit with an error, so we resolved it + echo "${addrName}" > ${tempDir}/adahandle-resolve.addr; addrName="${tempDir}/adahandle-resolve"; + #otherwise post an error message + else echo -e "\n\e[35mERROR - Destination Address can't be resolved. Maybe filename wrong, or not a payment- or stake-address.\n\e[0m"; exit 1; fi fi @@ -71,18 +48,34 @@ if [[ ${typeOfAddr} == ${addrTypePayment} ]]; then #Enterprise and Base UTXO ad echo -e "\e[0mAddress-Type / Era:\e[32m $(get_addressType "${checkAddr}")\e[0m / \e[32m$(get_addressEra "${checkAddr}")\e[0m" echo - #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in offlinemode from the transferFile - #${nodeEraParam} not needed anymore - if ${onlineMode}; then - showProcessAnimation "Query-UTXO: " & - utxo=$(${cardanocli} query utxo --address ${checkAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in lightmode via API requests, in offlinemode from the transferFile + case ${workMode} in + "online") if [[ "${utxo}" == "" ]]; then #only query it again if not already queried via an adahandle check before + #check that the node is fully synced, otherwise the query would mabye return a false state + if [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced or not running, please let your node sync to 100% first !\e[0m\n"; exit 1; fi + showProcessAnimation "Query-UTXO: " & + utxo=$(${cardanocli} ${cliEra} query utxo --address ${checkAddr} 2> /dev/stdout); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + fi + showProcessAnimation "Convert-UTXO: " & + utxoJSON=$(generate_UTXO "${utxo}" "${checkAddr}"); stopProcessAnimation; + ;; + + "light") if [[ "${utxo}" == "" ]]; then #only query it again if not already queried via an adahandle check before + showProcessAnimation "Query-UTXO-LightMode: " & + utxo=$(queryLight_UTXO "${checkAddr}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + fi showProcessAnimation "Convert-UTXO: " & utxoJSON=$(generate_UTXO "${utxo}" "${checkAddr}"); stopProcessAnimation; - else - readOfflineFile; #Reads the offlinefile into the offlineJSON variable - utxoJSON=$(jq -r ".address.\"${checkAddr}\".utxoJSON" <<< ${offlineJSON}) + ;; + + + "offline") readOfflineFile; #Reads the offlinefile into the offlineJSON variable + utxoJSON=$(jq -r ".address.\"${checkAddr}\".utxoJSON" <<< ${offlineJSON} 2> /dev/null) if [[ "${utxoJSON}" == null ]]; then echo -e "\e[35mAddress not included in the offline transferFile, please include it first online!\e[0m\n"; exit 1; fi - fi + ;; + esac utxoEntryCnt=$(jq length <<< ${utxoJSON}) if [[ ${utxoEntryCnt} == 0 ]]; then echo -e "\e[35mNo funds on the Address!\e[0m\n"; exit 1; else echo -e "\e[32m${utxoEntryCnt} UTXOs\e[0m found on the Address!"; fi @@ -141,9 +134,20 @@ if [[ ${typeOfAddr} == ${addrTypePayment} ]]; then #Enterprise and Base UTXO ad totalAssetsJSON=$( jq ". += {\"${assetHash}${point}${assetName}\":{amount: \"${newValue}\", name: \"${assetTmpName}\", bech: \"${assetBech}\"}}" <<< ${totalAssetsJSON}) if [[ "${assetTmpName:0:1}" == "." ]]; then assetTmpName=${assetTmpName:1}; else assetTmpName="{${assetTmpName}}"; fi - case ${assetHash} in - "${adahandlePolicyID}" ) #$adahandle - if [[ ${assetTmpName:1:8} == "000de140" ]]; then assetName=${assetName:8}; fi #if it is a cip-68 adahandle, cut the first 4 bytes (8 chars in hex format) + case "${assetHash}${assetTmpName:1:8}" in + "${adahandlePolicyID}000de140" ) #$adahandle cip-68 + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Own): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}00000000" ) #$adahandle virtual + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Vir): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}000643b0" ) #$adahandle reference + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Ref): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}"* ) #$adahandle cip-25 echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle: \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" ;; * ) #default @@ -202,14 +206,26 @@ elif [[ ${typeOfAddr} == ${addrTypeStake} ]]; then #Staking Address echo -e "\e[0mAddress-Type / Era:\e[32m $(get_addressType "${checkAddr}")\e[0m / \e[32m$(get_addressEra "${checkAddr}")\e[0m" echo - #Get rewards state data for the address. When in online mode of course from the node and the chain, in offlinemode from the transferFile - if ${onlineMode}; then - rewardsJSON=$(${cardanocli} query stake-address-info --address ${checkAddr} ${magicparam} | jq -rc .) - else - rewardsJSON=$(cat ${offlineFile} | jq -r ".address.\"${checkAddr}\".rewardsJSON" 2> /dev/null) + #Get rewards state data for the address. When in online mode of course from the node and the chain, in light mode via koios, in offlinemode from the transferFile + case ${workMode} in + + "online") showProcessAnimation "Query-StakeAddress-Info: " & + rewardsJSON=$(${cardanocli} ${cliEra} query stake-address-info --address ${checkAddr} 2> /dev/null ) + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${rewardsJSON}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + rewardsJSON=$(jq -rc . <<< "${rewardsJSON}") + ;; + + "light") showProcessAnimation "Query-StakeAddress-Info-LightMode: " & + rewardsJSON=$(queryLight_stakeAddressInfo "${checkAddr}") + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${rewardsJSON}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + + "offline") readOfflineFile; #Reads the offlinefile into the offlineJSON variable + rewardsJSON=$(jq -r ".address.\"${checkAddr}\".rewardsJSON" <<< ${offlineJSON} 2> /dev/null) if [[ "${rewardsJSON}" == null ]]; then echo -e "\e[35mAddress not included in the offline transferFile, please include it first online!\e[0m\n"; exit; fi - fi - checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi + ;; + + esac rewardsEntryCnt=$(jq -r 'length' <<< ${rewardsJSON}) @@ -224,10 +240,10 @@ elif [[ ${typeOfAddr} == ${addrTypeStake} ]]; then #Staking Address rewardsAmount=$(jq -r ".[${tmpCnt}].rewardAccountBalance" <<< ${rewardsJSON}) rewardsAmountInADA=$(bc <<< "scale=6; ${rewardsAmount} / 1000000") - delegationPoolID=$(jq -r ".[${tmpCnt}].delegation" <<< ${rewardsJSON}) + delegationPoolID=$(jq -r ".[${tmpCnt}].delegation // .[${tmpCnt}].stakeDelegation" <<< ${rewardsJSON}) rewardsSum=$((${rewardsSum}+${rewardsAmount})) - rewardsSumInADA=$(bc <<< "scale=6; ${rewardsSum} / 1000000") + rewardsSumInADA=$(bc <<< "scale=6; ${rewardsSum} / 1000000") echo -ne "[$((${tmpCnt}+1))]\t" @@ -237,7 +253,47 @@ elif [[ ${typeOfAddr} == ${addrTypeStake} ]]; then #Staking Address fi #If delegated to a pool, show the current pool ID - if [[ ! ${delegationPoolID} == null ]]; then echo -e " \tAccount is delegated to a Pool with ID: \e[32m${delegationPoolID}\e[0m"; else echo -e " \tAccount is not delegated to a Pool !"; fi + if [[ ! ${delegationPoolID} == null ]]; then + echo -e " \tAccount is delegated to a Pool with ID: \e[32m${delegationPoolID}\e[0m"; + + if [[ ${onlineMode} == true && ${koiosAPI} != "" ]]; then + + #query poolinfo via poolid on koios + errorcnt=0; error=-1; + showProcessAnimation "Query Pool-Info via Koios: " & + while [[ ${errorcnt} -lt 5 && ${error} -ne 0 ]]; do #try a maximum of 5 times to request the information + error=0 + response=$(curl -sL -m 30 -X POST -w "---spo-scripts---%{http_code}" "${koiosAPI}/pool_info" -H "Accept: application/json" -H "Content-Type: application/json" -d "{\"_pool_bech32_ids\":[\"${delegationPoolID}\"]}" 2> /dev/null) + if [[ $? -ne 0 ]]; then error=1; sleep 1; fi; #if there is an error, wait for a second and repeat + errorcnt=$(( ${errorcnt} + 1 )) + done + stopProcessAnimation; + + #if no error occured, split the response string into JSON content and the HTTP-ResponseCode + if [[ ${error} -eq 0 && "${response}" =~ (.*)---spo-scripts---([0-9]*)* ]]; then + + responseJSON="${BASH_REMATCH[1]}" + responseCode="${BASH_REMATCH[2]}" + + #if the responseCode is 200 (OK) and the received json only contains one entry in the array (will also not be 1 if not a valid json) + if [[ ${responseCode} -eq 200 && $(jq ". | length" 2> /dev/null <<< ${responseJSON}) -eq 1 ]]; then + { read poolNameInfo; read poolTickerInfo; read poolStatusInfo; } <<< $(jq -r ".[0].meta_json.name // \"-\", .[0].meta_json.ticker // \"-\", .[0].pool_status // \"-\"" 2> /dev/null <<< ${responseJSON}) + echo -e " \t\e[0mInformation about the Pool: \e[32m${poolNameInfo} (${poolTickerInfo})\e[0m" + echo -e " \t\e[0m Status: \e[32m${poolStatusInfo}\e[0m" + echo + unset poolNameInfo poolTickerInfo poolStatusInfo + fi #responseCode & jsoncheck + + fi #error & response + unset errorcnt error + + fi #onlineMode & koiosAPI + + else + + echo -e " \tAccount is not delegated to a Pool !"; + + fi echo diff --git a/cardano/mainnet/01_sendAssets.sh b/cardano/mainnet/01_sendAssets.sh index 8509f199..4fd20b69 100755 --- a/cardano/mainnet/01_sendAssets.sh +++ b/cardano/mainnet/01_sendAssets.sh @@ -101,37 +101,17 @@ if [ ${paramCnt} -ge 2 ]; then typeOfAddr=$(get_addressType "${toAddr}"); if [[ ${typeOfAddr} == ${addrTypePayment} ]]; then echo "$(basename ${toAddr})" > ${tempDir}/tempTo.addr; toAddr="${tempDir}/tempTo"; - #check if its an root adahandle (without a @ char) - elif checkAdaRootHandleFormat "${toAddr}"; then - if ${offlineMode}; then echo -e "\n\e[35mERROR - Adahandles are only supported in Online mode.\n\e[0m"; exit 1; fi + #check if its an adahandle (root/sub/virtual) + elif checkAdaHandleFormat "${toAddr}"; then + adahandleName=${toAddr,,} - assetNameHex=$(convert_assetNameASCII2HEX ${adahandleName:1}) - #query classic cip-25 adahandle asset holding address via koios - showProcessAnimation "Query Adahandle(CIP-25) into holding address: " & - response=$(curl -s -m 10 -X GET "${koiosAPI}/asset_address_list?_asset_policy=${adahandlePolicyID}&_asset_name=${assetNameHex}" -H "Accept: application/json" 2> /dev/null) - stopProcessAnimation; - #check if the received json only contains one entry in the array (will also not be 1 if not a valid json) - if [[ $(jq ". | length" 2> /dev/null <<< ${response}) -ne 1 ]]; then - #query classic cip-68 adahandle asset holding address via koios - showProcessAnimation "Query Adahandle(CIP-68) into holding address: " & - response=$(curl -s -m 10 -X GET "${koiosAPI}/asset_address_list?_asset_policy=${adahandlePolicyID}&_asset_name=000de140${assetNameHex}" -H "Accept: application/json" 2> /dev/null) - stopProcessAnimation; - #check if the received json only contains one entry in the array (will also not be 1 if not a valid json) - if [[ $(jq ". | length" 2> /dev/null <<< ${response}) -ne 1 ]]; then echo -e "\n\e[35mCould not resolve Adahandle to an address.\n\e[0m"; exit 1; fi - assetNameHex="000de140${assetNameHex}" - fi - toAddr=$(jq -r ".[0].payment_address" <<< ${response} 2> /dev/null) - typeOfAddr=$(get_addressType "${toAddr}"); - if [[ ${typeOfAddr} != ${addrTypePayment} ]]; then echo -e "\n\e[35mERROR - Resolved address '${toAddr}' is not a valid payment address.\n\e[0m"; exit 1; fi; - showProcessAnimation "Verify Adahandle is on resolved address: " & - utxo=$(${cardanocli} query utxo --address ${toAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; - if [[ $(grep "${adahandlePolicyID}.${assetNameHex} " <<< ${utxo} | wc -l) -ne 1 ]]; then - echo -e "\n\e[35mERROR - Resolved address '${toAddr}' does not hold the \$adahandle '${adahandleName}' !\n\e[0m"; exit 1; fi; - echo -e "\e[0mFound \$adahandle '${adahandleName}' on Address:\e[32m ${toAddr}\e[0m\n" - echo "$(basename ${toAddr})" > ${tempDir}/adahandle-resolve.addr; toAddr="${tempDir}/adahandle-resolve"; - - elif checkAdaSubHandleFormat "${toAddr}"; then - echo -e "\n\e[33mINFO - AdaSubHandles are not supported yet.\n\e[0m"; exit 1; + + #resolve given adahandle into address + resolveAdahandle "${adahandleName}" "toAddr" #if successful, it resolves the adahandle and writes it out into the variable 'toAddr'. also sets the variable 'utxo' if possible + unset utxo #remove utxo information from the adahandle lookup, because we only use it as a destination target + + #resolveAdahandle did not exit with an error, so we resolved it + echo "${toAddr}" > ${tempDir}/adahandle-resolve.addr; toAddr="${tempDir}/adahandle-resolve"; #otherwise post an error message else echo -e "\n\e[35mERROR - Destination Address can't be resolved. Maybe filename wrong, or not a payment-address.\n\e[0m"; exit 1; @@ -394,9 +374,8 @@ echo -e "\e[0mSending assets from Address\e[32m ${fromAddr}.addr\e[0m to Address echo #get live values -currentTip=$(get_currentTip) -ttl=$(get_currentTTL) -currentEPOCH=$(get_currentEpoch) +currentTip=$(get_currentTip); checkError "$?"; +ttl=$(( ${currentTip} + ${defTTL} )) echo -e "\e[0mCurrent Slot-Height:\e[32m ${currentTip} \e[0m(setting TTL[invalid_hereafter] to ${ttl})" echo @@ -409,20 +388,39 @@ echo # Checking UTXO Data of the source address and gathering data about total lovelaces and total assets # - #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in offlinemode from the transferFile - if ${onlineMode}; then + + #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in lightmode via API requests, in offlinemode from the transferFile + case ${workMode} in + "online") + #check that the node is fully synced, otherwise the query would mabye return a false state + if [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced or not running, please let your node sync to 100% first !\e[0m\n"; exit 1; fi showProcessAnimation "Query-UTXO: " & - utxo=$(${cardanocli} query utxo --address ${sendFromAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + utxo=$(${cardanocli} ${cliEra} query utxo --address ${sendFromAddr} 2> /dev/stdout); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + if [[ ${skipUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep -v "${skipUtxoWithAsset}" ); fi #if its set to keep utxos that contains certain policies, filter them out + if [[ ${onlyUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep "${onlyUtxoWithAsset}" ); utxo=$(echo -e "Header\n-----\n${utxo}"); fi #only use given utxos. rebuild the two header lines + if [[ ${utxoLimitCnt} -gt 0 ]]; then utxo=$(echo "${utxo}" | head -n $(( ${utxoLimitCnt} + 2 )) ); fi #if there was a utxo cnt limit set, reduce it (+2 for the header) + showProcessAnimation "Convert-UTXO: " & + utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; + ;; + + "light") + showProcessAnimation "Query-UTXO-LightMode: " & + utxo=$(queryLight_UTXO "${sendFromAddr}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; if [[ ${skipUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep -v "${skipUtxoWithAsset}" ); fi #if its set to keep utxos that contains certain policies, filter them out if [[ ${onlyUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep "${onlyUtxoWithAsset}" ); utxo=$(echo -e "Header\n-----\n${utxo}"); fi #only use given utxos. rebuild the two header lines if [[ ${utxoLimitCnt} -gt 0 ]]; then utxo=$(echo "${utxo}" | head -n $(( ${utxoLimitCnt} + 2 )) ); fi #if there was a utxo cnt limit set, reduce it (+2 for the header) showProcessAnimation "Convert-UTXO: " & utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; - else - readOfflineFile; #Reads the offlinefile into the offlineJSON variable - utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON}) + ;; + + + "offline") readOfflineFile; #Reads the offlinefile into the offlineJSON variable + utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON} 2> /dev/null) if [[ "${utxoJSON}" == null ]]; then echo -e "\e[35mPayment-Address not included in the offline transferFile, please include it first online!\e[0m\n"; exit 1; fi - fi + ;; + esac #Only use UTXOs specied in the extra parameter if present if [[ ! "${filterForUTXO}" == "" ]]; then echo -e "\e[0mUTXO-Mode: \e[32mOnly using the UTXO with Hash ${filterForUTXO}\e[0m\n"; utxoJSON=$(filterFor_UTXO "${utxoJSON}" "${filterForUTXO}"); fi @@ -483,8 +481,20 @@ echo totalAssetsJSON=$( jq ". += {\"${assetHash}${point}${assetName}\":{amount: \"${newValue}\", name: \"${assetTmpName}\", bech: \"${assetBech}\"}}" <<< ${totalAssetsJSON}) if [[ "${assetTmpName:0:1}" == "." ]]; then assetTmpName=${assetTmpName:1}; else assetTmpName="{${assetTmpName}}"; fi - case ${assetHash} in - "${adahandlePolicyID}" ) #$adahandle + case "${assetHash}${assetTmpName:1:8}" in + "${adahandlePolicyID}000de140" ) #$adahandle cip-68 + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Own): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}00000000" ) #$adahandle virtual + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Vir): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}000643b0" ) #$adahandle reference + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Ref): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}"* ) #$adahandle cip-25 echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle: \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" ;; * ) #default @@ -635,11 +645,11 @@ fi rxcnt=2 #Read ProtocolParameters -if ${onlineMode}; then - protocolParametersJSON=$(${cardanocli} query protocol-parameters ${magicparam} ); #onlinemode - else - protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON}); #offlinemode - fi +case ${workMode} in + "online") protocolParametersJSON=$(${cardanocli} ${cliEra} query protocol-parameters );; #onlinemode + "light") protocolParametersJSON=${lightModeParametersJSON};; #lightmode + "offline") protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON});; #offlinemode +esac checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #minOutUTXO=$(calc_minOutUTXO "${protocolParametersJSON}" "${sendToAddr}+0${assetsSendString}") @@ -649,9 +659,9 @@ minReturnUTXO=$(calc_minOutUTXO "${protocolParametersJSON}" "${sendToAddr}+10000 #Generate Dummy-TxBody file for fee calculation txBodyFile="${tempDir}/dummy.txbody" rm ${txBodyFile} 2> /dev/null -${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+1000000${assetsSendString}" --tx-out "${sendToAddr}+1000000${assetsReturnString}" --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --out-file ${txBodyFile} +${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+1000000${assetsSendString}" --tx-out "${sendToAddr}+1000000${assetsReturnString}" --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi -fee=$(${cardanocli} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} ${magicparam} --witness-count 1 --byron-witness-count 0 | awk '{ print $1 }') +fee=$(${cardanocli} ${cliEra} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} --witness-count 1 --byron-witness-count 0 | awk '{ print $1 }') checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "\e[0mMinimum Transaction Fee for ${txcnt}x TxIn & ${rxcnt}x TxOut: \e[32m $(convertToADA ${fee}) ADA / ${fee} lovelaces \e[90m" @@ -679,7 +689,7 @@ echo #Building unsigned transaction body rm ${txBodyFile} 2> /dev/null -${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsSendString}" --tx-out "${sendFromAddr}+${lovelacesToReturn}${assetsReturnString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --out-file ${txBodyFile} +${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsSendString}" --tx-out "${sendFromAddr}+${lovelacesToReturn}${assetsReturnString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi dispFile=$(cat ${txBodyFile}); if ${cropTxOutput} && [[ ${#dispFile} -gt 4000 ]]; then echo "${dispFile:0:4000} ... (cropped)"; else echo "${dispFile}"; fi @@ -718,7 +728,7 @@ if [[ -f "${fromAddr}.hwsfile" ]]; then if [[ "${tmp^^}" =~ (ERROR|DISCONNECT) ]]; then echo -e "\e[35m${tmp}\e[0m\n"; exit 1; else echo -ne "\e[0mWitnessed ... "; fi checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - ${cardanocli} transaction assemble --tx-body-file ${txBodyFile} --witness-file ${txWitnessFile} --out-file ${txFile} + ${cardanocli} ${cliEra} transaction assemble --tx-body-file ${txBodyFile} --witness-file ${txWitnessFile} --out-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "Assembled ... \e[32mDONE\e[0m\n"; @@ -730,7 +740,7 @@ else echo -e "\e[0mSign the unsigned transaction body with the \e[32m${fromAddr}.skey\e[0m: \e[32m ${txFile}\e[0m" echo - ${cardanocli} transaction sign --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON}") ${magicparam} --out-file ${txFile} + ${cardanocli} ${cliEra} transaction sign --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON}") --out-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #forget the signing keys @@ -755,20 +765,32 @@ if [[ ${txSize} -le ${maxTxSize} ]]; then echo -e "\e[0mTransaction-Size: ${txSi #if ask "\e[33mDoes this look good for you, continue ?" N; then if [ "${ENV_SKIP_PROMPT}" == "YES" ] || ask "\n\e[33mDoes this look good for you, continue ?" N; then - echo - if ${onlineMode}; then #onlinesubmit + echo + case ${workMode} in + "online") + #onlinesubmit echo -ne "\e[0mSubmitting the transaction via the node... " - ${cardanocli} transaction submit --tx-file ${txFile} ${magicparam} + ${cardanocli} ${cliEra} transaction submit --tx-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "\e[32mDONE\n" #Show the TxID - txID=$(${cardanocli} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" + txID=$(${cardanocli} ${cliEra} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; + + "light") + #lightmode submit + showProcessAnimation "Submit-Transaction-LightMode: " & + txID=$(submitLight "${txFile}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${txID}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + echo -e "\e[0mSubmit-Transaction-LightMode: \e[32mDONE\n" + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; - - else #offlinestore + "offline") + #offlinestore txFileJSON=$(cat ${txFile} | jq .) offlineJSON=$( jq ".transactions += [ { date: \"$(date -R)\", type: \"Transaction\", @@ -781,7 +803,6 @@ if [ "${ENV_SKIP_PROMPT}" == "YES" ] || ask "\n\e[33mDoes this look good for you #Write the new offileFile content offlineJSON=$( jq ".history += [ { date: \"$(date -R)\", action: \"generated and signed utxo-token-transaction from '${fromAddr}' to '${toAddr}'\" } ]" <<< ${offlineJSON}) offlineJSON=$( jq ".general += {offlineCLI: \"${versionCLI}\" }" <<< ${offlineJSON}) - offlineJSON=$( jq ".general += {offlineNODE: \"${versionNODE}\" }" <<< ${offlineJSON}) echo "${offlineJSON}" > ${offlineFile} #Readback the tx content and compare it to the current one readback=$(cat ${offlineFile} | jq -r ".transactions[-1].txJSON") @@ -791,10 +812,11 @@ if [ "${ENV_SKIP_PROMPT}" == "YES" ] || ask "\n\e[33mDoes this look good for you else echo -e "\e[35mERROR - Could not verify the written data in the '$(basename ${offlineFile})'. Retry again or generate a new '$(basename ${offlineFile})'.\e[0m\n"; fi + ;; - fi -fi + esac +fi echo -e "\e[0m\n" diff --git a/cardano/mainnet/01_sendLovelaces.sh b/cardano/mainnet/01_sendLovelaces.sh index 433c831c..3ebeefd9 100755 --- a/cardano/mainnet/01_sendLovelaces.sh +++ b/cardano/mainnet/01_sendLovelaces.sh @@ -168,37 +168,17 @@ if [ ! -f "${toAddr}.addr" ]; then typeOfAddr=$(get_addressType "${toAddr}"); if [[ ${typeOfAddr} == ${addrTypePayment} ]]; then echo "$(basename ${toAddr})" > ${tempDir}/tempTo.addr; toAddr="${tempDir}/tempTo"; - #check if its an root adahandle (without a @ char) - elif checkAdaRootHandleFormat "${toAddr}"; then - if ${offlineMode}; then echo -e "\n\e[35mERROR - Adahandles are only supported in Online mode.\n\e[0m"; exit 1; fi + #check if its an adahandle (root/sub/virtual) + elif checkAdaHandleFormat "${toAddr}"; then + adahandleName=${toAddr,,} - assetNameHex=$(convert_assetNameASCII2HEX ${adahandleName:1}) - #query classic cip-25 adahandle asset holding address via koios - showProcessAnimation "Query Adahandle(CIP-25) into holding address: " & - response=$(curl -s -m 10 -X GET "${koiosAPI}/asset_address_list?_asset_policy=${adahandlePolicyID}&_asset_name=${assetNameHex}" -H "Accept: application/json" 2> /dev/null) - stopProcessAnimation; - #check if the received json only contains one entry in the array (will also not be 1 if not a valid json) - if [[ $(jq ". | length" 2> /dev/null <<< ${response}) -ne 1 ]]; then - #query classic cip-68 adahandle asset holding address via koios - showProcessAnimation "Query Adahandle(CIP-68) into holding address: " & - response=$(curl -s -m 10 -X GET "${koiosAPI}/asset_address_list?_asset_policy=${adahandlePolicyID}&_asset_name=000de140${assetNameHex}" -H "Accept: application/json" 2> /dev/null) - stopProcessAnimation; - #check if the received json only contains one entry in the array (will also not be 1 if not a valid json) - if [[ $(jq ". | length" 2> /dev/null <<< ${response}) -ne 1 ]]; then echo -e "\n\e[35mCould not resolve Adahandle to an address.\n\e[0m"; exit 1; fi - assetNameHex="000de140${assetNameHex}" - fi - toAddr=$(jq -r ".[0].payment_address" <<< ${response} 2> /dev/null) - typeOfAddr=$(get_addressType "${toAddr}"); - if [[ ${typeOfAddr} != ${addrTypePayment} ]]; then echo -e "\n\e[35mERROR - Resolved address '${toAddr}' is not a valid payment address.\n\e[0m"; exit 1; fi; - showProcessAnimation "Verify Adahandle is on resolved address: " & - utxo=$(${cardanocli} query utxo --address ${toAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; - if [[ $(grep "${adahandlePolicyID}.${assetNameHex} " <<< ${utxo} | wc -l) -ne 1 ]]; then - echo -e "\n\e[35mERROR - Resolved address '${toAddr}' does not hold the \$adahandle '${adahandleName}' !\n\e[0m"; exit 1; fi; - echo -e "\e[0mFound \$adahandle '${adahandleName}' on Address:\e[32m ${toAddr}\e[0m\n" - echo "$(basename ${toAddr})" > ${tempDir}/adahandle-resolve.addr; toAddr="${tempDir}/adahandle-resolve"; - - elif checkAdaSubHandleFormat "${toAddr}"; then - echo -e "\n\e[33mINFO - AdaSubHandles are not supported yet.\n\e[0m"; exit 1; + + #resolve given adahandle into address + resolveAdahandle "${adahandleName}" "toAddr" #if successful, it resolves the adahandle and writes it out into the variable 'toAddr'. also sets the variable 'utxo' if possible + unset utxo #remove utxo information from the adahandle lookup, because we only use it as a destination target + + #resolveAdahandle did not exit with an error, so we resolved it + echo "${toAddr}" > ${tempDir}/adahandle-resolve.addr; toAddr="${tempDir}/adahandle-resolve"; #otherwise post an error message else echo -e "\n\e[35mERROR - Destination Address can't be resolved. Maybe filename wrong, or not a payment-address.\n\e[0m"; exit 1; @@ -247,9 +227,8 @@ echo -e "\e[0mSending lovelaces from Address\e[32m ${fromAddr}.addr\e[0m to Addr echo #get live values -currentTip=$(get_currentTip) -ttl=$(get_currentTTL) -currentEPOCH=$(get_currentEpoch) +currentTip=$(get_currentTip); checkError "$?"; +ttl=$(( ${currentTip} + ${defTTL} )) echo -e "\e[0mCurrent Slot-Height:\e[32m ${currentTip} \e[0m(setting TTL[invalid_hereafter] to ${ttl})" echo @@ -263,20 +242,38 @@ echo # Checking UTXO Data of the source address and gathering data about total lovelaces and total assets # - #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in offlinemode from the transferFile - if ${onlineMode}; then + #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in lightmode via API requests, in offlinemode from the transferFile + case ${workMode} in + "online") + #check that the node is fully synced, otherwise the query would mabye return a false state + if [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced or not running, please let your node sync to 100% first !\e[0m\n"; exit 1; fi showProcessAnimation "Query-UTXO: " & - utxo=$(${cardanocli} query utxo --address ${sendFromAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; - if [[ ${skipUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep -v "${skipUtxoWithAsset}" ); fi #if its set to keep utxos that contains certain policies, filter them out - if [[ ${onlyUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep "${onlyUtxoWithAsset}" ); utxo=$(echo -e "Header\n-----\n${utxo}"); fi #only use given utxos. rebuild the two header lines - if [[ ${utxoLimitCnt} -gt 0 ]]; then utxo=$(echo "${utxo}" | head -n $(( ${utxoLimitCnt} + 2 )) ); fi #if there was a utxo cnt limit set, reduce it (+2 for the header) + utxo=$(${cardanocli} ${cliEra} query utxo --address ${sendFromAddr} 2> /dev/stdout); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + if [[ ${skipUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep -v "${skipUtxoWithAsset}" ); fi #if its set to keep utxos that contains certain policies, filter them out + if [[ ${onlyUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep "${onlyUtxoWithAsset}" ); utxo=$(echo -e "Header\n-----\n${utxo}"); fi #only use given utxos. rebuild the two header lines + if [[ ${utxoLimitCnt} -gt 0 ]]; then utxo=$(echo "${utxo}" | head -n $(( ${utxoLimitCnt} + 2 )) ); fi #if there was a utxo cnt limit set, reduce it (+2 for the header) + showProcessAnimation "Convert-UTXO: " & + utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; + ;; + + "light") + showProcessAnimation "Query-UTXO-LightMode: " & + utxo=$(queryLight_UTXO "${sendFromAddr}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + if [[ ${skipUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep -v "${skipUtxoWithAsset}" ); fi #if its set to keep utxos that contains certain policies, filter them out + if [[ ${onlyUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep "${onlyUtxoWithAsset}" ); utxo=$(echo -e "Header\n-----\n${utxo}"); fi #only use given utxos. rebuild the two header lines + if [[ ${utxoLimitCnt} -gt 0 ]]; then utxo=$(echo "${utxo}" | head -n $(( ${utxoLimitCnt} + 2 )) ); fi #if there was a utxo cnt limit set, reduce it (+2 for the header) showProcessAnimation "Convert-UTXO: " & utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; - else - readOfflineFile; #Reads the offlinefile into the offlineJSON variable - utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON}) + ;; + + + "offline") readOfflineFile; #Reads the offlinefile into the offlineJSON variable + utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON} 2> /dev/null) if [[ "${utxoJSON}" == null ]]; then echo -e "\e[35mPayment-Address not included in the offline transferFile, please include it first online!\e[0m\n"; exit 1; fi - fi + ;; + esac #Only use UTXOs specied in the extra parameter if present if [[ ! "${filterForUTXO}" == "" ]]; then echo -e "\e[0mUTXO-Mode: \e[32mOnly using the UTXO with Hash ${filterForUTXO}\e[0m\n"; utxoJSON=$(filterFor_UTXO "${utxoJSON}" "${filterForUTXO}"); fi @@ -337,8 +334,20 @@ echo totalAssetsJSON=$( jq ". += {\"${assetHash}${point}${assetName}\":{amount: \"${newValue}\", name: \"${assetTmpName}\", bech: \"${assetBech}\"}}" <<< ${totalAssetsJSON}) if [[ "${assetTmpName:0:1}" == "." ]]; then assetTmpName=${assetTmpName:1}; else assetTmpName="{${assetTmpName}}"; fi - case ${assetHash} in - "${adahandlePolicyID}" ) #$adahandle + case "${assetHash}${assetTmpName:1:8}" in + "${adahandlePolicyID}000de140" ) #$adahandle cip-68 + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Own): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}00000000" ) #$adahandle virtual + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Vir): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}000643b0" ) #$adahandle reference + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Ref): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}"* ) #$adahandle cip-25 echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle: \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" ;; * ) #default @@ -403,11 +412,11 @@ if [[ ! "${transactionMessage}" == "{}" ]]; then fi #Read ProtocolParameters -if ${onlineMode}; then - protocolParametersJSON=$(${cardanocli} query protocol-parameters ${magicparam} ); #onlinemode - else - protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON}); #offlinemode - fi +case ${workMode} in + "online") protocolParametersJSON=$(${cardanocli} ${cliEra} query protocol-parameters);; #onlinemode + "light") protocolParametersJSON=${lightModeParametersJSON};; #lightmode + "offline") protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON});; #offlinemode +esac checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi # @@ -434,13 +443,13 @@ esac txBodyFile="${tempDir}/dummy.txbody" rm ${txBodyFile} 2> /dev/null if [[ ${rxcnt} == 1 ]]; then #Sending ALLFUNDS or sending ALL lovelaces and no assets on the address - ${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --out-file ${txBodyFile} + ${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi else #Sending chosen amount of lovelaces or ALL lovelaces but return the assets to the address - ${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --tx-out ${sendToAddr}+1000000 --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --out-file ${txBodyFile} + ${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --tx-out ${sendToAddr}+1000000 --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi fi -fee=$(${cardanocli} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} ${magicparam} --witness-count 1 --byron-witness-count 0 | awk '{ print $1 }') +fee=$(${cardanocli} ${cliEra} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} --witness-count 1 --byron-witness-count 0 | awk '{ print $1 }') checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #minOutUTXO=$(calc_minOutUTXO "${protocolParametersJSON}" "${sendToAddr}+0${assetsOutString}") @@ -527,11 +536,11 @@ echo #Building unsigned transaction body rm ${txBodyFile} 2> /dev/null if [[ ${rxcnt} == 1 ]]; then #Sending ALL funds (rxcnt=1) - ${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --out-file ${txBodyFile} + ${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi else #Sending chosen amount (rxcnt=2), return the rest(incl. assets) - ${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out ${sendToAddr}+${lovelacesToSend} --tx-out "${sendFromAddr}+${lovelacesToReturn}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --out-file ${txBodyFile} - #echo -e "\n\n\n${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out ${sendToAddr}+${lovelacesToSend} --tx-out \"${sendFromAddr}+${lovelacesToReturn}${assetsOutString}\" --invalid-hereafter ${ttl} --fee ${fee} --out-file ${txBodyFile}\n\n\n" + ${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out ${sendToAddr}+${lovelacesToSend} --tx-out "${sendFromAddr}+${lovelacesToReturn}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --out-file ${txBodyFile} + #echo -e "\n\n\n${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out ${sendToAddr}+${lovelacesToSend} --tx-out \"${sendFromAddr}+${lovelacesToReturn}${assetsOutString}\" --invalid-hereafter ${ttl} --fee ${fee} --out-file ${txBodyFile}\n\n\n" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi fi @@ -545,21 +554,10 @@ rm ${txFile} 2> /dev/null #If payment address is a hardware wallet, use the cardano-hw-cli for the signing if [[ -f "${fromAddr}.hwsfile" ]]; then -# currentAuxHash=$(cat ${txBodyFile} | sed -n "s/.*f5\(d90103.*\)\"/\1/p" | xxd -r -ps | b2sum -l 256 -b | awk {'print $1'}) #holds the expected auxhash -# currentAuxHash=$(cat ${txBodyFile} | sed -n "s/.*\($currentAuxHash\).*/\1/p") #holds the auxhash if it was found in the txcbor as a proof - echo -ne "\e[0mAutocorrect the TxBody for canonical order: " tmp=$(autocorrect_TxBodyFile "${txBodyFile}"); if [ $? -ne 0 ]; then echo -e "\e[35m${tmp}\e[0m\n\n"; exit 1; fi echo -e "\e[32m${tmp}\e[90m\n" -# newAuxHash=$(cat ${txBodyFile} | sed -n 's/.*f5\(d90103.*\)\"/\1/p' | xxd -r -ps | b2sum -l 256 -b | awk {'print $1'}) -# if [[ "${currentAuxHash}" != "" && "${currentAuxHash}" != "${newAuxHash}" ]]; then #only do it when the currentAuxHash holds a hash (detection worked) and if the new one is different to the old one -# echo -ne "\e[0mAutocorrect the AuxHash from '${currentAuxHash}' to '${newAuxHash}': " -# sed -i "s/${currentAuxHash}/${newAuxHash}/g" ${txBodyFile}; if [ $? -ne 0 ]; then echo -e "\e[35mCouldn't write new ${txBodyFile} with a corrected AuxHash!\e[0m\n\n"; exit 1; fi -# echo -e "\e[32mOK\e[90m\n" -# fi - - dispFile=$(cat ${txBodyFile}); if ${cropTxOutput} && [[ ${#dispFile} -gt 4000 ]]; then echo "${dispFile:0:4000} ... (cropped)"; else echo "${dispFile}"; fi echo @@ -584,7 +582,7 @@ if [[ -f "${fromAddr}.hwsfile" ]]; then if [[ "${tmp^^}" =~ (ERROR|DISCONNECT) ]]; then echo -e "\e[35m${tmp}\e[0m\n"; exit 1; else echo -ne "\e[0mWitnessed ... "; fi checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - ${cardanocli} transaction assemble --tx-body-file ${txBodyFile} --witness-file ${txWitnessFile} --out-file ${txFile} + ${cardanocli} ${cliEra} transaction assemble --tx-body-file ${txBodyFile} --witness-file ${txWitnessFile} --out-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "Assembled ... \e[32mDONE\e[0m\n"; @@ -596,7 +594,7 @@ else echo -e "\e[0mSign the unsigned transaction body with the \e[32m${fromAddr}.skey\e[0m: \e[32m ${txFile}\e[0m" echo - ${cardanocli} transaction sign --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON}") ${magicparam} --out-file ${txFile} + ${cardanocli} ${cliEra} transaction sign --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON}") --out-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #forget the signing keys @@ -621,18 +619,31 @@ if [[ ${txSize} -le ${maxTxSize} ]]; then echo -e "\e[0mTransaction-Size: ${txSi if [ "${ENV_SKIP_PROMPT}" == "YES" ] || ask "\n\e[33mDoes this look good for you, continue ?" N; then echo - if ${onlineMode}; then #onlinesubmit + case ${workMode} in + "online") + #onlinesubmit echo -ne "\e[0mSubmitting the transaction via the node... " - ${cardanocli} transaction submit --tx-file ${txFile} ${magicparam} + ${cardanocli} ${cliEra} transaction submit --tx-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "\e[32mDONE\n" #Show the TxID - txID=$(${cardanocli} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" + txID=$(${cardanocli} ${cliEra} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; + + "light") + #lightmode submit + showProcessAnimation "Submit-Transaction-LightMode: " & + txID=$(submitLight "${txFile}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${txID}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + echo -e "\e[0mSubmit-Transaction-LightMode: \e[32mDONE\n" + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; - else #offlinestore + "offline") + #offlinestore txFileJSON=$(cat ${txFile} | jq .) offlineJSON=$( jq ".transactions += [ { date: \"$(date -R)\", type: \"Transaction\", @@ -654,8 +665,9 @@ if [ "${ENV_SKIP_PROMPT}" == "YES" ] || ask "\n\e[33mDoes this look good for you else echo -e "\e[35mERROR - Could not verify the written data in the '$(basename ${offlineFile})'. Retry again or generate a new '$(basename ${offlineFile})'.\e[0m\n"; fi + ;; - fi + esac fi diff --git a/cardano/mainnet/01_workOffline.sh b/cardano/mainnet/01_workOffline.sh index 4743bdff..e596657c 100755 --- a/cardano/mainnet/01_workOffline.sh +++ b/cardano/mainnet/01_workOffline.sh @@ -37,8 +37,8 @@ case ${1} in new|execute|clear ) action="${1}"; - if ${offlineMode}; then echo -e "\e[35mYou have to be in ONLINE MODE to do this!\e[0m\n"; exit 1; #exit if command is called in offline mode, needs to be in online mode - elif [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mYour online Node must be fully synced!\e[0m\n"; exit 1; #check that the node is fully synced + if ${offlineMode}; then echo -e "\e[35mYou have to be in ONLINE or LIGHT MODE to do this!\e[0m\n"; exit 1; #exit if command is called in offline mode, needs to be in online mode + elif [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mYour ONLINE/LIGHT Node must be fully synced, please wait a bit!\e[0m\n"; exit 1; #check that the node is fully synced fi if [[ $# -eq 2 ]]; then executeCue=${2}; else executeCue=1; fi @@ -46,8 +46,8 @@ case ${1} in add ) action="${1}"; - if ${offlineMode}; then echo -e "\e[35mYou have to be in ONLINE MODE to do this!\e[0m\n"; exit 1; #exit if command is called in offline mode, needs to be in online mode - elif [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mYour online Node must be fully synced!\e[0m\n"; exit 1; #check that the node is fully synced + if ${offlineMode}; then echo -e "\e[35mYou have to be in ONLINE or LIGHT MODE to do this!\e[0m\n"; exit 1; #exit if command is called in offline mode, needs to be in online mode + elif [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mYour ONLINE/LIGHT Node must be fully synced, please wait a bit!\e[0m\n"; exit 1; #check that the node is fully synced fi if [[ $# -eq 2 ]]; then addrName="$(dirname $2)/$(basename $2 .addr)"; addrName=${addrName/#.\//}; else echo -e "\e[35mMissing AddressName for the Address!\e[0m\n"; showUsage; exit 1; fi if [ ! -f "${addrName}.addr" ]; then echo -e "\e[35mNo ${addrName}.addr file found for the Address!\e[0m\n"; showUsage; exit 1; fi @@ -111,13 +111,24 @@ case ${action} in new|clear ) #Build a fresh new offlineJSON with the current protocolParameters in it offlineJSON="{}"; - protocolParametersJSON=$(${cardanocli} query protocol-parameters ${magicparam} ) + + #Read ProtocolParameters + case ${workMode} in + "online") protocolParametersJSON=$(${cardanocli} ${cliEra} query protocol-parameters );; #onlinemode + "light") protocolParametersJSON=${lightModeParametersJSON};; #lightmode + esac checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi + offlineJSON=$( jq ".general += {onlineCLI: \"${versionCLI}\" }" <<< ${offlineJSON}) - offlineJSON=$( jq ".general += {onlineNODE: \"${versionNODE}\" }" <<< ${offlineJSON}) + if ${fullMode}; then + offlineJSON=$( jq ".general += {onlineNODE: \"${versionNODE}\" }" <<< ${offlineJSON}) + else + offlineJSON=$( jq ".general += {onlineNODE: \"light\" }" <<< ${offlineJSON}) + fi + offlineJSON=$( jq ".protocol += {parameters: ${protocolParametersJSON} }" <<< ${offlineJSON}) offlineJSON=$( jq ".protocol += {era: \"$(get_NodeEra)\" }" <<< ${offlineJSON}) - offlineJSON=$( jq ".history += [ { date: \"$(date -R)\", action: \"new file created\" } ]" <<< ${offlineJSON}) + offlineJSON=$( jq ".history += [ { date: \"$(date -R)\", action: \"new file created - ${workMode} mode\" } ]" <<< ${offlineJSON}) #Write the new offileFile content echo "${offlineJSON}" > ${offlineFile} showOfflineFileInfo; @@ -127,10 +138,19 @@ case ${action} in add ) #Updating the current protocolParameters before doing other stuff later on - protocolParametersJSON=$(${cardanocli} query protocol-parameters ${magicparam} ) - checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - offlineJSON=$( jq ".general += {onlineCLI: \"${versionCLI}\" }" <<< ${offlineJSON}) - offlineJSON=$( jq ".general += {onlineNODE: \"${versionNODE}\" }" <<< ${offlineJSON}) + case ${workMode} in + "online") protocolParametersJSON=$(${cardanocli} ${cliEra} query protocol-parameters );; #onlinemode + "light") protocolParametersJSON=${lightModeParametersJSON};; #lightmode + esac + checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi + + offlineJSON=$( jq ".general += {onlineCLI: \"${versionCLI}\" }" <<< ${offlineJSON}) + if ${fullMode}; then + offlineJSON=$( jq ".general += {onlineNODE: \"${versionNODE}\" }" <<< ${offlineJSON}) + else + offlineJSON=$( jq ".general += {onlineNODE: \"light\" }" <<< ${offlineJSON}) + fi + offlineJSON=$( jq ".protocol += {parameters: ${protocolParametersJSON} }" <<< ${offlineJSON}) offlineJSON=$( jq ".protocol += {era: \"$(get_NodeEra)\" }" <<< ${offlineJSON}) ;; @@ -192,11 +212,23 @@ if [[ ${typeOfAddr} == ${addrTypePayment} ]]; then #Enterprise and Base UTXO ad echo -e "\e[0mAddress-Type / Era:\e[32m $(get_addressType "${checkAddr}")\e[0m / \e[32m$(get_addressEra "${checkAddr}")\e[0m" echo - #Get UTX0 Data for the address - showProcessAnimation "Query-UTXO: " & - utxo=$(${cardanocli} query utxo --address ${checkAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; - showProcessAnimation "Convert-UTXO: " & - utxoJSON=$(generate_UTXO "${utxo}" "${checkAddr}"); stopProcessAnimation; + #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in lightmode via API requests + case ${workMode} in + "online") #check that the node is fully synced, otherwise the query would mabye return a false state + showProcessAnimation "Query-UTXO: " & + utxo=$(${cardanocli} ${cliEra} query utxo --address ${checkAddr} 2> /dev/stdout); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + showProcessAnimation "Convert-UTXO: " & + utxoJSON=$(generate_UTXO "${utxo}" "${checkAddr}"); stopProcessAnimation; + ;; + + "light") showProcessAnimation "Query-UTXO-LightMode: " & + utxo=$(queryLight_UTXO "${checkAddr}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + showProcessAnimation "Convert-UTXO: " & + utxoJSON=$(generate_UTXO "${utxo}" "${checkAddr}"); stopProcessAnimation; + ;; + esac utxoEntryCnt=$(jq length <<< ${utxoJSON}) if [[ ${utxoEntryCnt} == 0 ]]; then echo -e "\e[35mNo funds on the Address!\e[0m\n"; exit 1; else echo -e "\e[32m${utxoEntryCnt} UTXOs\e[0m found on the Address!"; fi @@ -255,8 +287,20 @@ if [[ ${typeOfAddr} == ${addrTypePayment} ]]; then #Enterprise and Base UTXO ad totalAssetsJSON=$( jq ". += {\"${assetHash}${point}${assetName}\":{amount: \"${newValue}\", name: \"${assetTmpName}\", bech: \"${assetBech}\"}}" <<< ${totalAssetsJSON}) if [[ "${assetTmpName:0:1}" == "." ]]; then assetTmpName=${assetTmpName:1}; else assetTmpName="{${assetTmpName}}"; fi - case ${assetHash} in - "${adahandlePolicyID}" ) #$adahandle + case "${assetHash}${assetTmpName:1:8}" in + "${adahandlePolicyID}000de140" ) #$adahandle cip-68 + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Own): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}00000000" ) #$adahandle virtual + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Vir): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}000643b0" ) #$adahandle reference + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Ref): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}"* ) #$adahandle cip-25 echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle: \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" ;; * ) #default @@ -292,9 +336,14 @@ if [[ ${typeOfAddr} == ${addrTypePayment} ]]; then #Enterprise and Base UTXO ad assetBech=${assetBechArray[${tmpCnt}]} assetHashHex="${assetHashName//./}" #remove a . if present, we need a clean subject here for the registry request - if $queryTokenRegistry; then if $onlineMode; then metaResponse=$(curl -sL -m 20 "${tokenMetaServer}/${assetHashHex}"); else metaResponse=$(jq -r ".tokenMetaServer.\"${assetHashHex}\"" <<< ${offlineJSON}); fi + if $queryTokenRegistry; then #if activated, check the current asset on the metadata server. if data is available, include it in the offlineJSON in a compact format + metaResponse=$(curl -sL -m 20 "${tokenMetaServer}/${assetHashHex}") metaAssetName=$(jq -r ".name.value | select (.!=null)" 2> /dev/null <<< ${metaResponse}); if [[ ! "${metaAssetName}" == "" ]]; then metaAssetName="${metaAssetName} "; fi metaAssetTicker=$(jq -r ".ticker.value | select (.!=null)" 2> /dev/null <<< ${metaResponse}) + if [[ "${metaAssetName}" != "" || "${metaAssetTicker}" != "" ]]; then + #reduce the keys in metaResponse to only name and ticker. remove the subkeys signatures and sequenceNumber to safe some storage space + offlineJSON=$( jq ".tokenMetaServer.\"${assetHashHex}\" += $(jq -cM "{name,ticker} | del(.[].signatures,.[].sequenceNumber)" <<< ${metaResponse} 2> /dev/null)" <<< ${offlineJSON}) + fi fi if [[ "${assetName}" == "." ]]; then assetName=""; fi @@ -337,8 +386,20 @@ elif [[ ${typeOfAddr} == ${addrTypeStake} ]]; then #Staking Address echo -e "\e[0mAddress-Type / Era:\e[32m $(get_addressType "${checkAddr}")\e[0m / \e[32m$(get_addressEra "${checkAddr}")\e[0m" echo - rewardsJSON=$(${cardanocli} query stake-address-info --address ${checkAddr} ${magicparam} | jq -rc .) - checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi + #Get rewards state data for the address. When in online mode of course from the node and the chain, in light mode via koios + case ${workMode} in + + "online") showProcessAnimation "Query-StakeAddress-Info: " & + rewardsJSON=$(${cardanocli} ${cliEra} query stake-address-info --address ${checkAddr} 2> /dev/null ) + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${rewardsJSON}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + rewardsJSON=$(jq . <<< "${rewardsJSON}") + ;; + + "light") showProcessAnimation "Query-StakeAddress-Info-LightMode: " & + rewardsJSON=$(queryLight_stakeAddressInfo "${checkAddr}") + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${rewardsJSON}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + esac rewardsEntryCnt=$(jq -r 'length' <<< ${rewardsJSON}) @@ -353,7 +414,7 @@ elif [[ ${typeOfAddr} == ${addrTypeStake} ]]; then #Staking Address rewardsAmount=$(jq -r ".[${tmpCnt}].rewardAccountBalance" <<< ${rewardsJSON}) rewardsAmountInADA=$(bc <<< "scale=6; ${rewardsAmount} / 1000000") - delegationPoolID=$(jq -r ".[${tmpCnt}].delegation" <<< ${rewardsJSON}) + delegationPoolID=$(jq -r ".[${tmpCnt}].delegation // .[${tmpCnt}].stakeDelegation" <<< ${rewardsJSON}) rewardsSum=$((${rewardsSum}+${rewardsAmount})) rewardsSumInADA=$(bc <<< "scale=6; ${rewardsSum} / 1000000") @@ -461,30 +522,61 @@ echo "${transactionTxJSON}" > ${txFile}; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi case ${transactionType} in + Transaction|Asset-Minting|Asset-Burning ) - #Normal UTXO Transaction (lovelaces and/or tokens) + #Normal UTXO Transaction (lovelaces and/or tokens) #Check that the UTXO on the paymentAddress (transactionFromAddr) has not changed - showProcessAnimation "Query-UTXO: " & - utxo=$(${cardanocli} query utxo --address ${transactionFromAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + case ${workMode} in + "online") showProcessAnimation "Query-UTXO: " & + utxo=$(${cardanocli} ${cliEra} query utxo --address ${transactionFromAddr} 2> /dev/stdout); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + + "light") showProcessAnimation "Query-UTXO-LightMode: " & + utxo=$(queryLight_UTXO "${transactionFromAddr}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + esac showProcessAnimation "Convert-UTXO: " & utxoLiveJSON=$(generate_UTXO "${utxo}" "${transactionFromAddr}"); stopProcessAnimation; utxoLiveJSON=$(jq . <<< ${utxoLiveJSON}) #to bring it in the jq format if compressed + utxoOfflineJSON=$(jq -r ".address.\"${transactionFromAddr}\".utxoJSON" <<< ${offlineJSON}) if [[ ! "${utxoLiveJSON}" == "${utxoOfflineJSON}" ]]; then echo -e "\e[35mERROR - The UTXO status between the offline capture and now has changed for the payment address '${transactionFromName}' !\e[0m\n"; exit 1; fi echo -e "\e[32m\t[${transactionCue}]\t\e[0m${transactionType}[${transactionEra}] from '${transactionFromName}' to '${transactionToName}' \e[90m(${transactionDate})\n\t \t\e[90mfrom ${transactionFromAddr}\n\t \t\e[90mto ${transactionToAddr}\e[0m" echo - txID=$(${cardanocli} transaction txid --tx-file ${txFile} ) - echo -e "\e[0mTxID will be: \e[32m${txID}\e[0m\n" if ask "\e[33mDoes this look good for you, continue ?" N; then - ${cardanocli} transaction submit --tx-file ${txFile} ${magicparam} - checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - echo -e "\n\e[0mStatus: \e[36mDONE - Transaction submitted\n" - if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + + echo + case ${workMode} in + "online") + #onlinesubmit + echo -ne "\e[0mSubmitting the transaction via the node ... " + ${cardanocli} ${cliEra} transaction submit --tx-file ${txFile} + checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi + echo -e "\n\e[0mStatus: \e[36mDONE - Transaction submitted\n" + + #Show the TxID + txID=$(${cardanocli} ${cliEra} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" + checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; + + "light") + #lightmode submit + showProcessAnimation "Submit-Transaction-LightMode: " & + txID=$(submitLight "${txFile}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${txID}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + echo -e "\e[0mSubmit-Transaction-LightMode ... \e[32mDONE\n" + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; + esac echo + #Write the new offileFile content offlineJSON=$( jq ".address.\"${transactionFromAddr}\" += {used: \"yes\" }" <<< ${offlineJSON}) #mark payment address as used if [[ ! "$(jq -r .address.\"${transactionToAddr}\" <<< ${offlineJSON})" == null ]]; then offlineJSON=$( jq ".address.\"${transactionToAddr}\" += {used: \"yes\" }" <<< ${offlineJSON}); fi #mark destination address as used if present @@ -502,32 +594,77 @@ case ${transactionType} in transactionStakeName=$(jq -r ".transactions[${transactionIdx}].stakeAddr" <<< ${offlineJSON}) transactionStakeAddr=$(jq -r ".transactions[${transactionIdx}].stakingAddr" <<< ${offlineJSON}) - #Check that the UTXO on the paymentAddress (transactionFromAddr) has not changed - showProcessAnimation "Query-UTXO: " & - utxo=$(${cardanocli} query utxo --address ${transactionFromAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + #Check that the UTXO on the paymentAddress (transactionFromAddr) has not changed + case ${workMode} in + "online") showProcessAnimation "Query-UTXO: " & + utxo=$(${cardanocli} ${cliEra} query utxo --address ${transactionFromAddr} 2> /dev/stdout); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + + "light") showProcessAnimation "Query-UTXO-LightMode: " & + utxo=$(queryLight_UTXO "${transactionFromAddr}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + esac showProcessAnimation "Convert-UTXO: " & utxoLiveJSON=$(generate_UTXO "${utxo}" "${transactionFromAddr}"); stopProcessAnimation; - utxoLiveJSON=$(jq . <<< ${utxoLiveJSON}) #to bring it in the jq format if compressed - utxoOfflineJSON=$(jq -r ".address.\"${transactionFromAddr}\".utxoJSON" <<< ${offlineJSON}) + utxoLiveJSON=$(jq . <<< ${utxoLiveJSON} 2> /dev/null) #to bring it in the jq format if compressed + + utxoOfflineJSON=$(jq -r ".address.\"${transactionFromAddr}\".utxoJSON" <<< ${offlineJSON}) + if [[ ! "${utxoLiveJSON}" == "${utxoOfflineJSON}" ]]; then echo -e "\e[35mERROR - The UTXO status between the offline capture and now has changed for the payment address '${transactionFromName}' !\e[0m\n"; exit 1; fi #Check that the RewardsState of the StakeAddress (transactionStakeAddr) has not changed - rewardsLiveJSON=$(${cardanocli} query stake-address-info --address ${transactionStakeAddr} ${magicparam} | jq .); checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + case ${workMode} in + + "online") showProcessAnimation "Query-StakeAddress-Info: " & + rewardsJSON=$(${cardanocli} ${cliEra} query stake-address-info --address ${transactionStakeAddr} 2> /dev/null ) + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${rewardsJSON}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + + "light") showProcessAnimation "Query-StakeAddress-Info-LightMode: " & + rewardsJSON=$(queryLight_stakeAddressInfo "${transactionStakeAddr}") + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${rewardsJSON}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + esac + rewardsLiveJSON=$(jq . <<< ${rewardsJSON} 2> /dev/null) + rewardsOfflineJSON=$(jq -r ".address.\"${transactionStakeAddr}\".rewardsJSON" <<< ${offlineJSON}) + if [[ ! "${rewardsLiveJSON}" == "${rewardsOfflineJSON}" ]]; then echo -e "\e[35mERROR - The rewards state between the offline capture and now has changed for the stake address '${transactionStakeName}' !\e[0m\n"; exit 1; fi echo -e "\e[32m\t[${transactionCue}]\t\e[0mRewards-Withdrawal[${transactionEra}] from '${transactionStakeName}' to '${transactionToName}', payment via '${transactionFromName}' \e[90m(${transactionDate})" echo -e "\t \t\e[90mfrom ${transactionStakeAddr}\n\t \t\e[90mto ${transactionToAddr}\n\t \t\e[90mpayment via ${transactionFromAddr}\e[0m" echo - txID=$(${cardanocli} transaction txid --tx-file ${txFile} ) - echo -e "\e[0mTxID will be: \e[32m${txID}\e[0m\n" if ask "\e[33mDoes this look good for you, continue ?" N; then - ${cardanocli} transaction submit --tx-file ${txFile} ${magicparam} - checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - echo -e "\n\e[0mStatus: \e[36mDONE - Transaction submitted\n" - if [[ ${magicparam} == "--mainnet" ]]; then echo -e "\e[0mTracking: \e[32mhttps://cardanoscan.io/transaction/${txID}\n"; fi - echo + + echo + case ${workMode} in + "online") + #onlinesubmit + echo -ne "\e[0mSubmitting the transaction via the node ... " + ${cardanocli} ${cliEra} transaction submit --tx-file ${txFile} + checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi + echo -e "\n\e[0mStatus: \e[36mDONE - Transaction submitted\n" + + #Show the TxID + txID=$(${cardanocli} ${cliEra} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" + checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; + + "light") + #lightmode submit + showProcessAnimation "Submit-Transaction-LightMode: " & + txID=$(submitLight "${txFile}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${txID}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + echo -e "\e[0mSubmit-Transaction-LightMode ... \e[32mDONE\n" + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; + esac + echo + #Write the new offileFile content offlineJSON=$( jq ".address.\"${transactionFromAddr}\" += {used: \"yes\" }" <<< ${offlineJSON}) offlineJSON=$( jq ".address.\"${transactionStakeAddr}\" += {used: \"yes\" }" <<< ${offlineJSON}) @@ -540,32 +677,63 @@ case ${transactionType} in fi ;; + StakeKeyRegistration|StakeKeyDeRegistration ) #StakeKey Registration of De-Registration Transaction transactionStakeName=$(jq -r ".transactions[${transactionIdx}].stakeAddr" <<< ${offlineJSON}) - #Check that the UTXO on the paymentAddress (transactionFromAddr) has not changed - showProcessAnimation "Query-UTXO: " & - utxo=$(${cardanocli} query utxo --address ${transactionFromAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + #Check that the UTXO on the paymentAddress (transactionFromAddr) has not changed + case ${workMode} in + "online") showProcessAnimation "Query-UTXO: " & + utxo=$(${cardanocli} ${cliEra} query utxo --address ${transactionFromAddr} 2> /dev/stdout); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + + "light") showProcessAnimation "Query-UTXO-LightMode: " & + utxo=$(queryLight_UTXO "${transactionFromAddr}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + esac showProcessAnimation "Convert-UTXO: " & utxoLiveJSON=$(generate_UTXO "${utxo}" "${transactionFromAddr}"); stopProcessAnimation; - utxoLiveJSON=$(jq . <<< ${utxoLiveJSON}) #to bring it in the jq format if compressed - utxoOfflineJSON=$(jq -r ".address.\"${transactionFromAddr}\".utxoJSON" <<< ${offlineJSON}) - if [[ ! "${utxoLiveJSON}" == "${utxoOfflineJSON}" ]]; then echo -e "\e[35mERROR - The UTXO status between the offline capture and now has changed for the payment address '${transactionFromName}' !\e[0m\n"; exit 1; fi + utxoLiveJSON=$(jq . <<< ${utxoLiveJSON}) #to bring it in the jq format if compressed + + utxoOfflineJSON=$(jq -r ".address.\"${transactionFromAddr}\".utxoJSON" <<< ${offlineJSON}) + if [[ ! "${utxoLiveJSON}" == "${utxoOfflineJSON}" ]]; then echo -e "\e[35mERROR - The UTXO status between the offline capture and now has changed for the payment address '${transactionFromName}' !\e[0m\n"; exit 1; fi echo -e "\e[90m\t[${transactionCue}]\t\e[0m${transactionType}[${transactionEra}] for '${transactionStakeName}', payment via '${transactionFromName}' \e[90m(${transactionDate})" echo -e "\t \t\e[90mpayment via ${transactionFromAddr}\e[0m" echo - txID=$(${cardanocli} transaction txid --tx-file ${txFile} ) - echo -e "\e[0mTxID will be: \e[32m${txID}\e[0m\n" if ask "\e[33mDoes this look good for you, continue ?" N; then - ${cardanocli} transaction submit --tx-file ${txFile} ${magicparam} - checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - echo -e "\n\e[0mStatus: \e[36mDONE - Transaction submitted\n" - if [[ ${magicparam} == "--mainnet" ]]; then echo -e "\e[0mTracking: \e[32mhttps://cardanoscan.io/transaction/${txID}\n"; fi - echo + + echo + case ${workMode} in + "online") + #onlinesubmit + echo -ne "\e[0mSubmitting the transaction via the node ... " + ${cardanocli} ${cliEra} transaction submit --tx-file ${txFile} + checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi + echo -e "\n\e[0mStatus: \e[36mDONE - Transaction submitted\n" + + #Show the TxID + txID=$(${cardanocli} ${cliEra} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" + checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; + + "light") + #lightmode submit + showProcessAnimation "Submit-Transaction-LightMode: " & + txID=$(submitLight "${txFile}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${txID}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + echo -e "\e[0mSubmit-Transaction-LightMode ... \e[32mDONE\n" + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; + esac + echo + #Write the new offileFile content offlineJSON=$( jq ".address.\"${transactionFromAddr}\" += {used: \"yes\" }" <<< ${offlineJSON}) offlineJSON=$( jq ".history += [ { date: \"$(date -R)\", action: \"tx submit ${txID} - ${transactionType} for '${transactionStakeName}', payment via '${transactionFromName}'\" } ]" <<< ${offlineJSON}) @@ -581,28 +749,58 @@ case ${transactionType} in #StakeKey Registration of De-Registration Transaction transactionDelegName=$(jq -r ".transactions[${transactionIdx}].delegName" <<< ${offlineJSON}) - #Check that the UTXO on the paymentAddress (transactionFromAddr) has not changed - showProcessAnimation "Query-UTXO: " & - utxo=$(${cardanocli} query utxo --address ${transactionFromAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + #Check that the UTXO on the paymentAddress (transactionFromAddr) has not changed + case ${workMode} in + "online") showProcessAnimation "Query-UTXO: " & + utxo=$(${cardanocli} ${cliEra} query utxo --address ${transactionFromAddr} 2> /dev/stdout); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + + "light") showProcessAnimation "Query-UTXO-LightMode: " & + utxo=$(queryLight_UTXO "${transactionFromAddr}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + esac showProcessAnimation "Convert-UTXO: " & utxoLiveJSON=$(generate_UTXO "${utxo}" "${transactionFromAddr}"); stopProcessAnimation; - utxoLiveJSON=$(jq . <<< ${utxoLiveJSON}) #to bring it in the jq format if compressed - utxoOfflineJSON=$(jq -r ".address.\"${transactionFromAddr}\".utxoJSON" <<< ${offlineJSON}) - if [[ ! "${utxoLiveJSON}" == "${utxoOfflineJSON}" ]]; then echo -e "\e[35mERROR - The UTXO status between the offline capture and now has changed for the payment address '${transactionFromName}' !\e[0m\n"; exit 1; fi + utxoLiveJSON=$(jq . <<< ${utxoLiveJSON}) #to bring it in the jq format if compressed + utxoOfflineJSON=$(jq -r ".address.\"${transactionFromAddr}\".utxoJSON" <<< ${offlineJSON}) + + if [[ ! "${utxoLiveJSON}" == "${utxoOfflineJSON}" ]]; then echo -e "\e[35mERROR - The UTXO status between the offline capture and now has changed for the payment address '${transactionFromName}' !\e[0m\n"; exit 1; fi echo -e "\e[90m\t[${transactionCue}]\t\e[0m${transactionType}[${transactionEra}] for '${transactionDelegName}', payment via '${transactionFromName}' \e[90m(${transactionDate})" echo -e "\t \t\e[90mpayment via ${transactionFromAddr}\e[0m" echo - txID=$(${cardanocli} transaction txid --tx-file ${txFile} ) - echo -e "\e[0mTxID will be: \e[32m${txID}\e[0m\n" if ask "\e[33mDoes this look good for you, continue ?" N; then - ${cardanocli} transaction submit --tx-file ${txFile} ${magicparam} - checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - echo -e "\n\e[0mStatus: \e[36mDONE - Transaction submitted\n" - if [[ ${magicparam} == "--mainnet" ]]; then echo -e "\e[0mTracking: \e[32mhttps://cardanoscan.io/transaction/${txID}\n"; fi - echo + + echo + case ${workMode} in + "online") + #onlinesubmit + echo -ne "\e[0mSubmitting the transaction via the node ... " + ${cardanocli} ${cliEra} transaction submit --tx-file ${txFile} + checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi + echo -e "\n\e[0mStatus: \e[36mDONE - Transaction submitted\n" + + #Show the TxID + txID=$(${cardanocli} ${cliEra} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" + checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; + + "light") + #lightmode submit + showProcessAnimation "Submit-Transaction-LightMode: " & + txID=$(submitLight "${txFile}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${txID}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + echo -e "\e[0mSubmit-Transaction-LightMode ... \e[32mDONE\n" + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; + esac + echo + #Write the new offileFile content offlineJSON=$( jq ".address.\"${transactionFromAddr}\" += {used: \"yes\" }" <<< ${offlineJSON}) offlineJSON=$( jq ".history += [ { date: \"$(date -R)\", action: \"tx submit ${txID} - ${transactionType} for '${transactionStakeName}', payment via '${transactionFromName}'\" } ]" <<< ${offlineJSON}) @@ -621,13 +819,24 @@ case ${transactionType} in poolMetaHash=$(jq -r ".transactions[${transactionIdx}].poolMetaHash" <<< ${offlineJSON}) regProtectionKey=$(jq -r ".transactions[${transactionIdx}].regProtectionKey" <<< ${offlineJSON}) - #Check that the UTXO on the paymentAddress (transactionFromAddr) has not changed - showProcessAnimation "Query-UTXO: " & - utxo=$(${cardanocli} query utxo --address ${transactionFromAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + #Check that the UTXO on the paymentAddress (transactionFromAddr) has not changed + case ${workMode} in + "online") showProcessAnimation "Query-UTXO: " & + utxo=$(${cardanocli} ${cliEra} query utxo --address ${transactionFromAddr} 2> /dev/stdout); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + + "light") showProcessAnimation "Query-UTXO-LightMode: " & + utxo=$(queryLight_UTXO "${transactionFromAddr}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + esac showProcessAnimation "Convert-UTXO: " & utxoLiveJSON=$(generate_UTXO "${utxo}" "${transactionFromAddr}"); stopProcessAnimation; - utxoLiveJSON=$(jq . <<< ${utxoLiveJSON}) #to bring it in the jq format if compressed - utxoOfflineJSON=$(jq -r ".address.\"${transactionFromAddr}\".utxoJSON" <<< ${offlineJSON}) + utxoLiveJSON=$(jq . <<< ${utxoLiveJSON}) #to bring it in the jq format if compressed + + utxoOfflineJSON=$(jq -r ".address.\"${transactionFromAddr}\".utxoJSON" <<< ${offlineJSON}) + if [[ ! "${utxoLiveJSON}" == "${utxoOfflineJSON}" ]]; then echo -e "\e[35mERROR - The UTXO status between the offline capture and now has changed for the payment address '${transactionFromName}' !\e[0m\n"; exit 1; fi echo -e "\e[90m\t[${transactionCue}]\t\e[0m${transactionType}[${transactionEra}] for Pool '${poolMetaTicker}', payment via '${transactionFromName}' \e[90m(${transactionDate})" @@ -636,7 +845,7 @@ case ${transactionType} in #Check if the regProtectionKey is correct, this is a service to not have any duplicated Tickers on the Chain. If you know how to code you can see that it is easy, just a little protection for Noobs echo -ne "\e[0m\x54\x69\x63\x6B\x65\x72\x20\x50\x72\x6F\x74\x65\x63\x74\x69\x6F\x6E\x20\x43\x68\x65\x63\x6B\x20\x66\x6F\x72\x20\x54\x69\x63\x6B\x65\x72\x20'\e[32m${poolMetaTicker}\e[0m': " - checkResult=$(curl -m 5 -s $(echo -e "\x68\x74\x74\x70\x73\x3A\x2F\x2F\x6D\x79\x2D\x69\x70\x2E\x61\x74\x2F\x63\x68\x65\x63\x6B\x74\x69\x63\x6B\x65\x72\x3F\x74\x69\x63\x6B\x65\x72\x3D${poolMetaTicker}&key=${regProtectionKey}") ); + checkResult=$(curl -m 20 -s $(echo -e "\x68\x74\x74\x70\x73\x3A\x2F\x2F\x6D\x79\x2D\x69\x70\x2E\x61\x74\x2F\x63\x68\x65\x63\x6B\x74\x69\x63\x6B\x65\x72\x3F\x74\x69\x63\x6B\x65\x72\x3D${poolMetaTicker}&key=${regProtectionKey}") ); if [[ $? -ne 0 ]]; then echo -e "\e[33m\x50\x72\x6F\x74\x65\x63\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x20\x6F\x66\x66\x6C\x69\x6E\x65\e[0m"; else if [[ ! "${checkResult}" == "OK" ]]; then @@ -660,7 +869,7 @@ case ${transactionType} in tmpCheckJSON=$(jq . "${tmpMetadataJSON}" 2> /dev/null) if [[ $? -ne 0 ]]; then echo -e "\e[35mERROR - Not a valid JSON file on the webserver!\e[0m\n"; exit 1; fi #Ok, downloaded file is a valid JSON file. So now look into the HASH - onlineMetaHash=$(${cardanocli} stake-pool metadata-hash --pool-metadata-file "${tmpMetadataJSON}") + onlineMetaHash=$(${cardanocli} ${cliEra} stake-pool metadata-hash --pool-metadata-file "${tmpMetadataJSON}") checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #Compare the HASH now, if they don't match up, output an ERROR message and exit if [[ ! "${poolMetaHash}" == "${onlineMetaHash}" ]]; then @@ -674,15 +883,34 @@ case ${transactionType} in else echo -e "\e[32mOK\e[0m\n"; fi #Ok, HASH is the same, continue - txID=$(${cardanocli} transaction txid --tx-file ${txFile} ) - echo -e "\e[0mTxID will be: \e[32m${txID}\e[0m\n" - if ask "\e[33mDoes this look good for you, continue ?" N; then - ${cardanocli} transaction submit --tx-file ${txFile} ${magicparam} - checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - echo -e "\n\e[0mStatus: \e[36mDONE - Transaction submitted\n" - if [[ ${magicparam} == "--mainnet" ]]; then echo -e "\e[0mTracking: \e[32mhttps://cardanoscan.io/transaction/${txID}\n"; fi - echo + + echo + case ${workMode} in + "online") + #onlinesubmit + echo -ne "\e[0mSubmitting the transaction via the node ... " + ${cardanocli} ${cliEra} transaction submit --tx-file ${txFile} + checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi + echo -e "\n\e[0mStatus: \e[36mDONE - Transaction submitted\n" + + #Show the TxID + txID=$(${cardanocli} ${cliEra} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" + checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; + + "light") + #lightmode submit + showProcessAnimation "Submit-Transaction-LightMode: " & + txID=$(submitLight "${txFile}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${txID}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + echo -e "\e[0mSubmit-Transaction-LightMode ... \e[32mDONE\n" + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; + esac + echo + #Write the new offileFile content offlineJSON=$( jq ".address.\"${transactionFromAddr}\" += {used: \"yes\" }" <<< ${offlineJSON}) offlineJSON=$( jq ".history += [ { date: \"$(date -R)\", action: \"tx submit ${txID} - ${transactionType} for Pool '${poolMetaTicker}', payment via '${transactionFromName}'\" } ]" <<< ${offlineJSON}) @@ -698,27 +926,58 @@ case ${transactionType} in #Pool Retirement poolMetaTicker=$(jq -r ".transactions[${transactionIdx}].poolMetaTicker" <<< ${offlineJSON}) - #Check that the UTXO on the paymentAddress (transactionFromAddr) has not changed - showProcessAnimation "Query-UTXO: " & - utxo=$(${cardanocli} query utxo --address ${transactionFromAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + #Check that the UTXO on the paymentAddress (transactionFromAddr) has not changed + case ${workMode} in + "online") showProcessAnimation "Query-UTXO: " & + utxo=$(${cardanocli} ${cliEra} query utxo --address ${transactionFromAddr} 2> /dev/stdout); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + + "light") showProcessAnimation "Query-UTXO-LightMode: " & + utxo=$(queryLight_UTXO "${transactionFromAddr}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + esac showProcessAnimation "Convert-UTXO: " & utxoLiveJSON=$(generate_UTXO "${utxo}" "${transactionFromAddr}"); stopProcessAnimation; - utxoLiveJSON=$(jq . <<< ${utxoLiveJSON}) #to bring it in the jq format if compressed - utxoOfflineJSON=$(jq -r ".address.\"${transactionFromAddr}\".utxoJSON" <<< ${offlineJSON}) + utxoLiveJSON=$(jq . <<< ${utxoLiveJSON}) #to bring it in the jq format if compressed + + utxoOfflineJSON=$(jq -r ".address.\"${transactionFromAddr}\".utxoJSON" <<< ${offlineJSON}) + if [[ ! "${utxoLiveJSON}" == "${utxoOfflineJSON}" ]]; then echo -e "\e[35mERROR - The UTXO status between the offline capture and now has changed for the payment address '${transactionFromName}' !\e[0m\n"; exit 1; fi echo -e "\e[90m\t[${transactionCue}]\t\e[0m${transactionType}[${transactionEra}] for Pool '${poolMetaTicker}', payment via '${transactionFromName}' \e[90m(${transactionDate})" echo -e "\t \t\e[90mpayment via ${transactionFromAddr}\e[0m" echo - txID=$(${cardanocli} transaction txid --tx-file ${txFile} ) - echo -e "\e[0mTxID will be: \e[32m${txID}\e[0m\n" if ask "\e[33mDoes this look good for you, continue ?" N; then - ${cardanocli} transaction submit --tx-file ${txFile} ${magicparam} - checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - echo -e "\n\e[0mStatus: \e[36mDONE - Transaction submitted\n" - if [[ ${magicparam} == "--mainnet" ]]; then echo -e "\e[0mTracking: \e[32mhttps://cardanoscan.io/transaction/${txID}\n"; fi - echo + + echo + case ${workMode} in + "online") + #onlinesubmit + echo -ne "\e[0mSubmitting the transaction via the node ... " + ${cardanocli} ${cliEra} transaction submit --tx-file ${txFile} + checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi + echo -e "\n\e[0mStatus: \e[36mDONE - Transaction submitted\n" + + #Show the TxID + txID=$(${cardanocli} ${cliEra} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" + checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; + + "light") + #lightmode submit + showProcessAnimation "Submit-Transaction-LightMode: " & + txID=$(submitLight "${txFile}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${txID}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + echo -e "\e[0mSubmit-Transaction-LightMode ... \e[32mDONE\n" + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; + esac + echo + #Write the new offileFile content offlineJSON=$( jq ".address.\"${transactionFromAddr}\" += {used: \"yes\" }" <<< ${offlineJSON}) offlineJSON=$( jq ".history += [ { date: \"$(date -R)\", action: \"tx submit ${txID} - ${transactionType} for Pool '${poolMetaTicker}', payment via '${transactionFromName}'\" } ]" <<< ${offlineJSON}) diff --git a/cardano/mainnet/02_genPaymentAddrOnly.sh b/cardano/mainnet/02_genPaymentAddrOnly.sh index 3c74a8ac..12da59c4 100755 --- a/cardano/mainnet/02_genPaymentAddrOnly.sh +++ b/cardano/mainnet/02_genPaymentAddrOnly.sh @@ -9,7 +9,7 @@ #Check command line parameter if [ $# -lt 2 ] || [[ ! ${2^^} =~ ^(CLI|HW|ENC|HWMULTI)$ ]]; then cat >&2 < [Acc# 0-2147483647 for HW-Wallet-Path, Default=0] [Idx# 0-2147483647 for HW-Wallet-Path, Default=0] +Usage: $(basename $0) [Acc# 0-2147483647 for HW-Wallet-Path, Default=0] [Idx# 0-2147483647 for HW-Wallet-Path, Default=0] Examples: $(basename $0) owner cli ... generates a PaymentOnly Address via cli (was default method before) @@ -17,7 +17,6 @@ $(basename $0) owner enc ... generates a PaymentOnly Address via cl $(basename $0) owner hw ... generates a PaymentOnly Address by using a Ledger/Trezor HW-Wallet with normal path 1852H/1815H//0/ $(basename $0) owner hwmulti ... generates a PaymentOnly Address by using a Ledger/Trezor HW-Wallet with multisig path 1854H/1815H//0/ - Optional with Hardware-Account-Numbers: $(basename $0) owner hw 1 ... generates a PaymentOnly Address by using a Leder/Trezor HW-Wallet and SubAccount #1 (Default=0) $(basename $0) owner hw 5 1 ... generates a PaymentOnly Address by using a Leder/Trezor HW-Wallet, SubAccount #5, Index #1 @@ -65,7 +64,7 @@ if [ -f "${addrName}.addr" ]; then echo -e "\e[35mWARNING - ${addrName}.addr alr if [[ "${keyType^^}" == "CLI" ]]; then #Building it from the cli - ${cardanocli} address key-gen --verification-key-file ${addrName}.vkey --signing-key-file ${addrName}.skey + ${cardanocli} ${cliEra} address key-gen --verification-key-file ${addrName}.vkey --signing-key-file ${addrName}.skey checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi file_lock ${addrName}.vkey file_lock ${addrName}.skey @@ -78,7 +77,7 @@ if [[ "${keyType^^}" == "CLI" ]]; then #Building it from the cli echo #Building a Payment Address - ${cardanocli} address build --payment-verification-key-file ${addrName}.vkey ${addrformat} > ${addrName}.addr + ${cardanocli} ${cliEra} address build --payment-verification-key-file ${addrName}.vkey ${addrformat} > ${addrName}.addr checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi file_lock ${addrName}.addr @@ -90,7 +89,7 @@ if [[ "${keyType^^}" == "CLI" ]]; then #Building it from the cli elif [[ "${keyType^^}" == "ENC" ]]; then #Building it from the cli and encrypt the skey file. The skey file never touches the hdd unencrypted - skeyJSON=$(${cardanocli} address key-gen --verification-key-file "${addrName}.vkey" --signing-key-file /dev/stdout 2> /dev/null) + skeyJSON=$(${cardanocli} ${cliEra} address key-gen --verification-key-file "${addrName}.vkey" --signing-key-file /dev/stdout 2> /dev/null) checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi file_lock ${addrName}.vkey @@ -159,7 +158,7 @@ elif [[ "${keyType^^}" == "ENC" ]]; then #Building it from the cli and encrypt t echo #Building a Payment Address - ${cardanocli} address build --payment-verification-key-file ${addrName}.vkey ${addrformat} > ${addrName}.addr + ${cardanocli} ${cliEra} address build --payment-verification-key-file ${addrName}.vkey ${addrformat} > ${addrName}.addr checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi file_lock ${addrName}.addr @@ -191,7 +190,7 @@ elif [[ "${keyType^^}" == "HW" ]]; then #Building it from HW-Keys echo #Building a Payment Address - ${cardanocli} address build --payment-verification-key-file ${addrName}.vkey ${addrformat} > ${addrName}.addr + ${cardanocli} ${cliEra} address build --payment-verification-key-file ${addrName}.vkey ${addrformat} > ${addrName}.addr checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi file_lock ${addrName}.addr @@ -201,7 +200,7 @@ elif [[ "${keyType^^}" == "HW" ]]; then #Building it from HW-Keys echo -e "\e[0m\n" -else #Building from HW-Keys with MultiSig-Path "HWMULTI" +elif [[ "${keyType^^}" == "HWMULTI" ]]; then #Building from HW-Keys with MultiSig-Path "HWMULTI" #We need a enterprise paymentonly keypair with vkey and hwsfile from a Hardware-Key, so lets' create them start_HwWallet; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi @@ -223,7 +222,7 @@ else #Building from HW-Keys with MultiSig-Path "HWMULTI" echo #Building a Payment Address - ${cardanocli} address build --payment-verification-key-file ${addrName}.vkey ${addrformat} > ${addrName}.addr + ${cardanocli} ${cliEra} address build --payment-verification-key-file ${addrName}.vkey ${addrformat} > ${addrName}.addr checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi file_lock ${addrName}.addr @@ -233,6 +232,11 @@ else #Building from HW-Keys with MultiSig-Path "HWMULTI" echo -e "\e[0m\n" +else #unknown keyType + + echo -e "\e[33mUnknown keyType '${keyType^^}'\e[00m" + echo + fi diff --git a/cardano/mainnet/03a_genStakingPaymentAddr.sh b/cardano/mainnet/03a_genStakingPaymentAddr.sh index 0815b6b1..05d3bb58 100755 --- a/cardano/mainnet/03a_genStakingPaymentAddr.sh +++ b/cardano/mainnet/03a_genStakingPaymentAddr.sh @@ -124,7 +124,7 @@ fi if [[ "${keyType}" == "CLI" ]]; then #Payment Keys via CLI (unencrypted) #We need a normal payment(base) keypair with vkey and skey, so let's create that one - ${cardanocli} address key-gen --verification-key-file "${addrName}.payment.vkey" --signing-key-file "${addrName}.payment.skey" + ${cardanocli} ${cliEra} address key-gen --verification-key-file "${addrName}.payment.vkey" --signing-key-file "${addrName}.payment.skey" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi file_lock ${addrName}.payment.vkey file_lock ${addrName}.payment.skey @@ -184,7 +184,7 @@ elif [[ "${keyType}" == "MNEMONICS" ]]; then #Payment Keys via Mnemonics (unencr vkeyJSON=$(jq -r ".output.vkey" <<< ${signerJSON} 2> /dev/null) checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - vkeyJSON=$(${cardanocli} key non-extended-key --extended-verification-key-file <(echo "${vkeyJSON}") --verification-key-file /dev/stdout) #convert the extended vkey into a normal one + vkeyJSON=$(${cardanocli} ${cliEra} key non-extended-key --extended-verification-key-file <(echo "${vkeyJSON}") --verification-key-file /dev/stdout) #convert the extended vkey into a normal one checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi vkeyJSON=$(jq ".description = \"Payment Verification Key\"" <<< ${vkeyJSON} 2> /dev/null) checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi @@ -206,7 +206,7 @@ elif [[ "${keyType}" == "MNEMONICS" ]]; then #Payment Keys via Mnemonics (unencr elif [[ "${keyType}" == "ENC" ]]; then #Payment Keys via CLI (encrypted) #We need a normal payment(base) keypair with vkey and skey, so let's create that one - skeyJSON=$(${cardanocli} address key-gen --verification-key-file "${addrName}.payment.vkey" --signing-key-file /dev/stdout 2> /dev/null) + skeyJSON=$(${cardanocli} ${cliEra} address key-gen --verification-key-file "${addrName}.payment.vkey" --signing-key-file /dev/stdout 2> /dev/null) checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi file_lock ${addrName}.payment.vkey @@ -310,7 +310,7 @@ echo if [[ "${keyType}" == "CLI" || "${keyType}" == "HYBRID" || "${keyType}" == "HYBRIDMULTI" ]]; then #Staking Keys via CLI (unencrypted) #Building the StakeAddress Keys from CLI for the normal CLI type or when HYBRID was choosen - ${cardanocli} stake-address key-gen --verification-key-file "${addrName}.staking.vkey" --signing-key-file "${addrName}.staking.skey" + ${cardanocli} ${cliEra} stake-address key-gen --verification-key-file "${addrName}.staking.vkey" --signing-key-file "${addrName}.staking.skey" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi file_lock ${addrName}.staking.vkey file_lock ${addrName}.staking.skey @@ -340,7 +340,7 @@ elif [[ "${keyType}" == "MNEMONICS" ]]; then #Payment Keys via Mnemonics (unencr vkeyJSON=$(jq -r ".output.vkey" <<< ${signerJSON} 2> /dev/null) checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - vkeyJSON=$(${cardanocli} key non-extended-key --extended-verification-key-file <(echo "${vkeyJSON}") --verification-key-file /dev/stdout) #convert the extended vkey into a normal one + vkeyJSON=$(${cardanocli} ${cliEra} key non-extended-key --extended-verification-key-file <(echo "${vkeyJSON}") --verification-key-file /dev/stdout) #convert the extended vkey into a normal one checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi vkeyJSON=$(jq ".description = \"Stake Verification Key\"" <<< ${vkeyJSON} 2> /dev/null) checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi @@ -362,7 +362,7 @@ elif [[ "${keyType}" == "MNEMONICS" ]]; then #Payment Keys via Mnemonics (unencr elif [[ "${keyType}" == "ENC" || "${keyType}" == "HYBRIDENC" || "${keyType}" == "HYBRIDMULTIENC" ]]; then #Staking Keys via CLI (encrypted) #Building the StakeAddress Keys from CLI for the normal CLI type or when HYBRID was choosen - skeyJSON=$(${cardanocli} stake-address key-gen --verification-key-file "${addrName}.staking.vkey" --signing-key-file /dev/stdout 2> /dev/null) + skeyJSON=$(${cardanocli} ${cliEra} stake-address key-gen --verification-key-file "${addrName}.staking.vkey" --signing-key-file /dev/stdout 2> /dev/null) checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi file_lock "${addrName}.staking.vkey" @@ -459,7 +459,7 @@ else #Staking Keys via HW-Wallet fi #Building a Payment Address -${cardanocli} address build --payment-verification-key-file "${addrName}.payment.vkey" --staking-verification-key-file "${addrName}.staking.vkey" ${addrformat} > "${addrName}.payment.addr" +${cardanocli} ${cliEra} address build --payment-verification-key-file "${addrName}.payment.vkey" --staking-verification-key-file "${addrName}.staking.vkey" ${addrformat} > "${addrName}.payment.addr" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi file_lock "${addrName}.payment.addr" @@ -469,22 +469,13 @@ echo echo #Building a Staking Address -${cardanocli} stake-address build --staking-verification-key-file "${addrName}.staking.vkey" ${addrformat} > "${addrName}.staking.addr" +${cardanocli} ${cliEra} stake-address build --staking-verification-key-file "${addrName}.staking.vkey" ${addrformat} > "${addrName}.staking.addr" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi file_lock "${addrName}.staking.addr" echo -e "\e[0mStaking(Rewards)-Address built: \e[32m ${addrName}.staking.addr \e[90m" cat "${addrName}.staking.addr" echo - -#create an address registration certificate -${cardanocli} stake-address registration-certificate --staking-verification-key-file "${addrName}.staking.vkey" --out-file "${addrName}.staking.cert" -checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi -file_lock "${addrName}.staking.cert" - -echo -e "\e[0mStaking-Address-Registration-Certificate built: \e[32m ${addrName}.staking.cert \e[90m" -cat "${addrName}.staking.cert" -echo echo echo -e "\e[35mIf you wanna register the Staking-Address, please now run the script 03b_regStakingAddrCert.sh !\e[0m" echo diff --git a/cardano/mainnet/03b_regStakingAddrCert.sh b/cardano/mainnet/03b_regStakingAddrCert.sh index 38ac62db..beaff50a 100755 --- a/cardano/mainnet/03b_regStakingAddrCert.sh +++ b/cardano/mainnet/03b_regStakingAddrCert.sh @@ -52,15 +52,13 @@ fromAddr="$(dirname $2)/$(basename $2 .addr)"; fromAddr=${fromAddr/#.\//}; #Check about required files: Registration Certificate, Signing Key and Address of the payment Account #For StakeKeyRegistration -if [ ! -f "${stakeAddr}.cert" ]; then echo -e "\n\e[35mERROR - \"${stakeAddr}.cert\" Registration Certificate does not exist! Please create it first with script 03a.\e[0m"; exit 2; fi -if [ ! -f "${stakeAddr}.addr" ]; then echo -e "\n\e[35mERROR - \"${stakeAddr}.addr\" Stake Address file does not exist! Please create it first with script 03a.\e[0m"; exit 2; fi +if [ ! -f "${stakeAddr}.addr" ]; then echo -e "\n\e[35mERROR - \"${stakeAddr}.addr\" Stake Address file does not exist! Please create it first with script 03a.\e[0m"; exit 1; fi +if ! [[ -f "${stakeAddr}.skey" || -f "${stakeAddr}.hwsfile" ]]; then echo -e "\n\e[35mERROR - \"${stakeAddr}.skey/hwsfile\" does not exist! Please create it first with script 03a.\n\e[0m"; exit 1; fi #For payment if [ ! -f "${fromAddr}.addr" ]; then echo -e "\n\e[35mERROR - \"${fromAddr}.addr\" does not exist! Please create it first with script 03a or 02.\e[0m"; exit 1; fi if ! [[ -f "${fromAddr}.skey" || -f "${fromAddr}.hwsfile" ]]; then echo -e "\n\e[35mERROR - \"${fromAddr}.skey/hwsfile\" does not exist! Please create it first with script 03a or 02.\e[0m"; exit 1; fi - - #Setting default variables metafileParameter=""; metafile=""; transactionMessage="{}"; enc=""; passphrase="cardano" #Setting defaults @@ -151,47 +149,141 @@ if [[ ! "${transactionMessage}" == "{}" ]]; then fi - - +#---------------------------------------------------- echo -echo -e "\e[0mRegister Staking Address\e[32m ${stakeAddr}.addr\e[0m with funds from Address\e[32m ${fromAddr}.addr\e[0m" +echo -e "\e[0mRegister Stake Address\e[32m ${stakeAddr}.addr\e[0m with funds from Address\e[32m ${fromAddr}.addr\e[0m" echo - - checkAddr=$(cat ${stakeAddr}.addr) typeOfAddr=$(get_addressType "${checkAddr}") #Do a check that the given address is really a Stake Address -if [[ ! ${typeOfAddr} == ${addrTypeStake} ]]; then echo -e "\e[35mERROR: Given Staking Address (${checkAddr}) is not a valid Stake Address !\e[0m\n"; exit 2; fi +if [[ ! ${typeOfAddr} == ${addrTypeStake} ]]; then echo -e "\e[35mERROR: Given Stake Address (${checkAddr}) is not a valid Stake Address !\e[0m\n"; exit 2; fi + -#If in online mode, do a check it the StakeKey is already registered on the chain +#If in online/light mode, do a check if the StakeKey is already registered on the chain if ${onlineMode}; then - echo -e "\e[0mChecking current ChainStatus of Stake-Address: ${checkAddr}" - echo + echo -e "\e[0mChecking current ChainStatus of Stake-Address:\e[32m ${checkAddr}\e[0m" - rewardsAmount=$(${cardanocli} query stake-address-info --address ${checkAddr} ${magicparam} | jq -r "flatten | .[0].rewardAccountBalance") - checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - delegationPoolID=$(${cardanocli} query stake-address-info --address ${checkAddr} ${magicparam} | jq -r "flatten | .[0].delegation") - checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi + #Get rewards state data for the address. When in online mode of course from the node and the chain, in light mode via koios + case ${workMode} in + + "online") showProcessAnimation "Query-StakeAddress-Info: " & + rewardsJSON=$(${cardanocli} ${cliEra} query stake-address-info --address ${checkAddr} 2> /dev/stdout ) + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${rewardsJSON}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + rewardsJSON=$(jq -rc . <<< "${rewardsJSON}") + ;; + + "light") showProcessAnimation "Query-StakeAddress-Info-LightMode: " & + rewardsJSON=$(queryLight_stakeAddressInfo "${checkAddr}") + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${rewardsJSON}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + + esac + + { read rewardsEntryCnt; read delegationPoolID; } <<< $(jq -r 'length, .[0].delegation // .[0].stakeDelegation' <<< ${rewardsJSON}) #Checking about the content - if [[ ${rewardsAmount} == null ]]; then echo -e "\e[0mStaking Address is NOT on the chain, we will continue to register it ...\e[0m\n"; - else echo -e "\e[33mStaking Address is already registered on the chain !\e[0m\n" - #If delegated to a pool, show the current pool ID - if [[ ! ${delegationPoolID} == null ]]; then echo -e "Account is currenty delegated to a Pool with ID: \e[32m${delegationPoolID}\e[0m\n"; fi - exit - fi + if [[ ${rewardsEntryCnt} == 0 ]]; then #not registered yet -fi + echo -e "\e[0mStake Address is NOT on the chain, we will continue to register it ...\e[0m\n"; + else #already registered + + echo -e "\e[33mStake Address is already registered on the chain !\e[0m\n" + + #If delegated to a pool, show the current pool ID + if [[ ! ${delegationPoolID} == null ]]; then + + echo -e "Account is delegated to a Pool with ID: \e[32m${delegationPoolID}\e[0m"; + + if [[ ${onlineMode} == true && ${koiosAPI} != "" ]]; then + + #query poolinfo via poolid on koios + errorcnt=0; error=-1; + showProcessAnimation "Query Pool-Info via Koios: " & + while [[ ${errorcnt} -lt 5 && ${error} -ne 0 ]]; do #try a maximum of 5 times to request the information + error=0 + response=$(curl -sL -m 30 -X POST -w "---spo-scripts---%{http_code}" "${koiosAPI}/pool_info" -H "Accept: application/json" -H "Content-Type: application/json" -d "{\"_pool_bech32_ids\":[\"${delegationPoolID}\"]}" 2> /dev/null) + if [[ $? -ne 0 ]]; then error=1; sleep 1; fi; #if there is an error, wait for a second and repeat + errorcnt=$(( ${errorcnt} + 1 )) + done + stopProcessAnimation; + + #if no error occured, split the response string into JSON content and the HTTP-ResponseCode + if [[ ${error} -eq 0 && "${response}" =~ (.*)---spo-scripts---([0-9]*)* ]]; then + + responseJSON="${BASH_REMATCH[1]}" + responseCode="${BASH_REMATCH[2]}" + + #if the responseCode is 200 (OK) and the received json only contains one entry in the array (will also not be 1 if not a valid json) + if [[ ${responseCode} -eq 200 && $(jq ". | length" 2> /dev/null <<< ${responseJSON}) -eq 1 ]]; then + { read poolNameInfo; read poolTickerInfo; read poolStatusInfo; } <<< $(jq -r ".[0].meta_json.name // \"-\", .[0].meta_json.ticker // \"-\", .[0].pool_status // \"-\"" 2> /dev/null <<< ${responseJSON}) + echo -e " \t\e[0mInformation about the Pool: \e[32m${poolNameInfo} (${poolTickerInfo})\e[0m" + echo -e " \t\e[0m Status: \e[32m${poolStatusInfo}\e[0m" + echo + unset poolNameInfo poolTickerInfo poolStatusInfo + fi #responseCode & jsoncheck + + fi #error & response + unset errorcnt error + + fi #onlineMode & koiosAPI + + else + echo -e "\e[0mAccount is not delegated to a Pool !\n"; + fi + + exit #because already registered + + fi ## ${rewardsEntryCnt} == 0 + +fi ## ${onlineMode} == true + + +#Read ProtocolParameters +case ${workMode} in + "online") protocolParametersJSON=$(${cardanocli} ${cliEra} query protocol-parameters);; #onlinemode + "light") protocolParametersJSON=${lightModeParametersJSON};; #lightmode + "offline") readOfflineFile; #Reads the offlinefile into the offlineJSON variable + protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON});; #offlinemode +esac +checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi + +#Lets use the currently set keyDeposit amount +stakeAddressDepositFee=$(jq -r .stakeAddressDeposit <<< ${protocolParametersJSON}) + +#generate the certificate depending on the era with/without the --key-reg-deposit-amt parameter +case ${cliEra} in + + "babbage"|"alonzo"|"mary"|"allegra"|"shelley") + echo -e "\e[0mGenerate Registration-Certificate in ${cliEra} format ...\e[0m\n" + regCert=$(${cardanocli} ${cliEra} stake-address registration-certificate --stake-address "${checkAddr}" --out-file /dev/stdout 2> /dev/null) + ;; + + *) #conway and later + echo -e "\e[0mGenerate Registration-Certificate with the currently set deposit fee:\e[32m ${stakeAddressDepositFee} lovelaces\e[0m\n" + regCert=$(${cardanocli} ${cliEra} stake-address registration-certificate --stake-address "${checkAddr}" --key-reg-deposit-amt "${stakeAddressDepositFee}" --out-file /dev/stdout 2> /dev/null) + ;; + +esac +checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi +file_unlock "${stakeAddr}.cert" +echo -e "${regCert}" > "${stakeAddr}.cert" 2> /dev/null +if [ $? -ne 0 ]; then echo -e "\n\e[35mERROR - Could not write out the certificate file ${stakeAddr}.cert !\n\e[0m"; exit 1; fi +file_lock "${stakeAddr}.cert" +unset regCert + +echo -e "\e[0mStake Address Registration-Certificate built:\e[32m ${stakeAddr}.cert \e[90m" +cat "${stakeAddr}.cert" + +echo -e "\e[0m" -#get values to register the staking address on the blockchain #get live values -currentTip=$(get_currentTip) -ttl=$(get_currentTTL) +currentTip=$(get_currentTip); checkError "$?"; +ttl=$(( ${currentTip} + ${defTTL} )) echo -e "Current Slot-Height:\e[32m ${currentTip}\e[0m (setting TTL[invalid_hereafter] to ${ttl})" @@ -210,18 +302,31 @@ echo # # Checking UTXO Data of the source address and gathering data about total lovelaces and total assets # - #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in offlinemode from the transferFile - if ${onlineMode}; then - showProcessAnimation "Query-UTXO: " & - utxo=$(${cardanocli} query utxo --address ${sendFromAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + + #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in lightmode via API requests, in offlinemode from the transferFile + case ${workMode} in + "online") #check that the node is fully synced, otherwise the query would mabye return a false state + if [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced or not running, please let your node sync to 100% first !\e[0m\n"; exit 1; fi + showProcessAnimation "Query-UTXO: " & + utxo=$(${cardanocli} ${cliEra} query utxo --address ${sendFromAddr} 2> /dev/stdout); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; showProcessAnimation "Convert-UTXO: " & utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; - #utxoJSON=$(${cardanocli} query utxo --address ${sendFromAddr} ${magicparam} --out-file /dev/stdout); checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; - else - readOfflineFile; #Reads the offlinefile into the offlineJSON variable - utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON}) - if [[ "${utxoJSON}" == null ]]; then echo -e "\e[35mPayment-Address not included in the offline transferFile, please include it first online!\e[0m\n"; exit; fi - fi + ;; + + "light") showProcessAnimation "Query-UTXO-LightMode: " & + utxo=$(queryLight_UTXO "${sendFromAddr}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + showProcessAnimation "Convert-UTXO: " & + utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; + ;; + + "offline") readOfflineFile; #Reads the offlinefile into the offlineJSON variable + utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON} 2> /dev/null) + if [[ "${utxoJSON}" == null ]]; then echo -e "\e[35mPayment-Address not included in the offline transferFile, please include it first online!\e[0m\n"; exit 1; fi + ;; + esac + txcnt=$(jq length <<< ${utxoJSON}) #Get number of UTXO entries (Hash#Idx), this is also the number of --tx-in for the transaction if [[ ${txcnt} == 0 ]]; then echo -e "\e[35mNo funds on the Source Address!\e[0m\n"; exit 1; else echo -e "\e[32m${txcnt} UTXOs\e[0m found on the Source Address!\n"; fi @@ -280,8 +385,20 @@ echo totalAssetsJSON=$( jq ". += {\"${assetHash}${point}${assetName}\":{amount: \"${newValue}\", name: \"${assetTmpName}\", bech: \"${assetBech}\"}}" <<< ${totalAssetsJSON}) if [[ "${assetTmpName:0:1}" == "." ]]; then assetTmpName=${assetTmpName:1}; else assetTmpName="{${assetTmpName}}"; fi - case ${assetHash} in - "${adahandlePolicyID}" ) #$adahandle + case "${assetHash}${assetTmpName:1:8}" in + "${adahandlePolicyID}000de140" ) #$adahandle cip-68 + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Own): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}00000000" ) #$adahandle virtual + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Vir): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}000643b0" ) #$adahandle reference + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Ref): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}"* ) #$adahandle cip-25 echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle: \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" ;; * ) #default @@ -347,38 +464,35 @@ if [[ ! "${transactionMessage}" == "{}" ]]; then echo -e "\e[0mInclude Transaction-Message-Metadata-File:\e[32m ${transactionMessageMetadataFile}\n\e[90m"; cat ${transactionMessageMetadataFile}; echo -e "\e[0m"; fi -#Read ProtocolParameters -if ${onlineMode}; then - protocolParametersJSON=$(${cardanocli} query protocol-parameters ${magicparam} ); #onlinemode - else - protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON}); #offlinemode - fi -checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi -minOutUTXO=$(calc_minOutUTXO "${protocolParametersJSON}" "${sendToAddr}+1000000${assetsOutString}") #---------------------------------------------------- +#get values to register the staking address on the blockchain +minOutUTXO=$(calc_minOutUTXO "${protocolParametersJSON}" "${sendToAddr}+1000000${assetsOutString}") + + #Generate Dummy-TxBody file for fee calculation txBodyFile="${tempDir}/dummy.txbody"; rm ${txBodyFile} 2> /dev/null rm ${txBodyFile} 2> /dev/null -#echo -e "${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --invalid-hereafter ${ttl} --fee 100 --certificate ${stakeAddr}.cert --out-file ${txBodyFile}" -${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --invalid-hereafter ${ttl} --fee 100 ${metafileParameter} --certificate ${stakeAddr}.cert --out-file ${txBodyFile} +#echo -e "${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --invalid-hereafter ${ttl} --fee 100 --certificate ${stakeAddr}.cert --out-file ${txBodyFile}" +${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --invalid-hereafter ${ttl} --fee 100 ${metafileParameter} --certificate ${stakeAddr}.cert --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi -fee=$(${cardanocli} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} ${magicparam} --witness-count 1 --byron-witness-count 0 | awk '{ print $1 }') +fee=$(${cardanocli} ${cliEra} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} --witness-count 2 --byron-witness-count 0 | awk '{ print $1 }') checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "\e[0mMimimum transfer Fee for ${txcnt}x TxIn & ${rxcnt}x TxOut & 1x Certificate: \e[32m $(convertToADA ${fee}) ADA / ${fee} lovelaces \e[90m" -stakeAddressDepositFee=$(jq -r .stakeAddressDeposit <<< ${protocolParametersJSON}) +echo echo -e "\e[0mStake Address Deposit Fee: \e[32m ${stakeAddressDepositFee} lovelaces \e[90m" -minRegistrationFund=$(( ${stakeAddressDepositFee}+${fee} )) + +minRegistrationFund=$(( ${stakeAddressDepositFee}+${fee}+${minOutUTXO} )) echo echo -e "\e[0mMimimum funds required for registration (Sum of fees): \e[32m ${minRegistrationFund} lovelaces \e[90m" echo #calculate new balance for destination address -lovelacesToSend=$(( ${totalLovelaces}-${minRegistrationFund} )) +lovelacesToSend=$(( ${totalLovelaces}-${fee}-${stakeAddressDepositFee} )) echo -e "\e[0mLovelaces that will be returned to payment Address (UTXO-Sum minus fees): \e[32m $(convertToADA ${lovelacesToSend}) ADA / ${lovelacesToSend} lovelaces \e[90m (min. required ${minOutUTXO} lovelaces)" echo @@ -395,7 +509,7 @@ echo #Building unsigned transaction body rm ${txBodyFile} 2> /dev/null -${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --certificate ${stakeAddr}.cert --out-file ${txBodyFile} +${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --certificate ${stakeAddr}.cert --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi dispFile=$(cat ${txBodyFile}); if ${cropTxOutput} && [[ ${#dispFile} -gt 4000 ]]; then echo "${dispFile:0:4000} ... (cropped)"; else echo "${dispFile}"; fi @@ -425,7 +539,7 @@ if [[ -f "${fromAddr}.hwsfile" && -f "${stakeAddr}.hwsfile" && "${paymentName}" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi if [[ "${tmp^^}" =~ (ERROR|DISCONNECT) ]]; then echo -e "\e[35m${tmp}\e[0m\n"; exit 1; else echo -ne "\e[0mWitnessed ... "; fi - ${cardanocli} transaction assemble --tx-body-file ${txBodyFile} --witness-file ${txWitnessFile} --out-file ${txFile} + ${cardanocli} ${cliEra} transaction assemble --tx-body-file ${txBodyFile} --witness-file ${txWitnessFile} --out-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "Assembled ... \e[32mDONE\e[0m\n"; @@ -433,16 +547,18 @@ elif [[ -f "${fromAddr}.skey" ]]; then #with the normal cli skey #read the needed signing keys into ram and sign the transaction - skeyJSON=$(read_skeyFILE "${fromAddr}.skey"); if [ $? -ne 0 ]; then echo -e "\e[35m${skeyJSON}\e[0m\n"; exit 1; else echo -e "\e[32mOK\e[0m\n"; fi + skeyJSON1=$(read_skeyFILE "${fromAddr}.skey"); if [ $? -ne 0 ]; then echo -e "\e[35m${skeyJSON1}\e[0m\n"; exit 1; else echo -e "\e[32mOK\e[0m\n"; fi + skeyJSON2=$(read_skeyFILE "${stakeAddr}.skey"); if [ $? -ne 0 ]; then echo -e "\e[35m${skeyJSON2}\e[0m\n"; exit 1; else echo -e "\e[32mOK\e[0m\n"; fi - echo -e "\e[0mSign the unsigned transaction body with the \e[32m${fromAddr}.skey\e[0m: \e[32m ${txFile}\e[0m" + echo -e "\e[0mSign the unsigned transaction body with the \e[32m${fromAddr}.skey & ${stakeAddr}.skey\e[0m: \e[32m ${txFile}\e[0m" echo - ${cardanocli} transaction sign --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON}") ${magicparam} --out-file ${txFile} + ${cardanocli} ${cliEra} transaction sign --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON1}") --signing-key-file <(echo "${skeyJSON2}") --out-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #forget the signing keys - unset skeyJSON + unset skeyJSON1 + unset skeyJSON2 else echo -e "\e[35mThis combination is not allowed! A Hardware-Wallet can only be used to register its own staking key on the chain.\e[0m\n"; exit 1; @@ -462,20 +578,34 @@ if [[ ${txSize} -le ${maxTxSize} ]]; then echo -e "\e[0mTransaction-Size: ${txSi #If you wanna skip the Prompt, set the environment variable ENV_SKIP_PROMPT to "YES" - be careful!!! #if ask "\e[33mDoes this look good for you, continue ?" N; then if [ "${ENV_SKIP_PROMPT}" == "YES" ] || ask "\n\e[33mDoes this look good for you, continue ?" N; then + + echo - if ${onlineMode}; then #onlinesubmit + case ${workMode} in + "online") + #onlinesubmit echo -ne "\e[0mSubmitting the transaction via the node... " - ${cardanocli} transaction submit --tx-file ${txFile} ${magicparam} + ${cardanocli} ${cliEra} transaction submit --tx-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "\e[32mDONE\n" #Show the TxID - txID=$(${cardanocli} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" + txID=$(${cardanocli} ${cliEra} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; + + "light") + #lightmode submit + showProcessAnimation "Submit-Transaction-LightMode: " & + txID=$(submitLight "${txFile}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${txID}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + echo -e "\e[0mSubmit-Transaction-LightMode: \e[32mDONE\n" + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; - - else #offlinestore + "offline") + #offlinestore txFileJSON=$(cat ${txFile} | jq .) offlineJSON=$( jq ".transactions += [ { date: \"$(date -R)\", type: \"StakeKeyRegistration\", @@ -489,7 +619,6 @@ if [ "${ENV_SKIP_PROMPT}" == "YES" ] || ask "\n\e[33mDoes this look good for you #Write the new offileFile content offlineJSON=$( jq ".history += [ { date: \"$(date -R)\", action: \"signed staking key registration transaction for '${stakeAddr}', payment via '${fromAddr}'\" } ]" <<< ${offlineJSON}) offlineJSON=$( jq ".general += {offlineCLI: \"${versionCLI}\" }" <<< ${offlineJSON}) - offlineJSON=$( jq ".general += {offlineNODE: \"${versionNODE}\" }" <<< ${offlineJSON}) echo "${offlineJSON}" > ${offlineFile} #Readback the tx content and compare it to the current one readback=$(cat ${offlineFile} | jq -r ".transactions[-1].txJSON") @@ -499,8 +628,10 @@ if [ "${ENV_SKIP_PROMPT}" == "YES" ] || ask "\n\e[33mDoes this look good for you else echo -e "\e[35mERROR - Could not verify the written data in the '$(basename ${offlineFile})'. Retry again or generate a new '$(basename ${offlineFile})'.\e[0m\n"; fi + ;; + + esac - fi fi diff --git a/cardano/mainnet/03c_checkStakingAddrOnChain.sh b/cardano/mainnet/03c_checkStakingAddrOnChain.sh index 632c6e69..610b6416 100755 --- a/cardano/mainnet/03c_checkStakingAddrOnChain.sh +++ b/cardano/mainnet/03c_checkStakingAddrOnChain.sh @@ -9,7 +9,7 @@ if [[ $# -eq 1 && ! $1 == "" ]]; then addrName="$(dirname $1)/$(basename $(basename $1 .addr) .staking)"; addrName=${addrName/#.\//}; else echo "ERROR - Usage: $0 "; exit 2; fi #Check can only be done in online mode -if ${offlineMode}; then echo -e "\e[35mYou have to be in ONLINE MODE to do this!\e[0m\n"; exit 1; fi +if ${offlineMode}; then echo -e "\e[35mYou have to be in ONLINE or LIGHT mode to do this!\e[0m\n"; exit 1; fi #Check if Address file doesn not exists, make a dummy one in the temp directory and fill in the given parameter as the hash address if [ ! -f "${addrName}.staking.addr" ]; then echo "$(basename ${addrName})" > ${tempDir}/tempAddr.staking.addr; addrName="${tempDir}/tempAddr"; fi @@ -21,39 +21,84 @@ typeOfAddr=$(get_addressType "${checkAddr}") #What type of Address is it? Stake? if [[ ${typeOfAddr} == ${addrTypeStake} ]]; then #Staking Address - echo -e "\e[0mChecking ChainStatus of Stake-Address-File\e[32m ${addrName}.staking.addr\e[0m: ${checkAddr}" - echo - - rewardsAmount=$(${cardanocli} query stake-address-info --address ${checkAddr} ${magicparam} | jq -r "flatten | .[0].rewardAccountBalance") - checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - delegationPoolID=$(${cardanocli} query stake-address-info --address ${checkAddr} ${magicparam} | jq -r "flatten | .[0].delegation") - checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - - #Checking about the content - if [[ ${rewardsAmount} == null ]]; then echo -e "\e[35mStaking Address is NOT on the chain, register it first !\e[0m\n"; - else echo -e "\e[32mStaking Address is registered on the chain !\e[0m\n" - fi - - #If delegated to a pool, show the current pool ID - if [[ ! ${delegationPoolID} == null ]]; then - echo -e "Account is delegated to a Pool with ID: \e[32m${delegationPoolID}\e[0m\n"; - - #query poolinfo via poolid on koios - showProcessAnimation "Query Pool-Info via Koios: " & - response=$(curl -s -m 10 -X POST "${koiosAPI}/pool_info" -H "Accept: application/json" -H "Content-Type: application/json" -d "{\"_pool_bech32_ids\":[\"${delegationPoolID}\"]}" 2> /dev/null) - stopProcessAnimation; - #check if the received json only contains one entry in the array (will also not be 1 if not a valid json) - if [[ $(jq ". | length" 2> /dev/null <<< ${response}) -eq 1 ]]; then - poolName=$(jq -r ".[0].meta_json.name | select (.!=null)" 2> /dev/null <<< ${response}) - poolTicker=$(jq -r ".[0].meta_json.ticker | select (.!=null)" 2> /dev/null <<< ${response}) - echo -e "\e[0mInformation about the Pool: \e[32m${poolName} (${poolTicker})\e[0m" - echo - fi - - fi + echo -e "\e[0mChecking current ChainStatus of Stake-Address: \e[32m${checkAddr}\e[0m" + echo + + #Get rewards state data for the address. When in online mode of course from the node and the chain, in light mode via koios + case ${workMode} in + + "online") showProcessAnimation "Query-StakeAddress-Info: " & + rewardsJSON=$(${cardanocli} ${cliEra} query stake-address-info --address ${checkAddr} 2> /dev/stdout) + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${rewardsJSON}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + rewardsJSON=$(jq -rc . <<< "${rewardsJSON}") + ;; + + "light") showProcessAnimation "Query-StakeAddress-Info-LightMode: " & + rewardsJSON=$(queryLight_stakeAddressInfo "${checkAddr}") + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${rewardsJSON}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + + esac + + { read rewardsEntryCnt; read delegationPoolID; read keyDepositFee; read rewardsAmount; } <<< $(jq -r "length, .[0].delegation // .[0].stakeDelegation, .[0].delegationDeposit, .[0].rewardAccountBalance" <<< ${rewardsJSON}) + + rewardsEntryCnt=$(jq -r 'length' <<< ${rewardsJSON}) + + #Checking about the content + if [[ ${rewardsEntryCnt} == 0 ]]; then #not registered yet + echo -e "\e[33mStaking Address is NOT on the chain, register it first with script 03b ...\e[0m\n"; + else #already registered + + echo -e "\e[0mStaking Address is \e[32mregistered\e[0m on the chain with a deposit of \e[32m${keyDepositFee}\e[0m lovelaces !\n" + + #If delegated to a pool, show the current pool ID + if [[ ! ${delegationPoolID} == null ]]; then + + echo -e "Account is delegated to a Pool with ID: \e[32m${delegationPoolID}\e[0m"; + + if [[ ${onlineMode} == true && ${koiosAPI} != "" ]]; then + + #query poolinfo via poolid on koios + errorcnt=0; error=-1; + showProcessAnimation "Query Pool-Info via Koios: " & + while [[ ${errorcnt} -lt 5 && ${error} -ne 0 ]]; do #try a maximum of 5 times to request the information + error=0 + response=$(curl -sL -m 30 -X POST -w "---spo-scripts---%{http_code}" "${koiosAPI}/pool_info" -H "Accept: application/json" -H "Content-Type: application/json" -d "{\"_pool_bech32_ids\":[\"${delegationPoolID}\"]}" 2> /dev/null) + if [[ $? -ne 0 ]]; then error=1; sleep 1; fi; #if there is an error, wait for a second and repeat + errorcnt=$(( ${errorcnt} + 1 )) + done + stopProcessAnimation; + + #if no error occured, split the response string into JSON content and the HTTP-ResponseCode + if [[ ${error} -eq 0 && "${response}" =~ (.*)---spo-scripts---([0-9]*)* ]]; then + + responseJSON="${BASH_REMATCH[1]}" + responseCode="${BASH_REMATCH[2]}" + + #if the responseCode is 200 (OK) and the received json only contains one entry in the array (will also not be 1 if not a valid json) + if [[ ${responseCode} -eq 200 && $(jq ". | length" 2> /dev/null <<< ${responseJSON}) -eq 1 ]]; then + { read poolNameInfo; read poolTickerInfo; read poolStatusInfo; } <<< $(jq -r ".[0].meta_json.name // \"-\", .[0].meta_json.ticker // \"-\", .[0].pool_status // \"-\"" 2> /dev/null <<< ${responseJSON}) + echo -e " \t\e[0mInformation about the Pool: \e[32m${poolNameInfo} (${poolTickerInfo})\e[0m" + echo -e " \t\e[0m Status: \e[32m${poolStatusInfo}\e[0m" + echo + unset poolNameInfo poolTickerInfo poolStatusInfo + fi #responseCode & jsoncheck + + fi #error & response + unset errorcnt error + + fi #onlineMode & koiosAPI + + else + echo -e "\e[0mAccount is not delegated to a Pool !\n"; + fi + + exit #because already registered + fi ## ${rewardsEntryCnt} == 0 + else #unsupported address type echo -e "\e[35mAddress type unknown!\e[0m"; -fi +fi ## typeOfAddr diff --git a/cardano/mainnet/04a_genNodeKeys.sh b/cardano/mainnet/04a_genNodeKeys.sh index d5478e0c..68ae06a5 100755 --- a/cardano/mainnet/04a_genNodeKeys.sh +++ b/cardano/mainnet/04a_genNodeKeys.sh @@ -51,7 +51,7 @@ if [[ "${keyType^^}" == "CLI" ]]; then #Building it from the cli (unencrypted) echo -e "\e[0mCreating Node Cold/Offline Keys (CLI)\e[32m ${nodeName}.node.vkey/skey\e[0m and Issue.Counter File\e[32m ${nodeName}.node.counter" echo - ${cardanocli} node key-gen --verification-key-file "${nodeName}.node.vkey" --signing-key-file "${nodeName}.node.skey" --operational-certificate-issue-counter "${nodeName}.node.counter" + ${cardanocli} ${cliEra} node key-gen --verification-key-file "${nodeName}.node.vkey" --signing-key-file "${nodeName}.node.skey" --operational-certificate-issue-counter "${nodeName}.node.counter" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi file_lock ${nodeName}.node.vkey file_lock ${nodeName}.node.skey @@ -69,7 +69,7 @@ if [[ "${keyType^^}" == "CLI" ]]; then #Building it from the cli (unencrypted) elif [[ "${keyType^^}" == "ENC" ]]; then #Building it from the cli (encrypted) - skeyJSON=$(${cardanocli} node key-gen --verification-key-file "${nodeName}.node.vkey" --signing-key-file /dev/stdout --operational-certificate-issue-counter "${nodeName}.node.counter" 2> /dev/null) + skeyJSON=$(${cardanocli} ${cliEra} node key-gen --verification-key-file "${nodeName}.node.vkey" --signing-key-file /dev/stdout --operational-certificate-issue-counter "${nodeName}.node.counter" 2> /dev/null) checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi file_lock "${nodeName}.node.vkey" file_lock "${nodeName}.node.counter" diff --git a/cardano/mainnet/04b_genVRFKeys.sh b/cardano/mainnet/04b_genVRFKeys.sh index 6fee2471..fad4b375 100755 --- a/cardano/mainnet/04b_genVRFKeys.sh +++ b/cardano/mainnet/04b_genVRFKeys.sh @@ -39,7 +39,7 @@ echo if [[ "${keyType^^}" == "CLI" ]]; then #Building it from the cli (unencrypted) - ${cardanocli} node key-gen-VRF --verification-key-file "${nodeName}.vrf.vkey" --signing-key-file "${nodeName}.vrf.skey" + ${cardanocli} ${cliEra} node key-gen-VRF --verification-key-file "${nodeName}.vrf.vkey" --signing-key-file "${nodeName}.vrf.skey" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi file_lock ${nodeName}.vrf.vkey file_lock ${nodeName}.vrf.skey @@ -53,7 +53,7 @@ if [[ "${keyType^^}" == "CLI" ]]; then #Building it from the cli (unencrypted) elif [[ "${keyType^^}" == "ENC" ]]; then #Building it from the cli (encrypted) - skeyJSON=$(${cardanocli} node key-gen-VRF --verification-key-file "${nodeName}.vrf.vkey" --signing-key-file /dev/stdout) + skeyJSON=$(${cardanocli} ${cliEra} node key-gen-VRF --verification-key-file "${nodeName}.vrf.vkey" --signing-key-file /dev/stdout) checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi file_lock ${nodeName}.vrf.vkey diff --git a/cardano/mainnet/04c_genKESKeys.sh b/cardano/mainnet/04c_genKESKeys.sh index 5a6690e2..c971f6e3 100755 --- a/cardano/mainnet/04c_genKESKeys.sh +++ b/cardano/mainnet/04c_genKESKeys.sh @@ -79,7 +79,7 @@ if [ -f "${nodeName}.kes-${nextKESnumber}.skey" ]; then echo -e "\e[35mWARNING - #Build KES Keys unencrypted or encrypted if [[ "${keyType^^}" == "CLI" ]]; then #Building it from the cli (unencrypted) - ${cardanocli} node key-gen-KES --verification-key-file "${nodeName}.kes-${nextKESnumber}.vkey" --signing-key-file "${nodeName}.kes-${nextKESnumber}.skey" + ${cardanocli} ${cliEra} node key-gen-KES --verification-key-file "${nodeName}.kes-${nextKESnumber}.vkey" --signing-key-file "${nodeName}.kes-${nextKESnumber}.skey" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi file_lock "${nodeName}.kes-${nextKESnumber}.vkey" file_lock "${nodeName}.kes-${nextKESnumber}.skey" @@ -91,7 +91,7 @@ if [[ "${keyType^^}" == "CLI" ]]; then #Building it from the cli (unencrypted) elif [[ "${keyType^^}" == "ENC" ]]; then #Building it from the cli (encrypted) - skeyJSON=$(${cardanocli} node key-gen-KES --verification-key-file "${nodeName}.kes-${nextKESnumber}.vkey" --signing-key-file /dev/stdout 2> /dev/null) + skeyJSON=$(${cardanocli} ${cliEra} node key-gen-KES --verification-key-file "${nodeName}.kes-${nextKESnumber}.vkey" --signing-key-file /dev/stdout 2> /dev/null) checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi file_lock ${nodeName}.kes-${nextKESnumber}.vkey diff --git a/cardano/mainnet/04d_genNodeOpCert.sh b/cardano/mainnet/04d_genNodeOpCert.sh index e1d76ad5..ee591583 100755 --- a/cardano/mainnet/04d_genNodeOpCert.sh +++ b/cardano/mainnet/04d_genNodeOpCert.sh @@ -15,8 +15,10 @@ if ${onlineMode}; then fi -#check that *.node.skey/hwsfile is present +#check that *.node.skey/hwsfile is present, we also need the *.node.vkey for the poolID and maybe for an opcert generation if ! [[ -f "${nodeName}.node.skey" || -f "${nodeName}.node.hwsfile" ]]; then echo -e "\e[0mERROR - Cannot find '${nodeName}.node.skey/hwsfile', please generate Node Keys with ${nodeName}.node.counter first with script 04a ...\e[0m"; exit 2; fi +if [ ! -f "${nodeName}.node.vkey" ]; then echo -e "\n\e[35mERROR - Cannot find '${nodeName}.node.vkey', please generate Node Keys first with script 04a ...\e[0m\n"; exit 2; fi + #check that there is a new kes keys present by checking the counters. If counterfiles are present, check that the values are identical if [[ -f "${nodeName}.kes.counter" && -f "${nodeName}.kes.counter-next" ]]; then @@ -29,8 +31,7 @@ fi kesVkeyFile="${nodeName}.kes-${latestKESnumber}.vkey" -if ! [[ -f "${kesVkeyFile}" ]]; then echo -e "\e[0mERROR - Cannot find '${}kesVkeyFile', please generate new KES Keys first using script 04c !\e[0m"; exit 2; fi - +if ! [[ -f "${kesVkeyFile}" ]]; then echo -e "\e[0mERROR - Cannot find '${kesVkeyFile}', please generate new KES Keys first using script 04c !\e[0m"; exit 2; fi loop=0 @@ -42,16 +43,14 @@ skeyJSON="" # while true; do - #check if there was a new given "useOpCertCounter" value if [[ "${useOpCertCounter}" != "" ]]; then if ask "\e[33m${question} '${useOpCertCounter}' as the next one?" Y; then poolNodeCounter=${useOpCertCounter}; #set to the given value - if [ ! -f "${nodeName}.node.vkey" ]; then echo -e "\n\e[35mERROR - Cannot find '${nodeName}.node.vkey', please generate Node Keys first with script 04a ...\e[0m\n"; exit 2; fi file_unlock "${nodeName}.node.counter" - ${cardanocli} node new-counter --cold-verification-key-file ${nodeName}.node.vkey --counter-value ${poolNodeCounter} --operational-certificate-issue-counter-file ${nodeName}.node.counter + ${cardanocli} ${cliEra} node new-counter --cold-verification-key-file ${nodeName}.node.vkey --counter-value ${poolNodeCounter} --operational-certificate-issue-counter-file ${nodeName}.node.counter checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #NodeCounter file was written, now add the description in the file to reflect the next node counter number newCounterJSON=$(jq ".description = \"Next certificate issue number: $((${poolNodeCounter}+0))\"" < "${nodeName}.node.counter") @@ -75,8 +74,7 @@ if [ ! -f "${nodeName}.node.counter" ]; then if ask "\e[33mCannot find '${nodeName}.node.counter', do you wanna create a new one?" N; then poolNodeCounter=0; #set to zero for now - if [ ! -f "${nodeName}.node.vkey" ]; then echo -e "\n\e[35mERROR - Cannot find '${nodeName}.node.vkey', please generate Node Keys first with script 04a ...\e[0m\n"; exit 2; fi - ${cardanocli} node new-counter --cold-verification-key-file ${nodeName}.node.vkey --counter-value ${poolNodeCounter} --operational-certificate-issue-counter-file ${nodeName}.node.counter + ${cardanocli} ${cliEra} node new-counter --cold-verification-key-file ${nodeName}.node.vkey --counter-value ${poolNodeCounter} --operational-certificate-issue-counter-file ${nodeName}.node.counter checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #NodeCounter file was written, now add the description in the file to reflect the next node counter number newCounterJSON=$(jq ".description = \"Next certificate issue number: $((${poolNodeCounter}+0))\"" < "${nodeName}.node.counter") @@ -97,50 +95,29 @@ echo echo -e "\e[0mIssue a new Node operational certificate using KES-vKey \e[32m${kesVkeyFile}\e[0m and Cold-sKey \e[32m${nodeName}.node.skey/hwsfile\e[0m:" echo -#Static -slotLength=$(cat ${genesisfile} | jq -r .slotLength) #In Secs -epochLength=$(cat ${genesisfile} | jq -r .epochLength) #In Secs -slotsPerKESPeriod=$(cat ${genesisfile} | jq -r .slotsPerKESPeriod) #Number -startTimeByron=$(cat ${genesisfile_byron} | jq -r .startTime) #In Secs(abs) -startTimeGenesis=$(cat ${genesisfile} | jq -r .systemStart) #In Text -startTimeSec=$(date --date=${startTimeGenesis} +%s) #In Secs(abs) -transTimeEnd=$(( ${startTimeSec}+(${byronToShelleyEpochs}*${epochLength}) )) #In Secs(abs) End of the TransitionPhase = Start of KES Period 0 -byronSlots=$(( (${startTimeSec}-${startTimeByron}) / 20 )) #NumSlots between ByronChainStart and ShelleyGenesisStart(TransitionStart) -transSlots=$(( (${byronToShelleyEpochs}*${epochLength}) / 20 )) #NumSlots in the TransitionPhase - -#Dynamic -currentTimeSec=$(date -u +%s) #In Secs(abs) - -#Calculate current slot -if [[ "${currentTimeSec}" -lt "${transTimeEnd}" ]]; - then #In Transistion Phase between ShelleyGenesisStart and TransitionEnd - currentSlot=$(( ${byronSlots} + (${currentTimeSec}-${startTimeSec}) / 20 )) - else #After Transition Phase - currentSlot=$(( ${byronSlots} + ${transSlots} + ((${currentTimeSec}-${transTimeEnd}) / ${slotLength}) )) -fi - -#Calculating KES period -currentKESperiod=$(( (${currentSlot}-${byronSlots}) / (${slotsPerKESPeriod}*${slotLength}) )) -if [[ "${currentKESperiod}" -lt 0 ]]; then currentKESperiod=0; fi - -echo -e "\e[0mCurrent KES period:\e[32m ${currentKESperiod}\e[0m" - #Reading kesVkeyFile cborHex to show the Vkey-Bech32-String kesVkeyBech=$(jq -r .cborHex ${kesVkeyFile} 2> /dev/null | tail -c +5 | ${bech32_bin} "kes_vk" 2> /dev/null) echo -e "\e[0mKES-vKey-File Bech:\e[32m ${kesVkeyBech}\e[0m" -#Show PoolID from node.vkey file -if [ -f "${nodeName}.node.vkey" ]; then - poolID=$(${cardanocli} stake-pool id --cold-verification-key-file "${nodeName}.node.vkey" --output-format bech32 2> /dev/null); - echo -e "\e[0mOpcert for Pool-ID:\e[32m ${poolID}\e[0m" -fi - +#PoolID from node.vkey file +poolID=$(${cardanocli} ${cliEra} stake-pool id --cold-verification-key-file "${nodeName}.node.vkey" --output-format bech32 2> /dev/null); +echo -e "\e[0mOpcert for Pool-ID:\e[32m ${poolID}\e[0m" echo +#Calculating KES period +currentSlot=$(get_currentTip); checkError "$?"; + +#Check the presence of the genesisfile (shelley) +if [[ ! -f "${genesisfile}" ]]; then majorError "Path ERROR - Path to the shelley genesis file '${genesisfile}' is wrong or the file is missing!"; exit 1; fi +{ read slotLength; read slotsPerKESPeriod; read maxKESEvolutions; } <<< $(jq -r ".slotLength // \"null\", .slotsPerKESPeriod // \"null\", .maxKESEvolutions // \"null\"" < ${genesisfile} 2> /dev/null) + +currentKESperiod=$(( ${currentSlot} / (${slotsPerKESPeriod}*${slotLength}) )) +if [[ "${currentKESperiod}" -lt 0 ]]; then currentKESperiod=0; fi +echo -e "\e[0mCurrent KES period:\e[32m ${currentKESperiod}\e[0m\n" + #Calculating Expire KES Period and Date/Time -maxKESEvolutions=$(cat ${genesisfile} | jq -r .maxKESEvolutions) +currentTimeSec=$(date -u +%s) expiresKESperiod=$(( ${currentKESperiod} + ${maxKESEvolutions} )) -#expireTimeSec=$(( ${transTimeEnd} + (${slotLength}*${expiresKESperiod}*${slotsPerKESPeriod}) )) expireTimeSec=$(( ${currentTimeSec} + (${slotLength}*${maxKESEvolutions}*${slotsPerKESPeriod}) )) expireDate=$(date --date=@${expireTimeSec}) @@ -148,7 +125,6 @@ file_unlock ${nodeName}.kes-expire.json echo -e "{\n\t\"latestKESfileindex\": \"${latestKESnumber}\",\n\t\"currentKESperiod\": \"${currentKESperiod}\",\n\t\"expireKESperiod\": \"${expiresKESperiod}\",\n\t\"expireKESdate\": \"${expireDate}\"\n}" > ${nodeName}.kes-expire.json file_lock ${nodeName}.kes-expire.json - opcertFile="${nodeName}.node-${latestKESnumber}.opcert" #Generate the opcert from a classic cli node skey or from a hwsfile (hw-wallet) @@ -162,7 +138,7 @@ if [ -f "${nodeName}.node.skey" ]; then #key is a normal one echo -ne "\e[0mGenerating a new opcert from a cli signing key '\e[33m${nodeName}.node.skey\e[0m' ... " file_unlock ${opcertFile} file_unlock ${nodeName}.node.counter - ${cardanocli} node issue-op-cert --hot-kes-verification-key-file ${kesVkeyFile} --cold-signing-key-file <(echo "${skeyJSON}") --operational-certificate-issue-counter-file ${nodeName}.node.counter --kes-period ${currentKESperiod} --out-file ${opcertFile} + ${cardanocli} ${cliEra} node issue-op-cert --hot-kes-verification-key-file ${kesVkeyFile} --cold-signing-key-file <(echo "${skeyJSON}") --operational-certificate-issue-counter-file ${nodeName}.node.counter --kes-period ${currentKESperiod} --out-file ${opcertFile} checkError "$?"; if [ $? -ne 0 ]; then file_lock ${opcertFile}; file_lock ${nodeName}.node.counter; exit $?; fi file_lock ${opcertFile} file_lock ${nodeName}.node.counter @@ -187,31 +163,79 @@ echo -e "\e[32mOK\e[0m\n" #in onlineMode, check the opcert file against the current chain status to use the right OpCertCounter value if ${onlineMode}; then -echo -ne "\e[0mChecking operational certificate \e[32m${opcertFile}\e[0m for the right OpCertCounter ... " - #query the current opcertstate from the chain - queryFile="${tempDir}/opcert.query" - rm ${queryFile} 2> /dev/null - tmp=$(${cardanocli} query kes-period-info ${magicparam} --op-cert-file ${opcertFile} --out-file ${queryFile} 2> /dev/null); - if [ $? -ne 0 ]; then echo -e "\n\n\e[35mError - Couldn't query the onChain OpCertCounter state !\e[0m"; echo; exit 2; fi + case ${workMode} in + + "online") + echo -e "\e[0mChecking operational certificate \e[32m${opcertFile}\e[0m for the right OpCertCounter:" + echo + + #check that the node is fully synced, otherwise the opcertcounter query could return a false state + if [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced !\e[0m\n"; exit 2; fi - onChainOpcertCount=$(jq -r ".qKesNodeStateOperationalCertificateNumber | select (.!=null)" 2> /dev/null ${queryFile}); if [[ ${onChainOpcertCount} == "" ]]; then onChainOpcertCount=-1; fi #if there is none, set it to -1 - onDiskOpcertCount=$(jq -r ".qKesOnDiskOperationalCertificateNumber | select (.!=null)" 2> /dev/null ${queryFile}); - rm ${queryFile} 2> /dev/null + #query the current opcertstate from the local node + queryFile="${tempDir}/opcert.query" + rm ${queryFile} 2> /dev/null + tmp=$(${cardanocli} ${cliEra} query kes-period-info --op-cert-file ${opcertFile} --out-file ${queryFile} 2> /dev/stdout); + if [ $? -ne 0 ]; then echo -e "\n\n\e[35mError - Couldn't query the onChain OpCertCounter state !\n${tmp}\e[0m"; echo; exit 2; fi + + onChainOpcertCount=$(jq -r ".qKesNodeStateOperationalCertificateNumber | select (.!=null)" 2> /dev/null ${queryFile}); if [[ ${onChainOpcertCount} == "" ]]; then onChainOpcertCount=-1; fi #if there is none, set it to -1 + onDiskOpcertCount=$(jq -r ".qKesOnDiskOperationalCertificateNumber | select (.!=null)" 2> /dev/null ${queryFile}); + rm ${queryFile} 2> /dev/null + + echo -e "\e[0mThe last known OpCertCounter on the chain is: \e[32m${onChainOpcertCount//-1/not used yet}\e[0m" + ;; + + "light") + #query the current opcertstate via online api + echo -e "\e[0mChecking the OpCertCounter for the Pool-ID \e[32m${poolID}\e[0m via ${koiosAPI}:" + echo + #query poolinfo via poolid on koios + showProcessAnimation "Query Pool-Info via Koios: " & + response=$(curl -sL -m 30 -X POST "${koiosAPI}/pool_info" -H "Accept: application/json" -H "Content-Type: application/json" -d "{\"_pool_bech32_ids\":[\"${poolID}\"]}" 2> /dev/null) + stopProcessAnimation; + tmp=$(jq -r . <<< ${response}); if [ $? -ne 0 ]; then echo -e "\n\n\e[35mError - Koios API request sent not back a valid JSON !\e[0m"; echo; exit 2; fi + #check if the received json only contains one entry in the array (will also not be 1 if not a valid json) + if [[ $(jq ". | length" 2> /dev/null <<< ${response}) -eq 1 ]]; then + onChainOpcertCount=$(jq -r ".[0].op_cert_counter | select (.!=null)" 2> /dev/null <<< ${response}) + poolName=$(jq -r ".[0].meta_json.name | select (.!=null)" 2> /dev/null <<< ${response}) + poolTicker=$(jq -r ".[0].meta_json.ticker | select (.!=null)" 2> /dev/null <<< ${response}) + echo -e "\e[0mGot the information back for the Pool: \e[32m${poolName} (${poolTicker})\e[0m" + echo + echo -e "\e[0mThe last known OpCertCounter on the chain is: \e[32m${onChainOpcertCount}\e[0m" + else + echo -e "\e[0mThere is no information available from the chain about the OpCertCounter. Looks like the pool has not made a block yet.\nSo we are going with a next counter of \e[33m0\e[0m" + onChainOpcertCount=-1 #if there is none, set it to -1 + fi + + #lets read out the onDiscOpcertNumber directly from the opcert file + cborHex=$(jq -r ".cborHex" "${opcertFile}" 2> /dev/null); + if [ $? -ne 0 ]; then echo -e "\n\n\e[35mError - Couldn't read the opcert file '${opcertFile}' !\e[0m"; echo; exit 2; fi + onDiskOpcertCount=$(int_from_cbor "${cborHex:72}") #opcert counter starts at index 72, lets decode the unsigned integer number + if [ $? -ne 0 ]; then echo -e "\n\n\e[35mError - Couldn't decode opcert counter from file '${opcertFile}' !\e[0m"; echo; exit 2; fi +# onDiskKESStart=$(int_from_cbor "${cborHex:72}" 1) #kes start counter is the next number after the opcert number, so lets skip 1 number +# echo -e "\e[0m File KES start Period: \e[35m${onDiskKESStart}\e[0m" + ;; + + + *) exit;; + + esac nextChainOpcertCount=$(( ${onChainOpcertCount} + 1 )); #the next opcert counter that should be used on the chain is the last seen one + 1 + echo + if [[ ${nextChainOpcertCount} -eq ${onDiskOpcertCount} ]]; then - echo -e "\e[32mOK\e[0m\n"; + echo -e "\e[0mCheck: \e[32mOK\e[0m\n"; echo -e "\e[0mLatest OnChain Counter: \e[32m${onChainOpcertCount//-1/not used yet}\e[0m" echo -e "\e[0mNext Counter should be: \e[32m${nextChainOpcertCount}\e[0m" echo -e "\e[0m OnDisk Counter is: \e[32m${onDiskOpcertCount}\e[0m" echo break; #exit the while loop - - else - echo -e "\e[35mFALSE\e[0m\n"; + else + echo -e "\e[0mCheck: \e[35mFALSE\e[0m\n"; echo -e "\e[0mLatest OnChain Counter: \e[32m${onChainOpcertCount//-1/not used yet}\e[0m" echo -e "\e[0mNext Counter should be: \e[32m${nextChainOpcertCount}\e[0m" echo -e "\e[0m OnDisk Counter Is: \e[35m${onDiskOpcertCount}\e[0m" diff --git a/cardano/mainnet/04e_checkNodeOpCert.sh b/cardano/mainnet/04e_checkNodeOpCert.sh index 289054b9..72273cc5 100755 --- a/cardano/mainnet/04e_checkNodeOpCert.sh +++ b/cardano/mainnet/04e_checkNodeOpCert.sh @@ -137,48 +137,94 @@ fi if [[ "${checkSource}" == "localFile" ]]; then +#Check agains chaindata not possible in offline mode +if ${offlineMode}; then echo -e "\e[35mYou have to be in ONLINE or LIGHT mode to run this script for a check against the chain-data!\e[0m\n"; exit 1; fi + #Node must be fully synced for the online query of the OpCertCounter, show info if starting in offline mode -if ${onlineMode}; then +if ${fullMode}; then #check that the node is fully synced, otherwise the opcertcounter query could return a false state if [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced !\e[0m\n"; exit 2; fi -else -#Check can only be done in online mode - echo -e "\e[35mYou have to be in ONLINE MODE to do this!\e[0m\n"; exit 1; fi echo -e "\e[0mChecking OpCertFile \e[32m${opCertFile}\e[0m for the correct OpCertCounter and KES-Interval:" echo -#Dynamic -currentTimeSec=$(date -u +%s) #In Secs(abs) -currentSlot=$(get_currentTip) -currentEPOCH=$(get_currentEpoch) -maxKESEvolutions=$(cat ${genesisfile} | jq -r .maxKESEvolutions) +#Dynamic + Static +currentSlot=$(get_currentTip); checkError "$?"; +currentEPOCH=$(get_currentEpoch); checkError "$?"; -#Static -slotLength=$(cat ${genesisfile} | jq -r .slotLength) #In Secs -slotsPerKESPeriod=$(cat ${genesisfile} | jq -r .slotsPerKESPeriod) #Number +#Check presence of the genesisfile (shelley) +if [[ ! -f "${genesisfile}" ]]; then majorError "Path ERROR - Path to the shelley genesis file '${genesisfile}' is wrong or the file is missing!"; exit 1; fi +{ read slotLength; read slotsPerKESPeriod; read maxKESEvolutions; } <<< $(jq -r ".slotLength // \"null\", .slotsPerKESPeriod // \"null\", .maxKESEvolutions // \"null\"" < ${genesisfile} 2> /dev/null) #Calculating KES period currentKESperiod=$(( ${currentSlot} / (${slotsPerKESPeriod}*${slotLength}) )) if [[ "${currentKESperiod}" -lt 0 ]]; then currentKESperiod=0; fi -echo -e "\e[0mCurrent EPOCH:\e[32m ${currentEPOCH}\e[0m" -echo - -#query the current opcertstate from the chain -queryFile="${tempDir}/${nodeName}.query" -rm ${queryFile} 2> /dev/null +case ${workMode} in + + "online") + echo -e "\e[0mChecking operational certificate \e[32m${opCertFile}\e[0m for the right OpCertCounter:" + echo + + #check that the node is fully synced, otherwise the opcertcounter query could return a false state + if [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced !\e[0m\n"; exit 2; fi + + #query the current opcertstate from the local node + queryFile="${tempDir}/opcert.query" + rm ${queryFile} 2> /dev/null + tmp=$(${cardanocli} ${cliEra} query kes-period-info --op-cert-file ${opCertFile} --out-file ${queryFile} 2> /dev/stdout); + if [ $? -ne 0 ]; then echo -e "\n\n\e[35mError - Couldn't query the onChain OpCertCounter state !\n${tmp}\e[0m"; echo; exit 2; fi + + onChainOpcertCount=$(jq -r ".qKesNodeStateOperationalCertificateNumber | select (.!=null)" 2> /dev/null ${queryFile}); if [[ ${onChainOpcertCount} == "" ]]; then onChainOpcertCount=-1; fi #if there is none, set it to -1 + onDiskOpcertCount=$(jq -r ".qKesOnDiskOperationalCertificateNumber | select (.!=null)" 2> /dev/null ${queryFile}); + onDiskKESStart=$(jq -r ".qKesStartKesInterval | select (.!=null)" 2> /dev/null ${queryFile}); + rm ${queryFile} 2> /dev/null + + echo -e "\e[0mThe last known OpCertCounter on the chain is: \e[32m${onChainOpcertCount//-1/not used yet}\e[0m" + ;; + + "light") + #query the current opcertstate via online api + + #lets read out the onDiscOpcertNumber directly from the opcert file + cborHex=$(jq -r ".cborHex" "${opCertFile}" 2> /dev/null); + if [ $? -ne 0 ]; then echo -e "\n\n\e[35mError - Couldn't read the opcert file '${opCertFile}' !\e[0m"; echo; exit 2; fi + onDiskOpcertCount=$(int_from_cbor "${cborHex:72}") #opcert counter starts at index 72, lets decode the unsigned integer number + if [ $? -ne 0 ]; then echo -e "\n\n\e[35mError - Couldn't decode opcert counter from file '${opCertFile}' !\e[0m"; echo; exit 2; fi + onDiskKESStart=$(int_from_cbor "${cborHex:72}" 1) #kes start counter is the next number after the opcert number, so lets skip 1 number + #get the pool id from the node vkey information within the opcert file + poolID=$(xxd -r -ps <<< ${cborHex: -64} | b2sum -l 224 -b | cut -d' ' -f 1 | ${bech32_bin} "pool") + + echo -e "\e[0mChecking the OpCertCounter for the Pool-ID \e[32m${poolID}\e[0m via ${koiosAPI}:" + echo + #query poolinfo via poolid on koios + showProcessAnimation "Query Pool-Info via Koios: " & + response=$(curl -sL -m 30 -X POST "${koiosAPI}/pool_info" -H "Accept: application/json" -H "Content-Type: application/json" -d "{\"_pool_bech32_ids\":[\"${poolID}\"]}" 2> /dev/null) + stopProcessAnimation; + tmp=$(jq -r . <<< ${response}); if [ $? -ne 0 ]; then echo -e "\n\n\e[35mError - Koios API request sent not back a valid JSON !\e[0m"; echo; exit 2; fi + #check if the received json only contains one entry in the array (will also not be 1 if not a valid json) + if [[ $(jq ". | length" 2> /dev/null <<< ${response}) -eq 1 ]]; then + onChainOpcertCount=$(jq -r ".[0].op_cert_counter | select (.!=null)" 2> /dev/null <<< ${response}) + poolName=$(jq -r ".[0].meta_json.name | select (.!=null)" 2> /dev/null <<< ${response}) + poolTicker=$(jq -r ".[0].meta_json.ticker | select (.!=null)" 2> /dev/null <<< ${response}) + echo -e "\e[0mGot the information back for the Pool: \e[32m${poolName} (${poolTicker})\e[0m" + echo + echo -e "\e[0mThe last known OpCertCounter on the chain is: \e[32m${onChainOpcertCount}\e[0m" + else + echo -e "\e[0mThere is no information available from the chain about the OpCertCounter. Looks like the pool has not made a block yet.\nSo we are going with a next counter of \e[33m0\e[0m" + onChainOpcertCount=-1 #if there is none, set it to -1 + fi + + ;; + + *) exit;; + + esac -showProcessAnimation "Query operational certificate for the right values: " & -tmp=$(${cardanocli} query kes-period-info ${magicparam} --op-cert-file ${opCertFile} --out-file ${queryFile} 2> /dev/null); -stopProcessAnimation; -if [ $? -ne 0 ]; then echo -e "\n\n\e[35mError - Couldn't query the onChain OpCertCounter state !\e[0m"; echo; exit 2; fi -onChainOpcertCount=$(jq -r ".qKesNodeStateOperationalCertificateNumber | select (.!=null)" 2> /dev/null ${queryFile}); if [[ ${onChainOpcertCount} == "" ]]; then onChainOpcertCount=-1; fi #if there is none, set it to -1 -onDiskOpcertCount=$(jq -r ".qKesOnDiskOperationalCertificateNumber | select (.!=null)" 2> /dev/null ${queryFile}); -onDiskKESStart=$(jq -r ".qKesStartKesInterval | select (.!=null)" 2> /dev/null ${queryFile}); -rm ${queryFile} 2> /dev/null +echo +echo -e "\e[0mCurrent EPOCH:\e[32m ${currentEPOCH}\e[0m" echo #Verifying right KES Interval @@ -294,15 +340,15 @@ fi ##### Checking against a local OpCert File #### if [[ "${checkSource}" == "poolID" ]]; then -#Only possible in onlineMode -> KOIOS request -if ${offlineMode}; then echo -e "\e[35mYou have to be in ONLINE MODE to do this!\e[0m\n"; exit 1; fi +#Check agains chaindata not possible in offline mode +if ${offlineMode}; then echo -e "\e[35mYou have to be in ONLINE or LIGHT mode to run this script for a check against the chain-data!\e[0m\n"; exit 1; fi echo -e "\e[0mChecking the OpCertCounter for the Pool-ID \e[32m${poolID}\e[0m via ${koiosAPI}:" echo #query poolinfo via poolid on koios showProcessAnimation "Query Pool-Info via Koios: " & -response=$(curl -s -m 10 -X POST "${koiosAPI}/pool_info" -H "Accept: application/json" -H "Content-Type: application/json" -d "{\"_pool_bech32_ids\":[\"${poolID}\"]}" 2> /dev/null) +response=$(curl -sL -m 30 -X POST "${koiosAPI}/pool_info" -H "Accept: application/json" -H "Content-Type: application/json" -d "{\"_pool_bech32_ids\":[\"${poolID}\"]}" 2> /dev/null) stopProcessAnimation; #check if the received json only contains one entry in the array (will also not be 1 if not a valid json) if [[ $(jq ". | length" 2> /dev/null <<< ${response}) -ne 1 ]]; then echo -e "\n\e[35mCould not query the information via Koios, maybe pool not registered yet.\n\nResponse was: ${response}\n\e[0m"; exit 1; fi diff --git a/cardano/mainnet/05a_genStakepoolCert.sh b/cardano/mainnet/05a_genStakepoolCert.sh index 3c3a6120..f437a041 100755 --- a/cardano/mainnet/05a_genStakepoolCert.sh +++ b/cardano/mainnet/05a_genStakepoolCert.sh @@ -42,7 +42,7 @@ echo " } " > ${poolFile}.pool.json echo -echo -e "\e[0mStakepool Info JSON:\e[32m ${poolFile}.pool.json \e[90m" +echo -e "\e[0mStakepool Config JSON:\e[32m ${poolFile}.pool.json \e[90m" cat ${poolFile}.pool.json echo echo -e "\e[0m" @@ -70,13 +70,17 @@ poolMargin=$(readJSONparam "poolMargin"); if [[ ! $? == 0 ]]; then exit 1; fi #Check if the poolFile entry is the same as the calling one if [[ ! "${poolName}" == "${poolFile}" ]]; then echo -e "\n\e[35mERROR - The entry for the 'poolName' in your ${poolFile}.pool.json is '${poolName}' and does not match the current path '${poolFile}'. Do you have imported it?\e[0m\n"; exit 1; fi +#Check needed inputfiles +if [ ! -f "${poolName}.node.vkey" ]; then echo -e "\e[33mERROR - ${poolName}.node.vkey is missing! Check poolName field in ${poolFile}.pool.json about the right path, or generate it with script 04a !\e[0m"; exit 1; fi +if [ ! -f "${poolName}.vrf.vkey" ]; then echo -e "\e[33mERROR - ${poolName}.vrf.vkey is missing! Check poolName field in ${poolFile}.pool.json about the right path, or generate it with script 04b !\e[0m"; exit 1; fi +if [ ! -f "${rewardsName}.staking.vkey" ]; then echo -e "\e[33mERROR - ${rewardsName}.staking.vkey is missing! Check poolRewards field in ${poolFile}.pool.json, or generate one with script 03a !\e[0m"; exit 1; fi + #Read ProtocolParameters -if ${onlineMode}; then - protocolParametersJSON=$(${cardanocli} query protocol-parameters ${magicparam} ); #onlinemode - else - readOfflineFile; - protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON}); #offlinemode - fi +case ${workMode} in + "online") protocolParametersJSON=$(${cardanocli} ${cliEra} query protocol-parameters);; #onlinemode + "light") protocolParametersJSON=${lightModeParametersJSON};; #lightmode + "offline") readOfflineFile; protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON});; #offlinemode +esac checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #Check poolCost Setting @@ -97,6 +101,13 @@ if [[ ${poolCost} -lt ${minPoolCost} ]]; then #If poolCost is set to low, than a fi fi +#Check poolMargin Setting - bc will only return a 1 if valid, if invalid like chars it will not return a 1 +if [[ $(bc <<< "${poolMargin} >= 0.00 && ${poolMargin} <= 1.00" 2> /dev/null) -ne 1 ]]; then + echo -e "\e[33mERROR - Parameter \"poolMargin\": The current value of '${poolMargin}' is not in the range 0.00 - 1.00 (0-100%). Please re-edit your ${poolFile}.pool.json file !\n\e[0m"; exit 1; +fi +poolMarginPct=$(bc <<< "${poolMargin} * 100" 2> /dev/null) + + #Check PoolRelay Entries tmp=$(readJSONparam "poolRelays"); if [[ ! $? == 0 ]]; then exit 1; fi poolRelayCnt=$(jq -r '.poolRelays | length' ${poolFile}.pool.json) @@ -170,7 +181,7 @@ if [[ ${#poolMetaDescription} -gt 255 ]]; then echo -e "\e[35mERROR - The poolMe #Read out the POOL-ID and store it in the ${poolName}.pool.json -poolID=$(${cardanocli} stake-pool id --cold-verification-key-file ${poolName}.node.vkey --output-format hex) #New method since 1.23.0 +poolID=$(${cardanocli} ${cliEra} stake-pool id --cold-verification-key-file ${poolName}.node.vkey --output-format hex) #New method since 1.23.0 checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi file_unlock ${poolFile}.pool.json newJSON=$(cat ${poolFile}.pool.json | jq ". += {poolID: \"${poolID}\"}") @@ -182,7 +193,7 @@ file_unlock ${poolFile}.pool.id echo "${poolID}" > ${poolFile}.pool.id file_lock ${poolFile}.pool.id -poolIDbech=$(${cardanocli} stake-pool id --cold-verification-key-file ${poolName}.node.vkey) #New method since 1.23.0 +poolIDbech=$(${cardanocli} ${cliEra} stake-pool id --cold-verification-key-file ${poolName}.node.vkey) #New method since 1.23.0 checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #Save out the POOL-ID also in the xxx.id-bech file file_unlock ${poolFile}.pool.id-bech @@ -308,7 +319,7 @@ if [[ ${metaFileSize} -gt 512 ]]; then echo -e "\e[35mERROR - The total filesize #Generate HASH for the .metadata.json -poolMetaHash=$(${cardanocli} stake-pool metadata-hash --pool-metadata-file ${poolFile}.metadata.json) +poolMetaHash=$(${cardanocli} ${cliEra} stake-pool metadata-hash --pool-metadata-file ${poolFile}.metadata.json) checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #Add the HASH to the .pool.json info file @@ -333,11 +344,6 @@ fi ownerKeys="" #building string for the certificate -#Check needed inputfiles -if [ ! -f "${poolName}.node.vkey" ]; then echo -e "\e[0mERROR - ${poolName}.node.vkey is missing! Check poolName field in ${poolFile}.pool.json about the right path, or generate it with script 04a !\e[0m"; exit 1; fi -if [ ! -f "${poolName}.vrf.vkey" ]; then echo -e "\e[0mERROR - ${poolName}.vrf.vkey is missing! Check poolName field in ${poolFile}.pool.json about the right path, or generate it with script 04b !\e[0m"; exit 1; fi -if [ ! -f "${rewardsName}.staking.vkey" ]; then echo -e "\e[0mERROR - ${rewardsName}.staking.vkey is missing! Check poolRewards field in ${poolFile}.pool.json, or generate one with script 03a !\e[0m"; exit 1; fi - rewardsAccountIncluded="no" for (( tmpCnt=0; tmpCnt<${ownerCnt}; tmpCnt++ )) @@ -379,15 +385,15 @@ do done echo -ne "\e[0m Rewards Stake:\e[32m ${rewardsName}.staking.vkey \e[0m" if [[ "$(jq -r .description < ${rewardsName}.staking.vkey)" == *"Hardware"* ]]; then echo -e "(Hardware-Key)"; else echo; fi -echo -e "\e[0m Pledge:\e[32m ${poolPledge} \e[90mlovelaces" -echo -e "\e[0m Cost:\e[32m ${poolCost} \e[90mlovelaces" -echo -e "\e[0m Margin:\e[32m ${poolMargin} \e[0m" +echo -e "\e[0m Pledge:\e[32m ${poolPledge} \e[90mlovelaces \e[0m(\e[32m$(convertToADA ${poolPledge}) \e[90mADA\e[0m)" +echo -e "\e[0m Cost:\e[32m ${poolCost} \e[90mlovelaces \e[0m(\e[32m$(convertToADA ${poolCost}) \e[90mADA\e[0m)" +echo -e "\e[0m Margin:\e[32m ${poolMargin} \e[0m(\e[32m${poolMarginPct}%\e[0m)" echo # Create a stake pool registration certificate file_unlock ${poolName}.pool.cert -${cardanocli} stake-pool registration-certificate --cold-verification-key-file ${poolName}.node.vkey --vrf-verification-key-file ${poolName}.vrf.vkey --pool-pledge ${poolPledge} --pool-cost ${poolCost} --pool-margin ${poolMargin} --pool-reward-account-verification-key-file ${rewardsName}.staking.vkey ${ownerKeys} ${poolRelays} --metadata-url ${poolMetaUrl} --metadata-hash ${poolMetaHash} ${magicparam} --out-file ${poolName}.pool.cert +${cardanocli} ${cliEra} stake-pool registration-certificate --cold-verification-key-file ${poolName}.node.vkey --vrf-verification-key-file ${poolName}.vrf.vkey --pool-pledge ${poolPledge} --pool-cost ${poolCost} --pool-margin ${poolMargin} --pool-reward-account-verification-key-file ${rewardsName}.staking.vkey ${ownerKeys} ${poolRelays} --metadata-url ${poolMetaUrl} --metadata-hash ${poolMetaHash} --out-file ${poolName}.pool.cert checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #No error, so lets update the pool JSON file with the date and file the certFile was created @@ -416,7 +422,7 @@ cat ${poolName}.pool.cert echo echo -echo -e "\e[0mStakepool Info JSON:\e[32m ${poolFile}.pool.json \e[90m" +echo -e "\e[0mStakepool Config JSON:\e[32m ${poolFile}.pool.json \e[90m" cat ${poolFile}.pool.json echo diff --git a/cardano/mainnet/05b_genDelegationCert.sh b/cardano/mainnet/05b_genDelegationCert.sh index cf120d61..a60059c5 100755 --- a/cardano/mainnet/05b_genDelegationCert.sh +++ b/cardano/mainnet/05b_genDelegationCert.sh @@ -24,7 +24,7 @@ if [[ "${toPoolID//[![:xdigit:]]}" == "${toPoolID}" && ${#toPoolID} -eq 56 ]]; t echo -e "\e[0mCreate a delegation registration certificate for Delegator\e[32m ${delegateStakeAddr}.staking.vkey\e[0m \nto the Pool with Hex-ID\e[32m ${toPoolID}\e[90m:" echo file_unlock ${delegateStakeAddr}.deleg.cert - ${cardanocli} stake-address delegation-certificate --stake-verification-key-file ${delegateStakeAddr}.staking.vkey --stake-pool-id ${toPoolID} --out-file ${delegateStakeAddr}.deleg.cert + ${cardanocli} ${cliEra} stake-address stake-delegation-certificate --stake-verification-key-file ${delegateStakeAddr}.staking.vkey --stake-pool-id ${toPoolID} --out-file ${delegateStakeAddr}.deleg.cert checkError "$?"; if [ $? -ne 0 ]; then file_lock ${delegateStakeAddr}.deleg.cert; exit $?; fi file_lock ${delegateStakeAddr}.deleg.cert @@ -38,7 +38,7 @@ elif [[ "${toPoolID:0:5}" == "pool1" && ${#toPoolID} -eq 56 ]]; then #parameter echo -e "\e[0mCreate a delegation registration certificate for Delegator\e[32m ${delegateStakeAddr}.staking.vkey\e[0m \nto the Pool with Bech32-ID\e[32m ${toPoolID}\e[90m:" echo file_unlock ${delegateStakeAddr}.deleg.cert - ${cardanocli} stake-address delegation-certificate --stake-verification-key-file ${delegateStakeAddr}.staking.vkey --stake-pool-id ${toPoolID} --out-file ${delegateStakeAddr}.deleg.cert + ${cardanocli} ${cliEra} stake-address stake-delegation-certificate --stake-verification-key-file ${delegateStakeAddr}.staking.vkey --stake-pool-id ${toPoolID} --out-file ${delegateStakeAddr}.deleg.cert checkError "$?"; if [ $? -ne 0 ]; then file_lock ${delegateStakeAddr}.deleg.cert; exit $?; fi file_lock ${delegateStakeAddr}.deleg.cert @@ -47,7 +47,7 @@ elif [ -f "${toPoolNodeName}.node.vkey" ]; then #parameter is a pool verificatio echo -e "\e[0mCreate a delegation registration certificate for Delegator\e[32m ${delegateStakeAddr}.staking.vkey\e[0m \nto the Pool with the Key-File\e[32m ${toPoolNodeName}.node.vkey\e[90m:" echo file_unlock ${delegateStakeAddr}.deleg.cert - ${cardanocli} stake-address delegation-certificate --stake-verification-key-file ${delegateStakeAddr}.staking.vkey --cold-verification-key-file ${toPoolNodeName}.node.vkey --out-file ${delegateStakeAddr}.deleg.cert + ${cardanocli} ${cliEra} stake-address stake-delegation-certificate --stake-verification-key-file ${delegateStakeAddr}.staking.vkey --cold-verification-key-file ${toPoolNodeName}.node.vkey --out-file ${delegateStakeAddr}.deleg.cert checkError "$?"; if [ $? -ne 0 ]; then file_lock ${delegateStakeAddr}.deleg.cert; exit $?; fi file_lock ${delegateStakeAddr}.deleg.cert diff --git a/cardano/mainnet/05c_regStakepoolCert.sh b/cardano/mainnet/05c_regStakepoolCert.sh index b1568482..6fa39c9d 100755 --- a/cardano/mainnet/05c_regStakepoolCert.sh +++ b/cardano/mainnet/05c_regStakepoolCert.sh @@ -5,8 +5,6 @@ #load variables and functions from common.sh . "$(dirname "$0")"/00_common.sh - - #Check command line parameter if [ $# -lt 2 ]; then cat >&2 < /dev/null); if [[ ! "${deregSubmitted}" == null ]]; then echo -e "\n\e[35mERROR - I'am confused, the pool was registered and retired before. Please specify if you wanna register or reregister the pool now with the optional parameter "type:REG" or "type:REREG" !\e[0m\n"; exit 1; fi #In Online-Mode check if the Pool is already registered on the chain, if so print an info that the method was forced to a REREG if ${onlineMode}; then - #check that the node is fully synced, otherwise the opcertcounter query could return a false state - if [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced, please let your node sync to 100% first !\e[0m\n"; exit 2; fi - - #check if the poolIDbech is already on the chain - poolsInLedger=$(${cardanocli} query stake-pools ${magicparam} 2> /dev/null); checkError "$?"; if [ $? -ne 0 ]; then echo -e "\n\e[35mERROR - Could not query if Pool-ID is already on the chain.\e[0m\n"; exit 1; fi - poolInLedgerCnt=$(grep "${poolIDbech}" <<< ${poolsInLedger} | wc -l) - if [[ ${poolInLedgerCnt} -eq 1 ]]; then echo -e "Pool-ID is already on the chain, continue with a Re-Registration\e[0m\n"; regSubmitted="xxx"; - elif [[ ${poolInLedgerCnt} -eq 0 ]]; then echo -e "Pool-ID is not on the chain yet, continue with a normal Registration\e[0m\n"; regSubmitted=""; - else echo -e "\e[35mERROR - The Pool-ID is more than once in the ledgers stake-pool list, this shouldn't be possible!\e[0m\n"; exit 2; - fi - fi + + case ${workMode} in + + "online") + + #check that the node is fully synced, otherwise the opcertcounter query could return a false state + if [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced !\e[0m\n"; exit 1; fi + + #check ledger-state via the local node + showProcessAnimation "Query-Ledger-State: " & + poolsInLedger=$(${cardanocli} ${cliEra} query stake-pools 2> /dev/null); if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\n\e[35mERROR - Could not query stake-pools from the chain.\e[0m\n"; exit 1; fi + stopProcessAnimation; + + #now lets see how often the poolIDbech is listed: 0->Not on the chain, 1->On the chain, any other value -> ERROR + poolInLedgerCnt=$(grep "${poolIDbech}" <<< ${poolsInLedger} | wc -l) + if [[ ${poolInLedgerCnt} -eq 1 ]]; then echo -e "Info via Local-Node: Pool-ID is already on the chain, continue with a Re-Registration\e[0m\n"; regSubmitted="xxx"; + elif [[ ${poolInLedgerCnt} -eq 0 ]]; then echo -e "Info via Local-Node: Pool-ID is not on the chain (yet), continue with a normal Registration\e[0m\n"; regSubmitted=""; + else echo -e "\e[35mERROR - The Pool-ID '${poolIDbech}' is more than once in the ledgers stake-pool list, this shouldn't be possible!\e[0m\n"; exit 1; + fi + ;; + + "light") + + #query poolinfo via poolid on koios -> this is just to have a nice output about the pool we wanna delegate to. if koios is down or so, it doesn't matter in online(full) mode + error=0 + if [[ "${koiosAPI}" != "" ]]; then + + errorcnt=0 + error=-1 + showProcessAnimation "Query Pool-Info via Koios: " & + while [[ ${errorcnt} -lt 5 && ${error} -ne 0 ]]; do #try a maximum of 5 times to request the information via koios API + error=0 + response=$(curl -sL -m 30 -X POST -w "---spo-scripts---%{http_code}" "${koiosAPI}/pool_info" -H "Accept: application/json" -H "Content-Type: application/json" -d "{\"_pool_bech32_ids\":[\"${poolIDbech}\"]}" 2> /dev/null) + if [ $? -ne 0 ]; then error=1; fi; + errorcnt=$(( ${errorcnt} + 1 )) + done + stopProcessAnimation; + if [[ ${error} -ne 0 ]]; then echo -e "\e[33mQuery of the Pool-Status via Koios-API failed, tried 5 times.\e[0m\n"; fi; #curl query failed + + #Split the response string into JSON content and the HTTP-ResponseCode + if [[ "${response}" =~ (.*)---spo-scripts---([0-9]*)* ]]; then + responseJSON="${BASH_REMATCH[1]}" + responseCode="${BASH_REMATCH[2]}" + fi + + if [[ ${error} -eq 0 && ${responseCode} -eq 200 ]]; then + #check if the received json only contains one entry in the array (will also not be 1 if not a valid json) + if [[ $(jq ". | length" 2> /dev/null <<< ${responseJSON}) -eq 1 ]]; then + { read poolNameInfo; read poolTickerInfo; read poolStatusInfo; } <<< $(jq -r "(.[0].meta_json.name | select (.!=null)), (.[0].meta_json.ticker | select (.!=null)), (.[0].pool_status | select (.!=null))" 2> /dev/null <<< ${responseJSON}) + echo -e "\e[0mName (Ticker): \e[32m${poolNameInfo} (${poolTickerInfo})\e[0m" + echo + + case "${poolStatusInfo^^}" in + "REGISTERED") echo -e "\e[0mInfo via Koios-API: \e[32mPool is REGISTERED on the chain, continue with a Re-Registration.\e[0m\n"; regSubmitted="xxx";; + "RETIRED") echo -e "\e[0mInfo via Koios-API: \e[33mPool was RETIRED and is currently NOT registered on the chain. Lets do a registration.\e[0m\n"; regSubmitted="";; + "RETIRING") retiringEpoch=$(jq -r ".[0].retiring_epoch | select (.!=null)" 2> /dev/null <<< ${responseJSON}) + echo -e "\e[0mInfo via Koios-API: \e[36mPool will RETIRE in epoch ${retiringEpoch}, currently REGISTERED.\e[0m Continue with a Re-Registration.\e[0m\n"; regSubmitted="xxx";; + *) echo -e "\e[0mInfo via Koios-API: Pool-Status is ${poolStatusInfo^^}\e[0m\n";; + esac + + else + echo -e "\e[0mInfo via Koios-API: \e[33mPool is NOT registered on the chain, never was. Lets do a registration.\e[0m\n"; regSubmitted=""; + fi + fi + + unset poolNameInfo poolTickerInfo poolStatusInfo responseJSON responseCode error errorcnt + + fi #koiosAPI!="" + ;; + + esac #workmode + + fi #onlinemode elif [[ "${forceParam^^}" == "REG" ]]; then regSubmitted=""; #force a new registration elif [[ "${forceParam^^}" == "REREG" ]]; then regSubmitted="xxx"; #force a re-registration @@ -284,11 +345,11 @@ fi #------------------------------------------------------------------------- #get values to register the staking address on the blockchain -currentTip=$(get_currentTip) -currentEPOCH=$(get_currentEpoch) +currentTip=$(get_currentTip); checkError "$?"; +currentEPOCH=$(get_currentEpoch); checkError "$?"; if [[ "${regWitnessID}" == "" ]]; then #New witness collection - ttl=$(get_currentTTL) + ttl=$(( ${currentTip} + ${defTTL} )) else ttl=$(jq -r .regWitness.ttl <<< ${poolJSON}) #load data from already started witness collection if [[ ${ttl} -lt ${currentTip} ]]; then #if the TTL stored in the witness collection is lower than the current tip, the transaction window is over @@ -337,7 +398,7 @@ if ${onlineMode}; then tmpCheckJSON=$(jq . "${tmpMetadataJSON}" 2> /dev/null) if [[ $? -ne 0 ]]; then echo -e "\e[33mERROR - Not a valid JSON file on the webserver!\e[0m\n"; exit 1; fi #Ok, downloaded file is a valid JSON file. So now look into the HASH - onlineMetaHash=$(${cardanocli} stake-pool metadata-hash --pool-metadata-file "${tmpMetadataJSON}") + onlineMetaHash=$(${cardanocli} ${cliEra} stake-pool metadata-hash --pool-metadata-file "${tmpMetadataJSON}") checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #Compare the HASH now, if they don't match up, output an ERROR message and exit if [[ ! "${poolMetaHash}" == "${onlineMetaHash}" ]]; then @@ -359,13 +420,12 @@ if ${onlineMode}; then fi; #onlinemode #Read ProtocolParameters -if ${onlineMode}; then - protocolParametersJSON=$(${cardanocli} query protocol-parameters ${magicparam} ); #onlinemode - else - readOfflineFile; - protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON}); #offlinemode - fi - +case ${workMode} in + "online") protocolParametersJSON=$(${cardanocli} ${cliEra} query protocol-parameters);; #onlinemode + "light") protocolParametersJSON=${lightModeParametersJSON};; #lightmode + "offline") readOfflineFile; + protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON});; #offlinemode +esac checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "\e[0m Owner Stake Keys:\e[32m ${ownerCnt}\e[0m owner(s) with the key(s)" @@ -378,12 +438,13 @@ done echo -ne "\e[0m Rewards Stake:\e[32m ${rewardsName}.staking.vkey \e[0m" if [[ "$(jq -r .description < ${rewardsName}.staking.vkey)" == *"Hardware"* ]]; then echo -e "(Hardware-Key)"; else echo; fi echo -e "\e[0m Witnesses needed:\e[32m ${witnessCount} signed witnesses \e[0m" -echo -e "\e[0m Pledge:\e[32m ${poolPledge} \e[90mlovelaces" -echo -e "\e[0m Cost:\e[32m ${poolCost} \e[90mlovelaces" -echo -e "\e[0m Margin:\e[32m ${poolMargin} \e[0m" +echo -e "\e[0m Pledge:\e[32m ${poolPledge} \e[90mlovelaces \e[0m(\e[32m$(convertToADA ${poolPledge}) \e[90mADA\e[0m)" +echo -e "\e[0m Cost:\e[32m ${poolCost} \e[90mlovelaces \e[0m(\e[32m$(convertToADA ${poolCost}) \e[90mADA\e[0m)" +poolMarginPct=$(bc <<< "${poolMargin} * 100" 2> /dev/null) +echo -e "\e[0m Margin:\e[32m ${poolMargin} \e[0m(\e[32m${poolMarginPct}%\e[0m)" echo echo -e "\e[0m Current EPOCH:\e[32m ${currentEPOCH}\e[0m" -echo -e "\e[0mCurrent Slot-Height:\e[32m ${currentTip}\e[0m (set TTL[invalid_hereafter] is ${ttl})" +echo -e "\e[0mCurrent Slot-Height:\e[32m ${currentTip}\e[0m (set TTL[invalid_hereafter] to ${ttl})" rxcnt="1" #transmit to one destination addr. all utxos will be sent back to the fromAddr @@ -402,18 +463,31 @@ if [[ "${regWitnessID}" == "" ]]; then # # Checking UTXO Data of the source address and gathering data about total lovelaces and total assets # - #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in offlinemode from the transferFile - if ${onlineMode}; then + + #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in lightmode via API requests, in offlinemode from the transferFile + case ${workMode} in + "online") #check that the node is fully synced, otherwise the query would mabye return a false state + if [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced or not running, please let your node sync to 100% first !\e[0m\n"; exit 1; fi showProcessAnimation "Query-UTXO: " & - utxo=$(${cardanocli} query utxo --address ${sendFromAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + utxo=$(${cardanocli} ${cliEra} query utxo --address ${sendFromAddr} 2> /dev/stdout); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; showProcessAnimation "Convert-UTXO: " & utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; - #utxoJSON=$(${cardanocli} query utxo --address ${sendFromAddr} ${magicparam} --out-file /dev/stdout); checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; - else - readOfflineFile; #Reads the offlinefile into the offlineJSON variable - utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON}) - if [[ "${utxoJSON}" == null ]]; then echo -e "\e[35mPayment-Address not included in the offline transferFile, please include it first online!\e[0m\n"; exit; fi - fi + ;; + + "light") showProcessAnimation "Query-UTXO-LightMode: " & + utxo=$(queryLight_UTXO "${sendFromAddr}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + showProcessAnimation "Convert-UTXO: " & + utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; + ;; + + "offline") readOfflineFile; #Reads the offlinefile into the offlineJSON variable + utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON} 2> /dev/null) + if [[ "${utxoJSON}" == null ]]; then echo -e "\e[35mPayment-Address not included in the offline transferFile, please include it first online!\e[0m\n"; exit 1; fi + ;; + esac + txcnt=$(jq length <<< ${utxoJSON}) #Get number of UTXO entries (Hash#Idx), this is also the number of --tx-in for the transaction if [[ ${txcnt} == 0 ]]; then echo -e "\e[35mNo funds on the Source Address!\e[0m\n"; exit; else echo -e "\e[32m${txcnt} UTXOs\e[0m found on the Source Address!\n"; fi @@ -439,7 +513,6 @@ if [[ "${regWitnessID}" == "" ]]; then utxoHashIndex=${utxoHashIndexArray[${tmpCnt}]} utxoAmount=${utxoLovelaceArray[${tmpCnt}]} #Lovelaces totalLovelaces=$(bc <<< "${totalLovelaces} + ${utxoAmount}" ) -# echo -e "Hash#Index: ${utxoHashIndex}\tAmount: ${utxoAmount}"; echo -e "Hash#Index: ${utxoHashIndex}\tADA: $(convertToADA ${utxoAmount}) \e[90m(${utxoAmount} lovelaces)\e[0m"; if [[ ! "${utxoDatumHashArray[${tmpCnt}]}" == null ]]; then echo -e " DatumHash: ${utxoDatumHashArray[${tmpCnt}]}"; fi assetsEntryCnt=${assetsEntryCntArray[${tmpCnt}]} @@ -473,8 +546,20 @@ if [[ "${regWitnessID}" == "" ]]; then totalAssetsJSON=$( jq ". += {\"${assetHash}${point}${assetName}\":{amount: \"${newValue}\", name: \"${assetTmpName}\", bech: \"${assetBech}\"}}" <<< ${totalAssetsJSON}) if [[ "${assetTmpName:0:1}" == "." ]]; then assetTmpName=${assetTmpName:1}; else assetTmpName="{${assetTmpName}}"; fi - case ${assetHash} in - "${adahandlePolicyID}" ) #$adahandle + case "${assetHash}${assetTmpName:1:8}" in + "${adahandlePolicyID}000de140" ) #$adahandle cip-68 + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Own): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}00000000" ) #$adahandle virtual + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Vir): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}000643b0" ) #$adahandle reference + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Ref): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}"* ) #$adahandle cip-25 echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle: \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" ;; * ) #default @@ -545,16 +630,16 @@ minOutUTXO=$(calc_minOutUTXO "${protocolParametersJSON}" "${sendToAddr}+1000000$ #Generate Dummy-TxBody file for fee calculation txBodyFile="${tempDir}/dummy.txbody" rm ${txBodyFile} 2> /dev/null -${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} ${registrationCerts} --out-file ${txBodyFile} +${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} ${registrationCerts} --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi -fee=$(${cardanocli} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} ${magicparam} --witness-count ${witnessCount} --byron-witness-count 0 | awk '{ print $1 }') +fee=$(${cardanocli} ${cliEra} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} --witness-count ${witnessCount} --byron-witness-count 0 | awk '{ print $1 }') checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "\e[0mMinimum transfer Fee for ${txcnt}x TxIn & ${rxcnt}x TxOut & ${certCnt}x Certificate: \e[32m $(convertToADA ${fee}) ADA / ${fee} lovelaces \e[90m" #Check if pool was registered before and calculate Fee for registration or set it to zero for re-registration if [[ "${regSubmitted}" == "" ]]; then #pool not registered before poolDepositFee=$(jq -r .stakePoolDeposit <<< ${protocolParametersJSON}) - echo -e "\e[0mPool Deposit Fee: \e[32m ${poolDepositFee} lovelaces \e[90m" + echo -e "\e[0mPool Deposit Fee: \e[32m${poolDepositFee} lovelaces \e[90m" minRegistrationFees=$(( ${poolDepositFee}+${fee} )) registrationType="PoolRegistration" echo @@ -562,6 +647,7 @@ if [[ "${regSubmitted}" == "" ]]; then #pool not registered before echo else #pool was registered before -> reregistration -> no poolDepositFee poolDepositFee=0 + echo -e "\e[0mNo Pool Deposit Fee: \e[32mReRegistration (PoolUpdate) \e[90m" minRegistrationFees=$(( ${poolDepositFee}+${fee} )) registrationType="PoolReRegistration" echo @@ -585,7 +671,7 @@ echo #Building unsigned transaction body rm ${txBodyFile} 2> /dev/null -${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} ${registrationCerts} --out-file ${txBodyFile} +${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} ${registrationCerts} --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi dispFile=$(cat ${txBodyFile}); if ${cropTxOutput} && [[ ${#dispFile} -gt 4000 ]]; then echo "${dispFile:0:4000} ... (cropped)"; else echo "${dispFile}"; fi @@ -623,7 +709,7 @@ if [ -f "${poolName}.node.skey" ]; then #key is a normal one skeyJSON=$(read_skeyFILE "${poolName}.node.skey"); if [ $? -ne 0 ]; then echo -e "\e[35m${skeyJSON}\e[0m\n"; exit 1; else echo -e "\e[32mOK\e[0m\n"; fi echo -ne "\e[0mAdding the pool node witness '\e[33m${poolName}.node.skey\e[0m' ... " - tmpWitness=$(${cardanocli} transaction witness --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON}") ${magicparam} --out-file /dev/stdout) + tmpWitness=$(${cardanocli} ${cliEra} transaction witness --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON}") --out-file /dev/stdout) checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "\e[32mOK\n" @@ -657,7 +743,7 @@ fi skeyJSON=$(read_skeyFILE "${regPayName}.skey"); if [ $? -ne 0 ]; then echo -e "\e[35m${skeyJSON}\e[0m\n"; exit 1; else echo -e "\e[32mOK\e[0m\n"; fi echo -ne "\e[0mAdding the payment witness from a local payment address '\e[33m${regPayName}.skey\e[0m' ... " - tmpWitness=$(${cardanocli} transaction witness --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON}") ${magicparam} --out-file /dev/stdout) + tmpWitness=$(${cardanocli} ${cliEra} transaction witness --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON}") --out-file /dev/stdout) checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "\e[32mOK\n" @@ -684,7 +770,7 @@ do skeyJSON=$(read_skeyFILE "${ownerName}.staking.skey"); if [ $? -ne 0 ]; then echo -e "\e[35m${skeyJSON}\e[0m\n"; exit 1; else echo -e "\e[32mOK\e[0m\n"; fi echo -ne "\e[0mAdding the owner witness from a local signing key '\e[33m${ownerName}.skey\e[0m' ... " - tmpWitness=$(${cardanocli} transaction witness --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON}") ${magicparam} --out-file /dev/stdout) + tmpWitness=$(${cardanocli} ${cliEra} transaction witness --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON}") --out-file /dev/stdout) checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "\e[32mOK\n" @@ -838,7 +924,7 @@ done #Assemble the transaction rm ${txFile} 2> /dev/null -${cardanocli} transaction assemble --tx-body-file ${txBodyFile} ${witnessString} --out-file ${txFile} +${cardanocli} ${cliEra} transaction assemble --tx-body-file ${txBodyFile} ${witnessString} --out-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -ne "\e[90m" dispFile=$(cat ${txFile}); if ${cropTxOutput} && [[ ${#dispFile} -gt 4000 ]]; then echo "${dispFile:0:4000} ... (cropped)"; else echo "${dispFile}"; fi @@ -859,42 +945,45 @@ do done #Read out the POOL-ID -poolIDhex=$(${cardanocli} stake-pool id --cold-verification-key-file ${poolName}.node.vkey --output-format hex) #New method since 1.23.0 +poolIDhex=$(${cardanocli} ${cliEra} stake-pool id --cold-verification-key-file ${poolName}.node.vkey --output-format hex) #New method since 1.23.0 checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi -poolIDbech=$(${cardanocli} stake-pool id --cold-verification-key-file ${poolName}.node.vkey) #New method since 1.23.0 +poolIDbech=$(${cardanocli} ${cliEra} stake-pool id --cold-verification-key-file ${poolName}.node.vkey) #New method since 1.23.0 checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "\e[0mPool-ID:\e[32m ${poolIDhex} / ${poolIDbech} \e[90m" echo #Show a warning to respect the pledge amount -if [[ ${poolPledge} -gt 0 ]]; then echo -e "\e[35mATTENTION - You're registered Pledge will be set to ${poolPledge} lovelaces, please respect it with the sum of all registered owner addresses!\e[0m\n"; fi +if [[ ${poolPledge} -gt 0 ]]; then echo -e "\e[35mATTENTION - You're registered Pledge will be set to $(convertToADA ${poolPledge}) ADA, please respect it with the sum of all registered owner addresses!\e[0m\n"; fi #Show a message about the registration type echo -e "\e[0mThis will be a: \e[32m${regWitnessType}\e[0m\n"; offlineRegistrationType="${regWitnessType}"; #Just as Type info for the offline file, same as the regWitnessType if ask "\e[33mDoes this look good for you? Do you have enough pledge in your owner account(s), continue and register on chain ?" N; then + echo - if ${onlineMode}; then #onlinesubmit + case ${workMode} in + + "online") + #onlinesubmit echo -ne "\e[0mSubmitting the transaction via the node... " - ${cardanocli} transaction submit --tx-file ${txFile} ${magicparam} - #No error, so lets update the pool JSON file with the date and file the certFile was registered on the blockchain + ${cardanocli} ${cliEra} transaction submit --tx-file ${txFile} + #If no error, update the pool JSON file with the date and file the certFile was registered on the blockchain if [[ $? -eq 0 ]]; then - file_unlock ${poolFile}.pool.json - newJSON=$(cat ${poolFile}.pool.json | jq ". += {regEpoch: \"${currentEPOCH}\"}" | jq ". += {regSubmitted: \"$(date -R)\"}" | jq "del (.regWitness)") - echo "${newJSON}" > ${poolFile}.pool.json - file_lock ${poolFile}.pool.json - echo -e "\e[32mDONE\n" - - #Delete the just used RegistrationCertificat so it can't be submitted again as a mistake, build one again with 05a first - file_unlock ${regCertFile} - rm ${regCertFile} - + file_unlock ${poolFile}.pool.json + newJSON=$(cat ${poolFile}.pool.json | jq ". += {regEpoch: \"${currentEPOCH}\"}" | jq ". += {regSubmitted: \"$(date -R)\"}" | jq "del (.regWitness)") + echo "${newJSON}" > ${poolFile}.pool.json + file_lock ${poolFile}.pool.json + echo -e "\e[32mDONE\n" + + #Delete the just used RegistrationCertificat so it can't be submitted again as a mistake, build one again with 05a first + file_unlock ${regCertFile} + rm ${regCertFile} else - echo -e "\n\n\e[35mERROR (Code $?) !\e[0m"; exit 1; + echo -e "\n\n\e[35mERROR (Code $?) !\e[0m"; exit 1; fi echo echo -e "\e[0mStakepool Info JSON:\e[32m ${poolFile}.pool.json \e[90m" @@ -902,16 +991,53 @@ if ask "\e[33mDoes this look good for you? Do you have enough pledge in your own echo #Show the TxID - txID=$(${cardanocli} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" + txID=$(${cardanocli} ${cliEra} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + #Display information to manually register the OwnerDelegationCertificates on the chain if a hardware-wallet is involved. With only cli based staking keys, we can include all the delegation certificates in one transaction + if [[ "${regWitnessHardwareWalletIncluded}" == "yes" ]]; then + echo -e "\n\e[33mThere is at least one Hardware-Wallet involved, so you have to register the DelegationCertificate for each Owner in additional transactions after the ${regWitnessType} !\e[0m\n"; fi + ;; + + + "light") + #lightmode submit + showProcessAnimation "Submit-Transaction-LightMode: " & + txID=$(submitLight "${txFile}"); + #If no error, update the pool JSON file with the date and file the certFile was registered on the blockchain + if [[ $? -eq 0 ]]; then + stopProcessAnimation; + file_unlock ${poolFile}.pool.json + newJSON=$(cat ${poolFile}.pool.json | jq ". += {regEpoch: \"${currentEPOCH}\"}" | jq ". += {regSubmitted: \"$(date -R)\"}" | jq "del (.regWitness)") + echo "${newJSON}" > ${poolFile}.pool.json + file_lock ${poolFile}.pool.json + echo -e "\e[32mDONE\n" + + #Delete the just used RegistrationCertificat so it can't be submitted again as a mistake, build one again with 05a first + file_unlock ${regCertFile} + rm ${regCertFile} + else + stopProcessAnimation; + echo -e "\n\n\e[35mERROR (Code $?) !\e[0m"; exit 1; + fi + + echo + echo -e "\e[0mStakepool Info JSON:\e[32m ${poolFile}.pool.json \e[90m" + cat ${poolFile}.pool.json + echo + + #Show the TxID + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi #Display information to manually register the OwnerDelegationCertificates on the chain if a hardware-wallet is involved. With only cli based staking keys, we can include all the delegation certificates in one transaction if [[ "${regWitnessHardwareWalletIncluded}" == "yes" ]]; then echo -e "\n\e[33mThere is at least one Hardware-Wallet involved, so you have to register the DelegationCertificate for each Owner in additional transactions after the ${regWitnessType} !\e[0m\n"; fi + ;; - else #offlinestore + + "offline") + #offlinestore txFileJSON=$(cat ${txFile} | jq .) offlineJSON=$( jq ".transactions += [ { date: \"$(date -R)\", type: \"${offlineRegistrationType}\", @@ -973,8 +1099,9 @@ if ask "\e[33mDoes this look good for you? Do you have enough pledge in your own else echo -e "\e[35mERROR - Could not verify the written data in the '$(basename ${offlineFile})'. Retry again or generate a new '$(basename ${offlineFile})'.\e[0m\n"; fi + ;; - fi + esac #workMode else #ask: Does this look good for you? Do you have enough pledge in your owner account(s), continue and register on chain ? diff --git a/cardano/mainnet/05d_poolWitness.sh b/cardano/mainnet/05d_poolWitness.sh index 7eb90d1e..0a686410 100755 --- a/cardano/mainnet/05d_poolWitness.sh +++ b/cardano/mainnet/05d_poolWitness.sh @@ -32,7 +32,7 @@ regWitnessPayName=$(jq -r ".regWitness.regPayName" <<< ${poolJSON}) poolMetaTicker=$(jq -r ".poolMetaTicker" <<< ${poolJSON}) regWitnessMetadataFilesList=$(jq -r ".regWitness.metadataFilesList" <<< ${poolJSON}) -currentTip=$(get_currentTip) +currentTip=$(get_currentTip); checkError "$?"; ttl=$(jq -r ".regWitness.ttl" <<< ${poolJSON}) echo -e "\e[0mChecking Witness Content in the poolFile: \e[32m${poolFile}.pool.json\e[0m" @@ -144,6 +144,7 @@ case ${1} in * ) showUsage; exit 1; ;; + esac case ${action} in @@ -197,8 +198,6 @@ case ${action} in witnessSigningName=$(jq -r ".\"signing-name\"" <<< ${witnessJSON}) witnessSigningVkey=$(jq -r ".\"signing-vkey\"" <<< ${witnessJSON} | jq .) witnessPoolMetaTicker=$(jq -r ".poolMetaTicker" <<< ${witnessJSON}) - currentTip=$(get_currentTip) - regWitnessID=$(jq -r ".regWitness.id" <<< ${poolJSON}) regWitnessDate=$(date --date="@${regWitnessID}" -R) @@ -208,7 +207,7 @@ case ${action} in regWitnessMetadataFilesList=$(jq -r ".regWitness.metadataFilesList" <<< ${poolJSON}) poolMetaTicker=$(jq -r ".poolMetaTicker" <<< ${poolJSON}) - currentTip=$(get_currentTip) + currentTip=$(get_currentTip); checkError "$?"; ttl=$(jq -r ".regWitness.ttl" <<< ${poolJSON}) echo -e "\e[0mAdding a Signed Witness \e[32m${witnessFile}\e[0m into the poolFile: \e[32m${poolFile}.pool.json\e[0m" @@ -358,7 +357,7 @@ case ${action} in witnessSigningVkey=$(jq -r ".\"signing-vkey\"" <<< ${witnessJSON} | jq .) poolMetaTicker=$(jq -r ".poolMetaTicker" <<< ${witnessJSON}) regWitnessMetadataFilesList=$(jq -r ".metadataFilesList" <<< ${witnessJSON}) - currentTip=$(get_currentTip) + currentTip=$(get_currentTip); checkError "$?"; echo -e "\e[0mSigning Witness in the witnessFile \e[32m${witnessFile}\e[0m with the signing key: \e[32m${signingKey}\e[0m" echo @@ -420,7 +419,7 @@ case ${action} in #read the needed signing keys into ram and sign the transaction skeyJSON=$(read_skeyFILE "${signingKey}.skey"); if [ $? -ne 0 ]; then echo -e "\e[35m${skeyJSON}\e[0m\n"; exit 1; else echo -e "\e[32mOK\e[0m\n"; fi - tmpWitness=$(${cardanocli} transaction witness --tx-body-file ${tmpWitnessTxBody} --signing-key-file <(echo "${skeyJSON}") ${magicparam} --out-file /dev/stdout) + tmpWitness=$(${cardanocli} ${cliEra} transaction witness --tx-body-file ${tmpWitnessTxBody} --signing-key-file <(echo "${skeyJSON}") --out-file /dev/stdout) checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi witnessJSON=$(jq ".signedWitness = ${tmpWitness}" <<< ${witnessJSON}); #include the witness in the witnessJSON checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi diff --git a/cardano/mainnet/05e_checkPoolOnChain.sh b/cardano/mainnet/05e_checkPoolOnChain.sh index c510e39c..9a3fced8 100755 --- a/cardano/mainnet/05e_checkPoolOnChain.sh +++ b/cardano/mainnet/05e_checkPoolOnChain.sh @@ -16,14 +16,7 @@ fi #Node must be fully synced for the online query of the OpCertCounter, show info if starting in offline mode -if ${onlineMode}; then - #check that the node is fully synced, otherwise the opcertcounter query could return a false state - if [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced !\e[0m\n"; exit 2; fi -else -#Check can only be done in online mode - echo -e "\e[35mYou have to be in ONLINE MODE to do this!\e[0m\n"; exit 1; -fi - +if ${offlineMode}; then echo -e "\e[35mYou have to be in ONLINE or LIGHT mode to do this!\e[0m\n"; exit 1; fi #Check if the provided Pool-Identification is a Hex-PoolID(length56), a Bech32-PoolID(length56 and starting with pool1) or a pool.id / pool.id-bech / pool.json File @@ -115,23 +108,103 @@ else fi - #OK, we should have a well formated Bech-Pool-ID in the poolIDBech variable now echo -e "\e[0mChecking OnChain-Status for Bech-PoolID:\e[32m ${poolIDBech}\e[0m" echo -#check ledger-state -showProcessAnimation "Query-Ledger-State: " & -poolsInLedger=$(${cardanocli} query stake-pools ${magicparam} 2> /dev/null); checkError "$?"; if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\n\e[35mERROR - Could not query stake-pools from the chain.\e[0m\n"; exit 1; fi -stopProcessAnimation; -#now lets see how often the poolIDBech is listed: 0->Not on the chain, 1->On the chain, any other value -> ERROR -poolInLedgerCnt=$(grep "${poolIDBech}" <<< ${poolsInLedger} | wc -l) +#query poolinfo via poolid on koios -> this is just to have a nice output about the pool we wanna delegate to. if koios is down or so, it doesn't matter in online(full) mode +error=0 +if [[ "${koiosAPI}" != "" ]]; then + + errorcnt=0 + error=-1 + showProcessAnimation "Query Pool-Info via Koios: " & + while [[ ${errorcnt} -lt 5 && ${error} -ne 0 ]]; do #try a maximum of 5 times to request the information via koios API + error=0 + response=$(curl -sL -m 30 -X POST -w "---spo-scripts---%{http_code}" "${koiosAPI}/pool_info" -H "Accept: application/json" -H "Content-Type: application/json" -d "{\"_pool_bech32_ids\":[\"${poolIDBech}\"]}" 2> /dev/null) + if [ $? -ne 0 ]; then error=1; fi; + errorcnt=$(( ${errorcnt} + 1 )) + done + stopProcessAnimation; + + #Split the response string into JSON content and the HTTP-ResponseCode + if [[ "${response}" =~ (.*)---spo-scripts---([0-9]*)* ]]; then + responseJSON="${BASH_REMATCH[1]}" + responseCode="${BASH_REMATCH[2]}" + fi -if [[ ${poolInLedgerCnt} -eq 1 ]]; then echo -e "\e[32mYES, the Pool-ID is in the ledgers stake-pool list!\e[0m"; -elif [[ ${poolInLedgerCnt} -eq 0 ]]; then echo -e "\e[33mNO, the Pool-ID is NOT in the ledgers stake-pool list!\e[0m"; -else echo -e "\e[35mERROR - The Pool-ID is more than once in the ledgers stake-pool list, this shouldn't be possible!\e[0m" -fi + if [[ ${error} -eq 0 && ${responseCode} -eq 200 ]]; then + #check if the received json only contains one entry in the array (will also not be 1 if not a valid json) + if [[ $(jq ". | length" 2> /dev/null <<< ${responseJSON}) -eq 1 ]]; then + { read poolName; + read poolTicker; + read poolStatus; + read poolPledge; + read poolLivePledge; + read poolMargin; + read poolFixedCost; + read poolMetaUrl; + read poolMetaHash; + read poolOpcertCounter; + read poolRewardAddr; + read poolVrfHash; + } <<< $(jq -r ".[0].meta_json.name // \"-\", .[0].meta_json.ticker // \"-\", .[0].pool_status // \"-\", .[0].pledge // \"0\", .[0].live_pledge // \"0\", .[0].margin // \"-\", .[0].fixed_cost // \"0\", .[0].meta_url // \"-\", .[0].meta_hash // \"-\", .[0].op_cert_counter // \"-\", .[0].reward_addr // \"-\", .[0].vrf_key_hash // \"-\"" 2> /dev/null <<< ${responseJSON}) + + echo -e "\e[0m Name (Ticker): \e[32m${poolName} (${poolTicker})\e[0m" + echo -e "\e[0m Set Pledge:\e[32m ${poolPledge} \e[90mlovelaces \e[0m(\e[32m$(convertToADA ${poolPledge}) \e[90mADA\e[0m)" + echo -e "\e[0m Live Pledge:\e[32m ${poolLivePledge} \e[90mlovelaces \e[0m(\e[32m$(convertToADA ${poolLivePledge}) \e[90mADA\e[0m)" + echo -e "\e[0m FixedCost:\e[32m ${poolFixedCost} \e[90mlovelaces \e[0m(\e[32m$(convertToADA ${poolFixedCost}) \e[90mADA\e[0m)" + poolMarginPct=$(bc <<< "${poolMargin} * 100" 2> /dev/null) + echo -e "\e[0m Margin:\e[32m ${poolMargin} \e[0m(\e[32m${poolMarginPct}%\e[0m)" + echo -e "\e[0m Reward-Address:\e[32m ${poolRewardAddr} \e[0m" + echo -e "\e[0mMetadata (Hash):\e[32m ${poolMetaUrl} \e[0m(\e[32m${poolMetaHash}\e[0m)" + echo -e "\e[0m OpCertCounter:\e[32m ${poolOpcertCounter} \e[0m" + echo -e "\e[0m VRF-Key-Hash:\e[32m ${poolVrfHash} \e[0m" + + echo + + case "${poolStatus^^}" in + "REGISTERED") echo -e "\e[0mInfo via Koios-API: \e[32mPool is REGISTERED on the chain.\e[0m\n";; + "RETIRED") echo -e "\e[0mInfo via Koios-API: \e[33mPool was RETIRED and is NOT registered on the chain.\e[0m\n";; + "RETIRING") retiringEpoch=$(jq -r ".[0].retiring_epoch | select (.!=null)" 2> /dev/null <<< ${responseJSON}) + echo -e "\e[0mInfo via Koios-API: \e[36mPool will RETIRE in epoch ${retiringEpoch}, currently REGISTERED.\e[0m\n";; + *) echo -e "\e[0mInfo via Koios-API: Pool-Status is ${poolStatus^^}\e[0m\n";; + esac + + else + echo -e "\e[0mInfo via Koios-API: \e[33mPool is NOT registered on the chain, never was.\e[0m\n"; + fi + fi + +fi #koiosAPI!="" + +case ${workMode} in + + "online") + + #check that the node is fully synced, otherwise the opcertcounter query could return a false state + if [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced !\e[0m\n"; exit 1; fi + + #check ledger-state via the local node + showProcessAnimation "Query-Ledger-State: " & + poolsInLedger=$(${cardanocli} ${cliEra} query stake-pools 2> /dev/null); if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\n\e[35mERROR - Could not query stake-pools from the chain.\e[0m\n"; exit 1; fi + stopProcessAnimation; + + #now lets see how often the poolIDBech is listed: 0->Not on the chain, 1->On the chain, any other value -> ERROR + poolInLedgerCnt=$(grep "${poolIDBech}" <<< ${poolsInLedger} | wc -l) + if [[ ${poolInLedgerCnt} -eq 1 ]]; then echo -e "\e[0mInfo from Local-Node: \e[32mPool is REGISTERED on the chain.\e[0m\n"; + elif [[ ${poolInLedgerCnt} -eq 0 ]]; then echo -e "\e[0mInfo from Local-Node: \e[33mPool is NOT registered on the chain.\e[0m\n"; exit 1 + else echo -e "\e[35mERROR - The Pool-ID is more than once in the ledgers stake-pool list, this shouldn't be possible!\e[0m"; exit 1 + fi + ;; + + "light") + #in light mode, all infos are already displayed. just display an error message if the info could not have been queried + if [[ ${error} -ne 0 ]]; then echo -e "Query of the Koios-API via curl failed, tried 5 times."; exit 1; fi; #curl query failed + ;; + +esac echo -e "\e[0m\n" diff --git a/cardano/mainnet/06_regDelegationCert.sh b/cardano/mainnet/06_regDelegationCert.sh index ab0820aa..3c8c9b25 100755 --- a/cardano/mainnet/06_regDelegationCert.sh +++ b/cardano/mainnet/06_regDelegationCert.sh @@ -162,10 +162,87 @@ echo echo -e "\e[0mDelegating \e[32m${delegName}\e[0m to pool with ID:\e[32m ${delegPoolID}\e[0m" echo -#If in online mode, do a check it the StakeAddress is registered on the chain + +#If in online/light mode, do a check if the pool to delegate to is registered if ${onlineMode}; then - #get the bech stakeaddress for mainnet/testnets + #get the bech poolID + delegationPoolID=$(${bech32_bin} "pool" <<< ${delegPoolID} | tr -d '\n') + checkError "$?"; if [ $? -ne 0 ]; then echo -e "\n\e[35mERROR - Could not convert the Hex-PoolID from the Delegation-Certificate into a Bech Pool-ID.\e[0m\n"; exit 1; fi + + echo -e "\e[0mStaking Address will be delegated to Bech-PoolID:\e[33m ${delegationPoolID}\e[0m" + + if [[ ${onlineMode} == true && ${koiosAPI} != "" ]]; then + + #query poolinfo via poolid on koios + errorcnt=0; error=-1; + showProcessAnimation "Query Pool-Info via Koios: " & + while [[ ${errorcnt} -lt 5 && ${error} -ne 0 ]]; do #try a maximum of 5 times to request the information + error=0 + response=$(curl -sL -m 30 -X POST -w "---spo-scripts---%{http_code}" "${koiosAPI}/pool_info" -H "Accept: application/json" -H "Content-Type: application/json" -d "{\"_pool_bech32_ids\":[\"${delegationPoolID}\"]}" 2> /dev/null) + if [[ $? -ne 0 ]]; then error=1; sleep 1; fi; #if there is an error, wait for a second and repeat + errorcnt=$(( ${errorcnt} + 1 )) + done + stopProcessAnimation; + + #if no error occured, split the response string into JSON content and the HTTP-ResponseCode + if [[ ${error} -eq 0 && "${response}" =~ (.*)---spo-scripts---([0-9]*)* ]]; then + + responseJSON="${BASH_REMATCH[1]}" + responseCode="${BASH_REMATCH[2]}" + + #if the responseCode is 200 (OK) and the received json only contains one entry in the array (will also not be 1 if not a valid json) + if [[ ${responseCode} -eq 200 && $(jq ". | length" 2> /dev/null <<< ${responseJSON}) -eq 1 ]]; then + { read poolNameInfo; read poolTickerInfo; read poolStatusInfo; } <<< $(jq -r ".[0].meta_json.name // \"-\", .[0].meta_json.ticker // \"-\", .[0].pool_status // \"-\"" 2> /dev/null <<< ${responseJSON}) + echo -e " \t\e[0mInformation about the Pool: \e[32m${poolNameInfo} (${poolTickerInfo})\e[0m" + echo -e " \t\e[0m Status: \e[32m${poolStatusInfo}\e[0m" + echo + fi #responseCode & jsoncheck + + fi #error & response + unset errorcnt error + + fi #onlineMode & koiosAPI + + #check if the pool to delegate to is already registered on chain, if not, abort + case ${workMode} in + + "online") + #check that the node is fully synced, otherwise the query would mabye return a false state + if [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced or not running, please let your node sync to 100% first !\e[0m\n"; exit 1; fi + #check ledger-state via the local node + showProcessAnimation "Query-Ledger-State: " & + poolsInLedger=$(${cardanocli} ${cliEra} query stake-pools 2> /dev/null); checkError "$?"; if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\n\e[35mERROR - Could not query stake-pools from the chain.\e[0m\n"; exit 1; fi + stopProcessAnimation; + + #now lets see how often the delegationPoolID is listed: 0->Not on the chain, 1->On the chain, any other value -> ERROR + poolInLedgerCnt=$(grep "${delegationPoolID}" <<< ${poolsInLedger} | wc -l) + + if [[ ${poolInLedgerCnt} -eq 1 ]]; then echo -ne ""; #echo -e "\e[0mPool is registered on the chain, we continue ...\n"; + elif [[ ${poolInLedgerCnt} -eq 0 ]]; then echo -e "\e[33mPool is NOT on the chain, please register it first to do the delegation!\e[0m\n"; exit 1; + else echo -e "\e[35mERROR - The Pool-ID is more than once in the ledgers stake-pool list, this shouldn't be possible!\e[0m"; exit 1; + fi + ;; + + + "light") + #query about the poolinfo via koios has already been done a few lines before + if [[ $(jq ". | length" 2> /dev/null <<< ${responseJSON}) -eq 1 ]]; then + poolStatusInfo=$(jq -r ".[0].pool_status | select (.!=null)" 2> /dev/null <<< ${responseJSON}) + if [[ ${poolStatusInfo^^} != "REGISTERED" ]]; then + echo -e "\e[33mPool-Status is currently '${poolStatusInfo}', please register it first to do the delegation!\e[0m\n"; exit 1; + fi + + else echo -e "\e[33mPool is NOT on the chain or Koios-API error, please register it first to do the delegation!\e[0m\n"; exit 1; + + fi + ;; + + esac + + unset poolNameInfo, poolTickerInfo, poolStatusInfo + + #get the bech stakeaddress for mainnet/testnets directly out of the delegation certificate if [[ "${magicparam}" == *"mainnet"* ]]; then checkAddr=$(echo -n "e1${delegCBOR:12:56}" | ${bech32_bin} "stake"); else @@ -175,44 +252,86 @@ if ${onlineMode}; then echo -e "\e[0mChecking OnChain-Status for the Stake-Address:\e[32m ${checkAddr}\e[0m" echo - #check ledger-state - showProcessAnimation "Query-Ledger-State: " & - rewardsAmount=$(${cardanocli} query stake-address-info --address ${checkAddr} ${magicparam} | jq -r "flatten | .[0].rewardAccountBalance") - checkError "$?"; if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\n\e[35mERROR - Could not query stake-address info from the chain.\e[0m\n"; exit 1; fi - stopProcessAnimation; + #Get rewards state data for the address. When in online mode of course from the node and the chain, in light mode via koios + case ${workMode} in + + "online") #check that the node is fully synced, otherwise the query would mabye return a false state + if [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced or not running, please let your node sync to 100% first !\e[0m\n"; exit 1; fi + showProcessAnimation "Query-StakeAddress-Info: " & + rewardsJSON=$(${cardanocli} ${cliEra} query stake-address-info --address ${checkAddr} 2> /dev/stdout ) + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${rewardsJSON}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + rewardsJSON=$(jq -rc . <<< "${rewardsJSON}") + ;; + + "light") showProcessAnimation "Query-StakeAddress-Info-LightMode: " & + rewardsJSON=$(queryLight_stakeAddressInfo "${checkAddr}") + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${rewardsJSON}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + + esac + + rewardsEntryCnt=$(jq -r 'length' <<< ${rewardsJSON}) #Checking about the content - if [[ ${rewardsAmount} == null ]]; then echo -e "\e[33mStaking Address is NOT on the chain, please register it first to do a delegation !\e[0m\n"; exit 1; - else echo -e "\e[0mStaking Address is registered on the chain, we continue ...\n" - fi + if [[ ${rewardsEntryCnt} == 0 ]]; then #not registered yet + echo -e "\e[33mStaking Address is NOT on the chain, please register it first to do a delegation !\e[0m\n"; exit 1; + else #already registered + #echo -e "Staking Address is registered on the chain, we continue ...\e[0m\n" - #get the bech poolID - poolIDBech=$(${bech32_bin} "pool" <<< ${delegPoolID} | tr -d '\n') - checkError "$?"; if [ $? -ne 0 ]; then echo -e "\n\e[35mERROR - Could not convert the given Hex-PoolID \"${poolID}\" into a Bech Pool-ID.\e[0m\n"; exit 1; fi + delegationPoolID=$(jq -r ".[0].delegation // .[0].stakeDelegation" <<< ${rewardsJSON}) - echo -e "\e[0mChecking OnChain-Status for the Bech-PoolID:\e[32m ${poolIDBech}\e[0m" - echo + #If delegated to a pool, show the current pool ID + if [[ ! ${delegationPoolID} == null ]]; then - #check ledger-state - showProcessAnimation "Query-Ledger-State: " & - poolsInLedger=$(${cardanocli} query stake-pools ${magicparam} 2> /dev/null); checkError "$?"; if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\n\e[35mERROR - Could not query stake-pools from the chain.\e[0m\n"; exit 1; fi - stopProcessAnimation; + echo -e "Staking Address is currently delegated to PoolID: \e[94m${delegationPoolID}\e[0m"; - #now lets see how often the poolIDBech is listed: 0->Not on the chain, 1->On the chain, any other value -> ERROR - poolInLedgerCnt=$(grep "${poolIDBech}" <<< ${poolsInLedger} | wc -l) + if [[ ${onlineMode} == true && ${koiosAPI} != "" ]]; then - if [[ ${poolInLedgerCnt} -eq 1 ]]; then echo -e "\e[0mPool is registered on the chain, we continue ...\n"; - elif [[ ${poolInLedgerCnt} -eq 0 ]]; then echo -e "\e[33mPool is NOT on the chain, please register it first to do the delegation!\e[0m\n"; exit 1; - else echo -e "\e[35mERROR - The Pool-ID is more than once in the ledgers stake-pool list, this shouldn't be possible!\e[0m"; exit 1; - fi + #query poolinfo via poolid on koios + errorcnt=0; error=-1; + showProcessAnimation "Query Pool-Info via Koios: " & + while [[ ${errorcnt} -lt 5 && ${error} -ne 0 ]]; do #try a maximum of 5 times to request the information + error=0 + response=$(curl -sL -m 30 -X POST -w "---spo-scripts---%{http_code}" "${koiosAPI}/pool_info" -H "Accept: application/json" -H "Content-Type: application/json" -d "{\"_pool_bech32_ids\":[\"${delegationPoolID}\"]}" 2> /dev/null) + if [[ $? -ne 0 ]]; then error=1; sleep 1; fi; #if there is an error, wait for a second and repeat + errorcnt=$(( ${errorcnt} + 1 )) + done + stopProcessAnimation; + + #if no error occured, split the response string into JSON content and the HTTP-ResponseCode + if [[ ${error} -eq 0 && "${response}" =~ (.*)---spo-scripts---([0-9]*)* ]]; then + + responseJSON="${BASH_REMATCH[1]}" + responseCode="${BASH_REMATCH[2]}" + + #if the responseCode is 200 (OK) and the received json only contains one entry in the array (will also not be 1 if not a valid json) + if [[ ${responseCode} -eq 200 && $(jq ". | length" 2> /dev/null <<< ${responseJSON}) -eq 1 ]]; then + { read poolNameInfo; read poolTickerInfo; read poolStatusInfo; } <<< $(jq -r ".[0].meta_json.name // \"-\", .[0].meta_json.ticker // \"-\", .[0].pool_status // \"-\"" 2> /dev/null <<< ${responseJSON}) + echo -e "\e[0m Name: \e[94m${poolNameInfo} (${poolTickerInfo})\e[0m" + echo -e "\e[0m Status: \e[94m${poolStatusInfo}\e[0m" + echo + unset poolNameInfo poolTickerInfo poolStatusInfo + fi #responseCode & jsoncheck + + fi #error & response + unset errorcnt error + + fi #onlineMode & koiosAPI + + else + echo -e "\e[0mAccount is not delegated to a Pool yet - so lets change this :-)\n"; + fi + + fi ## ${rewardsEntryCnt} == 0 + +fi ## ${onlineMode} == true -fi #get values to register the delegation certificate on the blockchain #get live values -currentTip=$(get_currentTip) -ttl=$(get_currentTTL) +currentTip=$(get_currentTip); checkError "$?"; +ttl=$(( ${currentTip} + ${defTTL} )) echo -e "Current Slot-Height:\e[32m ${currentTip}\e[0m (setting TTL[invalid_hereafter] to ${ttl})" @@ -229,18 +348,32 @@ echo # # Checking UTXO Data of the source address and gathering data about total lovelaces and total assets # - #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in offlinemode from the transferFile - if ${onlineMode}; then + + + #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in lightmode via API requests, in offlinemode from the transferFile + case ${workMode} in + "online") #check that the node is fully synced, otherwise the query would mabye return a false state + if [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced or not running, please let your node sync to 100% first !\e[0m\n"; exit 1; fi showProcessAnimation "Query-UTXO: " & - utxo=$(${cardanocli} query utxo --address ${sendFromAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + utxo=$(${cardanocli} ${cliEra} query utxo --address ${sendFromAddr} 2> /dev/stdout); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; showProcessAnimation "Convert-UTXO: " & utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; - #utxoJSON=$(${cardanocli} query utxo --address ${sendFromAddr} ${magicparam} --out-file /dev/stdout); checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; - else - readOfflineFile; #Reads the offlinefile into the offlineJSON variable - utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON}) - if [[ "${utxoJSON}" == null ]]; then echo -e "\e[35mPayment-Address not included in the offline transferFile, please include it first online!\e[0m\n"; exit; fi - fi + ;; + + "light") showProcessAnimation "Query-UTXO-LightMode: " & + utxo=$(queryLight_UTXO "${sendFromAddr}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + showProcessAnimation "Convert-UTXO: " & + utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; + ;; + + "offline") readOfflineFile; #Reads the offlinefile into the offlineJSON variable + utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON} 2> /dev/null) + if [[ "${utxoJSON}" == null ]]; then echo -e "\e[35mPayment-Address not included in the offline transferFile, please include it first online!\e[0m\n"; exit 1; fi + ;; + esac + txcnt=$(jq length <<< ${utxoJSON}) #Get number of UTXO entries (Hash#Idx), this is also the number of --tx-in for the transaction if [[ ${txcnt} == 0 ]]; then echo -e "\e[35mNo funds on the Source Address!\e[0m\n"; exit 1; else echo -e "\e[32m${txcnt} UTXOs\e[0m found on the Source Address!\n"; fi @@ -266,7 +399,6 @@ echo utxoHashIndex=${utxoHashIndexArray[${tmpCnt}]} utxoAmount=${utxoLovelaceArray[${tmpCnt}]} #Lovelaces totalLovelaces=$(bc <<< "${totalLovelaces} + ${utxoAmount}" ) -# echo -e "Hash#Index: ${utxoHashIndex}\tAmount: ${utxoAmount}"; echo -e "Hash#Index: ${utxoHashIndex}\tADA: $(convertToADA ${utxoAmount}) \e[90m(${utxoAmount} lovelaces)\e[0m"; if [[ ! "${utxoDatumHashArray[${tmpCnt}]}" == null ]]; then echo -e " DatumHash: ${utxoDatumHashArray[${tmpCnt}]}"; fi assetsEntryCnt=${assetsEntryCntArray[${tmpCnt}]} @@ -300,8 +432,20 @@ echo totalAssetsJSON=$( jq ". += {\"${assetHash}${point}${assetName}\":{amount: \"${newValue}\", name: \"${assetTmpName}\", bech: \"${assetBech}\"}}" <<< ${totalAssetsJSON}) if [[ "${assetTmpName:0:1}" == "." ]]; then assetTmpName=${assetTmpName:1}; else assetTmpName="{${assetTmpName}}"; fi - case ${assetHash} in - "${adahandlePolicyID}" ) #$adahandle + case "${assetHash}${assetTmpName:1:8}" in + "${adahandlePolicyID}000de140" ) #$adahandle cip-68 + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Own): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}00000000" ) #$adahandle virtual + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Vir): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}000643b0" ) #$adahandle reference + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Ref): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}"* ) #$adahandle cip-25 echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle: \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" ;; * ) #default @@ -368,12 +512,13 @@ if [[ ! "${transactionMessage}" == "{}" ]]; then fi #Read ProtocolParameters -if ${onlineMode}; then - protocolParametersJSON=$(${cardanocli} query protocol-parameters ${magicparam} ); #onlinemode - else - protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON}); #offlinemode - fi +case ${workMode} in + "online") protocolParametersJSON=$(${cardanocli} ${cliEra} query protocol-parameters);; #onlinemode + "light") protocolParametersJSON=${lightModeParametersJSON};; #lightmode + "offline") protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON});; #offlinemode +esac checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi + minOutUTXO=$(calc_minOutUTXO "${protocolParametersJSON}" "${sendToAddr}+1000000${assetsOutString}") #------------------------------------- @@ -382,10 +527,10 @@ minOutUTXO=$(calc_minOutUTXO "${protocolParametersJSON}" "${sendToAddr}+1000000$ #Generate Dummy-TxBody file for fee calculation txBodyFile="${tempDir}/dummy.txbody" rm ${txBodyFile} 2> /dev/null -${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --certificate ${delegName}.deleg.cert --out-file ${txBodyFile} +${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --certificate ${delegName}.deleg.cert --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi -fee=$(${cardanocli} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} ${magicparam} --witness-count 2 --byron-witness-count 0 | awk '{ print $1 }') +fee=$(${cardanocli} ${cliEra} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} --witness-count 2 --byron-witness-count 0 | awk '{ print $1 }') checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "\e[0mMinimum transfer Fee for ${txcnt}x TxIn & ${rxcnt}x TxOut & 1x Certificate: \e[32m $(convertToADA ${fee}) ADA / ${fee} lovelaces \e[90m" @@ -414,7 +559,7 @@ echo #Building unsigned transaction body rm ${txBodyFile} 2> /dev/null -${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --certificate ${delegName}.deleg.cert --out-file ${txBodyFile} +${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --certificate ${delegName}.deleg.cert --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi dispFile=$(cat ${txBodyFile}); if ${cropTxOutput} && [[ ${#dispFile} -gt 4000 ]]; then echo "${dispFile:0:4000} ... (cropped)"; else echo "${dispFile}"; fi @@ -443,7 +588,7 @@ if [[ -f "${regPayName}.hwsfile" && -f "${delegName}.staking.hwsfile" && "${paym if [[ "${tmp^^}" =~ (ERROR|DISCONNECT) ]]; then echo -e "\e[35m${tmp}\e[0m\n"; exit 1; else echo -ne "\e[0mWitnessed ... "; fi checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - ${cardanocli} transaction assemble --tx-body-file ${txBodyFile} --witness-file ${txWitnessFile}-payment --witness-file ${txWitnessFile}-staking --out-file ${txFile} + ${cardanocli} ${cliEra} transaction assemble --tx-body-file ${txBodyFile} --witness-file ${txWitnessFile}-payment --witness-file ${txWitnessFile}-staking --out-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "Assembled ... \e[32mDONE\e[0m\n"; @@ -458,7 +603,7 @@ elif [[ -f "${delegName}.staking.skey" && -f "${regPayName}.skey" ]]; then #with echo -e "\e[0mSign the unsigned transaction body with the \e[32m${regPayName}.skey\e[0m & \e[32m${delegName}.staking.skey\e[0m: \e[32m ${txFile} \e[90m" echo - ${cardanocli} transaction sign --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON1}") --signing-key-file <(echo "${skeyJSON2}") ${magicparam} --out-file ${txFile} + ${cardanocli} ${cliEra} transaction sign --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON1}") --signing-key-file <(echo "${skeyJSON2}") --out-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #forget the signing keys @@ -482,20 +627,35 @@ if [[ ${txSize} -le ${maxTxSize} ]]; then echo -e "\e[0mTransaction-Size: ${txSi if ask "\e[33mDoes this look good for you ?" N; then + echo - if ${onlineMode}; then #onlinesubmit + case ${workMode} in + "online") + #onlinesubmit echo -ne "\e[0mSubmitting the transaction via the node... " - ${cardanocli} transaction submit --tx-file ${txFile} ${magicparam} + ${cardanocli} ${cliEra} transaction submit --tx-file ${txFile} if [ $? -ne 0 ]; then echo -e "\n\e[35mError - Make sure the pool is already registered.\n\e[0m\n"; exit $?; fi echo -e "\e[32mDONE\n" #Show the TxID - txID=$(${cardanocli} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" + txID=$(${cardanocli} ${cliEra} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; + + "light") + #lightmode submit + showProcessAnimation "Submit-Transaction-LightMode: " & + txID=$(submitLight "${txFile}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${txID}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + echo -e "\e[0mSubmit-Transaction-LightMode: \e[32mDONE\n" + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; - else #offlinestore + + "offline") + #offlinestore txFileJSON=$(cat ${txFile} | jq .) offlineJSON=$( jq ".transactions += [ { date: \"$(date -R)\", type: \"DelegationCertRegistration\", @@ -509,7 +669,6 @@ if ask "\e[33mDoes this look good for you ?" N; then #Write the new offileFile content offlineJSON=$( jq ".history += [ { date: \"$(date -R)\", action: \"signed delegation cert registration transaction for '${delegName}', payment via '${regPayName}'\" } ]" <<< ${offlineJSON}) offlineJSON=$( jq ".general += {offlineCLI: \"${versionCLI}\" }" <<< ${offlineJSON}) - offlineJSON=$( jq ".general += {offlineNODE: \"${versionNODE}\" }" <<< ${offlineJSON}) echo "${offlineJSON}" > ${offlineFile} #Readback the tx content and compare it to the current one readback=$(cat ${offlineFile} | jq -r ".transactions[-1].txJSON") @@ -519,8 +678,9 @@ if ask "\e[33mDoes this look good for you ?" N; then else echo -e "\e[35mERROR - Could not verify the written data in the '$(basename ${offlineFile})'. Retry again or generate a new '$(basename ${offlineFile})'.\e[0m\n"; fi + ;; - fi + esac fi diff --git a/cardano/mainnet/07a_genStakepoolRetireCert.sh b/cardano/mainnet/07a_genStakepoolRetireCert.sh index 9ffd3577..f309145c 100755 --- a/cardano/mainnet/07a_genStakepoolRetireCert.sh +++ b/cardano/mainnet/07a_genStakepoolRetireCert.sh @@ -50,16 +50,17 @@ echo -e "\e[0mCreate a Stakepool de-Registration (retire) certificate for PoolNo echo #Read ProtocolParameters -if ${onlineMode}; then - protocolParametersJSON=$(${cardanocli} query protocol-parameters ${magicparam} ); #onlinemode - else - readOfflineFile; #Reads the offlinefile into the offlineJSON variable - protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON}); #offlinemode - fi +case ${workMode} in + "online") protocolParametersJSON=$(${cardanocli} ${cliEra} query protocol-parameters);; #onlinemode + "light") protocolParametersJSON=${lightModeParametersJSON};; #lightmode + "offline") readOfflineFile; + protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON});; #offlinemode +esac checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi -poolRetireMaxEpoch=$(jq -r .poolRetireMaxEpoch <<< ${protocolParametersJSON}) -currentEPOCH=$(get_currentEpoch) +poolRetireMaxEpoch=$(jq -r .poolRetireMaxEpoch <<< ${protocolParametersJSON}) #eMax + +currentEPOCH=$(get_currentEpoch); checkError "$?"; minRetireEpoch=$(( ${currentEPOCH} + 1 )) #earliest one maxRetireEpoch=$(( ${currentEPOCH} + ${poolRetireMaxEpoch} )) #latest one @@ -81,7 +82,7 @@ echo -e "Retire EPOCH set to:\e[32m ${retireEPOCH}\e[0m" file_unlock ${poolName}.pool.dereg-cert -${cardanocli} stake-pool deregistration-certificate --cold-verification-key-file ${poolName}.node.vkey --epoch ${retireEPOCH} --out-file ${poolName}.pool.dereg-cert +${cardanocli} ${cliEra} stake-pool deregistration-certificate --cold-verification-key-file ${poolName}.node.vkey --epoch ${retireEPOCH} --out-file ${poolName}.pool.dereg-cert checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #No error, so lets update the pool JSON file with the date and file the certFile was created diff --git a/cardano/mainnet/07b_deregStakepoolCert.sh b/cardano/mainnet/07b_deregStakepoolCert.sh index 07079065..31e81e20 100755 --- a/cardano/mainnet/07b_deregStakepoolCert.sh +++ b/cardano/mainnet/07b_deregStakepoolCert.sh @@ -183,8 +183,8 @@ echo #get live values -currentTip=$(get_currentTip) -ttl=$(get_currentTTL) +currentTip=$(get_currentTip); checkError "$?"; +ttl=$(( ${currentTip} + ${defTTL} )) echo -e "Current Slot-Height:\e[32m ${currentTip}\e[0m (setting TTL[invalid_hereafter] to ${ttl})" @@ -201,18 +201,40 @@ echo # # Checking UTXO Data of the source address and gathering data about total lovelaces and total assets # - #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in offlinemode from the transferFile - if ${onlineMode}; then + + #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in lightmode via API requests, in offlinemode from the transferFile + case ${workMode} in + "online") + #check that the node is fully synced, otherwise the query would mabye return a false state + if [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced or not running, please let your node sync to 100% first !\e[0m\n"; exit 1; fi showProcessAnimation "Query-UTXO: " & - utxo=$(${cardanocli} query utxo --address ${sendFromAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + utxo=$(${cardanocli} ${cliEra} query utxo --address ${sendFromAddr} 2> /dev/stdout); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + if [[ ${skipUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep -v "${skipUtxoWithAsset}" ); fi #if its set to keep utxos that contains certain policies, filter them out + if [[ ${onlyUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep "${onlyUtxoWithAsset}" ); utxo=$(echo -e "Header\n-----\n${utxo}"); fi #only use given utxos. rebuild the two header lines + if [[ ${utxoLimitCnt} -gt 0 ]]; then utxo=$(echo "${utxo}" | head -n $(( ${utxoLimitCnt} + 2 )) ); fi #if there was a utxo cnt limit set, reduce it (+2 for the header) showProcessAnimation "Convert-UTXO: " & utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; - #utxoJSON=$(${cardanocli} query utxo --address ${sendFromAddr} ${magicparam} --out-file /dev/stdout); checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; - else - readOfflineFile; #Reads the offlinefile into the offlineJSON variable - utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON}) - if [[ "${utxoJSON}" == null ]]; then echo -e "\e[35mPayment-Address not included in the offline transferFile, please include it first online!\e[0m\n"; exit; fi - fi + ;; + + "light") + showProcessAnimation "Query-UTXO-LightMode: " & + utxo=$(queryLight_UTXO "${sendFromAddr}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + if [[ ${skipUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep -v "${skipUtxoWithAsset}" ); fi #if its set to keep utxos that contains certain policies, filter them out + if [[ ${onlyUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep "${onlyUtxoWithAsset}" ); utxo=$(echo -e "Header\n-----\n${utxo}"); fi #only use given utxos. rebuild the two header lines + if [[ ${utxoLimitCnt} -gt 0 ]]; then utxo=$(echo "${utxo}" | head -n $(( ${utxoLimitCnt} + 2 )) ); fi #if there was a utxo cnt limit set, reduce it (+2 for the header) + showProcessAnimation "Convert-UTXO: " & + utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; + ;; + + + "offline") readOfflineFile; #Reads the offlinefile into the offlineJSON variable + utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON} 2> /dev/null) + if [[ "${utxoJSON}" == null ]]; then echo -e "\e[35mPayment-Address not included in the offline transferFile, please include it first online!\e[0m\n"; exit 1; fi + ;; + esac + txcnt=$(jq length <<< ${utxoJSON}) #Get number of UTXO entries (Hash#Idx), this is also the number of --tx-in for the transaction if [[ ${txcnt} == 0 ]]; then echo -e "\e[35mNo funds on the Source Address!\e[0m\n"; exit 1; else echo -e "\e[32m${txcnt} UTXOs\e[0m found on the Source Address!\n"; fi @@ -272,8 +294,20 @@ echo totalAssetsJSON=$( jq ". += {\"${assetHash}${point}${assetName}\":{amount: \"${newValue}\", name: \"${assetTmpName}\", bech: \"${assetBech}\"}}" <<< ${totalAssetsJSON}) if [[ "${assetTmpName:0:1}" == "." ]]; then assetTmpName=${assetTmpName:1}; else assetTmpName="{${assetTmpName}}"; fi - case ${assetHash} in - "${adahandlePolicyID}" ) #$adahandle + case "${assetHash}${assetTmpName:1:8}" in + "${adahandlePolicyID}000de140" ) #$adahandle cip-68 + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Own): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}00000000" ) #$adahandle virtual + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Vir): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}000643b0" ) #$adahandle reference + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Ref): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}"* ) #$adahandle cip-25 echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle: \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" ;; * ) #default @@ -340,11 +374,11 @@ if [[ ! "${transactionMessage}" == "{}" ]]; then fi #Read ProtocolParameters -if ${onlineMode}; then - protocolParametersJSON=$(${cardanocli} query protocol-parameters ${magicparam} ); #onlinemode - else - protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON}); #offlinemode - fi +case ${workMode} in + "online") protocolParametersJSON=$(${cardanocli} ${cliEra} query protocol-parameters);; #onlinemode + "light") protocolParametersJSON=${lightModeParametersJSON};; #lightmode + "offline") protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON});; #offlinemode +esac checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi minOutUTXO=$(calc_minOutUTXO "${protocolParametersJSON}" "${sendToAddr}+1000000${assetsOutString}") @@ -354,10 +388,10 @@ minOutUTXO=$(calc_minOutUTXO "${protocolParametersJSON}" "${sendToAddr}+1000000$ #Generate Dummy-TxBody file for fee calculation txBodyFile="${tempDir}/dummy.txbody" rm ${txBodyFile} 2> /dev/null -${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --certificate ${deregCertFile} --out-file ${txBodyFile} +${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --certificate ${deregCertFile} --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi -fee=$(${cardanocli} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} ${magicparam} --witness-count 2 --byron-witness-count 0 | awk '{ print $1 }') +fee=$(${cardanocli} ${cliEra} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} ${magicparam} --witness-count 2 --byron-witness-count 0 | awk '{ print $1 }') checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "\e[0mMinimum transfer Fee for ${txcnt}x TxIn & ${rxcnt}x TxOut & 1x Certificate: \e[32m $(convertToADA ${fee}) ADA / ${fee} lovelaces \e[90m" @@ -386,7 +420,7 @@ echo #Building unsigned transaction body rm ${txBodyFile} 2> /dev/null -${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --certificate ${deregCertFile} --out-file ${txBodyFile} +${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --certificate ${deregCertFile} --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi dispFile=$(cat ${txBodyFile}); if ${cropTxOutput} && [[ ${#dispFile} -gt 4000 ]]; then echo "${dispFile:0:4000} ... (cropped)"; else echo "${dispFile}"; fi @@ -410,7 +444,7 @@ if [[ -f "${deregPayName}.hwsfile" && -f "${poolName}.node.hwsfile" ]]; then #wi if [[ "${tmp^^}" =~ (ERROR|DISCONNECT) ]]; then echo -e "\e[35m${tmp}\e[0m\n"; exit 1; else echo -ne "\e[0mWitnessed ... "; fi checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - ${cardanocli} transaction assemble --tx-body-file ${txBodyFile} --witness-file ${txWitnessFile}-payment --witness-file ${txWitnessFile}-node --out-file ${txFile} + ${cardanocli} ${cliEra} transaction assemble --tx-body-file ${txBodyFile} --witness-file ${txWitnessFile}-payment --witness-file ${txWitnessFile}-node --out-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "Assembled ... \e[32mDONE\e[0m\n"; @@ -428,7 +462,7 @@ elif [[ -f "${deregPayName}.skey" && -f "${poolName}.node.skey" ]]; then #with t echo -e "\e[0mSign the unsigned transaction body with the payment \e[32m${deregPayName}.skey\e[0m & node \e[32m${poolName}.node.skey\e[0m: \e[32m ${txFile} \e[90m" echo - ${cardanocli} transaction sign --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON1}") --signing-key-file <(echo "${skeyJSON2}") ${magicparam} --out-file ${txFile} + ${cardanocli} ${cliEra} transaction sign --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON1}") --signing-key-file <(echo "${skeyJSON2}") ${magicparam} --out-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #forget the signing keys @@ -452,12 +486,15 @@ if [[ ${txSize} -le ${maxTxSize} ]]; then echo -e "\e[0mTransaction-Size: ${txSi else echo -e "\n\e[35mError - ${txSize} bytes Transaction-Size is too big! The maximum is currently ${maxTxSize} bytes.\e[0m\n"; exit 1; fi if ask "\e[33mDoes this look good for you? Continue ?" N; then + echo - if ${onlineMode}; then #onlinesubmit + case ${workMode} in + "online") + #onlinesubmit echo -ne "\e[0mSubmitting the transaction via the node... " - ${cardanocli} transaction submit --tx-file ${txFile} ${magicparam} + ${cardanocli} ${cliEra} transaction submit --tx-file ${txFile} + checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #No error, so lets update the pool JSON file with the date and file the certFile was registered on the blockchain - if [[ $? -eq 0 ]]; then file_unlock ${poolFile}.pool.json newJSON=$(cat ${poolFile}.pool.json | jq ". += {deregSubmitted: \"$(date -R)\"}") echo "${newJSON}" > ${poolFile}.pool.json @@ -465,22 +502,46 @@ if ask "\e[33mDoes this look good for you? Continue ?" N; then echo -e "\e[32mDONE\n" #Show the TxID - txID=$(${cardanocli} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" + txID=$(${cardanocli} ${cliEra} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + #Show the updated Stakepool-Info-JSON + echo + echo -e "\e[0mStakepool Info JSON:\e[32m ${poolFile}.pool.json \e[90m" + cat ${poolFile}.pool.json + echo + echo -e "\e[33mDon't de-register/delete your rewards staking account/address yet! You will receive the pool deposit fees on it!\n" + echo -e "\e[0m\n" + ;; + + "light") + #lightmode submit + showProcessAnimation "Submit-Transaction-LightMode: " & + txID=$(submitLight "${txFile}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${txID}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + #No error, so lets update the pool JSON file with the date and file the certFile was registered on the blockchain + file_unlock ${poolFile}.pool.json + newJSON=$(cat ${poolFile}.pool.json | jq ". += {deregSubmitted: \"$(date -R)\"}") + echo "${newJSON}" > ${poolFile}.pool.json + file_lock ${poolFile}.pool.json + echo -e "\e[0mSubmit-Transaction-LightMode: \e[32mDONE\n" - else - echo -e "\n\n\e[35mERROR (Code $?) !\e[0m"; exit 1; - fi + #Show the TxID + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + + #Show the updated Stakepool-Info-JSON echo echo -e "\e[0mStakepool Info JSON:\e[32m ${poolFile}.pool.json \e[90m" cat ${poolFile}.pool.json echo echo -e "\e[33mDon't de-register/delete your rewards staking account/address yet! You will receive the pool deposit fees on it!\n" echo -e "\e[0m\n" + ;; - else #offlinestore + + "offline") + #offlinestore txFileJSON=$(cat ${txFile} | jq .) offlineJSON=$( jq ".transactions += [ { date: \"$(date -R)\", type: \"PoolRetirement\", @@ -511,8 +572,13 @@ if ask "\e[33mDoes this look good for you? Continue ?" N; then else echo -e "\e[35mERROR - Could not verify the written data in the '$(basename ${offlineFile})'. Retry again or generate a new '$(basename ${offlineFile})'.\e[0m\n"; fi + ;; + + esac + + + - fi fi diff --git a/cardano/mainnet/08a_genStakingAddrRetireCert.sh b/cardano/mainnet/08a_genStakingAddrRetireCert.sh index 9ef8c59e..e0f60d8b 100755 --- a/cardano/mainnet/08a_genStakingAddrRetireCert.sh +++ b/cardano/mainnet/08a_genStakingAddrRetireCert.sh @@ -5,24 +5,130 @@ #load variables and functions from common.sh . "$(dirname "$0")"/00_common.sh - if [[ $# -eq 1 && ! $1 == "" ]]; then addrName="$(dirname $1)/$(basename $(basename $1 .addr) .staking)"; addrName=${addrName/#.\//}; else echo "ERROR - Usage: $0 "; exit 2; fi #Checks for needed files -if [ ! -f "${addrName}.staking.vkey" ]; then echo -e "\n\e[35mERROR - \"${addrName}.staking.vkey\" does not exist! Maybe a typo?\n\e[0m"; exit 1; fi +if [ ! -f "${addrName}.staking.addr" ]; then echo -e "\n\e[35mERROR - \"${addrName}.staking.addr\" does not exist! Maybe a typo?\n\e[0m"; exit 1; fi -#create a stake-address de-registration certificate -file_unlock ${addrName}.staking.dereg-cert -${cardanocli} stake-address deregistration-certificate --stake-verification-key-file ${addrName}.staking.vkey --out-file ${addrName}.staking.dereg-cert -checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi -file_lock ${addrName}.staking.dereg-cert +#read the content of the provided address file +stakingAddr=$(cat ${addrName}.staking.addr) + +#What type of Address is it? Stake? +typeOfAddr=$(get_addressType "${stakingAddr}") +if [[ ${typeOfAddr} != ${addrTypeStake} ]]; then #not a stake address + echo -e "\n\e[35mERROR - \"${addrName}.staking.addr\" with the content \"${stakingAddr}\" is not a valid stake address!\n\e[0m"; + exit 1 +fi -echo -e "\e[0mStaking-Address-DeRegistration-Certificate built: \e[32m ${addrName}.staking.dereg-cert \e[90m" -cat ${addrName}.staking.dereg-cert echo +echo -e "\e[0mChecking status of Stake Address:\e[32m ${stakingAddr}\e[0m" echo -echo -e "\e[35mIf you wanna de-register the Staking-Address, please use script 08b now!\e[0m" + +#Get stake address info. When in online mode of course from the node and the chain, in light mode via koios, in offlinemode from the transferFile +case ${workMode} in + + "online") showProcessAnimation "Query-StakeAddress-Info: " & + rewardsJSON=$(${cardanocli} ${cliEra} query stake-address-info --address ${stakingAddr} 2> /dev/null ) + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${rewardsJSON}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + rewardsJSON=$(jq -rc . <<< "${rewardsJSON}") + ;; + + "light") showProcessAnimation "Query-StakeAddress-Info-LightMode: " & + rewardsJSON=$(queryLight_stakeAddressInfo "${stakingAddr}") + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${rewardsJSON}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + + "offline") readOfflineFile; #Reads the offlinefile into the offlineJSON variable + rewardsJSON=$(jq -r ".address.\"${stakingAddr}\".rewardsJSON" <<< ${offlineJSON} 2> /dev/null) + if [[ "${rewardsJSON}" == null ]]; then echo -e "\e[35mAddress not included in the offline transferFile, please include it first online!\e[0m\n"; exit; fi + ;; + +esac + +#Check if the stake address is registered on the chain, if not, we don't need to unregister it +{ read rewardsEntryCnt; read delegationPoolID; read keyDepositFee; read rewardsAmount; } <<< $(jq -r "length, .[0].delegation // .[0].stakeDelegation, .[0].delegationDeposit, .[0].rewardAccountBalance" <<< ${rewardsJSON}) + +#Checking about the content +if [[ ${rewardsEntryCnt} == 0 ]]; then #not registered yet + echo -e "\e[33mStaking Address is NOT on the chain, register it first with script 03b ...\e[0m\n"; + exit; + + else # registered + + echo -e "\e[0mStaking Address is \e[32mregistered\e[0m on the chain with a deposit fee:\e[32m ${keyDepositFee} lovelaces\e[0m\n" + + #If delegated to a pool, show the current pool ID + if [[ ! ${delegationPoolID} == null ]]; then + echo -e "Account is delegated to a Pool with ID: \e[32m${delegationPoolID}\e[0m"; + + if [[ ${onlineMode} == true && ${koiosAPI} != "" ]]; then + + #query poolinfo via poolid on koios + errorcnt=0; error=-1; + showProcessAnimation "Query Pool-Info via Koios: " & + while [[ ${errorcnt} -lt 5 && ${error} -ne 0 ]]; do #try a maximum of 5 times to request the information + error=0 + response=$(curl -sL -m 30 -X POST -w "---spo-scripts---%{http_code}" "${koiosAPI}/pool_info" -H "Accept: application/json" -H "Content-Type: application/json" -d "{\"_pool_bech32_ids\":[\"${delegationPoolID}\"]}" 2> /dev/null) + if [[ $? -ne 0 ]]; then error=1; sleep 1; fi; #if there is an error, wait for a second and repeat + errorcnt=$(( ${errorcnt} + 1 )) + done + stopProcessAnimation; + + #if no error occured, split the response string into JSON content and the HTTP-ResponseCode + if [[ ${error} -eq 0 && "${response}" =~ (.*)---spo-scripts---([0-9]*)* ]]; then + + responseJSON="${BASH_REMATCH[1]}" + responseCode="${BASH_REMATCH[2]}" + + #if the responseCode is 200 (OK) and the received json only contains one entry in the array (will also not be 1 if not a valid json) + if [[ ${responseCode} -eq 200 && $(jq ". | length" 2> /dev/null <<< ${responseJSON}) -eq 1 ]]; then + { read poolNameInfo; read poolTickerInfo; read poolStatusInfo; } <<< $(jq -r ".[0].meta_json.name // \"-\", .[0].meta_json.ticker // \"-\", .[0].pool_status // \"-\"" 2> /dev/null <<< ${responseJSON}) + echo -e " \t\e[0mInformation about the Pool: \e[32m${poolNameInfo} (${poolTickerInfo})\e[0m" + echo -e " \t\e[0m Status: \e[32m${poolStatusInfo}\e[0m" + echo + unset poolNameInfo poolTickerInfo poolStatusInfo + fi #responseCode & jsoncheck + + fi #error & response + unset errorcnt error + + fi #onlineMode & koiosAPI + + else + echo -e "\e[0mAccount is not delegated to a Pool !\n"; + fi ## ${delegationPoolID} == null + + if [[ ${rewardsAmount} == null || ${rewardsAmount} -ne 0 ]]; then echo -e "\e[33mStake account still holds \e[0m$(convertToADA ${rewardsAmount}) ADA\e[33m of rewards.\nYou need to claim them first via script 01_claimRewards.sh !\e[0m\n"; exit; fi + +fi ## ${rewardsEntryCnt} == 0 + +#generate the certificate depending on the era with/without the --key-reg-deposit-amt parameter +case ${cliEra} in + + "babbage"|"alonzo"|"mary"|"allegra"|"shelley") + echo -e "\e[0mGenerate Retirement-Certificate in ${cliEra} format ...\e[0m\n" + deregCert=$(${cardanocli} ${cliEra} stake-address deregistration-certificate --stake-address "${stakingAddr}" --out-file /dev/stdout 2> /dev/null) + ;; + + *) #conway and later + echo -e "\e[0mGenerate Retirement-Certificate with the used deposit fee:\e[32m ${keyDepositFee} lovelaces\e[0m\n" + deregCert=$(${cardanocli} ${cliEra} stake-address deregistration-certificate --stake-address "${stakingAddr}" --key-reg-deposit-amt "${keyDepositFee}" --out-file /dev/stdout 2> /dev/null) + ;; + +esac +checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi +file_unlock "${addrName}.staking.dereg-cert" +echo -e "${deregCert}" > "${addrName}.staking.dereg-cert" 2> /dev/null +if [ $? -ne 0 ]; then echo -e "\n\e[35mERROR - Could not write out the certificate file ${addrName}.staking.dereg-cert !\n\e[0m"; exit 1; fi +file_lock "${addrName}.staking.dereg-cert" +unset deregCert + +echo -e "\e[0mStake Address Retirement-Certificate built:\e[32m ${addrName}.staking.dereg-cert \e[90m" +cat "${addrName}.staking.dereg-cert" + +echo -e "\e[0m" + +echo -e "\e[33mPlease use script 08b now to submit the Retirement-Certificate!\e[0m" echo -echo -e "\e[0m\n" diff --git a/cardano/mainnet/08b_deregStakingAddrCert.sh b/cardano/mainnet/08b_deregStakingAddrCert.sh index b4caad77..2ac7a1c6 100755 --- a/cardano/mainnet/08b_deregStakingAddrCert.sh +++ b/cardano/mainnet/08b_deregStakingAddrCert.sh @@ -153,52 +153,127 @@ if [[ ! "${transactionMessage}" == "{}" ]]; then fi - - +#---------------------------------------------------- echo echo -e "\e[0mDe-Register (retire) the Staking Address\e[32m ${stakeAddr}.addr\e[0m with funds from Address\e[32m ${fromAddr}.addr\e[0m" echo - - checkAddr=$(cat ${stakeAddr}.addr) typeOfAddr=$(get_addressType "${checkAddr}") #Do a check that the given address is really a Stake Address if [[ ! ${typeOfAddr} == ${addrTypeStake} ]]; then echo -e "\e[35mERROR: Given Staking Address (${checkAddr}) is not a valid Stake Address !\e[0m\n"; exit 2; fi -#If in online mode, do a check it the StakeKey is registered on the chain + +#If in online/light mode, do a check if the StakeKey is already registered on the chain if ${onlineMode}; then - echo -e "\e[0mChecking current ChainStatus of Stake-Address: ${checkAddr}" - echo + echo -e "\e[0mChecking current ChainStatus of Stake-Address:\e[32m ${checkAddr}\e[0m" - rewardsAmount=$(${cardanocli} query stake-address-info --address ${checkAddr} ${magicparam} | jq -r "flatten | .[0].rewardAccountBalance") - checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - delegationPoolID=$(${cardanocli} query stake-address-info --address ${checkAddr} ${magicparam} | jq -r "flatten | .[0].delegation") - checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi + #Get rewards state data for the address. When in online mode of course from the node and the chain, in light mode via koios + case ${workMode} in + + "online") showProcessAnimation "Query-StakeAddress-Info: " & + rewardsJSON=$(${cardanocli} ${cliEra} query stake-address-info --address ${checkAddr} 2> /dev/stdout ) + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${rewardsJSON}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + rewardsJSON=$(jq -rc . <<< "${rewardsJSON}") + ;; + + "light") showProcessAnimation "Query-StakeAddress-Info-LightMode: " & + rewardsJSON=$(queryLight_stakeAddressInfo "${checkAddr}") + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${rewardsJSON}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + ;; + + esac + + rewardsEntryCnt=$(jq -r 'length' <<< ${rewardsJSON}) #Checking about the content - if [[ ${rewardsAmount} == null ]]; then echo -e "\e[33mStaking Address is NOT on the chain, no need to de-register it !\e[0m\n"; exit; - else echo -e "\e[0mStaking Address is registered on the chain, we continue ...\n" - fi + if [[ ${rewardsEntryCnt} == 0 ]]; then #not registered yet + echo -e "\e[33mStaking Address is NOT on the chain, register it first with script 03b ...\e[0m\n"; + exit -fi + else #registered + echo -e "\e[0mStake Address is registered on the chain, we continue ...\e[0m\n" + + delegationPoolID=$(jq -r ".[0].delegation // .[0].stakeDelegation" <<< ${rewardsJSON}) + + #If delegated to a pool, show the current pool ID + if [[ ! ${delegationPoolID} == null ]]; then + + echo -e "Account is delegated to a Pool with ID: \e[32m${delegationPoolID}\e[0m"; + + if [[ ${onlineMode} == true && ${koiosAPI} != "" ]]; then + + #query poolinfo via poolid on koios + errorcnt=0; error=-1; + showProcessAnimation "Query Pool-Info via Koios: " & + while [[ ${errorcnt} -lt 5 && ${error} -ne 0 ]]; do #try a maximum of 5 times to request the information + error=0 + response=$(curl -sL -m 30 -X POST -w "---spo-scripts---%{http_code}" "${koiosAPI}/pool_info" -H "Accept: application/json" -H "Content-Type: application/json" -d "{\"_pool_bech32_ids\":[\"${delegationPoolID}\"]}" 2> /dev/null) + if [[ $? -ne 0 ]]; then error=1; sleep 1; fi; #if there is an error, wait for a second and repeat + errorcnt=$(( ${errorcnt} + 1 )) + done + stopProcessAnimation; + + #if no error occured, split the response string into JSON content and the HTTP-ResponseCode + if [[ ${error} -eq 0 && "${response}" =~ (.*)---spo-scripts---([0-9]*)* ]]; then + + responseJSON="${BASH_REMATCH[1]}" + responseCode="${BASH_REMATCH[2]}" + + #if the responseCode is 200 (OK) and the received json only contains one entry in the array (will also not be 1 if not a valid json) + if [[ ${responseCode} -eq 200 && $(jq ". | length" 2> /dev/null <<< ${responseJSON}) -eq 1 ]]; then + { read poolNameInfo; read poolTickerInfo; read poolStatusInfo; } <<< $(jq -r ".[0].meta_json.name // \"-\", .[0].meta_json.ticker // \"-\", .[0].pool_status // \"-\"" 2> /dev/null <<< ${responseJSON}) + echo -e " \t\e[0mInformation about the Pool: \e[32m${poolNameInfo} (${poolTickerInfo})\e[0m" + echo -e " \t\e[0m Status: \e[32m${poolStatusInfo}\e[0m" + echo + unset poolNameInfo poolTickerInfo poolStatusInfo + fi #responseCode & jsoncheck + + fi #error & response + unset errorcnt error + + fi #onlineMode & koiosAPI + + else + echo -e "\e[0mAccount is not delegated to a Pool !\n"; + fi + + unset poolNameInfo, poolTickerInfo, poolStatusInfo + fi ## ${rewardsEntryCnt} == 0 + +fi ## ${onlineMode} == true #get values to deregister the staking address on the blockchain +#starting with conway era we can have a different keyDeposit value than 2000000 lovelaces +#lets read out the needed value from the already generated deregistration certificate file +echo -ne "\e[0mReading Stake Address Deposit Fee from certificate file:\e[32m ${stakeAddr}.dereg-cert\e[0m " +cborHex=$(jq -r ".cborHex" "${stakeAddr}.dereg-cert" 2> /dev/null); +if [ $? -ne 0 ]; then echo -e "\n\n\e[35mError - Couldn't read the deregistration certificate file '${stakeAddr}.dereg-cert' !\e[0m"; echo; exit 2; fi +stakeAddressDepositFee=$(int_from_cbor "${cborHex:68}") #needed deposit fee starts at index 68, lets decode the unsigned integer number +if [[ ${stakeAddressDepositFee} == "error" ]]; then #this means it is an older certificate (pre conway), so the default value is 2000000 lovelaces + stakeAddressDepositFee=2000000; #default value pre conway + echo -e "(pre conway cert)" + else + echo -e "" +fi +echo -e "\e[0mStake Address Deposit Fee used for registration: \e[32m $(convertToADA ${stakeAddressDepositFee}) ADA / ${stakeAddressDepositFee} lovelaces\e[0m" +echo +echo + #get live values -currentTip=$(get_currentTip) -ttl=$(get_currentTTL) +currentTip=$(get_currentTip); checkError "$?"; +ttl=$(( ${currentTip} + ${defTTL} )) echo -e "Current Slot-Height:\e[32m ${currentTip}\e[0m (setting TTL[invalid_hereafter] to ${ttl})" -rxcnt="1" #transmit to one destination addr. all utxos will be sent back to the fromAddr +rxcnt="1" #send to one destination addr. all utxos will be sent back to the fromAddr sendFromAddr=$(cat ${fromAddr}.addr); check_address "${sendFromAddr}"; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; -toAddr=${fromAddr} -sendToAddr=$(cat ${fromAddr}.addr); check_address "${sendToAddr}"; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; +toAddr=${fromAddr}; sendToAddr=$(cat ${fromAddr}.addr); echo echo -e "Pay fees from Address\e[32m ${fromAddr}.addr\e[0m: ${sendFromAddr}" @@ -208,18 +283,31 @@ echo # # Checking UTXO Data of the source address and gathering data about total lovelaces and total assets # - #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in offlinemode from the transferFile - if ${onlineMode}; then + + #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in lightmode via API requests, in offlinemode from the transferFile + case ${workMode} in + "online") #check that the node is fully synced, otherwise the query would mabye return a false state + if [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced or not running, please let your node sync to 100% first !\e[0m\n"; exit 1; fi showProcessAnimation "Query-UTXO: " & - utxo=$(${cardanocli} query utxo --address ${sendFromAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + utxo=$(${cardanocli} ${cliEra} query utxo --address ${sendFromAddr} 2> /dev/stdout); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; showProcessAnimation "Convert-UTXO: " & utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; - #utxoJSON=$(${cardanocli} query utxo --address ${sendFromAddr} ${magicparam} --out-file /dev/stdout); checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; - else - readOfflineFile; #Reads the offlinefile into the offlineJSON variable - utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON}) - if [[ "${utxoJSON}" == null ]]; then echo -e "\e[35mPayment-Address not included in the offline transferFile, please include it first online!\e[0m\n"; exit; fi - fi + ;; + + "light") showProcessAnimation "Query-UTXO-LightMode: " & + utxo=$(queryLight_UTXO "${sendFromAddr}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + showProcessAnimation "Convert-UTXO: " & + utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; + ;; + + "offline") readOfflineFile; #Reads the offlinefile into the offlineJSON variable + utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON} 2> /dev/null) + if [[ "${utxoJSON}" == null ]]; then echo -e "\e[35mPayment-Address not included in the offline transferFile, please include it first online!\e[0m\n"; exit 1; fi + ;; + esac + txcnt=$(jq length <<< ${utxoJSON}) #Get number of UTXO entries (Hash#Idx), this is also the number of --tx-in for the transaction if [[ ${txcnt} == 0 ]]; then echo -e "\e[35mNo funds on the Source Address!\e[0m\n"; exit 1; else echo -e "\e[32m${txcnt} UTXOs\e[0m found on the Source Address!\n"; fi @@ -245,7 +333,6 @@ echo utxoHashIndex=${utxoHashIndexArray[${tmpCnt}]} utxoAmount=${utxoLovelaceArray[${tmpCnt}]} #Lovelaces totalLovelaces=$(bc <<< "${totalLovelaces} + ${utxoAmount}" ) -# echo -e "Hash#Index: ${utxoHashIndex}\tAmount: ${utxoAmount}"; echo -e "Hash#Index: ${utxoHashIndex}\tADA: $(convertToADA ${utxoAmount}) \e[90m(${utxoAmount} lovelaces)\e[0m"; if [[ ! "${utxoDatumHashArray[${tmpCnt}]}" == null ]]; then echo -e " DatumHash: ${utxoDatumHashArray[${tmpCnt}]}"; fi assetsEntryCnt=${assetsEntryCntArray[${tmpCnt}]} @@ -279,8 +366,20 @@ echo totalAssetsJSON=$( jq ". += {\"${assetHash}${point}${assetName}\":{amount: \"${newValue}\", name: \"${assetTmpName}\", bech: \"${assetBech}\"}}" <<< ${totalAssetsJSON}) if [[ "${assetTmpName:0:1}" == "." ]]; then assetTmpName=${assetTmpName:1}; else assetTmpName="{${assetTmpName}}"; fi - case ${assetHash} in - "${adahandlePolicyID}" ) #$adahandle + case "${assetHash}${assetTmpName:1:8}" in + "${adahandlePolicyID}000de140" ) #$adahandle cip-68 + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Own): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}00000000" ) #$adahandle virtual + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Vir): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}000643b0" ) #$adahandle reference + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Ref): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}"* ) #$adahandle cip-25 echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle: \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" ;; * ) #default @@ -296,7 +395,6 @@ echo echo -e "\e[0m-----------------------------------------------------------------------------------------------------" echo -e "Total ADA on the Address:\e[32m $(convertToADA ${totalLovelaces}) ADA / ${totalLovelaces} lovelaces \e[0m\n" - totalPolicyIDsCnt=$(echo -ne "${totalPolicyIDsLIST}" | sort | uniq | wc -l) totalAssetsCnt=$(jq length <<< ${totalAssetsJSON}); if [[ ${totalAssetsCnt} -gt 0 ]]; then @@ -346,12 +444,14 @@ if [[ ! "${transactionMessage}" == "{}" ]]; then echo -e "\e[0mInclude Transaction-Message-Metadata-File:\e[32m ${transactionMessageMetadataFile}\n\e[90m"; cat ${transactionMessageMetadataFile}; echo -e "\e[0m"; fi + #Read ProtocolParameters -if ${onlineMode}; then - protocolParametersJSON=$(${cardanocli} query protocol-parameters ${magicparam} ); #onlinemode - else - protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON}); #offlinemode - fi +case ${workMode} in + "online") protocolParametersJSON=$(${cardanocli} ${cliEra} query protocol-parameters);; #onlinemode + "light") protocolParametersJSON=${lightModeParametersJSON};; #lightmode + "offline") readOfflineFile; #Reads the offlinefile into the offlineJSON variable + protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON});; #offlinemode +esac checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi minOutUTXO=$(calc_minOutUTXO "${protocolParametersJSON}" "${sendToAddr}+1000000${assetsOutString}") @@ -362,24 +462,25 @@ minOutUTXO=$(calc_minOutUTXO "${protocolParametersJSON}" "${sendToAddr}+1000000$ #Generate Dummy-TxBody file for fee calculation txBodyFile="${tempDir}/dummy.txbody" rm ${txBodyFile} 2> /dev/null -${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --certificate ${stakeAddr}.dereg-cert --out-file ${txBodyFile} +${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --certificate ${stakeAddr}.dereg-cert --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi -fee=$(${cardanocli} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} ${magicparam} --witness-count 2 --byron-witness-count 0 | awk '{ print $1 }') +fee=$(${cardanocli} ${cliEra} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} ${magicparam} --witness-count 2 --byron-witness-count 0 | awk '{ print $1 }') checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "\e[0mMimimum transfer Fee for ${txcnt}x TxIn & ${rxcnt}x TxOut & 1x Certificate: \e[32m $(convertToADA ${fee}) ADA / ${fee} lovelaces \e[90m" -stakeAddressDepositFee=$(jq -r .stakeAddressDeposit <<< ${protocolParametersJSON}) +echo echo -e "\e[0mStake Address Deposit Fee that will be refunded: \e[32m $(convertToADA ${stakeAddressDepositFee}) ADA / ${stakeAddressDepositFee} lovelaces \e[90m" -minDeregistrationFund=$(( ${fee} )) +minDeregistrationFund=$(( ${minOutUTXO} + ${fee} - ${stakeAddressDepositFee} )) +if [[ ${minDeregistrationFund} -lt ${minOutUTXO} ]]; then minDeregistrationFund=${minOutUTXO}; fi echo -echo -e "\e[0mMimimum funds required for de-registration: \e[32m 0 ADA / 0 lovelaces \e[90mbecause the stakeAddressDepositFee refund will pay for it, maybe more needed for assets sending!" +echo -e "\e[0mMimimum funds required for de-registration: \e[32m $(convertToADA ${minDeregistrationFund}) ADA / ${minDeregistrationFund} lovelaces \e[90mbecause the stakeAddressDepositFee refund will also pay for it, maybe more needed for assets sending!" echo #calculate new balance for destination address -lovelacesToSend=$(( ${totalLovelaces}-${minDeregistrationFund}+${stakeAddressDepositFee} )) +lovelacesToSend=$(( ${totalLovelaces} - ${fee} + ${stakeAddressDepositFee} )) echo -e "\e[0mLovelaces that will be returned to payment Address (UTXO-Sum minus Fees plus KeyDepositRefunds): \e[32m $(convertToADA ${lovelacesToSend}) ADA / ${lovelacesToSend} lovelaces \e[90m (min. required ${minOutUTXO} lovelaces)" echo @@ -397,7 +498,7 @@ echo #Building unsigned transaction body rm ${txBodyFile} 2> /dev/null -${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --certificate ${stakeAddr}.dereg-cert --out-file ${txBodyFile} +${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --certificate ${stakeAddr}.dereg-cert --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi dispFile=$(cat ${txBodyFile}); if ${cropTxOutput} && [[ ${#dispFile} -gt 4000 ]]; then echo "${dispFile:0:4000} ... (cropped)"; else echo "${dispFile}"; fi @@ -427,7 +528,7 @@ if [[ -f "${fromAddr}.hwsfile" && -f "${stakeAddr}.hwsfile" && "${paymentName}" if [[ "${tmp^^}" =~ (ERROR|DISCONNECT) ]]; then echo -e "\e[35m${tmp}\e[0m\n"; exit 1; else echo -ne "\e[0mWitnessed ... "; fi checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - ${cardanocli} transaction assemble --tx-body-file ${txBodyFile} --witness-file ${txWitnessFile}-payment --witness-file ${txWitnessFile}-staking --out-file ${txFile} + ${cardanocli} ${cliEra} transaction assemble --tx-body-file ${txBodyFile} --witness-file ${txWitnessFile}-payment --witness-file ${txWitnessFile}-staking --out-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "Assembled ... \e[32mDONE\e[0m\n"; @@ -441,7 +542,7 @@ elif [[ -f "${stakeAddr}.skey" && -f "${fromAddr}.skey" ]]; then #with the norma echo -e "\e[0mSign the unsigned transaction body with the \e[32m${fromAddr}.skey\e[0m & \e[32m${stakeAddr}.skey\e[0m: \e[32m ${txFile} \e[90m" echo - ${cardanocli} transaction sign --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON1}") --signing-key-file <(echo "${skeyJSON2}") ${magicparam} --out-file ${txFile} + ${cardanocli} ${cliEra} transaction sign --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON1}") --signing-key-file <(echo "${skeyJSON2}") ${magicparam} --out-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #forget the signing keys @@ -467,20 +568,37 @@ if [[ ${txSize} -le ${maxTxSize} ]]; then echo -e "\e[0mTransaction-Size: ${txSi if ask "\e[33mDoes this look good for you, continue ?" N; then + echo - if ${onlineMode}; then #onlinesubmit + case ${workMode} in + "online") + #onlinesubmit echo -ne "\e[0mSubmitting the transaction via the node... " - ${cardanocli} transaction submit --tx-file ${txFile} ${magicparam} - checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi + ${cardanocli} ${cliEra} transaction submit --tx-file ${txFile} + if [ $? -ne 0 ]; then echo -e "\n\e[35mError - Make sure the pool is already registered.\n\e[0m\n"; exit $?; fi echo -e "\e[32mDONE\n" #Show the TxID - txID=$(${cardanocli} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" + txID=$(${cardanocli} ${cliEra} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; - else #offlinestore + "light") + #lightmode submit + showProcessAnimation "Submit-Transaction-LightMode: " & + txID=$(submitLight "${txFile}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${txID}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + echo -e "\e[0mSubmit-Transaction-LightMode: \e[32mDONE\n" + + #Show the TxID + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; + + + "offline") + #offlinestore txFileJSON=$(cat ${txFile} | jq .) offlineJSON=$( jq ".transactions += [ { date: \"$(date -R)\", type: \"StakeKeyDeRegistration\", @@ -494,7 +612,6 @@ if ask "\e[33mDoes this look good for you, continue ?" N; then #Write the new offileFile content offlineJSON=$( jq ".history += [ { date: \"$(date -R)\", action: \"signed staking key deregistration transaction for '${stakeAddr}', payment via '${fromAddr}'\" } ]" <<< ${offlineJSON}) offlineJSON=$( jq ".general += {offlineCLI: \"${versionCLI}\" }" <<< ${offlineJSON}) - offlineJSON=$( jq ".general += {offlineNODE: \"${versionNODE}\" }" <<< ${offlineJSON}) echo "${offlineJSON}" > ${offlineFile} #Readback the tx content and compare it to the current one readback=$(cat ${offlineFile} | jq -r ".transactions[-1].txJSON") @@ -504,8 +621,9 @@ if ask "\e[33mDoes this look good for you, continue ?" N; then else echo -e "\e[35mERROR - Could not verify the written data in the '$(basename ${offlineFile})'. Retry again or generate a new '$(basename ${offlineFile})'.\e[0m\n"; fi + ;; - fi + esac #workMode fi diff --git a/cardano/mainnet/09a_catalystVote.sh b/cardano/mainnet/09a_catalystVote.sh index 6a577250..80aa6008 100755 --- a/cardano/mainnet/09a_catalystVote.sh +++ b/cardano/mainnet/09a_catalystVote.sh @@ -273,40 +273,17 @@ case ${1,,} in typeOfAddr=$(get_addressType "${rewardsPayoutAddr}"); checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; if [[ ! ${typeOfAddr} == ${addrTypePayment} ]]; then echo -e "\n\e[35mERROR - \"${rewardsAcct}.addr\" does not contain a valid payment address!\e[0m"; exit 1; fi - #check if its an root adahandle (without a @ char) - elif checkAdaRootHandleFormat "${rewardsAcct}"; then + #check if its an adahandle (root/sub/virtual) + elif checkAdaHandleFormat "${rewardsAcct}"; then + addrName=${allParameters[3]} - if ${offlineMode}; then echo -e "\n\e[35mERROR - Adahandles are only supported in Online mode.\n\e[0m"; exit 1; fi - adahandleName=${addrName,,} - assetNameHex=$(convert_assetNameASCII2HEX ${adahandleName:1}) - #query classic cip-25 adahandle asset holding address via koios - showProcessAnimation "Query Adahandle(CIP-25) into holding address: " & - response=$(curl -s -m 10 -X GET "${koiosAPI}/asset_address_list?_asset_policy=${adahandlePolicyID}&_asset_name=${assetNameHex}" -H "Accept: application/json" 2> /dev/null) - stopProcessAnimation; - #check if the received json only contains one entry in the array (will also not be 1 if not a valid json) - if [[ $(jq ". | length" 2> /dev/null <<< ${response}) -ne 1 ]]; then - #query classic cip-68 adahandle asset holding address via koios - showProcessAnimation "Query Adahandle(CIP-68) into holding address: " & - response=$(curl -s -m 10 -X GET "${koiosAPI}/asset_address_list?_asset_policy=${adahandlePolicyID}&_asset_name=000de140${assetNameHex}" -H "Accept: application/json" 2> /dev/null) - stopProcessAnimation; - #check if the received json only contains one entry in the array (will also not be 1 if not a valid json) - if [[ $(jq ". | length" 2> /dev/null <<< ${response}) -ne 1 ]]; then echo -e "\n\e[35mCould not resolve Adahandle to an address.\n\e[0m"; exit 1; fi - assetNameHex="000de140${assetNameHex}" - fi - addrName=$(jq -r ".[0].payment_address" <<< ${response} 2> /dev/null) - typeOfAddr=$(get_addressType "${addrName}"); - if [[ ${typeOfAddr} != ${addrTypePayment} ]]; then echo -e "\n\e[35mERROR - Resolved address '${addrName}' is not a valid payment address.\n\e[0m"; exit 1; fi; - showProcessAnimation "Verify Adahandle is on resolved address: " & - utxo=$(${cardanocli} query utxo --address ${addrName} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; - if [[ $(grep "${adahandlePolicyID}.${assetNameHex} " <<< ${utxo} | wc -l) -ne 1 ]]; then - echo -e "\n\e[35mERROR - Resolved address '${addrName}' does not hold the \$adahandle '${adahandleName}' !\n\e[0m"; exit 1; fi; - echo -e "\e[0mFound \$adahandle '${adahandleName}' on Address:\e[32m ${addrName}\e[0m\n" - rewardsPayoutAddr=${addrName} - - - elif checkAdaSubHandleFormat "${addrName}"; then - echo -e "\n\e[33mINFO - AdaSubHandles are not supported yet.\n\e[0m"; exit 1; + adahandleName=${addrName,,} + + #resolve given adahandle into address + resolveAdahandle "${adahandleName}" "rewardsPayoutAddr" #if successful, it resolves the adahandle and writes it out into the variable 'rewardsPayoutAddr'. also sets the variable 'utxo' if possible + unset utxo + #resolveAdahandle did not exit with an error, so we resolved it else #try it as a direct payment bech address rewardsPayoutAddr=$(trimString "${allParameters[3]}") @@ -377,8 +354,7 @@ case ${1,,} in done - currentTip=$(get_currentTip) #we use the current slotHeight as the nonce parameter - if [ $? -ne 0 ]; then exit $?; fi + currentTip=$(get_currentTip); checkError "$?"; #we use the current slotHeight as the nonce parameter #add the reward address, nonce and networkmagic to the parameterSet cardanoSignerParameters+="--payment-address ${rewardsPayoutAddr} --nonce ${currentTip} ${magicparam} " @@ -447,8 +423,7 @@ case ${1,,} in if [ -f "${votingMetaFile}" ]; then #all good echo -e "\e[0mThe Metadata-Registration-CBOR File \"\e[32m${votingMetaFile}\e[0m\" was generated. :-)\n\nYou can now submit it on the chain by including it in a transaction with Script: 01_sendLovelaces.sh\nExample:\e[33m 01_sendLovelaces.sh mywallet mywallet min ${votingMetaFile}\n\e[0m"; - if checkAdaRootHandleFormat "${rewardsAcct}"; then echo -e "\e[33mBe aware, the rewards address is now fixed. Moving the rootAdaHandle to another address will not change the rewards address!!!\e[0m\n"; fi - if checkAdaSubHandleFormat "${rewardsAcct}"; then echo -e "\e[33mBe aware, the rewards address is now fixed. Moving the subAdaHandle to another address will not change the rewards address!!!\e[0m\n"; fi + if checkAdaHandleFormat "${rewardsAcct}"; then echo -e "\e[33mBe aware, the rewards address is now fixed. Moving the AdaHandle to another address will not change the rewards address!!!\e[0m\n"; fi echo else #hmm, something went wrong echo -e "\e[35mError - Something went wrong while generating the \"${votingMetaFile}\" metadata file !\e[0m\n"; exit 1; diff --git a/cardano/mainnet/0x_importHelper.sh b/cardano/mainnet/0x_importHelper.sh index b0df4ee7..756c4437 100755 --- a/cardano/mainnet/0x_importHelper.sh +++ b/cardano/mainnet/0x_importHelper.sh @@ -74,7 +74,7 @@ elif ${onlineMode}; then echo -ne "\e[0mFetching Pooldata online via koios for PoolID: '\e[32m${poolIDBech}\e[0m' ... "; #query poolinfo via poolid on koios - importJSON=$(curl -s -m 10 -X POST "${koiosAPI}/pool_info" -H "Accept: application/json" -H "Content-Type: application/json" -d "{\"_pool_bech32_ids\":[\"${poolIDBech}\"]}" 2> /dev/null) + importJSON=$(curl -sL -m 30 -X POST "${koiosAPI}/pool_info" -H "Accept: application/json" -H "Content-Type: application/json" -d "{\"_pool_bech32_ids\":[\"${poolIDBech}\"]}" 2> /dev/null) #check if the received json only contains one entry in the array (will also not be 1 if not a valid json) if [[ $(jq ". | length" 2> /dev/null <<< ${importJSON}) -ne 1 ]]; then echo -e "\e[33mERROR, can't fetch the current online pool data from '${koiosAPI}/pool_info' !\e[0m\n"; exit 1; fi @@ -89,7 +89,7 @@ elif ${onlineMode}; then echo -ne "\e[0mFetching latest Pool-Update online via koios for PoolID: '\e[32m${poolIDBech}\e[0m' ... "; #query poolinfo via poolid on koios - latestUpdateJSON=$(curl -s -m 10 -X GET "${koiosAPI}/pool_updates?_pool_bech32=${poolIDBech}" -H "Accept: application/json" 2> /dev/null | jq -r .[0] 2> /dev/null) + latestUpdateJSON=$(curl -sL -m 30 -X GET "${koiosAPI}/pool_updates?_pool_bech32=${poolIDBech}" -H "Accept: application/json" 2> /dev/null | jq -r .[0] 2> /dev/null) #check if the received json only contains one entry in the array (will also not be 1 if not a valid json) if [[ ${latestUpdateJSON} == "" ]]; then echo -e "\e[33mERROR, can't fetch the latest pool update from '${koiosAPI}/pool_updates' !\e[0m\n"; exit 1; fi @@ -245,7 +245,7 @@ do done -#Add current date as regSubmitted entry, if because the pool is already registered on the chain +#Add current date as regSubmitted entry, if the pool is already registered on the chain if [[ "${poolStatus}" == "registered" ]]; then poolJSON=$(jq ".regEpoch = \"${poolLastUpdateEpoch}\"" <<< ${poolJSON}) poolJSON=$(jq ".regSubmitted = \"$(date -R --date=@${poolLastUpdateTime})\"" <<< ${poolJSON}) diff --git a/cardano/mainnet/10_genPolicy.sh b/cardano/mainnet/10_genPolicy.sh index 8ed09d9a..2c18aaad 100755 --- a/cardano/mainnet/10_genPolicy.sh +++ b/cardano/mainnet/10_genPolicy.sh @@ -53,7 +53,7 @@ if [ ! -d "${policyDirName}" ]; then mkdir -p ${policyDirName}; checkError "$?"; if [[ ${keyType^^} == "CLI" ]]; then #Building it from the cli (unencrypted) - ${cardanocli} address key-gen --verification-key-file "${policyName}.policy.vkey" --signing-key-file "${policyName}.policy.skey" + ${cardanocli} ${cliEra} address key-gen --verification-key-file "${policyName}.policy.vkey" --signing-key-file "${policyName}.policy.skey" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi file_lock "${policyName}.policy.vkey" file_lock "${policyName}.policy.skey" @@ -68,7 +68,7 @@ if [[ ${keyType^^} == "CLI" ]]; then #Building it from the cli (unencrypted) elif [[ ${keyType^^} == "ENC" ]]; then #Building it from the cli (encrypted) - skeyJSON=$(${cardanocli} address key-gen --verification-key-file "${policyName}.policy.vkey" --signing-key-file /dev/stdout 2> /dev/null) + skeyJSON=$(${cardanocli} ${cliEra} address key-gen --verification-key-file "${policyName}.policy.vkey" --signing-key-file /dev/stdout 2> /dev/null) checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi file_lock "${policyName}.policy.vkey" @@ -163,11 +163,11 @@ else #Building it from hw fi -policyKeyHASH=$(${cardanocli} address key-hash --payment-verification-key-file ${policyName}.policy.vkey) +policyKeyHASH=$(${cardanocli} ${cliEra} address key-hash --payment-verification-key-file ${policyName}.policy.vkey) checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi -currentTip=$(get_currentTip) +currentTip=$(get_currentTip); checkError "$?"; echo -e "\e[0mCurrent Slot-Height:\e[32m ${currentTip} \e[0m" echo -e "\e[0mPolicy invalid after Slot-Height:\e[33m ${validBefore}\e[0m" echo @@ -184,14 +184,18 @@ cat ${policyName}.policy.script | jq echo if [[ "${keyType^^}" == "CLI" || "${keyType^^}" == "ENC" ]]; then #generate the policyID via cli command - policyID=$(${cardanocli} transaction policyid --script-file ${policyName}.policy.script) + + policyID=$(${cardanocli} ${cliEra} transaction policyid --script-file ${policyName}.policy.script) + else #show it via the hw-wallet. not really needed but a nice feature to also show the invalid hereafter value if present - echo -e "\e[0mGeneration the PolicyID via the HW-Wallet GUI ... \n" - start_HwWallet; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - tmp=$(${cardanohwcli} transaction policyid --script-file ${policyName}.policy.script --hw-signing-file ${policyName}.policy.hwsfile 2> /dev/stdout) - if [[ "${tmp^^}" =~ (ERROR|DISCONNECT) ]]; then echo -e "\e[35m${tmp}\e[0m\n"; exit 1; else echo -e "\e[32mDONE\e[0m\n"; fi - checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - policyID=${tmp} + + echo -e "\e[0mGeneration the PolicyID via the HW-Wallet GUI ... \n" + start_HwWallet; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi + tmp=$(${cardanohwcli} transaction policyid --script-file ${policyName}.policy.script --hw-signing-file ${policyName}.policy.hwsfile 2> /dev/stdout) + if [[ "${tmp^^}" =~ (ERROR|DISCONNECT) ]]; then echo -e "\e[35m${tmp}\e[0m\n"; exit 1; else echo -e "\e[32mDONE\e[0m\n"; fi + checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi + policyID=${tmp} + fi echo -e "${policyID}" > ${policyName}.policy.id diff --git a/cardano/mainnet/11a_mintAsset.sh b/cardano/mainnet/11a_mintAsset.sh index 810e4dd7..96913bfd 100755 --- a/cardano/mainnet/11a_mintAsset.sh +++ b/cardano/mainnet/11a_mintAsset.sh @@ -169,12 +169,12 @@ assetMintSubject="${policyID}${assetMintName}" #assetMintName already in HEX-For echo -e "\e[0mMinting Asset \e[32m${assetMintAmount} '${assetMintInputName}' -> '$(convert_assetNameHEX2ASCII_ifpossible ${assetMintName})'\e[0m with Policy \e[32m'${policyName}'\e[0m: ${assetMintBech}" #get live values -currentTip=$(get_currentTip); +currentTip=$(get_currentTip); checkError "$?"; #set timetolife (inherent hereafter) to the currentTTL or to the value set in the policy.script for the "before" slot (limited policy lifespan) ttlFromScript=$(cat ${policyName}.policy.script | jq -r ".scripts[] | select(.type == \"before\") | .slot" 2> /dev/null || echo "unlimited") if [[ ${ttlFromScript} == "" ]]; then ttlFromScript="unlimited"; fi #also set it to unlimited if empty -if [[ ! ${ttlFromScript} == "unlimited" ]]; then ttl=${ttlFromScript}; else ttl=$(get_currentTTL); fi +if [[ ! ${ttlFromScript} == "unlimited" ]]; then ttl=${ttlFromScript}; else ttl=$(( ${currentTip} + ${defTTL} )); fi echo echo -e "\e[0mPolicy valid before Slot-Height:\e[33m ${ttlFromScript}\e[0m" echo @@ -193,18 +193,33 @@ echo # # Checking UTXO Data of the source address and gathering data about total lovelaces and total assets # - #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in offlinemode from the transferFile - if ${onlineMode}; then + + #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in lightmode via API requests, in offlinemode from the transferFile + case ${workMode} in + "online") + #check that the node is fully synced, otherwise the query would mabye return a false state + if [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced or not running, please let your node sync to 100% first !\e[0m\n"; exit 1; fi showProcessAnimation "Query-UTXO: " & - utxo=$(${cardanocli} query utxo --address ${sendFromAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + utxo=$(${cardanocli} ${cliEra} query utxo --address ${sendFromAddr} 2> /dev/stdout); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + showProcessAnimation "Convert-UTXO: " & + utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; + ;; + + "light") + showProcessAnimation "Query-UTXO-LightMode: " & + utxo=$(queryLight_UTXO "${sendFromAddr}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; showProcessAnimation "Convert-UTXO: " & utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; - #utxoJSON=$(${cardanocli} query utxo --address ${sendFromAddr} ${magicparam} --out-file /dev/stdout); checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; - else - readOfflineFile; #Reads the offlinefile into the offlineJSON variable - utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON}) + ;; + + + "offline") readOfflineFile; #Reads the offlinefile into the offlineJSON variable + utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON} 2> /dev/null) if [[ "${utxoJSON}" == null ]]; then echo -e "\e[35mPayment-Address not included in the offline transferFile, please include it first online!\e[0m\n"; exit 1; fi - fi + ;; + esac #Only use UTXOs specified in the extra parameter if present if [[ ! "${filterForUTXO}" == "" ]]; then echo -e "\e[0mUTXO-Mode: \e[32mOnly using the UTXO with Hash ${filterForUTXO}\e[0m\n"; utxoJSON=$(filterFor_UTXO "${utxoJSON}" "${filterForUTXO}"); fi @@ -276,8 +291,20 @@ echo totalAssetsJSON=$( jq ". += {\"${assetHash}${point}${assetName}\":{amount: \"${newValue}\", name: \"${assetTmpName}\", bech: \"${assetBech}\"}}" <<< ${totalAssetsJSON}) if [[ "${assetTmpName:0:1}" == "." ]]; then assetTmpName=${assetTmpName:1}; else assetTmpName="{${assetTmpName}}"; fi - case ${assetHash} in - "${adahandlePolicyID}" ) #$adahandle + case "${assetHash}${assetTmpName:1:8}" in + "${adahandlePolicyID}000de140" ) #$adahandle cip-68 + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Own): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}00000000" ) #$adahandle virtual + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Vir): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}000643b0" ) #$adahandle reference + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Ref): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}"* ) #$adahandle cip-25 echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle: \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" ;; * ) #default @@ -345,11 +372,11 @@ if [[ ! "${transactionMessage}" == "{}" ]]; then fi #Read ProtocolParameters -if ${onlineMode}; then - protocolParametersJSON=$(${cardanocli} query protocol-parameters ${magicparam} ); #onlinemode - else - protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON}); #offlinemode - fi +case ${workMode} in + "online") protocolParametersJSON=$(${cardanocli} ${cliEra} query protocol-parameters);; #onlinemode + "light") protocolParametersJSON=${lightModeParametersJSON};; #lightmode + "offline") protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON});; #offlinemode +esac checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi minOutUTXO=$(calc_minOutUTXO "${protocolParametersJSON}" "${sendToAddr}+1000000${assetsOutString}") @@ -359,9 +386,9 @@ if [[ "${assetMintName}" == "" ]]; then point=""; else point="."; fi #Generate Dummy-TxBody file for fee calculation txBodyFile="${tempDir}/dummy.txbody" rm ${txBodyFile} 2> /dev/null -${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --mint "${assetMintAmount} ${policyID}${point}${assetMintName}" --minting-script-file ${policyName}.policy.script --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --out-file ${txBodyFile} +${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --mint "${assetMintAmount} ${policyID}${point}${assetMintName}" --minting-script-file ${policyName}.policy.script --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi -fee=$(${cardanocli} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} ${magicparam} --witness-count 2 --byron-witness-count 0 | awk '{ print $1 }') +fee=$(${cardanocli} ${cliEra} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} --witness-count 2 --byron-witness-count 0 | awk '{ print $1 }') checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "\e[0mMinimum Transaction Fee for ${txcnt}x TxIn & ${rxcnt}x TxOut: \e[32m $(convertToADA ${fee}) ADA / ${fee} lovelaces \e[90m" @@ -390,7 +417,7 @@ echo #Building unsigned transaction body rm ${txBodyFile} 2> /dev/null -${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsOutString}" --mint "${assetMintAmount} ${policyID}${point}${assetMintName}" --minting-script-file ${policyName}.policy.script --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --out-file ${txBodyFile} +${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsOutString}" --mint "${assetMintAmount} ${policyID}${point}${assetMintName}" --minting-script-file ${policyName}.policy.script --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi dispFile=$(cat ${txBodyFile}); if ${cropTxOutput} && [[ ${#dispFile} -gt 4000 ]]; then echo "${dispFile:0:4000} ... (cropped)"; else echo "${dispFile}"; fi @@ -423,7 +450,7 @@ else #generate the policy witness via the cli #read the needed signing keys into ram skeyJSON=$(read_skeyFILE "${policyName}.policy.skey"); if [ $? -ne 0 ]; then echo -e "\e[35m${skeyJSON}\e[0m\n"; exit 1; else echo -e "\e[32mOK\e[0m\n"; fi - ${cardanocli} transaction witness --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON}") ${magicparam} --out-file ${txWitnessPolicyFile} + ${cardanocli} ${cliEra} transaction witness --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON}") --out-file ${txWitnessPolicyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #forget the signing keys @@ -447,7 +474,7 @@ else #generate the payment witness via the cli #read the needed signing keys into ram skeyJSON=$(read_skeyFILE "${fromAddr}.skey"); if [ $? -ne 0 ]; then echo -e "\e[35m${skeyJSON}\e[0m\n"; exit 1; else echo -e "\e[32mOK\e[0m\n"; fi - ${cardanocli} transaction witness --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON}") ${magicparam} --out-file ${txWitnessPaymentFile} + ${cardanocli} ${cliEra} transaction witness --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON}") --out-file ${txWitnessPaymentFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #forget the signing keys @@ -457,7 +484,7 @@ fi #Assemble all witnesses into the final TxBody rm ${txFile} 2> /dev/null -${cardanocli} transaction assemble --tx-body-file ${txBodyFile} --witness-file ${txWitnessPolicyFile} --witness-file ${txWitnessPaymentFile} --out-file ${txFile} +${cardanocli} ${cliEra} transaction assemble --tx-body-file ${txBodyFile} --witness-file ${txWitnessPolicyFile} --witness-file ${txWitnessPaymentFile} --out-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -ne "\e[90m" @@ -473,15 +500,18 @@ if [[ ${txSize} -le ${maxTxSize} ]]; then echo -e "\e[0mTransaction-Size: ${txSi #if ask "\e[33mDoes this look good for you, continue ?" N; then if [ "${ENV_SKIP_PROMPT}" == "YES" ] || ask "\n\e[33mDoes this look good for you, continue ?" N; then + echo - if ${onlineMode}; then #onlinesubmit + case ${workMode} in + "online") + #onlinesubmit echo -ne "\e[0mSubmitting the transaction via the node... " - ${cardanocli} transaction submit --tx-file ${txFile} ${magicparam} + ${cardanocli} ${cliEra} transaction submit --tx-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "\e[32mDONE\n" #Show the TxID - txID=$(${cardanocli} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" + txID=$(${cardanocli} ${cliEra} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi @@ -511,11 +541,63 @@ if [ "${ENV_SKIP_PROMPT}" == "YES" ] || ask "\n\e[33mDoes this look good for you #Combine the Skeleton with the real one assetFileJSON=$(echo "${assetFileSkeletonJSON} ${assetFileJSON}" | jq -rs 'reduce .[] as $item ({}; . * $item)') + oldValue=$(jq -r ".minted" <<< ${assetFileJSON}); if [[ "${oldValue}" == "" ]]; then oldValue=0; fi + newValue=$(bc <<< "${oldValue} + ${assetMintAmount}") + assetFileJSON=$( jq ". += {minted: \"${newValue}\", + name: \"${assetTmpName}\", + hexname: \"${assetHexMintName}\", + bechName: \"${assetMintBech}\", + policyID: \"${policyID}\", + policyValidBeforeSlot: \"${ttlFromScript}\", + subject: \"${assetMintSubject}\", + lastUpdate: \"$(date -R)\", + lastAction: \"mint ${assetMintAmount}\"}" <<< ${assetFileJSON}) + + file_unlock ${assetFileName} + echo -e "${assetFileJSON}" > ${assetFileName} + file_lock ${assetFileName} + + echo -e "\e[0mAsset-File: \e[32m ${assetFileName} \e[90m\n" + cat ${assetFileName} + echo + ;; + -#Currently disabled by IOHK -# metaSubUnitDecimals: 0, -# metaSubUnitName: \"\", + "light") + #lightmode submit + showProcessAnimation "Submit-Transaction-LightMode: " & + txID=$(submitLight "${txFile}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${txID}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + echo -e "\e[0mSubmit-Transaction-LightMode: \e[32mDONE\n" + #Show the TxID + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + + assetTmpName=$(convert_assetNameHEX2ASCII_ifpossible ${assetMintName}); if [[ "${assetTmpName:0:1}" == "." ]]; then assetTmpName=${assetTmpName:1}; fi + + #Updating the ${policyName}.${assetMintInputName}.asset json + assetFileName="${policyName}.${assetMintInputName}.asset" + + #Make assetFileSkeleton + assetFileSkeletonJSON=$(jq ". += {metaName: \"${assetTmpName:0:50}\", + metaDescription: \"\", + \"---\": \"--- Optional additional info ---\", + metaTicker: \"\", + metaUrl: \"\", + metaDecimals: \"0\", + metaLogoPNG: \"\", + \"===\": \"--- DO NOT EDIT BELOW THIS LINE !!! ---\", + minted: \"0\"}" <<< "{}") + + + #If there is no assetFileName file, create one + if [ ! -f "${assetFileName}" ]; then echo "{}" > ${assetFileName}; fi + + #Read in the current file + assetFileJSON=$(cat ${assetFileName}) + + #Combine the Skeleton with the real one + assetFileJSON=$(echo "${assetFileSkeletonJSON} ${assetFileJSON}" | jq -rs 'reduce .[] as $item ({}; . * $item)') oldValue=$(jq -r ".minted" <<< ${assetFileJSON}); if [[ "${oldValue}" == "" ]]; then oldValue=0; fi newValue=$(bc <<< "${oldValue} + ${assetMintAmount}") @@ -536,8 +618,11 @@ if [ "${ENV_SKIP_PROMPT}" == "YES" ] || ask "\n\e[33mDoes this look good for you echo -e "\e[0mAsset-File: \e[32m ${assetFileName} \e[90m\n" cat ${assetFileName} echo + ;; - else #offlinestore + + "offline") + #offlinestore txFileJSON=$(cat ${txFile} | jq .) offlineJSON=$( jq ".transactions += [ { date: \"$(date -R)\", type: \"Asset-Minting\", @@ -550,7 +635,6 @@ if [ "${ENV_SKIP_PROMPT}" == "YES" ] || ask "\n\e[33mDoes this look good for you #Write the new offileFile content offlineJSON=$( jq ".history += [ { date: \"$(date -R)\", action: \"minted ${assetMintAmount} '${assetMintInputName}' on '${fromAddr}'\" } ]" <<< ${offlineJSON}) offlineJSON=$( jq ".general += {offlineCLI: \"${versionCLI}\" }" <<< ${offlineJSON}) - offlineJSON=$( jq ".general += {offlineNODE: \"${versionNODE}\" }" <<< ${offlineJSON}) echo "${offlineJSON}" > ${offlineFile} #Readback the tx content and compare it to the current one readback=$(cat ${offlineFile} | jq -r ".transactions[-1].txJSON") @@ -606,9 +690,11 @@ if [ "${ENV_SKIP_PROMPT}" == "YES" ] || ask "\n\e[33mDoes this look good for you else echo -e "\e[35mERROR - Could not verify the written data in the '$(basename ${offlineFile})'. Retry again or generate a new '$(basename ${offlineFile})'.\e[0m\n"; - fi - fi + fi #"${txFileJSON}"=="${readback}" + ;; + esac + fi echo -e "\e[0m\n" diff --git a/cardano/mainnet/11b_burnAsset.sh b/cardano/mainnet/11b_burnAsset.sh index e3802462..943b698c 100755 --- a/cardano/mainnet/11b_burnAsset.sh +++ b/cardano/mainnet/11b_burnAsset.sh @@ -165,12 +165,12 @@ assetBurnSubject="${policyID}${assetBurnName}" echo -e "\e[0mBurning Asset \e[32m${assetBurnAmount} '${assetBurnInputName}' -> '$(convert_assetNameHEX2ASCII_ifpossible ${assetBurnName})'\e[0m with Policy \e[32m'${policyName}'\e[0m: ${assetBurnBech}" #get live values -currentTip=$(get_currentTip) +currentTip=$(get_currentTip); checkError "$?"; #set timetolife (inherent hereafter) to the currentTTL or to the value set in the policy.script for the "before" slot (limited policy lifespan) ttlFromScript=$(cat ${policyName}.policy.script | jq -r ".scripts[] | select(.type == \"before\") | .slot" 2> /dev/null || echo "unlimited") if [[ ${ttlFromScript} == "" ]]; then ttlFromScript="unlimited"; fi #also set it to unlimited if empty -if [[ ! ${ttlFromScript} == "unlimited" ]]; then ttl=${ttlFromScript}; else ttl=$(get_currentTTL); fi +if [[ ! ${ttlFromScript} == "unlimited" ]]; then ttl=${ttlFromScript}; else ttl=$(( ${currentTip} + ${defTTL} )); fi echo echo -e "\e[0mPolicy valid before Slot-Height:\e[33m ${ttlFromScript}\e[0m" echo @@ -191,18 +191,33 @@ echo # # Checking UTXO Data of the source address and gathering data about total lovelaces and total assets # - #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in offlinemode from the transferFile - if ${onlineMode}; then + + #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in lightmode via API requests, in offlinemode from the transferFile + case ${workMode} in + "online") + #check that the node is fully synced, otherwise the query would mabye return a false state + if [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced or not running, please let your node sync to 100% first !\e[0m\n"; exit 1; fi showProcessAnimation "Query-UTXO: " & - utxo=$(${cardanocli} query utxo --address ${sendFromAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + utxo=$(${cardanocli} ${cliEra} query utxo --address ${sendFromAddr} 2> /dev/stdout); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; showProcessAnimation "Convert-UTXO: " & utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; - #utxoJSON=$(${cardanocli} query utxo --address ${sendFromAddr} ${magicparam} --out-file /dev/stdout); checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; - else - readOfflineFile; #Reads the offlinefile into the offlineJSON variable - utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON}) - if [[ "${utxoJSON}" == null ]]; then echo -e "\e[35mPayment-Address not included in the offline transferFile, please include it first online!\e[0m\n"; exit; fi - fi + ;; + + "light") + showProcessAnimation "Query-UTXO-LightMode: " & + utxo=$(queryLight_UTXO "${sendFromAddr}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + showProcessAnimation "Convert-UTXO: " & + utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; + ;; + + + "offline") readOfflineFile; #Reads the offlinefile into the offlineJSON variable + utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON} 2> /dev/null) + if [[ "${utxoJSON}" == null ]]; then echo -e "\e[35mPayment-Address not included in the offline transferFile, please include it first online!\e[0m\n"; exit 1; fi + ;; + esac #Only use UTXOs specied in the extra parameter if present if [[ ! "${filterForUTXO}" == "" ]]; then echo -e "\e[0mUTXO-Mode: \e[32mOnly using the UTXO with Hash ${filterForUTXO}\e[0m\n"; utxoJSON=$(filterFor_UTXO "${utxoJSON}" "${filterForUTXO}"); fi @@ -338,26 +353,27 @@ if [[ ! "${transactionMessage}" == "{}" ]]; then fi #Read ProtocolParameters -if ${onlineMode}; then - protocolParametersJSON=$(${cardanocli} query protocol-parameters ${magicparam} ); #onlinemode - else - protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON}); #offlinemode - fi +case ${workMode} in + "online") protocolParametersJSON=$(${cardanocli} ${cliEra} query protocol-parameters);; #onlinemode + "light") protocolParametersJSON=${lightModeParametersJSON};; #lightmode + "offline") protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON});; #offlinemode +esac checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi + minOutUTXO=$(calc_minOutUTXO "${protocolParametersJSON}" "${sendToAddr}+1000000${assetsOutString}") if [[ "${assetBurnName}" == "" ]]; then point=""; else point="."; fi #Check amount of assets after the burn assetAmountAfterBurn=$(jq -r ".\"${policyID}${point}${assetBurnName}\".amount" <<< ${totalAssetsJSON}) -if [[ $(bc <<< "${assetAmountAfterBurn}<0") -eq 1 ]]; then echo -e "\n\e[35mYou can't burn ${assetBurnAmount} '${assetBurnName}' Assets with that policy, you can only burn $(bc <<< "${assetBurnAmount}+${assetAmountAfterBurn}") Assets!\e[0m"; exit; fi +if [[ $(bc <<< "${assetAmountAfterBurn}<0") -eq 1 ]]; then echo -e "\n\e[35mYou can't burn ${assetBurnAmount} '${assetBurnInputName}' Assets with that policy, you can only burn $(bc <<< "${assetBurnAmount}+${assetAmountAfterBurn}") Assets!\e[0m"; exit; fi #Generate Dummy-TxBody file for fee calculation txBodyFile="${tempDir}/dummy.txbody" rm ${txBodyFile} 2> /dev/null -${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --mint "-${assetBurnAmount} ${policyID}${point}${assetBurnName}" --minting-script-file ${policyName}.policy.script --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --out-file ${txBodyFile} +${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --mint "-${assetBurnAmount} ${policyID}${point}${assetBurnName}" --minting-script-file ${policyName}.policy.script --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi -fee=$(${cardanocli} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} ${magicparam} --witness-count 2 --byron-witness-count 0 | awk '{ print $1 }') +fee=$(${cardanocli} ${cliEra} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} --witness-count 2 --byron-witness-count 0 | awk '{ print $1 }') checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "\e[0mMinimum Transaction Fee for ${txcnt}x TxIn & ${rxcnt}x TxOut: \e[32m $(convertToADA ${fee}) ADA / ${fee} lovelaces \e[90m" @@ -386,7 +402,7 @@ echo #Building unsigned transaction body rm ${txBodyFile} 2> /dev/null -${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsOutString}" --mint "-${assetBurnAmount} ${policyID}${point}${assetBurnName}" --minting-script-file ${policyName}.policy.script --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --out-file ${txBodyFile} +${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsOutString}" --mint "-${assetBurnAmount} ${policyID}${point}${assetBurnName}" --minting-script-file ${policyName}.policy.script --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi dispFile=$(cat ${txBodyFile}); if ${cropTxOutput} && [[ ${#dispFile} -gt 4000 ]]; then echo "${dispFile:0:4000} ... (cropped)"; else echo "${dispFile}"; fi @@ -420,7 +436,7 @@ else #generate the policy witness via the cli #read the needed signing keys into ram skeyJSON=$(read_skeyFILE "${policyName}.policy.skey"); if [ $? -ne 0 ]; then echo -e "\e[35m${skeyJSON}\e[0m\n"; exit 1; else echo -e "\e[32mOK\e[0m\n"; fi - ${cardanocli} transaction witness --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON}") ${magicparam} --out-file ${txWitnessPolicyFile} + ${cardanocli} ${cliEra} transaction witness --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON}") --out-file ${txWitnessPolicyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #forget the signing keys @@ -444,7 +460,7 @@ else #generate the payment witness via the cli #read the needed signing keys into ram skeyJSON=$(read_skeyFILE "${fromAddr}.skey"); if [ $? -ne 0 ]; then echo -e "\e[35m${skeyJSON}\e[0m\n"; exit 1; else echo -e "\e[32mOK\e[0m\n"; fi - ${cardanocli} transaction witness --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON}") ${magicparam} --out-file ${txWitnessPaymentFile} + ${cardanocli} ${cliEra} transaction witness --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON}") --out-file ${txWitnessPaymentFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #forget the signing keys @@ -455,7 +471,7 @@ fi #Assemble all witnesses into the final TxBody rm ${txFile} 2> /dev/null -${cardanocli} transaction assemble --tx-body-file ${txBodyFile} --witness-file ${txWitnessPolicyFile} --witness-file ${txWitnessPaymentFile} --out-file ${txFile} +${cardanocli} ${cliEra} transaction assemble --tx-body-file ${txBodyFile} --witness-file ${txWitnessPolicyFile} --witness-file ${txWitnessPaymentFile} --out-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -ne "\e[90m" @@ -472,15 +488,18 @@ if [[ ${txSize} -le ${maxTxSize} ]]; then echo -e "\e[0mTransaction-Size: ${txSi #if ask "\e[33mDoes this look good for you, continue ?" N; then if [ "${ENV_SKIP_PROMPT}" == "YES" ] || ask "\e[33mDoes this look good for you, continue ?" N; then + echo - if ${onlineMode}; then #onlinesubmit + case ${workMode} in + "online") + #onlinesubmit echo -ne "\e[0mSubmitting the transaction via the node... " - ${cardanocli} transaction submit --tx-file ${txFile} ${magicparam} + ${cardanocli} ${cliEra} transaction submit --tx-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "\e[32mDONE\n" #Show the TxID - txID=$(${cardanocli} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" + txID=$(${cardanocli} ${cliEra} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi @@ -530,8 +549,70 @@ if [ "${ENV_SKIP_PROMPT}" == "YES" ] || ask "\e[33mDoes this look good for you, echo -e "\e[0mAsset-File: \e[32m ${assetFileName} \e[90m\n" cat ${assetFileName} echo + ;; - else #offlinestore + + "light") + #lightmode submit + showProcessAnimation "Submit-Transaction-LightMode: " & + txID=$(submitLight "${txFile}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${txID}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + echo -e "\e[0mSubmit-Transaction-LightMode: \e[32mDONE\n" + + #Show the TxID + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + + assetTmpName=$(convert_assetNameHEX2ASCII_ifpossible ${assetBurnName}); if [[ "${assetTmpName:0:1}" == "." ]]; then assetTmpName=${assetTmpName:1}; fi + + #Updating the ${policyName}.${assetBurnInputName}.asset json + assetFileName="${policyName}.${assetBurnInputName}.asset" + + #Make assetFileSkeleton + assetFileSkeletonJSON=$(jq ". += {metaName: \"${assetTmpName:0:50}\", + metaDescription: \"\", + \"---\": \"--- Optional additional info ---\", + metaTicker: \"\", + metaUrl: \"\", + metaDecimals: \"0\", + metaLogoPNG: \"\", + \"===\": \"--- DO NOT EDIT BELOW THIS LINE !!! ---\", + minted: \"0\"}" <<< "{}") + + + #If there is no assetFileName file, create one + if [ ! -f "${assetFileName}" ]; then echo "{}" > ${assetFileName}; fi + + #Read in the current file + assetFileJSON=$(cat ${assetFileName}) + + #Combine the Skeleton with the real one + assetFileJSON=$(echo "${assetFileSkeletonJSON} ${assetFileJSON}" | jq -rs 'reduce .[] as $item ({}; . * $item)') + + oldValue=$(jq -r ".minted" <<< ${assetFileJSON}); if [[ "${oldValue}" == "" ]]; then oldValue=0; fi + newValue=$(bc <<< "${oldValue} - ${assetBurnAmount}") + assetFileJSON=$( jq ". += {minted: \"${newValue}\", + name: \"${assetTmpName}\", + hexname: \"${assetHexBurnName}\", + bechName: \"${assetBurnBech}\", + policyID: \"${policyID}\", + policyValidBeforeSlot: \"${ttlFromScript}\", + subject: \"${assetBurnSubject}\", + lastUpdate: \"$(date -R)\", + lastAction: \"burn ${assetBurnAmount}\"}" <<< ${assetFileJSON}) + + + file_unlock ${assetFileName} + echo -e "${assetFileJSON}" > ${assetFileName} + file_lock ${assetFileName} + + echo -e "\e[0mAsset-File: \e[32m ${assetFileName} \e[90m\n" + cat ${assetFileName} + echo + ;; + + + "offline") + #offlinestore txFileJSON=$(cat ${txFile} | jq .) offlineJSON=$( jq ".transactions += [ { date: \"$(date -R)\", type: \"Asset-Burning\", @@ -544,7 +625,6 @@ if [ "${ENV_SKIP_PROMPT}" == "YES" ] || ask "\e[33mDoes this look good for you, #Write the new offileFile content offlineJSON=$( jq ".history += [ { date: \"$(date -R)\", action: \"burned ${assetBurnAmount} '${assetBurnInputName}' on '${fromAddr}'\" } ]" <<< ${offlineJSON}) offlineJSON=$( jq ".general += {offlineCLI: \"${versionCLI}\" }" <<< ${offlineJSON}) - offlineJSON=$( jq ".general += {offlineNODE: \"${versionNODE}\" }" <<< ${offlineJSON}) echo "${offlineJSON}" > ${offlineFile} #Readback the tx content and compare it to the current one readback=$(cat ${offlineFile} | jq -r ".transactions[-1].txJSON") @@ -600,9 +680,12 @@ if [ "${ENV_SKIP_PROMPT}" == "YES" ] || ask "\e[33mDoes this look good for you, else echo -e "\e[35mERROR - Could not verify the written data in the '$(basename ${offlineFile})'. Retry again or generate a new '$(basename ${offlineFile})'.\e[0m\n"; - fi - fi + fi #"${txFileJSON}"=="${readback}" + ;; + + esac + fi echo -e "\e[0m\n" diff --git a/cardano/mainnet/12a_genAssetMeta.sh b/cardano/mainnet/12a_genAssetMeta.sh index 79ef077f..8cb5d5b2 100755 --- a/cardano/mainnet/12a_genAssetMeta.sh +++ b/cardano/mainnet/12a_genAssetMeta.sh @@ -27,6 +27,8 @@ Usage: $(basename $0) EOF exit 1;; esac + + assetFileName="${policyName}.${assetName}.asset" #save the output assetfilename here, because at that state the assetName is with or without the {} brackets # Check for needed input files diff --git a/cardano/mainnet/12b_checkAssetMetaServer.sh b/cardano/mainnet/12b_checkAssetMetaServer.sh index a7360a39..dfca2dba 100755 --- a/cardano/mainnet/12b_checkAssetMetaServer.sh +++ b/cardano/mainnet/12b_checkAssetMetaServer.sh @@ -23,6 +23,8 @@ Usage: $(basename $0) EOF exit 1;; esac + + #Check assetName if [[ "${assetName}" == ".asset" ]]; then assetName=""; fi assetFileName="${policyName}.${assetName}.asset" diff --git a/cardano/mainnet/13a_spoPoll.sh b/cardano/mainnet/13a_spoPoll.sh index aa2379f8..da53dbcb 100755 --- a/cardano/mainnet/13a_spoPoll.sh +++ b/cardano/mainnet/13a_spoPoll.sh @@ -11,6 +11,8 @@ if [[ $# -eq 1 && ! $1 == "" && "${1//[![:xdigit:]]}" == "${1}" && ${#1} -eq 64 #Get the Question Metadata via koios if ${offlineMode}; then echo -e "\n\e[35mERROR - SPO-Poll is only supported in Online mode.\n\e[0m"; exit 1; fi + + echo -e "\e[0mSPO-Poll question via metadata from txHash: \e[32m${txHash}\e[0m" echo diff --git a/cardano/mainnet/13b_sendSpoPoll.sh b/cardano/mainnet/13b_sendSpoPoll.sh index 2a64100f..b6a9904e 100755 --- a/cardano/mainnet/13b_sendSpoPoll.sh +++ b/cardano/mainnet/13b_sendSpoPoll.sh @@ -175,37 +175,17 @@ if [ ! -f "${toAddr}.addr" ]; then typeOfAddr=$(get_addressType "${toAddr}"); if [[ ${typeOfAddr} == ${addrTypePayment} ]]; then echo "$(basename ${toAddr})" > ${tempDir}/tempTo.addr; toAddr="${tempDir}/tempTo"; - #check if its an root adahandle (without a @ char) - elif checkAdaRootHandleFormat "${toAddr}"; then - if ${offlineMode}; then echo -e "\n\e[35mERROR - Adahandles are only supported in Online mode.\n\e[0m"; exit 1; fi + #check if its an adahandle (root/sub/virtual) + elif checkAdaHandleFormat "${toAddr}"; then + adahandleName=${toAddr,,} - assetNameHex=$(convert_assetNameASCII2HEX ${adahandleName:1}) - #query classic cip-25 adahandle asset holding address via koios - showProcessAnimation "Query Adahandle(CIP-25) into holding address: " & - response=$(curl -s -m 10 -X GET "${koiosAPI}/asset_address_list?_asset_policy=${adahandlePolicyID}&_asset_name=${assetNameHex}" -H "Accept: application/json" 2> /dev/null) - stopProcessAnimation; - #check if the received json only contains one entry in the array (will also not be 1 if not a valid json) - if [[ $(jq ". | length" 2> /dev/null <<< ${response}) -ne 1 ]]; then - #query classic cip-68 adahandle asset holding address via koios - showProcessAnimation "Query Adahandle(CIP-68) into holding address: " & - response=$(curl -s -m 10 -X GET "${koiosAPI}/asset_address_list?_asset_policy=${adahandlePolicyID}&_asset_name=000de140${assetNameHex}" -H "Accept: application/json" 2> /dev/null) - stopProcessAnimation; - #check if the received json only contains one entry in the array (will also not be 1 if not a valid json) - if [[ $(jq ". | length" 2> /dev/null <<< ${response}) -ne 1 ]]; then echo -e "\n\e[35mCould not resolve Adahandle to an address.\n\e[0m"; exit 1; fi - assetNameHex="000de140${assetNameHex}" - fi - toAddr=$(jq -r ".[0].payment_address" <<< ${response} 2> /dev/null) - typeOfAddr=$(get_addressType "${toAddr}"); - if [[ ${typeOfAddr} != ${addrTypePayment} ]]; then echo -e "\n\e[35mERROR - Resolved address '${toAddr}' is not a valid payment address.\n\e[0m"; exit 1; fi; - showProcessAnimation "Verify Adahandle is on resolved address: " & - utxo=$(${cardanocli} query utxo --address ${toAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; - if [[ $(grep "${adahandlePolicyID}.${assetNameHex} " <<< ${utxo} | wc -l) -ne 1 ]]; then - echo -e "\n\e[35mERROR - Resolved address '${toAddr}' does not hold the \$adahandle '${adahandleName}' !\n\e[0m"; exit 1; fi; - echo -e "\e[0mFound \$adahandle '${adahandleName}' on Address:\e[32m ${toAddr}\e[0m\n" - echo "$(basename ${toAddr})" > ${tempDir}/adahandle-resolve.addr; toAddr="${tempDir}/adahandle-resolve"; - - elif checkAdaSubHandleFormat "${toAddr}"; then - echo -e "\n\e[33mINFO - AdaSubHandles are not supported yet.\n\e[0m"; exit 1; + + #resolve given adahandle into address + resolveAdahandle "${adahandleName}" "toAddr" #if successful, it resolves the adahandle and writes it out into the variable 'toAddr'. also sets the variable 'utxo' if possible + unset utxo #remove utxo information from the adahandle lookup, because we only use it as a destination target + + #resolveAdahandle did not exit with an error, so we resolved it + echo "${toAddr}" > ${tempDir}/adahandle-resolve.addr; toAddr="${tempDir}/adahandle-resolve"; #otherwise post an error message else echo -e "\n\e[35mERROR - Destination Address can't be resolved. Maybe filename wrong, or not a payment-address.\n\e[0m"; exit 1; @@ -254,9 +234,8 @@ echo -e "\e[0mSending lovelaces from Address\e[32m ${fromAddr}.addr\e[0m to Addr echo #get live values -currentTip=$(get_currentTip) -ttl=$(get_currentTTL) -currentEPOCH=$(get_currentEpoch) +currentTip=$(get_currentTip); checkError "$?"; +ttl=$(( ${currentTip} + ${defTTL} )) echo -e "\e[0mCurrent Slot-Height:\e[32m ${currentTip} \e[0m(setting TTL[invalid_hereafter] to ${ttl})" echo @@ -270,20 +249,38 @@ echo # Checking UTXO Data of the source address and gathering data about total lovelaces and total assets # - #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in offlinemode from the transferFile - if ${onlineMode}; then + #Get UTX0 Data for the address. When in online mode of course from the node and the chain, in lightmode via API requests, in offlinemode from the transferFile + case ${workMode} in + "online") + #check that the node is fully synced, otherwise the query would mabye return a false state + if [[ $(get_currentSync) != "synced" ]]; then echo -e "\e[35mError - Node not fully synced or not running, please let your node sync to 100% first !\e[0m\n"; exit 1; fi showProcessAnimation "Query-UTXO: " & - utxo=$(${cardanocli} query utxo --address ${sendFromAddr} ${magicparam} ); stopProcessAnimation; checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; + utxo=$(${cardanocli} ${cliEra} query utxo --address ${sendFromAddr} 2> /dev/stdout); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + if [[ ${skipUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep -v "${skipUtxoWithAsset}" ); fi #if its set to keep utxos that contains certain policies, filter them out + if [[ ${onlyUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep "${onlyUtxoWithAsset}" ); utxo=$(echo -e "Header\n-----\n${utxo}"); fi #only use given utxos. rebuild the two header lines + if [[ ${utxoLimitCnt} -gt 0 ]]; then utxo=$(echo "${utxo}" | head -n $(( ${utxoLimitCnt} + 2 )) ); fi #if there was a utxo cnt limit set, reduce it (+2 for the header) + showProcessAnimation "Convert-UTXO: " & + utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; + ;; + + "light") + showProcessAnimation "Query-UTXO-LightMode: " & + utxo=$(queryLight_UTXO "${sendFromAddr}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${utxo}\e[0m\n"; exit $?; else stopProcessAnimation; fi; if [[ ${skipUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep -v "${skipUtxoWithAsset}" ); fi #if its set to keep utxos that contains certain policies, filter them out if [[ ${onlyUtxoWithAsset} != "" ]]; then utxo=$(echo "${utxo}" | egrep "${onlyUtxoWithAsset}" ); utxo=$(echo -e "Header\n-----\n${utxo}"); fi #only use given utxos. rebuild the two header lines if [[ ${utxoLimitCnt} -gt 0 ]]; then utxo=$(echo "${utxo}" | head -n $(( ${utxoLimitCnt} + 2 )) ); fi #if there was a utxo cnt limit set, reduce it (+2 for the header) showProcessAnimation "Convert-UTXO: " & utxoJSON=$(generate_UTXO "${utxo}" "${sendFromAddr}"); stopProcessAnimation; - else - readOfflineFile; #Reads the offlinefile into the offlineJSON variable - utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON}) + ;; + + + "offline") readOfflineFile; #Reads the offlinefile into the offlineJSON variable + utxoJSON=$(jq -r ".address.\"${sendFromAddr}\".utxoJSON" <<< ${offlineJSON} 2> /dev/null) if [[ "${utxoJSON}" == null ]]; then echo -e "\e[35mPayment-Address not included in the offline transferFile, please include it first online!\e[0m\n"; exit 1; fi - fi + ;; + esac #Only use UTXOs specied in the extra parameter if present if [[ ! "${filterForUTXO}" == "" ]]; then echo -e "\e[0mUTXO-Mode: \e[32mOnly using the UTXO with Hash ${filterForUTXO}\e[0m\n"; utxoJSON=$(filterFor_UTXO "${utxoJSON}" "${filterForUTXO}"); fi @@ -344,8 +341,20 @@ echo totalAssetsJSON=$( jq ". += {\"${assetHash}${point}${assetName}\":{amount: \"${newValue}\", name: \"${assetTmpName}\", bech: \"${assetBech}\"}}" <<< ${totalAssetsJSON}) if [[ "${assetTmpName:0:1}" == "." ]]; then assetTmpName=${assetTmpName:1}; else assetTmpName="{${assetTmpName}}"; fi - case ${assetHash} in - "${adahandlePolicyID}" ) #$adahandle + case "${assetHash}${assetTmpName:1:8}" in + "${adahandlePolicyID}000de140" ) #$adahandle cip-68 + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Own): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}00000000" ) #$adahandle virtual + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Vir): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}000643b0" ) #$adahandle reference + assetName=${assetName:8}; + echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle(Ref): \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" + ;; + "${adahandlePolicyID}"* ) #$adahandle cip-25 echo -e "\e[90m Asset: ${assetBech} \e[33mADA Handle: \$$(convert_assetNameHEX2ASCII ${assetName}) ${assetTmpName}\e[0m" ;; * ) #default @@ -414,11 +423,11 @@ if [[ ! "${transactionMessage}" == "{}" ]]; then fi #Read ProtocolParameters -if ${onlineMode}; then - protocolParametersJSON=$(${cardanocli} query protocol-parameters ${magicparam} ); #onlinemode - else - protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON}); #offlinemode - fi +case ${workMode} in + "online") protocolParametersJSON=$(${cardanocli} ${cliEra} query protocol-parameters);; #onlinemode + "light") protocolParametersJSON=${lightModeParametersJSON};; #lightmode + "offline") protocolParametersJSON=$(jq ".protocol.parameters" <<< ${offlineJSON});; #offlinemode +esac checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi # @@ -446,13 +455,13 @@ txBodyFile="${tempDir}/dummy.txbody" dummyRequiredHash="12345678901234567890123456789012345678901234567890123456" rm ${txBodyFile} 2> /dev/null if [[ ${rxcnt} == 1 ]]; then #Sending ALLFUNDS or sending ALL lovelaces and no assets on the address - ${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --required-signer-hash ${dummyRequiredHash} --out-file ${txBodyFile} + ${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --required-signer-hash ${dummyRequiredHash} --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi else #Sending chosen amount of lovelaces or ALL lovelaces but return the assets to the address - ${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --tx-out ${sendToAddr}+1000000 --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --required-signer-hash ${dummyRequiredHash} --out-file ${txBodyFile} + ${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+1000000${assetsOutString}" --tx-out ${sendToAddr}+1000000 --invalid-hereafter ${ttl} --fee 0 ${metafileParameter} --required-signer-hash ${dummyRequiredHash} --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi fi -fee=$(${cardanocli} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} ${magicparam} --witness-count 2 --byron-witness-count 0 | awk '{ print $1 }') +fee=$(${cardanocli} ${cliEra} transaction calculate-min-fee --tx-body-file ${txBodyFile} --protocol-params-file <(echo ${protocolParametersJSON}) --tx-in-count ${txcnt} --tx-out-count ${rxcnt} --witness-count 2 --byron-witness-count 0 | awk '{ print $1 }') checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #minOutUTXO=$(calc_minOutUTXO "${protocolParametersJSON}" "${sendToAddr}+0${assetsOutString}") @@ -537,7 +546,7 @@ txFile="${tempDir}/$(basename ${fromAddr}).tx" #read the needed signing keys into ram echo skeyNodeJSON=$(read_skeyFILE "${nodeName}.node.skey"); if [ $? -ne 0 ]; then echo -e "\e[35m${skeyNodeJSON}\e[0m\n"; exit 1; else echo -e "\e[32mOK\e[0m\n"; fi -vkeyNodeHash=$(${cardanocli} key verification-key --signing-key-file <(echo "${skeyNodeJSON}") --verification-key-file /dev/stdout | jq -r .cborHex | tail -c +5 | xxd -r -ps | b2sum -l 224 -b | cut -d' ' -f 1) +vkeyNodeHash=$(${cardanocli} ${cliEra} key verification-key --signing-key-file <(echo "${skeyNodeJSON}") --verification-key-file /dev/stdout | jq -r .cborHex | tail -c +5 | xxd -r -ps | b2sum -l 224 -b | cut -d' ' -f 1) echo -e "\e[0mBuilding the VKEY-Hash (Pool-ID) for the required signer field: \e[32m${vkeyNodeHash}\e[0m" echo @@ -547,11 +556,11 @@ echo #Building unsigned transaction body rm ${txBodyFile} 2> /dev/null if [[ ${rxcnt} == 1 ]]; then #Sending ALL funds (rxcnt=1) - ${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --required-signer-hash ${vkeyNodeHash} --out-file ${txBodyFile} + ${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out "${sendToAddr}+${lovelacesToSend}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --required-signer-hash ${vkeyNodeHash} --out-file ${txBodyFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi else #Sending chosen amount (rxcnt=2), return the rest(incl. assets) - ${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out ${sendToAddr}+${lovelacesToSend} --tx-out "${sendFromAddr}+${lovelacesToReturn}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --required-signer-hash ${vkeyNodeHash} --out-file ${txBodyFile} - #echo -e "\n\n\n${cardanocli} transaction build-raw ${nodeEraParam} ${txInString} --tx-out ${sendToAddr}+${lovelacesToSend} --tx-out \"${sendFromAddr}+${lovelacesToReturn}${assetsOutString}\" --invalid-hereafter ${ttl} --fee ${fee} --out-file ${txBodyFile}\n\n\n" + ${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out ${sendToAddr}+${lovelacesToSend} --tx-out "${sendFromAddr}+${lovelacesToReturn}${assetsOutString}" --invalid-hereafter ${ttl} --fee ${fee} ${metafileParameter} --required-signer-hash ${vkeyNodeHash} --out-file ${txBodyFile} + #echo -e "\n\n\n${cardanocli} ${cliEra} transaction build-raw ${txInString} --tx-out ${sendToAddr}+${lovelacesToSend} --tx-out \"${sendFromAddr}+${lovelacesToReturn}${assetsOutString}\" --invalid-hereafter ${ttl} --fee ${fee} --out-file ${txBodyFile}\n\n\n" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi fi @@ -565,21 +574,10 @@ rm ${txFile} 2> /dev/null #If payment address is a hardware wallet, use the cardano-hw-cli for the signing if [[ -f "${fromAddr}.hwsfile" ]]; then -# currentAuxHash=$(cat ${txBodyFile} | sed -n "s/.*f5\(d90103.*\)\"/\1/p" | xxd -r -ps | b2sum -l 256 -b | awk {'print $1'}) #holds the expected auxhash -# currentAuxHash=$(cat ${txBodyFile} | sed -n "s/.*\($currentAuxHash\).*/\1/p") #holds the auxhash if it was found in the txcbor as a proof - echo -ne "\e[0mAutocorrect the TxBody for canonical order: " tmp=$(autocorrect_TxBodyFile "${txBodyFile}"); if [ $? -ne 0 ]; then echo -e "\e[35m${tmp}\e[0m\n\n"; exit 1; fi echo -e "\e[32m${tmp}\e[90m\n" -# newAuxHash=$(cat ${txBodyFile} | sed -n 's/.*f5\(d90103.*\)\"/\1/p' | xxd -r -ps | b2sum -l 256 -b | awk {'print $1'}) -# if [[ "${currentAuxHash}" != "" && "${currentAuxHash}" != "${newAuxHash}" ]]; then #only do it when the currentAuxHash holds a hash (detection worked) and if the new one is different to the old one -# echo -ne "\e[0mAutocorrect the AuxHash from '${currentAuxHash}' to '${newAuxHash}': " -# sed -i "s/${currentAuxHash}/${newAuxHash}/g" ${txBodyFile}; if [ $? -ne 0 ]; then echo -e "\e[35mCouldn't write new ${txBodyFile} with a corrected AuxHash!\e[0m\n\n"; exit 1; fi -# echo -e "\e[32mOK\e[90m\n" -# fi - - dispFile=$(cat ${txBodyFile}); if ${cropTxOutput} && [[ ${#dispFile} -gt 4000 ]]; then echo "${dispFile:0:4000} ... (cropped)"; else echo "${dispFile}"; fi echo @@ -605,11 +603,11 @@ if [[ -f "${fromAddr}.hwsfile" ]]; then checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -ne "\e[0mAdding the pool node witness '\e[33m${nodeName}.node.skey\e[0m' ... " - tmp=$(${cardanocli} transaction witness --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyNodeJSON}") ${magicparam} --out-file ${txNodeWitnessFile} 2> /dev/stdout) + tmp=$(${cardanocli} ${cliEra} transaction witness --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyNodeJSON}") --out-file ${txNodeWitnessFile} 2> /dev/stdout) checkError "$?"; if [ $? -ne 0 ]; then echo -e "\e[35m${tmp}\e[0m\n"; exit 1; fi echo -e "\e[32mOK\n" - ${cardanocli} transaction assemble --tx-body-file ${txBodyFile} --witness-file ${txWitnessFile} --witness-file ${txNodeWitnessFile} --out-file ${txFile} + ${cardanocli} ${cliEra} transaction assemble --tx-body-file ${txBodyFile} --witness-file ${txWitnessFile} --witness-file ${txNodeWitnessFile} --out-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi echo -e "\e[0mAssembled ... \e[32mDONE\e[0m\n"; @@ -621,7 +619,7 @@ else echo -e "\e[0mSign the unsigned transaction body with the \e[32m${fromAddr}.skey\e[0m and \e[32m${nodeName}.node.skey\e[0m: \e[32m ${txFile}\e[0m" echo - ${cardanocli} transaction sign --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON}") --signing-key-file <(echo "${skeyNodeJSON}") ${magicparam} --out-file ${txFile} + ${cardanocli} ${cliEra} transaction sign --tx-body-file ${txBodyFile} --signing-key-file <(echo "${skeyJSON}") --signing-key-file <(echo "${skeyNodeJSON}") --out-file ${txFile} checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi #forget the signing keys @@ -645,42 +643,56 @@ if [[ ${txSize} -le ${maxTxSize} ]]; then echo -e "\e[0mTransaction-Size: ${txSi #if ask "\e[33mDoes this look good for you, continue ?" N; then if [ "${ENV_SKIP_PROMPT}" == "YES" ] || ask "\n\e[33mDoes this look good for you, continue ?" N; then - echo - if ${onlineMode}; then #onlinesubmit - echo -ne "\e[0mSubmitting the transaction via the node... " - ${cardanocli} transaction submit --tx-file ${txFile} ${magicparam} - checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi - echo -e "\e[32mDONE\n" + echo + case ${workMode} in + "online") + #onlinesubmit + echo -ne "\e[0mSubmitting the transaction via the node... " + ${cardanocli} ${cliEra} transaction submit --tx-file ${txFile} + checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi + echo -e "\e[32mDONE\n" #Show the TxID - txID=$(${cardanocli} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" + txID=$(${cardanocli} ${cliEra} transaction txid --tx-file ${txFile}); echo -e "\e[0m TxID is: \e[32m${txID}\e[0m" checkError "$?"; if [ $? -ne 0 ]; then exit $?; fi; if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi - - else #offlinestore - txFileJSON=$(cat ${txFile} | jq .) - offlineJSON=$( jq ".transactions += [ { date: \"$(date -R)\", - type: \"Transaction\", - era: \"$(jq -r .protocol.era <<< ${offlineJSON})\", - fromAddr: \"${fromAddr}\", - sendFromAddr: \"${sendFromAddr}\", - toAddr: \"${toAddr}\", - sendToAddr: \"${sendToAddr}\", - txJSON: ${txFileJSON} } ]" <<< ${offlineJSON}) - #Write the new offileFile content - offlineJSON=$( jq ".history += [ { date: \"$(date -R)\", action: \"signed utxo-transaction from '${fromAddr}' to '${toAddr}'\" } ]" <<< ${offlineJSON}) - offlineJSON=$( jq ".general += {offlineCLI: \"${versionCLI}\" }" <<< ${offlineJSON}) - echo "${offlineJSON}" > ${offlineFile} - #Readback the tx content and compare it to the current one - readback=$(cat ${offlineFile} | jq -r ".transactions[-1].txJSON") - if [[ "${txFileJSON}" == "${readback}" ]]; then + ;; + + "light") + #lightmode submit + showProcessAnimation "Submit-Transaction-LightMode: " & + txID=$(submitLight "${txFile}"); + if [ $? -ne 0 ]; then stopProcessAnimation; echo -e "\e[35mERROR - ${txID}\e[0m\n"; exit $?; else stopProcessAnimation; fi; + echo -e "\e[0mSubmit-Transaction-LightMode: \e[32mDONE\n" + if [[ "${transactionExplorer}" != "" ]]; then echo -e "\e[0mTracking: \e[32m${transactionExplorer}/${txID}\n\e[0m"; fi + ;; + + "offline") + #offlinestore + txFileJSON=$(cat ${txFile} | jq .) + offlineJSON=$( jq ".transactions += [ { date: \"$(date -R)\", + type: \"Transaction\", + era: \"$(jq -r .protocol.era <<< ${offlineJSON})\", + fromAddr: \"${fromAddr}\", + sendFromAddr: \"${sendFromAddr}\", + toAddr: \"${toAddr}\", + sendToAddr: \"${sendToAddr}\", + txJSON: ${txFileJSON} } ]" <<< ${offlineJSON}) + #Write the new offileFile content + offlineJSON=$( jq ".history += [ { date: \"$(date -R)\", action: \"signed utxo-transaction from '${fromAddr}' to '${toAddr}'\" } ]" <<< ${offlineJSON}) + offlineJSON=$( jq ".general += {offlineCLI: \"${versionCLI}\" }" <<< ${offlineJSON}) + echo "${offlineJSON}" > ${offlineFile} + #Readback the tx content and compare it to the current one + readback=$(cat ${offlineFile} | jq -r ".transactions[-1].txJSON") + if [[ "${txFileJSON}" == "${readback}" ]]; then showOfflineFileInfo; echo -e "\e[33mTransaction txJSON has been stored in the '$(basename ${offlineFile})'.\nYou can now transfer it to your online machine for execution.\e[0m\n"; else echo -e "\e[35mERROR - Could not verify the written data in the '$(basename ${offlineFile})'. Retry again or generate a new '$(basename ${offlineFile})'.\e[0m\n"; - fi + fi + ;; - fi + esac fi diff --git a/cardano/mainnet/README.md b/cardano/mainnet/README.md index eee4dd13..28b4a508 100644 --- a/cardano/mainnet/README.md +++ b/cardano/mainnet/README.md @@ -1,49 +1,56 @@ -# StakePool Operator Scripts (SPOS) for the Cardano MAINNET +# StakePool Operator Scripts (SPOS) for Cardano MainNet and TestNets -*Examples on how to use the scripts **ONLINE** and/or **OFFLINE**, with or without a **Ledger/Trezor-Wallet** can be found on this page :smiley:* +*Examples on how to use the scripts in **ONLINE-**, **LIGHT-** and **OFFLINE-** Mode, with or without a **Ledger/Trezor-Wallet** can be found on this page* :smiley: -| | [cardano-node & cli](https://github.com/input-output-hk/cardano-node/releases/latest) | [cardano-hw-cli](https://github.com/vacuumlabs/cardano-hw-cli/releases/latest) | Ledger Cardano-App | Trezor Firmware | -| :--- | :---: | :---: | :---: | :---: | -| *Required
version
or higher* | 1.35.5
**git checkout tags/1.35.5** | 1.13.0
**if you use hw-wallets** | 5.0.0
(6.0.3 for voting)
**if you use hw-wallets** | 2.6.0
**if you use hw-wallets** | +| | [cardano-cli](https://github.com/input-output-hk/cardano-node/releases/latest) | [cardano-node](https://github.com/input-output-hk/cardano-node/releases/latest) | [cardano-hw-cli](https://github.com/vacuumlabs/cardano-hw-cli/releases/latest) | Ledger Cardano-App | Trezor Firmware | [cardano-signer](https://github.com/gitmachtl/cardano-signer/releases/latest) | +| :--- | :---: | :---: | :---: | :---: | :---: | :---: | +| *Required
version
or higher* | 8.17.0 | 8.7.2
**only needed in online(full)-mode** | 1.13.0
**if you use hw-wallets** | 5.0.0
(6.0.3 for Voting)
**if you use hw-wallets** | 2.6.0
**if you use hw-wallets** | 1.14.0 | -> :bulb: PLEASE USE THE **CONFIG AND GENESIS FILES** FROM [**here**](https://book.world.dev.cardano.org/environments.html), choose MAINNET! +> 💡 PLEASE USE THE **CONFIG AND GENESIS FILES** FROM [**here**](https://book.play.dev.cardano.org/environments.html), choose MAINNET, PREPROD, PREVIEW or SANCHONET!  
### About -Theses scripts here should help you to manage your StakePool via the CLI. As always use them at your own risk, but they should be errorfree. Scripts were made to make things easier while learning all the commands and steps to bring up the stakepool node. So, don't be mad at me if something is not working. CLI calls are different almost daily currently. As always, use them at your own risk.
 
+Theses scripts here should help you to manage your StakePool via the CLI or to do just transactions and advanced stuff on the CLI. They should be errorfree, please report any errors via the [issues](https://github.com/gitmachtl/scripts/issues) section. + +The Scripts were made to make things easier, while learning all the commands and steps to bring up the stakepool node. Please look at them, they are programmed in an easy to understand structure. Each script is a stand-alone script. Also you can do very advanced things with the scripts on the CLI, try them out.
 
Some scripts are using **jq, curl, bc & xxd** so make sure you have it installed with a command like
```$ sudo apt update && sudo apt install -y jq curl bc xxd```  
**Contacts**: Telegram - [@atada_stakepool](https://t.me/atada_stakepool), Twitter - [@ATADA_Stakepool](https://twitter.com/ATADA_Stakepool), Homepage - https://stakepool.at -If you can't hold back and wanna give me a little Tip, here's my MainNet Shelley Ada Address, thx! :-) -```addr1q9vlwp87xnzwywfamwf0xc33e0mqc9ncznm3x5xqnx4qtelejwuh8k0n08tw8vnncxs5e0kustmwenpgzx92ee9crhxqvprhql``` +If you can't hold back and wanna give me a little Tip, here's my MainNet Shelley Ada Address, thx! 🙂 +```addr1v9alunnka0sjm2px9ltwufrrj82yjy9qu45dpa7rze2h7agenhx54``` / ```Adahandle: $gitmachtl``` +  
 
-# Online-Mode vs. Offline-Mode +# Online-Mode vs. Light-Mode vs. Offline-Mode -The scripts are capable to be used in [**Online**](#examples-in-online-mode)- and [**Offline**](#examples-in-offline-mode)-Mode (examples below). It depends on your setup, your needs and just how you wanna work. Doing transactions with pledge accounts in Online-Mode can be a security risk, also doing Stakepool-Registrations in pure Online-Mode can be risky. To enhance Security the scripts can be used on a Online-Machine and an Offline-Machine. You only have to **transfer one single file (offlineTransfer.json)** between the Machines. If you wanna use the Offline-Mode, your **Gateway-Script** to get Data In/Out of the offlineTransfer.json is the **01_workOffline.sh** Script. The **offlineTransfer.json** is your carry bag between the Machines.
+The scripts are capable to be used in [**Online**](#examples-in-online-mode)-, [**Light**](#examples-in-light-mode) and [**Offline**](#examples-in-offline-mode)-Mode (examples below). It depends on your setup, your needs and just how you wanna work. Doing transactions with pledge accounts in Online-Mode can be a security risk, also doing Stakepool-Registrations in pure Online-Mode can be risky. To enhance Security the scripts can be used on a Online-Machine and an Offline-Machine. You only have to **transfer one single file (offlineTransfer.json)** between the Machines. If you wanna use the Offline-Mode, your **Gateway-Script** to get Data In/Out of the offlineTransfer.json is the **01_workOffline.sh** Script. The **offlineTransfer.json** is your carry bag between the Machines.
-Why not always using Offline-Mode? You have to do transactions online, you have to check balances online. Also, there are plenty of usecases using small wallets without the need of the additional steps to do all offline everytime. Also if you're testing some things on Testnets, it would be a pain to always transfer files between the Hot- and the Cold-Machine. You choose how you wanna work... :smiley:
+**Why not always using Offline-Mode?** You have to do transactions online, you have to check balances online. Also, there are plenty of usecases using small wallets without the need of the additional steps to do all offline everytime. Also if you're testing some things on Testnets, it would be a pain to always transfer files between the Hot- and the Cold-Machine. You choose how you wanna work... :smiley:
+ +**So whats this Light-Mode than?** If you switch the scripts into Light-Mode - see below how easy it is to do so - you have the advantage of being online with your machine, but you don't need a running synced cardano-node. You can switch between Networks Mainnet, PreProd and PreView within seconds. This comes is handy if you just don't want to install and run a cardano-node, if you don't have the space for the database or if you just don't have the time to wait for a resync. All transactions are of course generated and signed locally, but the queries and the transmit is done via online APIs like Koios.
- How do you switch between Online- and Offline-Mode? :bookmark_tabs: + How do you switch between Online-, Light- and Offline-Mode? 📑 -
Thats simple, you just change a single entry in the 00_common.sh, common.inc or $HOME/.common.inc config-file: -
```offlineMode="no"``` Scripts are working in Online-Mode -
```offlineMode="yes"``` Scripts are working in Offline-Mode - -So on the Online-Machine you set the ```offlineMode="no"``` and on the Offline-Machine you set the ```offlineMode="yes"```. +
Thats simple, you just change a single entry in the **00_common.sh**, **common.inc** or **$HOME/.common.inc** config-file: +* **`workMode="online"`:** Scripts are working in Online-Mode aka Full-Mode. A locally running and synced cardano-node is needed. +* **`workMode="light"`:** Scripts are working in Light-Mode. No cardano-node needed. +* **`workMode="offline"`:** Scripts are working in isolation and completely offline. No cardano-node needed.
- What do you need on the Online- and the Offline-Machine? :bookmark_tabs: + What do you need on the Online- and the Offline-Machine? 📑 -
On the Online-Machine you need a running and fully synced cardano-node, the cardano-cli and also your ```*.addr``` files to query the current balance of them for the Offline-Machine. **You should not have any signing keys ```*.skey``` files of big wallets laying around!** Metadata-Files are fine, you need them anyway to transfer them to your Stakepool-Webserver, also they are public available, no security issue. +
On the Online-Machine you need a running and fully synced cardano-node, the cardano-cli and also your ```*.addr``` files to query the current balance of them for the Offline-Machine. +**You should not have any signing keys `*.skey` files of big wallets laying around!** Metadata-Files are fine, you need them anyway to transfer them to your Stakepool-Webserver, also they are public available, no security issue. + +On the Machine running in Light-Mode you need cardano-cli but you don't need cardano-node. You also have your ```*.addr``` files to query the current balance of them for the Offline-Machine. **You should not have any signing keys ```*.skey``` files of big wallets laying around!** Metadata-Files are fine, you need them anyway to transfer them to your Stakepool-Webserver, also they are public available, no security issue. On the Offline-Machine you have your signing keys, thats the ```*.skey``` files, also you have your kes-keys, vrf-keys, opcerts, etc. on this Machine. You need the cardano-cli on the Offline-Machine, same version as on the Online-Machine! You don't need the cardano-node, because you will never be online with that Machine! @@ -56,7 +63,7 @@ The scripts need a few other helper tools: **curl, bc, xxd** and **jq**. To get 1. Make a temporary directory, change into that directory and run the following command:
```sudo apt-get update && sudo apt-get download bc xxd jq curl``` -:floppy_disk: Transfer the *.deb files from that directory to the Offline-Machine. +💾 Transfer the *.deb files from that directory to the Offline-Machine. **Offline-Machine:** @@ -67,7 +74,7 @@ Done, you have successfully installed the few little tools now on your Offline-M
- Best practice Advise for Stakepool Operators ... :bookmark_tabs: + Best practice Advise for Stakepool Operators ... 📑  
1. Work in Offline-Mode whenever you can, even when you use Hardware-Keys, your PoolNode-Cold-Keys should be on an Offline-Machine. @@ -80,14 +87,14 @@ Done, you have successfully installed the few little tools now on your Offline-M
- How do you migrate your existing StakePool to HW-Wallet-Owner-Keys ... :bookmark_tabs: + How do you migrate your existing StakePool to HW-Wallet-Owner-Keys ... 📑
You can find examples below in the Online- and Offline-Examples section. [Online-Migration-Example](#migrate-your-existing-stakepool-to-hw-wallet-owner-keys-ledgertrezor), [Offline-Migration-Example](#migrate-your-existing-stakepool-offline-to-hw-wallet-owner-keys-ledgertrezor)
- How do you import your existing Keys made via CLI or Tutorials ... :bookmark_tabs: + How do you import your existing Keys made via CLI or Tutorials ... 📑
You can find examples how to import your existing live PoolData in Online- or Offline-Mode [here](#import-your-existing-pool-from-cli-keys-or-tutorials) @@ -99,6 +106,7 @@ Done, you have successfully installed the few little tools now on your Offline-M We all work closely together in the Cardano-Ecosystem, so there is no need that i repeat a How-To here. Instead i will point you to a few Tutorials that are already online and maintained. You can come back here after you have successfully installed the cardano-node. :smiley: +* [Cardano-Node-Compiling-Guide](https://github.com/input-output-hk/cardano-node-wiki/blob/main/docs/getting-started/install.md) by IOHK * [Cardano-Node-Installation-Guide](https://cardano-node-installation.stakepool247.eu/) by Stakepool247.eu * [How-to-build-a-Haskell-Stakepool-Node](https://www.coincashew.com/coins/overview-ada/guide-how-to-build-a-haskell-stakepool-node) Coincashew-Tutorial * [Cardano-Foundation-Stakepool-Course](https://cardano-foundation.gitbook.io/stake-pool-course/stake-pool-guide/getting-started/install-node) StakePool-Course by Cardano-Foundation @@ -110,7 +118,7 @@ We all work closely together in the Cardano-Ecosystem, so there is no need that Installation is simple, just copy them over or do a git clone so you can also do a quick update in the future.
- How to get the scripts on your Linux machine ... :bookmark_tabs:
+ How to get the scripts on your Linux machine ... 📑

You can just download the [ZIP-Archive](https://github.com/gitmachtl/scripts/archive/master.zip), unzip it in a directory of your choice and use the scripts directly in there.
However, if you wanna make them usable in all directories you should make a fixed directory like **$HOME/stakepoolscripts** and add this directory to your global PATH environment: @@ -149,7 +157,7 @@ cp cardano/testnet/* bin/
- How to verify the SHA256 checksum for Mainnet-Scripts ... :bookmark_tabs:
+ How to verify the SHA256 checksum for Mainnet-Scripts ... 📑

In addition to the `sha256sum_sposcripts.txt` file that is stored in the GitHub Repository, you can do an additional check with a file that is hosted on a different secure webserver: @@ -158,13 +166,14 @@ cp cardano/testnet/* bin/ cd $HOME/stakepoolscripts/bin sha256sum -c <(curl -s https://my-ip.at/sha256/sha256sum_sposcripts.txt) ``` -This will fetch the checksum file from an external webserver and it will compare each \*.sh file with the stored sha256 checksum, you should get an output like this:
+This will fetch the checksum file from an external webserver and it will compare each file with the stored sha256 checksum, you should get an output like this:
```console 00_common.sh: OK 01_claimRewards.sh: OK +01_protectKey.sh: OK 01_queryAddress.sh: OK -01_sendLovelaces.sh: OK 01_sendAssets.sh: OK +01_sendLovelaces.sh: OK 01_workOffline.sh: OK 02_genPaymentAddrOnly.sh: OK 03a_genStakingPaymentAddr.sh: OK @@ -174,24 +183,37 @@ This will fetch the checksum file from an external webserver and it will compare 04b_genVRFKeys.sh: OK 04c_genKESKeys.sh: OK 04d_genNodeOpCert.sh: OK +04e_checkNodeOpCert.sh: OK 05a_genStakepoolCert.sh: OK 05b_genDelegationCert.sh: OK 05c_regStakepoolCert.sh: OK 05d_poolWitness.sh: OK +05e_checkPoolOnChain.sh: OK 06_regDelegationCert.sh: OK 07a_genStakepoolRetireCert.sh: OK 07b_deregStakepoolCert.sh: OK 08a_genStakingAddrRetireCert.sh: OK 08b_deregStakingAddrCert.sh: OK -0x_convertITNtoStakeAddress.sh: OK -0x_showCurrentEpochKES.sh: OK +09a_catalystVote.sh: OK +0x_importHelper.sh: OK +10_genPolicy.sh: OK +11a_mintAsset.sh: OK +11b_burnAsset.sh: OK +12a_genAssetMeta.sh: OK +12b_checkAssetMetaServer.sh: OK +13a_spoPoll.sh: OK +13b_sendSpoPoll.sh: OK +bech32: OK +token-metadata-creator: OK +catalyst-toolbox: OK +cardano-signer: OK ``` All files are verified! :smiley:
**Don't panic if you see a fail**, this could also mean that you have not the latest version of the script on your system. Read above on how to simply update to the latest version.
 
- Checkout how to use the scripts with directories for wallets/pooldata... :bookmark_tabs:
+ Checkout how to use the scripts with directories for wallets/pooldata... 📑

There is no fixed directory structure, the current design is FLAT. So all Examples below are generating/using files within the same directory. This should be fine for the most of you. If you're fine with this, skip this section and check the [Scriptfile Syntax](#configuration-scriptfiles-syntax--filenames) above.

However, if you wanna use directories there is a way: * **Method-1:** Making a directory for a complete set: (all wallet and poolfiles in one directory) @@ -206,7 +228,7 @@ All files are verified! :smiley:
**Don't panic if you see a fail**, this coul
```03a_genStakingPaymentAddr.sh mywallets/allmyada cli``` this will generate your StakeAddressCombo with name allmyada in the mywallets subdirectory
```05b_genDelegationCert.sh mypools/superpool mywallets/allmyada``` this will generate the DelegationCertificate for your StakeAddress allmyada to your Pool named superpool. So, just use always the directory name infront to reference it on the commandline parameters. And keep in mind, you have to do it always from your choosen BASE directory. Because files like the poolname.pool.json are refering also to the subdirectories. And YES, you need a name like superpool or allmyada for it, don't call the scripts without them.
- :bulb: Don't call the scripts with directories like ../xyz or /xyz/abc, it will not work at the moment. Call them from the choosen BASE directory without a leading . or .. Thx! + 💡 Don't call the scripts with directories like ../xyz or /xyz/abc, it will not work at the moment. Call them from the choosen BASE directory without a leading . or .. Thx!

@@ -221,36 +243,38 @@ Checkout the configuration parameters in your 00_common.sh Main-Configuration fi Here are the Main Configuration parameters and the full Syntax details for each script: -
00_common.sh: main config file (:warning:) for the environment itself! Set your variables in there for your config, will be used by the scripts.:bookmark_tabs: - +
00_common.sh: main config file ⚠️ for the environment itself! Set your variables in there for your config, will be used by the scripts. 📑 +
| Important Parameters | Description | Example | | :--- | :--- | :--- | -| offlineMode | Switch for the scripts to work
in *Online*- or *Offline*-Mode | ```yes``` for Offline-Mode
```no``` for Online-Mode (Default) | -| offlineFile | Path to the File used for the transfer
between the Online- and Offline-Machine | ```./offlineTransfer.json``` (Default) | +| workMode | Switch for the scripts to work
in *Online*- *Light*- or *Offline*-Mode | ```online``` for Online(Full)-Mode (Default)
```light``` for Light-Mode
```offline``` for Offline-Mode | | cardanocli | Path to your *cardano-cli* binary | ```./cardano-cli``` (Default)
```cardano-cli``` if in the global PATH | | cardanonode | Path to your *cardano-node* binary
(only for Online-Mode) | ```./cardano-node``` (Default)
```cardano-node``` if in the global PATH | +| offlineFile | Path to the File used for the transfer
between the Online- and Offline-Machine | ```./offlineTransfer.json``` (Default) | | socket | Path to your running passive node
(only for Online-Mode) | ```db-mainnet/node.socket``` | | bech32_bin | Path to your *bech32* binary
(part of the scripts) |```./bech32``` (Default)
```bech32``` if in the global PATH| | cardanohwcli | Path to your *cardano-hw-cli* binary
(only for HW-Wallet support) | ```cardano-hw-cli``` if in the global PATH (Default)| +| cardansigner | Path to your *cardano-signer* binary
(part of the scripts)| ```./cardano-signer``` (Default)
```cardano-signer```if in the global PATH| | genesisfile | Path to your *SHELLEY* genesis file | ```config-mainnet/mainnet-shelley-genesis.json``` | | genesisfile_byron | Path to your *BYRON* genesis file | ```config-mainnet/mainnet-byron-genesis.json``` | -| network | Name of the preconfigured network-settings | ```mainnet``` for the Mainnet (Default)
```preprod``` for PreProduction-TN
```preview``` for Preview-TN
```legacy``` for the Legacy-TN
```vasil-dev``` for the Vasil-Developer-Chain | +| network | Name of the preconfigured network-settings | ```mainnet``` for the Mainnet (Default)
```preprod``` for PreProduction-TN
```preview``` for Preview-TN
```sancho``` for the SanchoNet-Testnet | | magicparam¹
addrformat¹ | Type of the Chain your using
and the Address-Format | ```--mainnet``` for mainnet
```--testnet-magic 1097911063``` for the testnet
```--testnet-magic 3``` for launchpad | | byronToShelleyEpochs¹ | Number of Epochs between Byron
to Shelley Fork | ```208``` for mainnet (Default)
```74``` for the testnet
```8``` for alonzo-purple(light) | -| jcli_bin | Path to your *jcli* binary
(only for ITN ticker proof) | ```./jcli``` (Default) | | cardanometa | Path to your *token-metadata-creator* binary
(part of the scripts) |```./token-metadata-creator``` (Default)
```token-metadata-creator``` if in the global PATH| +| catalyst_toolbox_bin | Path to your *catalyst-toolbox* binary
(part of the scripts) |```./catalyst-toolbox``` (Default)
```catalyst-toolbox``` if in the global PATH| + **¹ Optional-Option**: If the ```network``` parameter is not set. - :bulb: **Overwritting the default settings:** You can now place a file with name ```common.inc``` in the calling directory and it will be sourced by the 00_common.sh automatically. So you can overwrite the setting-variables dynamically if you want. Or if you wanna place it in a more permanent place, you can name it ```.common.inc``` and place it in the user home directory. The ```common.inc``` in a calling directory will overwrite the one in the home directory if present.
+ 💡 **Overwritting the default settings:** You can place a file with name ```common.inc``` in the calling directory and it will be sourced by the 00_common.sh automatically. So you can overwrite the setting-variables dynamically if you want. Or if you wanna place it in a more permanent place, you can name it ```.common.inc``` and place it in the user home directory. The ```common.inc``` in a calling directory will overwrite the one in the home directory if present.
You can also use it to set the CARDANO_NODE_SOCKET_PATH environment variable by just calling ```source ./00_common.sh```  
-
01_workOffline.sh: this is the script you're doing your Online-Offline-Online-Offline work with:bookmark_tabs: +
01_workOffline.sh: this is the script you're doing your Online-Offline-Online-Offline work with📑
```./01_workOffline.sh [additional data]```
```./01_workOffline.sh new``` Resets the offlineTransfer.json with only the current protocol-parameters in it (OnlineMode only) @@ -270,21 +294,23 @@ Checkout the configuration parameters in your 00_common.sh Main-Configuration fi  
-
01_queryAddress.sh: checks the amount of lovelaces and tokens on an address with autoselection about a UTXO query on enterprise & payment(base) addresses or a rewards query for stake addresses:bookmark_tabs: +
01_queryAddress.sh: checks the amount of lovelaces and tokens on an address with autoselection about a UTXO query on enterprise & payment(base) addresses or a rewards query for stake addresses📑 -
```./01_queryAddress.sh ``` **NEW** you can use now an $adahandle too +
```./01_queryAddress.sh ``` 🆕 you can use Adahandles $adahandle, Sub- and Virtual-Handles $sub@hndl too
```./01_queryAddress.sh addr1``` shows the lovelaces from addr1.addr
```./01_queryAddress.sh owner.staking``` shows the current rewards on the owner.staking.addr
```./01_queryAddress.sh addr1vyjz4gde3aqw7e2vgg6ftdu687pcnpyzal8ax37cjukq5fg3ng25m``` shows the lovelaces on this given Bech32 address
```./01_queryAddress.sh stake1u9w60cpjg0xnp6uje8v3plcsmmrlv3vndcz0t2lgjma0segm2x9gk``` shows the rewards on this given Bech32 address
```./01_queryAddress.sh '$adahandle'``` shows the lovelaces of the address that hold the $adahandle. Important: put it always into ' ' like ```'$myadahandle'``` +
```./01_queryAddress.sh '$sub@hndl'``` shows the lovelaces of the address that holds the Sub-Adahandle $sub@hndl +
```./01_queryAddress.sh '$virtual@hndl'``` shows the lovelaces of the address that is associated with the Virtual-Adahandle $virtual@hndl  
-
01_sendLovelaces.sh: sends a given amount of lovelaces or ALL lovelaces or ALLFUNDS lovelaces+tokens from one address to another, uses always all UTXOs of the source address:bookmark_tabs: +
01_sendLovelaces.sh: sends a given amount of lovelaces or ALL lovelaces or ALLFUNDS lovelaces+tokens from one address to another, uses always all UTXOs of the source address📑 -
```./01_sendLovelaces.sh [Opt: metadata.json/cbor] [Opt: "msg: messages"] [Opt: selected UTXOs]```**¹**```[Opt: "utxolimit:"] [Opt: "skiputxowithasset:"] [Opt: "onlyutxowithasset:"]```**²** (you can send to an HASH address too) +
```./01_sendLovelaces.sh [Opt: metadata.json/cbor] [Opt: "msg: messages"] [Opt: selected UTXOs]```**¹**```[Opt: "utxolimit:"] [Opt: "skiputxowithasset:"] [Opt: "onlyutxowithasset:"]```**²**```[Opt: "enc: encryptionmode]```**³**```[Opt: "pass:```./01_sendLovelaces.sh addr1 addr2 1000000``` to send 1000000 lovelaces from addr1.addr to addr2.addr
```./01_sendLovelaces.sh addr1 addr2 2000000 "msg: here is your money"``` to send 2000000 lovelaces from addr1.addr to addr2.addr and add the transaction message "here is your money" @@ -295,20 +321,22 @@ Checkout the configuration parameters in your 00_common.sh Main-Configuration fi
```./01_sendLovelaces.sh addr1 addr2 5000000 mymetadata.json``` to send 5 ADA from addr1.addr to addr2.addr and attach the metadata-file mymetadata.json
```./01_sendLovelaces.sh addr1 addr1 min myvoteregistration.cbor``` to send the metadata-file myvoteregistration.cbor and use the minimum required amount of lovelaces to do so - :bulb: **¹ Expert-Option**: It is possible to specify the exact UTXOs the script should use for the transfer, you can provide these as an additional parameter within quotes like ```"5cf85f03990804631a851f0b0770e613f9f86af303bfdb106374c6093924916b#0"``` to specify one UTXO and like ```"5cf85f03990804631a851f0b0770e613f9f86af303bfdb106374c6093924916b#0|6ab045e549ec9cb65e70f544dfe153f67aed451094e8e5c32f179a4899d7783c#1"``` to specify two UTXOs separated via a `|` char. + 💡 **¹ Expert-Option**: It is possible to specify the exact UTXOs the script should use for the transfer, you can provide these as an additional parameter within quotes like ```"5cf85f03990804631a851f0b0770e613f9f86af303bfdb106374c6093924916b#0"``` to specify one UTXO and like ```"5cf85f03990804631a851f0b0770e613f9f86af303bfdb106374c6093924916b#0|6ab045e549ec9cb65e70f544dfe153f67aed451094e8e5c32f179a4899d7783c#1"``` to specify two UTXOs separated via a `|` char. - :bulb: **² Expert-Option**: It is possible to specify the maximum number of input UTXOs the script should use for the transfer, you can provide these as an additional parameter within quotes like ```"utxolimit: 300"``` to set the max. no of input UTXOs to 300. + 💡 **² Expert-Option**: It is possible to specify the maximum number of input UTXOs the script should use for the transfer, you can provide these as an additional parameter within quotes like ```"utxolimit: 300"``` to set the max. no of input UTXOs to 300. - :bulb: **² Expert-Option**: In rare cases you wanna **skip** input UTXOs that contains one or more defined Assets policyIDs(+assetName) in hex-format:
```"skiputxowithasset: 34250edd1e9836f5378702fbf9416b709bc140e04f668cc35520851801020304"``` to skip all input UTXOs that contains assets(hexformat) '34250edd1e9836f5378702fbf9416b709bc140e04f668cc35520851801020304'
```"skiputxowithasset: yyy|zzz"``` to skip all input UTXOs that contains assets with the policyID yyy or zzz + 💡 **² Expert-Option**: In rare cases you wanna **skip** input UTXOs that contains one or more defined Assets policyIDs(+assetName) in hex-format:
```"skiputxowithasset: 34250edd1e9836f5378702fbf9416b709bc140e04f668cc35520851801020304"``` to skip all input UTXOs that contains assets(hexformat) '34250edd1e9836f5378702fbf9416b709bc140e04f668cc35520851801020304'
```"skiputxowithasset: yyy|zzz"``` to skip all input UTXOs that contains assets with the policyID yyy or zzz - :bulb: **² Expert-Option**: In rare cases you **only** wanna use input UTXOs that contains one or more defined Assets policyIDs(+assetName) in hex-format:
```"onlyutxowithasset: 34250edd1e9836f5378702fbf9416b709bc140e04f668cc35520851801020304"``` to use only UTXOs that contains assets(hexformat) '34250edd1e9836f5378702fbf9416b709bc140e04f668cc35520851801020304'
```"onlyutxowithasset: yyy|zzz"``` to only use input UTXOs that contains assets with the policyID yyy or zzz - + 💡 **² Expert-Option**: In rare cases you **only** wanna use input UTXOs that contains one or more defined Assets policyIDs(+assetName) in hex-format:
```"onlyutxowithasset: 34250edd1e9836f5378702fbf9416b709bc140e04f668cc35520851801020304"``` to use only UTXOs that contains assets(hexformat) '34250edd1e9836f5378702fbf9416b709bc140e04f668cc35520851801020304'
```"onlyutxowithasset: yyy|zzz"``` to only use input UTXOs that contains assets with the policyID yyy or zzz + + 💡 **³ Security-Option**: You can encrypt your transactions message (provided via the "msg: ..." parameter), by enabling the encryption mode. To do so, add ```"enc: basic"``` to the parameters. If you wanna change the default passphrase from `cardano` to an own one, you can provide it via the ```"pass:"``` parameter. Be aware, the passphrase starts right after the : char, so spaces are also included in a passphrase! +  
-
01_sendAssets.sh: sends Assets(Tokens) and optional a given amount of lovelaces from one address to another:bookmark_tabs: +
01_sendAssets.sh: sends Assets(Tokens) and optional a given amount of lovelaces from one address to another📑 -
```./01_sendAssets.sh .asset|bech32-Assetname> ```**¹** ```[Opt: Amount of lovelaces to attach] [Opt: metadata.json] [Opt: "msg: messages"] [Opt: selected UTXOs]```**²**```[Opt: "utxolimit:"] [Opt: "skiputxowithasset:"] [Opt: "onlyutxowithasset:"]```**³** +
```./01_sendAssets.sh .asset|bech32-Assetname> ```**¹** ```[Opt: Amount of lovelaces to attach] [Opt: metadata.json] [Opt: "msg: messages"] [Opt: selected UTXOs]```**²**```[Opt: "utxolimit:"] [Opt: "skiputxowithasset:"] [Opt: "onlyutxowithasset:"]```**³**```[Opt: "enc: encryptionmode]```4```[Opt: "pass:4
```./01_sendAssets.sh addr1 addr2 mypolicy.SUPERTOKEN 15```
to send 15 SUPERTOKEN from addr1.addr to addr2.addr with minimum lovelaces attached
```./01_sendAssets.sh addr1 addr2 mypolicy.SUPERTOKEN 20 "msg: here are your tokens"```
to send 20 SUPERTOKEN from addr1.addr to addr2.addr with minimum lovelaces attached, also with the transaction message "here are your tokens" @@ -320,37 +348,41 @@ Checkout the configuration parameters in your 00_common.sh Main-Configuration fi Using the **PolicyID.TokenNameHASH** or **Bech-AssetName** allowes you to send out Tokens you've got from others. Your own generated Tokens can also be referenced by the AssetFile 'policyName.tokenName.asset' schema for an easier handling. - :bulb: **¹ Expert-Option**: It is possible to send multiple different tokens at the same time! To do so just specify them all in a quoted parameter-3 like: ```"asset14a8suq4v20watch3tzt2f7yj8kvmecgrcsqsps 15 | asset1pmmzqf2akudknt05ealtvcvsy7n6wnc9dd03mf 99"```. You can use the asset-filename, the policyID.Name or the bech32-Assetname for it. The tokens are separated via a `|` char. + 💡 **¹ Expert-Option**: It is possible to send multiple different tokens at the same time! To do so just specify them all in a quoted parameter-3 like: ```"asset14a8suq4v20watch3tzt2f7yj8kvmecgrcsqsps 15 | asset1pmmzqf2akudknt05ealtvcvsy7n6wnc9dd03mf 99"```. You can use the asset-filename, the policyID.Name or the bech32-Assetname for it. The tokens are separated via a `|` char. - :bulb: **¹ Expert-Option**: It is also possible to **bulk send** all tokens starting with a given policyID.name* at the same time! To do so just specify them like: ```"7724da6519bbdda506e4d8acce11e01e01019726ddf017418f9c958a.* all"```. To send out all your CryptoDoggies at the same time. You can even go further and specify them with starting chars for the assetName like: ```"b43131f2c82825ee3d81705de0896c611f35ed38e48e33a3bdf298dc.Crypto* all"```. To send out all assets with the specified policyID, and the assetName is starting with 'Crypto'. Make sure to have a `*` at the end! :smiley: + 💡 **¹ Expert-Option**: It is also possible to **bulk send** all tokens starting with a given policyID.name* at the same time! To do so just specify them like: ```"7724da6519bbdda506e4d8acce11e01e01019726ddf017418f9c958a.* all"```. To send out all your CryptoDoggies at the same time. You can even go further and specify them with starting chars for the assetName like: ```"b43131f2c82825ee3d81705de0896c611f35ed38e48e33a3bdf298dc.Crypto* all"```. To send out all assets with the specified policyID, and the assetName is starting with 'Crypto'. Make sure to have a `*` at the end! :smiley: - :bulb: **² Expert-Option**: It is possible to specify the exact UTXOs the script should use for the transfer, you can provide these as an additional parameter within quotes like ```"5cf85f03990804631a851f0b0770e613f9f86af303bfdb106374c6093924916b#0"``` to specify one UTXO and like ```"5cf85f03990804631a851f0b0770e613f9f86af303bfdb106374c6093924916b#0|6ab045e549ec9cb65e70f544dfe153f67aed451094e8e5c32f179a4899d7783c#1"``` to specify two UTXOs separated via a `|` char. + 💡 **² Expert-Option**: It is possible to specify the exact UTXOs the script should use for the transfer, you can provide these as an additional parameter within quotes like ```"5cf85f03990804631a851f0b0770e613f9f86af303bfdb106374c6093924916b#0"``` to specify one UTXO and like ```"5cf85f03990804631a851f0b0770e613f9f86af303bfdb106374c6093924916b#0|6ab045e549ec9cb65e70f544dfe153f67aed451094e8e5c32f179a4899d7783c#1"``` to specify two UTXOs separated via a `|` char. - :bulb: **³ Expert-Option**: It is possible to specify the maximum number of input UTXOs the script should use for the transfer, you can provide these as an additional parameter within quotes like ```"utxolimit: 300"``` to set the max. no of input UTXOs to 300. + 💡 **³ Expert-Option**: It is possible to specify the maximum number of input UTXOs the script should use for the transfer, you can provide these as an additional parameter within quotes like ```"utxolimit: 300"``` to set the max. no of input UTXOs to 300. - :bulb: **³ Expert-Option**: In rare cases you wanna **skip** input UTXOs that contains one or more defined Assets policyIDs(+assetName) in hex-format:
```"skiputxowithasset: 34250edd1e9836f5378702fbf9416b709bc140e04f668cc35520851801020304"``` to skip all input UTXOs that contains assets(hexformat) '34250edd1e9836f5378702fbf9416b709bc140e04f668cc35520851801020304'
```"skiputxowithasset: yyy|zzz"``` to skip all input UTXOs that contains assets with the policyID yyy or zzz + 💡 **³ Expert-Option**: In rare cases you wanna **skip** input UTXOs that contains one or more defined Assets policyIDs(+assetName) in hex-format:
```"skiputxowithasset: 34250edd1e9836f5378702fbf9416b709bc140e04f668cc35520851801020304"``` to skip all input UTXOs that contains assets(hexformat) '34250edd1e9836f5378702fbf9416b709bc140e04f668cc35520851801020304'
```"skiputxowithasset: yyy|zzz"``` to skip all input UTXOs that contains assets with the policyID yyy or zzz + + 💡 **³ Expert-Option**: In rare cases you **only** wanna use input UTXOs that contains one or more defined Assets policyIDs(+assetName) in hex-format:
```"onlyutxowithasset: 34250edd1e9836f5378702fbf9416b709bc140e04f668cc35520851801020304"``` to use only UTXOs that contains assets(hexformat) '34250edd1e9836f5378702fbf9416b709bc140e04f668cc35520851801020304'
```"onlyutxowithasset: yyy|zzz"``` to only use input UTXOs that contains assets with the policyID yyy or zzz + + 💡 **4 Security-Option**: You can encrypt your transactions message (provided via the "msg: ..." parameter), by enabling the encryption mode. To do so, add ```"enc: basic"``` to the parameters. If you wanna change the default passphrase from `cardano` to an own one, you can provide it via the ```"pass:"``` parameter. Be aware, the passphrase starts right after the : char, so spaces are also included in a passphrase! - :bulb: **³ Expert-Option**: In rare cases you **only** wanna use input UTXOs that contains one or more defined Assets policyIDs(+assetName) in hex-format:
```"onlyutxowithasset: 34250edd1e9836f5378702fbf9416b709bc140e04f668cc35520851801020304"``` to use only UTXOs that contains assets(hexformat) '34250edd1e9836f5378702fbf9416b709bc140e04f668cc35520851801020304'
```"onlyutxowithasset: yyy|zzz"``` to only use input UTXOs that contains assets with the policyID yyy or zzz -  
-
01_claimRewards.sh claims all rewards from the given stake address and sends it to a receiver address:bookmark_tabs: +
01_claimRewards.sh claims all rewards from the given stake address and sends it to a receiver address📑 -
```./01_claimRewards.sh [Opt: ] [Opt: metadata.json/cbor] [Opt: "msg: messages"] [Opt: selected UTXOs]```**¹** +
```./01_claimRewards.sh [Opt: ] [Opt: metadata.json/cbor] [Opt: "msg: messages"] [Opt: selected UTXOs]```**¹**```[Opt: "enc: encryptionmode]```**²**```[Opt: "pass:```./01_claimRewards.sh owner.staking owner.payment``` sends the rewards from owner.staking.addr to the owner.payment.addr. The transaction fees will also be paid from the owner.payment.addr
```./01_claimRewards.sh owner.staking myrewards myfunds``` sends the rewards from owner.staking.addr to the myrewards.addr. The transaction fees will be paid from the myfunds.addr
```./01_claimRewards.sh owner.staking myrewards "msg: rewards for epoch xxx"``` sends the rewards from owner.staking.addr to the myrewards.addr. Also add the message "rewards from epoch xxx" to it.
```./01_claimRewards.sh owner.staking '$adahandle' myfunds``` sends the rewards from owner.staking.addr to the address with the adahandle. The transaction fees will be paid from the myfunds.addr -:bulb: **¹ Expert-Option**: It is possible to specify the exact UTXOs the script should use for the transfer, you can provide these as an additional parameter within quotes like ```"5cf85f03990804631a851f0b0770e613f9f86af303bfdb106374c6093924916b#0"``` to specify one UTXO and like ```"5cf85f03990804631a851f0b0770e613f9f86af303bfdb106374c6093924916b#0|6ab045e549ec9cb65e70f544dfe153f67aed451094e8e5c32f179a4899d7783c#1"``` to specify two UTXOs separated via a `|` char. +💡 **¹ Expert-Option**: It is possible to specify the exact UTXOs the script should use for the transfer, you can provide these as an additional parameter within quotes like ```"5cf85f03990804631a851f0b0770e613f9f86af303bfdb106374c6093924916b#0"``` to specify one UTXO and like ```"5cf85f03990804631a851f0b0770e613f9f86af303bfdb106374c6093924916b#0|6ab045e549ec9cb65e70f544dfe153f67aed451094e8e5c32f179a4899d7783c#1"``` to specify two UTXOs separated via a `|` char. + +💡 **² Security-Option**: You can encrypt your transactions message (provided via the "msg: ..." parameter), by enabling the encryption mode. To do so, add ```"enc: basic"``` to the parameters. If you wanna change the default passphrase from `cardano` to an own one, you can provide it via the ```"pass:"``` parameter. Be aware, the passphrase starts right after the : char, so spaces are also included in a passphrase!  
-
01_protectKey.sh encrypts or decrypts a specified .skey file with a given password:bookmark_tabs: +
01_protectKey.sh encrypts or decrypts a specified .skey file with a given password📑
```./01_protectKey.sh ```
```./01_protectKey.sh enc mywallet``` Encrypts the mywallet.skey file @@ -360,29 +392,32 @@ Checkout the configuration parameters in your 00_common.sh Main-Configuration fi
```./01_protectKey.sh dec owner.staking``` Decrypts the owner.staking.skey file
```./01_protectKey.sh dec mypool.vrf.skey``` Decrypts the mypool.vrf.skey file -:bulb: There is no need to decrypt a file before usage, if an encrypted .skey file is used in a transaction, a password prompt shows up automatically! +💡 There is no need to decrypt a file before usage, if an encrypted .skey file is used in a transaction, a password prompt shows up automatically!  
-
02_genPaymentAddrOnly.sh: generates an "enterprise" address with the given name for just transfering funds:bookmark_tabs: +
02_genPaymentAddrOnly.sh: generates an "enterprise" address with the given name for just transfering funds📑 -
```./02_genPaymentAddrOnly.sh [Account# 0-1000 for HW-Wallet-Path, Default=0]```**¹** +
```./02_genPaymentAddrOnly.sh [Account# 0-1000 for HW-Wallet-Path, Def=0]```**¹**
```./02_genPaymentAddrOnly.sh addr1 cli``` will generate the CLI-based files addr1.addr, addr1.skey, addr1.vkey
```./02_genPaymentAddrOnly.sh owner enc``` will generate the CLI-based and Password encrypted files addr1.addr, addr1.skey, addr1.vkey
```./02_genPaymentAddrOnly.sh addr1 hw``` will generate the HardwareWallet-based files addr1.addr, addr1.hwsfiles, addr1.vkey
```./02_genPaymentAddrOnly.sh addr2 hw 1``` will generate the HardwareWallet-based files addr2.addr, addr2.hwsfiles, addr2.vkey from subaccount #1 (default=0)
-:bulb: **¹ Expert-Option**: It is possible to specify SubAccounts on your Hardware-Wallet. Theses will derive to the Paths ```1852H/1815H/Account#/0/0``` for the payment-key and ```1852H/1815H/Account#/2/0``` for the staking-key. Be aware, not all Wallets support SubAccounts in this way! The default value is: 0 +💡 **¹ Expert-Option**: It is possible to specify SubAccounts on your Hardware-Wallet. Theses will derive to the Paths ```1852H/1815H/Account#/0/0``` for the payment-key and ```1852H/1815H/Account#/2/0``` for the staking-key. Be aware, not all Wallets support SubAccounts in this way! The default value is: 0  
-
03a_genStakingPaymentAddr.sh: generates the base/payment address & staking address combo with the given name and also the stake address registration certificate:bookmark_tabs: +
03a_genStakingPaymentAddr.sh: generates the base/payment address & staking address combo with the given name and also the stake address registration certificate📑 -
```./03a_genStakingPaymentAddr.sh [Account# 0-1000 for HW-Wallet-Path, Default=0]```**¹** +
```./03a_genStakingPaymentAddr.sh ```

```Optional parameters:```
``` + ["Idx: 0-2147483647"] Sets the IndexNo of the DerivationPath for HW-Keys and CLI-Mnemonics: 1852H/1815H/*H/*/IndexNo (def: 0)```
``` + ["Acc: 0-2147483647"] Sets the AccountNo of the DerivationPath for HW-KEys and CLI-Mnemonics: 1852H/1815H/H/*/* (def: 0)```
``` + ["Mnemonics: 24-words-mnemonics"] To provide a given set of 24 mnemonic words to derive the CLI-Mnemonics keys, otherwise new ones will be generated.``` **¹** ```./03a_genStakingPaymentAddr.sh owner cli``` will generate CLI-based files owner.payment.addr, owner.payment.skey, owner.payment.vkey, owner.staking.addr, owner.staking.skey, owner.staking.vkey, owner.staking.cert @@ -396,21 +431,27 @@ Checkout the configuration parameters in your 00_common.sh Main-Configuration fi ```./03a_genStakingPaymentAddr.sh owner hw 5``` will generate HardwareWallet-based files owner.payment.addr, owner.payment.hwsfile, owner.payment.vkey, owner.staking.addr, owner.staking.hwsfile, owner.staking.vkey, owner.staking.cert using SubAccount #5 (Default=#0) + ```./03a_genStakingPaymentAddr.sh owner mnemonics``` will generate CLI-based files owner.payment.addr, owner.payment.skey, owner.payment.vkey, owner.staking.addr, owner.staking.skey, owner.staking.vkey, owner.staking.cert and owner.payment.mnemonics to be used also with other wallets like Daedalus or Eternl. + + ```./03a_genStakingPaymentAddr.sh owner mnemonics "mnemonics: word1 word2 ... word24"``` to generate payment and staking keys from the given mnemonic words. -:bulb: **¹ Expert-Option**: It is possible to specify SubAccounts on your Hardware-Wallet. Theses will derive to the Paths ```1852H/1815H/Account#/0/0``` for the payment-key and ```1852H/1815H/Account#/2/0``` for the staking-key. Be aware, not all Wallets support SubAccounts in this way! The default value is: 0 +💡 **¹ Expert-Option**: It is possible to specify SubAccounts on your Hardware-Wallet. Theses will derive to the Paths ```1852H/1815H/Account#/0/0``` for the payment-key and ```1852H/1815H/Account#/2/0``` for the staking-key. Be aware, not all Wallets support SubAccounts in this way! The default value is: 0  

-
03b_regStakingAddrCert.sh: register the staking address on the blockchain with the certificate from 03a.:bookmark_tabs: +
03b_regStakingAddrCert.sh: register the staking address on the blockchain with the certificate from 03a.📑 + +
```./03b_regStakingAddrCert.sh [Opt: metadata.json/cbor] [Opt: "msg: messages"] [Opt: "enc: encryptionmode] [Opt: "pass:4 -
```./03b_regStakingAddrCert.sh ```
```./03b_regStakingAddrCert.sh owner.staking addr1``` will register the staking addr owner.staking using the owner.staking.cert with funds from addr1 on the blockchain. you could of course also use the owner.payment address here for funding.
+ 💡 **4 Security-Option**: You can encrypt your transactions message (provided via the "msg: ..." parameter), by enabling the encryption mode. To do so, add ```"enc: basic"``` to the parameters. If you wanna change the default passphrase from `cardano` to an own one, you can provide it via the ```"pass:"``` parameter. Be aware, the passphrase starts right after the : char, so spaces are also included in a passphrase! +  
-
03c_checkStakingAddrOnChain.sh: check the blockchain about the staking address:bookmark_tabs: +
03c_checkStakingAddrOnChain.sh: check the blockchain about the staking address📑
```./03c_checkStakingAddrOnChain.sh ```
```./03c_checkStakingAddrOnChain.sh owner``` will check if the address in owner.staking.addr is currently registered on the blockchain @@ -418,7 +459,7 @@ Checkout the configuration parameters in your 00_common.sh Main-Configuration fi  
-
04a_genNodeKeys.sh: generates the poolname.node.vkey and poolname.node.skey/hwsfile cold keys:bookmark_tabs: +
04a_genNodeKeys.sh: generates the poolname.node.vkey and poolname.node.skey/hwsfile cold keys📑
```./04a_genNodeKeys.sh [ColdKeyIndex# for HW-Wallet, Def=0]```
```./04a_genNodeKeys.sh mypool cli``` generates the node cold keys from standard CLI commands (was default before hw option) @@ -429,7 +470,7 @@ Checkout the configuration parameters in your 00_common.sh Main-Configuration fi  
-
04b_genVRFKeys.sh: generates the poolname.vrf.vkey/skey files:bookmark_tabs: +
04b_genVRFKeys.sh: generates the poolname.vrf.vkey/skey files📑
```./04b_genVRFKeys.sh ```
```./04b_genVRFKeys.sh mypool cli``` generates the node VRF keys from standard CLI commands (was default before) @@ -438,7 +479,7 @@ Checkout the configuration parameters in your 00_common.sh Main-Configuration fi  
-
04c_genKESKeys.sh: generates a new pair of poolname.kes-xxx.vkey/skey files, and updates the poolname.kes.counter file:bookmark_tabs: +
04c_genKESKeys.sh: generates a new pair of poolname.kes-xxx.vkey/skey files, and updates the poolname.kes.counter file📑
Every time you generate a new keypair the number(xxx) autoincrements. To renew your kes/opcert before the keys of your node expires just rerun 04c and 04d!
```04c_genKESKeys.sh ``` @@ -448,20 +489,21 @@ Checkout the configuration parameters in your 00_common.sh Main-Configuration fi  
-
04d_genNodeOpCert.sh: calculates the current KES period from the genesis.json and issues a new poolname.node-xxx.opcert cert:bookmark_tabs: +
04d_genNodeOpCert.sh: calculates the current KES period from the genesis.json and issues a new poolname.node-xxx.opcert cert📑
It also generates the poolname.kes-expire.json file which contains the valid start KES-Period and also contains infos when the generated kes-keys will expire. to renew your kes/opcert before the keys of your node expires just rerun 04c and 04d! after that, update the files on your stakepool server and restart the coreNode
```./04d_genNodeOpCert.sh ```
```./04d_genNodeOpCert.sh mypool``` -:warning: Starting with the Babbage-Era, you're only allowed to increase your OpCertCounter by +1 after at least one block was made in the previous KES periods (last OpCert used).
The script 04d will help you to select the right OpCertCounter!
Please also use script 04e to verify your config! +⚠️ Starting with the Babbage-Era, you're only allowed to increase your OpCertCounter by +1 after at least one block was made in the previous KES periods (last OpCert used).
The script 04d will help you to select the right OpCertCounter!
Please also use script 04e to verify your config!  
-
04e_checkNodeOpCert.sh: checks your current or planned next OpCertFile about the right KES and OpCertCounter:bookmark_tabs: +
04e_checkNodeOpCert.sh: checks your current or planned next OpCertFile about the right KES and OpCertCounter📑
```./04e_checkNodeOpCert.sh ``` +
Examples for detailed results **via LocalNode (OpCertFile)**:
```04e_checkNodeOpCert.sh mypool current``` ... searches for the latest OpCertFile of mypool and checks it to be used as the CURRENT OpCert making blocks
```04e_checkNodeOpCert.sh mypool next``` ... searches for the latest OpCertFile of mypool and checks it to be used as the NEXT OpCert making blocks @@ -473,13 +515,13 @@ Checkout the configuration parameters in your 00_common.sh Main-Configuration fi
```04e_checkNodeOpCert.sh 00000036d515e12e18cd3c88c74f09a67984c2c279a5296aa96efe89``` ... is looking up the current OpCertCounter via Koios for the given HEX-Pool-ID
```04e_checkNodeOpCert.sh mypool``` ... is looking up the current OpCertCounter via Koios for the mypool.pool.id-bech file -:warning: Starting with the Babbage-Era, you're only allowed to increase your OpCertCounter by +1 after at least one block was made in the previous KES periods (last OpCert used).
The script 04d will help you to select the right OpCertCounter!
Please also use script 04e to verify your config! +⚠️ Starting with the Babbage-Era, you're only allowed to increase your OpCertCounter by +1 after at least one block was made in the previous KES periods (last OpCert used).
The script 04d will help you to select the right OpCertCounter!
Please also use script 04e to verify your config!  
-
05a_genStakepoolCert.sh: generates the certificate poolname.pool.cert to (re)register a stakepool on the blockchain:bookmark_tabs: +
05a_genStakepoolCert.sh: generates the certificate poolname.pool.cert to (re)register a stakepool on the blockchain📑
```./05a_genStakepoolCert.sh [optional registration-protection key]``` will generate the certificate poolname.pool.cert from poolname.pool.json file
To register a protected Ticker you will have to provide the secret protection key as a second parameter to the script.
@@ -514,16 +556,16 @@ Checkout the configuration parameters in your 00_common.sh Main-Configuration fi "---": "--- DO NOT EDIT BELOW THIS LINE ---" } ``` - :bulb: **If the json file does not exist with that name, the script will generate one for you, so you can easily edit it.**
+ 💡 **If the json file does not exist with that name, the script will generate one for you, so you can easily edit it.**
poolName is the name of your poolFiles from steps 04a-04d, poolOwner is an array of all the ownerStake from steps 03, poolRewards is the name of the stakeaddress getting the pool rewards (can be the same as poolOwner account), poolPledge in lovelaces, poolCost per epoch in lovelaces, poolMargin in 0.00-1.00 (0-100%).
poolRelays is an array of your IPv4/IPv6 or DNS named public pool relays. Currently the types DNS, IP, IP4, IPv4, IP6 and IPv6 are supported. Examples of multiple relays can be found [HERE](#using-multiple-relays-in-your-poolnamepooljson)
MetaName/Description/Ticker/Homepage is your Metadata for your Pool. The script generates the poolname.metadata.json for you. In poolMetaUrl you must specify your location of the file later on your webserver (you have to upload it to this location).
There is also the option to provide ITN-Witness data in an extended metadata json file. Please read some infos about that [here](#bulb-itn-witness-ticker-check-for-wallets)
After the edit, rerun the script with the name again.
- > :bulb: **Update Pool values (re-registration):** If you have already registered a stakepool on the chain and want to change some parameters, simply [change](#file-autolock-for-enhanced-security) them in the json file and rerun the script again. The 05c_regStakepoolCert.sh script will later do a re-registration instead of a new registration for you. + > 💡 **Update Pool values (re-registration):** If you have already registered a stakepool on the chain and want to change some parameters, simply [change](#file-autolock-for-enhanced-security) them in the json file and rerun the script again. The 05c_regStakepoolCert.sh script will later do a re-registration instead of a new registration for you.  
-
05b_genDelegationCert.sh: generates the delegation certificate name.deleg.cert to delegate a stakeAddress to a Pool:bookmark_tabs: +
05b_genDelegationCert.sh: generates the delegation certificate name.deleg.cert to delegate a stakeAddress to a Pool📑
As pool owner you have to delegate to your own pool, this is registered as pledged stake on your pool. @@ -538,19 +580,20 @@ Checkout the configuration parameters in your 00_common.sh Main-Configuration fi  
-
05c_regStakepoolCert.sh: (re)register your poolname.pool.cert certificate:bookmark_tabs: +
05c_regStakepoolCert.sh: (re)register your poolname.pool.cert certificate📑
It also uses submits **owner name.deleg.cert certificate** with funds from the given name.addr on the blockchain. Also it updates the pool-ID and the registration date in the poolname.pool.json -
```./05c_regStakepoolCert.sh [optional REG / REREG keyword]``` +
```./05c_regStakepoolCert.sh ```

``` [Opt: force a registration "type: REG", force a re-registration "type: REREG"]```
``` [Opt: Message comment, starting with "msg: ...", | is the separator]```
``` [Opt: encrypted message mode "enc:basic". Currently only 'basic' mode is available.]```
``` [Opt: passphrase for encrypted message mode "pass:", the default passphrase is 'cardano' if not provided]``` +
```./05c_regStakepoolCert.sh mypool owner.payment``` this will register your pool mypool with the cert and json generated with script 05a on the blockchain. Owner.payment.addr will pay for the fees.
If the pool was registered before (when there is a **regSubmitted** value in the name.pool.json file), the script will automatically do a re-registration instead of a registration. The difference is that you don't have to pay additional fees for a re-registration.
- > :bulb: If something went wrong with the original pool registration, you can force the script to redo a normal registration by adding the keyword REG on the commandline like ```./05c_regStakepoolCert.sh mypool mywallet REG```
-Also you can force the script to do a re-registration by adding the keyword REREG on the command line like ```./05c_regStakepoolCert.sh mypool mywallet REREG``` + > 💡 If something went wrong with the original pool registration, you can force the script to redo a normal registration by setting the registration-type to REG like ```./05c_regStakepoolCert.sh mypool mywallet "type: REG"```
+Also you can force the script to do a re-registration by using the REREG type on the command line like ```./05c_regStakepoolCert.sh mypool mywallet "type: REREG"```  

-
05d_poolWitness.sh: gives you Status Information, also Signing, Adding and Clearing Witnesses for a PoolRegistration:bookmark_tabs: +
05d_poolWitness.sh: gives you Status Information, also Signing, Adding and Clearing Witnesses for a PoolRegistration📑
```./05d_poolWitness.sh [additional data]```
```05d_poolWitness.sh sign ``` signs the witnessFile with the given signingKey @@ -569,7 +612,7 @@ Also you can force the script to do a re-registration by adding the keyword RERE
-
05e_checkPoolOnChain.sh: gives you Status Information if the specified PoolName or PoolID is registered on the chain:bookmark_tabs: +
05e_checkPoolOnChain.sh: gives you Status Information if the specified PoolName or PoolID is registered on the chain📑
```./05e_checkPoolOnChain.sh ```
```05e_checkPoolOnChain.sh mypool``` checks if the pool mypool is on the chain (it automatically checks the files mypool.pool.id, mypool.pool.id-bech, mypool.pool.json) @@ -580,7 +623,7 @@ Also you can force the script to do a re-registration by adding the keyword RERE
-
06_regDelegationCert.sh: register a simple delegation (from 05b) name.deleg.cert:bookmark_tabs: +
06_regDelegationCert.sh: register a simple delegation (from 05b) name.deleg.cert📑
```./06_regDelegationCert.sh ```
```./06_regDelegationCert.sh someone someone.payment``` this will register the delegation certificate someone.deleg.cert for the stake-address someone.staking.addr on the blockchain. The transaction fees will be paid from someone.payment.addr. @@ -588,7 +631,7 @@ Also you can force the script to do a re-registration by adding the keyword RERE  
-
07a_genStakepoolRetireCert.sh: generates the de-registration certificate poolname.pool.dereg-cert to retire a stakepool from the blockchain:bookmark_tabs: +
07a_genStakepoolRetireCert.sh: generates the de-registration certificate poolname.pool.dereg-cert to retire a stakepool from the blockchain📑
```./07a_genStakepoolRetireCert.sh [optional retire EPOCH]```
```./07a_genStakepoolRetireCert.sh mypool``` generates the mypool.pool.dereg-cert to retire the pool in the NEXT epoch @@ -601,17 +644,17 @@ The script requires a poolname.pool.json file with values for at least the PoolN  
-
07b_deregStakepoolCert.sh: de-register (retire) your pool with the poolname.pool.dereg-cert certificate:bookmark_tabs: +
07b_deregStakepoolCert.sh: de-register (retire) your pool with the poolname.pool.dereg-cert certificate📑
Uses funds from name.payment.addr, it also updates the de-registration date in the poolname.pool.json
```./07b_deregStakepoolCert.sh ```
```./07b_deregStakepoolCert.sh mypool mywallet``` this will retire your pool mypool with the cert generated with script 07a from the blockchain. The transactions fees will be paid from the mywallet.addr account.
- :bulb: Don't de-register your rewards/staking account yet, you will receive the pool deposit fee on it!
+ 💡 Don't de-register your rewards/staking account yet, you will receive the pool deposit fee on it!
 
-
08a_genStakingAddrRetireCert.sh: generates the de-registration certificate name.staking.dereg-cert to retire a stake-address form the blockchain:bookmark_tabs: +
08a_genStakingAddrRetireCert.sh: generates the de-registration certificate name.staking.dereg-cert to retire a stake-address form the blockchain📑
```./08a_genStakingAddrRetireCert.sh ```
```./08a_genStakingAddrRetireCert.sh owner``` generates the owner.staking.dereg-cert to retire the owner.staking.addr @@ -619,7 +662,7 @@ The script requires a poolname.pool.json file with values for at least the PoolN  
-
08b_deregStakingAddrCert.sh: re-register (retire) you stake-address with the name.staking.dereg-cert certificate with funds from name.payment.add from the blockchain.:bookmark_tabs: +
08b_deregStakingAddrCert.sh: re-register (retire) you stake-address with the name.staking.dereg-cert certificate with funds from name.payment.add from the blockchain.📑
```./08b_deregStakingAddrCert.sh ```
```./08b_deregStakingAddrCert.sh owner.staking owner.payment``` this will retire your owner staking address with the cert generated with script 08a from the blockchain. @@ -627,7 +670,7 @@ The script requires a poolname.pool.json file with values for at least the PoolN  
-
09a_catalystVote.sh: Script for generating CIP36-Catalyst-Registration Data, Mnemonics and the QR Code for the Voting-App:bookmark_tabs: +
09a_catalystVote.sh: Script for generating CIP36-Catalyst-Registration Data, Mnemonics and the QR Code for the Voting-App📑
```09a_catalystVote.sh new cli ``` ... Generates a new 24-Words-Mnemonic and derives the VotingKeyPair with the given name
```09a_catalystVote.sh new cli "<24-words-mnenonics>"``` ... Generates a new VotingKeyPair with the given name from an existing 24-Words-Mnemonic @@ -660,7 +703,7 @@ Examples:  
-
10_genPolicy.sh: generate policy keys, signing script and id as files name.policy.skey/hwsfile/vkey/script/id. You need a policy for Token minting.:bookmark_tabs: +
10_genPolicy.sh: generate policy keys, signing script and id as files name.policy.skey/hwsfile/vkey/script/id. You need a policy for Token minting.📑
```./10_genPolicy.sh [Optional valid xxx Slots, Policy invalid after xxx Slots (default=unlimited)]``` @@ -675,10 +718,10 @@ Examples:  
-
11a_mintAsset.sh: mint/generate new Assets(Token) on a given payment address with a policyName (or hexencoded {...}) generated before.:bookmark_tabs: +
11a_mintAsset.sh: mint/generate new Assets(Token) on a given payment address with a policyName (or hexencoded {...}) generated before.📑
This updates the Token Status File **policyname.assetname.asset** for later usage when sending/burning Tokens. -
```./11a_mintAsset.sh [Opt: Metadata JSON to include] [Opt: transaction-messages]``` +
```./11a_mintAsset.sh [Opt: Metadata JSON to include] [Opt: transaction-messages] [Opt: "enc: encryptionmode]```**¹**```[Opt: "pass:this will mint 1000 new SUPERTOKEN with policy 'mypolicy' on the payment address mywallet.addr @@ -692,13 +735,15 @@ Examples: It generally depends on the Policy-Type (made by the script 10a) if you can mint unlimited Tokens or if you are Time-Limited so a fixed Value of Tokens exists and there will never be more. +💡 **¹ Security-Option**: You can encrypt your transactions message (provided via the "msg: ..." parameter), by enabling the encryption mode. To do so, add ```"enc: basic"``` to the parameters. If you wanna change the default passphrase from `cardano` to an own one, you can provide it via the ```"pass:"``` parameter. Be aware, the passphrase starts right after the : char, so spaces are also included in a passphrase! +  
-
11b_burnAsset.sh: burnes Assets(Token) on a given payment address with a policyName you own the keys for.:bookmark_tabs: +
11b_burnAsset.sh: burnes Assets(Token) on a given payment address with a policyName you own the keys for.📑
This updates the Token Status File **policyname.assetname.asset** for later usage when sending/burning Tokens. -
```./11b_burnAsset.sh [Opt: Metadata JSON to include] [Opt: transaction-messages]``` +
```./11b_burnAsset.sh [Opt: Metadata JSON to include] [Opt: transaction-messages] [Opt: "enc: encryptionmode]```**¹**```[Opt: "pass:this will burn 22 SUPERTOKEN with policy 'mypolicy' on the payment address mywallet.addr @@ -710,10 +755,12 @@ It generally depends on the Policy-Type (made by the script 10a) if you can mint It generally depends on the Policy-Type (made by the script 10) if you can burn unlimited Tokens or if you are Time-Limited so a fixed Value of Tokens exists and there will never be less. +💡 **¹ Security-Option**: You can encrypt your transactions message (provided via the "msg: ..." parameter), by enabling the encryption mode. To do so, add ```"enc: basic"``` to the parameters. If you wanna change the default passphrase from `cardano` to an own one, you can provide it via the ```"pass:"``` parameter. Be aware, the passphrase starts right after the : char, so spaces are also included in a passphrase! +  
-
12a_genAssetMeta.sh: is used to generate and sign the special JSON format which is used to register your Token Metadata on the Token-Registry-Server.:bookmark_tabs: +
12a_genAssetMeta.sh: is used to generate and sign the special JSON format which is used to register your Token Metadata on the Token-Registry-Server.📑
This script needs the tool **token-metadata-creator** from IOHK (https://github.com/input-output-hk/offchain-metadata-tools). I uploaded a version of it into the scripts directory so you have a faster start.
```./12a_genAssetMeta.sh ``` @@ -725,7 +772,7 @@ It will use the information stored in the .asset file to g  
-
12b_checkAssetMetaServer.sh: will check the currently stored information about the given Asset from the TokenRegistryServer (only in Online-Mode):bookmark_tabs: +
12b_checkAssetMetaServer.sh: will check the currently stored information about the given Asset from the TokenRegistryServer (only in Online-Mode)📑
```./12b_checkAssetMetaServer.sh ``` @@ -743,7 +790,7 @@ You can run a query by that command against the Cardano Token Registry Server (h The **poolname.pool.json** file is your Config-Json to manage your individual Pool-Settings like owners, fees, costs. You don't have to create the base structure of this Config-Json, **the script 05a_genStakepoolCert.sh will generate a blank one for you** ...
- Checkout how the Config-Json looks like and the parameters ... :bookmark_tabs:
+ Checkout how the Config-Json looks like and the parameters ... 📑

**Sample mypool.pool.json** ```console @@ -797,9 +844,9 @@ The **poolname.pool.json** file is your Config-Json to manage your individual Po | *poolRelays:* relayType | The type of relayEntry you wanna use:
**ip:** you provide the relayEntry as an IPv4 x.x.x.x
**ip6:** you provide the relayEntry as an IPv6 address
**dns:** you provide the relayEntry as a FQDN entry like relay1.wakandapool.com | dns (prefered) | | *poolRelays:* relayEntry | The IP-Address or DNS-Name your relay is reachable to the public| relay1.wakandapool.com | | *poolRelays:* relayPort | The public TCP-Port of your relay, this port must be opened to everyone so they can reach your relay node| 3001 (default) | -| poolMetaName | This is a longer Name for your StakePool, this will be shown in the Wallets like Daedalus or Yoroi.| Wakanda Forever StakePool | -| poolMetaDescription | This is a longer description for your StakePool, this will be shown in the Wallets like Daedalus or Yoroi.| ...tell your story... | -| poolMetaTicker | Thats the short name - also known as Ticker - for your StakePool, this will be shown in the Wallets like Daedalus or Yoroi.| WKNDA | +| poolMetaName | This is a longer Name for your StakePool, this will be shown in the Wallets like Daedalus or Eternl.| Wakanda Forever StakePool | +| poolMetaDescription | This is a longer description for your StakePool, this will be shown in the Wallets like Daedalus or Eternl.| ...tell your story... | +| poolMetaTicker | Thats the short name - also known as Ticker - for your StakePool, this will be shown in the Wallets like Daedalus or Eternl.| WKNDA | | poolMetaHomepage | This is a link to your StakePool-Homepage. As we are security oriented, this should be a https:// link.| `https://www.wakandapool.com` | | poolMetaUrl | This is a link to your MetaFile of your StakePool, it contains all the MetaData above to be shown in the wallets. The scripts will automatically produce this file (f.e. mypool.metadata.json) for you, but you have to upload it yourself to your Homepage. As we are security oriented, this should be a https:// link.| `https://www.wakandapool.com/mypool.metadata.json` | | poolExtendedMetaUrl | You don't need this entry for a working StakePool!
Like the one above, it contains all the special additional informations about your StakePool that cannot be stored in the normal MetaData file. Like your ITN Witness, or all the additions Adapools.org made. The scripts will automatically produce this file (f.e. mypool.extended-metadata.json) for you. Learn more about it [here](#itn-witness-ticker-check-for-wallets-and-extended-metadatajson-infos)| `https://www.wakandapool.com/mypool.metadata.json` | @@ -866,7 +913,7 @@ The **poolname.pool.json** file is your Config-Json to manage your individual Po The **policyName.assetName.asset** file is your Config- and Information Json for your own NativeAssets you minted. In addition to the basic information this also holds your Metadata you wanna provide to the TokenRegistry Server.
**This file will be automatically created by the scripts 11a, 11b or 12a** ...
- Checkout how the AssetFile-Json looks like and the parameters ... :bookmark_tabs:
+ Checkout how the AssetFile-Json looks like and the parameters ... 📑

**Sample wakandaPolicy.mySuperToken.asset** ```console @@ -900,7 +947,7 @@ The **policyName.assetName.asset** file is your Config- and Information Json for | metaUrl | optional | Secure Weblink, must start with https:// (max. 250chars) | https://wakandaforever.io | | metaLogoPNG | optional | Path to a valid PNG Image File for your NativeAsset (max. 64kB) | supertoken.png | -> *:warning: Don't edit the file below the **--- DO NOT EDIT BELOW THIS LINE !!! ---** line. The scripts will store information about your minting and burning process in there together with additional information like lastAction.* +> *⚠️ Don't edit the file below the **--- DO NOT EDIT BELOW THIS LINE !!! ---** line. The scripts will store information about your minting and burning process in there together with additional information like lastAction.* @@ -918,7 +965,7 @@ The **policyName.assetName.asset** file is your Config- and Information Json for | lastUpdate | This shows the date when the assetFile was updated the last time by generation Metadata or Minting/Burning Tokens | *Date* | | lastAction | Short descrition of the process that happend at the date show in the entry lastUpdate | *Action* | -> *:warning: Don't edit the file below the **--- DO NOT EDIT BELOW THIS LINE !!! ---** line. The scripts will store information about your minting and burning process in there together with additional information like lastAction.* +> *⚠️ Don't edit the file below the **--- DO NOT EDIT BELOW THIS LINE !!! ---** line. The scripts will store information about your minting and burning process in there together with additional information like lastAction.*  
 
@@ -930,7 +977,7 @@ The **policyName.assetName.asset** file is your Config- and Information Json for ### Filenames used
- Show all used naming schemes like *.addr, *.skey, *.pool.json, ... :bookmark_tabs:
+ Show all used naming schemes like *.addr, *.skey, *.pool.json, ... 📑

I use the following naming scheme for the files:
``` @@ -940,6 +987,7 @@ name.addr, name.vkey, name.skey Payment(Base)/Staking address combo: name.payment.addr, name.payment.skey/vkey, name.deleg.cert name.staking.addr, name.staking.skey/vkey, name.staking.cert/dereg-cert +name.payment.mnemonics Node/Pool files: poolname.node.skey/vkey, poolname.node.counter, poolname.pool.cert/dereg-cert, poolname.pool.json, @@ -955,7 +1003,7 @@ ITN witness files: poolname.itn.skey/vkey ``` -New for Hardware-Wallet (Ledger/Trezor) support:
+For Hardware-Wallet (Ledger/Trezor) support:
``` Hardware-SigningFile for simple "enterprise" address: name.hwsfile (its like the .skey) @@ -967,7 +1015,7 @@ Witness-Files for PoolRegistration or PoolReRegistration: poolname_name_id.witness ``` -New in Mary-Era:
+For Native-Assets:
``` Policy files: policyname.policy.skey/vkey, policyname.policy.script, policyname.policy.id @@ -994,20 +1042,20 @@ chmod 400 poolname.pool.json  
 
# Working with Hardware-Wallets as an SPO -Please take a few minutes and take a look at the Sections here to find out how to prepare your system, what are the limitations when working with a Hardware-Wallet Ledger Nano S, Nano X or Trezor Model-T. If you need Multi-Witnesses and how to work with them if so ... +Please take a few minutes and take a look at the Sections here to find out how to prepare your system, what are the limitations when working with a Hardware-Wallet Ledger Nano S, Nano S+, Nano X or Trezor Model-T. If you need Multi-Witnesses and how to work with them if so ... ## Choose your preferred Key-Type for your Owner-Pledge-Account(s) As an SPO you can choose how to handle your Owner Pledge Account(s). You can have them as CLI-based Payment&Stake keys, as HW-based Payment&Stake keys or you can have them as HYBRID keys with Hardware-Payment Protection via a HW-Wallet and Stake keys via normal CLI.
- How to generate different Key-Types, Pros and Contras ... :bookmark_tabs:
+ How to generate different Key-Types, Pros and Contras ... 📑

Generating the different Key-Types is easy with the ```./03a_genStakingPaymentAddr.sh ``` script. It takes two parameters: * name: Thats the name you wanna use for the account/filename * key-type: Here you can choose between the normal CLI keys, HW (Ledger/Trezor) keys and HYBRID keys. -| Key
Type | Payment/Spending
Key :key: | Staking/Rewards
Key :key: | Security
Level | Pros and Cons | +| Key
Type | Payment/Spending
Key 🔑 | Staking/Rewards
Key 🔑 | Security
Level | Pros and Cons | | :---: | :---: | :---: | :---: | :---: | | CLI | via cli
(.skey) | via cli
(.skey) | medium | You can do everything, but you have
to keep your .skeys offline for enhanced security | | HYBRID **¹** | via HW-Wallet
(.hwsfile) | via cli
(.skey) | high | The pledge funds are protected via the Hardware-Wallet.
You can do Pool-Updates for MultiOwners without
any Hardware-Wallet attached. **¹** | @@ -1015,29 +1063,29 @@ As an SPO you can choose how to handle your Owner Pledge Account(s). You can hav So you can see in this table there are Pros and Cons with the different types of Keys. You as the SPO have to choose how you wanna work. -:warning: **¹**) The Hybrid-Mode is kind of a "comfort" mode for MultiOwnerPools, but you have to take the following in consideration: You have to use the generated payment(base) Address to fund with your Pledge, you will not see your Wallet delegated to your Pool if your plug the Hardware-Key into Daedalus-, Yoroi- or Adalite-Wallet. If you do a transaction out of it via one of the said wallets, you have to take everything out and send it back to the generated payment(base) Address. So, this mode is comfortable, it protects the Funds with the Hardware-Key, but you also must be a little careful. :smiley: +⚠️ **¹**) The Hybrid-Mode is kind of a "comfort" mode for MultiOwnerPools, but you have to take the following in consideration: You have to use the generated payment(base) Address to fund with your Pledge, you will not see your Wallet delegated to your Pool if your plug the Hardware-Key into Daedalus-, Eternl- or Adalite-Wallet. If you do a transaction out of it via one of the said wallets, you have to take everything out and send it back to the generated payment(base) Address. So, this mode is comfortable, it protects the Funds with the Hardware-Key, but you also must be a little careful. :smiley:
- Can i create more than one account on the Hardware-Key? ... :bookmark_tabs:
+ Can i create more than one account on the Hardware-Key? ... 📑

Yes, there are different ways you can create more than one account on a Hardware-Wallet. If you own a Trezor Model-T for example, enable the **Passphrase-Mode** on the device. In this case you will be asked about a passphrase everytime you access the Trezor device. Each different passphrase will result in a different account. This is also the prefered option to enhance the security on the Trezor device. So even if you have only one account, use the passphrase method! There is also another way by using different derive paths on Hardware-Wallets that let you create multiple SubAccounts on it. The paths will are possible with ```1852H/1815H/Account#/0/0``` for the payment-key and ```1852H/1815H/Account#/2/0``` for the staking-key. The normal(default) account is using Account# 0. The scripts 02 and 03a are supporting this kind of SubAccounts, please checkout the full syntax [here](#main-configuration-file-00_commonsh---syntax-for-all-the-other-ones) -:bulb: Be aware, not all Wallets support SubAccounts in this way! Adalite for example supports this method for the first 100 Accounts, but you have to use them in order. So first transfer some ADA to the Account# 0, after that you can create an Account #1 with some ADA and so on. If you skip an Account, ADALITE and most likely the other wallets too will not show you the balance. You can always access them via the CLI of course. +💡 Be aware, not all Wallets support SubAccounts in this way! Adalite for example supports this method for the first 100 Accounts, but you have to use them in order. So first transfer some ADA to the Account# 0, after that you can create an Account #1 with some ADA and so on. If you skip an Account, ADALITE and most likely the other wallets too will not show you the balance. You can always access them via the CLI of course.
## Limitations to the PoolOperation when using Hardware-Wallets
- About Limitations, what can you do, what can't you do ...:bookmark_tabs:
+ About Limitations, what can you do, what can't you do ...📑

So, there are many things you can do with your Hardware-Wallet as an SPO, but there are also many limitations because of security restrictions. I have tried to make this list below so you can see whats possible and whats not. If its not in this list, its not possible with a Hardware-Wallet for now: -| Action | Payment via CLI-Keys:key: | Payment via HW-Keys:key: (Ledger/Trezor) | +| Action | Payment via CLI-Keys🔑 | Payment via HW-Keys🔑 (Ledger/Trezor) | | :--- | :---: | :---: | | Create a enterprise(payment only, no staking) address | :heavy_check_mark: | :heavy_check_mark: | | Create a stakingaddress combo (base-payment & stake address) | :heavy_check_mark: | :heavy_check_mark: | @@ -1072,7 +1120,7 @@ Basically, you have to do all HW-Wallet related things directly with the hardwar We don't want to run the scripts as a superuser (sudo), so you should add some udev informations. Also for Trezor you have to install the Trezor Bridge.
- Prepare your system so you can use the Hardware-Wallet as a Non-SuperUser ...:bookmark_tabs:
+ Prepare your system so you can use the Hardware-Wallet as a Non-SuperUser ...📑
### Installing the cardano-hw-cli from Vacuumlabs @@ -1164,7 +1212,7 @@ You should now be able to use your Trezor Model-T device as the username you hav Many steps in the workflow are pretty much the same with or without a Hardware-Wallet involved. But there were changes needed to some steps and scripts calls. There are several Limitations what you can do with a HW-Wallet, you can find the list [here](#limitations-to-the-pooloperation-when-using-hardware-wallets).
- Register a StakePool with Hardware-Wallet owners involved ... :bookmark_tabs:
+ Register a StakePool with Hardware-Wallet owners involved ... 📑

One of the major changes comes when you have at least one owner in the StakePool with the stake key from a Hardware-Wallet. Before (when we had only one or more CLI-based stake keys as owners) the StakePool Registration was made with the script ```./05c_regStakepoolCert.sh``` alone, and that Registration included the StakePool Certificate itself and also ALL of the owner delegations to the pool. Thats not possible anymore with a Hardware-Wallet involved as an owner! Only the PoolRegistrationCertificate itself can be included in the Registration. You have to register each owner delegation after the pool Registration individually. (Still possible to do it in one step if a Hardware-Wallet is only used as the destination rewards address for a StakePool!) @@ -1202,20 +1250,20 @@ You can see two different examples, ```local``` and ```external```: * **external** means that you wanna sign this Witness separate in an additional step. This can be on the *same machine* or it can be on *another machine*. So this comes also in handy when you run a *MultiOwnerPool*, thats the method you collect the signed Witnesses from all the other owners. -> :warning: As i wrote above, when at least one pool owner is using a Hardware-Wallet stake key, the individual owner delegations are not included anymore automatically when running ```./05c_regStakepoolCert.sh```. Therefore **you have to transmit each pool delegation** for each owner one by one **after the pool Registration** via the script ```./06_regDelegationCert.sh```! If you're doing this on an Offline-Machine, make sure you have a few small CLI-based operator wallets laying around (smallwallet1, smallwallet2, smallwallet3,...) to directly pay for each delegation registration.
Also you can include all the unsigned Witness files in the **offlineTransfer.json** to bring it out of your Offline-Machine if you like. :smiley: +> ⚠️ As i wrote above, when at least one pool owner is using a Hardware-Wallet stake key, the individual owner delegations are not included anymore automatically when running ```./05c_regStakepoolCert.sh```. Therefore **you have to transmit each pool delegation** for each owner one by one **after the pool Registration** via the script ```./06_regDelegationCert.sh```! If you're doing this on an Offline-Machine, make sure you have a few small CLI-based operator wallets laying around (smallwallet1, smallwallet2, smallwallet3,...) to directly pay for each delegation registration.
Also you can include all the unsigned Witness files in the **offlineTransfer.json** to bring it out of your Offline-Machine if you like. :smiley: Read more about how to sign, transfer and assemble unsigned/signed Witnesses in the next Article.
- How do you register a StakePool with HW-Node-Cold-Keys ... :bookmark_tabs: + How do you register a StakePool with HW-Node-Cold-Keys ... 📑
You can find examples below in the Online- and Offline-Examples section. [Online-HW-Pool-Example](#create-the-stakepool-with-full-hw-wallet-keys-cold-and-owner-ledger), [Offline-HW-Pool-Example](#create-the-stakepool-offline-with-full-hw-wallet-keys-cold-and-owner-ledger)
- How to work with Multi-Witnesses with/without Hardware-Wallet owners involved ... :bookmark_tabs:
+ How to work with Multi-Witnesses with/without Hardware-Wallet owners involved ... 📑

As you have read in the previous article, we have to deal with Multi-Witnesses now for a PoolRegistration if Hardware-Wallets are involved as owners. You can also use Multi-Witnesses with normal CLI-based accounts if you like to work this way in a MultiPoolOwner environment. @@ -1230,7 +1278,7 @@ You can check the current status of your Witnesses for your pool **mypool** (exa This will show you how many Witnesses included in your current PoolRegistration are READY **signed (green)** and which ones are MISSING **unsigned (magenta)** and must be signed now.
To do so you have the Witness-File we learned about a few lines above ```._.witness```. You can **sign a Witness-File** on the same machine, on your Online-Machine, on your Offline-Machine or send the file around the world and let it sign by a friend so he can send it back to you later. -> :warning: You have a limited time window to complete all the Witnesses, this is set to 100.000 slots, so a little bit over 1 day ! +> ⚠️ You have a limited time window to complete all the Witnesses, this is set to 100.000 slots, so a little bit over 1 day ! ### Sign an unsigned Witness-File @@ -1260,9 +1308,9 @@ If you're in Offline-Mode, the script will again ask you if you wanna include th DONE - Puuh :smiley: -> :warning: If you have created a new Pool or if you have added new owners, you have to register each Delegation now on the chain via script ```./06_regDelegationCert.sh```. This additional step is normally included in the ```./05c_regStakepoolCert.sh``` but cannot be used if an owner is a Hardware-Wallet ! +> ⚠️ If you have created a new Pool or if you have added new owners, you have to register each Delegation now on the chain via script ```./06_regDelegationCert.sh```. This additional step is normally included in the ```./05c_regStakepoolCert.sh``` but cannot be used if an owner is a Hardware-Wallet ! -> :warning: As long as you have an ongoing opened Pool Registration, you're not allowed to use your payment address for anything else, because the txBody is already made with the exact amounts of ADA for the transaction in & out ! +> ⚠️ As long as you have an ongoing opened Pool Registration, you're not allowed to use your payment address for anything else, because the txBody is already made with the exact amounts of ADA for the transaction in & out ! ### Abort an ongoing Pool Registration Witness-Collection @@ -1275,13 +1323,12 @@ Yep, it was that simple.
- How do you migrate your existing StakePool to HW-Wallet-Owner-Keys ... :bookmark_tabs: + How do you migrate your existing StakePool to HW-Wallet-Owner-Keys ... 📑
You can find examples below in the Online- and Offline-Examples section. [Online-Migration-Example](#migrate-your-existing-stakepool-to-hw-wallet-owner-keys-ledgertrezor), [Offline-Migration-Example](#migrate-your-existing-stakepool-offline-to-hw-wallet-owner-keys-ledgertrezor)
-  
 
# Catalyst-Voting-Registration @@ -1293,7 +1340,7 @@ The rewards payout address is now a regular payment (base or enterprise) address If you are already using the SPO-Scripts, you're set to do it the simple way. If not, please copy/clone them from the [SPO-Scripts-Mainnet](https://github.com/gitmachtl/scripts/tree/master/cardano/mainnet) folder. All required executables/binaries are included in the repo. You still need your running cardano-node and cardano-cli of course. A detailed [README.md](https://github.com/gitmachtl/scripts/tree/master/cardano/mainnet#readme) about the feature and how to install/use the scripts can be found in the repo.
- Checkout the few easy Steps to do the Registration/Delegation ... :bookmark_tabs: + Checkout the few easy Steps to do the Registration/Delegation ... 📑 ## Register funds of CLI-Keys, HYBRID-Keys or Hardware-Wallets @@ -1304,7 +1351,7 @@ The SPO-Scripts repo contains the following binaries: In case you wanna register funds from your **Hardware-Wallet**, please make sure to also install: * [cardano-hw-cli](https://github.com/vacuumlabs/cardano-hw-cli/releases/latest) v1.13.0 - and the Cardano-App on the HW-Wallet should be v6.0.3 or above for Ledger-HW-Wallets, and v2.5.3 for Trezor Model-T devices.
:warning: In case there is no public release available yet for Cardano-App v6.0.3 via the Ledger-Live Desktop application, you can get it by opening up your Ledger-Live Desktop Application and change the following:
**`-> Settings -> Experimental Features -> My Ledger provider -> Enable it and set it to 4`**.
After that you should see a new available version which you can update to.
? You can find further information [here](https://github.com/gitmachtl/scripts/tree/master/cardano/mainnet#how-to-prepare-your-system-before-using-a-hardware-wallet) on how to prepare your system to work with Hardware-Wallets. + and the Cardano-App on the HW-Wallet should be v6.0.3 or above for Ledger-HW-Wallets, and v2.5.3 for Trezor Model-T devices.
⚠️ In case there is no public release available yet for Cardano-App v6.0.3 via the Ledger-Live Desktop application, you can get it by opening up your Ledger-Live Desktop Application and change the following:
**`-> Settings -> Experimental Features -> My Ledger provider -> Enable it and set it to 4`**.
After that you should see a new available version which you can update to.
? You can find further information [here](https://github.com/gitmachtl/scripts/tree/master/cardano/mainnet#how-to-prepare-your-system-before-using-a-hardware-wallet) on how to prepare your system to work with Hardware-Wallets.
To **generate your Voting-Registration**, the **09a_catalystVote.sh script** from the MainNet Repo is used, below are the 4 simple steps: 1. **[Generate a Voting-KeyPair](#1-generate-a-voting-keypair)** @@ -1332,7 +1379,7 @@ Files that have been created and derived from the CIP36 path `1694H/1815H/0H/0/0 * `myvote.voting.pkey`: the vote public key in bech format, starting with `cvote_vk1...` * `myvote.voting.mnemonics`: the 24-word mnemonics to use on a dApp enabled Wallet (like [eternl](https://eternl.io), [typhon](https://typhonwallet.io/)...) -:warning: Starting with Fund10, the voting will be available via the **Catalyst Voting Center** and transactions/signing confirmed via a dApp Wallet. For that you can generate the voting key on the CLI like above and use the generated Mnemonics. +⚠️ Starting with Fund10, the voting will be available via the **Catalyst Voting Center** and transactions/signing confirmed via a dApp Wallet. For that you can generate the voting key on the CLI like above and use the generated Mnemonics.  
@@ -1410,15 +1457,14 @@ You have successfully transmitted your voting registration onto the chain. To do 3. Scan the QR-Code with the latest version of the Catalyst-Voting-App on your mobile phone to get access to your Voting-Power 4. Done -:warning: Your Voting-Power will be displayed in the Voting-App once the voting is open. +⚠️ Your Voting-Power will be displayed in the Voting-App once the voting is open. -:warning: With the Special Voting Event in April 2023, its only allowed to use CIP36 registration format to do a 100% Voting-Power delegation. So all the examples above are doing that. The description will be updated again for Fund10 to also give example on how to delegate your Voting-Power to multiple Vote-Public-Keys. But for now, please don't use that function for the Special Voting Event, thx! +⚠️ With the Special Voting Event in April 2023, its only allowed to use CIP36 registration format to do a 100% Voting-Power delegation. So all the examples above are doing that. The description will be updated again for Fund10 to also give example on how to delegate your Voting-Power to multiple Vote-Public-Keys. But for now, please don't use that function for the Special Voting Event, thx!
 
 
- # Import your existing Pool from CLI-Keys or Tutorials If you already have your Pool running and you made it all via the cli commands, or you made it for example via the [Coincashew-Tutorial](https://www.coincashew.com/coins/overview-ada/guide-how-to-build-a-haskell-stakepool-node) you can now import/copy that keys pretty easy with the new importHelper tool. Please checkout the two methods below for doing it in Online- and Offline-Mode. @@ -1428,7 +1474,7 @@ If you already have your Pool running and you made it all via the cli commands, Find out how to import your existing pool data in Online-Mode.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑

So, the StakePoolOperator Scripts needs all the owner/pool data in a specific naming scheme. You can learn about that in the information above in this README. To help you a little bit bringing over your existing data there is now a little script called 0x_importHelper.sh available. All you have to do is to give your pool a name (this is used to reference it on the filenames) and your current PoolID in Hex or Bech32 format. I have partnered up with Crypto2099 to get your current Pooldata via his API. The tool will ask you about the location of your ***.skeys*** for your node(cold), vrf, owner and rewards account. It will copy them all into a new directory for you with the right naming scheme and it will also prepopulate the needed pool.json file for you :smiley:
@@ -1453,7 +1499,7 @@ You can now start to use theses StakePoolOperator Scripts like you already has u Find out how to import your existing pool data in Offline-Mode.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑

So, the StakePoolOperator Scripts needs all the owner/pool data in a specific naming scheme. You can learn about that in the information above in this README. To help you a little bit bringing over your existing data there is now a little script called 0x_importHelper.sh available. All you have to do is to give your pool a name (this is used to reference it on the filenames) and your current PoolID in Hex or Bech32 format. I have partnered up with Crypto2099 to get your current Pooldata via his API. The tool will ask you about the location of your ***.skeys*** for your node(cold), vrf, owner and rewards account. It will copy them all into a new directory for you with the right naming scheme and it will also prepopulate the needed pool.json file for you :smiley:
@@ -1468,7 +1514,7 @@ Lets say you wanna import the data for your pool "WAKANDA FOREVER" with the pool The script will also ask you if you wanna add the exported file directly to the *offlineTransfer.json.* Answer that with yes. -:floppy_disk: Transfer the offlineTransfer.json to the Offline-Machine. +💾 Transfer the offlineTransfer.json to the Offline-Machine. **Offline-Machine:** @@ -1488,26 +1534,34 @@ You can now start to use theses StakePoolOperator Scripts like you already has u  
 
+# Examples in Light-Mode + +> 💡 **The examples below for the Online-Mode can also be used 1:1 for working in the Light-Mode setup!** + +Please make sure to enable the Light-Mode by setting `workMode="light"` in your **00_common.sh** or **common.inc** file. You don't need a running synced cardano-node, all the examples below for the Online(Full)-Mode are usabe for the Light-Mode too 😄 + + 
 
+ # Examples in Online-Mode -> :bulb: **The examples below are using the scripts in the same directory, so they are listed with a leading ./**
+> 💡 **The examples below are using the scripts in the same directory, so they are listed with a leading ./**
**If you have the scripts copied to an other directory reachable via the PATH environment variable, than call the scripts WITHOUT the leading ./ !** The examples in here are for using the scripts in Online-Mode. Please get yourself familiar on how to use each single script, a detailed Syntax about each script can be found [here](#configuration-scriptfiles-syntax--filenames). Make sure you have a fully synced passive node running on your machine, make sure you have set the right parameters in the scirpts config file **00_common.sh**
Working in [Offline-Mode](#examples-in-offline-mode) introduces another step before and ofter each example, so you should understand the Online-Mode first. -:bulb: Make sure your 00_common.sh is having the correct setup for your system! +💡 Make sure your 00_common.sh is having the correct setup for your system! ## Generate some wallets for the daily operator work So first you should create yourself a few small wallets for the daily Operator work, there is no need to use your big-owner-pledge-wallet for this every time. Lets say we wanna create three small wallets with the name smallwallet1, smallwallet2 and smallwallet3. And we wanna fund them via daedalus for example.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑

Steps: 1. Create three new payment-only wallets by running
```./02_genPaymentAddrOnly.sh smallwallet1 cli```
```./02_genPaymentAddrOnly.sh smallwallet2 cli```
```./02_genPaymentAddrOnly.sh smallwallet3 cli``` -1. Fund the three wallets with some ADA from your existing Daedalus or Yoroi wallet. You can show the address and the current balance by running
+1. Fund the three wallets with some ADA from your existing Daedalus or Eternl wallet. You can show the address and the current balance by running
```./01_queryAddress.sh smallwallet1```
```./01_queryAddress.sh smallwallet2```
```./01_queryAddress.sh smallwallet3``` Theses are your **daily work** operator wallets, never ever use your pledge owner wallet for such works, don't do it, be safe.
@@ -1520,7 +1574,7 @@ If you wanna do a pool registration (next step) make sure that you have **at lea Similar to the example above you can directly encrypt your .skey files with a password. This enhances the security.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑

Steps: 1. Create a new payment-only encrypted wallet by running
```./02_genPaymentAddrOnly.sh smallwallet1 enc``` @@ -1536,7 +1590,7 @@ Remember, there is no need to decrypt the smallwallet1.skey file before using it If you just wanna send some lovelaces from your smallwallet1 to your smallwallet2 or to anybody else, you can do that via the script 01_sendLovelaces.sh.
This script can do much more, but please checkout the Example below for a simple Transaction also with a Transaction-Message-Text.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑

Single Message and some ADA: 1. We want to send 10 ADA (10000000 lovelaces) from smallwallet1 to smallwallet2 and also the message "here is your money" with it, simply run:
@@ -1555,7 +1609,13 @@ So as you can see, you can use the "msg: xxx" parameter multiple times. You can let me send you a little tip here ciao :-) ``` - + +
Send an encrypted Message: +1. We want to send 5 ADA (5000000 lovelaces) from smallwallet1 to smallwallet2 and also the message "this is an encrypted message" with it. This message should be encrypted with the default passphrase 'cardano'. We can do this by running:
+ ```./01_sendLovelaces.sh smallwallet1 smallwallet2 5000000 "msg: this is an encrypted message" "enc: basic"``` + +Thats it, along with your 5 ADA, the script automatically creates a metadata.json for you that includes the encrypted message and includes it into the transaction. +
@@ -1564,7 +1624,7 @@ So as you can see, you can use the "msg: xxx" parameter multiple times. You can This is as simply as sending lovelaces(ADA) from one wallet address to another address. Here you can find two examples on how to do it with self created Tokens and with Tokens you got from other ones.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑
### _Sending one type of token at the same time_ @@ -1626,7 +1686,7 @@ For the complete available syntax, please check the 01_sendAsset.sh description We want to make ourself a pool owner stake address with the nickname owner, we want to register the pool with the name mypool. The name is only to keep the files on the harddisc in order, name is not a ticker!
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑

Steps: 1. Make sure you have enough funds on your *smallwallet1* account we created before. You will need around **505 ADA to complete the process**. You can check the current balance by running ```./01_queryAddress.sh smallwallet1``` @@ -1674,15 +1734,15 @@ We want to make ourself a pool owner stake address with the nickname owner, we w ``` 1. Run ```./05a_genStakepoolCert.sh mypool``` again with the saved json file, this will generate the **mypool.pool.cert** file 1. Delegate to your own pool as owner -> **pledge** ```./05b_genDelegationCert.sh mypool owner``` this will generate the **owner.deleg.cert** -1. :bulb: **Upload** the generated ```mypool.metadata.json``` file **onto your webserver** so that it is reachable via the URL you specified in the poolMetaUrl entry! Otherwise the next step will abort with an error. +1. 💡 **Upload** the generated ```mypool.metadata.json``` file **onto your webserver** so that it is reachable via the URL you specified in the poolMetaUrl entry! Otherwise the next step will abort with an error. 1. Register your stakepool on the blockchain ```./05c_regStakepoolCert.sh mypool smallwallet1``` 1. Wait a minute so the transaction and stakepool registration is completed 1. Check that the pool is successfully registered by running
```./05e_checkPoolOnChain.sh mypool``` 1. You can also verify that your delegation to your pool is ok by running
```./03c_checkStakingAddrOnChain.sh owner``` if you don't see it instantly, wait a little and retry the same command -:warning: Make sure you transfer enough ADA to your new **owner.payment.addr** so you respect the registered Pledge amount, otherwise you will not get any rewards for you or your delegators! +⚠️ Make sure you transfer enough ADA to your new **owner.payment.addr** so you respect the registered Pledge amount, otherwise you will not get any rewards for you or your delegators! -:warning: Don't forget to register your Rewards-Account on the Chain via script 03b if its different from an Owner-Account! +⚠️ Don't forget to register your Rewards-Account on the Chain via script 03b if its different from an Owner-Account! Done. :smiley:
@@ -1692,7 +1752,7 @@ Done. :smiley: We want to make ourself a pool owner stake address with the nickname ledgerowner by using a HW-Key, we want to register the pool with the poolname mypool. The poolname is only to keep the files on the harddisc in order, poolname is not a ticker!
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑

Steps: 1. Make sure you have enough funds on your *smallwallet1* account we created before. You will need around **510 ADA to complete the process**. You can check the current balance by running ```./01_queryAddress.sh smallwallet1``` @@ -1744,17 +1804,17 @@ ledgerowner as owner and also as rewards-account. We do the signing on the machi ``` 1. Run ```./05a_genStakepoolCert.sh mypool``` again with the saved json file, this will generate the **mypool.pool.cert** file 1. Delegate to your own pool as owner -> **pledge** ```./05b_genDelegationCert.sh mypool ledgerowner``` this will generate the **ledgerowner.deleg.cert** -1. :bulb: **Upload** the generated ```mypool.metadata.json``` file **onto your webserver** so that it is reachable via the URL you specified in the poolMetaUrl entry! Otherwise the next step will abort with an error. +1. 💡 **Upload** the generated ```mypool.metadata.json``` file **onto your webserver** so that it is reachable via the URL you specified in the poolMetaUrl entry! Otherwise the next step will abort with an error. 1. Register your stakepool on the blockchain, smallwallet1 will pay for the registration fees
```./05c_regStakepoolCert.sh mypool smallwallet1``` 1. Wait a minute so the transaction and stakepool registration is completed 1. Check that the pool is successfully registered by running
```./05e_checkPoolOnChain.sh mypool``` -1. Send all owner delegations to the blockchain. :bulb: Notice! This is different than before when using only CLI-Owner-Keys, if any owner is a HW-Wallet than you have to send the individual delegations after the stakepool registration. You can read more about it [here](#changes-to-the-operator-workflow-when-hardware-wallets-are-involved).
We have only one owner so lets do this by running the following command, **the HW-Wallet itself must pay for this**
```./06_regDelegationCert.sh ledgerowner ledgerowner.payment``` +1. Send all owner delegations to the blockchain. 💡 Notice! This is different than before when using only CLI-Owner-Keys, if any owner is a HW-Wallet than you have to send the individual delegations after the stakepool registration. You can read more about it [here](#changes-to-the-operator-workflow-when-hardware-wallets-are-involved).
We have only one owner so lets do this by running the following command, **the HW-Wallet itself must pay for this**
```./06_regDelegationCert.sh ledgerowner ledgerowner.payment``` 1. Wait a minute so the transaction and delegation certificate is completed 1. Verify that your owner delegation to your pool is ok by running
```./03c_checkStakingAddrOnChain.sh ledgerowner``` if you don't see it instantly, wait a little and retry the same command -:warning: Make sure you transfer enough ADA to your new **ledgerowner.payment.addr** so you respect the registered Pledge amount, otherwise you will not get any rewards for you or your delegators! +⚠️ Make sure you transfer enough ADA to your new **ledgerowner.payment.addr** so you respect the registered Pledge amount, otherwise you will not get any rewards for you or your delegators! -:warning: Don't forget to register your Rewards-Account on the Chain via script 03b if its different from an Owner-Account! +⚠️ Don't forget to register your Rewards-Account on the Chain via script 03b if its different from an Owner-Account! Done. :smiley:
@@ -1764,7 +1824,7 @@ Done. :smiley: We want to make ourself a pool owner stake address with the nickname ledgerowner by using a HW-Key, we want to register the pool also with the pool coldkeys on the HW-Wallet and with the poolname mypool. The poolname is only to keep the files on the harddisc in order, poolname is not a ticker!
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑

Steps: 1. Make sure you have enough funds on your *smallwallet1* account we created before. You will need around **510 ADA to complete the process**. You can check the current balance by running ```./01_queryAddress.sh smallwallet1``` @@ -1816,17 +1876,17 @@ ledgerowner as owner and also as rewards-account. We do the signing on the machi ``` 1. Run ```./05a_genStakepoolCert.sh mypool``` again with the saved json file, this will generate the **mypool.pool.cert** file 1. Delegate to your own pool as owner -> **pledge** ```./05b_genDelegationCert.sh mypool ledgerowner``` this will generate the **ledgerowner.deleg.cert** -1. :bulb: **Upload** the generated ```mypool.metadata.json``` file **onto your webserver** so that it is reachable via the URL you specified in the poolMetaUrl entry! Otherwise the next step will abort with an error. +1. 💡 **Upload** the generated ```mypool.metadata.json``` file **onto your webserver** so that it is reachable via the URL you specified in the poolMetaUrl entry! Otherwise the next step will abort with an error. 1. Register your stakepool on the blockchain, smallwallet1 will pay for the registration fees
```./05c_regStakepoolCert.sh mypool smallwallet1``` 1. Wait a minute so the transaction and stakepool registration is completed 1. Check that the pool is successfully registered by running
```./05e_checkPoolOnChain.sh mypool``` -1. Send all owner delegations to the blockchain. :bulb: Notice! This is different than before when using only CLI-Owner-Keys, if any owner is a HW-Wallet than you have to send the individual delegations after the stakepool registration. You can read more about it [here](#changes-to-the-operator-workflow-when-hardware-wallets-are-involved).
We have only one owner so lets do this by running the following command, **the HW-Wallet itself must pay for this**
```./06_regDelegationCert.sh ledgerowner ledgerowner.payment``` +1. Send all owner delegations to the blockchain. 💡 Notice! This is different than before when using only CLI-Owner-Keys, if any owner is a HW-Wallet than you have to send the individual delegations after the stakepool registration. You can read more about it [here](#changes-to-the-operator-workflow-when-hardware-wallets-are-involved).
We have only one owner so lets do this by running the following command, **the HW-Wallet itself must pay for this**
```./06_regDelegationCert.sh ledgerowner ledgerowner.payment``` 1. Wait a minute so the transaction and delegation certificate is completed 1. Verify that your owner delegation to your pool is ok by running
```./03c_checkStakingAddrOnChain.sh ledgerowner``` if you don't see it instantly, wait a little and retry the same command -:warning: Make sure you transfer enough ADA to your new **ledgerowner.payment.addr** so you respect the registered Pledge amount, otherwise you will not get any rewards for you or your delegators! +⚠️ Make sure you transfer enough ADA to your new **ledgerowner.payment.addr** so you respect the registered Pledge amount, otherwise you will not get any rewards for you or your delegators! -:warning: Don't forget to register your Rewards-Account on the Chain via script 03b if its different from an Owner-Account! +⚠️ Don't forget to register your Rewards-Account on the Chain via script 03b if its different from an Owner-Account! Done. :smiley:
@@ -1837,7 +1897,7 @@ Done. :smiley: So this is an important one for many of you that already have registered a stakepool on Cardano before. Now is the time to upgrade your owner funds security to the next level by using HW-Wallet-Keys instead of CLI-Keys. In the example below we have an existing CLI-Owner with name **owner**, and we want to migrate that to the new owner with name **ledgerowner**. The poolname is mypool in this example, but you know the game, you have done it before.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑

Steps: 1. Make sure you have enough funds on your *smallwallet1* account we created before. You will need around **5 ADA to complete the process**. You can check the current balance by running ```./01_queryAddress.sh smallwallet1``` @@ -1890,7 +1950,7 @@ So this is an important one for many of you that already have registered a stake 1. If you have changed also some Metadata, **upload** the newly generated ```mypool.metadata.json``` file **onto your webserver** so that it is reachable via the URL you specified in the poolMetaUrl entry! Otherwise the next step will abort with an error. If you have only updated the owners, skip it. 1. Re-Register your stakepool on the blockchain, smallwallet1 will pay for the registration fees. This will be only a pool update, so this will not cost you the initial 500 ADA, only a few fees.
```./05c_regStakepoolCert.sh mypool smallwallet1 REREG``` 1. Wait a minute so the transaction and stakepool registration is completed -1. Send all new owner delegations to the blockchain. :bulb: Notice! This is different than before when using only CLI-Owner-Keys, if any owner is a HW-Wallet than you have to send the individual delegations after the stakepool registration. You can read more about it [here](#changes-to-the-operator-workflow-when-hardware-wallets-are-involved). We have only one new owner so lets do this by running the following command:
 
+1. Send all new owner delegations to the blockchain. 💡 Notice! This is different than before when using only CLI-Owner-Keys, if any owner is a HW-Wallet than you have to send the individual delegations after the stakepool registration. You can read more about it [here](#changes-to-the-operator-workflow-when-hardware-wallets-are-involved). We have only one new owner so lets do this by running the following command:
 
* ```./06_regDelegationCert.sh ledgerowner ledgerowner.payment``` if you have a Full-Hardware(**HW**) key (Step 3)
or * ```./06_regDelegationCert.sh ledgerowner smallwallet1``` if you have a Hybrid-Hardware(**HYBRID**) key (Step 3)
  @@ -1898,7 +1958,7 @@ So this is an important one for many of you that already have registered a stake 1. Verify that your new owner delegation to your pool is ok by running
```./03c_checkStakingAddrOnChain.sh ledgerowner``` if you don't see it instantly, wait a little and retry the same command  
-:warning: Now WAIT! Wait for 2 epoch changes! :warning: So if you're doing this in epoch n, wait until epoch n+2 before you continue! +⚠️ Now WAIT! Wait for 2 epoch changes! ⚠️ So if you're doing this in epoch n, wait until epoch n+2 before you continue!  
Now two epochs later your new additional **ledgerowner** co-owner is fully active. Its now the time to **transfer your owner funds** from the old **owner** to the new **ledgerowner**. You can do this by running:
```./01_sendLovelaces.sh owner.payment ledgerowner.payment ALLFUNDS```
This will move over all lovelaces and even assets that are on your old owner.payment address to your new ledger.payment address. @@ -1906,7 +1966,7 @@ Now two epochs later your new additional **ledgerowner** co-owner is fully activ Be aware, this little transaction needed some fees, so you maybe have to top up your ledgerowner.payment account with 1 ADA from another wallet to met your registered pledge again. Check your balance on your ledgerowner account by running ```./01_queryAddress.sh ledgerowner.payment```  
-:warning: WAIT AGAIN! Wait for 2 epoch changes! :warning: So if you're doing this in epoch n, wait until epoch n+2 before you continue! :warning: +⚠️ WAIT AGAIN! Wait for 2 epoch changes! ⚠️ So if you're doing this in epoch n, wait until epoch n+2 before you continue! ⚠️  
Why waiting again? Well, **we** also **changed the rewards-account** when we added the new ledgerowner, this takes 4 epochs on the blockchain to get fully updated. So, until now **you have received the rewards** of the pool **to your old owner.staking account**. Please check you rewards now and do a withdrawal of them, an example can be found below. @@ -1924,12 +1984,12 @@ Why waiting again? Well, **we** also **changed the rewards-account** when we add If you wanna update you pledge, costs, owners or metadata on a registered stakepool just do the following
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑

Steps: 1. [Unlock](#file-autolock-for-enhanced-security) the existing mypool.pool.json file and edit it. Only edit the values above the "--- DO NOT EDIT BELOW THIS LINE ---" line, save it again. 1. Run ```./05a_genStakepoolCert.sh mypool``` to generate a new mypool.pool.cert file from it -1. :bulb: **Upload** the new ```mypool.metadata.json``` file **onto your webserver** so that it is reachable via the URL you specified in the poolMetaUrl entry! Otherwise the next step will abort with an error. +1. 💡 **Upload** the new ```mypool.metadata.json``` file **onto your webserver** so that it is reachable via the URL you specified in the poolMetaUrl entry! Otherwise the next step will abort with an error. 1. (Optional create delegation certificates if you have added an owner or an extra rewards account with script 05b) 1. Re-Register your stakepool on the blockchain with ```./05c_regStakepoolCert.sh mypool owner.payment```
No delegation update needed. @@ -1941,7 +2001,7 @@ Done. I'am sure you wanna claim some of your rewards that you earned running your stakepool. So lets say you have rewards in your owner.staking address and you wanna claim it to the owner.payment address.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑

Steps: 1. Check that you have rewards in your stakeaccount by running ```./01_queryAddress.sh owner.staking``` @@ -1949,7 +2009,7 @@ I'am sure you wanna claim some of your rewards that you earned running your stak This will claim the rewards from the owner.staking account and sends it to the owner.payment address, also owner.payment will pay for the transaction fees.
Or, you can claim your rewards by running ```./01_claimRewards.sh owner.staking owner.payment smallwallet1``` This will claim the rewards from the owner.staking account and sends it to the owner.payment address, the smallwallet1 will pay for the transaction fees. It is only possible to claim all rewards, not only a part of it. -:bulb: ATTENTION, claiming rewards costs transaction fees! So you have two choices for that: The destination address pays for the transaction fees, or you specify an additional account that pays for the transaction fees like in the 2nd method shown above. +💡 ATTENTION, claiming rewards costs transaction fees! So you have two choices for that: The destination address pays for the transaction fees, or you specify an additional account that pays for the transaction fees like in the 2nd method shown above. Done. @@ -1973,7 +2033,7 @@ Done. From time to time you have to rotate the so called HOT-Keys on your BlockProducer Node, thats the KES-Keys and the OPCERT. Here is an example on how to rotate the keys for your mypool.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑

Steps: 1. ```./04c_genKESKeys.sh mypool cli``` @@ -1989,7 +2049,7 @@ Done. Lets say we wanna create a payment(base)/stake address combo with the nickname delegator and we wanna delegate the funds in the payment(base) address of that to the pool yourpool. (You'll need the yourpool.node.vkey for that.)
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑

Steps: 1. Generate the delegator stake/payment combo with ```./03a_genStakingPaymentAddr.sh delegator enc``` @@ -2009,7 +2069,7 @@ Done. It's similar to a single owner stake pool registration (example above). All owners must have a registered stake address on the blockchain first! Here is a 2 owner example ...
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑

Steps: 1. Generate the stakepool certificate @@ -2041,7 +2101,7 @@ It's similar to a single owner stake pool registration (example above). All owne 1. Check that the pool is successfully registered by running
```./05e_checkPoolOnChain.sh mypool``` 1. Also you can verify that your delegation to your pool is ok by running
```./03c_checkStakingAddrOnChain.sh owner-1``` and ```./03c_checkStakingAddrOnChain.sh owner-2``` if you don't see it instantly, wait a little and retry the same command -:warning: Don't forget to register your Rewards-Account on the Chain via script 03b if its different from an Owner-Account! +⚠️ Don't forget to register your Rewards-Account on the Chain via script 03b if its different from an Owner-Account! Done.
@@ -2051,7 +2111,7 @@ Done. From the Mary-Era on, you can easily mint(generate) Native-Tokens by yourself, here you can find an example on how to do it.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑
### Mint an unresticted amount of Tokens @@ -2101,7 +2161,7 @@ Done - You have minted (created) 77 new binary/hexencoded Tokens 0x01020304 and If you wanna burn(destroy) some Native-Tokens, you can do it similar to the minting process. Here you can find an example on how to do it.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑

Important, you can only burn Native-Tokes that you have the policy for. You cannot burn other Native-Tokens that were sent to your wallet address. So lets say we wanna burn 200 **SUPERTOKEN** that we created before under the policy **mypolicy**. The AssetFiles were stored in the *assets* subdirectory, and the address we wanna burn the Tokens from is the account **mywallet**. @@ -2120,7 +2180,7 @@ Done - You have burned (destroyed) 200 SUPERTOKENs. You can send Native-Tokens w Here you can find the steps to add Metadata (Name, Decimals, an Url, a Picture ...) of your Native Tokens to the TokenRegistryServer.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑
### Generate the special formatted and signed JSON File for the GitHub PullRequest @@ -2157,13 +2217,13 @@ So lets say we wanna create the Metadata registration JSON for our **SUPERTOKEN* "lastAction": "created Asset-File" } ``` - > **You can find more details about the parameters [here](#nativeasset-information-file-policynameassetnameasset---for-your-own-nativeassets)**
*:warning: Don't edit the file below the **--- DO NOT EDIT BELOW THIS LINE !!! ---** line.* + > **You can find more details about the parameters [here](#nativeasset-information-file-policynameassetnameasset---for-your-own-nativeassets)**
*⚠️ Don't edit the file below the **--- DO NOT EDIT BELOW THIS LINE !!! ---** line.* 1. Save the AssetFile. 1. Run ```./12a_genAssetMeta.sh assets/mypolicy.SUPERTOKEN``` again to produce the special JSON file for the Registration -1. The special file was created, in this example it would be a file with the name
**aeaab6fa86997512b4f850049148610d662b5a7a971d6e132a0940626d795375706572546f6b656e.json**
:warning: Do not rename the file! +1. The special file was created, in this example it would be a file with the name
**aeaab6fa86997512b4f850049148610d662b5a7a971d6e132a0940626d795375706572546f6b656e.json**
⚠️ Do not rename the file! 1. Go to https://github.com/cardano-foundation/cardano-token-registry and clone the Repo into your own Repo > The TokenRegistryServer for the Public-Testnet is: https://github.com/input-output-hk/metadata-registry-testnet @@ -2193,7 +2253,7 @@ You will get a feedback on the data that is stored on the server, this check is You can mix'n'match multiple relay entries in your poolname.pool.json file, below are a few common examples.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑
### Using two dns named relay entries @@ -2264,14 +2324,14 @@ Your poolRelays array section in the json file should like similar to: If you wanna retire your registered stakepool mypool, you have to do just a few things
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑

Steps: 1. Generate the retirement certificate for the stakepool mypool from data in mypool.pool.json
```./07a_genStakepoolRetireCert.sh mypool``` this will retire the pool at the next epoch 1. De-Register your stakepool from the blockchain with ```./07b_deregStakepoolCert.sh mypool smallwallet1``` -:warning: You're PoolDepositFee (500 ADA) will be returned to the rewards account you have set for your pool! So don't delete this account until you received the PoolDepositFee back. They are returned as Rewards, not as a normal Payment! +⚠️ You're PoolDepositFee (500 ADA) will be returned to the rewards account you have set for your pool! So don't delete this account until you received the PoolDepositFee back. They are returned as Rewards, not as a normal Payment! Done.
@@ -2281,7 +2341,7 @@ Done. If you wanna retire the staking address owner, you have to do just a few things
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑

Steps: 1. Generate the retirement certificate for the stake-address ```./08a_genStakingAddrRetireCert.sh owner```
this will generate the owner.staking.dereg-cert file @@ -2289,7 +2349,7 @@ If you wanna retire the staking address owner, you have to do just a few things 1. You can check the current status of your onchain registration via the script 03c like
```./03c_checkStakingAddrOnChain.sh owner```
If it doesn't go away directly, wait a little and retry this script. -:warning: Don't retire a stakeaddress if you were delegated to a blockproducing StakePool before, you will receive rewards for the next 2 epochs on that account. Retire it only afterwards! +⚠️ Don't retire a stakeaddress if you were delegated to a blockproducing StakePool before, you will receive rewards for the next 2 epochs on that account. Retire it only afterwards! Done. @@ -2298,9 +2358,9 @@ Done. ## ITN-Witness Ticker check for wallets and Extended-Metadata.json Infos
- Explore how to use your ITN Ticker as Proof and also how to use extended-metadata.json :bookmark_tabs:
+ Explore how to use your ITN Ticker as Proof and also how to use extended-metadata.json 📑
-There is now an implementation of the extended-metadata.json for the pooldata. This can hold any kind of additional data for the registered pool. We see some Ticker spoofing getting more and more, so new people are trying to take over the Ticker from the people that ran a stakepool in the ITN and built up there reputation. There is no real way to forbid a double ticker registration, however, the "spoofing" stakepoolticker can be shown in the Daedalus/Yoroi/Pegasus wallet as a "spoof", so people can see this is not the real pool. I support this in my scripts. To anticipate in this (it is not fixed yet) you will need a "**jcli**" binary on your machine with the right path set in ```00_common.sh```. Prepare two files in the pool directory: +There is now an implementation of the extended-metadata.json for the pooldata. This can hold any kind of additional data for the registered pool. We see some Ticker spoofing getting more and more, so new people are trying to take over the Ticker from the people that ran a stakepool in the ITN and built up there reputation. There is no real way to forbid a double ticker registration, however, the "spoofing" stakepoolticker can be shown in the Daedalus/Eternl/Pegasus wallet as a "spoof", so people can see this is not the real pool. I support this in my scripts. To anticipate in this (it is not fixed yet) you will need a "**jcli**" binary on your machine with the right path set in ```00_common.sh```. Prepare two files in the pool directory:
```.itn.skey``` this textfile should hold your ITN secret/private key
```.itn.vkey``` this textfile should hold your ITN public/verification key
also you would need to add an additional URL **poolExtendedMetaUrl** for the next extended metadata json file on your webserver to your ```.pool.json``` file like: @@ -2325,7 +2385,7 @@ So if you hold a file ```.additional-metadata.json``` with additional ## How to do a voting for SPOCRA in a simple process
- Explore how to vote for SPOCRA :bookmark_tabs:
+ Explore how to vote for SPOCRA 📑
We have created a simplified script to transmit a voting.json file on-chain. This version will currently be used to submit your vote on-chain for the SPOCRA voting.
A Step-by-Step Instruction on how to create the voting.json file can be found on Adam Dean's website -> [Step-by-Step Instruction](https://vote.crypto2099.io/SPOCRA-voting/).
After you have generated your voting.json file you simply transmit it in a transaction on-chain with the script ```01_sendLovelaces.sh``` like:
```./01_sendVoteMeta.sh mywallet mywallet 1000000 myvote.json```
This will for example transmit the myvote.json file onto the chain. You just make a small transaction back to yourself (1 ADA minimum) and include the Metadata.json file.
@@ -2338,39 +2398,41 @@ Thats it. :-) The examples in here are for using the scripts in Offine-Mode. Please get yourself familiar first with the scripts in [Online-Mode](#examples-in-online-mode). Also a detailed Syntax about each script can be found [here](#configuration-scriptfiles-syntax--filenames). Working offline is like working online, all is working in Offline-Mode, theses are just a few examples. :smiley:
-:bulb: Make sure your 00_common.sh is having the correct setup for your system! +💡 Make sure your 00_common.sh is having the correct setup for your system! **Understand the workflow in Offline-Mode:** -* **Step 1 : On the Online-Machine** +* **Step 1 : On the Online- or Light-Machine** Query up2date information about your address balances, rewards, blockchain-parameters...
If you wanna pay offline from your mywallet1.addr, just add the information for that. If you wanna claim rewards from your mywallet.staking address and you wanna pay with your smallwallet1.addr for that, just add these two addresses to the information. You need to add the information of your addresses you wanna pay with or you wanna claim rewards from, nothing more.
- Update the **offlineTransfer.json file with ./01_workOffline.sh** and send(:floppy_disk:) it over to the Offline-Machine. + Update the **offlineTransfer.json file with ./01_workOffline.sh** and send(💾) it over to the Offline-Machine. * **Step 2 : On the Offline-Machine** Do your normal work with the scripts like sending lovelaces or tokens from address to address, updating your stakepool parameters, claiming your rewards, etc...
Sign the transactions on the Offline-Machine, they will be automatically stored in the offlineTransfer.json. If you wanna do multiple transactions at the same time, use a few small payment wallets for this, because you can only pay from one individual wallet in an offline transaction at the same time. So if you wanna claim your rewards and also update your pool parameters, use two small payment wallets for that.
All offline transactions and also updated files like your pool.metadata.json or pool.extended-metadata.json will be stored in the offlineTransfer.json if you say so.
- When you're finished, send(:floppy_disk:) the offlineTransfer.json back to your Online-Machine. + When you're finished, send(💾) the offlineTransfer.json back to your Online-Machine. -* **Step 3 : On the Online-Machine** +* **Step 3 : On the Online- or Light-Machine** **Execute the offline signed transactions** and/or extract files from the offlineTransfer.json like your updated pool.metadata.json file for example with **./01_workOffline.sh**
You're done, if you wanna continue to do some work: Gather again the latest balance informations from the address you wanna work with and send the offlineTransfer.json back to your Offline-Machine. And so on...
The offlineTransfer.json is your little carry bag for your balance/rewards information, transactions and files. :-) **Config-Settings on the Online- / Offline-Machine:** -* Online-Machine: Set the ```offlineMode="no"``` parameter in the 00_common.sh, common.inc or ~/.common.inc config file.
Make sure you have a running and fully synced cardano-node on this Machine. Also cardano-cli. +* Online-Machine (Fullmode): Set the ```workMode="online"``` parameter in the 00_common.sh, common.inc or ~/.common.inc config file.
Make sure you have a running and fully synced cardano-node on this Machine. Also cardano-cli. + +* Light-Machine Set the ```workMode="light"``` parameter in the 00_common.sh, common.inc or ~/.common.inc config file.
Make sure you have cardano-cli installed. No cardano-node binaries needed. -* Offline-Machine: Set the ```offlineMode="yes"``` parameter in the 00_common.sh, common.inc or ~/.common.inc config file.
You only need the cardano-cli on this Machine, no cardano-node binaries. +* Offline-Machine: Set the ```workMode="offline"``` parameter in the 00_common.sh, common.inc or ~/.common.inc config file.
You only need the cardano-cli on this Machine, no cardano-node binaries. > The scripts need a few other helper tools: **curl, bc, xxd** and **jq**. To get them onto the Offline-Machine you can do the following: > -> **Online-Machine:** +> **Online- or Light-Machine:** > > 1. Make a temporary directory, change into that directory and run the following command:
```sudo apt-get update && sudo apt-get download bc xxd jq curl``` > -> :floppy_disk: Transfer the *.deb files from that directory to the Offline-Machine. +> 💾 Transfer the *.deb files from that directory to the Offline-Machine. > > **Offline-Machine:** > @@ -2385,26 +2447,26 @@ The examples in here are for using the scripts in Offine-Mode. Please get yourse So first you should create yourself a few small wallets for the daily Operator work, there is no need to use your big-owner-pledge-wallet for this every time. Lets say we wanna create three small wallets with the name smallwallet1, smallwallet2 and smallwallet3. And we wanna fund them via daedalus for example.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑
-
**Online-Machine:** +
**Online- or Light-Machine:** 1. Make a fresh version of the offlineTransfer.json by running ```./01_workOffline.sh new``` -:floppy_disk: Transfer the offlineTransfer.json to the Offline-Machine. +💾 Transfer the offlineTransfer.json to the Offline-Machine. **Offline-Machine:** 1. Create three new payment-only wallets by running
```./02_genPaymentAddrOnly.sh smallwallet1 cli```
```./02_genPaymentAddrOnly.sh smallwallet2 cli```
```./02_genPaymentAddrOnly.sh smallwallet3 cli``` 1. Add the three new smallwallet1/2/3.addr files to your offlineTransfer.json
```./01_workOffline.sh attach smallwallet1.addr```
```./01_workOffline.sh attach smallwallet2.addr```
```./01_workOffline.sh attach smallwallet3.addr``` -:floppy_disk: Transfer the offlineTransfer.json to the Online-Machine. +💾 Transfer the offlineTransfer.json to the Online- or Light-Machine. -**Online-Machine:** +**Online- or Light-Machine:** -1. Extract the three included address files to the Online-Machine
```./01_workOffline.sh extract``` +1. Extract the three included address files to the Online- or Light-Machine
```./01_workOffline.sh extract``` -You have now successfully brought over the three files smallwallet1.addr, smallwallet2.addr and smallwallet3.addr to your Online-Machine. You can check the current balance on them like you did before running ```./01_queryAddress.sh smallwallet1```
+You have now successfully brought over the three files smallwallet1.addr, smallwallet2.addr and smallwallet3.addr to your Online- or Light-Machine. You can check the current balance on them like you did before running ```./01_queryAddress.sh smallwallet1```
Ok, now fund those three small wallets via daedalus for example. Of course you can also do this from your big-owner-pledge-wallet offline via multiple steps, but we're just learning the steps together, so not overcomplicate the things. :-)
You can of course use your already made and funded wallets for the following examples, we just need a starting point here. @@ -2415,19 +2477,19 @@ You can of course use your already made and funded wallets for the following exa We want to make a pool owner stake address the nickname owner, also we want to register a pool with the nickname mypool. The nickname is only to keep the files on the harddisc in order, nickname is not a ticker! We use the smallwallet1&2 to pay for the different fees in this process. Make sure you have enough funds on smallwallet1 & smallwallet2 for this registration.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑
-
**Online-Machine:** +
**Online- or Light-Machine:** 1. Add/Update the current UTXO balance for smallwallet1 in the offlineTransfer.json by running
```./01_workOffline.sh add smallwallet1``` (smallwallet1 will pay for the stake-address registration, 2 ADA + fees) 1. Add/Update the current UTXO balance for smallwallet2 in the offlineTransfer.json by running
```./01_workOffline.sh add smallwallet2``` (smallwallet2 will pay for the pool registration, 500 ADA + fees) -:floppy_disk: Transfer the offlineTransfer.json to the Offline-Machine. +💾 Transfer the offlineTransfer.json to the Offline-Machine. **Offline-Machine:** (same steps like working online) 1. Generate the owner stake/payment combo with ```./03a_genStakingPaymentAddr.sh owner enc``` -1. Attach the newly created payment and staking address into your offlineTransfer.json for later usage on the Online-Machine
```./01_workOffline.sh attach owner.payment.addr```
```./01_workOffline.sh attach owner.staking.addr``` +1. Attach the newly created payment and staking address into your offlineTransfer.json for later usage on the Online- or Light-Machine
```./01_workOffline.sh attach owner.payment.addr```
```./01_workOffline.sh attach owner.staking.addr``` 1. Generate the owner stakeaddress registration transaction and pay the fees with smallwallet1
```./03b_regStakingAddrCert.sh owner.staking smallwallet1``` 1. Generate encrypted keys for your Pool 1. ```./04a_genNodeKeys.sh mypool enc``` @@ -2468,15 +2530,15 @@ We want to make a pool owner stake address the nickname owner, also we want to r } ``` - :bulb: You can find more details on the scripty-syntax [here](#configuration-scriptfiles-syntax--filenames) + 💡 You can find more details on the script-syntax [here](#configuration-scriptfiles-syntax--filenames) -1. Run ```./05a_genStakepoolCert.sh mypool``` again with the saved json file, this will generate the mypool.pool.cert file.
:bulb: If you wanna protect your TICKER a little more against others, contact me and you will get a unique TickerProtectionKey for your Ticker! If you already have one, run ```./05a_genStakepoolCert.sh ```
+1. Run ```./05a_genStakepoolCert.sh mypool``` again with the saved json file, this will generate the mypool.pool.cert file.
💡 If you wanna protect your TICKER a little more against others, contact me and you will get a unique TickerProtectionKey for your Ticker! If you already have one, run ```./05a_genStakepoolCert.sh ```
1. Delegate to your own pool as owner -> pledge ```./05b_genDelegationCert.sh mypool owner``` this will generate the owner.deleg.cert 1. Generate the stakepool registration transaction and pay the fees with smallwallet2
```./05c_regStakepoolCert.sh mypool smallwallet2```
Let the script also autoinclude your new mypool.metadata.json file into the transferOffline.json -:floppy_disk: Transfer the offlineTransfer.json to the Online-Machine. +💾 Transfer the offlineTransfer.json to the Online- or Light-Machine. -**Online-Machine:** +**Online- or Light-Machine:** 1. Extract all the attached files (mypool.metadata.json, owner.payment.addr, owner.staking.addr) from the transferOffline.json
```./01_workOffline.sh extract``` 1. Now would be the time to upload the mypool.metadata.json file to your webserver. @@ -2485,7 +2547,7 @@ We want to make a pool owner stake address the nickname owner, also we want to r You can check the balance of your owner.payment and the rewards of owner.staking with the ```./01_queryAddress.sh``` script. Make sure to transfer enough ADA to your owner.payment account so you respect the registered pledge amount. -:warning: Don't forget to register your Rewards-Account on the Chain via script 03b if its different from an Owner-Account! +⚠️ Don't forget to register your Rewards-Account on the Chain via script 03b if its different from an Owner-Account! Done. @@ -2499,13 +2561,13 @@ We want to make ourself a pool owner stake address with the nickname ledgerowner We use the smallwallet1 to pay for the different fees in this process. Make sure you have at least **510 ADA** on it.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑
-
**Online-Machine:** +
**Online- or Light-Machine:** 1. Add/Update the current UTXO balance for smallwallet1 in the offlineTransfer.json by running
```./01_workOffline.sh add smallwallet1``` (smallwallet1 will source the new ledgerowner for the stake-address and delegation registration, **at least 510 ADA should be on that wallet**) -:floppy_disk: Transfer the offlineTransfer.json to the Offline-Machine. +💾 Transfer the offlineTransfer.json to the Offline-Machine. **Offline-Machine:** @@ -2515,9 +2577,9 @@ We use the smallwallet1 to pay for the different fees in this process. Make sure 1. Make an offline transaction by sending some funds from your *smallwallet1* to your new *ledgerowner.payment* address for the stake key and delegation registration, 6 ADA should be ok for this ```./01_sendLovelaces.sh smallwallet1 ledgerowner.payment 6000000``` 1. Add the new ledgerowner.payment.addr and ledgerowner.staking.addr to your offlineTransfer.json
```./01_workOffline.sh attach ledgerowner.payment.addr```
```./01_workOffline.sh attach ledgerowner.staking.addr``` -:floppy_disk: Transfer the offlineTransfer.json to the Online-Machine. +💾 Transfer the offlineTransfer.json to the Online- or Light-Machine. -**Online-Machine:** +**Online- or Light-Machine:** 1. Extract the attached files (ledgerowner.payment.addr, ledgerowner.staking.addr) from the transferOffline.json
```./01_workOffline.sh extract``` 1. Execute the cued transaction (smallwallet1 to ledgerowner.payment) to the blockchain by running
```./01_workOffline.sh execute``` @@ -2527,7 +2589,7 @@ We use the smallwallet1 to pay for the different fees in this process. Make sure 1. Add/Update the current UTXO balance for smallwallet1 in the offlineTransfer.json by running
```./01_workOffline.sh add smallwallet1``` (we need it to pay for the pool registration and you've just paid with it) -:floppy_disk: Transfer the offlineTransfer.json to the Offline-Machine. +💾 Transfer the offlineTransfer.json to the Offline-Machine. **Offline-Machine:** @@ -2538,7 +2600,7 @@ We use the smallwallet1 to pay for the different fees in this process. Make sure 1. ```./04c_genKESKeys.sh mypool cli``` 1. ```./04d_genNodeOpCert.sh mypool``` 1. Now you have all the key files to start your coreNode with them: **mypool.vrf.skey, mypool.kes-000.skey, mypool.node-000.opcert** -1. You can include them also in the offlineTransfer.json to bring them over to your Online-Machine if you like by running
```./01_workOffline.sh attach mypool.vrf.skey```
```./01_workOffline.sh attach mypool.kes-000.skey```
```./01_workOffline.sh attach mypool.node-000.opcert``` +1. You can include them also in the offlineTransfer.json to bring them over to your Online- or Light-Machine if you like by running
```./01_workOffline.sh attach mypool.vrf.skey```
```./01_workOffline.sh attach mypool.kes-000.skey```
```./01_workOffline.sh attach mypool.node-000.opcert``` 1. Generate your stakepool certificate 1. ```./05a_genStakepoolCert.sh mypool```
will generate a prefilled **mypool.pool.json** file for you, **edit it !** 1. We want 200k ADA pledge, 500 ADA costs per epoch and 4% pool margin so let us set these and the Metadata values in the json file like below. Also we want the @@ -2576,9 +2638,9 @@ ledgerowner as owner and also as rewards-account. We do the signing on the machi 1. Delegate to your own pool as owner -> **pledge** ```./05b_genDelegationCert.sh mypool ledgerowner``` this will generate the **ledgerowner.deleg.cert** 1. Generate now the transaction for the the stakepool registration, smallwallet1 will pay for the registration fees
```./05c_regStakepoolCert.sh mypool smallwallet1```
Let the script also autoinclude your new mypool.metadata.json file into the transferOffline.json! -:floppy_disk: Transfer the offlineTransfer.json to the Online-Machine. +💾 Transfer the offlineTransfer.json to the Online- or Light-Machine. -**Online-Machine:** +**Online- or Light-Machine:** 1. Extract the attached files (mypool.metadata.json, mypool.vrf.skey, mypool.kes-000.skey, mypool.node-000.opcert) from the transferOffline.json ```./01_workOffline.sh extract``` 1. Now would be the time to **upload the mypool.metadata.json file to your webserver**, or the next steps will fail! @@ -2589,25 +2651,25 @@ ledgerowner as owner and also as rewards-account. We do the signing on the machi 1. Wait a minute so the transaction is complete 1. Add/Update the current UTXO balance for ledgerowner.payment in the offlineTransfer.json by running
```./01_workOffline.sh add ledgerowner.payment``` (we need it to pay for the delegation next and you just paid with it) -:floppy_disk: Transfer the offlineTransfer.json to the Offline-Machine. +💾 Transfer the offlineTransfer.json to the Offline-Machine. **Offline-Machine:** -1. Send all owner delegations to the blockchain. :bulb: Notice! This is different than before when using only CLI-Owner-Keys, if any owner is a HW-Wallet than you have to send the individual delegations after the stakepool registration. You can read more about it [here](#changes-to-the-operator-workflow-when-hardware-wallets-are-involved).
We have only one owner so lets do this by running the following command, **the HW-Wallet itself must pay for this**
```./06_regDelegationCert.sh ledgerowner ledgerowner.payment``` +1. Send all owner delegations to the blockchain. 💡 Notice! This is different than before when using only CLI-Owner-Keys, if any owner is a HW-Wallet than you have to send the individual delegations after the stakepool registration. You can read more about it [here](#changes-to-the-operator-workflow-when-hardware-wallets-are-involved).
We have only one owner so lets do this by running the following command, **the HW-Wallet itself must pay for this**
```./06_regDelegationCert.sh ledgerowner ledgerowner.payment``` -:floppy_disk: Transfer the offlineTransfer.json to the Online-Machine. +💾 Transfer the offlineTransfer.json to the Online- or Light-Machine. -**Online-Machine:** +**Online- or Light-Machine:** 1. Execute the cued transaction (ledgerowner delegation registration) on the blockchain by running
```./01_workOffline.sh execute``` 1. Wait a minute so the transaction is completed 1. Verify that your owner delegation to your pool is ok by running
```./03c_checkStakingAddrOnChain.sh ledgerowner``` if you don't see it instantly, wait a little and retry the same command -:warning: Transfer enough ADA to your new **ledgerowner.payment.addr** so you respect the registered Pledge amount, otherwise you will not get any rewards for you or your delegators!
You can always check the balance of your ledgerowner.payment by running ```./01_queryAddress.sh ledgerowner.payment``` on the Online-Machine.
You can check about rewards on the ledgerowner.staking by running ```./01_queryAddress.sh ledgerowner.staking``` +⚠️ Transfer enough ADA to your new **ledgerowner.payment.addr** so you respect the registered Pledge amount, otherwise you will not get any rewards for you or your delegators!
You can always check the balance of your ledgerowner.payment by running ```./01_queryAddress.sh ledgerowner.payment``` on the Online- or Light-Machine.
You can check about rewards on the ledgerowner.staking by running ```./01_queryAddress.sh ledgerowner.staking``` **Done**, yes this is more work to do when you wanna do this in offline mode, but it is how it is. :smiley: -:warning: Don't forget to register your Rewards-Account on the Chain via script 03b if its different from an Owner-Account! +⚠️ Don't forget to register your Rewards-Account on the Chain via script 03b if its different from an Owner-Account!
@@ -2619,13 +2681,13 @@ We want to make ourself a pool owner stake address with the nickname ledgerowner We use the smallwallet1 to pay for the different fees in this process. Make sure you have at least **510 ADA** on it.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑
-
**Online-Machine:** +
**Online- or Light-Machine:** 1. Add/Update the current UTXO balance for smallwallet1 in the offlineTransfer.json by running
```./01_workOffline.sh add smallwallet1``` (smallwallet1 will source the new ledgerowner for the stake-address and delegation registration, **at least 510 ADA should be on that wallet**) -:floppy_disk: Transfer the offlineTransfer.json to the Offline-Machine. +💾 Transfer the offlineTransfer.json to the Offline-Machine. **Offline-Machine:** @@ -2635,9 +2697,9 @@ We use the smallwallet1 to pay for the different fees in this process. Make sure 1. Make an offline transaction by sending some funds from your *smallwallet1* to your new *ledgerowner.payment* address for the stake key and delegation registration, 6 ADA should be ok for this ```./01_sendLovelaces.sh smallwallet1 ledgerowner.payment 6000000``` 1. Add the new ledgerowner.payment.addr and ledgerowner.staking.addr to your offlineTransfer.json
```./01_workOffline.sh attach ledgerowner.payment.addr```
```./01_workOffline.sh attach ledgerowner.staking.addr``` -:floppy_disk: Transfer the offlineTransfer.json to the Online-Machine. +💾 Transfer the offlineTransfer.json to the Online- or Light-Machine. -**Online-Machine:** +**Online- or Light-Machine:** 1. Extract the attached files (ledgerowner.payment.addr, ledgerowner.staking.addr) from the transferOffline.json
```./01_workOffline.sh extract``` 1. Execute the cued transaction (smallwallet1 to ledgerowner.payment) to the blockchain by running
```./01_workOffline.sh execute``` @@ -2647,7 +2709,7 @@ We use the smallwallet1 to pay for the different fees in this process. Make sure 1. Add/Update the current UTXO balance for smallwallet1 in the offlineTransfer.json by running
```./01_workOffline.sh add smallwallet1``` (we need it to pay for the pool registration and you've just paid with it) -:floppy_disk: Transfer the offlineTransfer.json to the Offline-Machine. +💾 Transfer the offlineTransfer.json to the Offline-Machine. **Offline-Machine:** @@ -2658,7 +2720,7 @@ We use the smallwallet1 to pay for the different fees in this process. Make sure 1. ```./04c_genKESKeys.sh mypool cli``` (to enycrypt the KES keys, change cli->enc) 1. ```./04d_genNodeOpCert.sh mypool``` 1. Now you have all the key files to start your coreNode with them: **mypool.vrf.skey, mypool.kes-000.skey, mypool.node-000.opcert** -1. You can include them also in the offlineTransfer.json to bring them over to your Online-Machine if you like by running
```./01_workOffline.sh attach mypool.vrf.skey```
```./01_workOffline.sh attach mypool.kes-000.skey```
```./01_workOffline.sh attach mypool.node-000.opcert``` +1. You can include them also in the offlineTransfer.json to bring them over to your Online- or Light-Machine if you like by running
```./01_workOffline.sh attach mypool.vrf.skey```
```./01_workOffline.sh attach mypool.kes-000.skey```
```./01_workOffline.sh attach mypool.node-000.opcert``` 1. Generate your stakepool certificate 1. ```./05a_genStakepoolCert.sh mypool```
will generate a prefilled **mypool.pool.json** file for you, **edit it !** 1. We want 200k ADA pledge, 500 ADA costs per epoch and 4% pool margin so let us set these and the Metadata values in the json file like below. Also we want the @@ -2696,9 +2758,9 @@ ledgerowner as owner and also as rewards-account. We do the signing on the machi 1. Delegate to your own pool as owner -> **pledge** ```./05b_genDelegationCert.sh mypool ledgerowner``` this will generate the **ledgerowner.deleg.cert** 1. Generate now the transaction for the the stakepool registration, smallwallet1 will pay for the registration fees
```./05c_regStakepoolCert.sh mypool smallwallet1```
Let the script also autoinclude your new mypool.metadata.json file into the transferOffline.json! -:floppy_disk: Transfer the offlineTransfer.json to the Online-Machine. +💾 Transfer the offlineTransfer.json to the Online- or Light-Machine. -**Online-Machine:** +**Online- or Light-Machine:** 1. Extract the attached files (mypool.metadata.json, mypool.vrf.skey, mypool.kes-000.skey, mypool.node-000.opcert) from the transferOffline.json ```./01_workOffline.sh extract``` 1. Now would be the time to **upload the mypool.metadata.json file to your webserver**, or the next steps will fail! @@ -2709,25 +2771,25 @@ ledgerowner as owner and also as rewards-account. We do the signing on the machi 1. Wait a minute so the transaction is complete 1. Add/Update the current UTXO balance for ledgerowner.payment in the offlineTransfer.json by running
```./01_workOffline.sh add ledgerowner.payment``` (we need it to pay for the delegation next and you just paid with it) -:floppy_disk: Transfer the offlineTransfer.json to the Offline-Machine. +💾 Transfer the offlineTransfer.json to the Offline-Machine. **Offline-Machine:** -1. Send all owner delegations to the blockchain. :bulb: Notice! This is different than before when using only CLI-Owner-Keys, if any owner is a HW-Wallet than you have to send the individual delegations after the stakepool registration. You can read more about it [here](#changes-to-the-operator-workflow-when-hardware-wallets-are-involved).
We have only one owner so lets do this by running the following command, **the HW-Wallet itself must pay for this**
```./06_regDelegationCert.sh ledgerowner ledgerowner.payment``` +1. Send all owner delegations to the blockchain. 💡 Notice! This is different than before when using only CLI-Owner-Keys, if any owner is a HW-Wallet than you have to send the individual delegations after the stakepool registration. You can read more about it [here](#changes-to-the-operator-workflow-when-hardware-wallets-are-involved).
We have only one owner so lets do this by running the following command, **the HW-Wallet itself must pay for this**
```./06_regDelegationCert.sh ledgerowner ledgerowner.payment``` -:floppy_disk: Transfer the offlineTransfer.json to the Online-Machine. +💾 Transfer the offlineTransfer.json to the Online- or Light-Machine. -**Online-Machine:** +**Online- or Light-Machine:** 1. Execute the cued transaction (ledgerowner delegation registration) on the blockchain by running
```./01_workOffline.sh execute``` 1. Wait a minute so the transaction is completed 1. Verify that your owner delegation to your pool is ok by running
```./03c_checkStakingAddrOnChain.sh ledgerowner``` if you don't see it instantly, wait a little and retry the same command -:warning: Transfer enough ADA to your new **ledgerowner.payment.addr** so you respect the registered Pledge amount, otherwise you will not get any rewards for you or your delegators!
You can always check the balance of your ledgerowner.payment by running ```./01_queryAddress.sh ledgerowner.payment``` on the Online-Machine.
You can check about rewards on the ledgerowner.staking by running ```./01_queryAddress.sh ledgerowner.staking``` +⚠️ Transfer enough ADA to your new **ledgerowner.payment.addr** so you respect the registered Pledge amount, otherwise you will not get any rewards for you or your delegators!
You can always check the balance of your ledgerowner.payment by running ```./01_queryAddress.sh ledgerowner.payment``` on the Online- or Light-Machine.
You can check about rewards on the ledgerowner.staking by running ```./01_queryAddress.sh ledgerowner.staking``` **Done**, yes this is more work to do when you wanna do this in offline mode, but it is how it is. :smiley: -:warning: Don't forget to register your Rewards-Account on the Chain via script 03b if its different from an Owner-Account! +⚠️ Don't forget to register your Rewards-Account on the Chain via script 03b if its different from an Owner-Account!
@@ -2738,13 +2800,13 @@ So this is an important one for many of you that already have registered a stake We use the smallwallet1 to pay for the different fees in this process. Make sure you have at least **10 ADA** on it.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑
-
**Online-Machine:** +
**Online- or Light-Machine:** 1. Add/Update the current UTXO balance for smallwallet1 in the offlineTransfer.json by running
```./01_workOffline.sh add smallwallet1``` (smallwallet1 will source the new ledgerowner for the stake-address and delegation registration, **at least 10 ADA should be on that wallet**) -:floppy_disk: Transfer the offlineTransfer.json to the Offline-Machine. +💾 Transfer the offlineTransfer.json to the Offline-Machine. **Offline-Machine:** @@ -2754,9 +2816,9 @@ We use the smallwallet1 to pay for the different fees in this process. Make sure 1. Make an offline transaction by sending some funds from your *smallwallet1* to your new *ledgerowner.payment* address for the stake key and delegation registration, 5 ADA should be ok for this ```./01_sendLovelaces.sh smallwallet1 ledgerowner.payment 5000000``` 1. Add the new ledgerowner.payment.addr and ledgerowner.staking.addr to your offlineTransfer.json
```./01_workOffline.sh attach ledgerowner.payment.addr```
```./01_workOffline.sh attach ledgerowner.staking.addr``` -:floppy_disk: Transfer the offlineTransfer.json to the Online-Machine. +💾 Transfer the offlineTransfer.json to the Online- or Light-Machine. -**Online-Machine:** +**Online- or Light-Machine:** 1. Extract the attached files (ledgerowner.payment.addr, ledgerowner.staking.addr) from the transferOffline.json
```./01_workOffline.sh extract``` 1. Execute the cued transaction (smallwallet1 to ledgerowner.payment) to the blockchain by running
```./01_workOffline.sh execute``` @@ -2766,7 +2828,7 @@ We use the smallwallet1 to pay for the different fees in this process. Make sure 1. Add/Update the current UTXO balance for smallwallet1 in the offlineTransfer.json by running
```./01_workOffline.sh add smallwallet1``` (we need it to pay for the pool Re-Registration and you've just paid with it) -:floppy_disk: Transfer the offlineTransfer.json to the Offline-Machine. +💾 Transfer the offlineTransfer.json to the Offline-Machine. **Offline-Machine:** @@ -2809,9 +2871,9 @@ We use the smallwallet1 to pay for the different fees in this process. Make sure 1. Delegate to your own pool as owner -> **pledge** ```./05b_genDelegationCert.sh mypool ledgerowner``` this will generate the **ledgerowner.deleg.cert** 1. Generate now the transaction for the stakepool re-registration, smallwallet1 will pay for the re-registration fees
```./05c_regStakepoolCert.sh mypool smallwallet1 REREG```
Let the script also autoinclude your new mypool.metadata.json file into the transferOffline.json if you have changed some Metadata! -:floppy_disk: Transfer the offlineTransfer.json to the Online-Machine. +💾 Transfer the offlineTransfer.json to the Online- or Light-Machine. -**Online-Machine:** +**Online- or Light-Machine:** 1. Extract the maybe attached files (mypool.metadata.json) from the transferOffline.json ```./01_workOffline.sh extract``` 1. If you have changed also some Metadata, **upload** the newly generated ```mypool.metadata.json``` file **onto your webserver** so that it is reachable via the URL you specified in the poolMetaUrl entry! Otherwise the next step will abort with an error. If you have only updated the owners, skip it. @@ -2822,31 +2884,31 @@ We use the smallwallet1 to pay for the different fees in this process. Make sure 1. Wait a minute so the transaction is complete 1. Add/Update the current UTXO balance for ledgerowner.payment in the offlineTransfer.json by running
```./01_workOffline.sh add ledgerowner.payment``` (we need it to pay for the delegation next and you just paid with it) -:floppy_disk: Transfer the offlineTransfer.json to the Offline-Machine. +💾 Transfer the offlineTransfer.json to the Offline-Machine. **Offline-Machine:** -1. Send all owner delegations to the blockchain. :bulb: Notice! This is different than before when using only CLI-Owner-Keys, if any owner is a HW-Wallet than you have to send the individual delegations after the stakepool registration. You can read more about it [here](#changes-to-the-operator-workflow-when-hardware-wallets-are-involved).
We have only one new owner (ledgerowner) so lets do this by running the following command, **the HW-Wallet itself must pay for this**
```./06_regDelegationCert.sh ledgerowner ledgerowner.payment``` +1. Send all owner delegations to the blockchain. 💡 Notice! This is different than before when using only CLI-Owner-Keys, if any owner is a HW-Wallet than you have to send the individual delegations after the stakepool registration. You can read more about it [here](#changes-to-the-operator-workflow-when-hardware-wallets-are-involved).
We have only one new owner (ledgerowner) so lets do this by running the following command, **the HW-Wallet itself must pay for this**
```./06_regDelegationCert.sh ledgerowner ledgerowner.payment``` -:floppy_disk: Transfer the offlineTransfer.json to the Online-Machine. +💾 Transfer the offlineTransfer.json to the Online- or Light-Machine. -**Online-Machine:** +**Online- or Light-Machine:** 1. Execute the cued transaction (ledgerowner delegation registration) on the blockchain by running
```./01_workOffline.sh execute``` 1. Wait a minute so the transaction is completed 1. Verify that your owner delegation to your pool is ok by running
```./03c_checkStakingAddrOnChain.sh ledgerowner``` if you don't see it instantly, wait a little and retry the same command  
-:warning: Now WAIT! Wait for 2 epoch changes! :warning: So if you're doing this in epoch n, wait until epoch n+2 before you continue! +⚠️ Now WAIT! Wait for 2 epoch changes! ⚠️ So if you're doing this in epoch n, wait until epoch n+2 before you continue!  
Now two epochs later your new additional **ledgerowner** co-owner is fully active. Its now the time to **transfer your owner funds** from the old **owner** to the new **ledgerowner**. -**Online-Machine:** +**Online- or Light-Machine:** 1. Add/Update the current UTXO balance for owner.payment (oldaccount) in the offlineTransfer.json by running
```./01_workOffline.sh add owner.payment``` -:floppy_disk: Transfer the offlineTransfer.json to the Offline-Machine. +💾 Transfer the offlineTransfer.json to the Offline-Machine. **Offline-Machine:** @@ -2854,14 +2916,14 @@ Now two epochs later your new additional **ledgerowner** co-owner is fully activ Be aware, this little transaction needed some fees, so you maybe have to top up your ledgerowner.payment account later with 1 ADA from another wallet to met your registered pledge again! -:floppy_disk: Transfer the offlineTransfer.json to the Online-Machine. +💾 Transfer the offlineTransfer.json to the Online- or Light-Machine. -**Online-Machine:** +**Online- or Light-Machine:** 1. Execute the cued transaction (owner.payment to ledgerowner.payment) on the blockchain by running
```./01_workOffline.sh execute```  
-:warning: WAIT AGAIN! Wait for 2 epoch changes! :warning: So if you're doing this in epoch n, wait until epoch n+2 before you continue! :warning: +⚠️ WAIT AGAIN! Wait for 2 epoch changes! ⚠️ So if you're doing this in epoch n, wait until epoch n+2 before you continue! ⚠️  
Why waiting again? Well, **we** also **changed the rewards-account** when we added the new ledgerowner, this takes 4 epochs on the blockchain to get fully updated. So, until now **you have received the rewards** of the pool **to your old owner.staking account**. Please check you rewards now and do a withdrawal of them, an example can be found below. @@ -2872,7 +2934,7 @@ Why waiting again? Well, **we** also **changed the rewards-account** when we add > Optional: If you wanna get rid of your old owner entry (you can leave it in there) in your stakepool registration - do the following:
Do it like the steps above, re-edit your mypool.pool.json file and remove the entry of the old owner from the poolOwner list. Save the file, generate a new certificate by running script 05a. Register it on the chain again like above or like the example below "Update stakepool parameters on the blockchain in Offline-Mode". Now you have only your new ledgerowner in your pool registration. -:warning: Don't forget to register your Rewards-Account on the Chain via script 03b if its different from an Owner-Account! +⚠️ Don't forget to register your Rewards-Account on the Chain via script 03b if its different from an Owner-Account!
@@ -2881,24 +2943,24 @@ Why waiting again? Well, **we** also **changed the rewards-account** when we add Lets pretend you already have registered your stakepool 'mypool' in the past using theses scripts, now lets update some pool parameters like pledge, fees or the description for the stakepool(metadata). We use the smallwallet1 to pay for this update.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑
-
**Online-Machine:** +
**Online- or Light-Machine:** 1. Add/Update the current UTXO balance for smallwallet1 in the offlineTransfer.json by running
```./01_workOffline.sh add smallwallet1``` -:floppy_disk: Transfer the offlineTransfer.json to the Offline-Machine. +💾 Transfer the offlineTransfer.json to the Offline-Machine. **Offline-Machine:** (same steps like working online) 1. [Unlock](#file-autolock-for-enhanced-security) the existing mypool.pool.json file and edit it. Only edit the values above the "--- DO NOT EDIT BELOW THIS LINE ---" line, save it again. 1. Run ```./05a_genStakepoolCert.sh mypool``` to generate a new mypool.pool.cert, mypool.metadata.json file from it 1. (Optional create delegation certificates if you have added an owner or an extra rewards account with script 05b) -1. Generate the offline Re-Registration of your stakepool with ```./05c_regStakepoolCert.sh mypool smallwallet1```
Your transaction with your updated pool-certificate is now stored in the offlineTransfer.json. As you have noticed, the 05c script also asked you if it should include the (maybe new) metadata files also in the offlineTransfer.json. So you need only one file for the transfer, we can extract them on the Online-Machine. +1. Generate the offline Re-Registration of your stakepool with ```./05c_regStakepoolCert.sh mypool smallwallet1```
Your transaction with your updated pool-certificate is now stored in the offlineTransfer.json. As you have noticed, the 05c script also asked you if it should include the (maybe new) metadata files also in the offlineTransfer.json. So you need only one file for the transfer, we can extract them on the Online- or Light-Machine. -:floppy_disk: Transfer the offlineTransfer.json to the Online-Machine. +💾 Transfer the offlineTransfer.json to the Online- or Light-Machine. -**Online-Machine:** +**Online- or Light-Machine:** 1. If your metadata/extended-metadata.json has changed and is in the transferOffline.json, extract it via
```./01_workOffline.sh extract``` 1. Now would be the time to upload the new metadata/extended-metadata.json files to your webserver. If they have not changed at all, skip this step of course. 1. Finally we submit the created offline transaction now to the blockchain by running
```./01_workOffline.sh execute``` @@ -2911,28 +2973,28 @@ Done. I'am sure you wanna claim some of your rewards that you earned running your stakepool. So lets say you have rewards in your owner.staking address and you wanna claim it to the owner.payment address by paying with funds from smallwallet2.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑
-
**Online-Machine:** +
**Online- or Light-Machine:** -Make sure you have your owner.staking.addr and smallwallet2.addr file on your Online-Machine, if not, copy it over from your Offline-Machine like a normal filecopy or use the attach->extract method we used in the example [here](#generate-some-wallets-for-the-daily-operator-work) +Make sure you have your owner.staking.addr and smallwallet2.addr file on your Online- or Light-Machine, if not, copy it over from your Offline-Machine like a normal filecopy or use the attach->extract method we used in the example [here](#generate-some-wallets-for-the-daily-operator-work) 1. Add/Update the current UTXO balance for smallwallet2 in the offlineTransfer.json by running
```./01_workOffline.sh add smallwallet2``` 1. Add/Update the current rewards state for owner.staking in the offlineTransfer.json by running
```./01_workOffline.sh add owner.staking``` Now we have the up2date information about the payment address smallwallet2 and also the current rewards state of owner.staking in the offlineTransfer.json. -:floppy_disk: Transfer the offlineTransfer.json to the Offline-Machine. +💾 Transfer the offlineTransfer.json to the Offline-Machine. **Offline-Machine:** (same steps like working online) 1. You can claim your rewards by running ```./01_claimRewards.sh owner.staking owner.payment smallwallet2``` This will claim the rewards from the owner.staking account and sends it to the owner.payment address, smallwallet2 will pay for the transaction fees.
- :bulb: ATTENTION, claiming rewards costs transaction fees! So you have two choices for that: The destination address pays for the transaction fees, or you specify an additional account that pays for the transaction fees like we did now. You can find examples for that above at the script 01_claimRewards.sh description. + 💡 ATTENTION, claiming rewards costs transaction fees! So you have two choices for that: The destination address pays for the transaction fees, or you specify an additional account that pays for the transaction fees like we did now. You can find examples for that above at the script 01_claimRewards.sh description. -:floppy_disk: Transfer the offlineTransfer.json to the Online-Machine. +💾 Transfer the offlineTransfer.json to the Online- or Light-Machine. -**Online-Machine:** +**Online- or Light-Machine:** 1. Execute the created offline rewards claim now on the blockchain by running
```./01_workOffline.sh execute``` Done. @@ -2945,25 +3007,25 @@ Lets say you wanna transfer 1000 Ada from your big-owner-payment-wallet owner.pa Also you wanna transfer 20 ADA from smallwallet1 to smallwallet3 at the same time, only transfering the offlineTransfer.json once.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑
-
**Online-Machine:** +
**Online- or Light-Machine:** -Make sure you have your owner.payment.addr and smallwallet1.addr file on your Online-Machine, if not, copy it over from your Offline-Machine like a normal filecopy or use the attach->extract method we used in the example [here](#generate-some-wallets-for-the-daily-operator-work) +Make sure you have your owner.payment.addr and smallwallet1.addr file on your Online- or Light-Machine, if not, copy it over from your Offline-Machine like a normal filecopy or use the attach->extract method we used in the example [here](#generate-some-wallets-for-the-daily-operator-work) 1. Add/Update the current UTXO balance for owner.payment in the offlineTransfer.json by running
```./01_workOffline.sh add owner.payment``` 1. Add/Update the current UTXO balance for smallwallet1 in the offlineTransfer.json by running
```./01_workOffline.sh add smallwallet1``` -:floppy_disk: Transfer the offlineTransfer.json to the Offline-Machine. +💾 Transfer the offlineTransfer.json to the Offline-Machine. **Offline-Machine:** (same steps like working online) 1. Generate the transaction to transfer 1000000000 lovelaces from owner.payment to smallwallet3
```./01_sendLovelaces.sh owner.payment smallwallet3 1000000000``` 1. Generate the transaction to transfer 20000000 lovelaces from smallwallet1 also smallwallet3
```./01_sendLovelaces.sh smallwallet1 smallwallet3 20000000``` -:floppy_disk: Transfer the offlineTransfer.json to the Online-Machine. +💾 Transfer the offlineTransfer.json to the Online- or Light-Machine. -**Online-Machine:** +**Online- or Light-Machine:** 1. Execute the first created offline transaction now on the blockchain by running
```./01_workOffline.sh execute``` 1. Execute the second created offline transaction now on the blockchain by running
```./01_workOffline.sh execute``` again @@ -2977,17 +3039,17 @@ Done. From the Mary-Era on, you can easily mint(generate) Native-Tokens by yourself, here you can find an example on how to do it.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑
### Mint an unresticted amount of Tokens So lets say we wanna create 1000 new Tokens with the name **SUPERTOKEN** under the policy **mypolicy**. And we want that theses AssetFiles are stored in the *assets* subdirectory. These Tokens should be generated on the account **mywallet**. -**Online-Machine:** +**Online- or Light-Machine:** 1. Add/Update the current UTXO balance for mywallet in the offlineTransfer.json by running
```./01_workOffline.sh add mywallet``` -:floppy_disk: Transfer the offlineTransfer.json to the Offline-Machine. +💾 Transfer the offlineTransfer.json to the Offline-Machine. **Offline-Machine:** (same steps like working online) @@ -2997,9 +3059,9 @@ So lets say we wanna create 1000 new Tokens with the name **SUPERTOKEN** under t The AssetsFile ***assets/mypolicy.SUPERTOKEN.asset*** was also written/updated with the latest action. You can see the totally minted Token count in there too. -:floppy_disk: Transfer the offlineTransfer.json to the Online-Machine. +💾 Transfer the offlineTransfer.json to the Online- or Light-Machine. -**Online-Machine:** +**Online- or Light-Machine:** 1. Execute the created offline transaction now on the blockchain by running
```./01_workOffline.sh execute``` @@ -3011,11 +3073,11 @@ Done - You have minted (created) 1000 new SUPERTOKENs and they are now added to Lets say we wanna create 200000 Tokens with the name **RARETOKEN** under the policy **special**. And we want that theses AssetFiles are stored in the *assets* subdirectory. These Tokens should be generated on the account **mywallet**. -**Online-Machine:** +**Online- or Light-Machine:** 1. Add/Update the current UTXO balance for mywallet in the offlineTransfer.json by running
```./01_workOffline.sh add mywallet``` -:floppy_disk: Transfer the offlineTransfer.json to the Offline-Machine. +💾 Transfer the offlineTransfer.json to the Offline-Machine. **Offline-Machine:** (same steps like working online) @@ -3025,9 +3087,9 @@ Lets say we wanna create 200000 Tokens with the name **RARETOKEN** under the pol The AssetsFile ***assets/special.RARETOKEN.asset*** was also written/updated with the latest action. You can see the totally minted Token count in there too. -:floppy_disk: Transfer the offlineTransfer.json to the Online-Machine. +💾 Transfer the offlineTransfer.json to the Online- or Light-Machine. -**Online-Machine:** +**Online- or Light-Machine:** 1. Execute the created offline transaction now on the blockchain by running
```./01_workOffline.sh execute``` @@ -3049,15 +3111,15 @@ Please checkout the example in the Online-Mode section, its exactly the same as If you wanna burn(destroy) some Native-Tokens, you can do it similar to the minting process. Here you can find an example on how to do it.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑

Important, you can only burn Native-Tokes that you have the policy for. You cannot burn other Native-Tokens that were sent to your wallet address. So lets say we wanna burn 200 **SUPERTOKEN** that we created before under the policy **mypolicy**. The AssetFiles were stored in the *assets* subdirectory, and the address we wanna burn the Tokens from is the account **mywallet**. -**Online-Machine:** +**Online- or Light-Machine:** 1. Add/Update the current UTXO balance for mywallet in the offlineTransfer.json by running
```./01_workOffline.sh add mywallet``` -:floppy_disk: Transfer the offlineTransfer.json to the Offline-Machine. +💾 Transfer the offlineTransfer.json to the Offline-Machine. **Offline-Machine:** (same steps like working online) @@ -3065,9 +3127,9 @@ If you wanna burn(destroy) some Native-Tokens, you can do it similar to the mint The AssetsFile ***assets/mypolicy.SUPERTOKEN.asset*** was also written/updated with the latest action. You can see the totally minted Token count in there too. -:floppy_disk: Transfer the offlineTransfer.json to the Online-Machine. +💾 Transfer the offlineTransfer.json to the Online- or Light-Machine. -**Online-Machine:** +**Online- or Light-Machine:** 1. Execute the created offline transaction now on the blockchain by running
```./01_workOffline.sh execute``` @@ -3081,23 +3143,23 @@ Done - You have burned (destroyed) 200 SUPERTOKENs. You can send Native-Tokens w This is as simply as sending lovelaces(ADA) from one wallet address to another address. Here you can find two examples on how to do it with self created Tokens and with Tokens you got from other ones.
- Show Example ... :bookmark_tabs:
+ Show Example ... 📑

Lets say we wanna send 15 **SUPERTOKEN** that we created by our own before under the policy **mypolicy**. The AssetFiles were stored in the *assets* subdirectory. The Tokens are on the address **mywallet** and we wanna send them to the address in **yourwallet**. -**Online-Machine:** +**Online- or Light-Machine:** 1. Add/Update the current UTXO balance for mywallet in the offlineTransfer.json by running
```./01_workOffline.sh add mywallet``` -:floppy_disk: Transfer the offlineTransfer.json to the Offline-Machine. +💾 Transfer the offlineTransfer.json to the Offline-Machine. **Offline-Machine:** (same steps like working online) 1. Run ```./01_sendAssets.sh mywallet yourwallet assets/mypolicy.SUPERTOKEN.asset 15``` to send 15 SUPERTOKENs from *mywallet* to *yourwallet*. -:floppy_disk: Transfer the offlineTransfer.json to the Online-Machine. +💾 Transfer the offlineTransfer.json to the Online- or Light-Machine. -**Online-Machine:** +**Online- or Light-Machine:** 1. Execute the created offline transaction now on the blockchain by running
```./01_workOffline.sh execute``` @@ -3107,11 +3169,11 @@ As you can see, we referenced the Token via the AssetsFile ***assets/mypolicy.SU Lets now say we wanna send 36 **RANDOMCOIN**s that we got from another user. For that we have to reference it via the full PolicyID.Assetname scheme. In this example these RANDOMCOIN Tokens are on the address **mywallet** and we wanna send them to the address in **yourwallet**. -**Online-Machine:** +**Online- or Light-Machine:** 1. Add/Update the current UTXO balance for mywallet in the offlineTransfer.json by running
```./01_workOffline.sh add mywallet``` -:floppy_disk: Transfer the offlineTransfer.json to the Offline-Machine. +💾 Transfer the offlineTransfer.json to the Offline-Machine. **Offline-Machine:** (same steps like working online) @@ -3121,9 +3183,9 @@ Lets now say we wanna send 36 **RANDOMCOIN**s that we got from another user. For Paste it into the command Step 3. 1. Run ```./01_sendAssets.sh mywallet yourwallet 34250edd1e9836f5378702fbf9416b709bc140e04f668cc355208518.RANDOMCOIN 36``` to send 36 of theses RANDOMCOINs from *mywallet* to *yourwallet*. -:floppy_disk: Transfer the offlineTransfer.json to the Online-Machine. +💾 Transfer the offlineTransfer.json to the Online- or Light-Machine. -**Online-Machine:** +**Online- or Light-Machine:** 1. Execute the created offline transaction now on the blockchain by running
```./01_workOffline.sh execute``` @@ -3149,7 +3211,7 @@ As you can see, its always the same procedure working in Offline-Mode: 1. Get the information about your payment/rewards addresses online using ./01_workOffline.sh 1. Transfer the offlineTransfer.json to the Offline-Machine 1. Do your normal operations on the Offline-Machine (only one payment from an individual payment address) -1. Transfer the offlineTransfer.json to the Online-Machine +1. Transfer the offlineTransfer.json to the Online- or Light-Machine 1. Execute the operation online on the chain, and/or extract some included files too using ./01_workOffline.sh If you have questions, feel free to contact me via telegram: @atada_stakepool diff --git a/cardano/mainnet/sha256sum_sposcripts.txt b/cardano/mainnet/sha256sum_sposcripts.txt index b19ba397..6c15c3b5 100644 --- a/cardano/mainnet/sha256sum_sposcripts.txt +++ b/cardano/mainnet/sha256sum_sposcripts.txt @@ -1,39 +1,39 @@ -fb24bad20e526eea989ca9b5def5985d5d5a50b2ca231b21735d6e042708216a 00_common.sh -0af3521d719785ba7a378f8f63a8894fae4216c5f7b192b90132d6990dfedb27 01_claimRewards.sh -5a31f33c423f7399e6be5d845a926008decaac226cb510cc5f24d1fa1a7fc08c 01_protectKey.sh -d9d0ecb31c8846f640dd53d88cf2450f95caea2ddc5566fa99a14ddc1ab2d9df 01_queryAddress.sh -1721e412ecad309f9f81b5f253beb33a225b488441842f251c0f17601a2454d6 01_sendAssets.sh -b5c4c6a619cf1d95039c4f35290d5686c423d6af4a5d5d89513b9cfe6042a1dd 01_sendLovelaces.sh -13fd5966f24a125b40d4cb74930eab76007cfcd6bf449660c3441d2a5094460a 01_workOffline.sh -2baf25f9c21d0310616d47bc6bb722414c5251c0eaac6bc528e28b6e398af5bc 02_genPaymentAddrOnly.sh -83edd112bec7bc5a3307d3e485b637150acf5c3e19ce188759bd7f1669a3b262 03a_genStakingPaymentAddr.sh -f13252c9a98e9069c20c9e378b7e98ad7765f6efd656623158cddeb1d9b24834 03b_regStakingAddrCert.sh -29c5a48936fbf48624ea76ece77cca4f0ddb5cd0e227ed319a2f1fd96d5cee67 03c_checkStakingAddrOnChain.sh -a40446b9a6112663047530b628ebd6142bb0094f22e1c70c109d36b31a278b4c 04a_genNodeKeys.sh -a78c422363cc3634dc5da44df16f6505b672c8cb59e886ca1dee3d679d2df0f5 04b_genVRFKeys.sh -b931feb432ab62b7b5e4036c02cf416cf58d56ad5069f6bb50955d845d3fdd45 04c_genKESKeys.sh -86720b89964f53916353ed30203cb6e6042e3752f82e737089106c0648bf5226 04d_genNodeOpCert.sh -a77eac7ea5d69a9d445e1c5dad07f367294eaec2c3abd382f62aa6808494590e 04e_checkNodeOpCert.sh -0efea85cee029938cfa75fb61c0bd7a39677ddbbe254c007d684108ae6d39ab0 05a_genStakepoolCert.sh -09228f93f278fd9d633963c320f57beae428702ad44f19f79c3c9eee6b90b133 05b_genDelegationCert.sh -f05e6765c7b0a282562e3455a0ec31e7b2792fa0b355aa9635e2664b3af8e0bc 05c_regStakepoolCert.sh -08e1dcb0f8a85c02d96fbd4886a0067a2ede9c3e88c31429365f2b0e7e0dd47c 05d_poolWitness.sh -9dabb487620890352a4f8adf45e45dad0f5813743314bdb832f470a553fb6440 05e_checkPoolOnChain.sh -2da6df17d30d6b2712b23d79e5176de1f3493872f1cf7d381e0ffec087a275aa 06_regDelegationCert.sh -c3513b7d381403c93011b24a39a151febdbc3d13e73527452f22cca3b59589da 07a_genStakepoolRetireCert.sh -8c61d41dbf3da80ae4eb1bccfb071ca08b20e1639941534d6d17ee8029703740 07b_deregStakepoolCert.sh -f19545e6e2e397fe2336f3e6308b13ba32f462e9ff50cd0e09565265524956c0 08a_genStakingAddrRetireCert.sh -0408079294943b365315eacf7157583fde7e81b576b29681d04af6964b26668d 08b_deregStakingAddrCert.sh +e56cc3a0faa64c32f083ca5ff4161379b1131b62a37b6640458084fff64939a1 00_common.sh +13785840fb2ede730f0073c3b1e09a1400e899b63479dc05b1fbafc645d3d63f 01_claimRewards.sh +6aac68033368157b234165ef441e5a91fbedc637d96db1ca38bbf6b265c0e3c3 01_protectKey.sh +6d3f4a4eb273b309a517fe10729f7be4a11b1277e9e298c84d8f0e123ba7ac17 01_queryAddress.sh +951ce80cead0c50d6695aad6960e8dbd2ab3846532ef22c9ce53f5b49d5ae393 01_sendAssets.sh +0b2ffd64509dc73312a3d96c9b003fdf6171829e8d7d46c86ab61b410c71bc1f 01_sendLovelaces.sh +6c1b5253f1a590fb6557e98764cb53f74431b74726d355ccd663e46cfa23272d 01_workOffline.sh +f20d77de6541d6daba1233cc7d0a53a6ce0534392633fd9a3edd68477e9b5024 02_genPaymentAddrOnly.sh +93c7b80a231d10a9230a1a156d1ba71618b6db0e0a4712e373554011d040479a 03a_genStakingPaymentAddr.sh +e8ec7a930b2ed7a82c67dad3b4b255a8db7a049fd2d217330b7a7140f1e45fd8 03b_regStakingAddrCert.sh +ff84282faf855222140adad3e69ae17c0b4ce15f56906cea97d6e109e044782f 03c_checkStakingAddrOnChain.sh +d2af1bb6cc181c18f92cc6efe1e2114bd4267fdbbade4aef7e00338c63eba60d 04a_genNodeKeys.sh +363e0ab2da5302c845e55024f3e83284de5793249cba1a50ca5a5e734bb6d586 04b_genVRFKeys.sh +910fcaf40b83dc520125d0d0919aa32f13591cafc1bbf31b6f758f3d04a85830 04c_genKESKeys.sh +4c985cf075a2e6f136ff08bd912a5931a070d59d37e52b0a181bac6e1a3d35c0 04d_genNodeOpCert.sh +22c6fe720f63b0c03aed1598b3f4278d15c61102201ba97512113555e3b77caf 04e_checkNodeOpCert.sh +97b6728f2a20843eee2b4d05aece14efdba2dcbdf6fcbdec686560832aa7ed25 05a_genStakepoolCert.sh +12f422ace94861ab186227a4f920c10b444ea8e9c8d8f13280f3181397598ca5 05b_genDelegationCert.sh +7d1fba63ec2b0fa174f42dedda4305f8ff6607293028502e32b2a738d6c36471 05c_regStakepoolCert.sh +40afc69ad709b0d9e482b89f4bc9b51781863b32e04b0efa1ab3a0cb7ebd0af6 05d_poolWitness.sh +4afb9ec11b3ed952e99f8c34045408895c69c6fc178f1811ec823b4c0b638de7 05e_checkPoolOnChain.sh +2936ff019446d0d568076b03d74ba7e342dbf5c936d6093d85461de2a3ca6f42 06_regDelegationCert.sh +d054ec0f94e1c16ed34f081ae820909bad807a93fee90d9e37d1f117483154d0 07a_genStakepoolRetireCert.sh +af28c4862c347a69952915d5149a62b4077cd8998650200fb8008ac9a2ad56ec 07b_deregStakepoolCert.sh +05bdda8eb501d0a298cc9574185eab743ffd3d0d0fbd509b5783c4d4829bf8d9 08a_genStakingAddrRetireCert.sh +1872a484a7424dd2b026c70c92c89eccfbbcf07afc5d11bb86e46edd63fad404 08b_deregStakingAddrCert.sh b3af1679830c957cd293b9a1e64ebc67307a2544cee5e0c96224c563b57a0115 09a_catalystVoteF10.sh -d60b3678f05fd24c4cad966d58257c19b96c2cb1b935ebc3f6d1cba2cd6f8678 09a_catalystVote.sh -ac9a57b8800477615cc4fcc60729871550ef4259255bb10cb56d3112f837f8d0 0x_importHelper.sh -34452f826a7904045798eec90343ff53a32c031d98ef856d9631e7b4852569cd 10_genPolicy.sh -98c9ba1af11fd5149397a29f50ddd459d013235351774722dc0e3c85ff317018 11a_mintAsset.sh -82955d2f725c8fa5aab7e51852b10900d0649330053cd759b216ee9158b4bba7 11b_burnAsset.sh -8a3961be34a453a98247982e17192bcae6c9b6169c19208ef431a7cc68cdf7c5 12a_genAssetMeta.sh -f6db67f62eb047e1125be44f48e912fb4e792103f7dc9f7dd0e3b84eb91a9de7 12b_checkAssetMetaServer.sh -c61dffe5234cfa7da3e391e1de72f22580208b2725370acdc1c2e765557d73ae 13a_spoPoll.sh -889fe699277a331950dcfc8604c3eabf11babe3c193eda77f20922136d4feecd 13b_sendSpoPoll.sh +fc1d55c371c8bdba4966bc76072846be7342b9740f328e4916b4530e4a904ebd 09a_catalystVote.sh +8c5ab77b3dd4680e65e6d6dd6c400bb96536bb7e47f8d0be44037ffb6ecb74f4 0x_importHelper.sh +448419dccb927f8da8d847e20482c9e9997d894a57851477aaa149a9f02a7028 10_genPolicy.sh +4f1d2d83fe7b4a8be35cb627c8b90c62e5da6a68f27b775e629ae359590de5eb 11a_mintAsset.sh +2aff137002af2e2434ba7a4759f4d94668114d9f82e174996a1a02dbefbf190f 11b_burnAsset.sh +bdfbfbf12dc16908dad53a73831ca9ae4a520e53a3124f8a19500f89c0c2d8c6 12a_genAssetMeta.sh +6af5a628402d67dd5133f4dca8ce3d8bd16f7ef82ae2f380b1d147230838e836 12b_checkAssetMetaServer.sh +8be7ed22afc2f9a4c3319cf9a9410a534ed0b715104f1db4312f330259bc1aaf 13a_spoPoll.sh +c1f79441448cde6eb5ecb9fb25f8670d09e4f4155ccb57242df89e711f67b561 13b_sendSpoPoll.sh b7b13da87eeafe5dbd0f0d1810e2f4e69dc02c8c1e0697f8c7847740dc73a4fb bech32 6c5df521e2848c6767f878bbe81a7ec077ff8d1b0dbd01819aea45e1701d5a4a token-metadata-creator 0ae1c4ae68451994edceafc2282af23ef5f1fdd641efb907c769ef135c701e03 catalyst-toolbox diff --git a/cardano/testnet/05e_checkPoolOnChain.sh b/cardano/testnet/05e_checkPoolOnChain.sh index d3bf3447..9a3fced8 100755 --- a/cardano/testnet/05e_checkPoolOnChain.sh +++ b/cardano/testnet/05e_checkPoolOnChain.sh @@ -150,7 +150,7 @@ if [[ "${koiosAPI}" != "" ]]; then read poolOpcertCounter; read poolRewardAddr; read poolVrfHash; - } <<< $(jq -r ".[0].meta_json.name // \"-\", .[0].meta_json.ticker // \"-\", .[0].pool_status // \"-\", .[0].pledge // \"-\", .[0].live_pledge // \"-\", .[0].margin // \"-\", .[0].fixed_cost // \"-\", .[0].meta_url // \"-\", .[0].meta_hash // \"-\", .[0].op_cert_counter // \"-\", .[0].reward_addr // \"-\", .[0].vrf_key_hash // \"-\"" 2> /dev/null <<< ${responseJSON}) + } <<< $(jq -r ".[0].meta_json.name // \"-\", .[0].meta_json.ticker // \"-\", .[0].pool_status // \"-\", .[0].pledge // \"0\", .[0].live_pledge // \"0\", .[0].margin // \"-\", .[0].fixed_cost // \"0\", .[0].meta_url // \"-\", .[0].meta_hash // \"-\", .[0].op_cert_counter // \"-\", .[0].reward_addr // \"-\", .[0].vrf_key_hash // \"-\"" 2> /dev/null <<< ${responseJSON}) echo -e "\e[0m Name (Ticker): \e[32m${poolName} (${poolTicker})\e[0m" echo -e "\e[0m Set Pledge:\e[32m ${poolPledge} \e[90mlovelaces \e[0m(\e[32m$(convertToADA ${poolPledge}) \e[90mADA\e[0m)"