diff --git a/.github/workflows/cs.yml b/.github/workflows/cs.yml
index 7c70660442452..b4bd74e278434 100644
--- a/.github/workflows/cs.yml
+++ b/.github/workflows/cs.yml
@@ -33,7 +33,7 @@ jobs:
fi
- uses: actions/setup-dotnet@v4
with:
- dotnet-version: '7.0.x'
+ dotnet-version: '9.0.x'
dotnet-quality: 'preview'
- uses: actions/setup-node@v4
with:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 0a6c6f805f1fd..2e4dfbbd74438 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -50,7 +50,7 @@ jobs:
sudo mkdir -p /usr/share/dotnet
- uses: actions/setup-dotnet@v4
with:
- dotnet-version: '7.0.x'
+ dotnet-version: '9.0.x'
dotnet-quality: 'preview'
run: |
sudo mkdir -p /usr/share/dotnet
diff --git a/README.md b/README.md
index 066078b8d88f2..fe928975f4c46 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# CCXT – CryptoCurrency eXchange Trading Library
-[](https://www.npmjs.com/package/ccxt) [](https://npmjs.com/package/ccxt) [](https://pypi.python.org/pypi/ccxt) [](https://www.nuget.org/packages/ccxt) [](https://godoc.org/github.com/ccxt/ccxt/go/v4) [](https://discord.gg/ccxt) [](https://github.com/ccxt/ccxt/wiki/Exchange-Markets) [](https://x.com/ccxt_official)
+[](https://www.npmjs.com/package/ccxt) [](https://npmjs.com/package/ccxt) [](https://pypi.python.org/pypi/ccxt) [](https://www.nuget.org/packages/ccxt) [](https://godoc.org/github.com/ccxt/ccxt/go/v4) [](https://discord.gg/ccxt) [](https://github.com/ccxt/ccxt/wiki/Exchange-Markets) [](https://x.com/ccxt_official)
A `JavaScript` / `Python` / `PHP` / `C#` / `Go` library for cryptocurrency trading and e-commerce with support for many bitcoin/ether/altcoin exchange markets and merchant APIs.
@@ -53,7 +53,7 @@ Current feature list:
| [](https://dex.woo.org/en/trade?ref=CCXT) | woofipro | [WOOFI PRO](https://dex.woo.org/en/trade?ref=CCXT) | [](https://orderly.network/docs/build-on-evm/building-on-evm) |  | [](https://github.com/ccxt/ccxt/wiki/Certification) | [](https://ccxt.pro) | [](https://dex.woo.org/en/trade?ref=CCXT) |
## Supported Cryptocurrency Exchanges
-The CCXT library currently supports the following 103 cryptocurrency exchange markets and trading APIs:
+The CCXT library currently supports the following 102 cryptocurrency exchange markets and trading APIs:
|logo |id |name |ver |type |certified |pro |
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------|----------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------:|--------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------|
@@ -97,7 +97,6 @@ Current feature list:
| [](https://partner.coincatch.cc/bg/92hy70391729607848548) | coincatch | [CoinCatch](https://partner.coincatch.cc/bg/92hy70391729607848548) | [](https://coincatch.github.io/github.io/en/) |  | | [](https://ccxt.pro) |
| [](https://coincheck.com) | coincheck | [coincheck](https://coincheck.com) | [](https://coincheck.com/documents/exchange/api) |  | | |
| [](https://www.coinex.com/register?refer_code=yw5fz) | coinex | [CoinEx](https://www.coinex.com/register?refer_code=yw5fz) | [](https://docs.coinex.com/api/v2) |  | [](https://github.com/ccxt/ccxt/wiki/Certification) | [](https://ccxt.pro) |
-| [](https://coinlist.co) | coinlist | [Coinlist](https://coinlist.co) | [](https://trade-docs.coinlist.co) |  | | |
| [](https://coinmate.io?referral=YTFkM1RsOWFObVpmY1ZjMGREQmpTRnBsWjJJNVp3PT0) | coinmate | [CoinMate](https://coinmate.io?referral=YTFkM1RsOWFObVpmY1ZjMGREQmpTRnBsWjJJNVp3PT0) | [](https://coinmate.docs.apiary.io) |  | | |
| [](https://go.coinmetro.com/?ref=crypto24) | coinmetro | [Coinmetro](https://go.coinmetro.com/?ref=crypto24) | [](https://documenter.getpostman.com/view/3653795/SVfWN6KS) |  | | |
| [](https://coinone.co.kr) | coinone | [CoinOne](https://coinone.co.kr) | [](https://doc.coinone.co.kr) |  | | |
@@ -221,13 +220,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/ccxt@4.4.89/dist/ccxt.browser.min.js
-* unpkg: https://unpkg.com/ccxt@4.4.89/dist/ccxt.browser.min.js
+* jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.4.92/dist/ccxt.browser.min.js
+* unpkg: https://unpkg.com/ccxt@4.4.92/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
-
+
```
Creates a global `ccxt` object:
diff --git a/build/export-exchanges.js b/build/export-exchanges.js
index 47ccf597ab0a8..b32228e4015f4 100644
--- a/build/export-exchanges.js
+++ b/build/export-exchanges.js
@@ -21,6 +21,8 @@ ansi.nice
const unlimitedLog = log.unlimited;
+let isPartiaBuild = false;
+
const capitalize = (s) => {
return s.length ? (s.charAt (0).toUpperCase () + s.slice (1)) : s;
};
@@ -44,12 +46,20 @@ function logExportExchanges (filename, regex, replacement) {
function getIncludedExchangeIds (pathToDirectory) {
+ if (process.argv.length > 2) {
+ // allow a specific exchange to be specified via command line
+ isPartiaBuild = true;
+ return process.argv.slice (2);
+ }
+
const includedIds = fs.readFileSync ('exchanges.cfg')
.toString () // Buffer → String
.split ('\n') // String → Array
.map (line => line.split ('#')[0].trim ()) // trim comments
.filter (exchange => exchange); // filter empty lines
+ isPartiaBuild = includedIds.length > 0;
+
const isIncluded = (id) => ((includedIds.length === 0) || includedIds.includes (id))
const ids = fs.readdirSync (pathToDirectory)
.filter (file => file.match (/[a-zA-Z0-9_-]+.ts$/))
@@ -709,6 +719,11 @@ async function exportEverything () {
// strategically placed exactly here (we can require it AFTER the export)
const exchanges = await createExchanges (ids)
+ if (isPartiaBuild) {
+ log.bright.cyan ('Using a partial build'.yellow, 'building only', ids)
+ return
+ }
+
const wikiPath = 'wiki'
, gitWikiPath = 'build/ccxt.wiki'
diff --git a/build/goTranspiler.ts b/build/goTranspiler.ts
index 8e2a7dfb8769f..2e55c16b6eb3a 100644
--- a/build/goTranspiler.ts
+++ b/build/goTranspiler.ts
@@ -137,9 +137,11 @@ const VIRTUAL_BASE_METHODS: any = {
"parsePosition": false,
"parseTicker": false,
"parseTrade": false,
+ "parseGreeks": false,
"parseTransaction": false,
"parseTransfer": false,
"parseWithdrawal": false,
+ "parseLeverage": false,
"parseWithdrawalStatus": false,
"safeMarket": false, // try to remove custom implementations
"market": false,
@@ -212,7 +214,7 @@ class NewTranspiler {
// c# custom method
- customCSharpPropAssignment(node: any, identation: any) {
+ customgoPropAssignment(node: any, identation: any) {
const stringValue = node.getFullText().trim();
if (Object.keys(errors).includes(stringValue)) {
return `typeof(${stringValue})`;
@@ -349,7 +351,7 @@ class NewTranspiler {
if (!exchangeMethods) {
exchangeMethods = {}
}
- // const transformedComment = this.transformTSCommentIntoCSharp(methodName, description, sees,params, returnType, returnDescription);
+ // const transformedComment = this.transformTSCommentIntogo(methodName, description, sees,params, returnType, returnDescription);
exchangeMethods[methodName] = comment;
goComments[exchangeName] = exchangeMethods
return comment;
@@ -382,7 +384,7 @@ class NewTranspiler {
return values;
}
- getCsharpImports(file: any, ws = false) {
+ getgoImports(file: any, ws = false) {
const namespace = ws ? 'namespace ccxt.pro;' : 'namespace ccxt;';
const values = [
// "using ccxt;",
@@ -442,7 +444,7 @@ class NewTranspiler {
return isPromise ? `<- chan ${type}` : type;
}
- const csharpReplacements: dict = {
+ const goReplacements: dict = {
'OrderType': 'string',
'OrderSide': 'string', // tmp
}
@@ -486,8 +488,8 @@ class NewTranspiler {
if (wrappedType === 'Strings') {
return addTaskIfNeeded('[]string')
}
- if (csharpReplacements[wrappedType] !== undefined) {
- return addTaskIfNeeded(csharpReplacements[wrappedType]);
+ if (goReplacements[wrappedType] !== undefined) {
+ return addTaskIfNeeded(goReplacements[wrappedType]);
}
if (wrappedType.startsWith('Dictionary<')) {
@@ -830,7 +832,7 @@ class NewTranspiler {
}
createExchangesWrappers(): string[] {
- // in csharp classes should be Capitalized, so I'm creating a wrapper class for each exchange
+ // in go classes should be Capitalized, so I'm creating a wrapper class for each exchange
const res: string[] = ['// class wrappers'];
exchangeIds.forEach((exchange: string) => {
const capitalizedExchange = exchange.charAt(0).toUpperCase() + exchange.slice(1);
@@ -992,7 +994,7 @@ ${constStatements.join('\n')}
return `<-this.DerivedExchange.${capitalizedMethod}(${p2})`;
});
// create wrappers with specific types
- // this.createCSharpWrappers('Exchange', GLOBAL_WRAPPER_FILE, baseFile.methodsTypes)
+ // this.creategoWrappers('Exchange', GLOBAL_WRAPPER_FILE, baseFile.methodsTypes)
// custom transformations needed for go
@@ -1076,7 +1078,7 @@ ${caseStatements.join('\n')}
}
- getCsharpExamplesWarning() {
+ getgoExamplesWarning() {
return [
'',
' // !!Warning!! This example was automatically transpiled',
@@ -1103,10 +1105,10 @@ ${caseStatements.join('\n')}
if (tsContent.indexOf (transpileFlagPhrase) > -1) {
const fileName = filenameWithExtenstion.replace ('.ts', '')
log.magenta ('[C#] Transpiling example from', (tsFile as any).yellow)
- const csharp = this.transpiler.transpileCSharp(tsContent);
+ const go = this.transpiler.transpileGo(tsContent);
const transpiledFixed = this.regexAll(
- csharp.content,
+ go.content,
[
[/object exchange/, 'Exchange exchange'],
[/async public Task example/gm, 'async public Task ' + this.camelize(fileName)],
@@ -1119,7 +1121,7 @@ ${caseStatements.join('\n')}
'using ccxt;',
'using ccxt.pro;',
'namespace examples;',
- // this.getCsharpExamplesWarning(),
+ // this.getgoExamplesWarning(),
'partial class Examples',
'{',
transpiledFixed,
@@ -1139,26 +1141,26 @@ ${caseStatements.join('\n')}
inputExchanges = exchanges.ws;
}
// @ts-expect-error
- const options = { csharpFolder: EXCHANGES_WS_FOLDER, exchanges:inputExchanges }
- // const options = { csharpFolder: EXCHANGES_WS_FOLDER, exchanges:['bitget'] }
+ const options = { goFolder: EXCHANGES_WS_FOLDER, exchanges:inputExchanges }
+ // const options = { goFolder: EXCHANGES_WS_FOLDER, exchanges:['bitget'] }
await this.transpileDerivedExchangeFiles (tsFolder, options, '.ts', force, !!(inputExchanges), true )
}
async transpileEverything (force = false, child = false, baseOnly = false, examplesOnly = false) {
const exchanges = process.argv.slice (2).filter (x => !x.startsWith ('--'))
- , csharpFolder = EXCHANGES_FOLDER
+ , goFolder = EXCHANGES_FOLDER
, tsFolder = './ts/src/'
, exchangeBase = './ts/src/base/Exchange.ts'
if (!child) {
- createFolderRecursively (csharpFolder)
+ createFolderRecursively (goFolder)
}
const transpilingSingleExchange = (exchanges.length === 1); // when transpiling single exchange, we can skip some steps because this is only used for testing/debugging
if (transpilingSingleExchange) {
force = true; // when transpiling single exchange, we always force
}
- const options = { csharpFolder, exchanges }
+ const options = { goFolder, exchanges }
if (!baseOnly && !examplesOnly) {
await this.transpileDerivedExchangeFiles (tsFolder, options, '.ts', force, !!(child || exchanges.length))
@@ -1277,7 +1279,7 @@ ${caseStatements.join('\n')}
// const transpiled = transpiledFiles[i];
// const exchangeName = exchanges[i].replace('.ts','');
// const path = EXCHANGE_WS_WRAPPER_FOLDER + exchangeName + '.go';
- // this.createCSharpWrappers(exchangeName, path, transpiled.methodsTypes, true)
+ // this.creategoWrappers(exchangeName, path, transpiled.methodsTypes, true)
}
}
exchanges.map ((file: string, idx: number) => this.transpileDerivedExchangeFile (jsFolder, file, options, transpiledFiles[idx], force, ws))
@@ -1328,7 +1330,7 @@ ${caseStatements.join('\n')}
if (ws) {
// const wsRegexes = this.getWsRegexes();
// content = this.regexAll (content, wsRegexes);
- // content = this.replaceImportedRestClasses (content, csharpVersion.imports);
+ // content = this.replaceImportedRestClasses (content, goVersion.imports);
// const classNameRegex = /public\spartial\sclass\s(\w+)\s:\s(\w+)/gm;
// const classNameExec = classNameRegex.exec(content);
// const className = classNameExec ? classNameExec[1] : '';
@@ -1374,35 +1376,35 @@ func (this *${className}) Init(userConfig map[string]interface{}) {
return content;
}
- transpileDerivedExchangeFile (tsFolder: string, filename: string, options: any, csharpResult: any, force = false, ws = false) {
+ transpileDerivedExchangeFile (tsFolder: string, filename: string, options: any, goResult: any, force = false, ws = false) {
const tsPath = tsFolder + filename
- const { csharpFolder } = options
+ const { goFolder } = options
const extensionlessName = filename.replace ('.ts', '')
const goFilename = filename.replace ('.ts', '.go')
const tsMtime = fs.statSync (tsPath).mtime.getTime ()
- const csharp = this.createGoExchange (extensionlessName, csharpResult, ws)
+ const go = this.createGoExchange (extensionlessName, goResult, ws)
- if (csharpFolder) {
- overwriteFileAndFolder (csharpFolder + goFilename, csharp)
- // fs.utimesSync (csharpFolder + csharpFilename, new Date (), new Date (tsMtime))
+ if (goFolder) {
+ overwriteFileAndFolder (goFolder + goFilename, go)
+ // fs.utimesSync (goFolder + goFilename, new Date (), new Date (tsMtime))
}
}
// ---------------------------------------------------------------------------------------------
- transpileWsOrderbookTestsToCSharp (outDir: string) {
+ transpileWsOrderbookTestsToGo (outDir: string) {
const jsFile = './ts/src/pro/test/base/test.OrderBook.ts';
- const csharpFile = `${outDir}/Orderbook.go`;
+ const goFile = `${outDir}/Orderbook.go`;
log.magenta ('Transpiling from', (jsFile as any).yellow)
- const csharp = this.transpiler.transpileCSharpByPath(jsFile);
- let content = csharp.content;
+ const go = this.transpiler.transpileGoByPath(jsFile);
+ let content = go.content;
const splitParts = content.split('// --------------------------------------------------------------------------------------------------------------------');
splitParts.shift();
content = splitParts.join('\n// --------------------------------------------------------------------------------------------------------------------\n');
@@ -1428,21 +1430,21 @@ func (this *${className}) Init(userConfig map[string]interface{}) {
'}',
].join('\n')
- log.magenta ('→', (csharpFile as any).yellow)
+ log.magenta ('→', (goFile as any).yellow)
- overwriteFileAndFolder (csharpFile, file);
+ overwriteFileAndFolder (goFile, file);
}
// ---------------------------------------------------------------------------------------------
- transpileWsCacheTestsToCSharp (outDir: string) {
+ transpileWsCacheTestsToGo (outDir: string) {
const jsFile = './ts/src/pro/test/base/test.Cache.ts';
- const csharpFile = `${outDir}/Cache.go`;
+ const goFile = `${outDir}/Cache.go`;
log.magenta ('Transpiling from', (jsFile as any).yellow)
- const csharp = this.transpiler.transpileCSharpByPath(jsFile);
- let content = csharp.content;
+ const go = this.transpiler.transpileGoByPath(jsFile);
+ let content = go.content;
const splitParts = content.split('// ----------------------------------------------------------------------------');
splitParts.shift();
content = splitParts.join('\n// ----------------------------------------------------------------------------\n');
@@ -1468,9 +1470,9 @@ func (this *${className}) Init(userConfig map[string]interface{}) {
'}',
].join('\n')
- log.magenta ('→', (csharpFile as any).yellow)
+ log.magenta ('→', (goFile as any).yellow)
- overwriteFileAndFolder (csharpFile, file);
+ overwriteFileAndFolder (goFile, file);
}
// ---------------------------------------------------------------------------------------------
@@ -1482,8 +1484,8 @@ func (this *${className}) Init(userConfig map[string]interface{}) {
log.magenta ('[go] Transpiling from', (jsFile as any).yellow)
- const csharp = this.transpiler.transpileGoByPath(jsFile);
- let content = csharp.content;
+ const go = this.transpiler.transpileGoByPath(jsFile);
+ let content = go.content;
content = this.regexAll (content, [
[/new ccxt.Exchange.+\n.+\n.+/gm, 'ccxt.Exchange{}' ],
[ /func Equals\(.+\n.*\n.*\n.*}/gm, '' ], // remove equals
@@ -1504,8 +1506,8 @@ func (this *${className}) Init(userConfig map[string]interface{}) {
}
transpileExchangeTest(name: string, path: string): [string, string] {
- const csharp = this.transpiler.transpileCSharpByPath(path);
- let content = csharp.content;
+ const go = this.transpiler.transpileGoByPath(path);
+ let content = go.content;
const parsedName = name.replace('.ts', '');
const parsedParts = parsedName.split('.');
@@ -1535,7 +1537,7 @@ func (this *${className}) Init(userConfig map[string]interface{}) {
return [finalName, file];
}
- async transpileExchangeTestsToCsharp() {
+ async transpileExchangeTestsToGo() {
const inputDir = './ts/src/test/exchange/';
// @ts-expect-error
const outDir = GENERATED_TESTS_FOLDER;
@@ -1556,8 +1558,8 @@ func (this *${className}) Init(userConfig map[string]interface{}) {
const outDir = BASE_TESTS_FOLDER;
this.transpileBaseTests(outDir);
this.transpileCryptoTestsToGo(outDir);
- // this.transpileWsCacheTestsToCSharp(outDir);
- // this.transpileWsOrderbookTestsToCSharp(outDir);
+ // this.transpileWsCacheTestsToGo(outDir);
+ // this.transpileWsOrderbookTestsToGo(outDir);
}
transpileBaseTests (outDir: string) {
@@ -1700,7 +1702,7 @@ func (this *${className}) Init(userConfig map[string]interface{}) {
// const baseFolders = {
// ts: './ts/src/pro/test/Exchange/',
- // csharp: EXCHANGE_GENERATED_FOLDER + 'Ws/',
+ // go: EXCHANGE_GENERATED_FOLDER + 'Ws/',
// };
// const wsTests = fs.readdirSync (baseFolders.ts).filter(filename => filename.endsWith('.ts')).map(filename => filename.replace('.ts', ''));
@@ -1711,7 +1713,7 @@ func (this *${className}) Init(userConfig map[string]interface{}) {
// tests.push({
// name: test,
// tsFile: baseFolders.ts + test + '.ts',
- // csharpFile: baseFolders.goharp + test + '.go',
+ // goFile: baseFolders.goharp + test + '.go',
// });
// });
diff --git a/build/single-js-build.sh b/build/single-js-build.sh
new file mode 100755
index 0000000000000..c27009e8c7c05
--- /dev/null
+++ b/build/single-js-build.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+if [ -z "$1" ]; then
+ echo "Error: Missing required argument."
+ echo "Usage: $0 ExchangeName"
+ exit 1
+fi
+
+# export only the required exchange
+npm run export-exchanges "$1"
+
+# build ts to js
+npm run tsBuild
+
+
+MATCH="$1"
+
+for DIR in js/src js/src/pro; do
+ find "$DIR" -maxdepth 1 -type f ! -name "*$MATCH*" -exec rm -v {} \;
+done
\ No newline at end of file
diff --git a/cli/ts/cli.ts b/cli/ts/cli.ts
index 735c5abb5fb1c..d24e2cb9caebc 100644
--- a/cli/ts/cli.ts
+++ b/cli/ts/cli.ts
@@ -69,7 +69,6 @@ interface CLIOptions {
raw?: boolean;
noKeys?: boolean;
i?: boolean;
- history?: boolean;
name?: string;
param?: any;
config?: any;
@@ -119,7 +118,6 @@ program
.option ('--clipboard', 'Copies the result to clipboard automatically.')
.option ('--signIn', 'calls the signIn() method if available')
.option ('--cache-markets', 'forces markets caching')
- .option ('--history', 'prints the history of executed commands')
.option ('--no-load-markets', 'skips markets loading')
.option ('--no-table', 'does not prettify the results')
.option ('--spot', 'sets defaultType as spot')
diff --git a/cs/ccxt/api/coinlist.cs b/cs/ccxt/api/coinlist.cs
deleted file mode 100644
index ab3a888ffabe4..0000000000000
--- a/cs/ccxt/api/coinlist.cs
+++ /dev/null
@@ -1,279 +0,0 @@
-// -------------------------------------------------------------------------------
-
-// PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
-// https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
-
-// -------------------------------------------------------------------------------
-
-namespace ccxt;
-
-public partial class coinlist : Exchange
-{
- public coinlist (object args = null): base(args) {}
-
- public async Task