ccxt 4.3.44__py2.py3-none-any.whl → 4.3.45__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/__init__.py +3 -1
- ccxt/abstract/bitstamp.py +18 -2
- ccxt/abstract/kucoin.py +14 -0
- ccxt/abstract/kucoinfutures.py +14 -0
- ccxt/abstract/oxfun.py +34 -0
- ccxt/async_support/__init__.py +3 -1
- ccxt/async_support/base/exchange.py +1 -1
- ccxt/async_support/bitstamp.py +18 -2
- ccxt/async_support/kucoin.py +27 -1
- ccxt/async_support/luno.py +9 -1
- ccxt/async_support/oxfun.py +2773 -0
- ccxt/async_support/wavesexchange.py +118 -105
- ccxt/async_support/xt.py +1 -1
- ccxt/base/exchange.py +1 -1
- ccxt/bitstamp.py +18 -2
- ccxt/kucoin.py +27 -1
- ccxt/luno.py +9 -1
- ccxt/oxfun.py +2772 -0
- ccxt/pro/__init__.py +3 -1
- ccxt/pro/oxfun.py +950 -0
- ccxt/test/test_async.py +17 -1
- ccxt/test/test_sync.py +17 -1
- ccxt/wavesexchange.py +118 -105
- ccxt/xt.py +1 -1
- {ccxt-4.3.44.dist-info → ccxt-4.3.45.dist-info}/METADATA +8 -8
- {ccxt-4.3.44.dist-info → ccxt-4.3.45.dist-info}/RECORD +28 -24
- {ccxt-4.3.44.dist-info → ccxt-4.3.45.dist-info}/WHEEL +0 -0
- {ccxt-4.3.44.dist-info → ccxt-4.3.45.dist-info}/top_level.txt +0 -0
@@ -21,7 +21,7 @@ from ccxt.base.errors import InvalidOrder
|
|
21
21
|
from ccxt.base.errors import OrderNotFound
|
22
22
|
from ccxt.base.errors import DuplicateOrderId
|
23
23
|
from ccxt.base.errors import ExchangeNotAvailable
|
24
|
-
from ccxt.base.decimal_to_precision import
|
24
|
+
from ccxt.base.decimal_to_precision import TICK_SIZE
|
25
25
|
from ccxt.base.precise import Precise
|
26
26
|
|
27
27
|
|
@@ -329,9 +329,9 @@ class wavesexchange(Exchange, ImplicitAPI):
|
|
329
329
|
},
|
330
330
|
},
|
331
331
|
'currencies': {
|
332
|
-
'WX': self.safe_currency_structure({'id': 'EMAMLxDnv3xiz8RXg8Btj33jcEw3wLczL3JKYYmuubpc', 'numericId': None, 'code': 'WX', 'precision': self.
|
332
|
+
'WX': self.safe_currency_structure({'id': 'EMAMLxDnv3xiz8RXg8Btj33jcEw3wLczL3JKYYmuubpc', 'numericId': None, 'code': 'WX', 'precision': self.parse_number('1e-8')}),
|
333
333
|
},
|
334
|
-
'precisionMode':
|
334
|
+
'precisionMode': TICK_SIZE,
|
335
335
|
'options': {
|
336
336
|
'allowedCandles': 1440,
|
337
337
|
'accessToken': None,
|
@@ -342,7 +342,7 @@ class wavesexchange(Exchange, ImplicitAPI):
|
|
342
342
|
'wavesAddress': None,
|
343
343
|
'withdrawFeeUSDN': 7420,
|
344
344
|
'withdrawFeeWAVES': 100000,
|
345
|
-
'wavesPrecision': 8,
|
345
|
+
'wavesPrecision': 1e-8,
|
346
346
|
'messagePrefix': 'W', # W for production, T for testnet
|
347
347
|
'networks': {
|
348
348
|
'ERC20': 'ETH',
|
@@ -390,8 +390,8 @@ class wavesexchange(Exchange, ImplicitAPI):
|
|
390
390
|
async def get_fees_for_asset(self, symbol: str, side, amount, price, params={}):
|
391
391
|
await self.load_markets()
|
392
392
|
market = self.market(symbol)
|
393
|
-
amount = self.
|
394
|
-
price = self.
|
393
|
+
amount = self.to_real_symbol_amount(symbol, amount)
|
394
|
+
price = self.to_real_symbol_price(symbol, price)
|
395
395
|
request = self.extend({
|
396
396
|
'baseId': market['baseId'],
|
397
397
|
'quoteId': market['quoteId'],
|
@@ -422,7 +422,7 @@ class wavesexchange(Exchange, ImplicitAPI):
|
|
422
422
|
matcherFee = self.safe_string(mode, 'matcherFee')
|
423
423
|
feeAssetId = self.safe_string(mode, 'feeAssetId')
|
424
424
|
feeAsset = self.safe_currency_code(feeAssetId)
|
425
|
-
adjustedMatcherFee = self.
|
425
|
+
adjustedMatcherFee = self.from_real_currency_amount(feeAsset, matcherFee)
|
426
426
|
amountAsString = self.number_to_string(amount)
|
427
427
|
priceAsString = self.number_to_string(price)
|
428
428
|
feeCost = self.fee_to_precision(symbol, self.parse_number(adjustedMatcherFee))
|
@@ -570,8 +570,8 @@ class wavesexchange(Exchange, ImplicitAPI):
|
|
570
570
|
'strike': None,
|
571
571
|
'optionType': None,
|
572
572
|
'precision': {
|
573
|
-
'amount': self.
|
574
|
-
'price': self.
|
573
|
+
'amount': self.parse_number(self.parse_precision(self.safe_string(entry, 'amountAssetDecimals'))),
|
574
|
+
'price': self.parse_number(self.parse_precision(self.safe_string(entry, 'priceAssetDecimals'))),
|
575
575
|
},
|
576
576
|
'limits': {
|
577
577
|
'leverage': {
|
@@ -625,12 +625,11 @@ class wavesexchange(Exchange, ImplicitAPI):
|
|
625
625
|
|
626
626
|
def parse_order_book_side(self, bookSide, market=None, limit: Int = None):
|
627
627
|
precision = market['precision']
|
628
|
-
wavesPrecision = self.safe_string(self.options, 'wavesPrecision', '8')
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
pricePrecision = '1e' + Precise.string_sub(wavesPrecision, difference)
|
628
|
+
wavesPrecision = self.safe_string(self.options, 'wavesPrecision', '1e-8')
|
629
|
+
amountPrecisionString = self.safe_string(precision, 'amount')
|
630
|
+
pricePrecisionString = self.safe_string(precision, 'price')
|
631
|
+
difference = Precise.string_div(amountPrecisionString, pricePrecisionString)
|
632
|
+
pricePrecision = Precise.string_div(wavesPrecision, difference)
|
634
633
|
result = []
|
635
634
|
for i in range(0, len(bookSide)):
|
636
635
|
entry = bookSide[i]
|
@@ -639,9 +638,9 @@ class wavesexchange(Exchange, ImplicitAPI):
|
|
639
638
|
price = None
|
640
639
|
amount = None
|
641
640
|
if (pricePrecision is not None) and (entryPrice is not None):
|
642
|
-
price = Precise.
|
643
|
-
if (
|
644
|
-
amount = Precise.
|
641
|
+
price = Precise.string_mul(entryPrice, pricePrecision)
|
642
|
+
if (amountPrecisionString is not None) and (entryAmount is not None):
|
643
|
+
amount = Precise.string_mul(entryAmount, amountPrecisionString)
|
645
644
|
if (limit is not None) and (i > limit):
|
646
645
|
break
|
647
646
|
result.append([
|
@@ -1171,50 +1170,35 @@ class wavesexchange(Exchange, ImplicitAPI):
|
|
1171
1170
|
return ''
|
1172
1171
|
return currencyId
|
1173
1172
|
|
1174
|
-
def
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
precisionPrice = self.number_to_string(market['precision']['price'])
|
1179
|
-
difference = Precise.string_sub(amount, precisionPrice)
|
1180
|
-
precision = Precise.string_sub(wavesPrecision, difference)
|
1181
|
-
pricePrecision = self.to_precision(price, str(precision))
|
1182
|
-
return self.parse_to_int(float(pricePrecision))
|
1183
|
-
|
1184
|
-
def custom_amount_to_precision(self, symbol, amount):
|
1185
|
-
amountPrecision = self.number_to_string(self.to_precision(amount, self.number_to_string(self.markets[symbol]['precision']['amount'])))
|
1186
|
-
return self.parse_to_int(float(amountPrecision))
|
1173
|
+
def to_real_currency_amount(self, code: str, amount: float, networkCode=None):
|
1174
|
+
currency = self.currency(code)
|
1175
|
+
stringValue = Precise.string_div(self.number_to_string(amount), self.safe_string(currency, 'precision'))
|
1176
|
+
return int(stringValue)
|
1187
1177
|
|
1188
|
-
def
|
1189
|
-
|
1190
|
-
|
1178
|
+
def from_real_currency_amount(self, code: str, amountString: str):
|
1179
|
+
if not (code in self.currencies):
|
1180
|
+
return amountString
|
1181
|
+
currency = self.currency(code)
|
1182
|
+
precisionAmount = self.safe_string(currency, 'precision')
|
1183
|
+
return Precise.string_mul(amountString, precisionAmount)
|
1191
1184
|
|
1192
|
-
def
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
precise.decimals = self.sum(precise.decimals, scale)
|
1197
|
-
precise.reduce()
|
1198
|
-
return str(precise)
|
1185
|
+
def to_real_symbol_price(self, symbol: str, price: float):
|
1186
|
+
market = self.market(symbol)
|
1187
|
+
stringValue = Precise.string_div(self.number_to_string(price), self.safe_string(market['precision'], 'price'))
|
1188
|
+
return int(stringValue)
|
1199
1189
|
|
1200
|
-
def
|
1201
|
-
|
1202
|
-
|
1203
|
-
# precise.decimals should be integer
|
1204
|
-
precise.decimals = self.parse_to_int(Precise.string_sub(self.number_to_string(precise.decimals), self.number_to_string(scale)))
|
1205
|
-
precise.reduce()
|
1206
|
-
stringValue = str(precise)
|
1207
|
-
return stringValue
|
1190
|
+
def from_real_symbol_price(self, symbol: str, priceString: str):
|
1191
|
+
market = self.markets[symbol]
|
1192
|
+
return Precise.string_mul(priceString, self.safe_string(market['precision'], 'price'))
|
1208
1193
|
|
1209
|
-
def
|
1210
|
-
|
1211
|
-
|
1194
|
+
def to_real_symbol_amount(self, symbol: str, amount: float):
|
1195
|
+
market = self.market(symbol)
|
1196
|
+
stringValue = Precise.string_div(self.number_to_string(amount), self.safe_string(market['precision'], 'amount'))
|
1197
|
+
return int(stringValue)
|
1212
1198
|
|
1213
|
-
def
|
1199
|
+
def from_real_symbol_amount(self, symbol: str, amountString: str):
|
1214
1200
|
market = self.markets[symbol]
|
1215
|
-
|
1216
|
-
scale = self.sum(wavesPrecision, market['precision']['price']) - market['precision']['amount']
|
1217
|
-
return self.from_precision(price, scale)
|
1201
|
+
return Precise.string_mul(amountString, market['precision']['amount'])
|
1218
1202
|
|
1219
1203
|
def safe_get_dynamic(self, settings):
|
1220
1204
|
orderFee = self.safe_value(settings, 'orderFee')
|
@@ -1288,26 +1272,26 @@ class wavesexchange(Exchange, ImplicitAPI):
|
|
1288
1272
|
raise InvalidOrder(self.id + ' asset fee must be ' + baseFeeAsset + ' or ' + discountFeeAsset)
|
1289
1273
|
matcherFeeAsset = self.safe_currency_code(matcherFeeAssetId)
|
1290
1274
|
rawMatcherFee = baseMatcherFee if (matcherFeeAssetId == baseFeeAssetId) else discountMatcherFee
|
1291
|
-
floatMatcherFee = float(self.
|
1275
|
+
floatMatcherFee = float(self.from_real_currency_amount(matcherFeeAsset, rawMatcherFee))
|
1292
1276
|
if (matcherFeeAsset in balances) and (balances[matcherFeeAsset]['free'] >= floatMatcherFee):
|
1293
1277
|
matcherFee = int(rawMatcherFee)
|
1294
1278
|
else:
|
1295
1279
|
raise InsufficientFunds(self.id + ' not enough funds of the selected asset fee')
|
1280
|
+
floatBaseMatcherFee = self.from_real_currency_amount(baseFeeAsset, baseMatcherFee)
|
1281
|
+
floatDiscountMatcherFee = self.from_real_currency_amount(discountFeeAsset, discountMatcherFee)
|
1296
1282
|
if matcherFeeAssetId is None:
|
1297
1283
|
# try to the pay the fee using the base first then discount asset
|
1298
|
-
|
1299
|
-
if (baseFeeAsset in balances) and (balances[baseFeeAsset]['free'] >= floatBaseMatcherFee):
|
1284
|
+
if (baseFeeAsset in balances) and (balances[baseFeeAsset]['free'] >= float(floatBaseMatcherFee)):
|
1300
1285
|
matcherFeeAssetId = baseFeeAssetId
|
1301
1286
|
matcherFee = int(baseMatcherFee)
|
1302
1287
|
else:
|
1303
|
-
|
1304
|
-
if (discountFeeAsset in balances) and (balances[discountFeeAsset]['free'] >= floatDiscountMatcherFee):
|
1288
|
+
if (discountFeeAsset in balances) and (balances[discountFeeAsset]['free'] >= float(floatDiscountMatcherFee)):
|
1305
1289
|
matcherFeeAssetId = discountFeeAssetId
|
1306
1290
|
matcherFee = int(discountMatcherFee)
|
1307
1291
|
if matcherFeeAssetId is None:
|
1308
|
-
raise InsufficientFunds(self.id + ' not enough funds on none of the eligible asset fees')
|
1309
|
-
amount = self.
|
1310
|
-
price = self.
|
1292
|
+
raise InsufficientFunds(self.id + ' not enough funds on none of the eligible asset fees: ' + baseFeeAsset + ' ' + floatBaseMatcherFee + ' or ' + discountFeeAsset + ' ' + floatDiscountMatcherFee)
|
1293
|
+
amount = self.to_real_symbol_amount(symbol, amount)
|
1294
|
+
price = self.to_real_symbol_price(symbol, price)
|
1311
1295
|
assetPair: dict = {
|
1312
1296
|
'amountAsset': amountAsset,
|
1313
1297
|
'priceAsset': priceAsset,
|
@@ -1345,7 +1329,7 @@ class wavesexchange(Exchange, ImplicitAPI):
|
|
1345
1329
|
'c': {
|
1346
1330
|
't': 'sp',
|
1347
1331
|
'v': {
|
1348
|
-
'p': self.
|
1332
|
+
'p': self.to_real_symbol_price(symbol, stopPrice),
|
1349
1333
|
},
|
1350
1334
|
},
|
1351
1335
|
}
|
@@ -1671,23 +1655,23 @@ class wavesexchange(Exchange, ImplicitAPI):
|
|
1671
1655
|
elif market is not None:
|
1672
1656
|
symbol = market['symbol']
|
1673
1657
|
amountCurrency = self.safe_currency_code(self.safe_string(assetPair, 'amountAsset', 'WAVES'))
|
1674
|
-
price = self.
|
1675
|
-
amount = self.
|
1676
|
-
filled = self.
|
1677
|
-
average = self.
|
1658
|
+
price = self.from_real_symbol_price(symbol, priceString)
|
1659
|
+
amount = self.from_real_currency_amount(amountCurrency, amountString)
|
1660
|
+
filled = self.from_real_currency_amount(amountCurrency, filledString)
|
1661
|
+
average = self.from_real_symbol_price(symbol, self.safe_string(order, 'avgWeighedPrice'))
|
1678
1662
|
status = self.parse_order_status(self.safe_string(order, 'status'))
|
1679
1663
|
fee = None
|
1680
1664
|
if 'type' in order:
|
1681
|
-
|
1665
|
+
code = self.safe_currency_code(self.safe_string(order, 'feeAsset'))
|
1682
1666
|
fee = {
|
1683
|
-
'currency':
|
1684
|
-
'fee': self.parse_number(self.
|
1667
|
+
'currency': code,
|
1668
|
+
'fee': self.parse_number(self.from_real_currency_amount(code, self.safe_string(order, 'filledFee'))),
|
1685
1669
|
}
|
1686
1670
|
else:
|
1687
|
-
|
1671
|
+
code = self.safe_currency_code(self.safe_string(order, 'matcherFeeAssetId', 'WAVES'))
|
1688
1672
|
fee = {
|
1689
|
-
'currency':
|
1690
|
-
'fee': self.parse_number(self.
|
1673
|
+
'currency': code,
|
1674
|
+
'fee': self.parse_number(self.from_real_currency_amount(code, self.safe_string(order, 'matcherFee'))),
|
1691
1675
|
}
|
1692
1676
|
triggerPrice = None
|
1693
1677
|
attachment = self.safe_string(order, 'attachment')
|
@@ -1802,16 +1786,14 @@ class wavesexchange(Exchange, ImplicitAPI):
|
|
1802
1786
|
issueTransaction = self.safe_value(entry, 'issueTransaction')
|
1803
1787
|
currencyId = self.safe_string(entry, 'assetId')
|
1804
1788
|
balance = self.safe_string(entry, 'balance')
|
1805
|
-
|
1806
|
-
|
1807
|
-
nonStandardBalances.append(balance)
|
1808
|
-
continue
|
1809
|
-
decimals = self.safe_integer(issueTransaction, 'decimals')
|
1810
|
-
code = None
|
1811
|
-
if currencyId in self.currencies_by_id:
|
1789
|
+
currencyExists = (currencyId in self.currencies_by_id)
|
1790
|
+
if currencyExists:
|
1812
1791
|
code = self.safe_currency_code(currencyId)
|
1813
1792
|
result[code] = self.account()
|
1814
|
-
result[code]['total'] = self.
|
1793
|
+
result[code]['total'] = self.from_real_currency_amount(code, balance)
|
1794
|
+
elif issueTransaction is None:
|
1795
|
+
assetIds.append(currencyId)
|
1796
|
+
nonStandardBalances.append(balance)
|
1815
1797
|
nonStandardAssets = len(assetIds)
|
1816
1798
|
if nonStandardAssets:
|
1817
1799
|
requestInner: dict = {
|
@@ -1823,11 +1805,11 @@ class wavesexchange(Exchange, ImplicitAPI):
|
|
1823
1805
|
entry = data[i]
|
1824
1806
|
balance = nonStandardBalances[i]
|
1825
1807
|
inner = self.safe_value(entry, 'data')
|
1826
|
-
|
1808
|
+
precision = self.parse_precision(self.safe_string(inner, 'precision'))
|
1827
1809
|
ticker = self.safe_string(inner, 'ticker')
|
1828
1810
|
code = self.safe_currency_code(ticker)
|
1829
1811
|
result[code] = self.account()
|
1830
|
-
result[code]['total'] =
|
1812
|
+
result[code]['total'] = Precise.string_mul(balance, precision)
|
1831
1813
|
currentTimestamp = self.milliseconds()
|
1832
1814
|
byteArray = [
|
1833
1815
|
self.base58_to_binary(self.apiKey),
|
@@ -1850,10 +1832,7 @@ class wavesexchange(Exchange, ImplicitAPI):
|
|
1850
1832
|
if not (code in result):
|
1851
1833
|
result[code] = self.account()
|
1852
1834
|
amount = self.safe_string(reservedBalance, currencyId)
|
1853
|
-
|
1854
|
-
result[code]['used'] = self.currency_from_precision(code, amount)
|
1855
|
-
else:
|
1856
|
-
result[code]['used'] = amount
|
1835
|
+
result[code]['used'] = self.from_real_currency_amount(code, amount)
|
1857
1836
|
wavesRequest: dict = {
|
1858
1837
|
'address': wavesAddress,
|
1859
1838
|
}
|
@@ -1863,17 +1842,21 @@ class wavesexchange(Exchange, ImplicitAPI):
|
|
1863
1842
|
# "confirmations": 0,
|
1864
1843
|
# "balance": 909085978
|
1865
1844
|
# }
|
1866
|
-
result['WAVES'] = self.safe_value(result, 'WAVES',
|
1867
|
-
result['WAVES']['total'] = self.
|
1868
|
-
|
1869
|
-
for i in range(0, len(codes)):
|
1870
|
-
code = codes[i]
|
1871
|
-
if self.safe_value(result[code], 'used') is None:
|
1872
|
-
result[code]['used'] = '0'
|
1845
|
+
result['WAVES'] = self.safe_value(result, 'WAVES', self.account())
|
1846
|
+
result['WAVES']['total'] = self.from_real_currency_amount('WAVES', self.safe_string(wavesTotal, 'balance'))
|
1847
|
+
result = self.set_undefined_balances_to_zero(result)
|
1873
1848
|
result['timestamp'] = timestamp
|
1874
1849
|
result['datetime'] = self.iso8601(timestamp)
|
1875
1850
|
return self.safe_balance(result)
|
1876
1851
|
|
1852
|
+
def set_undefined_balances_to_zero(self, balances, key='used'):
|
1853
|
+
codes = list(balances.keys())
|
1854
|
+
for i in range(0, len(codes)):
|
1855
|
+
code = codes[i]
|
1856
|
+
if self.safe_value(balances[code], 'used') is None:
|
1857
|
+
balances[code][key] = '0'
|
1858
|
+
return balances
|
1859
|
+
|
1877
1860
|
async def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1878
1861
|
"""
|
1879
1862
|
fetch all trades made by the user
|
@@ -2374,7 +2357,7 @@ class wavesexchange(Exchange, ImplicitAPI):
|
|
2374
2357
|
feeAssetId = 'WAVES'
|
2375
2358
|
type = 4 # transfer
|
2376
2359
|
version = 2
|
2377
|
-
amountInteger = self.
|
2360
|
+
amountInteger = self.to_real_currency_amount(code, amount)
|
2378
2361
|
currency = self.currency(code)
|
2379
2362
|
timestamp = self.milliseconds()
|
2380
2363
|
byteArray = [
|
@@ -2434,18 +2417,45 @@ class wavesexchange(Exchange, ImplicitAPI):
|
|
2434
2417
|
# "amount": 0
|
2435
2418
|
# }
|
2436
2419
|
#
|
2420
|
+
# withdraw new:
|
2421
|
+
# {
|
2422
|
+
# type: "4",
|
2423
|
+
# id: "2xnWTqG9ar7jEDrLxfbVyyspPZ6XZNrrw9ai9sQ81Eya",
|
2424
|
+
# fee: "100000",
|
2425
|
+
# feeAssetId: null,
|
2426
|
+
# timestamp: "1715786263807",
|
2427
|
+
# version: "2",
|
2428
|
+
# sender: "3P81LLX1kk2CSJC9L8C2enxdHB7XvnSGAEE",
|
2429
|
+
# senderPublicKey: "DdmzmXf9mty1FBE8AdVGnrncVLEAzP4gR4nWoTFAJoXz",
|
2430
|
+
# proofs: ["RyoKwdSYv3EqotJCYftfFM9JE2j1ZpDRxKwYfiRhLAFeyNp6VfJUXNDS884XfeCeHeNypNmTCZt5NYR1ekyjCX3",],
|
2431
|
+
# recipient: "3P9tXxu38a8tgewNEKFzourVxeqHd11ppOc",
|
2432
|
+
# assetId: null,
|
2433
|
+
# feeAsset: null,
|
2434
|
+
# amount: "2000000",
|
2435
|
+
# attachment: "",
|
2436
|
+
# }
|
2437
|
+
#
|
2437
2438
|
currency = self.safe_currency(None, currency)
|
2439
|
+
code = currency['code']
|
2440
|
+
typeRaw = self.safe_string(transaction, 'type')
|
2441
|
+
type = 'withdraw' if (typeRaw == '4') else 'deposit'
|
2442
|
+
amount = self.parse_number(self.from_real_currency_amount(code, self.safe_string(transaction, 'amount')))
|
2443
|
+
feeString = self.safe_string(transaction, 'fee')
|
2444
|
+
feeAssetId = self.safe_string(transaction, 'feeAssetId', 'WAVES')
|
2445
|
+
feeCode = self.safe_currency_code(feeAssetId)
|
2446
|
+
feeAmount = self.parse_number(self.from_real_currency_amount(feeCode, feeString))
|
2447
|
+
timestamp = self.safe_integer(transaction, 'timestamp')
|
2438
2448
|
return {
|
2439
|
-
'id':
|
2449
|
+
'id': self.safe_string(transaction, 'id'),
|
2440
2450
|
'txid': None,
|
2441
|
-
'timestamp':
|
2442
|
-
'datetime':
|
2451
|
+
'timestamp': timestamp,
|
2452
|
+
'datetime': self.iso8601(timestamp),
|
2443
2453
|
'network': None,
|
2444
|
-
'addressFrom':
|
2454
|
+
'addressFrom': self.safe_string(transaction, 'sender'),
|
2445
2455
|
'address': None,
|
2446
|
-
'addressTo':
|
2447
|
-
'amount':
|
2448
|
-
'type':
|
2456
|
+
'addressTo': self.safe_string(transaction, 'recipient'),
|
2457
|
+
'amount': amount,
|
2458
|
+
'type': type,
|
2449
2459
|
'currency': currency['code'],
|
2450
2460
|
'status': None,
|
2451
2461
|
'updated': None,
|
@@ -2454,6 +2464,9 @@ class wavesexchange(Exchange, ImplicitAPI):
|
|
2454
2464
|
'tagTo': None,
|
2455
2465
|
'comment': None,
|
2456
2466
|
'internal': None,
|
2457
|
-
'fee':
|
2467
|
+
'fee': {
|
2468
|
+
'currency': feeCode,
|
2469
|
+
'cost': feeAmount,
|
2470
|
+
},
|
2458
2471
|
'info': transaction,
|
2459
2472
|
}
|
ccxt/async_support/xt.py
CHANGED
ccxt/base/exchange.py
CHANGED
ccxt/bitstamp.py
CHANGED
@@ -232,7 +232,7 @@ class bitstamp(Exchange, ImplicitAPI):
|
|
232
232
|
'uni_withdrawal/': 1,
|
233
233
|
'uni_address/': 1,
|
234
234
|
'yfi_withdrawal/': 1,
|
235
|
-
'yfi_address': 1,
|
235
|
+
'yfi_address/': 1,
|
236
236
|
'audio_withdrawal/': 1,
|
237
237
|
'audio_address/': 1,
|
238
238
|
'crv_withdrawal/': 1,
|
@@ -241,7 +241,7 @@ class bitstamp(Exchange, ImplicitAPI):
|
|
241
241
|
'algo_address/': 1,
|
242
242
|
'comp_withdrawal/': 1,
|
243
243
|
'comp_address/': 1,
|
244
|
-
'grt_withdrawal': 1,
|
244
|
+
'grt_withdrawal/': 1,
|
245
245
|
'grt_address/': 1,
|
246
246
|
'usdt_withdrawal/': 1,
|
247
247
|
'usdt_address/': 1,
|
@@ -379,6 +379,22 @@ class bitstamp(Exchange, ImplicitAPI):
|
|
379
379
|
'vchf_address/': 1,
|
380
380
|
'veur_withdrawal/': 1,
|
381
381
|
'veur_address/': 1,
|
382
|
+
'truf_withdrawal/': 1,
|
383
|
+
'truf_address/': 1,
|
384
|
+
'wif_withdrawal/': 1,
|
385
|
+
'wif_address/': 1,
|
386
|
+
'smt_withdrawal/': 1,
|
387
|
+
'smt_address/': 1,
|
388
|
+
'sui_withdrawal/': 1,
|
389
|
+
'sui_address/': 1,
|
390
|
+
'jup_withdrawal/': 1,
|
391
|
+
'jup_address/': 1,
|
392
|
+
'ondo_withdrawal/': 1,
|
393
|
+
'ondo_address/': 1,
|
394
|
+
'boba_withdrawal/': 1,
|
395
|
+
'boba_address/': 1,
|
396
|
+
'pyth_withdrawal/': 1,
|
397
|
+
'pyth_address/': 1,
|
382
398
|
},
|
383
399
|
},
|
384
400
|
},
|
ccxt/kucoin.py
CHANGED
@@ -140,6 +140,7 @@ class kucoin(Exchange, ImplicitAPI):
|
|
140
140
|
'futuresPublic': 'https://api-futures.kucoin.com',
|
141
141
|
'webExchange': 'https://kucoin.com/_api',
|
142
142
|
'broker': 'https://api-broker.kucoin.com',
|
143
|
+
'earn': 'https://api.kucoin.com',
|
143
144
|
},
|
144
145
|
'www': 'https://www.kucoin.com',
|
145
146
|
'doc': [
|
@@ -407,6 +408,9 @@ class kucoin(Exchange, ImplicitAPI):
|
|
407
408
|
'broker/nd/account': 2,
|
408
409
|
'broker/nd/account/apikey': 2,
|
409
410
|
'broker/nd/rebase/download': 3,
|
411
|
+
'broker/nd/transfer/detail': 1,
|
412
|
+
'broker/nd/deposit/detail': 1,
|
413
|
+
'broker/nd/withdraw/detail': 1,
|
410
414
|
},
|
411
415
|
'post': {
|
412
416
|
'broker/nd/transfer': 1,
|
@@ -418,6 +422,25 @@ class kucoin(Exchange, ImplicitAPI):
|
|
418
422
|
'broker/nd/account/apikey': 3,
|
419
423
|
},
|
420
424
|
},
|
425
|
+
'earn': {
|
426
|
+
'get': {
|
427
|
+
'otc-loan/loan': 1,
|
428
|
+
'otc-loan/accounts': 1,
|
429
|
+
'earn/redeem-preview': 7.5, # 5EW
|
430
|
+
'earn/saving/products': 7.5, # 5EW
|
431
|
+
'earn/hold-assets': 7.5, # 5EW
|
432
|
+
'earn/promotion/products': 7.5, # 5EW
|
433
|
+
'earn/kcs-staking/products': 7.5, # 5EW
|
434
|
+
'earn/staking/products': 7.5, # 5EW
|
435
|
+
'earn/eth-staking/products': 7.5, # 5EW
|
436
|
+
},
|
437
|
+
'post': {
|
438
|
+
'earn/orders': 7.5, # 5EW
|
439
|
+
},
|
440
|
+
'delete': {
|
441
|
+
'earn/orders': 7.5, # 5EW
|
442
|
+
},
|
443
|
+
},
|
421
444
|
},
|
422
445
|
'timeframes': {
|
423
446
|
'1m': '1min',
|
@@ -4506,6 +4529,8 @@ class kucoin(Exchange, ImplicitAPI):
|
|
4506
4529
|
endpoint = '/api/' + version + '/' + self.implode_params(path, params)
|
4507
4530
|
if api == 'webExchange':
|
4508
4531
|
endpoint = '/' + self.implode_params(path, params)
|
4532
|
+
if api == 'earn':
|
4533
|
+
endpoint = '/api/v1/' + self.implode_params(path, params)
|
4509
4534
|
query = self.omit(params, self.extract_params(path))
|
4510
4535
|
endpart = ''
|
4511
4536
|
headers = headers if (headers is not None) else {}
|
@@ -4521,7 +4546,8 @@ class kucoin(Exchange, ImplicitAPI):
|
|
4521
4546
|
isFuturePrivate = (api == 'futuresPrivate')
|
4522
4547
|
isPrivate = (api == 'private')
|
4523
4548
|
isBroker = (api == 'broker')
|
4524
|
-
|
4549
|
+
isEarn = (api == 'earn')
|
4550
|
+
if isPrivate or isFuturePrivate or isBroker or isEarn:
|
4525
4551
|
self.check_required_credentials()
|
4526
4552
|
timestamp = str(self.nonce())
|
4527
4553
|
headers = self.extend({
|
ccxt/luno.py
CHANGED
@@ -897,7 +897,15 @@ class luno(Exchange, ImplicitAPI):
|
|
897
897
|
request: dict = {
|
898
898
|
'order_id': id,
|
899
899
|
}
|
900
|
-
|
900
|
+
response = self.privatePostStoporder(self.extend(request, params))
|
901
|
+
#
|
902
|
+
# {
|
903
|
+
# "success": True
|
904
|
+
# }
|
905
|
+
#
|
906
|
+
return self.safe_order({
|
907
|
+
'info': response,
|
908
|
+
})
|
901
909
|
|
902
910
|
def fetch_ledger_by_entries(self, code: Str = None, entry=None, limit=None, params={}):
|
903
911
|
# by default without entry number or limit number, return most recent entry
|