Skip to content

Commit 8413317

Browse files
authored
Merge branch 'ccxt:master' into master
2 parents 65648d8 + a76e668 commit 8413317

391 files changed

Lines changed: 9637 additions & 7054 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,13 +226,13 @@ console.log(version, Object.keys(exchanges));
226226

227227
All-in-one browser bundle (dependencies included), served from a CDN of your choice:
228228

229-
* jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.4.77/dist/ccxt.browser.min.js
230-
* unpkg: https://unpkg.com/ccxt@4.4.77/dist/ccxt.browser.min.js
229+
* jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.4.78/dist/ccxt.browser.min.js
230+
* unpkg: https://unpkg.com/ccxt@4.4.78/dist/ccxt.browser.min.js
231231

232232
CDNs are not updated in real-time and may have delays. Defaulting to the most recent version without specifying the version number is not recommended. Please, keep in mind that we are not responsible for the correct operation of those CDN servers.
233233

234234
```HTML
235-
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.4.77/dist/ccxt.browser.min.js"></script>
235+
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.4.78/dist/ccxt.browser.min.js"></script>
236236
```
237237

238238
Creates a global `ccxt` object:

cs/ccxt/base/Exchange.MetaData.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ namespace ccxt;
33
// file updated automatically by vss and export-exchanges
44
public partial class Exchange
55
{
6-
public static string ccxtVersion = "4.4.77";
6+
public static string ccxtVersion = "4.4.78";
77

88
public static List<string> exchanges = new List<string> { "alpaca", "apex", "ascendex", "bequant", "bigone", "binance", "binancecoinm", "binanceus", "binanceusdm", "bingx", "bit2c", "bitbank", "bitbns", "bitfinex", "bitflyer", "bitget", "bithumb", "bitmart", "bitmex", "bitopro", "bitrue", "bitso", "bitstamp", "bitteam", "bitvavo", "bl3p", "blockchaincom", "blofin", "btcalpha", "btcbox", "btcmarkets", "btcturk", "bybit", "cex", "coinbase", "coinbaseadvanced", "coinbaseexchange", "coinbaseinternational", "coincatch", "coincheck", "coinex", "coinlist", "coinmate", "coinmetro", "coinone", "coinsph", "coinspot", "cryptocom", "cryptomus", "defx", "delta", "deribit", "derive", "digifinex", "ellipx", "exmo", "fmfwio", "gate", "gateio", "gemini", "hashkey", "hitbtc", "hollaex", "htx", "huobi", "huobijp", "hyperliquid", "idex", "independentreserve", "indodax", "kraken", "krakenfutures", "kucoin", "kucoinfutures", "kuna", "latoken", "lbank", "luno", "mercado", "mexc", "myokx", "ndax", "novadax", "oceanex", "okcoin", "okx", "onetrading", "oxfun", "p2b", "paradex", "paymium", "phemex", "poloniex", "probit", "timex", "tokocrypto", "tradeogre", "upbit", "vertex", "wavesexchange", "whitebit", "woo", "woofipro", "xt", "yobit", "zaif", "zonda" };
99
}

cs/ccxt/ccxt.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
<PropertyGroup>
1111
<PackageId>ccxt</PackageId>
1212
<Authors>Carlos, Kroitor, Carlo</Authors>
13-
<PackageVersion>4.4.77</PackageVersion>
14-
<AssemblyVersion>4.4.77</AssemblyVersion>
15-
<FileVersion>4.4.77</FileVersion>
13+
<PackageVersion>4.4.78</PackageVersion>
14+
<AssemblyVersion>4.4.78</AssemblyVersion>
15+
<FileVersion>4.4.78</FileVersion>
1616
<PackageReadmeFile>README.md</PackageReadmeFile>
1717
<Description>Cryptocurrency trading API with support for more than 100 bitcoin/altcoin exchanges</Description>
1818
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>

cs/ccxt/exchanges/bitget.cs

Lines changed: 70 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,28 +1329,41 @@ public override object describe()
13291329
{ "fillResponseFromRequest", true },
13301330
} },
13311331
{ "fetchOHLCV", new Dictionary<string, object>() {
1332-
{ "spot", new Dictionary<string, object>() {
1333-
{ "method", "publicSpotGetV2SpotMarketCandles" },
1334-
} },
1335-
{ "swap", new Dictionary<string, object>() {
1336-
{ "method", "publicMixGetV2MixMarketCandles" },
1337-
} },
1338-
{ "maxDaysPerTimeframe", new Dictionary<string, object>() {
1332+
{ "maxRecentDaysPerTimeframe", new Dictionary<string, object>() {
13391333
{ "1m", 30 },
13401334
{ "3m", 30 },
13411335
{ "5m", 30 },
1342-
{ "10m", 30 },
1343-
{ "15m", 52 },
1344-
{ "30m", 62 },
1345-
{ "1h", 83 },
1346-
{ "2h", 120 },
1336+
{ "15m", 30 },
1337+
{ "30m", 30 },
1338+
{ "1h", 60 },
13471339
{ "4h", 240 },
13481340
{ "6h", 360 },
1349-
{ "12h", 360 },
1350-
{ "1d", 300 },
1351-
{ "3d", 300 },
1352-
{ "1w", 300 },
1353-
{ "1M", 300 },
1341+
{ "12h", 720 },
1342+
{ "1d", 1440 },
1343+
{ "3d", multiply(1440, 3) },
1344+
{ "1w", multiply(1440, 7) },
1345+
{ "1M", multiply(1440, 30) },
1346+
} },
1347+
{ "spot", new Dictionary<string, object>() {
1348+
{ "maxLimitPerTimeframe", new Dictionary<string, object>() {
1349+
{ "1d", 300 },
1350+
{ "3d", 100 },
1351+
{ "1w", 100 },
1352+
{ "1M", 100 },
1353+
} },
1354+
{ "method", "publicSpotGetV2SpotMarketCandles" },
1355+
} },
1356+
{ "swap", new Dictionary<string, object>() {
1357+
{ "maxLimitPerTimeframe", new Dictionary<string, object>() {
1358+
{ "4h", 540 },
1359+
{ "6h", 360 },
1360+
{ "12h", 180 },
1361+
{ "1d", 90 },
1362+
{ "3d", 30 },
1363+
{ "1w", 13 },
1364+
{ "1M", 4 },
1365+
} },
1366+
{ "method", "publicMixGetV2MixMarketCandles" },
13541367
} },
13551368
} },
13561369
{ "fetchTrades", new Dictionary<string, object>() {
@@ -1544,7 +1557,7 @@ public override object describe()
15441557
{ "symbolRequired", false },
15451558
} },
15461559
{ "fetchOHLCV", new Dictionary<string, object>() {
1547-
{ "limit", 1000 },
1560+
{ "limit", 200 },
15481561
} },
15491562
} },
15501563
{ "forPerps", new Dictionary<string, object>() {
@@ -1621,14 +1634,11 @@ public virtual object handleProductTypeAndParams(object market = null, object pa
16211634
if (isTrue(isTrue((!isEqual(subType, null))) && isTrue((isEqual(market, null)))))
16221635
{
16231636
// set default only if subType is defined and market is not defined, since there is also USDC productTypes which are also linear
1624-
object sandboxMode = this.safeBool(this.options, "sandboxMode", false);
1625-
if (isTrue(sandboxMode))
1626-
{
1627-
defaultProductType = ((bool) isTrue((isEqual(subType, "linear")))) ? "SUSDT-FUTURES" : "SCOIN-FUTURES";
1628-
} else
1629-
{
1630-
defaultProductType = ((bool) isTrue((isEqual(subType, "linear")))) ? "USDT-FUTURES" : "COIN-FUTURES";
1631-
}
1637+
// const sandboxMode = this.safeBool (this.options, 'sandboxMode', false);
1638+
// if (sandboxMode) {
1639+
// defaultProductType = (subType === 'linear') ? 'SUSDT-FUTURES' : 'SCOIN-FUTURES';
1640+
// } else {
1641+
defaultProductType = ((bool) isTrue((isEqual(subType, "linear")))) ? "USDT-FUTURES" : "COIN-FUTURES";
16321642
}
16331643
object productType = this.safeString(parameters, "productType", defaultProductType);
16341644
if (isTrue(isTrue((isEqual(productType, null))) && isTrue((!isEqual(market, null)))))
@@ -3607,30 +3617,32 @@ public async override Task<object> fetchOHLCV(object symbol, object timeframe =
36073617
object market = this.market(symbol);
36083618
object marketType = ((bool) isTrue(getValue(market, "spot"))) ? "spot" : "swap";
36093619
object timeframes = getValue(getValue(this.options, "timeframes"), marketType);
3610-
object msInDay = 86400000;
3611-
object duration = multiply(this.parseTimeframe(timeframe), 1000);
36123620
object request = new Dictionary<string, object>() {
36133621
{ "symbol", getValue(market, "id") },
36143622
{ "granularity", this.safeString(timeframes, timeframe, timeframe) },
36153623
};
3624+
object msInDay = 86400000;
3625+
object now = this.milliseconds();
3626+
object duration = multiply(this.parseTimeframe(timeframe), 1000);
36163627
object until = this.safeInteger(parameters, "until");
36173628
object limitDefined = !isEqual(limit, null);
36183629
object sinceDefined = !isEqual(since, null);
36193630
object untilDefined = !isEqual(until, null);
36203631
parameters = this.omit(parameters, new List<object>() {"until"});
3621-
object response = null;
3622-
object now = this.milliseconds();
36233632
// retrievable periods listed here:
36243633
// - https://www.bitget.com/api-doc/spot/market/Get-Candle-Data#request-parameters
36253634
// - https://www.bitget.com/api-doc/contract/market/Get-Candle-Data#description
3626-
object ohlcOptions = this.safeDict(this.options, "fetchOHLCV", new Dictionary<string, object>() {});
3627-
object retrievableDaysMap = this.safeDict(ohlcOptions, "maxDaysPerTimeframe", new Dictionary<string, object>() {});
3628-
object maxRetrievableDaysForRecent = this.safeInteger(retrievableDaysMap, timeframe, 30); // default to safe minimum
3629-
object endpointTsBoundary = subtract(now, multiply((subtract(maxRetrievableDaysForRecent, 1)), msInDay));
3635+
object key = ((bool) isTrue(getValue(market, "spot"))) ? "spot" : "swap";
3636+
object ohlcOptions = this.safeDict(getValue(this.options, "fetchOHLCV"), key, new Dictionary<string, object>() {});
3637+
object maxLimitPerTimeframe = this.safeDict(ohlcOptions, "maxLimitPerTimeframe", new Dictionary<string, object>() {});
3638+
object maxLimitForThisTimeframe = this.safeInteger(maxLimitPerTimeframe, timeframe, limit);
3639+
object recentEndpointDaysMap = this.safeDict(getValue(this.options, "fetchOHLCV"), "maxRecentDaysPerTimeframe", new Dictionary<string, object>() {});
3640+
object recentEndpointAvailableDays = this.safeInteger(recentEndpointDaysMap, timeframe);
3641+
object recentEndpointBoundaryTs = subtract(now, multiply((subtract(recentEndpointAvailableDays, 1)), msInDay));
36303642
if (isTrue(limitDefined))
36313643
{
36323644
limit = mathMin(limit, maxLimitForRecentEndpoint);
3633-
((IDictionary<string,object>)request)["limit"] = limit;
3645+
limit = mathMin(limit, maxLimitForThisTimeframe);
36343646
} else
36353647
{
36363648
limit = defaultLimit;
@@ -3659,20 +3671,36 @@ public async override Task<object> fetchOHLCV(object symbol, object timeframe =
36593671
calculatedStartTime = subtract(calculatedEndTime, limitMultipliedDuration);
36603672
}
36613673
}
3662-
object historicalEndpointNeeded = isTrue((!isEqual(calculatedStartTime, null))) && isTrue((isLessThanOrEqual(calculatedStartTime, endpointTsBoundary)));
3663-
if (isTrue(historicalEndpointNeeded))
3674+
// if historical endpoint is needed, we should re-set the variables
3675+
object historicalEndpointNeeded = false;
3676+
if (isTrue(isTrue((isTrue(!isEqual(calculatedStartTime, null)) && isTrue(isLessThanOrEqual(calculatedStartTime, recentEndpointBoundaryTs)))) || isTrue(useHistoryEndpoint)))
36643677
{
3678+
historicalEndpointNeeded = true;
36653679
// only for "historical-candles" - ensure we use correct max limit
3666-
if (isTrue(limitDefined))
3667-
{
3668-
((IDictionary<string,object>)request)["limit"] = mathMin(limit, maxLimitForHistoryEndpoint);
3680+
limit = mathMin(limit, maxLimitForHistoryEndpoint);
3681+
limitMultipliedDuration = multiply(limit, duration);
3682+
calculatedStartTime = subtract(calculatedEndTime, limitMultipliedDuration);
3683+
((IDictionary<string,object>)request)["startTime"] = calculatedStartTime;
3684+
// for contract, maximum 90 days allowed between start-end times
3685+
if (!isTrue(getValue(market, "spot")))
3686+
{
3687+
object maxDistanceDaysForContracts = 90;
3688+
// only correct if request is larger
3689+
if (isTrue(isGreaterThan(subtract(calculatedEndTime, calculatedStartTime), multiply(maxDistanceDaysForContracts, msInDay))))
3690+
{
3691+
calculatedEndTime = this.sum(calculatedStartTime, multiply(maxDistanceDaysForContracts, msInDay));
3692+
((IDictionary<string,object>)request)["endTime"] = calculatedEndTime;
3693+
}
36693694
}
36703695
}
3696+
// we need to set limit to safely cover the period
3697+
((IDictionary<string,object>)request)["limit"] = limit;
36713698
// make request
3699+
object response = null;
36723700
if (isTrue(getValue(market, "spot")))
36733701
{
36743702
// checks if we need history endpoint
3675-
if (isTrue(isTrue(historicalEndpointNeeded) || isTrue(useHistoryEndpoint)))
3703+
if (isTrue(historicalEndpointNeeded))
36763704
{
36773705
response = await this.publicSpotGetV2SpotMarketHistoryCandles(this.extend(request, parameters));
36783706
} else
@@ -3681,18 +3709,6 @@ public async override Task<object> fetchOHLCV(object symbol, object timeframe =
36813709
}
36823710
} else
36833711
{
3684-
object maxDistanceDaysForContracts = 90; // for contract, maximum 90 days allowed between start-end times
3685-
// only correct the request to fix 90 days if until was auto-calculated
3686-
if (isTrue(sinceDefined))
3687-
{
3688-
if (!isTrue(untilDefined))
3689-
{
3690-
((IDictionary<string,object>)request)["endTime"] = mathMin(calculatedEndTime, this.sum(since, multiply(maxDistanceDaysForContracts, msInDay)));
3691-
} else if (isTrue(isGreaterThan(subtract(calculatedEndTime, calculatedStartTime), multiply(maxDistanceDaysForContracts, msInDay))))
3692-
{
3693-
throw new BadRequest ((string)add(add(add(this.id, " fetchOHLCV() between start and end must be less than "), ((object)maxDistanceDaysForContracts).ToString()), " days")) ;
3694-
}
3695-
}
36963712
object priceType = null;
36973713
var priceTypeparametersVariable = this.handleParamString(parameters, "price");
36983714
priceType = ((IList<object>)priceTypeparametersVariable)[0];
@@ -3712,7 +3728,7 @@ public async override Task<object> fetchOHLCV(object symbol, object timeframe =
37123728
response = await this.publicMixGetV2MixMarketHistoryIndexCandles(extended);
37133729
} else
37143730
{
3715-
if (isTrue(isTrue(historicalEndpointNeeded) || isTrue(useHistoryEndpoint)))
3731+
if (isTrue(historicalEndpointNeeded))
37163732
{
37173733
response = await this.publicMixGetV2MixMarketHistoryCandles(extended);
37183734
} else

cs/ccxt/exchanges/bitmex.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,7 @@ public async override Task<object> fetchCurrencies(object parameters = null)
480480
object maxWithdrawal = this.parseNumber(Precise.stringMul(maxWithdrawalString, precisionString));
481481
object minDepositString = this.safeString(currency, "minDepositAmount");
482482
object minDeposit = this.parseNumber(Precise.stringMul(minDepositString, precisionString));
483+
object isCrypto = isEqual(this.safeString(currency, "currencyType"), "Crypto");
483484
((IDictionary<string,object>)result)[(string)code] = new Dictionary<string, object>() {
484485
{ "id", id },
485486
{ "code", code },
@@ -505,6 +506,7 @@ public async override Task<object> fetchCurrencies(object parameters = null)
505506
} },
506507
} },
507508
{ "networks", networks },
509+
{ "type", ((bool) isTrue(isCrypto)) ? "crypto" : "other" },
508510
};
509511
}
510512
return result;

cs/ccxt/exchanges/bitopro.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ public async override Task<object> fetchCurrencies(object parameters = null)
373373
{ "fee", fee },
374374
{ "precision", null },
375375
{ "limits", limits },
376+
{ "networks", null },
376377
};
377378
}
378379
return result;

cs/ccxt/exchanges/bitrue.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,8 @@ public async override Task<object> fetchCurrencies(object parameters = null)
789789
{ "withdraw", withdraw },
790790
{ "networks", networks },
791791
{ "fee", this.parseNumber(minWithdrawFeeString) },
792+
{ "fees", null },
793+
{ "type", "crypto" },
792794
{ "limits", new Dictionary<string, object>() {
793795
{ "withdraw", new Dictionary<string, object>() {
794796
{ "min", this.parseNumber(minWithdrawString) },

cs/ccxt/exchanges/bitvavo.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,7 @@ public virtual object parseCurrenciesCustom(object currencies)
597597
{ "networks", networks },
598598
{ "fee", withdrawFee },
599599
{ "precision", precision },
600+
{ "type", "crypto" },
600601
{ "limits", new Dictionary<string, object>() {
601602
{ "amount", new Dictionary<string, object>() {
602603
{ "min", null },

0 commit comments

Comments
 (0)