From a109e5c3626cbc6ceb666617fb621382aff3e7fd Mon Sep 17 00:00:00 2001 From: "Ola [AHLNET]" Date: Wed, 21 Apr 2021 16:32:14 +0200 Subject: [PATCH] CNTools 8.2.0 (#895) # Added - Ability to create & update a Cardano Token Registry submission JSON file - Requires 'token-metadata-creator' tool, instructions to download/build this tool added to Guild Operators documentation: - https://cardano-community.github.io/guild-operators/#/Build/offchainMetadataTools - Token Registry lookup in Wallet >> Show - Token asset fingerprint generation according to https://github.com/cardano-foundation/CIPs/pull/64 # Changed - Redesigned input handling to be more flexible and improve output Many line changes due to some code refactoring for println and the new ask function to handle input --- docs/Build/offchain-metadata-tools.md | 44 + docs/Build/rest.md | 2 +- docs/Scripts/cntools-changelog.md | 11 + docs/Scripts/cntools.md | 5 +- docs/_sidebar.md | 4 +- docs/build.md | 39 +- docs/index.html | 2 +- scripts/cnode-helper-scripts/cncli.sh | 58 +- scripts/cnode-helper-scripts/cntools.library | 626 +++--- scripts/cnode-helper-scripts/cntools.sh | 1894 +++++++++-------- scripts/cnode-helper-scripts/env | 241 ++- scripts/cnode-helper-scripts/gLiveView.sh | 48 +- .../cnode-helper-scripts/topologyUpdater.sh | 55 +- 13 files changed, 1628 insertions(+), 1401 deletions(-) create mode 100644 docs/Build/offchain-metadata-tools.md diff --git a/docs/Build/offchain-metadata-tools.md b/docs/Build/offchain-metadata-tools.md new file mode 100644 index 000000000..7a270c032 --- /dev/null +++ b/docs/Build/offchain-metadata-tools.md @@ -0,0 +1,44 @@ +!> - An average pool operator may not require offline-metadata-tools at all. Please verify if it is required for your use as mentioned [here](build.md#components) + +>Ensure the [Pre-Requisites](basics.md#pre-requisites) are in place before you proceed. + +In the Cardano multi-asset era, this project helps you create and submit metadata describing your assets, storing them off-the-chain. + +##### Download pre-built binaries + +Go to [input-output-hk/offchain-metadata-tools](https://github.com/input-output-hk/offchain-metadata-tools#pre-built-binaries) to download the binaries and place in a direcotry specified by `PATH`, eg `$HOME/.cabal/bin/`. + +##### Build Instructions + +An alternative to pre-built binaries. Instructions describe how to build the `token-metadata-creator` tool but the offchain-metadata-tools repository contains other tools as well. Build the ones needed for your installation. + +##### Clone the repository + +Execute the below to clone the offchain-metadata-tools repository to $HOME/git folder on your system: + +``` bash +cd ~/git +git clone https://github.com/input-output-hk/offchain-metadata-tools.git +cd offchain-metadata-tools/token-metadata-creator +``` + +##### Build token-metadata-creator + +You can use the instructions below to build token-metadata-creator, same steps can be executed in future to update the binaries (replacing appropriate tag) as well. + +``` bash +git fetch --tags --all +git pull +# Replace master with appropriate tag if you'd like to avoid compiling against master +git checkout master +$CNODE_HOME/scripts/cabal-build-all.sh +``` +The above would copy the binaries into `~/.cabal/bin` folder. + +##### Verify that token-metadata-creator is installed + +Verify that the tool is executable from anywhere by running: + +``` bash +token-metadata-creator -h +``` diff --git a/docs/Build/rest.md b/docs/Build/rest.md index ee6ab1001..db8becc31 100644 --- a/docs/Build/rest.md +++ b/docs/Build/rest.md @@ -1,4 +1,4 @@ -!> - An average pool operator may not require cardano-wallet at all. Please verify if it is required for your use as mentioned [here](build.md#components) +!> - An average pool operator may not require cardano-rest at all. Please verify if it is required for your use as mentioned [here](build.md#components) >Ensure the [Pre-Requisites](basics.md#pre-requisites) are in place before you proceed. diff --git a/docs/Scripts/cntools-changelog.md b/docs/Scripts/cntools-changelog.md index 27377e6d8..7cbac78ff 100644 --- a/docs/Scripts/cntools-changelog.md +++ b/docs/Scripts/cntools-changelog.md @@ -5,6 +5,17 @@ All notable changes to this tool will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [8.2.0] - 2021-04-18 +##### Added +- Ability to create & update a Cardano Token Registry submission JSON file + - Requires 'token-metadata-creator' tool, instructions to download/build this tool added to Guild Operators documentation: + - https://cardano-community.github.io/guild-operators/#/Build/offchainMetadataTools +- Token Registry lookup in Wallet >> Show +- Token asset fingerprint generation according to https://github.com/cardano-foundation/CIPs/pull/64 + +##### Changed +- Redesigned input handling to be more flexible and improve output + ## [8.1.6] - 2021-04-14 ##### Changed - Metadata creation now offer the choice to add a metadata JSON scaffold to see the required structure diff --git a/docs/Scripts/cntools.md b/docs/Scripts/cntools.md index f9d9d5fed..b95cb8efd 100644 --- a/docs/Scripts/cntools.md +++ b/docs/Scripts/cntools.md @@ -34,6 +34,8 @@ See [CNCLI](Scripts/cncli.md) and [Log Monitor](Scripts/logmonitor.md) sections ##### Download and Update The update functionality is provided from within CNTools. In case of breaking changes, please follow the prompts post upgrade. If stuck, it's always best to re-run latest prereqs before proceeding. +!> If you have not updated in a while, it is possible that you might come from a release with breaking change. If so, please be sure to check out the [upgrade](upgrade.md) instructions + ##### Navigation The scripts menu supports both arrow key navigation and shortcut key selection. The character within the square brackets is the shortcut to press for quick navigation. For other selections like wallet and pool menu that doesn't contain shortcuts, there is a third way to navigate. Key pressed is compared to the first character of the menu option and if there is a match selection jumps to this location. A handy way to quickly navigate a large menu. @@ -51,6 +53,7 @@ Supported devices: Model T Make sure the latest firmware is installed on the device. In addition to this, install `Trezor Bridge` for your system before trying to use your Trezor device in CNTools. You can find the latest version of the bridge at https://wallet.trezor.io/#/bridge ##### Offline Workflow + CNTools can be run in online and offline mode. At a very high level, for working with offline devices, remember that you need to use CNTools on an online node to generate a staging transaction for the desired type of transaction, and then move the staging transaction to offline node to sign (authorize) using your offline node signing keys - and then bring back updated transaction to the online node for submission to chain. For offline workflow all wallet and pool keys should be kept on the offline node. The backup function in CNTools has an option to create a backup without private keys(sensitive signing keys) to be transfered to online node. All other files are included in the backup to be transfered to the online node. @@ -59,7 +62,7 @@ Keys excluded from backup when created without private keys: **Wallet** - payment.skey, stake.skey **Pool** - cold.skey -Example workflow for creating a wallet and pool +Note that setting up an offline server requires good sysops background (you need to be aware of how to set up your server with offline mirror repository, how to transfer files across and be fairly familiar with the disk layout of guild tools). The prereqs.sh in its current state is not expected to run on an offline machine. Essentially you simply need `cardano-cli`,`bech32`,`cardano-address` binary in your $PATH, OS level dependency packages [ `jq`,`coreutils`,`pkgconfig`,`gcc-c++` and `bc` ], perhaps a copy from your online cnode folder (to ensure you have the right genesis/config files on your offline server). We strongly recommend you to familiarise with the workflow on testnet / guild network first, before attempting on mainnet. Example workflow for creating a wallet and pool ``` mermaid diff --git a/docs/_sidebar.md b/docs/_sidebar.md index 510c3ddc8..afd31b79c 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -3,9 +3,9 @@ * [Build and Run](build.md) * [Node and CLI](Build/node-cli.md "Cardano Node and CLI") * [Wallet](Build/wallet.md "Cardano Wallet") - * [DBSync tool](Build/dbsync.md "Cardano DB Sync Tool") - * [REST](Build/rest.md "Cardano Rest") + * [DBSync](Build/dbsync.md "Cardano DB Sync Tool") * [PostgREST](Build/pgrest.md "PostgREST") + * [Offchain Metadata Tools](Build/offchain-metadata-tools.md "Offchain Metadata Tools") * [Docker](docker/docker.md "Cardano Docker by Guild Operators") * [Build](docker/build.md "Build your own Cardano Node") * [Run](docker/run.md "Run you own Cardano Node") diff --git a/docs/build.md b/docs/build.md index 45cbed586..7bc168734 100644 --- a/docs/build.md +++ b/docs/build.md @@ -8,39 +8,32 @@ For most Pool Operators, simply building [cardano-node](Build/node-cli.md) shoul graph TB A(Need to interact with
HD Wallets or query
pool metadata locally?) B(Need to explore
blockchain locally?) - C(Automate pool-ops
tasks using
menu navigations?) + C(Manage pool-ops
and asset operation
tasks using
menu navigations?) + D(Create Custom Assets?) + E(Monitor node
using Terminal UI) O{{Node}} P{{PostgREST}} Q{{DBSync }} R{{Wallet}} S{{CNTools}} - T{{Rest}} - -O --x A --x R + T{{*Rest}} + U{{*GraphQL}} + V{{Offline Metadata Tools}} + X{{gLiveView}} + +O --x E --x X +O --x C --x S +O --x D --x V O --x B B --x P --x Q B --x T --x Q -O --x C -C --x S +B --x U --x Q +O --x A --x R ``` -**The instructions are intentionally limited to cabal** to avoid wait times/availability of nix/docker files on, what we expect to be, a rapidly developing codebase - this will also help prevent managing multiple versions of instructions (at least for now). +> We have retired usage of Rest/GraphQL components from guild website due to lack of advantages over PostgREST , as well as simplicity/not having to work with/mix different technologies for base layer itself. + +**The instructions are intentionally limited to stack/cabal** to avoid wait times/availability of nix/docker files on, what we expect to be, a rapidly developing codebase - this will also help prevent managing multiple versions of instructions (at least for now). Note that the instructions are predominantly focused around building Cardano components and OS/3rd-party software (eg: postgres) setup instructions are intended to provide basic information only. -###### Docker Builds - -If you would like to go down the Docker route, the basic instructions to get you set up with Docker itself are below. Additionally, you can follow [IOHK Adrestia documentation](https://docs.cardano.org/projects/adrestia) for the latest release information: -``` bash -# CentOS -sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo -sudo yum install https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.6-3.3.el7.x86_64.rpm -sudo yum install -y docker-ce docker-ce-cli -sudo systemctl enable docker -sudo chkconfig docker on - -## These steps would be automatically performed by the install above -# sudo groupadd docker -# sudo usermod -aG docker $USER -sudo curl -L "https://github.com/docker/compose/releases/download/1.25.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/bin/docker-compose;chmod 755 /usr/bin/docker-compose -``` diff --git a/docs/index.html b/docs/index.html index 6da1c1453..42260fd31 100644 --- a/docs/index.html +++ b/docs/index.html @@ -66,7 +66,7 @@ hook.beforeEach(function(content) { // Invoked each time before parsing the Markdown file. // ... - var custommarkdown = '!> Note that there was a breaking change introduced to guild repository scripts on 15th October. If you are coming from release before, please be sure to check out the [upgrade](upgrade.md) instructions\n' + var custommarkdown = '' return custommarkdown + '\n' + content; }); //hook.doneEach(function() { diff --git a/scripts/cnode-helper-scripts/cncli.sh b/scripts/cnode-helper-scripts/cncli.sh index f4ad441bd..6d4fddfa3 100755 --- a/scripts/cnode-helper-scripts/cncli.sh +++ b/scripts/cnode-helper-scripts/cncli.sh @@ -126,64 +126,16 @@ cncliInit() { if ! command -v sqlite3 >/dev/null; then echo "ERROR: sqlite3 not found, please install before activating blocklog function" && exit 1; fi PARENT="$(dirname $0)" - - # Check if update is available - [[ -f "${PARENT}"/.env_branch ]] && BRANCH="$(cat ${PARENT}/.env_branch)" || BRANCH="master" - URL="https://raw.githubusercontent.com/cardano-community/guild-operators/${BRANCH}/scripts/cnode-helper-scripts" - if curl -s -f -m 10 -o "${PARENT}"/cncli.sh.tmp ${URL}/cncli.sh && curl -s -f -m 10 -o "${PARENT}"/env.tmp ${URL}/env && [[ -f "${PARENT}"/cncli.sh.tmp && -f "${PARENT}"/env.tmp ]]; then - if [[ -f "${PARENT}"/env ]]; then - if [[ $(grep "_HOME=" "${PARENT}"/env) =~ ^#?([^[:space:]]+)_HOME ]]; then - vname=$(tr '[:upper:]' '[:lower:]' <<< "${BASH_REMATCH[1]}") - else - echo -e "\nFailed to get cnode instance name from env file, aborting!\n" - rm -f "${PARENT}"/cncli.sh.tmp - rm -f "${PARENT}"/env.tmp - exit 1 - fi - sed -e "s@/opt/cardano/[c]node@/opt/cardano/${vname}@g" -e "s@[C]NODE_HOME@${BASH_REMATCH[1]}_HOME@g" -i "${PARENT}"/cncli.sh.tmp -i "${PARENT}"/env.tmp - CNCLI_TEMPL=$(awk '/^# Do NOT modify/,0' "${PARENT}"/cncli.sh) - CNCLI_TEMPL2=$(awk '/^# Do NOT modify/,0' "${PARENT}"/cncli.sh.tmp) - ENV_TEMPL=$(awk '/^# Do NOT modify/,0' "${PARENT}"/env) - ENV_TEMPL2=$(awk '/^# Do NOT modify/,0' "${PARENT}"/env.tmp) - if [[ "$(echo ${CNCLI_TEMPL} | sha256sum)" != "$(echo ${CNCLI_TEMPL2} | sha256sum)" || "$(echo ${ENV_TEMPL} | sha256sum)" != "$(echo ${ENV_TEMPL2} | sha256sum)" ]]; then - . "${PARENT}"/env offline &>/dev/null # source in offline mode and ignore errors to get some common functions, sourced at a later point again - if [[ ${BATCH_AUTO_UPDATE} = 'Y' ]] || { [[ -t 1 ]] && getAnswer "\nA new version is available, do you want to upgrade?"; }; then - cp "${PARENT}"/cncli.sh "${PARENT}/cncli.sh_bkp$(date +%s)" - cp "${PARENT}"/env "${PARENT}/env_bkp$(date +%s)" - CNCLI_STATIC=$(awk '/#!/{x=1}/^# Do NOT modify/{exit} x' "${PARENT}"/cncli.sh) - ENV_STATIC=$(awk '/#!/{x=1}/^# Do NOT modify/{exit} x' "${PARENT}"/env) - printf '%s\n%s\n' "$CNCLI_STATIC" "$CNCLI_TEMPL2" > "${PARENT}"/cncli.sh.tmp - printf '%s\n%s\n' "$ENV_STATIC" "$ENV_TEMPL2" > "${PARENT}"/env.tmp - { - mv -f "${PARENT}"/cncli.sh.tmp "${PARENT}"/cncli.sh && \ - mv -f "${PARENT}"/env.tmp "${PARENT}"/env && \ - chmod 755 "${PARENT}"/cncli.sh "${PARENT}"/env && \ - echo -e "\nUpdate applied successfully, please run cncli again!\n" && \ - exit 0; - } || { - echo -e "\n${FG_RED}Update failed!${NC}\n\nplease install cncli.sh & env with prereqs.sh or manually download from GitHub" && \ - rm -f "${PARENT}"/cncli.sh.tmp && \ - rm -f "${PARENT}"/env.tmp && \ - exit 1; - } - fi - fi - else - mv "${PARENT}"/env.tmp "${PARENT}"/env - rm -f "${PARENT}"/cncli.sh.tmp - echo -e "\nCommon env file downloaded: ${PARENT}/env" - echo -e "This is a mandatory prerequisite, please set variables accordingly in User Variables section in the env file and restart cncli.sh\n" - exit 0 - fi - fi - rm -f "${PARENT}"/cncli.sh.tmp - rm -f "${PARENT}"/env.tmp - + if [[ ! -f "${PARENT}"/env ]]; then echo -e "\nCommon env file missing: ${PARENT}/env" echo -e "This is a mandatory prerequisite, please install with prereqs.sh or manually download from GitHub\n" exit 1 fi + + # Check if update is available + ! checkUpdate env ${BATCH_AUTO_UPDATE} && exit 1 + ! checkUpdate cncli.sh ${BATCH_AUTO_UPDATE} && exit 1 until . "${PARENT}"/env; do echo "sleeping for 10s and testing again..." diff --git a/scripts/cnode-helper-scripts/cntools.library b/scripts/cnode-helper-scripts/cntools.library index 6ed7bc484..2fc5e78bc 100644 --- a/scripts/cnode-helper-scripts/cntools.library +++ b/scripts/cnode-helper-scripts/cntools.library @@ -9,9 +9,9 @@ # Major: Any considerable change in the code base, big feature, workflow or breaking change from previous version CNTOOLS_MAJOR_VERSION=8 # Minor: Changes and features of minor character that can be applied without breaking existing functionality or workflow -CNTOOLS_MINOR_VERSION=1 +CNTOOLS_MINOR_VERSION=2 # Patch: Backwards compatible bug fixes. No additional functionality or major changes -CNTOOLS_PATCH_VERSION=6 +CNTOOLS_PATCH_VERSION=0 CNTOOLS_VERSION="${CNTOOLS_MAJOR_VERSION}.${CNTOOLS_MINOR_VERSION}.${CNTOOLS_PATCH_VERSION}" ############################################################ @@ -52,7 +52,7 @@ logln() { done } -# Command : println [log level] [message] +# Command : println [log level] [newline] [message] # Description : print and log(if enabled) message # Parameters : log level > log level (default: INFO) # OFF : logging disabled, output only to tty @@ -61,26 +61,45 @@ logln() { # INFO : normal output printed to tty and logged # ACTION : e.g cardano-cli executions etc, logged but not printed to tty # ERROR : stderr output and error messages +# : newline > Add a newline at the end for tty output (default true) # : message > The message to print/log println() { sleep 0.05 # hack, sleep 50ms before each print to preserve order of execution local log_level=$1 shift + local newline="\n" + if [[ $1 =~ true|false ]]; then + [[ $1 = false ]] && newline="" + shift + fi case $log_level in - OFF) printf '%b\n' "$@" >&6 ;; + OFF) printf "%b${newline}" "$@" >&6 ;; LOG) logln "DEBUG" "$@" ;; - DEBUG) printf '%b\n' "$@" >&6; logln "DEBUG" "$@" ;; - INFO) printf '%b\n' "$@" ;; + DEBUG) printf "%b${newline}" "$@" >&6; logln "DEBUG" "$@" ;; + INFO) printf "%b${newline}" "$@" ;; ACTION) logln "ACTION" "$@" ;; - ERROR) printf '%b\n' "$@" >&2 ;; - *) printf '%b\n' "${log_level}"; [[ $# -ge 1 ]] && printf '%s\n' "$@" ;; + ERROR) printf "%b${newline}" "$@" >&2 ;; + *) printf "%b${newline}" "${log_level}"; [[ $# -ge 1 ]] && printf "%b${newline}" "$@" ;; esac } -# Command : distanceToBottom [rows] -# Description : print blank rows and reset cursor position -createDistanceToBottom() { - printf "%0.s\n" $(seq $1) >&6; printf "\033[$1A" >&6 +# Command : getAnswerAnyCust [variable name] [log] [question] +# Description : wrapper function for getAnswerAny() in env to read input from stdin +# and save response into provided variable name while also logging response +# Parameters : variable name > the name of the variable to save users response into +# : log > [true|false] log question (default: true) +# : question > what to ask user to input +getAnswerAnyCust() { + sleep 0.1 # hack, sleep 100ms before asking question to preserve order + var_name=$1 + shift + local log_question=true + if [[ $1 =~ true|false ]]; then + [[ $1 = false ]] && log_question=false + shift + fi + getAnswerAny "${var_name}" "$*" >&6 + [[ ${log_question} = true ]] && println LOG "$*: ${!var_name}" } # Command : archiveLog @@ -96,56 +115,30 @@ archiveLog() { # Command : waitForInput [optional: message] # Description : wait for user keypress to continue -# Parameters : message > [optional]: override default 'press any key to return to home menu' message +# Parameters : message > [optional]: override default 'press any key to proceed ..' message waitForInput() { exec >&6 # normal stdout - createDistanceToBottom $(( $# + 1 )) - tput sc - ESC=$(printf "\033") - echo - if [[ $# -eq 0 ]]; then - echo "press any key to return to home menu" - else - printf '%b\n' "$@" - fi - read -rsn1 key # get 1 character - if [[ $key == $ESC ]]; then - read -rsn2 key # read 2 more chars - fi - tput rc && tput ed + waitToProceed "$*" exec >&8 # custom stdout } -# Command : need_cmd [command] -# Description : Check if command is available, else print error -# Parameters : command > The command to check -need_cmd() { - if ! command -v "$1" &>/dev/null; then - println "ERROR" "${FG_RED}ERROR${NC}: need '$1' (command not found)\ntry 'sudo apt install $1'\nplease install with your packet manager of choice(apt/yum etc..) and relaunch CNTools" - return 1 - fi -} - - # Command : protectionPreRequisites # Description : Check if needed protection prerequisites is available, else print error protectionPreRequisites() { - if ! need_cmd "gpg"; then - return 1 - fi + ! cmdAvailable "gpg" && return 1 - if ! need_cmd "chattr" &>/dev/null; then - [[ ${ENABLE_CHATTR} = true ]] && println "ERROR" "chattr command not available but enabled in config, please install or disable in cntools.config and re-run CNTools" && return 1 + if ! cmdAvailable "chattr" &>/dev/null; then + [[ ${ENABLE_CHATTR} = true ]] && println ERROR "chattr command not available but enabled in config, please install or disable in cntools.config and re-run CNTools" && return 1 elif [[ ${ENABLE_CHATTR} = true ]]; then # chattr available and enabled, make sure sudo access to chattr is enabled touch "${TMP_DIR}"/test - println "DEBUG" "Testing chattr access permission, enter user password if requested..." + println DEBUG "Testing chattr access permission, enter user password if requested..." if ! sudo chattr -i "${TMP_DIR}"/test; then rm -f "${TMP_DIR}"/test echo - println "ERROR" "${FG_YELLOW}WARN${NC}: Elevated privileges needed for chattr command used to write protect wallet and pool keys" - println "ERROR" "Add required sudo permissions or run the following command to add passwordless sudo access to chattr command for '$(whoami)' user" + println ERROR "${FG_YELLOW}WARN${NC}: Elevated privileges needed for chattr command used to write protect wallet and pool keys" + println ERROR "Add required sudo permissions or run the following command to add passwordless sudo access to chattr command for '$(whoami)' user" echo - println "ERROR" "echo \"$(whoami) ALL=NOPASSWD: $(command -v chattr)\" | sudo tee /etc/sudoers.d/cntools" + println ERROR "echo \"$(whoami) ALL=NOPASSWD: $(command -v chattr)\" | sudo tee /etc/sudoers.d/cntools" return 1 fi rm -f "${TMP_DIR}"/test @@ -163,7 +156,7 @@ safeDel() { if "${delcommand}" -rf "${path}"; then println "Deleted: ${path}" else - println "ERROR" "${FG_RED}ERROR${NC}: delete failed for ${path}" + println ERROR "${FG_RED}ERROR${NC}: delete failed for ${path}" return 1 fi return 0 @@ -235,16 +228,21 @@ dialogSetup() { # : title > The dialog title text # : verbosity > [optional] Start path when dialog is opened, either dir or file (default: ${TMP_DIR}/) fileDialog() { - exec >&6 2>&7 # normal stdout/stderr if [[ ${ENABLE_DIALOG} = "false" ]]; then - printf "$1: " && read -r file - return + getAnswerAnyCust file "$1" && return + else + println DEBUG false "${1}: " + waitForInput "Press any key to open the file explorer [cancel to skip!]" fi + exec >&6 2>&7 # normal stdout/stderr + sleep 0.1 dialogSetup [[ -n $2 ]] && start_path="$2" || start_path="${TMP_DIR}/" dialog --clear --keep-tite --title "$1" --fselect "${start_path}" $(($(tput lines)-14)) $(($(tput cols)-10)) 2>"${TMP_DIR}/dialog.out" file=$([[ -f "${TMP_DIR}/dialog.out" ]] && cat "${TMP_DIR}/dialog.out" || echo "") + tput cup $(( ${ROW#*[} -1 )) $(( ${COL} -1 )) exec >&8 2>&9 # custom stdout/stderr + println DEBUG "${FG_LGRAY}${file}${NC}" } # Command : dirDialog [title] [optional: start dir] # Description : open a directory dialog @@ -252,16 +250,21 @@ fileDialog() { # : title > The dialog title text # : verbosity > [optional] Start path when dialog is opened, either dir or file (default: ${TMP_DIR}/) dirDialog() { - exec >&6 2>&7 # normal stdout/stderr if [[ ${ENABLE_DIALOG} = "false" ]]; then - printf "$1: " && read -r dir - return + getAnswerAnyCust dir "$1" && return + else + println DEBUG false "${1}: " + waitForInput "Press any key to open the file explorer [cancel to skip!]" fi + exec >&6 2>&7 # normal stdout/stderr + sleep 0.1 dialogSetup [[ -n $2 ]] && start_path="$2" || start_path="${TMP_DIR}/" dialog --clear --keep-tite --title "$1" --dselect "${start_path}" $(($(tput lines)-14)) $(($(tput cols)-10)) 2>"${TMP_DIR}/dialog.out" dir=$([[ -f "${TMP_DIR}/dialog.out" ]] && cat "${TMP_DIR}/dialog.out" || echo "") + tput cup $(( ${ROW#*[} -1 )) $(( ${COL} -1 )) exec >&8 2>&9 # custom stdout/stderr + println DEBUG "${FG_LGRAY}${dir}${NC}" } @@ -368,7 +371,7 @@ select_opt() { local answer=$? exec >&8 # custom stdout selected_value="${opts[${answer}]}" - println "DEBUG" "Selected value: ${selected_value}" + println DEBUG "Selected value: ${selected_value}" return $answer } @@ -378,7 +381,7 @@ select_opt() { # Return : populates ${dirs} array getDirs() { if [[ ! -d "$1" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: Missing folder: $1" + println ERROR "${FG_RED}ERROR${NC}: Missing folder: $1" waitForInput && return 1 fi dirs=() @@ -402,7 +405,7 @@ selectDir() { dir_name=${dirs[$?]} [[ "${dir_name}" = "[Esc] Cancel" ]] && return 1 exec >&8 # custom stdout - println "DEBUG" "Selected ${type}: ${dir_name}" + println DEBUG "Selected ${type}: ${dir_name}" } # Command : selectWallet [mode] [file1 file2 ... | wallet_name1 wallet_name1 ... ] @@ -417,7 +420,7 @@ selectWallet() { if [[ ${CNTOOLS_MODE} = "CONNECTED" && ${mode} != "none" ]]; then tput sc wallet_count=${#dirs[@]} - [[ ${wallet_count} -le ${WALLET_SELECTION_FILTER_LIMIT} ]] && println "OFF" "Balance checking wallets..." + [[ ${wallet_count} -le ${WALLET_SELECTION_FILTER_LIMIT} ]] && println OFF "Balance checking wallets..." fi for dir in "${dirs[@]}"; do for arg in "$@"; do # check if wallet is missing a required file or name matches execution, if so hide it @@ -491,13 +494,13 @@ selectWallet() { if [[ ${CNTOOLS_MODE} = "CONNECTED" && ${mode} != "none" ]]; then tput rc && tput ed; fi if [[ ${#wallet_dirs[@]} -eq 0 ]]; then if [[ ${mode} = "balance" ]]; then - println "ERROR" "${FG_YELLOW}WARN${NC}: No wallets with funds available for selection! Required files:\n$(printf '%b\n' "$@")" + println ERROR "${FG_YELLOW}WARN${NC}: No wallets with funds available for selection! Required files:\n$(printf '%b\n' "$@")" elif [[ ${mode} = "delegate" ]]; then - println "ERROR" "${FG_YELLOW}WARN${NC}: No wallets available that can be delegated or used as pool pledge/owner/reward wallet! Required files:\n$(printf '%b\n' "$@")" + println ERROR "${FG_YELLOW}WARN${NC}: No wallets available that can be delegated or used as pool pledge/owner/reward wallet! Required files:\n$(printf '%b\n' "$@")" elif [[ ${mode} = "reward" ]]; then - println "ERROR" "${FG_YELLOW}WARN${NC}: No wallets available that have rewards to withdraw!" + println ERROR "${FG_YELLOW}WARN${NC}: No wallets available that have rewards to withdraw!" else - println "ERROR" "${FG_YELLOW}WARN${NC}: No wallets available for selection! Required files:\n$(printf '%b\n' "$@")" + println ERROR "${FG_YELLOW}WARN${NC}: No wallets available for selection! Required files:\n$(printf '%b\n' "$@")" fi return 1 fi @@ -536,11 +539,11 @@ selectPool() { pool_dirs+=("${dir}") done if [[ ${#pool_dirs[@]} -eq 0 ]]; then - println "ERROR" "${FG_YELLOW}WARN${NC}: No pools available that can be selected! Required files:\n$(printf '%b\n' "$@")" - [[ ${enc_req_files} -gt 0 ]] && println "DEBUG" "\n${FG_YELLOW}* Encrypted pools found but not listed *${NC}" + println ERROR "${FG_YELLOW}WARN${NC}: No pools available that can be selected! Required files:\n$(printf '%b\n' "$@")" + [[ ${enc_req_files} -gt 0 ]] && println DEBUG "\n${FG_YELLOW}* Encrypted pools found but not listed *${NC}" return 1 fi - [[ ${enc_req_files} -gt 0 ]] && println "DEBUG" "${FG_YELLOW}encrypted pools found but NOT listed, please decrypt to show${NC}" + [[ ${enc_req_files} -gt 0 ]] && println DEBUG "${FG_YELLOW}encrypted pools found but NOT listed, please decrypt to show${NC}" if ! selectDir "pool" "${pool_dirs[@]}"; then return 1; fi # ${dir_name} populated by selectDir function pool_name="$(echo ${dir_name} | cut -d' ' -f1)" } @@ -548,7 +551,7 @@ selectPool() { # Command : selectPolicy [mode] [file1 file2 ...] # Description : A helper function to select a Multi-Asset policy -# Parameters : fileX > array of files required to exist in pool folder for it to be selectable +# Parameters : fileX > array of files required to exist in policy folder for it to be selectable # Return : populates ${policy_name} variable with selected policy selectPolicy() { policy_dirs=() @@ -572,71 +575,27 @@ selectPolicy() { policy_dirs+=("${dir}") done if [[ ${#policy_dirs[@]} -eq 0 ]]; then - println "ERROR" "${FG_YELLOW}WARN${NC}: No policies available that can be selected! Required files:\n$(printf '%b\n' "$@")" - [[ ${enc_req_files} -gt 0 ]] && println "DEBUG" "\n${FG_YELLOW}* Encrypted policies found but not listed *${NC}" + println ERROR "${FG_YELLOW}WARN${NC}: No policies available that can be selected! Required files:\n$(printf '%b\n' "$@")" + [[ ${enc_req_files} -gt 0 ]] && println DEBUG "\n${FG_YELLOW}* Encrypted policies found but not listed *${NC}" return 1 fi - [[ ${enc_req_files} -gt 0 ]] && println "DEBUG" "${FG_YELLOW}encrypted policies found but NOT listed, please decrypt to show${NC}" + [[ ${enc_req_files} -gt 0 ]] && println DEBUG "${FG_YELLOW}encrypted policies found but NOT listed, please decrypt to show${NC}" if ! selectDir "policy" "${policy_dirs[@]}"; then return 1; fi # ${dir_name} populated by selectDir function policy_name="$(echo ${dir_name} | cut -d' ' -f1)" } - -# Command : getPassword [optional: confirm] +# Command : getPasswordCust [optional: confirm] # Description : Get password from user on STDIN # Parameters : confirm > [optional] force user to provide password twice for confirmation # Return : populates ${password} variable, make sure to unset variable when done -getPassword() { +getPasswordCust() { exec >&6 2>&7 # normal stdout/stderr sleep 0.1 - while true; do - readPassword "Enter password (length >= 8)" - password=${read_password} && unset read_password - if [ ${#password} -lt 8 ]; then - echo - echo -e "${FG_RED}ERROR${NC}: password length too short, please use a minimum of 8 characters." - echo - echo "Press q to abort or any other key to retry" - read -rsn 1 abort - [[ ${abort} = "q" ]] && unset password && exec >&8 2>&9 && return 1 - echo - continue - fi - if [[ "$1" = "confirm" ]]; then - echo && readPassword "Confirm password" - check_password=${read_password} && unset read_password - if [[ "${password}" != "${check_password}" ]]; then - echo - echo -e "${FG_RED}ERROR${NC}: password missmatch!" - echo - echo "Press q to abort or any other key to retry" - read -rsn 1 abort - [[ ${abort} = "q" ]] && unset password && unset check_password && exec >&8 2>&9 && return 1 - echo - else - echo && unset check_password && exec >&8 2>&9 && return - fi - else - echo && exec >&8 2>&9 && return - fi - done + getPassword 8 $1 + return_code=$? exec >&8 2>&9 # custom stdout/stderr + return ${return_code} } -readPassword() { - read_password="" - prompt="$1: " - while IFS= read -p "${prompt}" -r -s -n 1 char; do - if [[ ${char} == $'\0' ]]; then break; fi - if [[ ${char} == $'\b' ]]; then - [[ ${#read_password} -gt 0 ]] && printf "\033[1D\033[0K" && read_password=${read_password%?} - prompt='' - else - prompt='*' - read_password+="${char}" - fi - done -} - # Command : encryptFile [file] [password] # Description : Encrypt file with GPG @@ -648,11 +607,11 @@ encryptFile() { echo "${2}" | gpg --symmetric --yes --batch --cipher-algo AES256 --passphrase-fd 0 --output "${1}.gpg" "${1}" &>/dev/null && \ safeDel "${1}" >/dev/null || { exec >&8 2>&9 # custom stdout/stderr - println "ERROR" "${FG_RED}ERROR${NC}: failed to encrypt ${1}" + println ERROR "${FG_RED}ERROR${NC}: failed to encrypt ${1}" return 1 } exec >&8 2>&9 # custom stdout/stderr - println "DEBUG" "${1} successfully encrypted" + println DEBUG "${1} successfully encrypted" } @@ -666,11 +625,11 @@ decryptFile() { echo "${2}" | gpg --decrypt --batch --yes --passphrase-fd 0 --output "${1%.*}" "${1}" &>/dev/null && \ rm -f "${1}" || { exec >&8 2>&9 # custom stdout/stderr - println "ERROR" "${FG_RED}ERROR${NC}: failed to decrypt ${1}" + println ERROR "${FG_RED}ERROR${NC}: failed to decrypt ${1}" return 1 } exec >&8 2>&9 # custom stdout/stderr - println "DEBUG" "${1} successfully decrypted" + println DEBUG "${1} successfully decrypted" } # Command : unlockFile [file] @@ -699,7 +658,7 @@ lockFile() { # Return : expiration date can be accessed through variable ${expiration_date} after function has been executed kesExpiration() { if [[ -z "${1##*[!0-9]*}" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: KES start period must be an integer number [$1]" + println ERROR "${FG_RED}ERROR${NC}: KES start period must be an integer number [$1]" return 1 fi pool_kes_start_period=$1 @@ -716,8 +675,8 @@ kesExpiration() { # Parameters : silent > any argument to function will prevent DEBUG output to tty waitNewBlockCreated() { counter=${TIMEOUT_NO_OF_SLOTS} - [[ $# -eq 0 ]] && println "DEBUG" "Waiting for new block to be created (timeout = ${counter} slots, $(( counter * SLOT_LENGTH ))s)" - [[ $# -eq 0 ]] && println "DEBUG" "${FG_BLUE}INFO${NC}: press any key to cancel and return (won't stop transaction)" + [[ $# -eq 0 ]] && println DEBUG "Waiting for new block to be created (timeout = ${counter} slots, $(( counter * SLOT_LENGTH ))s)" + [[ $# -eq 0 ]] && println DEBUG "${FG_BLUE}INFO${NC}: press any key to cancel and return (won't stop transaction)" getNodeMetrics initialTip=${slotnum} actualTip=${slotnum} @@ -736,7 +695,7 @@ waitNewBlockCreated() { return 1 fi done - println "LOG" "New block was created - ${actualTip}" + println LOG "New block was created - ${actualTip}" } # Command : verifyTx [address] @@ -746,97 +705,14 @@ verifyTx() { if ! waitNewBlockCreated; then return 1; fi getBalance ${1} while [[ ${assets[lovelace]} -ne ${newBalance} ]]; do - println "DEBUG" "${FG_YELLOW}WARN${NC}: Balance mismatch, transaction not included in latest block... waiting for next block!" - println "LOG" "$(formatLovelace ${assets[lovelace]}) != $(formatLovelace ${newBalance})" + println DEBUG "${FG_YELLOW}WARN${NC}: Balance mismatch, transaction not included in latest block... waiting for next block!" + println LOG "$(formatLovelace ${assets[lovelace]}) != $(formatLovelace ${newBalance})" if ! waitNewBlockCreated "silent"; then return 1; fi getBalance ${1} done return 0 } -# Command : validateDecimalNbr [decimalNbr] -# Description : validate decimal number -# Parameters : decimalNbr > decimal number -validateDecimalNbr() { - re_decimal_nbr='^[0-9]+([.][0-9]+)?$' - if [[ $1 =~ ${re_decimal_nbr} ]]; then - return 0 - else - return 1 - fi -} - -# Command : formatLovelace -# Description : Pretty print Lovelace value -# Parameters : Lovelace > Amount in Lovelace -formatLovelace() { - if isNumber $1; then - [[ $1 -eq 0 ]] && echo 0 && return - [[ $1 -le 999999 ]] && printf '0.%06d' "$1" && return - printf '%s.%s' "$(sed ':a;s/\B[0-9]\{3\}\>/,&/;ta' <<< ${1::-6})" "${1: -6}" - else - println "ERROR" "${FG_RED}ERROR${NC}: must be a valid integer number" - return 1 - fi -} - -# Command : formatAsset -# Description : Pretty print Ada value -# Parameters : Ada > Amount in Ada -formatAsset() { - if isNumber $1; then - sed ':a;s/\B[0-9]\{3\}\>/,&/;ta' <<< $1 - else - println "ERROR" "${FG_RED}ERROR${NC}: must be a valid integer number" - return 1 - fi -} - -# Command : AdaToLovelace [Ada] -# Description : Convert number in Ada to Lovelace -# Parameters : Ada > Amount in Ada, decimal number accepted -AdaToLovelace() { - if validateDecimalNbr $1; then - echo "$1 * 1000000 / 1" | bc # /1 is to remove decimals from bc command - else - println "ERROR" "${FG_RED}ERROR${NC}: must be a valid integer or decimal number" - return 1 - fi -} - -# Command : pctToFraction [percent] -# Description : Convert number as percent to fraction -# Parameters : percent > number to be converted in range 0-100 -pctToFraction() { - if validateDecimalNbr $1; then - if [[ $(bc <<< "$1 >= 0" ) -eq 0 || $(bc <<< "$1 <= 100" ) -eq 0 ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: must be a number between 0-100" - return 1 - else - echo "x=$1 / 100; if(x<1) print 0; x" | bc -l | sed '/\./ s/\.\{0,1\}0\{1,\}$//' - fi - else - println "ERROR" "${FG_RED}ERROR${NC}: must be a valid integer or decimal number" - return 1 - fi -} - -# Command : fractionToPCT [fraction] -# Description : Convert fraction number to precent -# Parameters : fraction > number to be converted -fractionToPCT() { - if validateDecimalNbr $1; then - if (( $(bc <<<"$1 > 0") )); then - echo "x=$1 * 100; if(x<1) print 0; x" | bc -l | sed '/\./ s/\.\{0,1\}0\{1,\}$//' - else - echo 0 - fi - else - println "ERROR" "${FG_RED}ERROR${NC}: must be a valid decimal number" - return 1 - fi -} - # Command : getPoolID [pool name] # Description : create and save pool id in hex & bech32 encoded format # Parameters : pool name > the name of the pool @@ -849,8 +725,8 @@ getPoolID() { pool_id_bech32="" pool_coldkey_vk_file="${POOL_FOLDER}/${1}/${POOL_COLDKEY_VK_FILENAME}" if [[ -f ${pool_coldkey_vk_file} ]]; then - println "ACTION" "${CCLI} stake-pool id --cold-verification-key-file ${pool_coldkey_vk_file} --output-format hex" - println "ACTION" "${CCLI} stake-pool id --cold-verification-key-file ${pool_coldkey_vk_file}" + println ACTION "${CCLI} stake-pool id --cold-verification-key-file ${pool_coldkey_vk_file} --output-format hex" + println ACTION "${CCLI} stake-pool id --cold-verification-key-file ${pool_coldkey_vk_file}" if ! pool_id=$(${CCLI} stake-pool id --cold-verification-key-file "${pool_coldkey_vk_file}" --output-format hex 2>/dev/null) || \ ! pool_id_bech32=$(${CCLI} stake-pool id --cold-verification-key-file "${pool_coldkey_vk_file}" 2>/dev/null); then return 1 @@ -872,7 +748,7 @@ getPayAddress() { [[ -f ${payment_addr_file} ]] && pay_addr=$(cat "${payment_addr_file}") && return 0 pay_addr="" if [[ -f "${payment_vk_file}" ]]; then - println "ACTION" "${CCLI} address build --payment-verification-key-file ${payment_vk_file} --out-file ${payment_addr_file} ${HASH_IDENTIFIER}" + println ACTION "${CCLI} address build --payment-verification-key-file ${payment_vk_file} --out-file ${payment_addr_file} ${HASH_IDENTIFIER}" if ${CCLI} address build --payment-verification-key-file "${payment_vk_file}" --out-file "${payment_addr_file}" ${HASH_IDENTIFIER} 2>/dev/null; then pay_addr=$(cat "${payment_addr_file}") return 0 @@ -892,13 +768,13 @@ getBaseAddress() { [[ -f ${base_addr_file} ]] && base_addr=$(cat "${base_addr_file}") && return 0 base_addr="" if [[ -f "${payment_vk_file}" && -f "${stake_vk_file}" ]]; then - println "ACTION" "${CCLI} address build --payment-verification-key-file ${payment_vk_file} --stake-verification-key-file ${stake_vk_file} --out-file ${base_addr_file} ${HASH_IDENTIFIER}" + println ACTION "${CCLI} address build --payment-verification-key-file ${payment_vk_file} --stake-verification-key-file ${stake_vk_file} --out-file ${base_addr_file} ${HASH_IDENTIFIER}" if ${CCLI} address build --payment-verification-key-file "${payment_vk_file}" --stake-verification-key-file "${stake_vk_file}" --out-file "${base_addr_file}" ${HASH_IDENTIFIER} 2>/dev/null; then base_addr=$(cat "${base_addr_file}") return 0 fi elif [[ $# -eq 2 && -f "${1}" && -f "${2}" ]]; then - println "ACTION" "${CCLI} address build --payment-verification-key-file ${1} --stake-verification-key-file ${2} ${HASH_IDENTIFIER}" + println ACTION "${CCLI} address build --payment-verification-key-file ${1} --stake-verification-key-file ${2} ${HASH_IDENTIFIER}" base_addr=$(${CCLI} address build --payment-verification-key-file "${1}" --stake-verification-key-file "${2}" ${HASH_IDENTIFIER} 2>/dev/null) fi return 1 @@ -914,13 +790,13 @@ getRewardAddress() { [[ -f ${stake_addr_file} ]] && reward_addr=$(cat "${stake_addr_file}") && return 0 reward_addr="" if [[ -f "${stake_vk_file}" ]]; then - println "ACTION" "${CCLI} stake-address build --stake-verification-key-file ${stake_vk_file} --out-file ${stake_addr_file} ${HASH_IDENTIFIER}" + println ACTION "${CCLI} stake-address build --stake-verification-key-file ${stake_vk_file} --out-file ${stake_addr_file} ${HASH_IDENTIFIER}" if ${CCLI} stake-address build --stake-verification-key-file "${stake_vk_file}" --out-file "${stake_addr_file}" ${HASH_IDENTIFIER} 2>/dev/null; then reward_addr=$(cat "${stake_addr_file}") return 0 fi elif [[ -f "${1}" ]]; then - println "ACTION" "${CCLI} stake-address build --stake-verification-key-file ${1} ${HASH_IDENTIFIER}" + println ACTION "${CCLI} stake-address build --stake-verification-key-file ${1} ${HASH_IDENTIFIER}" reward_addr=$(${CCLI} stake-address build --stake-verification-key-file "${1}" ${HASH_IDENTIFIER} 2>/dev/null) fi return 1 @@ -931,7 +807,7 @@ getRewardAddress() { # Parameters : stake key > path to stake.vkey file # Return : populates ${reward_addr} getRewardAddressFromKey() { - println "ACTION" "${CCLI} stake-address build --stake-verification-key-file ${1} ${HASH_IDENTIFIER}" + println ACTION "${CCLI} stake-address build --stake-verification-key-file ${1} ${HASH_IDENTIFIER}" reward_addr=$(${CCLI} stake-address build --stake-verification-key-file "${1}" ${HASH_IDENTIFIER} 2>/dev/null) } @@ -940,7 +816,7 @@ getRewardAddressFromKey() { # Parameters : address > the wallet address to query # Return : populates ${address_info} getAddressInfo() { - println "ACTION" "${CCLI} address info --address $1" + println ACTION "${CCLI} address info --address $1" address_info=$(${CCLI} address info --address $1) } @@ -964,7 +840,7 @@ getBalance() { ((utxo_cnt++)) tx_in+=" --tx-in ${utxo_entry[0]}#${utxo_entry[1]}" utxos["${utxo_entry[0]}#${utxo_entry[1]}. Ada"]=${utxo_entry[2]} # Space added before 'Ada' for sort to place it first - assets["lovelace"]=$(( ${assets["lovelace"]:-0} + ${utxo_entry[2]} )) + assets["lovelace"]=$(( ${assets["lovelace"]:-0} + utxo_entry[2] )) if [[ ${#utxo_entry[@]} -gt 4 ]]; then idx=5 while [[ ${#utxo_entry[@]} -gt ${idx} ]]; do @@ -973,7 +849,8 @@ getBalance() { IFS='.' read -ra asset <<< "${asset_hash_name}" policyIDs["${asset[0]}"]=1 [[ ${#asset[@]} -eq 2 && ${#asset[1]} -gt ${asset_name_maxlen} ]] && asset_name_maxlen=${#asset[1]} - [[ ${#asset_amount} -gt ${asset_amount_maxlen} ]] && asset_amount_maxlen=${#asset_amount} + local asset_fmt="$(formatAsset ${asset_amount})" + [[ ${#asset_fmt} -gt ${asset_amount_maxlen} ]] && asset_amount_maxlen=${#asset_fmt} assets["${asset_hash_name}"]=$(( ${assets["${asset_hash_name}"]:-0} + asset_amount )) utxos["${utxo_entry[0]}#${utxo_entry[1]}.${asset_hash_name}"]=${asset_amount} idx=$(( idx + 3 )) @@ -1055,11 +932,14 @@ getMinUTxO() { [[ -z ${minUTxOValue} ]] && minUTxOValue=$(jq -r '.minUTxOValue //1000000' <<< "${PROT_PARAMS}") min_utxo_out=${minUTxOValue} - # chain constants - local coinSize=0 # will be changed to 2 in the next HFE - local pidSize=28 # current value, unchanged in the next era/HFE - local utxoEntrySizeWithoutVal=27 # 6 + txOutLenNoVal(14) + txInLen(7) - local adaOnlyUTxOSize=$(( utxoEntrySizeWithoutVal + coinSize )) + # chain constants, based on: https://hydra.iohk.io/build/5949624/download/1/shelley-ma.pdf + local k0=0 # coinSize=0 in mary-era, 2 in alonzo-era + local k1=6 + local k2=12 # assetSize=12 + local k3=28 # pidSize=28 + local k4=8 # word=8 bytes + local utxoEntrySizeWithoutVal=27 # 6 + txOutLenNoVal(14) + txInLen(7) + local adaOnlyUTxOSize=$((${utxoEntrySizeWithoutVal} + ${k0})) # split the tx-out string into the assets IFS='+' read -ra asset_entry <<< "${1}" @@ -1089,8 +969,8 @@ getMinUTxO() { done local sumAssetNameLengths=$(_len=0;for K in "${!nameCollector[@]}";do ((_len+=$(printf "%s" "$K" | wc -c)));done;echo ${_len}) - local roundupBytesToWords=$(bc <<< "scale=0; ( ${#assetsCollector[@]}*12 + ${sumAssetNameLengths} + ${#pidCollector[@]}*${pidSize} + 7 ) / 8") - local tokenBundleSize=$(( 6 + roundupBytesToWords )) + local roundupBytesToWords=$(bc <<< "scale=0; ( ${#assetsCollector[@]}*${k2} + ${sumAssetNameLengths} + ${#pidCollector[@]}*${k3} + (${k4}-1) ) / ${k4}") + local tokenBundleSize=$(( k1 + roundupBytesToWords )) local minAda=$(( $(bc <<< "scale=0; ${minUTxOValue} / ${adaOnlyUTxOSize}") * ( utxoEntrySizeWithoutVal + tokenBundleSize ) )) [[ ${minAda} -gt ${minUTxOValue} ]] && min_utxo_out=${minAda} fi @@ -1115,7 +995,7 @@ getRewards() { # Parameters : stake address > the address from stake.vkey # Return : populates ${reward_lovelace} getRewardsFromAddr() { - println "ACTION" "${CCLI} query stake-address-info ${NETWORK_IDENTIFIER} --address ${1}" + println ACTION "${CCLI} query stake-address-info ${NETWORK_IDENTIFIER} --address ${1}" stake_address_info=$(${CCLI} query stake-address-info ${NETWORK_IDENTIFIER} --address ${1}) reward_lovelace=0 for reward_entry in $(jq -r '.[] | @base64' <<< "${stake_address_info}"); do @@ -1129,7 +1009,7 @@ getRewardsFromAddr() { # Parameters : wallet name > the name of the wallet isWalletRegistered() { if getRewardAddress $1; then - println "ACTION" "${CCLI} query stake-address-info ${NETWORK_IDENTIFIER} --address ${reward_addr}" + println ACTION "${CCLI} query stake-address-info ${NETWORK_IDENTIFIER} --address ${reward_addr}" stake_address_info=$(${CCLI} query stake-address-info ${NETWORK_IDENTIFIER} --address ${reward_addr}) [[ -n "${stake_address_info}" && $(jq -r 'length' <<< ${stake_address_info}) -gt 0 ]] && return 0 fi @@ -1164,18 +1044,18 @@ getWalletType() { getTTL() { tip_ref=$(getSlotTipRef) if [[ ${op_mode} = "hybrid" ]]; then - println "DEBUG" "\nHow long do you want the transaction to be valid?" - sleep 0.1 && read -r -p "TTL (in seconds, default: 1800/30min): " ttl_enter 2>&6 && println "LOG" "TTL (in seconds, default: 1800/30min): ${ttl_enter}" + println DEBUG "\nHow long do you want the transaction to be valid?" + getAnswerAnyCust ttl_enter "TTL (in seconds, default: 1800/30min)" ttl_enter=${ttl_enter:-1800} if ! isNumber ${ttl_enter}; then - println "ERROR" "\n${FG_RED}ERROR${NC}: invalid TTL number, non digit characters found: ${ttl_enter}" + println ERROR "\n${FG_RED}ERROR${NC}: invalid TTL number, non digit characters found: ${ttl_enter}" return 1 fi ttl=$(( tip_ref + (ttl_enter/SLOT_LENGTH) )) else ttl=$(( tip_ref + (600/SLOT_LENGTH) )) # TTL default: 10min fi - println "LOG" "Current slot is ${tip_ref}, setting ttl to ${ttl}" + println LOG "Current slot is ${tip_ref}, setting ttl to ${ttl}" } # Command : buildOfflineJSON [type] @@ -1200,7 +1080,7 @@ registerStakeWallet() { wallet_source="base" if [[ -z $2 || $2 = "false" ]]; then - println "DEBUG" "Wallet ${FG_GREEN}${wallet_name}${NC} not registered on chain" + println DEBUG "Wallet ${FG_GREEN}${wallet_name}${NC} not registered on chain" waitForInput "press any key to continue with registration" fi @@ -1210,12 +1090,12 @@ registerStakeWallet() { getBaseAddress "${wallet_name}" getBalance ${base_addr} - println "ACTION" "${CCLI} stake-address registration-certificate --stake-verification-key-file ${stake_vk_file} --out-file ${stake_cert_file}" + println ACTION "${CCLI} stake-address registration-certificate --stake-verification-key-file ${stake_vk_file} --out-file ${stake_cert_file}" if ! ${CCLI} stake-address registration-certificate --stake-verification-key-file "${stake_vk_file}" --out-file "${stake_cert_file}"; then return 1; fi if ! getTTL; then return 1; fi stakeAddressDeposit=$(jq -r '.stakeAddressDeposit' <<< "${PROT_PARAMS}") - println "LOG" "Key Deposit is ${stakeAddressDeposit}" + println LOG "Key Deposit is ${stakeAddressDeposit}" getAssetsTxOut @@ -1228,7 +1108,7 @@ registerStakeWallet() { ${ERA_IDENTIFIER} --out-file "${TMP_DIR}"/tx0.tmp ) - println "ACTION" "${CCLI} transaction build-raw ${dummy_build_args[@]}" + println ACTION "${CCLI} transaction build-raw ${dummy_build_args[@]}" if ! ${CCLI} transaction build-raw "${dummy_build_args[@]}"; then return 1; fi min_fee_args=( @@ -1241,15 +1121,15 @@ registerStakeWallet() { --byron-witness-count 0 --protocol-params-file "${TMP_DIR}"/protparams.json ) - println "ACTION" "${CCLI} ${min_fee_args[*]}" + println ACTION "${CCLI} ${min_fee_args[*]}" min_fee=$([[ "$(${CCLI} ${min_fee_args[*]})" =~ ([0-9]+) ]] && echo ${BASH_REMATCH[1]}) - println "LOG" "fee is $(formatLovelace ${min_fee}) Ada" + println LOG "fee is $(formatLovelace ${min_fee}) Ada" newBalance=$(( ${assets[lovelace]} - min_fee - stakeAddressDeposit )) - println "LOG" "New balance after tx fee and key deposit is $(formatLovelace ${newBalance}) Ada ($(formatLovelace ${assets[lovelace]}) - $(formatLovelace ${min_fee}) - $(formatLovelace ${stakeAddressDeposit}))" + println LOG "New balance after tx fee and key deposit is $(formatLovelace ${newBalance}) Ada ($(formatLovelace ${assets[lovelace]}) - $(formatLovelace ${min_fee}) - $(formatLovelace ${stakeAddressDeposit}))" if [[ ${assets[lovelace]} -lt $(( min_fee + stakeAddressDeposit )) ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: Not enough Ada in base address for tx fee and key deposit!"\ + println ERROR "\n${FG_RED}ERROR${NC}: Not enough Ada in base address for tx fee and key deposit!"\ "Funds in address: ${FG_LBLUE}$(formatLovelace ${assets[lovelace]})${NC} Ada"\ "Minimum required: ${FG_LBLUE}$(formatLovelace $(( min_fee + stakeAddressDeposit )))${NC} Ada" return 1 @@ -1258,7 +1138,7 @@ registerStakeWallet() { tx_out="${base_addr}+${newBalance}${assets_tx_out}" getMinUTxO "${tx_out}" if [[ ${newBalance} -lt ${min_utxo_out} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, only ${FG_LBLUE}$(formatLovelace ${newBalance})${NC} Ada left in address after tx fee and key deposit, at least ${FG_LBLUE}$(formatLovelace ${min_utxo_out})${NC} Ada required!" + println ERROR "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, only ${FG_LBLUE}$(formatLovelace ${newBalance})${NC} Ada left in address after tx fee and key deposit, at least ${FG_LBLUE}$(formatLovelace ${min_utxo_out})${NC} Ada required!" return 1 fi @@ -1285,9 +1165,9 @@ registerStakeWallet() { jq -r . <<< "${offlineJSON}" > "${offline_tx}" echo println "Offline transaction successfully built and saved to: ${FG_LGRAY}${offline_tx}${NC}" - println "DEBUG" "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" - println "DEBUG" "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${payment_sk_file})${NC}" - println "DEBUG" "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${stake_sk_file})${NC}" + println DEBUG "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" + println DEBUG "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${payment_sk_file})${NC}" + println DEBUG "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${stake_sk_file})${NC}" return 2 # return as failed to stop main processing and return to home menu fi @@ -1307,13 +1187,13 @@ deregisterStakeWallet() { wallet_source="base" stake_dereg_file="${WALLET_FOLDER}/${wallet_name}/${WALLET_STAKE_DEREG_FILENAME}" - println "ACTION" "${CCLI} stake-address deregistration-certificate --stake-verification-key-file ${stake_vk_file} --out-file ${stake_dereg_file}" + println ACTION "${CCLI} stake-address deregistration-certificate --stake-verification-key-file ${stake_vk_file} --out-file ${stake_dereg_file}" if ! ${CCLI} stake-address deregistration-certificate --stake-verification-key-file "${stake_vk_file}" --out-file "${stake_dereg_file}"; then return 1; fi if ! getTTL; then return 1; fi stakeAddressDeposit=$(jq -r '.stakeAddressDeposit' <<< "${PROT_PARAMS}") - println "LOG" "Key Deposit is ${stakeAddressDeposit}" + println LOG "Key Deposit is ${stakeAddressDeposit}" getAssetsTxOut @@ -1326,7 +1206,7 @@ deregisterStakeWallet() { ${ERA_IDENTIFIER} --out-file "${TMP_DIR}"/tx0.tmp ) - println "ACTION" "${CCLI} transaction build-raw ${dummy_build_args[@]}" + println ACTION "${CCLI} transaction build-raw ${dummy_build_args[@]}" if ! ${CCLI} transaction build-raw "${dummy_build_args[@]}"; then return 1; fi min_fee_args=( @@ -1339,15 +1219,15 @@ deregisterStakeWallet() { --byron-witness-count 0 --protocol-params-file "${TMP_DIR}"/protparams.json ) - println "ACTION" "${CCLI} ${min_fee_args[*]}" + println ACTION "${CCLI} ${min_fee_args[*]}" min_fee=$([[ "$(${CCLI} ${min_fee_args[*]})" =~ ([0-9]+) ]] && echo ${BASH_REMATCH[1]}) - println "LOG" "fee is $(formatLovelace ${min_fee}) Ada" + println LOG "fee is $(formatLovelace ${min_fee}) Ada" newBalance=$(( ${assets[lovelace]} + stakeAddressDeposit - min_fee )) - println "LOG" "New balance after returned key deposit and subtracted tx fee is $(formatLovelace ${newBalance}) Ada ($(formatLovelace ${assets[lovelace]}) + $(formatLovelace ${stakeAddressDeposit}) - $(formatLovelace ${min_fee}))" + println LOG "New balance after returned key deposit and subtracted tx fee is $(formatLovelace ${newBalance}) Ada ($(formatLovelace ${assets[lovelace]}) + $(formatLovelace ${stakeAddressDeposit}) - $(formatLovelace ${min_fee}))" if [[ $(( ${assets[lovelace]} + stakeAddressDeposit )) -lt ${min_fee} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: Not enough Ada in base address for tx fee!"\ + println ERROR "\n${FG_RED}ERROR${NC}: Not enough Ada in base address for tx fee!"\ "Funds in address: ${FG_LBLUE}$(formatLovelace ${assets[lovelace]})${NC} Ada"\ "Minimum required: ${FG_LBLUE}$(formatLovelace $(( min_fee - stakeAddressDeposit )))${NC} Ada" return 1 @@ -1356,7 +1236,7 @@ deregisterStakeWallet() { tx_out="${base_addr}+${newBalance}${assets_tx_out}" getMinUTxO "${tx_out}" if [[ ${newBalance} -lt ${min_utxo_out} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, only ${FG_LBLUE}$(formatLovelace ${newBalance})${NC} Ada left in address after tx fee and returned key deposit, at least ${FG_LBLUE}$(formatLovelace ${min_utxo_out})${NC} Ada required!" + println ERROR "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, only ${FG_LBLUE}$(formatLovelace ${newBalance})${NC} Ada left in address after tx fee and returned key deposit, at least ${FG_LBLUE}$(formatLovelace ${min_utxo_out})${NC} Ada required!" return 1 fi @@ -1384,9 +1264,9 @@ deregisterStakeWallet() { jq -r . <<< "${offlineJSON}" > "${offline_tx}" echo println "Offline transaction successfully built and saved to: ${FG_LGRAY}${offline_tx}${NC}" - println "DEBUG" "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" - println "DEBUG" "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${payment_sk_file})${NC}" - println "DEBUG" "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${stake_sk_file})${NC}" + println DEBUG "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" + println DEBUG "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${payment_sk_file})${NC}" + println DEBUG "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${stake_sk_file})${NC}" return 2 # return as failed to stop main processing and return to home menu fi @@ -1431,7 +1311,7 @@ sendAssets() { else dummy_build_args+=( --tx-out "${s_addr}+0${assets_tx_out_s}" --tx-out "${d_addr}+0${assets_tx_out_d}" ) fi - println "ACTION" "${CCLI} transaction build-raw ${dummy_build_args[*]}" + println ACTION "${CCLI} transaction build-raw ${dummy_build_args[*]}" if ! ${CCLI} transaction build-raw "${dummy_build_args[@]}"; then return 1; fi min_fee_args=( @@ -1444,9 +1324,9 @@ sendAssets() { --byron-witness-count 0 --protocol-params-file "${TMP_DIR}"/protparams.json ) - println "ACTION" "${CCLI} ${min_fee_args[*]}" + println ACTION "${CCLI} ${min_fee_args[*]}" min_fee=$([[ "$(${CCLI} ${min_fee_args[*]})" =~ ([0-9]+) ]] && echo ${BASH_REMATCH[1]}) - println "LOG" "fee is $(formatLovelace ${min_fee}) Ada" + println LOG "fee is $(formatLovelace ${min_fee}) Ada" build_args=( ${tx_in} @@ -1460,8 +1340,8 @@ sendAssets() { tx_out="${d_addr}+$(( ${assets_to_send[lovelace]} - min_fee ))${assets_tx_out_d}" getMinUTxO "${tx_out}" if [[ ${assets_to_send[lovelace]} -lt ${min_utxo_out} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: Not enough Ada in address ( $(formatLovelace ${assets_to_send[lovelace]}) < $(formatLovelace ${min_utxo_out}) )" - println "ERROR" "Top up wallet with enough Ada to cover minimum UTxO balance" + println ERROR "\n${FG_RED}ERROR${NC}: Not enough Ada in address ( $(formatLovelace ${assets_to_send[lovelace]}) < $(formatLovelace ${min_utxo_out}) )" + println ERROR "Top up wallet with enough Ada to cover minimum UTxO balance" return 1 fi build_args+=( --tx-out "${tx_out}" ) @@ -1483,11 +1363,11 @@ sendAssets() { build_args+=( --tx-out "${tx_out_s}" ) if [[ ${newBalance} -lt ${min_utxo_out_s} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: Not enough Ada left in source address ( $(formatLovelace ${newBalance}) < $(formatLovelace ${min_utxo_out_s}) )" - println "ERROR" "Send all Ada or top up wallet with enough Ada to cover minimum UTxO balance" + println ERROR "\n${FG_RED}ERROR${NC}: Not enough Ada left in source address ( $(formatLovelace ${newBalance}) < $(formatLovelace ${min_utxo_out_s}) )" + println ERROR "Send all Ada or top up wallet with enough Ada to cover minimum UTxO balance" return 1 elif [[ ${assets_to_send[lovelace]} -lt ${min_utxo_out_d} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, requires ${FG_LBLUE}$(formatLovelace ${min_utxo_out_d})${NC} Ada to be sent along!" + println ERROR "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, requires ${FG_LBLUE}$(formatLovelace ${min_utxo_out_d})${NC} Ada to be sent along!" return 1 fi fi @@ -1512,8 +1392,8 @@ sendAssets() { jq -r . <<< "${offlineJSON}" > "${offline_tx}" echo println "Offline transaction successfully built and saved to: ${FG_LGRAY}${offline_tx}${NC}" - println "DEBUG" "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" - println "DEBUG" "Source Wallet ${FG_GREEN}${s_wallet} ${FG_LGRAY}$(basename ${s_payment_sk_file})${NC}" + println DEBUG "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" + println DEBUG "Source Wallet ${FG_GREEN}${s_wallet} ${FG_LGRAY}$(basename ${s_payment_sk_file})${NC}" return 2 # return as failed to stop main processing and return to home menu fi @@ -1540,7 +1420,7 @@ delegate() { ${ERA_IDENTIFIER} --out-file "${TMP_DIR}"/tx0.tmp ) - println "ACTION" "${CCLI} transaction build-raw ${dummy_build_args[@]}" + println ACTION "${CCLI} transaction build-raw ${dummy_build_args[@]}" if ! ${CCLI} transaction build-raw "${dummy_build_args[@]}"; then return 1; fi min_fee_args=( @@ -1553,15 +1433,15 @@ delegate() { --byron-witness-count 0 --protocol-params-file "${TMP_DIR}"/protparams.json ) - println "ACTION" "${CCLI} ${min_fee_args[*]}" + println ACTION "${CCLI} ${min_fee_args[*]}" min_fee=$([[ "$(${CCLI} ${min_fee_args[*]})" =~ ([0-9]+) ]] && echo ${BASH_REMATCH[1]}) - println "LOG" "fee is $(formatLovelace ${min_fee}) Ada" + println LOG "fee is $(formatLovelace ${min_fee}) Ada" newBalance=$(( ${assets[lovelace]} - min_fee )) - println "LOG" "Balance left to be returned in used UTxO is $(formatLovelace ${newBalance}) Ada ( $(formatLovelace ${assets[lovelace]}) - $(formatLovelace ${min_fee}) )" + println LOG "Balance left to be returned in used UTxO is $(formatLovelace ${newBalance}) Ada ( $(formatLovelace ${assets[lovelace]}) - $(formatLovelace ${min_fee}) )" if [[ ${assets[lovelace]} -lt ${min_fee} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: Not enough Ada in base address for tx fee!"\ + println ERROR "\n${FG_RED}ERROR${NC}: Not enough Ada in base address for tx fee!"\ "Funds in address: ${FG_LBLUE}$(formatLovelace ${assets[lovelace]})${NC} Ada"\ "Minimum required: ${FG_LBLUE}$(formatLovelace ${min_fee})${NC} Ada" return 1 @@ -1570,7 +1450,7 @@ delegate() { tx_out="${base_addr}+${newBalance}${assets_tx_out}" getMinUTxO "${tx_out}" if [[ ${newBalance} -lt ${min_utxo_out} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, only ${FG_LBLUE}$(formatLovelace ${newBalance})${NC} Ada left in address after tx fee, at least ${FG_LBLUE}$(formatLovelace ${min_utxo_out})${NC} Ada required!" + println ERROR "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, only ${FG_LBLUE}$(formatLovelace ${newBalance})${NC} Ada left in address after tx fee, at least ${FG_LBLUE}$(formatLovelace ${min_utxo_out})${NC} Ada required!" return 1 fi @@ -1597,9 +1477,9 @@ delegate() { jq -r . <<< "${offlineJSON}" > "${offline_tx}" echo println "Offline transaction successfully built and saved to: ${FG_LGRAY}${offline_tx}${NC}" - println "DEBUG" "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" - println "DEBUG" "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${payment_sk_file})${NC}" - println "DEBUG" "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${stake_sk_file})${NC}" + println DEBUG "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" + println DEBUG "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${payment_sk_file})${NC}" + println DEBUG "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${stake_sk_file})${NC}" return 2 # return as failed to stop main processing and return to home menu fi @@ -1625,7 +1505,7 @@ withdrawRewards() { ${ERA_IDENTIFIER} --out-file "${TMP_DIR}"/tx0.tmp ) - println "ACTION" "${CCLI} transaction build-raw ${dummy_build_args[@]}" + println ACTION "${CCLI} transaction build-raw ${dummy_build_args[@]}" if ! ${CCLI} transaction build-raw "${dummy_build_args[@]}"; then return 1; fi min_fee_args=( @@ -1638,15 +1518,15 @@ withdrawRewards() { --byron-witness-count 0 --protocol-params-file "${TMP_DIR}"/protparams.json ) - println "ACTION" "${CCLI} ${min_fee_args[*]}" + println ACTION "${CCLI} ${min_fee_args[*]}" min_fee=$([[ "$(${CCLI} ${min_fee_args[*]})" =~ ([0-9]+) ]] && echo ${BASH_REMATCH[1]}) - println "LOG" "fee is $(formatLovelace ${min_fee}) Ada" + println LOG "fee is $(formatLovelace ${min_fee}) Ada" newBalance=$(( ${assets[lovelace]} - min_fee + reward_lovelace )) - println "LOG" "Balance left to be returned in used UTxO is $(formatLovelace ${newBalance}) Ada ( $(formatLovelace ${assets[lovelace]}) - $(formatLovelace ${min_fee}) )" + println LOG "Balance left to be returned in used UTxO is $(formatLovelace ${newBalance}) Ada ( $(formatLovelace ${assets[lovelace]}) - $(formatLovelace ${min_fee}) )" if [[ ${assets[lovelace]} -lt ${min_fee} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: Not enough Ada in base address for tx fee!"\ + println ERROR "\n${FG_RED}ERROR${NC}: Not enough Ada in base address for tx fee!"\ "Funds in address: ${FG_LBLUE}$(formatLovelace ${assets[lovelace]})${NC} Ada"\ "Minimum required: ${FG_LBLUE}$(formatLovelace $((min_fee - reward_lovelace)))${NC} Ada" return 1 @@ -1655,7 +1535,7 @@ withdrawRewards() { tx_out="${base_addr}+${newBalance}${assets_tx_out}" getMinUTxO "${tx_out}" if [[ ${newBalance} -lt ${min_utxo_out} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, only ${FG_LBLUE}$(formatLovelace ${newBalance})${NC} Ada left in address after tx fee and withdrawal, at least ${FG_LBLUE}$(formatLovelace ${min_utxo_out})${NC} Ada required!" + println ERROR "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, only ${FG_LBLUE}$(formatLovelace ${newBalance})${NC} Ada left in address after tx fee and withdrawal, at least ${FG_LBLUE}$(formatLovelace ${min_utxo_out})${NC} Ada required!" return 1 fi @@ -1683,9 +1563,9 @@ withdrawRewards() { jq -r . <<< "${offlineJSON}" > "${offline_tx}" echo println "Offline transaction successfully built and saved to: ${FG_LGRAY}${offline_tx}${NC}" - println "DEBUG" "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" - println "DEBUG" "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${payment_sk_file})${NC}" - println "DEBUG" "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${stake_sk_file})${NC}" + println DEBUG "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" + println DEBUG "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${payment_sk_file})${NC}" + println DEBUG "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${stake_sk_file})${NC}" return 2 # return as failed to stop main processing and return to home menu fi @@ -1703,7 +1583,7 @@ registerPool() { if ! getTTL; then return 1; fi stakePoolDeposit=$(jq -r '.stakePoolDeposit' <<< "${PROT_PARAMS}") - println "LOG" "Pool Deposit is ${stakePoolDeposit}" + println LOG "Pool Deposit is ${stakePoolDeposit}" owner_delegation_cert="" [[ ${delegate_owner_wallet} = 'Y' ]] && owner_delegation_cert="--certificate-file ${owner_delegation_cert_file}" @@ -1741,7 +1621,7 @@ registerPool() { ) [[ -n ${owner_delegation_cert} ]] && dummy_build_args+=( --certificate-file "${owner_delegation_cert}" ) [[ -n ${reward_delegation_cert} ]] && dummy_build_args+=( --certificate-file "${reward_delegation_cert}" ) - println "ACTION" "${CCLI} transaction build-raw ${dummy_build_args[@]}" + println ACTION "${CCLI} transaction build-raw ${dummy_build_args[@]}" if ! ${CCLI} transaction build-raw "${dummy_build_args[@]}"; then return 1; fi min_fee_args=( @@ -1754,15 +1634,15 @@ registerPool() { --byron-witness-count 0 --protocol-params-file "${TMP_DIR}"/protparams.json ) - println "ACTION" "${CCLI} ${min_fee_args[*]}" + println ACTION "${CCLI} ${min_fee_args[*]}" min_fee=$([[ "$(${CCLI} ${min_fee_args[*]})" =~ ([0-9]+) ]] && echo ${BASH_REMATCH[1]}) - println "LOG" "fee is $(formatLovelace ${min_fee}) Ada" + println LOG "fee is $(formatLovelace ${min_fee}) Ada" newBalance=$(( ${assets[lovelace]} - min_fee - stakePoolDeposit )) - println "LOG" "Balance left to be returned in used UTxO is $(formatLovelace ${newBalance}) Ada ( $(formatLovelace ${assets[lovelace]}) - $(formatLovelace ${min_fee}) - $(formatLovelace ${stakePoolDeposit}) )" + println LOG "Balance left to be returned in used UTxO is $(formatLovelace ${newBalance}) Ada ( $(formatLovelace ${assets[lovelace]}) - $(formatLovelace ${min_fee}) - $(formatLovelace ${stakePoolDeposit}) )" if [[ ${assets[lovelace]} -lt $(( min_fee + stakePoolDeposit )) ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: Not enough Ada in base address for tx fee and pool registration deposit!"\ + println ERROR "\n${FG_RED}ERROR${NC}: Not enough Ada in base address for tx fee and pool registration deposit!"\ "Funds in address: ${FG_LBLUE}$(formatLovelace ${assets[lovelace]})${NC} Ada"\ "Minimum required: ${FG_LBLUE}$(formatLovelace $(( min_fee + stakePoolDeposit )))${NC} Ada" return 1 @@ -1771,7 +1651,7 @@ registerPool() { tx_out="${base_addr}+${newBalance}${assets_tx_out}" getMinUTxO "${tx_out}" if [[ ${newBalance} -lt ${min_utxo_out} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, only ${FG_LBLUE}$(formatLovelace ${newBalance})${NC} Ada left in address after tx fee and pool registration deposit, at least ${FG_LBLUE}$(formatLovelace ${min_utxo_out})${NC} Ada required!" + println ERROR "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, only ${FG_LBLUE}$(formatLovelace ${newBalance})${NC} Ada left in address after tx fee and pool registration deposit, at least ${FG_LBLUE}$(formatLovelace ${min_utxo_out})${NC} Ada required!" return 1 fi @@ -1813,14 +1693,14 @@ registerPool() { jq -r . <<< "${offlineJSON}" > "${offline_tx}" echo println "Offline transaction successfully built and saved to: ${FG_LGRAY}${offline_tx}${NC}" - println "DEBUG" "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" - println "DEBUG" "Pool ${FG_GREEN}${pool_name} ${FG_LGRAY}${POOL_COLDKEY_SK_FILENAME}${NC}" - println "DEBUG" "Owner #1 ${FG_GREEN}${owner_wallets[0]} ${FG_LGRAY}${WALLET_PAY_SK_FILENAME}${NC} & ${FG_LGRAY}${WALLET_STAKE_SK_FILENAME}${NC}" + println DEBUG "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" + println DEBUG "Pool ${FG_GREEN}${pool_name} ${FG_LGRAY}${POOL_COLDKEY_SK_FILENAME}${NC}" + println DEBUG "Owner #1 ${FG_GREEN}${owner_wallets[0]} ${FG_LGRAY}${WALLET_PAY_SK_FILENAME}${NC} & ${FG_LGRAY}${WALLET_STAKE_SK_FILENAME}${NC}" for index in "${!owner_wallets[@]}"; do [[ ${index} -eq 0 ]] && continue # skip main owner - println "DEBUG" "Owner #$((index+1)) ${FG_GREEN}${owner_wallets[${index}]} ${FG_LGRAY}${WALLET_STAKE_SK_FILENAME}${NC}" + println DEBUG "Owner #$((index+1)) ${FG_GREEN}${owner_wallets[${index}]} ${FG_LGRAY}${WALLET_STAKE_SK_FILENAME}${NC}" done - [[ delegate_reward_wallet = 'Y' ]] && println "DEBUG" "Reward wallet ${FG_GREEN}${reward_wallet} ${FG_LGRAY}$(basename ${reward_stake_sk_file})${NC}" + [[ delegate_reward_wallet = 'Y' ]] && println DEBUG "Reward wallet ${FG_GREEN}${reward_wallet} ${FG_LGRAY}$(basename ${reward_stake_sk_file})${NC}" return 2 # return as failed to stop main processing and return to home menu fi @@ -1860,7 +1740,7 @@ modifyPool() { ${ERA_IDENTIFIER} --out-file "${TMP_DIR}"/tx0.tmp ) - println "ACTION" "${CCLI} transaction build-raw ${dummy_build_args[@]}" + println ACTION "${CCLI} transaction build-raw ${dummy_build_args[@]}" if ! ${CCLI} transaction build-raw "${dummy_build_args[@]}"; then return 1; fi min_fee_args=( @@ -1873,15 +1753,15 @@ modifyPool() { --byron-witness-count 0 --protocol-params-file "${TMP_DIR}"/protparams.json ) - println "ACTION" "${CCLI} ${min_fee_args[*]}" + println ACTION "${CCLI} ${min_fee_args[*]}" min_fee=$([[ "$(${CCLI} ${min_fee_args[*]})" =~ ([0-9]+) ]] && echo ${BASH_REMATCH[1]}) - println "LOG" "fee is $(formatLovelace ${min_fee}) Ada" + println LOG "fee is $(formatLovelace ${min_fee}) Ada" newBalance=$(( ${assets[lovelace]} - min_fee )) - println "LOG" "Balance left to be returned in used UTxO is $(formatLovelace ${newBalance}) Ada ( $(formatLovelace ${assets[lovelace]}) - $(formatLovelace ${min_fee}) )" + println LOG "Balance left to be returned in used UTxO is $(formatLovelace ${newBalance}) Ada ( $(formatLovelace ${assets[lovelace]}) - $(formatLovelace ${min_fee}) )" if [[ ${assets[lovelace]} -lt ${min_fee} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: Not enough Ada in base address for tx fee!"\ + println ERROR "\n${FG_RED}ERROR${NC}: Not enough Ada in base address for tx fee!"\ "Funds in address: ${FG_LBLUE}$(formatLovelace ${assets[lovelace]})${NC} Ada"\ "Minimum required: ${FG_LBLUE}$(formatLovelace ${min_fee})${NC} Ada" return 1 @@ -1890,7 +1770,7 @@ modifyPool() { tx_out="${base_addr}+${newBalance}${assets_tx_out}" getMinUTxO "${tx_out}" if [[ ${newBalance} -lt ${min_utxo_out} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, only ${FG_LBLUE}$(formatLovelace ${newBalance})${NC} Ada left in address after tx fee, at least ${FG_LBLUE}$(formatLovelace ${min_utxo_out})${NC} Ada required!" + println ERROR "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, only ${FG_LBLUE}$(formatLovelace ${newBalance})${NC} Ada left in address after tx fee, at least ${FG_LBLUE}$(formatLovelace ${min_utxo_out})${NC} Ada required!" return 1 fi @@ -1929,12 +1809,12 @@ modifyPool() { jq -r . <<< "${offlineJSON}" > "${offline_tx}" echo println "Offline transaction successfully built and saved to: ${FG_LGRAY}${offline_tx}${NC}" - println "DEBUG" "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" - println "DEBUG" "Pool ${FG_GREEN}${pool_name} ${FG_LGRAY}${POOL_COLDKEY_SK_FILENAME}${NC}" - println "DEBUG" "Owner #1 ${FG_GREEN}${owner_wallets[0]} ${FG_LGRAY}${WALLET_PAY_SK_FILENAME}${NC} & ${FG_LGRAY}${WALLET_STAKE_SK_FILENAME}${NC}" + println DEBUG "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" + println DEBUG "Pool ${FG_GREEN}${pool_name} ${FG_LGRAY}${POOL_COLDKEY_SK_FILENAME}${NC}" + println DEBUG "Owner #1 ${FG_GREEN}${owner_wallets[0]} ${FG_LGRAY}${WALLET_PAY_SK_FILENAME}${NC} & ${FG_LGRAY}${WALLET_STAKE_SK_FILENAME}${NC}" for index in "${!owner_wallets[@]}"; do [[ ${index} -eq 0 ]] && continue # skip main owner - println "DEBUG" "Owner #$((index+1)) ${FG_GREEN}${owner_wallets[${index}]} ${FG_LGRAY}${WALLET_STAKE_SK_FILENAME}${NC}" + println DEBUG "Owner #$((index+1)) ${FG_GREEN}${owner_wallets[${index}]} ${FG_LGRAY}${WALLET_STAKE_SK_FILENAME}${NC}" done return 2 # return as failed to stop main processing and return to home menu fi @@ -1971,7 +1851,7 @@ deRegisterPool() { ${ERA_IDENTIFIER} --out-file "${TMP_DIR}"/tx0.tmp ) - println "ACTION" "${CCLI} transaction build-raw ${dummy_build_args[@]}" + println ACTION "${CCLI} transaction build-raw ${dummy_build_args[@]}" if ! ${CCLI} transaction build-raw "${dummy_build_args[@]}"; then return 1; fi min_fee_args=( @@ -1984,15 +1864,15 @@ deRegisterPool() { --byron-witness-count 0 --protocol-params-file "${TMP_DIR}"/protparams.json ) - println "ACTION" "${CCLI} ${min_fee_args[*]}" + println ACTION "${CCLI} ${min_fee_args[*]}" min_fee=$([[ "$(${CCLI} ${min_fee_args[*]})" =~ ([0-9]+) ]] && echo ${BASH_REMATCH[1]}) - println "LOG" "fee is $(formatLovelace ${min_fee}) Ada" + println LOG "fee is $(formatLovelace ${min_fee}) Ada" newBalance=$(( ${assets[lovelace]} - min_fee )) - println "LOG" "Balance left to be returned in used UTxO is $(formatLovelace ${newBalance}) Ada ( $(formatLovelace ${assets[lovelace]}) - $(formatLovelace ${min_fee}) )" + println LOG "Balance left to be returned in used UTxO is $(formatLovelace ${newBalance}) Ada ( $(formatLovelace ${assets[lovelace]}) - $(formatLovelace ${min_fee}) )" if [[ ${assets[lovelace]} -lt ${min_fee} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: Not enough Ada in ${wallet_source} address for tx fee!"\ + println ERROR "\n${FG_RED}ERROR${NC}: Not enough Ada in ${wallet_source} address for tx fee!"\ "Funds in address: ${FG_LBLUE}$(formatLovelace ${assets[lovelace]})${NC} Ada"\ "Minimum required: ${FG_LBLUE}$(formatLovelace ${min_fee})${NC} Ada" return 1 @@ -2001,7 +1881,7 @@ deRegisterPool() { tx_out="${addr}+${newBalance}${assets_tx_out}" getMinUTxO "${tx_out}" if [[ ${newBalance} -lt ${min_utxo_out} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, only ${FG_LBLUE}$(formatLovelace ${newBalance})${NC} Ada left in address after tx fee, at least ${FG_LBLUE}$(formatLovelace ${min_utxo_out})${NC} Ada required!" + println ERROR "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, only ${FG_LBLUE}$(formatLovelace ${newBalance})${NC} Ada left in address after tx fee, at least ${FG_LBLUE}$(formatLovelace ${min_utxo_out})${NC} Ada required!" return 1 fi @@ -2036,9 +1916,9 @@ deRegisterPool() { jq -r . <<< "${offlineJSON}" > "${offline_tx}" echo println "Offline transaction successfully built and saved to: ${FG_LGRAY}${offline_tx}${NC}" - println "DEBUG" "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" - println "DEBUG" "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${payment_sk_file})${NC}" - println "DEBUG" "Pool ${FG_GREEN}${pool_name} ${FG_LGRAY}$(basename ${pool_coldkey_sk_file})${NC}" + println DEBUG "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" + println DEBUG "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${payment_sk_file})${NC}" + println DEBUG "Pool ${FG_GREEN}${pool_name} ${FG_LGRAY}$(basename ${pool_coldkey_sk_file})${NC}" return 2 # return as failed to stop main processing and return to home menu fi @@ -2063,9 +1943,9 @@ rotatePoolKeys() { current_kes_period=$(getCurrentKESperiod) echo "${current_kes_period}" > ${pool_saved_kes_start} - println "ACTION" "${CCLI} node key-gen-KES --verification-key-file ${pool_hotkey_vk_file} --signing-key-file ${pool_hotkey_sk_file}" + println ACTION "${CCLI} node key-gen-KES --verification-key-file ${pool_hotkey_vk_file} --signing-key-file ${pool_hotkey_sk_file}" if ! ${CCLI} node key-gen-KES --verification-key-file "${pool_hotkey_vk_file}" --signing-key-file "${pool_hotkey_sk_file}"; then return 1; fi - println "ACTION" "${CCLI} node issue-op-cert --kes-verification-key-file ${pool_hotkey_vk_file} --cold-signing-key-file ${pool_coldkey_sk_file} --operational-certificate-issue-counter-file ${pool_opcert_counter_file} --kes-period ${current_kes_period} --out-file ${pool_opcert_file}" + println ACTION "${CCLI} node issue-op-cert --kes-verification-key-file ${pool_hotkey_vk_file} --cold-signing-key-file ${pool_coldkey_sk_file} --operational-certificate-issue-counter-file ${pool_opcert_counter_file} --kes-period ${current_kes_period} --out-file ${pool_opcert_file}" if ! ${CCLI} node issue-op-cert --kes-verification-key-file "${pool_hotkey_vk_file}" --cold-signing-key-file "${pool_coldkey_sk_file}" --operational-certificate-issue-counter-file "${pool_opcert_counter_file}" --kes-period "${current_kes_period}" --out-file "${pool_opcert_file}"; then return 1; fi chmod 700 ${POOL_FOLDER}/${pool_name}/* @@ -2085,7 +1965,7 @@ sendMetadata() { elif [[ ${metatype} = "cbor" ]]; then metafile_param="--metadata-cbor-file ${metafile}" else - println "ERROR" "${FG_RED}ERROR${NC}: unknown metadata type '${metatype}'" + println ERROR "${FG_RED}ERROR${NC}: unknown metadata type '${metatype}'" return 1 fi @@ -2103,7 +1983,7 @@ sendMetadata() { ${ERA_IDENTIFIER} --out-file "${TMP_DIR}"/tx0.tmp ) - println "ACTION" "${CCLI} transaction build-raw ${dummy_build_args[@]}" + println ACTION "${CCLI} transaction build-raw ${dummy_build_args[@]}" if ! ${CCLI} transaction build-raw "${dummy_build_args[@]}"; then return 1; fi min_fee_args=( @@ -2116,15 +1996,15 @@ sendMetadata() { --byron-witness-count 0 --protocol-params-file "${TMP_DIR}"/protparams.json ) - println "ACTION" "${CCLI} ${min_fee_args[*]}" + println ACTION "${CCLI} ${min_fee_args[*]}" min_fee=$([[ "$(${CCLI} ${min_fee_args[*]})" =~ ([0-9]+) ]] && echo ${BASH_REMATCH[1]}) - println "LOG" "fee is $(formatLovelace ${min_fee}) Ada" + println LOG "fee is $(formatLovelace ${min_fee}) Ada" newBalance=$(( ${assets[lovelace]} - min_fee )) - println "LOG" "Balance left to be returned in used UTxO is $(formatLovelace ${newBalance}) Ada ( $(formatLovelace ${assets[lovelace]}) - $(formatLovelace ${min_fee}) )" + println LOG "Balance left to be returned in used UTxO is $(formatLovelace ${newBalance}) Ada ( $(formatLovelace ${assets[lovelace]}) - $(formatLovelace ${min_fee}) )" if [[ ${assets[lovelace]} -lt ${min_fee} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: Not enough Ada in ${wallet_source} address for tx fee!"\ + println ERROR "\n${FG_RED}ERROR${NC}: Not enough Ada in ${wallet_source} address for tx fee!"\ "Funds in address: ${FG_LBLUE}$(formatLovelace ${assets[lovelace]})${NC} Ada"\ "Minimum required: ${FG_LBLUE}$(formatLovelace ${min_fee})${NC} Ada" return 1 @@ -2133,7 +2013,7 @@ sendMetadata() { tx_out="${addr}+${newBalance}${assets_tx_out}" getMinUTxO "${tx_out}" if [[ ${newBalance} -lt ${min_utxo_out} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, only ${FG_LBLUE}$(formatLovelace ${newBalance})${NC} Ada left in address after tx fee, at least ${FG_LBLUE}$(formatLovelace ${min_utxo_out})${NC} Ada required!" + println ERROR "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, only ${FG_LBLUE}$(formatLovelace ${newBalance})${NC} Ada left in address after tx fee, at least ${FG_LBLUE}$(formatLovelace ${min_utxo_out})${NC} Ada required!" return 1 fi @@ -2160,8 +2040,8 @@ sendMetadata() { jq -r . <<< "${offlineJSON}" > "${offline_tx}" echo println "Offline transaction successfully built and saved to: ${FG_LGRAY}${offline_tx}${NC}" - println "DEBUG" "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" - println "DEBUG" "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${payment_sk_file})${NC}" + println DEBUG "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" + println DEBUG "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${payment_sk_file})${NC}" return 2 # return as failed to stop main processing and return to home menu fi @@ -2182,7 +2062,7 @@ mintAsset() { else ttl=${policy_ttl} tip_ref=$(getSlotTipRef) - println "LOG" "Current slot is ${tip_ref}, setting ttl to ${ttl} based on policy expiration" + println LOG "Current slot is ${tip_ref}, setting ttl to ${ttl} based on policy expiration" fi [[ -z ${asset_name} ]] && asset_name_out="" || asset_name_out=".${asset_name}" @@ -2198,7 +2078,7 @@ mintAsset() { ${ERA_IDENTIFIER} --out-file "${TMP_DIR}"/tx0.tmp ) - println "ACTION" "${CCLI} transaction build-raw ${dummy_build_args[@]}" + println ACTION "${CCLI} transaction build-raw ${dummy_build_args[@]}" if ! ${CCLI} transaction build-raw "${dummy_build_args[@]}"; then return 1; fi min_fee_args=( @@ -2211,15 +2091,15 @@ mintAsset() { --byron-witness-count 0 --protocol-params-file "${TMP_DIR}"/protparams.json ) - println "ACTION" "${CCLI} ${min_fee_args[*]}" + println ACTION "${CCLI} ${min_fee_args[*]}" min_fee=$([[ "$(${CCLI} ${min_fee_args[*]})" =~ ([0-9]+) ]] && echo ${BASH_REMATCH[1]}) - println "LOG" "fee is $(formatLovelace ${min_fee}) Ada" + println LOG "fee is $(formatLovelace ${min_fee}) Ada" newBalance=$(( ${assets[lovelace]} - min_fee )) - println "LOG" "Balance left to be returned in used UTxO is $(formatLovelace ${newBalance}) Ada ( $(formatLovelace ${assets[lovelace]}) - $(formatLovelace ${min_fee}) )" + println LOG "Balance left to be returned in used UTxO is $(formatLovelace ${newBalance}) Ada ( $(formatLovelace ${assets[lovelace]}) - $(formatLovelace ${min_fee}) )" if [[ ${assets[lovelace]} -lt ${min_fee} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: Not enough Ada in ${wallet_source} address for tx fee!"\ + println ERROR "\n${FG_RED}ERROR${NC}: Not enough Ada in ${wallet_source} address for tx fee!"\ "Funds in address: ${FG_LBLUE}$(formatLovelace ${assets[lovelace]})${NC} Ada"\ "Minimum required: ${FG_LBLUE}$(formatLovelace ${min_fee})${NC} Ada" return 1 @@ -2228,7 +2108,7 @@ mintAsset() { tx_out="${addr}+${newBalance}${assets_tx_out}" getMinUTxO "${tx_out}" if [[ ${newBalance} -lt ${min_utxo_out} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, only ${FG_LBLUE}$(formatLovelace ${newBalance})${NC} Ada left in address after tx fee, at least ${FG_LBLUE}$(formatLovelace ${min_utxo_out})${NC} Ada required!" + println ERROR "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, only ${FG_LBLUE}$(formatLovelace ${newBalance})${NC} Ada left in address after tx fee, at least ${FG_LBLUE}$(formatLovelace ${min_utxo_out})${NC} Ada required!" return 1 fi @@ -2263,10 +2143,10 @@ mintAsset() { jq -r . <<< "${offlineJSON}" > "${offline_tx}" echo println "Offline transaction successfully built and saved to: ${FG_LGRAY}${offline_tx}${NC}" - println "DEBUG" "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" - println "DEBUG" "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${payment_sk_file})${NC}" - println "DEBUG" "Policy ${FG_GREEN}${policy_name} ${FG_LGRAY}$(basename ${policy_sk_file})${NC}" - println "DEBUG" "Policy ${FG_GREEN}${policy_name} ${FG_LGRAY}$(basename ${policy_script_file})${NC}" + println DEBUG "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" + println DEBUG "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${payment_sk_file})${NC}" + println DEBUG "Policy ${FG_GREEN}${policy_name} ${FG_LGRAY}$(basename ${policy_sk_file})${NC}" + println DEBUG "Policy ${FG_GREEN}${policy_name} ${FG_LGRAY}$(basename ${policy_script_file})${NC}" return 2 # return as failed to stop main processing and return to home menu fi @@ -2285,7 +2165,7 @@ burnAsset() { else ttl=${policy_ttl} tip_ref=$(getSlotTipRef) - println "LOG" "Current slot is ${tip_ref}, setting ttl to ${ttl} based on policy expiration" + println LOG "Current slot is ${tip_ref}, setting ttl to ${ttl} based on policy expiration" fi [[ -z ${asset_name} ]] && asset_name_out="" || asset_name_out=".${asset_name}" @@ -2301,7 +2181,7 @@ burnAsset() { ${ERA_IDENTIFIER} --out-file "${TMP_DIR}"/tx0.tmp ) - println "ACTION" "${CCLI} transaction build-raw ${dummy_build_args[@]}" + println ACTION "${CCLI} transaction build-raw ${dummy_build_args[@]}" if ! ${CCLI} transaction build-raw "${dummy_build_args[@]}"; then return 1; fi min_fee_args=( @@ -2314,15 +2194,15 @@ burnAsset() { --byron-witness-count 0 --protocol-params-file "${TMP_DIR}"/protparams.json ) - println "ACTION" "${CCLI} ${min_fee_args[*]}" + println ACTION "${CCLI} ${min_fee_args[*]}" min_fee=$([[ "$(${CCLI} ${min_fee_args[*]})" =~ ([0-9]+) ]] && echo ${BASH_REMATCH[1]}) - println "LOG" "fee is $(formatLovelace ${min_fee}) Ada" + println LOG "fee is $(formatLovelace ${min_fee}) Ada" newBalance=$(( ${assets[lovelace]} - min_fee )) - println "LOG" "Balance left to be returned in used UTxO is $(formatLovelace ${newBalance}) Ada ( $(formatLovelace ${assets[lovelace]}) - $(formatLovelace ${min_fee}) )" + println LOG "Balance left to be returned in used UTxO is $(formatLovelace ${newBalance}) Ada ( $(formatLovelace ${assets[lovelace]}) - $(formatLovelace ${min_fee}) )" if [[ ${assets[lovelace]} -lt ${min_fee} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: Not enough Ada in ${wallet_source} address for tx fee!"\ + println ERROR "\n${FG_RED}ERROR${NC}: Not enough Ada in ${wallet_source} address for tx fee!"\ "Funds in address: ${FG_LBLUE}$(formatLovelace ${assets[lovelace]})${NC} Ada"\ "Minimum required: ${FG_LBLUE}$(formatLovelace ${min_fee})${NC} Ada" return 1 @@ -2331,7 +2211,7 @@ burnAsset() { tx_out="${addr}+${newBalance}${assets_tx_out}" getMinUTxO "${tx_out}" if [[ ${newBalance} -lt ${min_utxo_out} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, only ${FG_LBLUE}$(formatLovelace ${newBalance})${NC} Ada left in address after tx fee, at least ${FG_LBLUE}$(formatLovelace ${min_utxo_out})${NC} Ada required!" + println ERROR "\n${FG_RED}ERROR${NC}: minimum UTxO value not fulfilled, only ${FG_LBLUE}$(formatLovelace ${newBalance})${NC} Ada left in address after tx fee, at least ${FG_LBLUE}$(formatLovelace ${min_utxo_out})${NC} Ada required!" return 1 fi @@ -2366,10 +2246,10 @@ burnAsset() { jq -r . <<< "${offlineJSON}" > "${offline_tx}" echo println "Offline transaction successfully built and saved to: ${FG_LGRAY}${offline_tx}${NC}" - println "DEBUG" "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" - println "DEBUG" "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${payment_sk_file})${NC}" - println "DEBUG" "Policy ${FG_GREEN}${policy_name} ${FG_LGRAY}$(basename ${policy_sk_file})${NC}" - println "DEBUG" "Policy ${FG_GREEN}${policy_name} ${FG_LGRAY}$(basename ${policy_script_file})${NC}" + println DEBUG "move file to offline computer and sign it using CNTools in offline mode '-o' [Transaction >> Sign] with:" + println DEBUG "Wallet ${FG_GREEN}${wallet_name} ${FG_LGRAY}$(basename ${payment_sk_file})${NC}" + println DEBUG "Policy ${FG_GREEN}${policy_name} ${FG_LGRAY}$(basename ${policy_sk_file})${NC}" + println DEBUG "Policy ${FG_GREEN}${policy_name} ${FG_LGRAY}$(basename ${policy_script_file})${NC}" return 2 # return as failed to stop main processing and return to home menu fi @@ -2383,7 +2263,7 @@ burnAsset() { # : populate an array variable called 'build_args' with all data # Parameters : build_args > an array with all the arguments to assemble the transaction buildTx() { - println "ACTION" "${CCLI} transaction build-raw ${ERA_IDENTIFIER} ${build_args[*]}" + println ACTION "${CCLI} transaction build-raw ${ERA_IDENTIFIER} ${build_args[*]}" ${CCLI} transaction build-raw ${ERA_IDENTIFIER} "${build_args[@]}" } @@ -2398,7 +2278,7 @@ witnessTx() { for skey in "$@"; do [[ -z ${skey//[[:blank:]]/} ]] && continue if [[ ! -f "${skey}" ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: file not found: ${skey}" + println ERROR "\n${FG_RED}ERROR${NC}: file not found: ${skey}" return 1 elif [[ $(jq -r '.description' "${skey}") = *"Hardware"* ]]; then # HW signing key if ! unlockHWDevice "witness the transaction"; then return 1; fi @@ -2410,8 +2290,8 @@ witnessTx() { ${NETWORK_IDENTIFIER} --out-file "${tx_witness}" ) - println "ACTION" "${witness_command[@]}" - if ! ${witness_command[@]}; then println "ERROR" "\n${FG_RED}ERROR${NC}: during hardware wallet signing !!" && return 1; fi + println ACTION "${witness_command[@]}" + if ! ${witness_command[@]}; then println ERROR "\n${FG_RED}ERROR${NC}: during hardware wallet signing !!" && return 1; fi else tx_witness="$(mktemp "${TMP_DIR}/tx.witness_XXXXXXXXXX")" witness_command=( @@ -2421,8 +2301,8 @@ witnessTx() { ${NETWORK_IDENTIFIER} --out-file "${tx_witness}" ) - println "ACTION" "${witness_command[@]}" - if ! ${witness_command[@]}; then println "ERROR" "\n${FG_RED}ERROR${NC}: during transaction signing !!" && return 1; fi + println ACTION "${witness_command[@]}" + if ! ${witness_command[@]}; then println ERROR "\n${FG_RED}ERROR${NC}: during transaction signing !!" && return 1; fi fi tx_witness_files+=( "${tx_witness}" ) done @@ -2440,7 +2320,7 @@ assembleTx() { if [[ -f "${witness}" ]]; then tx_witness_out+=( "--witness-file ${witness}" ) else - println "ERROR" "\n${FG_RED}ERROR${NC}: witness file not found: ${witness}" + println ERROR "\n${FG_RED}ERROR${NC}: witness file not found: ${witness}" return 1 fi done @@ -2450,10 +2330,10 @@ assembleTx() { ${tx_witness_out[@]} --out-file "${tx_signed}" ) - println "ACTION" "${sign_command[@]}" + println ACTION "${sign_command[@]}" ${sign_command[@]} else - println "ERROR" "\n${FG_RED}ERROR${NC}: no witness files provided, unable to assemble tx!" + println ERROR "\n${FG_RED}ERROR${NC}: no witness files provided, unable to assemble tx!" return 1 fi } @@ -2473,7 +2353,7 @@ signTx() { [[ -z ${skey//[[:blank:]]/} ]] && continue skey_desc="$(jq -r '.description //empty' "${skey}")" if [[ ! -f "${skey}" ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: file not found: ${skey}" + println ERROR "\n${FG_RED}ERROR${NC}: file not found: ${skey}" return 1 elif [[ ${skey} = *".script" ]]; then tx_sign_out+=( "--script-file ${skey}" ) @@ -2508,11 +2388,11 @@ signTx() { ) fi else - println "ERROR" "\n${FG_RED}ERROR${NC}: no signing keys provided, unable to sign tx!" + println ERROR "\n${FG_RED}ERROR${NC}: no signing keys provided, unable to sign tx!" return 1 fi - println "ACTION" "${sign_command[@]}" + println ACTION "${sign_command[@]}" ${sign_command[@]} } @@ -2528,7 +2408,7 @@ submitTx() { ${NETWORK_IDENTIFIER} ) - println "ACTION" "${submit_command[@]}" + println ACTION "${submit_command[@]}" ${submit_command[@]} } @@ -2538,36 +2418,36 @@ submitTx() { unlockHWDevice() { if ! HWCLIversionCheck; then waitForInput && return 1; fi waitForInput "${FG_BLUE}INFO${NC}: please connect and unlock hardware device" " ${FG_YELLOW}Ledger${NC} - Unlock with pin and open Cardano app" " ${FG_YELLOW}Trezor${NC} - Make sure trezor bridge is installed (https://wallet.trezor.io/#/bridge) " "" "when done, press any key to continue" - println "ACTION" "cardano-hw-cli device version" + println ACTION "cardano-hw-cli device version" device_app="$(cardano-hw-cli device version)" device_app_vendor="$(cut -d' ' -f1 <<< "${device_app}")" device_app_version="$(cut -d' ' -f4 <<< "${device_app}")" if [[ ! ${device_app_version} =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: unable to identify connected hardware device, is the device plugged in and unlocked?" - println "ERROR" "Make sure device is seen by OS using tools like lsusb etc and is working correctly" + println ERROR "${FG_RED}ERROR${NC}: unable to identify connected hardware device, is the device plugged in and unlocked?" + println ERROR "Make sure device is seen by OS using tools like lsusb etc and is working correctly" waitForInput && return 1 elif [[ ${device_app_vendor} = Ledger ]]; then if ! versionCheck "2.2.0" "${device_app_version}"; then - println "ERROR" "${FG_RED}ERROR${NC}: Cardano app version installed on Ledger is ${FG_LGRAY}v${device_app_version}${NC}, minimum required version is ${FG_GREEN}v2.2.0${NC} !!" + println ERROR "${FG_RED}ERROR${NC}: Cardano app version installed on Ledger is ${FG_LGRAY}v${device_app_version}${NC}, minimum required version is ${FG_GREEN}v2.2.0${NC} !!" return 1 fi elif [[ ${device_app_vendor} = Trezor ]]; then if ! versionCheck "2.3.6" "${device_app_version}"; then - println "ERROR" "${FG_RED}ERROR${NC}: Trezor firmware installed on device is ${FG_LGRAY}v${device_app_version}${NC}, minimum required version is ${FG_GREEN}v2.3.6${NC} !!" + println ERROR "${FG_RED}ERROR${NC}: Trezor firmware installed on device is ${FG_LGRAY}v${device_app_version}${NC}, minimum required version is ${FG_GREEN}v2.3.6${NC} !!" return 1 fi else - println "ERROR" "${FG_RED}ERROR${NC}: Unknown vendor: ${FG_LGRAY}${device_app_vendor}${NC} !!" + println ERROR "${FG_RED}ERROR${NC}: Unknown vendor: ${FG_LGRAY}${device_app_vendor}${NC} !!" return 1 fi - println "DEBUG" "\n${FG_BLUE}INFO${NC}: follow directions on hardware device to $1" + println DEBUG "\n${FG_BLUE}INFO${NC}: follow directions on hardware device to $1" } HWCLIversionCheck() { HWCLI_version="$(cardano-hw-cli version 2>/dev/null | head -n 1 | cut -d' ' -f6)" if ! versionCheck "1.2.0" "${HWCLI_version}"; then - println "ERROR" "${FG_RED}ERROR${NC}: Vacuumlabs cardano-hw-cli ${FG_LGRAY}v${HWCLI_version}${NC} installed on system, minimum required version is ${FG_GREEN}v1.1.3${NC} !!" - println "ERROR" "Please run ${FG_LGRAY}prereqs.sh -w${NC} to upgrade to the latest version." + println ERROR "${FG_RED}ERROR${NC}: Vacuumlabs cardano-hw-cli ${FG_LGRAY}v${HWCLI_version}${NC} installed on system, minimum required version is ${FG_GREEN}v1.1.3${NC} !!" + println ERROR "Please run ${FG_LGRAY}prereqs.sh -w${NC} to upgrade to the latest version." return 1 fi return 0 @@ -2576,7 +2456,7 @@ HWCLIversionCheck() { # Command : selectOpMode # Description : Helper function to choose operational mode selectOpMode() { - println "OFF" "\nOnline mode - The default mode to use if all keys are available\n"\ + println OFF "\nOnline mode - The default mode to use if all keys are available\n"\ "Hybrid mode - 1) Go through steps to build a transaction file"\ " 2) Copy built tx file to offline computer"\ " 3) Sign it using 'Sign Tx' with keys on offline computer"\ diff --git a/scripts/cnode-helper-scripts/cntools.sh b/scripts/cnode-helper-scripts/cntools.sh index b8c1b519b..b06ba13b5 100755 --- a/scripts/cnode-helper-scripts/cntools.sh +++ b/scripts/cnode-helper-scripts/cntools.sh @@ -56,39 +56,17 @@ while getopts :oab: opt; do done shift $((OPTIND -1)) -URL_RAW="https://raw.githubusercontent.com/cardano-community/guild-operators/${BRANCH}" -URL="${URL_RAW}/scripts/cnode-helper-scripts" -URL_DOCS="${URL_RAW}/docs/Scripts" +if [[ ! -f "${PARENT}"/env ]]; then + echo -e "\nCommon env file missing: ${PARENT}/env" + echo -e "This is a mandatory prerequisite, please install with prereqs.sh or manually download from GitHub\n" + myExit 1 +fi + +. "${PARENT}"/env offline &>/dev/null # ignore any errors, re-sourced later # env version check if [[ ${CNTOOLS_MODE} = "CONNECTED" ]]; then - if curl -s -f -m 10 -o "${PARENT}"/env.tmp ${URL}/env 2>/dev/null && [[ -f "${PARENT}"/env.tmp ]]; then - if [[ -f "${PARENT}"/env ]]; then - if [[ $(grep "_HOME=" "${PARENT}"/env) =~ ^#?([^[:space:]]+)_HOME ]]; then - vname=$(tr '[:upper:]' '[:lower:]' <<< ${BASH_REMATCH[1]}) - sed -e "s@/opt/cardano/[c]node@/opt/cardano/${vname}@g" -e "s@[C]NODE_HOME@${BASH_REMATCH[1]}_HOME@g" -i "${PARENT}"/env.tmp - else - myExit 1 "Update for env file failed! Please use prereqs.sh to force an update or manually download $(basename $0) + env from GitHub" - fi - TEMPL_CMD=$(awk '/^# Do NOT modify/,0' "${PARENT}"/env) - TEMPL2_CMD=$(awk '/^# Do NOT modify/,0' "${PARENT}"/env.tmp) - if [[ "$(echo ${TEMPL_CMD} | sha256sum)" != "$(echo ${TEMPL2_CMD} | sha256sum)" ]]; then - . "${PARENT}"/env offline &>/dev/null # source in offline mode and ignore errors to get some common functions, sourced at a later point again - if getAnswer "\nThe static content from env file does not match with guild-operators repository, do you want to download the updated file?"; then - cp "${PARENT}"/env "${PARENT}/env_bkp$(date +%s)" - STATIC_CMD=$(awk '/#!/{x=1}/^# Do NOT modify/{exit} x' "${PARENT}"/env) - printf '%s\n%s\n' "$STATIC_CMD" "$TEMPL2_CMD" > "${PARENT}"/env.tmp - mv "${PARENT}"/env.tmp "${PARENT}"/env - echo -e "\nenv update successfully applied!" - waitToProceed - fi - fi - else - mv "${PARENT}"/env.tmp "${PARENT}"/env - myExit 0 "Common env file downloaded: ${PARENT}/env\nThis is a mandatory prerequisite, please set variables accordingly in User Variables section in the env file and restart CNTools" - fi - fi - rm -f "${PARENT}"/env.tmp + ! checkUpdate env && myExit 1 ! . "${PARENT}"/env && myExit 1 "ERROR: CNTools failed to load common env file\nPlease verify set values in 'User Variables' section in env file or log an issue on GitHub" else . "${PARENT}"/env offline @@ -115,19 +93,13 @@ exec 7>&2 # Link file descriptor #7 with normal stderr. exec 8>&1 # Link file descriptor #8 with custom stdout. exec 9>&2 # Link file descriptor #9 with custom stderr. -# check that bash version is > 4.4.0 -[[ $(bash --version | head -n 1) =~ ([0-9]+\.[0-9]+\.[0-9]+) ]] || myExit 1 "Unable to get BASH version" -if ! versionCheck "4.4.0" "${BASH_REMATCH[1]}"; then - myExit 1 "BASH does not meet the minimum required version of ${FG_LBLUE}4.4.0${NC}, found ${FG_LBLUE}${BASH_REMATCH[1]}${NC}\n\nPlease upgrade to a newer Linux distribution or compile latest BASH following official docs.\n\nINSTALL: https://www.gnu.org/software/bash/manual/html_node/Installing-Bash.html\nDOWNLOAD: http://git.savannah.gnu.org/cgit/bash.git/ (latest stable TAG)" -fi - # check for required command line tools -if ! need_cmd "curl" || \ - ! need_cmd "jq" || \ - ! need_cmd "bc" || \ - ! need_cmd "sed" || \ - ! need_cmd "awk" || \ - ! need_cmd "column" || \ +if ! cmdAvailable "curl" || \ + ! cmdAvailable "jq" || \ + ! cmdAvailable "bc" || \ + ! cmdAvailable "sed" || \ + ! cmdAvailable "awk" || \ + ! cmdAvailable "column" || \ ! protectionPreRequisites; then myExit 1 "Missing one or more of the required command line tools, press any key to exit" fi @@ -135,17 +107,17 @@ fi if [[ ${CNTOOLS_MODE} = "CONNECTED" ]]; then # check to see if there are any updates available clear - println "DEBUG" "CNTools version check...\n" + println DEBUG "CNTools version check...\n" if curl -s -f -m ${CURL_TIMEOUT} -o "${PARENT}"/cntools.library.tmp "${URL}/cntools.library" && [[ -f "${PARENT}"/cntools.library.tmp ]]; then GIT_MAJOR_VERSION=$(grep -r ^CNTOOLS_MAJOR_VERSION= "${PARENT}"/cntools.library.tmp |sed -e "s#.*=##") GIT_MINOR_VERSION=$(grep -r ^CNTOOLS_MINOR_VERSION= "${PARENT}"/cntools.library.tmp |sed -e "s#.*=##") GIT_PATCH_VERSION=$(grep -r ^CNTOOLS_PATCH_VERSION= "${PARENT}"/cntools.library.tmp |sed -e "s#.*=##") GIT_VERSION="${GIT_MAJOR_VERSION}.${GIT_MINOR_VERSION}.${GIT_PATCH_VERSION}" if ! versionCheck "${GIT_VERSION}" "${CNTOOLS_VERSION}"; then - println "DEBUG" "A new version of CNTools is available" + println DEBUG "A new version of CNTools is available" echo - println "DEBUG" "Installed Version : ${FG_LGRAY}${CNTOOLS_VERSION}${NC}" - println "DEBUG" "Available Version : ${FG_GREEN}${GIT_VERSION}${NC}" + println DEBUG "Installed Version : ${FG_LGRAY}${CNTOOLS_VERSION}${NC}" + println DEBUG "Available Version : ${FG_GREEN}${GIT_VERSION}${NC}" if getAnswer "\nDo you want to upgrade to the latest version of CNTools?"; then if curl -s -f -m ${CURL_TIMEOUT} -o "${PARENT}"/cntools.sh.tmp "${URL}/cntools.sh" && \ mv -f "${PARENT}"/cntools.sh "${PARENT}/cntools.sh_bkp$(printf '%(%s)T\n' -1)" && \ @@ -157,9 +129,8 @@ if [[ ${CNTOOLS_MODE} = "CONNECTED" ]]; then else myExit 1 "${FG_RED}Update failed!${NC}\n\nPlease use prereqs.sh or manually update CNTools" fi + waitForInput "press any key to proceed" fi - #println "DEBUG" "\nGo to Update section for upgrade\n\nAlternately, follow https://cardano-community.github.io/guild-operators/#/basics?id=pre-requisites to update cntools as well alongwith any other files" - waitForInput "press any key to proceed" else # check if CNTools was recently updated, if so show whats new if curl -s -f -m ${CURL_TIMEOUT} -o "${TMP_DIR}"/cntools-changelog.md "${URL_DOCS}/cntools-changelog.md"; then @@ -170,24 +141,24 @@ if [[ ${CNTOOLS_MODE} = "CONNECTED" ]]; then sleep 0.1 if [[ ! -f "${PARENT}/cntools-changelog.md" ]]; then # special case for first installation or 5.0.0 upgrade, print release notes until previous major version - println "OFF" "~ CNTools - What's New ~\n\n" "$(sed -n "/\[${CNTOOLS_MAJOR_VERSION}\.${CNTOOLS_MINOR_VERSION}\.${CNTOOLS_PATCH_VERSION}\]/,/\[$((CNTOOLS_MAJOR_VERSION-1))\.[0-9]\.[0-9]\]/p" "${TMP_DIR}"/cntools-changelog.md | head -n -2)" | less -X + println OFF "~ CNTools - What's New ~\n\n" "$(sed -n "/\[${CNTOOLS_MAJOR_VERSION}\.${CNTOOLS_MINOR_VERSION}\.${CNTOOLS_PATCH_VERSION}\]/,/\[$((CNTOOLS_MAJOR_VERSION-1))\.[0-9]\.[0-9]\]/p" "${TMP_DIR}"/cntools-changelog.md | head -n -2)" | less -X else # print release notes from current until previously installed version [[ $(cat "${PARENT}/cntools-changelog.md") =~ \[([[:digit:]])\.([[:digit:]])\.([[:digit:]])\] ]] - cat <(println "OFF" "~ CNTools - What's New ~\n") <(awk "1;/\[${BASH_REMATCH[1]}\.${BASH_REMATCH[2]}\.${BASH_REMATCH[3]}\]/{exit}" "${TMP_DIR}"/cntools-changelog.md | head -n -2 | tail -n +7) <(echo -e "\n [Press 'q' to quit and proceed to CNTools main menu]\n") | less -X + cat <(println OFF "~ CNTools - What's New ~\n") <(awk "1;/\[${BASH_REMATCH[1]}\.${BASH_REMATCH[2]}\.${BASH_REMATCH[3]}\]/{exit}" "${TMP_DIR}"/cntools-changelog.md | head -n -2 | tail -n +7) <(echo -e "\n [Press 'q' to quit and proceed to CNTools main menu]\n") | less -X fi exec >&8 # custom stdout cp "${TMP_DIR}"/cntools-changelog.md "${PARENT}/cntools-changelog.md" fi else - println "ERROR" "\n${FG_RED}ERROR${NC}: failed to download changelog from GitHub!" + println ERROR "\n${FG_RED}ERROR${NC}: failed to download changelog from GitHub!" waitForInput "press any key to proceed" fi - rm -f "${PARENT}"/cntools.sh.tmp - rm -f "${PARENT}"/cntools.library.tmp fi + rm -f "${PARENT}"/cntools.sh.tmp + rm -f "${PARENT}"/cntools.library.tmp else - println "ERROR" "\n${FG_RED}ERROR${NC}: failed to download cntools.library from GitHub, unable to perform version check!" + println ERROR "\n${FG_RED}ERROR${NC}: failed to download cntools.library from GitHub, unable to perform version check!" waitForInput "press any key to proceed" fi @@ -200,6 +171,12 @@ if [[ ${CNTOOLS_MODE} = "CONNECTED" ]]; then echo "${PROT_PARAMS}" > "${TMP_DIR}"/protparams.json fi +# check that bash version is > 4.4.0 +[[ $(bash --version | head -n 1) =~ ([0-9]+\.[0-9]+\.[0-9]+) ]] || myExit 1 "Unable to get BASH version" +if ! versionCheck "4.4.0" "${BASH_REMATCH[1]}"; then + myExit 1 "BASH does not meet the minimum required version of ${FG_LBLUE}4.4.0${NC}, found ${FG_LBLUE}${BASH_REMATCH[1]}${NC}\n\nPlease upgrade to a newer Linux distribution or compile latest BASH following official docs.\n\nINSTALL: https://www.gnu.org/software/bash/manual/html_node/Installing-Bash.html\nDOWNLOAD: http://git.savannah.gnu.org/cgit/bash.git/ (latest stable TAG)" +fi + # check if there are pools in need of KES key rotation clear kes_rotation_needed="no" @@ -210,16 +187,16 @@ while IFS= read -r -d '' pool; do kes_rotation_needed="yes" println "\n** WARNING **\nPool ${FG_GREEN}$(basename ${pool})${NC} in need of KES key rotation" if [[ ${expiration_time_sec_diff} -lt 0 ]]; then - println "DEBUG" "${FG_RED}Keys expired!${NC} : ${FG_RED}$(timeLeft ${expiration_time_sec_diff:1})${NC} ago" + println DEBUG "${FG_RED}Keys expired!${NC} : ${FG_RED}$(timeLeft ${expiration_time_sec_diff:1})${NC} ago" else - println "DEBUG" "Remaining KES periods : ${FG_RED}${remaining_kes_periods}${NC}" - println "DEBUG" "Time left : ${FG_RED}$(timeLeft ${expiration_time_sec_diff})${NC}" + println DEBUG "Remaining KES periods : ${FG_RED}${remaining_kes_periods}${NC}" + println DEBUG "Time left : ${FG_RED}$(timeLeft ${expiration_time_sec_diff})${NC}" fi elif [[ ${expiration_time_sec_diff} -lt ${KES_WARNING_PERIOD} ]]; then kes_rotation_needed="yes" - println "DEBUG" "\nPool ${FG_GREEN}$(basename ${pool})${NC} soon in need of KES key rotation" - println "DEBUG" "Remaining KES periods : ${FG_YELLOW}${remaining_kes_periods}${NC}" - println "DEBUG" "Time left : ${FG_YELLOW}$(timeLeft ${expiration_time_sec_diff})${NC}" + println DEBUG "\nPool ${FG_GREEN}$(basename ${pool})${NC} soon in need of KES key rotation" + println DEBUG "Remaining KES periods : ${FG_YELLOW}${remaining_kes_periods}${NC}" + println DEBUG "Time left : ${FG_YELLOW}$(timeLeft ${expiration_time_sec_diff})${NC}" fi fi done < <(find "${POOL_FOLDER}" -mindepth 1 -maxdepth 1 -type d -print0 | sort -z) @@ -236,16 +213,16 @@ fi function main { while true; do # Main loop # Start with a clean slate after each completed or canceled command excluding .dialogrc from purge - find "${TMP_DIR:?}" -type f -not \( -name 'protparams.json' -o -name '.dialogrc' -o -name "offline_tx*" -o -name "*_cntools_backup*" -o -name "metadata_*" \) -delete + find "${TMP_DIR:?}" -type f -not \( -name 'protparams.json' -o -name '.dialogrc' -o -name "offline_tx*" -o -name "*_cntools_backup*" -o -name "metadata_*" -o -name "asset*" \) -delete clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" if [[ ${CNTOOLS_MODE} = "CONNECTED" ]]; then println "$(printf " >> CNTools v%s - %s - ${FG_GREEN}%s${NC} << %$((84-23-${#CNTOOLS_VERSION}-${#NETWORK_NAME}-${#CNTOOLS_MODE}))s" "${CNTOOLS_VERSION}" "${NETWORK_NAME}" "${CNTOOLS_MODE}" "A Guild Operators collaboration")" else println "$(printf " >> CNTools v%s - %s - ${FG_LBLUE}%s${NC} << %$((84-23-${#CNTOOLS_VERSION}-${#NETWORK_NAME}-${#CNTOOLS_MODE}))s" "${CNTOOLS_VERSION}" "${NETWORK_NAME}" "${CNTOOLS_MODE}" "A Guild Operators collaboration")" fi - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - println "OFF" " Main Menu Telegram Announcement / Support channel: ${FG_YELLOW}t.me/guild_operators_official${NC}\n"\ + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println OFF " Main Menu Telegram Announcement / Support channel: ${FG_YELLOW}t.me/guild_operators_official${NC}\n"\ " ) Wallet - create, show, remove and protect wallets"\ " ) Funds - send, withdraw and delegate"\ " ) Pool - pool creation and management"\ @@ -255,19 +232,19 @@ function main { "$([[ ${ADVANCED_MODE} = true ]] && echo " ) Advanced - Developer and advanced features: metadata, multi-assets, ...")"\ " ) Refresh - reload home screen content"\ "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - println "DEBUG" "$(printf "%84s" "Epoch $(getEpoch) - $(timeLeft "$(timeUntilNextEpoch)") until next")" + println DEBUG "$(printf "%84s" "Epoch $(getEpoch) - $(timeLeft "$(timeUntilNextEpoch)") until next")" if [[ ${CNTOOLS_MODE} = "OFFLINE" ]]; then - println "DEBUG" " What would you like to do?" + println DEBUG " What would you like to do?" else getNodeMetrics tip_diff=$(( $(getSlotTipRef) - slotnum )) slot_interval=$(slotInterval) if [[ ${tip_diff} -le ${slot_interval} ]]; then - println "DEBUG" "$(printf " What would you like to do? %$((84-29-${#tip_diff}-3))s ${FG_GREEN}%s${NC}" "Node Sync:" "${tip_diff} :)")" + println DEBUG "$(printf " What would you like to do? %$((84-29-${#tip_diff}-3))s ${FG_GREEN}%s${NC}" "Node Sync:" "${tip_diff} :)")" elif [[ ${tip_diff} -le $(( slot_interval * 2 )) ]]; then - println "DEBUG" "$(printf " What would you like to do? %$((84-29-${#tip_diff}-3))s ${FG_YELLOW}%s${NC}" "Node Sync:" "${tip_diff} :|")" + println DEBUG "$(printf " What would you like to do? %$((84-29-${#tip_diff}-3))s ${FG_YELLOW}%s${NC}" "Node Sync:" "${tip_diff} :|")" else - println "DEBUG" "$(printf " What would you like to do? %$((84-29-${#tip_diff}-3))s ${FG_RED}%s${NC}" "Node Sync:" "${tip_diff} :(")" + println DEBUG "$(printf " What would you like to do? %$((84-29-${#tip_diff}-3))s ${FG_RED}%s${NC}" "Node Sync:" "${tip_diff} :(")" fi fi echo @@ -286,10 +263,10 @@ function main { case $OPERATION in wallet) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> WALLET" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - println "OFF" " Wallet Management\n\n ) New - create a new wallet"\ + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println OFF " Wallet Management\n\n ) New - create a new wallet"\ " ) Import - import a Daedalus/Yoroi 24/25 mnemonic or Ledger/Trezor HW wallet"\ " ) Register - register a wallet on chain"\ " ) De-Register - De-Register (retire) a registered wallet"\ @@ -299,7 +276,7 @@ function main { " ) Decrypt - remove write protection and decrypt wallet"\ " ) Encrypt - encrypt wallet keys and make all files immutable"\ "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - println "DEBUG" " Select Wallet Operation\n" + println DEBUG " Select Wallet Operation\n" select_opt "[n] New" "[i] Import" "[r] Register" "[z] De-Register" "[l] List" "[s] Show" "[x] Remove" "[d] Decrypt" "[e] Encrypt" "[h] Home" case $? in 0) SUBCOMMAND="new" ;; @@ -316,20 +293,20 @@ function main { case $SUBCOMMAND in new) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> WALLET >> NEW" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" echo - sleep 0.1 && read -r -p "Name of new wallet: " wallet_name 2>&6 && println "LOG" "Name of new wallet: ${wallet_name}" + getAnswerAnyCust wallet_name "Name of new wallet" wallet_name # Remove unwanted characters from wallet name wallet_name=${wallet_name//[^[:alnum:]]/_} if [[ -z "${wallet_name}" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: Empty wallet name, please retry!" + println ERROR "${FG_RED}ERROR${NC}: Empty wallet name, please retry!" waitForInput && continue fi echo if ! mkdir -p "${WALLET_FOLDER}/${wallet_name}"; then - println "ERROR" "${FG_RED}ERROR${NC}: Failed to create directory for wallet:\n${WALLET_FOLDER}/${wallet_name}" + println ERROR "${FG_RED}ERROR${NC}: Failed to create directory for wallet:\n${WALLET_FOLDER}/${wallet_name}" waitForInput && continue fi # Wallet key filenames @@ -342,13 +319,13 @@ function main { println " Choose another name or delete the existing one" waitForInput && continue fi - println "ACTION" "${CCLI} address key-gen --verification-key-file ${payment_vk_file} --signing-key-file ${payment_sk_file}" + println ACTION "${CCLI} address key-gen --verification-key-file ${payment_vk_file} --signing-key-file ${payment_sk_file}" if ! ${CCLI} address key-gen --verification-key-file "${payment_vk_file}" --signing-key-file "${payment_sk_file}"; then - println "ERROR" "\n${FG_RED}ERROR${NC}: failure during payment key creation!"; safeDel "${WALLET_FOLDER}/${wallet_name}"; waitForInput && continue + println ERROR "\n${FG_RED}ERROR${NC}: failure during payment key creation!"; safeDel "${WALLET_FOLDER}/${wallet_name}"; waitForInput && continue fi - println "ACTION" "${CCLI} stake-address key-gen --verification-key-file ${stake_vk_file} --signing-key-file ${stake_sk_file}" + println ACTION "${CCLI} stake-address key-gen --verification-key-file ${stake_vk_file} --signing-key-file ${stake_sk_file}" if ! ${CCLI} stake-address key-gen --verification-key-file "${stake_vk_file}" --signing-key-file "${stake_sk_file}"; then - println "ERROR" "\n${FG_RED}ERROR${NC}: failure during stake key creation!"; safeDel "${WALLET_FOLDER}/${wallet_name}"; waitForInput && continue + println ERROR "\n${FG_RED}ERROR${NC}: failure during stake key creation!"; safeDel "${WALLET_FOLDER}/${wallet_name}"; waitForInput && continue fi chmod 600 "${WALLET_FOLDER}/${wallet_name}/"* getBaseAddress ${wallet_name} @@ -357,21 +334,21 @@ function main { println "New Wallet : ${FG_GREEN}${wallet_name}${NC}" println "Address : ${FG_LGRAY}${base_addr}${NC}" println "Enterprise Address : ${FG_LGRAY}${pay_addr}${NC}" - println "DEBUG" "\nYou can now send and receive Ada using the above addresses." - println "DEBUG" "Note that Enterprise Address will not take part in staking." - println "DEBUG" "Wallet will be automatically registered on chain if you\nchoose to delegate or pledge wallet when registering a stake pool." + println DEBUG "\nYou can now send and receive Ada using the above addresses." + println DEBUG "Note that Enterprise Address will not take part in staking." + println DEBUG "Wallet will be automatically registered on chain if you\nchoose to delegate or pledge wallet when registering a stake pool." waitForInput && continue ;; ################################################################### import) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> WALLET >> IMPORT" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - println "OFF" " Wallet Import\n"\ + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println OFF " Wallet Import\n"\ " ) Mnemonic - Daedalus/Yoroi 24 or 25 word mnemonic"\ " ) HW Wallet - Ledger/Trezor hardware wallet"\ "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - println "DEBUG" " Select Wallet Import Operation\n" + println DEBUG " Select Wallet Import Operation\n" select_opt "[m] Mnemonic" "[w] HW Wallet" "[h] Home" case $? in 0) SUBCOMMAND="mnemonic" ;; @@ -381,26 +358,26 @@ function main { case $SUBCOMMAND in mnemonic) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> WALLET >> IMPORT >> MNEMONIC" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" echo - if ! need_cmd "bech32" || \ - ! need_cmd "cardano-address"; then - println "ERROR" "${FG_RED}ERROR${NC}: cardano-address and/or bech32 executables not found in path!" - println "ERROR" "Please run updated prereqs.sh and re-build cardano-node" + if ! cmdAvailable "bech32" &>/dev/null || \ + ! cmdAvailable "cardano-address" &>/dev/null; then + println ERROR "${FG_RED}ERROR${NC}: bech32 and/or cardano-address not found in '\$PATH'" + println ERROR "Please run updated prereqs.sh and re-build cardano-node" waitForInput && continue fi - sleep 0.1 && read -r -p "Name of imported wallet: " wallet_name 2>&6 && println "LOG" "Name of imported wallet: ${wallet_name}" + getAnswerAnyCust wallet_name "Name of imported wallet" # Remove unwanted characters from wallet name wallet_name=${wallet_name//[^[:alnum:]]/_} if [[ -z "${wallet_name}" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: Empty wallet name, please retry!" + println ERROR "${FG_RED}ERROR${NC}: Empty wallet name, please retry!" waitForInput && continue fi echo if ! mkdir -p "${WALLET_FOLDER}/${wallet_name}"; then - println "ERROR" "${FG_RED}ERROR${NC}: Failed to create directory for wallet:\n${WALLET_FOLDER}/${wallet_name}" + println ERROR "${FG_RED}ERROR${NC}: Failed to create directory for wallet:\n${WALLET_FOLDER}/${wallet_name}" waitForInput && continue fi if [[ $(find "${WALLET_FOLDER}/${wallet_name}" -type f -print0 | wc -c) -gt 0 ]]; then @@ -408,12 +385,13 @@ function main { println " Choose another name or delete the existing one" waitForInput && continue fi - sleep 0.1 && read -r -p "24 or 15 word mnemonic(space separated): " mnemonic 2>&6 + getAnswerAnyCust mnemonic false "24 or 15 word mnemonic(space separated)" echo IFS=" " read -r -a words <<< "${mnemonic}" if [[ ${#words[@]} -ne 24 ]] && [[ ${#words[@]} -ne 15 ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: 24 or 15 words expected, found ${FG_RED}${#words[@]}${NC}" + println ERROR "${FG_RED}ERROR${NC}: 24 or 15 words expected, found ${FG_RED}${#words[@]}${NC}" echo && safeDel "${WALLET_FOLDER}/${wallet_name}" + unset mnemonic; unset words waitForInput && continue fi payment_sk_file="${WALLET_FOLDER}/${wallet_name}/${WALLET_PAY_SK_FILENAME}" @@ -422,8 +400,10 @@ function main { stake_vk_file="${WALLET_FOLDER}/${wallet_name}/${WALLET_STAKE_VK_FILENAME}" if ! root_prv=$(cardano-address key from-recovery-phrase Shelley <<< ${mnemonic}); then echo && safeDel "${WALLET_FOLDER}/${wallet_name}" + unset mnemonic; unset words waitForInput && continue fi + unset mnemonic; unset words payment_xprv=$(cardano-address key child 1852H/1815H/0H/0/0 <<< ${root_prv}) stake_xprv=$(cardano-address key child 1852H/1815H/0H/2/0 <<< ${root_prv}) payment_xpub=$(cardano-address key public <<< ${payment_xprv}) @@ -431,11 +411,11 @@ function main { [[ "${NETWORKID}" = "Mainnet" ]] && network_tag=1 || network_tag=0 base_addr_candidate=$(cardano-address address delegation ${stake_xpub} <<< "$(cardano-address address payment --network-tag ${network_tag} <<< ${payment_xpub})") if [[ "${NETWORKID}" = "Testnet" ]]; then - println "LOG" "TestNet, converting address to 'addr_test'" + println LOG "TestNet, converting address to 'addr_test'" base_addr_candidate=$(bech32 addr_test <<< ${base_addr_candidate}) fi - println "LOG" "Base address candidate = ${base_addr_candidate}" - println "LOG" "Address Inspection:\n$(cardano-address address inspect <<< ${base_addr_candidate})" + println LOG "Base address candidate = ${base_addr_candidate}" + println LOG "Address Inspection:\n$(cardano-address address inspect <<< ${base_addr_candidate})" pes_key=$(bech32 <<< ${payment_xprv} | cut -b -128)$(bech32 <<< ${payment_xpub}) ses_key=$(bech32 <<< ${stake_xprv} | cut -b -128)$(bech32 <<< ${stake_xpub}) cat <<-EOF > "${payment_sk_file}" @@ -452,30 +432,30 @@ function main { "cborHex": "5880${ses_key}" } EOF - println "ACTION" "${CCLI} key verification-key --signing-key-file ${payment_sk_file} --verification-key-file ${TMP_DIR}/payment.evkey" + println ACTION "${CCLI} key verification-key --signing-key-file ${payment_sk_file} --verification-key-file ${TMP_DIR}/payment.evkey" if ! ${CCLI} key verification-key --signing-key-file "${payment_sk_file}" --verification-key-file "${TMP_DIR}/payment.evkey"; then - println "ERROR" "\n${FG_RED}ERROR${NC}: failure during payment signing key extraction!"; safeDel "${WALLET_FOLDER}/${wallet_name}"; waitForInput && continue + println ERROR "\n${FG_RED}ERROR${NC}: failure during payment signing key extraction!"; safeDel "${WALLET_FOLDER}/${wallet_name}"; waitForInput && continue fi - println "ACTION" "${CCLI} key verification-key --signing-key-file ${stake_sk_file} --verification-key-file ${TMP_DIR}/stake.evkey" + println ACTION "${CCLI} key verification-key --signing-key-file ${stake_sk_file} --verification-key-file ${TMP_DIR}/stake.evkey" if ! ${CCLI} key verification-key --signing-key-file "${stake_sk_file}" --verification-key-file "${TMP_DIR}/stake.evkey"; then - println "ERROR" "\n${FG_RED}ERROR${NC}: failure during stake signing key extraction!"; safeDel "${WALLET_FOLDER}/${wallet_name}"; waitForInput && continue + println ERROR "\n${FG_RED}ERROR${NC}: failure during stake signing key extraction!"; safeDel "${WALLET_FOLDER}/${wallet_name}"; waitForInput && continue fi - println "ACTION" "${CCLI} key non-extended-key --extended-verification-key-file ${TMP_DIR}/payment.evkey --verification-key-file ${payment_vk_file}" + println ACTION "${CCLI} key non-extended-key --extended-verification-key-file ${TMP_DIR}/payment.evkey --verification-key-file ${payment_vk_file}" if ! ${CCLI} key non-extended-key --extended-verification-key-file "${TMP_DIR}/payment.evkey" --verification-key-file "${payment_vk_file}"; then - println "ERROR" "\n${FG_RED}ERROR${NC}: failure during payment verification key extraction!"; safeDel "${WALLET_FOLDER}/${wallet_name}"; waitForInput && continue + println ERROR "\n${FG_RED}ERROR${NC}: failure during payment verification key extraction!"; safeDel "${WALLET_FOLDER}/${wallet_name}"; waitForInput && continue fi - println "ACTION" "${CCLI} key non-extended-key --extended-verification-key-file ${TMP_DIR}/stake.evkey --verification-key-file ${stake_vk_file}" + println ACTION "${CCLI} key non-extended-key --extended-verification-key-file ${TMP_DIR}/stake.evkey --verification-key-file ${stake_vk_file}" if ! ${CCLI} key non-extended-key --extended-verification-key-file "${TMP_DIR}/stake.evkey" --verification-key-file "${stake_vk_file}"; then - println "ERROR" "\n${FG_RED}ERROR${NC}: failure during stake verification key extraction!"; safeDel "${WALLET_FOLDER}/${wallet_name}"; waitForInput && continue + println ERROR "\n${FG_RED}ERROR${NC}: failure during stake verification key extraction!"; safeDel "${WALLET_FOLDER}/${wallet_name}"; waitForInput && continue fi chmod 600 "${WALLET_FOLDER}/${wallet_name}/"* getBaseAddress ${wallet_name} getPayAddress ${wallet_name} getRewardAddress ${wallet_name} if [[ ${base_addr} != "${base_addr_candidate}" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: base address generated doesn't match base address candidate." - println "ERROR" "base_addr[${FG_LGRAY}${base_addr}${NC}]\n!=\nbase_addr_candidate[${FG_LGRAY}${base_addr_candidate}${NC}]" - println "ERROR" "Create a GitHub issue and include log file from failed CNTools session." + println ERROR "${FG_RED}ERROR${NC}: base address generated doesn't match base address candidate." + println ERROR "base_addr[${FG_LGRAY}${base_addr}${NC}]\n!=\nbase_addr_candidate[${FG_LGRAY}${base_addr_candidate}${NC}]" + println ERROR "Create a GitHub issue and include log file from failed CNTools session." echo && safeDel "${WALLET_FOLDER}/${wallet_name}" waitForInput && continue fi @@ -484,33 +464,33 @@ function main { println "Address : ${FG_LGRAY}${base_addr}${NC}" println "Enterprise Address : ${FG_LGRAY}${pay_addr}${NC}" echo - println "DEBUG" "You can now send and receive Ada using the above addresses. Note that Enterprise Address will not take part in staking" - println "DEBUG" "Wallet will be automatically registered on chain if you choose to delegate or pledge wallet when registering a stake pool" + println DEBUG "You can now send and receive Ada using the above addresses. Note that Enterprise Address will not take part in staking" + println DEBUG "Wallet will be automatically registered on chain if you choose to delegate or pledge wallet when registering a stake pool" echo - println "DEBUG" "${FG_YELLOW}Using a mnemonic imported wallet in CNTools comes with a few limitations${NC}" + println DEBUG "${FG_YELLOW}Using a mnemonic imported wallet in CNTools comes with a few limitations${NC}" echo - println "DEBUG" "Only the first address in the HD wallet is extracted and because of this the following apply:" - println "DEBUG" " ${FG_LGRAY}>${NC} Address above should match the first address seen in Daedalus/Yoroi, please verify!!!" - println "DEBUG" " ${FG_LGRAY}>${NC} If restored wallet contain funds since before, send all Ada through Daedalus/Yoroi to address shown in CNTools" - println "DEBUG" " ${FG_LGRAY}>${NC} Only use receive address shown in CNTools" - println "DEBUG" " ${FG_LGRAY}>${NC} Only spend Ada from CNTools, if spent through Daedalus/Yoroi balance seen in CNTools wont match" + println DEBUG "Only the first address in the HD wallet is extracted and because of this the following apply:" + println DEBUG " ${FG_LGRAY}>${NC} Address above should match the first address seen in Daedalus/Yoroi, please verify!!!" + println DEBUG " ${FG_LGRAY}>${NC} If restored wallet contain funds since before, send all Ada through Daedalus/Yoroi to address shown in CNTools" + println DEBUG " ${FG_LGRAY}>${NC} Only use receive address shown in CNTools" + println DEBUG " ${FG_LGRAY}>${NC} Only spend Ada from CNTools, if spent through Daedalus/Yoroi balance seen in CNTools wont match" echo - println "DEBUG" "Some of the advantages of using a mnemonic imported wallet instead of CLI are:" - println "DEBUG" " ${FG_LGRAY}>${NC} Wallet can be restored from saved 24 or 15 word mnemonic if keys are lost/deleted" - println "DEBUG" " ${FG_LGRAY}>${NC} Track rewards in Daedalus/Yoroi" + println DEBUG "Some of the advantages of using a mnemonic imported wallet instead of CLI are:" + println DEBUG " ${FG_LGRAY}>${NC} Wallet can be restored from saved 24 or 15 word mnemonic if keys are lost/deleted" + println DEBUG " ${FG_LGRAY}>${NC} Track rewards in Daedalus/Yoroi" echo - println "DEBUG" "Please read more about HD wallets at:" - println "DEBUG" "https://cardano-community.github.io/support-faq/#/wallets?id=heirarchical-deterministic-hd-wallets" + println DEBUG "Please read more about HD wallets at:" + println DEBUG "https://cardano-community.github.io/support-faq/#/wallets?id=heirarchical-deterministic-hd-wallets" waitForInput && continue ;; ################################################################### hardware) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> WALLET >> IMPORT >> HARDWARE WALLET" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" echo - println "DEBUG" "Supported HW wallets: Ledger S, Ledger X, Trezor Model T" + println DEBUG "Supported HW wallets: Ledger S, Ledger X, Trezor Model T" println "Is your hardware wallet one of these models?" select_opt "[y] Yes" "[n] No" case $? in @@ -518,21 +498,21 @@ function main { 1) waitForInput "Unsupported hardware wallet, press any key to return home" && continue ;; esac echo - if ! need_cmd "cardano-hw-cli"; then - println "ERROR" "${FG_RED}ERROR${NC}: cardano-hw-cli executable not found in path!" - println "ERROR" "Please run '${FG_YELLOW}prereqs.sh -w${NC}' to add hardware wallet support and install Vaccumlabs cardano-hw-cli, '${FG_YELLOW}prereqs.sh -h${NC}' shows all available options" + if ! cmdAvailable "cardano-hw-cli" &>/dev/null; then + println ERROR "${FG_RED}ERROR${NC}: cardano-hw-cli executable not found in path!" + println ERROR "Please run '${FG_YELLOW}prereqs.sh -w${NC}' to add hardware wallet support and install Vaccumlabs cardano-hw-cli, '${FG_YELLOW}prereqs.sh -h${NC}' shows all available options" waitForInput && continue fi if ! HWCLIversionCheck; then waitForInput && continue; fi - sleep 0.1 && read -r -p "Name of imported wallet: " wallet_name 2>&6 && println "LOG" "Name of imported wallet: ${wallet_name}" + getAnswerAnyCust wallet_name "Name of imported wallet" # Remove unwanted characters from wallet name wallet_name=${wallet_name//[^[:alnum:]]/_} if [[ -z "${wallet_name}" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: Empty wallet name, please retry!" + println ERROR "${FG_RED}ERROR${NC}: Empty wallet name, please retry!" waitForInput && continue fi if ! mkdir -p "${WALLET_FOLDER}/${wallet_name}"; then - println "ERROR" "${FG_RED}ERROR${NC}: Failed to create directory for wallet:\n${WALLET_FOLDER}/${wallet_name}" + println ERROR "${FG_RED}ERROR${NC}: Failed to create directory for wallet:\n${WALLET_FOLDER}/${wallet_name}" waitForInput && continue fi if [[ $(find "${WALLET_FOLDER}/${wallet_name}" -type f -print0 | wc -c) -gt 0 ]]; then @@ -545,15 +525,15 @@ function main { stake_sk_file="${WALLET_FOLDER}/${wallet_name}/${WALLET_HW_STAKE_SK_FILENAME}" stake_vk_file="${WALLET_FOLDER}/${wallet_name}/${WALLET_STAKE_VK_FILENAME}" if ! unlockHWDevice "extract ${FG_LGRAY}payment keys${NC}"; then safeDel "${WALLET_FOLDER}/${wallet_name}"; continue; fi - println "ACTION" "cardano-hw-cli address key-gen --path 1852H/1815H/0H/0/0 --verification-key-file ${payment_vk_file} --hw-signing-file ${payment_sk_file}" + println ACTION "cardano-hw-cli address key-gen --path 1852H/1815H/0H/0/0 --verification-key-file ${payment_vk_file} --hw-signing-file ${payment_sk_file}" if ! cardano-hw-cli address key-gen --path 1852H/1815H/0H/0/0 --verification-key-file "${payment_vk_file}" --hw-signing-file "${payment_sk_file}"; then - println "ERROR" "\n${FG_RED}ERROR${NC}: failure during payment key extraction!"; safeDel "${WALLET_FOLDER}/${wallet_name}"; waitForInput && continue + println ERROR "\n${FG_RED}ERROR${NC}: failure during payment key extraction!"; safeDel "${WALLET_FOLDER}/${wallet_name}"; waitForInput && continue fi jq '.description = "Payment Hardware Verification Key"' "${payment_vk_file}" > "${TMP_DIR}/$(basename "${payment_vk_file}").tmp" && mv -f "${TMP_DIR}/$(basename "${payment_vk_file}").tmp" "${payment_vk_file}" - println "DEBUG" "${FG_BLUE}INFO${NC}: repeat and follow instructions on hardware device to extract the ${FG_LGRAY}stake keys${NC}" - println "ACTION" "cardano-hw-cli address key-gen --path 1852H/1815H/0H/2/0 --verification-key-file ${stake_vk_file} --hw-signing-file ${stake_sk_file}" + println DEBUG "${FG_BLUE}INFO${NC}: repeat and follow instructions on hardware device to extract the ${FG_LGRAY}stake keys${NC}" + println ACTION "cardano-hw-cli address key-gen --path 1852H/1815H/0H/2/0 --verification-key-file ${stake_vk_file} --hw-signing-file ${stake_sk_file}" if ! cardano-hw-cli address key-gen --path 1852H/1815H/0H/2/0 --verification-key-file "${stake_vk_file}" --hw-signing-file "${stake_sk_file}"; then - println "ERROR" "\n${FG_RED}ERROR${NC}: failure during stake key extraction!"; safeDel "${WALLET_FOLDER}/${wallet_name}"; waitForInput && continue + println ERROR "\n${FG_RED}ERROR${NC}: failure during stake key extraction!"; safeDel "${WALLET_FOLDER}/${wallet_name}"; waitForInput && continue fi jq '.description = "Stake Hardware Verification Key"' "${stake_vk_file}" > "${TMP_DIR}/$(basename "${stake_vk_file}").tmp" && mv -f "${TMP_DIR}/$(basename "${stake_vk_file}").tmp" "${stake_vk_file}" getBaseAddress ${wallet_name} @@ -564,47 +544,47 @@ function main { println "Address : ${FG_LGRAY}${base_addr}${NC}" println "Enterprise Address : ${FG_LGRAY}${pay_addr}${NC}" echo - println "DEBUG" "You can now send and receive Ada using the above addresses. Note that Enterprise Address will not take part in staking" + println DEBUG "You can now send and receive Ada using the above addresses. Note that Enterprise Address will not take part in staking" echo - println "DEBUG" "All transaction signing is now done through hardware device, please follow directions in both CNTools and the device display!" - println "DEBUG" "${FG_YELLOW}Using an imported hardware wallet in CNTools comes with a few limitations${NC}" + println DEBUG "All transaction signing is now done through hardware device, please follow directions in both CNTools and the device display!" + println DEBUG "${FG_YELLOW}Using an imported hardware wallet in CNTools comes with a few limitations${NC}" echo - println "DEBUG" "Most operations like delegation and sending funds is seamless. For pool registration/modification however the following apply:" - println "DEBUG" " ${FG_LGRAY}>${NC} Pool owner has to be a CLI wallet with enough funds to pay for pool registration deposit and transaction fee" - println "DEBUG" " ${FG_LGRAY}>${NC} Add the hardware wallet containing the pledge as a multi-owner to the pool" - println "DEBUG" " ${FG_LGRAY}>${NC} The hardware wallet can be used as the reward wallet, but has to be included as a multi-owner if it should be counted to pledge" + println DEBUG "Most operations like delegation and sending funds is seamless. For pool registration/modification however the following apply:" + println DEBUG " ${FG_LGRAY}>${NC} Pool owner has to be a CLI wallet with enough funds to pay for pool registration deposit and transaction fee" + println DEBUG " ${FG_LGRAY}>${NC} Add the hardware wallet containing the pledge as a multi-owner to the pool" + println DEBUG " ${FG_LGRAY}>${NC} The hardware wallet can be used as the reward wallet, but has to be included as a multi-owner if it should be counted to pledge" echo - println "DEBUG" "Only the first address in the HD wallet is extracted and because of this the following apply if also synced with Daedalus/Yoroi:" - println "DEBUG" " ${FG_LGRAY}>${NC} Address above should match the first address seen in Daedalus/Yoroi, please verify!!!" - println "DEBUG" " ${FG_LGRAY}>${NC} If restored wallet contain funds since before, send all Ada through Daedalus/Yoroi to address shown in CNTools" - println "DEBUG" " ${FG_LGRAY}>${NC} Only use the address shown in CNTools to receive funds" - println "DEBUG" " ${FG_LGRAY}>${NC} Only spend Ada from CNTools, if spent through Daedalus/Yoroi balance seen in CNTools wont match" + println DEBUG "Only the first address in the HD wallet is extracted and because of this the following apply if also synced with Daedalus/Yoroi:" + println DEBUG " ${FG_LGRAY}>${NC} Address above should match the first address seen in Daedalus/Yoroi, please verify!!!" + println DEBUG " ${FG_LGRAY}>${NC} If restored wallet contain funds since before, send all Ada through Daedalus/Yoroi to address shown in CNTools" + println DEBUG " ${FG_LGRAY}>${NC} Only use the address shown in CNTools to receive funds" + println DEBUG " ${FG_LGRAY}>${NC} Only spend Ada from CNTools, if spent through Daedalus/Yoroi balance seen in CNTools wont match" waitForInput && continue ;; ################################################################### esac ;; ################################################################### register) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> WALLET >> REGISTER" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" [[ ! $(ls -A "${WALLET_FOLDER}" 2>/dev/null) ]] && echo && println "${FG_YELLOW}No wallets available!${NC}" && waitForInput && continue if [[ ${CNTOOLS_MODE} = "OFFLINE" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: CNTools started in offline mode, option not available!" + println ERROR "${FG_RED}ERROR${NC}: CNTools started in offline mode, option not available!" waitForInput && continue else if ! selectOpMode; then continue; fi fi echo - println "DEBUG" "# Select wallet to register (only non-registered wallets shown)" + println DEBUG "# Select wallet to register (only non-registered wallets shown)" if [[ ${op_mode} = "online" ]]; then if ! selectWallet "non-reg" "${WALLET_PAY_VK_FILENAME}" "${WALLET_STAKE_VK_FILENAME}"; then [[ "${dir_name}" != "[Esc] Cancel" ]] && waitForInput; continue fi getWalletType ${wallet_name} case $? in - 2) println "ERROR" "${FG_RED}ERROR${NC}: signing keys encrypted, please decrypt before use!" && waitForInput && continue ;; - 3) println "ERROR" "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet!" && waitForInput && continue ;; + 2) println ERROR "${FG_RED}ERROR${NC}: signing keys encrypted, please decrypt before use!" && waitForInput && continue ;; + 3) println ERROR "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet!" && waitForInput && continue ;; esac else if ! selectWallet "non-reg" "${WALLET_PAY_VK_FILENAME}" "${WALLET_STAKE_VK_FILENAME}"; then @@ -616,12 +596,12 @@ function main { getBalance ${base_addr} if [[ ${assets[lovelace]} -gt 0 ]]; then if [[ -n ${wallet_count} && ${wallet_count} -gt ${WALLET_SELECTION_FILTER_LIMIT} ]]; then - println "DEBUG" "$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Funds in wallet:" "$(formatLovelace ${assets[lovelace]})")" + println DEBUG "$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Funds in wallet:" "$(formatLovelace ${assets[lovelace]})")" fi else - println "ERROR" "\n${FG_RED}ERROR${NC}: no funds available in base address for wallet ${FG_GREEN}${wallet_name}${NC}" + println ERROR "\n${FG_RED}ERROR${NC}: no funds available in base address for wallet ${FG_GREEN}${wallet_name}${NC}" stakeAddressDeposit=$(jq -r '.stakeAddressDeposit' <<< "${PROT_PARAMS}") - println "DEBUG" "Funds for key deposit($(formatLovelace ${stakeAddressDeposit}) Ada) + transaction fee needed to register the wallet" + println DEBUG "Funds for key deposit($(formatLovelace ${stakeAddressDeposit}) Ada) + transaction fee needed to register the wallet" waitForInput && continue fi if ! registerStakeWallet ${wallet_name} "true"; then @@ -632,26 +612,26 @@ function main { ;; ################################################################### deregister) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> WALLET >> DE-REGISTER" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" [[ ! $(ls -A "${WALLET_FOLDER}" 2>/dev/null) ]] && echo && println "${FG_YELLOW}No wallets available!${NC}" && waitForInput && continue if [[ ${CNTOOLS_MODE} = "OFFLINE" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: CNTools started in offline mode, option not available!" + println ERROR "${FG_RED}ERROR${NC}: CNTools started in offline mode, option not available!" waitForInput && continue else if ! selectOpMode; then continue; fi fi echo - println "DEBUG" "# Select wallet to de-register (only registered wallets shown)" + println DEBUG "# Select wallet to de-register (only registered wallets shown)" if [[ ${op_mode} = "online" ]]; then if ! selectWallet "reg" "${WALLET_PAY_VK_FILENAME}" "${WALLET_STAKE_VK_FILENAME}"; then [[ "${dir_name}" != "[Esc] Cancel" ]] && waitForInput; continue fi getWalletType ${wallet_name} case $? in - 2) println "ERROR" "${FG_RED}ERROR${NC}: signing keys encrypted, please decrypt before use!" && waitForInput && continue ;; - 3) println "ERROR" "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet!" && waitForInput && continue ;; + 2) println ERROR "${FG_RED}ERROR${NC}: signing keys encrypted, please decrypt before use!" && waitForInput && continue ;; + 3) println ERROR "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet!" && waitForInput && continue ;; esac else if ! selectWallet "reg" "${WALLET_PAY_VK_FILENAME}" "${WALLET_STAKE_VK_FILENAME}"; then @@ -667,8 +647,8 @@ function main { getBaseAddress ${wallet_name} getBalance ${base_addr} if [[ ${assets[lovelace]} -le 0 ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: no funds available in base address for wallet ${FG_GREEN}${wallet_name}${NC}" - println "ERROR" "Funds for transaction fee needed to deregister the wallet" + println ERROR "\n${FG_RED}ERROR${NC}: no funds available in base address for wallet ${FG_GREEN}${wallet_name}${NC}" + println ERROR "Funds for transaction fee needed to deregister the wallet" waitForInput && continue fi if ! deregisterStakeWallet; then @@ -684,12 +664,12 @@ function main { ;; ################################################################### list) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> WALLET >> LIST" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" [[ ! $(ls -A "${WALLET_FOLDER}" 2>/dev/null) ]] && echo && println "${FG_YELLOW}No wallets available!${NC}" && waitForInput && continue if [[ ${CNTOOLS_MODE} = "OFFLINE" ]]; then - println "DEBUG" "${FG_LGRAY}OFFLINE MODE${NC}: CNTools started in offline mode, wallet balance not shown!" + println DEBUG "${FG_LGRAY}OFFLINE MODE${NC}: CNTools started in offline mode, wallet balance not shown!" fi while IFS= read -r -d '' wallet; do wallet_name=$(basename ${wallet}) @@ -757,12 +737,12 @@ function main { ;; ################################################################### show) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> WALLET >> SHOW" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" [[ ! $(ls -A "${WALLET_FOLDER}" 2>/dev/null) ]] && echo && println "${FG_YELLOW}No wallets available!${NC}" && waitForInput && continue if [[ ${CNTOOLS_MODE} = "OFFLINE" ]]; then - println "DEBUG" "${FG_LGRAY}OFFLINE MODE${NC}: CNTools started in offline mode, limited wallet info shown!" + println DEBUG "${FG_LGRAY}OFFLINE MODE${NC}: CNTools started in offline mode, limited wallet info shown!" fi tput sc if ! selectWallet "none" "${WALLET_PAY_VK_FILENAME}"; then @@ -780,66 +760,132 @@ function main { getRewardAddress ${wallet_name} base_lovelace=0 pay_lovelace=0 + declare -A token_data=() + declare -A token_name=() + declare -A assets_total=() if [[ ${CNTOOLS_MODE} = "CONNECTED" ]]; then + # Token Metadata API URLs + case ${NWMAGIC} in + 764824073) token_meta_server="https://tokens.cardano.org/metadata/" ;; # mainnet + 1097911063) token_meta_server="https://metadata.cardano-testnet.iohkdev.io/metadata/" ;; # public testnet + *) token_meta_server="" ;; # Not a valid asset metadata network + esac for i in {1..2}; do if [[ $i -eq 1 ]]; then getBalance ${base_addr}; base_lovelace=${assets[lovelace]}; address_type="Base" else getBalance ${pay_addr}; pay_lovelace=${assets[lovelace]}; address_type="Enterprise"; fi [[ $i -eq 2 && ${utxo_cnt} -eq 0 ]] && continue + + # loop all assets to query metadata register for token data + for asset in "${!assets[@]}"; do + assets_total[${asset}]=$(( assets_total[asset] + assets[asset] )) + [[ ${asset} = "lovelace" ]] && continue + IFS='.' read -ra asset_arr <<< "${asset}" + [[ ${#asset_arr[@]} -eq 1 ]] && asset_name="" || asset_name="${asset_arr[1]}" + tsubject="${asset_arr[0]}$(asciiToHex "${asset_name}")" + if tdata=$(curl -sL -f -m ${CURL_TIMEOUT} ${token_meta_server}${tsubject}); then + token_data[${asset}]="${tdata}" + if tticker=$(jq -er .ticker.value <<< "${tdata}" 2>/dev/null); then token_name[${asset}]="${tticker}" + elif tname=$(jq -er .name.value <<< "${tdata}" 2>/dev/null); then token_name[${asset}]="${tname}" + fi + fi + done + echo println "${FG_LBLUE}${utxo_cnt} UTxO(s)${NC} found for ${FG_GREEN}${address_type}${NC} Address!" if [[ ${utxo_cnt} -gt 0 ]]; then echo - println "DEBUG" "$(printf "%-66s | %${asset_name_maxlen}s | %-${asset_amount_maxlen}s\n" "Hash#Index" "Asset" "Amount")" - println "DEBUG" "$(printf "%67s+%$((asset_name_maxlen+2))s+%$((asset_amount_maxlen+1))s\n" "" "" "" | tr " " "-")" + println DEBUG "$(printf "%-66s ${FG_DGRAY}|${NC} %${asset_name_maxlen}s ${FG_DGRAY}|${NC} %-${asset_amount_maxlen}s\n" "UTxO Hash#Index" "Asset" "Amount")" + println DEBUG "${FG_DGRAY}$(printf "%67s+%$((asset_name_maxlen+2))s+%$((asset_amount_maxlen+1))s\n" "" "" "" | tr " " "-")${NC}" mapfile -d '' utxos_sorted < <(printf '%s\0' "${!utxos[@]}" | sort -z) for utxo in "${utxos_sorted[@]}"; do IFS='.' read -ra utxo_arr <<< "${utxo}" if [[ ${#utxo_arr[@]} -eq 2 && ${utxo_arr[1]} = " Ada" ]]; then - println "DEBUG" "$(printf "%-66s | ${FG_GREEN}%${asset_name_maxlen}s${NC} | ${FG_LBLUE}%-${asset_amount_maxlen}s${NC}\n" "${utxo_arr[0]}" "Ada" "$(formatLovelace ${utxos["${utxo}"]})")" + println DEBUG "$(printf "%-66s ${FG_DGRAY}|${NC} ${FG_GREEN}%${asset_name_maxlen}s${NC} ${FG_DGRAY}|${NC} ${FG_LBLUE}%-${asset_amount_maxlen}s${NC}\n" "${utxo_arr[0]}" "Ada" "$(formatLovelace ${utxos["${utxo}"]})")" else - [[ ${#utxo_arr[@]} -eq 3 ]] && asset_name="${utxo_arr[2]}" || asset_name="." - println "DEBUG" "$(printf "${FG_DGRAY}%10s${NC}${FG_LGRAY}%56s${NC} | ${FG_MAGENTA}%${asset_name_maxlen}s${NC} | ${FG_LBLUE}%-${asset_amount_maxlen}s${NC}\n" "PolID: " "${utxo_arr[1]}" "${asset_name}" "$(formatAsset ${utxos["${utxo}"]})")" + [[ ${#utxo_arr[@]} -eq 3 ]] && asset_name="${utxo_arr[2]}" || asset_name="" + if [[ -n ${token_name[${utxo_arr[1]}.${asset_name}]} ]]; then + tname="${token_name[${utxo_arr[1]}.${asset_name}]}" + else + tname="${asset_name}" + fi + ! assets_id_bech32=$(getAssetIDBech32 ${utxo_arr[1]} ${asset_name}) && continue 3 + println DEBUG "$(printf "${FG_DGRAY}%22s${NC}${FG_LGRAY}%44s${NC} ${FG_DGRAY}|${NC} ${FG_MAGENTA}%${asset_name_maxlen}s${NC} ${FG_DGRAY}|${NC} ${FG_LBLUE}%-${asset_amount_maxlen}s${NC}\n" "Asset Fingerprint: " "${assets_id_bech32}" "${tname}" "$(formatAsset ${utxos["${utxo}"]})")" fi done fi - for utxo_entry in "${utxo_output[@]}"; do println "DEBUG" "${utxo_entry}"; done if [[ ${#assets[@]} -gt 0 ]]; then println "\nASSET SUMMARY: ${FG_LBLUE}${#assets[@]} Asset-Type(s)${NC} $([[ ${#assets[@]} -gt 1 ]] && echo -e "/ ${FG_LBLUE}${#policyIDs[@]} Unique Policy ID(s)${NC}")\n" - println "DEBUG" "$(printf "%${asset_amount_maxlen}s | %-${asset_name_maxlen}s%s\n" "Total Amount" "Asset" "$([[ ${#assets[@]} -gt 1 ]] && echo -e " | PolicyID")")" - println "DEBUG" "$(printf "%$((asset_amount_maxlen+1))s+%$((asset_name_maxlen+2))s%s\n" "" "" "$([[ ${#assets[@]} -gt 1 ]] && printf "+%57s" "")" | tr " " "-")" - println "DEBUG" "$(printf "${FG_LBLUE}%${asset_amount_maxlen}s${NC} | ${FG_GREEN}%-${asset_name_maxlen}s${NC}%s\n" "$(formatLovelace ${assets[lovelace]})" "Ada" "$([[ ${#assets[@]} -gt 1 ]] && echo " |")")" + println DEBUG "$(printf "%${asset_amount_maxlen}s ${FG_DGRAY}|${NC} %-${asset_name_maxlen}s%s\n" "Total Amount" "Asset" "$([[ ${#assets[@]} -gt 1 ]] && echo -e " ${FG_DGRAY}|${NC} Asset Fingerprint")")" + println DEBUG "${FG_DGRAY}$(printf "%$((asset_amount_maxlen+1))s+%$((asset_name_maxlen+2))s%s\n" "" "" "$([[ ${#assets[@]} -gt 1 ]] && printf "+%57s" "")" | tr " " "-")${NC}" + println DEBUG "$(printf "${FG_LBLUE}%${asset_amount_maxlen}s${NC} ${FG_DGRAY}|${NC} ${FG_GREEN}%-${asset_name_maxlen}s${NC}%s\n" "$(formatLovelace ${assets[lovelace]})" "Ada" "$([[ ${#assets[@]} -gt 1 ]] && echo -n " ${FG_DGRAY}|${NC}")")" mapfile -d '' assets_sorted < <(printf '%s\0' "${!assets[@]}" | sort -z) for asset in "${assets_sorted[@]}"; do [[ ${asset} = "lovelace" ]] && continue IFS='.' read -ra asset_arr <<< "${asset}" - [[ ${#asset_arr[@]} -eq 1 ]] && asset_name="." || asset_name="${asset_arr[1]}" - println "DEBUG" "$(printf "${FG_LBLUE}%${asset_amount_maxlen}s${NC} | ${FG_MAGENTA}%-${asset_name_maxlen}s${NC} | ${FG_LGRAY}%s${NC}\n" "$(formatAsset ${assets["${asset}"]})" "${asset_name}" "${asset_arr[0]}")" + [[ ${#asset_arr[@]} -eq 1 ]] && asset_name="" || asset_name="${asset_arr[1]}" + if [[ -n ${token_name[${asset_arr[0]}.${asset_name}]} ]]; then + tname="${token_name[${asset_arr[0]}.${asset_name}]}" + else + tname="${asset_name}" + fi + ! assets_id_bech32=$(getAssetIDBech32 ${asset_arr[0]} ${asset_name}) && continue 2 + println DEBUG "$(printf "${FG_LBLUE}%${asset_amount_maxlen}s${NC} ${FG_DGRAY}|${NC} ${FG_MAGENTA}%-${asset_name_maxlen}s${NC} ${FG_DGRAY}|${NC} ${FG_LGRAY}%s${NC}\n" "$(formatAsset ${assets["${asset}"]})" "${tname}" "${assets_id_bech32}")" done fi - echo -e "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" >&6 done - fi - echo - if [[ ${CNTOOLS_MODE} = "CONNECTED" ]]; then + + if [[ ${#assets_total[@]} -gt 1 ]]; then + echo -e "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" >&6 + println DEBUG "ASSET DETAILS & METADATA\n" + i=1 + for asset in "${!assets_total[@]}"; do + [[ ${asset} = "lovelace" ]] && continue + IFS='.' read -ra asset_arr <<< "${asset}" + [[ ${#asset_arr[@]} -eq 1 ]] && asset_name="" || asset_name="${asset_arr[1]}" + ! assets_id_bech32=$(getAssetIDBech32 ${asset_arr[0]} ${asset_name}) && continue 2 + println DEBUG "$(printf "%20s ${FG_DGRAY}:${NC} ${FG_LGRAY}%s${NC}" "Asset Fingerprint" "${assets_id_bech32}")" + if [[ -n ${token_data[${asset}]} ]]; then + if jq -er .ticker.value <<< "${token_data[${asset}]}" &>/dev/null; then MetaNameColor=${FG_LGRAY}; MetaTickerColor=${FG_MAGENTA}; else MetaNameColor=${FG_MAGENTA}; MetaTickerColor=${FG_LGRAY}; fi + println DEBUG "$(printf "%20s ${FG_DGRAY}:${NC} ${FG_LGRAY}%s${NC}" "PolicyID.AssetName" "${asset}")" + println DEBUG "$(printf "%-21s${FG_DGRAY}%s${NC}" "" ": # METADATA #")" + println DEBUG " $(printf "%18s ${FG_DGRAY}:${NC} ${MetaNameColor}%s${NC}" "Name" "$(jq -r .name.value <<< "${token_data[${asset}]}")")" + println DEBUG " $(printf "%18s ${FG_DGRAY}:${NC} ${FG_LGRAY}%s${NC}" "Description" "$(jq -r .description.value <<< "${token_data[${asset}]}")")" + tticker=$(jq -er .ticker.value <<< "${token_data[${asset}]}") && println DEBUG " $(printf "%18s ${FG_DGRAY}:${NC} ${MetaTickerColor}%s${NC}" "Ticker" "${tticker}")" + turl=$(jq -er .url.value <<< "${token_data[${asset}]}") && println DEBUG " $(printf "%18s ${FG_DGRAY}:${NC} ${FG_LGRAY}%s${NC}" "URL" "${turl}")" + if tlogo=$(jq -er .logo.value <<< "${token_data[${asset}]}"); then + base64 --decode <<< "${tlogo}" 2>/dev/null > "${TMP_DIR}/${assets_id_bech32}.png" + println DEBUG " $(printf "%18s ${FG_DGRAY}:${NC} ${FG_LGRAY}%s${NC}" "Logo" "Extracted to: ${TMP_DIR}/${assets_id_bech32}.png")" + fi + else + println DEBUG "$(printf "%20s ${FG_DGRAY}:${NC} ${FG_LGRAY}%s${NC}$([[ -n ${asset_name} ]] && echo ".")${FG_MAGENTA}%s${NC}" "PolicyID.AssetName" "${asset_arr[0]}" "${asset_name}")" + println DEBUG "$(printf "${FG_DGRAY}%22s${NC} ${FG_YELLOW}%s${NC}" ":" "No metadata registered in Cardano token register for this asset")" + fi + ((i++)) + [[ ${#assets_total[@]} -gt $i ]] && println OFF "${FG_DGRAY} -------------------+---------------------------------------------${NC}" + done + fi + + echo -e "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" >&6 if isWalletRegistered ${wallet_name}; then - println "$(printf "%-20s : ${FG_GREEN}%s${NC}" "Registered" "YES")" + println "$(printf "%-20s ${FG_DGRAY}:${NC} ${FG_GREEN}%s${NC}" "Registered" "YES")" else - println "$(printf "%-20s : ${FG_RED}%s${NC}" "Registered" "NO")" + println "$(printf "%-20s ${FG_DGRAY}:${NC} ${FG_RED}%s${NC}" "Registered" "NO")" fi else - println "$(printf "%-20s : ${FG_LGRAY}%s${NC}" "Registered" "Unknown")" + println "$(printf "%-20s ${FG_DGRAY}:${NC} ${FG_LGRAY}%s${NC}" "Registered" "Unknown")" fi - println "$(printf "%-20s : ${FG_LGRAY}%s${NC}" "Address" "${base_addr}")" - println "$(printf "%-20s : ${FG_LGRAY}%s${NC}" "Enterprise Address" "${pay_addr}")" - println "$(printf "%-20s : ${FG_LGRAY}%s${NC}" "Reward/Stake Address" "${reward_addr}")" + + println "$(printf "%-20s ${FG_DGRAY}:${NC} ${FG_LGRAY}%s${NC}" "Address" "${base_addr}")" + println "$(printf "%-20s ${FG_DGRAY}:${NC} ${FG_LGRAY}%s${NC}" "Enterprise Address" "${pay_addr}")" + println "$(printf "%-20s ${FG_DGRAY}:${NC} ${FG_LGRAY}%s${NC}" "Reward/Stake Address" "${reward_addr}")" if [[ ${CNTOOLS_MODE} = "CONNECTED" ]]; then getRewards ${wallet_name} if [[ "${reward_lovelace}" -ge 0 ]]; then - println "$(printf "%-20s : ${FG_LBLUE}%s${NC} Ada" "Rewards Available" "$(formatLovelace ${reward_lovelace})")" - println "$(printf "%-20s : ${FG_LBLUE}%s${NC} Ada" "Funds + Rewards" "$(formatLovelace $((pay_lovelace + base_lovelace + reward_lovelace)))")" + println "$(printf "%-20s ${FG_DGRAY}:${NC} ${FG_LBLUE}%s${NC} Ada" "Rewards Available" "$(formatLovelace ${reward_lovelace})")" + println "$(printf "%-20s ${FG_DGRAY}:${NC} ${FG_LBLUE}%s${NC} Ada" "Funds + Rewards" "$(formatLovelace $((pay_lovelace + base_lovelace + reward_lovelace)))")" fi getAddressInfo "${base_addr}" - println "$(printf "%-20s : ${FG_LGRAY}%s${NC}" "Encoding" "$(jq -r '.encoding' <<< ${address_info})")" + println "$(printf "%-20s ${FG_DGRAY}:${NC} ${FG_LGRAY}%s${NC}" "Encoding" "$(jq -r '.encoding' <<< ${address_info})")" delegation_pool_id=$(jq -r '.[0].delegation // empty' <<< "${stake_address_info}" 2>/dev/null) if [[ -n ${delegation_pool_id} ]]; then unset poolName @@ -857,21 +903,21 @@ function main { ;; ################################################################### remove) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> WALLET >> REMOVE" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" [[ ! $(ls -A "${WALLET_FOLDER}" 2>/dev/null) ]] && echo && println "${FG_YELLOW}No wallets available!${NC}" && waitForInput && continue if [[ ${CNTOOLS_MODE} = "OFFLINE" ]]; then - println "DEBUG" "${FG_LGRAY}OFFLINE MODE${NC}: CNTools started in offline mode, unable to verify wallet balance" + println DEBUG "${FG_LGRAY}OFFLINE MODE${NC}: CNTools started in offline mode, unable to verify wallet balance" fi echo - println "DEBUG" "# Select wallet to remove" + println DEBUG "# Select wallet to remove" if ! selectWallet "none"; then # ${wallet_name} populated by selectWallet function [[ "${dir_name}" != "[Esc] Cancel" ]] && waitForInput; continue fi echo if [[ ${CNTOOLS_MODE} = "OFFLINE" ]]; then - println "DEBUG" "Are you sure to delete wallet ${FG_GREEN}${wallet_name}${NC}?" + println DEBUG "Are you sure to delete wallet ${FG_GREEN}${wallet_name}${NC}?" select_opt "[y] Yes" "[n] No" case $? in 0) echo && safeDel "${WALLET_FOLDER:?}/${wallet_name}" @@ -882,8 +928,8 @@ function main { waitForInput && continue fi if ! getBaseAddress ${wallet_name} && ! getPayAddress ${wallet_name}; then - println "DEBUG" "${FG_RED}WARN${NC}: unable to get address for wallet and do a balance check" - println "DEBUG" "\nAre you sure to delete wallet ${FG_GREEN}${wallet_name}${NC} anyway?" + println DEBUG "${FG_RED}WARN${NC}: unable to get address for wallet and do a balance check" + println DEBUG "\nAre you sure to delete wallet ${FG_GREEN}${wallet_name}${NC} anyway?" select_opt "[y] Yes" "[n] No" case $? in 0) echo && safeDel "${WALLET_FOLDER:?}/${wallet_name}" @@ -907,9 +953,9 @@ function main { fi getRewards ${wallet_name} if [[ ${base_lovelace} -eq 0 && ${pay_lovelace} -eq 0 && ${reward_lovelace} -le 0 ]]; then - println "DEBUG" "INFO: This wallet appears to be empty" - println "DEBUG" "${FG_RED}WARN${NC}: Deleting this wallet is final and you can not recover it unless you have a backup\n" - println "DEBUG" "Are you sure to delete wallet ${FG_GREEN}${wallet_name}${NC}?" + println DEBUG "INFO: This wallet appears to be empty" + println DEBUG "${FG_RED}WARN${NC}: Deleting this wallet is final and you can not recover it unless you have a backup\n" + println DEBUG "Are you sure to delete wallet ${FG_GREEN}${wallet_name}${NC}?" select_opt "[y] Yes" "[n] No" case $? in 0) echo && safeDel "${WALLET_FOLDER:?}/${wallet_name}" @@ -923,8 +969,8 @@ function main { [[ ${pay_lovelace} -gt 0 ]] && println "Enterprise Funds : ${FG_LBLUE}$(formatLovelace ${base_lovelace})${NC} Ada" [[ ${reward_lovelace} -gt 0 ]] && println "Rewards : ${FG_LBLUE}$(formatLovelace ${reward_lovelace})${NC} Ada" echo - println "DEBUG" "${FG_RED}WARN${NC}: Deleting this wallet is final and you can not recover it unless you have a backup\n" - println "DEBUG" "Are you sure to delete wallet ${FG_GREEN}${wallet_name}${NC}?" + println DEBUG "${FG_RED}WARN${NC}: Deleting this wallet is final and you can not recover it unless you have a backup\n" + println DEBUG "Are you sure to delete wallet ${FG_GREEN}${wallet_name}${NC}?" select_opt "[y] Yes" "[n] No" case $? in 0) echo && safeDel "${WALLET_FOLDER:?}/${wallet_name}" @@ -937,30 +983,30 @@ function main { ;; ################################################################### decrypt) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> WALLET >> DECRYPT" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" echo [[ ! $(ls -A "${WALLET_FOLDER}" 2>/dev/null) ]] && println "${FG_YELLOW}No wallets available!${NC}" && waitForInput && continue - println "DEBUG" "# Select wallet to decrypt" + println DEBUG "# Select wallet to decrypt" if ! selectWallet "encrypted"; then # ${wallet_name} populated by selectWallet function [[ "${dir_name}" != "[Esc] Cancel" ]] && waitForInput; continue fi filesUnlocked=0 keysDecrypted=0 echo - println "DEBUG" "# Removing write protection from all wallet files" + println DEBUG "# Removing write protection from all wallet files" while IFS= read -r -d '' file; do unlockFile "${file}" filesUnlocked=$((++filesUnlocked)) - println "DEBUG" "${file}" + println DEBUG "${file}" done < <(find "${WALLET_FOLDER}/${wallet_name}" -mindepth 1 -maxdepth 1 -type f -print0) if [[ $(find "${WALLET_FOLDER}/${wallet_name}" -mindepth 1 -maxdepth 1 -type f -name '*.gpg' -print0 | wc -c) -gt 0 ]]; then echo - println "DEBUG" "# Decrypting GPG encrypted wallet files" + println DEBUG "# Decrypting GPG encrypted wallet files" echo - if ! getPassword; then # $password variable populated by getPassword function - println "\n\n" && println "ERROR" "${FG_RED}ERROR${NC}: password input aborted!" + if ! getPasswordCust; then # $password variable populated by getPasswordCust function + println "\n\n" && println ERROR "${FG_RED}ERROR${NC}: password input aborted!" waitForInput && continue fi while IFS= read -r -d '' file; do @@ -976,19 +1022,19 @@ function main { println "Files decrypted : ${FG_LBLUE}${keysDecrypted}${NC}" if [[ ${filesUnlocked} -ne 0 || ${keysDecrypted} -ne 0 ]]; then echo - println "DEBUG" "${FG_YELLOW}Wallet files are now unprotected${NC}" - println "DEBUG" "Use 'WALLET >> ENCRYPT' to re-lock" + println DEBUG "${FG_YELLOW}Wallet files are now unprotected${NC}" + println DEBUG "Use 'WALLET >> ENCRYPT' to re-lock" fi waitForInput && continue ;; ################################################################### encrypt) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> WALLET >> ENCRYPT" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" echo [[ ! $(ls -A "${WALLET_FOLDER}" 2>/dev/null) ]] && echo && println "${FG_YELLOW}No wallets available!${NC}" && waitForInput && continue - println "DEBUG" "# Select wallet to encrypt" + println DEBUG "# Select wallet to encrypt" if ! selectWallet "encrypted"; then # ${wallet_name} populated by selectWallet function [[ "${dir_name}" != "[Esc] Cancel" ]] && waitForInput; continue fi @@ -996,10 +1042,10 @@ function main { keysEncrypted=0 if [[ $(find "${WALLET_FOLDER}/${wallet_name}" -mindepth 1 -maxdepth 1 -type f -name '*.gpg' -print0 | wc -c) -le 0 ]]; then echo - println "DEBUG" "# Encrypting sensitive wallet keys with GPG" + println DEBUG "# Encrypting sensitive wallet keys with GPG" echo - if ! getPassword confirm; then # $password variable populated by getPassword function - println "\n\n" && println "ERROR" "${FG_RED}ERROR${NC}: password input aborted!" + if ! getPasswordCust confirm; then # $password variable populated by getPasswordCust function + println "\n\n" && println ERROR "${FG_RED}ERROR${NC}: password input aborted!" waitForInput && continue fi keyFiles=( @@ -1016,16 +1062,16 @@ function main { unset password else echo - println "DEBUG" "${FG_YELLOW}NOTE${NC}: found GPG encrypted files in folder, please decrypt/unlock wallet files before encrypting" + println DEBUG "${FG_YELLOW}NOTE${NC}: found GPG encrypted files in folder, please decrypt/unlock wallet files before encrypting" waitForInput && continue fi echo - println "DEBUG" "# Write protecting all wallet keys with 400 permission and if enabled 'chattr +i'" + println DEBUG "# Write protecting all wallet keys with 400 permission and if enabled 'chattr +i'" while IFS= read -r -d '' file; do [[ ${file} = *.addr ]] && continue lockFile "${file}" filesLocked=$((++filesLocked)) - println "DEBUG" "${file}" + println DEBUG "${file}" done < <(find "${WALLET_FOLDER}/${wallet_name}" -mindepth 1 -maxdepth 1 -type f -print0) echo println "Wallet protected : ${FG_GREEN}${wallet_name}${NC}" @@ -1033,8 +1079,8 @@ function main { println "Files encrypted : ${FG_LBLUE}${keysEncrypted}${NC}" if [[ ${filesLocked} -ne 0 || ${keysEncrypted} -ne 0 ]]; then echo - println "DEBUG" "${FG_BLUE}INFO${NC}: wallet files are now protected" - println "DEBUG" "Use 'WALLET >> DECRYPT' to unlock" + println DEBUG "${FG_BLUE}INFO${NC}: wallet files are now protected" + println DEBUG "Use 'WALLET >> DECRYPT' to unlock" fi waitForInput && continue ;; ################################################################### @@ -1042,15 +1088,15 @@ function main { ;; ################################################################### funds) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> FUNDS" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - println "OFF" " Handle Funds\n"\ + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println OFF " Handle Funds\n"\ " ) Send - send Ada and/or custom Assets from a local wallet"\ " ) Delegate - delegate wallet to a pool"\ " ) Withdraw - withdraw earned rewards to base address"\ "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - println "DEBUG" " Select Funds Operation\n" + println DEBUG " Select Funds Operation\n" select_opt "[s] Send" "[d] Delegate" "[w] Withdraw Rewards" "[h] Home" case $? in 0) SUBCOMMAND="send" ;; @@ -1061,27 +1107,27 @@ function main { case $SUBCOMMAND in send) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> FUNDS >> SEND" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" [[ ! $(ls -A "${WALLET_FOLDER}" 2>/dev/null) ]] && echo && println "${FG_YELLOW}No wallets available!${NC}" && waitForInput && continue if [[ ${CNTOOLS_MODE} = "OFFLINE" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: CNTools started in offline mode, option not available!" + println ERROR "${FG_RED}ERROR${NC}: CNTools started in offline mode, option not available!" waitForInput && continue else if ! selectOpMode; then continue; fi fi echo - println "DEBUG" "# Select ${FG_YELLOW}source${NC} wallet" + println DEBUG "# Select ${FG_YELLOW}source${NC} wallet" if [[ ${op_mode} = "online" ]]; then if ! selectWallet "balance" "${WALLET_PAY_VK_FILENAME}"; then # ${wallet_name} populated by selectWallet function [[ "${dir_name}" != "[Esc] Cancel" ]] && waitForInput; continue fi getWalletType ${wallet_name} case $? in - 2) println "ERROR" "${FG_RED}ERROR${NC}: signing keys encrypted, please decrypt before use!" && waitForInput && continue ;; - 3) println "ERROR" "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet!" && waitForInput && continue ;; + 2) println ERROR "${FG_RED}ERROR${NC}: signing keys encrypted, please decrypt before use!" && waitForInput && continue ;; + 3) println ERROR "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet!" && waitForInput && continue ;; esac else if ! selectWallet "balance" "${WALLET_PAY_VK_FILENAME}"; then # ${wallet_name} populated by selectWallet function @@ -1101,10 +1147,10 @@ function main { pay_lovelace=${assets[lovelace]} if [[ ${pay_lovelace} -gt 0 && ${base_lovelace} -gt 0 ]]; then # Both payment and base address available with funds, let user choose what to use - println "DEBUG" "Select source wallet address" + println DEBUG "Select source wallet address" if [[ -n ${wallet_count} && ${wallet_count} -gt ${WALLET_SELECTION_FILTER_LIMIT} ]]; then - println "DEBUG" "$(printf "%s\t\t${FG_LBLUE}%s${NC} Ada" "Funds :" "$(formatLovelace ${base_lovelace})")" - println "DEBUG" "$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Enterprise Funds :" "$(formatLovelace ${pay_lovelace})")" + println DEBUG "$(printf "%s\t\t${FG_LBLUE}%s${NC} Ada" "Funds :" "$(formatLovelace ${base_lovelace})")" + println DEBUG "$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Enterprise Funds :" "$(formatLovelace ${pay_lovelace})")" fi echo select_opt "[b] Base (default)" "[e] Enterprise" "[Esc] Cancel" @@ -1117,15 +1163,15 @@ function main { elif [[ ${pay_lovelace} -gt 0 ]]; then s_addr="${pay_addr}" if [[ -n ${wallet_count} && ${wallet_count} -gt ${WALLET_SELECTION_FILTER_LIMIT} ]]; then - println "DEBUG" "$(printf "%s\t${FG_LBLUE}%s${NC} Ada\n" "Enterprise Funds :" "$(formatLovelace ${pay_lovelace})")" + println DEBUG "$(printf "%s\t${FG_LBLUE}%s${NC} Ada\n" "Enterprise Funds :" "$(formatLovelace ${pay_lovelace})")" fi elif [[ ${base_lovelace} -gt 0 ]]; then s_addr="${base_addr}" if [[ -n ${wallet_count} && ${wallet_count} -gt ${WALLET_SELECTION_FILTER_LIMIT} ]]; then - println "DEBUG" "$(printf "%s\t\t${FG_LBLUE}%s${NC} Ada\n" "Funds :" "$(formatLovelace ${base_lovelace})")" + println DEBUG "$(printf "%s\t\t${FG_LBLUE}%s${NC} Ada\n" "Funds :" "$(formatLovelace ${base_lovelace})")" fi else - println "ERROR" "${FG_RED}ERROR${NC}: no funds available for wallet ${FG_GREEN}${s_wallet}${NC}" + println ERROR "${FG_RED}ERROR${NC}: no funds available for wallet ${FG_GREEN}${s_wallet}${NC}" waitForInput && continue fi @@ -1136,17 +1182,17 @@ function main { done minUTxOValue=$(jq -r '.minUTxOValue //1000000' <<< "${PROT_PARAMS}") # Amount - println "DEBUG" "# Amount to Send (in Ada)" - println "DEBUG" " Valid entry:" - println "DEBUG" " ${FG_LGRAY}>${NC} Integer (e.g. 15) or Decimal (e.g. 956.1235), commas allowed as thousand separator" - println "DEBUG" " ${FG_LGRAY}>${NC} The string '${FG_YELLOW}all${NC}' sends all available funds in source wallet" - println "DEBUG" " Multi-Asset Info:" - println "DEBUG" " ${FG_LGRAY}>${NC} If '${FG_YELLOW}all${NC}' is used and the wallet contain multiple assets," - println "DEBUG" " ${FG_LGRAY}>${NC} then all assets will be transferred(incl Ada) to the destination address" - println "DEBUG" " Minimum Amount: ${FG_LBLUE}$(formatLovelace ${minUTxOValue})${NC} Ada" - println "DEBUG" " ${FG_LGRAY}>${NC} To calculate the minimum Ada required if additional assets/tokens are to be sent,"\ + println DEBUG "# Amount to Send (in Ada)" + println DEBUG " Valid entry:" + println DEBUG " ${FG_LGRAY}>${NC} Integer (e.g. 15) or Decimal (e.g. 956.1235), commas allowed as thousand separator" + println DEBUG " ${FG_LGRAY}>${NC} The string '${FG_YELLOW}all${NC}' sends all available funds in source wallet" + println DEBUG " Multi-Asset Info:" + println DEBUG " ${FG_LGRAY}>${NC} If '${FG_YELLOW}all${NC}' is used and the wallet contain multiple assets," + println DEBUG " ${FG_LGRAY}>${NC} then all assets will be transferred(incl Ada) to the destination address" + println DEBUG " Minimum Amount: ${FG_LBLUE}$(formatLovelace ${minUTxOValue})${NC} Ada" + println DEBUG " ${FG_LGRAY}>${NC} To calculate the minimum Ada required if additional assets/tokens are to be sent,"\ " make a dummy transaction with ${FG_LBLUE}0${NC} Ada selecting the tokens to send with the correct amount\n" - sleep 0.1 && read -r -p "Amount (Ada): " amountADA 2>&6 && println "LOG" "Amount (Ada): ${amountADA}" + getAnswerAnyCust amountADA "Amount (Ada)" amountADA="${amountADA//,}" echo if [[ ${amountADA} != "all" ]]; then @@ -1154,8 +1200,8 @@ function main { waitForInput && continue fi amount_lovelace=$(AdaToLovelace "${amountADA}") - [[ ${amount_lovelace} -gt ${assets[lovelace]} ]] && println "ERROR" "${FG_RED}ERROR${NC}: not enough funds on address, ${FG_LBLUE}$(formatLovelace ${assets[lovelace]})${NC} Ada available but trying to send ${FG_LBLUE}$(formatLovelace ${amount_lovelace})${NC} Ada" && waitForInput && continue - println "DEBUG" "Fee payed by sender? [else amount sent is reduced]" + [[ ${amount_lovelace} -gt ${assets[lovelace]} ]] && println ERROR "${FG_RED}ERROR${NC}: not enough funds on address, ${FG_LBLUE}$(formatLovelace ${assets[lovelace]})${NC} Ada available but trying to send ${FG_LBLUE}$(formatLovelace ${amount_lovelace})${NC} Ada" && waitForInput && continue + println DEBUG "Fee payed by sender? [else amount sent is reduced]" select_opt "[y] Yes" "[n] No" "[Esc] Cancel" case $? in 0) include_fee="no" ;; @@ -1164,7 +1210,7 @@ function main { esac else amount_lovelace=${assets[lovelace]} - println "DEBUG" "Ada to send set to total supply: ${FG_LBLUE}$(formatLovelace ${amount_lovelace})${NC}" + println DEBUG "Ada to send set to total supply: ${FG_LBLUE}$(formatLovelace ${amount_lovelace})${NC}" include_fee="yes" fi echo @@ -1181,7 +1227,7 @@ function main { # Add additional assets to transaction? if [[ ${#assets_left[@]} -gt 0 && ${#assets[@]} -gt 1 ]]; then - println "DEBUG" "Additional assets found on address, include in transaction?" + println DEBUG "Additional assets found on address, include in transaction?" asset_cnt=1 select_opt "[n] No" "[y] Yes" "[Esc] Cancel" case $? in @@ -1195,13 +1241,13 @@ function main { select_opt "${!assets_on_addr[@]}" "[Esc] Cancel" selection=$? [[ ${selected_value} = "[Esc] Cancel" ]] && continue 2 - println "DEBUG" "Available to send: ${FG_LBLUE}$(formatAsset ${assets[${selected_value}]})${NC}" - sleep 0.1 && read -r -p "Amount (commas allowed as thousand separator): " asset_amount 2>&6 && println "LOG" "Amount (commas allowed as thousand separator): ${asset_amount}" + println DEBUG "Available to send: ${FG_LBLUE}$(formatAsset ${assets[${selected_value}]})${NC}" + getAnswerAnyCust asset_amount "Amount (commas allowed as thousand separator)" asset_amount="${asset_amount//,}" [[ ${asset_amount} = "all" ]] && asset_amount=${assets[${selected_value}]} - if ! isNumber ${asset_amount}; then println "ERROR" "${FG_RED}ERROR${NC}: invalid number, non digit characters found!" && continue; fi + if ! isNumber ${asset_amount}; then println ERROR "${FG_RED}ERROR${NC}: invalid number, non digit characters found!" && continue; fi if [[ ${asset_amount} -gt ${assets[${selected_value}]} ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: you cant send more assets than available on address!" && continue + println ERROR "${FG_RED}ERROR${NC}: you cant send more assets than available on address!" && continue elif [[ ${asset_amount} -eq ${assets[${selected_value}]} ]]; then unset assets_left[${selected_value}] else @@ -1210,7 +1256,7 @@ function main { assets_to_send[${selected_value}]=${asset_amount} unset assets_on_addr[${selected_value}] [[ $((++asset_cnt)) -eq ${#assets[@]} ]] && break - println "DEBUG" "Add more assets?" + println DEBUG "Add more assets?" select_opt "[n] No" "[y] Yes" "[Esc] Cancel" case $? in 0) break ;; @@ -1225,7 +1271,7 @@ function main { fi # Destination d_wallet="" - println "DEBUG" "# Select ${FG_YELLOW}destination${NC} type" + println DEBUG "# Select ${FG_YELLOW}destination${NC} type" select_opt "[w] Wallet" "[a] Address" "[Esc] Cancel" case $? in 0) if ! selectWallet "balance"; then # ${wallet_name} populated by selectWallet function @@ -1247,19 +1293,19 @@ function main { elif [[ -n "${pay_addr}" && "${pay_addr}" != "${s_addr}" ]]; then d_addr="${pay_addr}" elif [[ "${base_addr}" = "${s_addr}" || "${pay_addr}" = "${s_addr}" ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: sending to same address as source not supported" + println ERROR "\n${FG_RED}ERROR${NC}: sending to same address as source not supported" waitForInput && continue else - println "ERROR" "\n${FG_RED}ERROR${NC}: no address found for wallet ${FG_GREEN}${d_wallet}${NC} :(" + println ERROR "\n${FG_RED}ERROR${NC}: no address found for wallet ${FG_GREEN}${d_wallet}${NC} :(" waitForInput && continue fi ;; - 1) sleep 0.1 && read -r -p "Address: " d_addr 2>&6 && println "LOG" "Address: ${d_addr}" ;; + 1) getAnswerAnyCust d_addr "Address" ;; 2) continue ;; esac # Destination could be empty, if so without getting a valid address if [[ -z ${d_addr} ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: destination address field empty" + println ERROR "${FG_RED}ERROR${NC}: destination address field empty" waitForInput && continue fi if ! sendAssets; then @@ -1295,26 +1341,26 @@ function main { ;; ################################################################### delegate) # [WALLET NAME] [POOL NAME] clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> FUNDS >> DELEGATE" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" [[ ! $(ls -A "${WALLET_FOLDER}" 2>/dev/null) ]] && echo && println "${FG_YELLOW}No wallets available!${NC}" && waitForInput && continue if [[ ${CNTOOLS_MODE} = "OFFLINE" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: CNTools started in offline mode, option not available!" + println ERROR "${FG_RED}ERROR${NC}: CNTools started in offline mode, option not available!" waitForInput && continue else if ! selectOpMode; then continue; fi fi echo - println "DEBUG" "# Select wallet to delegate" + println DEBUG "# Select wallet to delegate" if [[ ${op_mode} = "online" ]]; then if ! selectWallet "delegate" "${WALLET_PAY_VK_FILENAME}" "${WALLET_STAKE_VK_FILENAME}"; then # ${wallet_name} populated by selectWallet function [[ "${dir_name}" != "[Esc] Cancel" ]] && waitForInput; continue fi getWalletType ${wallet_name} case $? in - 2) println "ERROR" "${FG_RED}ERROR${NC}: signing keys encrypted, please decrypt before use!" && waitForInput && continue ;; - 3) println "ERROR" "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet!" && waitForInput && continue ;; + 2) println ERROR "${FG_RED}ERROR${NC}: signing keys encrypted, please decrypt before use!" && waitForInput && continue ;; + 3) println ERROR "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet!" && waitForInput && continue ;; esac else if ! selectWallet "delegate" "${WALLET_PAY_VK_FILENAME}" "${WALLET_STAKE_VK_FILENAME}"; then # ${wallet_name} populated by selectWallet function @@ -1326,10 +1372,10 @@ function main { getBalance ${base_addr} if [[ ${assets[lovelace]} -gt 0 ]]; then if [[ -n ${wallet_count} && ${wallet_count} -gt ${WALLET_SELECTION_FILTER_LIMIT} ]]; then - println "DEBUG" "$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Funds in wallet:" "$(formatLovelace ${assets[lovelace]})")" + println DEBUG "$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Funds in wallet:" "$(formatLovelace ${assets[lovelace]})")" fi else - println "ERROR" "\n${FG_RED}ERROR${NC}: no funds available for wallet ${FG_GREEN}${wallet_name}${NC}" + println ERROR "\n${FG_RED}ERROR${NC}: no funds available for wallet ${FG_GREEN}${wallet_name}${NC}" waitForInput && continue fi getRewards ${wallet_name} @@ -1338,13 +1384,13 @@ function main { if [[ ${op_mode} = "online" ]]; then if ! registerStakeWallet ${wallet_name}; then waitForInput && continue; fi else - println "ERROR" "\n${FG_YELLOW}The wallet is not a registered wallet on chain and CNTools run in hybrid mode${NC}" - println "ERROR" "Please first register the wallet using 'Wallet >> Register'" + println ERROR "\n${FG_YELLOW}The wallet is not a registered wallet on chain and CNTools run in hybrid mode${NC}" + println ERROR "Please first register the wallet using 'Wallet >> Register'" waitForInput && continue fi fi echo - println "DEBUG" "Do you want to delegate to a local CNTools pool or specify the pool ID?" + println DEBUG "Do you want to delegate to a local CNTools pool or specify the pool ID?" select_opt "[p] CNTools Pool" "[i] Pool ID" "[Esc] Cancel" case $? in 0) if ! selectPool "reg" "${POOL_COLDKEY_VK_FILENAME}"; then # ${pool_name} populated by selectPool function @@ -1352,7 +1398,7 @@ function main { fi getPoolID "${pool_name}" ;; - 1) sleep 0.1 && read -r -p "Pool ID (blank to cancel): " pool_id 2>&6 && println "LOG" "Pool ID (blank to cancel): ${pool_id}" + 1) getAnswerAnyCust pool_id "Pool ID (blank to cancel)" [[ -z "${pool_id}" ]] && continue pool_name="${pool_id}" ;; @@ -1360,11 +1406,11 @@ function main { esac stake_vk_file="${WALLET_FOLDER}/${wallet_name}/${WALLET_STAKE_VK_FILENAME}" pool_delegcert_file="${WALLET_FOLDER}/${wallet_name}/${WALLET_DELEGCERT_FILENAME}" - println "ACTION" "${CCLI} stake-address delegation-certificate --stake-verification-key-file ${stake_vk_file} --stake-pool-id ${pool_id} --out-file ${pool_delegcert_file}" + println ACTION "${CCLI} stake-address delegation-certificate --stake-verification-key-file ${stake_vk_file} --stake-pool-id ${pool_id} --out-file ${pool_delegcert_file}" ${CCLI} stake-address delegation-certificate --stake-verification-key-file "${stake_vk_file}" --stake-pool-id "${pool_id}" --out-file "${pool_delegcert_file}" if ! delegate; then if [[ ${op_mode} = "online" ]]; then - echo && println "ERROR" "${FG_RED}ERROR${NC}: failure during delegation, removing newly created delegation certificate file" + echo && println ERROR "${FG_RED}ERROR${NC}: failure during delegation, removing newly created delegation certificate file" rm -f "${pool_delegcert_file}" fi waitForInput && continue @@ -1380,26 +1426,26 @@ function main { ;; ################################################################### withdrawrewards) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> FUNDS >> WITHDRAW REWARDS" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" [[ ! $(ls -A "${WALLET_FOLDER}" 2>/dev/null) ]] && echo && println "${FG_YELLOW}No wallets available!${NC}" && waitForInput && continue if [[ ${CNTOOLS_MODE} = "OFFLINE" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: CNTools started in offline mode, option not available!" + println ERROR "${FG_RED}ERROR${NC}: CNTools started in offline mode, option not available!" waitForInput && continue else if ! selectOpMode; then continue; fi fi echo - println "DEBUG" "# Select wallet to withdraw funds from" + println DEBUG "# Select wallet to withdraw funds from" if [[ ${op_mode} = "online" ]]; then if ! selectWallet "reward" "${WALLET_PAY_VK_FILENAME}" "${WALLET_STAKE_VK_FILENAME}"; then # ${wallet_name} populated by selectWallet function [[ "${dir_name}" != "[Esc] Cancel" ]] && waitForInput; continue fi getWalletType ${wallet_name} case $? in - 2) println "ERROR" "${FG_RED}ERROR${NC}: signing keys encrypted, please decrypt before use!" && waitForInput && continue ;; - 3) println "ERROR" "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet!" && waitForInput && continue ;; + 2) println ERROR "${FG_RED}ERROR${NC}: signing keys encrypted, please decrypt before use!" && waitForInput && continue ;; + 3) println ERROR "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet!" && waitForInput && continue ;; esac else if ! selectWallet "reward" "${WALLET_PAY_VK_FILENAME}" "${WALLET_STAKE_VK_FILENAME}"; then # ${wallet_name} populated by selectWallet function @@ -1412,14 +1458,14 @@ function main { getBalance ${base_addr} getRewards ${wallet_name} if [[ ${reward_lovelace} -le 0 ]]; then - println "ERROR" "Failed to locate any rewards associated with the chosen wallet, please try another one" + println ERROR "Failed to locate any rewards associated with the chosen wallet, please try another one" waitForInput && continue elif [[ ${assets[lovelace]} -eq 0 ]]; then - println "ERROR" "${FG_YELLOW}WARN${NC}: No funds in base address, please send funds to base address of wallet to cover withdraw transaction fee" + println ERROR "${FG_YELLOW}WARN${NC}: No funds in base address, please send funds to base address of wallet to cover withdraw transaction fee" waitForInput && continue fi - println "DEBUG" "$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Funds" "$(formatLovelace ${assets[lovelace]})")" - println "DEBUG" "$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Rewards" "$(formatLovelace ${reward_lovelace})")" + println DEBUG "$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Funds" "$(formatLovelace ${assets[lovelace]})")" + println DEBUG "$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Rewards" "$(formatLovelace ${reward_lovelace})")" if ! withdrawRewards; then waitForInput && continue fi @@ -1437,10 +1483,10 @@ function main { ;; ################################################################### pool) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> POOL" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - println "OFF" " Pool Management\n"\ + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println OFF " Pool Management\n"\ " ) New - create a new pool"\ " ) Register - register created pool on chain using a stake wallet (pledge wallet)"\ " ) Modify - change pool parameters and register updated pool values on chain"\ @@ -1451,7 +1497,7 @@ function main { " ) Decrypt - remove write protection and decrypt pool"\ " ) Encrypt - encrypt pool cold keys and make all files immutable"\ "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - println "DEBUG" " Select Pool Operation\n" + println DEBUG " Select Pool Operation\n" select_opt "[n] New" "[r] Register" "[m] Modify" "[x] Retire" "[l] List" "[s] Show" "[o] Rotate" "[d] Decrypt" "[e] Encrypt" "[h] Home" case $? in 0) SUBCOMMAND="new" ;; @@ -1468,15 +1514,15 @@ function main { case $SUBCOMMAND in new) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> POOL >> NEW" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" echo - sleep 0.1 && read -r -p "Pool Name: " pool_name 2>&6 && println "LOG" "Pool Name: ${pool_name}" + getAnswerAnyCust pool_name "Pool Name" # Remove unwanted characters from pool name pool_name=${pool_name//[^[:alnum:]]/_} if [[ -z "${pool_name}" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: Empty pool name, please retry!" + println ERROR "${FG_RED}ERROR${NC}: Empty pool name, please retry!" waitForInput && continue fi mkdir -p "${POOL_FOLDER}/${pool_name}" @@ -1488,20 +1534,20 @@ function main { pool_vrf_vk_file="${POOL_FOLDER}/${pool_name}/${POOL_VRF_VK_FILENAME}" pool_vrf_sk_file="${POOL_FOLDER}/${pool_name}/${POOL_VRF_SK_FILENAME}" if [[ -f "${pool_hotkey_vk_file}" ]]; then - println "ERROR" "${FG_RED}WARN${NC}: A pool ${FG_GREEN}$pool_name${NC} already exists" - println "ERROR" " Choose another name or delete the existing one" + println ERROR "${FG_RED}WARN${NC}: A pool ${FG_GREEN}$pool_name${NC} already exists" + println ERROR " Choose another name or delete the existing one" waitForInput && continue fi - println "ACTION" "${CCLI} node key-gen-KES --verification-key-file ${pool_hotkey_vk_file} --signing-key-file ${pool_hotkey_sk_file}" + println ACTION "${CCLI} node key-gen-KES --verification-key-file ${pool_hotkey_vk_file} --signing-key-file ${pool_hotkey_sk_file}" ${CCLI} node key-gen-KES --verification-key-file "${pool_hotkey_vk_file}" --signing-key-file "${pool_hotkey_sk_file}" if [ -f "${POOL_FOLDER}-pregen/${pool_name}/${POOL_ID_FILENAME}" ]; then mv ${POOL_FOLDER}'-pregen/'${pool_name}/* ${POOL_FOLDER}/${pool_name}/ rm -r ${POOL_FOLDER}'-pregen/'${pool_name} else - println "ACTION" "${CCLI} node key-gen --cold-verification-key-file ${pool_coldkey_vk_file} --cold-signing-key-file ${pool_coldkey_sk_file} --operational-certificate-issue-counter-file ${pool_opcert_counter_file}" + println ACTION "${CCLI} node key-gen --cold-verification-key-file ${pool_coldkey_vk_file} --cold-signing-key-file ${pool_coldkey_sk_file} --operational-certificate-issue-counter-file ${pool_opcert_counter_file}" ${CCLI} node key-gen --cold-verification-key-file "${pool_coldkey_vk_file}" --cold-signing-key-file "${pool_coldkey_sk_file}" --operational-certificate-issue-counter-file "${pool_opcert_counter_file}" fi - println "ACTION" "${CCLI} node key-gen-VRF --verification-key-file ${pool_vrf_vk_file} --signing-key-file ${pool_vrf_sk_file}" + println ACTION "${CCLI} node key-gen-VRF --verification-key-file ${pool_vrf_vk_file} --signing-key-file ${pool_vrf_sk_file}" ${CCLI} node key-gen-VRF --verification-key-file "${pool_vrf_vk_file}" --signing-key-file "${pool_vrf_sk_file}" chmod 600 "${POOL_FOLDER}/${pool_name}/"* getPoolID ${pool_name} @@ -1513,19 +1559,19 @@ function main { ;; ################################################################### register|modify) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> POOL >> ${SUBCOMMAND^^}" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" [[ ! $(ls -A "${POOL_FOLDER}" 2>/dev/null) ]] && echo && println "${FG_YELLOW}No pools available!${NC}" && waitForInput && continue [[ ! $(ls -A "${WALLET_FOLDER}" 2>/dev/null) ]] && echo && println "${FG_YELLOW}No wallets available!${NC}" && waitForInput && continue if [[ ${CNTOOLS_MODE} = "OFFLINE" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: CNTools started in offline mode, option not available!" + println ERROR "${FG_RED}ERROR${NC}: CNTools started in offline mode, option not available!" waitForInput && continue else if ! selectOpMode; then continue; fi fi echo - println "DEBUG" "# Select pool" + println DEBUG "# Select pool" [[ ${SUBCOMMAND} = "register" ]] && pool_filter="non-reg" || pool_filter="reg" if [[ ${op_mode} = "online" ]]; then if ! selectPool "${pool_filter}" "${POOL_COLDKEY_VK_FILENAME}" "${POOL_COLDKEY_SK_FILENAME}" "${POOL_VRF_VK_FILENAME}"; then # ${pool_name} populated by selectPool function @@ -1538,21 +1584,21 @@ function main { fi echo pool_config="${POOL_FOLDER}/${pool_name}/${POOL_CONFIG_FILENAME}" - println "DEBUG" "# Pool Parameters" + println DEBUG "# Pool Parameters" if [[ ${SUBCOMMAND} = "modify" ]]; then if [[ ! -f ${pool_config} ]]; then println "${FG_YELLOW}WARN${NC}: Missing pool config file: ${pool_config}" println "Unable to show old values, please re-enter all values to generate a new pool config file" else - println "DEBUG" "Old registration values shown as default, press enter to use default value" + println DEBUG "Old registration values shown as default, press enter to use default value" fi else - println "DEBUG" "press enter to use default value" + println DEBUG "press enter to use default value" fi echo pledge_ada=50000 # default pledge [[ -f "${pool_config}" ]] && pledge_ada=$(jq -r '.pledgeADA //0' "${pool_config}") - sleep 0.1 && read -r -p "Pledge (in Ada, default: $(formatAsset ${pledge_ada})): " pledge_enter 2>&6 && println "LOG" "Pledge (in Ada, default: $(formatAsset ${pledge_ada})): ${pledge_enter}" + getAnswerAnyCust pledge_enter "Pledge (in Ada, default: $(formatAsset ${pledge_ada}))" pledge_enter="${pledge_enter//,}" if [[ -n "${pledge_enter}" ]]; then if ! AdaToLovelace "${pledge_enter}" >/dev/null; then @@ -1565,7 +1611,7 @@ function main { fi margin=7.5 # default margin in % [[ -f "${pool_config}" ]] && margin=$(jq -r '.margin //0' "${pool_config}") - sleep 0.1 && read -r -p "Margin (in %, default: ${margin}): " margin_enter 2>&6 && println "LOG" "Margin (in %, default: ${margin}): ${margin_enter}" + getAnswerAnyCust margin_enter "Margin (in %, default: ${margin})" if [[ -n "${margin_enter}" ]]; then if ! pctToFraction "${margin_enter}" >/dev/null; then waitForInput && continue @@ -1578,7 +1624,7 @@ function main { minPoolCost=$(( $(jq -r '.minPoolCost //0' <<< "${PROT_PARAMS}") / 1000000 )) # convert to Ada [[ -f ${pool_config} ]] && cost_ada=$(jq -r '.costADA //0' "${pool_config}") || cost_ada=${minPoolCost} # default cost [[ ${cost_ada} -lt ${minPoolCost} ]] && cost_ada=${minPoolCost} # raise old value to new minimum cost - sleep 0.1 && read -r -p "Cost (in Ada, minimum: ${minPoolCost}, default: $(formatAsset ${cost_ada})): " cost_enter 2>&6 && println "LOG" "Cost (in Ada, minimum: ${minPoolCost}, default: $(formatAsset ${cost_ada})): ${cost_enter}" + getAnswerAnyCust cost_enter "Cost (in Ada, minimum: ${minPoolCost}, default: $(formatAsset ${cost_ada}))" cost_enter="${cost_enter//,}" if [[ -n "${cost_enter}" ]]; then if ! AdaToLovelace "${cost_enter}" >/dev/null; then @@ -1590,28 +1636,28 @@ function main { cost_lovelace=$(AdaToLovelace "${cost_ada}") fi if [[ ${cost_ada} -lt ${minPoolCost} ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: cost set lower than allowed" + println ERROR "\n${FG_RED}ERROR${NC}: cost set lower than allowed" waitForInput && continue fi - println "DEBUG" "\n# Pool Metadata\n" + println DEBUG "\n# Pool Metadata\n" pool_meta_file="${POOL_FOLDER}/${pool_name}/poolmeta.json" if [[ ! -f "${pool_config}" ]] || ! meta_json_url=$(jq -er .json_url "${pool_config}"); then meta_json_url="https://foo.bat/poolmeta.json"; fi - sleep 0.1 && read -r -p "Enter Pool's JSON URL to host metadata file - URL length should be less than 64 chars (default: ${meta_json_url}): " json_url_enter 2>&6 && println "LOG" "Enter Pool's JSON URL to host metadata file - URL length should be less than 64 chars (default: ${meta_json_url}): ${json_url_enter}" + getAnswerAnyCust json_url_enter "Enter Pool's JSON URL to host metadata file - URL length should be less than 64 chars (default: ${meta_json_url})" [[ -n "${json_url_enter}" ]] && meta_json_url="${json_url_enter}" if [[ ! "${meta_json_url}" =~ https?://.* || ${#meta_json_url} -gt 64 ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: invalid URL format or more than 64 chars in length" + println ERROR "${FG_RED}ERROR${NC}: invalid URL format or more than 64 chars in length" waitForInput && continue fi metadata_done=false meta_tmp="${TMP_DIR}/url_poolmeta.json" if curl -sL -f -m ${CURL_TIMEOUT} -o "${meta_tmp}" ${meta_json_url} && jq -er . "${meta_tmp}" &>/dev/null; then - [[ $(wc -c <"${meta_tmp}") -gt 512 ]] && println "ERROR" "${FG_RED}ERROR${NC}: file at specified URL contain more than allowed 512b of data!" && waitForInput && continue + [[ $(wc -c <"${meta_tmp}") -gt 512 ]] && println ERROR "${FG_RED}ERROR${NC}: file at specified URL contain more than allowed 512b of data!" && waitForInput && continue echo && jq -r . "${meta_tmp}" >&3 && echo - if ! jq -er .name "${meta_tmp}" &>/dev/null; then println "ERROR" "${FG_RED}ERROR${NC}: unable to get 'name' field from downloaded metadata file!" && waitForInput && continue; fi - if ! jq -er .ticker "${meta_tmp}" &>/dev/null; then println "ERROR" "${FG_RED}ERROR${NC}: unable to get 'ticker' field from downloaded metadata file!" && waitForInput && continue; fi - if ! jq -er .homepage "${meta_tmp}" &>/dev/null; then println "ERROR" "${FG_RED}ERROR${NC}: unable to get 'homepage' field from downloaded metadata file!" && waitForInput && continue; fi - if ! jq -er .description "${meta_tmp}" &>/dev/null; then println "ERROR" "${FG_RED}ERROR${NC}: unable to get 'description' field from downloaded metadata file!" && waitForInput && continue; fi - println "DEBUG" "Metadata exists at URL. Use existing data?" + if ! jq -er .name "${meta_tmp}" &>/dev/null; then println ERROR "${FG_RED}ERROR${NC}: unable to get 'name' field from downloaded metadata file!" && waitForInput && continue; fi + if ! jq -er .ticker "${meta_tmp}" &>/dev/null; then println ERROR "${FG_RED}ERROR${NC}: unable to get 'ticker' field from downloaded metadata file!" && waitForInput && continue; fi + if ! jq -er .homepage "${meta_tmp}" &>/dev/null; then println ERROR "${FG_RED}ERROR${NC}: unable to get 'homepage' field from downloaded metadata file!" && waitForInput && continue; fi + if ! jq -er .description "${meta_tmp}" &>/dev/null; then println ERROR "${FG_RED}ERROR${NC}: unable to get 'description' field from downloaded metadata file!" && waitForInput && continue; fi + println DEBUG "Metadata exists at URL. Use existing data?" select_opt "[y] Yes" "[n] No" case $? in 0) mv "${meta_tmp}" "${pool_meta_file}" @@ -1627,41 +1673,41 @@ function main { if [[ ! -f "${pool_meta_file}" ]] || ! meta_description=$(jq -er .description "${pool_meta_file}"); then meta_description="No Description"; fi if [[ ! -f "${pool_meta_file}" ]] || ! meta_homepage=$(jq -er .homepage "${pool_meta_file}"); then meta_homepage="https://foo.com"; fi if [[ ! -f "${pool_meta_file}" ]] || ! meta_extended=$(jq -er .extended "${pool_meta_file}"); then meta_extended="https://foo.com/metadata/extended.json"; fi - sleep 0.1 && read -r -p "Enter Pool's Name (default: ${meta_name}): " name_enter 2>&6 && println "LOG" "Enter Pool's Name (default: ${meta_name}): ${name_enter}" + getAnswerAnyCust name_enter "Enter Pool's Name (default: ${meta_name})" [[ -n "${name_enter}" ]] && meta_name="${name_enter}" if [[ ${#meta_name} -gt 50 ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: Name cannot exceed 50 characters" + println ERROR "${FG_RED}ERROR${NC}: Name cannot exceed 50 characters" waitForInput && continue fi - sleep 0.1 && read -r -p "Enter Pool's Ticker , should be between 3-5 characters (default: ${meta_ticker}): " ticker_enter 2>&6 && println "LOG" "Enter Pool's Ticker , should be between 3-5 characters (default: ${meta_ticker}): ${ticker_enter}" + getAnswerAnyCust ticker_enter "Enter Pool's Ticker , should be between 3-5 characters (default: ${meta_ticker})" ticker_enter=${ticker_enter//[^[:alnum:]]/} [[ -n "${ticker_enter}" ]] && meta_ticker="${ticker_enter^^}" if [[ ${#meta_ticker} -lt 3 || ${#meta_ticker} -gt 5 ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: ticker must be between 3-5 characters" + println ERROR "${FG_RED}ERROR${NC}: ticker must be between 3-5 characters" waitForInput && continue fi - sleep 0.1 && read -r -p "Enter Pool's Description (default: ${meta_description}): " desc_enter 2>&6 && println "LOG" "Enter Pool's Description (default: ${meta_description}): ${desc_enter}" + getAnswerAnyCust desc_enter "Enter Pool's Description (default: ${meta_description})" [[ -n "${desc_enter}" ]] && meta_description="${desc_enter}" if [[ ${#meta_description} -gt 255 ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: Description cannot exceed 255 characters" + println ERROR "${FG_RED}ERROR${NC}: Description cannot exceed 255 characters" waitForInput && continue fi - sleep 0.1 && read -r -p "Enter Pool's Homepage (default: ${meta_homepage}): " homepage_enter 2>&6 && println "LOG" "Enter Pool's Homepage (default: ${meta_homepage}): ${homepage_enter}" + getAnswerAnyCust homepage_enter "Enter Pool's Homepage (default: ${meta_homepage})" [[ -n "${homepage_enter}" ]] && meta_homepage="${homepage_enter}" if [[ ! "${meta_homepage}" =~ https?://.* || ${#meta_homepage} -gt 64 ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: invalid URL format or more than 64 chars in length" + println ERROR "${FG_RED}ERROR${NC}: invalid URL format or more than 64 chars in length" waitForInput && continue fi - println "DEBUG" "\nOptionally set an extended metadata URL?" + println DEBUG "\nOptionally set an extended metadata URL?" select_opt "[n] No" "[y] Yes" case $? in 0) meta_extended_option="" ;; - 1) echo && sleep 0.1 && read -r -p "Enter URL to extended metadata (default: ${meta_extended}): " extended_enter 2>&6 && println "LOG" "Enter URL to extended metadata (default: ${meta_extended}): ${extended_enter}" + 1) getAnswerAnyCust extended_enter "Enter URL to extended metadata (default: ${meta_extended})" extended_enter="${extended_enter}" [[ -n "${extended_enter}" ]] && meta_extended="${extended_enter}" if [[ ! "${meta_extended}" =~ https?://.* || ${#meta_extended} -gt 64 ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: invalid extended URL format or more than 64 chars in length" + println ERROR "${FG_RED}ERROR${NC}: invalid extended URL format or more than 64 chars in length" waitForInput && continue else meta_extended_option=",\"extended\":\"${meta_extended}\"" @@ -1672,22 +1718,22 @@ function main { jq . "${new_pool_meta_file}" metadata_size=$(stat -c%s "${new_pool_meta_file}") if [[ ${metadata_size} -gt 512 ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: Total metadata size cannot exceed 512 chars in length, current length: ${metadata_size}" + println ERROR "\n${FG_RED}ERROR${NC}: Total metadata size cannot exceed 512 chars in length, current length: ${metadata_size}" waitForInput && continue else cp -f "${new_pool_meta_file}" "${pool_meta_file}" fi - println "DEBUG" "\n${FG_YELLOW}Please host file ${pool_meta_file} as-is at ${meta_json_url}${NC}" + println DEBUG "\n${FG_YELLOW}Please host file ${pool_meta_file} as-is at ${meta_json_url}${NC}" waitForInput "Press any key to proceed with registration after metadata file is uploaded" fi relay_output="" relay_array=() - println "DEBUG" "\n# Pool Relay Registration" + println DEBUG "\n# Pool Relay Registration" # ToDo SRV support if [[ -f "${pool_config}" && $(jq '.relays | length' "${pool_config}") -gt 0 ]]; then - println "DEBUG" "\nPrevious relay configuration:\n" + println DEBUG "\nPrevious relay configuration:\n" jq -r '["TYPE","ADDRESS","PORT"], (.relays[] | [.type //"-",.address //"-",.port //"-"]) | @tsv' "${pool_config}" | column -t >&3 - println "DEBUG" "\nReuse previous relay configuration?" + println DEBUG "\nReuse previous relay configuration?" select_opt "[y] Yes" "[n] No" "[Esc] Cancel" case $? in 0) while read -r type address port; do @@ -1709,32 +1755,32 @@ function main { while true; do select_opt "[d] A or AAAA DNS record" "[i] IPv4/v6 address" "[Esc] Cancel" case $? in - 0) sleep 0.1 && read -r -p "Enter relays's DNS record, only A or AAAA DNS records: " relay_dns_enter 2>&6 && println "LOG" "Enter relays's DNS record, only A or AAAA DNS records: ${relay_dns_enter}" + 0) getAnswerAnyCust relay_dns_enter "Enter relays's DNS record, only A or AAAA DNS records" if [[ -z "${relay_dns_enter}" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: DNS record can not be empty!" + println ERROR "${FG_RED}ERROR${NC}: DNS record can not be empty!" else - sleep 0.1 && read -r -p "Enter relays's port: " relay_port_enter 2>&6 && println "LOG" "Enter relays's port: ${relay_port_enter}" + getAnswerAnyCust relay_port_enter "Enter relays's port" if [[ -n "${relay_port_enter}" ]]; then if ! isNumber ${relay_port_enter} || [[ ${relay_port_enter} -lt 1 || ${relay_port_enter} -gt 65535 ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: invalid port number!" + println ERROR "${FG_RED}ERROR${NC}: invalid port number!" else relay_array+=( "type" "DNS_A" "address" "${relay_dns_enter}" "port" "${relay_port_enter}" ) relay_output+="--single-host-pool-relay ${relay_dns_enter} --pool-relay-port ${relay_port_enter} " fi else - println "ERROR" "${FG_RED}ERROR${NC}: Port can not be empty!" + println ERROR "${FG_RED}ERROR${NC}: Port can not be empty!" fi fi ;; - 1) sleep 0.1 && read -r -p "Enter relays's IPv4/v6 address: " relay_ip_enter 2>&6 && println "LOG" "Enter relays's IPv4/v6 address: ${relay_ip_enter}" + 1) getAnswerAnyCust relay_ip_enter "Enter relays's IPv4/v6 address" if [[ -n "${relay_ip_enter}" ]]; then if ! isValidIPv4 "${relay_ip_enter}" && ! isValidIPv6 "${relay_ip_enter}"; then - println "ERROR" "${FG_RED}ERROR${NC}: invalid IPv4/v6 address format!" + println ERROR "${FG_RED}ERROR${NC}: invalid IPv4/v6 address format!" else - sleep 0.1 && read -r -p "Enter relays's port: " relay_port_enter 2>&6 && println "LOG" "Enter relays's port: ${relay_port_enter}" + getAnswerAnyCust relay_port_enter "Enter relays's port" if [[ -n "${relay_port_enter}" ]]; then if ! isNumber ${relay_port_enter} || [[ ${relay_port_enter} -lt 1 || ${relay_port_enter} -gt 65535 ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: invalid port number!" + println ERROR "${FG_RED}ERROR${NC}: invalid port number!" elif isValidIPv4 "${relay_ip_enter}"; then relay_array+=( "type" "IPv4" "address" "${relay_ip_enter}" "port" "${relay_port_enter}" ) relay_output+="--pool-relay-port ${relay_port_enter} --pool-relay-ipv4 ${relay_ip_enter} " @@ -1743,16 +1789,16 @@ function main { relay_output+="--pool-relay-port ${relay_port_enter} --pool-relay-ipv6 ${relay_ip_enter} " fi else - println "ERROR" "${FG_RED}ERROR${NC}: Port can not be empty!" + println ERROR "${FG_RED}ERROR${NC}: Port can not be empty!" fi fi else - println "ERROR" "${FG_RED}ERROR${NC}: IPv4/v6 address empty!" + println ERROR "${FG_RED}ERROR${NC}: IPv4/v6 address empty!" fi ;; 2) continue 2 ;; esac - println "DEBUG" "Add more relay entries?" + println DEBUG "Add more relay entries?" select_opt "[n] No" "[y] Yes" "[Esc] Cancel" case $? in 0) break ;; @@ -1769,20 +1815,20 @@ function main { reuse_wallets='N' # Old owner/reward wallets if [[ -f ${pool_config} ]]; then - println "DEBUG" "# Previous Owner(s)/Reward wallets" + println DEBUG "# Previous Owner(s)/Reward wallets" if jq -er '.pledgeWallet' "${pool_config}" &>/dev/null; then # legacy support owner_wallets+=( "$(jq -r '.pledgeWallet' "${pool_config}")" ) - println "DEBUG" "Owner wallet #1 : ${FG_GREEN}${owner_wallets[0]}${NC}" + println DEBUG "Owner wallet #1 : ${FG_GREEN}${owner_wallets[0]}${NC}" else for owner in $(jq -c '.owners[]' "${pool_config}"); do wallet_name=$(jq -r '.wallet_name' <<< "${owner}") owner_wallets+=( "${wallet_name}" ) - println "DEBUG" "Owner wallet #$(jq -r '.id' <<< "${owner}") : ${FG_GREEN}${wallet_name}${NC}" + println DEBUG "Owner wallet #$(jq -r '.id' <<< "${owner}") : ${FG_GREEN}${wallet_name}${NC}" done fi reward_wallet=$(jq -r '.rewardWallet //empty' "${pool_config}") - println "DEBUG" "Reward wallet : ${FG_GREEN}${reward_wallet}${NC}" - println "DEBUG" "\nReuse previous Owner(s)/Reward wallets?" + println DEBUG "Reward wallet : ${FG_GREEN}${reward_wallet}${NC}" + println DEBUG "\nReuse previous Owner(s)/Reward wallets?" select_opt "[y] Yes" "[n] No" "[Esc] Cancel" case $? in 0) reuse_wallets='Y' @@ -1790,30 +1836,30 @@ function main { getWalletType ${wallet_name} case $? in 0) if [[ ${wallet_name} = "${owner_wallets[0]}" ]]; then # main owner, must be a CLI wallet - println "ERROR" "${FG_RED}ERROR${NC}: main/first pool owner can NOT be a hardware wallet!" - println "ERROR" "Use a CLI wallet as owner with enough funds to pay for pool deposit and registration transaction fee" - println "ERROR" "Add the hardware wallet as an additional multi-owner to the pool later in the pool registration wizard" + println ERROR "${FG_RED}ERROR${NC}: main/first pool owner can NOT be a hardware wallet!" + println ERROR "Use a CLI wallet as owner with enough funds to pay for pool deposit and registration transaction fee" + println ERROR "Add the hardware wallet as an additional multi-owner to the pool later in the pool registration wizard" waitForInput "Unable to reuse old configuration, please set new owner(s) & reward wallet" && owner_wallets=() && reward_wallet="" && reuse_wallets='N' && break else hw_owner_wallets='Y'; fi ;; 2) if [[ ${op_mode} = "online" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: signing keys encrypted for wallet ${FG_GREEN}${wallet_name}${NC}, please decrypt before use!" + println ERROR "${FG_RED}ERROR${NC}: signing keys encrypted for wallet ${FG_GREEN}${wallet_name}${NC}, please decrypt before use!" waitForInput && continue 2 fi ;; - 3) println "ERROR" "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet ${FG_GREEN}${wallet_name}${NC}!" + 3) println ERROR "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet ${FG_GREEN}${wallet_name}${NC}!" waitForInput "Did you mean to run in Hybrid mode? press any key to return home!" && continue 2 ;; - 4) println "ERROR" "${FG_RED}ERROR${NC}: payment and/or stake verification keys missing from wallet ${FG_GREEN}${wallet_name}${NC}!" + 4) println ERROR "${FG_RED}ERROR${NC}: payment and/or stake verification keys missing from wallet ${FG_GREEN}${wallet_name}${NC}!" waitForInput "Unable to reuse old configuration, please set new owner(s) & reward wallet" && owner_wallets=() && reward_wallet="" && reuse_wallets='N' && break ;; esac if [[ ${wallet_name} = "${owner_wallets[0]}" ]] && ! isWalletRegistered ${wallet_name}; then # make sure at least main owner is registered if [[ ${op_mode} = "hybrid" ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: wallet ${FG_GREEN}${wallet_name}${NC} not a registered wallet on chain and CNTools run in hybrid mode" - println "ERROR" "Please first register main owner wallet to use in pool registration using 'Wallet >> Register'" + println ERROR "\n${FG_RED}ERROR${NC}: wallet ${FG_GREEN}${wallet_name}${NC} not a registered wallet on chain and CNTools run in hybrid mode" + println ERROR "Please first register main owner wallet to use in pool registration using 'Wallet >> Register'" waitForInput && continue 2 fi getBaseAddress ${wallet_name} getBalance ${base_addr} if [[ ${assets[lovelace]} -eq 0 ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: no funds available in base address for wallet ${FG_GREEN}${wallet_name}${NC}, needed to pay for registration fee" + println ERROR "${FG_RED}ERROR${NC}: no funds available in base address for wallet ${FG_GREEN}${wallet_name}${NC}, needed to pay for registration fee" waitForInput && continue 2 fi if ! registerStakeWallet ${wallet_name}; then waitForInput && continue 2; fi @@ -1826,56 +1872,56 @@ function main { [[ "${wallet_name}" = "${reward_wallet}" ]] && hw_reward_is_mu='Y' && break done if [[ ${hw_reward_is_mu} = 'N' ]]; then # main owner, must be a CLI wallet - println "ERROR" "${FG_RED}ERROR${NC}: reward wallet detected as hardware wallet but NOT a multi-owner to the pool!" - println "ERROR" "If hardware wallet is to be used for rewards, it MUST also be a multi-owner to the pool" + println ERROR "${FG_RED}ERROR${NC}: reward wallet detected as hardware wallet but NOT a multi-owner to the pool!" + println ERROR "If hardware wallet is to be used for rewards, it MUST also be a multi-owner to the pool" waitForInput "Unable to reuse old configuration, please set new owner(s) & reward wallet" && owner_wallets=() && reward_wallet="" && reuse_wallets='N' else hw_reward_wallet='Y'; fi ;; 2) if [[ ${op_mode} = "online" && ${SUBCOMMAND} = "register" && ${hw_owner_wallets} = 'N' ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: signing keys encrypted for reward wallet ${FG_GREEN}${reward_wallet}${NC}, please decrypt before use!" + println ERROR "${FG_RED}ERROR${NC}: signing keys encrypted for reward wallet ${FG_GREEN}${reward_wallet}${NC}, please decrypt before use!" waitForInput && continue fi ;; 3) if [[ ${SUBCOMMAND} = "register" && ${hw_owner_wallets} = 'N' ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from reward wallet ${FG_GREEN}${reward_wallet}${NC}!" + println ERROR "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from reward wallet ${FG_GREEN}${reward_wallet}${NC}!" waitForInput "Did you mean to run in Hybrid mode? press any key to return home!" && continue fi ;; - 4) println "ERROR" "${FG_RED}ERROR${NC}: payment and/or stake verification keys missing from reward wallet ${FG_GREEN}${reward_wallet}${NC}!" + 4) println ERROR "${FG_RED}ERROR${NC}: payment and/or stake verification keys missing from reward wallet ${FG_GREEN}${reward_wallet}${NC}!" waitForInput "Unable to reuse old configuration, please set new owner(s) & reward wallet" && owner_wallets=() && reward_wallet="" && reuse_wallets='N' ;; esac if ! isWalletRegistered ${reward_wallet}; then if [[ ${op_mode} = "hybrid" ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: reward wallet ${FG_GREEN}${reward_wallet}${NC} not a registered wallet on chain and CNTools run in hybrid mode" - println "ERROR" "Please first register the rewards wallet to use in pool registration using 'Wallet >> Register'" + println ERROR "\n${FG_RED}ERROR${NC}: reward wallet ${FG_GREEN}${reward_wallet}${NC} not a registered wallet on chain and CNTools run in hybrid mode" + println ERROR "Please first register the rewards wallet to use in pool registration using 'Wallet >> Register'" waitForInput && continue fi getBaseAddress ${reward_wallet} getBalance ${base_addr} if [[ ${assets[lovelace]} -eq 0 ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: no funds available in base address for reward wallet ${FG_GREEN}${reward_wallet}${NC}, needed to pay for registration fee" + println ERROR "${FG_RED}ERROR${NC}: no funds available in base address for reward wallet ${FG_GREEN}${reward_wallet}${NC}, needed to pay for registration fee" waitForInput && continue fi if ! registerStakeWallet ${reward_wallet}; then waitForInput && continue; fi fi ;; 1) owner_wallets=() && reward_wallet="" && reuse_wallets='N' - println "DEBUG" "\n${FG_YELLOW}If new wallets are chosen for owner(s)/reward, a manual delegation to the pool for each wallet is needed if not done already!${NC}\n" + println DEBUG "\n${FG_YELLOW}If new wallets are chosen for owner(s)/reward, a manual delegation to the pool for each wallet is needed if not done already!${NC}\n" ;; 2) continue ;; esac fi if [[ ${reuse_wallets} = 'N' ]]; then - println "DEBUG" "# Select main ${FG_YELLOW}owner/pledge${NC} wallet (normal CLI wallet)" + println DEBUG "# Select main ${FG_YELLOW}owner/pledge${NC} wallet (normal CLI wallet)" if [[ ${op_mode} = "online" ]]; then if ! selectWallet "delegate" "${WALLET_PAY_VK_FILENAME}" "${WALLET_STAKE_VK_FILENAME}"; then # ${wallet_name} populated by selectWallet function [[ "${dir_name}" != "[Esc] Cancel" ]] && waitForInput; continue fi getWalletType ${wallet_name} case $? in - 0) println "ERROR" "${FG_RED}ERROR${NC}: main pool owner can NOT be a hardware wallet!" - println "ERROR" "Use a CLI wallet as owner with enough funds to pay for pool deposit and registration transaction fee" - println "ERROR" "Add the hardware wallet as an additional multi-owner to the pool later in the pool registration wizard" + 0) println ERROR "${FG_RED}ERROR${NC}: main pool owner can NOT be a hardware wallet!" + println ERROR "Use a CLI wallet as owner with enough funds to pay for pool deposit and registration transaction fee" + println ERROR "Add the hardware wallet as an additional multi-owner to the pool later in the pool registration wizard" waitForInput && continue ;; - 2) println "ERROR" "${FG_RED}ERROR${NC}: signing keys encrypted, please decrypt before use!" && waitForInput && continue ;; - 3) println "ERROR" "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet!" && waitForInput && continue ;; + 2) println ERROR "${FG_RED}ERROR${NC}: signing keys encrypted, please decrypt before use!" && waitForInput && continue ;; + 3) println ERROR "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet!" && waitForInput && continue ;; esac else if ! selectWallet "delegate" "${WALLET_PAY_VK_FILENAME}" "${WALLET_STAKE_VK_FILENAME}"; then # ${wallet_name} populated by selectWallet function @@ -1885,23 +1931,23 @@ function main { fi if ! isWalletRegistered ${wallet_name}; then if [[ ${op_mode} = "hybrid" ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: wallet ${FG_GREEN}${wallet_name}${NC} not a registered wallet on chain and CNTools run in hybrid mode" - println "ERROR" "Please first register the main CLI wallet to use in pool registration using 'Wallet >> Register'" + println ERROR "\n${FG_RED}ERROR${NC}: wallet ${FG_GREEN}${wallet_name}${NC} not a registered wallet on chain and CNTools run in hybrid mode" + println ERROR "Please first register the main CLI wallet to use in pool registration using 'Wallet >> Register'" waitForInput && continue fi getBaseAddress ${wallet_name} getBalance ${base_addr} if [[ ${assets[lovelace]} -eq 0 ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: no funds available in base address for wallet ${FG_GREEN}${wallet_name}${NC}, needed to pay for registration fee" + println ERROR "${FG_RED}ERROR${NC}: no funds available in base address for wallet ${FG_GREEN}${wallet_name}${NC}, needed to pay for registration fee" waitForInput && continue fi if ! registerStakeWallet ${wallet_name}; then waitForInput && continue; fi fi owner_wallets+=( "${wallet_name}" ) - println "DEBUG" "Owner #1 : ${FG_GREEN}${wallet_name}${NC} added!" + println DEBUG "Owner #1 : ${FG_GREEN}${wallet_name}${NC} added!" fi if [[ ${reuse_wallets} = 'N' ]]; then - println "DEBUG" "\nRegister a multi-owner pool (you need to have stake.vkey of any additional owner in a seperate wallet folder under \$CNODE_HOME/priv/wallet)?" + println DEBUG "\nRegister a multi-owner pool (you need to have stake.vkey of any additional owner in a seperate wallet folder under \$CNODE_HOME/priv/wallet)?" while true; do select_opt "[n] No" "[y] Yes" "[Esc] Cancel" case $? in @@ -1911,29 +1957,29 @@ function main { case $? in 0) hw_owner_wallets='Y' ;; 2) if [[ ${op_mode} = "online" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: signing keys encrypted for wallet ${FG_GREEN}${wallet_name}${NC}, please decrypt before use!" + println ERROR "${FG_RED}ERROR${NC}: signing keys encrypted for wallet ${FG_GREEN}${wallet_name}${NC}, please decrypt before use!" waitForInput && continue 2 fi ;; - 3) println "ERROR" "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet ${FG_GREEN}${wallet_name}${NC}!" + 3) println ERROR "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet ${FG_GREEN}${wallet_name}${NC}!" waitForInput "Did you mean to run in Hybrid mode? press any key to return home!" && continue 2 ;; 4) if [[ ! -f "${WALLET_FOLDER}/${wallet_name}/${WALLET_STAKE_VK_FILENAME}" ]]; then # ignore if payment vkey is missing - println "ERROR" "${FG_RED}ERROR${NC}: stake verification key missing from wallet ${FG_GREEN}${wallet_name}${NC}!" - println "DEBUG" "Add another owner?" && continue + println ERROR "${FG_RED}ERROR${NC}: stake verification key missing from wallet ${FG_GREEN}${wallet_name}${NC}!" + println DEBUG "Add another owner?" && continue fi ;; esac else - println "DEBUG" "Add more owners?" && continue + println DEBUG "Add more owners?" && continue fi owner_wallets+=( "${wallet_name}" ) - println "DEBUG" "Owner #${#owner_wallets[@]} : ${FG_GREEN}${wallet_name}${NC} added!" + println DEBUG "Owner #${#owner_wallets[@]} : ${FG_GREEN}${wallet_name}${NC} added!" ;; 2) continue 2 ;; esac - println "DEBUG" "Add more owners?" + println DEBUG "Add more owners?" done fi if [[ ${reuse_wallets} = 'N' ]]; then - println "DEBUG" "\nUse a separate rewards wallet from main owner?" + println DEBUG "\nUse a separate rewards wallet from main owner?" select_opt "[n] No" "[y] Yes" "[Esc] Cancel" case $? in 0) reward_wallet="${owner_wallets[0]}" ;; @@ -1943,23 +1989,23 @@ function main { reward_wallet="${wallet_name}" if ! isWalletRegistered ${reward_wallet}; then if [[ ${op_mode} = "hybrid" ]]; then - println "ERROR" "\nReward wallet ${FG_GREEN}${reward_wallet}${NC} not a registered wallet on chain and CNTools run in hybrid mode" - println "ERROR" "Please first register the reward wallet to use in pool registration using 'Wallet >> Register'" + println ERROR "\nReward wallet ${FG_GREEN}${reward_wallet}${NC} not a registered wallet on chain and CNTools run in hybrid mode" + println ERROR "Please first register the reward wallet to use in pool registration using 'Wallet >> Register'" waitForInput && continue fi getWalletType ${reward_wallet} case $? in 0) hw_reward_wallet='Y' ;; - 2) println "ERROR" "${FG_RED}ERROR${NC}: stake signing key encrypted, please decrypt before use!" && waitForInput && continue ;; - 3) println "ERROR" "${FG_RED}ERROR${NC}: stake signing key missing from wallet!" && waitForInput && continue ;; + 2) println ERROR "${FG_RED}ERROR${NC}: stake signing key encrypted, please decrypt before use!" && waitForInput && continue ;; + 3) println ERROR "${FG_RED}ERROR${NC}: stake signing key missing from wallet!" && waitForInput && continue ;; esac getBaseAddress ${reward_wallet} getBalance ${base_addr} if [[ ${assets[lovelace]} -gt 0 ]]; then - println "DEBUG" "$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Funds in reward wallet:" "$(formatLovelace ${assets[lovelace]})")" + println DEBUG "$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Funds in reward wallet:" "$(formatLovelace ${assets[lovelace]})")" echo else - println "ERROR" "${FG_RED}ERROR${NC}: no funds available in base address for wallet ${FG_GREEN}${reward_wallet}${NC}, needed to pay for registration fee" + println ERROR "${FG_RED}ERROR${NC}: no funds available in base address for wallet ${FG_GREEN}${reward_wallet}${NC}, needed to pay for registration fee" waitForInput && continue fi if ! registerStakeWallet ${reward_wallet}; then @@ -2004,39 +2050,39 @@ function main { if [[ ${op_mode} = "online" ]]; then current_kes_period=$(getCurrentKESperiod) echo "${current_kes_period}" > ${pool_saved_kes_start} - println "ACTION" "${CCLI} node issue-op-cert --kes-verification-key-file ${pool_hotkey_vk_file} --cold-signing-key-file ${pool_coldkey_sk_file} --operational-certificate-issue-counter-file ${pool_opcert_counter_file} --kes-period ${current_kes_period} --out-file ${pool_opcert_file}" + println ACTION "${CCLI} node issue-op-cert --kes-verification-key-file ${pool_hotkey_vk_file} --cold-signing-key-file ${pool_coldkey_sk_file} --operational-certificate-issue-counter-file ${pool_opcert_counter_file} --kes-period ${current_kes_period} --out-file ${pool_opcert_file}" ${CCLI} node issue-op-cert --kes-verification-key-file "${pool_hotkey_vk_file}" --cold-signing-key-file "${pool_coldkey_sk_file}" --operational-certificate-issue-counter-file "${pool_opcert_counter_file}" --kes-period "${current_kes_period}" --out-file "${pool_opcert_file}" else - println "DEBUG" "\n${FG_YELLOW}Pool operational certificate not generated in hybrid mode," - println "DEBUG" "please use 'Pool >> Rotate' in offline mode to generate new hot keys, op cert and KES start period and transfer to online node!${NC}" - println "DEBUG" "Files generated when running 'Pool >> Rotate' to be transferred:" - println "DEBUG" "${FG_LGRAY}${pool_hotkey_vk_file}${NC}" - println "DEBUG" "${FG_LGRAY}${pool_hotkey_sk_file}${NC}" - println "DEBUG" "${FG_LGRAY}${pool_opcert_file}${NC}" - println "DEBUG" "${FG_LGRAY}${pool_saved_kes_start}${NC}" + println DEBUG "\n${FG_YELLOW}Pool operational certificate not generated in hybrid mode," + println DEBUG "please use 'Pool >> Rotate' in offline mode to generate new hot keys, op cert and KES start period and transfer to online node!${NC}" + println DEBUG "Files generated when running 'Pool >> Rotate' to be transferred:" + println DEBUG "${FG_LGRAY}${pool_hotkey_vk_file}${NC}" + println DEBUG "${FG_LGRAY}${pool_hotkey_sk_file}${NC}" + println DEBUG "${FG_LGRAY}${pool_opcert_file}${NC}" + println DEBUG "${FG_LGRAY}${pool_saved_kes_start}${NC}" waitForInput "press any key to continue" fi fi - println "LOG" "creating registration certificate" - println "ACTION" "${CCLI} stake-pool registration-certificate --cold-verification-key-file ${pool_coldkey_vk_file} --vrf-verification-key-file ${pool_vrf_vk_file} --pool-pledge ${pledge_lovelace} --pool-cost ${cost_lovelace} --pool-margin ${margin_fraction} --pool-reward-account-verification-key-file ${reward_stake_vk_file} --pool-owner-stake-verification-key-file ${owner_stake_vk_file} ${multi_owner_output} --metadata-url ${meta_json_url} --metadata-hash \$\(${CCLI} stake-pool metadata-hash --pool-metadata-file ${pool_meta_file} \) ${relay_output} ${NETWORK_IDENTIFIER} --out-file ${pool_regcert_file}" + println LOG "creating registration certificate" + println ACTION "${CCLI} stake-pool registration-certificate --cold-verification-key-file ${pool_coldkey_vk_file} --vrf-verification-key-file ${pool_vrf_vk_file} --pool-pledge ${pledge_lovelace} --pool-cost ${cost_lovelace} --pool-margin ${margin_fraction} --pool-reward-account-verification-key-file ${reward_stake_vk_file} --pool-owner-stake-verification-key-file ${owner_stake_vk_file} ${multi_owner_output} --metadata-url ${meta_json_url} --metadata-hash \$\(${CCLI} stake-pool metadata-hash --pool-metadata-file ${pool_meta_file} \) ${relay_output} ${NETWORK_IDENTIFIER} --out-file ${pool_regcert_file}" ${CCLI} stake-pool registration-certificate --cold-verification-key-file "${pool_coldkey_vk_file}" --vrf-verification-key-file "${pool_vrf_vk_file}" --pool-pledge ${pledge_lovelace} --pool-cost ${cost_lovelace} --pool-margin ${margin_fraction} --pool-reward-account-verification-key-file "${reward_stake_vk_file}" --pool-owner-stake-verification-key-file "${owner_stake_vk_file}" ${multi_owner_output} --metadata-url "${meta_json_url}" --metadata-hash "$(${CCLI} stake-pool metadata-hash --pool-metadata-file ${pool_meta_file} )" ${relay_output} ${NETWORK_IDENTIFIER} --out-file "${pool_regcert_file}" delegate_reward_wallet='N' delegate_owner_wallet='N' if [[ ${SUBCOMMAND} = "register" ]]; then if [[ ${hw_owner_wallets} = 'Y' || ${hw_reward_wallet} = 'Y' ]]; then - println "DEBUG" "\n${FG_BLUE}INFO${NC}: hardware wallet included as reward or multi-owner, automatic owner/reward wallet delegation disabled" - println "DEBUG" "${FG_BLUE}INFO${NC}: ${FG_YELLOW}please manually delegate all wallets to the pool!!!${NC}" + println DEBUG "\n${FG_BLUE}INFO${NC}: hardware wallet included as reward or multi-owner, automatic owner/reward wallet delegation disabled" + println DEBUG "${FG_BLUE}INFO${NC}: ${FG_YELLOW}please manually delegate all wallets to the pool!!!${NC}" waitForInput "press any key to continue" else - println "LOG" "creating delegation certificate for main owner wallet" - println "ACTION" "${CCLI} stake-address delegation-certificate --stake-verification-key-file ${owner_stake_vk_file} --cold-verification-key-file ${pool_coldkey_vk_file} --out-file ${owner_delegation_cert_file}" + println LOG "creating delegation certificate for main owner wallet" + println ACTION "${CCLI} stake-address delegation-certificate --stake-verification-key-file ${owner_stake_vk_file} --cold-verification-key-file ${pool_coldkey_vk_file} --out-file ${owner_delegation_cert_file}" ${CCLI} stake-address delegation-certificate --stake-verification-key-file "${owner_stake_vk_file}" --cold-verification-key-file "${pool_coldkey_vk_file}" --out-file "${owner_delegation_cert_file}" delegate_owner_wallet='Y' if [[ "${owner_wallets[0]}" != "${reward_wallet}" ]]; then - println "LOG" "creating delegation certificate for reward wallet" - println "ACTION" "${CCLI} stake-address delegation-certificate --stake-verification-key-file ${reward_stake_vk_file} --cold-verification-key-file ${pool_coldkey_vk_file} --out-file ${reward_delegation_cert_file}" + println LOG "creating delegation certificate for reward wallet" + println ACTION "${CCLI} stake-address delegation-certificate --stake-verification-key-file ${reward_stake_vk_file} --cold-verification-key-file ${pool_coldkey_vk_file} --out-file ${reward_delegation_cert_file}" ${CCLI} stake-address delegation-certificate --stake-verification-key-file "${reward_stake_vk_file}" --cold-verification-key-file "${pool_coldkey_vk_file}" --out-file "${reward_delegation_cert_file}" delegate_reward_wallet='Y' fi @@ -2055,7 +2101,7 @@ function main { [[ -f "${pool_regcert_file}.tmp" ]] && rm -f "${pool_regcert_file}.tmp" # remove backup of old reg cert if it exist (modify) [[ -f "${pool_deregcert_file}" ]] && rm -f "${pool_deregcert_file}" # delete de-registration cert if available else # rc=1 failed | rc=2 used for offline mode, treat as failed for now, files written on submission - [[ $rc -eq 1 ]] && echo && println "ERROR" "\n${FG_RED}ERROR${NC}: failure during pool ${SUBCOMMAND}!" + [[ $rc -eq 1 ]] && echo && println ERROR "\n${FG_RED}ERROR${NC}: failure during pool ${SUBCOMMAND}!" if [[ ${SUBCOMMAND} = "register" ]]; then [[ -f "${pool_regcert_file}" ]] && rm -f "${pool_regcert_file}" else @@ -2107,9 +2153,9 @@ function main { println "Cost : ${FG_LBLUE}$(formatAsset ${cost_ada})${NC} Ada" if [[ ${SUBCOMMAND} = "register" ]]; then if [[ ${op_mode} = "hybrid" ]]; then - println "DEBUG" "\n${FG_YELLOW}After offline pool transaction is signed and submitted, uncomment and set value for POOL_NAME in ${PARENT}/env with${NC} '${FG_GREEN}${pool_name}${NC}'" + println DEBUG "\n${FG_YELLOW}After offline pool transaction is signed and submitted, uncomment and set value for POOL_NAME in ${PARENT}/env with${NC} '${FG_GREEN}${pool_name}${NC}'" else - println "DEBUG" "\n${FG_YELLOW}Uncomment and set value for POOL_NAME in ${PARENT}/env with${NC} '${FG_GREEN}${pool_name}${NC}'" + println DEBUG "\n${FG_YELLOW}Uncomment and set value for POOL_NAME in ${PARENT}/env with${NC} '${FG_GREEN}${pool_name}${NC}'" fi fi echo @@ -2122,35 +2168,35 @@ function main { getRewards ${wallet_name} [[ ${reward_lovelace} -gt 0 ]] && total_pledge=$(( total_pledge + reward_lovelace )) done - println "DEBUG" "${FG_BLUE}INFO${NC}: Total balance in ${FG_LBLUE}${#owner_wallets[@]}${NC} owner/pledge wallet(s) are: ${FG_LBLUE}$(formatLovelace ${total_pledge})${NC} Ada" + println DEBUG "${FG_BLUE}INFO${NC}: Total balance in ${FG_LBLUE}${#owner_wallets[@]}${NC} owner/pledge wallet(s) are: ${FG_LBLUE}$(formatLovelace ${total_pledge})${NC} Ada" if [[ ${total_pledge} -lt ${pledge_lovelace} ]]; then - println "ERROR" "${FG_YELLOW}Not enough funds in owner/pledge wallet(s) to meet set pledge, please manually verify!!!${NC}" + println ERROR "${FG_YELLOW}Not enough funds in owner/pledge wallet(s) to meet set pledge, please manually verify!!!${NC}" fi fi if [[ ${#owner_wallets[@]} -gt 1 ]]; then if [[ ${op_mode} = "hybrid" ]]; then - println "DEBUG" "${FG_BLUE}INFO${NC}: please verify that all owner/reward wallets are delegated to the pool after the pool registration has been signed and submitted, if not do so!" + println DEBUG "${FG_BLUE}INFO${NC}: please verify that all owner/reward wallets are delegated to the pool after the pool registration has been signed and submitted, if not do so!" else - println "DEBUG" "${FG_BLUE}INFO${NC}: please verify that all owner/reward wallets are delegated to the pool, if not do so!" + println DEBUG "${FG_BLUE}INFO${NC}: please verify that all owner/reward wallets are delegated to the pool, if not do so!" fi fi waitForInput && continue ;; ################################################################### retire) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> POOL >> RETIRE" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" [[ ! $(ls -A "${POOL_FOLDER}" 2>/dev/null) ]] && echo && println "${FG_YELLOW}No pools available!${NC}" && waitForInput && continue [[ ! $(ls -A "${WALLET_FOLDER}" 2>/dev/null) ]] && echo && println "${FG_YELLOW}No wallets available to pay for pool de-registration!${NC}" && waitForInput && continue if [[ ${CNTOOLS_MODE} = "OFFLINE" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: CNTools started in offline mode, option not available!" + println ERROR "${FG_RED}ERROR${NC}: CNTools started in offline mode, option not available!" waitForInput && continue else if ! selectOpMode; then continue; fi fi echo - println "DEBUG" "# Select pool to retire" + println DEBUG "# Select pool to retire" if [[ ${op_mode} = "online" ]]; then if ! selectPool "reg" "${POOL_COLDKEY_VK_FILENAME}" "${POOL_COLDKEY_SK_FILENAME}"; then # ${pool_name} populated by selectPool function waitForInput && continue @@ -2163,28 +2209,28 @@ function main { echo epoch=$(getEpoch) poolRetireMaxEpoch=$(jq -r '.poolRetireMaxEpoch' <<< "${PROT_PARAMS}") - println "DEBUG" "Current epoch: ${FG_LBLUE}${epoch}${NC}" + println DEBUG "Current epoch: ${FG_LBLUE}${epoch}${NC}" epoch_start=$((epoch + 1)) epoch_end=$((epoch + poolRetireMaxEpoch)) - println "DEBUG" "earlist epoch to retire pool is ${FG_LBLUE}${epoch_start}${NC} and latest ${FG_LBLUE}${epoch_end}${NC}" + println DEBUG "earlist epoch to retire pool is ${FG_LBLUE}${epoch_start}${NC} and latest ${FG_LBLUE}${epoch_end}${NC}" echo - sleep 0.1 && read -r -p "Enter epoch in which to retire pool (blank for ${epoch_start}): " epoch_enter 2>&6 && println "LOG" "Enter epoch in which to retire pool (blank for ${epoch_start}): ${epoch_enter}" + getAnswerAnyCust epoch_enter "Enter epoch in which to retire pool (blank for ${epoch_start})" [[ -z "${epoch_enter}" ]] && epoch_enter=${epoch_start} echo if [[ ${epoch_enter} -lt ${epoch_start} || ${epoch_enter} -gt ${epoch_end} ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: epoch invalid, valid range: ${epoch_start}-${epoch_end}" + println ERROR "${FG_RED}ERROR${NC}: epoch invalid, valid range: ${epoch_start}-${epoch_end}" waitForInput && continue fi - println "DEBUG" "# Select wallet for pool de-registration transaction fee" + println DEBUG "# Select wallet for pool de-registration transaction fee" if [[ ${op_mode} = "online" ]]; then if ! selectWallet "balance" "${WALLET_PAY_VK_FILENAME}"; then # ${wallet_name} populated by selectWallet function [[ "${dir_name}" != "[Esc] Cancel" ]] && waitForInput; continue fi getWalletType ${wallet_name} case $? in - 0) println "ERROR" "${FG_RED}ERROR${NC}: please use a CLI wallet to pay for pool de-registration transaction fee!" && waitForInput && continue ;; - 2) println "ERROR" "${FG_RED}ERROR${NC}: signing keys encrypted, please decrypt before use!" && waitForInput && continue ;; - 3) println "ERROR" "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet!" && waitForInput && continue ;; + 0) println ERROR "${FG_RED}ERROR${NC}: please use a CLI wallet to pay for pool de-registration transaction fee!" && waitForInput && continue ;; + 2) println ERROR "${FG_RED}ERROR${NC}: signing keys encrypted, please decrypt before use!" && waitForInput && continue ;; + 3) println ERROR "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet!" && waitForInput && continue ;; esac else if ! selectWallet "balance" "${WALLET_PAY_VK_FILENAME}"; then # ${wallet_name} populated by selectWallet function @@ -2192,7 +2238,7 @@ function main { fi getWalletType ${wallet_name} case $? in - 0) println "ERROR" "${FG_RED}ERROR${NC}: please use a CLI wallet to pay for pool de-registration transaction fee!" && waitForInput && continue ;; + 0) println ERROR "${FG_RED}ERROR${NC}: please use a CLI wallet to pay for pool de-registration transaction fee!" && waitForInput && continue ;; esac fi getBaseAddress ${wallet_name} @@ -2203,10 +2249,10 @@ function main { pay_lovelace=${assets[lovelace]} if [[ ${pay_lovelace} -gt 0 && ${base_lovelace} -gt 0 ]]; then # Both payment and base address available with funds, let user choose what to use - println "DEBUG" "\n# Select wallet address to use" + println DEBUG "\n# Select wallet address to use" if [[ -n ${wallet_count} && ${wallet_count} -gt ${WALLET_SELECTION_FILTER_LIMIT} ]]; then - println "DEBUG" "$(printf "%s\t\t${FG_LBLUE}%s${NC} Ada" "Funds :" "$(formatLovelace ${base_lovelace})")" - println "DEBUG" "$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Enterprise Funds :" "$(formatLovelace ${pay_lovelace})")" + println DEBUG "$(printf "%s\t\t${FG_LBLUE}%s${NC} Ada" "Funds :" "$(formatLovelace ${base_lovelace})")" + println DEBUG "$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Enterprise Funds :" "$(formatLovelace ${pay_lovelace})")" fi select_opt "DEBUG" "[b] Base (default)" "[e] Enterprise" "[Esc] Cancel" case $? in @@ -2217,23 +2263,23 @@ function main { elif [[ ${pay_lovelace} -gt 0 ]]; then addr="${pay_addr}" if [[ -n ${wallet_count} && ${wallet_count} -gt ${WALLET_SELECTION_FILTER_LIMIT} ]]; then - println "DEBUG" "\n$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Enterprise Funds :" "$(formatLovelace ${pay_lovelace})")" + println DEBUG "\n$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Enterprise Funds :" "$(formatLovelace ${pay_lovelace})")" fi elif [[ ${base_lovelace} -gt 0 ]]; then addr="${base_addr}" if [[ -n ${wallet_count} && ${wallet_count} -gt ${WALLET_SELECTION_FILTER_LIMIT} ]]; then - println "DEBUG" "\n$(printf "%s\t\t${FG_LBLUE}%s${NC} Ada" "Funds :" "$(formatLovelace ${base_lovelace})")" + println DEBUG "\n$(printf "%s\t\t${FG_LBLUE}%s${NC} Ada" "Funds :" "$(formatLovelace ${base_lovelace})")" fi else - println "ERROR" "\n${FG_RED}ERROR${NC}: no funds available for wallet ${FG_GREEN}${wallet_name}${NC}" + println ERROR "\n${FG_RED}ERROR${NC}: no funds available for wallet ${FG_GREEN}${wallet_name}${NC}" waitForInput && continue fi pool_coldkey_vk_file="${POOL_FOLDER}/${pool_name}/${POOL_COLDKEY_VK_FILENAME}" pool_coldkey_sk_file="${POOL_FOLDER}/${pool_name}/${POOL_COLDKEY_SK_FILENAME}" pool_deregcert_file="${POOL_FOLDER}/${pool_name}/${POOL_DEREGCERT_FILENAME}" pool_regcert_file="${POOL_FOLDER}/${pool_name}/${POOL_REGCERT_FILENAME}" - println "LOG" "creating de-registration cert" - println "ACTION" "${CCLI} stake-pool deregistration-certificate --cold-verification-key-file ${pool_coldkey_vk_file} --epoch ${epoch_enter} --out-file ${pool_deregcert_file}" + println LOG "creating de-registration cert" + println ACTION "${CCLI} stake-pool deregistration-certificate --cold-verification-key-file ${pool_coldkey_vk_file} --epoch ${epoch_enter} --out-file ${pool_deregcert_file}" ${CCLI} stake-pool deregistration-certificate --cold-verification-key-file ${pool_coldkey_vk_file} --epoch ${epoch_enter} --out-file ${pool_deregcert_file} if ! deRegisterPool; then waitForInput && continue @@ -2248,9 +2294,9 @@ function main { ;; ################################################################### list) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> POOL >> LIST" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" [[ ! $(ls -A "${POOL_FOLDER}" 2>/dev/null) ]] && echo && println "${FG_YELLOW}No pools available!${NC}" && waitForInput && continue while IFS= read -r -d '' pool; do echo @@ -2286,12 +2332,12 @@ function main { ;; ################################################################### show) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> POOL >> SHOW" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" [[ ! $(ls -A "${POOL_FOLDER}" 2>/dev/null) ]] && echo && println "${FG_YELLOW}No pools available!${NC}" && waitForInput && continue if [[ ${CNTOOLS_MODE} = "OFFLINE" ]]; then - println "DEBUG" "${FG_LGRAY}OFFLINE MODE${NC}: CNTools started in offline mode, locally saved info shown!" + println DEBUG "${FG_LGRAY}OFFLINE MODE${NC}: CNTools started in offline mode, locally saved info shown!" fi tput sc if ! selectPool "all" "${POOL_ID_FILENAME}"; then # ${pool_name} populated by selectPool function @@ -2299,12 +2345,12 @@ function main { fi tput rc && tput ed if [[ ${CNTOOLS_MODE} = "CONNECTED" ]]; then - tput sc && println "DEBUG" "Dumping ledger-state from node, can take a while on larger networks...\n" - println "ACTION" "timeout -k 5 $TIMEOUT_LEDGER_STATE ${CCLI} query ledger-state ${NETWORK_IDENTIFIER}" + tput sc && println DEBUG "Dumping ledger-state from node, can take a while on larger networks...\n" + println ACTION "timeout -k 5 $TIMEOUT_LEDGER_STATE ${CCLI} query ledger-state ${NETWORK_IDENTIFIER}" if ! ledger_state=$(timeout -k 5 $TIMEOUT_LEDGER_STATE ${CCLI} query ledger-state ${NETWORK_IDENTIFIER}); then tput rc && tput ed - println "ERROR" "${FG_RED}ERROR${NC}: ledger dump failed/timed out" - println "ERROR" "increase timeout value in cntools.config" + println ERROR "${FG_RED}ERROR${NC}: ledger dump failed/timed out" + println ERROR "increase timeout value in cntools.config" waitForInput && continue fi tput rc && tput ed @@ -2345,7 +2391,7 @@ function main { println "$(printf " %-19s : ${FG_LGRAY}%s${NC}" "Description" "$(jq -r .description "${pool_meta_file}")")" [[ -f "${pool_config}" ]] && meta_url="$(jq -r .json_url "${pool_config}")" || meta_url="---" println "$(printf " %-19s : ${FG_LGRAY}%s${NC}" "URL" "${meta_url}")" - println "ACTION" "${CCLI} stake-pool metadata-hash --pool-metadata-file ${pool_meta_file}" + println ACTION "${CCLI} stake-pool metadata-hash --pool-metadata-file ${pool_meta_file}" meta_hash="$( ${CCLI} stake-pool metadata-hash --pool-metadata-file "${pool_meta_file}" )" println "$(printf " %-19s : ${FG_LGRAY}%s${NC}" "Hash" "${meta_hash}")" else @@ -2361,7 +2407,7 @@ function main { println "$(printf " %-19s : ${FG_LGRAY}%s${NC}" "Homepage" "$(jq -r .homepage "$TMP_DIR/url_poolmeta.json")")" println "$(printf " %-19s : ${FG_LGRAY}%s${NC}" "Description" "$(jq -r .description "$TMP_DIR/url_poolmeta.json")")" println "$(printf " %-19s : ${FG_LGRAY}%s${NC}" "URL" "${meta_json_url}")" - println "ACTION" "${CCLI} stake-pool metadata-hash --pool-metadata-file ${TMP_DIR}/url_poolmeta.json" + println ACTION "${CCLI} stake-pool metadata-hash --pool-metadata-file ${TMP_DIR}/url_poolmeta.json" meta_hash_url="$( ${CCLI} stake-pool metadata-hash --pool-metadata-file "${TMP_DIR}/url_poolmeta.json" )" meta_hash_pParams=$(jq -r '.metadata.hash //empty' <<< "${ledger_pParams}") meta_hash_fPParams=$(jq -r '.metadata.hash //empty' <<< "${ledger_fPParams}") @@ -2480,7 +2526,7 @@ function main { println "$(printf "%-21s : ${FG_LGRAY}%s${NC}" "Reward account" "${reward_account}")" fi fi - println "ACTION" "LC_NUMERIC=C printf %.10f \$(${CCLI} query stake-distribution ${NETWORK_IDENTIFIER} | grep ${pool_id_bech32} | tr -s ' ' | cut -d ' ' -f 2))" + println ACTION "LC_NUMERIC=C printf %.10f \$(${CCLI} query stake-distribution ${NETWORK_IDENTIFIER} | grep ${pool_id_bech32} | tr -s ' ' | cut -d ' ' -f 2))" stake_pct=$(fractionToPCT "$(LC_NUMERIC=C printf "%.10f" "$(${CCLI} query stake-distribution ${NETWORK_IDENTIFIER} | grep "${pool_id_bech32}" | tr -s ' ' | cut -d ' ' -f 2)")") if validateDecimalNbr ${stake_pct}; then println "$(printf "%-21s : ${FG_LBLUE}%s${NC} %%" "Stake distribution" "${stake_pct}")" @@ -2506,12 +2552,12 @@ function main { rotate) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> POOL >> ROTATE KES" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" echo [[ ! $(ls -A "${POOL_FOLDER}" 2>/dev/null) ]] && println "${FG_YELLOW}No pools available!${NC}" && waitForInput && continue - println "DEBUG" "# Select pool to rotate KES keys on" + println DEBUG "# Select pool to rotate KES keys on" if ! selectPool "all" "${POOL_COLDKEY_SK_FILENAME}" "${POOL_HOTKEY_SK_FILENAME}" "${POOL_HOTKEY_VK_FILENAME}" "${POOL_OPCERT_COUNTER_FILENAME}"; then # ${pool_name} populated by selectPool function waitForInput && continue fi @@ -2524,39 +2570,39 @@ function main { println "KES keys will expire : ${FG_LBLUE}$(( current_kes_period + MAX_KES_EVOLUTIONS ))${NC} - ${FG_LGRAY}${expiration_date}${NC}" echo if [[ ${CNTOOLS_MODE} = "OFFLINE" ]]; then - println "DEBUG" "Copy updated files to pool node replacing existing files:" - println "DEBUG" "${FG_LGRAY}${pool_hotkey_sk_file}${NC}" - println "DEBUG" "${FG_LGRAY}${pool_opcert_file}${NC}" + println DEBUG "Copy updated files to pool node replacing existing files:" + println DEBUG "${FG_LGRAY}${pool_hotkey_sk_file}${NC}" + println DEBUG "${FG_LGRAY}${pool_opcert_file}${NC}" echo fi - println "DEBUG" "Restart your pool node for changes to take effect" + println DEBUG "Restart your pool node for changes to take effect" waitForInput && continue ;; ################################################################### decrypt) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> POOL >> DECRYPT" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" echo [[ ! $(ls -A "${POOL_FOLDER}" 2>/dev/null) ]] && println "${FG_YELLOW}No pools available!${NC}" && waitForInput && continue - println "DEBUG" "# Select pool to decrypt" + println DEBUG "# Select pool to decrypt" if ! selectPool "encrypted"; then # ${pool_name} populated by selectPool function waitForInput && continue fi filesUnlocked=0 keysDecrypted=0 echo - println "DEBUG" "# Removing write protection from all pool files" + println DEBUG "# Removing write protection from all pool files" while IFS= read -r -d '' file; do unlockFile "${file}" filesUnlocked=$((++filesUnlocked)) - println "DEBUG" "${file}" + println DEBUG "${file}" done < <(find "${POOL_FOLDER}/${pool_name}" -mindepth 1 -maxdepth 1 -type f -print0) if [[ $(find "${POOL_FOLDER}/${pool_name}" -mindepth 1 -maxdepth 1 -type f -name '*.gpg' -print0 | wc -c) -gt 0 ]]; then echo println "# Decrypting GPG encrypted pool files" - if ! getPassword; then # $password variable populated by getPassword function - println "\n\n" && println "ERROR" "${FG_RED}ERROR${NC}: password input aborted!" + if ! getPasswordCust; then # $password variable populated by getPasswordCust function + println "\n\n" && println ERROR "${FG_RED}ERROR${NC}: password input aborted!" waitForInput && continue fi while IFS= read -r -d '' file; do @@ -2572,19 +2618,19 @@ function main { println "Files decrypted : ${FG_LBLUE}${keysDecrypted}${NC}" if [[ ${filesUnlocked} -ne 0 || ${keysDecrypted} -ne 0 ]]; then echo - println "DEBUG" "${FG_YELLOW}Pool files are now unprotected${NC}" - println "DEBUG" "Use 'POOL >> ENCRYPT / LOCK' to re-lock" + println DEBUG "${FG_YELLOW}Pool files are now unprotected${NC}" + println DEBUG "Use 'POOL >> ENCRYPT / LOCK' to re-lock" fi waitForInput && continue ;; ################################################################### encrypt) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> POOL >> ENCRYPT" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" echo [[ ! $(ls -A "${POOL_FOLDER}" 2>/dev/null) ]] && println "${FG_YELLOW}No pools available!${NC}" && waitForInput && continue - println "DEBUG" "# Select pool to encrypt" + println DEBUG "# Select pool to encrypt" if ! selectPool "encrypted"; then # ${pool_name} populated by selectPool function waitForInput && continue fi @@ -2592,9 +2638,9 @@ function main { keysEncrypted=0 if [[ $(find "${POOL_FOLDER}/${pool_name}" -mindepth 1 -maxdepth 1 -type f -name '*.gpg' -print0 | wc -c) -le 0 ]]; then echo - println "DEBUG" "# Encrypting sensitive pool keys with GPG" - if ! getPassword confirm; then # $password variable populated by getPassword function - println "\n\n" && println "ERROR" "${FG_RED}ERROR${NC}: password input aborted!" + println DEBUG "# Encrypting sensitive pool keys with GPG" + if ! getPasswordCust confirm; then # $password variable populated by getPasswordCust function + println "\n\n" && println ERROR "${FG_RED}ERROR${NC}: password input aborted!" waitForInput && continue fi keyFiles=( @@ -2610,15 +2656,15 @@ function main { unset password else echo - println "DEBUG" "${FG_YELLOW}NOTE${NC}: found GPG encrypted files in folder, please decrypt/unlock pool files before encrypting" + println DEBUG "${FG_YELLOW}NOTE${NC}: found GPG encrypted files in folder, please decrypt/unlock pool files before encrypting" waitForInput && continue fi echo - println "DEBUG" "# Write protecting all pool files with 400 permission and if enabled 'chattr +i'" + println DEBUG "# Write protecting all pool files with 400 permission and if enabled 'chattr +i'" while IFS= read -r -d '' file; do lockFile "$file" filesLocked=$((++filesLocked)) - println "DEBUG" "$file" + println DEBUG "$file" done < <(find "${POOL_FOLDER}/${pool_name}" -mindepth 1 -maxdepth 1 -type f -print0) echo println "Pool encrypted : ${FG_GREEN}${pool_name}${NC}" @@ -2626,8 +2672,8 @@ function main { println "Files encrypted : ${FG_LBLUE}${keysEncrypted}${NC}" if [[ ${filesLocked} -ne 0 || ${keysEncrypted} -ne 0 ]]; then echo - println "DEBUG" "${FG_BLUE}INFO${NC}: pool files are now protected" - println "DEBUG" "Use 'POOL >> DECRYPT / UNLOCK' to unlock" + println DEBUG "${FG_BLUE}INFO${NC}: pool files are now protected" + println DEBUG "Use 'POOL >> DECRYPT / UNLOCK' to unlock" fi waitForInput && continue ;; ################################################################### @@ -2635,14 +2681,14 @@ function main { ;; ################################################################### transaction) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> TRANSACTION" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - println "OFF" " Transaction Management\n"\ + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println OFF " Transaction Management\n"\ " ) Sign - witness/sign offline tx with signing keys"\ " ) Submit - submit signed offline tx to blockchain"\ "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - println "DEBUG" " Select Transaction Operation\n" + println DEBUG " Select Transaction Operation\n" select_opt "[s] Sign" "[t] Submit" "[h] Home" case $? in 0) SUBCOMMAND="sign" ;; @@ -2652,125 +2698,123 @@ function main { case $SUBCOMMAND in sign) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> TRANSACTION >> SIGN" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" echo - [[ ${ENABLE_DIALOG} = "true" ]] && println "DEBUG" "Enter path to offline tx file to sign" && waitForInput "Press any key to open the file explorer" - fileDialog "Enter path to offline tx file to sign" "${TMP_DIR}/" - println "DEBUG" "${FG_LGRAY}${file}${NC}\n" + fileDialog "Enter path to offline tx file to sign" "${TMP_DIR}/" && echo offline_tx=${file} [[ -z "${offline_tx}" ]] && continue if [[ ! -f "${offline_tx}" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: file not found: ${offline_tx}" + println ERROR "${FG_RED}ERROR${NC}: file not found: ${offline_tx}" waitForInput && continue elif ! offlineJSON=$(jq -erc . "${offline_tx}"); then - println "ERROR" "${FG_RED}ERROR${NC}: invalid JSON file: ${offline_tx}" + println ERROR "${FG_RED}ERROR${NC}: invalid JSON file: ${offline_tx}" waitForInput && continue fi - if ! otx_type="$(jq -er '.type' <<< ${offlineJSON})"; then println "ERROR" "${FG_RED}ERROR${NC}: field 'type' not found in: ${offline_tx}" && waitForInput && continue; fi - if ! otx_date_created="$(jq -er '."date-created"' <<< ${offlineJSON})"; then println "ERROR" "${FG_RED}ERROR${NC}: field 'date-created' not found in: ${offline_tx}" && waitForInput && continue; fi - if ! otx_date_expire="$(jq -er '."date-expire"' <<< ${offlineJSON})"; then println "ERROR" "${FG_RED}ERROR${NC}: field 'date-expire' not found in: ${offline_tx}" && waitForInput && continue; fi - if ! otx_txFee=$(jq -er '.txFee' <<< ${offlineJSON}); then println "ERROR" "${FG_RED}ERROR${NC}: field 'txFee' not found in: ${offline_tx}" && waitForInput && continue; fi - if ! otx_txBody=$(jq -er '.txBody' <<< ${offlineJSON}); then println "ERROR" "${FG_RED}ERROR${NC}: field 'txBody' not found in: ${offline_tx}" && waitForInput && continue; fi + if ! otx_type="$(jq -er '.type' <<< ${offlineJSON})"; then println ERROR "${FG_RED}ERROR${NC}: field 'type' not found in: ${offline_tx}" && waitForInput && continue; fi + if ! otx_date_created="$(jq -er '."date-created"' <<< ${offlineJSON})"; then println ERROR "${FG_RED}ERROR${NC}: field 'date-created' not found in: ${offline_tx}" && waitForInput && continue; fi + if ! otx_date_expire="$(jq -er '."date-expire"' <<< ${offlineJSON})"; then println ERROR "${FG_RED}ERROR${NC}: field 'date-expire' not found in: ${offline_tx}" && waitForInput && continue; fi + if ! otx_txFee=$(jq -er '.txFee' <<< ${offlineJSON}); then println ERROR "${FG_RED}ERROR${NC}: field 'txFee' not found in: ${offline_tx}" && waitForInput && continue; fi + if ! otx_txBody=$(jq -er '.txBody' <<< ${offlineJSON}); then println ERROR "${FG_RED}ERROR${NC}: field 'txBody' not found in: ${offline_tx}" && waitForInput && continue; fi echo -e "${otx_txBody}" > "${TMP_DIR}"/tx.raw - [[ $(jq -r '."signed-txBody" | length' <<< ${offlineJSON}) -gt 0 ]] && println "ERROR" "${FG_RED}ERROR${NC}: transaction already signed, please submit transaction to complete!" && waitForInput && continue - println "DEBUG" "Transaction type : ${FG_GREEN}${otx_type}${NC}" + [[ $(jq -r '."signed-txBody" | length' <<< ${offlineJSON}) -gt 0 ]] && println ERROR "${FG_RED}ERROR${NC}: transaction already signed, please submit transaction to complete!" && waitForInput && continue + println DEBUG "Transaction type : ${FG_GREEN}${otx_type}${NC}" if wallet_name=$(jq -er '."wallet-name"' <<< ${offlineJSON}); then - println "DEBUG" "Transaction fee : ${FG_LBLUE}$(formatLovelace ${otx_txFee})${NC} Ada, payed by ${FG_GREEN}${wallet_name}${NC}" + println DEBUG "Transaction fee : ${FG_LBLUE}$(formatLovelace ${otx_txFee})${NC} Ada, payed by ${FG_GREEN}${wallet_name}${NC}" [[ $(cat "${WALLET_FOLDER}/${wallet_name}/${WALLET_PAY_ADDR_FILENAME}" 2>/dev/null) = "${addr}" ]] && wallet_source="enterprise" || wallet_source="base" else - println "DEBUG" "Transaction fee : ${FG_LBLUE}$(formatLovelace ${otx_txFee})${NC} Ada" + println DEBUG "Transaction fee : ${FG_LBLUE}$(formatLovelace ${otx_txFee})${NC} Ada" fi - println "DEBUG" "Created : ${FG_LGRAY}$(date '+%F %T %Z' --date="${otx_date_created}")${NC}" + println DEBUG "Created : ${FG_LGRAY}$(date '+%F %T %Z' --date="${otx_date_created}")${NC}" if [[ $(date '+%s' --date="${otx_date_expire}") -lt $(date '+%s') ]]; then - println "DEBUG" "Expire : ${FG_RED}$(date '+%F %T %Z' --date="${otx_date_expire}")${NC}" - println "ERROR" "\n${FG_RED}ERROR${NC}: offline transaction expired! please create a new one with long enough Time To Live (TTL)" + println DEBUG "Expire : ${FG_RED}$(date '+%F %T %Z' --date="${otx_date_expire}")${NC}" + println ERROR "\n${FG_RED}ERROR${NC}: offline transaction expired! please create a new one with long enough Time To Live (TTL)" waitForInput && continue else - println "DEBUG" "Expire : ${FG_LGRAY}$(date '+%F %T %Z' --date="${otx_date_expire}")${NC}" + println DEBUG "Expire : ${FG_LGRAY}$(date '+%F %T %Z' --date="${otx_date_expire}")${NC}" fi tx_witness_files=() tx_sign_files=() case "${otx_type}" in "Wallet Registration"|"Wallet De-Registration"|"Payment"|"Wallet Delegation"|"Wallet Rewards Withdrawal"|"Pool De-Registration"|"Metadata") - [[ ${otx_type} = "Wallet De-Registration" ]] && println "DEBUG" "\nAmount returned : ${FG_LBLUE}$(formatLovelace "$(jq -r '."amount-returned"' <<< ${offlineJSON})")${NC} Ada" + [[ ${otx_type} = "Wallet De-Registration" ]] && println DEBUG "\nAmount returned : ${FG_LBLUE}$(formatLovelace "$(jq -r '."amount-returned"' <<< ${offlineJSON})")${NC} Ada" if [[ ${otx_type} = "Payment" ]]; then - println "DEBUG" "\nSource addr : ${FG_LGRAY}$(jq -r '."source-address"' <<< ${offlineJSON})${NC}" - println "DEBUG" "Destination addr : ${FG_LGRAY}$(jq -r '."destination-address"' <<< ${offlineJSON})${NC}" - println "DEBUG" "Amount : ${FG_LBLUE}$(formatLovelace "$(jq -r '.assets[] | select(.asset=="lovelace") | .amount' <<< ${offlineJSON})")${NC} Ada" + println DEBUG "\nSource addr : ${FG_LGRAY}$(jq -r '."source-address"' <<< ${offlineJSON})${NC}" + println DEBUG "Destination addr : ${FG_LGRAY}$(jq -r '."destination-address"' <<< ${offlineJSON})${NC}" + println DEBUG "Amount : ${FG_LBLUE}$(formatLovelace "$(jq -r '.assets[] | select(.asset=="lovelace") | .amount' <<< ${offlineJSON})")${NC} Ada" for otx_assets in $(jq -r '.assets[] | @base64' <<< "${offlineJSON}"); do _jq() { base64 -d <<< ${otx_assets} | jq -r "${1}"; } otx_asset=$(_jq '.asset') [[ ${otx_asset} = "lovelace" ]] && continue - println "DEBUG" " ${FG_LBLUE}$(formatAsset "$(_jq '.amount')")${NC} ${FG_LGRAY}${otx_asset}${NC}" + println DEBUG " ${FG_LBLUE}$(formatAsset "$(_jq '.amount')")${NC} ${FG_LGRAY}${otx_asset}${NC}" done fi - [[ ${otx_type} = "Wallet Rewards Withdrawal" ]] && println "DEBUG" "\nRewards : ${FG_LBLUE}$(formatLovelace "$(jq -r '.rewards' <<< ${offlineJSON})")${NC} Ada" - [[ ${otx_type} = "Pool De-Registration" ]] && println "DEBUG" "\nPool name : ${FG_LGRAY}$(jq -r '."pool-name"' <<< ${offlineJSON})${NC}" - [[ ${otx_type} = "Pool De-Registration" ]] && println "DEBUG" "Ticker : ${FG_LGRAY}$(jq -r '."pool-ticker"' <<< ${offlineJSON})${NC}" - [[ ${otx_type} = "Pool De-Registration" ]] && println "DEBUG" "To be retired : epoch ${FG_LGRAY}$(jq -r '."retire-epoch"' <<< ${offlineJSON})${NC}" - [[ ${otx_type} = "Metadata" ]] && println "DEBUG" "\nMetadata :\n$(jq -r '.metadata' <<< ${offlineJSON})\n" - [[ ${otx_type} = "Asset Minting" || ${otx_type} = "Asset Burning" ]] && println "DEBUG" "\nPolicy Name : ${FG_LGRAY}$(jq -r '."policy-name"' <<< ${offlineJSON})${NC}" - [[ ${otx_type} = "Asset Minting" || ${otx_type} = "Asset Burning" ]] && println "DEBUG" "Policy ID : ${FG_LGRAY}$(jq -r '."policy-id"' <<< ${offlineJSON})${NC}" - [[ ${otx_type} = "Asset Minting" || ${otx_type} = "Asset Burning" ]] && println "DEBUG" "Asset Name : ${FG_LGRAY}$(jq -r '."asset-name"' <<< ${offlineJSON})${NC}" - [[ ${otx_type} = "Asset Minting" ]] && println "DEBUG" "Assets To Mint : ${FG_LBLUE}$(formatAsset "$(jq -r '."asset-amount"' <<< ${offlineJSON})")${NC}" - [[ ${otx_type} = "Asset Minting" ]] && println "DEBUG" "Assets Minted : ${FG_LBLUE}$(formatAsset "$(jq -r '."asset-minted"' <<< ${offlineJSON})")${NC}" - [[ ${otx_type} = "Asset Burning" ]] && println "DEBUG" "Assets To Burn : ${FG_LBLUE}$(formatAsset "$(jq -r '."asset-amount"' <<< ${offlineJSON})")${NC}" - [[ ${otx_type} = "Asset Burning" ]] && println "DEBUG" "Assets Left : ${FG_LBLUE}$(formatAsset "$(jq -r '."asset-minted"' <<< ${offlineJSON})")${NC}" + [[ ${otx_type} = "Wallet Rewards Withdrawal" ]] && println DEBUG "\nRewards : ${FG_LBLUE}$(formatLovelace "$(jq -r '.rewards' <<< ${offlineJSON})")${NC} Ada" + [[ ${otx_type} = "Pool De-Registration" ]] && println DEBUG "\nPool name : ${FG_LGRAY}$(jq -r '."pool-name"' <<< ${offlineJSON})${NC}" + [[ ${otx_type} = "Pool De-Registration" ]] && println DEBUG "Ticker : ${FG_LGRAY}$(jq -r '."pool-ticker"' <<< ${offlineJSON})${NC}" + [[ ${otx_type} = "Pool De-Registration" ]] && println DEBUG "To be retired : epoch ${FG_LGRAY}$(jq -r '."retire-epoch"' <<< ${offlineJSON})${NC}" + [[ ${otx_type} = "Metadata" ]] && println DEBUG "\nMetadata :\n$(jq -r '.metadata' <<< ${offlineJSON})\n" + [[ ${otx_type} = "Asset Minting" || ${otx_type} = "Asset Burning" ]] && println DEBUG "\nPolicy Name : ${FG_LGRAY}$(jq -r '."policy-name"' <<< ${offlineJSON})${NC}" + [[ ${otx_type} = "Asset Minting" || ${otx_type} = "Asset Burning" ]] && println DEBUG "Policy ID : ${FG_LGRAY}$(jq -r '."policy-id"' <<< ${offlineJSON})${NC}" + [[ ${otx_type} = "Asset Minting" || ${otx_type} = "Asset Burning" ]] && println DEBUG "Asset Name : ${FG_LGRAY}$(jq -r '."asset-name"' <<< ${offlineJSON})${NC}" + [[ ${otx_type} = "Asset Minting" ]] && println DEBUG "Assets To Mint : ${FG_LBLUE}$(formatAsset "$(jq -r '."asset-amount"' <<< ${offlineJSON})")${NC}" + [[ ${otx_type} = "Asset Minting" ]] && println DEBUG "Assets Minted : ${FG_LBLUE}$(formatAsset "$(jq -r '."asset-minted"' <<< ${offlineJSON})")${NC}" + [[ ${otx_type} = "Asset Burning" ]] && println DEBUG "Assets To Burn : ${FG_LBLUE}$(formatAsset "$(jq -r '."asset-amount"' <<< ${offlineJSON})")${NC}" + [[ ${otx_type} = "Asset Burning" ]] && println DEBUG "Assets Left : ${FG_LBLUE}$(formatAsset "$(jq -r '."asset-minted"' <<< ${offlineJSON})")${NC}" for otx_signing_file in $(jq -r '."signing-file"[] | @base64' <<< "${offlineJSON}"); do _jq() { base64 -d <<< ${otx_signing_file} | jq -r "${1}"; } otx_signing_name=$(_jq '.name') - println "DEBUG" "\n# Sign the transaction with: ${FG_YELLOW}${otx_signing_name}${NC}" - [[ ${ENABLE_DIALOG} = "true" ]] && waitForInput "Press any key to open the file explorer" + println DEBUG "\n# Sign the transaction with: ${FG_YELLOW}${otx_signing_name}${NC}" [[ ${otx_signing_name} = "Wallet "* ]] && dialog_start_path="${WALLET_FOLDER}" || dialog_start_path="${POOL_FOLDER}" fileDialog "Enter path to ${otx_signing_name}" "${dialog_start_path}/" - [[ ! -f "${file}" ]] && println "ERROR" "${FG_RED}ERROR${NC}: file not found: ${file}" && waitForInput && continue 2 + [[ ! -f "${file}" ]] && println ERROR "${FG_RED}ERROR${NC}: file not found: ${file}" && waitForInput && continue 2 otx_vkey_cborHex="$(_jq '.vkey.cborHex')" if [[ $(jq -r '.description' "${file}") = *"Hardware"* ]]; then if ! grep -q "${otx_vkey_cborHex:4}" "${file}"; then # strip 5820 prefix - println "ERROR" "${FG_RED}ERROR${NC}: signing key provided doesn't match with verification key in offline transaction for: ${otx_signing_name}" - println "ERROR" "Provided hardware signing key's verification cborXPubKeyHex: $(jq -r .cborXPubKeyHex "${file}")" - println "ERROR" "Transaction verification cborHex: ${otx_vkey_cborHex:4}" + println ERROR "${FG_RED}ERROR${NC}: signing key provided doesn't match with verification key in offline transaction for: ${otx_signing_name}" + println ERROR "Provided hardware signing key's verification cborXPubKeyHex: $(jq -r .cborXPubKeyHex "${file}")" + println ERROR "Transaction verification cborHex: ${otx_vkey_cborHex:4}" waitForInput && continue 2 fi else - println "ACTION" "${CCLI} key verification-key --signing-key-file ${file} --verification-key-file ${TMP_DIR}/tmp.vkey" + println ACTION "${CCLI} key verification-key --signing-key-file ${file} --verification-key-file ${TMP_DIR}/tmp.vkey" if ! ${CCLI} key verification-key --signing-key-file "${file}" --verification-key-file "${TMP_DIR}"/tmp.vkey; then waitForInput && continue 2; fi if [[ $(jq -r '.type' "${file}") = *"Extended"* ]]; then - println "ACTION" "${CCLI} key non-extended-key --extended-verification-key-file ${TMP_DIR}/tmp.vkey --verification-key-file ${TMP_DIR}/tmp2.vkey" + println ACTION "${CCLI} key non-extended-key --extended-verification-key-file ${TMP_DIR}/tmp.vkey --verification-key-file ${TMP_DIR}/tmp2.vkey" if ! ${CCLI} key non-extended-key --extended-verification-key-file "${TMP_DIR}/tmp.vkey" --verification-key-file "${TMP_DIR}/tmp2.vkey"; then waitForInput && continue 2; fi mv -f "${TMP_DIR}/tmp2.vkey" "${TMP_DIR}/tmp.vkey" fi if [[ ${otx_vkey_cborHex} != $(jq -r .cborHex "${TMP_DIR}"/tmp.vkey) ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: signing key provided doesn't match with verification key in offline transaction for: ${otx_signing_name}" - println "ERROR" "Provided signing key's verification cborHex: $(jq -r .cborHex "${TMP_DIR}"/tmp.vkey)" - println "ERROR" "Transaction verification cborHex: ${otx_vkey_cborHex}" + println ERROR "${FG_RED}ERROR${NC}: signing key provided doesn't match with verification key in offline transaction for: ${otx_signing_name}" + println ERROR "Provided signing key's verification cborHex: $(jq -r .cborHex "${TMP_DIR}"/tmp.vkey)" + println ERROR "Transaction verification cborHex: ${otx_vkey_cborHex}" waitForInput && continue 2 fi fi - println "DEBUG" "${FG_GREEN}Successfully added!${NC}" + println DEBUG "${FG_GREEN}Successfully added!${NC}" tx_sign_files+=( "${file}" ) done if [[ ${#tx_sign_files[@]} -gt 0 ]]; then if ! signTx "${TMP_DIR}"/tx.raw "${tx_sign_files[@]}"; then waitForInput && continue; fi echo if jq ". += { \"signed-txBody\": $(jq -c . "${tx_signed}") }" <<< "${offlineJSON}" > "${offline_tx}"; then - println "Offline transaction successfully signed, please move ${offline_tx} back to online node and submit before ${FG_LGRAY}$(date '+%F %T %Z' --date="${otx_date_expire}")${NC}!" + println "Offline transaction successfully signed" + println "please move ${offline_tx} back to online node and submit before ${FG_LGRAY}$(date '+%F %T %Z' --date="${otx_date_expire}")${NC}!" else - println "ERROR" "${FG_RED}ERROR${NC}: failed to write signed tx body to offline transaction file!" + println ERROR "${FG_RED}ERROR${NC}: failed to write signed tx body to offline transaction file!" fi else - println "ERROR" "\n${FG_YELLOW}WARN${NC}: no signing keys added!" + println ERROR "\n${FG_YELLOW}WARN${NC}: no signing keys added!" fi ;; "Pool Registration"|"Pool Update") echo - println "DEBUG" "Pool name : ${FG_LGRAY}$(jq -r '."pool-metadata".name' <<< ${offlineJSON})${NC}" - println "DEBUG" "Ticker : ${FG_LGRAY}$(jq -r '."pool-metadata".ticker' <<< ${offlineJSON})${NC}" - println "DEBUG" "Pledge : ${FG_LBLUE}$(formatAsset "$(jq -r '."pool-pledge"' <<< ${offlineJSON})")${NC} Ada" - println "DEBUG" "Margin : ${FG_LBLUE}$(jq -r '."pool-margin"' <<< ${offlineJSON})${NC} %" - println "DEBUG" "Cost : ${FG_LBLUE}$(formatAsset "$(jq -r '."pool-cost"' <<< ${offlineJSON})")${NC} Ada" + println DEBUG "Pool name : ${FG_LGRAY}$(jq -r '."pool-metadata".name' <<< ${offlineJSON})${NC}" + println DEBUG "Ticker : ${FG_LGRAY}$(jq -r '."pool-metadata".ticker' <<< ${offlineJSON})${NC}" + println DEBUG "Pledge : ${FG_LBLUE}$(formatAsset "$(jq -r '."pool-pledge"' <<< ${offlineJSON})")${NC} Ada" + println DEBUG "Margin : ${FG_LBLUE}$(jq -r '."pool-margin"' <<< ${offlineJSON})${NC} %" + println DEBUG "Cost : ${FG_LBLUE}$(formatAsset "$(jq -r '."pool-cost"' <<< ${offlineJSON})")${NC} Ada" for otx_signing_file in $(jq -r '."signing-file"[] | @base64' <<< "${offlineJSON}"); do _jq() { base64 -d <<< ${otx_signing_file} | jq -r "${1}"; } otx_signing_name=$(_jq '.name') @@ -2778,32 +2822,32 @@ function main { __jq() { base64 -d <<< ${otx_witness} | jq -r "${1}"; } [[ $(_jq '.name') = $(__jq '.name') ]] && continue 2 # offline transaction already witnessed by this signing key done - println "DEBUG" "\nDo you want to sign ${otx_type} with: ${FG_LGRAY}${otx_signing_name}${NC} ?" + println DEBUG "\nDo you want to sign ${otx_type} with: ${FG_LGRAY}${otx_signing_name}${NC} ?" select_opt "[y] Yes" "[n] No" case $? in 0) [[ ${otx_signing_name} = "Pool "* ]] && dialog_start_path="${POOL_FOLDER}" || dialog_start_path="${WALLET_FOLDER}" fileDialog "Enter path to ${otx_signing_name}" "${dialog_start_path}/" - [[ ! -f "${file}" ]] && println "ERROR" "${FG_RED}ERROR${NC}: file not found: ${file}" && waitForInput && continue 2 + [[ ! -f "${file}" ]] && println ERROR "${FG_RED}ERROR${NC}: file not found: ${file}" && waitForInput && continue 2 otx_vkey_cborHex="$(_jq '.vkey.cborHex')" if [[ $(jq -r '.description' "${file}") = *"Hardware"* ]]; then if ! grep -q "${otx_vkey_cborHex:4}" "${file}"; then # strip 5820 prefix - println "ERROR" "${FG_RED}ERROR${NC}: signing key provided doesn't match with verification key in offline transaction for: ${otx_signing_name}" - println "ERROR" "Provided hardware signing key's verification cborXPubKeyHex: $(jq -r .cborXPubKeyHex "${file}")" - println "ERROR" "Transaction verification cborHex: ${otx_vkey_cborHex:4}" + println ERROR "${FG_RED}ERROR${NC}: signing key provided doesn't match with verification key in offline transaction for: ${otx_signing_name}" + println ERROR "Provided hardware signing key's verification cborXPubKeyHex: $(jq -r .cborXPubKeyHex "${file}")" + println ERROR "Transaction verification cborHex: ${otx_vkey_cborHex:4}" waitForInput && continue 2 fi else - println "ACTION" "${CCLI} key verification-key --signing-key-file ${file} --verification-key-file ${TMP_DIR}/tmp.vkey" + println ACTION "${CCLI} key verification-key --signing-key-file ${file} --verification-key-file ${TMP_DIR}/tmp.vkey" if ! ${CCLI} key verification-key --signing-key-file "${file}" --verification-key-file "${TMP_DIR}"/tmp.vkey; then waitForInput && continue 2; fi if [[ $(jq -r '.type' "${file}") = *"Extended"* ]]; then - println "ACTION" "${CCLI} key non-extended-key --extended-verification-key-file ${TMP_DIR}/tmp.vkey --verification-key-file ${TMP_DIR}/tmp2.vkey" + println ACTION "${CCLI} key non-extended-key --extended-verification-key-file ${TMP_DIR}/tmp.vkey --verification-key-file ${TMP_DIR}/tmp2.vkey" if ! ${CCLI} key non-extended-key --extended-verification-key-file "${TMP_DIR}/tmp.vkey" --verification-key-file "${TMP_DIR}/tmp2.vkey"; then waitForInput && continue 2; fi mv -f "${TMP_DIR}/tmp2.vkey" "${TMP_DIR}/tmp.vkey" fi if [[ ${otx_vkey_cborHex} != $(jq -r .cborHex "${TMP_DIR}"/tmp.vkey) ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: signing key provided doesn't match with verification key in offline transaction for: ${otx_signing_name}" - println "ERROR" "Provided signing key's verification cborHex: $(jq -r .cborHex "${TMP_DIR}"/tmp.vkey)" - println "ERROR" "Transaction verification cborHex: ${otx_vkey_cborHex}" + println ERROR "${FG_RED}ERROR${NC}: signing key provided doesn't match with verification key in offline transaction for: ${otx_signing_name}" + println ERROR "Provided signing key's verification cborHex: $(jq -r .cborHex "${TMP_DIR}"/tmp.vkey)" + println ERROR "Transaction verification cborHex: ${otx_vkey_cborHex}" waitForInput && continue 2 fi fi @@ -2827,92 +2871,90 @@ function main { println "Offline transaction successfully assembled and signed by all signing keys" println "please move ${offline_tx} back to online node and submit before ${FG_LGRAY}$(date '+%F %T %Z' --date="${otx_date_expire}")${NC}!" else - println "ERROR" "${FG_RED}ERROR${NC}: failed to write signed tx body to offline transaction file!" + println ERROR "${FG_RED}ERROR${NC}: failed to write signed tx body to offline transaction file!" fi else println "Offline transaction need to be signed by ${FG_LBLUE}$(jq -r '."signing-file" | length' <<< "${offlineJSON}")${NC} signing keys, signed by ${FG_LBLUE}$(jq -r '.witness | length' <<< "${offlineJSON}")${NC} so far!" fi ;; - *) println "ERROR" "${FG_RED}ERROR${NC}: unsupported offline tx type: ${otx_type}" && waitForInput && continue ;; + *) println ERROR "${FG_RED}ERROR${NC}: unsupported offline tx type: ${otx_type}" && waitForInput && continue ;; esac waitForInput && continue ;; ################################################################### submit) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> TRANSACTION >> SUBMIT" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" if [[ ${CNTOOLS_MODE} = "OFFLINE" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: CNTools started in offline mode, option not available!" + println ERROR "${FG_RED}ERROR${NC}: CNTools started in offline mode, option not available!" waitForInput && continue fi echo - [[ ${ENABLE_DIALOG} = "true" ]] && println "DEBUG" "Enter path to offline tx file to submit" && waitForInput "Press any key to open the file explorer" - fileDialog "Enter path to offline tx file to submit" "${TMP_DIR}/" - println "DEBUG" "${FG_LGRAY}${file}${NC}\n" + fileDialog "Enter path to offline tx file to submit" "${TMP_DIR}/" && echo offline_tx=${file} [[ -z "${offline_tx}" ]] && continue if [[ ! -f "${offline_tx}" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: file not found: ${offline_tx}" + println ERROR "${FG_RED}ERROR${NC}: file not found: ${offline_tx}" waitForInput && continue elif ! offlineJSON=$(jq -erc . "${offline_tx}"); then - println "ERROR" "${FG_RED}ERROR${NC}: invalid JSON file: ${offline_tx}" + println ERROR "${FG_RED}ERROR${NC}: invalid JSON file: ${offline_tx}" waitForInput && continue fi - if ! otx_type=$(jq -er '.type' <<< ${offlineJSON}); then println "ERROR" "${FG_RED}ERROR${NC}: field 'type' not found in: ${offline_tx}" && waitForInput && continue; fi - if ! otx_date_created=$(jq -er '."date-created"' <<< ${offlineJSON}); then println "ERROR" "${FG_RED}ERROR${NC}: field 'date-created' not found in: ${offline_tx}" && waitForInput && continue; fi - if ! otx_date_expire=$(jq -er '."date-expire"' <<< ${offlineJSON}); then println "ERROR" "${FG_RED}ERROR${NC}: field 'date-expire' not found in: ${offline_tx}" && waitForInput && continue; fi - if ! otx_txFee=$(jq -er '.txFee' <<< ${offlineJSON}); then println "ERROR" "${FG_RED}ERROR${NC}: field 'txFee' not found in: ${offline_tx}" && waitForInput && continue; fi - if ! otx_signed_txBody=$(jq -er '."signed-txBody"' <<< ${offlineJSON}); then println "ERROR" "${FG_RED}ERROR${NC}: field 'signed-txBody' not found in: ${offline_tx}" && waitForInput && continue; fi - [[ $(jq 'length' <<< ${otx_signed_txBody}) -eq 0 ]] && println "ERROR" "${FG_RED}ERROR${NC}: transaction not signed, please sign transaction first!" && waitForInput && continue - println "DEBUG" "Transaction type : ${FG_YELLOW}${otx_type}${NC}" + if ! otx_type=$(jq -er '.type' <<< ${offlineJSON}); then println ERROR "${FG_RED}ERROR${NC}: field 'type' not found in: ${offline_tx}" && waitForInput && continue; fi + if ! otx_date_created=$(jq -er '."date-created"' <<< ${offlineJSON}); then println ERROR "${FG_RED}ERROR${NC}: field 'date-created' not found in: ${offline_tx}" && waitForInput && continue; fi + if ! otx_date_expire=$(jq -er '."date-expire"' <<< ${offlineJSON}); then println ERROR "${FG_RED}ERROR${NC}: field 'date-expire' not found in: ${offline_tx}" && waitForInput && continue; fi + if ! otx_txFee=$(jq -er '.txFee' <<< ${offlineJSON}); then println ERROR "${FG_RED}ERROR${NC}: field 'txFee' not found in: ${offline_tx}" && waitForInput && continue; fi + if ! otx_signed_txBody=$(jq -er '."signed-txBody"' <<< ${offlineJSON}); then println ERROR "${FG_RED}ERROR${NC}: field 'signed-txBody' not found in: ${offline_tx}" && waitForInput && continue; fi + [[ $(jq 'length' <<< ${otx_signed_txBody}) -eq 0 ]] && println ERROR "${FG_RED}ERROR${NC}: transaction not signed, please sign transaction first!" && waitForInput && continue + println DEBUG "Transaction type : ${FG_YELLOW}${otx_type}${NC}" if jq -er '."wallet-name"' &>/dev/null <<< ${offlineJSON}; then - println "DEBUG" "Transaction fee : ${FG_LBLUE}$(formatLovelace ${otx_txFee})${NC} Ada, payed by ${FG_GREEN}$(jq -r '."wallet-name"' <<< ${offlineJSON})${NC}" + println DEBUG "Transaction fee : ${FG_LBLUE}$(formatLovelace ${otx_txFee})${NC} Ada, payed by ${FG_GREEN}$(jq -r '."wallet-name"' <<< ${offlineJSON})${NC}" else - println "DEBUG" "Transaction fee : ${FG_LBLUE}$(formatLovelace ${otx_txFee})${NC} Ada" + println DEBUG "Transaction fee : ${FG_LBLUE}$(formatLovelace ${otx_txFee})${NC} Ada" fi - println "DEBUG" "Created : ${FG_LGRAY}$(date '+%F %T %Z' --date="${otx_date_created}")${NC}" + println DEBUG "Created : ${FG_LGRAY}$(date '+%F %T %Z' --date="${otx_date_created}")${NC}" if [[ $(date '+%s' --date="${otx_date_expire}") -lt $(date '+%s') ]]; then - println "DEBUG" "Expire : ${FG_RED}$(date '+%F %T %Z' --date="${otx_date_expire}")${NC}" - println "ERROR" "\n${FG_RED}ERROR${NC}: offline transaction expired! please create a new one with long enough Time To Live (TTL)" + println DEBUG "Expire : ${FG_RED}$(date '+%F %T %Z' --date="${otx_date_expire}")${NC}" + println ERROR "\n${FG_RED}ERROR${NC}: offline transaction expired! please create a new one with long enough Time To Live (TTL)" waitForInput && continue else - println "DEBUG" "Expire : ${FG_LGRAY}$(date '+%F %T %Z' --date="${otx_date_expire}")${NC}" + println DEBUG "Expire : ${FG_LGRAY}$(date '+%F %T %Z' --date="${otx_date_expire}")${NC}" fi case "${otx_type}" in "Wallet Registration"|"Wallet De-Registration"|"Payment"|"Wallet Delegation"|"Wallet Rewards Withdrawal"|"Pool De-Registration"|"Metadata"|"Pool Registration"|"Pool Update"|"Asset Minting"|"Asset Burning") - [[ ${otx_type} = "Wallet De-Registration" ]] && println "DEBUG" "\nAmount returned : ${FG_LBLUE}$(formatLovelace "$(jq -r '."amount-returned"' <<< ${offlineJSON})")${NC} Ada" + [[ ${otx_type} = "Wallet De-Registration" ]] && println DEBUG "\nAmount returned : ${FG_LBLUE}$(formatLovelace "$(jq -r '."amount-returned"' <<< ${offlineJSON})")${NC} Ada" if [[ ${otx_type} = "Payment" ]]; then - println "DEBUG" "\nSource addr : ${FG_LGRAY}$(jq -r '."source-address"' <<< ${offlineJSON})${NC}" - println "DEBUG" "Destination addr : ${FG_LGRAY}$(jq -r '."destination-address"' <<< ${offlineJSON})${NC}" - println "DEBUG" "Amount : ${FG_LBLUE}$(formatLovelace "$(jq -r '.assets[] | select(.asset=="lovelace") | .amount' <<< ${offlineJSON})")${NC} ${FG_GREEN}Ada${NC}" + println DEBUG "\nSource addr : ${FG_LGRAY}$(jq -r '."source-address"' <<< ${offlineJSON})${NC}" + println DEBUG "Destination addr : ${FG_LGRAY}$(jq -r '."destination-address"' <<< ${offlineJSON})${NC}" + println DEBUG "Amount : ${FG_LBLUE}$(formatLovelace "$(jq -r '.assets[] | select(.asset=="lovelace") | .amount' <<< ${offlineJSON})")${NC} ${FG_GREEN}Ada${NC}" for otx_assets in $(jq -r '.assets[] | @base64' <<< "${offlineJSON}"); do _jq() { base64 -d <<< ${otx_assets} | jq -r "${1}"; } otx_asset=$(_jq '.asset') [[ ${otx_asset} = "lovelace" ]] && continue - println "DEBUG" " ${FG_LBLUE}$(formatAsset "$(_jq '.amount')")${NC} ${FG_LGRAY}${otx_asset}${NC}" + println DEBUG " ${FG_LBLUE}$(formatAsset "$(_jq '.amount')")${NC} ${FG_LGRAY}${otx_asset}${NC}" done fi - [[ ${otx_type} = "Wallet Rewards Withdrawal" ]] && println "DEBUG" "\nRewards : ${FG_LBLUE}$(formatLovelace "$(jq -r '.rewards' <<< ${offlineJSON})")${NC} Ada" - [[ ${otx_type} = "Pool De-Registration" ]] && println "DEBUG" "\nPool name : ${FG_LGRAY}$(jq -r '."pool-name"' <<< ${offlineJSON})${NC}" - [[ ${otx_type} = "Pool De-Registration" ]] && println "DEBUG" "Ticker : ${FG_LGRAY}$(jq -r '."pool-ticker"' <<< ${offlineJSON})${NC}" - [[ ${otx_type} = "Pool De-Registration" ]] && println "DEBUG" "To be retired : epoch ${FG_LGRAY}$(jq -r '."retire-epoch"' <<< ${offlineJSON})${NC}" - [[ ${otx_type} = "Metadata" ]] && println "DEBUG" "\nMetadata :\n$(jq -r '.metadata' <<< ${offlineJSON})\n" - [[ ${otx_type} = "Pool Registration" || ${otx_type} = "Pool Update" ]] && println "DEBUG" "\nPool name : ${FG_LGRAY}$(jq -r '."pool-metadata".name' <<< ${offlineJSON})${NC}" - [[ ${otx_type} = "Pool Registration" || ${otx_type} = "Pool Update" ]] && println "DEBUG" "Ticker : ${FG_LGRAY}$(jq -r '."pool-metadata".ticker' <<< ${offlineJSON})${NC}" - [[ ${otx_type} = "Pool Registration" || ${otx_type} = "Pool Update" ]] && println "DEBUG" "Pledge : ${FG_LBLUE}$(formatAsset "$(jq -r '."pool-pledge"' <<< ${offlineJSON})")${NC} Ada" - [[ ${otx_type} = "Pool Registration" || ${otx_type} = "Pool Update" ]] && println "DEBUG" "Margin : ${FG_LBLUE}$(jq -r '."pool-margin"' <<< ${offlineJSON})${NC} %" - [[ ${otx_type} = "Pool Registration" || ${otx_type} = "Pool Update" ]] && println "DEBUG" "Cost : ${FG_LBLUE}$(formatAsset "$(jq -r '."pool-cost"' <<< ${offlineJSON})")${NC} Ada" - [[ ${otx_type} = "Asset Minting" || ${otx_type} = "Asset Burning" ]] && println "DEBUG" "\nPolicy Name : ${FG_LGRAY}$(jq -r '."policy-name"' <<< ${offlineJSON})${NC}" - [[ ${otx_type} = "Asset Minting" || ${otx_type} = "Asset Burning" ]] && println "DEBUG" "Policy ID : ${FG_LGRAY}$(jq -r '."policy-id"' <<< ${offlineJSON})${NC}" - [[ ${otx_type} = "Asset Minting" || ${otx_type} = "Asset Burning" ]] && println "DEBUG" "Asset Name : ${FG_LGRAY}$(jq -r '."asset-name"' <<< ${offlineJSON})${NC}" - [[ ${otx_type} = "Asset Minting" ]] && println "DEBUG" "Assets To Mint : ${FG_LBLUE}$(formatAsset "$(jq -r '."asset-amount"' <<< ${offlineJSON})")${NC}" - [[ ${otx_type} = "Asset Minting" ]] && println "DEBUG" "Assets Minted : ${FG_LBLUE}$(formatAsset "$(jq -r '."asset-minted"' <<< ${offlineJSON})")${NC}" - [[ ${otx_type} = "Asset Burning" ]] && println "DEBUG" "Assets To Burn : ${FG_LBLUE}$(formatAsset "$(jq -r '."asset-amount"' <<< ${offlineJSON})")${NC}" - [[ ${otx_type} = "Asset Burning" ]] && println "DEBUG" "Assets Left : ${FG_LBLUE}$(formatAsset "$(jq -r '."asset-minted"' <<< ${offlineJSON})")${NC}" - if [[ ${otx_type} = "Asset Minting" || ${otx_type} = "Asset Burning" ]] && otx_metadata=$(jq -er '.metadata' <<< ${offlineJSON}); then println "DEBUG" "Metadata : \n${otx_metadata}\n"; fi + [[ ${otx_type} = "Wallet Rewards Withdrawal" ]] && println DEBUG "\nRewards : ${FG_LBLUE}$(formatLovelace "$(jq -r '.rewards' <<< ${offlineJSON})")${NC} Ada" + [[ ${otx_type} = "Pool De-Registration" ]] && println DEBUG "\nPool name : ${FG_LGRAY}$(jq -r '."pool-name"' <<< ${offlineJSON})${NC}" + [[ ${otx_type} = "Pool De-Registration" ]] && println DEBUG "Ticker : ${FG_LGRAY}$(jq -r '."pool-ticker"' <<< ${offlineJSON})${NC}" + [[ ${otx_type} = "Pool De-Registration" ]] && println DEBUG "To be retired : epoch ${FG_LGRAY}$(jq -r '."retire-epoch"' <<< ${offlineJSON})${NC}" + [[ ${otx_type} = "Metadata" ]] && println DEBUG "\nMetadata :\n$(jq -r '.metadata' <<< ${offlineJSON})\n" + [[ ${otx_type} = "Pool Registration" || ${otx_type} = "Pool Update" ]] && println DEBUG "\nPool name : ${FG_LGRAY}$(jq -r '."pool-metadata".name' <<< ${offlineJSON})${NC}" + [[ ${otx_type} = "Pool Registration" || ${otx_type} = "Pool Update" ]] && println DEBUG "Ticker : ${FG_LGRAY}$(jq -r '."pool-metadata".ticker' <<< ${offlineJSON})${NC}" + [[ ${otx_type} = "Pool Registration" || ${otx_type} = "Pool Update" ]] && println DEBUG "Pledge : ${FG_LBLUE}$(formatAsset "$(jq -r '."pool-pledge"' <<< ${offlineJSON})")${NC} Ada" + [[ ${otx_type} = "Pool Registration" || ${otx_type} = "Pool Update" ]] && println DEBUG "Margin : ${FG_LBLUE}$(jq -r '."pool-margin"' <<< ${offlineJSON})${NC} %" + [[ ${otx_type} = "Pool Registration" || ${otx_type} = "Pool Update" ]] && println DEBUG "Cost : ${FG_LBLUE}$(formatAsset "$(jq -r '."pool-cost"' <<< ${offlineJSON})")${NC} Ada" + [[ ${otx_type} = "Asset Minting" || ${otx_type} = "Asset Burning" ]] && println DEBUG "\nPolicy Name : ${FG_LGRAY}$(jq -r '."policy-name"' <<< ${offlineJSON})${NC}" + [[ ${otx_type} = "Asset Minting" || ${otx_type} = "Asset Burning" ]] && println DEBUG "Policy ID : ${FG_LGRAY}$(jq -r '."policy-id"' <<< ${offlineJSON})${NC}" + [[ ${otx_type} = "Asset Minting" || ${otx_type} = "Asset Burning" ]] && println DEBUG "Asset Name : ${FG_LGRAY}$(jq -r '."asset-name"' <<< ${offlineJSON})${NC}" + [[ ${otx_type} = "Asset Minting" ]] && println DEBUG "Assets To Mint : ${FG_LBLUE}$(formatAsset "$(jq -r '."asset-amount"' <<< ${offlineJSON})")${NC}" + [[ ${otx_type} = "Asset Minting" ]] && println DEBUG "Assets Minted : ${FG_LBLUE}$(formatAsset "$(jq -r '."asset-minted"' <<< ${offlineJSON})")${NC}" + [[ ${otx_type} = "Asset Burning" ]] && println DEBUG "Assets To Burn : ${FG_LBLUE}$(formatAsset "$(jq -r '."asset-amount"' <<< ${offlineJSON})")${NC}" + [[ ${otx_type} = "Asset Burning" ]] && println DEBUG "Assets Left : ${FG_LBLUE}$(formatAsset "$(jq -r '."asset-minted"' <<< ${offlineJSON})")${NC}" + if [[ ${otx_type} = "Asset Minting" || ${otx_type} = "Asset Burning" ]] && otx_metadata=$(jq -er '.metadata' <<< ${offlineJSON}); then println DEBUG "Metadata : \n${otx_metadata}\n"; fi tx_signed="${TMP_DIR}/tx.signed_$(date +%s)" - println "DEBUG" "\nProceed to submit transaction?" + println DEBUG "\nProceed to submit transaction?" select_opt "[y] Yes" "[n] No" case $? in 0) : ;; @@ -2922,23 +2964,23 @@ function main { if ! submitTx "${tx_signed}"; then waitForInput && continue; fi if [[ ${otx_type} = "Pool Registration" || ${otx_type} = "Pool Update" ]]; then if otx_pool_name=$(jq -er '."pool-name"' <<< ${offlineJSON}); then - if ! jq '."pool-reg-cert"' <<< "${offlineJSON}" > "${POOL_FOLDER}/${otx_pool_name}/${POOL_REGCERT_FILENAME}"; then println "ERROR" "${FG_RED}ERROR${NC}: failed to write pool cert to disk"; fi + if ! jq '."pool-reg-cert"' <<< "${offlineJSON}" > "${POOL_FOLDER}/${otx_pool_name}/${POOL_REGCERT_FILENAME}"; then println ERROR "${FG_RED}ERROR${NC}: failed to write pool cert to disk"; fi [[ -f "${POOL_FOLDER}/${otx_pool_name}/${POOL_DEREGCERT_FILENAME}" ]] && rm -f "${POOL_FOLDER}/${otx_pool_name}/${POOL_DEREGCERT_FILENAME}" # delete de-registration cert if available else - println "ERROR" "${FG_RED}ERROR${NC}: field 'pool-name' not found in: ${offline_tx}" + println ERROR "${FG_RED}ERROR${NC}: field 'pool-name' not found in: ${offline_tx}" fi fi echo println "Offline transaction successfully submitted and set to be included in next block!" echo - println "DEBUG" "Delete submitted offline transaction file?" + println DEBUG "Delete submitted offline transaction file?" select_opt "[y] Yes" "[n] No" case $? in 0) rm -f "${offline_tx}" ;; 1) : ;; esac ;; - *) println "ERROR" "${FG_RED}ERROR${NC}: unsupported offline tx type: ${otx_type}" && waitForInput && continue ;; + *) println ERROR "${FG_RED}ERROR${NC}: unsupported offline tx type: ${otx_type}" && waitForInput && continue ;; esac waitForInput && continue ;; ################################################################### @@ -2947,32 +2989,32 @@ function main { blocks) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> BLOCKS" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" if ! command -v sqlite3 >/dev/null; then - println "ERROR" "${FG_RED}ERROR${NC}: sqlite3 not found!" + println ERROR "${FG_RED}ERROR${NC}: sqlite3 not found!" waitForInput && continue fi current_epoch=$(getEpoch) - println "DEBUG" "Current epoch: ${FG_LBLUE}${current_epoch}${NC}\n" - println "DEBUG" "Show a block summary for all epochs or a detailed view for a specific epoch?" + println DEBUG "Current epoch: ${FG_LBLUE}${current_epoch}${NC}\n" + println DEBUG "Show a block summary for all epochs or a detailed view for a specific epoch?" select_opt "[s] Summary" "[e] Epoch" "[Esc] Cancel" case $? in - 0) echo && sleep 0.1 && read -r -p "Enter number of epochs to show (enter for 10): " epoch_enter 2>&6 && println "LOG" "Enter number of epochs to show (enter for 10): ${epoch_enter}" + 0) getAnswerAnyCust epoch_enter "Enter number of epochs to show (enter for 10)" epoch_enter=${epoch_enter:-10} if ! isNumber ${epoch_enter}; then - println "ERROR" "\n${FG_RED}ERROR${NC}: not a number" + println ERROR "\n${FG_RED}ERROR${NC}: not a number" waitForInput && continue fi view=1; view_output="${FG_YELLOW}[b] Block View${NC} | [i] Info" while true; do clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> BLOCKS" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" current_epoch=$(getEpoch) - println "DEBUG" "Current epoch: ${FG_LBLUE}${current_epoch}${NC}\n" + println DEBUG "Current epoch: ${FG_LBLUE}${current_epoch}${NC}\n" if [[ ${view} -eq 1 ]]; then [[ $(sqlite3 "${BLOCKLOG_DB}" "SELECT EXISTS(SELECT 1 FROM blocklog WHERE epoch=$((current_epoch+1)) LIMIT 1);" 2>/dev/null) -eq 1 ]] && ((current_epoch++)) first_epoch=$(( current_epoch - epoch_enter )) @@ -3003,23 +3045,23 @@ function main { done printf '|' >&3; printf "%$((5+6+ideal_len+luck_len+7+9+6+7+6+7+27+2))s" | tr " " "=" >&3; printf '|\n' >&3 else - println "OFF" "Block Status:\n" - println "OFF" "Leader - Scheduled to make block at this slot" - println "OFF" "Ideal - Expected/Ideal number of blocks assigned based on active stake (sigma)" - println "OFF" "Luck - Leader slots assigned vs Ideal slots for this epoch" - println "OFF" "Adopted - Block created successfully" - println "OFF" "Confirmed - Block created validated to be on-chain with the certainty" - println "OFF" " set in 'cncli.sh' for 'CONFIRM_BLOCK_CNT'" - println "OFF" "Missed - Scheduled at slot but no record of it in cncli DB and no" - println "OFF" " other pool has made a block for this slot" - println "OFF" "Ghosted - Block created but marked as orphaned and no other pool has made" - println "OFF" " a valid block for this slot, height battle or block propagation issue" - println "OFF" "Stolen - Another pool has a valid block registered on-chain for the same slot" - println "OFF" "Invalid - Pool failed to create block, base64 encoded error message" - println "OFF" " can be decoded with 'echo | base64 -d | jq -r'" + println OFF "Block Status:\n" + println OFF "Leader - Scheduled to make block at this slot" + println OFF "Ideal - Expected/Ideal number of blocks assigned based on active stake (sigma)" + println OFF "Luck - Leader slots assigned vs Ideal slots for this epoch" + println OFF "Adopted - Block created successfully" + println OFF "Confirmed - Block created validated to be on-chain with the certainty" + println OFF " set in 'cncli.sh' for 'CONFIRM_BLOCK_CNT'" + println OFF "Missed - Scheduled at slot but no record of it in cncli DB and no" + println OFF " other pool has made a block for this slot" + println OFF "Ghosted - Block created but marked as orphaned and no other pool has made" + println OFF " a valid block for this slot, height battle or block propagation issue" + println OFF "Stolen - Another pool has a valid block registered on-chain for the same slot" + println OFF "Invalid - Pool failed to create block, base64 encoded error message" + println OFF " can be decoded with 'echo | base64 -d | jq -r'" fi echo - println "OFF" "[h] Home | ${view_output} | [*] Refresh" + println OFF "[h] Home | ${view_output} | [*] Refresh" read -rsn1 key case ${key} in h ) continue 2 ;; @@ -3029,8 +3071,8 @@ function main { esac done ;; - 1) [[ $(sqlite3 "${BLOCKLOG_DB}" "SELECT EXISTS(SELECT 1 FROM blocklog WHERE epoch=$((current_epoch+1)) LIMIT 1);" 2>/dev/null) -eq 1 ]] && println "DEBUG" "\n${FG_YELLOW}Leader schedule for next epoch[$((current_epoch+1))] available${NC}" - echo && sleep 0.1 && read -r -p "Enter epoch to list (enter for current): " epoch_enter 2>&6 && println "LOG" "Enter epoch to list (enter for current): ${epoch_enter}" + 1) [[ $(sqlite3 "${BLOCKLOG_DB}" "SELECT EXISTS(SELECT 1 FROM blocklog WHERE epoch=$((current_epoch+1)) LIMIT 1);" 2>/dev/null) -eq 1 ]] && println DEBUG "\n${FG_YELLOW}Leader schedule for next epoch[$((current_epoch+1))] available${NC}" + echo && getAnswerAnyCust epoch_enter "Enter epoch to list (enter for current)" [[ -z "${epoch_enter}" ]] && epoch_enter=${current_epoch} if [[ $(sqlite3 "${BLOCKLOG_DB}" "SELECT EXISTS(SELECT 1 FROM blocklog WHERE epoch=${epoch_enter} LIMIT 1);" 2>/dev/null) -eq 0 ]]; then println "No blocks in epoch ${epoch_enter}" @@ -3039,12 +3081,12 @@ function main { view=1; view_output="${FG_YELLOW}[1] View 1${NC} | [2] View 2 | [3] View 3 | [i] Info" while true; do clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> BLOCKS" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" current_epoch=$(getEpoch) - println "DEBUG" "Current epoch : ${FG_LBLUE}${current_epoch}${NC}" - println "DEBUG" "Selected epoch : ${FG_LBLUE}${epoch_enter}${NC}\n" + println DEBUG "Current epoch : ${FG_LBLUE}${current_epoch}${NC}" + println DEBUG "Selected epoch : ${FG_LBLUE}${epoch_enter}${NC}\n" invalid_cnt=$(sqlite3 "${BLOCKLOG_DB}" "SELECT COUNT(*) FROM blocklog WHERE epoch=${epoch_enter} AND status='invalid';" 2>/dev/null) missed_cnt=$(sqlite3 "${BLOCKLOG_DB}" "SELECT COUNT(*) FROM blocklog WHERE epoch=${epoch_enter} AND status='missed';" 2>/dev/null) ghosted_cnt=$(sqlite3 "${BLOCKLOG_DB}" "SELECT COUNT(*) FROM blocklog WHERE epoch=${epoch_enter} AND status='ghosted';" 2>/dev/null) @@ -3117,23 +3159,23 @@ function main { done < <(sqlite3 "${BLOCKLOG_DB}" "SELECT status, block, slot, slot_in_epoch, at, size, hash FROM blocklog WHERE epoch=${epoch_enter} ORDER BY slot;" 2>/dev/null) printf '|' >&3; printf "%$((${#leader_cnt}+status_len+block_len+slot_len+slot_in_epoch_len+at_len+size_len+hash_len+23))s" | tr " " "=" >&3; printf '|\n' >&3 elif [[ ${view} -eq 4 ]]; then - println "OFF" "Block Status:\n" - println "OFF" "Leader - Scheduled to make block at this slot" - println "OFF" "Ideal - Expected/Ideal number of blocks assigned based on active stake (sigma)" - println "OFF" "Luck - Leader slots assigned vs Ideal slots for this epoch" - println "OFF" "Adopted - Block created successfully" - println "OFF" "Confirmed - Block created validated to be on-chain with the certainty" - println "OFF" " set in 'cncli.sh' for 'CONFIRM_BLOCK_CNT'" - println "OFF" "Missed - Scheduled at slot but no record of it in cncli DB and no" - println "OFF" " other pool has made a block for this slot" - println "OFF" "Ghosted - Block created but marked as orphaned and no other pool has made" - println "OFF" " a valid block for this slot, height battle or block propagation issue" - println "OFF" "Stolen - Another pool has a valid block registered on-chain for the same slot" - println "OFF" "Invalid - Pool failed to create block, base64 encoded error message" - println "OFF" " can be decoded with 'echo | base64 -d | jq -r'" + println OFF "Block Status:\n" + println OFF "Leader - Scheduled to make block at this slot" + println OFF "Ideal - Expected/Ideal number of blocks assigned based on active stake (sigma)" + println OFF "Luck - Leader slots assigned vs Ideal slots for this epoch" + println OFF "Adopted - Block created successfully" + println OFF "Confirmed - Block created validated to be on-chain with the certainty" + println OFF " set in 'cncli.sh' for 'CONFIRM_BLOCK_CNT'" + println OFF "Missed - Scheduled at slot but no record of it in cncli DB and no" + println OFF " other pool has made a block for this slot" + println OFF "Ghosted - Block created but marked as orphaned and no other pool has made" + println OFF " a valid block for this slot, height battle or block propagation issue" + println OFF "Stolen - Another pool has a valid block registered on-chain for the same slot" + println OFF "Invalid - Pool failed to create block, base64 encoded error message" + println OFF " can be decoded with 'echo | base64 -d | jq -r'" fi echo - println "OFF" "[h] Home | ${view_output} | [*] Refresh" + println OFF "[h] Home | ${view_output} | [*] Refresh" read -rsn1 key case ${key} in h ) continue 2 ;; @@ -3151,31 +3193,29 @@ function main { ;; ################################################################### backup) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> BACKUP & RESTORE" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" echo - println "DEBUG" "Create or restore a backup of CNTools wallets & pools" + println DEBUG "Create or restore a backup of CNTools wallets & pools" echo - println "DEBUG" "Backup or Restore?" + println DEBUG "Backup or Restore?" select_opt "[b] Backup" "[r] Restore" "[Esc] Cancel" case $? in 0) echo - [[ ${ENABLE_DIALOG} = "true" ]] && println "DEBUG" "Enter backup destination directory (created if non existent)" && waitForInput "Press any key to open the file explorer" - dirDialog "Enter backup destination directory (created if non existent)" + dirDialog "Enter backup destination directory (created if non existent)" && echo [[ "${dir}" != */ ]] && backup_path="${dir}/" || backup_path="${dir}" - println "DEBUG" "${FG_GREEN}${backup_path}${NC}\n" if [[ ! "${backup_path}" =~ ^/[-0-9A-Za-z_]+ ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: invalid path, please specify the full path to backup directory (space not allowed)" + println ERROR "${FG_RED}ERROR${NC}: invalid path, please specify the full path to backup directory (space not allowed)" waitForInput && continue fi - if ! mkdir -p "${backup_path}"; then println "ERROR" "${FG_RED}ERROR${NC}: failed to create backup directory:\n${backup_path}" && waitForInput && continue; fi + if ! mkdir -p "${backup_path}"; then println ERROR "${FG_RED}ERROR${NC}: failed to create backup directory:\n${backup_path}" && waitForInput && continue; fi missing_keys="false" excluded_files=() [[ -d "${ASSET_FOLDER}" ]] && asset_out=" and asset ${ASSET_POLICY_SK_FILENAME}" || asset_out="" - println "DEBUG" "Include private keys in backup?" - println "DEBUG" "- No > create a backup excluding wallets ${WALLET_PAY_SK_FILENAME}/${WALLET_STAKE_SK_FILENAME}, pools ${POOL_COLDKEY_SK_FILENAME}${asset_out}" - println "DEBUG" "- Yes > create a backup including all available files" + println DEBUG "Include private keys in backup?" + println DEBUG "- No > create a backup excluding wallets ${WALLET_PAY_SK_FILENAME}/${WALLET_STAKE_SK_FILENAME}, pools ${POOL_COLDKEY_SK_FILENAME}${asset_out}" + println DEBUG "- Yes > create a backup including all available files" select_opt "[n] No" "[y] Yes" case $? in 0) excluded_files=( @@ -3200,29 +3240,29 @@ function main { ) backup_list=() backup_cnt=0 - println "DEBUG" "Backup job include:\n" + println DEBUG "Backup job include:\n" for item in "${backup_source[@]}"; do [[ ! -d "${item}" ]] && continue - println "DEBUG" "$(basename "${item}")" + println DEBUG "$(basename "${item}")" while IFS= read -r -d '' dir; do backup_list+=( "${dir}" ) - println "DEBUG" " ${FG_LGRAY}$(basename "${dir}")${NC}" + println DEBUG " ${FG_LGRAY}$(basename "${dir}")${NC}" ((backup_cnt++)) done < <(find "${item}" -mindepth 1 -maxdepth 1 -type d -print0 2>/dev/null | sort -z) done [[ ${backup_cnt} -eq 0 ]] && println "\nNo folders found to include in backup :(" && waitForInput && continue echo - println "ACTION" "tar cf ${backup_file} ${backup_list[*]}" - if ! output=$(tar cf "${backup_file}" "${backup_list[@]}" 2>&1); then println "ERROR" "${FG_RED}ERROR${NC}: during tarball creation:\n${output}" && waitForInput && continue; fi + println ACTION "tar cf ${backup_file} ${backup_list[*]}" + if ! output=$(tar cf "${backup_file}" "${backup_list[@]}" 2>&1); then println ERROR "${FG_RED}ERROR${NC}: during tarball creation:\n${output}" && waitForInput && continue; fi if [[ ${#excluded_files[@]} -gt 0 ]]; then - println "ACTION" "tar --wildcards --file=\"${backup_file}\" ${excluded_files[*]}" + println ACTION "tar --wildcards --file=\"${backup_file}\" ${excluded_files[*]}" tar --wildcards --file="${backup_file}" ${excluded_files[*]} &>/dev/null # ignore any error, tar will write error if some of the keys to delete are not found - println "ACTION" "gzip ${backup_file}" - if ! output=$(gzip "${backup_file}" 2>&1); then println "ERROR" "${FG_RED}ERROR${NC}: gzip error:\n${output}" && waitForInput && continue; fi + println ACTION "gzip ${backup_file}" + if ! output=$(gzip "${backup_file}" 2>&1); then println ERROR "${FG_RED}ERROR${NC}: gzip error:\n${output}" && waitForInput && continue; fi backup_file+=".gz" else - println "ACTION" "gzip ${backup_file}" - if ! output=$(gzip "${backup_file}" 2>&1); then println "ERROR" "${FG_RED}ERROR${NC}: gzip error:\n${output}" && waitForInput && continue; fi + println ACTION "gzip ${backup_file}" + if ! output=$(gzip "${backup_file}" 2>&1); then println ERROR "${FG_RED}ERROR${NC}: gzip error:\n${output}" && waitForInput && continue; fi backup_file+=".gz" while IFS= read -r -d '' wallet; do # check for missing signing keys wallet_name=$(basename ${wallet}) @@ -3238,42 +3278,40 @@ function main { done < <(find "${POOL_FOLDER}" -mindepth 1 -maxdepth 1 -type d -print0 2>/dev/null | sort -z) [[ ${missing_keys} = "true" ]] && echo fi - println "DEBUG" "Encrypt backup?" + println DEBUG "Encrypt backup?" select_opt "[y] Yes" "[n] No" case $? in 0) echo - if getPassword confirm; then # $password variable populated by getPassword function + if getPasswordCust confirm; then # $password variable populated by getPasswordCust function encryptFile "${backup_file}" "${password}" backup_file="${backup_file}.gpg" unset password else - println "ERROR" "\n${FG_RED}ERROR${NC}: password input aborted!" + println ERROR "\n${FG_RED}ERROR${NC}: password input aborted!" fi ;; 1) : ;; # do nothing esac echo if [[ ${missing_keys} = "true" ]]; then - println "DEBUG" "${FG_YELLOW}There are wallets and/or pools with missing keys.\nIf removed in a previous backup, make sure to keep that master backup safe!${NC}" + println DEBUG "${FG_YELLOW}There are wallets and/or pools with missing keys.\nIf removed in a previous backup, make sure to keep that master backup safe!${NC}" println "\nIncremental backup file ${backup_file} successfully created" else println "Backup file ${FG_LGRAY}${backup_file}${NC} successfully created" fi ;; - 1) println "DEBUG" "\n${FG_BLUE}INFO${NC}: a backup of existing wallet and pool folders will be made before restore is executed\n" - [[ ${ENABLE_DIALOG} = "true" ]] && println "DEBUG" "Enter backup file to restore" && waitForInput "Press any key to open the file explorer" - fileDialog "Enter backup file to restore" + 1) println DEBUG "\n${FG_BLUE}INFO${NC}: a backup of existing wallet and pool folders will be made before restore is executed\n" + fileDialog "Enter backup file to restore" && echo backup_file=${file} if [[ ! -f "${backup_file}" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: file not found: ${backup_file}" + println ERROR "${FG_RED}ERROR${NC}: file not found: ${backup_file}" waitForInput && continue fi - println "DEBUG" "${FG_GREEN}${backup_file}${NC}\n" - if ! restore_path="$(mktemp -d "${TMP_DIR}/restore_XXXXXXXXXX")"; then println "ERROR" "${FG_RED}ERROR${NC}: failed to create restore directory:\n${restore_path}" && waitForInput && continue; fi + if ! restore_path="$(mktemp -d "${TMP_DIR}/restore_XXXXXXXXXX")"; then println ERROR "${FG_RED}ERROR${NC}: failed to create restore directory:\n${restore_path}" && waitForInput && continue; fi tmp_bkp_file="" if [ "${backup_file##*.}" = "gpg" ]; then - println "DEBUG" "Backup GPG encrypted, enter password to decrypt" - if getPassword; then # $password variable populated by getPassword function + println DEBUG "Backup GPG encrypted, enter password to decrypt" + if getPasswordCust; then # $password variable populated by getPasswordCust function tmp_bkp_file=$(mktemp "${TMP_DIR}/bkp_file_XXXXXXXXXX.tar.gz.gpg") cp -f "${backup_file}" "${tmp_bkp_file}" decryptFile "${backup_file}" "${password}" @@ -3281,12 +3319,12 @@ function main { unset password echo else - println "ERROR" "\n${FG_RED}ERROR${NC}: password input aborted!" + println ERROR "\n${FG_RED}ERROR${NC}: password input aborted!" waitForInput && continue fi fi - println "ACTION" "tar xfzk ${backup_file} -C ${restore_path}" - if ! output=$(tar xfzk "${backup_file}" -C "${restore_path}" 2>&1); then println "ERROR" "${FG_RED}ERROR${NC}: during tarball extraction:\n${output}" && waitForInput && continue; fi + println ACTION "tar xfzk ${backup_file} -C ${restore_path}" + if ! output=$(tar xfzk "${backup_file}" -C "${restore_path}" 2>&1); then println ERROR "${FG_RED}ERROR${NC}: during tarball extraction:\n${output}" && waitForInput && continue; fi [[ -n "${tmp_bkp_file}" ]] && mv -f "${tmp_bkp_file}" "${backup_file}.gpg" && rm -f "${backup_file}" # restore original encrypted backup file restore_source=( "${restore_path}${WALLET_FOLDER}" @@ -3295,19 +3333,19 @@ function main { ) restore_list=() restore_cnt=0 - println "DEBUG" "Restore job include:\n" + println DEBUG "Restore job include:\n" for item in "${restore_source[@]}"; do [[ ! -d "${item}" ]] && continue - println "DEBUG" "$(basename "${item}")" + println DEBUG "$(basename "${item}")" while IFS= read -r -d '' dir; do restore_list+=( "${dir}" ) - println "DEBUG" " ${FG_LGRAY}$(basename "${dir}")${NC}" + println DEBUG " ${FG_LGRAY}$(basename "${dir}")${NC}" ((restore_cnt++)) done < <(find "${item}" -mindepth 1 -maxdepth 1 -type d -print0 2>/dev/null | sort -z) done [[ ${restore_cnt} -eq 0 ]] && println "\nNothing in backup file to restore :(" && waitForInput && continue echo - println "DEBUG" "Continue with restore?" + println DEBUG "Continue with restore?" select_opt "[n] No" "[y] Yes" case $? in 0) continue ;; @@ -3331,19 +3369,19 @@ function main { done if [[ ${source_cnt} -gt 0 ]]; then archive_dest="${CNODE_HOME}/priv/archive" - if ! mkdir -p "${archive_dest}"; then println "ERROR" "${FG_RED}ERROR${NC}: failed to create archive directory:\n${archive_dest}" && waitForInput && continue; fi + if ! mkdir -p "${archive_dest}"; then println ERROR "${FG_RED}ERROR${NC}: failed to create archive directory:\n${archive_dest}" && waitForInput && continue; fi archive_file="${archive_dest}/archive_$(date '+%Y%m%d%H%M%S').tar.gz" - println "ACTION" "tar cfz ${archive_file} ${archive_list[*]}" - if ! output=$(tar cfz "${archive_file}" "${archive_list[@]}" 2>&1); then println "ERROR" "${FG_RED}ERROR${NC}: during archive/backup:\n${output}" && waitForInput && continue; fi - println "DEBUG" "An archive of current priv folder has been taken and stored in ${FG_LGRAY}${archive_file}${NC}" - println "DEBUG" "Please set a password to GPG encrypt the archive" - if getPassword confirm; then # $password variable populated by getPassword function + println ACTION "tar cfz ${archive_file} ${archive_list[*]}" + if ! output=$(tar cfz "${archive_file}" "${archive_list[@]}" 2>&1); then println ERROR "${FG_RED}ERROR${NC}: during archive/backup:\n${output}" && waitForInput && continue; fi + println DEBUG "An archive of current priv folder has been taken and stored in ${FG_LGRAY}${archive_file}${NC}" + println DEBUG "Please set a password to GPG encrypt the archive" + if getPasswordCust confirm; then # $password variable populated by getPasswordCust function encryptFile "${archive_file}" "${password}" archive_file="${archive_file}.gpg" unset password else - println "ERROR" "\n${FG_RED}ERROR${NC}: password input aborted!" - println "DEBUG" "${FG_YELLOW}archive stored unencrypted !!${NC}" + println ERROR "\n${FG_RED}ERROR${NC}: password input aborted!" + println DEBUG "${FG_YELLOW}archive stored unencrypted !!${NC}" fi echo fi @@ -3352,7 +3390,7 @@ function main { while IFS= read -r -d '' file; do # unlock files to make sure restore is successful unlockFile "${file}" done < <(find "${dest_path}" -mindepth 1 -maxdepth 1 -type f -print0 2>/dev/null) - println "ACTION" "cp -rf ${item} $(dirname "${dest_path}")" + println ACTION "cp -rf ${item} $(dirname "${dest_path}")" cp -rf "${item}" "$(dirname "${dest_path}")" done println "Backup ${FG_LGRAY}$(basename "${backup_file}")${NC} successfully restored!" @@ -3364,15 +3402,15 @@ function main { advanced) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> ADVANCED" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - println "OFF" " Developer & Advanced features\n"\ + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println OFF " Developer & Advanced features\n"\ " ) Metadata - create and optionally post metadata on-chain"\ " ) Multi-Asset - multi-asset nanagement"\ " ) Delete Keys - Delete all sign/cold keys from CNTools (wallet|pool|asset)"\ "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - println "DEBUG" " Select Operation\n" + println DEBUG " Select Operation\n" select_opt "[m] Metadata" "[a] Multi-Asset" "[x] Delete Private Keys" "[h] Home" case $? in 0) SUBCOMMAND="metadata" ;; @@ -3383,19 +3421,19 @@ function main { case $SUBCOMMAND in metadata) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> ADVANCED >> METADATA" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" [[ ! $(ls -A "${WALLET_FOLDER}" 2>/dev/null) ]] && echo && println "${FG_YELLOW}No wallets available to pay for transaction fee!${NC}" && waitForInput && continue if [[ ${CNTOOLS_MODE} = "OFFLINE" ]]; then - println "ERROR" "\n${FG_RED}ERROR${NC}: CNTools started in offline mode, option not available!" + println ERROR "\n${FG_RED}ERROR${NC}: CNTools started in offline mode, option not available!" waitForInput && continue else if ! selectOpMode; then continue; fi fi echo - println "DEBUG" "Select the type of metadata to post on-chain" - println "DEBUG" "ref: https://github.com/input-output-hk/cardano-node/blob/master/doc/reference/tx-metadata.md" + println DEBUG "Select the type of metadata to post on-chain" + println DEBUG "ref: https://github.com/input-output-hk/cardano-node/blob/master/doc/reference/tx-metadata.md" select_opt "[n] No JSON Schema (default)" "[d] Detailed JSON Schema" "[c] Raw CBOR" case $? in 0) metatype="no-schema" ;; @@ -3403,33 +3441,29 @@ function main { 2) metatype="cbor" ;; esac if [[ ${metatype} = "cbor" ]]; then - fileDialog "Enter path to raw CBOR metadata file" + fileDialog "Enter path to raw CBOR metadata file" && echo metafile="${file}" - println "DEBUG" "${FG_LGRAY}${metafile}${NC}\n" else metafile="${TMP_DIR}/metadata_$(date '+%Y%m%d%H%M%S').json" - println "DEBUG" "\nDo you want to select a metadata file, enter URL to metadata file, or enter/paste metadata content?" + println DEBUG "\nDo you want to select a metadata file, enter URL to metadata file, or enter/paste metadata content?" select_opt "[f] File" "[u] URL" "[e] Enter" case $? in - 0) tput sc - fileDialog "Enter path to JSON metadata file" + 0) fileDialog "Enter path to JSON metadata file" && echo metafile="${file}" if [[ ! -f "${metafile}" ]] || ! jq -er . "${metafile}" &>/dev/null; then - println "ERROR" "${FG_RED}ERROR${NC}: invalid JSON format or file not found" - println "ERROR" "${FG_LGRAY}${metafile}${NC}" + println ERROR "${FG_RED}ERROR${NC}: invalid JSON format or file not found" waitForInput && continue fi - tput rc && tput ed - println "DEBUG" "${FG_LGRAY}${metafile}${NC}:\n$(cat "${metafile}")\n" + println DEBUG "$(cat "${metafile}")\n" ;; 1) tput sc && echo - sleep 0.1 && read -r -p "Enter URL to JSON metadata file: " meta_json_url 2>&6 && println "LOG" "Enter URL to JSON metadata file: ${meta_json_url}" + getAnswerAnyCust meta_json_url "Enter URL to JSON metadata file" if [[ ! "${meta_json_url}" =~ https?://.* ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: invalid URL format" + println ERROR "${FG_RED}ERROR${NC}: invalid URL format" waitForInput && continue fi if ! curl -sL -m ${CURL_TIMEOUT} -o "${metafile}" ${meta_json_url} || ! jq -er . "${metafile}" &>/dev/null; then - println "ERROR" "${FG_RED}ERROR${NC}: metadata download failed, please make sure the URL point to a valid JSON file!" + println ERROR "${FG_RED}ERROR${NC}: metadata download failed, please make sure the URL point to a valid JSON file!" waitForInput && continue fi tput rc && tput ed @@ -3438,20 +3472,20 @@ function main { 2) println "Add an example metadata JSON scaffold?" select_opt "[y] Yes" "[n] No" case $? in - 0) jq <<< '{"1815":{"name":"Ada Lovelace","age":36,"parents":[{"id":0,"name":"George Gordon Byron"},{"id":1,"name":"Anne Isabella Byron"}]}}' > "${metafile}" ;; + 0) jq . <<< '{"1815":{"name":"Ada Lovelace","age":36,"parents":[{"id":0,"name":"George Gordon Byron"},{"id":1,"name":"Anne Isabella Byron"}]}}' > "${metafile}" ;; 1) : ;; # do nothing esac tput sc DEFAULTEDITOR="$(command -v nano &>/dev/null && echo 'nano' || echo 'vi')" - println "OFF" "\nPaste or enter the metadata text, opening text editor ${FG_LGRAY}${DEFAULTEDITOR}${NC}" - println "OFF" "${FG_YELLOW}Please don't change default file path when saving${NC}" + println OFF "\nPaste or enter the metadata text, opening text editor ${FG_LGRAY}${DEFAULTEDITOR}${NC}" + println OFF "${FG_YELLOW}Please don't change default file path when saving${NC}" exec >&6 2>&7 # normal stdout/stderr waitForInput "press any key to open ${DEFAULTEDITOR}" ${DEFAULTEDITOR} "${metafile}" exec >&8 2>&9 # custom stdout/stderr if [[ ! -f "${metafile}" ]] || ! jq -er . "${metafile}" &>/dev/null; then - println "ERROR" "${FG_RED}ERROR${NC}: file not found or invalid JSON format" - println "ERROR" "File: ${FG_LGRAY}${metafile}${NC}" + println ERROR "${FG_RED}ERROR${NC}: file not found or invalid JSON format" + println ERROR "File: ${FG_LGRAY}${metafile}${NC}" waitForInput && continue fi tput rc && tput ed @@ -3459,22 +3493,22 @@ function main { ;; esac fi - println "DEBUG" "\nContinue to post metadata on-chain or stop at this point?" + println DEBUG "\nContinue to post metadata on-chain or stop at this point?" select_opt "[c] Continue" "[s] Stop" case $? in 0) : ;; # do nothing 1) continue ;; esac - println "DEBUG" "\n# Select wallet to pay for metadata transaction fee" + println DEBUG "\n# Select wallet to pay for metadata transaction fee" if [[ ${op_mode} = "online" ]]; then if ! selectWallet "balance" "${WALLET_PAY_SK_FILENAME}"; then # ${wallet_name} populated by selectWallet function [[ "${dir_name}" != "[Esc] Cancel" ]] && waitForInput; continue fi getWalletType ${wallet_name} case $? in - 0) println "ERROR" "${FG_RED}ERROR${NC}: please use a CLI wallet to pay for metadata transaction fee!" && waitForInput && continue ;; - 2) println "ERROR" "${FG_RED}ERROR${NC}: signing keys encrypted, please decrypt before use!" && waitForInput && continue ;; - 3) println "ERROR" "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet!" && waitForInput && continue ;; + 0) println ERROR "${FG_RED}ERROR${NC}: please use a CLI wallet to pay for metadata transaction fee!" && waitForInput && continue ;; + 2) println ERROR "${FG_RED}ERROR${NC}: signing keys encrypted, please decrypt before use!" && waitForInput && continue ;; + 3) println ERROR "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet!" && waitForInput && continue ;; esac else if ! selectWallet "balance"; then # ${wallet_name} populated by selectWallet function @@ -3482,7 +3516,7 @@ function main { fi getWalletType ${wallet_name} case $? in - 0) println "ERROR" "${FG_RED}ERROR${NC}: please use a CLI wallet to pay for metadata transaction fee!" && waitForInput && continue ;; + 0) println ERROR "${FG_RED}ERROR${NC}: please use a CLI wallet to pay for metadata transaction fee!" && waitForInput && continue ;; esac fi echo @@ -3494,10 +3528,10 @@ function main { pay_lovelace=${assets[lovelace]} if [[ ${pay_lovelace} -gt 0 && ${base_lovelace} -gt 0 ]]; then # Both payment and base address available with funds, let user choose what to use - println "DEBUG" "Select source wallet address" + println DEBUG "Select source wallet address" if [[ -n ${wallet_count} && ${wallet_count} -gt ${WALLET_SELECTION_FILTER_LIMIT} ]]; then - println "DEBUG" "$(printf "%s\t\t${FG_LBLUE}%s${NC} Ada" "Funds :" "$(formatLovelace ${base_lovelace})")" - println "DEBUG" "$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Enterprise Funds :" "$(formatLovelace ${pay_lovelace})")" + println DEBUG "$(printf "%s\t\t${FG_LBLUE}%s${NC} Ada" "Funds :" "$(formatLovelace ${base_lovelace})")" + println DEBUG "$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Enterprise Funds :" "$(formatLovelace ${pay_lovelace})")" fi echo select_opt "[b] Base (default)" "[e] Enterprise" "[Esc] Cancel" @@ -3509,15 +3543,15 @@ function main { elif [[ ${pay_lovelace} -gt 0 ]]; then addr="${pay_addr}" if [[ -n ${wallet_count} && ${wallet_count} -gt ${WALLET_SELECTION_FILTER_LIMIT} ]]; then - println "DEBUG" "$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Enterprise Funds :" "$(formatLovelace ${pay_lovelace})")" + println DEBUG "$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Enterprise Funds :" "$(formatLovelace ${pay_lovelace})")" fi elif [[ ${base_lovelace} -gt 0 ]]; then addr="${base_addr}" if [[ -n ${wallet_count} && ${wallet_count} -gt ${WALLET_SELECTION_FILTER_LIMIT} ]]; then - println "DEBUG" "$(printf "%s\t\t${FG_LBLUE}%s${NC} Ada" "Funds :" "$(formatLovelace ${base_lovelace})")" + println DEBUG "$(printf "%s\t\t${FG_LBLUE}%s${NC} Ada" "Funds :" "$(formatLovelace ${base_lovelace})")" fi else - println "ERROR" "${FG_RED}ERROR${NC}: no funds available for wallet ${FG_GREEN}${wallet_name}${NC}" + println ERROR "${FG_RED}ERROR${NC}: no funds available for wallet ${FG_GREEN}${wallet_name}${NC}" waitForInput && continue fi if ! sendMetadata; then @@ -3531,19 +3565,20 @@ function main { ;; ################################################################### multi-asset) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> ADVANCED >> MULTI-ASSET" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - println "OFF" " Multi-Asset Token Management\n"\ + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println OFF " Multi-Asset Token Management\n"\ " ) Create Policy - create a new asset policy"\ " ) List Assets - list created/minted policies/assets"\ " ) Decrypt Policy - remove write protection and decrypt policy"\ " ) Encrypt Policy - encrypt policy sign key and make all files immutable"\ " ) Mint Asset - mint new assets for selected policy"\ " ) Burn Asset - burn a given amount of assets in selected wallet"\ + " ) Register Asset - create/update JSON submission file for Cardano Token Registry"\ "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - println "DEBUG" " Select Multi-Asset Operation\n" - select_opt "[c] Create Policy" "[l] List Assets" "[d] Decrypt / Unlock Policy" "[e] Encrypt / Lock Policy" "[m] Mint Asset" "[b] Burn Asset" "[h] Home" + println DEBUG " Select Multi-Asset Operation\n" + select_opt "[c] Create Policy" "[l] List Assets" "[d] Decrypt / Unlock Policy" "[e] Encrypt / Lock Policy" "[m] Mint Asset" "[b] Burn Asset" "[r] Register Asset" "[h] Home" case $? in 0) SUBCOMMAND="create-policy" ;; 1) SUBCOMMAND="list-assets" ;; @@ -3551,26 +3586,27 @@ function main { 3) SUBCOMMAND="encrypt-policy" ;; 4) SUBCOMMAND="mint-asset" ;; 5) SUBCOMMAND="burn-asset" ;; - 6) continue ;; + 6) SUBCOMMAND="register-asset" ;; + 7) continue ;; esac case $SUBCOMMAND in create-policy) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> ADVANCED >> MULTI-ASSET >> CREATE POLICY" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" echo - sleep 0.1 && read -r -p "Internal name to give the generated policy: " policy_name 2>&6 && println "LOG" "Internal name to give the generated policy: ${policy_name}" + getAnswerAnyCust policy_name "Internal name to give the generated policy" # Remove unwanted characters from policy name policy_name=${policy_name//[^[:alnum:]]/_} if [[ -z "${policy_name}" ]]; then - println "ERROR" "${FG_RED}ERROR${NC}: Empty policy name, please retry!" + println ERROR "${FG_RED}ERROR${NC}: Empty policy name, please retry!" waitForInput && continue fi policy_folder="${ASSET_FOLDER}/${policy_name}" echo if ! mkdir -p "${policy_folder}"; then - println "ERROR" "${FG_RED}ERROR${NC}: Failed to create directory for policy:\n${policy_folder}" + println ERROR "${FG_RED}ERROR${NC}: Failed to create directory for policy:\n${policy_folder}" waitForInput && continue fi # Policy filenames @@ -3583,20 +3619,20 @@ function main { println " Choose another name or delete the existing one" waitForInput && continue fi - println "ACTION" "${CCLI} address key-gen --verification-key-file ${policy_vk_file} --signing-key-file ${policy_sk_file}" + println ACTION "${CCLI} address key-gen --verification-key-file ${policy_vk_file} --signing-key-file ${policy_sk_file}" if ! ${CCLI} address key-gen --verification-key-file "${policy_vk_file}" --signing-key-file "${policy_sk_file}"; then - println "ERROR" "${FG_RED}ERROR${NC}: failure during policy key creation!"; safeDel "${policy_folder}"; waitForInput && continue + println ERROR "${FG_RED}ERROR${NC}: failure during policy key creation!"; safeDel "${policy_folder}"; waitForInput && continue fi - println "ACTION" "${CCLI} address key-hash --payment-verification-key-file ${policy_vk_file}" + println ACTION "${CCLI} address key-hash --payment-verification-key-file ${policy_vk_file}" if ! policy_key_hash=$(${CCLI} address key-hash --payment-verification-key-file "${policy_vk_file}"); then - println "ERROR" "${FG_RED}ERROR${NC}: failure during policy verification key hashing!"; safeDel "${policy_folder}"; waitForInput && continue + println ERROR "${FG_RED}ERROR${NC}: failure during policy verification key hashing!"; safeDel "${policy_folder}"; waitForInput && continue fi - println "DEBUG" "How long do you want the policy to be valid? (0/blank=unlimited)" - println "DEBUG" "${FG_YELLOW}Setting a limit will prevent you from minting/burning assets after the policy expire !!\nLeave blank/unlimited if unsure and just press enter${NC}" - sleep 0.1 && read -r -p "TTL (in seconds): " ttl_enter 2>&6 && println "LOG" "TTL (in seconds): ${ttl_enter}" + println DEBUG "How long do you want the policy to be valid? (0/blank=unlimited)" + println DEBUG "${FG_YELLOW}Setting a limit will prevent you from minting/burning assets after the policy expire !!\nLeave blank/unlimited if unsure and just press enter${NC}" + getAnswerAnyCust ttl_enter "TTL (in seconds)" ttl_enter=${ttl_enter:-0} if ! isNumber ${ttl_enter}; then - println "ERROR" "\n${FG_RED}ERROR${NC}: invalid TTL number, non digit characters found: ${ttl_enter}" + println ERROR "\n${FG_RED}ERROR${NC}: invalid TTL number, non digit characters found: ${ttl_enter}" safeDel "${policy_folder}"; waitForInput && continue fi if [[ ${ttl_enter} -eq 0 ]]; then @@ -3605,9 +3641,9 @@ function main { ttl=$(( $(getSlotTipRef) + (ttl_enter/SLOT_LENGTH) )) echo "{ \"type\": \"all\", \"scripts\": [ { \"slot\": ${ttl}, \"type\": \"before\" }, { \"keyHash\": \"${policy_key_hash}\", \"type\": \"sig\" } ] }" > "${policy_script_file}" fi - println "ACTION" "${CCLI} transaction policyid --script-file ${policy_script_file}" + println ACTION "${CCLI} transaction policyid --script-file ${policy_script_file}" if ! policy_id=$(${CCLI} transaction policyid --script-file "${policy_script_file}"); then - println "ERROR" "${FG_RED}ERROR${NC}: failure during policy ID generation!"; safeDel "${policy_folder}"; waitForInput && continue + println ERROR "${FG_RED}ERROR${NC}: failure during policy ID generation!"; safeDel "${policy_folder}"; waitForInput && continue fi echo "${policy_id}" > "${policy_id_file}" chmod 600 "${policy_folder}/"* @@ -3615,14 +3651,14 @@ function main { println "Policy Name : ${FG_GREEN}${policy_name}${NC}" println "Policy ID : ${FG_LGRAY}${policy_id}${NC}" println "Policy Expire : $([[ ${ttl_enter} -eq 0 ]] && echo "${FG_LGRAY}unlimited${NC}" || echo "${FG_LGRAY}$(getDateFromSlot ${ttl} '%(%F %T %Z)T')${NC}, ${FG_LGRAY}$(timeLeft $((ttl-$(getSlotTipRef))))${NC} remaining")" - println "DEBUG" "\nYou can now start minting your custom assets using this Policy!" + println DEBUG "\nYou can now start minting your custom assets using this Policy!" waitForInput && continue ;; ################################################################### list-assets) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> ADVANCED >> MULTI-ASSET >> LIST ASSETS" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" [[ ! $(ls -A "${ASSET_FOLDER}" 2>/dev/null) ]] && echo && println "${FG_YELLOW}No policies or assets found!${NC}" && waitForInput && continue while IFS= read -r -d '' policy; do echo @@ -3652,32 +3688,32 @@ function main { ;; ################################################################### decrypt-policy) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> ADVANCED >> MULTI-ASSET >> DECRYPT / UNLOCK POLICY" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" echo [[ ! $(ls -A "${ASSET_FOLDER}" 2>/dev/null) ]] && println "${FG_YELLOW}No policies available!${NC}" && waitForInput && continue - println "DEBUG" "# Select policy to decrypt" + println DEBUG "# Select policy to decrypt" if ! selectPolicy "encrypted"; then # ${policy_name} populated by selectPolicy function waitForInput && continue fi filesUnlocked=0 keysDecrypted=0 echo - println "DEBUG" "# Removing write protection from all policy files" + println DEBUG "# Removing write protection from all policy files" while IFS= read -r -d '' file; do if [[ ${ENABLE_CHATTR} = true && $(lsattr -R "$file") =~ -i- ]]; then sudo chattr -i "${file}" fi chmod 600 "${file}" filesUnlocked=$((++filesUnlocked)) - println "DEBUG" "${file}" + println DEBUG "${file}" done < <(find "${ASSET_FOLDER}/${policy_name}" -mindepth 1 -maxdepth 1 -type f -print0) if [[ $(find "${ASSET_FOLDER}/${policy_name}" -mindepth 1 -maxdepth 1 -type f -name '*.gpg' -print0 | wc -c) -gt 0 ]]; then echo println "# Decrypting GPG encrypted policy key" - if ! getPassword; then # $password variable populated by getPassword function - println "\n\n" && println "ERROR" "${FG_RED}ERROR${NC}: password input aborted!" + if ! getPasswordCust; then # $password variable populated by getPasswordCust function + println "\n\n" && println ERROR "${FG_RED}ERROR${NC}: password input aborted!" waitForInput && continue fi while IFS= read -r -d '' file; do @@ -3693,19 +3729,19 @@ function main { println "Files decrypted : ${FG_LBLUE}${keysDecrypted}${NC}" if [[ ${filesUnlocked} -ne 0 || ${keysDecrypted} -ne 0 ]]; then echo - println "DEBUG" "${FG_YELLOW}Policy files are now unprotected${NC}" - println "DEBUG" "Use 'ADVANCED >> MULTI-ASSET >> ENCRYPT / LOCK POLICY' to re-lock" + println DEBUG "${FG_YELLOW}Policy files are now unprotected${NC}" + println DEBUG "Use 'ADVANCED >> MULTI-ASSET >> ENCRYPT / LOCK POLICY' to re-lock" fi waitForInput && continue ;; ################################################################### encrypt-policy) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> ADVANCED >> MULTI-ASSET >> ENCRYPT / LOCK POLICY" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" echo [[ ! $(ls -A "${ASSET_FOLDER}" 2>/dev/null) ]] && println "${FG_YELLOW}No policies available!${NC}" && waitForInput && continue - println "DEBUG" "# Select policy to encrypt" + println DEBUG "# Select policy to encrypt" if ! selectPolicy "encrypted"; then # ${policy_name} populated by selectPolicy function waitForInput && continue fi @@ -3713,9 +3749,9 @@ function main { keysEncrypted=0 if [[ $(find "${ASSET_FOLDER}/${policy_name}" -mindepth 1 -maxdepth 1 -type f -name '*.gpg' -print0 | wc -c) -le 0 ]]; then echo - println "DEBUG" "# Encrypting policy signing key with GPG" - if ! getPassword confirm; then # $password variable populated by getPassword function - println "\n\n" && println "ERROR" "${FG_RED}ERROR${NC}: password input aborted!" + println DEBUG "# Encrypting policy signing key with GPG" + if ! getPasswordCust confirm; then # $password variable populated by getPasswordCust function + println "\n\n" && println ERROR "${FG_RED}ERROR${NC}: password input aborted!" waitForInput && continue fi keyFiles=( @@ -3731,18 +3767,18 @@ function main { unset password else echo - println "DEBUG" "${FG_YELLOW}NOTE${NC}: found GPG encrypted files in folder, please decrypt/unlock policy files before encrypting" + println DEBUG "${FG_YELLOW}NOTE${NC}: found GPG encrypted files in folder, please decrypt/unlock policy files before encrypting" waitForInput && continue fi echo - println "DEBUG" "# Write protecting all policy files with 400 permission and if enabled 'chattr +i'" + println DEBUG "# Write protecting all policy files with 400 permission and if enabled 'chattr +i'" while IFS= read -r -d '' file; do chmod 400 "$file" if [[ ${ENABLE_CHATTR} = true && ! $(lsattr -R "$file") =~ -i- ]]; then sudo chattr +i "$file" fi filesLocked=$((++filesLocked)) - println "DEBUG" "$file" + println DEBUG "$file" done < <(find "${ASSET_FOLDER}/${policy_name}" -mindepth 1 -maxdepth 1 -type f -print0) echo println "Policy encrypted : ${FG_GREEN}${policy_name}${NC}" @@ -3750,19 +3786,19 @@ function main { println "Files encrypted : ${FG_LBLUE}${keysEncrypted}${NC}" if [[ ${filesLocked} -ne 0 || ${keysEncrypted} -ne 0 ]]; then echo - println "DEBUG" "${FG_BLUE}INFO${NC}: policy files are now protected" - println "DEBUG" "Use 'ADVANCED >> MULTI-ASSET >> DECRYPT / UNLOCK POLICY' to unlock" + println DEBUG "${FG_BLUE}INFO${NC}: policy files are now protected" + println DEBUG "Use 'ADVANCED >> MULTI-ASSET >> DECRYPT / UNLOCK POLICY' to unlock" fi waitForInput && continue ;; ################################################################### mint-asset) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> ADVANCED >> MULTI-ASSET >> MINT ASSET" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" echo [[ ! $(ls -A "${ASSET_FOLDER}" 2>/dev/null) ]] && echo && println "${FG_YELLOW}No policies found!${NC}\n\nPlease first create a policy to mint asset with" && waitForInput && continue - println "DEBUG" "# Select the policy to use when minting the asset" + println DEBUG "# Select the policy to use when minting the asset" if ! selectPolicy "all" "${ASSET_POLICY_SK_FILENAME}" "${ASSET_POLICY_VK_FILENAME}" "${ASSET_POLICY_SCRIPT_FILENAME}" "${ASSET_POLICY_ID_FILENAME}"; then # ${policy_name} populated by selectPolicy function waitForInput && continue fi @@ -3774,10 +3810,10 @@ function main { policy_id_file="${policy_folder}/${ASSET_POLICY_ID_FILENAME}" policy_id="$(cat "${policy_id_file}")" policy_ttl=$(jq -r '.scripts[0].slot //0' "${policy_script_file}") - [[ ${policy_ttl} -gt 0 && ${policy_ttl} -lt $(getSlotTipRef) ]] && println "ERROR" "${FG_RED}ERROR${NC}: Policy expired!" && waitForInput && continue + [[ ${policy_ttl} -gt 0 && ${policy_ttl} -lt $(getSlotTipRef) ]] && println ERROR "${FG_RED}ERROR${NC}: Policy expired!" && waitForInput && continue echo if [[ $(find "${policy_folder}" -type f -name '*.asset' -print0 | wc -c) -gt 0 ]]; then - println "DEBUG" "# Assets minted for this Policy\n" + println DEBUG "# Assets minted for this Policy\n" asset_name_maxlen=5; asset_amount_maxlen=12 while IFS= read -r -d '' asset; do asset_filename=$(basename ${asset}) @@ -3786,51 +3822,49 @@ function main { asset_minted=$(jq -r '.minted //0' "${asset}") [[ ${#asset_minted} -gt ${asset_amount_maxlen} ]] && asset_amount_maxlen=${#asset_minted} done < <(find "${policy_folder}" -mindepth 1 -maxdepth 1 -type f -name '*.asset' -print0 | sort -z) - println "DEBUG" "$(printf "%${asset_amount_maxlen}s | %s\n" "Total Amount" "Policy ID[.AssetName]")" - println "DEBUG" "$(printf "%$((asset_amount_maxlen+1))s+%$((asset_name_maxlen+58))s\n" "" "" | tr " " "-")" + println DEBUG "$(printf "%${asset_amount_maxlen}s | %s\n" "Total Amount" "Policy ID[.AssetName]")" + println DEBUG "$(printf "%$((asset_amount_maxlen+1))s+%$((asset_name_maxlen+58))s\n" "" "" | tr " " "-")" while IFS= read -r -d '' asset; do asset_filename=$(basename ${asset}) [[ -z ${asset_filename%.*} ]] && asset_name="${FG_LGRAY}${policy_id}${NC}" || asset_name="${FG_LGRAY}${policy_id}.${FG_MAGENTA}${asset_filename%.*}${NC}" asset_minted=$(jq -r '.minted //0' "${asset}") - println "DEBUG" "$(printf "${FG_LBLUE}%${asset_amount_maxlen}s${NC} | %s\n" "${asset_minted}" "${asset_name}")" + println DEBUG "$(printf "${FG_LBLUE}%${asset_amount_maxlen}s${NC} | %s\n" "${asset_minted}" "${asset_name}")" done < <(find "${policy_folder}" -mindepth 1 -maxdepth 1 -type f -name '*.asset' -print0 | sort -z) - println "DEBUG" "\nEnter an existing AssetName to mint more tokens or enter a new name to create a new Asset for this Policy" + println DEBUG "\nEnter an existing AssetName to mint more tokens or enter a new name to create a new Asset for this Policy" fi - sleep 0.1 && read -r -p "Asset Name (empty valid): " asset_name 2>&6 && println "LOG" "Asset Name: ${asset_name}" - [[ ${asset_name} =~ ^[^[:alnum:]]$ ]] && println "ERROR" "${FG_RED}ERROR${NC}: Asset name should only contain alphanummeric chars!" && waitForInput && continue - [[ ${#asset_name} -gt 32 ]] && println "ERROR" "${FG_RED}ERROR${NC}: Asset name is limited to 32 chars in length!" && waitForInput && continue - [[ -z ${asset_name} ]] && asset_file="${policy_folder}/.asset" || asset_file="${policy_folder}/${asset_name}.asset" # use underscore as replacement for empty asset name + getAnswerAnyCust asset_name "Asset Name (empty valid)" + [[ ${asset_name} =~ ^[^[:alnum:]]$ ]] && println ERROR "${FG_RED}ERROR${NC}: Asset name should only contain alphanummeric chars!" && waitForInput && continue + [[ ${#asset_name} -gt 32 ]] && println ERROR "${FG_RED}ERROR${NC}: Asset name is limited to 32 chars in length!" && waitForInput && continue + asset_file="${policy_folder}/${asset_name}.asset" echo - sleep 0.1 && read -r -p "Amount (commas allowed as thousand separator): " asset_amount 2>&6 && println "LOG" "Amount (commas allowed as thousand separator): ${asset_amount}" + getAnswerAnyCust asset_amount "Amount (commas allowed as thousand separator)" asset_amount="${asset_amount//,}" - [[ -z "${asset_amount}" ]] && println "ERROR" "${FG_RED}ERROR${NC}: Amount empty, please set a valid integer number!" && waitForInput && continue - if ! isNumber ${asset_amount}; then println "ERROR" "${FG_RED}ERROR${NC}: Invalid number, should be an integer number. Decimals not allowed!" && waitForInput && continue; fi + [[ -z "${asset_amount}" ]] && println ERROR "${FG_RED}ERROR${NC}: Amount empty, please set a valid integer number!" && waitForInput && continue + if ! isNumber ${asset_amount}; then println ERROR "${FG_RED}ERROR${NC}: Invalid number, should be an integer number. Decimals not allowed!" && waitForInput && continue; fi [[ -f "${asset_file}" ]] && asset_minted=$(( $(jq -r .minted "${asset_file}") + asset_amount )) || asset_minted=${asset_amount} metafile_param="" - println "DEBUG" "\nDo you want to attach a metadata JSON file to the minting transaction?" + println DEBUG "\nDo you want to attach a metadata JSON file to the minting transaction?" select_opt "[n] No" "[y] Yes" case $? in 0) : ;; # do nothing - 1) [[ ${ENABLE_DIALOG} = "true" ]] && println "DEBUG" "Enter path to metadata JSON file" && waitForInput "Press any key to open the file explorer" - fileDialog "Enter path to metadata JSON file" "${TMP_DIR}/" - println "DEBUG" "${FG_LGRAY}${file}${NC}\n" + 1) fileDialog "Enter path to metadata JSON file" "${TMP_DIR}/" && echo metafile=${file} - [[ -z "${metafile}" ]] && println "ERROR" "${FG_RED}ERROR${NC}: Metadata file path empty!" && waitForInput && continue - [[ ! -f "${metafile}" ]] && println "ERROR" "${FG_RED}ERROR${NC}: File not found: ${metafile}" && waitForInput && continue - if ! jq -er . "${metafile}"; then println "ERROR" "${FG_RED}ERROR${NC}: Metadata file not a valid json file!" && waitForInput && continue; fi + [[ -z "${metafile}" ]] && println ERROR "${FG_RED}ERROR${NC}: Metadata file path empty!" && waitForInput && continue + [[ ! -f "${metafile}" ]] && println ERROR "${FG_RED}ERROR${NC}: File not found: ${metafile}" && waitForInput && continue + if ! jq -er . "${metafile}"; then println ERROR "${FG_RED}ERROR${NC}: Metadata file not a valid json file!" && waitForInput && continue; fi metafile_param="--metadata-json-file ${metafile}" ;; esac - println "DEBUG" "\n# Select wallet to mint assets on (also used for transaction fee)" + println DEBUG "\n# Select wallet to mint assets on (also used for transaction fee)" if [[ ${op_mode} = "online" ]]; then if ! selectWallet "balance" "${WALLET_PAY_SK_FILENAME}"; then # ${wallet_name} populated by selectWallet function [[ "${dir_name}" != "[Esc] Cancel" ]] && waitForInput; continue fi getWalletType ${wallet_name} case $? in - 0) println "ERROR" "${FG_RED}ERROR${NC}: hardware wallets not supported currently!" && waitForInput && continue ;; - 2) println "ERROR" "${FG_RED}ERROR${NC}: signing keys encrypted, please decrypt before use!" && waitForInput && continue ;; - 3) println "ERROR" "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet!" && waitForInput && continue ;; + 0) println ERROR "${FG_RED}ERROR${NC}: hardware wallets not supported currently!" && waitForInput && continue ;; + 2) println ERROR "${FG_RED}ERROR${NC}: signing keys encrypted, please decrypt before use!" && waitForInput && continue ;; + 3) println ERROR "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet!" && waitForInput && continue ;; esac else if ! selectWallet "balance"; then # ${wallet_name} populated by selectWallet function @@ -3838,7 +3872,7 @@ function main { fi getWalletType ${wallet_name} case $? in - 0) println "ERROR" "${FG_RED}ERROR${NC}: hardware wallets not supported currently!" && waitForInput && continue ;; + 0) println ERROR "${FG_RED}ERROR${NC}: hardware wallets not supported currently!" && waitForInput && continue ;; esac fi echo @@ -3850,10 +3884,10 @@ function main { pay_lovelace=${assets[lovelace]} if [[ ${pay_lovelace} -gt 0 && ${base_lovelace} -gt 0 ]]; then # Both payment and base address available with funds, let user choose what to use - println "DEBUG" "Select source wallet address" + println DEBUG "Select source wallet address" if [[ -n ${wallet_count} && ${wallet_count} -gt ${WALLET_SELECTION_FILTER_LIMIT} ]]; then - println "DEBUG" "$(printf "%s\t\t${FG_LBLUE}%s${NC} Ada" "Funds :" "$(formatLovelace ${base_lovelace})")" - println "DEBUG" "$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Enterprise Funds :" "$(formatLovelace ${pay_lovelace})")" + println DEBUG "$(printf "%s\t\t${FG_LBLUE}%s${NC} Ada" "Funds :" "$(formatLovelace ${base_lovelace})")" + println DEBUG "$(printf "%s\t${FG_LBLUE}%s${NC} Ada" "Enterprise Funds :" "$(formatLovelace ${pay_lovelace})")" fi echo select_opt "[b] Base (default)" "[e] Enterprise" "[Esc] Cancel" @@ -3866,22 +3900,22 @@ function main { elif [[ ${pay_lovelace} -gt 0 ]]; then addr="${pay_addr}" if [[ -n ${wallet_count} && ${wallet_count} -gt ${WALLET_SELECTION_FILTER_LIMIT} ]]; then - println "DEBUG" "$(printf "%s\t${FG_LBLUE}%s${NC} Ada\n" "Enterprise Funds :" "$(formatLovelace ${pay_lovelace})")" + println DEBUG "$(printf "%s\t${FG_LBLUE}%s${NC} Ada\n" "Enterprise Funds :" "$(formatLovelace ${pay_lovelace})")" fi elif [[ ${base_lovelace} -gt 0 ]]; then addr="${base_addr}" if [[ -n ${wallet_count} && ${wallet_count} -gt ${WALLET_SELECTION_FILTER_LIMIT} ]]; then - println "DEBUG" "$(printf "%s\t\t${FG_LBLUE}%s${NC} Ada\n" "Funds :" "$(formatLovelace ${base_lovelace})")" + println DEBUG "$(printf "%s\t\t${FG_LBLUE}%s${NC} Ada\n" "Funds :" "$(formatLovelace ${base_lovelace})")" fi else - println "ERROR" "${FG_RED}ERROR${NC}: no funds available for wallet ${FG_GREEN}${wallet_name}${NC}" + println ERROR "${FG_RED}ERROR${NC}: no funds available for wallet ${FG_GREEN}${wallet_name}${NC}" waitForInput && continue fi if ! mintAsset; then waitForInput && continue fi if [[ ! -f "${asset_file}" ]]; then echo "{}" > ${asset_file}; fi - assetJSON=$( jq ". += {minted: \"${asset_minted}\", name: \"${asset_name}\", policyID: \"${policy_id}\", policyValidBeforeSlot: \"${policy_ttl}\", lastUpdate: \"$(date)\", lastAction: \"mint ${asset_amount}\"}" < ${asset_file}) + assetJSON=$( jq ". += {minted: \"${asset_minted}\", name: \"${asset_name}\", policyID: \"${policy_id}\", policyValidBeforeSlot: \"${policy_ttl}\", lastUpdate: \"$(date -R)\", lastAction: \"mint ${asset_amount}\"}" < ${asset_file}) echo -e "${assetJSON}" > ${asset_file} if ! verifyTx ${addr}; then waitForInput && continue; fi echo @@ -3896,20 +3930,20 @@ function main { ;; ################################################################### burn-asset) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> ADVANCED >> MULTI-ASSET >> BURN ASSET" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" echo - println "DEBUG" "# Select wallet with assets to burn" + println DEBUG "# Select wallet with assets to burn" if [[ ${op_mode} = "online" ]]; then if ! selectWallet "balance" "${WALLET_PAY_SK_FILENAME}"; then # ${wallet_name} populated by selectWallet function [[ "${dir_name}" != "[Esc] Cancel" ]] && waitForInput; continue fi getWalletType ${wallet_name} case $? in - 0) println "ERROR" "${FG_RED}ERROR${NC}: please use a CLI wallet for asset burning!" && waitForInput && continue ;; - 2) println "ERROR" "${FG_RED}ERROR${NC}: signing keys encrypted, please decrypt before use!" && waitForInput && continue ;; - 3) println "ERROR" "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet!" && waitForInput && continue ;; + 0) println ERROR "${FG_RED}ERROR${NC}: please use a CLI wallet for asset burning!" && waitForInput && continue ;; + 2) println ERROR "${FG_RED}ERROR${NC}: signing keys encrypted, please decrypt before use!" && waitForInput && continue ;; + 3) println ERROR "${FG_RED}ERROR${NC}: payment and/or stake signing keys missing from wallet!" && waitForInput && continue ;; esac else if ! selectWallet "balance"; then # ${wallet_name} populated by selectWallet function @@ -3917,7 +3951,7 @@ function main { fi getWalletType ${wallet_name} case $? in - 0) println "ERROR" "${FG_RED}ERROR${NC}: please use a CLI wallet for asset burning!" && waitForInput && continue ;; + 0) println ERROR "${FG_RED}ERROR${NC}: please use a CLI wallet for asset burning!" && waitForInput && continue ;; esac fi # Let user choose asset on wallet to burn, both base and enterprise, fee payed with same address @@ -3937,8 +3971,8 @@ function main { assets_on_wallet+=( "${asset} (enterprise addr)" ) done echo - [[ ${#assets_on_wallet[@]} -eq 0 ]] && println "ERROR" "${FG_RED}ERROR${NC}: Wallet doesn't contain any assets!" && waitForInput && continue - println "DEBUG" "# Select Asset to burn" + [[ ${#assets_on_wallet[@]} -eq 0 ]] && println ERROR "${FG_RED}ERROR${NC}: Wallet doesn't contain any assets!" && waitForInput && continue + println DEBUG "# Select Asset to burn" select_opt "${assets_on_wallet[@]}" "[Esc] Cancel" selection=$? [[ ${selected_value} = "[Esc] Cancel" ]] && continue @@ -3961,7 +3995,7 @@ function main { while IFS= read -r -d '' file; do [[ ${asset_arr[0]} = "$(jq -r .policyID ${file})" ]] && asset_file="${file}" && break done < <(find "${ASSET_FOLDER}" -mindepth 2 -maxdepth 2 -type f -name '*.asset' -print0) - [[ -z ${asset_file} ]] && println "ERROR" "${FG_RED}ERROR${NC}: Searched all available policies in '${ASSET_FOLDER}' for matching '.asset' file but non found!" && waitForInput && continue + [[ -z ${asset_file} ]] && println ERROR "${FG_RED}ERROR${NC}: Searched all available policies in '${ASSET_FOLDER}' for matching '.asset' file but non found!" && waitForInput && continue [[ ${#asset_arr[@]} -eq 1 ]] && asset_name="" || asset_name="${asset_arr[1]}" @@ -3974,28 +4008,26 @@ function main { policy_id_file="${policy_folder}/${ASSET_POLICY_ID_FILENAME}" policy_id="$(cat "${policy_id_file}")" policy_ttl=$(jq -r '.scripts[0].slot //0' "${policy_script_file}") - [[ ${policy_ttl} -gt 0 && ${policy_ttl} -lt $(getSlotTipRef) ]] && println "ERROR" "${FG_RED}ERROR${NC}: Policy expired!" && waitForInput && continue - # Ask amount to burn - println "DEBUG" "Available assets to burn: ${FG_LBLUE}$(formatAsset "${asset_amount}")${NC}\n" - sleep 0.1 && read -r -p "Amount (commas allowed as thousand separator): " assets_to_burn 2>&6 && println "LOG" "Amount (commas allowed as thousand separator): ${assets_to_burn}" + [[ ${policy_ttl} -gt 0 && ${policy_ttl} -lt $(getSlotTipRef) ]] && println ERROR "${FG_RED}ERROR${NC}: Policy expired!" && waitForInput && continue + # ask amount to burn + println DEBUG "Available assets to burn: ${FG_LBLUE}$(formatAsset "${asset_amount}")${NC}\n" + getAnswerAnyCust assets_to_burn "Amount (commas allowed as thousand separator)" assets_to_burn="${assets_to_burn//,}" [[ ${assets_to_burn} = "all" ]] && assets_to_burn=${asset_amount} - if ! isNumber ${assets_to_burn}; then println "ERROR" "${FG_RED}ERROR${NC}: Invalid number, should be an integer number. Decimals not allowed!" && waitForInput && continue; fi - [[ ${assets_to_burn} -gt ${asset_amount} ]] && println "ERROR" "${FG_RED}ERROR${NC}: Amount exceeding assets in address, you can only burn ${FG_LBLUE}$(formatAsset "${asset_amount}")${NC}" && waitForInput && continue + if ! isNumber ${assets_to_burn}; then println ERROR "${FG_RED}ERROR${NC}: Invalid number, should be an integer number. Decimals not allowed!" && waitForInput && continue; fi + [[ ${assets_to_burn} -gt ${asset_amount} ]] && println ERROR "${FG_RED}ERROR${NC}: Amount exceeding assets in address, you can only burn ${FG_LBLUE}$(formatAsset "${asset_amount}")${NC}" && waitForInput && continue asset_minted=$(( $(jq -r .minted "${asset_file}") - assets_to_burn )) # Attach metadata? metafile_param="" - println "DEBUG" "\nDo you want to attach a metadata JSON file to the burning transaction?" + println DEBUG "\nDo you want to attach a metadata JSON file to the burning transaction?" select_opt "[n] No" "[y] Yes" case $? in 0) : ;; # do nothing - 1) [[ ${ENABLE_DIALOG} = "true" ]] && println "DEBUG" "Enter path to metadata JSON file" && waitForInput "Press any key to open the file explorer" - fileDialog "Enter path to metadata JSON file" "${TMP_DIR}/" - println "DEBUG" "${FG_LGRAY}${file}${NC}\n" + 1) fileDialog "Enter path to metadata JSON file" "${TMP_DIR}/" && echo metafile=${file} - [[ -z "${metafile}" ]] && println "ERROR" "${FG_RED}ERROR${NC}: Metadata file path empty!" && waitForInput && continue - [[ ! -f "${metafile}" ]] && println "ERROR" "${FG_RED}ERROR${NC}: File not found: ${metafile}" && waitForInput && continue - if ! jq -er . "${metafile}"; then println "ERROR" "${FG_RED}ERROR${NC}: Metadata file not a valid json file!" && waitForInput && continue; fi + [[ -z "${metafile}" ]] && println ERROR "${FG_RED}ERROR${NC}: Metadata file path empty!" && waitForInput && continue + [[ ! -f "${metafile}" ]] && println ERROR "${FG_RED}ERROR${NC}: File not found: ${metafile}" && waitForInput && continue + if ! jq -er . "${metafile}"; then println ERROR "${FG_RED}ERROR${NC}: Metadata file not a valid json file!" && waitForInput && continue; fi metafile_param="--metadata-json-file ${metafile}" ;; esac @@ -4006,7 +4038,7 @@ function main { fi # TODO: Update asset file if [[ ! -f "${asset_file}" ]]; then echo "{}" > ${asset_file}; fi - assetJSON=$( jq ". += {minted: \"${asset_minted}\", name: \"${asset_name}\", policyID: \"${policy_id}\", policyValidBeforeSlot: \"${policy_ttl}\", lastUpdate: \"$(date)\", lastAction: \"burn ${assets_to_burn}\"}" < ${asset_file}) + assetJSON=$( jq ". += {minted: \"${asset_minted}\", name: \"${asset_name}\", policyID: \"${policy_id}\", policyValidBeforeSlot: \"${policy_ttl}\", lastUpdate: \"$(date -R)\", lastAction: \"burn ${assets_to_burn}\"}" < ${asset_file}) echo -e "${assetJSON}" > ${asset_file} if ! verifyTx ${addr}; then waitForInput && continue; fi echo @@ -4019,35 +4051,183 @@ function main { println "Left in Address : ${FG_LBLUE}$(formatAsset $(( asset_amount - assets_to_burn )))${NC}" println "Left in Circulation : ${FG_LBLUE}$(formatAsset ${asset_minted})${NC} (local tracking)" waitForInput && continue + ;; ################################################################### + register-asset) + clear + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println " >> ADVANCED >> MULTI-ASSET >> REGISTER ASSET" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + echo + if ! cmdAvailable "token-metadata-creator"; then + println ERROR "Please follow instructions on Guild Operators site to download or build the tool:" + println ERROR "${FG_YELLOW}https://cardano-community.github.io/guild-operators/#/Build/offchainMetadataTools${NC}" + waitForInput && continue + fi + [[ ! $(ls -A "${ASSET_FOLDER}" 2>/dev/null) ]] && echo && println "${FG_YELLOW}No policies found!${NC}\n\nPlease first create a policy to use for Cardano Token Registry" && waitForInput && continue + println DEBUG "# Select the policy to use for Cardano Token Registry" + if ! selectPolicy "all" "${ASSET_POLICY_SK_FILENAME}" "${ASSET_POLICY_SCRIPT_FILENAME}" "${ASSET_POLICY_ID_FILENAME}"; then # ${policy_name} populated by selectPolicy function + waitForInput && continue + fi + policy_folder="${ASSET_FOLDER}/${policy_name}" + # Policy filenames + policy_sk_file="${policy_folder}/${ASSET_POLICY_SK_FILENAME}" + policy_script_file="${policy_folder}/${ASSET_POLICY_SCRIPT_FILENAME}" + policy_id="$(cat "${policy_folder}/${ASSET_POLICY_ID_FILENAME}")" + echo + if [[ $(find "${policy_folder}" -type f -name '*.asset' -print0 | wc -c) -gt 0 ]]; then + println DEBUG "# Assets previously minted for this Policy\n" + asset_name_maxlen=5; asset_amount_maxlen=12 + while IFS= read -r -d '' asset; do + asset_filename=$(basename ${asset}) + [[ -z ${asset_filename%.*} ]] && asset_name="." || asset_name="${asset_filename%.*}" + [[ ${#asset_name} -gt ${asset_name_maxlen} ]] && asset_name_maxlen=${#asset_name} + asset_minted=$(jq -r '.minted //0' "${asset}") + [[ ${#asset_minted} -gt ${asset_amount_maxlen} ]] && asset_amount_maxlen=${#asset_minted} + done < <(find "${policy_folder}" -mindepth 1 -maxdepth 1 -type f -name '*.asset' -print0 | sort -z) + println DEBUG "$(printf "%${asset_amount_maxlen}s | %s\n" "Total Amount" "Policy ID[.AssetName]")" + println DEBUG "$(printf "%$((asset_amount_maxlen+1))s+%$((asset_name_maxlen+58))s\n" "" "" | tr " " "-")" + while IFS= read -r -d '' asset; do + asset_filename=$(basename ${asset}) + [[ -z ${asset_filename%.*} ]] && asset_name="${FG_LGRAY}${policy_id}${NC}" || asset_name="${FG_LGRAY}${policy_id}.${FG_MAGENTA}${asset_filename%.*}${NC}" + asset_minted=$(jq -r '.minted //0' "${asset}") + println DEBUG "$(printf "${FG_LBLUE}%${asset_amount_maxlen}s${NC} | %s\n" "${asset_minted}" "${asset_name}")" + done < <(find "${policy_folder}" -mindepth 1 -maxdepth 1 -type f -name '*.asset' -print0 | sort -z) + echo + fi + println "Please enter the asset name as part of PolicyID.AssetName to create registry file for, either a previously minted coin or new" + getAnswerAnyCust asset_name "Asset Name (empty valid)" + [[ ${asset_name} =~ ^[^[:alnum:]]$ ]] && println ERROR "${FG_RED}ERROR${NC}: Asset name should only contain alphanummeric chars!" && waitForInput && continue + [[ ${#asset_name} -gt 32 ]] && println ERROR "${FG_RED}ERROR${NC}: Asset name is limited to 32 chars in length!" && waitForInput && continue + asset_file="${policy_folder}/${asset_name}.asset" + echo + sequence_number=0 + if [[ -f ${asset_file} ]]; then # a previous asset file exist, check if metadata has previously been entered + if jq -er .metadata "${asset_file}" &>/dev/null; then + println DEBUG "${FG_YELLOW}Previous metadata registration found:${NC}" + jq -r .metadata "${asset_file}" + sequence_number=$(( $(jq -r '.metadata.sequenceNumber //0' "${asset_file}" 2>/dev/null) + 1 )) + echo + fi + fi + println DEBUG "# Enter metadata (optional fields can be left empty)" + getAnswerAnyCust meta_name "Name [${FG_RED}required${NC}] (Max. 50 chars) " + [[ -z ${meta_name} || ${#meta_name} -gt 50 ]] && println ERROR "\${FG_RED}ERROR${NC}: Metadata name is a required field and limited to 50 chars in length!" && waitForInput && continue + getAnswerAnyCust meta_desc "Description [${FG_RED}required${NC}] (Max. 500 chars)" + [[ -z ${meta_desc} || ${#meta_desc} -gt 500 ]] && println ERROR "\n${FG_RED}ERROR${NC}: Metadata description is a required field and limited to 500 chars in length!" && waitForInput && continue + getAnswerAnyCust meta_ticker "Ticker [${FG_YELLOW}optional${NC}] (3-5 chars) " + [[ -n ${meta_ticker} && ( ${#meta_ticker} -lt 3 || ${#meta_ticker} -gt 5 ) ]] && println ERROR "\n${FG_RED}ERROR${NC}: Metadata ticker is limited to 3-5 chars in length!" && waitForInput && continue + getAnswerAnyCust meta_url "URL [${FG_YELLOW}optional${NC}] (Max. 250 chars)" + [[ -n ${meta_url} && ( ! ${meta_url} =~ https://.* || ${#meta_url} -gt 250 ) ]] && println ERROR "\n${FG_RED}ERROR${NC}: Invalid metadata URL format or greater than 250 char limit!" && waitForInput && continue + fileDialog "Logo/Icon [${FG_YELLOW}optional${NC}] (PNG, <64kb) " "${TMP_DIR}/" + meta_logo="${file}" + if [[ -n ${meta_logo} ]]; then + [[ ! -f ${meta_logo} ]] && println ERROR "\n${FG_RED}ERROR${NC}: Logo not found!" && waitForInput && continue + [[ $(wc -c ${meta_logo} | cut -d' ' -f1) -gt 64000 ]] && println ERROR "\n${FG_RED}ERROR${NC}: Logo more than 64kb in size!" && waitForInput && continue + [[ $(file -b ${meta_logo}) != "PNG"* ]] && println ERROR "\n${FG_RED}ERROR${NC}: Logo not of PNG image type!" && waitForInput && continue + fi + + asset_subject="${policy_id}$(asciiToHex "${asset_name}")" + + cmd_args=( + "entry" + "${asset_subject}" + "--init" + "--name" "${meta_name}" + "--description" "${meta_desc}" + "--policy" "${policy_script_file}" + ) + [[ -n ${meta_ticker} ]] && cmd_args+=( "--ticker" "${meta_ticker}" ) + [[ -n ${meta_url} ]] && cmd_args+=( "--url" "${meta_url}" ) + [[ -n ${meta_logo} ]] && cmd_args+=( "--logo" "${meta_logo}" ) + + pushd ${policy_folder} &>/dev/null || { println ERROR "\n${FG_RED}ERROR${NC}: unable to change directory to: ${policy_folder}" && waitForInput && continue; } + + # Create JSON draft + println DEBUG false "\nCreating Cardano Metadata Registry JSON draft file ..." + ! meta_file=$(token-metadata-creator "${cmd_args[@]}" 2>&1) && println ERROR "\n${FG_RED}ERROR${NC}: failure during token-metadata-creator draft:\n${meta_file}" && popd >/dev/null && waitForInput && continue + println DEBUG " ${FG_GREEN}OK${NC}!" + + # Update the sequence number if needed + if [[ ${sequence_number} -ne 0 ]]; then + println DEBUG false "Updating sequence number to ${FG_LBLUE}${sequence_number}${NC} ..." + ! sed -i "s/\"sequenceNumber\":\ .*,/\"sequenceNumber\":\ ${sequence_number},/g" ${meta_file} && popd >/dev/null && waitForInput && continue + println DEBUG " ${FG_GREEN}OK${NC}!" + fi + + # Signing draft file with policy signing key + println DEBUG false "Signing draft file with policy signing key ..." + ! meta_file=$(token-metadata-creator entry ${asset_subject} -a "${policy_sk_file}" 2>&1) && println ERROR "\n${FG_RED}ERROR${NC}: failure during token-metadata-creator signing:\n${meta_file}" && popd >/dev/null && waitForInput && continue + println DEBUG " ${FG_GREEN}OK${NC}!" + + # Finalizing the draft file + println DEBUG false "Finalizing the draft file ..." + ! meta_file=$(token-metadata-creator entry ${asset_subject} --finalize 2>&1) && println ERROR "\n${FG_RED}ERROR${NC}: failure during token-metadata-creator finalize:\n${meta_file}" && popd >/dev/null && waitForInput && continue + println DEBUG " ${FG_GREEN}OK${NC}!" + + # Adding Creator-Credits + tmpJSON=$(cat ${meta_file}) + tmpJSON=$(jq ". += {tool: {description: \"CNTools by Guild Operators\", url: \"https://cardano-community.github.io/guild-operators/#/Scripts/cntools\"} } " <<< ${tmpJSON}) + echo -e "${tmpJSON}" > ${meta_file} + + # Validating the final metadata registry submission file + println DEBUG false "Validating the final metadata registry submission file ..." + ! output=$(token-metadata-creator validate ${meta_file} 2>&1) && println ERROR "\n${FG_RED}ERROR${NC}: failure during token-metadata-creator validation:\n${output}" && popd >/dev/null && waitForInput && continue + println DEBUG " ${FG_GREEN}OK${NC}!" + + popd &>/dev/null || println ERROR "\n${FG_RED}ERROR${NC}: unable to return to previous directory!" + + # Update .asset file with registered metadata + assetFileJSON=$(cat ${asset_file}) + assetFileJSON=$(jq ". += {metadata: {name: \"${meta_name}\", description: \"${meta_desc}\", ticker: \"${meta_ticker}\", url: \"${meta_url}\", logo: \"${meta_logo}\", sequenceNumber: \"${sequence_number}\"} } " <<< ${assetFileJSON}) + assetFileJSON=$(jq ". += {lastUpdate: \"$(date -R)\", lastAction: \"created Cardano Token Registry submission file\"}" <<< ${assetFileJSON}) + echo -e "${assetFileJSON}" > ${asset_file} + + echo + println "Cardano Metadata Registry submission file successfully created!" + println "Available at: ${policy_folder}/${meta_file}" + case ${NWMAGIC} in + 764824073) # mainnet + println "\nPlease follow directions on CF Token Registry GitHub site to create a PR for the generated metadata file" + println "https://github.com/cardano-foundation/cardano-token-registry/wiki/How-to-submit-an-entry-to-the-registry" + ;; + 1097911063) # public testnet + println "\nPlease create a PR on IOHK Metadata Registry TestNet GitHub site for the generated metadata file" + println "https://github.com/input-output-hk/metadata-registry-testnet" + ;; + *) : ;; # ignore other networks + esac + + waitForInput && continue + ;; ################################################################### esac ;; ################################################################### del-keys) clear - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" println " >> ADVANCED >> DELETE PRIVATE KEYS" - println "DEBUG" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + println DEBUG "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" echo - println "DEBUG" "The following files will be removed" - println "DEBUG" "Wallet ${FG_LGRAY}${WALLET_PAY_SK_FILENAME}${NC} / ${FG_LGRAY}${WALLET_STAKE_SK_FILENAME}${NC}" - println "DEBUG" "Pool ${FG_LGRAY}${POOL_COLDKEY_SK_FILENAME}${NC}" - [[ -d "${ASSET_FOLDER}" ]] && println "DEBUG" "Asset ${FG_LGRAY}${ASSET_POLICY_SK_FILENAME}${NC}" + println DEBUG "The following files will be removed" + println DEBUG "Wallet ${FG_LGRAY}${WALLET_PAY_SK_FILENAME}${NC} / ${FG_LGRAY}${WALLET_STAKE_SK_FILENAME}${NC}" + println DEBUG "Pool ${FG_LGRAY}${POOL_COLDKEY_SK_FILENAME}${NC}" + [[ -d "${ASSET_FOLDER}" ]] && println DEBUG "Asset ${FG_LGRAY}${ASSET_POLICY_SK_FILENAME}${NC}" echo - println "DEBUG" "${FG_RED}Do you acknowledge that you have already taken a full backup, and are OK to simply delete the private keys? There is no going back !!!${NC}" + println DEBUG "${FG_RED}Do you acknowledge that you have already taken a full backup, and are OK to simply delete the private keys? There is no going back !!!${NC}" select_opt "[n] No" "[y] Yes" case $? in 0) continue ;; 1) : ;; # do nothing esac echo - println "DEBUG" "${FG_YELLOW}Please confirm!${NC} If unsure, cancel and verify that you have a valid backup. Continue with delete action?" + println DEBUG "${FG_YELLOW}Please confirm!${NC} If unsure, cancel and verify that you have a valid backup. Continue with delete action?" select_opt "[n] No" "[y] Yes" case $? in 0) continue ;; 1) : ;; # do nothing esac echo - println "DEBUG" "Delete encrypted keys as well?" + println DEBUG "Delete encrypted keys as well?" select_opt "[n] No" "[y] Yes" case $? in 0) enc_postfix="" ;; diff --git a/scripts/cnode-helper-scripts/env b/scripts/cnode-helper-scripts/env index bef5258d7..db797c61d 100644 --- a/scripts/cnode-helper-scripts/env +++ b/scripts/cnode-helper-scripts/env @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# shellcheck disable=SC2034,SC2086,SC2230,SC2009,SC2206,SC2062,SC2059 +# shellcheck disable=SC2034,SC2086,SC2230,SC2009,SC2206,SC2062,SC2059,SC2229,SC2154,SC2162,SC2120 ###################################### # User Variables - Change as desired # @@ -73,6 +73,12 @@ CNODE_PORT=6000 # Set node port # Do NOT modify code below # ###################################### +PARENT="$(dirname $0)" +[[ -z ${BRANCH} ]] && { [[ -f "${PARENT}"/.env_branch ]] && BRANCH=$(cat "${PARENT}"/.env_branch) || BRANCH=master; } +URL_RAW="https://raw.githubusercontent.com/cardano-community/guild-operators/${BRANCH}" +URL="${URL_RAW}/scripts/cnode-helper-scripts" +URL_DOCS="${URL_RAW}/docs/Scripts" + versionCheck() { printf '%s\n%s' "${1//v/}" "${2//v/}" | sort -C -V; } #$1=minimal_needed_version, $2=current_node_version OFFLINE_MODE='N' @@ -368,21 +374,110 @@ NC='\e[0m' # Description : Query user for yes or no answer getAnswer() { - printf "$* (yes/no): " >&2; read -r answer + getAnswerAny answer "$* (yes/no)" while : ; do case $answer in [Yy]*) return 0 ;; [Nn]*) return 1 ;; - *) printf "%s" "Please enter 'yes' or 'no' to continue: " >&2; read -r answer + *) getAnswerAny answer "Please enter 'yes' or 'no' to continue" esac done } -# Description : Wait for any key press before proceeding and clear screen +# Description : Query user for any question +# : $1 = the name of the variable to save users response into +# : $2 = what to ask user to input +getAnswerAny() { + var_name=$1 + shift + printf "%b: ${FG_GREEN}" "$*" + read -r ${var_name} /dev/null; then + # get vname from env file + if [[ $(grep "_HOME=" "${PARENT}"/env) =~ ^#?([^[:space:]]+)_HOME ]]; then + vname=$(tr '[:upper:]' '[:lower:]' <<< ${BASH_REMATCH[1]}) + # replace default CNODE with custom name if needed + [[ ${vname} != cnode ]] && sed -e "s@/opt/cardano/[c]node@/opt/cardano/${vname}@g" -e "s@[C]NODE_HOME@${BASH_REMATCH[1]}_HOME@g" -i "${PARENT}/${1}".tmp + else + printf "${FG_RED}ERROR${NC}: '${1}' update failed! Please use prereqs.sh to force an update or manually download the file from GitHub" + return 2 + fi + TEMPL_CMD=$(awk '/^# Do NOT modify/,0' "${PARENT}/${1}") + TEMPL2_CMD=$(awk '/^# Do NOT modify/,0' "${PARENT}/${1}".tmp) + if [[ "$(echo ${TEMPL_CMD} | sha256sum)" != "$(echo ${TEMPL2_CMD} | sha256sum)" ]]; then + if [[ $2 = Y ]] || { [[ -t 1 ]] && getAnswer "\nThe static content from ${FG_YELLOW}${1}${NC} does not match with guild-operators repository, do you want to download the updated file?"; }; then + cp "${PARENT}/${1}" "${PARENT}/${1}_bkp$(date +%s)" + STATIC_CMD=$(awk '/#!/{x=1}/^# Do NOT modify/{exit} x' "${PARENT}/${1}") + printf '%s\n%s\n' "$STATIC_CMD" "$TEMPL2_CMD" > "${PARENT}/${1}".tmp + mv "${PARENT}/${1}".tmp "${PARENT}/${1}" + echo -e "\n${FG_YELLOW}${1}${NC} update successfully applied!" + [[ -t 1 ]] && waitToProceed && clear + return 1 + fi + fi + fi + rm -f "${PARENT}/${1}".tmp + return 0 +} + +# Description : Check if command is available +# : $1 = executable to validate +cmdAvailable() { + if ! command -v "$1" &>/dev/null; then + printf "${FG_RED}ERROR${NC}: need '$1' (command not found)\nplease install with your packet manager of choice(apt/yum etc..) and relaunch CNTools\nhttps://command-not-found.com/$1" 1>&2 + return 1 + fi + return 0 +} + +# Description : wait for user keypress to continue +# Parameters : message > [optional]: override default 'press any key to return to home menu' message waitToProceed() { - printf "\npress any key to proceed..." - read -r -n 1 -s wait - clear + IFS=';' read -sdR -p $'\E[6n' ROW COL + echo + createDistanceToBottom $(( $# + 1 )) + ESC=$(printf "\033") + echo + if [[ $# -eq 0 || -z $1 ]]; then + echo "press any key to proceed .." + else + printf '%b\n' "$@" + fi + read -rsn1 key # get 1 character + if [[ $key == "$ESC" ]]; then + read -rsn2 key # read 2 more chars + fi + tput cup ${ROW#*[} ${COL} + tput ed +} + +# Description : Generate asset id according to CIP-14 standard +# https://github.com/cardano-foundation/CIPs/pull/64 +# : $1 = hex-encoded policy ID +# : $2 = ASCII formatted asset name +getAssetIDBech32() { + { ! cmdAvailable "bech32" || ! cmdAvailable "b2sum"; } && return 1 + printf "$(echo -n $1 | sed 's/../\\x&/g')%s" "$2" | b2sum -l 160 -b | cut -d' ' -f 1 | bech32 asset +} + +# Description : Convert a normal 1 byte ASCII string to hex (alnum chars) +# : $1 = ASCII string to convert +asciiToHex() { + local ascwrd=$1 + [[ -z ${ascwrd} ]] && return + for ((i=0;i<${#ascwrd};i++)); do + printf %02x \'${ascwrd:$i:1} + done } # Description : Helper function to validate that input is a number @@ -392,6 +487,79 @@ isNumber() { [[ $1 =~ ^[0-9]+$ ]] && return 0 || return 1 } +# Description : Validate decimal number +# : $1 = decimal number to validate +validateDecimalNbr() { + re_decimal_nbr='^[0-9]+([.][0-9]+)?$' + [[ $1 =~ ${re_decimal_nbr} ]] && return 0 || return 1 +} + +# Description : Pretty print Lovelace value +# : $1 = Amount in Lovelace +formatLovelace() { + if isNumber $1; then + [[ $1 -eq 0 ]] && echo 0 && return + [[ $1 -le 999999 ]] && printf '0.%06d' "$1" && return + printf '%s.%s' "$(sed ':a;s/\B[0-9]\{3\}\>/,&/;ta' <<< ${1::-6})" "${1: -6}" + else + printf "${FG_RED}ERROR${NC}: must be a valid integer number" 1>&2 + return 1 + fi +} + +# Description : Pretty print Ada/Token value +# : $1 = Amount as Integer +formatAsset() { + if isNumber $1; then + sed ':a;s/\B[0-9]\{3\}\>/,&/;ta' <<< $1 + else + printf "${FG_RED}ERROR${NC}: must be a valid integer number" 1>&2 + return 1 + fi +} + +# Description : Convert number in Ada to Lovelace +# : $1 = Amount in Ada, decimal number accepted (using dot) +AdaToLovelace() { + if validateDecimalNbr $1; then + echo "$1 * 1000000 / 1" | bc # /1 is to remove decimals from bc command + else + printf "${FG_RED}ERROR${NC}: must be a valid integer or decimal number" 1>&2 + return 1 + fi +} + +# Description : Convert number as percent to fraction +# : $1 = number to be converted in range 0-100 +pctToFraction() { + if validateDecimalNbr $1; then + if [[ $(bc <<< "$1 >= 0" ) -eq 0 || $(bc <<< "$1 <= 100" ) -eq 0 ]]; then + printf "${FG_RED}ERROR${NC}: must be a number between 0-100" 1>&2 + return 1 + else + echo "x=$1 / 100; if(x<1) print 0; x" | bc -l | sed '/\./ s/\.\{0,1\}0\{1,\}$//' + fi + else + printf "${FG_RED}ERROR${NC}: must be a valid integer or decimal number" 1>&2 + return 1 + fi +} + +# Description : Convert fraction number to precent +# : $1 = number to be converted +fractionToPCT() { + if validateDecimalNbr $1; then + if (( $(bc <<<"$1 > 0") )); then + echo "x=$1 * 100; if(x<1) print 0; x" | bc -l | sed '/\./ s/\.\{0,1\}0\{1,\}$//' + else + echo 0 + fi + else + printf "${FG_RED}ERROR${NC}: must be a valid decimal number" 1>&2 + return 1 + fi +} + # Description : Helper function to validate IPv4 address # : $1 = IP isValidIPv4() { @@ -403,6 +571,58 @@ isValidIPv4() { return 1 } +# Description : Get password from user on STDIN +# : populates ${password} variable, make sure to unset variable when done +# : $1 = Minimum password length +# : $2 = The string 'confirm' to force user to provide password twice for confirmation (optional) +getPassword() { + while true; do + readPassword "Enter password (length >= 8)" + password=${read_password} && unset read_password + if [ ${#password} -lt $1 ]; then + echo + echo -e "${FG_RED}ERROR${NC}: password length too short, please use a minimum of $1 characters." + echo + echo "Press q to abort or any other key to retry" + read -rsn 1 abort + [[ ${abort} = "q" ]] && unset password && return 1 + echo + continue + fi + if [[ $2 = "confirm" ]]; then + echo && readPassword "Confirm password" + check_password=${read_password} && unset read_password + if [[ "${password}" != "${check_password}" ]]; then + echo + echo -e "${FG_RED}ERROR${NC}: password missmatch!" + echo + echo "Press q to abort or any other key to retry" + read -rsn 1 abort + [[ ${abort} = "q" ]] && unset password && unset check_password && return 1 + echo + else + echo && unset check_password && return 0 + fi + else + echo && return 0 + fi + done +} +readPassword() { + read_password="" + prompt="$1: " + while IFS= read -p "${prompt}" -r -s -n 1 char; do + if [[ ${char} == $'\0' ]]; then break; fi + if [[ ${char} == $'\b' ]]; then + [[ ${#read_password} -gt 0 ]] && printf "\033[1D\033[0K" && read_password=${read_password%?} + prompt='' + else + prompt='*' + read_password+="${char}" + fi + done +} + # Description : Helper function to validate IPv6 address, works for normal IPv6 addresses, not dual incl IPv4 # : $1 = IP isValidIPv6() { @@ -423,6 +643,13 @@ isPrivateIP() { return 1 } +# Description : Print blank rows and reset cursor position +# : $1 = number of rows +createDistanceToBottom() { + printf "%0.s\n" $(seq $1) + printf "\033[$1A" +} + # Description : Query cardano-node for current metrics [[ -z ${USE_EKG} ]] && USE_EKG='N' getNodeMetrics() { diff --git a/scripts/cnode-helper-scripts/gLiveView.sh b/scripts/cnode-helper-scripts/gLiveView.sh index 982be27bf..1f9b1a151 100755 --- a/scripts/cnode-helper-scripts/gLiveView.sh +++ b/scripts/cnode-helper-scripts/gLiveView.sh @@ -55,7 +55,7 @@ setTheme() { # Do NOT modify code below # ###################################### -GLV_VERSION=v1.20.4 +GLV_VERSION=v1.20.5 PARENT="$(dirname $0)" [[ -f "${PARENT}"/.env_branch ]] && BRANCH="$(cat ${PARENT}/.env_branch)" || BRANCH="master" @@ -109,35 +109,20 @@ myExit() { # Version Check # ####################################################### clear + +if [[ ! -f "${PARENT}"/env ]]; then + echo -e "\nCommon env file missing: ${PARENT}/env" + echo -e "This is a mandatory prerequisite, please install with prereqs.sh or manually download from GitHub\n" + myExit 1 +fi + +. "${PARENT}"/env offline &>/dev/null # ignore any errors, re-sourced later + if [[ "${NO_INTERNET_MODE}" == "N" ]]; then - URL="https://raw.githubusercontent.com/cardano-community/guild-operators/${BRANCH}/scripts/cnode-helper-scripts" - if curl -s -f -m 10 -o "${PARENT}"/env.tmp ${URL}/env 2>/dev/null && [[ -f "${PARENT}"/env.tmp ]]; then - if [[ -f "${PARENT}"/env ]]; then - if [[ $(grep "_HOME=" "${PARENT}"/env) =~ ^#?([^[:space:]]+)_HOME ]]; then - vname=$(tr '[:upper:]' '[:lower:]' <<< ${BASH_REMATCH[1]}) - sed -e "s@/opt/cardano/[c]node@/opt/cardano/${vname}@g" -e "s@[C]NODE_HOME@${BASH_REMATCH[1]}_HOME@g" -i "${PARENT}"/env.tmp - else - myExit 1 "\nUpdate for env file failed! Please use prereqs.sh to force an update or manually download $(basename $0) + env from GitHub\n" - fi - TEMPL_CMD=$(awk '/^# Do NOT modify/,0' "${PARENT}"/env) - TEMPL2_CMD=$(awk '/^# Do NOT modify/,0' "${PARENT}"/env.tmp) - if [[ "$(echo ${TEMPL_CMD} | sha256sum)" != "$(echo ${TEMPL2_CMD} | sha256sum)" ]]; then - . "${PARENT}"/env offline &>/dev/null # source in offline mode and ignore errors to get some common functions, sourced at a later point again - if getAnswer "\nThe static content from env file does not match with guild-operators repository, do you want to download the updated file?"; then - cp "${PARENT}"/env "${PARENT}/env_bkp$(printf '%(%s)T\n' -1)" - STATIC_CMD=$(awk '/#!/{x=1}/^# Do NOT modify/{exit} x' "${PARENT}"/env) - printf '%s\n%s\n' "$STATIC_CMD" "$TEMPL2_CMD" > "${PARENT}"/env.tmp - mv "${PARENT}"/env.tmp "${PARENT}"/env - echo -e "\nenv update successfully applied!" - waitToProceed - fi - fi - else - mv "${PARENT}"/env.tmp "${PARENT}"/env - myExit 0 "Common env file downloaded: ${PARENT}/env\nThis is a mandatory prerequisite, please set variables accordingly in User Variables section in the env file and restart Guild LiveView\n" - fi - fi - rm -f "${PARENT}"/env.tmp + echo "Guild LiveView version check..." + # check for env update + ! checkUpdate env && myExit 1 + ! . "${PARENT}"/env && myExit 1 "ERROR: CNTools failed to load common env file\nPlease verify set values in 'User Variables' section in env file or log an issue on GitHub" # source common env variables in case it was updated . "${PARENT}"/env case $? in @@ -145,7 +130,6 @@ if [[ "${NO_INTERNET_MODE}" == "N" ]]; then 2) clear ;; esac - echo "Guild LiveView version check..." if curl -s -f -m ${CURL_TIMEOUT} -o "${PARENT}"/gLiveView.sh.tmp ${URL}/gLiveView.sh 2>/dev/null && [[ -f "${PARENT}"/gLiveView.sh.tmp ]]; then GIT_VERSION=$(grep -r ^GLV_VERSION= "${PARENT}"/gLiveView.sh.tmp | cut -d'=' -f2) : "${GIT_VERSION:=v0.0.0}" @@ -166,7 +150,7 @@ if [[ "${NO_INTERNET_MODE}" == "N" ]]; then fi else echo -e "\nFailed to download gLiveView.sh from GitHub, unable to perform version check!" - waitToProceed + waitToProceed && clear fi rm -f "${PARENT}"/gLiveView.sh.tmp else @@ -478,7 +462,7 @@ if [[ ${SHELLEY_TRANS_EPOCH} -eq -1 ]]; then printf "\n - Node in startup mode" printf "\n - Shelley era not reached" printf "\n After successful node boot or when sync to shelley era has been reached, calculations will be correct\n" - waitToProceed + waitToProceed && clear fi version=$("$(command -v cardano-node)" version) node_version=$(grep "cardano-node" <<< "${version}" | cut -d ' ' -f2) diff --git a/scripts/cnode-helper-scripts/topologyUpdater.sh b/scripts/cnode-helper-scripts/topologyUpdater.sh index d00a84c93..aa4340279 100755 --- a/scripts/cnode-helper-scripts/topologyUpdater.sh +++ b/scripts/cnode-helper-scripts/topologyUpdater.sh @@ -51,63 +51,16 @@ shift $((OPTIND -1)) [[ -z "${BATCH_AUTO_UPDATE}" ]] && BATCH_AUTO_UPDATE=N -# Check if update is available -URL="https://raw.githubusercontent.com/cardano-community/guild-operators/${BRANCH}/scripts/cnode-helper-scripts" -if curl -s -f -m 10 -o "${PARENT}"/topologyUpdater.sh.tmp ${URL}/topologyUpdater.sh && curl -s -f -m 10 -o "${PARENT}"/env.tmp ${URL}/env && [[ -f "${PARENT}"/topologyUpdater.sh.tmp && -f "${PARENT}"/env.tmp ]]; then - if [[ -f "${PARENT}"/env ]]; then - if [[ $(grep "_HOME=" "${PARENT}"/env) =~ ^#?([^[:space:]]+)_HOME ]]; then - vname=$(tr '[:upper:]' '[:lower:]' <<< "${BASH_REMATCH[1]}") - else - echo -e "\nFailed to get cnode instance name from env file, aborting!\n" - rm -f "${PARENT}"/topologyUpdater.sh.tmp - rm -f "${PARENT}"/env.tmp - exit 1 - fi - sed -e "s@/opt/cardano/[c]node@/opt/cardano/${vname}@g" -e "s@[C]NODE_HOME@${BASH_REMATCH[1]}_HOME@g" -i "${PARENT}"/topologyUpdater.sh.tmp -i "${PARENT}"/env.tmp - TU_TEMPL=$(awk '/^# Do NOT modify/,0' "${PARENT}"/topologyUpdater.sh) - TU_TEMPL2=$(awk '/^# Do NOT modify/,0' "${PARENT}"/topologyUpdater.sh.tmp) - ENV_TEMPL=$(awk '/^# Do NOT modify/,0' "${PARENT}"/env) - ENV_TEMPL2=$(awk '/^# Do NOT modify/,0' "${PARENT}"/env.tmp) - if [[ "$(echo ${TU_TEMPL} | sha256sum)" != "$(echo ${TU_TEMPL2} | sha256sum)" || "$(echo ${ENV_TEMPL} | sha256sum)" != "$(echo ${ENV_TEMPL2} | sha256sum)" ]]; then - . "${PARENT}"/env offline &>/dev/null # source in offline mode and ignore errors to get some common functions, sourced at a later point again - if [[ ${BATCH_AUTO_UPDATE} = 'Y' ]] || { [[ -t 1 ]] && getAnswer "\nA new version is available, do you want to upgrade?"; }; then - cp "${PARENT}"/topologyUpdater.sh "${PARENT}/topologyUpdater.sh_bkp$(date +%s)" - cp "${PARENT}"/env "${PARENT}/env_bkp$(date +%s)" - TU_STATIC=$(awk '/#!/{x=1}/^# Do NOT modify/{exit} x' "${PARENT}"/topologyUpdater.sh) - ENV_STATIC=$(awk '/#!/{x=1}/^# Do NOT modify/{exit} x' "${PARENT}"/env) - printf '%s\n%s\n' "$TU_STATIC" "$TU_TEMPL2" > "${PARENT}"/topologyUpdater.sh.tmp - printf '%s\n%s\n' "$ENV_STATIC" "$ENV_TEMPL2" > "${PARENT}"/env.tmp - { - mv -f "${PARENT}"/topologyUpdater.sh.tmp "${PARENT}"/topologyUpdater.sh && \ - mv -f "${PARENT}"/env.tmp "${PARENT}"/env && \ - chmod 755 "${PARENT}"/topologyUpdater.sh "${PARENT}"/env && \ - echo -e "\nUpdate applied successfully, please run topologyUpdater again!\n" && \ - exit 0; - } || { - echo -e "\n${FG_RED}Update failed!${NC}\n\nplease install topologyUpdater.sh & env with prereqs.sh or manually download from GitHub" && \ - rm -f "${PARENT}"/topologyUpdater.sh.tmp && \ - rm -f "${PARENT}"/env.tmp && \ - exit 1; - } - fi - fi - else - mv "${PARENT}"/env.tmp "${PARENT}"/env - rm -f "${PARENT}"/topologyUpdater.sh.tmp - echo -e "\nCommon env file downloaded: ${PARENT}/env" - echo -e "This is a mandatory prerequisite, please set variables accordingly in User Variables section in the env file and restart topologyUpdater.sh\n" - exit 0 - fi -fi -rm -f "${PARENT}"/topologyUpdater.sh.tmp -rm -f "${PARENT}"/env.tmp - if [[ ! -f "${PARENT}"/env ]]; then echo -e "\nCommon env file missing: ${PARENT}/env" echo -e "This is a mandatory prerequisite, please install with prereqs.sh or manually download from GitHub\n" exit 1 fi +# Check if update is available +! checkUpdate env ${BATCH_AUTO_UPDATE} && exit 1 +! checkUpdate topologyUpdater.sh ${BATCH_AUTO_UPDATE} && exit 1 + # source common env variables in case it was updated and run in offline mode, even for TU_PUSH mode as this will be cought by failed EKG query # ignore exit code 0 and 2, any other exits script . "${PARENT}"/env offline