Skip to content

Latest commit

 

History

History
296 lines (237 loc) · 13.4 KB

CONTRIBUTING.md

File metadata and controls

296 lines (237 loc) · 13.4 KB

Contributing To The CCXT Library

- This file is a work in progress, guidelines for contributing are being developed right now!

How To Submit An Issue

If you want to submit an issue and you want your issue to be resolved quickly, here's a basic checklist for you:

  • Read the Manual, and especially carefully read the following sections:
  • Read the Troubleshooting section and follow troubleshooting steps.
  • Read the API docs for your exchange.
  • Search for similar issues first to avoid duplicates.
  • If your issue is unique, along with a basic description of the failure, please, provide the following information:
    • your language version, ccxt library version
    • which exchange it is and which method you're trying to call
    • a full code snippet you're having difficulties with (avoid one-liners)
    • paste the full stacktrace of that snippet in verbose mode as is, unchanged

How To Contribute Code

Pending Tasks

Below is a list of functionality we would like to have implemented in the library in the first place. Most of these tasks are already in progress, implemented for some exchanges, but not all of them:

  • Unified fetchOrder
  • Unified fetchOrders, fetchOpenOrders, fetchClosedOrders
  • Unified fetchMyTrades, fetchOrderTrades
  • Unified deposit method
  • Unified fees
  • Improved proxy support
  • WebSocket interfaces:
    • Pub: Methods for trading and private calls where supported
    • Sub: Real-time balance, orderbooks and other properties with each exchange
  • REST long-poller with round-robin scheduler for HTTP requests

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.

If your proposal, suggestion or improvement does not relate to the above list of tasks before submitting it make sure it is:

  1. really needed by the majority of ccxt users
  2. designed to be a general-purpose solution, not hardcoded for your specific needs
  3. done in a generalized way compatible with all exchanges (not exchange-specific)
  4. portable (available in all supported languages)
  5. robust
  6. explicit in what it's doing
  7. doesn't break anything

The following is a set of rules for contributing to the ccxt library codebase.

What You Need To Have

  • Node.js (version 8 or higher)
  • Python 2/3
  • PHP 5.3+
  • Pandoc

What You Need To Know

Repository Structure

The contents of the repository are structured as follows:

/                    # root directory aka npm module/package folder for Node.js
/.babelrc            # babel config used for making the ES5 version of the library
/.eslintrc           # linter
/.gitattributes      # contains linguist settings for language detection in repo
/.gitignore          # ignore it
/.npmignore          # ignore it npm-style
/.travis.yml         # a YAML config for travis-ci (continuous integration)
/CHANGELOG.md        # says itself
/CONTRIBUTING.md     # this file
/LICENSE.txt         # MIT
/MANIFEST.in         # a PyPI-package file listing extra package files (license, configs, etc...)
/README.md           # master markdown for GitHub, npmjs.com, npms.io, yarn and others
/README.rst          # slave reStructuredText for PyPI
/build/              # a folder for the generated slave source files
/build/ccxt.php      # slave generated PHP version of the ccxt library
/ccxt.js             # master JS ES6 version of the ccxt library
/ccxt.php            # base code for the PHP version of the ccxt library
/ccxt.py             # base code for the Python version of the ccxt library
/ccxt/               # Python ccxt module/package folder for PyPI
/ccxt/__init__.py    # slave generated Python-version of the ccxt library
/countries.js        # a list of ISO 2-letter country codes in JS for testing, not very important
/examples/           # self-explaining
/examples/js         # ...
/examples/php        # ...
/examples/py         # ...
/export-exchanges.js # used to create tables of exchanges in the docs during the build
/package.json        # npm package file, also used in setup.py for version single-sourcing
/setup.cfg           # wheels config file for the Python package
/setup.py            # pip/setuptools script (build/install) for ccxt in Python
/run-tests.js        # a front-end to run invididual tests of all exchanges in all languages (JS/PHP/Python)
/test                # invididual tests for all languages
/tox.ini             # tox config for Python
/transpile.js        # the transpilation script
/update-badges.js    # a JS script to update badges in the README and in docs
/vss.js              # reads single-sourced version from package.json and writes it everywhere

Multilanguage Support

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 can read 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.

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 decided to switch to what we call a master/slave process. There is now a single master version in one language, that is JavaScript. Other language-specific versions are syntactically derived (transpiled, generated) from the master 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 master version as well.

The ccxt library includes one single file per each language:

/ccxt.js               # master JS ES6 version of the ccxt library
/ccxt.py               # base code for the slave Python version of the ccxt library
/ccxt.browser.js       # base code for the browserified version of the library
/ccxt.php              # base code for the slave PHP version of the ccxt library
/ccxt/__init__.py      # slave Python-version of the ccxt library
/build/ccxt.browser.js # slave browser bundle of the ccxt library
/build/ccxt.php        # slave PHP-version of the ccxt library

The module entry points are:

  • ./ccxt/__init__.py for the Python pip package
  • ./ccxt.js for the Node.js npm package
  • ./build/ccxt.browser.js for the browser bundle
  • ./build/ccxt.php for PHP

Slave files and docs are partially-generated from the master ccxt.js file by the npm run build command.

The structure of the master/slave file can be outlined like this:

        +----------------------------+  ←  beginning of file
h   ╭   |                            |
e   │   |  globals                   |
a   │   |                            |
d  ─┤   //---------------------------+  ←  thin horizontal ruler comment is used to separate code blocks
e   │   |                            |
r   │   |  base exchange class       |     above this first bold line all code is language-specific
    ╰   |                            |                    ↑
        //===========================+  ←  first bold horizontal ruler comment
    ╭   |                            |                    ↓
    │   |  derived exchange class A  |     below this line all code can be ported to other languages
    │   |                            |
b   │   //---------------------------+  ←  thin horizontal ruler used to separate derived classes
o   │   |                            |
d  ─┤   |  derived exchange class B  |
y   │   |                            |
    │   //---------------------------+
    │   |                            |
    │   | ...                        |     above this line all code is transpileable
    ╰   |                            |                    ↑
        //===========================+  ←  second bold horizontal ruler comment
f   ╭   |                            |                    ↓
o   │   |  other code                |     below this second bold line all code is language-specific
o   │   |                            |
t  ─┤   //---------------------------+  ←  thin horizontal ruler comment is used to separate code blocks
e   │   |                            |
r   │   |  other code                |
    ╰   |                            |
        //---------------------------+  ←  end of file

Key notes on the structure of the library file:

  • thin ruler comments are there for code block separation
  • bold ruler comments are there to separate language-specific base code from language-agnostic derived implementations
  • bold rulers are marker hints for the transpiler to quickly find the code for conversion
  • the second bold ruler and footer are optional
  • ...
JavaScript

UNDER CONSTRUCTION

Python

UNDER CONSTRUCTION

PHP

UNDER CONSTRUCTION

Base Class

UNDER CONSTRUCTION

Derived Exchange Classes

Below are key notes on how to keep the JS code transpileable:

  • do not use language-specific code syntax sugar, even if you really want to
  • unfold all maps and comprehensions to basic for-loops
  • every opening bracket like ( or { should have a space before it!
  • always use Python-style indentation, it is preserved as is for all languages
  • indent with spaces, avoid tabs
  • always put a semicolon ; at the end of each statement, as in PHP/C-style
  • all associative keys must be single-quoted strings everywhere, array['good'], array.bad
  • all local variables should be declared with the let keyword
  • do everything with base class methods only
  • if you need another base method you will have to implement it in all three languages
  • try to reduce syntax to basic one-liner expressions
  • multiple lines are ok, but you should avoid deep nesting with lots of brackets
  • do not use conditional statements that are too complex (heavy if-bracketing)
  • do not use heavy ternary conditionals
  • put an empty line between each of your methods
  • don't put empty lines in schema in the beginning of each exchange
  • don't put empty lines inside your methods
  • avoid mixed comment styles, use double-slash // in JS for line comments
  • avoid multi-line comments
  • ...

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 and try to copy the code flow and style.

The basic JSON-skeleton for a new exchange integration is as follows:

{
   "id": "example",
   "name": "Example Exchange",
   "country": [ "US", "EU", "CN", "RU" ],
   "rateLimit": 1000,
   "version": "1",
   "comment": "This comment is optional",
   "urls": {
      "logo": "https://example.com/image.jpg",
      "api": "https://api.example.com/api",
      "www": "https://www.example.com",
      "doc": [
         "https://www.example.com/docs/api",
         "https://www.example.com/docs/howto",
         "https://github.com/example/docs"
      ]
   },
   "api": {
      "public": {
         "get": [
            "endpoint/example",
            "orderbook/{pair}/full",
            "{pair}/ticker"
         ]
      },
      "private": {
         "post": [
            "balance"
         ]
      }
   }
}

UNDER CONSTRUCTION

Continuous Integration

Builds are automated by travis-ci. All build steps are described in the .travis.yml file.

Incoming pull requests are automatically validated by the CI service. You can watch the build process online here: travis-ci.org/kroitor/ccxt/builds.

How To Build & Run Tests On Your Local Machine

The command below will build everything and generate slave PHP/Python versions from master ccxt.js file:

npm run build

The following command will test the built slave source files (for all exchanges, symbols and languages):

node run-tests

You can restrict tests to a specific language, a particular exchange or symbol:

node run-tests [--php] [--js] [--python] [--python3] [exchange] [symbol]

For example, the first of the following lines will only test the single master version of source (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):

node run-tests --js             # test master ccxt.js, all exchanges

# other examples require the 'npm run build' to run

node run-tests --python         # test Python 2 version, all exchanges
node run-tests --php bitfinex   # test Bitfinex with PHP
node run-tests --python3 kraken # test Kraken with Python 3, requires 'npm run build'

UNDER CONSTRUCTION