Socket
Socket
Sign inDemoInstall

joyso

Package Overview
Dependencies
98
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.2.1 to 0.3.0

10

CHANGELOG.md
# Change Log
## v0.3.0 / 2018-10-16
### Added
- support for non-ETH quote pairs.
- new option value `token` to `fee` of `withdraw` method.
- get my trades api.
### Change
- pair format from ETH_XXX to XXX_ETH.
- option `fee` to `feeByJoy` of `buy`, `sell` and `trade` methods.
## v0.2.1 / 2018-10-08

@@ -4,0 +14,0 @@ ### Fixed

2

package.json
{
"name": "joyso",
"version": "0.2.1",
"version": "0.3.0",
"description": "JOYSO API client library for trading.",

@@ -5,0 +5,0 @@ "main": "src/joyso.js",

# JOYSO
JOYSO API client library for trading.
## Notice
v0.3.0 has breaking changes. Please see [CHANGELOG v0.3.0](https://github.com/Joyso-io/joyso-api/blob/master/CHANGELOG.md#v030--2018-10-16)
## Installation

@@ -28,3 +31,3 @@ You can use this command to install:

```JavaScript
const subscription = joyso.subscribeOrderBook('ETH_JOY', orderBook => {
const subscription = joyso.subscribeOrderBook('JOY_ETH', orderBook => {
console.log(JSON.stringify(orderBook));

@@ -63,3 +66,3 @@ });

```JavaScript
const subscription = joyso.subscribeTrades('ETH_JOY', trades => {
const subscription = joyso.subscribeTrades('JOY_ETH', trades => {
console.log(JSON.stringify(trades.slice(0, 2)));

@@ -76,3 +79,3 @@ });

"amount":"2",
"pair":"ETH_JOY"
"pair":"JOY_ETH"
},

@@ -84,3 +87,3 @@ {

"amount":"1",
"pair":"ETH_JOY"
"pair":"JOY_ETH"
}

@@ -130,3 +133,3 @@ ]

"fill":"0",
"pair":"ETH_T00"
"pair":"T00_ETH"
},

@@ -140,3 +143,3 @@ {

"fill":"3.5",
"pair":"ETH_JOY"
"pair":"JOY_ETH"
}

@@ -165,3 +168,3 @@ ]

"amount":"2",
"pair":"ETH_JOY",
"pair":"JOY_ETH",
"fee":"ETH",

@@ -178,3 +181,3 @@ "gasFee":"0",

"amount":"1",
"pair":"ETH_JOY",
"pair":"JOY_ETH",
"fee":"ETH",

@@ -228,3 +231,3 @@ "gasFee":"0.000105",

### buy({ pair, price, amount, fee })
### buy({ pair, price, amount, feeByJoy })
Place buying order

@@ -234,6 +237,6 @@ ```JavaScript

let order = await joyso.buy({
pair: 'ETH_JOY',
pair: 'JOY_ETH',
price: '0.000123481',
amount: 1,
fee: 'base'
feeByJoy: true
});

@@ -253,6 +256,6 @@ console.log(JSON.stringify(order));

|---|---|---|
|pair|O|Pair to trade, format is `${base}_${quote}`, eg: ETH_JOY|
|pair|O|Pair to trade, format is `${base}_${quote}`, eg: JOY_ETH|
|price|O|Order price, minimum is 0.000000001|
|amount|O|Quote amount|
|fee|O|Specify how to pay fee. `base` or `joy`.|
|feeByJoy||Specify how to pay fee. `true` will pay by JOY. `false` will pay by quote token(ETH if pair XXX_ETH). Default is `false`|

@@ -268,3 +271,3 @@ Result

"fill":"1",
"pair":"ETH_JOY"
"pair":"JOY_ETH"
}

@@ -275,10 +278,9 @@ ```

### sell({ pair, price, amount, fee })
### sell({ pair, price, amount, feeByJoy })
Place selling order
```JavaScript
let order = await joyso.sell({
pair: 'ETH_JOY',
pair: 'JOY_ETH',
price: '0.000123481',
amount: 100,
fee: 'base'
amount: 100
});

@@ -288,3 +290,3 @@ ```

### trade({ pair, price, amount, fee, side })
### trade({ pair, price, amount, feeByJoy, side })
Place order

@@ -294,6 +296,5 @@ ```JavaScript

side: 'buy',
pair: 'ETH_JOY',
pair: 'JOY_ETH',
price: '0.000123481',
amount: 100,
fee: 'joy'
amount: 100
});

@@ -322,4 +323,31 @@ ```

|amount|O|Amount to withdraw|
|fee|O|Specify how to pay fee. `eth` or `joy`.|
|fee|O|Specify how to pay fee. `eth`, `joy` or `token`. `token` can only be used when token is quote token.|
### getMyTrades({ from, to, quote, base, side, before, limit })
Get my trades
```JavaScript
await joyso.getMyTrades({
quote: 'ETH',
base: 'JOY',
side: 'sell',
from: 1539129600,
to: 1539216000,
before: 123,
limit: 10
});
```
Options
|Name|Required|Description|
|---|---|---|
|quote||Quote token|
|base||Base token|
|side||Specify side. `buy`, `sell` or blank. Blank means both.|
|from||From time (included). Unix timestamp|
|to||To time (excluded). Unix timestamp|
|before||Only return Trade ID before this. (excluded)|
|limit||Specify size of records to return|
Results are same with subscribeMyTrades.
### disconnect()

@@ -326,0 +354,0 @@ Disconnect from JOYSO.

@@ -12,3 +12,3 @@ const Joyso = require('../src/joyso');

// subscribe order book, notify if change
joyso.subscribeOrderBook('ETH_JOY', orderBook => {
joyso.subscribeOrderBook('JOY_ETH', orderBook => {
console.log(JSON.stringify(orderBook));

@@ -18,3 +18,3 @@ });

// subscribe market trades, notify if change
joyso.subscribeTrades('ETH_JOY', trades => {
joyso.subscribeTrades('JOY_ETH', trades => {
console.log(JSON.stringify(trades.slice(0, 5)));

@@ -48,6 +48,5 @@ });

order = await joyso.buy({
pair: 'ETH_JOY',
pair: 'JOY_ETH',
price: '0.000123481',
amount: 1,
fee: 'base'
amount: 1
});

@@ -57,6 +56,5 @@

order = await joyso.sell({
pair: 'ETH_JOY',
pair: 'JOY_ETH',
price: '0.000123481',
amount: 100,
fee: 'base'
amount: 100
});

@@ -67,6 +65,6 @@

side: 'buy',
pair: 'ETH_JOY',
pair: 'JOY_ETH',
price: '0.000123481',
amount: 100,
fee: 'joy'
feeByJoy: true
});

@@ -83,2 +81,13 @@

});
// get my trades
const trades = await joyso.getMyTrades({
quote: 'ETH',
base: 'JOY',
side: 'sell',
from: 1539680000,
to: 1539679000,
before: 123,
limit: 10
});
} catch (e) {

@@ -85,0 +94,0 @@ if (e.statusCode === 400) {

@@ -0,54 +1,67 @@

const EventEmitter = require('events');
const rp = require('request-promise');
class Account {
class Account extends EventEmitter {
constructor(client, address) {
super();
this.client = client;
this.address = address;
this.advanceReal;
this.advanceInOrder;
this.init = true;
}
subscribe() {
return new Promise(resolve => {
this.cable = this.client.cable.subscriptions.create({
channel: 'AccountAdvanceChannel',
contract: this.client.system.contract.substr(2),
address: this.address.substr(2)
}, {
connected: async () => {
await this.update();
if (this.init) {
this.init = false;
resolve();
}
},
received: data => {
switch (data.e) {
case 'update':
this.updateConfig(data.data);
break;
}
}
connect() {
if (this.cable) {
return Promise.reject();
}
const promise = new Promise((resolve, reject) => {
const timer = setTimeout(() => reject(new Error('timeout')), 15000);
this.once('update', () => {
clearTimeout(timer);
resolve();
});
this.once('error', e => {
clearTimeout(timer);
reject(e);
});
});
this.cable = this.client.cable.subscriptions.create({
channel: 'AccountAdvanceChannel',
contract: this.client.system.contract.substr(2),
address: this.address.substr(2)
}, {
connected: () => this.update(),
received: data => {
switch (data.e) {
case 'update':
this.updateConfig(data.data);
break;
}
}
});
return promise;
}
unsubscribe() {
destroy() {
clearTimeout(this.retryTimer);
this.cable.unsubscribe();
delete this.cable;
this.init = false;
}
async update() {
try {
clearTimeout(this.retryTimer);
const json = await this.client.request('accounts/advance', { data: { user: this.address.substr(2) } });
this.updateConfig(json);
} catch (e) {
this.emit('error', e);
this.retryTimer = setTimeout(() => this.update(), 5000);
}
}
updateConfig(json) {
this.advanceReal = json.advance_real;
this.advanceInOrder = json.advance_in_order;
this.emit('update', json);
}
async update() {
const json = await rp(this.client.createRequest(`accounts/advance?user=${this.address.substr(2)}`));
this.updateConfig(json);
}
}
module.exports = Account;

@@ -51,8 +51,8 @@ const rp = require('request-promise');

async get() {
const json = await rp(this.client.createRequest('balances', {
qs: {
const json = await this.client.request('balances', {
data: {
contract: this.client.system.contract.substr(2),
user: this.address.substr(2)
}
}));
});
json.balances.forEach(balance => this.updateBalance(balance));

@@ -59,0 +59,0 @@ }

@@ -57,2 +57,3 @@ const rp = require('request-promise');

unsubscribe() {
clearTimeout(this.retryTimer);
this.cable.unsubscribe();

@@ -68,16 +69,23 @@ delete this.cable;

this.requesting = this.requestId;
clearTimeout(this.retryTimer);
const after = this.funds.length ? this.funds[0].id : null;
const json = await this.get(after);
const funds = this.convert(json.funds, true);
if (after) {
this.funds.unshift(...funds);
} else {
this.funds = funds;
}
this.onReceived(this.funds);
if (this.requesting !== this.requestId) {
try {
const json = await this.get(after);
const funds = this.convert(json.funds, true);
if (after) {
this.funds.unshift(...funds);
} else {
this.funds = funds;
}
this.onReceived(this.funds);
if (this.requesting !== this.requestId) {
this.requesting = 0;
this.update();
} else {
this.requesting = 0;
}
} catch (e) {
console.log(e);
this.requesting = 0;
this.update();
} else {
this.requesting = 0;
this.retryTimer = setTimeout(() => this.update(), 5000);
}

@@ -118,4 +126,4 @@ }

get(after = null) {
return rp(this.client.createRequest('funds', {
qs: {
return this.client.request('funds', {
data: {
contract: this.client.system.contract.substr(2),

@@ -125,3 +133,3 @@ user: this.address.substr(2),

}
}));
});
}

@@ -128,0 +136,0 @@ }

@@ -16,4 +16,6 @@ const rp = require('request-promise');

BigNumber.config({ DECIMAL_PLACES: 36, ROUNDING_MODE: 1 });
BigNumber.config({ DECIMAL_PLACES: 36 });
const ETH_MAX_FEE_PRICE = new BigNumber('100000000');
const NON_ETH_MAX_FEE_PRICE = new BigNumber('1000000000000000000000000000');
const keys = {};

@@ -43,8 +45,9 @@

this.system = new System(this);
const json = await this.system.update();
this.system.subscribe();
this.tokenManager = new TokenManager(this, json.tokens);
this.tokenManager.subscribe();
this.system.once('update', json => {
this.tokenManager = new TokenManager(this, json);
this.tokenManager.subscribe();
});
await this.system.connect();
this.account = new Account(this, this.address);
await this.account.subscribe();
await this.account.connect();
this.balances = new Balances({ client: this, address: this.address });

@@ -81,9 +84,9 @@ await this.balances.subscribe();

try {
const r = await rp(this.createRequest('accounts', {
const r = await this.request('accounts', {
method: 'POST',
body: Object.assign({
data: Object.assign({
user: this.address.substr(2),
nonce: nonce
}, vrs)
}));
});
this.accessToken = r.access_token;

@@ -98,6 +101,6 @@ } finally {

try {
const r = await rp(this.createRequest('withdraw_queues', {
const r = await this.request('withdraw_queues', {
method: 'POST',
body: withdraw
}));
data: withdraw
});
} catch (e) {

@@ -184,8 +187,7 @@ if (!options.retry && e.statusCode === 400 && e.error.fee_changed) {

delete order.hash;
const r = await rp(this.createRequest('orders', {
const r = await this.request('orders', {
method: 'POST',
body: order
}));
data: order
});
this.updateHashTable(order.nonce, hash);
order.is_buy = options.side === 'buy';
order.id = r.order.id;

@@ -197,5 +199,7 @@ order.status = r.order.status;

if (!options.retry && e.statusCode === 400 && e.error.fee_changed) {
options.retry = true;
await this.tokenManager.refresh();
return this.trade(options);
if (e.error.length === 1) {
options.retry = true;
return this.trade(options);
}
}

@@ -206,4 +210,40 @@ throw e;

toAmountByPrice(token, quoteAmount, price, method) {
const amount = this.tokenManager.toRawAmount(token, quoteAmount.mul(price), method);
async getMyTrades({ from, to, quote, base, side, before, limit } = {}) {
const options = {};
quote = this.tokenManager.symbolMap[quote];
if (quote) {
if (this.tokenManager.quotes.find(t => t === quote)) {
options.token_base = quote.address.substr(2);
} else {
throw new Error('invalid quote');
}
}
base = this.tokenManager.symbolMap[base];
if (base) {
options.token_target = base.address.substr(2);
}
if (side === 'buy') {
options.is_buy = true;
} else if (side === 'sell') {
options.is_buy = false
}
if (from) {
options.from = from;
}
if (to) {
options.to = to;
}
if (before) {
options.before = before;
}
if (limit) {
options.limit = limit;
}
options.user = this.address.substr(2);
const json = await this.request('trades/history', { data: options });
return this.myTrades.convert(json.trades);
}
toAmountByPrice(token, baseAmount, price, method) {
const amount = this.tokenManager.toRawAmount(token, baseAmount.mul(price), method);
return this.tokenManager.toAmount(token, amount);

@@ -213,3 +253,3 @@ }

toPrice(baseAmount, quoteAmount) {
return baseAmount.div(quoteAmount).round(9);
return quoteAmount.div(baseAmount).round(9);
}

@@ -231,11 +271,9 @@

validateOrder(price, amount, fee, side) {
validateOrder(price, amount, side, quote) {
this.validateAmount(amount);
const v = new BigNumber(price).mul(1000000000);
const precision = new BigNumber(10).pow(quote.precision);
const v = new BigNumber(price).mul(precision);
if (!v.truncated().equals(v)) {
throw new Error('invalid price');
}
if (fee !== 'base' && fee !== 'joy' && fee !== 'eth') {
throw new Error('invalid fee');
}
if (side !== 'buy' && side !== 'sell') {

@@ -246,2 +284,8 @@ throw new Error('invalid side');

validatePair(base, quote) {
if (!base || !quote || !this.tokenManager.quotes.find(t => t === quote)) {
throw new Error('invalid pair');
}
}
repayGasFee(token) {

@@ -252,9 +296,8 @@ const ratio = new BigNumber(this.tokenManager.eth.gasFee).div(token.gasFee);

receivableGasFee(side, paymentMethod, token) {
let ethBalance, gasFee;
ethBalance = this.tokenManager.toRawAmount(this.tokenManager.eth, this.balances.balances.ETH.available || 0);
gasFee = this.tokenManager.eth.gasFee;
receivableGasFee(side, feeByJoy, tokenFee, quote) {
let gasFee = quote.gasFee;
let baseBalance = this.balances.balances[quote.symbol];
baseBalance = this.tokenManager.toRawAmount(quote, baseBalance && baseBalance.available || 0);
if (
side !== 'buy' && paymentMethod === 'base' && gasFee.gt(ethBalance)
side !== 'buy' && !feeByJoy && gasFee.gt(baseBalance)
&& this.account.advanceReal === 0 && this.account.advanceInOrder === 0

@@ -264,20 +307,18 @@ ) {

} else if (this.account.advanceReal !== 0 && this.account.advanceInOrder === 0) {
return this.repayGasFee(token);
return this.repayGasFee(tokenFee);
} else {
return token.gasFee;
return tokenFee.gasFee;
}
}
createOrder({ pair, price, amount, fee, side }) {
this.validateOrder(price, amount, fee, side);
createOrder({ pair, price, amount, feeByJoy, side }) {
const [base, quote]= this.tokenManager.getPair(pair);
if (!base || !quote || base !== this.tokenManager.eth) {
throw new Error('invalid pair');
}
let quoteAmount = new BigNumber(amount);
this.validatePair(base, quote);
this.validateOrder(price, amount, side, quote);
let baseAmount = new BigNumber(amount);
let method = side === 'buy' ? 'ceil' : 'floor';
let baseAmount = this.toAmountByPrice(base, quoteAmount, price, method);
let quoteAmount = this.toAmountByPrice(quote, baseAmount, price, method);
if (!this.toPrice(baseAmount, quoteAmount).equals(price)) {
method = method === 'floor' ? 'ceil' : 'floor';
baseAmount = this.toAmountByPrice(base, quoteAmount, price, method);
quoteAmount = this.toAmountByPrice(quote, baseAmount, price, method);
if (!this.toPrice(baseAmount, quoteAmount).equals(price)) {

@@ -287,9 +328,9 @@ throw new Error('invalid amount, too small');

}
baseAmount = this.tokenManager.toRawAmount(base, baseAmount);
quoteAmount = this.tokenManager.toRawAmount(quote, quoteAmount);
baseAmount = this.tokenManager.toRawAmount(base, baseAmount);
let takerFee, makerFee, tokenFee, feePrice, custom = false;
if (quote.taker_fee && quote.maker_fee) {
takerFee = quote.taker_fee;
makerFee = quote.maker_fee;
if (base.taker_fee && base.maker_fee) {
takerFee = base.taker_fee;
makerFee = base.maker_fee;
custom = true;

@@ -301,3 +342,3 @@ } else {

if (fee === 'joy') {
if (feeByJoy) {
tokenFee = this.tokenManager.joy;

@@ -308,5 +349,21 @@ if (!custom) {

}
feePrice = tokenFee.price.mul(10000000).truncated();
if (feePrice.gt(100000000)) {
feePrice = new BigNumber(100000000);
feePrice = tokenFee.price;
let maxFeePrice, offset;
if (quote === this.tokenManager.eth) {
maxFeePrice = ETH_MAX_FEE_PRICE;
offset = new BigNumber('10000000');
} else {
const priceToEth = quote.price;
if (feePrice && priceToEth) {
const decimalsOffset = new BigNumber(10).pow(tokenFee.decimals - quote.decimals);
offset = new BigNumber('1000000000000').div(decimalsOffset);
feePrice = new BigNumber(feePrice).div(priceToEth);
} else {
throw new Error('fee price invalid');
}
maxFeePrice = NON_ETH_MAX_FEE_PRICE;
}
feePrice = feePrice.mul(offset).truncated();
if (feePrice.gt(maxFeePrice)) {
feePrice = maxFeePrice;
} else if (feePrice.lt(1)) {

@@ -316,9 +373,14 @@ feePrice = new BigNumber(1);

} else {
tokenFee = this.tokenManager.eth;
tokenFee = quote;
feePrice = 0;
}
const gasFee = this.receivableGasFee(side, fee, tokenFee);
const gasFee = this.receivableGasFee(side, feeByJoy, tokenFee, quote);
let amountSell, amountBuy, tokenSell, tokenBuy;
if (side === 'buy') {
amountSell = quoteAmount;
amountBuy = baseAmount;
tokenSell = quote.address;
tokenBuy = base.address;
} else {
amountSell = baseAmount;

@@ -328,22 +390,35 @@ amountBuy = quoteAmount;

tokenBuy = quote.address;
} else {
amountSell = quoteAmount;
amountBuy = baseAmount;
tokenSell = quote.address;
tokenBuy = base.address;
}
const createHash = (nonce) => {
let data = _.padStart(nonce.toString(16), 8, '0');
data += _.padStart(takerFee.toString(16), 4, '0');
data += _.padStart(makerFee.toString(16), 4, '0');
data += _.padStart(feePrice.toString(16), 7, '0');
data += side === 'buy' ? '1' : '0';
let input;
if (quote === this.tokenManager.eth) {
let data = _.padStart(nonce.toString(16), 8, '0');
data += _.padStart(takerFee.toString(16), 4, '0');
data += _.padStart(makerFee.toString(16), 4, '0');
data += _.padStart(feePrice.toString(16), 7, '0');
data += side === 'buy' ? '1' : '0';
let input = this.system.contract.substr(2);
input += _.padStart(amountSell.toString(16), 64, '0');
input += _.padStart(amountBuy.toString(16), 64, '0');
input += _.padStart(gasFee.toString(16), 64, '0');
input += data;
input += quote.address.substr(2);
input = this.system.contract.substr(2);
input += _.padStart(amountSell.toString(16), 64, '0');
input += _.padStart(amountBuy.toString(16), 64, '0');
input += _.padStart(gasFee.toString(16), 64, '0');
input += data;
input += base.address.substr(2);
} else {
let data = _.padStart(nonce.toString(16), 8, '0');
data += _.padStart(takerFee.toString(16), 4, '0');
data += _.padStart(makerFee.toString(16), 4, '0');
data += '0000000';
data += side === 'buy' ? '1' : '0';
input = this.system.contract.substr(2);
input += _.padStart(amountSell.toString(16), 64, '0');
input += _.padStart(amountBuy.toString(16), 64, '0');
input += _.padStart(gasFee.toString(16), 64, '0');
input += data;
input += base.address.substr(2);
input += quote.address.substr(2);
input += _.padStart(feePrice.toString(16), 64, '0');
}
return ethUtil.keccak256(new Buffer(input, 'hex'));

@@ -364,3 +439,3 @@ };

taker_fee: takerFee,
fee_price: feePrice,
fee_price: feePrice.toString(10),
token_sell: tokenSell.substr(2),

@@ -373,4 +448,5 @@ token_buy: tokenBuy.substr(2),

amount_buy: amountBuy.toString(10),
payment_method: fee,
hash: hash.toString('hex')
payment_method: feeByJoy ? 'joy' : 'base',
hash: hash.toString('hex'),
is_buy: side === 'buy'
}, vrs);

@@ -380,8 +456,6 @@ }

cancel(orderId) {
return rp(this.createRequest(`orders/${orderId}`, {
return this.request(`orders/${orderId}`, {
method: 'DELETE',
headers: {
Authorization: `Bearer ${this.accessToken}`
}
}));
auth: true
});
}

@@ -394,5 +468,3 @@

const [base, quote] = this.tokenManager.getPair(pair);
if (!base || !quote || base !== this.tokenManager.eth) {
throw new Error('invalid pair');
}
this.validatePair(base, quote);
if (this.orderBooks[pair]) {

@@ -416,5 +488,3 @@ this.orderBooks[pair].unsubscribe();

const [base, quote] = this.tokenManager.getPair(pair);
if (!base || !quote || base !== this.tokenManager.eth) {
throw new Error('invalid pair');
}
this.validatePair(base, quote);
if (this.trades[pair]) {

@@ -515,7 +585,22 @@ this.trades[pair].unsubscribe();

createRequest(path, options) {
return Object.assign({
request(path, options = {}) {
let { headers, method, auth, data = {} } = options;
delete options.data;
delete options.auth;
if (auth) {
headers = headers || {};
headers['Authorization'] = `Bearer ${this.accessToken}`;
options.headers = headers;
}
const attr = (method || 'GET').toUpperCase() == 'GET' ? 'qs' : 'body';
options[attr] = options[attr] || {};
Object.assign(options[attr], data);
options = Object.assign({
uri: `${this.apiUrl}/${path}`,
json: true
}, options);
return rp(options);
}

@@ -522,0 +607,0 @@ }

@@ -54,2 +54,3 @@ const rp = require('request-promise');

unsubscribe() {
clearTimeout(this.retryTimer);
this.cable.unsubscribe();

@@ -65,16 +66,23 @@ delete this.cable;

this.requesting = this.requestId;
clearTimeout(this.retryTimer);
const after = this.trades.length ? this.trades[0].id : null;
const json = await this.get(after);
const trades = this.convert(json.trades, true);
if (after) {
this.trades.unshift(...trades);
} else {
this.trades = trades;
}
this.onReceived(this.trades);
if (this.requesting !== this.requestId) {
try {
const json = await this.get(after);
const trades = this.convert(json.trades, true);
if (after) {
this.trades.unshift(...trades);
} else {
this.trades = trades;
}
this.onReceived(this.trades);
if (this.requesting !== this.requestId) {
this.requesting = 0;
this.update();
} else {
this.requesting = 0;
}
} catch (e) {
console.log(e);
this.requesting = 0;
this.update();
} else {
this.requesting = 0;
this.retryTimer = setTimeout(() => this.update(), 5000);
}

@@ -85,7 +93,7 @@ }

return trades.map(trade => {
const base = this.client.tokenManager.addressMap[`0x${trade.token_base}`],
quote = this.client.tokenManager.addressMap[`0x${trade.token_target}`],
const quote = this.client.tokenManager.addressMap[`0x${trade.token_base}`],
base = this.client.tokenManager.addressMap[`0x${trade.token_target}`],
tokenFee = this.client.tokenManager.addressMap[`0x${trade.token_fee}`],
baseAmount = this.client.tokenManager.toAmount(base, trade.amount_base),
quoteAmount = this.client.tokenManager.toAmount(quote, trade.amount_target),
baseAmount = this.client.tokenManager.toAmount(base, trade.amount_target),
quoteAmount = this.client.tokenManager.toAmount(quote, trade.amount_base),
gasFee = this.client.tokenManager.toAmount(tokenFee, trade.gas_fee),

@@ -98,4 +106,4 @@ txFee = this.client.tokenManager.toAmount(tokenFee, trade.tx_fee);

side: trade.is_buy ? 'sell' : 'buy',
price: baseAmount.div(quoteAmount).round(9).toNumber(),
amount: quoteAmount,
price: quoteAmount.div(baseAmount).round(9).toNumber(),
amount: baseAmount,
pair: `${base.symbol}_${quote.symbol}`,

@@ -111,8 +119,8 @@ fee: tokenFee.symbol,

get(after = null) {
return rp(this.client.createRequest('trades/mine', {
qs: {
return this.client.request('trades/mine', {
data: {
user: this.address.substr(2),
after: after
}
}));
});
}

@@ -119,0 +127,0 @@ }

@@ -17,4 +17,4 @@ const rp = require('request-promise');

contract: this.client.system.contract.substr(2),
base: this.base.address.substr(2),
token: this.quote.address.substr(2)
token: this.base.address.substr(2),
base: this.quote.address.substr(2)
}, {

@@ -41,2 +41,3 @@ connected: () => this.update(),

unsubscribe() {
clearTimeout(this.retryTimer);
this.cable.unsubscribe();

@@ -48,10 +49,16 @@ delete this.cable;

async update() {
const json = await this.get();
['buy', 'sell'].forEach(t => {
Object.keys(json[t]).forEach(k => {
json[t][k] = new BigNumber(json[t][k]);
try {
clearTimeout(this.retryTimer);
const json = await this.get();
['buy', 'sell'].forEach(t => {
Object.keys(json[t]).forEach(k => {
json[t][k] = new BigNumber(json[t][k]);
});
});
});
this.orderBook = json;
this.notify();
this.orderBook = json;
this.notify();
} catch (e) {
console.log(e);
this.retryTimer = setTimeout(() => this.update(), 5000);
}
}

@@ -73,15 +80,15 @@

convert(key, amount) {
const quote = this.client.tokenManager.toAmount(this.quote, amount);
const base = this.client.tokenManager.toAmount(this.base, amount);
const price = parseFloat(key);
return { price, amount: quote };
return { price, amount: base };
}
get() {
return rp(this.client.createRequest('orders', {
qs: {
return this.client.request('orders', {
data: {
contract: this.client.system.contract.substr(2),
base: this.base.address.substr(2),
token: this.quote.address.substr(2)
token: this.base.address.substr(2),
base: this.quote.address.substr(2)
}
}));
});
}

@@ -88,0 +95,0 @@ }

@@ -52,2 +52,3 @@ const rp = require('request-promise');

unsubscribe() {
clearTimeout(this.retryTimer);
this.cable.unsubscribe();

@@ -63,16 +64,23 @@ delete this.cable;

this.requesting = this.requestId;
clearTimeout(this.retryTimer);
const after = this.orders.length ? this.orders[0].id : null;
const result = await this.get(after);
const orders = this.convert(result.orders);
if (after) {
this.orders.unshift(...orders);
} else {
this.orders = orders;
}
this.onReceived(this.orders);
if (this.requesting !== this.requestId) {
try {
const result = await this.get(after);
const orders = this.convert(result.orders);
if (after) {
this.orders.unshift(...orders);
} else {
this.orders = orders;
}
this.onReceived(this.orders);
if (this.requesting !== this.requestId) {
this.requesting = 0;
this.update();
} else {
this.requesting = 0;
}
} catch (e) {
console.log(e);
this.requesting = 0;
this.update();
} else {
this.requesting = 0;
this.retryTimer = setTimeout(() => this.update(), 5000);
}

@@ -87,3 +95,3 @@ }

amountBuy = this.client.tokenManager.toAmount(tokenBuy, o.amount_buy);
const [base, quote] = o.is_buy ? [tokenSell, tokenBuy] : [tokenBuy, tokenSell];
const [quote, base] = o.is_buy ? [tokenSell, tokenBuy] : [tokenBuy, tokenSell];
return {

@@ -95,3 +103,3 @@ id: o.id,

amount: o.is_buy ? amountBuy : amountSell,
fill: this.client.tokenManager.toAmount(quote, o.amount_fill),
fill: this.client.tokenManager.toAmount(base, o.amount_fill),
pair: `${base.symbol}_${quote.symbol}`

@@ -103,4 +111,4 @@ };

get(after = null) {
return rp(this.client.createRequest('orders/mine', {
qs: {
return this.client.request('orders/mine', {
data: {
contract: this.client.system.contract.substr(2),

@@ -110,3 +118,3 @@ user: this.address.substr(2),

}
}));
});
}

@@ -113,0 +121,0 @@ }

@@ -0,12 +1,29 @@

const EventEmitter = require('events');
const rp = require('request-promise');
class System {
class System extends EventEmitter {
constructor(client) {
super();
this.client = client;
}
subscribe() {
connect() {
if (this.cable) {
return Promise.reject();
}
const promise = new Promise((resolve, reject) => {
const timer = setTimeout(() => reject(new Error('timeout')), 15000);
this.once('update', () => {
clearTimeout(timer);
resolve();
});
this.once('error', e => {
clearTimeout(timer);
reject(e);
});
});
this.cable = this.client.cable.subscriptions.create({
channel: 'SystemChannel'
}, {
connected: () => this.update(),
received: data => {

@@ -20,5 +37,7 @@ switch (data.e) {

});
return promise;
}
unsubscribe() {
destroy() {
clearTimeout(this.retryTimer);
this.cable.unsubscribe();

@@ -29,6 +48,13 @@ delete this.cable;

async update() {
const json = await rp(this.client.createRequest('system'));
this.contract = `0x${json.contracts[0]}`;
this.updateConfig(json);
return json;
try {
clearTimeout(this.retryTimer);
const json = await this.client.request('system');
this.connected = true;
this.contract = `0x${json.contracts[0]}`;
this.updateConfig(json);
return json;
} catch (e) {
this.emit('error', e);
this.retryTimer = setTimeout(() => this.update(), 5000);
}
}

@@ -41,2 +67,3 @@

this.withdrawable = json.withdrawable;
this.emit('update', json);
}

@@ -43,0 +70,0 @@ }

const BigNumber = require('bignumber.js');
class TokenManager {
constructor(client, tokens) {
constructor(client, options) {
this.client = client;
this.reload(tokens);
this.reload(options);
}

@@ -17,3 +17,2 @@

case 'update':
console.log(data.e);
const token = this.addressMap[`0x${data.data.address}`];

@@ -42,10 +41,12 @@ if (token) {

const json = await this.client.system.update();
this.reload(json.tokens);
if (json) {
this.reload(json);
}
}
reload(tokens) {
this.tokens = tokens;
reload(json) {
this.tokens = json.tokens;
this.symbolMap = {};
this.addressMap = {};
tokens.forEach(t => {
json.tokens.forEach(t => {
t.address = `0x${t.address}`;

@@ -62,5 +63,19 @@ if (t.price) {

this.joy = this.symbolMap.JOY;
this.quotes = json.quotes.map(t => {
const token = this.addressMap[`0x${t.address}`];
token.precision = t.precision;
return token;
});
this.hiddenPairs = {};
Object.keys(json.hidden_pairs).forEach(quote => {
json.hidden_pairs[quote].forEach(base => {
this.hiddenPairs[`${base}_${quote}`] = true;
});
});
}
getPair(pair) {
if (this.hiddenPairs[pair]) {
return [];
}
let [base, quote] = pair.split('_');

@@ -67,0 +82,0 @@ return [this.symbolMap[base], this.symbolMap[quote]];

@@ -20,4 +20,4 @@ const rp = require('request-promise');

contract: this.client.system.contract.substr(2),
base: this.base.address.substr(2),
token: this.quote.address.substr(2)
token: this.base.address.substr(2),
base: this.quote.address.substr(2)
}, {

@@ -33,2 +33,3 @@ connected: () => this.update(),

unsubscribe() {
clearTimeout(this.retryTimer);
this.cable.unsubscribe();

@@ -44,16 +45,23 @@ delete this.cable;

this.requesting = this.requestId;
clearTimeout(this.retryTimer);
const after = this.trades.length ? this.trades[0].id : null;
const json = await this.get(after);
const trades = this.convert(json.trades, false);
if (after) {
this.trades.unshift(...trades);
} else {
this.trades = trades;
}
this.onReceived(this.trades);
if (this.requesting !== this.requestId) {
try {
const json = await this.get(after);
const trades = this.convert(json.trades, false);
if (after) {
this.trades.unshift(...trades);
} else {
this.trades = trades;
}
this.onReceived(this.trades);
if (this.requesting !== this.requestId) {
this.requesting = 0;
this.update();
} else {
this.requesting = 0;
}
} catch (e) {
console.log(e);
this.requesting = 0;
this.update();
} else {
this.requesting = 0;
this.retryTimer = setTimeout(() => this.update(), 5000);
}

@@ -64,11 +72,11 @@ }

return trades.map(trade => {
const base = this.client.tokenManager.addressMap[`0x${trade.token_base}`],
quote = this.client.tokenManager.addressMap[`0x${trade.token_target}`],
baseAmount = this.client.tokenManager.toAmount(base, trade.amount_base),
quoteAmount = this.client.tokenManager.toAmount(quote, trade.amount_target);
const quote = this.client.tokenManager.addressMap[`0x${trade.token_base}`],
base = this.client.tokenManager.addressMap[`0x${trade.token_target}`],
baseAmount = this.client.tokenManager.toAmount(base, trade.amount_target),
quoteAmount = this.client.tokenManager.toAmount(quote, trade.amount_base);
return {
id: trade.id,
side: trade.is_buy ? 'sell' : 'buy',
price: baseAmount.div(quoteAmount).round(9).toNumber(),
amount: quoteAmount,
price: quoteAmount.div(baseAmount).round(9).toNumber(),
amount: baseAmount,
pair: `${base.symbol}_${quote.symbol}`,

@@ -81,9 +89,9 @@ timestamp: trade.timestamp

get(after = null) {
return rp(this.client.createRequest('trades', {
qs: {
base: this.base.address.substr(2),
token: this.quote.address.substr(2),
return this.client.request('trades', {
data: {
token: this.base.address.substr(2),
base: this.quote.address.substr(2),
after: after
}
}));
});
}

@@ -90,0 +98,0 @@ }

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc