@alcorexchange/alcor-swap-sdk
Version:
**npm** ``` npm i @alcorexchange/alcor-swap-sdk ``` **yarn** ``` yarn add @alcorexchange/alcor-swap-sdk ``` ## Usage ### Import:
151 lines (148 loc) • 6.21 kB
JavaScript
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); }
import { decode, encode } from "@msgpack/msgpack";
import invariant from 'tiny-invariant';
import { Price } from './fractions';
import { Token } from './token';
import { Pool } from './pool';
/**
* Represents a list of pools through which a swap can occur
* @template TInput The input token
* @template TOutput The output token
*/
export let 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);
invariant(pools.length > 0, 'POOLS');
const wrappedInput = input;
invariant(pools[0].involvesToken(wrappedInput), 'INPUT');
invariant(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];
invariant(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 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.toBuffer(pool);
}
}),
input: Token.toJSON(route.input),
output: 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.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.fromBuffer(bytes);
}
});
const input = Token.fromJSON(json.input);
const output = 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 encode(json);
}
}, {
key: "fromBuffer",
value: function fromBuffer(buffer) {
const json = 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.toBuffer(pool);
}
}),
input: Token.toJSON(route.input),
output: Token.toJSON(route.output),
_midPrice: route._midPrice
};
return encode(json);
}
}]);
}();