Created
March 21, 2026 16:04
-
-
Save SmartFinn/33f26f464069d8cad2baa0c334945921 to your computer and use it in GitHub Desktop.
Get withdraw fees from HitBTC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| Created on Fri, 15 Dec 2023 20:59:24 +0200 | |
| @author: SmartFinn | |
| @documentation: https://api.hitbtc.com/ | |
| """ | |
| from tabulate import tabulate | |
| from typing import Any | |
| import requests | |
| class HitBTCMarket: | |
| DEFAULT_BASE_URL = "https://api.hitbtc.com/api/3/" | |
| DEFAULT_TIMEOUT = 30 | |
| def __init__( | |
| self, | |
| public_key=None, | |
| secret=None, | |
| base_url=DEFAULT_BASE_URL, | |
| request_timeout=DEFAULT_TIMEOUT, | |
| ) -> None: | |
| self.base_url = base_url | |
| self.request_timeout = request_timeout | |
| self.session = requests.session() | |
| if public_key and secret: | |
| self.session.auth = (public_key, secret) | |
| def _get(self, endpoint: str, params: str = "") -> Any: | |
| response_object = self.session.get( | |
| self.base_url + endpoint, params=params, timeout=self.request_timeout | |
| ) | |
| assert response_object.status_code == 200, "%s" % response_object.text | |
| try: | |
| response = response_object.json() | |
| except requests.exceptions.RequestException as e: | |
| raise e | |
| return response | |
| def get_currency(self, currencies: list[str] | None = None) -> dict[str, dict]: | |
| """Get ticker by symbol""" | |
| if currencies is None: | |
| currencies = [] | |
| return self._get("public/currency", params="currencies=" + ",".join(currencies)) | |
| def get_ticker(self, symbol: str) -> dict[str, str]: | |
| """Get ticker by symbol""" | |
| return self._get("public/ticker/" + symbol) | |
| def get_tickers(self, *symbols: str) -> dict[str, dict]: | |
| """Get tickers for all symbols or for specified symbols""" | |
| return self._get( | |
| "public/ticker", params="symbols=" + ",".join(symbols) | |
| ) | |
| def payout_enabled(data: dict) -> bool: | |
| return all([ | |
| data.get("payout_enabled", False), | |
| ]) | |
| def get_currency_without_protocol(currency: str, protocol: str) -> str: | |
| if currency == protocol: | |
| return currency | |
| if currency in ["USDT20", "POA20"]: | |
| return currency.removesuffix("20") | |
| if currency == "USDTRX": | |
| return currency.removesuffix("RX") | |
| if currency == "GMTSOL": | |
| return currency.removesuffix("SOL") | |
| if currency == "SETH" or currency == protocol: | |
| return currency | |
| return currency.removesuffix(protocol) | |
| def withdraw_fees( | |
| currencies: list = [], | |
| base_currency: str | None = None, | |
| min_volume: int = 0, | |
| ) -> list[list[str]]: | |
| hitbtc = HitBTCMarket() | |
| currencies = hitbtc.get_currency(currencies) | |
| table = [] | |
| if base_currency: | |
| tickers = hitbtc.get_tickers() | |
| for currency, data in currencies.items(): | |
| if not payout_enabled(data): | |
| continue | |
| for network in data.get("networks"): | |
| if not payout_enabled(network): | |
| continue | |
| row = [ | |
| currency, | |
| data["full_name"], | |
| network["protocol"], | |
| network["payout_fee"], | |
| ] | |
| if base_currency: | |
| currency = get_currency_without_protocol(currency, network.get("code")) | |
| if currency == base_currency: | |
| row.append(float(network["payout_fee"])) | |
| table.append(row) | |
| continue | |
| pair = f"{currency}{base_currency}" | |
| if pair not in tickers: | |
| continue | |
| ticker = tickers.get(pair) | |
| volume = float(ticker["volume_quote"]) | |
| if volume < min_volume: | |
| continue | |
| last_price = float(ticker["last"]) | |
| network_fee = float(network["payout_fee"]) | |
| fee_equivalent = last_price * network_fee | |
| row.append(fee_equivalent) | |
| table.append(row) | |
| return table | |
| if __name__ == "__main__": | |
| MIN_VOLUME = 0.1 | |
| headers = ["Currency", "Name", "Protocol", "Withdraw fee"] | |
| import argparse | |
| class UpperCaseAction(argparse.Action): | |
| def __call__(self, parser, namespace, values, option_string=None): | |
| setattr(namespace, self.dest, values.upper()) | |
| parser = argparse.ArgumentParser( | |
| description="Print HitBTC withdraw fees in fancy table.") | |
| parser.add_argument( | |
| "-c", "--currency", action="extend", nargs="+", default=[], | |
| help="List of currencies" | |
| ) | |
| parser.add_argument( | |
| "-b", "--base-currency", type=str, default=None, action=UpperCaseAction, | |
| help="Display fees as equivalent to the currency" | |
| ) | |
| parser.add_argument( | |
| "-m", "--min-volume", type=int, default=MIN_VOLUME, | |
| help="Minimum volume" | |
| ) | |
| parser.add_argument( | |
| "-t", "--table-format", type=str, default="plain", help="Table format" | |
| ) | |
| args = parser.parse_args() | |
| table = withdraw_fees(min_volume=args.min_volume, | |
| base_currency=args.base_currency, | |
| currencies=args.currency) | |
| if args.base_currency: | |
| headers.append(f"Equivalent in {args.base_currency}") | |
| table.sort(key=lambda x: x[4]) | |
| else: | |
| table.sort(key=lambda x: x[0]) | |
| print(tabulate(table, headers=headers, tablefmt=args.table_format)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment