@alcorexchange/alcor-swap-sdk
Version:
**npm** ``` npm i @alcorexchange/alcor-swap-sdk ``` **yarn** ``` yarn add @alcorexchange/alcor-swap-sdk ``` ## Usage ### Import:
157 lines (154 loc) • 6.63 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Route = void 0;
var _msgpack = require("@msgpack/msgpack");
var _tinyInvariant = _interopRequireDefault(require("tiny-invariant"));
var _fractions = require("./fractions");
var _token = require("./token");
var _pool = require("./pool");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
/**
* Represents a list of pools through which a swap can occur
* @template TInput The input token
* @template TOutput The output token
*/
let Route = exports.Route = /*#__PURE__*/function () {
/**
* Creates an instance of route.
* @param pools An array of `Pool` objects, ordered by the route the swap will take
* @param input The input token
* @param output The output token
*/
function Route(pools, input, output) {
_classCallCheck(this, Route);
_defineProperty(this, "pools", void 0);
_defineProperty(this, "tokenPath", void 0);
_defineProperty(this, "input", void 0);
_defineProperty(this, "output", void 0);
_defineProperty(this, "_midPrice", null);
(0, _tinyInvariant.default)(pools.length > 0, 'POOLS');
const wrappedInput = input;
(0, _tinyInvariant.default)(pools[0].involvesToken(wrappedInput), 'INPUT');
(0, _tinyInvariant.default)(pools[pools.length - 1].involvesToken(output), 'OUTPUT');
/**
* Normalizes tokenA-tokenB order and selects the next token/fee step to add to the path
* */
const tokenPath = [wrappedInput];
for (const [i, pool] of pools.entries()) {
const currentInputToken = tokenPath[i];
(0, _tinyInvariant.default)(currentInputToken.equals(pool.tokenA) || currentInputToken.equals(pool.tokenB), 'PATH');
const nextToken = currentInputToken.equals(pool.tokenA) ? pool.tokenB : pool.tokenA;
tokenPath.push(nextToken);
}
this.pools = pools;
this.tokenPath = tokenPath;
this.input = input;
this.output = output !== null && output !== void 0 ? output : tokenPath[tokenPath.length - 1];
}
/**
* Returns the mid price of the route
*/
return _createClass(Route, [{
key: "midPrice",
get: function () {
if (this._midPrice !== null) return this._midPrice;
const price = this.pools.slice(1).reduce(({
nextInput,
price
}, pool) => {
return nextInput.equals(pool.tokenA) ? {
nextInput: pool.tokenB,
price: price.multiply(pool.tokenAPrice)
} : {
nextInput: pool.tokenA,
price: price.multiply(pool.tokenBPrice)
};
}, this.pools[0].tokenA.equals(this.input) ? {
nextInput: this.pools[0].tokenB,
price: this.pools[0].tokenAPrice
} : {
nextInput: this.pools[0].tokenA,
price: this.pools[0].tokenBPrice
}).price;
return this._midPrice = new _fractions.Price(this.input, this.output, price.denominator, price.numerator);
}
}, {
key: "equals",
value: function equals(other) {
if (this.pools.length !== other.pools.length) return false;
for (let i = 0; i < this.pools.length; i++) {
if (!this.pools[i].equals(other.pools[i])) return false;
}
return this.input.equals(other.input) && this.output.equals(other.output);
}
}], [{
key: "toJSON",
value: function toJSON(route, lightWeightVersion = false) {
return {
pools: route.pools.map(pool => {
if (lightWeightVersion) {
return pool.id;
} else {
return _pool.Pool.toBuffer(pool);
}
}),
input: _token.Token.toJSON(route.input),
output: _token.Token.toJSON(route.output),
_midPrice: route._midPrice
};
}
}, {
key: "fromJSON",
value: function fromJSON(json) {
const pools = json.pools.map(pool => {
if (typeof pool === 'number') {
return _pool.Pool.fromId(pool);
} else {
const bytes = pool instanceof Uint8Array ? pool : typeof Buffer !== 'undefined' && typeof Buffer.isBuffer === 'function' && Buffer.isBuffer(pool) ? pool : pool instanceof ArrayBuffer ? new Uint8Array(pool) : pool && pool.buffer instanceof ArrayBuffer ? new Uint8Array(pool.buffer) : pool;
return _pool.Pool.fromBuffer(bytes);
}
});
const input = _token.Token.fromJSON(json.input);
const output = _token.Token.fromJSON(json.output);
return new Route(pools, input, output);
}
}, {
key: "toBuffer",
value: function toBuffer(route, lightWeightVersion = false) {
const json = this.toJSON(route, lightWeightVersion);
return (0, _msgpack.encode)(json);
}
}, {
key: "fromBuffer",
value: function fromBuffer(buffer) {
const json = (0, _msgpack.decode)(buffer);
return this.fromJSON(json);
}
}, {
key: "toBufferAdvanced",
value: function toBufferAdvanced(route, pools) {
const json = {
pools: pools.map(pool => {
const isBuffer = typeof Buffer !== 'undefined' && typeof Buffer.isBuffer === 'function' && Buffer.isBuffer(pool);
if (typeof pool === 'number' || pool instanceof Uint8Array || isBuffer) {
return pool;
} else {
return _pool.Pool.toBuffer(pool);
}
}),
input: _token.Token.toJSON(route.input),
output: _token.Token.toJSON(route.output),
_midPrice: route._midPrice
};
return (0, _msgpack.encode)(json);
}
}]);
}();