ccxt 3.1.60__py2.py3-none-any.whl → 4.0.3__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
ccxt/ripio.py DELETED
@@ -1,1102 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
- # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
-
6
- from ccxt.base.exchange import Exchange
7
- from ccxt.base.types import OrderSide
8
- from typing import Optional
9
- from typing import List
10
- from ccxt.base.errors import ExchangeError
11
- from ccxt.base.errors import ArgumentsRequired
12
- from ccxt.base.errors import BadRequest
13
- from ccxt.base.errors import BadSymbol
14
- from ccxt.base.errors import InsufficientFunds
15
- from ccxt.base.errors import InvalidOrder
16
- from ccxt.base.errors import OrderNotFound
17
- from ccxt.base.errors import DDoSProtection
18
- from ccxt.base.errors import AuthenticationError
19
- from ccxt.base.decimal_to_precision import TICK_SIZE
20
-
21
-
22
- class ripio(Exchange):
23
-
24
- def describe(self):
25
- return self.deep_extend(super(ripio, self).describe(), {
26
- 'id': 'ripio',
27
- 'name': 'Ripio',
28
- 'countries': ['AR', 'BR'], # Argentina
29
- 'rateLimit': 50,
30
- 'version': 'v1',
31
- 'pro': True,
32
- # new metainfo interface
33
- 'has': {
34
- 'CORS': None,
35
- 'spot': True,
36
- 'margin': False,
37
- 'swap': False,
38
- 'future': False,
39
- 'option': False,
40
- 'addMargin': False,
41
- 'cancelOrder': True,
42
- 'createOrder': True,
43
- 'createReduceOnlyOrder': False,
44
- 'fetchBalance': True,
45
- 'fetchBorrowRate': False,
46
- 'fetchBorrowRateHistories': False,
47
- 'fetchBorrowRateHistory': False,
48
- 'fetchBorrowRates': False,
49
- 'fetchBorrowRatesPerSymbol': False,
50
- 'fetchClosedOrders': True,
51
- 'fetchCurrencies': True,
52
- 'fetchFundingHistory': False,
53
- 'fetchFundingRate': False,
54
- 'fetchFundingRateHistory': False,
55
- 'fetchFundingRates': False,
56
- 'fetchIndexOHLCV': False,
57
- 'fetchLeverage': False,
58
- 'fetchLeverageTiers': False,
59
- 'fetchMarginMode': False,
60
- 'fetchMarkOHLCV': False,
61
- 'fetchMyTrades': True,
62
- 'fetchOpenInterestHistory': False,
63
- 'fetchOpenOrders': True,
64
- 'fetchOrder': True,
65
- 'fetchOrderBook': True,
66
- 'fetchOrders': True,
67
- 'fetchPosition': False,
68
- 'fetchPositionMode': False,
69
- 'fetchPositions': False,
70
- 'fetchPositionsRisk': False,
71
- 'fetchPremiumIndexOHLCV': False,
72
- 'fetchTicker': True,
73
- 'fetchTickers': True,
74
- 'fetchTrades': True,
75
- 'fetchTradingFee': False,
76
- 'fetchTradingFees': True,
77
- 'reduceMargin': False,
78
- 'setLeverage': False,
79
- 'setMarginMode': False,
80
- 'setPositionMode': False,
81
- },
82
- 'urls': {
83
- 'logo': 'https://user-images.githubusercontent.com/1294454/94507548-a83d6a80-0218-11eb-9998-28b9cec54165.jpg',
84
- 'api': {
85
- 'public': 'https://api.exchange.ripio.com/api',
86
- 'private': 'https://api.exchange.ripio.com/api',
87
- },
88
- 'www': 'https://exchange.ripio.com',
89
- 'doc': [
90
- 'https://exchange.ripio.com/en/api/',
91
- ],
92
- 'fees': 'https://exchange.ripio.com/en/fee',
93
- },
94
- 'api': {
95
- 'public': {
96
- 'get': [
97
- 'rate/all/',
98
- 'rate/{pair}/',
99
- 'orderbook/{pair}/',
100
- 'tradehistory/{pair}/',
101
- 'pair/',
102
- 'currency/',
103
- 'orderbook/{pair}/depth/',
104
- ],
105
- },
106
- 'private': {
107
- 'get': [
108
- 'balances/exchange_balances/',
109
- 'order/{pair}/{order_id}/',
110
- 'order/{pair}/',
111
- 'trade/{pair}/',
112
- ],
113
- 'post': [
114
- 'order/{pair}/',
115
- 'order/{pair}/{order_id}/cancel/',
116
- ],
117
- },
118
- },
119
- 'fees': {
120
- 'trading': {
121
- 'tierBased': True,
122
- 'percentage': True,
123
- 'taker': self.parse_number('0.0'),
124
- 'maker': self.parse_number('0.0'),
125
- },
126
- },
127
- 'precisionMode': TICK_SIZE,
128
- 'requiredCredentials': {
129
- 'apiKey': True,
130
- 'secret': False,
131
- },
132
- 'exceptions': {
133
- 'exact': {
134
- },
135
- 'broad': {
136
- 'Authentication credentials were not provided': AuthenticationError, # {"detail":"Authentication credentials were not provided."}
137
- 'Disabled pair': BadSymbol, # {"status_code":400,"errors":{"pair":["Invalid/Disabled pair BTC_ARS"]},"message":"An error has occurred, please check the form."}
138
- 'Invalid order type': InvalidOrder, # {"status_code":400,"errors":{"order_type":["Invalid order type. Valid options: ['MARKET', 'LIMIT']"]},"message":"An error has occurred, please check the form."}
139
- 'Your balance is not enough': InsufficientFunds, # {"status_code":400,"errors":{"non_field_errors":["Your balance is not enough for self order: You have 0 BTC but you need 1 BTC"]},"message":"An error has occurred, please check the form."}
140
- "Order couldn't be created": ExchangeError, # {'status_code': 400,'errors': {'non_field_errors': _("Order couldn't be created")}, 'message': _('Seems like an unexpected error occurred. Please try again later or write us to support@ripio.com if the problem persists.')}
141
- # {"status_code":404,"errors":{"order":["Order 286e560e-b8a2-464b-8b84-15a7e2a67eab not found."]},"message":"An error has occurred, please check the form."}
142
- # {"status_code":404,"errors":{"trade":["Trade <trade_id> not found."]},"message":"An error has occurred, please check the form."}
143
- 'not found': OrderNotFound,
144
- 'Invalid pair': BadSymbol, # {"status_code":400,"errors":{"pair":["Invalid pair FOOBAR"]},"message":"An error has occurred, please check the form."}
145
- 'amount must be a number': BadRequest, # {"status_code":400,"errors":{"amount":["amount must be a number"]},"message":"An error has occurred, please check the form."}
146
- 'Total must be at least': InvalidOrder, # {"status_code":400,"errors":{"non_field_errors":["Total must be at least 10."]},"message":"An error has occurred, please check the form."}
147
- 'Account not found': BadRequest, # {"error_description": "Account not found."}, "status": 404
148
- 'Wrong password provided': AuthenticationError, # {'error': "Wrong password provided."}, “status_code”: 400
149
- 'User tokens limit': DDoSProtection, # {'error': "User tokens limit. Can't create more than 10 tokens."}, “status_code”: 400
150
- 'Something unexpected ocurred': ExchangeError, # {'status_code': 400, 'errors': {'non_field_errors': 'Something unexpected ocurred!'}, 'message': 'Seems like an unexpected error occurred. Please try again later or write us to support@ripio.com if the problem persists.'}
151
- # {'status_code': 404, 'errors': {'account_balance': ['Exchange balance <currency>not found.']},'message': 'An error has occurred, please check the form.'}
152
- # {'status_code': 404, 'errors': {'account_balance': ['Account balance <id> not found.']},'message': 'An error has occurred, please check the form.'}
153
- 'account_balance': BadRequest,
154
- },
155
- },
156
- })
157
-
158
- def fetch_markets(self, params={}):
159
- """
160
- retrieves data on all markets for ripio
161
- :param dict params: extra parameters specific to the exchange api endpoint
162
- :returns [dict]: an array of objects representing market data
163
- """
164
- response = self.publicGetPair(params)
165
- #
166
- # {
167
- # "next":null,
168
- # "previous":null,
169
- # "results":[
170
- # {
171
- # "base":"BTC",
172
- # "base_name":"Bitcoin",
173
- # "quote":"USDC",
174
- # "quote_name":"USD Coin",
175
- # "symbol":"BTC_USDC",
176
- # "fees":[
177
- # {
178
- # "traded_volume": 0.0,
179
- # "maker_fee": 0.0,
180
- # "taker_fee": 0.0,
181
- # "cancellation_fee": 0.0
182
- # }
183
- # ],
184
- # "country":"ZZ",
185
- # "enabled":true,
186
- # "priority":10,
187
- # "min_amount":"0.00001",
188
- # "price_tick":"0.000001",
189
- # "min_value":"10",
190
- # "limit_price_threshold":"25.00"
191
- # },
192
- # ]
193
- # }
194
- #
195
- result = []
196
- results = self.safe_value(response, 'results', [])
197
- for i in range(0, len(results)):
198
- market = results[i]
199
- baseId = self.safe_string(market, 'base')
200
- quoteId = self.safe_string(market, 'quote')
201
- id = self.safe_string(market, 'symbol')
202
- base = self.safe_currency_code(baseId)
203
- quote = self.safe_currency_code(quoteId)
204
- fees = self.safe_value(market, 'fees', [])
205
- firstFee = self.safe_value(fees, 0, {})
206
- result.append({
207
- 'id': id,
208
- 'symbol': base + '/' + quote,
209
- 'base': base,
210
- 'quote': quote,
211
- 'settle': None,
212
- 'baseId': baseId,
213
- 'quoteId': quoteId,
214
- 'settleId': None,
215
- 'type': 'spot',
216
- 'spot': True,
217
- 'margin': False,
218
- 'swap': False,
219
- 'future': False,
220
- 'option': False,
221
- 'active': self.safe_value(market, 'enabled', True),
222
- 'contract': False,
223
- 'linear': None,
224
- 'inverse': None,
225
- 'taker': self.safe_number(firstFee, 'taker_fee', 0.0),
226
- 'maker': self.safe_number(firstFee, 'maker_fee', 0.0),
227
- 'contractSize': None,
228
- 'expiry': None,
229
- 'expiryDatetime': None,
230
- 'strike': None,
231
- 'optionType': None,
232
- 'precision': {
233
- 'amount': self.safe_number(market, 'min_amount'),
234
- 'price': self.safe_number(market, 'price_tick'),
235
- },
236
- 'limits': {
237
- 'leverage': {
238
- 'min': None,
239
- 'max': None,
240
- },
241
- 'amount': {
242
- 'min': self.safe_number(market, 'min_amount'),
243
- 'max': None,
244
- },
245
- 'price': {
246
- 'min': None,
247
- 'max': None,
248
- },
249
- 'cost': {
250
- 'min': self.safe_number(market, 'min_value'),
251
- 'max': None,
252
- },
253
- },
254
- 'info': market,
255
- })
256
- return result
257
-
258
- def fetch_currencies(self, params={}):
259
- """
260
- fetches all available currencies on an exchange
261
- :param dict params: extra parameters specific to the ripio api endpoint
262
- :returns dict: an associative dictionary of currencies
263
- """
264
- response = self.publicGetCurrency(params)
265
- #
266
- # {
267
- # "next":null,
268
- # "previous":null,
269
- # "results":[
270
- # {
271
- # "name":"Argentine Peso",
272
- # "symbol":"$",
273
- # "currency":"ARS",
274
- # "country":"AR",
275
- # "decimal_places":"2",
276
- # "enabled":true
277
- # },
278
- # {
279
- # "name":"Bitcoin Cash",
280
- # "symbol":"BCH",
281
- # "currency":"BCH",
282
- # "country":"AR",
283
- # "decimal_places":"8",
284
- # "enabled":true
285
- # },
286
- # {
287
- # "name":"Bitcoin",
288
- # "symbol":"BTC",
289
- # "currency":"BTC",
290
- # "country":"AR",
291
- # "decimal_places":"8",
292
- # "enabled":true
293
- # }
294
- # ]
295
- # }
296
- #
297
- results = self.safe_value(response, 'results', [])
298
- result = {}
299
- for i in range(0, len(results)):
300
- currency = results[i]
301
- id = self.safe_string(currency, 'currency')
302
- code = self.safe_currency_code(id)
303
- name = self.safe_string(currency, 'name')
304
- active = self.safe_value(currency, 'enabled', True)
305
- result[code] = {
306
- 'id': id,
307
- 'code': code,
308
- 'name': name,
309
- 'info': currency, # the original payload
310
- 'active': active,
311
- 'deposit': None,
312
- 'withdraw': None,
313
- 'fee': None,
314
- 'precision': self.parse_number(self.parse_precision(self.safe_string(currency, 'decimal_places'))),
315
- 'limits': {
316
- 'amount': {'min': None, 'max': None},
317
- 'withdraw': {'min': None, 'max': None},
318
- },
319
- }
320
- return result
321
-
322
- def parse_ticker(self, ticker, market=None):
323
- #
324
- # fetchTicker, fetchTickers
325
- #
326
- # {
327
- # "pair":"BTC_USDC",
328
- # "last_price":"10850.02",
329
- # "low":"10720.03",
330
- # "high":"10909.99",
331
- # "variation":"1.21",
332
- # "volume":"0.83868",
333
- # "base":"BTC",
334
- # "base_name":"Bitcoin",
335
- # "quote":"USDC",
336
- # "quote_name":"USD Coin",
337
- # "bid":"10811.00",
338
- # "ask":"10720.03",
339
- # "avg":"10851.47",
340
- # "ask_volume":"0.00140",
341
- # "bid_volume":"0.00185",
342
- # "created_at":"2020-09-28 21:44:51.228920+00:00"
343
- # }
344
- #
345
- timestamp = self.parse8601(self.safe_string(ticker, 'created_at'))
346
- marketId = self.safe_string(ticker, 'pair')
347
- market = self.safe_market(marketId, market, '_')
348
- symbol = market['symbol']
349
- last = self.safe_string(ticker, 'last_price')
350
- average = self.safe_string(ticker, 'avg')
351
- return self.safe_ticker({
352
- 'symbol': symbol,
353
- 'timestamp': timestamp,
354
- 'datetime': self.iso8601(timestamp),
355
- 'high': self.safe_string(ticker, 'high'),
356
- 'low': self.safe_string(ticker, 'low'),
357
- 'bid': self.safe_string(ticker, 'bid'),
358
- 'bidVolume': self.safe_string(ticker, 'bid_volume'),
359
- 'ask': self.safe_string(ticker, 'ask'),
360
- 'askVolume': self.safe_string(ticker, 'ask_volume'),
361
- 'vwap': None,
362
- 'open': None,
363
- 'close': last,
364
- 'last': last,
365
- 'previousClose': None,
366
- 'change': None,
367
- 'percentage': None,
368
- 'average': average,
369
- 'baseVolume': None,
370
- 'quoteVolume': None,
371
- 'info': ticker,
372
- }, market)
373
-
374
- def fetch_ticker(self, symbol: str, params={}):
375
- """
376
- fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
377
- :param str symbol: unified symbol of the market to fetch the ticker for
378
- :param dict params: extra parameters specific to the ripio api endpoint
379
- :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
380
- """
381
- self.load_markets()
382
- market = self.market(symbol)
383
- request = {
384
- 'pair': market['id'],
385
- }
386
- response = self.publicGetRatePair(self.extend(request, params))
387
- #
388
- # {
389
- # "pair":"BTC_USDC",
390
- # "last_price":"10850.02",
391
- # "low":"10720.03",
392
- # "high":"10909.99",
393
- # "variation":"1.21",
394
- # "volume":"0.83868",
395
- # "base":"BTC",
396
- # "base_name":"Bitcoin",
397
- # "quote":"USDC",
398
- # "quote_name":"USD Coin",
399
- # "bid":"10811.00",
400
- # "ask":"10720.03",
401
- # "avg":"10851.47",
402
- # "ask_volume":"0.00140",
403
- # "bid_volume":"0.00185",
404
- # "created_at":"2020-09-28 21:44:51.228920+00:00"
405
- # }
406
- #
407
- return self.parse_ticker(response, market)
408
-
409
- def fetch_tickers(self, symbols: Optional[List[str]] = None, params={}):
410
- """
411
- fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market
412
- :param [str]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
413
- :param dict params: extra parameters specific to the ripio api endpoint
414
- :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
415
- """
416
- self.load_markets()
417
- symbols = self.market_symbols(symbols)
418
- response = self.publicGetRateAll(params)
419
- #
420
- # [
421
- # {
422
- # "pair":"BTC_USDC",
423
- # "last_price":"10850.02",
424
- # "low":"10720.03",
425
- # "high":"10909.99",
426
- # "variation":"1.21",
427
- # "volume":"0.83868",
428
- # "base":"BTC",
429
- # "base_name":"Bitcoin",
430
- # "quote":"USDC",
431
- # "quote_name":"USD Coin",
432
- # "bid":"10811.00",
433
- # "ask":"10720.03",
434
- # "avg":"10851.47",
435
- # "ask_volume":"0.00140",
436
- # "bid_volume":"0.00185",
437
- # "created_at":"2020-09-28 21:44:51.228920+00:00"
438
- # }
439
- # ]
440
- #
441
- result = {}
442
- for i in range(0, len(response)):
443
- ticker = self.parse_ticker(response[i])
444
- symbol = ticker['symbol']
445
- result[symbol] = ticker
446
- return self.filter_by_array(result, 'symbol', symbols)
447
-
448
- def fetch_order_book(self, symbol: str, limit: Optional[int] = None, params={}):
449
- """
450
- fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
451
- :param str symbol: unified symbol of the market to fetch the order book for
452
- :param int|None limit: the maximum amount of order book entries to return
453
- :param dict params: extra parameters specific to the ripio api endpoint
454
- :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
455
- """
456
- self.load_markets()
457
- market = self.market(symbol)
458
- request = {
459
- 'pair': market['id'],
460
- }
461
- response = self.publicGetOrderbookPair(self.extend(request, params))
462
- #
463
- # {
464
- # "buy":[
465
- # {"amount":"0.00230","total":"24.95","price":"10850.02"},
466
- # {"amount":"0.07920","total":"858.52","price":"10840.00"},
467
- # {"amount":"0.00277","total":"30.00","price":"10833.03"},
468
- # ],
469
- # "sell":[
470
- # {"amount":"0.03193","total":"348.16","price":"10904.00"},
471
- # {"amount":"0.00210","total":"22.90","price":"10905.70"},
472
- # {"amount":"0.00300","total":"32.72","price":"10907.98"},
473
- # ],
474
- # "updated_id":47225
475
- # }
476
- #
477
- orderbook = self.parse_order_book(response, market['symbol'], None, 'buy', 'sell', 'price', 'amount')
478
- orderbook['nonce'] = self.safe_integer(response, 'updated_id')
479
- return orderbook
480
-
481
- def parse_trade(self, trade, market=None):
482
- #
483
- #
484
- # fetchTrades(public)
485
- #
486
- # {
487
- # "created_at":1649899167,
488
- # "amount":"0.00852",
489
- # "price":"3106.000000",
490
- # "side":"SELL",
491
- # "pair":"ETH_USDC",
492
- # "taker_fee":"0",
493
- # "taker_side":"SELL",
494
- # "maker_fee":"0"
495
- # }
496
- #
497
- #
498
- # fetchMyTrades(private)
499
- #
500
- # {
501
- # "created_at":1601322501,
502
- # "amount":"0.00276",
503
- # "price":"10850.020000",
504
- # "side":"SELL",
505
- # "pair":"BTC_USDC",
506
- # "taker_fee":"0",
507
- # "taker_side":"SELL",
508
- # "maker_fee":"0",
509
- # "taker":2577953,
510
- # "maker":2577937
511
- # }
512
- #
513
- # createOrder fills
514
- #
515
- # {
516
- # "pair":"BTC_USDC",
517
- # "exchanged":0.002,
518
- # "match_price":10593.99,
519
- # "maker_fee":0.0,
520
- # "taker_fee":0.0,
521
- # "timestamp":1601730306942
522
- # }
523
- #
524
- id = self.safe_string(trade, 'id')
525
- timestamp = self.safe_integer(trade, 'timestamp')
526
- timestamp = self.safe_timestamp(trade, 'created_at', timestamp)
527
- side = self.safe_string(trade, 'side')
528
- takerSide = self.safe_string(trade, 'taker_side')
529
- takerOrMaker = 'taker' if (takerSide == side) else 'maker'
530
- if side is not None:
531
- side = side.lower()
532
- priceString = self.safe_string_2(trade, 'price', 'match_price')
533
- amountString = self.safe_string_2(trade, 'amount', 'exchanged')
534
- marketId = self.safe_string(trade, 'pair')
535
- market = self.safe_market(marketId, market)
536
- feeCostString = self.safe_string(trade, takerOrMaker + '_fee')
537
- orderId = self.safe_string(trade, takerOrMaker)
538
- fee = None
539
- if feeCostString is not None:
540
- fee = {
541
- 'cost': feeCostString,
542
- 'currency': market['base'] if (side == 'buy') else market['quote'],
543
- }
544
- return self.safe_trade({
545
- 'id': id,
546
- 'order': orderId,
547
- 'timestamp': timestamp,
548
- 'datetime': self.iso8601(timestamp),
549
- 'symbol': market['symbol'],
550
- 'type': None,
551
- 'side': side,
552
- 'price': priceString,
553
- 'amount': amountString,
554
- 'cost': None,
555
- 'takerOrMaker': takerOrMaker,
556
- 'fee': fee,
557
- 'info': trade,
558
- }, market)
559
-
560
- def fetch_trades(self, symbol: str, since: Optional[int] = None, limit: Optional[int] = None, params={}):
561
- """
562
- get the list of most recent trades for a particular symbol
563
- :param str symbol: unified symbol of the market to fetch trades for
564
- :param int|None since: timestamp in ms of the earliest trade to fetch
565
- :param int|None limit: the maximum amount of trades to fetch
566
- :param dict params: extra parameters specific to the ripio api endpoint
567
- :returns [dict]: a list of `trade structures <https://docs.ccxt.com/en/latest/manual.html?#public-trades>`
568
- """
569
- self.load_markets()
570
- market = self.market(symbol)
571
- request = {
572
- 'pair': market['id'],
573
- }
574
- response = self.publicGetTradehistoryPair(self.extend(request, params))
575
- #
576
- # [
577
- # {
578
- # "created_at":1649899167,
579
- # "amount":"0.00852",
580
- # "price":"3106.000000",
581
- # "side":"SELL",
582
- # "pair":"ETH_USDC",
583
- # "taker_fee":"0",
584
- # "taker_side":"SELL",
585
- # "maker_fee":"0"
586
- # }
587
- # ]
588
- #
589
- return self.parse_trades(response, market, since, limit)
590
-
591
- def fetch_trading_fees(self, params={}):
592
- """
593
- fetch the trading fees for multiple markets
594
- :param dict params: extra parameters specific to the ripio api endpoint
595
- :returns dict: a dictionary of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>` indexed by market symbols
596
- """
597
- self.load_markets()
598
- response = self.publicGetPair(params)
599
- #
600
- # {
601
- # next: null,
602
- # previous: null,
603
- # results: [
604
- # {
605
- # base: 'BTC',
606
- # base_name: 'Bitcoin',
607
- # quote: 'USDC',
608
- # quote_name: 'USD Coin',
609
- # symbol: 'BTC_USDC',
610
- # fees: [
611
- # {
612
- # traded_volume: '0.0',
613
- # maker_fee: '0.0',
614
- # taker_fee: '0.0',
615
- # cancellation_fee: '0.0'
616
- # }
617
- # ],
618
- # country: 'ZZ',
619
- # enabled: True,
620
- # priority: '10',
621
- # min_amount: '0.0000100000',
622
- # price_tick: '0.000001',
623
- # min_value: '10',
624
- # limit_price_threshold: '25.00'
625
- # },
626
- # ]
627
- # }
628
- #
629
- results = self.safe_value(response, 'results', [])
630
- result = {}
631
- for i in range(0, len(results)):
632
- pair = results[i]
633
- marketId = self.safe_string(pair, 'symbol')
634
- symbol = self.safe_symbol(marketId, None, '_')
635
- fees = self.safe_value(pair, 'fees', [])
636
- fee = self.safe_value(fees, 0, {})
637
- result[symbol] = {
638
- 'info': pair,
639
- 'symbol': symbol,
640
- 'maker': self.safe_number(fee, 'maker_fee'),
641
- 'taker': self.safe_number(fee, 'taker_fee'),
642
- 'tierBased': False,
643
- }
644
- return result
645
-
646
- def parse_balance(self, response):
647
- result = {'info': response}
648
- for i in range(0, len(response)):
649
- balance = response[i]
650
- currencyId = self.safe_string(balance, 'symbol')
651
- code = self.safe_currency_code(currencyId)
652
- account = self.account()
653
- account['free'] = self.safe_string(balance, 'available')
654
- account['used'] = self.safe_string(balance, 'locked')
655
- result[code] = account
656
- return self.safe_balance(result)
657
-
658
- def fetch_balance(self, params={}):
659
- """
660
- query for balance and get the amount of funds available for trading or funds locked in orders
661
- :param dict params: extra parameters specific to the ripio api endpoint
662
- :returns dict: a `balance structure <https://docs.ccxt.com/en/latest/manual.html?#balance-structure>`
663
- """
664
- self.load_markets()
665
- response = self.privateGetBalancesExchangeBalances(params)
666
- #
667
- # [
668
- # {
669
- # "id":603794,
670
- # "currency":"USD Coin",
671
- # "symbol":"USDC",
672
- # "available":"0",
673
- # "locked":"0",
674
- # "code":"exchange",
675
- # "balance_type":"crypto"
676
- # },
677
- # ]
678
- #
679
- return self.parse_balance(response)
680
-
681
- def create_order(self, symbol: str, type, side: OrderSide, amount, price=None, params={}):
682
- """
683
- create a trade order
684
- :param str symbol: unified symbol of the market to create an order in
685
- :param str type: 'market' or 'limit'
686
- :param str side: 'buy' or 'sell'
687
- :param float amount: how much of currency you want to trade in units of base currency
688
- :param float|None price: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
689
- :param dict params: extra parameters specific to the ripio api endpoint
690
- :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
691
- """
692
- self.load_markets()
693
- market = self.market(symbol)
694
- uppercaseType = type.upper()
695
- uppercaseSide = side.upper()
696
- request = {
697
- 'pair': market['id'],
698
- 'order_type': uppercaseType, # LIMIT, MARKET
699
- 'side': uppercaseSide, # BUY or SELL
700
- 'amount': self.amount_to_precision(symbol, amount),
701
- }
702
- if uppercaseType == 'LIMIT':
703
- request['limit_price'] = self.price_to_precision(symbol, price)
704
- response = self.privatePostOrderPair(self.extend(request, params))
705
- #
706
- # {
707
- # "order_id": "160f523c-f6ef-4cd1-a7c9-1a8ede1468d8",
708
- # "pair": "BTC_ARS",
709
- # "side": "BUY",
710
- # "amount": "0.00400",
711
- # "notional": null,
712
- # "fill_or_kill": False,
713
- # "all_or_none": False,
714
- # "order_type": "LIMIT",
715
- # "status": "OPEN",
716
- # "created_at": 1578413945,
717
- # "filled": "0.00000",
718
- # "limit_price": "10.00",
719
- # "stop_price": null,
720
- # "distance": null
721
- # }
722
- #
723
- # createOrder market type
724
- #
725
- # {
726
- # "order_id":"d6b60c01-8624-44f2-9e6c-9e8cd677ea5c",
727
- # "pair":"BTC_USDC",
728
- # "side":"BUY",
729
- # "amount":"0.00200",
730
- # "notional":"50",
731
- # "fill_or_kill":false,
732
- # "all_or_none":false,
733
- # "order_type":"MARKET",
734
- # "status":"OPEN",
735
- # "created_at":1601730306,
736
- # "filled":"0.00000",
737
- # "fill_price":10593.99,
738
- # "fee":0.0,
739
- # "fills":[
740
- # {
741
- # "pair":"BTC_USDC",
742
- # "exchanged":0.002,
743
- # "match_price":10593.99,
744
- # "maker_fee":0.0,
745
- # "taker_fee":0.0,
746
- # "timestamp":1601730306942
747
- # }
748
- # ],
749
- # "filled_at":"2020-10-03T13:05:06.942186Z",
750
- # "limit_price":"0.000000",
751
- # "stop_price":null,
752
- # "distance":null
753
- # }
754
- #
755
- return self.parse_order(response, market)
756
-
757
- def cancel_order(self, id: str, symbol: Optional[str] = None, params={}):
758
- """
759
- cancels an open order
760
- :param str id: order id
761
- :param str symbol: unified symbol of the market the order was made in
762
- :param dict params: extra parameters specific to the ripio api endpoint
763
- :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
764
- """
765
- if symbol is None:
766
- raise ArgumentsRequired(self.id + ' cancelOrder() requires a symbol argument')
767
- self.load_markets()
768
- market = self.market(symbol)
769
- request = {
770
- 'pair': market['id'],
771
- 'order_id': id,
772
- }
773
- response = self.privatePostOrderPairOrderIdCancel(self.extend(request, params))
774
- #
775
- # {
776
- # "order_id": "286e560e-b8a2-464b-8b84-15a7e2a67eab",
777
- # "pair": "BTC_ARS",
778
- # "side": "SELL",
779
- # "amount": "0.00100",
780
- # "notional": null,
781
- # "fill_or_kill": False,
782
- # "all_or_none": False,
783
- # "order_type": "LIMIT",
784
- # "status": "CANC",
785
- # "created_at": 1575472707,
786
- # "filled": "0.00000",
787
- # "limit_price": "681000.00",
788
- # "stop_price": null,
789
- # "distance": null
790
- # }
791
- #
792
- return self.parse_order(response, market)
793
-
794
- def fetch_order(self, id: str, symbol: Optional[str] = None, params={}):
795
- """
796
- fetches information on an order made by the user
797
- :param str symbol: unified symbol of the market the order was made in
798
- :param dict params: extra parameters specific to the ripio api endpoint
799
- :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
800
- """
801
- if symbol is None:
802
- raise ArgumentsRequired(self.id + ' fetchOrder() requires a symbol argument')
803
- self.load_markets()
804
- market = self.market(symbol)
805
- request = {
806
- 'pair': market['id'],
807
- 'order_id': id,
808
- }
809
- response = self.privateGetOrderPairOrderId(self.extend(request, params))
810
- #
811
- # {
812
- # "order_id": "0b4ff48e-cfd6-42db-8d8c-3b536da447af",
813
- # "pair": "BTC_ARS",
814
- # "side": "BUY",
815
- # "amount": "0.00100",
816
- # "notional": null,
817
- # "fill_or_kill": False,
818
- # "all_or_none": False,
819
- # "order_type": "LIMIT",
820
- # "status": "OPEN",
821
- # "created_at": 1575472944,
822
- # "filled": "0.00000",
823
- # "limit_price": "661000.00",
824
- # "stop_price": null,
825
- # "distance": null
826
- # }
827
- #
828
- return self.parse_order(response, market)
829
-
830
- def fetch_orders(self, symbol: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
831
- """
832
- fetches information on multiple orders made by the user
833
- :param str symbol: unified market symbol of the market orders were made in
834
- :param int|None since: the earliest time in ms to fetch orders for
835
- :param int|None limit: the maximum number of orde structures to retrieve
836
- :param dict params: extra parameters specific to the ripio api endpoint
837
- :returns [dict]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
838
- """
839
- if symbol is None:
840
- raise ArgumentsRequired(self.id + ' fetchOrders() requires a symbol argument')
841
- self.load_markets()
842
- market = self.market(symbol)
843
- request = {
844
- 'pair': market['id'],
845
- # 'status': 'OPEN,PART,CLOS,CANC,COMP',
846
- # 'offset': 0,
847
- # 'limit': limit,
848
- }
849
- if limit is not None:
850
- request['offset'] = limit
851
- response = self.privateGetOrderPair(self.extend(request, params))
852
- #
853
- # {
854
- # "next": "https://api.exchange.ripio.com/api/v1/order/BTC_ARS/?limit=20&offset=20&page=1&page_size=25&status=OPEN%2CPART",
855
- # "previous": null,
856
- # "results": {
857
- # "data": [
858
- # {
859
- # "order_id": "ca74280b-6966-4b73-a720-68709078922b",
860
- # "pair": "BTC_ARS",
861
- # "side": "SELL",
862
- # "amount": "0.00100",
863
- # "notional": null,
864
- # "fill_or_kill": False,
865
- # "all_or_none": False,
866
- # "order_type": "LIMIT",
867
- # "status": "OPEN",
868
- # "created_at": 1578340134,
869
- # "filled": "0.00000",
870
- # "limit_price": "665000.00",
871
- # "stop_price": null,
872
- # "distance": null
873
- # },
874
- # ]
875
- # }
876
- # }
877
- #
878
- results = self.safe_value(response, 'results', {})
879
- data = self.safe_value(results, 'data', [])
880
- return self.parse_orders(data, market, since, limit)
881
-
882
- def fetch_open_orders(self, symbol: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
883
- """
884
- fetch all unfilled currently open orders
885
- :param str symbol: unified market symbol
886
- :param int|None since: the earliest time in ms to fetch open orders for
887
- :param int|None limit: the maximum number of open orders structures to retrieve
888
- :param dict params: extra parameters specific to the ripio api endpoint
889
- :returns [dict]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
890
- """
891
- request = {
892
- 'status': 'OPEN,PART',
893
- }
894
- return self.fetch_orders(symbol, since, limit, self.extend(request, params))
895
-
896
- def fetch_closed_orders(self, symbol: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
897
- """
898
- fetches information on multiple closed orders made by the user
899
- :param str symbol: unified market symbol of the market orders were made in
900
- :param int|None since: the earliest time in ms to fetch orders for
901
- :param int|None limit: the maximum number of orde structures to retrieve
902
- :param dict params: extra parameters specific to the ripio api endpoint
903
- :returns [dict]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
904
- """
905
- request = {
906
- 'status': 'CLOS,CANC,COMP',
907
- }
908
- return self.fetch_orders(symbol, since, limit, self.extend(request, params))
909
-
910
- def parse_order_status(self, status):
911
- statuses = {
912
- 'OPEN': 'open',
913
- 'PART': 'open',
914
- 'CLOS': 'canceled',
915
- 'CANC': 'canceled',
916
- 'COMP': 'closed',
917
- }
918
- return self.safe_string(statuses, status, status)
919
-
920
- def parse_order(self, order, market=None):
921
- #
922
- # createOrder, cancelOrder, fetchOpenOrders, fetchClosedOrders, fetchOrders, fetchOrder
923
- #
924
- # {
925
- # "order_id": "286e560e-b8a2-464b-8b84-15a7e2a67eab",
926
- # "pair": "BTC_ARS",
927
- # "side": "SELL",
928
- # "amount": "0.00100",
929
- # "notional": null,
930
- # "fill_or_kill": False,
931
- # "all_or_none": False,
932
- # "order_type": "LIMIT",
933
- # "status": "CANC",
934
- # "created_at": 1575472707,
935
- # "filled": "0.00000",
936
- # "limit_price": "681000.00",
937
- # "stop_price": null,
938
- # "distance": null
939
- # }
940
- #
941
- # {
942
- # "order_id": "d6b60c01-8624-44f2-9e6c-9e8cd677ea5c",
943
- # "pair": "BTC_USDC",
944
- # "side": "BUY",
945
- # "amount": "0.00200",
946
- # "notional": "50",
947
- # "fill_or_kill": False,
948
- # "all_or_none": False,
949
- # "order_type": "MARKET",
950
- # "status": "OPEN",
951
- # "created_at": 1601730306,
952
- # "filled": "0.00000",
953
- # "fill_price": 10593.99,
954
- # "fee": 0.0,
955
- # "fills": [
956
- # {
957
- # "pair": "BTC_USDC",
958
- # "exchanged": 0.002,
959
- # "match_price": 10593.99,
960
- # "maker_fee": 0.0,
961
- # "taker_fee": 0.0,
962
- # "timestamp": 1601730306942
963
- # }
964
- # ],
965
- # "filled_at": "2020-10-03T13:05:06.942186Z",
966
- # "limit_price": "0.000000",
967
- # "stop_price": null,
968
- # "distance": null
969
- # }
970
- #
971
- id = self.safe_string(order, 'order_id')
972
- amount = self.safe_string(order, 'amount')
973
- cost = self.safe_string(order, 'notional')
974
- type = self.safe_string_lower(order, 'order_type')
975
- priceField = 'fill_price' if (type == 'market') else 'limit_price'
976
- price = self.safe_string(order, priceField)
977
- side = self.safe_string_lower(order, 'side')
978
- status = self.parse_order_status(self.safe_string(order, 'status'))
979
- timestamp = self.safe_timestamp(order, 'created_at')
980
- average = self.safe_string(order, 'fill_price')
981
- filled = self.safe_string(order, 'filled')
982
- fills = self.safe_value(order, 'fills')
983
- marketId = self.safe_string(order, 'pair')
984
- return self.safe_order({
985
- 'info': order,
986
- 'id': id,
987
- 'clientOrderId': None,
988
- 'timestamp': timestamp,
989
- 'datetime': self.iso8601(timestamp),
990
- 'lastTradeTimestamp': None,
991
- 'symbol': self.safe_symbol(marketId, market, '_'),
992
- 'type': type,
993
- 'timeInForce': None,
994
- 'postOnly': None,
995
- 'side': side,
996
- 'price': price,
997
- 'stopPrice': self.safe_string(order, 'stop_price'),
998
- 'triggerPrice': self.safe_string(order, 'stop_price'),
999
- 'amount': amount,
1000
- 'cost': cost,
1001
- 'average': average,
1002
- 'filled': filled,
1003
- 'remaining': None,
1004
- 'status': status,
1005
- 'fee': None,
1006
- 'trades': fills,
1007
- }, market)
1008
-
1009
- def fetch_my_trades(self, symbol: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
1010
- """
1011
- fetch all trades made by the user
1012
- :param str symbol: unified market symbol
1013
- :param int|None since: the earliest time in ms to fetch trades for
1014
- :param int|None limit: the maximum number of trades structures to retrieve
1015
- :param dict params: extra parameters specific to the ripio api endpoint
1016
- :returns [dict]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1017
- """
1018
- if symbol is None:
1019
- raise ArgumentsRequired(self.id + ' fetchMyTrades() requires a symbol argument')
1020
- self.load_markets()
1021
- market = self.market(symbol)
1022
- request = {
1023
- 'pair': market['id'],
1024
- # 'offset': 0,
1025
- # 'limit': limit,
1026
- }
1027
- if limit is not None:
1028
- request['limit'] = limit
1029
- response = self.privateGetTradePair(self.extend(request, params))
1030
- #
1031
- # {
1032
- # "next": "https://api.exchange.ripio.com/api/v1/trade/<pair>/?limit=20&offset=20",
1033
- # "previous": null,
1034
- # "results": {
1035
- # "data": [
1036
- # {
1037
- # "created_at": 1578414028,
1038
- # "amount": "0.00100",
1039
- # "price": "665000.00",
1040
- # "side": "BUY",
1041
- # "taker_fee": "0",
1042
- # "taker_side": "BUY",
1043
- # "match_price": "66500000",
1044
- # "maker_fee": "0",
1045
- # "taker": 4892,
1046
- # "maker": 4889
1047
- # },
1048
- # ]
1049
- # }
1050
- # }
1051
- #
1052
- results = self.safe_value(response, 'results', {})
1053
- data = self.safe_value(results, 'data', [])
1054
- return self.parse_trades(data, market, since, limit)
1055
-
1056
- def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
1057
- request = '/' + self.version + '/' + self.implode_params(path, params)
1058
- url = self.urls['api'][api] + request
1059
- query = self.omit(params, self.extract_params(path))
1060
- if api == 'public':
1061
- if query:
1062
- url += '?' + self.urlencode(query)
1063
- elif api == 'private':
1064
- self.check_required_credentials()
1065
- if method == 'POST':
1066
- body = self.json(query)
1067
- else:
1068
- if query:
1069
- url += '?' + self.urlencode(query)
1070
- headers = {
1071
- 'Content-Type': 'application/json',
1072
- 'Authorization': 'Bearer ' + self.apiKey,
1073
- }
1074
- return {'url': url, 'method': method, 'body': body, 'headers': headers}
1075
-
1076
- def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
1077
- if response is None:
1078
- return None
1079
- #
1080
- # {"detail":"Authentication credentials were not provided."}
1081
- # {"status_code":400,"errors":{"pair":["Invalid pair FOOBAR"]},"message":"An error has occurred, please check the form."}
1082
- # {"status_code":400,"errors":{"order_type":["Invalid order type. Valid options: ['MARKET', 'LIMIT']"]},"message":"An error has occurred, please check the form."}
1083
- # {"status_code":400,"errors":{"non_field_errors":"Something unexpected ocurred!"},"message":"Seems like an unexpected error occurred. Please try again later or write us to support@ripio.com if the problem persists."}
1084
- # {"status_code":400,"errors":{"pair":["Invalid/Disabled pair BTC_ARS"]},"message":"An error has occurred, please check the form."}
1085
- #
1086
- detail = self.safe_string(response, 'detail')
1087
- if detail is not None:
1088
- feedback = self.id + ' ' + body
1089
- # self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
1090
- self.throw_broadly_matched_exception(self.exceptions['broad'], detail, feedback)
1091
- errors = self.safe_value(response, 'errors')
1092
- if errors is not None:
1093
- feedback = self.id + ' ' + body
1094
- keys = list(errors.keys())
1095
- for i in range(0, len(keys)):
1096
- key = keys[i]
1097
- error = self.safe_value(errors, key, [])
1098
- message = self.safe_string(error, 0)
1099
- # self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
1100
- self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
1101
- raise ExchangeError(feedback) # unknown message
1102
- return None