From f587e2b8bc84c644dee7df08c356f326e1813181 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Sat, 28 Jun 2025 00:35:59 +0100 Subject: [PATCH 01/12] init create action file script --- scripts/action-create.sh | 62 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100755 scripts/action-create.sh diff --git a/scripts/action-create.sh b/scripts/action-create.sh new file mode 100755 index 0000000..fd59f7f --- /dev/null +++ b/scripts/action-create.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +################################################## + +# Default configuration values + + +################################################## + +# Check if cardano-cli is installed +if ! command -v cardano-cli >/dev/null 2>&1; then + echo "Error: cardano-cli is not installed or not in your PATH." >&2 + exit 1 +fi + +# Usage message +usage() { + echo "Usage: $0 [--some-options]" + echo "Options:" + echo " --some-options Compare against CIP-108 schema (default: $DEFAULT_USE_CIP_108)" + exit 1 +} + +# Initialize variables with defaults +input_file="" + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + --some-options) + use_cip_108="true" + shift + ;; + --cip100) + use_cip_100="true" + shift + ;; + --cip136) + use_cip_136="true" + shift + ;; + --intersect-treasury) + use_intersect_treasury="true" + shift + ;; + --schema) + user_schema_url="$2" + user_schema="true" + shift 2 + ;; + -h|--help) + usage + ;; + *) + if [ -z "$input_file" ]; then + input_file="$1" + fi + shift + ;; + esac +done + From 2e614aa9071d5c8a67347b27d4b2a7917677f038 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Tue, 1 Jul 2025 17:29:04 +0200 Subject: [PATCH 02/12] init action create tw script --- scripts/action-create-tw.sh | 200 ++++++++++++++++++++++++++++++++++++ scripts/action-create.sh | 62 ----------- 2 files changed, 200 insertions(+), 62 deletions(-) create mode 100755 scripts/action-create-tw.sh delete mode 100755 scripts/action-create.sh diff --git a/scripts/action-create-tw.sh b/scripts/action-create-tw.sh new file mode 100755 index 0000000..9f68ee7 --- /dev/null +++ b/scripts/action-create-tw.sh @@ -0,0 +1,200 @@ +#!/bin/bash + +################################################## + +# Default configuration values + + + +################################################## + +# Exit immediately if a command exits with a non-zero status, +# treat unset variables as an error, and fail if any command in a pipeline fails +set -euo pipefail + +# Colors +#BLACK='\033[0;30m' +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +BRIGHTWHITE='\033[0;37;1m' +NC='\033[0m' + +# Check if cardano-cli is installed +if ! command -v cardano-cli >/dev/null 2>&1; then + echo "Error: cardano-cli is not installed or not in your PATH." >&2 + exit 1 +fi + +# Check if ipfs cli is installed +if ! command -v ipfs >/dev/null 2>&1; then + echo "Error: ipfs cli is not installed or not in your PATH." >&2 + exit 1 +fi + +# Usage message + +# todo get the network/testnet magic from the set $SOCKET_PATH + +usage() { + echo "Usage: $0 [--testnet-magic ] [--deposit-return-addr ] [--single-withdrawal-addr ]" + echo "Options:" + echo " --testnet-magic Use a test network, denoted by magic value" + echo " --deposit-return-addr Check that metadata deposit return address matches provided one (Bech32)" + echo " --single-withdrawal-addr Check that metadata withdrawal address matches provided one (Bech32)" + exit 1 +} + +# Initialize variables with defaults +input_file="" + +# Optional variables +testnet_magic="" +deposit_return_address="" +withdrawal_address="" + +# todo check all the inputs work + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + --testnet-magic) + testnet_magic="$2" + shift 2 + ;; + --deposit-return-addr) + deposit_return_address="$3" + shift 3 + ;; + --single-withdrawal-addr) + withdrawal_address="$4" + shift 4 + ;; + -h|--help) + usage + ;; + *) + if [ -z "$input_file" ]; then + input_file="$1" + fi + shift + ;; + esac +done + +echo "Creating a treasury withdrawal governance action from a given metadata file" +echo "This script assumes compliance Intersect's treasury withdrawal action schema" +echo "This script assumes that SOCKET_PATH is set to a local node socket file" +echo " " + +# Exit is socket path is not set +if [ -z "$SOCKET_PATH" ]; then + echo "Error: Cardano node $SOCKET_PATH environment variable is not set." >&2 + exit 1 +fi + +# Open the provided metadata file + +# todo: add checks to exit if any of these fields are not found + +title=$(jq -r '.body.title' "$input_file") +ga_type=$(jq -r '.body.onChain.governanceActionType' "$input_file") +deposit_return=$(jq -r '.body.onChain.depositReturnAddress' "$input_file") + +# todo: for now just support one withdrawal +withdrawal_address=$(jq -r '.body.onChain.withdrawals[0].withdrawalAddress' "$input_file") +withdrawal_address=$(jq -r '.body.onChain.withdrawals[0].withdrawalAmount' "$input_file") + +# Do some basic validation checks +echo -e " " +echo -e "${CYAN}Doing some basic validation and checks on metadata${NC}" + +if [ "$ga_type" = "treasuryWithdrawals" ]; then + echo "Metadata has correct governanceActionType" +else + echo "Metadata does not have the correct governanceActionType" + echo "Expected: treasuryWithdrawals found: $ga_type" + exit 1 +fi + +# deposit address is the same network as the connected and provided testnet_magic + +# check the bech32 prefix to determine network +# if [ "$($deposit_return_address)" = "stake1" && "$testnet_magic" = "" ]; then +# echo +# else + +# fi + +# deposit address matches the one provided + +# if return address provided check against metadata +if [ !"$deposit_return_address" = "" ]; then + echo "Deposit return address provided" + echo "Comparing provided address to metadata" + if [ "$deposit_return_address" = "$deposit_return" ]; then + echo "Metadata has expected deposit return address" + else + echo "Metadata does not have expected deposit return address" + exit 1 + fi +fi + +echo -e "${GREEN}Automatic validations passed${NC}" +echo -e " " +echo -e "${CYAN}Computing details${NC}" + +# compute if provided addresses are script-based or key-based +# we should warn the user if they are key-based + +# Compute the hash and IPFS URI +file_hash=$(b2sum -l 256 "$input_file" | awk '{print $1}') +echo "Metadata file hash: $file_hash" + +ipfs_cid=$(ipfs add -Q --cid-version 1 "$input_file") +echo "IPFS URI: ipfs://$ipfs_cid" + +# Make user manually confirm the choices +echo " " +echo "Creating treasury withdrawal action" +echo "Titled: $title" +echo "Deposit return address: $deposit_return" + +read -p "Do you want to proceed with this deposit return address? (yes/no): " confirm_deposit + +if [ "$confirm_deposit" != "yes" ]; then + echo -e "${RED}Deposit address not confirmed by user, exiting.${NC}" + exit 1 +fi + +echo "Withdrawal address: $withdrawal_address" + +# todo also show amount in ada + +echo "Withdrawal amount (lovelace): $withdrawal_amount" + +read -p "Do you want to proceed with these files? (yes/no): " confirm_withdrawal + +if [ "$confirm_withdrawal" != "yes" ]; then + echo -e "${RED}Withdrawal amount or withdrawal address not confirmed by user, exiting.${NC}" + exit 1 +fi + +# Create the action +echo "Creating action" + +cardano-cli conway governance action create-treasury-withdrawal \ + --mainnet \ + --governance-action-deposit $(cardano-cli conway query gov-state | jq -r '.currentPParams.govActionDeposit') \ + --deposit-return-stake-address "$deposit_return_address" \ + --anchor-url "ipfs://$ipfs_cid" \ + --anchor-data-hash "$file_hash" \ + --check-anchor-data \ + --funds-receiving-stake-address "$withdrawal_address" \ + --transfer "$withdrawal_amount" \ + --constitution-script-hash $(cardano-cli conway query constitution | jq -r '.script') \ + --out-file "$input_file.action" + + diff --git a/scripts/action-create.sh b/scripts/action-create.sh deleted file mode 100755 index fd59f7f..0000000 --- a/scripts/action-create.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/bash - -################################################## - -# Default configuration values - - -################################################## - -# Check if cardano-cli is installed -if ! command -v cardano-cli >/dev/null 2>&1; then - echo "Error: cardano-cli is not installed or not in your PATH." >&2 - exit 1 -fi - -# Usage message -usage() { - echo "Usage: $0 [--some-options]" - echo "Options:" - echo " --some-options Compare against CIP-108 schema (default: $DEFAULT_USE_CIP_108)" - exit 1 -} - -# Initialize variables with defaults -input_file="" - -# Parse command line arguments -while [[ $# -gt 0 ]]; do - case $1 in - --some-options) - use_cip_108="true" - shift - ;; - --cip100) - use_cip_100="true" - shift - ;; - --cip136) - use_cip_136="true" - shift - ;; - --intersect-treasury) - use_intersect_treasury="true" - shift - ;; - --schema) - user_schema_url="$2" - user_schema="true" - shift 2 - ;; - -h|--help) - usage - ;; - *) - if [ -z "$input_file" ]; then - input_file="$1" - fi - shift - ;; - esac -done - From 8f5fcadc171000d8a8e936f59254eb16b5028372 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Fri, 4 Jul 2025 15:56:49 +0100 Subject: [PATCH 03/12] add check for fields --- scripts/action-create-tw.sh | 43 +++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/scripts/action-create-tw.sh b/scripts/action-create-tw.sh index 9f68ee7..f5ef75d 100755 --- a/scripts/action-create-tw.sh +++ b/scripts/action-create-tw.sh @@ -41,7 +41,7 @@ fi usage() { echo "Usage: $0 [--testnet-magic ] [--deposit-return-addr ] [--single-withdrawal-addr ]" echo "Options:" - echo " --testnet-magic Use a test network, denoted by magic value" + echo " --testnet-magic Use a test network, denoted by magic protocol value" echo " --deposit-return-addr Check that metadata deposit return address matches provided one (Bech32)" echo " --single-withdrawal-addr Check that metadata withdrawal address matches provided one (Bech32)" exit 1 @@ -97,19 +97,36 @@ fi # Open the provided metadata file -# todo: add checks to exit if any of these fields are not found +# Do some basic validation checks on metadata +echo -e " " +echo -e "${CYAN}Doing some basic validation and checks on metadata${NC}" + +# Function to check if jq query returned null or empty +check_field() { + local field_name="$1" + local field_value="$2" + + if [ -z "$field_value" ] || [ "$field_value" = "null" ]; then + echo -e "${RED}Error: Required field '$field_name' not found in metadata${NC}" >&2 + exit 1 + fi +} +# Extract and validate required fields title=$(jq -r '.body.title' "$input_file") +check_field "title" "$title" + ga_type=$(jq -r '.body.onChain.governanceActionType' "$input_file") +check_field "governanceActionType" "$ga_type" + deposit_return=$(jq -r '.body.onChain.depositReturnAddress' "$input_file") +check_field "depositReturnAddress" "$deposit_return" -# todo: for now just support one withdrawal +# todo: support multiple withdrawals withdrawal_address=$(jq -r '.body.onChain.withdrawals[0].withdrawalAddress' "$input_file") -withdrawal_address=$(jq -r '.body.onChain.withdrawals[0].withdrawalAmount' "$input_file") - -# Do some basic validation checks -echo -e " " -echo -e "${CYAN}Doing some basic validation and checks on metadata${NC}" +check_field "withdrawalAddress" "$withdrawal_address" +withdrawal_amount=$(jq -r '.body.onChain.withdrawals[0].withdrawalAmount' "$input_file") +check_field "withdrawalAmount" "$withdrawal_amount" if [ "$ga_type" = "treasuryWithdrawals" ]; then echo "Metadata has correct governanceActionType" @@ -157,10 +174,10 @@ ipfs_cid=$(ipfs add -Q --cid-version 1 "$input_file") echo "IPFS URI: ipfs://$ipfs_cid" # Make user manually confirm the choices -echo " " -echo "Creating treasury withdrawal action" -echo "Titled: $title" -echo "Deposit return address: $deposit_return" +echo -e " " +echo -e "${CYAN}Creating treasury withdrawal action${NC}" +echo -e "Title: $title" +echo -e "Deposit return address: $deposit_return" read -p "Do you want to proceed with this deposit return address? (yes/no): " confirm_deposit @@ -196,5 +213,3 @@ cardano-cli conway governance action create-treasury-withdrawal \ --transfer "$withdrawal_amount" \ --constitution-script-hash $(cardano-cli conway query constitution | jq -r '.script') \ --out-file "$input_file.action" - - From a4731f48364f2070e036b3414cb953c9de09616f Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Fri, 4 Jul 2025 16:08:21 +0100 Subject: [PATCH 04/12] improve readability --- scripts/action-create-tw.sh | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/scripts/action-create-tw.sh b/scripts/action-create-tw.sh index f5ef75d..bce9417 100755 --- a/scripts/action-create-tw.sh +++ b/scripts/action-create-tw.sh @@ -136,18 +136,9 @@ else exit 1 fi -# deposit address is the same network as the connected and provided testnet_magic +# todo: add check that the deposit address is the same network as the connected and provided testnet_magic -# check the bech32 prefix to determine network -# if [ "$($deposit_return_address)" = "stake1" && "$testnet_magic" = "" ]; then -# echo -# else - -# fi - -# deposit address matches the one provided - -# if return address provided check against metadata +# if return address passed in check against metadata if [ !"$deposit_return_address" = "" ]; then echo "Deposit return address provided" echo "Comparing provided address to metadata" @@ -168,16 +159,17 @@ echo -e "${CYAN}Computing details${NC}" # Compute the hash and IPFS URI file_hash=$(b2sum -l 256 "$input_file" | awk '{print $1}') -echo "Metadata file hash: $file_hash" +echo -e "Metadata file hash: ${YELLOW}$file_hash${NC}" ipfs_cid=$(ipfs add -Q --cid-version 1 "$input_file") -echo "IPFS URI: ipfs://$ipfs_cid" +echo -e "IPFS URI: ${YELLOW}ipfs://$ipfs_cid${NC}" # Make user manually confirm the choices echo -e " " echo -e "${CYAN}Creating treasury withdrawal action${NC}" -echo -e "Title: $title" -echo -e "Deposit return address: $deposit_return" +echo -e "Title: ${YELLOW}$title${NC}" +echo -e " " +echo -e "Deposit return address: ${YELLOW}$deposit_return${NC}" read -p "Do you want to proceed with this deposit return address? (yes/no): " confirm_deposit @@ -186,11 +178,12 @@ if [ "$confirm_deposit" != "yes" ]; then exit 1 fi -echo "Withdrawal address: $withdrawal_address" - -# todo also show amount in ada +echo " " +echo "Withdrawal address: ${YELLOW}$withdrawal_address${NC}" -echo "Withdrawal amount (lovelace): $withdrawal_amount" +ada_amount=$(echo "scale=6; $withdrawal_amount / 1000000" | bc) +ada_amount_formatted=$(printf "%'0.6f" "$ada_amount") +echo "Withdrawal amount (ada): ${YELLOW}$ada_amount${NC}" read -p "Do you want to proceed with these files? (yes/no): " confirm_withdrawal From 8cfacf39c5a35a33d32ff9940758d8d02efb3f7b Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Fri, 4 Jul 2025 16:12:35 +0100 Subject: [PATCH 05/12] add withdrawal address check --- scripts/action-create-tw.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/scripts/action-create-tw.sh b/scripts/action-create-tw.sh index bce9417..4c79e16 100755 --- a/scripts/action-create-tw.sh +++ b/scripts/action-create-tw.sh @@ -53,7 +53,7 @@ input_file="" # Optional variables testnet_magic="" deposit_return_address="" -withdrawal_address="" +withdrawal_address_input="" # todo check all the inputs work @@ -69,7 +69,7 @@ while [[ $# -gt 0 ]]; do shift 3 ;; --single-withdrawal-addr) - withdrawal_address="$4" + withdrawal_address_input="$4" shift 4 ;; -h|--help) @@ -150,6 +150,18 @@ if [ !"$deposit_return_address" = "" ]; then fi fi +# check if withdrawal address is provided +if [ ! -z "$withdrawal_address_input" ]; then + echo "Withdrawal address provided" + echo "Comparing provided address to metadata" + if [ "$withdrawal_address_input" = "$withdrawal_address" ]; then + echo "Metadata has expected withdrawal address" + else + echo "Metadata does not have expected withdrawal address" + exit 1 + fi +fi + echo -e "${GREEN}Automatic validations passed${NC}" echo -e " " echo -e "${CYAN}Computing details${NC}" From a9cf662826e421946437c48db83dfa86ae4910cf Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Fri, 4 Jul 2025 16:25:28 +0100 Subject: [PATCH 06/12] greatly improve how arguments are passed --- scripts/action-create-tw.sh | 54 ++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/scripts/action-create-tw.sh b/scripts/action-create-tw.sh index 4c79e16..92d1385 100755 --- a/scripts/action-create-tw.sh +++ b/scripts/action-create-tw.sh @@ -39,11 +39,11 @@ fi # todo get the network/testnet magic from the set $SOCKET_PATH usage() { - echo "Usage: $0 [--testnet-magic ] [--deposit-return-addr ] [--single-withdrawal-addr ]" + echo "Usage: $0 [--testnet-magic ] [--deposit-return-addr ] [--withdrawal-addr ]" echo "Options:" echo " --testnet-magic Use a test network, denoted by magic protocol value" echo " --deposit-return-addr Check that metadata deposit return address matches provided one (Bech32)" - echo " --single-withdrawal-addr Check that metadata withdrawal address matches provided one (Bech32)" + echo " --withdrawal-addr Check that metadata withdrawal address matches provided one (Bech32)" exit 1 } @@ -61,16 +61,31 @@ withdrawal_address_input="" while [[ $# -gt 0 ]]; do case $1 in --testnet-magic) - testnet_magic="$2" - shift 2 + if [ -n "${2:-}" ]; then + testnet_magic="$2" + shift 2 + else + echo -e "${RED}Error: --testnet-magic requires a value${NC}" >&2 + usage + fi ;; --deposit-return-addr) - deposit_return_address="$3" - shift 3 + if [ -n "${2:-}" ]; then + deposit_return_address="$2" + shift 2 + else + echo -e "${RED}Error: --deposit-return-addr requires a value${NC}" >&2 + usage + fi ;; - --single-withdrawal-addr) - withdrawal_address_input="$4" - shift 4 + --withdrawal-addr) + if [ -n "${2:-}" ]; then + withdrawal_address_input="$2" + shift 2 + else + echo -e "${RED}Error: --withdrawal-addr requires a value${NC}" >&2 + usage + fi ;; -h|--help) usage @@ -78,17 +93,30 @@ while [[ $# -gt 0 ]]; do *) if [ -z "$input_file" ]; then input_file="$1" + else + echo -e "${RED}Error: Input file already specified. Unexpected argument: $1${NC}" >&2 + usage fi shift ;; esac done -echo "Creating a treasury withdrawal governance action from a given metadata file" -echo "This script assumes compliance Intersect's treasury withdrawal action schema" -echo "This script assumes that SOCKET_PATH is set to a local node socket file" -echo " " +# If no input file provided, show usage +if [ -z "$input_file" ]; then + echo -e "${RED}Error: No input file specified${NC}" >&2 + usage +fi + +# Check if input file exists +if [ ! -f "$input_file" ]; then + echo -e "${RED}Error: Input file not found: $input_file${NC}" >&2 + exit 1 +fi +echo -e "${YELLOW}Creating a treasury withdrawal governance action from a given metadata file${NC}" +echo -e "${CYAN}This script assumes compliance Intersect's treasury withdrawal action schema${NC}" +echo -e "${CYAN}This script assumes that SOCKET_PATH is set to a local node socket file${NC}" # Exit is socket path is not set if [ -z "$SOCKET_PATH" ]; then echo "Error: Cardano node $SOCKET_PATH environment variable is not set." >&2 From 834d456e97267adeaaf85c1c8504b47d956bcfdb Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Fri, 4 Jul 2025 16:29:08 +0100 Subject: [PATCH 07/12] fix check for deposit return address --- scripts/action-create-tw.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/action-create-tw.sh b/scripts/action-create-tw.sh index 92d1385..0bb638d 100755 --- a/scripts/action-create-tw.sh +++ b/scripts/action-create-tw.sh @@ -52,7 +52,7 @@ input_file="" # Optional variables testnet_magic="" -deposit_return_address="" +deposit_return_address_input="" withdrawal_address_input="" # todo check all the inputs work @@ -71,7 +71,7 @@ while [[ $# -gt 0 ]]; do ;; --deposit-return-addr) if [ -n "${2:-}" ]; then - deposit_return_address="$2" + deposit_return_address_input="$2" shift 2 else echo -e "${RED}Error: --deposit-return-addr requires a value${NC}" >&2 @@ -167,13 +167,13 @@ fi # todo: add check that the deposit address is the same network as the connected and provided testnet_magic # if return address passed in check against metadata -if [ !"$deposit_return_address" = "" ]; then +if [ ! -z "$deposit_return_address_input" ]; then echo "Deposit return address provided" echo "Comparing provided address to metadata" - if [ "$deposit_return_address" = "$deposit_return" ]; then - echo "Metadata has expected deposit return address" + if [ "$deposit_return_address_input" = "$deposit_return" ]; then + echo -e "${GREEN}Metadata has expected deposit return address${NC}" else - echo "Metadata does not have expected deposit return address" + echo -e "${RED}Metadata does not have expected deposit return address${NC}" exit 1 fi fi @@ -183,9 +183,9 @@ if [ ! -z "$withdrawal_address_input" ]; then echo "Withdrawal address provided" echo "Comparing provided address to metadata" if [ "$withdrawal_address_input" = "$withdrawal_address" ]; then - echo "Metadata has expected withdrawal address" + echo -e "${GREEN}Metadata has expected withdrawal address${NC}" else - echo "Metadata does not have expected withdrawal address" + echo -e "${RED}Metadata does not have expected withdrawal address${NC}" exit 1 fi fi From a056dfb7e43a3c8e51ee61061845a61273674b15 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Fri, 4 Jul 2025 16:33:27 +0100 Subject: [PATCH 08/12] improve outputs --- scripts/action-create-tw.sh | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/scripts/action-create-tw.sh b/scripts/action-create-tw.sh index 0bb638d..3576629 100755 --- a/scripts/action-create-tw.sh +++ b/scripts/action-create-tw.sh @@ -218,14 +218,14 @@ if [ "$confirm_deposit" != "yes" ]; then exit 1 fi -echo " " -echo "Withdrawal address: ${YELLOW}$withdrawal_address${NC}" +echo -e " " +echo -e "Withdrawal address: ${YELLOW}$withdrawal_address${NC}" ada_amount=$(echo "scale=6; $withdrawal_amount / 1000000" | bc) ada_amount_formatted=$(printf "%'0.6f" "$ada_amount") -echo "Withdrawal amount (ada): ${YELLOW}$ada_amount${NC}" +echo -e "Withdrawal amount (ada): ${YELLOW}$ada_amount_formatted${NC}" -read -p "Do you want to proceed with these files? (yes/no): " confirm_withdrawal +read -p "Do you want to proceed with this withdrawal address and amount? (yes/no): " confirm_withdrawal if [ "$confirm_withdrawal" != "yes" ]; then echo -e "${RED}Withdrawal amount or withdrawal address not confirmed by user, exiting.${NC}" @@ -233,9 +233,11 @@ if [ "$confirm_withdrawal" != "yes" ]; then fi # Create the action -echo "Creating action" +echo -e " " +echo -e "${CYAN}Creating action file...${NC}" cardano-cli conway governance action create-treasury-withdrawal \ + --socket-path $SOCKET_PATH \ --mainnet \ --governance-action-deposit $(cardano-cli conway query gov-state | jq -r '.currentPParams.govActionDeposit') \ --deposit-return-stake-address "$deposit_return_address" \ From 76a9d63e57d1b323d88b3d9b31abfe960e324531 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Fri, 4 Jul 2025 17:16:15 +0100 Subject: [PATCH 09/12] use cardano-cli environment variables --- scripts/action-create-tw.sh | 47 +++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/scripts/action-create-tw.sh b/scripts/action-create-tw.sh index 3576629..2cecf53 100755 --- a/scripts/action-create-tw.sh +++ b/scripts/action-create-tw.sh @@ -36,12 +36,9 @@ fi # Usage message -# todo get the network/testnet magic from the set $SOCKET_PATH - usage() { - echo "Usage: $0 [--testnet-magic ] [--deposit-return-addr ] [--withdrawal-addr ]" + echo "Usage: $0 [--deposit-return-addr ] [--withdrawal-addr ]" echo "Options:" - echo " --testnet-magic Use a test network, denoted by magic protocol value" echo " --deposit-return-addr Check that metadata deposit return address matches provided one (Bech32)" echo " --withdrawal-addr Check that metadata withdrawal address matches provided one (Bech32)" exit 1 @@ -51,7 +48,6 @@ usage() { input_file="" # Optional variables -testnet_magic="" deposit_return_address_input="" withdrawal_address_input="" @@ -60,15 +56,6 @@ withdrawal_address_input="" # Parse command line arguments while [[ $# -gt 0 ]]; do case $1 in - --testnet-magic) - if [ -n "${2:-}" ]; then - testnet_magic="$2" - shift 2 - else - echo -e "${RED}Error: --testnet-magic requires a value${NC}" >&2 - usage - fi - ;; --deposit-return-addr) if [ -n "${2:-}" ]; then deposit_return_address_input="$2" @@ -116,13 +103,21 @@ fi echo -e "${YELLOW}Creating a treasury withdrawal governance action from a given metadata file${NC}" echo -e "${CYAN}This script assumes compliance Intersect's treasury withdrawal action schema${NC}" -echo -e "${CYAN}This script assumes that SOCKET_PATH is set to a local node socket file${NC}" -# Exit is socket path is not set -if [ -z "$SOCKET_PATH" ]; then - echo "Error: Cardano node $SOCKET_PATH environment variable is not set." >&2 +echo -e " " +echo -e "${CYAN}This script assumes that CARDANO_NODE_SOCKET_PATH is set${NC}" +echo -e "${CYAN}This script assumes that CARDANO_NODE_NETWORK_ID is set${NC}" + +# Exit if socket path is not set +if [ -z "$CARDANO_NODE_SOCKET_PATH" ]; then + echo "Error: Cardano node $CARDANO_NODE_SOCKET_PATH environment variable is not set." >&2 exit 1 fi +# Exit if network id is not set +if [ -z "$CARDANO_NODE_NETWORK_ID" ]; then + echo "Error: Cardano node $CARDANO_NODE_NETWORK_ID environment variable is not set." >&2 +fi + # Open the provided metadata file # Do some basic validation checks on metadata @@ -236,15 +231,21 @@ fi echo -e " " echo -e "${CYAN}Creating action file...${NC}" +# todo support other networks +if [ -n "$testnet_magic" ]; then + echo -e "${YELLOW}Using testnet magic: $testnet_magic${NC}" +else + echo -e "${YELLOW}Using mainnet${NC}" +fi + cardano-cli conway governance action create-treasury-withdrawal \ - --socket-path $SOCKET_PATH \ - --mainnet \ - --governance-action-deposit $(cardano-cli conway query gov-state | jq -r '.currentPParams.govActionDeposit') \ - --deposit-return-stake-address "$deposit_return_address" \ + -- \ + --governance-action-deposit $(cardano-cli conway query gov-state --mainnet | jq -r '.currentPParams.govActionDeposit') \ + --deposit-return-stake-address "$deposit_return" \ --anchor-url "ipfs://$ipfs_cid" \ --anchor-data-hash "$file_hash" \ --check-anchor-data \ --funds-receiving-stake-address "$withdrawal_address" \ --transfer "$withdrawal_amount" \ - --constitution-script-hash $(cardano-cli conway query constitution | jq -r '.script') \ + --constitution-script-hash $(cardano-cli conway query constitution --mainnet | jq -r '.script') \ --out-file "$input_file.action" From 7fc0a715baebaa5eca87ec310480d2d61f10f493 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Fri, 4 Jul 2025 17:49:06 +0100 Subject: [PATCH 10/12] add check for addresses network --- scripts/action-create-tw.sh | 95 +++++++++++++++++++++++++++++-------- 1 file changed, 76 insertions(+), 19 deletions(-) diff --git a/scripts/action-create-tw.sh b/scripts/action-create-tw.sh index 2cecf53..fb46238 100755 --- a/scripts/action-create-tw.sh +++ b/scripts/action-create-tw.sh @@ -3,8 +3,7 @@ ################################################## # Default configuration values - - +WITHDRAW_TO_SCRIPT="false" ################################################## @@ -37,10 +36,13 @@ fi # Usage message usage() { - echo "Usage: $0 [--deposit-return-addr ] [--withdrawal-addr ]" + echo "Usage: $0 [--withdraw-to-script] [--deposit-return-addr ] [--withdrawal-addr ]" echo "Options:" - echo " --deposit-return-addr Check that metadata deposit return address matches provided one (Bech32)" - echo " --withdrawal-addr Check that metadata withdrawal address matches provided one (Bech32)" + echo " Path to the JSON-LD metadata file or directory containing metadata files" + echo " --withdraw-to-script Check that the withdrawal address is a script-based address, exit otherwise" + echo " --deposit-return-addr Check that metadata deposit return address matches provided one (Bech32)" + echo " --withdrawal-addr Check that metadata withdrawal address matches provided one (Bech32)" + echo " -h, --help Show this help message and exit" exit 1 } @@ -48,6 +50,7 @@ usage() { input_file="" # Optional variables +withdraw_to_script="$WITHDRAW_TO_SCRIPT" deposit_return_address_input="" withdrawal_address_input="" @@ -56,6 +59,10 @@ withdrawal_address_input="" # Parse command line arguments while [[ $# -gt 0 ]]; do case $1 in + --withdraw-to-script) + withdraw_to_script="true" + shift + ;; --deposit-return-addr) if [ -n "${2:-}" ]; then deposit_return_address_input="$2" @@ -101,11 +108,10 @@ if [ ! -f "$input_file" ]; then exit 1 fi +echo -e " " echo -e "${YELLOW}Creating a treasury withdrawal governance action from a given metadata file${NC}" echo -e "${CYAN}This script assumes compliance Intersect's treasury withdrawal action schema${NC}" -echo -e " " -echo -e "${CYAN}This script assumes that CARDANO_NODE_SOCKET_PATH is set${NC}" -echo -e "${CYAN}This script assumes that CARDANO_NODE_NETWORK_ID is set${NC}" +echo -e "${CYAN}This script assumes that CARDANO_NODE_SOCKET_PATH and CARDANO_NODE_NETWORK_ID are set${NC}" # Exit if socket path is not set if [ -z "$CARDANO_NODE_SOCKET_PATH" ]; then @@ -118,6 +124,15 @@ if [ -z "$CARDANO_NODE_NETWORK_ID" ]; then echo "Error: Cardano node $CARDANO_NODE_NETWORK_ID environment variable is not set." >&2 fi +# Get if mainnet or testnet +if [ "$CARDANO_NODE_NETWORK_ID" = "764824073" ] || [ "$CARDANO_NODE_NETWORK_ID" = "mainnet" ]; then + echo -e "${YELLOW}Local node is using mainnet${NC}" + protocol_magic="mainnet" +else + echo -e "${YELLOW}Local node is using a testnet${NC}" + protocol_magic="$CARDANO_NODE_NETWORK_ID" +fi + # Open the provided metadata file # Do some basic validation checks on metadata @@ -159,8 +174,6 @@ else exit 1 fi -# todo: add check that the deposit address is the same network as the connected and provided testnet_magic - # if return address passed in check against metadata if [ ! -z "$deposit_return_address_input" ]; then echo "Deposit return address provided" @@ -185,6 +198,54 @@ if [ ! -z "$withdrawal_address_input" ]; then fi fi +# todo: check if addresses are on the same network as local node + +# use bech32 prefix to determine if addresses are mainnet or testnet +is_stake_address_mainnet() { + local address="$1" + # Check if address starts with stake1 (mainnet) + if [[ "$address" =~ ^stake1 ]]; then + return 0 + # Check if address starts with stake_test1 (testnet) + elif [[ "$address" =~ ^stake_test1 ]]; then + return 1 + else + echo -e "${RED}Error: Invalid stake address format: $address${NC}" >&2 + exit 1 + fi +} + +# if mainnet node then expect addresses to be mainnet +if [ "$protocol_magic" = "mainnet" ]; then + if is_stake_address_mainnet "$deposit_return"; then + echo -e "Deposit return address is a valid mainnet stake address" + else + echo -e "${RED}Deposit return address is not a valid mainnet stake address${NC}" + exit 1 + fi + + if is_stake_address_mainnet "$withdrawal_address"; then + echo -e "Withdrawal address is a valid mainnet stake address" + else + echo -e "${RED}Withdrawal address is not a valid mainnet stake address${NC}" + exit 1 + fi +else + if ! is_stake_address_mainnet "$deposit_return"; then + echo -e "Deposit return address is a valid testnet stake address" + else + echo -e "${RED}Deposit return address is not a valid testnet stake address${NC}" + exit 1 + fi + + if ! is_stake_address_mainnet "$withdrawal_address"; then + echo -e "Withdrawal address is a valid testnet stake address" + else + echo -e "${RED}Withdrawal address is not a valid testnet stake address${NC}" + exit 1 + fi +fi + echo -e "${GREEN}Automatic validations passed${NC}" echo -e " " echo -e "${CYAN}Computing details${NC}" @@ -199,6 +260,8 @@ echo -e "Metadata file hash: ${YELLOW}$file_hash${NC}" ipfs_cid=$(ipfs add -Q --cid-version 1 "$input_file") echo -e "IPFS URI: ${YELLOW}ipfs://$ipfs_cid${NC}" +# todo add information about if addresses are script-based or key-based + # Make user manually confirm the choices echo -e " " echo -e "${CYAN}Creating treasury withdrawal action${NC}" @@ -231,21 +294,15 @@ fi echo -e " " echo -e "${CYAN}Creating action file...${NC}" -# todo support other networks -if [ -n "$testnet_magic" ]; then - echo -e "${YELLOW}Using testnet magic: $testnet_magic${NC}" -else - echo -e "${YELLOW}Using mainnet${NC}" -fi cardano-cli conway governance action create-treasury-withdrawal \ - -- \ - --governance-action-deposit $(cardano-cli conway query gov-state --mainnet | jq -r '.currentPParams.govActionDeposit') \ + --mainnet \ + --governance-action-deposit $(cardano-cli conway query gov-state | jq -r '.currentPParams.govActionDeposit') \ --deposit-return-stake-address "$deposit_return" \ --anchor-url "ipfs://$ipfs_cid" \ --anchor-data-hash "$file_hash" \ --check-anchor-data \ --funds-receiving-stake-address "$withdrawal_address" \ --transfer "$withdrawal_amount" \ - --constitution-script-hash $(cardano-cli conway query constitution --mainnet | jq -r '.script') \ + --constitution-script-hash $(cardano-cli conway query constitution | jq -r '.script') \ --out-file "$input_file.action" From ac235502a4a6c999d0d7b0ddfd913dc4f070460f Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Fri, 4 Jul 2025 18:10:17 +0100 Subject: [PATCH 11/12] add logic to detect if addresses are script or key based --- scripts/action-create-tw.sh | 43 +++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/scripts/action-create-tw.sh b/scripts/action-create-tw.sh index fb46238..7741a4c 100755 --- a/scripts/action-create-tw.sh +++ b/scripts/action-create-tw.sh @@ -111,7 +111,7 @@ fi echo -e " " echo -e "${YELLOW}Creating a treasury withdrawal governance action from a given metadata file${NC}" echo -e "${CYAN}This script assumes compliance Intersect's treasury withdrawal action schema${NC}" -echo -e "${CYAN}This script assumes that CARDANO_NODE_SOCKET_PATH and CARDANO_NODE_NETWORK_ID are set${NC}" +echo -e "${CYAN}This script assumes that CARDANO_NODE_SOCKET_PATH, CARDANO_NODE_NETWORK_ID and IPFS_GATEWAY_URI are set${NC}" # Exit if socket path is not set if [ -z "$CARDANO_NODE_SOCKET_PATH" ]; then @@ -198,8 +198,6 @@ if [ ! -z "$withdrawal_address_input" ]; then fi fi -# todo: check if addresses are on the same network as local node - # use bech32 prefix to determine if addresses are mainnet or testnet is_stake_address_mainnet() { local address="$1" @@ -246,6 +244,32 @@ else fi fi +# use header byte to determine if stake address is script-based or key-based +is_stake_address_script() { + local address="$1" + + address_hex=$(cardano-cli address info --address "$address"| jq -r ".base16") + first_char="${address_hex:0:1}" + + if [ "$first_char" = "f" ]; then + return 0 # true + elif [ "$first_char" = "e" ]; then + return 1 # false + else + echo -e "${RED}Error: Invalid stake address header byte${NC}" >&2 + exit 1 + fi +} + +if [ "$withdraw_to_script" = "true" ]; then + if is_stake_address_script "$withdrawal_address"; then + echo -e "Withdrawal address is script-based" + else + echo -e "${RED}Withdrawal address is not script-based as requested, exiting.${NC}" + exit 1 + fi +fi + echo -e "${GREEN}Automatic validations passed${NC}" echo -e " " echo -e "${CYAN}Computing details${NC}" @@ -260,7 +284,6 @@ echo -e "Metadata file hash: ${YELLOW}$file_hash${NC}" ipfs_cid=$(ipfs add -Q --cid-version 1 "$input_file") echo -e "IPFS URI: ${YELLOW}ipfs://$ipfs_cid${NC}" -# todo add information about if addresses are script-based or key-based # Make user manually confirm the choices echo -e " " @@ -268,7 +291,13 @@ echo -e "${CYAN}Creating treasury withdrawal action${NC}" echo -e "Title: ${YELLOW}$title${NC}" echo -e " " echo -e "Deposit return address: ${YELLOW}$deposit_return${NC}" +if is_stake_address_script "$deposit_return"; then + echo -e "(this is a script-based address)" +else + echo -e "(this is a key-based address)" +fi +echo -e " " read -p "Do you want to proceed with this deposit return address? (yes/no): " confirm_deposit if [ "$confirm_deposit" != "yes" ]; then @@ -278,11 +307,17 @@ fi echo -e " " echo -e "Withdrawal address: ${YELLOW}$withdrawal_address${NC}" +if is_stake_address_script "$withdrawal_address"; then + echo -e "(this is a script-based address)" +else + echo -e "(this is a key-based address)" +fi ada_amount=$(echo "scale=6; $withdrawal_amount / 1000000" | bc) ada_amount_formatted=$(printf "%'0.6f" "$ada_amount") echo -e "Withdrawal amount (ada): ${YELLOW}$ada_amount_formatted${NC}" +echo -e " " read -p "Do you want to proceed with this withdrawal address and amount? (yes/no): " confirm_withdrawal if [ "$confirm_withdrawal" != "yes" ]; then From b50cae1c65017b0eb942d3a73d72ebe9ac3e6839 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Fri, 4 Jul 2025 18:14:18 +0100 Subject: [PATCH 12/12] add JSON representation --- scripts/action-create-tw.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/action-create-tw.sh b/scripts/action-create-tw.sh index 7741a4c..288bea2 100755 --- a/scripts/action-create-tw.sh +++ b/scripts/action-create-tw.sh @@ -329,7 +329,6 @@ fi echo -e " " echo -e "${CYAN}Creating action file...${NC}" - cardano-cli conway governance action create-treasury-withdrawal \ --mainnet \ --governance-action-deposit $(cardano-cli conway query gov-state | jq -r '.currentPParams.govActionDeposit') \ @@ -341,3 +340,11 @@ cardano-cli conway governance action create-treasury-withdrawal \ --transfer "$withdrawal_amount" \ --constitution-script-hash $(cardano-cli conway query constitution | jq -r '.script') \ --out-file "$input_file.action" + +echo -e "${GREEN}Action file created at "$input_file.action" ${NC}" + +echo -e " " +echo -e "${CYAN}Creating JSON representation of action file...${NC}" + +cardano-cli conway governance action view --action-file "$input_file.action" > "$input_file.action.json" +echo -e "${GREEN}JSON file created at "$input_file.action.json" ${NC}" \ No newline at end of file