peshay /
btcde
| 1 | #! /usr/bin/env python |
||
| 2 | """API Wrapper for Bitcoin.de Trading API.""" |
||
| 3 | |||
| 4 | import requests |
||
| 5 | import time |
||
| 6 | import json |
||
| 7 | import hmac |
||
| 8 | import hashlib |
||
| 9 | import logging |
||
| 10 | import codecs |
||
| 11 | import decimal |
||
| 12 | import inspect |
||
| 13 | import urllib |
||
| 14 | |||
| 15 | from urllib.parse import urlencode |
||
| 16 | |||
| 17 | logging.basicConfig() |
||
| 18 | log = logging.getLogger(__name__) |
||
| 19 | requests_log = logging.getLogger("requests.packages.urllib3") |
||
| 20 | requests_log.propagate = True |
||
| 21 | |||
| 22 | __version__ = '4.1' |
||
| 23 | |||
| 24 | class ParameterBuilder(object): |
||
| 25 | '''To verify given parameters for API.''' |
||
| 26 | def __init__(self, avail_params, given_params, uri): |
||
| 27 | self.verify_keys_and_values(avail_params, given_params) |
||
| 28 | self.params = given_params |
||
| 29 | self.create_url(uri) |
||
| 30 | |||
| 31 | def verify_keys_and_values(self, avail_params, given_params): |
||
| 32 | for k, v in given_params.items(): |
||
| 33 | if k not in avail_params: |
||
| 34 | list_string = ', '.join(avail_params) |
||
| 35 | raise KeyError("{} is not any of {}".format(k, list_string)) |
||
| 36 | if k == 'trading_pair': |
||
| 37 | self.error_on_invalid_value(v, self.TRADING_PAIRS) |
||
| 38 | elif k == 'type': |
||
| 39 | self.error_on_invalid_value(v, self.TRADE_TYPES) |
||
| 40 | elif k == 'currency': |
||
| 41 | self.error_on_invalid_value(v, self.CURRENCIES) |
||
| 42 | elif k == 'seat_of_bank': |
||
| 43 | self.error_on_invalid_value(v, self.BANK_SEATS) |
||
| 44 | elif k in ['min_trust_level', 'trust_level']: |
||
| 45 | self.error_on_invalid_value(v, self.TRUST_LEVELS) |
||
| 46 | elif k == 'payment_option': |
||
| 47 | self.error_on_invalid_value(v, self.PAYMENT_OPTIONS) |
||
| 48 | elif k == 'state': |
||
| 49 | caller = inspect.stack()[2][3] |
||
| 50 | if caller in ["showMyOrders", "showMyOrderDetails"]: |
||
| 51 | self.error_on_invalid_value(v, self.ORDER_STATES) |
||
| 52 | elif caller in ["showMyTrades", "showMyTradesDetails"]: |
||
| 53 | self.error_on_invalid_value(v, self.TRADE_STATES) |
||
| 54 | |||
| 55 | def error_on_invalid_value(self, value, list): |
||
| 56 | if value not in list: |
||
| 57 | list_string = ', '.join(str(x) for x in list) |
||
| 58 | raise ValueError("{} is not any of {}".format(value, list_string)) |
||
| 59 | |||
| 60 | def create_url(self, uri): |
||
| 61 | if self.params: |
||
| 62 | self.encoded_string = urlencode(sorted(self.params.items())) |
||
| 63 | self.url = uri + '?' + self.encoded_string |
||
| 64 | else: |
||
| 65 | self.encoded_string = '' |
||
| 66 | self.url = uri |
||
| 67 | |||
| 68 | |||
| 69 | TRADING_PAIRS = ['btceur', 'bcheur', 'etheur', 'btgeur', 'bsveur', 'ltceur', |
||
| 70 | 'iotabtc', 'dashbtc', 'gntbtc', 'ltcbtc', 'xrpeur', 'usdteur', 'btcusdt', 'ethusdt'] |
||
| 71 | ORDER_TYPES = ['buy', 'sell'] |
||
| 72 | CURRENCIES = ['btc', 'bch', 'eth', 'btg', 'bsv', 'ltc', |
||
| 73 | 'iota', 'dash', 'gnt', 'xrp', 'usdt'] |
||
| 74 | BANK_SEATS = ['AT', 'BE', 'BG', 'CH', 'CY', 'CZ', |
||
| 75 | 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', |
||
| 76 | 'GB', 'GR', 'HR', 'HU', 'IE', 'IS', |
||
| 77 | 'IT', 'LI', 'LT', 'LU', 'LV', 'MT', |
||
| 78 | 'MQ', 'NL', 'NO', 'PL', 'PT', 'RO', |
||
| 79 | 'SE', 'SI', 'SK'] |
||
| 80 | TRUST_LEVELS = ['bronze', 'silver', 'gold', 'platin'] |
||
| 81 | TRADE_STATES = [-1, 0, 1] |
||
| 82 | ORDER_STATES = [-2, -1, 0] |
||
| 83 | PAYMENT_OPTIONS = [1, 2, 3] |
||
| 84 | TRADE_TYPES = ['all', 'buy', 'sell', 'inpayment', |
||
| 85 | 'payout', 'affiliate', 'welcome_btc', |
||
| 86 | 'buy_yubikey', 'buy_goldshop', |
||
| 87 | 'buy_diamondshop', 'kickback', |
||
| 88 | 'outgoing_fee_voluntary'] |
||
| 89 | |||
| 90 | def HandleRequestsException(e): |
||
| 91 | """Handle Exception from request.""" |
||
| 92 | log.warning(e) |
||
| 93 | |||
| 94 | |||
| 95 | def HandleAPIErrors(r): |
||
| 96 | """To handle Errors from BTCDE API.""" |
||
| 97 | valid_status_codes = [200, 201, 204] |
||
| 98 | if r.status_code not in valid_status_codes: |
||
| 99 | content = r.json() |
||
| 100 | errors = content.get('errors') |
||
| 101 | log.warning('API Error Code: {}'.format(str(errors[0]['code']))) |
||
| 102 | log.warning('API Error Message: {}'.format(errors[0]['message'])) |
||
| 103 | log.warning('API Error URL: {}'.format(r.url)) |
||
| 104 | return False |
||
| 105 | else: |
||
| 106 | return True |
||
| 107 | |||
| 108 | class Connection(object): |
||
| 109 | """To provide connection credentials to the trading API""" |
||
| 110 | def __init__(self, api_key, api_secret): |
||
| 111 | self.api_key = api_key |
||
| 112 | self.api_secret = api_secret |
||
| 113 | # set initial self.nonce |
||
| 114 | self.nonce = int(time.time() * 1000000) |
||
| 115 | # Bitcoin.de API URI |
||
| 116 | self.apihost = 'https://api.bitcoin.de' |
||
| 117 | self.apiversion = 'v4' |
||
| 118 | self.apibase = f'{self.apihost}/{self.apiversion}/' |
||
| 119 | |||
| 120 | def build_hmac_sign(self, md5string, method, url): |
||
| 121 | hmac_data = '#'.join([method, url, self.api_key, str(self.nonce), md5string]) |
||
| 122 | hmac_signed = hmac.new(bytearray(self.api_secret.encode()), msg=hmac_data.encode(), digestmod=hashlib.sha256).hexdigest() |
||
| 123 | return hmac_signed |
||
| 124 | |||
| 125 | def set_header(self, url, method, encoded_string): |
||
| 126 | # raise self.nonce before using |
||
| 127 | self.nonce = int(time.time() * 1000000) |
||
| 128 | if method == 'POST': |
||
| 129 | md5_encoded_query_string = hashlib.md5(encoded_string.encode()).hexdigest() |
||
| 130 | else: |
||
| 131 | md5_encoded_query_string = hashlib.md5(b'').hexdigest() |
||
| 132 | hmac_signed = self.build_hmac_sign(md5_encoded_query_string, |
||
| 133 | method, url) |
||
| 134 | # set header |
||
| 135 | header = {'content-type': |
||
| 136 | 'application/x-www-form-urlencoded; charset=utf-8', |
||
| 137 | 'X-API-KEY': self.api_key, |
||
| 138 | 'X-API-NONCE': str(self.nonce), |
||
| 139 | 'X-API-SIGNATURE': hmac_signed } |
||
| 140 | return header |
||
| 141 | |||
| 142 | def send_request(self, url, method, header, encoded_string): |
||
| 143 | if method == 'GET': |
||
| 144 | r = requests.get(url, headers=(header), |
||
| 145 | stream=True, verify=False) |
||
| 146 | elif method == 'POST': |
||
| 147 | r = requests.post(url, headers=(header), data=encoded_string, |
||
| 148 | stream=True, verify=False) |
||
| 149 | elif method == 'DELETE': |
||
| 150 | r = requests.delete(url, headers=(header), |
||
| 151 | stream=True, verify=False) |
||
| 152 | return r |
||
|
0 ignored issues
–
show
introduced
by
Loading history...
|
|||
| 153 | |||
| 154 | def APIConnect(self, method, params): |
||
| 155 | """Transform Parameters to URL""" |
||
| 156 | header = self.set_header(params.url, method, |
||
| 157 | params.encoded_string) |
||
| 158 | log.debug('Set Header: {}'.format(header)) |
||
| 159 | try: |
||
| 160 | r = self.send_request(params.url, method, header, |
||
| 161 | params.encoded_string) |
||
| 162 | # Handle API Errors |
||
| 163 | if HandleAPIErrors(r): |
||
| 164 | # get results |
||
| 165 | result = r.json(parse_float=decimal.Decimal) |
||
| 166 | else: |
||
| 167 | result = {} |
||
| 168 | except requests.exceptions.RequestException as e: |
||
| 169 | HandleRequestsException(e) |
||
| 170 | result = {} |
||
| 171 | return result |
||
| 172 | |||
| 173 | def addToAddressPool(self, currency, address, **args): |
||
| 174 | """Add address to pool""" |
||
| 175 | uri = f'{self.apibase}{currency}/address' |
||
| 176 | params = {'address': address} |
||
| 177 | params.update(args) |
||
| 178 | avail_params = ['address', 'amount_usages', 'comment'] |
||
| 179 | p = ParameterBuilder(avail_params, params, uri) |
||
| 180 | return self.APIConnect('POST', p) |
||
| 181 | |||
| 182 | def removeFromAddressPool(self, currency, address): |
||
| 183 | """Remove address from pool""" |
||
| 184 | uri = f'{self.apibase}{currency}/address/{address}' |
||
| 185 | params = {'currency': currency, 'address': address} |
||
| 186 | avail_params = ['currency', 'address'] |
||
| 187 | p = ParameterBuilder({}, {}, uri) |
||
| 188 | p.verify_keys_and_values(avail_params, params) |
||
| 189 | return self.APIConnect('DELETE', p) |
||
| 190 | |||
| 191 | def listAddressPool(self, currency, **args): |
||
| 192 | """List address pool""" |
||
| 193 | uri = f'{self.apibase}{currency}/address' |
||
| 194 | params = args |
||
| 195 | avail_params = ['usable', 'comment', 'page'] |
||
| 196 | p = ParameterBuilder(avail_params, params, uri) |
||
| 197 | return self.APIConnect('GET', p) |
||
| 198 | |||
| 199 | def showOrderbook(self, order_type, trading_pair, **args): |
||
| 200 | """Search Orderbook for offers.""" |
||
| 201 | uri = f'{self.apibase}{trading_pair}/orderbook' |
||
| 202 | params = {'type': order_type} |
||
| 203 | params.update(args) |
||
| 204 | avail_params = ['type', 'trading_pair', 'amount_currency_to_trade', 'price', |
||
| 205 | 'order_requirements_fullfilled', |
||
| 206 | 'only_kyc_full', 'only_express_orders', 'payment_option', |
||
| 207 | 'sepa_option', 'only_same_bankgroup', 'only_same_bic', |
||
| 208 | 'seat_of_bank', 'page_size'] |
||
| 209 | p = ParameterBuilder(avail_params, params, uri) |
||
| 210 | return self.APIConnect('GET', p) |
||
| 211 | |||
| 212 | def showOrderDetails(self, trading_pair, order_id): |
||
| 213 | """Show details for an offer.""" |
||
| 214 | uri = f'{self.apibase}{trading_pair}/orders/public/details/{order_id}' |
||
| 215 | params = {'trading_pair': trading_pair, 'order_id': order_id} |
||
| 216 | avail_params = ['trading_pair', 'order_id'] |
||
| 217 | p = ParameterBuilder({}, {}, uri) |
||
| 218 | p.verify_keys_and_values(avail_params, params) |
||
| 219 | return self.APIConnect('GET', p) |
||
| 220 | |||
| 221 | def createOrder(self, order_type, trading_pair, max_amount_currency_to_trade, price, **args): |
||
| 222 | """Create a new Order.""" |
||
| 223 | uri = f'{self.apibase}{trading_pair}/orders' |
||
| 224 | # Build parameters |
||
| 225 | params = {'type': order_type, |
||
| 226 | 'max_amount_currency_to_trade': max_amount_currency_to_trade, |
||
| 227 | 'price': price} |
||
| 228 | params.update(args) |
||
| 229 | avail_params = ['type', 'max_amount_currency_to_trade', 'price', |
||
| 230 | 'min_amount_currency_to_trade', 'end_datetime', |
||
| 231 | 'new_order_for_remaining_amount', 'trading_pair', |
||
| 232 | 'min_trust_level', 'only_kyc_full', 'payment_option', |
||
| 233 | 'sepa_option', 'seat_of_bank'] |
||
| 234 | p = ParameterBuilder(avail_params, params, uri) |
||
| 235 | p.verify_keys_and_values(avail_params, {'trading_pair': trading_pair}) |
||
| 236 | return self.APIConnect('POST', p) |
||
| 237 | |||
| 238 | def deleteOrder(self, order_id, trading_pair): |
||
| 239 | """Delete an Order.""" |
||
| 240 | # Build parameters |
||
| 241 | uri = f'{self.apibase}{trading_pair}/orders/{order_id}' |
||
| 242 | avail_params = ['order_id', 'trading_pair'] |
||
| 243 | params = { 'order_id': order_id, 'trading_pair': trading_pair} |
||
| 244 | p = ParameterBuilder({}, {}, uri) |
||
| 245 | p.verify_keys_and_values(avail_params, params) |
||
| 246 | return self.APIConnect('DELETE', p) |
||
| 247 | |||
| 248 | def showMyOrders(self, **args): |
||
| 249 | """Query and Filter own Orders.""" |
||
| 250 | # Build parameters |
||
| 251 | params = args |
||
| 252 | avail_params = ['type', 'trading_pair', 'state', |
||
| 253 | 'date_start', 'date_end', 'page'] |
||
| 254 | if params.get("trading_pair"): |
||
| 255 | uri = f'{self.apibase}{params["trading_pair"]}/orders' |
||
| 256 | del params["trading_pair"] |
||
| 257 | else: |
||
| 258 | uri = f'{self.apibase}orders' |
||
| 259 | p = ParameterBuilder(avail_params, params, uri) |
||
| 260 | return self.APIConnect('GET', p) |
||
| 261 | |||
| 262 | def showMyOrderDetails(self, trading_pair, order_id): |
||
| 263 | """Details to an own Order.""" |
||
| 264 | uri = f'{self.apibase}{trading_pair}/orders/{order_id}' |
||
| 265 | p = ParameterBuilder({}, {}, uri) |
||
| 266 | return self.APIConnect('GET', p) |
||
| 267 | |||
| 268 | def executeTrade(self, trading_pair, order_id, order_type, amount): |
||
| 269 | """Buy/Sell on a specific Order.""" |
||
| 270 | uri = f'{self.apibase}{trading_pair}/trades/{order_id}' |
||
| 271 | params = { 'type': order_type, |
||
| 272 | 'amount_currency_to_trade': amount} |
||
| 273 | avail_params = ['type', 'amount_currency_to_trade'] |
||
| 274 | p = ParameterBuilder(avail_params, params, uri) |
||
| 275 | return self.APIConnect('POST', p) |
||
| 276 | |||
| 277 | def showMyTrades(self, **args): |
||
| 278 | """Query and Filter on past Trades.""" |
||
| 279 | # Build parameters |
||
| 280 | params = args |
||
| 281 | avail_params = ['type', 'trading_pair', 'state', |
||
| 282 | 'only_trades_with_action_for_payment_or_transfer_required', |
||
| 283 | 'payment_method', 'date_start', 'date_end', 'page'] |
||
| 284 | if params.get("trading_pair"): |
||
| 285 | uri = f'{self.apibase}{params["trading_pair"]}/trades' |
||
| 286 | del params["trading_pair"] |
||
| 287 | else: |
||
| 288 | uri = f'{self.apibase}trades' |
||
| 289 | p = ParameterBuilder(avail_params, params, uri) |
||
| 290 | return self.APIConnect('GET', p) |
||
| 291 | |||
| 292 | def showMyTradeDetails(self, trading_pair, trade_id): |
||
| 293 | """Details to a specific Trade.""" |
||
| 294 | params = {'trading_pair': trading_pair, 'trade_id': trade_id} |
||
| 295 | avail_params = [ 'trading_pair', 'trade_id' ] |
||
| 296 | uri = f'{self.apibase}{trading_pair}/trades/{trade_id}' |
||
| 297 | p = ParameterBuilder({}, {}, uri) |
||
| 298 | p.verify_keys_and_values(avail_params, params) |
||
| 299 | return self.APIConnect('GET', p) |
||
| 300 | |||
| 301 | def markCoinsAsTransferred(self, trading_pair, trade_id, amount_currency_to_trade_after_fee): |
||
| 302 | """Mark trade as transferred.""" |
||
| 303 | params = {'amount_currency_to_trade_after_fee': amount_currency_to_trade_after_fee, |
||
| 304 | 'trading_pair': trading_pair, 'trade_id': trade_id} |
||
| 305 | |||
| 306 | avail_params = [ 'trading_pair', 'trade_id', 'amount_currency_to_trade_after_fee' ] |
||
| 307 | uri = f'{self.apibase}{trading_pair}/trades/{trade_id}/mark_coins_as_transferred' |
||
| 308 | p = ParameterBuilder(avail_params, |
||
| 309 | {'amount_currency_to_trade_after_fee': amount_currency_to_trade_after_fee}, uri) |
||
| 310 | p.verify_keys_and_values(avail_params, params) |
||
| 311 | return self.APIConnect('POST', p) |
||
| 312 | |||
| 313 | def markTradeAsPaid(self, trading_pair, trade_id, volume_currency_to_pay_after_fee): |
||
| 314 | """Mark traded as paid.""" |
||
| 315 | params = {'volume_currency_to_pay_after_fee': volume_currency_to_pay_after_fee, |
||
| 316 | 'trading_pair': trading_pair, 'trade_id': trade_id} |
||
| 317 | |||
| 318 | avail_params = [ 'trading_pair', 'trade_id', 'volume_currency_to_pay_after_fee' ] |
||
| 319 | uri = f'{self.apibase}{trading_pair}/trades/{trade_id}/mark_trade_as_paid' |
||
| 320 | p = ParameterBuilder(avail_params, |
||
| 321 | {'volume_currency_to_pay_after_fee': volume_currency_to_pay_after_fee}, uri) |
||
| 322 | p.verify_keys_and_values(avail_params, params) |
||
| 323 | return self.APIConnect('POST', p) |
||
| 324 | |||
| 325 | def markCoinsAsReceived(self, trading_pair, trade_id, amount_currency_to_trade_after_fee, rating): |
||
| 326 | """Mark coins as received.""" |
||
| 327 | params = {'amount_currency_to_trade_after_fee': amount_currency_to_trade_after_fee, |
||
| 328 | 'trading_pair': trading_pair, 'trade_id': trade_id, 'rating': rating} |
||
| 329 | params_post = {'amount_currency_to_trade_after_fee': amount_currency_to_trade_after_fee, |
||
| 330 | 'rating': rating} |
||
| 331 | avail_params = [ 'trading_pair', 'trade_id', 'amount_currency_to_trade_after_fee', 'rating' ] |
||
| 332 | uri = f'{self.apibase}{trading_pair}/trades/{trade_id}/mark_coins_as_received' |
||
| 333 | p = ParameterBuilder(avail_params, params_post, uri) |
||
| 334 | p.verify_keys_and_values(avail_params, params) |
||
| 335 | return self.APIConnect('POST', p) |
||
| 336 | |||
| 337 | def markTradeAsPaymentReceived(self, trading_pair, trade_id, |
||
| 338 | volume_currency_to_pay_after_fee, rating, |
||
| 339 | is_paid_from_correct_bank_account): |
||
| 340 | """Mark coins as received.""" |
||
| 341 | params = {'volume_currency_to_pay_after_fee': volume_currency_to_pay_after_fee, |
||
| 342 | 'trading_pair': trading_pair, 'trade_id': trade_id, 'rating': rating} |
||
| 343 | params_post = {'volume_currency_to_pay_after_fee': volume_currency_to_pay_after_fee, |
||
| 344 | 'rating': rating, |
||
| 345 | 'is_paid_from_correct_bank_account': is_paid_from_correct_bank_account} |
||
| 346 | avail_params = [ 'trading_pair', 'trade_id', 'volume_currency_to_pay_after_fee', |
||
| 347 | 'rating', 'is_paid_from_correct_bank_account' ] |
||
| 348 | uri = f'{self.apibase}{trading_pair}/trades/{trade_id}/mark_trade_as_payment_received' |
||
| 349 | p = ParameterBuilder(avail_params, params_post, uri) |
||
| 350 | p.verify_keys_and_values(avail_params, params) |
||
| 351 | return self.APIConnect('POST', p) |
||
| 352 | |||
| 353 | def addTradeRating(self, trading_pair, trade_id, rating): |
||
| 354 | """Mark coins as received.""" |
||
| 355 | params = {'trading_pair': trading_pair, 'trade_id': trade_id, 'rating': rating} |
||
| 356 | params_post = {'rating': rating} |
||
| 357 | avail_params = [ 'trading_pair', 'trade_id', 'rating' ] |
||
| 358 | uri = f'{self.apibase}{trading_pair}/trades/{trade_id}/add_trade_rating' |
||
| 359 | p = ParameterBuilder(avail_params, params_post, uri) |
||
| 360 | p.verify_keys_and_values(avail_params, params) |
||
| 361 | return self.APIConnect('POST', p) |
||
| 362 | |||
| 363 | def showAccountInfo(self): |
||
| 364 | """Query on Account Infos.""" |
||
| 365 | uri = f'{self.apibase}account' |
||
| 366 | p = ParameterBuilder({}, {}, uri) |
||
| 367 | return self.APIConnect('GET', p) |
||
| 368 | |||
| 369 | def showOrderbookCompact(self, trading_pair): |
||
| 370 | """Bids and Asks in compact format.""" |
||
| 371 | params = {'trading_pair': trading_pair} |
||
| 372 | avail_params = ['trading_pair'] |
||
| 373 | uri = f'{self.apibase}{trading_pair}/orderbook/compact' |
||
| 374 | # Build parameters |
||
| 375 | p = ParameterBuilder({}, {}, uri) |
||
| 376 | p.verify_keys_and_values(avail_params, params) |
||
| 377 | return self.APIConnect('GET', p) |
||
| 378 | |||
| 379 | def showPublicTradeHistory(self, trading_pair, **args): |
||
| 380 | """All successful trades of the last 24 hours.""" |
||
| 381 | params = { 'trading_pair': trading_pair } |
||
| 382 | params.update(args) |
||
| 383 | avail_params = ['trading_pair', 'since_tid'] |
||
| 384 | uri = f'{self.apibase}{trading_pair}/trades/history' |
||
| 385 | if params.get('since_tid'): |
||
| 386 | del params["trading_pair"] |
||
| 387 | p = ParameterBuilder(avail_params, params, uri) |
||
| 388 | else: |
||
| 389 | p = ParameterBuilder({}, {}, uri) |
||
| 390 | p.verify_keys_and_values(avail_params, params) |
||
| 391 | return self.APIConnect('GET', p) |
||
| 392 | |||
| 393 | def showRates(self, trading_pair): |
||
| 394 | """Query of the average rate last 3 and 12 hours.""" |
||
| 395 | uri = f'{self.apibase}{trading_pair}/rates' |
||
| 396 | params = {'trading_pair': trading_pair} |
||
| 397 | avail_params = ['trading_pair'] |
||
| 398 | # Build parameters |
||
| 399 | p = ParameterBuilder({}, {}, uri) |
||
| 400 | p.verify_keys_and_values(avail_params, params) |
||
| 401 | return self.APIConnect('GET', p) |
||
| 402 | |||
| 403 | def showAccountLedger(self, currency, **args): |
||
| 404 | """Query on Account statement.""" |
||
| 405 | params = {'currency': currency} |
||
| 406 | params.update(args) |
||
| 407 | uri = f'{self.apibase}{currency}/account/ledger' |
||
| 408 | avail_params = ['currency', 'type', |
||
| 409 | 'datetime_start', 'datetime_end', 'page'] |
||
| 410 | p = ParameterBuilder(avail_params, params, uri) |
||
| 411 | del params['currency'] |
||
| 412 | p = ParameterBuilder(avail_params, params, uri) |
||
| 413 | return self.APIConnect('GET', p) |
||
| 414 | |||
| 415 | def showPermissions(self): |
||
| 416 | """Show permissions that are allowed for used API key""" |
||
| 417 | uri = f'{self.apibase}permissions' |
||
| 418 | p = ParameterBuilder({}, {}, uri) |
||
| 419 | return self.APIConnect('GET', p) |