import requests
import json
import hmac
import hashlib
import base64
import string
import random
import time

#base_url = "https://test.zeuscasinovip.com/api/ezugi/live_casino/v1/"
base_url = "https://casino-administracion.com/api/ezugi/live_casino/v1/"
ezugi_url = "https://playint.tableslive.com/auth/"
secret_key = "CHANGE-ME"
operator_id = "10907001"
uid=""
launch_token = "2gjPo8dL5heqmpGIYZQdZZYiVHgq"
session_token=""
debit_transaction_id=""
credit_transaction_id=""
rollback_transaction_id=""

username=""
password=""

#use bitflags
test_results=0
test_data = {
    "test_1" : {
        "name" : "Authentication",
        "request" : {},
        "response" : {}
    },
    "test_2" : {
        "name" : "Repeated Authentication",
        "request" : {},
        "response" : {}
    },
    "test_3" : {
        "name" : "Debit",
        "request" : {},
        "response" : {}
    },
    "test_4" : {
        "name" : "Retry for Debit",
        "request" : {},
        "response" : {}
    },
    "test_5" : {
        "name" : "Rollback",
        "request" : {},
        "response" : {}
    },
    "test_6" : {
        "name" : "Retry for rollback",
        "request" : {},
        "response" : {}
    },
    "test_7" : {
        "name" : "Rollback before debit",
        "request" : {},
        "response" : {}
    },
    "test_8" : {
        "name" : "Debit after rollback",
        "request" : {},
        "response" : {}
    },
    # HERE
    "test_9" : { 
        "name" : "Credit",
        "request" : {},
        "response" : {}
    },
    "test_10" : {
        "name" : "Retry for Credit",
        "request" : {},
        "response" : {}
    },
    "test_11" : {
        "name" : "Credit with amount 0",
        "request" : {},
        "response" : {}
    },
    "test_12" : {
        "name" : "Insuficient funds",
        "request" : {},
        "response" : {}
    },
    "test_13" : {
        "name" : "Debit with wrong token",
        "request" : {},
        "response" : {}
    },
    "test_14" : {
        "name" : "Debit from an unknown user",
        "request" : {},
        "response" : {}
    },
    "test_15" : {
        "name" : "Debit with negative amount",
        "request" : {},
        "response" : {}
    },
    "test_16" : {
        "name" : "Debit all player's balance",
        "request" : {},
        "response" : {}
    },
    "test_17" : {
        "name" : "Return reason 1 in Credit call (Cancel bet)",
        "request" : {},
        "response" : {}
    },
    "test_18" : {
        "name" : "Return reason 2 in Credit call (Cancel round)",
        "request" : {},
        "response" : {}
    },
    "test_19" : {
        "name" : "Rollback with wrong amount",
        "request" : {},
        "response" : {}
    },
    "test_20" : {
        "name" : "Credit without debitTransactionId key",
        "request" : {},
        "response" : {}
    },
    "test_21" : {
        "name" : "Credit without debitTransactionId value",
        "request" : {},
        "response" : {}
    },
    "test_22" : {
        "name" : "Credit with debitTransactionId which never was processed",
        "request" : {},
        "response" : {}
    },
    "test_23" : {
        "name" : "Credit with debitTransactionId which already was processed",
        "request" : {},
        "response" : {}
    },
    "test_24" : {
        "name" : "Invalid Bet Type Case",
        "request" : {},
        "response" : {}
    },
    "test_25" : {
        "name" : "Unknown Game ID Case",
        "request" : {},
        "response" : {}
    },
    "test_26" : {
        "name" : "Invalid HASH Case",
        "request" : {},
        "response" : {}
    },
}


def allOnes(to_test: int, size: int) -> bool:
    return to_test == (1 << size) - 1

def is_json(myjson):
  try:
    json.loads(myjson)
  except ValueError as e:
    return False
  return True

def test_hmac(secretKey, stringData):
    return base64.b64encode(hmac.new(secretKey.encode(), stringData.encode(), hashlib.sha256).digest()).decode('utf-8')

def get_current_timestamp():
    return int(time.time())

def generate_transaction_id():
    return ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(30))

def generate_base64_encoded_hmac(jsonData, secretKey):
    #print("DEBUG: " + json.dumps(jsonData, separators=(',', ':')) + "\n")
    return base64.b64encode(hmac.new(str(secretKey).encode(), (json.dumps(jsonData, separators=(',', ':'))).encode(), hashlib.sha256).digest()).decode('utf-8')

def pretty_json(jsonData):
    return json.dumps(jsonData, indent=2)

def launch():
    global launch_token
    global secret_key
    global username
    global password
    # The API endpoint
    
    url = base_url + "launch"

    data = {
        "username": username,
        "password": password
    }

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)
    json_response = response.json()

    if 'token' in json_response:
        print("Saving launch token")
        launch_token = json_response.get('token')
        # Print the response
    return json_response

def auth():
    global session_token
    global secret_key
    global operator_id
    global launch_token
    global uid
    # The API endpoint
    
    url = base_url + "auth"

    data = {
        "platformId": 0,
        "operatorId": operator_id,
        "token": launch_token,
        "timestamp": get_current_timestamp()
    }

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)
    

    json_response = response.json()
    if 'token' in json_response:
        print("Saving session token")
        session_token = json_response.get('token')
        # Print the response
    if 'uid' in json_response:
        print('Saving UID')
        uid = json_response.get('uid')

    return json_response

def rollback():
    global session_token
    global secret_key
    global debit_transaction_id
    global rollback_transaction_id
    global operator_id
    global uid
    # The API endpoint
    
    if rollback_transaction_id and debit_transaction_id and debit_transaction_id != rollback_transaction_id:
        rollback_transaction_id = debit_transaction_id
    elif not rollback_transaction_id and debit_transaction_id:
        rollback_transaction_id = debit_transaction_id
    else:
        rollback_transaction_id = generate_transaction_id()

    url = base_url + "rollback"

    data = {
         "operatorId": operator_id,
         "uid": uid,
         "transactionId": rollback_transaction_id,
         "gameId": 3,
         "token": session_token,
         "rollbackAmount": 10,
         "betTypeID": "1",
         "serverId": 102,
         "roundId": 94520713,
         "currency": "ARS",
         "platformId": 0,
         "tableId": 1,
         "timestamp": get_current_timestamp()
    }

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)
    
    json_response = response.json()
    return json_response


def debit():
    global session_token
    global secret_key
    global debit_transaction_id
    global operator_id
    global uid
    # The API endpoint
    
    if rollback_transaction_id and debit_transaction_id != rollback_transaction_id:
        debit_transaction_id = rollback_transaction_id
    else:
        debit_transaction_id = generate_transaction_id()

    url = base_url + "debit"

    data = {
        "gameId": 3,
        "debitAmount": 10,
        "platformId": 0,
        "serverId": 102,
        "transactionId": debit_transaction_id,
        "token": session_token,
        "uid": uid,
        "betTypeID": "1",
        "tableId": 1,
        "currency": "ARS",
        "operatorId": operator_id,
        "roundId": 94520713,
        "timestamp": get_current_timestamp()
    }

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)
    
    json_response = response.json()
    return json_response

def getNewToken():
    global session_token
    global secret_key
    global operator_id
    global uid

    # The API endpoint
    
    url = base_url + "getNewToken"

    data = {
        "currentToken": session_token,
        "gameId": 3,
        "uid": uid,
        "tableId": 1,
        "operatorId": operator_id,
        "timestamp": get_current_timestamp()
    }

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)
    
    json_response = response.json()

    if 'token' in json_response:
        session_token = json_response.get('token')

    return json_response



def credit():
    global session_token
    global secret_key
    global debit_transaction_id
    global credit_transaction_id
    global operator_id
    global uid
    # The API endpoint
    
    credit_transaction_id = generate_transaction_id()

    url = base_url + "credit"

    data = {
        "gameId": 3,
        "debitTransactionId": debit_transaction_id,
        "isEndRound": True,
        "creditIndex": "1|1",
        "platformId": 0,
        "serverId": 102,
        "transactionId": credit_transaction_id,
        "token": session_token,
        "uid": uid,
        "returnReason": 0,
        "betTypeID": "1",
        "tableId": 1,
        "currency": "ARS",
        "creditAmount": 15.00,
        "operatorId": operator_id,
        "roundId": 94520713,
        "timestamp": get_current_timestamp()
    }

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)
    
    json_response = response.json()
    return json_response


################
# EZUGI TESTS #
################

def api_test_1():
    global test_results
    global secret_key
    global operator_id
    global launch_token
    global test_data
    # The API endpoint
    
    url = base_url + "auth"

    data = {
        "platformId": 1,
        "operatorId": operator_id,
        "token": launch_token,
        "timestamp": get_current_timestamp()
    }

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)

    json_response = response.json()

    test_data["test_1"]["request"] = data
    test_data["test_1"]["response"] = json_response

    if 'token' in json_response:
        session_token = json_response.get('token')
    if 'uid' in json_response:
        uid = json_response.get('uid')
    
    #Verify TEST SUCCESS

    test_success = True

    if not 'token' in json_response:
        test_success = False
    elif (not 'operatorId' in json_response) or (json_response.get('operatorId') != operator_id):
        test_success = False
    elif (not 'playerTokenAtLaunch' in json_response) or (json_response.get('playerTokenAtLaunch') != launch_token):
        test_success = False
    elif (not 'errorCode' in json_response) or (json_response.get('errorCode') != 0):
        test_success = False

    res = "REQUEST:\n" + pretty_json(data) + "\n\nRESPONSE:\n" + pretty_json(json_response) + "\n"

    if test_success:
        test_results |= 0b1
        res = "==== AUTHENTICATION TEST SUCCESS ====\n\n" + res + "==== AUTHENTICATION TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b1
        res = "==== AUTHENTICATION TEST FAILED  ====\n\n" + res + "==== AUTHENTICATION TEST FAILED ====\n\n"
    
    #res = "{0:b}".format(test_results)
    return res


def api_test_2():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 1):
        return "Need to pass previous tests"

    local_data = test_data["test_1"]["response"]

    # The API endpoint
    
    url = base_url + "auth"

    data = test_data["test_1"]["request"]

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)

    json_response = response.json()


    test_data["test_2"]["request"] = data
    test_data["test_2"]["response"] = json_response

    #Verify TEST SUCCESS

    test_success = True

    if (not 'operatorId' in json_response) or (json_response.get('operatorId') != local_data["operatorId"]):
        test_success = False
    elif (not 'errorCode' in json_response) or (json_response.get('errorCode') != 6):
        test_success = False
    elif (not 'errorDescription' in json_response) or (json_response.get('errorDescription') != 'Token not found.'):
        test_success = False


    res = "REQUEST:\n" + pretty_json(data) + "\n\nRESPONSE:\n" + pretty_json(json_response) + "\n"

    if test_success:
        test_results |= 0b10
        res = "==== REPEATED AUTHENTICATION TEST SUCCESS ====\n\n" + res + "==== REPEATED AUTHENTICATION TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b10
        res = "==== REPEATED AUTHENTICATION TEST FAILED  ====\n\n" + res + "==== REPEATED AUTHENTICATION TEST FAILED ====\n\n"
    
    return res

def api_test_3():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 2):
        return "Need to pass previous tests"

    auth_data = test_data["test_1"]["response"]

    # The API endpoint
    
    url = base_url + "debit"

    data = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : 1,
        "token" : auth_data['token'],
        "debitAmount" : 1.00,
        "betTypeID" : 1,
        "serverId" : 102,
        "roundId" : 45354,
        "currency" : auth_data['currency'],
        "seatId" : "s1",
        "platformId" : 1,
        "tableId" : 1,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = auth_data["balance"] - data["debitAmount"]

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)

    json_response = response.json()


    test_data["test_3"]["request"] = data
    test_data["test_3"]["response"] = json_response

    #Verify TEST SUCCESS

    test_success = True

    if (not 'operatorId' in json_response) or (json_response.get('operatorId') != data["operatorId"]):
        test_success = False
    elif (not 'errorCode' in json_response) or (json_response.get('errorCode') != 0):
        test_success = False
    elif (not 'errorDescription' in json_response) or (json_response.get('errorDescription') != 'OK'):
        test_success = False
    elif (not 'transactionId' in json_response) or (json_response.get('transactionId') != data["transactionId"]):
        test_success = False
    elif (not 'token' in json_response) or (json_response.get('token') != data["token"]):
        test_success = False
    elif (not 'currency' in json_response) or (json_response.get('currency') != data["currency"]):
        test_success = false
    elif (not 'uid' in json_response) or (json_response.get('uid') != data["uid"]):
        test_success = False
    elif (not 'roundId' in json_response) or (json_response.get('roundId') != data["roundId"]):
        test_success = False
    elif (not 'balance' in json_response) or (json_response.get('balance') != expected_balance):
        test_success = False
    elif (not 'nickName' in json_response) or (json_response.get('nickName') != auth_data['nickName']):
        test_success = False


    res = "REQUEST:\n" + pretty_json(data) + "\n\nRESPONSE:\n" + pretty_json(json_response) + "\n"

    if test_success:
        test_data["test_1"]["response"]["balance"] = json_response.get('balance')
        test_results |= 0b100
        res = "==== DEBIT TEST SUCCESS ====\n\n" + res + "==== DEBIT TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b100
        res = "==== DEBIT TEST FAILED  ====\n\n" + res + "==== DEBIT TEST FAILED ====\n\n"
    
    return res

def api_test_4():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 3):
        return "Need to pass previous tests"

    # The API endpoint
    
    url = base_url + "debit"

    auth_data = test_data["test_1"]["response"]
    data = test_data["test_3"]["request"]
    data["timestamp"] = get_current_timestamp()
    expected_balance = test_data["test_3"]["response"]["balance"]

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)

    json_response = response.json()


    test_data["test_4"]["request"] = data
    test_data["test_4"]["response"] = json_response

    #Verify TEST SUCCESS

    test_success = True

    if (not 'operatorId' in json_response) or (json_response.get('operatorId') != data["operatorId"]):
        test_success = False
    elif (not 'errorCode' in json_response) or (json_response.get('errorCode') != 0):
        test_success = False
    elif (not 'errorDescription' in json_response) or (json_response.get('errorDescription') != 'Transaction already processed'):
        test_success = False
    elif (not 'transactionId' in json_response) or (json_response.get('transactionId') != data["transactionId"]):
        test_success = False
    elif (not 'token' in json_response) or (json_response.get('token') != data["token"]):
        test_success = False
    elif (not 'currency' in json_response) or (json_response.get('currency') != data["currency"]):
        test_success = false
    elif (not 'uid' in json_response) or (json_response.get('uid') != data["uid"]):
        test_success = False
    elif (not 'roundId' in json_response) or (json_response.get('roundId') != data["roundId"]):
        test_success = False
    elif (not 'balance' in json_response) or (json_response.get('balance') != expected_balance):
        test_success = False
    elif (not 'nickName' in json_response) or (json_response.get('nickName') != auth_data['nickName']):
        test_success = False


    res = "REQUEST:\n" + pretty_json(data) + "\n\nRESPONSE:\n" + pretty_json(json_response) + "\n"

    if test_success:
        test_results |= 0b1000
        res = "==== RETRY FOR DEBIT TEST SUCCESS ====\n\n" + res + "==== RETRY FOR DEBIT TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b1000
        res = "==== RETRY FOR DEBIT TEST FAILED  ====\n\n" + res + "==== RETRY FOR DEBIT TEST FAILED ====\n\n"
    
    return res

def api_test_5():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 4):
        return "Need to pass previous tests"


    # The API endpoint
    
    url = base_url + "rollback"

    auth_data = test_data["test_1"]["response"]
    debit_data = test_data["test_3"]["request"]
    debit_response = test_data["test_3"]["response"]

    data = {
        "operatorId" : debit_data['operatorId'],
        "uid" : debit_data['uid'],
        "transactionId" : debit_data['transactionId'],
        "gameId" : debit_data['gameId'],
        "token" : debit_data['token'],
        "rollbackAmount" : debit_data['debitAmount'],
        "betTypeID" : debit_data['betTypeID'],
        "serverId" : debit_data['serverId'],
        "roundId" : debit_data['roundId'],
        "currency" : debit_data['currency'],
        "seatId" : debit_data['seatId'],
        "platformId" : debit_data['platformId'],
        "tableId" : debit_data['tableId'],
        "timestamp" : get_current_timestamp()
    }

    expected_balance = debit_response['balance'] + data['rollbackAmount']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)

    json_response = response.json()


    test_data["test_5"]["request"] = data
    test_data["test_5"]["response"] = json_response

    #Verify TEST SUCCESS

    test_success = True

    if (not 'operatorId' in json_response) or (json_response.get('operatorId') != data["operatorId"]):
        test_success = False
    elif (not 'errorCode' in json_response) or (json_response.get('errorCode') != 0):
        test_success = False
    elif (not 'errorDescription' in json_response) or (json_response.get('errorDescription') != 'OK'):
        test_success = False
    elif (not 'transactionId' in json_response) or (json_response.get('transactionId') != data["transactionId"]):
        test_success = False
    elif (not 'token' in json_response) or (json_response.get('token') != data["token"]):
        test_success = False
    elif (not 'currency' in json_response) or (json_response.get('currency') != data["currency"]):
        test_success = false
    elif (not 'uid' in json_response) or (json_response.get('uid') != data["uid"]):
        test_success = False
    elif (not 'roundId' in json_response) or (json_response.get('roundId') != data["roundId"]):
        test_success = False
    elif (not 'balance' in json_response) or (json_response.get('balance') != expected_balance):
        test_success = False
    elif (not 'nickName' in json_response) or (json_response.get('nickName') != auth_data['nickName']):
        test_success = False


    res = "REQUEST:\n" + pretty_json(data) + "\n\nRESPONSE:\n" + pretty_json(json_response) + "\n"

    if test_success:
        test_results |= 0b10000
        res = "==== ROLLBACK TEST SUCCESS ====\n\n" + res + "==== ROLLBACK TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b10000
        res = "==== ROLLBACK TEST FAILED  ====\n\n" + res + "==== ROLLBACK TEST FAILED ====\n\n"
    
    return res

def api_test_6():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 5):
        return "Need to pass previous tests"


    # The API endpoint
    
    url = base_url + "rollback"

    auth_data = test_data["test_1"]["response"]
    debit_data = test_data["test_3"]["request"]
    rollback_response = test_data["test_5"]["response"]

    data = {
        "operatorId" : debit_data['operatorId'],
        "uid" : debit_data['uid'],
        "transactionId" : debit_data['transactionId'],
        "gameId" : debit_data['gameId'],
        "token" : debit_data['token'],
        "rollbackAmount" : debit_data['debitAmount'],
        "betTypeID" : debit_data['betTypeID'],
        "serverId" : debit_data['serverId'],
        "roundId" : debit_data['roundId'],
        "currency" : debit_data['currency'],
        "seatId" : debit_data['seatId'],
        "platformId" : debit_data['platformId'],
        "tableId" : debit_data['tableId'],
        "timestamp" : get_current_timestamp()
    }

    expected_balance = rollback_response['balance']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)

    json_response = response.json()


    test_data["test_6"]["request"] = data
    test_data["test_6"]["response"] = json_response

    #Verify TEST SUCCESS

    test_success = True

    if (not 'operatorId' in json_response) or (json_response.get('operatorId') != data["operatorId"]):
        print("FAILED OPERATOR")
        test_success = False
    elif (not 'errorCode' in json_response) or (json_response.get('errorCode') != 0):
        print("FAILED ERROR CODE")
        test_success = False
    elif (not 'errorDescription' in json_response) or (json_response.get('errorDescription') != 'Transaction already processed'):
        print("FAILED ERROR DESC")
        test_success = False
    elif (not 'transactionId' in json_response) or (json_response.get('transactionId') != data["transactionId"]):
        print("FAILED TRANSACTIONID")
        test_success = False
    elif (not 'token' in json_response) or (json_response.get('token') != data["token"]):
        print("FAILED TOKEN")
        test_success = False
    elif (not 'currency' in json_response) or (json_response.get('currency') != data["currency"]):
        print("FAILED CURRENCY")
        test_success = False
    elif (not 'uid' in json_response) or (json_response.get('uid') != data["uid"]):
        print("FAILED UID")
        test_success = False
    elif (not 'roundId' in json_response) or (json_response.get('roundId') != data["roundId"]):
        print("FAILED ROUNDID")
        test_success = False
    elif (not 'balance' in json_response) or (json_response.get('balance') != expected_balance):
        print("FAILED BALANCE")
        test_success = False
    elif (not 'nickName' in json_response) or (json_response.get('nickName') != auth_data['nickName']):
        print("FAILED NICKNAME")
        test_success = False

    res = "REQUEST:\n" + pretty_json(data) + "\n\nRESPONSE:\n" + pretty_json(json_response) + "\n"

    if test_success:
        test_results |= 0b100000
        res = "==== RETRY ROLLBACK TEST SUCCESS ====\n\n" + res + "==== RETRY ROLLBACK TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b100000
        res = "==== RETRY ROLLBACK TEST FAILED  ====\n\n" + res + "==== RETRY ROLLBACK TEST FAILED ====\n\n"
    
    return res

def api_test_7():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 6):
        return "Need to pass previous tests"

    # The API endpoint
    
    url = base_url + "rollback"

    auth_data = test_data["test_1"]["response"]
    rollback_response = test_data["test_6"]["response"]

    data = {
        "operatorId" : auth_data['operatorId'],
        "uid" :auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : 1,
        "token" : auth_data['token'],
        "rollbackAmount" : 1.00,
        "betTypeID" : 1,
        "serverId" : 102,
        "roundId" : 45355,
        "currency" : auth_data['currency'],
        "seatId" : "s1",
        "platformId" : 1,
        "tableId" : 1,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = rollback_response['balance']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)

    json_response = response.json()

    test_data["test_7"]["request"] = data
    test_data["test_7"]["response"] = json_response

    #Verify TEST SUCCESS

    test_success = True

    if (not 'operatorId' in json_response) or (json_response.get('operatorId') != data["operatorId"]):
        print("FAILED OPERATOR")
        test_success = False
    elif (not 'errorCode' in json_response) or (json_response.get('errorCode') != 9):
        print("FAILED ERROR CODE")
        test_success = False
    elif (not 'errorDescription' in json_response) or (json_response.get('errorDescription') != 'Transaction not found'):
        print("FAILED ERROR DESC")
        test_success = False
    elif (not 'transactionId' in json_response) or (json_response.get('transactionId') != data["transactionId"]):
        print("FAILED TRANSACTIONID")
        test_success = False
    elif (not 'token' in json_response) or (json_response.get('token') != data["token"]):
        print("FAILED TOKEN")
        test_success = False
    elif (not 'currency' in json_response) or (json_response.get('currency') != data["currency"]):
        print("FAILED CURRENCY")
        test_success = False
    elif (not 'uid' in json_response) or (json_response.get('uid') != data["uid"]):
        print("FAILED UID")
        test_success = False
    elif (not 'roundId' in json_response) or (json_response.get('roundId') != data["roundId"]):
        print("FAILED ROUNDID")
        test_success = False
    elif (not 'balance' in json_response) or (json_response.get('balance') != expected_balance):
        print("FAILED BALANCE")
        test_success = False

    res = "REQUEST:\n" + pretty_json(data) + "\n\nRESPONSE:\n" + pretty_json(json_response) + "\n"

    if test_success:
        test_results |= 0b1000000
        res = "==== ROLLBACK BEFORE DEBIT TEST SUCCESS ====\n\n" + res + "==== ROLLBACK BEFORE DEBIT TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b1000000
        res = "==== ROLLBACK BEFORE DEBIT TEST FAILED  ====\n\n" + res + "==== ROLLBACK BEFORE DEBIT TEST FAILED ====\n\n"
    
    return res

def api_test_8():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 7):
        return "Need to pass previous tests"

    url = base_url + "debit"

    auth_data = test_data["test_1"]["response"]
    rollback_request = test_data['test_7']['request']
    rollback_response = test_data["test_7"]["response"]

    data = {
        "operatorId" :rollback_request['operatorId'],
        "uid" : rollback_request['uid'],
        "transactionId" : rollback_request['transactionId'],
        "gameId" : rollback_request['gameId'],
        "token" : rollback_request['token'],
        "debitAmount" : rollback_request['rollbackAmount'],
        "betTypeID" : rollback_request['betTypeID'],
        "serverId" : rollback_request['serverId'],
        "roundId" : rollback_request['roundId'],
        "currency" : rollback_request['currency'],
        "seatId" : rollback_request['seatId'],
        "platformId" : rollback_request['platformId'],
        "tableId" : rollback_request['tableId'],
        "timestamp" : get_current_timestamp()
    }

    expected_balance = rollback_response['balance']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)

    json_response = response.json()


    test_data["test_8"]["request"] = data
    test_data["test_8"]["response"] = json_response

    #Verify TEST SUCCESS

    test_success = True

    if (not 'operatorId' in json_response) or (json_response.get('operatorId') != data["operatorId"]):
        print("FAILED OPERATOR")
        test_success = False
    elif (not 'errorCode' in json_response) or (json_response.get('errorCode') != 1):
        print("FAILED ERROR CODE")
        test_success = False
    elif (not 'errorDescription' in json_response) or (json_response.get('errorDescription') != 'Debit after rollback'):
        print("FAILED ERROR DESC")
        test_success = False
    elif (not 'transactionId' in json_response) or (json_response.get('transactionId') != data["transactionId"]):
        print("FAILED TRANSACTIONID")
        test_success = False
    elif (not 'token' in json_response) or (json_response.get('token') != data["token"]):
        print("FAILED TOKEN")
        test_success = False
    elif (not 'currency' in json_response) or (json_response.get('currency') != data["currency"]):
        print("FAILED CURRENCY")
        test_success = False
    elif (not 'uid' in json_response) or (json_response.get('uid') != data["uid"]):
        print("FAILED UID")
        test_success = False
    elif (not 'roundId' in json_response) or (json_response.get('roundId') != data["roundId"]):
        print("FAILED ROUNDID")
        test_success = False
    elif (not 'balance' in json_response) or (json_response.get('balance') != expected_balance):
        print("FAILED BALANCE")
        test_success = False
    elif (not 'nickName' in json_response) or (json_response.get('nickName') != auth_data['nickName']):
        print("FAILED NICKNAME")
        test_success = False

    res = "REQUEST:\n" + pretty_json(data) + "\n\nRESPONSE:\n" + pretty_json(json_response) + "\n"

    if test_success:
        test_results |= 0b10000000
        res = "==== DEBIT AFTER ROLLBACK TEST SUCCESS ====\n\n" + res + "==== DEBIT AFTER ROLLBACK TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b10000000
        res = "==== DEBIT AFTER ROLLBACK TEST FAILED  ====\n\n" + res + "==== DEBIT AFTER ROLLBACK TEST FAILED ====\n\n"
    
    return res


def api_test_9():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 8):
        return "Need to pass previous tests"

    ###################
    # PART I: Debit
    ####################
    url = base_url + "debit"

    auth_data = test_data["test_1"]["response"]
    previous_debit_response = test_data["test_8"]["response"]

    debit_request = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : 1,
        "token" : auth_data['token'],
        "debitAmount" : 1.00,
        "betTypeID" : 1,
        "serverId" : 102,
        "roundId" : 45356,
        "currency" : auth_data['currency'],
        "seatId" : "s1",
        "platformId" : 1,
        "tableId" : 1,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = previous_debit_response['balance'] - debit_request['debitAmount']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(debit_request, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=debit_request, headers=headers)

    debit_response = response.json()

    #Verify PART I
    test_success = True

    if (not 'operatorId' in debit_response) or (debit_response.get('operatorId') != debit_request["operatorId"]):
        print("FAILED OPERATOR")
        test_success = False
    elif (not 'errorCode' in debit_response) or (debit_response.get('errorCode') != 0):
        print("FAILED ERROR CODE")
        test_success = False
    elif (not 'errorDescription' in debit_response) or (debit_response.get('errorDescription') != 'OK'):
        print("FAILED ERROR DESC")
        test_success = False
    elif (not 'transactionId' in debit_response) or (debit_response.get('transactionId') != debit_request["transactionId"]):
        print("FAILED TRANSACTIONID")
        test_success = False
    elif (not 'token' in debit_response) or (debit_response.get('token') != debit_request["token"]):
        print("FAILED TOKEN")
        test_success = False
    elif (not 'currency' in debit_response) or (debit_response.get('currency') != debit_request["currency"]):
        print("FAILED CURRENCY")
        test_success = False
    elif (not 'uid' in debit_response) or (debit_response.get('uid') != debit_request["uid"]):
        print("FAILED UID")
        test_success = False
    elif (not 'roundId' in debit_response) or (debit_response.get('roundId') != debit_request["roundId"]):
        print("FAILED ROUNDID")
        test_success = False
    elif (not 'balance' in debit_response) or (debit_response.get('balance') != expected_balance):
        print("FAILED BALANCE")
        test_success = False
    elif (not 'nickName' in debit_response) or (debit_response.get('nickName') != auth_data['nickName']):
        print("FAILED NICKNAME")
        test_success = False

    res = "PART I REQUEST:\n" + pretty_json(debit_request) + "\n\nPART I RESPONSE:\n" + pretty_json(debit_response) + "\n"

    if not test_success:
        test_results &= ~0b100000000
        res = "==== CREDIT TEST FAILET AT PART I ====\n\n" + res + "==== CREDIT TEST FAILED AT PART I  ====\n\n"
        return res


    ###################
    # PART II: Credit
    ####################
    url = base_url + "credit"

    credit_request = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : debit_request['gameId'],
        "token" : auth_data['token'],
        "creditAmount" : 2.00,
        "betTypeID" : 101,
        "serverId" : debit_request['serverId'],
        "roundId" : debit_request['roundId'],
        "currency" : auth_data['currency'],
        "seatId" : debit_request['seatId'],
        "platformId" : debit_request['platformId'],
        "tableId" : debit_request['tableId'],
        "returnReason" : 0,
        "creditIndex" : "1|1",
        "isEndRound" : True,
        "debitTransactionId" : debit_request['transactionId'],
        "timestamp" : get_current_timestamp()
    }

    expected_balance = debit_response['balance'] + credit_request['creditAmount']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(credit_request, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=credit_request, headers=headers)

    credit_response = response.json()

    test_data["test_9"]["request"] = credit_request
    test_data["test_9"]["response"] = credit_response

    #Verify TEST SUCCESS

    if (not 'operatorId' in credit_response) or (credit_response.get('operatorId') !=credit_request["operatorId"]):
        print("FAILED OPERATOR")
        test_success = False
    elif (not 'errorCode' in credit_response) or (credit_response.get('errorCode') != 0):
        print("FAILED ERROR CODE")
        test_success = False
    elif (not 'errorDescription' in credit_response) or (credit_response.get('errorDescription') != 'OK'):
        print("FAILED ERROR DESC")
        test_success = False
    elif (not 'transactionId' in credit_response) or (credit_response.get('transactionId') !=credit_request["transactionId"]):
        print("FAILED TRANSACTIONID")
        test_success = False
    elif (not 'token' in credit_response) or (credit_response.get('token') !=credit_request["token"]):
        print("FAILED TOKEN")
        test_success = False
    elif (not 'currency' in credit_response) or (credit_response.get('currency') !=credit_request["currency"]):
        print("FAILED CURRENCY")
        test_success = False
    elif (not 'uid' in credit_response) or (credit_response.get('uid') !=credit_request["uid"]):
        print("FAILED UID")
        test_success = False
    elif (not 'roundId' in credit_response) or (credit_response.get('roundId') !=credit_request["roundId"]):
        print("FAILED ROUNDID")
        test_success = False
    elif (not 'balance' in credit_response) or (credit_response.get('balance') != expected_balance):
        print("FAILED BALANCE")
        test_success = False
    elif (not 'nickName' in credit_response) or (credit_response.get('nickName') != auth_data['nickName']):
        print("FAILED NICKNAME")
        test_success = False

    res = "REQUEST:\n" + pretty_json(credit_request) + "\n\nRESPONSE:\n" + pretty_json(credit_response) + "\n"

    if test_success:
        test_results |= 0b100000000
        res = "==== CREDIT TEST SUCCESS ====\n\n" + res + "==== CREDIT TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b100000000
        res = "==== CREDIT TEST FAILED PART II  ====\n\n" + res + "==== CREDIT TEST FAILED PART II ====\n\n"
    
    return res

def api_test_10():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 9):
        return "Need to pass previous tests"

    url = base_url + "credit"

    auth_data = test_data["test_1"]["response"]
    credit_request = test_data['test_9']['request']
    credit_response = test_data["test_9"]["response"]

    data = credit_request
    data['timestamp'] = get_current_timestamp()

    expected_balance = credit_response['balance']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)

    json_response = response.json()

    test_data["test_10"]["request"] = data
    test_data["test_10"]["response"] = json_response

    #Verify TEST SUCCESS

    test_success = True

    if (not 'operatorId' in json_response) or (json_response.get('operatorId') != data["operatorId"]):
        print("FAILED OPERATOR")
        test_success = False
    elif (not 'errorCode' in json_response) or (json_response.get('errorCode') != 0):
        print("FAILED ERROR CODE")
        test_success = False
    elif (not 'errorDescription' in json_response) or (json_response.get('errorDescription') != 'Transaction already processed'):
        print("FAILED ERROR DESC")
        test_success = False
    elif (not 'transactionId' in json_response) or (json_response.get('transactionId') != data["transactionId"]):
        print("FAILED TRANSACTIONID")
        test_success = False
    elif (not 'token' in json_response) or (json_response.get('token') != data["token"]):
        print("FAILED TOKEN")
        test_success = False
    elif (not 'currency' in json_response) or (json_response.get('currency') != data["currency"]):
        print("FAILED CURRENCY")
        test_success = False
    elif (not 'uid' in json_response) or (json_response.get('uid') != data["uid"]):
        print("FAILED UID")
        test_success = False
    elif (not 'roundId' in json_response) or (json_response.get('roundId') != data["roundId"]):
        print("FAILED ROUNDID")
        test_success = False
    elif (not 'balance' in json_response) or (json_response.get('balance') != expected_balance):
        print("FAILED BALANCE")
        test_success = False
    elif (not 'nickName' in json_response) or (json_response.get('nickName') != auth_data['nickName']):
        print("FAILED NICKNAME")
        test_success = False

    res = "REQUEST:\n" + pretty_json(data) + "\n\nRESPONSE:\n" + pretty_json(json_response) + "\n"

    if test_success:
        test_results |= 0b1000000000
        res = "==== RETRY FOR CREDIT TEST SUCCESS ====\n\n" + res + "==== RETRY FOR CREDIT TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b1000000000
        res = "==== RETRY FOR CREDIT TEST FAILED  ====\n\n" + res + "==== RETRY FOR CREDIT TEST FAILED ====\n\n"
    
    return res

def api_test_11():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 10):
        return "Need to pass previous tests"

    ###################
    # PART I: Debit
    ####################
    url = base_url + "debit"

    auth_data = test_data["test_1"]["response"]
    previous_credit_response = test_data["test_10"]["response"]

    debit_request = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : 1,
        "token" : auth_data['token'],
        "debitAmount" : 1.00,
        "betTypeID" : 1,
        "serverId" : 102,
        "roundId" : 45357,
        "currency" : auth_data['currency'],
        "seatId" : "s1",
        "platformId" : 1,
        "tableId" : 1,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = previous_credit_response['balance'] - debit_request['debitAmount']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(debit_request, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=debit_request, headers=headers)

    debit_response = response.json()

    #Verify PART I
    test_success = True

    if (not 'operatorId' in debit_response) or (debit_response.get('operatorId') != debit_request["operatorId"]):
        print("FAILED OPERATOR")
        test_success = False
    elif (not 'errorCode' in debit_response) or (debit_response.get('errorCode') != 0):
        print("FAILED ERROR CODE")
        test_success = False
    elif (not 'errorDescription' in debit_response) or (debit_response.get('errorDescription') != 'OK'):
        print("FAILED ERROR DESC")
        test_success = False
    elif (not 'transactionId' in debit_response) or (debit_response.get('transactionId') != debit_request["transactionId"]):
        print("FAILED TRANSACTIONID")
        test_success = False
    elif (not 'token' in debit_response) or (debit_response.get('token') != debit_request["token"]):
        print("FAILED TOKEN")
        test_success = False
    elif (not 'currency' in debit_response) or (debit_response.get('currency') != debit_request["currency"]):
        print("FAILED CURRENCY")
        test_success = False
    elif (not 'uid' in debit_response) or (debit_response.get('uid') != debit_request["uid"]):
        print("FAILED UID")
        test_success = False
    elif (not 'roundId' in debit_response) or (debit_response.get('roundId') != debit_request["roundId"]):
        print("FAILED ROUNDID")
        test_success = False
    elif (not 'balance' in debit_response) or (debit_response.get('balance') != expected_balance):
        print("FAILED BALANCE")
        test_success = False
    elif (not 'nickName' in debit_response) or (debit_response.get('nickName') != auth_data['nickName']):
        print("FAILED NICKNAME")
        test_success = False

    res = "PART I REQUEST:\n" + pretty_json(debit_request) + "\n\nPART I RESPONSE:\n" + pretty_json(debit_response) + "\n"

    if not test_success:
        test_results &= ~0b10000000000
        res = "==== CREDIT WITH AMOUNT 0 TEST FAILET AT PART I ====\n\n" + res + "==== CREDIT WITH AMOUNT 0 TEST FAILED AT PART I  ====\n\n"
        return res


    ###################
    # PART II: Credit
    ####################
    url = base_url + "credit"

    credit_request = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : debit_request['gameId'],
        "token" : auth_data['token'],
        "creditAmount" : 0.00,
        "betTypeID" : 101,
        "serverId" : debit_request['serverId'],
        "roundId" : debit_request['roundId'],
        "currency" : auth_data['currency'],
        "seatId" : debit_request['seatId'],
        "platformId" : debit_request['platformId'],
        "tableId" : debit_request['tableId'],
        "returnReason" : 0,
        "creditIndex" : "1|1",
        "isEndRound" : True,
        "debitTransactionId" : debit_request['transactionId'],
        "timestamp" : get_current_timestamp()
    }

    expected_balance = debit_response['balance'] + credit_request['creditAmount']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(credit_request, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=credit_request, headers=headers)

    credit_response = response.json()

    test_data["test_11"]["request"] = credit_request
    test_data["test_11"]["response"] = credit_response

    #Verify TEST SUCCESS

    if (not 'operatorId' in credit_response) or (credit_response.get('operatorId') !=credit_request["operatorId"]):
        print("FAILED OPERATOR")
        test_success = False
    elif (not 'errorCode' in credit_response) or (credit_response.get('errorCode') != 0):
        print("FAILED ERROR CODE")
        test_success = False
    elif (not 'errorDescription' in credit_response) or (credit_response.get('errorDescription') != 'OK'):
        print("FAILED ERROR DESC")
        test_success = False
    elif (not 'transactionId' in credit_response) or (credit_response.get('transactionId') !=credit_request["transactionId"]):
        print("FAILED TRANSACTIONID")
        test_success = False
    elif (not 'token' in credit_response) or (credit_response.get('token') !=credit_request["token"]):
        print("FAILED TOKEN")
        test_success = False
    elif (not 'currency' in credit_response) or (credit_response.get('currency') !=credit_request["currency"]):
        print("FAILED CURRENCY")
        test_success = False
    elif (not 'uid' in credit_response) or (credit_response.get('uid') !=credit_request["uid"]):
        print("FAILED UID")
        test_success = False
    elif (not 'roundId' in credit_response) or (credit_response.get('roundId') !=credit_request["roundId"]):
        print("FAILED ROUNDID")
        test_success = False
    elif (not 'balance' in credit_response) or (credit_response.get('balance') != expected_balance):
        print("FAILED BALANCE")
        test_success = False
    elif (not 'nickName' in credit_response) or (credit_response.get('nickName') != auth_data['nickName']):
        print("FAILED NICKNAME")
        test_success = False

    res = "REQUEST:\n" + pretty_json(credit_request) + "\n\nRESPONSE:\n" + pretty_json(credit_response) + "\n"

    if test_success:
        test_results |= 0b10000000000
        res = "==== CREDIT WITH AMOUNT 0 TEST SUCCESS ====\n\n" + res + "==== CREDIT WITH AMOUNT 0 TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b10000000000
        res = "==== CREDIT WITH AMOUNT 0 TEST FAILED PART II  ====\n\n" + res + "==== CREDIT WITH AMOUNT 0 TEST FAILED PART II ====\n\n"
    
    return res


def api_test_12():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 11):
        return "Need to pass previous tests"

    auth_data = test_data["test_1"]["response"]
    credit_response = test_data["test_11"]["response"]

    # The API endpoint
    
    url = base_url + "debit"

    data = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : 1,
        "token" : auth_data['token'],
        "debitAmount" : (credit_response['balance'] + 1.00),
        "betTypeID" : 1,
        "serverId" : 102,
        "roundId" : 45358,
        "currency" : auth_data['currency'],
        "seatId" : "s1",
        "platformId" : 1,
        "tableId" : 1,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = credit_response['balance']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)

    json_response = response.json()


    test_data["test_12"]["request"] = data
    test_data["test_12"]["response"] = json_response

    #Verify TEST SUCCESS

    test_success = True

    if (not 'operatorId' in json_response) or (json_response.get('operatorId') != data["operatorId"]):
        test_success = False
    elif (not 'errorCode' in json_response) or (json_response.get('errorCode') != 3):
        test_success = False
    elif (not 'errorDescription' in json_response) or (json_response.get('errorDescription') != 'Insufficient funds'):
        test_success = False
    elif (not 'transactionId' in json_response) or (json_response.get('transactionId') != data["transactionId"]):
        test_success = False
    elif (not 'token' in json_response) or (json_response.get('token') != data["token"]):
        test_success = False
    elif (not 'currency' in json_response) or (json_response.get('currency') != data["currency"]):
        test_success = false
    elif (not 'uid' in json_response) or (json_response.get('uid') != data["uid"]):
        test_success = False
    elif (not 'roundId' in json_response) or (json_response.get('roundId') != data["roundId"]):
        test_success = False
    elif (not 'balance' in json_response) or (json_response.get('balance') != expected_balance):
        test_success = False

    res = "REQUEST:\n" + pretty_json(data) + "\n\nRESPONSE:\n" + pretty_json(json_response) + "\n"

    if test_success:
        test_results |= 0b100000000000
        res = "==== INSUFICCIENT FUNDS TEST SUCCESS ====\n\n" + res + "==== INSUFICCIENT FUNDS TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b100000000000
        res = "==== INSUFICCIENT FUNDS TEST FAILED  ====\n\n" + res + "==== INSUFICCIENT FUNDS TEST FAILED ====\n\n"
    
    return res

def api_test_13():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 12):
        return "Need to pass previous tests"

    auth_data = test_data["test_1"]["response"]
    debit_response = test_data["test_12"]["response"]

    # The API endpoint
    
    url = base_url + "debit"

    data = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : 1,
        "token" : "sdj2ksalskdow3ssjKjzdE2as", # Invalid token for testing purposes
        "debitAmount" : 1.00,
        "betTypeID" : 1,
        "serverId" : 102,
        "roundId" : 45359,
        "currency" : auth_data['currency'],
        "seatId" : "s1",
        "platformId" : 1,
        "tableId" : 1,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = 0.0

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)

    json_response = response.json()


    test_data["test_13"]["request"] = data
    test_data["test_13"]["response"] = json_response

    #Verify TEST SUCCESS

    test_success = True

    if (not 'operatorId' in json_response) or (json_response.get('operatorId') != data["operatorId"]):
        test_success = False
    elif (not 'errorCode' in json_response) or (json_response.get('errorCode') != 6):
        test_success = False
    elif (not 'errorDescription' in json_response) or (json_response.get('errorDescription') != 'Token not found'):
        test_success = False
    elif (not 'transactionId' in json_response) or (json_response.get('transactionId') != data["transactionId"]):
        test_success = False
    elif (not 'token' in json_response) or (json_response.get('token') != data["token"]):
        test_success = False
    elif (not 'currency' in json_response) or (json_response.get('currency') != data["currency"]):
        test_success = false
    elif (not 'uid' in json_response) or (json_response.get('uid') != data["uid"]):
        test_success = False
    elif (not 'roundId' in json_response) or (json_response.get('roundId') != data["roundId"]):
        test_success = False
    elif (not 'balance' in json_response) or (json_response.get('balance') != expected_balance):
        test_success = False

    res = "REQUEST:\n" + pretty_json(data) + "\n\nRESPONSE:\n" + pretty_json(json_response) + "\n"

    if test_success:
        test_results |= 0b1000000000000
        res = "==== DEBIT WITH WRONG TOKEN TEST SUCCESS ====\n\n" + res + "==== DEBIT WITH WRONG TOKEN TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b1000000000000
        res = "==== DEBIT WITH WRONG TOKEN TEST FAILED  ====\n\n" + res + "==== DEBIT WITH WRONG TOKEN TEST FAILED ====\n\n"
    
    return res

def api_test_14():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 13):
        return "Need to pass previous tests"

    auth_data = test_data["test_1"]["response"]
    debit_response = test_data["test_13"]["response"]

    # The API endpoint
    
    url = base_url + "debit"

    data = {
        "operatorId" : auth_data['operatorId'],
        "uid" : "sdl2kasdlw", # Invalid userid for testing purposes
        "transactionId" : generate_transaction_id(),
        "gameId" : 1,
        "token" : auth_data['token'],
        "debitAmount" : 1.00,
        "betTypeID" : 1,
        "serverId" : 102,
        "roundId" : 45360,
        "currency" : auth_data['currency'],
        "seatId" : "s1",
        "platformId" : 1,
        "tableId" : 1,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = 0.0

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)

    json_response = response.json()


    test_data["test_14"]["request"] = data
    test_data["test_14"]["response"] = json_response

    #Verify TEST SUCCESS

    test_success = True

    if (not 'operatorId' in json_response) or (json_response.get('operatorId') != data["operatorId"]):
        test_success = False
    elif (not 'errorCode' in json_response) or (json_response.get('errorCode') != 7):
        test_success = False
    elif (not 'errorDescription' in json_response) or (json_response.get('errorDescription') != 'User not found'):
        test_success = False
    elif (not 'transactionId' in json_response) or (json_response.get('transactionId') != data["transactionId"]):
        test_success = False
    elif (not 'token' in json_response) or (json_response.get('token') != data["token"]):
        test_success = False
    elif (not 'currency' in json_response) or (json_response.get('currency') != data["currency"]):
        test_success = false
    elif (not 'uid' in json_response) or (json_response.get('uid') != data["uid"]):
        test_success = False
    elif (not 'roundId' in json_response) or (json_response.get('roundId') != data["roundId"]):
        test_success = False
    elif (not 'balance' in json_response) or (json_response.get('balance') != expected_balance):
        test_success = False

    res = "REQUEST:\n" + pretty_json(data) + "\n\nRESPONSE:\n" + pretty_json(json_response) + "\n"

    if test_success:
        test_results |= 0b10000000000000
        res = "==== DEBIT FROM UNKNOWN USER TEST SUCCESS ====\n\n" + res + "==== DEBIT FROM UNKNOWN USER TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b10000000000000
        res = "==== DEBIT FROM UNKNOWN USER TEST FAILED  ====\n\n" + res + "==== DEBIT FROM UNKNOWN USER TEST FAILED ====\n\n"
    
    return res

def api_test_15():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 14):
        return "Need to pass previous tests"

    auth_data = test_data["test_1"]["response"]
    debit_response = test_data["test_12"]["response"]

    # The API endpoint
    
    url = base_url + "debit"

    data = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : 1,
        "token" : auth_data['token'],
        "debitAmount" : -1.00,
        "betTypeID" : 1,
        "serverId" : 102,
        "roundId" : 45361,
        "currency" : auth_data['currency'],
        "seatId" : "s1",
        "platformId" : 1,
        "tableId" : 1,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = debit_response['balance']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)

    json_response = response.json()


    test_data["test_15"]["request"] = data
    test_data["test_15"]["response"] = json_response

    #Verify TEST SUCCESS

    test_success = True

    if (not 'operatorId' in json_response) or (json_response.get('operatorId') != data["operatorId"]):
        test_success = False
    elif (not 'errorCode' in json_response) or (json_response.get('errorCode') != 1):
        test_success = False
    elif (not 'errorDescription' in json_response) or (json_response.get('errorDescription') != 'Negative amount'):
        test_success = False
    elif (not 'transactionId' in json_response) or (json_response.get('transactionId') != data["transactionId"]):
        test_success = False
    elif (not 'token' in json_response) or (json_response.get('token') != data["token"]):
        test_success = False
    elif (not 'currency' in json_response) or (json_response.get('currency') != data["currency"]):
        test_success = false
    elif (not 'uid' in json_response) or (json_response.get('uid') != data["uid"]):
        test_success = False
    elif (not 'roundId' in json_response) or (json_response.get('roundId') != data["roundId"]):
        test_success = False
    elif (not 'balance' in json_response) or (json_response.get('balance') != expected_balance):
        test_success = False

    res = "REQUEST:\n" + pretty_json(data) + "\n\nRESPONSE:\n" + pretty_json(json_response) + "\n"

    if test_success:
        test_results |= 0b100000000000000
        res = "==== DEBIT WITH NEGATIVE AMOUNT TEST SUCCESS ====\n\n" + res + "==== DEBIT WITH NEGATIVE AMOUNT TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b100000000000000
        res = "==== DEBIT WITH NEGATIVE AMOUNT TEST FAILED  ====\n\n" + res + "==== DEBIT WITH NEGATIVE AMOUNT TEST FAILED ====\n\n"
    
    return res

def api_test_16():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 15):
        return "Need to pass previous tests"

    auth_data = test_data["test_1"]["response"]
    debit_response = test_data["test_15"]["response"]

    # The API endpoint
    
    url = base_url + "debit"

    data = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : 1,
        "token" : auth_data['token'],
        "debitAmount" : debit_response['balance'],
        "betTypeID" : 1,
        "serverId" : 102,
        "roundId" : 45362,
        "currency" : auth_data['currency'],
        "seatId" : "s1",
        "platformId" : 1,
        "tableId" : 1,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = 0.0

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)

    json_response = response.json()


    test_data["test_16"]["request"] = data
    test_data["test_16"]["response"] = json_response

    #Verify TEST SUCCESS

    test_success = True

    if (not 'operatorId' in json_response) or (json_response.get('operatorId') != data["operatorId"]):
        test_success = False
    elif (not 'errorCode' in json_response) or (json_response.get('errorCode') != 0):
        test_success = False
    elif (not 'errorDescription' in json_response) or (json_response.get('errorDescription') != 'OK'):
        test_success = False
    elif (not 'transactionId' in json_response) or (json_response.get('transactionId') != data["transactionId"]):
        test_success = False
    elif (not 'token' in json_response) or (json_response.get('token') != data["token"]):
        test_success = False
    elif (not 'currency' in json_response) or (json_response.get('currency') != data["currency"]):
        test_success = false
    elif (not 'uid' in json_response) or (json_response.get('uid') != data["uid"]):
        test_success = False
    elif (not 'roundId' in json_response) or (json_response.get('roundId') != data["roundId"]):
        test_success = False
    elif (not 'balance' in json_response) or (json_response.get('balance') != expected_balance):
        test_success = False

    res = "REQUEST:\n" + pretty_json(data) + "\n\nRESPONSE:\n" + pretty_json(json_response) + "\n"

    if test_success:
        test_results |= 0b1000000000000000
        res = "==== DEBIT ALL PLAYER BALANCE TEST SUCCESS ====\n\n" + res + "==== DEBIT ALL PLAYER BALANCE TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b1000000000000000
        res = "==== DEBIT ALL PLAYER BALANCE TEST FAILED  ====\n\n" + res + "==== DEBIT ALL PLAYER BALANCE TEST FAILED ====\n\n"
    
    return res

def api_test_17():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 16):
        return "Need to pass previous tests"

    auth_data = test_data["test_1"]["response"]

    previous_debit_response = test_data["test_15"]["response"]
    debit_request = test_data["test_16"]["request"]
    debit_response = test_data["test_16"]["response"]

    # The API endpoint
    
    url = base_url + "credit"

    data = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : debit_request['gameId'],
        "token" : auth_data['token'],
        "creditAmount" : debit_request['debitAmount'],
        "betTypeID" : 101,
        "serverId" : debit_request['serverId'],
        "roundId" : debit_request['roundId'],
        "currency" : auth_data['currency'],
        "seatId" : debit_request['seatId'],
        "platformId" : debit_request['platformId'],
        "tableId" : debit_request['tableId'],
        "returnReason" : 1,
        "creditIndex" : "1|1",
        "isEndRound" : True,
        "debitTransactionId" : debit_request['transactionId'],
        "timestamp" : get_current_timestamp()
    }

    expected_balance = previous_debit_response['balance']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)

    json_response = response.json()


    test_data["test_17"]["request"] = data
    test_data["test_17"]["response"] = json_response

    #Verify TEST SUCCESS

    test_success = True

    if (not 'operatorId' in json_response) or (json_response.get('operatorId') != data["operatorId"]):
        test_success = False
    elif (not 'errorCode' in json_response) or (json_response.get('errorCode') != 0):
        test_success = False
    elif (not 'errorDescription' in json_response) or (json_response.get('errorDescription') != 'OK'):
        test_success = False
    elif (not 'transactionId' in json_response) or (json_response.get('transactionId') != data["transactionId"]):
        test_success = False
    elif (not 'token' in json_response) or (json_response.get('token') != data["token"]):
        test_success = False
    elif (not 'currency' in json_response) or (json_response.get('currency') != data["currency"]):
        test_success = false
    elif (not 'uid' in json_response) or (json_response.get('uid') != data["uid"]):
        test_success = False
    elif (not 'roundId' in json_response) or (json_response.get('roundId') != data["roundId"]):
        test_success = False
    elif (not 'balance' in json_response) or (json_response.get('balance') != expected_balance):
        test_success = False

    res = "REQUEST:\n" + pretty_json(data) + "\n\nRESPONSE:\n" + pretty_json(json_response) + "\n"

    if test_success:
        test_results |= 0b10000000000000000
        res = "==== RETURN REASON 1 IN CREDIT CALL TEST SUCCESS ====\n\n" + res + "==== RETURN REASON 1 IN CREDIT CALL TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b10000000000000000
        res = "==== RETURN REASON 1 IN CREDIT CALL FAILED  ====\n\n" + res + "==== RETURN REASON 1 IN CREDIT CALL TEST FAILED ====\n\n"
    
    return res

def api_test_18():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 17):
        return "Need to pass previous tests"

    ###################
    # PART I: Debit
    ####################
    url = base_url + "debit"

    auth_data = test_data["test_1"]["response"]
    previous_credit_response = test_data["test_17"]["response"]

    debit_request = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : 1,
        "token" : auth_data['token'],
        "debitAmount" : 1.00,
        "betTypeID" : 1,
        "serverId" : 102,
        "roundId" : 45363,
        "currency" : auth_data['currency'],
        "seatId" : "s1",
        "platformId" : 1,
        "tableId" : 1,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = previous_credit_response['balance'] - debit_request['debitAmount']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(debit_request, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=debit_request, headers=headers)

    debit_response = response.json()

    #Verify PART I
    test_success = True

    if (not 'operatorId' in debit_response) or (debit_response.get('operatorId') != debit_request["operatorId"]):
        print("FAILED OPERATOR")
        test_success = False
    elif (not 'errorCode' in debit_response) or (debit_response.get('errorCode') != 0):
        print("FAILED ERROR CODE")
        test_success = False
    elif (not 'errorDescription' in debit_response) or (debit_response.get('errorDescription') != 'OK'):
        print("FAILED ERROR DESC")
        test_success = False
    elif (not 'transactionId' in debit_response) or (debit_response.get('transactionId') != debit_request["transactionId"]):
        print("FAILED TRANSACTIONID")
        test_success = False
    elif (not 'token' in debit_response) or (debit_response.get('token') != debit_request["token"]):
        print("FAILED TOKEN")
        test_success = False
    elif (not 'currency' in debit_response) or (debit_response.get('currency') != debit_request["currency"]):
        print("FAILED CURRENCY")
        test_success = False
    elif (not 'uid' in debit_response) or (debit_response.get('uid') != debit_request["uid"]):
        print("FAILED UID")
        test_success = False
    elif (not 'roundId' in debit_response) or (debit_response.get('roundId') != debit_request["roundId"]):
        print("FAILED ROUNDID")
        test_success = False
    elif (not 'balance' in debit_response) or (debit_response.get('balance') != expected_balance):
        print("FAILED BALANCE")
        test_success = False
    elif (not 'nickName' in debit_response) or (debit_response.get('nickName') != auth_data['nickName']):
        print("FAILED NICKNAME")
        test_success = False

    res = "PART I REQUEST:\n" + pretty_json(debit_request) + "\n\nPART I RESPONSE:\n" + pretty_json(debit_response) + "\n"

    if not test_success:
        test_results &= ~0b100000000
        res = "==== RETURN REASON 2 IN CREDIT TEST FAILED AT PART I ====\n\n" + res + "==== RETURN REASON 2 IN CREDIT TEST FAILED AT PART I  ====\n\n"
        return res


    ###################
    # PART II: Credit
    ####################
    url = base_url + "credit"

    credit_request = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : debit_request['gameId'],
        "token" : auth_data['token'],
        "creditAmount" : debit_request['debitAmount'],
        "betTypeID" : 101,
        "serverId" : debit_request['serverId'],
        "roundId" : debit_request['roundId'],
        "currency" : auth_data['currency'],
        "seatId" : debit_request['seatId'],
        "platformId" : debit_request['platformId'],
        "tableId" : debit_request['tableId'],
        "returnReason" : 2,
        "creditIndex" : "1|1",
        "isEndRound" : True,
        "debitTransactionId" : debit_request['transactionId'],
        "timestamp" : get_current_timestamp()
    }

    expected_balance = previous_credit_response['balance']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(credit_request, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=credit_request, headers=headers)

    credit_response = response.json()

    test_data["test_18"]["request"] = credit_request
    test_data["test_18"]["response"] = credit_response

    #Verify TEST SUCCESS

    if (not 'operatorId' in credit_response) or (credit_response.get('operatorId') !=credit_request["operatorId"]):
        print("FAILED OPERATOR")
        test_success = False
    elif (not 'errorCode' in credit_response) or (credit_response.get('errorCode') != 0):
        print("FAILED ERROR CODE")
        test_success = False
    elif (not 'errorDescription' in credit_response) or (credit_response.get('errorDescription') != 'OK'):
        print("FAILED ERROR DESC")
        test_success = False
    elif (not 'transactionId' in credit_response) or (credit_response.get('transactionId') !=credit_request["transactionId"]):
        print("FAILED TRANSACTIONID")
        test_success = False
    elif (not 'token' in credit_response) or (credit_response.get('token') !=credit_request["token"]):
        print("FAILED TOKEN")
        test_success = False
    elif (not 'currency' in credit_response) or (credit_response.get('currency') !=credit_request["currency"]):
        print("FAILED CURRENCY")
        test_success = False
    elif (not 'uid' in credit_response) or (credit_response.get('uid') !=credit_request["uid"]):
        print("FAILED UID")
        test_success = False
    elif (not 'roundId' in credit_response) or (credit_response.get('roundId') !=credit_request["roundId"]):
        print("FAILED ROUNDID")
        test_success = False
    elif (not 'balance' in credit_response) or (credit_response.get('balance') != expected_balance):
        print("FAILED BALANCE")
        test_success = False
    elif (not 'nickName' in credit_response) or (credit_response.get('nickName') != auth_data['nickName']):
        print("FAILED NICKNAME")
        test_success = False

    res = "REQUEST:\n" + pretty_json(credit_request) + "\n\nRESPONSE:\n" + pretty_json(credit_response) + "\n"

    if test_success:
        test_results |= 0b100000000000000000
        res = "==== RETURN REASON 2 CREDIT TEST SUCCESS ====\n\n" + res + "==== RETURN REASON 2 CREDIT TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b100000000000000000
        res = "==== RETURN REASON 2 CREDIT TEST FAILED PART II  ====\n\n" + res + "==== RETURN REASON 2 CREDIT TEST FAILED PART II ====\n\n"
    
    return res

def api_test_19():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 18):
        return "Need to pass previous tests"

    ###################
    # PART I: Debit
    ####################
    url = base_url + "debit"

    auth_data = test_data["test_1"]["response"]
    previous_credit_response = test_data["test_18"]["response"]

    debit_request = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : 1,
        "token" : auth_data['token'],
        "debitAmount" : 1.00,
        "betTypeID" : 1,
        "serverId" : 102,
        "roundId" : 45364,
        "currency" : auth_data['currency'],
        "seatId" : "s1",
        "platformId" : 1,
        "tableId" : 1,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = previous_credit_response['balance'] - debit_request['debitAmount']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(debit_request, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=debit_request, headers=headers)

    debit_response = response.json()

    #Verify PART I
    test_success = True

    if (not 'operatorId' in debit_response) or (debit_response.get('operatorId') != debit_request["operatorId"]):
        print("FAILED OPERATOR")
        test_success = False
    elif (not 'errorCode' in debit_response) or (debit_response.get('errorCode') != 0):
        print("FAILED ERROR CODE")
        test_success = False
    elif (not 'errorDescription' in debit_response) or (debit_response.get('errorDescription') != 'OK'):
        print("FAILED ERROR DESC")
        test_success = False
    elif (not 'transactionId' in debit_response) or (debit_response.get('transactionId') != debit_request["transactionId"]):
        print("FAILED TRANSACTIONID")
        test_success = False
    elif (not 'token' in debit_response) or (debit_response.get('token') != debit_request["token"]):
        print("FAILED TOKEN")
        test_success = False
    elif (not 'currency' in debit_response) or (debit_response.get('currency') != debit_request["currency"]):
        print("FAILED CURRENCY")
        test_success = False
    elif (not 'uid' in debit_response) or (debit_response.get('uid') != debit_request["uid"]):
        print("FAILED UID")
        test_success = False
    elif (not 'roundId' in debit_response) or (debit_response.get('roundId') != debit_request["roundId"]):
        print("FAILED ROUNDID")
        test_success = False
    elif (not 'balance' in debit_response) or (debit_response.get('balance') != expected_balance):
        print("FAILED BALANCE")
        test_success = False
    elif (not 'nickName' in debit_response) or (debit_response.get('nickName') != auth_data['nickName']):
        print("FAILED NICKNAME")
        test_success = False

    res = "PART I REQUEST:\n" + pretty_json(debit_request) + "\n\nPART I RESPONSE:\n" + pretty_json(debit_response) + "\n"

    if not test_success:
        test_results &= ~0b1000000000000000000
        res = "==== ROLLBACK WITH WRONG AMOUNT FAILED AT PART I ====\n\n" + res + "==== ROLLBACK WITH WRONG AMOUNT TEST FAILED AT PART I  ====\n\n"
        return res


    ###################
    # PART II: Rollback
    ####################
    url = base_url + "rollback"

    rollback_request = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : debit_response['transactionId'],
        "gameId" : debit_request['gameId'],
        "token" : auth_data['token'],
        "rollbackAmount" : 2.0,
        "betTypeID" : 1,
        "serverId" : debit_request['serverId'],
        "roundId" : debit_request['roundId'],
        "currency" : auth_data['currency'],
        "seatId" : debit_request['seatId'],
        "platformId" : debit_request['platformId'],
        "tableId" : debit_request['tableId'],
        "returnReason" : 2,
        "creditIndex" : "1|1",
        "isEndRound" : True,
        "debitTransactionId" : debit_request['transactionId'],
        "timestamp" : get_current_timestamp()
    }

    expected_balance = debit_response['balance']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(rollback_request, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=rollback_request, headers=headers)

    rollback_response = response.json()

    test_data["test_19"]["request"] = rollback_request
    test_data["test_19"]["response"] = rollback_response

    #Verify TEST SUCCESS

    if (not 'operatorId' in rollback_response) or (rollback_response.get('operatorId') !=rollback_request["operatorId"]):
        print("FAILED OPERATOR")
        test_success = False
    elif (not 'errorCode' in rollback_response) or (rollback_response.get('errorCode') != 1):
        print("FAILED ERROR CODE")
        test_success = False
    elif (not 'errorDescription' in rollback_response) or (rollback_response.get('errorDescription') != 'Invalid amount'):
        print("FAILED ERROR DESC")
        test_success = False
    elif (not 'transactionId' in rollback_response) or (rollback_response.get('transactionId') !=rollback_request["transactionId"]):
        print("FAILED TRANSACTIONID")
        test_success = False
    elif (not 'token' in rollback_response) or (rollback_response.get('token') !=rollback_request["token"]):
        print("FAILED TOKEN")
        test_success = False
    elif (not 'currency' in rollback_response) or (rollback_response.get('currency') !=rollback_request["currency"]):
        print("FAILED CURRENCY")
        test_success = False
    elif (not 'uid' in rollback_response) or (rollback_response.get('uid') !=rollback_request["uid"]):
        print("FAILED UID")
        test_success = False
    elif (not 'roundId' in rollback_response) or (rollback_response.get('roundId') !=rollback_request["roundId"]):
        print("FAILED ROUNDID")
        test_success = False
    elif (not 'balance' in rollback_response) or (rollback_response.get('balance') != expected_balance):
        print("FAILED BALANCE")
        test_success = False
    elif (not 'nickName' in rollback_response) or (rollback_response.get('nickName') != auth_data['nickName']):
        print("FAILED NICKNAME")
        test_success = False

    res = "REQUEST:\n" + pretty_json(rollback_request) + "\n\nRESPONSE:\n" + pretty_json(rollback_response) + "\n"

    if test_success:
        test_results |= 0b1000000000000000000
        res = "==== ROLLBACK WITH WRONG AMOUNT TEST SUCCESS ====\n\n" + res + "==== ROLLBACK WITH WRONG AMOUNT TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b1000000000000000000
        res = "==== ROLLBACK WITH WRONG AMOUNT TEST FAILED PART II  ====\n\n" + res + "==== ROLLBACK WITH WRONG AMOUNT TEST FAILED PART II ====\n\n"
    
    return res

def api_test_20():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 19):
        return "Need to pass previous tests"

    ###################
    # PART I: Debit
    ####################
    url = base_url + "debit"

    auth_data = test_data["test_1"]["response"]
    previous_rollback_response = test_data["test_19"]["response"]

    debit_request = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : 1,
        "token" : auth_data['token'],
        "debitAmount" : 1.00,
        "betTypeID" : 1,
        "serverId" : 102,
        "roundId" : 45365,
        "currency" : auth_data['currency'],
        "seatId" : "s1",
        "platformId" : 1,
        "tableId" : 1,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = previous_rollback_response['balance'] - debit_request['debitAmount']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(debit_request, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=debit_request, headers=headers)

    debit_response = response.json()

    #Verify PART I
    test_success = True

    if (not 'operatorId' in debit_response) or (debit_response.get('operatorId') != debit_request["operatorId"]):
        print("FAILED OPERATOR")
        test_success = False
    elif (not 'errorCode' in debit_response) or (debit_response.get('errorCode') != 0):
        print("FAILED ERROR CODE")
        test_success = False
    elif (not 'errorDescription' in debit_response) or (debit_response.get('errorDescription') != 'OK'):
        print("FAILED ERROR DESC")
        test_success = False
    elif (not 'transactionId' in debit_response) or (debit_response.get('transactionId') != debit_request["transactionId"]):
        print("FAILED TRANSACTIONID")
        test_success = False
    elif (not 'token' in debit_response) or (debit_response.get('token') != debit_request["token"]):
        print("FAILED TOKEN")
        test_success = False
    elif (not 'currency' in debit_response) or (debit_response.get('currency') != debit_request["currency"]):
        print("FAILED CURRENCY")
        test_success = False
    elif (not 'uid' in debit_response) or (debit_response.get('uid') != debit_request["uid"]):
        print("FAILED UID")
        test_success = False
    elif (not 'roundId' in debit_response) or (debit_response.get('roundId') != debit_request["roundId"]):
        print("FAILED ROUNDID")
        test_success = False
    elif (not 'balance' in debit_response) or (debit_response.get('balance') != expected_balance):
        print("FAILED BALANCE")
        test_success = False
    elif (not 'nickName' in debit_response) or (debit_response.get('nickName') != auth_data['nickName']):
        print("FAILED NICKNAME")
        test_success = False

    res = "PART I REQUEST:\n" + pretty_json(debit_request) + "\n\nPART I RESPONSE:\n" + pretty_json(debit_response) + "\n"

    if not test_success:
        test_results &= ~0b10000000000000000000
        res = "==== CREDIT WITHOUT DEBIT TRANSACTION ID TEST FAILED AT PART I ====\n\n" + res + "==== CREDIT WITHOUT DEBIT TRANSACTION ID TEST FAILED AT PART I  ====\n\n"
        return res


    ###################
    # PART II: Credit
    ####################
    url = base_url + "credit"

    credit_request = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : debit_request['gameId'],
        "token" : auth_data['token'],
        "creditAmount" : 2.0,
        "betTypeID" : 101,
        "serverId" : debit_request['serverId'],
        "roundId" : debit_request['roundId'],
        "currency" : auth_data['currency'],
        "seatId" : debit_request['seatId'],
        "platformId" : debit_request['platformId'],
        "tableId" : debit_request['tableId'],
        "returnReason" : 0,
        "creditIndex" : "1|1",
        "isEndRound" : True,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = debit_response['balance']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(credit_request, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=credit_request, headers=headers)

    credit_response = response.json()

    test_data["test_20"]["request"] = credit_request
    test_data["test_20"]["response"] = credit_response

    #Verify TEST SUCCESS

    if (not 'operatorId' in credit_response) or (credit_response.get('operatorId') !=credit_request["operatorId"]):
        print("FAILED OPERATOR")
        test_success = False
    elif (not 'errorCode' in credit_response) or (credit_response.get('errorCode') != 9):
        print("FAILED ERROR CODE")
        test_success = False
    elif (not 'errorDescription' in credit_response) or (credit_response.get('errorDescription') != 'Debit transaction ID not found'):
        print("FAILED ERROR DESC")
        test_success = False
    elif (not 'transactionId' in credit_response) or (credit_response.get('transactionId') !=credit_request["transactionId"]):
        print("FAILED TRANSACTIONID")
        test_success = False
    elif (not 'token' in credit_response) or (credit_response.get('token') !=credit_request["token"]):
        print("FAILED TOKEN")
        test_success = False
    elif (not 'currency' in credit_response) or (credit_response.get('currency') !=credit_request["currency"]):
        print("FAILED CURRENCY")
        test_success = False
    elif (not 'uid' in credit_response) or (credit_response.get('uid') !=credit_request["uid"]):
        print("FAILED UID")
        test_success = False
    elif (not 'roundId' in credit_response) or (credit_response.get('roundId') !=credit_request["roundId"]):
        print("FAILED ROUNDID")
        test_success = False
    elif (not 'balance' in credit_response) or (credit_response.get('balance') != expected_balance):
        print("FAILED BALANCE")
        test_success = False
    elif (not 'nickName' in credit_response) or (credit_response.get('nickName') != auth_data['nickName']):
        print("FAILED NICKNAME")
        test_success = False

    res = "REQUEST:\n" + pretty_json(credit_request) + "\n\nRESPONSE:\n" + pretty_json(credit_response) + "\n"

    if test_success:
        test_results |= 0b10000000000000000000
        res = "==== CREDIT WITHOUT DEBIT TRANSACTION ID TEST SUCCESS ====\n\n" + res + "==== CREDIT WITHOUT DEBIT TRANSACTION ID TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b10000000000000000000
        res = "==== CREDIT WITHOUT DEBIT TRANSACTION ID TEST FAILED PART II  ====\n\n" + res + "==== CREDIT WITHOUT DEBIT TRANSACTION ID TEST FAILED PART II ====\n\n"
    
    return res

def api_test_21():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 20):
        return "Need to pass previous tests"

    ###################
    # PART I: Debit
    ####################
    url = base_url + "debit"

    auth_data = test_data["test_1"]["response"]
    previous_credit_response = test_data["test_20"]["response"]

    debit_request = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : 1,
        "token" : auth_data['token'],
        "debitAmount" : 1.00,
        "betTypeID" : 1,
        "serverId" : 102,
        "roundId" : 45366,
        "currency" : auth_data['currency'],
        "seatId" : "s1",
        "platformId" : 1,
        "tableId" : 1,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = previous_credit_response['balance'] - debit_request['debitAmount']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(debit_request, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=debit_request, headers=headers)

    debit_response = response.json()

    #Verify PART I
    test_success = True

    if (not 'operatorId' in debit_response) or (debit_response.get('operatorId') != debit_request["operatorId"]):
        print("FAILED OPERATOR")
        test_success = False
    elif (not 'errorCode' in debit_response) or (debit_response.get('errorCode') != 0):
        print("FAILED ERROR CODE")
        test_success = False
    elif (not 'errorDescription' in debit_response) or (debit_response.get('errorDescription') != 'OK'):
        print("FAILED ERROR DESC")
        test_success = False
    elif (not 'transactionId' in debit_response) or (debit_response.get('transactionId') != debit_request["transactionId"]):
        print("FAILED TRANSACTIONID")
        test_success = False
    elif (not 'token' in debit_response) or (debit_response.get('token') != debit_request["token"]):
        print("FAILED TOKEN")
        test_success = False
    elif (not 'currency' in debit_response) or (debit_response.get('currency') != debit_request["currency"]):
        print("FAILED CURRENCY")
        test_success = False
    elif (not 'uid' in debit_response) or (debit_response.get('uid') != debit_request["uid"]):
        print("FAILED UID")
        test_success = False
    elif (not 'roundId' in debit_response) or (debit_response.get('roundId') != debit_request["roundId"]):
        print("FAILED ROUNDID")
        test_success = False
    elif (not 'balance' in debit_response) or (debit_response.get('balance') != expected_balance):
        print("FAILED BALANCE")
        test_success = False
    elif (not 'nickName' in debit_response) or (debit_response.get('nickName') != auth_data['nickName']):
        print("FAILED NICKNAME")
        test_success = False

    res = "PART I REQUEST:\n" + pretty_json(debit_request) + "\n\nPART I RESPONSE:\n" + pretty_json(debit_response) + "\n"

    if not test_success:
        test_results &= ~0b100000000000000000000
        res = "==== CREDIT WITH EMPTY DEBIT TRANSACTION ID TEST FAILED AT PART I ====\n\n" + res + "==== CREDIT WITH EMPTY DEBIT TRANSACTION ID TEST FAILED AT PART I  ====\n\n"
        return res


    ###################
    # PART II: Credit
    ####################
    url = base_url + "credit"

    credit_request = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : debit_request['gameId'],
        "token" : auth_data['token'],
        "creditAmount" : 2.0,
        "betTypeID" : 101,
        "serverId" : debit_request['serverId'],
        "roundId" : debit_request['roundId'],
        "currency" : auth_data['currency'],
        "seatId" : debit_request['seatId'],
        "platformId" : debit_request['platformId'],
        "tableId" : debit_request['tableId'],
        "debitTransactionId" : "",
        "returnReason" : 0,
        "creditIndex" : "1|1",
        "isEndRound" : True,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = debit_response['balance']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(credit_request, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=credit_request, headers=headers)

    credit_response = response.json()

    test_data["test_21"]["request"] = credit_request
    test_data["test_21"]["response"] = credit_response

    #Verify TEST SUCCESS

    if (not 'operatorId' in credit_response) or (credit_response.get('operatorId') !=credit_request["operatorId"]):
        print("FAILED OPERATOR")
        test_success = False
    elif (not 'errorCode' in credit_response) or (credit_response.get('errorCode') != 9):
        print("FAILED ERROR CODE")
        test_success = False
    elif (not 'errorDescription' in credit_response) or (credit_response.get('errorDescription') != 'Debit transaction ID not found'):
        print("FAILED ERROR DESC")
        test_success = False
    elif (not 'transactionId' in credit_response) or (credit_response.get('transactionId') !=credit_request["transactionId"]):
        print("FAILED TRANSACTIONID")
        test_success = False
    elif (not 'token' in credit_response) or (credit_response.get('token') !=credit_request["token"]):
        print("FAILED TOKEN")
        test_success = False
    elif (not 'currency' in credit_response) or (credit_response.get('currency') !=credit_request["currency"]):
        print("FAILED CURRENCY")
        test_success = False
    elif (not 'uid' in credit_response) or (credit_response.get('uid') !=credit_request["uid"]):
        print("FAILED UID")
        test_success = False
    elif (not 'roundId' in credit_response) or (credit_response.get('roundId') !=credit_request["roundId"]):
        print("FAILED ROUNDID")
        test_success = False
    elif (not 'balance' in credit_response) or (credit_response.get('balance') != expected_balance):
        print("FAILED BALANCE")
        test_success = False
    elif (not 'nickName' in credit_response) or (credit_response.get('nickName') != auth_data['nickName']):
        print("FAILED NICKNAME")
        test_success = False

    res = "REQUEST:\n" + pretty_json(credit_request) + "\n\nRESPONSE:\n" + pretty_json(credit_response) + "\n"

    if test_success:
        test_results |= 0b100000000000000000000
        res = "==== CREDIT WITH EMPTY DEBIT TRANSACTION ID TEST SUCCESS ====\n\n" + res + "==== CREDIT WITH EMPTY DEBIT TRANSACTION ID TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b100000000000000000000
        res = "==== CREDIT WITH EMPTY DEBIT TRANSACTION ID TEST FAILED PART II  ====\n\n" + res + "==== CREDIT WITH EMPTY DEBIT TRANSACTION ID TEST FAILED PART II ====\n\n"
    
    return res

def api_test_22():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 21):
        return "Need to pass previous tests"

    ###################
    # PART I: Debit
    ####################
    url = base_url + "debit"

    auth_data = test_data["test_1"]["response"]
    previous_credit_response = test_data["test_21"]["response"]

    debit_request = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : 1,
        "token" : auth_data['token'],
        "debitAmount" : 1.00,
        "betTypeID" : 1,
        "serverId" : 102,
        "roundId" : 45367,
        "currency" : auth_data['currency'],
        "seatId" : "s1",
        "platformId" : 1,
        "tableId" : 1,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = previous_credit_response['balance'] - debit_request['debitAmount']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(debit_request, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=debit_request, headers=headers)

    debit_response = response.json()

    #Verify PART I
    test_success = True

    if (not 'operatorId' in debit_response) or (debit_response.get('operatorId') != debit_request["operatorId"]):
        print("FAILED OPERATOR")
        test_success = False
    elif (not 'errorCode' in debit_response) or (debit_response.get('errorCode') != 0):
        print("FAILED ERROR CODE")
        test_success = False
    elif (not 'errorDescription' in debit_response) or (debit_response.get('errorDescription') != 'OK'):
        print("FAILED ERROR DESC")
        test_success = False
    elif (not 'transactionId' in debit_response) or (debit_response.get('transactionId') != debit_request["transactionId"]):
        print("FAILED TRANSACTIONID")
        test_success = False
    elif (not 'token' in debit_response) or (debit_response.get('token') != debit_request["token"]):
        print("FAILED TOKEN")
        test_success = False
    elif (not 'currency' in debit_response) or (debit_response.get('currency') != debit_request["currency"]):
        print("FAILED CURRENCY")
        test_success = False
    elif (not 'uid' in debit_response) or (debit_response.get('uid') != debit_request["uid"]):
        print("FAILED UID")
        test_success = False
    elif (not 'roundId' in debit_response) or (debit_response.get('roundId') != debit_request["roundId"]):
        print("FAILED ROUNDID")
        test_success = False
    elif (not 'balance' in debit_response) or (debit_response.get('balance') != expected_balance):
        print("FAILED BALANCE")
        test_success = False
    elif (not 'nickName' in debit_response) or (debit_response.get('nickName') != auth_data['nickName']):
        print("FAILED NICKNAME")
        test_success = False

    res = "PART I REQUEST:\n" + pretty_json(debit_request) + "\n\nPART I RESPONSE:\n" + pretty_json(debit_response) + "\n"

    if not test_success:
        test_results &= ~0b1000000000000000000000
        res = "==== CREDIT WITH DEBIT TRANSACTION NEVER PROCESSED TEST FAILED AT PART I ====\n\n" + res + "==== CREDIT WITH DEBIT TRANSACTION NEVER PROCESSED TEST FAILED AT PART I  ====\n\n"
        return res


    ###################
    # PART II: First Credit
    ####################
    url = base_url + "credit"

    credit_request = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : debit_request['gameId'],
        "token" : auth_data['token'],
        "creditAmount" : 2.0,
        "betTypeID" : 101,
        "serverId" : debit_request['serverId'],
        "roundId" : debit_request['roundId'],
        "currency" : auth_data['currency'],
        "seatId" : debit_request['seatId'],
        "platformId" : debit_request['platformId'],
        "tableId" : debit_request['tableId'],
        "debitTransactionId" : generate_transaction_id(), #creating invalid transaction id
        "returnReason" : 0,
        "creditIndex" : "1|1",
        "isEndRound" : True,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = debit_response['balance']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(credit_request, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=credit_request, headers=headers)

    credit_response = response.json()

    test_data["test_22"]["request"] = credit_request
    test_data["test_22"]["response"] = credit_response

    #Verify TEST SUCCESS

    if (not 'operatorId' in credit_response) or (credit_response.get('operatorId') !=credit_request["operatorId"]):
        print("FAILED OPERATOR")
        test_success = False
    elif (not 'errorCode' in credit_response) or (credit_response.get('errorCode') != 9):
        print("FAILED ERROR CODE")
        test_success = False
    elif (not 'errorDescription' in credit_response) or (credit_response.get('errorDescription') != 'Debit transaction ID not found'):
        print("FAILED ERROR DESC")
        test_success = False
    elif (not 'transactionId' in credit_response) or (credit_response.get('transactionId') !=credit_request["transactionId"]):
        print("FAILED TRANSACTIONID")
        test_success = False
    elif (not 'token' in credit_response) or (credit_response.get('token') !=credit_request["token"]):
        print("FAILED TOKEN")
        test_success = False
    elif (not 'currency' in credit_response) or (credit_response.get('currency') !=credit_request["currency"]):
        print("FAILED CURRENCY")
        test_success = False
    elif (not 'uid' in credit_response) or (credit_response.get('uid') !=credit_request["uid"]):
        print("FAILED UID")
        test_success = False
    elif (not 'roundId' in credit_response) or (credit_response.get('roundId') !=credit_request["roundId"]):
        print("FAILED ROUNDID")
        test_success = False
    elif (not 'balance' in credit_response) or (credit_response.get('balance') != expected_balance):
        print("FAILED BALANCE")
        test_success = False
    elif (not 'nickName' in credit_response) or (credit_response.get('nickName') != auth_data['nickName']):
        print("FAILED NICKNAME")
        test_success = False

    res = "REQUEST:\n" + pretty_json(credit_request) + "\n\nRESPONSE:\n" + pretty_json(credit_response) + "\n"

    if test_success:
        test_results |= 0b1000000000000000000000
        res = "==== CREDIT WITH NEVER PROCESSED DEBIT TRANSACTION TEST SUCCESS ====\n\n" + res + "==== CREDIT WITH NEVER PROCESSED DEBIT TRANSACTION TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b1000000000000000000000
        res = "==== CREDIT WITH NEVER PROCESSED DEBIT TRANSACTION ID TEST FAILED PART II  ====\n\n" + res + "==== CREDIT WITH NEVER PROCESSED DEBIT TRANSACTION TEST FAILED PART II ====\n\n"
    
    return res

def api_test_23():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 22):
        return "Need to pass previous tests"

    ###################
    # PART I: Debit
    ####################
    url = base_url + "debit"

    auth_data = test_data["test_1"]["response"]
    previous_credit_response = test_data["test_22"]["response"]

    debit_request = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : 1,
        "token" : auth_data['token'],
        "debitAmount" : 1.00,
        "betTypeID" : 1,
        "serverId" : 102,
        "roundId" : 45368,
        "currency" : auth_data['currency'],
        "seatId" : "s1",
        "platformId" : 1,
        "tableId" : 1,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = previous_credit_response['balance'] - debit_request['debitAmount']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(debit_request, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=debit_request, headers=headers)

    debit_response = response.json()

    #Verify PART I
    test_success = True

    if (not 'operatorId' in debit_response) or (debit_response.get('operatorId') != debit_request["operatorId"]):
        print("FAILED OPERATOR")
        test_success = False
    elif (not 'errorCode' in debit_response) or (debit_response.get('errorCode') != 0):
        print("FAILED ERROR CODE")
        test_success = False
    elif (not 'errorDescription' in debit_response) or (debit_response.get('errorDescription') != 'OK'):
        print("FAILED ERROR DESC")
        test_success = False
    elif (not 'transactionId' in debit_response) or (debit_response.get('transactionId') != debit_request["transactionId"]):
        print("FAILED TRANSACTIONID")
        test_success = False
    elif (not 'token' in debit_response) or (debit_response.get('token') != debit_request["token"]):
        print("FAILED TOKEN")
        test_success = False
    elif (not 'currency' in debit_response) or (debit_response.get('currency') != debit_request["currency"]):
        print("FAILED CURRENCY")
        test_success = False
    elif (not 'uid' in debit_response) or (debit_response.get('uid') != debit_request["uid"]):
        print("FAILED UID")
        test_success = False
    elif (not 'roundId' in debit_response) or (debit_response.get('roundId') != debit_request["roundId"]):
        print("FAILED ROUNDID")
        test_success = False
    elif (not 'balance' in debit_response) or (debit_response.get('balance') != expected_balance):
        print("FAILED BALANCE")
        test_success = False
    elif (not 'nickName' in debit_response) or (debit_response.get('nickName') != auth_data['nickName']):
        print("FAILED NICKNAME")
        test_success = False

    res = "PART I REQUEST:\n" + pretty_json(debit_request) + "\n\nPART I RESPONSE:\n" + pretty_json(debit_response) + "\n"

    if not test_success:
        test_results &= ~0b10000000000000000000000
        res = "==== CREDIT WITH DEBIT TRANSACTION ALREADY PROCESSED TEST FAILED AT PART I ====\n\n" + res + "==== CREDIT WITH DEBIT TRANSACTION ALREADY PROCESSED TEST FAILED AT PART I  ====\n\n"
        return res


    ###################
    # PART II: First Credit
    ####################
    url = base_url + "credit"

    credit_request = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : debit_request['gameId'],
        "token" : auth_data['token'],
        "creditAmount" : 2.0,
        "betTypeID" : 101,
        "serverId" : debit_request['serverId'],
        "roundId" : debit_request['roundId'],
        "currency" : auth_data['currency'],
        "seatId" : debit_request['seatId'],
        "platformId" : debit_request['platformId'],
        "tableId" : debit_request['tableId'],
        "debitTransactionId" : debit_request['transactionId'],
        "returnReason" : 0,
        "creditIndex" : "1|1",
        "isEndRound" : True,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = debit_response['balance'] + credit_request['creditAmount']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(credit_request, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=credit_request, headers=headers)

    credit_response = response.json()

    #Verify TEST SUCCESS

    if (not 'operatorId' in credit_response) or (credit_response.get('operatorId') !=credit_request["operatorId"]):
        print("FAILED OPERATOR")
        test_success = False
    elif (not 'errorCode' in credit_response) or (credit_response.get('errorCode') != 0):
        print("FAILED ERROR CODE")
        test_success = False
    elif (not 'errorDescription' in credit_response) or (credit_response.get('errorDescription') != 'OK'):
        print("FAILED ERROR DESC")
        test_success = False
    elif (not 'transactionId' in credit_response) or (credit_response.get('transactionId') !=credit_request["transactionId"]):
        print("FAILED TRANSACTIONID")
        test_success = False
    elif (not 'token' in credit_response) or (credit_response.get('token') !=credit_request["token"]):
        print("FAILED TOKEN")
        test_success = False
    elif (not 'currency' in credit_response) or (credit_response.get('currency') !=credit_request["currency"]):
        print("FAILED CURRENCY")
        test_success = False
    elif (not 'uid' in credit_response) or (credit_response.get('uid') !=credit_request["uid"]):
        print("FAILED UID")
        test_success = False
    elif (not 'roundId' in credit_response) or (credit_response.get('roundId') !=credit_request["roundId"]):
        print("FAILED ROUNDID")
        test_success = False
    elif (not 'balance' in credit_response) or (credit_response.get('balance') != expected_balance):
        print("FAILED BALANCE")
        test_success = False
    elif (not 'nickName' in credit_response) or (credit_response.get('nickName') != auth_data['nickName']):
        print("FAILED NICKNAME")
        test_success = False

    res = "PART II REQUEST:\n" + pretty_json(credit_request) + "\n\nPART I RESPONSE:\n" + pretty_json(credit_response) + "\n"

    if not test_success:
        test_results &= ~0b10000000000000000000000
        res = "==== CREDIT WITH DEBIT TRANSACTION ALREADY PROCESSED TEST FAILED AT PART II ====\n\n" + res + "==== CREDIT WITH DEBIT TRANSACTION ALREADY PROCESSED TEST FAILED AT PART I  ====\n\n"
        return res

    ###################
    # PART III: Second repeated credit
    ####################
    url = base_url + "credit"

    credit_request = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : debit_request['gameId'],
        "token" : auth_data['token'],
        "creditAmount" : 2.0,
        "betTypeID" : 101,
        "serverId" : debit_request['serverId'],
        "roundId" : debit_request['roundId'],
        "currency" : auth_data['currency'],
        "seatId" : debit_request['seatId'],
        "platformId" : debit_request['platformId'],
        "tableId" : debit_request['tableId'],
        "debitTransactionId" : debit_request['transactionId'],
        "returnReason" : 0,
        "creditIndex" : "1|1",
        "isEndRound" : True,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = credit_response['balance']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(credit_request, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=credit_request, headers=headers)

    credit_response = response.json()

    test_data["test_23"]["request"] = credit_request
    test_data["test_23"]["response"] = credit_response

    #Verify TEST SUCCESS

    if (not 'operatorId' in credit_response) or (credit_response.get('operatorId') !=credit_request["operatorId"]):
        print("FAILED OPERATOR")
        test_success = False
    elif (not 'errorCode' in credit_response) or (credit_response.get('errorCode') != 1):
        print("FAILED ERROR CODE")
        test_success = False
    elif (not 'errorDescription' in credit_response) or (credit_response.get('errorDescription') != 'Debit transaction already processed'):
        print("FAILED ERROR DESC")
        test_success = False
    elif (not 'transactionId' in credit_response) or (credit_response.get('transactionId') !=credit_request["transactionId"]):
        print("FAILED TRANSACTIONID")
        test_success = False
    elif (not 'token' in credit_response) or (credit_response.get('token') !=credit_request["token"]):
        print("FAILED TOKEN")
        test_success = False
    elif (not 'currency' in credit_response) or (credit_response.get('currency') !=credit_request["currency"]):
        print("FAILED CURRENCY")
        test_success = False
    elif (not 'uid' in credit_response) or (credit_response.get('uid') !=credit_request["uid"]):
        print("FAILED UID")
        test_success = False
    elif (not 'roundId' in credit_response) or (credit_response.get('roundId') !=credit_request["roundId"]):
        print("FAILED ROUNDID")
        test_success = False
    elif (not 'balance' in credit_response) or (credit_response.get('balance') != expected_balance):
        print("FAILED BALANCE")
        test_success = False
    elif (not 'nickName' in credit_response) or (credit_response.get('nickName') != auth_data['nickName']):
        print("FAILED NICKNAME")
        test_success = False

    res = "PART II REQUEST:\n" + pretty_json(credit_request) + "\n\nPART I RESPONSE:\n" + pretty_json(credit_response) + "\n"

    if test_success:
        test_results |= 0b10000000000000000000000
        res = "==== CREDIT WITH ALREADY PROCESSED DEBIT TRANSACTION TEST SUCCESS ====\n\n" + res + "==== CREDIT WITH ALREADY PROCESSED PROCESSED DEBIT TRANSACTION TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b10000000000000000000000
        res = "==== CREDIT WITH ALREADY PROCESSED DEBIT TRANSACTION TEST FAILED PART III  ====\n\n" + res + "==== CREDIT WITH ALREADY PROCESSED DEBIT TRANSACTION TEST FAILED PART III ====\n\n"


    return res

def api_test_24():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 23):
        return "Need to pass previous tests"

    auth_data = test_data["test_1"]["response"]
    credit_response = test_data["test_23"]["response"]

    # The API endpoint
    
    url = base_url + "debit"

    data = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : 1,
        "token" : auth_data['token'],
        "debitAmount" : 1.0,
        "betTypeID" : 89,
        "serverId" : 102,
        "roundId" : 198613,
        "currency" : auth_data['currency'],
        "seatId" : "s6",
        "platformId" : 0,
        "tableId" : 1,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = credit_response['balance']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)

    json_response = response.json()


    test_data["test_24"]["request"] = data
    test_data["test_24"]["response"] = json_response

    #Verify TEST SUCCESS

    test_success = True

    if (not 'operatorId' in json_response) or (json_response.get('operatorId') != data["operatorId"]):
        test_success = False
    elif (not 'errorCode' in json_response) or (json_response.get('errorCode') != 1):
        test_success = False
    elif (not 'errorDescription' in json_response) or (json_response.get('errorDescription') != 'Invalid Bet Type'):
        test_success = False
    elif (not 'transactionId' in json_response) or (json_response.get('transactionId') != data["transactionId"]):
        test_success = False
    elif (not 'token' in json_response) or (json_response.get('token') != data["token"]):
        test_success = False
    elif (not 'currency' in json_response) or (json_response.get('currency') != data["currency"]):
        test_success = false
    elif (not 'uid' in json_response) or (json_response.get('uid') != data["uid"]):
        test_success = False
    elif (not 'roundId' in json_response) or (json_response.get('roundId') != data["roundId"]):
        test_success = False
    elif (not 'balance' in json_response) or (json_response.get('balance') != expected_balance):
        test_success = False

    res = "REQUEST:\n" + pretty_json(data) + "\n\nRESPONSE:\n" + pretty_json(json_response) + "\n"

    if test_success:
        test_results |= 0b100000000000000000000000
        res = "==== INVALID BET TYPE TEST SUCCESS ====\n\n" + res + "==== INVALID BET TYPE TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b100000000000000000000000
        res = "==== INVALID BET TYPE TEST FAILED  ====\n\n" + res + "==== INVALID BET TYPE TEST FAILED ====\n\n"
    
    return res

def api_test_25():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 24):
        return "Need to pass previous tests"

    auth_data = test_data["test_1"]["response"]
    debit_response = test_data["test_24"]["response"]

    # The API endpoint
    
    url = base_url + "debit"

    data = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : 919,
        "token" : auth_data['token'],
        "debitAmount" : 1.99,
        "betTypeID" : 1,
        "serverId" : 102,
        "roundId" : 198612,
        "currency" : auth_data['currency'],
        "seatId" : "s6",
        "platformId" : 0,
        "tableId" : 1,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = debit_response['balance']

    headers = {
            'content-type': 'application/json',
            'hash' :  generate_base64_encoded_hmac(data, secret_key)
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)

    json_response = response.json()


    test_data["test_25"]["request"] = data
    test_data["test_25"]["response"] = json_response

    #Verify TEST SUCCESS

    test_success = True

    if (not 'operatorId' in json_response) or (json_response.get('operatorId') != data["operatorId"]):
        test_success = False
    elif (not 'errorCode' in json_response) or (json_response.get('errorCode') != 1):
        test_success = False
    elif (not 'errorDescription' in json_response) or (json_response.get('errorDescription') != 'Unknown Game ID'):
        test_success = False
    elif (not 'transactionId' in json_response) or (json_response.get('transactionId') != data["transactionId"]):
        test_success = False
    elif (not 'token' in json_response) or (json_response.get('token') != data["token"]):
        test_success = False
    elif (not 'currency' in json_response) or (json_response.get('currency') != data["currency"]):
        test_success = false
    elif (not 'uid' in json_response) or (json_response.get('uid') != data["uid"]):
        test_success = False
    elif (not 'roundId' in json_response) or (json_response.get('roundId') != data["roundId"]):
        test_success = False
    elif (not 'balance' in json_response) or (json_response.get('balance') != expected_balance):
        test_success = False

    res = "REQUEST:\n" + pretty_json(data) + "\n\nRESPONSE:\n" + pretty_json(json_response) + "\n"

    if test_success:
        test_results |= 0b1000000000000000000000000
        res = "==== UNKNOWN GAME TEST SUCCESS ====\n\n" + res + "==== UNKNOWN GAME TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b1000000000000000000000000
        res = "==== UNKNOWN GAME TEST FAILED  ====\n\n" + res + "==== UNKNOWN GAME TEST FAILED ====\n\n"
    
    return res

def api_test_26():
    global test_data
    global test_results
    global secret_key

    if not allOnes(test_results, 25):
        return "Need to pass previous tests"

    auth_data = test_data["test_1"]["response"]
    debit_response = test_data["test_25"]["response"]

    # The API endpoint
    
    url = base_url + "debit"

    data = {
        "operatorId" : auth_data['operatorId'],
        "uid" : auth_data['uid'],
        "transactionId" : generate_transaction_id(),
        "gameId" : 1,
        "token" : auth_data['token'],
        "debitAmount" : 1.99,
        "betTypeID" : 1,
        "serverId" : 102,
        "roundId" : 198612,
        "currency" : auth_data['currency'],
        "seatId" : "s6",
        "platformId" : 0,
        "tableId" : 1,
        "timestamp" : get_current_timestamp()
    }

    expected_balance = 0.0

    headers = {
            'content-type': 'application/json'
    }

    # A POST request to the API
    response = requests.post(url, json=data, headers=headers)

    json_response = response.json()


    test_data["test_25"]["request"] = data
    test_data["test_25"]["response"] = json_response

    #Verify TEST SUCCESS

    test_success = True

    if (not 'operatorId' in json_response) or (json_response.get('operatorId') != data["operatorId"]):
        test_success = False
    elif (not 'errorCode' in json_response) or (json_response.get('errorCode') != 1):
        test_success = False
    elif (not 'errorDescription' in json_response) or (json_response.get('errorDescription') != 'Invalid Hash'):
        test_success = False
    elif (not 'transactionId' in json_response) or (json_response.get('transactionId') != data["transactionId"]):
        test_success = False
    elif (not 'token' in json_response) or (json_response.get('token') != data["token"]):
        test_success = False
    elif (not 'currency' in json_response) or (json_response.get('currency') != data["currency"]):
        test_success = false
    elif (not 'uid' in json_response) or (json_response.get('uid') != data["uid"]):
        test_success = False
    elif (not 'roundId' in json_response) or (json_response.get('roundId') != data["roundId"]):
        test_success = False
    elif (not 'balance' in json_response) or (json_response.get('balance') != expected_balance):
        test_success = False

    res = "REQUEST:\n" + pretty_json(data) + "\n\nRESPONSE:\n" + pretty_json(json_response) + "\n"

    if test_success:
        test_results |= 0b1000000000000000000000000
        res = "==== INVALID HASH TEST SUCCESS ====\n\n" + res + "==== INVALID HASH TEST SUCCESS ====\n\n"
    else:
        test_results &= ~0b1000000000000000000000000
        res = "==== INVALID HASH TEST FAILED  ====\n\n" + res + "=== INVALID HASH TEST FAILED ====\n\n"
    
    return res


def process_input(input_res):
    global username
    global password
    global launch_token

    if (input_res == 'launch'):
        return launch()
    elif (input_res == 'auth'):
        return auth()
    elif (input_res == 'init'):
        launch_token = input("Enter launch token: " )
    elif (input_res == 'debit'):
        return debit()
    elif (input_res == 'credit'):
        return credit()
    elif (input_res == 'rollback'):
        return rollback()
    elif (input_res == 'getNewToken'):
        return getNewToken()
    elif (input_res == 'test all'):
        res_str = api_test_1()
        res_str += "\n\n" + api_test_2()
        res_str += "\n\n" + api_test_3()
        res_str += "\n\n" + api_test_4()
        res_str += "\n\n" + api_test_5()
        res_str += "\n\n" + api_test_6()
        res_str += "\n\n" + api_test_7()
        res_str += "\n\n" + api_test_8()
        res_str += "\n\n" + api_test_9()
        res_str += "\n\n" + api_test_10()
        res_str += "\n\n" + api_test_11()
        res_str += "\n\n" + api_test_12()
        res_str += "\n\n" + api_test_13()
        res_str += "\n\n" + api_test_14()
        res_str += "\n\n" + api_test_15()
        res_str += "\n\n" + api_test_16()
        res_str += "\n\n" + api_test_17()
        res_str += "\n\n" + api_test_18()
        res_str += "\n\n" + api_test_19()
        res_str += "\n\n" + api_test_20()
        res_str += "\n\n" + api_test_21()
        res_str += "\n\n" + api_test_22()
        res_str += "\n\n" + api_test_23()
        res_str += "\n\n" + api_test_24()
        res_str += "\n\n" + api_test_25()
        res_str += "\n\n" + api_test_26()
        return res_str
    elif (input_res == 'test1'):
        return api_test_1()
    elif (input_res == 'test2'):
        return api_test_2()
    elif (input_res == 'test3'):
        return api_test_3()
    elif (input_res == 'test4'):
        return api_test_4()
    elif (input_res == 'test5'):
        return api_test_5()
    elif (input_res == 'test6'):
        return api_test_6()
    elif (input_res == 'test7'):
        return api_test_7()
    elif (input_res == 'test8'):
        return api_test_8()
    elif (input_res == 'test9'):
        return api_test_9()
    elif (input_res == 'test10'):
        return api_test_10()
    elif (input_res == 'test11'):
        return api_test_11()
    elif (input_res == 'test12'):
        return api_test_12()
    elif (input_res == 'test13'):
        return api_test_13()
    elif (input_res == 'test14'):
        return api_test_14()
    elif (input_res == 'test15'):
        return api_test_15()
    elif (input_res == 'test16'):
        return api_test_16()
    elif (input_res == 'test17'):
        return api_test_17()
    elif (input_res == 'test18'):
        return api_test_18()
    elif (input_res == 'test19'):
        return api_test_19()
    elif (input_res == 'test20'):
        return api_test_20()
    elif (input_res == 'test21'):
        return api_test_21()
    elif (input_res == 'test22'):
        return api_test_22()
    elif (input_res == 'test23'):
        return api_test_23()
    elif (input_res == 'test24'):
        return api_test_24()


    elif (input_res == 'exit'):
        return "bye"
    elif (input_res == "hmac"):
        newHmacStr = test_hmac(secret_key, "{\"platformId\":0,\"operatorId\":10907001,\"token\":\"1LFbtMR9jZGlnbUENaQAuZk9jD8o\",\"timestamp\":1715284950805}")
        oldHmacStr = generate_base64_encoded_hmac("{\"platformId\":0,\"operatorId\":10907001,\"token\":\"1LFbtMR9jZGlnbUENaQAuZk9jD8o\",\"timestamp\":1715284950805}", secret_key)
        return "OLDHMAC: " + oldHmacStr + "\nNEWHMAC: " +newHmacStr
        #EyKo9xBdLMxkFxIafw273SUaAHVA72Xf23AOTYkxmFU=
    elif (input_res == 'login'):
        username = input("Enter username: " )
        password = input("Enter password:")
    else:
        return "Invalid action";

res = "ok"
while (res != "exit"):
    res = input("Write the name of the API Action: ")
    print(process_input(res))
