diff --git a/__pycache__/balance_accounts.cpython-311.pyc b/__pycache__/balance_accounts.cpython-311.pyc deleted file mode 100644 index 0ee0867..0000000 Binary files a/__pycache__/balance_accounts.cpython-311.pyc and /dev/null differ diff --git a/__pycache__/credentials.cpython-311.pyc b/__pycache__/credentials.cpython-311.pyc deleted file mode 100644 index 4acc2f7..0000000 Binary files a/__pycache__/credentials.cpython-311.pyc and /dev/null differ diff --git a/__pycache__/earn_binance.cpython-311.pyc b/__pycache__/earn_binance.cpython-311.pyc deleted file mode 100644 index cc4ae71..0000000 Binary files a/__pycache__/earn_binance.cpython-311.pyc and /dev/null differ diff --git a/__pycache__/earn_gateio.cpython-311.pyc b/__pycache__/earn_gateio.cpython-311.pyc deleted file mode 100644 index 6f2d743..0000000 Binary files a/__pycache__/earn_gateio.cpython-311.pyc and /dev/null differ diff --git a/__pycache__/earn_kucoin.cpython-311.pyc b/__pycache__/earn_kucoin.cpython-311.pyc deleted file mode 100644 index e87ee8c..0000000 Binary files a/__pycache__/earn_kucoin.cpython-311.pyc and /dev/null differ diff --git a/__pycache__/earn_okx.cpython-311.pyc b/__pycache__/earn_okx.cpython-311.pyc deleted file mode 100644 index 1c61d95..0000000 Binary files a/__pycache__/earn_okx.cpython-311.pyc and /dev/null differ diff --git a/libraries/wrappers/__pycache__/earn_gateio.cpython-311.pyc b/libraries/wrappers/__pycache__/earn_gateio.cpython-311.pyc index e724e5a..bc7504f 100644 Binary files a/libraries/wrappers/__pycache__/earn_gateio.cpython-311.pyc and b/libraries/wrappers/__pycache__/earn_gateio.cpython-311.pyc differ diff --git a/libraries/wrappers/__pycache__/earn_kucoin.cpython-311.pyc b/libraries/wrappers/__pycache__/earn_kucoin.cpython-311.pyc index ab955c0..556ba30 100644 Binary files a/libraries/wrappers/__pycache__/earn_kucoin.cpython-311.pyc and b/libraries/wrappers/__pycache__/earn_kucoin.cpython-311.pyc differ diff --git a/libraries/wrappers/earn_binance.py b/libraries/wrappers/earn_binance.py index 9e5f316..3195580 100644 --- a/libraries/wrappers/earn_binance.py +++ b/libraries/wrappers/earn_binance.py @@ -19,7 +19,7 @@ class binance_earn: account = self.client.account() for item in account["balances"]: if item["asset"]==coin: - return item["free"] + return {coin: item["free"]} def get_available_products(self, coin): diff --git a/libraries/wrappers/earn_gateio.py b/libraries/wrappers/earn_gateio.py index 2bdcb39..9339d2f 100644 --- a/libraries/wrappers/earn_gateio.py +++ b/libraries/wrappers/earn_gateio.py @@ -4,49 +4,152 @@ https://www.gate.io/docs/developers/apiv4/#earnuni # Implement from scratch, gateio python connector is AWFUL. +import time +import hashlib +import hmac +import requests +import json from credentials import get_api_key + class gateio_earn: def __init__(self): - api_key, api_secret = get_api_key("gateio") + self.api_key, self.api_secret = get_api_key("gateio") + self.host = "https://api.gateio.ws" + self.prefix = "/api/v4" + + + def gen_sign(self, method, url, query_string=None, payload_string=None): + ''' + Generates a signature for the API request + From Gate.io API docs + ''' + + t = time.time() + m = hashlib.sha512() + m.update((payload_string or "").encode("utf-8")) + hashed_payload = m.hexdigest() + s = '%s\n%s\n%s\n%s\n%s' % (method, url, query_string or "", hashed_payload, t) + sign = hmac.new(self.api_secret.encode('utf-8'), s.encode('utf-8'), hashlib.sha512).hexdigest() + return {'KEY': self.api_key, 'Timestamp': str(t), 'SIGN': sign} def get_trading_balance(self, coin): ''' Returns the free available balance of a coin in the trading account (or the equivalent account in the exchange) ''' - return {"Error": "To be implemented"} + url = f"/spot/accounts" + query_param = "" + headers = {"Accept": "application/json", "Content-Type": "application/json"} + sign_headers = self.gen_sign("GET", self.prefix+url, query_param) + headers.update(sign_headers) + response = requests.get(self.host+self.prefix+url, params=query_param, headers=headers) + if response.status_code == 200: + for item in response.json(): + if item["currency"] == coin: + return {coin: item["available"]} + return {"Error": "Coin not found"} + else: + return {"Error": response.text} def get_available_products(self,coin): - return {"Error": "To be implemented"} + url = "/earn/uni/currencies" + headers = {"Accept": "application/json", "Content-Type": "application/json"} + query_param = "" + sign_headers = self.gen_sign("GET", self.prefix+url, query_param) + headers.update(sign_headers) + response = requests.get(self.host+self.prefix+url, params=query_param, headers=sign_headers) + if response.status_code == 200: + return response.json() + else: + return {"Error": response.text} + def get_product_detail(self,coin): - return {"Error": "To be implemented"} + url = f"/earn/uni/currencies/{coin}" + headers = {"Accept": "application/json", "Content-Type": "application/json"} + sign_headers = self.gen_sign("GET", self.prefix+url) + headers.update(sign_headers) + response = requests.get(self.host+self.prefix+url, headers=sign_headers) + if response.status_code == 200: + return response.json() + else: + return {"Error": response.text} + def subscribe_product(self, coin, amount, rate): - return {"Error": "To be implemented"} + url = "/earn/uni/lends" + headers = {"Accept": "application/json", "Content-Type": "application/json"} + query_params = "" + body = {"currency": coin, "amount": str(amount), "min_rate": rate, "type": "lend"} + sign_headers = self.gen_sign("POST", self.prefix+url, query_params, body) + headers.update(sign_headers) + response = requests.post(self.host+self.prefix+url, headers=sign_headers, data=body) + if response.status_code == 200: + return response.json() + else: + return {"Error": response.text} + + + def redeem_product(self, coin, amount, rate): + url = "/earn/uni/lends" + headers = {"Accept": "application/json", "Content-Type": "application/json"} + query_params = "" + body = {"currency": coin, "amount": str(amount), "min_rate": rate, "type": "redeem"} + sign_headers = self.gen_sign("POST", self.prefix+url, query_params, body) + headers.update(sign_headers) + response = requests.post(self.host+self.prefix+url, headers=sign_headers, data=body) + if response.status_code == 200: + return response.json() + else: + return {"Error": response.text} - def redeem_product(self, product_id, redeem_all=True, amount=0, destination_account="SPOT"): - return {"Error": "To be implemented"} def get_position(self, **kwargs): return {"Error": "To be implemented"} - def get_account(self, coin, recv_window=5000): - return {"Error": "To be implemented"} + + def get_account(self): + url = f"/earn/uni/lends" + headers = {"Accept": "application/json", "Content-Type": "application/json"} + sign_headers = self.gen_sign("GET", self.prefix+url) + headers.update(sign_headers) + response = requests.get(self.host+self.prefix+url, headers=sign_headers) + if response.status_code == 200: + return response.json() + else: + return {"Error": response.text} + + + def amend_rate(self,coin,min_rate): + url = f"/earn/uni/lends" + body = {"currency": coin, "min_rate": min_rate} + headers = {"Accept": "application/json", "Content-Type": "application/json"} + sign_headers = self.gen_sign("PATCH", self.prefix+url, body) + headers.update(sign_headers) + response = requests.patch(self.host+self.prefix+url, headers=headers, data=body) + if response.status_code == 200: + return response.json() + else: + return {"Error": response.text} + def get_personal_left_quota(self, product_id, **kwargs): return {"Error": "To be implemented"} + def get_subscription_record(self, **kwargs): return {"Error": "To be implemented"} + def get_redemption_record(self, **kwargs): return {"Error": "To be implemented"} + def get_rewards_history(self, type="ALL", **kwargs): return {"Error": "To be implemented"} + def get_subscription_preview(self, product_id, amount, **kwargs): return {"Error": "To be implemented"} \ No newline at end of file diff --git a/libraries/wrappers/earn_kucoin.py b/libraries/wrappers/earn_kucoin.py index e2c1a9d..d4cf826 100644 --- a/libraries/wrappers/earn_kucoin.py +++ b/libraries/wrappers/earn_kucoin.py @@ -51,7 +51,7 @@ class kucoin_earn: request = GetSpotAccountListReqBuilder().set_currency(coin).set_type("trade").build() response = self.account_api().get_spot_account_list(request) balance = response.to_dict()["data"][0]["available"] - return balance + return {coin: balance} def get_available_products(self, coin): diff --git a/libraries/wrappers/earn_okx.py b/libraries/wrappers/earn_okx.py index a2502fb..97721a7 100644 --- a/libraries/wrappers/earn_okx.py +++ b/libraries/wrappers/earn_okx.py @@ -26,16 +26,16 @@ class okx_earn: balances = self.account_api.get_account_balance() for item in balances["data"][0]["details"]: if item["ccy"] == coin: - return item["availBal"] - return 0.0 + return {coin: item["availBal"]} + return {"Error": "Coin not found"} def get_funding_balance(self, coin): balances = self.funding_api.get_balances() for item in balances["data"]: if item["ccy"] == coin: - return item["availBal"] - return 0.0 + return {coin: item["availBal"]} + return {"Error": "Coin not found"} def transfer_to_funding(self,coin,amount): diff --git a/main.py b/main.py index 3db1a07..fc032e6 100644 --- a/main.py +++ b/main.py @@ -12,6 +12,6 @@ gateio = earn_gateio.gateio_earn() if __name__=="__main__": #Available products - print(gateio.get_product_detail("USDT")) + print(gateio.get_trading_balance("USDT"))