bugfixes
This commit is contained in:
@@ -6,12 +6,14 @@ import {ethers} from "ethers";
|
|||||||
|
|
||||||
// synchronous version may return null but will trigger a lookup
|
// synchronous version may return null but will trigger a lookup
|
||||||
export function token(addr) {
|
export function token(addr) {
|
||||||
|
console.log('token', addr)
|
||||||
if( !addr ) {
|
if( !addr ) {
|
||||||
// console.log('ignoring call to token', addr)
|
// console.log('ignoring call to token', addr)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
if( !(addr in s.tokens) ) {
|
if( !(addr in s.tokens) ) {
|
||||||
|
// noinspection JSIgnoredPromiseFromCall
|
||||||
getToken(addr)
|
getToken(addr)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,12 +24,7 @@
|
|||||||
</suspense>
|
</suspense>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:item.avg="{ item }">
|
<template v-slot:item.avg="{ item }">
|
||||||
{{ pairPrice(item.order.tokenIn, item.order.tokenOut, item.avg) }}
|
<pair-price :base-addr="item.order.tokenIn" :quote-addr="item.order.tokenOut" :value="item.avg" :show-btn="true"/>
|
||||||
<btn v-if="pairPrice(item.order.tokenIn, item.order.tokenOut, item.avg)!==''" size="small"
|
|
||||||
variant="plain"
|
|
||||||
@click="inverted[[vaultAddr,item.index]] = !inverted[[vaultAddr,item.index]]">
|
|
||||||
{{ pair(item.order.tokenIn, item.order.tokenOut, vaultAddr, item.index) }}
|
|
||||||
</btn>
|
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:item.status="{ item }">
|
<template v-slot:item.status="{ item }">
|
||||||
<v-chip v-if="item.state===OrderState.Signing" prepend-icon="mdi-signature" color="yellow">Signing</v-chip>
|
<v-chip v-if="item.state===OrderState.Signing" prepend-icon="mdi-signature" color="yellow">Signing</v-chip>
|
||||||
@@ -101,12 +96,12 @@
|
|||||||
import {FixedNumber} from "ethers";
|
import {FixedNumber} from "ethers";
|
||||||
import {useStore} from "@/store/store";
|
import {useStore} from "@/store/store";
|
||||||
import {computed, defineAsyncComponent, reactive} from "vue";
|
import {computed, defineAsyncComponent, reactive} from "vue";
|
||||||
import {token} from "@/blockchain/token.js";
|
|
||||||
import Btn from "@/components/Btn.vue"
|
import Btn from "@/components/Btn.vue"
|
||||||
import {cancelAll, cancelOrder} from "@/blockchain/wallet.js";
|
import {cancelAll, cancelOrder} from "@/blockchain/wallet.js";
|
||||||
import {dateString} from "@/misc.js";
|
import {dateString, pairPriceAddr} from "@/misc.js";
|
||||||
import {isOpen, OrderState} from "@/blockchain/orderlib.js";
|
import {isOpen, OrderState} from "@/blockchain/orderlib.js";
|
||||||
import NewOrder from "@/components/NewOrder.vue";
|
import NewOrder from "@/components/NewOrder.vue";
|
||||||
|
import PairPrice from "@/components/PairPrice.vue";
|
||||||
|
|
||||||
const TokenAmount = defineAsyncComponent(()=>import('./TokenAmount.vue'))
|
const TokenAmount = defineAsyncComponent(()=>import('./TokenAmount.vue'))
|
||||||
|
|
||||||
@@ -116,39 +111,6 @@ const vaultAddr = computed(()=>props.vault?props.vault:s.vault)
|
|||||||
const inverted = reactive({})
|
const inverted = reactive({})
|
||||||
|
|
||||||
|
|
||||||
// todo create a Price component that keeps inversion flags in the store and defaults to stablecoins as the quote
|
|
||||||
function pairPrice(inTokenAddr, outTokenAddr, price) {
|
|
||||||
if( price === null )
|
|
||||||
return ''
|
|
||||||
const inToken = token(inTokenAddr)
|
|
||||||
const outToken = token(outTokenAddr)
|
|
||||||
if( !inToken || !outToken )
|
|
||||||
return ''
|
|
||||||
|
|
||||||
const decimals = inToken.decimals-outToken.decimals
|
|
||||||
if( decimals > 0 )
|
|
||||||
price /= 10 ** decimals
|
|
||||||
else
|
|
||||||
price *= 10 ** -decimals
|
|
||||||
const token0 = inTokenAddr < outTokenAddr ? inTokenAddr : outTokenAddr
|
|
||||||
const token1 = inTokenAddr > outTokenAddr ? inTokenAddr : outTokenAddr
|
|
||||||
const invertedKey = [token0, token1];
|
|
||||||
if( !(invertedKey in inverted) ) {
|
|
||||||
// todo prefer stablecoins as the quote asset
|
|
||||||
inverted[invertedKey] = false
|
|
||||||
}
|
|
||||||
const inv = inverted[invertedKey]
|
|
||||||
return inv ? (1 / price).toPrecision(5) : price.toPrecision(5)
|
|
||||||
}
|
|
||||||
|
|
||||||
function pair(inTokenAddr, outTokenAddr, vaultAddr, index) {
|
|
||||||
const inToken = token(inTokenAddr)
|
|
||||||
const outToken = token(outTokenAddr)
|
|
||||||
return !inToken || !outToken ? null : inverted[[vaultAddr,index]] ?
|
|
||||||
outToken.symbol+'\\'+inToken.symbol : inToken.symbol+'\\'+outToken.symbol
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// <thead>
|
// <thead>
|
||||||
// <tr>
|
// <tr>
|
||||||
// <th className="num d-none d-md-table-cell">Date</th>
|
// <th className="num d-none d-md-table-cell">Date</th>
|
||||||
@@ -233,10 +195,14 @@ const orders = computed(()=>{
|
|||||||
})
|
})
|
||||||
const fmtX18 = {decimals: 18, width: 256, signed: false};
|
const fmtX18 = {decimals: 18, width: 256, signed: false};
|
||||||
st.filled = o.amountIsInput ? st.filledIn : st.filledOut
|
st.filled = o.amountIsInput ? st.filledIn : st.filledOut
|
||||||
st.avg = BigInt(st.filled) === 0n ? null :
|
if(BigInt(st.filled) === 0n)
|
||||||
FixedNumber.fromValue(status.filledOut, 0, fmtX18)
|
st.avg = null
|
||||||
.div(FixedNumber.fromValue(status.filledIn, 0, fmtX18))
|
else {
|
||||||
.toUnsafeFloat().toPrecision(5) // todo precision
|
st.avg = FixedNumber.fromValue(status.filledOut, 0, fmtX18)
|
||||||
|
.div(FixedNumber.fromValue(status.filledIn, 0, fmtX18)).toUnsafeFloat();
|
||||||
|
if( o.tokenIn > o.tokenOut )
|
||||||
|
st.avg = 1/st.avg
|
||||||
|
}
|
||||||
st.trancheFilled = o.amountIsInput ? st.trancheFilledIn : st.trancheFilledOut
|
st.trancheFilled = o.amountIsInput ? st.trancheFilledIn : st.trancheFilledOut
|
||||||
st.amountToken = o.amountIsInput ? o.tokenIn : o.tokenOut
|
st.amountToken = o.amountIsInput ? o.tokenIn : o.tokenOut
|
||||||
st.input = o.amountIsInput ? o.amount : 0
|
st.input = o.amountIsInput ? o.amount : 0
|
||||||
@@ -270,12 +236,17 @@ function describeTrancheTime(st, isStart, t) {
|
|||||||
function describeTrancheLine(st, isMin, b, m) {
|
function describeTrancheLine(st, isMin, b, m) {
|
||||||
// todo make this a PairPrice
|
// todo make this a PairPrice
|
||||||
if( b===0 && m===0 ) return ''
|
if( b===0 && m===0 ) return ''
|
||||||
// console.log('tranche line', isMin, b, m)
|
console.log('tranche line', isMin, b, m)
|
||||||
|
const inverted = st.order.tokenIn > st.order.tokenOut
|
||||||
|
const t0 = inverted ? st.order.tokenIn : st.order.tokenOut
|
||||||
|
const t1 = !inverted ? st.order.tokenIn : st.order.tokenOut
|
||||||
if( m !== 0 ) {
|
if( m !== 0 ) {
|
||||||
const limit = b + m * s.time
|
const limit = b + m * s.time
|
||||||
return 'diagonal ' + pairPrice(st.order.tokenIn, st.order.tokenOut, limit)
|
const price = pairPriceAddr(t0, t1, limit);
|
||||||
|
return 'diagonal ' + (price === null ? null : price.toPrecision(5))
|
||||||
}
|
}
|
||||||
return (isMin === st.order.amountIsInput ? 'dont-chase ' : 'limit ') + pairPrice(st.order.tokenIn, st.order.tokenOut, b)
|
const price = pairPriceAddr(t0, t1, b)
|
||||||
|
return (isMin === st.order.amountIsInput ? 'dont-chase ' : 'limit ') + (price === null ? null : price.toPrecision(5))
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -42,11 +42,11 @@ const os = useOrderStore()
|
|||||||
|
|
||||||
const tokenA = computed({
|
const tokenA = computed({
|
||||||
get() {
|
get() {
|
||||||
return os.tokenA
|
return os.baseToken
|
||||||
},
|
},
|
||||||
set(value) {
|
set(value) {
|
||||||
if( !os.tokenA || os.tokenA.address !== value.address ) {
|
if( !os.baseToken || os.baseToken.address !== value.address ) {
|
||||||
os.tokenA = value
|
os.baseToken = value
|
||||||
routeFinder.invoke()
|
routeFinder.invoke()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ const routes = computed({
|
|||||||
})
|
})
|
||||||
|
|
||||||
async function componentFindRoute() {
|
async function componentFindRoute() {
|
||||||
const tokenA = os.tokenA
|
const tokenA = os.baseToken
|
||||||
const tokenB = os.tokenB
|
const tokenB = os.tokenB
|
||||||
os.routes = []
|
os.routes = []
|
||||||
if (!tokenA || !tokenB)
|
if (!tokenA || !tokenB)
|
||||||
|
|||||||
@@ -1,39 +1,38 @@
|
|||||||
<template>
|
<template>
|
||||||
<span>{{adjValue}}</span>
|
<span>
|
||||||
<!-- todo optional pair label and inversion button -->
|
{{adjValue}}
|
||||||
|
<btn v-if="showBtn && adjValue!==null" size="small" variant="plain" @click="invert()">{{pair}}</btn>
|
||||||
|
</span>
|
||||||
|
<!-- todo optional pair label and inversion button -->
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {usePrefStore, useStore} from "@/store/store";
|
import {usePrefStore, useStore} from "@/store/store";
|
||||||
import {computed} from "vue";
|
import {computed} from "vue";
|
||||||
import {token} from "@/blockchain/token.js";
|
import {token} from "@/blockchain/token.js";
|
||||||
|
import {pairKey, pairPrice} from "@/misc.js";
|
||||||
|
import Btn from "@/components/Btn.vue";
|
||||||
|
|
||||||
const props = defineProps(['value','tokenA','tokenB','addrA','addrB',])
|
const props = defineProps(['value', 'baseToken', 'quoteToken', 'baseAddr', 'quoteAddr', 'showBtn', 'decimals'])
|
||||||
|
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
const prefs = usePrefStore()
|
const prefs = usePrefStore()
|
||||||
|
|
||||||
const adjValue = computed(()=>{
|
const base = computed(() => props.baseToken ? props.baseToken : token(props.baseAddr))
|
||||||
const a = props.tokenA ? props.tokenA : token(s.chainId,props.addrA)
|
const quote = computed(() => props.quoteToken ? props.quoteToken : token(props.quoteAddr))
|
||||||
const b = props.tokenB ? props.tokenB : token(s.chainId,props.addrB)
|
|
||||||
if( !a || !b )
|
function invert() {
|
||||||
return ''
|
const k = pairKey(base.value,quote.value)
|
||||||
let price = props.value
|
prefs.inverted[k] = !prefs.inverted[k]
|
||||||
const decimals = b.decimals-a.decimals
|
}
|
||||||
if( decimals > 0 )
|
|
||||||
price /= 10 ** decimals
|
const adjValue = computed(() => !base.value || !quote.value ? null : pairPrice(base.value, quote.value, props.value, props.decimals).toPrecision(5))
|
||||||
else
|
|
||||||
price *= 10 ** -decimals
|
const pair = computed(() => {
|
||||||
const token0 = a.address < b.address ? a.address : b.address
|
const inToken = props.baseToken ? props.baseToken : token(props.baseAddr)
|
||||||
const token1 = a.address > b.address ? a.address : b.address
|
const outToken = props.quoteToken ? props.quoteToken : token(props.quoteAddr)
|
||||||
const invertedKey = [token0, token1];
|
return !inToken || !outToken ? '___\\___' : prefs.inverted[pairKey(inToken, outToken)] ?
|
||||||
if( !(invertedKey in prefs.inverted) ) {
|
outToken.symbol + '\\' + inToken.symbol : inToken.symbol + '\\' + outToken.symbol
|
||||||
// todo prefer stablecoins as the quote asset
|
|
||||||
prefs.inverted[invertedKey] = false
|
|
||||||
}
|
|
||||||
if( prefs.inverted[invertedKey] )
|
|
||||||
price = 1/price
|
|
||||||
return price.toPrecision(5)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
42
src/misc.js
42
src/misc.js
@@ -1,5 +1,6 @@
|
|||||||
import {FixedNumber} from "ethers";
|
import {FixedNumber} from "ethers";
|
||||||
import {useStore} from "@/store/store.js";
|
import {usePrefStore, useStore} from "@/store/store.js";
|
||||||
|
import {token} from "@/blockchain/token.js";
|
||||||
|
|
||||||
export class SingletonCoroutine {
|
export class SingletonCoroutine {
|
||||||
constructor(f, delay=10, retry=true) {
|
constructor(f, delay=10, retry=true) {
|
||||||
@@ -84,3 +85,42 @@ export function timestamp(date=null) {
|
|||||||
date = new Date()
|
date = new Date()
|
||||||
return Math.round(date.getTime() / 1000)
|
return Math.round(date.getTime() / 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function pairKey(tokenA, tokenB) {
|
||||||
|
const token0 = tokenA.address < tokenB.address ? tokenA.address : tokenB.address
|
||||||
|
const token1 = tokenA.address > tokenB.address ? tokenA.address : tokenB.address
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import {knownTokens} from "@/knownTokens.js";
|
import {knownTokens} from "@/knownTokens.js";
|
||||||
import {computed, ref} from "vue";
|
import {computed, ref} from "vue";
|
||||||
import {timestamp} from "@/misc.js";
|
|
||||||
|
|
||||||
|
|
||||||
// USING THE STORE:
|
// USING THE STORE:
|
||||||
@@ -28,6 +27,9 @@ import {timestamp} from "@/misc.js";
|
|||||||
// const stuff = [ {}, [], true ]
|
// const stuff = [ {}, [], true ]
|
||||||
// if( s.obj.value in stuff || s.obj.value === {} ) ... // use .value to access the raw object instead of its reference
|
// if( s.obj.value in stuff || s.obj.value === {} ) ... // use .value to access the raw object instead of its reference
|
||||||
|
|
||||||
|
function timestamp() {
|
||||||
|
return Math.round(new Date().getTime() / 1000)
|
||||||
|
}
|
||||||
|
|
||||||
export const useStore = defineStore('app', ()=> {
|
export const useStore = defineStore('app', ()=> {
|
||||||
const time = ref(timestamp())
|
const time = ref(timestamp())
|
||||||
@@ -179,7 +181,7 @@ export const useOrderStore = defineStore('order', ()=> {
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
export const usePrefStore = defineStore('order', ()=> {
|
export const usePrefStore = defineStore('prefs', ()=> {
|
||||||
// user preferences
|
// user preferences
|
||||||
const inverted = ref({})
|
const inverted = ref({})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user