Optional parameter why insert always ?

Hi, i have this part of code

response=""
 
 _ByBit_PlaceOrder(){

	local apiUrl=""
	 
	RECVWINDOW=5000
	TIMESTAMP=$(($(date +%s%N)/1000000))
		
	# Imposta il tuo timestamp all'interno della finestra di ricezione
    local TIMESTAMP_INSIDE_WINDOW=$((TIMESTAMP + RECVWINDOW))

    # Confronta con il timestamp corrente
    if [ "$TIMESTAMP_INSIDE_WINDOW" -gt "$TIMESTAMP" ]; then
        local URLPART2="", whichapi="", category="", symbol="", isleverage="", side="", ordertype="", qty="", marketunit="", price="", triggerdirection=""
        local orderfilter="", triggerprice="", orederiv="", timeinforce="", positionidx="", orderlinkid="", takeprofit="", stoploss="", tptriggerby="", sltriggerby=""
        local reduceonly="", closeontrigger="", smptype="", mmp="", tpslmode="", tplimitprice="", sllimitprice="", tpordertype="", slordertype=""
 
        # Leggi i parametri della funzione
        while [ "$#" -gt 0 ]; do
            case "$1" in
                "--which-api" )
                    shift
                    whichapi="$1"
                    ;;
                "--category" )
                    shift
                    category="$1"
                    ;;
                "--symbol" )
                    shift
                    symbol="$1"
                    ;;
                "--is-leverage" )
                    shift
                    isleverage="$1"
                    ;;
                "--side" )
                    shift
                    side="$1"
                    ;;
                "--order-type" )
                    shift
                    ordertype="$1"
                    ;;
                "--qty" )
                    shift
                    qty="$1"
                    ;;
                "--market-unit" )
                    shift
                    marketunit="$1"
                    ;;
                "--price" )
                    shift
                    price="$1"
                    ;;
                "--trigger-direction" )
                    shift
                    triggerdirection="$1"
                    ;;
                "--order-filter" )
                    shift
                    orderfilter="$1"
                    ;;
                "--trigger-price" )
                    shift
                    triggerprice="$1"
                    ;;
                "--trigger-by" )
                    shift
                    triggerby="$1"
                    ;;
                "--oreder-iv" )
                    shift
                    orederiv="$1"
                    ;;
                "--time-in-force" )
                    shift
                    timeinforce="$1"
                    ;;
                "--position-idx" )
                    shift
                    positionidx="$1"
                    ;;
                "--order-link-id" )
                    shift
                    orderlinkid="$1"
                    ;;
                "--take-profit" )
                    shift
                    takeprofit="$1"
                    ;;
                "--sttop-loss" )
                    shift
                    stoploss="$1"
                    ;;
                "--tp-trigger-by" )
                    shift
                    tptriggerby="$1"
                    ;;
                "--sl-trigger-by" )
                    shift
                    sltriggerby="$1"
                    ;;
                "--reduce-only" )
                    shift
                    reduceonly="$1"
                    ;;
                "--close-on-trigger" )
                    shift
                    closeontrigger="$1"
                    ;;
                "--smp-type" )
                    shift
                    smptype="$1"
                    ;;
                "--mmp" )
                    shift
                    mmp="$1"
                    ;;
                "--tpsl-mode" )
                    shift
                    tpslmode="$1"
                    ;;
                "--tp-limit-price" )
                    shift
                    tplimitprice="$1"
                    ;;
                "--sl-limit-price" )
                    shift
                    sllimitprice="$1"
                    ;;
                "--tp-order-type" )
                    shift
                    tpordertype="$1"
                    ;;
                "--sl-order-type" )
                    shift
                    slordertype="$1"
                    ;;
                * )
                    echo "Errore: Parametro non riconosciuto: $1"
                    return 1
                    ;;
            esac
            shift
        done
        
       _Init_BYBIT_ApiSecretIDData "$gApiTypo"  
            
    if [ "$whichapi" == "sand_bybit" ]; then
		ApiUrl="https://api-testnet.bybit.com/"
		_Init_BYBIT_ApiSecretIDData "sand_bybit"
	elif [ "$whichapi" == "bybit" ]; then
		ApiUrl="https://api.bybit.com/"
		_Init_BYBIT_ApiSecretIDData "bybit"
	fi
		
		
	 apiUrl="${ApiUrl}v5/order/create"

        # Verifica se i parametri obbligatori sono presenti
        if [ -z "$category" ] || [ -z "$symbol" ] [ -z "$side" ] || [ -z "$ordertype" ]|| [ -z "$qty" ]; then
            echo "Errore: I parametri --symbol, --category --side  --oreder-type --qty sono obbligatori"
            return 1
        fi
	
	#URLPART2="{\"category\":\"$category\",\"symbol\":\"$symbol\",\"side\":\"$side\",\"positionIdx\":$positionidx,\"orderType\":\"$ordertype\",\"qty\":\"$qty\",\"price\":\"$price\",\"timeInForce\":\"$timeinforce\",\"orderLinkId\":\"$orderlinkid\"}"
	
	 # Costruisci la variabile URLPART2 in base ai parametri opzionali forniti
		URLPART2="{\"category\":\"$category\",\"symbol\":\"$symbol\",\"side\":\"$side\",\"orderType\":\"$ordertype\",\"qty\":\"$qty\""

		# Aggiungi parametri opzionali solo se sono presenti e non vuoti
		[ -n "$isleverage" ] && URLPART2+=",\"isLeverage\":$isleverage"
		[ -n "$marketunit" ] && URLPART2+=",\"marketUnit\":\"$marketunit\""
		[ -n "$price" ] && URLPART2+=",\"price\":\"$price\""
		[ -n "$triggerdirection" ] && URLPART2+=",\"triggerDirection\":$triggerdirection"
		[ -n "$orderfilter" ] && URLPART2+=",\"orderFilter\":\"$orderfilter\""
		[ -n "$triggerprice" ] && URLPART2+=",\"triggerPrice\":\"$triggerprice\""
		[ -n "$triggerby" ] && URLPART2+=",\"triggerBy\":\"$triggerby\""
		[ -n "$orederiv" ] && URLPART2+=",\"oreDeriv\":\"$orederiv\""
		[ -n "$timeinforce" ] && URLPART2+=",\"timeInForce\":\"$timeinforce\""
		[ -n "$positionidx" ] && URLPART2+=",\"positionIdx\":$positionidx"
		[ -n "$orderlinkid" ] && URLPART2+=",\"orderLinkId\":\"$orderlinkid\""
		[ -n "$takeprofit" ] && URLPART2+=",\"takeProfit\":\"$takeprofit\""
		[ -n "$stoploss" ] && URLPART2+=",\"stopLoss\":\"$stoploss\""
		[ -n "$tptriggerby" ] && URLPART2+=",\"tpTriggerBy\":\"$tptriggerby\""
		[ -n "$sltriggerby" ] && URLPART2+=",\"slTriggerBy\":\"$sltriggerby\""
		[ -n "$reduceonly" ] && URLPART2+=",\"reduceOnly\":$reduceonly"
		[ -n "$closeontrigger" ] && URLPART2+=",\"closeOnTrigger\":$closeontrigger"
		[ -n "$smptype" ] && URLPART2+=",\"smpType\":\"$smptype\""
		[ -n "$mmp" ] && URLPART2+=",\"mmp\":$mmp"
		[ -n "$tpslmode" ] && URLPART2+=",\"tpslMode\":\"$tpslmode\""
		[ -n "$tplimitprice" ] && URLPART2+=",\"tpLimitPrice\":\"$tplimitprice\""
		[ -n "$sllimitprice" ] && URLPART2+=",\"slLimitPrice\":\"$sllimitprice\""
		[ -n "$tpordertype" ] && URLPART2+=",\"tpOrderType\":\"$tpordertype\""
		[ -n "$slordertype" ] && URLPART2+=",\"slOrderType\":\"$slordertype\""

		URLPART2="$URLPART2}"

	echo "$URLPART2"
	
	ORIGINAL_STRING="${TIMESTAMP}${BYBITApiKey}${RECVWINDOW}${URLPART2}"
			# Calcola la firma HMAC
	SIGNATURE=$(echo -n "$ORIGINAL_STRING" | openssl dgst -sha256 -hmac "$BYBITSecretKey" | cut -c 18-)


	response=$(curl --location --request POST 'https://api-testnet.bybit.com/v5/order/create' \
	--header 'X-BAPI-SIGN-TYPE: 2' \
	--header 'X-BAPI-SIGN: '${SIGNATURE} \
	--header 'X-BAPI-API-KEY: '${BYBITApiKey} \
	--header 'X-BAPI-TIMESTAMP: '${TIMESTAMP}  \
	--header 'X-BAPI-RECV-WINDOW: 5000' \
	--header 'Content-Type: application/json' \
	--data-raw "${URLPART2}")

		echo "$response"
	else
        echo "Errore: Il timestamp corretto รจ al di fuori della finestra di ricezione."
        return 1
    fi
}

_Initialize_Api_ByBit --api-typo "sand_bybit" 
_ByBit_PlaceOrder --category "linear" --symbol "BTCUSDT"  --side "Buy" --position-idx "0" --order-type "Limit" --qty "0.001" --price "10000" --time-in-force "GTC" --order-link-id "TEST1234"

the problem is when i call the function return me this error

/BYBIT_TEST.sh: line 227: [: too many arguments
{"category":"linear","symbol":"BTCUSDT","side":"Buy","orderType":"Limit","qty":"0.001","isLeverage":",","marketUnit":",","price":"10000","orderFilter":",","triggerPrice":",","oreDeriv":",","timeInForce":"GTC","positionIdx":"0","orderLinkId":"TEST1234","takeProfit":",","stopLoss":",","tpTriggerBy":",","reduceOnly":",","closeOnTrigger":",","smpType":",","mmp":",","tpslMode":",","tpLimitPrice":",","slLimitPrice":",","tpOrderType":","}
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   537  100   102  100   435    151    645 --:--:-- --:--:-- --:--:--   797
{"retCode":10001,"retMsg":"Request parameter error.","result":{},"retExtInfo":{},"time":1709633449038}
also inserts empty optional parameters o_O

i tryed also with if

if [ -n "$isleverage" ]; then
    URLPART2+=",\"isLeverage\":$isleverage"
fi

if [ -n "$marketunit" ]; then
    URLPART2+=",\"marketUnit\":\"$marketunit\""
fi
but return the same effect.. some idea?

@faustf , Welcome, Run your script through the shellcheck https://www.shellcheck.net
utility and check the results from that, then address any issues raised.

shellcheck t.bash 

In t.bash line 151:
       _Init_BYBIT_ApiSecretIDData "$gApiTypo"
                                    ^-------^ SC2154: gApiTypo is referenced but not assigned.


In t.bash line 162:
	 apiUrl="${ApiUrl}v5/order/create"
         ^----^ SC2034: apiUrl appears unused. Verify use (or export if used externally).


In t.bash line 205:
	ORIGINAL_STRING="${TIMESTAMP}${BYBITApiKey}${RECVWINDOW}${URLPART2}"
                                     ^------------^ SC2154: BYBITApiKey is referenced but not assigned.


In t.bash line 207:
	SIGNATURE=$(echo -n "$ORIGINAL_STRING" | openssl dgst -sha256 -hmac "$BYBITSecretKey" | cut -c 18-)
                                                                             ^-------------^ SC2154: BYBITSecretKey is referenced but not assigned.


In t.bash line 212:
	--header 'X-BAPI-SIGN: '${SIGNATURE} \
                                ^----------^ SC2086: Double quote to prevent globbing and word splitting.

Did you mean: 
	--header 'X-BAPI-SIGN: '"${SIGNATURE}" \


In t.bash line 213:
	--header 'X-BAPI-API-KEY: '${BYBITApiKey} \
                                   ^------------^ SC2086: Double quote to prevent globbing and word splitting.

Did you mean: 
	--header 'X-BAPI-API-KEY: '"${BYBITApiKey}" \

For more information:
  https://www.shellcheck.net/wiki/SC2034 -- apiUrl appears unused. Verify use...
  https://www.shellcheck.net/wiki/SC2154 -- BYBITApiKey is referenced but not...

Usually the error happens if a $variable is not in " " so the shell splits it into words or even matches it to files.
Go for the shellcheck suggestion after "Did you mean"!

A space is required between ] and ||

A comma is not a separator; it will be appended to the "" and assigned to the variables.
I think you want all variables empty:

local URLPART2="" whichapi="" category="" symbol="" isleverage="" side="" ordertype="" qty="" marketunit="" price="" triggerdirection=""

thanks so much for this super tools

super god bless youuuuuu , thanks so much :kissing_heart:

Using shellcheck to find and fix all its diagnostics is always helpful. However, it does not show any obvious syntax issues. The two SC2086 errors may be inserting unquoted syntax elements though.

It is throwing an error on line 227, the last line. It does that because it only discovers at EOF that you have an unbalanced [ ... ] construct that started somewhere in the preceding 226 lines. In that situation, error messages usually have little meaning, because so much other syntax has been processed on the way through.

I am somewhat suspicious of line 164:

if [ -z "$category" ] || [ -z "$symbol" ] [ -z "$side" ] || [ -z "$ordertype" ]|| [ -z "$qty" ]; then

There is a missing || between two of the tests, and inconsistent spacing around the final ||.

The structure leaves a lot to be desired. Smaller functions would be more testable and localise the scope of variables. There is a lot of repetition which could be avoided using arrays and/or case statements. (In particular, setting up an associative array indexed by the option names of the parameters would be useful both in storing the option values and in constructing URLPART2.)

I assume you did not write the whole thing at once before testing any of it. Do you have any previous versions which you can compare to find where the issue was introduced?

One debug method would be to append groups of lines to a new source (starting from a skeleton of the main function), and see which addition first raises the problem.

yea thank is ther the problem i just fixed thank so much for your help :smiley: