Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
# Conflicts:
#	ccxt.d.ts
  • Loading branch information
wook committed Dec 20, 2019
2 parents 86a8fd6 + 2e1063b commit ff6fb11
Show file tree
Hide file tree
Showing 730 changed files with 188,868 additions and 102,461 deletions.
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
open_collective: ccxt
9 changes: 8 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
ccxt.egg-info/
build/
build/**/*
!build/countries.js
!build/export-exchanges.js
!build/fs.js
!build/transpile.js
!build/vss.js
examples/
node_modules/
python/
php/
tmp/
doc/
vendor/
wiki/
.tox/
.github/
.DS_Store
.nyc_output
.travis.yml
Expand Down
80 changes: 76 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,9 @@ The contents of the repository are structured as follows:

### 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.
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.

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 *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.
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.

The module entry points are:
- `./python/__init__.py` for the Python pip package
Expand Down Expand Up @@ -268,7 +268,7 @@ And structurally:

Most of exchanges' API endpoints will require an exchange-specific market symbol or trading pair or instrument to be specified in the request.

**We don't send unified symbols to exchanges directly!** They are not interchangeable! There is a significant difference between an *exchange-specific market-ids* and *unified symbols*! This is explained in the Manual, here:
**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:

- https://github.com/ccxt/ccxt/wiki/Manual#markets
- https://github.com/ccxt/ccxt/wiki/Manual#symbols-and-market-ids
Expand Down Expand Up @@ -402,7 +402,7 @@ In JavaScript, dictionary keys can be accessed in two notations:

Both work almost identically, and one is implicitly converted to another upon executing the JavaScript code.

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 was 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.
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.

To keep the code transpileable, please, remeber 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!*

Expand Down Expand Up @@ -444,6 +444,14 @@ if some_dictionary.get('nonExistentKey'):

Most languages will not tolerate an attempt to access a non-existent key in an object.

For the above reasons, please, **never do this** in the transpiled JS files:

```JavaScript
// JavaScript
const value = object['key'] || other_value; // will not work in Python or PHP!
if (object['key'] || other_value) { /* will not work in Python or PHP! */ }
```

Therefore we have a family of `safe*` functions:

- `safeInteger (object, key)`, `safeInteger2 (object, key1, key2)`
Expand Down Expand Up @@ -479,6 +487,70 @@ if ('foo' in params) {
}
```

#### Using Base Class Cryptography Methods For Authentication

Do not reinvent the wheel. Always use base-class methods for cryptography.

The CCXT library supports the following authentication algorithms and cryptography algorithms:

- HMAC
- JWT (JSON Web Token)
- RSA
- ECDSA Elliptic Curve Cryptography
- NIST P256
- secp256k1
- OTP 2FA (one-time password 2-factor authentication)

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.

- `hash (message, hash = 'md5', digest = 'hex')`
- `hmac (message, secret, hash = 'sha256', digest = 'hex')`
- `jwt (message, secret, hash = 'HS256')`
- `rsa (message, secret, alg = 'RS256')`
- `ecdsa (request, secret, algorithm = 'p256', hash = undefined)`
- `totp (secret)`
- `stringToBase64()`, `base64ToBinary()`, `binaryToBase64()`...

The `hash()` method supports the following `hash` algorithms:

- `'md5'`
- `'sha1'`
- `'sha3'`
- `'sha256'`
- `'sha384'`
- `'sha512'`
- `'keccak'`

The `digest` encoding argument accepts the following values:

- `'hex'`
- `'binary'`

The `hmac()` method also supports `'base64'` for the `digest` argument. This is for `hmac()` only, other implementations should use `'binary'` with `binaryToBase64()`.

#### Timestamps

**All timestamps throughout all unified structures within this library are integer timestamp _in milliseconds_!**

In order to convert to milliseconds timestamps, CCXT implementes the following methods:

```JavaScript
const data = {
'unixTimestampInSeconds': 1565242530,
'unixTimestampInMilliseconds': 1565242530165,
'stringInSeconds': '1565242530',
};

// convert to integer if the underlying value is already in milliseconds
const timestamp = this.safeInteger (data, 'unixTimestampInMilliseconds'); // === 1565242530165

// convert to integer and multiply by a thousand if the value is a UNIX timestamp in seconds
const timestamp = this.safeTimestamp (data, 'unixTimestampInSeconds'); // === 1565242530000

// convert to integer and multiply by a thousand if the value is in seconds
const timestamp = this.safeTimestamp (data, 'stringInSeconds'); // === 1565242530000
```

#### Working With Array Lengths

In JavaScript the common syntax to get a length of a string or an array is to reference the `.length` property like shown here:
Expand Down
11 changes: 8 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,22 @@ RUN sed -i 's/archive\.ubuntu\.com/us\.archive\.ubuntu\.com/' /etc/apt/sources.l
# Python 2
&& apt-get install -y python-pip \
&& pip2 install --upgrade setuptools \
&& pip2 install tox \
# Python 3
&& apt-get install -y python3 python3-pip \
&& pip3 install --upgrade setuptools \
&& pip3 install tox \
# Copy files to workdir to && install scripts against it (will be replaced with a live-mounted volume at startup)
&& mkdir -p /ccxt \
&& rm -rf /ccxt/node_modules \
&& mkdir -p /ccxt \
&& rm -rf /ccxt/node_modules \
# Installs as a local Node & Python module, so that `require ('ccxt')` and `import ccxt` should work after that
&& npm install \
&& ln -s /ccxt /usr/lib/node_modules/ \
&& echo "export NODE_PATH=/usr/lib/node_modules" >> $HOME/.bashrc \
&& cd python && python3 setup.py install && python setup.py install && cd .. \
&& cd python \
&& python3 setup.py develop \
&& python setup.py develop \
&& cd .. \
## Remove apt sources
&& apt-get -y autoremove && apt-get clean && apt-get autoclean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
Loading

0 comments on commit ff6fb11

Please sign in to comment.