/* eslint-disable no-unused-vars */ import { parseMoveStructTag, StructTag, TypeTag, u64 } from '@manahippo/move-to-ts'; import { HexString, Types } from 'aptos'; import { App } from '../generated'; import { PriceType, QuoteType, TradingPool, TradingPoolProvider, UITokenAmount } from './types'; import bigInt from 'big-integer'; import { CoinInfo } from '../generated/coin_list/coin_list'; import { typeTagToTypeInfo } from '../utils'; export class OmniTradingPool extends TradingPool { omniPool: object | null; constructor( public ownerAddress: HexString, public _xCoinInfo: CoinInfo, public _yCoinInfo: CoinInfo, public poolResourceTag: StructTag ) { super(); this.omniPool = null; } get isRoutable(): boolean { throw true; } get xCoinInfo() { return this._xCoinInfo; } get yCoinInfo() { return this._yCoinInfo; } isStateLoaded(): boolean { return this.omniPool != undefined; } async reloadState(app: App): Promise { this.omniPool = await app.client.getAccountResource(this.ownerAddress, this.poolResourceTag.getAptosMoveTypeTag()); } getPrice(): PriceType { if (!this.omniPool) { throw new Error('Pontem pool not loaded. cannot compute price'); } throw new Error('Not Implemented'); } getQuote(inputUiAmt: UITokenAmount, isXtoY: boolean): QuoteType { if (!this.omniPool) { throw new Error('Omni pool not loaded. cannot compute quote'); } const inputTokenInfo = isXtoY ? this.xCoinInfo : this.yCoinInfo; const outputTokenInfo = isXtoY ? this.yCoinInfo : this.xCoinInfo; const coinXReserve = (this.omniPool as any).data.coin_x.value as string; const coinYReserve = (this.omniPool as any).data.coin_y.value as string; const coinInAmt = bigInt(Math.floor(inputUiAmt * Math.pow(10, inputTokenInfo.decimals.toJsNumber()))); const reserveInAmt = bigInt(isXtoY ? coinXReserve : coinYReserve); const reserveOutAmt = bigInt(isXtoY ? coinYReserve : coinXReserve); const coinOutAmt = getCoinOutWithFees(coinInAmt, reserveInAmt, reserveOutAmt); const outputUiAmt = coinOutAmt.toJSNumber() / Math.pow(10, outputTokenInfo.decimals.toJsNumber()); return { inputSymbol: inputTokenInfo.symbol.str(), outputSymbol: outputTokenInfo.symbol.str(), inputUiAmt, outputUiAmt, avgPrice: outputUiAmt / inputUiAmt }; } // build payload directly if not routable makePayload(inputUiAmt: UITokenAmount, minOutAmt: UITokenAmount): Types.EntryFunctionPayload { throw new Error('Not Implemented'); } } export class OmniPoolProvider extends TradingPoolProvider { async loadPoolList(): Promise { const poolList: TradingPool[] = []; const ownerAddress = this.netConfig.omniCoinListAddress; const resources = await this.app.client.getAccountResources(ownerAddress); for (const resource of resources) { if (resource.type.indexOf('implements::LiquidityPool') >= 0) { const tag = parseMoveStructTag(resource.type); const xTag = tag.typeParams[0] as StructTag; const yTag = tag.typeParams[1] as StructTag; //const lpTag = tag.typeParams[2] as StructTag; const xCoinInfo = this.registry.getCoinInfoByType(typeTagToTypeInfo(xTag)); const yCoinInfo = this.registry.getCoinInfoByType(typeTagToTypeInfo(yTag)); if (!xCoinInfo || !yCoinInfo) { continue; } const pool = new OmniTradingPool(ownerAddress, xCoinInfo, yCoinInfo, tag); poolList.push(pool); } } return poolList; } } export function getCoinOutWithFees( coinInVal: bigInt.BigInteger, reserveInSize: bigInt.BigInteger, reserveOutSize: bigInt.BigInteger ) { const feePct = bigInt(3); const feeScale = bigInt(1000); const feeMultiplier = feeScale.subtract(feePct); const coinInAfterFees = coinInVal.multiply(feeMultiplier); const newReservesInSize = reserveInSize.multiply(feeScale).add(coinInAfterFees); return coinInAfterFees.multiply(reserveOutSize).divide(newReservesInSize); }