diff --git a/charts/akash-provider/scripts/price_script_generic.sh b/charts/akash-provider/scripts/price_script_generic.sh index 55a45f69..668c9982 100755 --- a/charts/akash-provider/scripts/price_script_generic.sh +++ b/charts/akash-provider/scripts/price_script_generic.sh @@ -2,7 +2,7 @@ # WARNING: the runtime of this script should NOT exceed 5 seconds! (Perhaps can be amended via AKASH_BID_PRICE_SCRIPT_PROCESS_TIMEOUT env variable) # Requirements: # curl jq bc mawk ca-certificates -# Version: Aug-14-2023 +# Version: Aug-16-2023 set -o pipefail # Example: @@ -23,21 +23,11 @@ if ! [[ -z $WHITELIST_URL ]]; then fi if ! grep -qw "$AKASH_OWNER" $WHITELIST; then - echo "$AKASH_OWNER is not whitelisted" >&2 + echo -n "$AKASH_OWNER is not whitelisted" >&2 exit 1 fi fi -data_in=$(jq .) -# Pull the pricing data from the deployment request -price=$(echo "$data_in" | jq -r '.price? // empty') - -## DEBUG -if ! [[ -z $DEBUG_BID_SCRIPT ]]; then - echo "$(TZ=UTC date -R)" >> /tmp/${AKASH_OWNER}.log - echo "$data_in" >> /tmp/${AKASH_OWNER}.log -fi - function get_akt_price { # cache AKT price for 60 minutes to reduce the API pressure as well as to slightly accelerate the bidding (+5s) CACHE_FILE=/tmp/aktprice.cache @@ -55,34 +45,56 @@ function get_akt_price { # check price is an integer/floating number re='^[0-9]+([.][0-9]+)?$' if ! [[ $usd_per_akt =~ $re ]]; then - echo "$usd_per_akt is not an integer/floating number!" >&2 + echo -n "$usd_per_akt is not an integer/floating number!" >&2 exit 1 fi # make sure price is in the permitted range if ! (( $(echo "$usd_per_akt > 0" | bc -l) && \ $(echo "$usd_per_akt <= 1000000" | bc -l) )); then - echo "$usd_per_akt is outside the permitted range (>0, <=1000000)" >&2 + echo -n "$usd_per_akt is outside the permitted range (>0, <=1000000)" >&2 exit 1 fi echo "$usd_per_akt" > $CACHE_FILE fi - # TODO: figure some sort of monitoring to inform the provider in the event API breaks + # TODO: figure some monitoring to inform the provider in the event API breaks fi - # Fail if script can't read CACHE_FILE for some reason + # Fail if the script can't read CACHE_FILE for some reason set -e usd_per_akt=$(cat $CACHE_FILE) echo $usd_per_akt set +e } + +# bid script starts reading the deployment order request specs here (passed by the Akash Provider) +data_in=$(jq .) + +## DEBUG +if ! [[ -z $DEBUG_BID_SCRIPT ]]; then + echo "$(TZ=UTC date -R)" >> /tmp/${AKASH_OWNER}.log + echo "$data_in" >> /tmp/${AKASH_OWNER}.log +fi + +# Pull the pricing data from the deployment request +hasPrice=$(echo "$data_in" | jq -r 'has("price")?') + +# default price precision to 6 (for backward compatibility) +precision=$(jq -r '.price_precision? // 6' <<<"$data_in") + # If the price parameter is set, new rate calculations will be used -# otherwise, the original rate calculations will be used (for backwards compatibility) -if ! [[ -z "$price" ]]; then - isDenom=true +# otherwise, the original rate calculations will be used (for backward compatibility) +if [[ "$hasPrice" == true ]]; then + isObject=$(jq -r 'if .price?|type == "object" then true else false end' <<<"$data_in") + if [[ "$isObject" != true ]]; then + echo -n "price must be an object! make sure you are using the latest akash-provider." >&2 + exit 1 + fi + denom=$(jq -r '.price.denom' <<<"$data_in") + amount=$(jq -r '.price.amount' <<<"$data_in") # strip off the .price by setting data_in to .resources data_in=$(echo "$data_in" | jq -r '.resources') @@ -145,38 +157,33 @@ total_cost_akt_target=$(bc -l <<<"(${total_cost_usd_target}/$usd_per_akt)") total_cost_uakt_target=$(bc -l <<<"(${total_cost_akt_target}*1000000)") rate_per_block_uakt=$(bc -l <<<"(${total_cost_uakt_target}/${blocks_a_month})") rate_per_block_usd=$(bc -l <<<"(${total_cost_usd_target}/${blocks_a_month})") -total_cost_uakt="$(printf "%.18f" $rate_per_block_uakt)" +total_cost_uakt="$(printf "%.*f" $precision $rate_per_block_uakt)" # NOTE: max_rate_usd, max_rate_uakt = are per block rates ! -if [[ $isDenom = true ]]; then - denom=$(echo '{"price":"'$price'"}' | jq -r '.price | capture("^[0-9]*\\.?[0-9]*(?.*)") | .denom') - - case "$price" in - - *"uakt") - max_rate_uakt=$(echo '{"price":"'$price'"}' | jq -r '.price | gsub("[^0-9.]"; "")') +if [[ $hasPrice = true ]]; then + case "$denom" in + "uakt") # Hint: bc <<< "$a > $b" (if a is greater than b, it will return 1, otherwise 0) - if bc <<< "$rate_per_block_uakt > $max_rate_uakt" | grep -qw 1; then - printf "requested rate is too low. min expected %.18f%s" "$rate_per_block_uakt" "$denom" >&2 + if bc <<< "$rate_per_block_uakt > $amount" | grep -qw 1; then + printf "requested rate is too low. min expected %.*f%s" "$precision" "$rate_per_block_uakt" "$denom" >&2 exit 1 fi # tell the provider uakt/block rate - echo $total_cost_uakt + printf "%.*f" "$precision" "$total_cost_uakt" ;; # sandbox: Axelar USDC - *"ibc/12C6A0C374171B595A0A9E18B83FA09D295FB1F2D8C6DAA3AC28683471752D84") - max_rate_usd=$(echo '{"price":"'$price'"}' | jq -r '.price | gsub("[^0-9.]"; "")') - rate_per_block_usd_normalized=$(bc -l <<<"(${rate_per_block_usd}*1000000)" | awk '{printf "%.18f", $0}') - if bc <<< "$rate_per_block_usd_normalized > $max_rate_usd" | grep -qw 1; then - printf "requested rate is too low. min expected %.18f%s" "$rate_per_block_usd_normalized" "$denom" >&2 + "ibc/12C6A0C374171B595A0A9E18B83FA09D295FB1F2D8C6DAA3AC28683471752D84") + rate_per_block_usd_normalized=$(bc -l <<<"(${rate_per_block_usd}*1000000)" | awk -v precision="$precision" '{printf "%.*f", precision, $0}') + if bc <<< "$rate_per_block_usd_normalized > $amount" | grep -qw 1; then + printf "requested rate is too low. min expected %.*f%s" "$precision" "$rate_per_block_usd_normalized" "$denom" >&2 exit 1 fi # tell the provider usd/block rate - echo $rate_per_block_usd_normalized + printf "%.*f" "$precision" "$rate_per_block_usd_normalized" ;; *) @@ -188,6 +195,5 @@ if [[ $isDenom = true ]]; then else # provider only accepts rate in uakt/block when no price is received in structure (backwards compatibility) - echo $total_cost_uakt + printf "%.f" "$total_cost_uakt" fi -