IPC removed, replaced by WS
This commit is contained in:
1 parent
ba4217fb24
commit
656c193511
503 files changed
+28128
-34498
No files matched your search
+118
-166
@@ -48,17 +48,13 @@ const BN = require ('../static_dependencies/BN/bn')
|
||||
// ----------------------------------------------------------------------------
|
||||
// web3 / 0x imports
|
||||
|
||||
let Web3 = undefined
|
||||
, ethAbi = undefined
|
||||
let ethAbi = undefined
|
||||
, ethUtil = undefined
|
||||
, BigNumber = undefined
|
||||
|
||||
try {
|
||||
const requireFunction = require;
|
||||
Web3 = requireFunction ('web3') // eslint-disable-line global-require
|
||||
ethAbi = requireFunction ('ethereumjs-abi') // eslint-disable-line global-require
|
||||
ethUtil = requireFunction ('ethereumjs-util') // eslint-disable-line global-require
|
||||
BigNumber = requireFunction ('bignumber.js') // eslint-disable-line global-require
|
||||
// we prefer bignumber.js over BN.js
|
||||
// BN = requireFunction ('bn.js') // eslint-disable-line global-require
|
||||
} catch (e) {
|
||||
@@ -77,6 +73,7 @@ module.exports = class Exchange {
|
||||
'enableRateLimit': false,
|
||||
'rateLimit': 2000, // milliseconds = seconds * 1000
|
||||
'certified': false,
|
||||
'pro': false,
|
||||
'has': {
|
||||
'cancelAllOrders': false,
|
||||
'cancelOrder': true,
|
||||
@@ -169,6 +166,7 @@ module.exports = class Exchange {
|
||||
'429': RateLimitExceeded,
|
||||
'404': ExchangeNotAvailable,
|
||||
'409': ExchangeNotAvailable,
|
||||
'410': ExchangeNotAvailable,
|
||||
'500': ExchangeNotAvailable,
|
||||
'501': ExchangeNotAvailable,
|
||||
'502': ExchangeNotAvailable,
|
||||
@@ -276,8 +274,6 @@ module.exports = class Exchange {
|
||||
this.last_json_response = undefined
|
||||
this.last_response_headers = undefined
|
||||
|
||||
this.arrayConcat = (a, b) => a.concat (b)
|
||||
|
||||
const unCamelCaseProperties = (obj = this) => {
|
||||
if (obj !== null) {
|
||||
for (const k of Object.getOwnPropertyNames (obj)) {
|
||||
@@ -315,11 +311,6 @@ module.exports = class Exchange {
|
||||
|
||||
if (this.markets)
|
||||
this.setMarkets (this.markets)
|
||||
|
||||
if (this.requiresWeb3 && !this.web3 && Web3) {
|
||||
const provider = (this.web3ProviderURL) ? new Web3.providers.HttpProvider (this.web3ProviderURL) : new Web3.providers.HttpProvider ()
|
||||
this.web3 = new Web3 (Web3.givenProvider || provider)
|
||||
}
|
||||
}
|
||||
|
||||
defaults () {
|
||||
@@ -367,7 +358,6 @@ module.exports = class Exchange {
|
||||
throw new Error (this.id + '.rateLimit property is not configured')
|
||||
|
||||
this.tokenBucket = this.extend ({
|
||||
refillRate: 1 / this.rateLimit,
|
||||
delay: 1,
|
||||
capacity: 1,
|
||||
defaultCost: 1,
|
||||
@@ -472,42 +462,50 @@ module.exports = class Exchange {
|
||||
}
|
||||
}
|
||||
|
||||
print (... args) {
|
||||
console.log (... args)
|
||||
}
|
||||
|
||||
fetch (url, method = 'GET', headers = undefined, body = undefined) {
|
||||
|
||||
if (isNode && this.userAgent) {
|
||||
if (typeof this.userAgent === 'string')
|
||||
if (typeof this.userAgent === 'string') {
|
||||
headers = extend ({ 'User-Agent': this.userAgent }, headers)
|
||||
else if ((typeof this.userAgent === 'object') && ('User-Agent' in this.userAgent))
|
||||
} else if ((typeof this.userAgent === 'object') && ('User-Agent' in this.userAgent)) {
|
||||
headers = extend (this.userAgent, headers)
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof this.proxy === 'function') {
|
||||
|
||||
url = this.proxy (url)
|
||||
if (isNode)
|
||||
if (isNode) {
|
||||
headers = extend ({ 'Origin': this.origin }, headers)
|
||||
}
|
||||
|
||||
} else if (typeof this.proxy === 'string') {
|
||||
|
||||
if (this.proxy.length)
|
||||
if (isNode)
|
||||
headers = extend ({ 'Origin': this.origin }, headers)
|
||||
if (this.proxy.length && isNode) {
|
||||
headers = extend ({ 'Origin': this.origin }, headers)
|
||||
}
|
||||
|
||||
url = this.proxy + url
|
||||
}
|
||||
|
||||
headers = extend (this.headers, headers)
|
||||
|
||||
if (this.verbose)
|
||||
console.log ("fetch:\n", this.id, method, url, "\nRequest:\n", headers, "\n", body, "\n")
|
||||
if (this.verbose) {
|
||||
this.print ("fetch:\n", this.id, method, url, "\nRequest:\n", headers, "\n", body, "\n")
|
||||
}
|
||||
|
||||
return this.executeRestRequest (url, method, headers, body)
|
||||
}
|
||||
|
||||
async fetch2 (path, type = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
|
||||
|
||||
if (this.enableRateLimit)
|
||||
await this.throttle ()
|
||||
if (this.enableRateLimit) {
|
||||
await this.throttle (this.rateLimit)
|
||||
}
|
||||
|
||||
const request = this.sign (path, type, method, params, headers, body)
|
||||
return this.fetch (request.url, request.method, request.headers, request.body)
|
||||
@@ -622,8 +620,9 @@ module.exports = class Exchange {
|
||||
this.last_json_response = json // FIXME: for those classes that haven't switched to handleErrors yet
|
||||
}
|
||||
|
||||
if (this.verbose)
|
||||
console.log ("handleRestResponse:\n", this.id, method, url, response.status, response.statusText, "\nResponse:\n", responseHeaders, "\n", responseBody, "\n")
|
||||
if (this.verbose) {
|
||||
this.print ("handleRestResponse:\n", this.id, method, url, response.status, response.statusText, "\nResponse:\n", responseHeaders, "\n", responseBody, "\n")
|
||||
}
|
||||
|
||||
this.handleErrors (response.status, response.statusText, url, method, responseHeaders, responseBody, json, requestHeaders, requestBody)
|
||||
this.defaultErrorHandler (response.status, response.statusText, url, method, responseHeaders, responseBody, json)
|
||||
@@ -645,7 +644,7 @@ module.exports = class Exchange {
|
||||
if (currencies) {
|
||||
this.currencies = deepExtend (currencies, this.currencies)
|
||||
} else {
|
||||
const baseCurrencies =
|
||||
let baseCurrencies =
|
||||
values.filter (market => 'base' in market)
|
||||
.map (market => ({
|
||||
id: market.baseId || market.base,
|
||||
@@ -653,7 +652,7 @@ module.exports = class Exchange {
|
||||
code: market.base,
|
||||
precision: market.precision ? (market.precision.base || market.precision.amount) : 8,
|
||||
}))
|
||||
const quoteCurrencies =
|
||||
let quoteCurrencies =
|
||||
values.filter (market => 'quote' in market)
|
||||
.map (market => ({
|
||||
id: market.quoteId || market.quote,
|
||||
@@ -661,6 +660,10 @@ module.exports = class Exchange {
|
||||
code: market.quote,
|
||||
precision: market.precision ? (market.precision.quote || market.precision.price) : 8,
|
||||
}))
|
||||
baseCurrencies = sortBy (baseCurrencies, 'code')
|
||||
quoteCurrencies = sortBy (quoteCurrencies, 'code')
|
||||
this.baseCurrencies = indexBy (baseCurrencies, 'code')
|
||||
this.quoteCurrencies = indexBy (quoteCurrencies, 'code')
|
||||
const allCurrencies = baseCurrencies.concat (quoteCurrencies)
|
||||
const groupedCurrencies = groupBy (allCurrencies, 'code')
|
||||
const currencies = Object.keys (groupedCurrencies).map (code =>
|
||||
@@ -673,7 +676,7 @@ module.exports = class Exchange {
|
||||
return this.markets
|
||||
}
|
||||
|
||||
async loadMarkets (reload = false, params = {}) {
|
||||
async loadMarketsHelper (reload = false, params = {}) {
|
||||
if (!reload && this.markets) {
|
||||
if (!this.markets_by_id) {
|
||||
return this.setMarkets (this.markets)
|
||||
@@ -688,6 +691,21 @@ module.exports = class Exchange {
|
||||
return this.setMarkets (markets, currencies)
|
||||
}
|
||||
|
||||
// is async (returns a promise)
|
||||
loadMarkets (reload = false, params = {}) {
|
||||
if ((reload && !this.reloadingMarkets) || !this.marketsLoading) {
|
||||
this.reloadingMarkets = true
|
||||
this.marketsLoading = this.loadMarketsHelper (reload, params).then ((resolved) => {
|
||||
this.reloadingMarkets = false
|
||||
return resolved
|
||||
}, (error) => {
|
||||
this.reloadingMarkets = false
|
||||
throw error
|
||||
})
|
||||
}
|
||||
return this.marketsLoading
|
||||
}
|
||||
|
||||
async loadAccounts (reload = false, params = {}) {
|
||||
if (reload) {
|
||||
this.accounts = await this.fetchAccounts (params)
|
||||
@@ -725,43 +743,42 @@ module.exports = class Exchange {
|
||||
}
|
||||
|
||||
parseTradingViewOHLCV (ohlcvs, market = undefined, timeframe = '1m', since = undefined, limit = undefined) {
|
||||
const result = this.convertTradingViewToOHLCV (ohlcvs);
|
||||
return this.parseOHLCVs (result, market, timeframe, since, limit);
|
||||
const result = this.convertTradingViewToOHLCV (ohlcvs)
|
||||
return this.parseOHLCVs (result, market, timeframe, since, limit)
|
||||
}
|
||||
|
||||
convertTradingViewToOHLCV (ohlcvs) {
|
||||
convertTradingViewToOHLCV (ohlcvs, t = 't', o = 'o', h = 'h', l = 'l', c = 'c', v = 'v', ms = false) {
|
||||
const result = [];
|
||||
for (let i = 0; i < ohlcvs['t'].length; i++) {
|
||||
for (let i = 0; i < ohlcvs[t].length; i++) {
|
||||
result.push ([
|
||||
ohlcvs['t'][i] * 1000,
|
||||
ohlcvs['o'][i],
|
||||
ohlcvs['h'][i],
|
||||
ohlcvs['l'][i],
|
||||
ohlcvs['c'][i],
|
||||
ohlcvs['v'][i],
|
||||
]);
|
||||
ms ? ohlcvs[t][i] : (ohlcvs[t][i] * 1000),
|
||||
ohlcvs[o][i],
|
||||
ohlcvs[h][i],
|
||||
ohlcvs[l][i],
|
||||
ohlcvs[c][i],
|
||||
ohlcvs[v][i],
|
||||
])
|
||||
}
|
||||
return result;
|
||||
return result
|
||||
}
|
||||
|
||||
convertOHLCVToTradingView (ohlcvs) {
|
||||
const result = {
|
||||
't': [],
|
||||
'o': [],
|
||||
'h': [],
|
||||
'l': [],
|
||||
'c': [],
|
||||
'v': [],
|
||||
};
|
||||
convertOHLCVToTradingView (ohlcvs, t = 't', o = 'o', h = 'h', l = 'l', c = 'c', v = 'v', ms = false) {
|
||||
const result = {}
|
||||
result[t] = []
|
||||
result[o] = []
|
||||
result[h] = []
|
||||
result[l] = []
|
||||
result[c] = []
|
||||
result[v] = []
|
||||
for (let i = 0; i < ohlcvs.length; i++) {
|
||||
result['t'].push (parseInt (ohlcvs[i][0] / 1000));
|
||||
result['o'].push (ohlcvs[i][1]);
|
||||
result['h'].push (ohlcvs[i][2]);
|
||||
result['l'].push (ohlcvs[i][3]);
|
||||
result['c'].push (ohlcvs[i][4]);
|
||||
result['v'].push (ohlcvs[i][5]);
|
||||
result[t].push (ms ? ohlcvs[i][0] : parseInt (ohlcvs[i][0] / 1000))
|
||||
result[o].push (ohlcvs[i][1])
|
||||
result[h].push (ohlcvs[i][2])
|
||||
result[l].push (ohlcvs[i][3])
|
||||
result[c].push (ohlcvs[i][4])
|
||||
result[v].push (ohlcvs[i][5])
|
||||
}
|
||||
return result;
|
||||
return result
|
||||
}
|
||||
|
||||
fetchTicker (symbol, params = {}) {
|
||||
@@ -993,8 +1010,8 @@ module.exports = class Exchange {
|
||||
|
||||
async fetchStatus (params = {}) {
|
||||
if (this.has['fetchTime']) {
|
||||
const time = await this.fetchTime(params)
|
||||
return this.status = this.extend(this.status, {
|
||||
const time = await this.fetchTime (params)
|
||||
this.status = this.extend (this.status, {
|
||||
'updated': time,
|
||||
})
|
||||
}
|
||||
@@ -1026,27 +1043,34 @@ module.exports = class Exchange {
|
||||
return this.markets;
|
||||
}
|
||||
|
||||
filterBySinceLimit (array, since = undefined, limit = undefined, key = 'timestamp') {
|
||||
if (since !== undefined && since !== null)
|
||||
array = array.filter (entry => entry[key] >= since)
|
||||
if (limit !== undefined && limit !== null)
|
||||
array = array.slice (0, limit)
|
||||
filterBySinceLimit (array, since = undefined, limit = undefined, key = 'timestamp', tail = false) {
|
||||
const sinceIsDefined = (since !== undefined && since !== null)
|
||||
if (sinceIsDefined) {
|
||||
array = array.filter ((entry) => entry[key] >= since)
|
||||
}
|
||||
if (limit !== undefined && limit !== null) {
|
||||
array = (tail && !sinceIsDefined) ? array.slice (-limit) : array.slice (0, limit)
|
||||
}
|
||||
return array
|
||||
}
|
||||
|
||||
filterByValueSinceLimit (array, field, value = undefined, since = undefined, limit = undefined) {
|
||||
filterByValueSinceLimit (array, field, value = undefined, since = undefined, limit = undefined, key = 'timestamp', tail = false) {
|
||||
|
||||
const valueIsDefined = value !== undefined && value !== null
|
||||
const sinceIsDefined = since !== undefined && since !== null
|
||||
|
||||
// single-pass filter for both symbol and since
|
||||
if (valueIsDefined || sinceIsDefined)
|
||||
array = Object.values (array).filter (entry =>
|
||||
((valueIsDefined ? (entry[field] === value) : true) &&
|
||||
(sinceIsDefined ? (entry.timestamp >= since) : true)))
|
||||
if (valueIsDefined || sinceIsDefined) {
|
||||
array = Object.values (array).filter ((entry) =>
|
||||
((valueIsDefined ? (entry[field] === value) : true) &&
|
||||
(sinceIsDefined ? (entry[key] >= since) : true)))
|
||||
}
|
||||
|
||||
if (limit !== undefined && limit !== null)
|
||||
array = Object.values (array).slice (0, limit)
|
||||
if (limit !== undefined && limit !== null) {
|
||||
array = ((tail && !sinceIsDefined) ?
|
||||
Object.values (array).slice (-limit) :
|
||||
Object.values (array).slice (0, limit))
|
||||
}
|
||||
|
||||
return array
|
||||
}
|
||||
@@ -1064,13 +1088,15 @@ module.exports = class Exchange {
|
||||
objects = Object.values (objects)
|
||||
|
||||
// return all of them if no values were passed
|
||||
if (values === undefined || values === null)
|
||||
if (values === undefined || values === null) {
|
||||
return indexed ? indexBy (objects, key) : objects
|
||||
}
|
||||
|
||||
const result = []
|
||||
for (let i = 0; i < objects.length; i++) {
|
||||
if (values.includes (objects[i][key]))
|
||||
if (values.includes (objects[i][key])) {
|
||||
result.push (objects[i])
|
||||
}
|
||||
}
|
||||
|
||||
return indexed ? indexBy (result, key) : result
|
||||
@@ -1081,7 +1107,7 @@ module.exports = class Exchange {
|
||||
// if (!this.isArray (trades)) {
|
||||
// throw new ExchangeError (this.id + ' parseTrades expected an array in the trades argument, but got ' + typeof trades);
|
||||
// }
|
||||
let result = Object.values (trades || []).map (trade => this.extend (this.parseTrade (trade, market), params))
|
||||
let result = Object.values (trades || []).map ((trade) => this.extend (this.parseTrade (trade, market), params))
|
||||
result = sortBy (result, 'timestamp')
|
||||
const symbol = (market !== undefined) ? market['symbol'] : undefined
|
||||
return this.filterBySymbolSinceLimit (result, symbol, since, limit)
|
||||
@@ -1092,7 +1118,7 @@ module.exports = class Exchange {
|
||||
// if (!this.isArray (transactions)) {
|
||||
// throw new ExchangeError (this.id + ' parseTransactions expected an array in the transactions argument, but got ' + typeof transactions);
|
||||
// }
|
||||
let result = Object.values (transactions || []).map (transaction => this.extend (this.parseTransaction (transaction, currency), params))
|
||||
let result = Object.values (transactions || []).map ((transaction) => this.extend (this.parseTransaction (transaction, currency), params))
|
||||
result = this.sortBy (result, 'timestamp');
|
||||
const code = (currency !== undefined) ? currency['code'] : undefined;
|
||||
return this.filterByCurrencySinceLimit (result, code, since, limit);
|
||||
@@ -1248,97 +1274,32 @@ module.exports = class Exchange {
|
||||
// ------------------------------------------------------------------------
|
||||
// web3 / 0x methods
|
||||
static hasWeb3 () {
|
||||
return Web3 && ethUtil && ethAbi && BigNumber
|
||||
return ethUtil && ethAbi
|
||||
}
|
||||
|
||||
checkRequiredDependencies () {
|
||||
if (!Exchange.hasWeb3 ()) {
|
||||
throw new ExchangeError ("Required dependencies missing: \nnpm i web3 ethereumjs-util ethereumjs-abi bignumber.js --no-save");
|
||||
throw new ExchangeError ('Required dependencies missing: \nnpm i ethereumjs-util ethereumjs-abi --no-save');
|
||||
}
|
||||
}
|
||||
|
||||
ethDecimals (unit = 'ether') {
|
||||
const units = {
|
||||
'wei': 0, // 1
|
||||
'kwei': 3, // 1000
|
||||
'babbage': 3, // 1000
|
||||
'femtoether': 3, // 1000
|
||||
'mwei': 6, // 1000000
|
||||
'lovelace': 6, // 1000000
|
||||
'picoether': 6, // 1000000
|
||||
'gwei': 9, // 1000000000
|
||||
'shannon': 9, // 1000000000
|
||||
'nanoether': 9, // 1000000000
|
||||
'nano': 9, // 1000000000
|
||||
'szabo': 12, // 1000000000000
|
||||
'microether': 12, // 1000000000000
|
||||
'micro': 12, // 1000000000000
|
||||
'finney': 15, // 1000000000000000
|
||||
'milliether': 15, // 1000000000000000
|
||||
'milli': 15, // 1000000000000000
|
||||
'ether': 18, // 1000000000000000000
|
||||
'kether': 21, // 1000000000000000000000
|
||||
'grand': 21, // 1000000000000000000000
|
||||
'mether': 24, // 1000000000000000000000000
|
||||
'gether': 27, // 1000000000000000000000000000
|
||||
'tether': 30, // 1000000000000000000000000000000
|
||||
}
|
||||
return this.safeValue (units, unit)
|
||||
}
|
||||
|
||||
ethUnit (decimals = 18) {
|
||||
const units = {
|
||||
0: 'wei', // 1000000000000000000
|
||||
3: 'kwei', // 1000000000000000
|
||||
6: 'mwei', // 1000000000000
|
||||
9: 'gwei', // 1000000000
|
||||
12: 'szabo', // 1000000
|
||||
15: 'finney', // 1000
|
||||
18: 'ether', // 1
|
||||
21: 'kether', // 0.001
|
||||
24: 'mether', // 0.000001
|
||||
27: 'gether', // 0.000000001
|
||||
30: 'tether', // 0.000000000001
|
||||
}
|
||||
return this.safeValue (units, decimals)
|
||||
}
|
||||
|
||||
fromWei (amount, unit = 'ether', decimals = 18) {
|
||||
if (amount === undefined) {
|
||||
return amount
|
||||
}
|
||||
if (decimals !== 18) {
|
||||
amount = new BigNumber (amount).times (new BigNumber (10 ** (18 - decimals))).toFixed ()
|
||||
} else {
|
||||
amount = new BigNumber (amount).toFixed ()
|
||||
}
|
||||
return parseFloat (this.web3.utils.fromWei (amount, unit))
|
||||
}
|
||||
|
||||
toWei (amount, unit = 'ether', decimals = 18) {
|
||||
if (amount === undefined) {
|
||||
return amount
|
||||
}
|
||||
if (decimals !== 18) {
|
||||
amount = new BigNumber (this.numberToString (amount)).div (new BigNumber (10 ** (18 - decimals))).toFixed ()
|
||||
} else {
|
||||
amount = this.numberToString (amount)
|
||||
}
|
||||
return this.web3.utils.toWei (amount, unit)
|
||||
}
|
||||
|
||||
soliditySha3 (array) {
|
||||
const values = this.solidityValues (array);
|
||||
const types = this.solidityTypes (values);
|
||||
return '0x' + ethAbi.soliditySHA3 (types, values).toString ('hex')
|
||||
}
|
||||
|
||||
solidityTypes (array) {
|
||||
return array.map (value => (this.web3.utils.isAddress (value) ? 'address' : 'uint256'))
|
||||
}
|
||||
|
||||
solidityValues (array) {
|
||||
return array.map (value => (this.web3.utils.isAddress (value) ? value : (new BigNumber (value).toFixed ())))
|
||||
// we only support address, uint256, and string solidity types
|
||||
const encoded = []
|
||||
for (const value of array) {
|
||||
if (Number.isInteger (value) || value.match (/^[0-9]+$/)) {
|
||||
encoded.push (this.numberToBE (this.numberToString (value), 32))
|
||||
} else {
|
||||
const noPrefix = Exchange.remove0xPrefix (value)
|
||||
if (noPrefix.length === 40 && noPrefix.toLowerCase ().match (/^[0-9a-f]+$/)) { // check if it is an address
|
||||
encoded.push (this.base16ToBinary (noPrefix))
|
||||
} else {
|
||||
encoded.push (this.stringToBinary (noPrefix))
|
||||
}
|
||||
}
|
||||
}
|
||||
const concated = this.binaryConcatArray (encoded)
|
||||
return '0x' + this.hash (concated, 'keccak', 'hex')
|
||||
}
|
||||
|
||||
getZeroExOrderHash (order) {
|
||||
@@ -1424,15 +1385,6 @@ module.exports = class Exchange {
|
||||
])).toString ('hex');
|
||||
}
|
||||
|
||||
signZeroExOrder (order, privateKey) {
|
||||
const orderHash = this.getZeroExOrderHash (order);
|
||||
const signature = this.signMessage (orderHash, privateKey);
|
||||
return this.extend (order, {
|
||||
'orderHash': orderHash,
|
||||
'ecSignature': signature, // todo fix v if needed
|
||||
})
|
||||
}
|
||||
|
||||
signZeroExOrderV2 (order, privateKey) {
|
||||
const orderHash = this.getZeroExOrderHashV2 (order);
|
||||
const signature = this.signMessage (orderHash, privateKey);
|
||||
|
||||
+9
-11
@@ -31,6 +31,7 @@ module.exports =
|
||||
, index
|
||||
, ordered: x => x // a stub to keep assoc keys in order (in JS it does nothing, it's mostly for Python)
|
||||
, unique: x => Array.from (index (x))
|
||||
, arrayConcat: (a, b) => a.concat (b)
|
||||
|
||||
/* ............................................. */
|
||||
|
||||
@@ -199,7 +200,7 @@ module.exports =
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
@@ -217,22 +218,19 @@ module.exports =
|
||||
/* ............................................. */
|
||||
|
||||
, deepExtend: function deepExtend (...xs) {
|
||||
|
||||
let out = undefined
|
||||
|
||||
for (const x of xs) {
|
||||
|
||||
if (isDictionary (x)) {
|
||||
|
||||
if (!isObject (out))
|
||||
if (!isObject (out)) {
|
||||
out = {}
|
||||
|
||||
for (const k in x)
|
||||
}
|
||||
for (const k in x) {
|
||||
out[k] = deepExtend (out[k], x[k])
|
||||
|
||||
} else out = x
|
||||
}
|
||||
} else {
|
||||
out = x
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
|
||||
+31
-6
@@ -106,9 +106,13 @@ const decimalToPrecision = (x, roundingMode
|
||||
|
||||
/* handle tick size */
|
||||
if (countingMode === TICK_SIZE) {
|
||||
const missing = x % numPrecisionDigits
|
||||
const reminder = x / numPrecisionDigits
|
||||
if (reminder !== Math.floor (reminder)) {
|
||||
const precisionDigitsString = decimalToPrecision (numPrecisionDigits, ROUND, 100, DECIMAL_PLACES, NO_PADDING)
|
||||
const newNumPrecisionDigits = precisionFromString (precisionDigitsString)
|
||||
let missing = x % numPrecisionDigits
|
||||
// See: https://github.com/ccxt/ccxt/pull/6486
|
||||
missing = Number (decimalToPrecision (missing, ROUND, 8, DECIMAL_PLACES, NO_PADDING));
|
||||
const fpError = decimalToPrecision (missing / numPrecisionDigits, ROUND, Math.max (newNumPrecisionDigits, 8), DECIMAL_PLACES, NO_PADDING)
|
||||
if (precisionFromString (fpError) !== 0) {
|
||||
if (roundingMode === ROUND) {
|
||||
if (x > 0) {
|
||||
if (missing >= numPrecisionDigits / 2) {
|
||||
@@ -127,8 +131,6 @@ const decimalToPrecision = (x, roundingMode
|
||||
x = x - missing
|
||||
}
|
||||
}
|
||||
const precisionDigitsString = decimalToPrecision (numPrecisionDigits, ROUND, 100, DECIMAL_PLACES, NO_PADDING)
|
||||
const newNumPrecisionDigits = precisionFromString (precisionDigitsString)
|
||||
return decimalToPrecision (x, ROUND, newNumPrecisionDigits, DECIMAL_PLACES, paddingMode);
|
||||
}
|
||||
|
||||
@@ -282,10 +284,33 @@ const decimalToPrecision = (x, roundingMode
|
||||
return String.fromCharCode (...out)
|
||||
}
|
||||
|
||||
// toWei / fromWei
|
||||
|
||||
function fromWei (amount, decimals = 18) {
|
||||
if (amount === undefined) {
|
||||
return amount
|
||||
}
|
||||
const exponential = Math.floor (amount).toExponential () // wei must be whole numbers
|
||||
const [ n, exponent ] = exponential.split ('e')
|
||||
const newExponent = parseInt (exponent) - decimals
|
||||
return parseFloat (n + 'e' + newExponent)
|
||||
}
|
||||
|
||||
function toWei (amount, decimals = 18) {
|
||||
if (amount === undefined) {
|
||||
return amount
|
||||
}
|
||||
const exponential = parseFloat (amount).toExponential ()
|
||||
const [ n, exponent ] = exponential.split ('e')
|
||||
const newExponent = parseInt (exponent) + decimals
|
||||
return numberToString (Math.floor (parseFloat (n + 'e' + newExponent))) // wei must be whole numbers
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
module.exports = {
|
||||
|
||||
toWei,
|
||||
fromWei,
|
||||
numberToString,
|
||||
precisionFromString,
|
||||
decimalToPrecision,
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@ module.exports = {
|
||||
|
||||
const queue = []
|
||||
|
||||
return Object.assign ((cost) => {
|
||||
return Object.assign ((rateLimit, cost) => {
|
||||
|
||||
if (queue.length > cfg.maxCapacity)
|
||||
throw new Error ('Backlog is over max capacity of ' + cfg.maxCapacity)
|
||||
@@ -46,7 +46,7 @@ module.exports = {
|
||||
const t = now ()
|
||||
, elapsed = t - lastTimestamp
|
||||
lastTimestamp = t
|
||||
numTokens = Math.min (cfg.capacity, numTokens + elapsed * cfg.refillRate)
|
||||
numTokens = Math.min (cfg.capacity, numTokens + elapsed * (1 / rateLimit))
|
||||
await sleep (cfg.delay)
|
||||
}
|
||||
running = false
|
||||
|
||||
+2
@@ -3,6 +3,7 @@
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
const isNumber = Number.isFinite
|
||||
, isInteger = Number.isInteger
|
||||
, isArray = Array.isArray
|
||||
, hasProps = o => ((o !== undefined) && (o !== null))
|
||||
, isString = s => (typeof s === 'string')
|
||||
@@ -25,6 +26,7 @@ const asFloat = x => ((isNumber (x) || isString (x)) ? parseFloat (x) : Na
|
||||
module.exports = {
|
||||
|
||||
isNumber
|
||||
, isInteger
|
||||
, isArray
|
||||
, isObject
|
||||
, isString
|
||||
|
||||
Reference in new issue
Block a user