137 lines
3.8 KiB
JavaScript
137 lines
3.8 KiB
JavaScript
import {FixedNumber} from "ethers";
|
|
import {usePrefStore, useStore} from "@/store/store.js";
|
|
import {token} from "@/blockchain/token.js";
|
|
|
|
export class SingletonCoroutine {
|
|
constructor(f, delay=10, retry=true) {
|
|
this.f = f
|
|
this.delay = delay
|
|
this.timeout = null
|
|
this.args = null
|
|
}
|
|
|
|
pending() {
|
|
return this.timeout !== null
|
|
}
|
|
|
|
invoke(/*arguments*/) {
|
|
this.args = arguments
|
|
// console.log('invoke', arguments)
|
|
if( this.timeout === null )
|
|
this.timeout = setTimeout(this.onTimeout, this.delay, this)
|
|
}
|
|
|
|
async onTimeout(self) {
|
|
try {
|
|
await self.f(...self.args)
|
|
}
|
|
catch (e) {
|
|
if( self.retry ) {
|
|
console.log('retrying', this.f, 'due to error', e)
|
|
self.timeout = null
|
|
self.invoke(self.args)
|
|
}
|
|
else
|
|
console.error(e)
|
|
}
|
|
finally {
|
|
self.timeout = null
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
export const vAutoSelect = {
|
|
beforeMount: (el) => {
|
|
const input = el.querySelector('input')
|
|
input.onfocus = () => setTimeout(() => input.select(), 0)
|
|
}
|
|
}
|
|
export const uint32max = 4294967295n
|
|
export const uint64max = 18446744073709551615n
|
|
|
|
export function tokenNumber(token, balance) {
|
|
return FixedNumber.fromValue(balance, token.decimals, {decimals:token.decimals, width: 256})
|
|
}
|
|
|
|
export function tokenFloat(token, balance) {
|
|
return tokenNumber(token,balance).toUnsafeFloat()
|
|
}
|
|
|
|
export function routeInverted(route) {
|
|
const s = useStore()
|
|
return route && (route.token0 === s.tokenA) === s.inverted
|
|
}
|
|
|
|
export function intervalString(seconds) {
|
|
if( seconds < 1 )
|
|
return 'now'
|
|
else if( seconds < 60 )
|
|
return `${seconds} seconds`
|
|
else if( seconds < 3600 )
|
|
return `${(seconds/60).toFixed(1)} minutes`
|
|
else if( seconds < 86400 )
|
|
return `${(seconds/3600).toFixed(1)} hours`
|
|
else
|
|
return `${(seconds/86400).toFixed(1)} days`
|
|
}
|
|
|
|
const _dateFormat = new Intl.DateTimeFormat( undefined, {dateStyle: 'medium', timeStyle: 'short'})
|
|
export function dateString(seconds) {
|
|
const date = new Date(seconds*1000)
|
|
return _dateFormat.format(date)
|
|
}
|
|
|
|
|
|
export function timestamp(date=null) {
|
|
if(date===null)
|
|
date = new Date()
|
|
return Math.round(date.getTime() / 1000)
|
|
}
|
|
|
|
|
|
export function pairKey(tokenA, tokenB) {
|
|
const token0 = tokenA.a < tokenB.a ? tokenA.a : tokenB.a
|
|
const token1 = tokenA.a > tokenB.a ? tokenA.a : tokenB.a
|
|
return [token0, token1];
|
|
}
|
|
|
|
|
|
export function pairPriceAddr(baseTokenAddr, quoteTokenAddr, price) {
|
|
const baseToken = token(baseTokenAddr)
|
|
const quoteToken = token(quoteTokenAddr)
|
|
if( !baseToken || !quoteToken )
|
|
return null
|
|
return pairPrice(baseToken, quoteToken, price)
|
|
}
|
|
|
|
|
|
export function pairPrice(baseToken, quoteToken, price, decimals=null) {
|
|
if( price === null || price === undefined )
|
|
return price
|
|
if( decimals === null )
|
|
decimals = baseToken.decimals-quoteToken.decimals
|
|
console.log('pairPrice', baseToken, quoteToken, price, decimals)
|
|
if( decimals >= 0 )
|
|
price /= 10 ** decimals
|
|
else
|
|
price *= 10 ** -decimals
|
|
const invertedKey = pairKey(baseToken, quoteToken);
|
|
const prefs = usePrefStore()
|
|
if( !(invertedKey in prefs.inverted) ) {
|
|
// todo prefer stablecoins as the quote asset
|
|
prefs.inverted[invertedKey] = false
|
|
}
|
|
if( prefs.inverted[invertedKey] )
|
|
price = 1/price
|
|
return price
|
|
}
|
|
|
|
export const sleep = ms => new Promise(r => setTimeout(r, ms))
|
|
|
|
export function builderDefaults(builder, defaults) {
|
|
for (const k in defaults)
|
|
if (builder[k] === undefined)
|
|
builder[k] = defaults[k] instanceof Function ? defaults[k]() : defaults[k]
|
|
}
|