Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/ccxt/ccxt
Browse files Browse the repository at this point in the history
  • Loading branch information
kroitor committed Jan 17, 2025
2 parents 8d0c70e + 23f3c4c commit 4d91d78
Show file tree
Hide file tree
Showing 410 changed files with 21,944 additions and 1,223 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,13 +226,13 @@ console.log(version, Object.keys(exchanges));

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

* jsDelivr: https://cdn.jsdelivr.net/npm/[email protected].47/dist/ccxt.browser.min.js
* unpkg: https://unpkg.com/[email protected].47/dist/ccxt.browser.min.js
* jsDelivr: https://cdn.jsdelivr.net/npm/[email protected].49/dist/ccxt.browser.min.js
* unpkg: https://unpkg.com/[email protected].49/dist/ccxt.browser.min.js

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.

```HTML
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected].47/dist/ccxt.browser.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected].49/dist/ccxt.browser.min.js"></script>
```

Creates a global `ccxt` object:
Expand Down
1 change: 1 addition & 0 deletions build/dummy.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ release!!!!
!!!!
!!!!
!
!
!
2 changes: 1 addition & 1 deletion cs/ccxt/base/Exchange.MetaData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ namespace ccxt;
// file updated automatically by vss and export-exchanges
public partial class Exchange
{
public static string ccxtVersion = "4.4.47";
public static string ccxtVersion = "4.4.49";

public static List<string> exchanges = new List<string> { "ace", "alpaca", "ascendex", "bequant", "bigone", "binance", "binancecoinm", "binanceus", "binanceusdm", "bingx", "bit2c", "bitbank", "bitbns", "bitcoincom", "bitfinex", "bitfinex1", "bitflyer", "bitget", "bithumb", "bitmart", "bitmex", "bitopro", "bitpanda", "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", "currencycom", "defx", "delta", "deribit", "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", "lykke", "mercado", "mexc", "myokx", "ndax", "novadax", "oceanex", "okcoin", "okx", "onetrading", "oxfun", "p2b", "paradex", "paymium", "phemex", "poloniex", "poloniexfutures", "probit", "timex", "tokocrypto", "tradeogre", "upbit", "vertex", "wavesexchange", "wazirx", "whitebit", "woo", "woofipro", "xt", "yobit", "zaif", "zonda" };
}
6 changes: 3 additions & 3 deletions cs/ccxt/ccxt.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
<PropertyGroup>
<PackageId>ccxt</PackageId>
<Authors>Carlos, Kroitor, Carlo</Authors>
<PackageVersion>4.4.47</PackageVersion>
<AssemblyVersion>4.4.47</AssemblyVersion>
<FileVersion>4.4.47</FileVersion>
<PackageVersion>4.4.49</PackageVersion>
<AssemblyVersion>4.4.49</AssemblyVersion>
<FileVersion>4.4.49</FileVersion>
<PackageReadmeFile>README.md</PackageReadmeFile>
<Description>Cryptocurrency trading API with support for more than 100 bitcoin/altcoin exchanges</Description>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
Expand Down
35 changes: 20 additions & 15 deletions cs/ccxt/exchanges/binance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10164,21 +10164,26 @@ public async override Task<object> fetchFundingRateHistory(object symbol = null,
// "fundingTime": "1621267200000",
// }
//
object rates = new List<object>() {};
for (object i = 0; isLessThan(i, getArrayLength(response)); postFixIncrement(ref i))
{
object entry = getValue(response, i);
object timestamp = this.safeInteger(entry, "fundingTime");
((IList<object>)rates).Add(new Dictionary<string, object>() {
{ "info", entry },
{ "symbol", this.safeSymbol(this.safeString(entry, "symbol"), null, null, "swap") },
{ "fundingRate", this.safeNumber(entry, "fundingRate") },
{ "timestamp", timestamp },
{ "datetime", this.iso8601(timestamp) },
});
}
object sorted = this.sortBy(rates, "timestamp");
return this.filterBySymbolSinceLimit(sorted, symbol, since, limit);
return this.parseFundingRateHistories(response, market, since, limit);
}

public override object parseFundingRateHistory(object contract, object market = null)
{
//
// {
// "symbol": "BTCUSDT",
// "fundingRate": "0.00063521",
// "fundingTime": "1621267200000",
// }
//
object timestamp = this.safeInteger(contract, "fundingTime");
return new Dictionary<string, object>() {
{ "info", contract },
{ "symbol", this.safeSymbol(this.safeString(contract, "symbol"), null, null, "swap") },
{ "fundingRate", this.safeNumber(contract, "fundingRate") },
{ "timestamp", timestamp },
{ "datetime", this.iso8601(timestamp) },
};
}

/**
Expand Down
133 changes: 102 additions & 31 deletions cs/ccxt/exchanges/bingx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -828,8 +828,8 @@ public async virtual Task<object> fetchSpotMarkets(object parameters)
// "symbols": [
// {
// "symbol": "GEAR-USDT",
// "minQty": 735,
// "maxQty": 2941177,
// "minQty": 735, // deprecated
// "maxQty": 2941177, // deprecated
// "minNotional": 5,
// "maxNotional": 20000,
// "status": 1,
Expand Down Expand Up @@ -964,6 +964,11 @@ public override object parseMarket(object market)
}
object isInverse = ((bool) isTrue((spot))) ? null : checkIsInverse;
object isLinear = ((bool) isTrue((spot))) ? null : checkIsLinear;
object minAmount = null;
if (!isTrue(spot))
{
minAmount = this.safeNumber2(market, "minQty", "tradeMinQuantity");
}
object timeOnline = this.safeInteger(market, "timeOnline");
if (isTrue(isEqual(timeOnline, 0)))
{
Expand Down Expand Up @@ -1006,8 +1011,8 @@ public override object parseMarket(object market)
{ "max", null },
} },
{ "amount", new Dictionary<string, object>() {
{ "min", this.safeNumber2(market, "minQty", "tradeMinQuantity") },
{ "max", this.safeNumber(market, "maxQty") },
{ "min", minAmount },
{ "max", null },
} },
{ "price", new Dictionary<string, object>() {
{ "min", minTickSize },
Expand Down Expand Up @@ -1726,23 +1731,26 @@ public async override Task<object> fetchFundingRateHistory(object symbol = null,
// }
//
object data = this.safeList(response, "data", new List<object>() {});
object rates = new List<object>() {};
for (object i = 0; isLessThan(i, getArrayLength(data)); postFixIncrement(ref i))
{
object entry = getValue(data, i);
object marketId = this.safeString(entry, "symbol");
object symbolInner = this.safeSymbol(marketId, market, "-", "swap");
object timestamp = this.safeInteger(entry, "fundingTime");
((IList<object>)rates).Add(new Dictionary<string, object>() {
{ "info", entry },
{ "symbol", symbolInner },
{ "fundingRate", this.safeNumber(entry, "fundingRate") },
{ "timestamp", timestamp },
{ "datetime", this.iso8601(timestamp) },
});
}
object sorted = this.sortBy(rates, "timestamp");
return this.filterBySymbolSinceLimit(sorted, getValue(market, "symbol"), since, limit);
return this.parseFundingRateHistories(data, market, since, limit);
}

public override object parseFundingRateHistory(object contract, object market = null)
{
//
// {
// "symbol": "BTC-USDT",
// "fundingRate": "0.0001",
// "fundingTime": 1585684800000
// }
//
object timestamp = this.safeInteger(contract, "fundingTime");
return new Dictionary<string, object>() {
{ "info", contract },
{ "symbol", this.safeSymbol(this.safeString(contract, "symbol"), market, "-", "swap") },
{ "fundingRate", this.safeNumber(contract, "fundingRate") },
{ "timestamp", timestamp },
{ "datetime", this.iso8601(timestamp) },
};
}

/**
Expand Down Expand Up @@ -2373,12 +2381,15 @@ public override object parseBalance(object response)
{
object linearSwapData = this.safeDict(response, "data", new Dictionary<string, object>() {});
object linearSwapBalance = this.safeDict(linearSwapData, "balance");
object currencyId = this.safeString(linearSwapBalance, "asset");
object code = this.safeCurrencyCode(currencyId);
object account = this.account();
((IDictionary<string,object>)account)["free"] = this.safeString(linearSwapBalance, "availableMargin");
((IDictionary<string,object>)account)["used"] = this.safeString(linearSwapBalance, "usedMargin");
((IDictionary<string,object>)result)[(string)code] = account;
if (isTrue(linearSwapBalance))
{
object currencyId = this.safeString(linearSwapBalance, "asset");
object code = this.safeCurrencyCode(currencyId);
object account = this.account();
((IDictionary<string,object>)account)["free"] = this.safeString(linearSwapBalance, "availableMargin");
((IDictionary<string,object>)account)["used"] = this.safeString(linearSwapBalance, "usedMargin");
((IDictionary<string,object>)result)[(string)code] = account;
}
}
return this.safeBalance(result);
}
Expand Down Expand Up @@ -5979,6 +5990,57 @@ public virtual object parseTradingFee(object fee, object market = null)
};
}

public virtual object customEncode(object parameters)
{
object sortedParams = this.keysort(parameters);
object keys = new List<object>(((IDictionary<string,object>)sortedParams).Keys);
object adjustedValue = null;
object result = null;
for (object i = 0; isLessThan(i, getArrayLength(keys)); postFixIncrement(ref i))
{
object key = getValue(keys, i);
object value = getValue(sortedParams, key);
if (isTrue(((value is IList<object>) || (value.GetType().IsGenericType && value.GetType().GetGenericTypeDefinition().IsAssignableFrom(typeof(List<>))))))
{
object arrStr = null;
for (object j = 0; isLessThan(j, getArrayLength(value)); postFixIncrement(ref j))
{
object arrayElement = getValue(value, j);
object isString = ((arrayElement is string));
if (isTrue(isString))
{
if (isTrue(isGreaterThan(j, 0)))
{
arrStr = add(arrStr, add(add(add(",", "\""), ((object)arrayElement).ToString()), "\""));
} else
{
arrStr = add(add("\"", ((object)arrayElement).ToString()), "\"");
}
} else
{
if (isTrue(isGreaterThan(j, 0)))
{
arrStr = add(arrStr, add(",", ((object)arrayElement).ToString()));
} else
{
arrStr = ((object)arrayElement).ToString();
}
}
}
adjustedValue = add(add("[", arrStr), "]");
value = adjustedValue;
}
if (isTrue(isEqual(i, 0)))
{
result = add(add(key, "="), value);
} else
{
result = add(result, add(add(add("&", key), "="), value));
}
}
return result;
}

public override object sign(object path, object section = null, object method = null, object parameters = null, object headers = null, object body = null)
{
section ??= "public";
Expand Down Expand Up @@ -6024,17 +6086,26 @@ public override object sign(object path, object section = null, object method =
{
this.checkRequiredCredentials();
object isJsonContentType = (isTrue((isTrue((isEqual(type, "subAccount"))) || isTrue((isEqual(type, "account/transfer"))))) && isTrue((isEqual(method, "POST"))));
object parsedParams = this.parseParams(parameters);
object signature = this.hmac(this.encode(this.rawencode(parsedParams)), this.encode(this.secret), sha256);
object parsedParams = null;
object encodeRequest = null;
if (isTrue(isJsonContentType))
{
encodeRequest = this.customEncode(parameters);
} else
{
parsedParams = this.parseParams(parameters);
encodeRequest = this.rawencode(parsedParams);
}
object signature = this.hmac(this.encode(encodeRequest), this.encode(this.secret), sha256);
headers = new Dictionary<string, object>() {
{ "X-BX-APIKEY", this.apiKey },
{ "X-SOURCE-KEY", this.safeString(this.options, "broker", "CCXT") },
};
if (isTrue(isJsonContentType))
{
((IDictionary<string,object>)headers)["Content-Type"] = "application/json";
((IDictionary<string,object>)parsedParams)["signature"] = signature;
body = this.json(parsedParams);
((IDictionary<string,object>)parameters)["signature"] = signature;
body = this.json(parameters);
} else
{
object query = this.urlencode(parsedParams);
Expand Down
22 changes: 12 additions & 10 deletions cs/ccxt/exchanges/bitget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1339,18 +1339,18 @@ public override object describe()
{ "1m", 30 },
{ "3m", 30 },
{ "5m", 30 },
{ "10m", 52 },
{ "10m", 30 },
{ "15m", 52 },
{ "30m", 52 },
{ "30m", 62 },
{ "1h", 83 },
{ "2h", 120 },
{ "4h", 240 },
{ "6h", 360 },
{ "12h", 360 },
{ "1d", 360 },
{ "3d", 1000 },
{ "1w", 1000 },
{ "1M", 1000 },
{ "1d", 300 },
{ "3d", 300 },
{ "1w", 300 },
{ "1M", 300 },
} },
} },
{ "fetchTrades", new Dictionary<string, object>() {
Expand Down Expand Up @@ -3676,6 +3676,7 @@ public override object parseOHLCV(object ohlcv, object market = null)
* @param {int} [limit] the maximum amount of candles to fetch
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {int} [params.until] timestamp in ms of the latest candle to fetch
* @param {boolean} [params.useHistoryEndpoint] whether to force to use historical endpoint (it has max limit of 200)
* @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
* @param {string} [params.price] *swap only* "mark" (to fetch mark price candles) or "index" (to fetch index price candles)
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
Expand All @@ -3694,9 +3695,10 @@ public async override Task<object> fetchOHLCV(object symbol, object timeframe =
parameters = ((IList<object>)paginateparametersVariable)[1];
if (isTrue(paginate))
{
return await this.fetchPaginatedCallDeterministic("fetchOHLCV", symbol, since, limit, timeframe, parameters, maxLimitForHistoryEndpoint);
return await this.fetchPaginatedCallDeterministic("fetchOHLCV", symbol, since, limit, timeframe, parameters, maxLimitForRecentEndpoint);
}
object sandboxMode = this.safeBool(this.options, "sandboxMode", false);
object useHistoryEndpoint = this.safeBool(parameters, "useHistoryEndpoint", false);
object market = null;
if (isTrue(sandboxMode))
{
Expand Down Expand Up @@ -3727,7 +3729,7 @@ public async override Task<object> fetchOHLCV(object symbol, object timeframe =
object ohlcOptions = this.safeDict(this.options, "fetchOHLCV", new Dictionary<string, object>() {});
object retrievableDaysMap = this.safeDict(ohlcOptions, "maxDaysPerTimeframe", new Dictionary<string, object>() {});
object maxRetrievableDaysForRecent = this.safeInteger(retrievableDaysMap, timeframe, 30); // default to safe minimum
object endpointTsBoundary = subtract(now, multiply(maxRetrievableDaysForRecent, msInDay));
object endpointTsBoundary = subtract(now, multiply((subtract(maxRetrievableDaysForRecent, 1)), msInDay));
if (isTrue(limitDefined))
{
limit = mathMin(limit, maxLimitForRecentEndpoint);
Expand Down Expand Up @@ -3773,7 +3775,7 @@ public async override Task<object> fetchOHLCV(object symbol, object timeframe =
if (isTrue(getValue(market, "spot")))
{
// checks if we need history endpoint
if (isTrue(historicalEndpointNeeded))
if (isTrue(isTrue(historicalEndpointNeeded) || isTrue(useHistoryEndpoint)))
{
response = await this.publicSpotGetV2SpotMarketHistoryCandles(this.extend(request, parameters));
} else
Expand Down Expand Up @@ -3813,7 +3815,7 @@ public async override Task<object> fetchOHLCV(object symbol, object timeframe =
response = await this.publicMixGetV2MixMarketHistoryIndexCandles(extended);
} else
{
if (isTrue(historicalEndpointNeeded))
if (isTrue(isTrue(historicalEndpointNeeded) || isTrue(useHistoryEndpoint)))
{
response = await this.publicMixGetV2MixMarketHistoryCandles(extended);
} else
Expand Down
Loading

0 comments on commit 4d91d78

Please sign in to comment.