ccxt-look 1.81.50

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.
Files changed (264) hide show
  1. package/.cache/eslintcache +1 -0
  2. package/.dockerignore +6 -0
  3. package/.eslintignore +1 -0
  4. package/.gitattributes +5 -0
  5. package/.readthedocs.yaml +16 -0
  6. package/CONTRIBUTING.md +1049 -0
  7. package/LICENSE.txt +21 -0
  8. package/README.md +537 -0
  9. package/SECURITY.md +5 -0
  10. package/build/cleanup-old-tags.js +94 -0
  11. package/build/countries.js +256 -0
  12. package/build/export-exchanges.js +520 -0
  13. package/build/fs.js +51 -0
  14. package/build/transpile.js +1772 -0
  15. package/build/vss.js +78 -0
  16. package/ccxt.browser.js +7 -0
  17. package/ccxt.d.ts +692 -0
  18. package/ccxt.js +171 -0
  19. package/cleanup.sh +2 -0
  20. package/composer-install.sh +20 -0
  21. package/dist/ccxt.browser.js +208383 -0
  22. package/gource.sh +3 -0
  23. package/index.html +7 -0
  24. package/js/.eslintrc +87 -0
  25. package/js/aax.js +2686 -0
  26. package/js/ascendex.js +2584 -0
  27. package/js/base/.eslintrc.js +43 -0
  28. package/js/base/Exchange.js +2371 -0
  29. package/js/base/Precise.js +283 -0
  30. package/js/base/errorHierarchy.js +47 -0
  31. package/js/base/errors.js +55 -0
  32. package/js/base/functions/crypto.js +158 -0
  33. package/js/base/functions/encode.js +118 -0
  34. package/js/base/functions/generic.js +270 -0
  35. package/js/base/functions/misc.js +138 -0
  36. package/js/base/functions/number.js +329 -0
  37. package/js/base/functions/platform.js +38 -0
  38. package/js/base/functions/string.js +21 -0
  39. package/js/base/functions/throttle.js +79 -0
  40. package/js/base/functions/time.js +210 -0
  41. package/js/base/functions/type.js +66 -0
  42. package/js/base/functions.js +28 -0
  43. package/js/bequant.js +32 -0
  44. package/js/bibox.js +1407 -0
  45. package/js/bigone.js +1366 -0
  46. package/js/binance.js +5652 -0
  47. package/js/binancecoinm.js +46 -0
  48. package/js/binanceus.js +46 -0
  49. package/js/binanceusdm.js +49 -0
  50. package/js/bit2c.js +535 -0
  51. package/js/bitbank.js +842 -0
  52. package/js/bitbay.js +16 -0
  53. package/js/bitbns.js +1073 -0
  54. package/js/bitcoincom.js +15 -0
  55. package/js/bitfinex.js +1433 -0
  56. package/js/bitfinex2.js +2025 -0
  57. package/js/bitflyer.js +840 -0
  58. package/js/bitforex.js +614 -0
  59. package/js/bitget.js +2397 -0
  60. package/js/bithumb.js +980 -0
  61. package/js/bitmart.js +2516 -0
  62. package/js/bitmex.js +1809 -0
  63. package/js/bitopro.js +1443 -0
  64. package/js/bitpanda.js +1782 -0
  65. package/js/bitrue.js +1747 -0
  66. package/js/bitso.js +1062 -0
  67. package/js/bitstamp.js +1757 -0
  68. package/js/bitstamp1.js +343 -0
  69. package/js/bittrex.js +1876 -0
  70. package/js/bitvavo.js +1579 -0
  71. package/js/bkex.js +1233 -0
  72. package/js/bl3p.js +346 -0
  73. package/js/blockchaincom.js +969 -0
  74. package/js/btcalpha.js +680 -0
  75. package/js/btcbox.js +477 -0
  76. package/js/btcmarkets.js +1022 -0
  77. package/js/btctradeua.js +466 -0
  78. package/js/btcturk.js +734 -0
  79. package/js/buda.js +946 -0
  80. package/js/bw.js +1265 -0
  81. package/js/bybit.js +3372 -0
  82. package/js/bytetrade.js +1336 -0
  83. package/js/cdax.js +1646 -0
  84. package/js/cex.js +1410 -0
  85. package/js/coinbase.js +1342 -0
  86. package/js/coinbaseprime.js +31 -0
  87. package/js/coinbasepro.js +1466 -0
  88. package/js/coincheck.js +755 -0
  89. package/js/coinex.js +3400 -0
  90. package/js/coinfalcon.js +880 -0
  91. package/js/coinmate.js +794 -0
  92. package/js/coinone.js +816 -0
  93. package/js/coinspot.js +345 -0
  94. package/js/crex24.js +1636 -0
  95. package/js/cryptocom.js +1832 -0
  96. package/js/currencycom.js +1748 -0
  97. package/js/delta.js +1547 -0
  98. package/js/deribit.js +2148 -0
  99. package/js/digifinex.js +1585 -0
  100. package/js/eqonex.js +1660 -0
  101. package/js/exmo.js +1670 -0
  102. package/js/fairdesk.js +1231 -0
  103. package/js/flowbtc.js +35 -0
  104. package/js/fmfwio.js +34 -0
  105. package/js/ftx.js +2751 -0
  106. package/js/ftxus.js +38 -0
  107. package/js/gateio.js +4174 -0
  108. package/js/gemini.js +1397 -0
  109. package/js/hitbtc.js +1343 -0
  110. package/js/hitbtc3.js +2329 -0
  111. package/js/hollaex.js +1486 -0
  112. package/js/huobi.js +5706 -0
  113. package/js/huobijp.js +1710 -0
  114. package/js/huobipro.js +18 -0
  115. package/js/idex.js +1439 -0
  116. package/js/independentreserve.js +649 -0
  117. package/js/indodax.js +742 -0
  118. package/js/itbit.js +722 -0
  119. package/js/kraken.js +2179 -0
  120. package/js/kucoin.js +2571 -0
  121. package/js/kucoinfutures.js +1771 -0
  122. package/js/kuna.js +809 -0
  123. package/js/latoken.js +1445 -0
  124. package/js/lbank.js +760 -0
  125. package/js/liquid.js +1432 -0
  126. package/js/luno.js +873 -0
  127. package/js/lykke.js +1147 -0
  128. package/js/mercado.js +771 -0
  129. package/js/mexc.js +3151 -0
  130. package/js/ndax.js +2233 -0
  131. package/js/novadax.js +1318 -0
  132. package/js/oceanex.js +816 -0
  133. package/js/okcoin.js +3841 -0
  134. package/js/okex.js +16 -0
  135. package/js/okex5.js +16 -0
  136. package/js/okx.js +4795 -0
  137. package/js/paymium.js +498 -0
  138. package/js/phemex.js +2957 -0
  139. package/js/poloniex.js +1674 -0
  140. package/js/probit.js +1346 -0
  141. package/js/qtrade.js +1588 -0
  142. package/js/ripio.js +1061 -0
  143. package/js/static_dependencies/BN/bn.js +3526 -0
  144. package/js/static_dependencies/README.md +1 -0
  145. package/js/static_dependencies/crypto-js/crypto-js.js +5988 -0
  146. package/js/static_dependencies/elliptic/lib/elliptic/curve/base.js +375 -0
  147. package/js/static_dependencies/elliptic/lib/elliptic/curve/edwards.js +433 -0
  148. package/js/static_dependencies/elliptic/lib/elliptic/curve/index.js +8 -0
  149. package/js/static_dependencies/elliptic/lib/elliptic/curve/mont.js +180 -0
  150. package/js/static_dependencies/elliptic/lib/elliptic/curve/short.js +938 -0
  151. package/js/static_dependencies/elliptic/lib/elliptic/curves.js +204 -0
  152. package/js/static_dependencies/elliptic/lib/elliptic/ec/index.js +240 -0
  153. package/js/static_dependencies/elliptic/lib/elliptic/ec/key.js +119 -0
  154. package/js/static_dependencies/elliptic/lib/elliptic/ec/signature.js +24 -0
  155. package/js/static_dependencies/elliptic/lib/elliptic/eddsa/index.js +145 -0
  156. package/js/static_dependencies/elliptic/lib/elliptic/eddsa/key.js +100 -0
  157. package/js/static_dependencies/elliptic/lib/elliptic/eddsa/signature.js +65 -0
  158. package/js/static_dependencies/elliptic/lib/elliptic/precomputed/secp256k1.js +780 -0
  159. package/js/static_dependencies/elliptic/lib/elliptic/utils.js +214 -0
  160. package/js/static_dependencies/elliptic/lib/elliptic.js +22 -0
  161. package/js/static_dependencies/elliptic/lib/hmac-drbg/hmac-drbg.js +114 -0
  162. package/js/static_dependencies/fetch-ponyfill/fetch-node.js +39 -0
  163. package/js/static_dependencies/node-fetch/index.js +1564 -0
  164. package/js/static_dependencies/node-rsa/NodeRSA.js +223 -0
  165. package/js/static_dependencies/node-rsa/asn1/ber/errors.js +13 -0
  166. package/js/static_dependencies/node-rsa/asn1/ber/index.js +21 -0
  167. package/js/static_dependencies/node-rsa/asn1/ber/reader.js +262 -0
  168. package/js/static_dependencies/node-rsa/asn1/ber/types.js +36 -0
  169. package/js/static_dependencies/node-rsa/asn1/index.js +17 -0
  170. package/js/static_dependencies/node-rsa/encryptEngines/js.js +34 -0
  171. package/js/static_dependencies/node-rsa/formats/components.js +71 -0
  172. package/js/static_dependencies/node-rsa/formats/formats.js +31 -0
  173. package/js/static_dependencies/node-rsa/formats/pkcs1.js +148 -0
  174. package/js/static_dependencies/node-rsa/formats/pkcs8.js +187 -0
  175. package/js/static_dependencies/node-rsa/libs/jsbn.js +1252 -0
  176. package/js/static_dependencies/node-rsa/libs/rsa.js +147 -0
  177. package/js/static_dependencies/node-rsa/schemes/pkcs1.js +176 -0
  178. package/js/static_dependencies/node-rsa/schemes/schemes.js +21 -0
  179. package/js/static_dependencies/node-rsa/utils.js +98 -0
  180. package/js/static_dependencies/qs/formats.js +18 -0
  181. package/js/static_dependencies/qs/index.js +11 -0
  182. package/js/static_dependencies/qs/parse.js +242 -0
  183. package/js/static_dependencies/qs/stringify.js +269 -0
  184. package/js/static_dependencies/qs/utils.js +230 -0
  185. package/js/stex.js +1925 -0
  186. package/js/test/.eslintrc.js +42 -0
  187. package/js/test/Exchange/test.balance.js +61 -0
  188. package/js/test/Exchange/test.borrowRate.js +32 -0
  189. package/js/test/Exchange/test.currency.js +52 -0
  190. package/js/test/Exchange/test.fetchBalance.js +23 -0
  191. package/js/test/Exchange/test.fetchBorrowInterest.js +59 -0
  192. package/js/test/Exchange/test.fetchBorrowRate.js +32 -0
  193. package/js/test/Exchange/test.fetchBorrowRates.js +28 -0
  194. package/js/test/Exchange/test.fetchClosedOrders.js +32 -0
  195. package/js/test/Exchange/test.fetchCurrencies.js +35 -0
  196. package/js/test/Exchange/test.fetchDeposits.js +31 -0
  197. package/js/test/Exchange/test.fetchFundingFees.js +19 -0
  198. package/js/test/Exchange/test.fetchFundingRateHistory.js +40 -0
  199. package/js/test/Exchange/test.fetchL2OrderBook.js +23 -0
  200. package/js/test/Exchange/test.fetchLedger.js +42 -0
  201. package/js/test/Exchange/test.fetchLeverageTiers.js +33 -0
  202. package/js/test/Exchange/test.fetchMarketLeverageTiers.js +22 -0
  203. package/js/test/Exchange/test.fetchMarkets.js +33 -0
  204. package/js/test/Exchange/test.fetchMyTrades.js +42 -0
  205. package/js/test/Exchange/test.fetchOHLCV.js +46 -0
  206. package/js/test/Exchange/test.fetchOpenOrders.js +36 -0
  207. package/js/test/Exchange/test.fetchOrderBook.js +25 -0
  208. package/js/test/Exchange/test.fetchOrderBooks.js +35 -0
  209. package/js/test/Exchange/test.fetchOrders.js +41 -0
  210. package/js/test/Exchange/test.fetchPositions.js +47 -0
  211. package/js/test/Exchange/test.fetchStatus.js +35 -0
  212. package/js/test/Exchange/test.fetchTicker.js +38 -0
  213. package/js/test/Exchange/test.fetchTickers.js +49 -0
  214. package/js/test/Exchange/test.fetchTrades.js +39 -0
  215. package/js/test/Exchange/test.fetchTradingFee.js +18 -0
  216. package/js/test/Exchange/test.fetchTradingFees.js +22 -0
  217. package/js/test/Exchange/test.fetchTransactions.js +31 -0
  218. package/js/test/Exchange/test.fetchWithdrawals.js +31 -0
  219. package/js/test/Exchange/test.ledgerItem.js +46 -0
  220. package/js/test/Exchange/test.leverageTier.js +33 -0
  221. package/js/test/Exchange/test.loadMarkets.js +35 -0
  222. package/js/test/Exchange/test.market.js +129 -0
  223. package/js/test/Exchange/test.ohlcv.js +33 -0
  224. package/js/test/Exchange/test.order.js +62 -0
  225. package/js/test/Exchange/test.orderbook.js +61 -0
  226. package/js/test/Exchange/test.position.js +21 -0
  227. package/js/test/Exchange/test.throttle.js +94 -0
  228. package/js/test/Exchange/test.ticker.js +95 -0
  229. package/js/test/Exchange/test.trade.js +68 -0
  230. package/js/test/Exchange/test.tradingFee.js +34 -0
  231. package/js/test/Exchange/test.transaction.js +35 -0
  232. package/js/test/base/.eslintrc +38 -0
  233. package/js/test/base/functions/test.crypto.js +110 -0
  234. package/js/test/base/functions/test.datetime.js +62 -0
  235. package/js/test/base/functions/test.generic.js +152 -0
  236. package/js/test/base/functions/test.number.js +362 -0
  237. package/js/test/base/functions/test.time.js +56 -0
  238. package/js/test/base/functions/test.type.js +53 -0
  239. package/js/test/base/test.base.js +193 -0
  240. package/js/test/errors/test.InsufficientFunds.js +86 -0
  241. package/js/test/errors/test.InvalidNonce.js +64 -0
  242. package/js/test/errors/test.InvalidOrder.js +35 -0
  243. package/js/test/errors/test.OrderNotFound.js +39 -0
  244. package/js/test/test.js +426 -0
  245. package/js/test/test.timeout_hang.js +12 -0
  246. package/js/therock.js +1431 -0
  247. package/js/tidebit.js +632 -0
  248. package/js/tidex.js +939 -0
  249. package/js/timex.js +1283 -0
  250. package/js/upbit.js +1622 -0
  251. package/js/vcc.js +1353 -0
  252. package/js/wavesexchange.js +2185 -0
  253. package/js/wazirx.js +732 -0
  254. package/js/whitebit.js +1352 -0
  255. package/js/woo.js +1577 -0
  256. package/js/xena.js +1948 -0
  257. package/js/yobit.js +1129 -0
  258. package/js/zaif.js +647 -0
  259. package/js/zb.js +4088 -0
  260. package/js/zipmex.js +40 -0
  261. package/js/zonda.js +1497 -0
  262. package/multilang.sh +159 -0
  263. package/package.json +591 -0
  264. package/postinstall.js +103 -0
@@ -0,0 +1,1049 @@
1
+ # Contributing To The CCXT Library
2
+
3
+ - [How To Submit A Question Or Issue](#how-to-submit-an-issue)
4
+ - [How To Contribute Code](#how-to-contribute-code)
5
+ - [What You Need To Have](#what-you-need-to-have)
6
+ - [What You Need To Know](#what-you-need-to-know)
7
+
8
+ ## How To Submit An Issue
9
+
10
+ If you want to submit an issue and you want your issue to be resolved quickly, here's a checklist for you:
11
+
12
+ - Read the [Manual](https://github.com/ccxt/ccxt/wiki/Manual), and especially carefully read the following sections:
13
+ - [Exchange Properties](https://github.com/ccxt/ccxt/wiki/Manual#exchange-properties)
14
+ - [Rate Limit](https://github.com/ccxt/ccxt/wiki/Manual#rate-limit)
15
+ - [DDoS Protection](https://github.com/ccxt/ccxt/wiki/Manual#ddos-protection-by-cloudflare--incapsula)
16
+ - [Authentication](https://github.com/ccxt/ccxt/wiki/Manual#authentication)
17
+ - [API Keys Setup](https://github.com/ccxt/ccxt/wiki/Manual#api-keys-setup)
18
+ - Read the [Troubleshooting](https://github.com/ccxt/ccxt/wiki/Manual#troubleshooting) section and follow troubleshooting steps.
19
+ - Read the [FAQ](https://github.com/ccxt/ccxt/wiki/FAQ) for most frequently asked questions.
20
+ - Read the [API docs](https://github.com/ccxt/ccxt/wiki/Exchange-Markets) for your exchange.
21
+ - Search for similar issues first to avoid duplicates.
22
+ - If your issue is unique, along with a basic description of the failure, the following **IS REQUIRED**:
23
+ - **set `exchange.verbose = true` property on the exchange instance before calling its functions or methods**
24
+ - **DON'T POST SCREENSHOTS OF CODE OR ERRORS, POST THE OUTPUT AND CODE IN PLAIN TEXT!**
25
+ - **surround code and output with triple backticks: ```GOOD```**
26
+ - don't confuse the backtick symbol (`) with the quote symbol (\'): '''BAD'''
27
+ - don't confuse a single backtick with triple backticks: `BAD`
28
+ - paste a complete code snippet you're having difficulties with, avoid one-liners
29
+ - paste the **full verbose output** of the failing method without your keys
30
+ - the verbose output should include the request and response from the exchange (not just an error callstack)
31
+ - write your language **and version**
32
+ - write ccxt library version
33
+ - which exchange it is
34
+ - which method you're trying to call
35
+
36
+ ### Reporting Vulnerabilities And Critical Issues
37
+
38
+ If you found a security issue or a critical vulnerability and reporting it in public would impose risk – please feel free to send us a message to <a href="mailto:info@ccxt.trade">info@ccxt.trade</a>.
39
+
40
+ ## How To Contribute Code
41
+
42
+ - **[MAKE SURE YOUR CODE IS UNIFIED](https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#derived-exchange-classes)!**
43
+
44
+ **↑ This is the most important rule of all!!!**
45
+
46
+ - **PLEASE, DO NOT COMMIT THE FOLLOWING FILES IN PULL REQUESTS:**
47
+
48
+ - `/doc/*` (these files are generated from `/wiki/*`, place your edits there)
49
+ - `/build/*` (these are generated automatically)
50
+ - `/php/*` (except for base classes)
51
+ - `/python/*` (except for base classes)
52
+ - `/ccxt.js`
53
+ - `/README.md` (exchange lists are generated automatically)
54
+ - `/package.json`
55
+ - `/package.lock`
56
+ - `/wiki/*` (except for real edits, exchange lists are generated automatically)
57
+ - `/dist/ccxt.browser.js` (this is also browserified automatically)
58
+
59
+
60
+ These files are generated ([explained below](https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#multilanguage-support)) and will be overwritten upon build. Please don't commit them to avoid bloating the repository which is already quite large. Most often, you have to commit just one single source file to submit an edit to the implementation of an exchange.
61
+
62
+ - **PLEASE, SUBMIT ATOMIC EDITS, ONE PULL REQUEST PER ONE EXCHANGE, DO NOT MIX THEM**
63
+ - **MAKE SURE YOUR CODE PASSES ALL SYNTAX CHECKS BY RUNNING `npm run build`**
64
+
65
+ ## Pending Tasks
66
+
67
+ Below is a list of functionality we would like to have implemented and fully **unified** in the library in the first place at this time. Most of these tasks are already in progress, implemented for some exchanges, but not all of them:
68
+
69
+ - Margin trading
70
+ - Leverage
71
+ - Derivatives (futures, options)
72
+ - Main account / subaccounts
73
+ - Conditional orders (stop loss, take profit)
74
+ - `transfer` between subaccounts and main account
75
+ - `fetchTransfer`
76
+ - `fetchTransfers`
77
+ - `fetchLedger`
78
+ - `fetchPositions`
79
+ - `closePosition`
80
+ - `closePositions`
81
+
82
+ If you want to contribute by submitting partial implementations be sure to look up examples of how it's done inside the library (where implemented already) and copy the adopted practices.
83
+
84
+ If your proposal, suggestion or improvement does not relate to the above list of tasks before submitting it make sure it is:
85
+ 1. really needed by the majority of ccxt users
86
+ 2. designed to be a general-purpose solution, not hardcoded for your specific needs
87
+ 3. done in a generalized way compatible with all exchanges (not exchange-specific)
88
+ 4. portable (available in all supported languages)
89
+ 5. robust
90
+ 6. explicit in what it's doing
91
+ 7. doesn't break anything (if you change a method, make sure that all other methods calling the edited method are not broken)
92
+
93
+ The following is a set of rules for contributing to the ccxt library codebase.
94
+
95
+ ## What You Need To Have
96
+
97
+ If you're not going to develop CCXT and contribute code to the CCXT library, then you don't need the Docker image nor the CCXT repository. If you just want to use CCXT inside your project simply install it as a regular package into the project folder as documented in the Manual (https://github.com/ccxt/ccxt/wiki/Install):
98
+
99
+ - [JavaScript / Node.js / NPM](https://github.com/ccxt/ccxt/wiki/Install#javascript-npm)
100
+
101
+ ```shell
102
+ # JavaScript / Node.js / NPM
103
+ npm install ccxt
104
+ ```
105
+
106
+ - [Python / PIP](https://github.com/ccxt/ccxt/wiki/Install#python)
107
+
108
+ ```shell
109
+ # Python
110
+ pip install ccxt # or pip3 install ccxt
111
+ ```
112
+
113
+ - [PHP / Composer](https://github.com/ccxt/ccxt/wiki/Install#php)
114
+
115
+ ```shell
116
+ # PHP / Composer
117
+ composer install ccxt
118
+ ```
119
+
120
+ ### With Docker
121
+
122
+ The easiest way is to use Docker to run an isolated build & test enviroment with all the dependencies installed:
123
+
124
+ ```shell
125
+ docker-compose run --rm ccxt
126
+ ```
127
+
128
+ That builds a container and opens a shell, where the `npm run build` and `node run-tests` commands should simply work out of the box.
129
+
130
+ The CCXT folder is mapped inside of the container, except the `node_modules` folder — the container would have its own ephemeral copy — so that won't mess up your locally installed modules. This means that you can edit sources on your host machine using your favorite editor and build/test them in the running container.
131
+
132
+ This way you can keep the build tools and processes isolated, not having to work through the painful process of installing all those dependencies to your host machine manually.
133
+
134
+ ### Without Docker
135
+
136
+ #### Dependencies
137
+
138
+ - Git
139
+ - [Node.js](https://nodejs.org/en/download/) 8+
140
+ - [Python](https://www.python.org/downloads/) 3.5.3+
141
+ - requests (`pip install requests`)
142
+ - [aiohttp](https://docs.aiohttp.org/) (`pip install aiohttp`)
143
+ - [tox](https://tox.readthedocs.io)
144
+ - via pip: `pip install tox`
145
+ - MacOS with [brew](https://brew.sh): `brew install tox`
146
+ - Ubuntu Linux: `apt-get install tox`
147
+ - [PHP](https://secure.php.net/downloads.php) 5.3+ with the following extensions installed and enabled:
148
+ - cURL
149
+ - iconv
150
+ - mbstring
151
+ - PCRE
152
+ - bcmath (php<7.1)
153
+
154
+ #### Build Steps
155
+
156
+ ```shell
157
+ git clone https://github.com/ccxt/ccxt.git
158
+ ```
159
+
160
+ ```shell
161
+ cd ccxt
162
+ ```
163
+
164
+ ```shell
165
+ npm install
166
+ ```
167
+
168
+ ```shell
169
+ npm run build
170
+ ```
171
+
172
+ ## What You Need To Know
173
+
174
+ ### Repository Structure
175
+
176
+ The contents of the repository are structured as follows:
177
+
178
+ ```shell
179
+ / # root directory aka npm module/package folder for Node.js
180
+ /.babelrc # babel config used for making the ES5 version of the library
181
+ /.eslintrc # linter
182
+ /.gitattributes # contains linguist settings for language detection in repo
183
+ /.gitignore # ignore it
184
+ /.npmignore # files to exclude from the NPM package
185
+ /.travis.yml # a YAML config for travis-ci (continuous integration)
186
+ /CONTRIBUTING.md # this file
187
+ /LICENSE.txt # MIT
188
+ /README.md # master markdown for GitHub, npmjs.com, npms.io, yarn and others
189
+ /build/ # build scripts
190
+ /build/export-exchanges.js # used to create tables of exchanges in the docs during the build
191
+ /build/transpile.js # the transpilation script
192
+ /build/update-badges.js # a JS script to update badges in the README and in docs
193
+ /build/vss.js # reads single-sourced version from package.json and writes it everywhere
194
+ /dist/ # a folder for the generated browser bundle of CCXT
195
+ /ccxt.js # entry point for the master JS version of the ccxt library
196
+ /ccxt.php # entry point for the PHP version of the ccxt library
197
+ /doc/ # Sphinx-generated rst-docs for http://docs.ccxt.com/
198
+ /js/ # the JS version of the library
199
+ /php/ # PHP ccxt module/package folder
200
+ /python/ # Python ccxt module/package folder for PyPI
201
+ /python/__init__.py # entry point for the Python version of the ccxt.library
202
+ /python/async_support/ # asynchronous version of the ccxt.library for Python 3.5.3+ asyncio
203
+ /python/base/ # base code for the Python version of the ccxt library
204
+ /python/MANIFEST.in # a PyPI-package file listing extra package files (license, configs, etc...)
205
+ /python/README.md # a copy of README.md for PyPI
206
+ /python/setup.cfg # wheels config file for the Python package
207
+ /python/setup.py # pip/setuptools script (build/install) for ccxt in Python
208
+ /python/tox.ini # tox config for Python
209
+ /examples/ # self-explanatory
210
+ /examples/js # ...
211
+ /examples/php # ...
212
+ /examples/py # ...
213
+ /exchanges.cfg # custom bundle config for including only the exchanges you need
214
+ /package.json # npm package file, also used in setup.py for version single-sourcing
215
+ /run-tests.js # a front-end to run individual tests of all exchanges in all languages (JS/PHP/Python)
216
+ /wiki/ # the source of all docs (edits go here)
217
+ ```
218
+
219
+ ### Multilanguage Support
220
+
221
+ The ccxt library is available in three different languages (more to come). We encourage developers to design *portable* code, so that a single-language user could read the code in other languages and understand it easily. This helps the adoption of the library. The main goal is to provide a generalized, unified, consistent and robust interface to as many existing cryptocurrency exchanges as possible.
222
+
223
+ At first, all language-specific versions were developed in parallel, but separately from each other. But when it became too hard to maintain and keep the code consistent among all supported languages we have decided to switch to what we call a *source/generated* process. There is now a single source version in one language, that is JavaScript. Other language-specific versions are syntactically derived (transpiled, generated) automatically from the source version. But it doesn't mean that you have to be a JS coder to contribute. The portability principle allows Python and PHP devs to effectively participate in developing the source version as well.
224
+
225
+ The module entry points are:
226
+ - `./python/__init__.py` for the Python pip package
227
+ - `./python/async/__init__.py` for the Python 3.5.3+ ccxt.async_support subpackage
228
+ - `./ccxt.js` for the Node.js npm package
229
+ - `./dist/ccxt.browser.js` for the browser bundle
230
+ - `./ccxt.php` for PHP
231
+
232
+ Generated versions and docs are transpiled from the source `ccxt.js` file and files in `./js/` by the `npm run build` command.
233
+
234
+ ### Transpiled (generated) files
235
+
236
+ - All derived exchange classes are transpiled automatically from source JS files. The source files are language-agnostic, easily mapped line-to-line to any other language and written in a cross-language-compatible way. Any coder can read it (by design).
237
+ - All base classes are **not** transpiled, those are language-specific.
238
+
239
+ #### JavaScript
240
+
241
+ The `ccxt.browser.js` is generated with Babel from source.
242
+
243
+ #### Python
244
+
245
+ These files containing derived exchange classes are transpiled from JS into Python:
246
+
247
+ - `js/[_a-z].js` → `python/ccxt/async/[_a-z].py`
248
+ - `python/ccxt/async[_a-z].py` → `python/ccxt/[_a-z].py` (Python 3 asyncio → Python sync transpilation stage)
249
+ - `python/ccxt/test/test_async.py` → `python/ccxt/test/test_sync.py` (the sync test is generated from the async test)
250
+
251
+ These Python base classes and files are not transpiled:
252
+
253
+ - `python/ccxt/base/*`
254
+ - `python/ccxt/async/base/*`
255
+
256
+ #### PHP
257
+
258
+ These files containing derived exchange classes are transpiled from JS into PHP:
259
+
260
+ - `js/[_a-z].js` → `php/[_a-z].php`
261
+
262
+ These PHP base classes and files are not transpiled:
263
+
264
+ - `php/Exchange.php php/ExchangeError.php php/Precise.php ...`
265
+
266
+ #### Typescript
267
+
268
+ - `js/[_a-z].js` → `ccxt.d.ts`
269
+
270
+ ### Base Class
271
+
272
+ ```UNDER CONSTRUCTION```
273
+
274
+ ### Derived Exchange Classes
275
+
276
+ Transpiler is regex-based and heavily relies on specific formatting rules. If you break them then the transpiler will either
277
+ fail to generate Python/PHP classes at all or will generate malformed Python/PHP syntax.
278
+
279
+ Below are key notes on how to keep the JS code transpileable.
280
+
281
+ Use the linter `npm run lint js/your-exchange-implementation.js` before you build. It will cover many (but not all) the issues,
282
+ so manual checking will still be required if transpilation fails.
283
+
284
+ If you see a `[TypeError] Cannot read property '1' of null` exception or any other transpilation error when you `npm run build`, check if your code satisfies the following rules:
285
+
286
+ - don't put empty lines inside your methods
287
+ - always use Python-style indentation, it is preserved as is for all languages
288
+ - indent with 4 spaces **exactly**, avoid tabs
289
+ - put an empty line between each of your methods
290
+ - avoid mixed comment styles, use double-slash `//` in JS for line comments
291
+ - avoid multi-line comments
292
+
293
+ If the transpiling process finishes successfully, but generates incorrect Python/PHP syntax, check for the following:
294
+
295
+ - every opening bracket like `(` or `{` should have a space before it!
296
+ - do not use language-specific code syntax sugar, even if you really want to
297
+ - unfold all maps and comprehensions to basic for-loops
298
+ - don't change the arguments of overridden inherited methods, keep them uniform across all exchanges
299
+ - everything should be done using base class methods only (for example, use `this.json ()` for converting objects to json)
300
+ - always put a semicolon `;` at the end of each statement, as in PHP/C-style
301
+ - all associative keys must be single-quoted strings everywhere (`array['good']`), do not use the dot notation (`array.bad`)
302
+ - never use the `var` keyword, instead use `const` for constants or `let` for variables
303
+
304
+ And structurally:
305
+
306
+ - if you need another base method you will have to implement it in all three languages
307
+ - try not to issue more than one HTTP request from a unified method
308
+ - avoid changing the contents of the arguments and params passed by reference into function calls
309
+ - keep it simple, don't do more than one statement in one line
310
+ - try to reduce syntax & logic (if possible) to basic one-liner expressions
311
+ - multiple lines are ok, but you should avoid deep nesting with lots of brackets
312
+ - do not use conditional statements that are too complex (heavy if-bracketing)
313
+ - do not use heavy ternary conditionals
314
+ - avoid operators clutter (**don't do this**: `a && b || c ? d + 80 : e ** f`)
315
+ - do not use `.includes()`, use `.indexOf()` instead!
316
+ - never use `.toString()` on floats: `Number (0.00000001).toString () === '1e-8'`
317
+ - do not use closures, `a.map` or `a.filter (x => (x === 'foobar'))` is not acceptable in derived classes
318
+ - do not use the `in` operator to check if a value is in a non-associative array (list)
319
+ - don't add custom currency or symbol/pair conversions and formatting, copy from existing code instead
320
+ - **don't access non-existent keys, `array['key'] || {}` won't work in other languages!**
321
+
322
+ #### Sending Market Ids
323
+
324
+ Most of exchanges' API endpoints will require an exchange-specific market symbol or trading pair or instrument to be specified in the request.
325
+
326
+ **We don't send unified symbols to exchanges directly!** They are not interchangeable! There is a significant difference between *exchange-specific market-ids* and *unified symbols*! This is explained in the Manual, here:
327
+
328
+ - https://github.com/ccxt/ccxt/wiki/Manual#markets
329
+ - https://github.com/ccxt/ccxt/wiki/Manual#symbols-and-market-ids
330
+
331
+ **NEVER DO THIS:**
332
+
333
+ ```JavaScript
334
+ async fetchTicker (symbol, params = {}) {
335
+ const request = {
336
+ 'pair': symbol, // very bad, sending unified symbols to the exchange directly
337
+ };
338
+ const response = await this.publicGetEndpoint (request);
339
+ // parse in a unified way...
340
+ }
341
+ ```
342
+
343
+ **DO NOT DO THIS EITHER:**
344
+
345
+ ```JavaScript
346
+ async fetchTicker (symbol, params = {}) {
347
+ const request = {
348
+ 'symbol': symbol, // very bad, sending unified symbols to the exchange directly
349
+ };
350
+ const response = await this.publicGetEndpoint (request);
351
+ // parse in a unified way...
352
+ }
353
+ ```
354
+
355
+ Instead of sending a unified CCXT symbol to the exchange, we **always** take the exchange-specific market-`id` that corresponds to that symbol. If it so happens that an exchange specific market-id is exactly the same as the CCXT unified symbol – that's a happy coincidence, but we never rely on that in the unified CCXT API.
356
+
357
+ To get the exchange-specific market-id by a unified CCXT symbol, use the following methods:
358
+
359
+ - `this.market (symbol)` – returns the entire unified market structure, containing the `id`, `baseId`, `quoteId`, and many other interesting things
360
+ - `this.marketId (symbol)` – returns just the exchange-specific `id` of a market by a unified symbol (if you don't need anything else)
361
+
362
+ **GOOD EXAMPLES:**
363
+
364
+ ```JavaScript
365
+ async fetchTicker (symbol, params = {}) {
366
+ const market = this.market (symbol); // the entire market structure
367
+ const request = {
368
+ 'pair': market['id'], // good, they may be equal, but often differ, it's ok
369
+ };
370
+ const response = await this.publicGetEndpoint (this.extend (request, params));
371
+ // parse in a unified way...
372
+ }
373
+ ```
374
+
375
+ ```JavaScript
376
+ async fetchTicker (symbol, params = {}) {
377
+ const marketId = this.marketId (symbol); // just the id
378
+ const request = {
379
+ 'symbol': marketId, // good, they may be equal, but often differ, it's ok
380
+ };
381
+ const response = await this.publicGetEndpoint (this.extend (request, params));
382
+ // parse in a unified way...
383
+ }
384
+ ```
385
+
386
+ #### Parsing Symbols
387
+
388
+ When sending requests to the exchange unified symbols have to be _"converted"_ to exchange-specific market-`id`s like shown above. The same is true on the other end – when receiving an exchange response it has an exchange-specific market-`id` inside it that has to be _"converted back"_ to a unified CCXT symbol.
389
+
390
+ **We don't put exchange-specific market-`id`s in unified structures directly!** We can't freely interchange symbols with ids! There is a significant difference between an *exchange-specific market-ids* and *unified symbols*! This is explained in the Manual, here:
391
+
392
+ - https://github.com/ccxt/ccxt/wiki/Manual#markets
393
+ - https://github.com/ccxt/ccxt/wiki/Manual#symbols-and-market-ids
394
+
395
+ **NEVER DO THIS:**:
396
+
397
+ ```JavaScript
398
+ parseTrade (trade, market = undefined) {
399
+ // parsing code...
400
+ return {
401
+ 'info': trade,
402
+ 'symbol': trade['pair'], // very bad, returning exchange-specific market-ids in a unified structure!
403
+ // other fields...
404
+ };
405
+ }
406
+ ```
407
+
408
+ **DO NOT DO THIS EITHER**
409
+
410
+ ```JavaScript
411
+ parseTrade (trade, market = undefined) {
412
+ // parsing code...
413
+ return {
414
+ 'info': trade,
415
+ 'symbol': trade['symbol'], // very bad, returning exchange-specific market-ids in a unified structure!
416
+ // other fields...
417
+ };
418
+ }
419
+ ```
420
+
421
+ In order to handle the market-`id` properly it has to be looked-up in the info cached on this exchange with `loadMarkets()`:
422
+
423
+ **GOOD EXAMPLE:**
424
+
425
+ ```JavaScript
426
+ parseTrade (trade, market = undefined) {
427
+ const marketId = this.safeString (trade, 'pair');
428
+ // safeSymbol is used to parse the market id to a unified symbol
429
+ const symbol = this.safeSymbol (marketId, market);
430
+ return {
431
+ 'info': trade,
432
+ 'symbol': symbol, // very good, a unified symbol here now
433
+ // other fields...
434
+ };
435
+ }
436
+ ```
437
+
438
+ #### Accessing Dictionary Keys
439
+
440
+ In JavaScript, dictionary keys can be accessed in two notations:
441
+
442
+ - `object['key']` (single-quoted string key notation)
443
+ - `object.key` (property notation)
444
+
445
+ Both work almost identically, and one is implicitly converted to another upon executing the JavaScript code.
446
+
447
+ While the above does work in JavaScript, **it will not work in Python or PHP**. In most languages, associative dictionary keys are not treated in the same way as properties. Therefore, in Python `object.key` is not the same as `object['key']`. In PHP `$object->key` is not the same as `$object['key']` as well. Languages that differentiate between associative keys and properties use different notations for the two.
448
+
449
+ To keep the code transpileable, please, remember this simple rule: *always use the single-quoted string key notation `object['key']` for accessing all associative dictionary keys in all languages everywhere throughout this library!*
450
+
451
+ #### Sanitizing Input With `safe`-Methods
452
+
453
+ JavaScript is less restrictive than other languages. It will tolerate an attempt to dereference a non-existent key where other languages will throw an Exception:
454
+
455
+ ```JavaScript
456
+ // JavaScript
457
+
458
+ const someObject = {}
459
+
460
+ if (someObject['nonExistentKey']) {
461
+ // the body of this conditional will not execute in JavaScript
462
+ // because someObject['nonExistentKey'] === undefined === false
463
+ // but JavaScript will not throw an exception on the if-clause
464
+ }
465
+ ```
466
+
467
+ However, the above logic with *"an undefined value by default"* will not work in Python or PHP.
468
+
469
+ ```Python
470
+ # Python
471
+ some_dictionary = {}
472
+
473
+ # breaks
474
+ if some_dictionary['nonExistentKey']:
475
+ # in Python the attempt to dereference the nonExistentKey value
476
+ # will throw a standard built-in KeyError exception
477
+
478
+ # works
479
+ if 'nonExistentKey' in some_dictionary and some_dictionary['nonExistentKey']:
480
+ # this is a way to check if the key exists before accessing the value
481
+
482
+ # also works
483
+ if some_dictionary.get('nonExistentKey'):
484
+ # another a way to check if the key exists before accessing the value...
485
+ ```
486
+
487
+ Most languages will not tolerate an attempt to access a non-existent key in an object.
488
+
489
+ For the above reasons, please, **never do this** in the transpiled JS files:
490
+
491
+ ```JavaScript
492
+ // JavaScript
493
+ const value = object['key'] || other_value; // will not work in Python or PHP!
494
+ if (object['key'] || other_value) { /* will not work in Python or PHP! */ }
495
+ ```
496
+
497
+ Therefore we have a family of `safe*` functions:
498
+
499
+ - `safeInteger (object, key, default)`, `safeInteger2 (object, key1, key2, default)` –for parsing timestamps in milliseconds
500
+ - `safeNumber (object, key, default)`, `safeNumber2 (object, key1, key2, default)` – for parsing amounts, prices, costs
501
+ - `safeString (object, key, default)`, `safeString2 (object, key1, key2, default)` – for parsing ids, types, statuses
502
+ - `safeStringLower (object, key, default)`, `safeStringLower2 (object, key1, key2, default)` – for parsing and turning to lowercase
503
+ - `safeStringUpper (object, key, default)`, `safeStringUpper2 (object, key1, key2, default)` – for parsing and turning to lowercase
504
+ - `safeValue (object, key, default)`, `safeValue2 (object, key1, key2, default)` – for parsing objects (dictionaries) and arrays (lists)
505
+ - `safeTimestamp (object, key, default)`, `safeTimestamp2 (object, key1, key2, default)` – for parsing UNIX timestamps in seconds
506
+
507
+
508
+ The `safeValue` function is used for objects inside objects, arrays inside objects and boolean `true/false` values.
509
+
510
+ The above safe-functions will check for the existence of the `key` (or `key1`, `key2`) in the object and will properly return `undefined/None/null` values for JS/Python/PHP. Each function also accepts the `default` value to be returned instead of `undefined/None/null` in the last argument.
511
+
512
+ Alternatively, you could check for the key existence first...
513
+
514
+ So, you have to change this:
515
+
516
+ ```JavaScript
517
+ if (params['foo'] !== undefined) {
518
+ }
519
+ ```
520
+
521
+
522
+
523
+ ```JavaScript
524
+ const foo = this.safeValue (params, 'foo');
525
+ if (foo !== undefined) {
526
+ }
527
+ ```
528
+
529
+ Or:
530
+
531
+ ```JavaScript
532
+ if ('foo' in params) {
533
+ }
534
+ ```
535
+
536
+ #### Using Base Class Cryptography Methods For Authentication
537
+
538
+ Do not reinvent the wheel. Always use base-class methods for cryptography.
539
+
540
+ The CCXT library supports the following authentication algorithms and cryptography algorithms:
541
+
542
+ - HMAC
543
+ - JWT (JSON Web Token)
544
+ - RSA
545
+ - ECDSA Elliptic Curve Cryptography
546
+ - NIST P256
547
+ - secp256k1
548
+ - OTP 2FA (one-time password 2-factor authentication)
549
+
550
+ The base `Exchange` class offers several methods that are key to practically all cryptography in this lib. Derived exchange implementations must not use external dependencies for cryptography, everything should be done with base methods only.
551
+
552
+ - `hash (message, hash = 'md5', digest = 'hex')`
553
+ - `hmac (message, secret, hash = 'sha256', digest = 'hex')`
554
+ - `jwt (message, secret, hash = 'HS256')`
555
+ - `rsa (message, secret, alg = 'RS256')`
556
+ - `ecdsa (request, secret, algorithm = 'p256', hash = undefined)`
557
+ - `totp (secret)`
558
+ - `stringToBase64()`, `base64ToBinary()`, `binaryToBase64()`...
559
+
560
+ The `hash()` method supports the following `hash` algorithms:
561
+
562
+ - `'md5'`
563
+ - `'sha1'`
564
+ - `'sha3'`
565
+ - `'sha256'`
566
+ - `'sha384'`
567
+ - `'sha512'`
568
+ - `'keccak'`
569
+
570
+ The `digest` encoding argument accepts the following values:
571
+
572
+ - `'hex'`
573
+ - `'binary'`
574
+
575
+ The `hmac()` method also supports `'base64'` for the `digest` argument. This is for `hmac()` only, other implementations should use `'binary'` with `binaryToBase64()`.
576
+
577
+ #### Timestamps
578
+
579
+ **All timestamps throughout all unified structures within this library are integer UTC timestamps _in milliseconds_!**
580
+
581
+ In order to convert to milliseconds timestamps, CCXT implements the following methods:
582
+
583
+ ```JavaScript
584
+ const data = {
585
+ 'unixTimestampInSeconds': 1565242530,
586
+ 'unixTimestampInMilliseconds': 1565242530165,
587
+ 'unixTimestampAsDecimal': 1565242530.165,
588
+ 'stringInSeconds': '1565242530',
589
+ };
590
+
591
+ // convert to integer if the underlying value is already in milliseconds
592
+ const timestamp = this.safeInteger (data, 'unixTimestampInMilliseconds'); // === 1565242530165
593
+
594
+ // convert to integer and multiply by a thousand if the value has milliseconds after dot
595
+ const timestamp = this.safeTimestamp (data, 'unixTimestampAsDecimal'); // === 1565242530165
596
+
597
+ // convert to integer and multiply by a thousand if the value is a UNIX timestamp in seconds
598
+ const timestamp = this.safeTimestamp (data, 'unixTimestampInSeconds'); // === 1565242530000
599
+
600
+ // convert to integer and multiply by a thousand if the value is in seconds
601
+ const timestamp = this.safeTimestamp (data, 'stringInSeconds'); // === 1565242530000
602
+ ```
603
+
604
+ #### Working With Array Lengths
605
+
606
+ In JavaScript the common syntax to get a length of a string or an array is to reference the `.length` property like shown here:
607
+
608
+ ```JavaScript
609
+ someArray.length
610
+
611
+ // or
612
+
613
+ someString.length
614
+ ```
615
+
616
+ And it works for both strings and arrays. In Python this is done in a similar way:
617
+
618
+ ```Python
619
+ len(some_array)
620
+
621
+ # or
622
+
623
+ len(some_string)
624
+ ```
625
+
626
+ So the length is accessible in the same way for both strings and arrays and both work fine.
627
+
628
+ However, with PHP this is different, so the syntax for string lengths and array lengths is different:
629
+
630
+ ```PHP
631
+ count(some_array);
632
+
633
+ // or
634
+
635
+ strlen(some_string); // or mb_strlen
636
+ ```
637
+
638
+ Because the transpiler works line-by-line and does no code introspection, it cannot tell arrays from strings and cannot properly transpile `.length` to PHP without additional hinting. It will always transpile JS `.length` to PHP `strlen` and will prefer string lengths over array lengths. In order to indicate an array length properly we have to do the following:
639
+
640
+ ```JavaScript
641
+ const arrayLength = someArray.length;
642
+ // the above line ends with .length;
643
+ // that ending is a hint for the transpiler that will recognize someArray
644
+ // as an array variable in this place, rather than a string type variable
645
+ // now we can use arrayLength for the arithmetic
646
+ ```
647
+
648
+ That `.length;` line ending does the trick. The only case when the array `.length` is preferred over the string `.length` is the `for` loop. In the header of the `for` loop, the `.length` always refers to array length (not string length).
649
+
650
+ #### Adding Numbers And Concatenating Strings
651
+
652
+ In JS the arithmetic addition `+` operator handles both strings and numbers. So, it can concatenate strings with `+` and can sum up numbers with `+` as well. The same is true with Python. With PHP this is different, so it has different operators for string concatenation (the "dot" operator `.`) and for arithmetic addition (the "plus" operator `+`). Once again, because the transpiler does no code introspection it cannot tell if you're adding up numbers or strings in JS. This works fine until you want to transpile this to other languages, be it PHP or whatever other language it is.
653
+
654
+ There's this aspect of representation of numbers throughout the lib.
655
+ The existing approach documented int the Manual says that the library will accept and will return "floats everywhere" for amounts, prices, costs, etc.
656
+ Using floats is the easiest way of unboarding new users.
657
+ This has known quirks, it's impossible to represent exact numbers with floats (https://0.30000000000000004.com/)
658
+
659
+ To address that, we are switching to string-based representations everywhere.
660
+ So, we are now in the process of moving towards strings in a non-breaking way.
661
+
662
+ The new approach is:
663
+
664
+ We are adding an internal layer for string-based representations and string-based maths in the response parsers.
665
+ That internal layer is built on top of the base `Precise` class, that is used to do all string-based maths.
666
+ That class requires strings to operate on them and it will return strings as well.
667
+ All existing old parsers must be rewritten to use `Precise` string-based representations, on first-encounter.
668
+ All new code of all new parsers must be initially written with `Precise` string-based representations.
669
+
670
+ What exactly that means:
671
+
672
+ Compare this pseudocode showing how it was done **before** (an example of some arbitrary parsing code for the purpose of explaining it):
673
+
674
+ ```JavaScript
675
+ const amount = this.safeFloat (order, 'amount');
676
+ const remaining = this.safeFloat (order, 'remaining');
677
+ if (remaining > 0) {
678
+ status = 'open';
679
+ } else {
680
+ status = 'closed';
681
+ }
682
+ // ...
683
+ return {
684
+ // ...
685
+ 'amount': amount,
686
+ 'remaining': remaining,
687
+ 'status': status,
688
+ // ...
689
+ };
690
+ ```
691
+
692
+ This is how we should do it **from now on**:
693
+
694
+ ```JavaScript
695
+ const amount = this.safeNumber (order, 'amount'); // internal string-layer
696
+ const remaining = this.safeString (order, 'remaining'); // internal string-layer
697
+ if (Precise.stringGt (remaining, '0')) { // internal string-layer
698
+ status = 'open';
699
+ } else {
700
+ status = 'closed';
701
+ }
702
+ // ...
703
+ return {
704
+ // ...
705
+ 'amount': amount, // external layer, goes to the user
706
+ 'remaining': this.parseNumber (remaining), // external layer, goes to the user
707
+ 'status': status,
708
+ // ...
709
+ };
710
+ ```
711
+
712
+ In all new code of all parsers we should use string-based numbers throughout the body of the parser. Also we should add `parseNumber` as the last step of handling numeric values upon returning the result to the caller. The above two snippets are just examples, showing the usage of `Precise` with `safeString` and `parseNumber`. The actual parsers of orders also involve safeOrder-methods: https://github.com/ccxt/ccxt/pulls?q=safeOrder2.
713
+
714
+ The user will ultimately have an option to choose which implementation of parseNumber he wants: the one returning floats or the one returning strings. This way everyone will remain happy and the library will work both ways in a non-breaking fashion.
715
+
716
+ The rule of thumb is: **`+` is for string concatenation only (!)** and **ALL arithmetic operations must use `Precise`**.
717
+
718
+ #### Formatting Decimal Numbers To Precision
719
+
720
+ This section covers the request-assembly part. The `.toFixed ()` method has [known rounding bugs](https://www.google.com/search?q=toFixed+bug) in JavaScript, and so do the other rounding methods in the other languages as well. In order to work with number formatting consistently use the [`decimalToPrecision` method as described in the Manual](https://github.com/ccxt/ccxt/wiki/Manual#methods-for-formatting-decimals).
721
+
722
+ #### Escaped Control Characters
723
+
724
+ When using strings containing control characters like `"\n"`, `"\t"`, always enclose them in double quotes (`"`), not single quotes (`'`)! Single-quoted strings are not parsed for control characters and are treated as is in many languages apart from JavaScript. Therefore for tabs and newlines to work in PHP, we need to surround them with double quotes (especially in the `sign()` implementation).
725
+
726
+ Bad:
727
+
728
+ ```JavaScript
729
+ const a = 'GET' + method.toLowerCase () + '\n' + path;
730
+ const b = 'api\nfoobar.com\n';
731
+ ```
732
+
733
+ Good:
734
+
735
+ ```JavaScript
736
+ const a = 'GET' + method.toLowerCase () + "\n" + path; // eslint-disable-line quotes
737
+ // eslint-disable-next-line quotes
738
+ const b = "api\nfoobar.com\n";
739
+ ```
740
+
741
+ **↑ The `eslint-*` comments are mandatory!**
742
+
743
+ #### Using Ternary Conditionals
744
+
745
+ Do not use heavy ternary (`?:`) conditionals, **always use brackets in ternary operators!**
746
+
747
+ Despite that there is operator precedence in the programming languages themselves, the transpiler is regex-based and it does no code introspection, therefore it treats everything as plaintext.
748
+
749
+ The brackets are needed to hint the transpiler which part of the conditional is which. In the absence of brackets it's hard to understand the line and the intent of the developer.
750
+
751
+ Here are some examples of a badly-designed code that will break the transpiler:
752
+
753
+ ```JavaScript
754
+ // this is an example of bad codestyle that will likely break the transpiler
755
+ const foo = {
756
+ 'bar': 'a' + qux === 'baz' ? this.a () : this.b () + 'b',
757
+ };
758
+ ```
759
+
760
+ ```JavaScript
761
+ // this confuses the transpiler and a human developer as well
762
+ const foo = 'bar' + baz + qux ? 'a' : '' + this.c ();
763
+ ```
764
+
765
+ Adding surrounding brackets to corresponding parts would be a more or less correct way to resolve it.
766
+
767
+ ```JavaScript
768
+ const foo = {
769
+ 'bar': (qux === 'baz') ? this.a () : this.b (), // much better now
770
+ };
771
+ ```
772
+
773
+ The universally-working way to solve it is to just break the complex line into a few simpler lines, even at a cost of adding extra lines and conditionals:
774
+
775
+ ```JavaScript
776
+ // before:
777
+ // const foo = {
778
+ // 'bar': 'a' + qux === 'baz' ? this.a () : this.b () + 'b',
779
+ // };
780
+ // ----------------------------------------------------------------------------
781
+ // after:
782
+ const bar = (qux === 'baz') ? this.a () : this.b ();
783
+ const foo = {
784
+ 'bar': 'a' + bar + 'b',
785
+ };
786
+ ```
787
+
788
+ Or even:
789
+
790
+ ```JavaScript
791
+ // before:
792
+ // const foo = 'bar' + baz + qux ? 'a' : '' + this.c ();
793
+ // ----------------------------------------------------------------------------
794
+ // after:
795
+ let foo = 'bar' + baz;
796
+ if (qux) {
797
+ foo += 'a';
798
+ };
799
+ foo += this.c ();
800
+ ```
801
+
802
+ ---
803
+
804
+ ### New Exchange Integrations
805
+
806
+ **REMEMBER:** The key reason why this library is used at all is **Unification**. When developing a new exchange file the goal is not to implement it somehow, but to implement it in a very pedantic, precise and exact way, just as the other exchanges are implemented. For that we have to copy bits of logic from other exchanges and make sure that the new exchange conforms to the Manual in the following aspects:
807
+
808
+ - market ids, trading pair symbols, currency ids, token codes, symbolic unification and `commonCurrencies` must be standardized in all parsing methods (`fetchMarkets`, `fetchCurrencies`, `parseTrade`, `parseOrder`, ...)
809
+ - all unified API method names and arguments are standard – can't add or change them freely
810
+ - all parser input must be `safe`-sanitized as [described above](#sanitizing-input-with-safe-methods)
811
+ - for bulk operations the base methods should be used (`parseTrades`, `parseOrders`, note the `s` plural ending)
812
+ - use as much of base functionality as you can, do not reinvent the wheel, nor the bicycle, nor the bicycle wheel
813
+ - respect default argument values in `fetch`-methods, check if `since` and `limit` are `undefined` and do not send them to the exchange, we intentionally use the exchanges' defaults in such cases
814
+ - when implementing a unified method that has some arguments – we can't ignore or miss any of those arguments
815
+ - all structures returned from the unified methods must conform to their specifications from the Manual
816
+ - all API endpoints have to be listed out with proper support for params substituted in the URLs
817
+
818
+ Please, see the following document for new integrations: https://github.com/ccxt/ccxt/wiki/Requirements
819
+
820
+ A quick merge of a Pull Request for a new exchange integration depends on consistency and compliance with the above unified rules and standards. Breaking one of those is the key reason for not merging a Pull Request.
821
+
822
+ **If you want to add (support for) another exchange, or implement a new method for a particular exchange, then the best way to make it a consistent improvement is to learn from example. Take a look at how same things are implemented in other exchanges (we recommend certified exchanges) and try to copy the code flow and style.**
823
+
824
+ The basic JSON-skeleton for a new exchange integration is as follows:
825
+
826
+ ```
827
+ {
828
+ 'id': 'example',
829
+ 'name': 'Example Exchange',
830
+ 'country': [ 'US', 'EU', 'CN', 'RU' ],
831
+ 'rateLimit': 1000,
832
+ 'version': '1',
833
+ 'comment': 'This comment is optional',
834
+ 'urls': {
835
+ 'logo': 'https://example.com/image.jpg',
836
+ 'api': 'https://api.example.com/api',
837
+ 'www': 'https://www.example.com',
838
+ 'doc': [
839
+ 'https://www.example.com/docs/api',
840
+ 'https://www.example.com/docs/howto',
841
+ 'https://github.com/example/docs',
842
+ ],
843
+ },
844
+ 'api': {
845
+ 'public': {
846
+ 'get': [
847
+ 'endpoint/example',
848
+ 'orderbook/{pair}/full',
849
+ '{pair}/ticker',
850
+ ],
851
+ },
852
+ 'private': {
853
+ 'post': [
854
+ 'balance',
855
+ ],
856
+ },
857
+ },
858
+ }
859
+ ```
860
+
861
+ ### Implicit API Methods
862
+
863
+ In the code for each exchange, you'll notice that the functions that make API requests aren't explicitly defined. This is because the `api` definition in the exchange description JSON is used to create *magic functions* (aka *partial functions* or *closures*) inside the exchange subclass. That implicit injection is done by the `defineRestApi/define_rest_api` base exchange method.
864
+
865
+ Each partial function takes a dictionary of `params` and returns the API response. In the example JSON above, the `'endpoint/example'` results in the injection of a `this.publicGetEndpointExample` function. Similarly, the `'orderbook/{pair}/full'` results in a `this.publicGetOrderbookPairFull` function, that takes a ``pair`` parameter (again, passed in the `params` argument).
866
+
867
+ Upon instantiation the base exchange class takes each URL from its list of endpoints, splits it into words, and then makes up a callable function name from those words by using a partial construct. That process is the same in JS, Python and PHP as well. It is also described here:
868
+
869
+ - https://github.com/ccxt/ccxt/wiki/Manual#api-methods--endpoints
870
+ - https://github.com/ccxt/ccxt/wiki/Manual#implicit-api-methods
871
+ - https://github.com/ccxt-dev/ccxt/wiki/Manual#api-method-naming-conventions
872
+
873
+ ```UNDER CONSTRUCTION```
874
+
875
+ ### Continuous Integration
876
+
877
+ Builds are automated with [Travis CI](https://app.travis-ci.com/github/ccxt/ccxt). The build steps for Travis CI are described in the [`.travis.yml`](https://github.com/ccxt/ccxt/blob/master/.travis.yml) file.
878
+
879
+ Windows builds are automated with [Appveyor](https://ci.appveyor.com/project/ccxt/ccxt). The build steps for Appveyor are in the [`appveyor.yml`](https://github.com/ccxt/ccxt/blob/master/appveyor.yml) file.
880
+
881
+ Incoming pull requests are automatically validated by the CI service. You can watch the build process online here: [app.travis-ci.com/github/ccxt/ccxt/builds](https://app.travis-ci.com/github/ccxt/ccxt/builds).
882
+
883
+ ### How To Build & Run Tests On Your Local Machine
884
+
885
+ #### Adding Exchange Credentials
886
+
887
+ CCXT has tests for both the public API and the private authenticated API. By default, CCXT's built-in tests will only test the public APIs, because the code repository does not include the [API keys](https://github.com/ccxt/ccxt/wiki/Manual#authentication) that are required for the private API tests. Also, the included private tests will not alter the balance of the account in any way, all tests are non-intrusive. In order to enable private API testing, one must configure the API keys. That can be done either in `keys.local.json` or with the `env` variables.
888
+
889
+ ##### Configuring API keys and options in `keys.local.json`
890
+
891
+ Exchange API keys can be added to the `keys.local.json` in the root folder inside the repository. If it does not exist on your side – create it first. That file is in `.gitignore` and in `.npmignore`. You can add exchange credentials and various options for different exchanges to the `keys.local.json` file.
892
+
893
+ An example of `keys.local.json` file:
894
+
895
+ ```JavaScript
896
+ {
897
+ "ftx": {
898
+ "apiKey": "XXX",
899
+ "secret": "YYY"
900
+ },
901
+ "binance": {
902
+ "apiKey": "XXX",
903
+ "secret": "YYY",
904
+ "options": {
905
+ "some-option": "some value"
906
+ }
907
+ },
908
+ // ...
909
+ }
910
+ ```
911
+
912
+ ##### Configuring API keys as environment variables
913
+
914
+ You can also define API keys as `env` variables:
915
+
916
+ - https://www.google.com/search?q=set+env+variable+linux
917
+ - https://www.google.com/search?q=set+env+variable+mac
918
+ - https://www.google.com/search?q=set+env+variable+windows
919
+
920
+ Consult the docs for your OS and shell on how to set an environment variable. Most of the time a `set` command, or a `export` command will work. The `env` command might help check the already-set environment variables.
921
+
922
+ Examples of `env` variables: `BINANCE_APIKEY`, `BINANCE_SECRET`, `KRAKEN_APIKEY`, `KRAKEN_SECRET`, etc.
923
+
924
+ #### Building
925
+
926
+ Before building for the first time, install Node dependencies (skip this step if you're running our Docker image):
927
+
928
+ ```
929
+ npm install
930
+ ```
931
+
932
+ The command below will build everything and generate PHP/Python versions from source JS files:
933
+
934
+ ```
935
+ npm run build
936
+ ```
937
+
938
+ #### Testing
939
+
940
+ The following command will test the built generated files (for all exchanges, symbols and languages):
941
+
942
+ ```
943
+ node run-tests
944
+ ```
945
+
946
+ You can restrict tests to a specific language, a particular exchange or symbol:
947
+
948
+ ```
949
+ node run-tests [--js] [--python] [--python-async] [--php] [--php-async] [exchange] [symbol]
950
+ ```
951
+
952
+ The `node run-tests exchangename` will try 5 tests: `js`, `python`, `python-async`, `php`, `php-async`. You can control that like so:
953
+
954
+ ```
955
+ node run-tests exchange --js
956
+ node run-tests exchange --js --python-async
957
+ node run-tests exchange --js --php
958
+ node run-tests exchange --python --python-async
959
+ ...
960
+ ```
961
+
962
+ However, if that fails, you might have to bury one level lower and run language-specific tests to see what exactly is wrong:
963
+
964
+ ```
965
+ node js/test/test exchange --verbose
966
+ python3 python/ccxt/test/test_sync.py exchange --verbose
967
+ python3 python/ccxt/test/test_async.py exchange --verbose
968
+ php -f php/test/test_sync.php exchange --verbose
969
+ php -f php/test/test_async.php exchange --verbose
970
+ ```
971
+
972
+ The `test_sync` is just a synchronous version of `test_async`, so in most cases just running `test_async.py` and `test_async.php` is enough:
973
+
974
+ ```
975
+ node js/test/test exchange --verbose
976
+ python3 python/ccxt/test/test_async.py exchange --verbose
977
+ php -f php/test/test_async.php exchange --verbose
978
+ ```
979
+
980
+ When all of the language-specific tests work, then node run-tests will also succeed. In order to run those tests you want to make sure that the build has completed successfully.
981
+
982
+ For example, the first of the following lines will only test the source JS version of the library (`ccxt.js`). It does not require an `npm run build` before running it (can be useful if you need to verify quickly whether your changes break the code or not):
983
+
984
+ ```shell
985
+
986
+ node run-tests --js # test master ccxt.js, all exchanges
987
+
988
+ # other examples require the 'npm run build' to run
989
+
990
+ node run-tests --python # test Python sync version, all exchanges
991
+ node run-tests --php bitfinex # test Bitfinex with PHP
992
+ node run-tests --python-async kraken # test Kraken with Python async test, requires 'npm run build'
993
+ ```
994
+
995
+ ## Committing Changes To The Repository
996
+
997
+ The build process generates many changes in the transpiled exchange files, e.g. for Python and PHP. **You should NOT commit them to GitHub, commit only the base (JS) file changes please**.
998
+
999
+ ## Financial Contributions
1000
+
1001
+ We also welcome financial contributions in full transparency on our [open collective](https://opencollective.com/ccxt).
1002
+
1003
+ ## Credits
1004
+
1005
+ ### Contributors
1006
+
1007
+ Thank you to all the people who have already contributed to ccxt!
1008
+
1009
+ <a href="https://github.com/ccxt/ccxt/graphs/contributors"><img src="https://opencollective.com/ccxt/contributors.svg?width=890" /></a>
1010
+
1011
+ ### Backers
1012
+
1013
+ Thank you to all our backers! [[Become a backer](https://opencollective.com/ccxt#backer)]
1014
+
1015
+ <a href="https://opencollective.com/ccxt#backers" target="_blank"><img src="https://opencollective.com/ccxt/backers.svg?width=890"></a>
1016
+
1017
+ ### Supporters
1018
+
1019
+ Support this project by becoming a supporter. Your avatar will show up here with a link to your website.
1020
+
1021
+ [[Become a supporter](https://opencollective.com/ccxt#supporter)]
1022
+
1023
+ <a href="https://opencollective.com/ccxt/tiers/supporter/0/website" target="_blank"><img src="https://opencollective.com/ccxt/tiers/supporter/0/avatar.svg"></a>
1024
+ <a href="https://opencollective.com/ccxt/tiers/supporter/1/website" target="_blank"><img src="https://opencollective.com/ccxt/tiers/supporter/1/avatar.svg"></a>
1025
+ <a href="https://opencollective.com/ccxt/tiers/supporter/2/website" target="_blank"><img src="https://opencollective.com/ccxt/tiers/supporter/2/avatar.svg"></a>
1026
+ <a href="https://opencollective.com/ccxt/tiers/supporter/3/website" target="_blank"><img src="https://opencollective.com/ccxt/tiers/supporter/3/avatar.svg"></a>
1027
+ <a href="https://opencollective.com/ccxt/tiers/supporter/4/website" target="_blank"><img src="https://opencollective.com/ccxt/tiers/supporter/4/avatar.svg"></a>
1028
+ <a href="https://opencollective.com/ccxt/tiers/supporter/5/website" target="_blank"><img src="https://opencollective.com/ccxt/tiers/supporter/5/avatar.svg"></a>
1029
+ <a href="https://opencollective.com/ccxt/tiers/supporter/6/website" target="_blank"><img src="https://opencollective.com/ccxt/tiers/supporter/6/avatar.svg"></a>
1030
+ <a href="https://opencollective.com/ccxt/tiers/supporter/7/website" target="_blank"><img src="https://opencollective.com/ccxt/tiers/supporter/7/avatar.svg"></a>
1031
+ <a href="https://opencollective.com/ccxt/tiers/supporter/8/website" target="_blank"><img src="https://opencollective.com/ccxt/tiers/supporter/8/avatar.svg"></a>
1032
+ <a href="https://opencollective.com/ccxt/tiers/supporter/9/website" target="_blank"><img src="https://opencollective.com/ccxt/tiers/supporter/9/avatar.svg"></a>
1033
+
1034
+ ### Sponsors
1035
+
1036
+ Thank you to all our sponsors! (please ask your company to also support this open source project by [becoming a sponsor](https://opencollective.com/ccxt#sponsor))
1037
+
1038
+ [[Become a sponsor](https://opencollective.com/ccxt#sponsor)]
1039
+
1040
+ <a href="https://opencollective.com/ccxt/tiers/sponsor/0/website" target="_blank"><img src="https://opencollective.com/ccxt/tiers/sponsor/0/avatar.svg"></a>
1041
+ <a href="https://opencollective.com/ccxt/tiers/sponsor/1/website" target="_blank"><img src="https://opencollective.com/ccxt/tiers/sponsor/1/avatar.svg"></a>
1042
+ <a href="https://opencollective.com/ccxt/tiers/sponsor/2/website" target="_blank"><img src="https://opencollective.com/ccxt/tiers/sponsor/2/avatar.svg"></a>
1043
+ <a href="https://opencollective.com/ccxt/tiers/sponsor/3/website" target="_blank"><img src="https://opencollective.com/ccxt/tiers/sponsor/3/avatar.svg"></a>
1044
+ <a href="https://opencollective.com/ccxt/tiers/sponsor/4/website" target="_blank"><img src="https://opencollective.com/ccxt/tiers/sponsor/4/avatar.svg"></a>
1045
+ <a href="https://opencollective.com/ccxt/tiers/sponsor/5/website" target="_blank"><img src="https://opencollective.com/ccxt/tiers/sponsor/5/avatar.svg"></a>
1046
+ <a href="https://opencollective.com/ccxt/tiers/sponsor/6/website" target="_blank"><img src="https://opencollective.com/ccxt/tiers/sponsor/6/avatar.svg"></a>
1047
+ <a href="https://opencollective.com/ccxt/tiers/sponsor/7/website" target="_blank"><img src="https://opencollective.com/ccxt/tiers/sponsor/7/avatar.svg"></a>
1048
+ <a href="https://opencollective.com/ccxt/tiers/sponsor/8/website" target="_blank"><img src="https://opencollective.com/ccxt/tiers/sponsor/8/avatar.svg"></a>
1049
+ <a href="https://opencollective.com/ccxt/tiers/sponsor/9/website" target="_blank"><img src="https://opencollective.com/ccxt/tiers/sponsor/9/avatar.svg"></a>