UNPKG

@alcorexchange/alcor-swap-sdk

Version:

## Installation ​​ **npm** ``` npm i @alcorexchange/alcor-swap-sdk ``` **yarn** ``` yarn add @alcorexchange/alcor-swap-sdk ``` ## Usage ### Import:

163 lines (143 loc) 4.62 kB
import msgpack from "msgpack-lite" import invariant from 'tiny-invariant' import { Currency } from './currency' 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 class Route<TInput extends Currency, TOutput extends Currency> { public readonly pools: Pool[]; public readonly tokenPath: Token[]; public readonly input: TInput; public readonly output: TOutput; private _midPrice: Price<TInput, TOutput> | null = null; /** * 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 */ public constructor(pools: Pool[], input: TInput, output: TOutput) { 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: Token[] = [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 ?? tokenPath[tokenPath.length - 1]; } /** * Returns the mid price of the route */ public get midPrice(): Price<TInput, TOutput> { 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 )); } static toJSON(route: Route<Currency, Currency>, 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, }; } static fromJSON(json: any) { const pools = json.pools.map((pool) => { if (typeof pool === 'number') { return Pool.fromId(pool); } else { return Pool.fromBuffer(Buffer.from(pool)); } }); const input = Token.fromJSON(json.input); const output = Token.fromJSON(json.output); return new Route(pools, input, output); } static toBuffer( route: Route<Currency, Currency>, lightWeightVersion = false ) { const json = this.toJSON(route, lightWeightVersion); return msgpack.encode(json); } static fromBuffer(buffer: Buffer) { const json = msgpack.decode(buffer); return this.fromJSON(json); } static toBufferAdvanced(route: Route<Currency, Currency>, pools: any[]) { const json = { pools: pools.map((pool) => { if (typeof pool === 'number' || Buffer.isBuffer(pool)) { return pool; } else { return Pool.toBuffer(pool); } }), input: Token.toJSON(route.input), output: Token.toJSON(route.output), _midPrice: route._midPrice, }; return msgpack.encode(json); } public equals(other: Route<Currency, Currency>): boolean { 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); } }