2021-10-29 15:51:41 +00:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
|
|
|
# Qortal defaults
|
|
|
|
host="localhost"
|
2022-08-12 12:38:03 +00:00
|
|
|
port=12391
|
2021-10-29 15:51:41 +00:00
|
|
|
|
|
|
|
if [ -z "$*" ]; then
|
2023-06-27 20:29:10 +00:00
|
|
|
echo "Usage:"
|
2021-10-29 15:51:41 +00:00
|
|
|
echo
|
|
|
|
echo "Host/update data:"
|
2023-06-27 20:29:10 +00:00
|
|
|
echo "qdn POST [service] [name] PATH [dirpath] <identifier> <title> <description> <tags=tag1,tag2,tag3> <category> <fee> <preview (true or false)>"
|
2023-03-17 10:22:26 +00:00
|
|
|
echo "qdn POST [service] [name] STRING [data-string] <identifier>"
|
2021-10-29 15:51:41 +00:00
|
|
|
echo
|
|
|
|
echo "Fetch data:"
|
2023-03-17 10:22:26 +00:00
|
|
|
echo "qdn GET [service] [name] <identifier-or-default> <filepath-or-default> <rebuild>"
|
2021-11-12 17:42:21 +00:00
|
|
|
echo
|
|
|
|
echo "Notes:"
|
2021-11-12 18:22:10 +00:00
|
|
|
echo "- When requesting a resource, please use 'default' to indicate a file with no identifier."
|
2021-11-12 17:42:21 +00:00
|
|
|
echo "- The same applies when specifying the relative path to a file within the data structure; use 'default'"
|
|
|
|
echo " to indicate a single file resource."
|
2021-10-29 15:51:41 +00:00
|
|
|
echo
|
|
|
|
exit
|
|
|
|
fi
|
|
|
|
|
2023-06-27 20:29:10 +00:00
|
|
|
|
|
|
|
# Default ports for Qortal
|
|
|
|
mainnet_port=12391
|
|
|
|
testnet_port=62391
|
|
|
|
|
|
|
|
# Check if the '-t' operator is passed, if so change to utilizing testnet.
|
|
|
|
if [[ "$1" == "-t" ]]; then
|
|
|
|
# Use testnet port
|
|
|
|
port=$testnet_port
|
|
|
|
shift
|
|
|
|
else
|
|
|
|
# Use mainnet port
|
|
|
|
port=$mainnet_port
|
|
|
|
fi
|
|
|
|
|
2022-01-14 11:46:26 +00:00
|
|
|
script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
|
|
|
|
|
|
|
if [ -f "apikey.txt" ]; then
|
|
|
|
apikey=$(cat "apikey.txt")
|
|
|
|
elif [ -f "${script_dir}/../apikey.txt" ]; then
|
|
|
|
apikey=$(cat "${script_dir}/../apikey.txt")
|
2022-01-20 20:31:16 +00:00
|
|
|
elif [ -f "${HOME}/qortal/apikey.txt" ]; then
|
|
|
|
apikey=$(cat "${HOME}/qortal/apikey.txt")
|
2022-01-14 11:46:26 +00:00
|
|
|
fi
|
|
|
|
|
2021-10-29 15:51:41 +00:00
|
|
|
method=$1
|
|
|
|
service=$2
|
|
|
|
name=$3
|
|
|
|
|
|
|
|
if [ -z "${method}" ]; then
|
2023-06-27 20:29:10 +00:00
|
|
|
echo "Error: missing method"
|
|
|
|
exit 1
|
2021-10-29 15:51:41 +00:00
|
|
|
fi
|
|
|
|
if [ -z "${service}" ]; then
|
2023-06-27 20:29:10 +00:00
|
|
|
echo "Error: missing service"
|
|
|
|
exit 1
|
2021-10-29 15:51:41 +00:00
|
|
|
fi
|
|
|
|
if [ -z "${name}" ]; then
|
2023-06-27 20:29:10 +00:00
|
|
|
echo "Error: missing name"
|
|
|
|
exit 1
|
2021-10-29 15:51:41 +00:00
|
|
|
fi
|
|
|
|
|
2021-11-16 19:36:24 +00:00
|
|
|
if [[ "${method}" == "POST" ]]; then
|
2021-11-17 18:57:46 +00:00
|
|
|
type=$4
|
|
|
|
data=$5
|
|
|
|
identifier=$6
|
2023-06-27 20:29:10 +00:00
|
|
|
title=$7
|
|
|
|
description=$8
|
|
|
|
tags=$9
|
|
|
|
category=${10}
|
|
|
|
fee=${11}
|
|
|
|
preview=${12}
|
|
|
|
|
|
|
|
|
2021-10-29 15:51:41 +00:00
|
|
|
|
2021-11-17 18:57:46 +00:00
|
|
|
if [ -z "${data}" ]; then
|
|
|
|
if [[ "${type}" == "PATH" ]]; then
|
2023-06-27 20:29:10 +00:00
|
|
|
echo "Error: missing directory - please use a path to a directory with a SINGLE file wishing to be published"
|
|
|
|
exit 1
|
2021-11-17 18:57:46 +00:00
|
|
|
elif [[ "${type}" == "STRING" ]]; then
|
2023-06-27 20:29:10 +00:00
|
|
|
echo "Error: missing data string - please input the data string you wish to publish"
|
|
|
|
exit 1
|
2021-11-17 18:57:46 +00:00
|
|
|
else
|
2023-06-27 20:29:10 +00:00
|
|
|
echo "Error: unrecognized type"
|
|
|
|
exit 1
|
2021-11-17 18:57:46 +00:00
|
|
|
fi
|
2021-10-29 15:51:41 +00:00
|
|
|
fi
|
2021-10-29 16:24:22 +00:00
|
|
|
if [ -z "${QORTAL_PRIVKEY}" ]; then
|
2023-06-27 20:29:10 +00:00
|
|
|
echo "Error: missing private key. Set it by running: export QORTAL_PRIVKEY=privkeyhere"
|
|
|
|
exit 1
|
2021-10-29 15:51:41 +00:00
|
|
|
fi
|
|
|
|
|
2021-12-22 13:59:08 +00:00
|
|
|
if [ -z "${identifier}" ]; then
|
|
|
|
identifier="default"
|
2021-11-17 18:57:46 +00:00
|
|
|
fi
|
|
|
|
|
|
|
|
# Create type component in URL
|
|
|
|
if [[ "${type}" == "PATH" ]]; then
|
|
|
|
type_component=""
|
|
|
|
elif [[ "${type}" == "STRING" ]]; then
|
|
|
|
type_component="/string"
|
|
|
|
fi
|
2023-06-27 20:29:10 +00:00
|
|
|
|
|
|
|
# Create tags component in URL, comma-separated list of tags, will be added to the tags call.
|
|
|
|
tags_component=""
|
|
|
|
if [ -n "${tags}" ]; then
|
|
|
|
IFS=',' read -ra tag_array <<< "${tags}"
|
|
|
|
for tag in "${tag_array[@]}"; do
|
|
|
|
tags_component+="&tags=${tag}"
|
|
|
|
done
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ -z ${tags_component} ]; then
|
|
|
|
tags_component=""
|
|
|
|
echo "nothing in tags, using empty tags"
|
|
|
|
fi
|
|
|
|
|
|
|
|
#Create category component with pre-defined list of categories. Error if category is specified but not in list.
|
|
|
|
allowed_categories=("ART" "AUTOMOTIVE" "BEAUTY" "BOOKS" "BUSINESS" "COMMUNICATIONS" "CRYPTOCURRENCY" "CULTURE" "DATING" "DESIGN" "ENTERTAINMENT" "EVENTS" "FAITH" "FASHION" "FINANCE" "FOOD" "GAMING" "GEOGRAPHY" "HEALTH" "HISTORY" "HOME" "KNOWLEDGE" "LANGUAGE" "LIFESTYLE" "MANUFACTURING" "MAPS" "MUSIC" "NEWS" "OTHER" "PETS" "PHILOSOPHY" "PHOTOGRAPHY" "POLITICS" "PRODUCE" "PRODUCTIVITY" "PSYCHOLOGY" "QORTAL" "SCIENCE" "SELF_CARE" "SELF_SUFFICIENCY" "SHOPPING" "SOCIAL" "SOFTWARE" "SPIRITUALITY" "SPORTS" "STORYTELLING" "TECHNOLOGY" "TOOLS" "TRAVEL" "UNCATEGORIZED" "VIDEO" "WEATHER")
|
|
|
|
|
|
|
|
if [[ -n "$category" && ! " ${allowed_categories[@]} " =~ " $category " ]]; then
|
|
|
|
echo "Error: Invalid category. Allowed categories are: ${allowed_categories[*]} be sure to place your overall script inputs in the correct order"
|
|
|
|
exit 1
|
|
|
|
elif [ -z "$category" ]; then
|
|
|
|
category=""
|
|
|
|
echo "No category is being set"
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ -n "$fee" ]; then
|
2023-09-08 07:30:06 +00:00
|
|
|
if [[ "$fee" == "1" || "$fee" == ".01" ]]; then
|
|
|
|
fee="1000000"
|
2023-06-27 20:29:10 +00:00
|
|
|
elif [ -z "$fee" ]; then
|
|
|
|
fee=""
|
|
|
|
else
|
2023-09-08 07:30:06 +00:00
|
|
|
echo "Error: Invalid fee value. Expected '1', '.01' or no input."
|
2023-06-27 20:29:10 +00:00
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
final_fee="${fee}"
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
# check that preview is true/false
|
|
|
|
if [[ -n "$preview" && ! ( "$preview" == "true" || "$preview" == "false" ) ]]; then
|
|
|
|
echo "Error: Invalid preview value. Expected 'true' or 'false'. Please retry with boolean as preview entry."
|
|
|
|
exit 1
|
|
|
|
elif [ -z "$preview" ]; then
|
|
|
|
preview=""
|
|
|
|
fi
|
|
|
|
|
|
|
|
# Build the API URL
|
|
|
|
api_url="http://${host}:${port}/arbitrary/${service}/${name}/${identifier}${type_component}"
|
|
|
|
api_url+="?title=${title}&description=${description}&tags=${tags_component}&category=${category}&fee=${final_fee}&preview=${preview}"
|
|
|
|
|
2021-11-17 18:57:46 +00:00
|
|
|
|
2021-10-29 15:51:41 +00:00
|
|
|
echo "Creating transaction - this can take a while..."
|
2023-06-27 20:29:10 +00:00
|
|
|
tx_data=$(curl --silent --insecure -X ${method} "${api_url}" -H "accept: text/plain" -H "X-API-KEY: ${apikey}" -H "Content-Type: text/plain" -d "${data}")
|
2021-11-17 18:57:46 +00:00
|
|
|
|
2021-10-29 15:51:41 +00:00
|
|
|
if [[ "${tx_data}" == *"error"* || "${tx_data}" == *"ERROR"* ]]; then
|
2023-06-27 20:29:10 +00:00
|
|
|
echo "Error creating transaction: ${tx_data}"
|
|
|
|
exit 1
|
2021-11-17 18:57:46 +00:00
|
|
|
elif [ -z "${tx_data}" ]; then
|
2023-06-27 20:29:10 +00:00
|
|
|
echo "Error: no transaction data returned"
|
|
|
|
exit 1
|
2021-10-29 15:51:41 +00:00
|
|
|
fi
|
|
|
|
|
2021-12-03 17:33:07 +00:00
|
|
|
echo "Computing nonce..."
|
2022-01-14 11:46:26 +00:00
|
|
|
computed_tx_data=$(curl --silent --insecure -X POST "http://${host}:${port}/arbitrary/compute" -H "Content-Type: application/json" -H "X-API-KEY: ${apikey}" -d "${tx_data}")
|
2023-06-27 20:29:10 +00:00
|
|
|
|
2021-12-03 17:33:07 +00:00
|
|
|
if [[ "${computed_tx_data}" == *"error"* || "${computed_tx_data}" == *"ERROR"* ]]; then
|
2023-06-27 20:29:10 +00:00
|
|
|
echo "Error computing nonce: ${computed_tx_data}"
|
|
|
|
exit 1
|
2021-12-03 17:33:07 +00:00
|
|
|
fi
|
|
|
|
|
2021-10-29 15:51:41 +00:00
|
|
|
echo "Signing..."
|
2021-12-03 17:33:07 +00:00
|
|
|
signed_tx_data=$(curl --silent --insecure -X POST "http://${host}:${port}/transactions/sign" -H "Content-Type: application/json" -d "{\"privateKey\":\"${QORTAL_PRIVKEY}\",\"transactionBytes\":\"${computed_tx_data}\"}")
|
2023-06-27 20:29:10 +00:00
|
|
|
|
2021-10-29 15:51:41 +00:00
|
|
|
if [[ "${signed_tx_data}" == *"error"* || "${signed_tx_data}" == *"ERROR"* ]]; then
|
2023-06-27 20:29:10 +00:00
|
|
|
echo "Error signing transaction: ${signed_tx_data}"
|
|
|
|
exit 1
|
2021-10-29 15:51:41 +00:00
|
|
|
fi
|
|
|
|
|
|
|
|
echo "Broadcasting..."
|
|
|
|
success=$(curl --silent --insecure -X POST "http://${host}:${port}/transactions/process" -H "Content-Type: text/plain" -d "${signed_tx_data}")
|
2023-06-27 20:29:10 +00:00
|
|
|
|
2021-10-29 15:51:41 +00:00
|
|
|
if [[ "${success}" == "true" ]]; then
|
|
|
|
echo "Transaction broadcast successfully"
|
|
|
|
else
|
|
|
|
echo "Error when broadcasting transaction. Please try again."
|
2021-10-29 16:26:40 +00:00
|
|
|
echo "Response: ${success}"
|
2021-10-29 15:51:41 +00:00
|
|
|
fi
|
|
|
|
|
|
|
|
elif [[ "${method}" == "GET" ]]; then
|
2021-11-12 17:42:21 +00:00
|
|
|
identifier=$4
|
|
|
|
filepath=$5
|
|
|
|
rebuild=$6
|
2021-10-29 15:51:41 +00:00
|
|
|
|
|
|
|
if [ -z "${rebuild}" ]; then
|
|
|
|
rebuild="false"
|
|
|
|
fi
|
|
|
|
|
2021-11-12 17:42:21 +00:00
|
|
|
# Handle default
|
|
|
|
if [[ "${filepath}" == "default" ]]; then
|
|
|
|
filepath=""
|
|
|
|
fi
|
|
|
|
|
|
|
|
# We use a different API depending on whether or not an identifier is supplied
|
|
|
|
if [ -n "${identifier}" ]; then
|
2022-01-14 11:46:26 +00:00
|
|
|
response=$(curl --silent --insecure -X GET "http://${host}:${port}/arbitrary/${service}/${name}/${identifier}?rebuild=${rebuild}&filepath=${filepath}" -H "X-API-KEY: ${apikey}")
|
2021-11-12 17:42:21 +00:00
|
|
|
else
|
2022-01-14 11:46:26 +00:00
|
|
|
response=$(curl --silent --insecure -X GET "http://${host}:${port}/arbitrary/${service}/${name}?rebuild=${rebuild}&filepath=${filepath}" -H "X-API-KEY: ${apikey}")
|
2021-11-12 17:42:21 +00:00
|
|
|
fi
|
|
|
|
|
2021-10-29 17:58:59 +00:00
|
|
|
if [ -z "${response}" ]; then
|
|
|
|
echo "Empty response from ${host}:${port}"
|
|
|
|
fi
|
2021-10-29 15:51:41 +00:00
|
|
|
if [[ "${response}" == *"error"* || "${response}" == *"ERROR"* ]]; then
|
2023-06-27 20:29:10 +00:00
|
|
|
echo "${response}"
|
|
|
|
exit 1
|
2021-10-29 15:51:41 +00:00
|
|
|
fi
|
|
|
|
|
2021-10-29 17:52:05 +00:00
|
|
|
echo "${response}"
|
2021-10-29 15:51:41 +00:00
|
|
|
fi
|
2023-06-27 20:29:10 +00:00
|
|
|
|