Skip to content

Commit

Permalink
fix: parse price object in price_script_generic.sh (#216)
Browse files Browse the repository at this point in the history
* fix: parse price object in price_script_generic.sh

* fix(bid-script): improved price object parsing and validation

* fix(bid-script): use price_precision

---------

Co-authored-by: Andrey Arapov <[email protected]>
  • Loading branch information
troian and andy108369 authored Aug 16, 2023
1 parent 7888545 commit 2146854
Showing 1 changed file with 44 additions and 38 deletions.
82 changes: 44 additions & 38 deletions charts/akash-provider/scripts/price_script_generic.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
Expand All @@ -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')
Expand Down Expand Up @@ -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>.*)") | .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"
;;

*)
Expand All @@ -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

0 comments on commit 2146854

Please sign in to comment.