import { createModule , action , mutation } from "vuex-class-component" ; import { ProposedConvertTransaction , LiquidityParams , OpposingLiquidParams , ModalChoice , NetworkChoice , FeeParams , NewOwnerParams , HistoryRow , ProposedToTransaction , ProposedFromTransaction , ModuleParam , UserPoolBalances , OpposingLiquid , PoolTokenPosition , ViewRelay , ViewToken , LiquidityModule , ConvertReturn } from "@/types/bancor" ; import { vxm , store } from "@/store" ; import { compareString , updateArray , fetchBinanceUsdPriceOfBnt } from "@/api/helpers" ; import { defaultModule } from "@/router" ; interface BntPrice { price : null | number ; lastChecked : number ; } const VuexModule = createModule ( { strict : false } ) ; interface RootParam { initialModuleParam ? : ModuleParam ; initialChain ? : string ; } const moduleIds = [ { label : "EOS" , id : "eos" } , { label : "ETH" , id : "eth" } ] ; interface Module { id : string ; label : string ; loading : boolean ; loaded : boolean ; error : boolean ; } const slippageTolerance = "SLIPPAGE_TOLERANCE" ; export class BancorModule extends VuexModule . With ( { namespaced : "bancor/" } ) { usdPriceOfBnt : BntPrice = { price : null , lastChecked : 0 } ; modules : Module [ ] = moduleIds . map ( ( { id , label } ) => ( { id , label , loading : false , loaded : false , error : false } ) ) ; slippageTolerance = 0.005 ; @ mutation setTolerance ( tolerance ) { this . slippageTolerance = tolerance ; } @ action async setSlippageTolerance ( tolerance ) { this . setTolerance ( tolerance ) ; localStorage . setItem ( slippageTolerance , String ( tolerance ) ) ; } get currentNetwork ( ) { if ( store . state . routeModule && store . state . routeModule . params && store . state . routeModule . params . service ) { return store . state . routeModule . params . service ; } else { return defaultModule ; } } get liquidityHistory ( ) : LiquidityModule [ "liquidityHistory" ] { return vxm [ `${ this . currentNetwork }Bancor` ] [ "liquidityHistory" ] ; } get tokens ( ) : ViewToken [ ] { return vxm [ `${ this . currentNetwork }Bancor` ] [ "tokens" ] ; } get supportedFeatures ( ) { return vxm [ `${ this . currentNetwork }Bancor` ] [ "supportedFeatures" ] ; } get token ( ) : ( tokenId : string ) => ViewToken { return vxm [ `${ this . currentNetwork }Bancor` ] [ "token" ] ; } get relays ( ) : ViewRelay [ ] { return vxm [ `${ this . currentNetwork }Bancor` ] [ "relays" ] ; } get moreTokensAvailable ( ) { return vxm [ `${ this . currentNetwork }Bancor` ] [ "moreTokensAvailable" ] ; } get tokenBalance ( ) { return vxm [ `${ this . currentNetwork }Bancor` ] [ "tokenBalance" ] ; } get loadingTokens ( ) { return vxm [ `${ this . currentNetwork }Bancor` ] [ "loadingTokens" ] ; } get newPoolTokenChoices ( ) : ( networkTokenSymbol : string ) => ModalChoice [ ] { return vxm [ `${ this . currentNetwork }Bancor` ] [ "newPoolTokenChoices" ] ; } get newNetworkTokenChoices ( ) : NetworkChoice [ ] { return vxm [ `${ this . currentNetwork }Bancor` ] [ "newNetworkTokenChoices" ] ; } get relay ( ) { return vxm [ `${ this . currentNetwork }Bancor` ] [ "relay" ] ; } get primaryReserveChoices ( ) { return vxm [ `${ this . currentNetwork }Bancor` ] [ "primaryReserveChoices" ] ; } get secondaryReserveChoices ( ) { return vxm [ `${ this . currentNetwork }Bancor` ] [ "secondaryReserveChoices" ] ; } get morePoolsAvailable ( ) { return vxm [ `${ this . currentNetwork }Bancor` ] [ "morePoolsAvailable" ] ; } get loadingPools ( ) { return vxm [ `${ this . currentNetwork }Bancor` ] [ "loadingPools" ] ; } get wallet ( ) { return vxm [ `${ this . currentNetwork }Bancor` ] [ "wallet" ] ; } get stats ( ) : LiquidityModule [ "stats" ] { return vxm [ `${ this . currentNetwork }Bancor` ] [ "stats" ] ; } get poolTokenPositions ( ) : PoolTokenPosition [ ] { return vxm [ `${ this . currentNetwork }Bancor` ] [ "poolTokenPositions" ] ; } @ mutation updateModule ( { id , updater } ) { const newModules = updateArray ( this . modules , module => compareString ( id , module . id ) , updater ) ; this . modules = newModules ; } @ action async moduleInitialised ( id ) { this . updateModule ( { id , updater : module => ( { ... module , loaded : true , loading : false , error : false } ) } ) ; } @ action async moduleThrown ( id ) { this . updateModule ( { id , updater : module => ( { ... module , loaded : false , loading : false , error : true } ) } ) ; } @ action async moduleInitalising ( id ) { this . updateModule ( { id , updater : module => ( { ... module , loading : true } ) } ) ; } @ action async initialiseModule ( { moduleId , params , resolveWhenFinished = false } ) { this . moduleInitalising ( moduleId ) ; const tolerance = localStorage . getItem ( slippageTolerance ) ; if ( tolerance ) { this . setTolerance ( Number ( tolerance ) ) ; } if ( resolveWhenFinished ) { try { await this . $store . dispatch ( `${ moduleId }Bancor/init` , params || null , { root : true } ) ; this . moduleInitialised ( moduleId ) ; } catch ( e ) { this . moduleThrown ( moduleId ) ; } } else { try { this . $store . dispatch ( `${ moduleId }Bancor/init` , params || null , { root : true } ) . then ( ( ) => this . moduleInitialised ( moduleId ) ) ; } catch ( e ) { this . moduleThrown ( moduleId ) ; } } } @ action async init ( param ? ) { if ( param && param . initialChain && param . initialModuleParam ) { return this . initialiseModule ( { moduleId : param . initialChain , params : param . initialModuleParam , resolveWhenFinished : true } ) ; } else { return Promise . all ( this . modules . map ( module => module . id ) . map ( moduleId => this . initialiseModule ( { moduleId , resolveWhenFinished : moduleId == "eth" } ) ) ) ; } } @ action async getUsdPrice ( ) { try { const usdPrice = await fetchBinanceUsdPriceOfBnt ( ) ; this . setUsdPriceOfBnt ( { price : usdPrice , lastChecked : Date . now ( ) } ) ; return usdPrice ; } catch ( e ) { throw new Error ( `Failed to find USD Price of BNT from External API & Relay ${ e . message }` ) ; } } @ action async fetchUsdPriceOfBnt ( ) { const timeNow = new Date ( ) . getTime ( ) ; const millisecondGap = 5000 ; const makeNetworkRequest = ! this . usdPriceOfBnt . lastChecked || this . usdPriceOfBnt . lastChecked + millisecondGap < timeNow ; return makeNetworkRequest ? this . getUsdPrice ( ) : ( this . usdPriceOfBnt . price as number ) ; } @ mutation setUsdPriceOfBnt ( usdPriceOfBnt ) { this . usdPriceOfBnt = usdPriceOfBnt ; } @ action async fetchHistoryData ( relayId ) { return this . dispatcher ( [ "fetchHistoryData" , relayId ] ) ; } @ action async convert ( tx ) { return this . dispatcher ( [ "convert" , tx ] ) ; } @ action async updateFee ( fee ) { return this . dispatcher ( [ "updateFee" , fee ] ) ; } @ action async loadMorePools ( ) { return this . dispatcher ( [ "loadMorePools" ] ) ; } @ action async removeRelay ( symbolName ) { return this . dispatcher ( [ "removeRelay" , symbolName ] ) ; } @ action async updateOwner ( owner ) { return this . dispatcher ( [ "updateOwner" , owner ] ) ; } @ action async getUserBalances ( relayId ) { return this . dispatcher ( [ "getUserBalances" , relayId ] ) ; } @ action async createPool ( newPoolParams ) { return this . dispatcher ( [ "createPool" , newPoolParams ] ) ; } @ action async getCost ( proposedTransaction ) { return this . dispatcher ( [ "getCost" , proposedTransaction ] ) ; } @ action async getReturn ( proposedTransaction ) { return this . dispatcher ( [ "getReturn" , proposedTransaction ] ) as Promise < ConvertReturn > ; } @ action async addLiquidity ( addLiquidityParams ) { return this . dispatcher ( [ "addLiquidity" , addLiquidityParams ] ) ; } @ action async removeLiquidity ( removeLiquidityParams ) { return this . dispatcher ( [ "removeLiquidity" , removeLiquidityParams ] ) ; } @ action async calculateOpposingDeposit ( opposingDeposit ) { return this . dispatcher ( [ "calculateOpposingDeposit" , opposingDeposit ] ) ; } @ action async calculateOpposingWithdraw ( opposingWithdraw ) { return this . dispatcher ( [ "calculateOpposingWithdraw" , opposingWithdraw ] ) ; } @ action async focusSymbol ( symbolName ) { return this . dispatcher ( [ "focusSymbol" , symbolName ] ) ; } @ action async dispatcher ( [ methodName , params ] ) { return params ? this . $store . dispatch ( `${ this . currentNetwork }Bancor/${ methodName }` , params , { root : true } ) : this . $store . dispatch ( `${ this . currentNetwork }Bancor/${ methodName }` , null , { root : true } ) ; } @ action async refreshBalances ( symbols = [ ] ) { if ( vxm . wallet . currentUser ) { return this . dispatcher ( [ "refreshBalances" , symbols ] ) ; } } @ action async checkPriceDeviationTooHigh ( { relayId , selectedTokenAddress } ) { return this . dispatcher ( [ "checkPriceDeviationTooHigh" , { relayId , selectedTokenAddress } ] ) ; } }