crypto-client
Version:
An unified client for all cryptocurrency exchanges.
179 lines (178 loc) • 6.33 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.signDataOrder = exports.signData = exports.sort = exports.signOrder = exports.getKeys = void 0;
// forked from https://github.com/WhaleEx/API/blob/master/sample/nodejs/whaleex-sign.js
const assert_1 = require("assert");
const crypto_1 = __importDefault(require("crypto"));
const eos_utils_1 = require("eos-utils");
const eosjs_ecc_1 = require("eosjs-ecc");
const long_1 = __importDefault(require("long"));
const mathjs_1 = require("mathjs");
const config_1 = require("../config");
const math = mathjs_1.create(mathjs_1.all, {
number: 'BigNumber',
precision: 64,
});
const WHALEEX_EOS_ACCOUNT = 'whaleexchang';
function defaultHandler(params) {
return Object.assign({ timestamp: Date.now(), APIKey: config_1.USER_CONFIG.WHALEEX_API_KEY, pk: eosjs_ecc_1.privateToPublic(config_1.USER_CONFIG.eosPrivateKey) }, params);
}
const HANDLER = {
'/api/v1/order/orders': defaultHandler,
'/api/auth/pk/status': (params) => {
return Object.assign({ pk: eosjs_ecc_1.privateToPublic(config_1.USER_CONFIG.eosPrivateKey) }, params);
},
'/api/v1/order/matchresults': defaultHandler,
default: defaultHandler,
};
// Pack all kinds of data into a binary buffer.
class Packer {
constructor() {
this.buf = Buffer.alloc(0);
}
updateStr(str) {
this.buf = Buffer.concat([this.buf, Buffer.from(str)]);
return this;
}
updateInt8(i) {
const tmp = Buffer.alloc(1);
tmp.writeInt8(i, 0);
this.buf = Buffer.concat([this.buf, tmp]);
return this;
}
updateInt16(i) {
const tmp = Buffer.alloc(2);
tmp.writeInt16LE(i, 0);
this.buf = Buffer.concat([this.buf, tmp]);
return this;
}
updateInt32(i) {
const tmp = Buffer.alloc(4);
tmp.writeInt32LE(i, 0);
this.buf = Buffer.concat([this.buf, tmp]);
return this;
}
updateInt64(str) {
const long = long_1.default.fromString(str, 10);
this.buf = Buffer.concat([this.buf, Buffer.from(long.toBytesLE())]);
return this;
}
finalize() {
return this.buf;
}
clear() {
this.buf = Buffer.alloc(0);
}
}
function getHandle(path) {
return HANDLER[path] || HANDLER.default;
}
function getHash() {
return crypto_1.default.createHash('sha256');
}
function multiply(m, n, decimal, ceil = false) {
const result = math.evaluate(`${m} * ${n} * ${10 ** decimal}`);
if (ceil) {
return String(Math.ceil(result));
}
return String(result).split('.')[0];
}
function getKeys() {
assert_1.strict.ok(config_1.USER_CONFIG.eosPrivateKey);
assert_1.strict.ok(config_1.USER_CONFIG.WHALEEX_API_KEY);
return {
privateKey: config_1.USER_CONFIG.eosPrivateKey,
publicKey: eosjs_ecc_1.privateToPublic(config_1.USER_CONFIG.eosPrivateKey),
APIKey: config_1.USER_CONFIG.WHALEEX_API_KEY,
};
}
exports.getKeys = getKeys;
function signOrder(post, timestamp, symbolObj) {
const { baseToken = 'IQ', quoteToken = 'EOS', basePrecision = 3, quotePrecision = eos_utils_1.EOS_QUANTITY_PRECISION, baseContract, quoteContract, } = symbolObj;
// "IQ/EOS for example"
const pack = new Packer();
pack
.updateStr(config_1.USER_CONFIG.eosAccount)
.updateStr(WHALEEX_EOS_ACCOUNT)
.updateInt64(post.orderId.toString())
.updateInt32(Math.floor(timestamp / 1000));
const price = parseFloat(post.price);
const quantity = parseFloat(post.amount);
if (post.type === 'buy-limit') {
pack
.updateStr(quoteContract)
.updateStr(quoteToken)
.updateInt64(multiply(price, quantity, quotePrecision, true))
.updateStr(baseContract)
.updateStr(baseToken)
.updateInt64(multiply(1, quantity, basePrecision));
}
if (post.type === 'sell-limit') {
pack
.updateStr(baseContract)
.updateStr(baseToken)
.updateInt64(multiply(1, quantity, basePrecision))
.updateStr(quoteContract)
.updateStr(quoteToken)
.updateInt64(multiply(price, quantity, quotePrecision));
}
if (post.type === 'buy-market') {
pack
.updateStr(quoteContract)
.updateStr(quoteToken)
.updateInt64(multiply(1, quantity, quotePrecision))
.updateStr(baseContract)
.updateStr(baseToken)
.updateInt64('0');
}
if (post.type === 'sell-market') {
pack
.updateStr(baseContract)
.updateStr(baseToken)
.updateInt64(multiply(1, quantity, basePrecision))
.updateStr(quoteContract)
.updateStr(quoteToken)
.updateInt64('0');
}
pack.updateInt16(10).updateInt16(10);
const buf = pack.finalize();
const hashData = getHash().update(buf).digest('hex');
const { privateKey } = getKeys();
const sig = eosjs_ecc_1.signHash(hashData, privateKey);
return sig;
}
exports.signOrder = signOrder;
function sort(params) {
const sb = []; // String buffer
const keys = Object.keys(params).sort();
keys.forEach((key) => {
sb.push(`${key}=${params[key]}`);
});
return sb.join('&');
}
exports.sort = sort;
function signData(method, path, params = {}) {
const { privateKey } = getKeys();
// console.log("signData", method, path, params);
const paramsStr = sort(getHandle(path)(params));
const data = `${method.toUpperCase()}\napi.whaleex.com\n${path}\n${encodeURIComponent(paramsStr)}`;
const signature = eosjs_ecc_1.sign(data, privateKey);
return `${paramsStr}&Signature=${signature}`;
}
exports.signData = signData;
function signDataOrder(order, symbolObj) {
const { APIKey, publicKey } = getKeys();
const map = {
APIKey: APIKey,
timestamp: Date.now(),
pk: publicKey,
orderId: order.orderId,
};
const paramsText = sort(map);
const signature = signOrder(order, map.timestamp, symbolObj);
return `${paramsText}&Signature=${signature}`;
}
exports.signDataOrder = signDataOrder;