diagonal line support
This commit is contained in:
@@ -4,31 +4,43 @@
|
||||
<div class="title">Line Point A</div>
|
||||
<v-divider/>
|
||||
<time-entry v-model="time1" class="mb-0" hide-details="true"/>
|
||||
<limit-price v-model="price1" label="Price A" :required="true"/>
|
||||
<limit-price v-model="price1" label="Price A" :required="true" :show-price="false"/>
|
||||
<div class="title">Line Point B</div>
|
||||
<v-divider/>
|
||||
<time-entry v-model="time2" hide-details="true"/>
|
||||
<limit-price v-model="price2" label="Price B" :required="true"/>
|
||||
<div><i>Backend support for diagonal lines is coming soon...</i></div>
|
||||
<limit-price v-model="price2" label="Price B" :required="true" :show-price="false"/>
|
||||
<div v-if="curLimit">
|
||||
<v-row>
|
||||
<v-col cols="6">
|
||||
<span>Current line value</span> <span class="text-green">{{curLimit ? curLimit.toPrecision(5) : curLimit}}</span>
|
||||
</v-col>
|
||||
<v-col cols="6">
|
||||
<span>Current price</span> <route-price class="text-green"/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
{{os.limitIsMinimum}}
|
||||
</order>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {useOrderStore} from "@/store/store";
|
||||
import {useOrderStore, useStore} from "@/store/store";
|
||||
import LimitPrice from "@/components/LimitPrice.vue";
|
||||
import Order from "@/components/Order.vue";
|
||||
import {computed, ref} from "vue";
|
||||
import {applyLimit, applyLinePoints} from "@/orderbuild.js";
|
||||
import {validateRequired, validateTranches} from "@/validate.js";
|
||||
import {MAX_FRACTION, newTranche} from "@/blockchain/orderlib.js";
|
||||
import {applyLinePoints, linePointsValue} from "@/orderbuild.js";
|
||||
import {newTranche} from "@/blockchain/orderlib.js";
|
||||
import TimeEntry from "@/components/TimeEntry.vue";
|
||||
import RoutePrice from "@/components/RoutePrice.vue";
|
||||
|
||||
const s = useStore()
|
||||
const os = useOrderStore()
|
||||
|
||||
const time1 = ref(new Date())
|
||||
const price1 = ref(null)
|
||||
const time2 = ref(new Date())
|
||||
const price2 = ref(null)
|
||||
const curLimit = computed(()=>linePointsValue(time1.value, price1.value, time2.value, price2.value, s.time))
|
||||
|
||||
function buildTranches() {
|
||||
const t = newTranche();
|
||||
@@ -37,7 +49,7 @@ function buildTranches() {
|
||||
}
|
||||
|
||||
function validOrder() {
|
||||
return false
|
||||
return time1.value && (price1.value || price1.value===0) && time2.value && (price2.value || price2.value===0)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
</suspense>
|
||||
</template>
|
||||
<template v-slot:item.avg="{ item }">
|
||||
{{ pairPrice(item.order.tokenIn, item.order.tokenOut, vaultAddr, item.avg) }}
|
||||
<btn v-if="pairPrice(item.order.tokenIn, item.order.tokenOut, vaultAddr, item.avg)!==''" size="small"
|
||||
{{ pairPrice(item.order.tokenIn, item.order.tokenOut, item.avg) }}
|
||||
<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) }}
|
||||
@@ -117,7 +117,7 @@ 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, vaultAddr, price) {
|
||||
function pairPrice(inTokenAddr, outTokenAddr, price) {
|
||||
if( price === null )
|
||||
return ''
|
||||
const inToken = token(inTokenAddr)
|
||||
@@ -125,7 +125,7 @@ function pairPrice(inTokenAddr, outTokenAddr, vaultAddr, price) {
|
||||
if( !inToken || !outToken )
|
||||
return ''
|
||||
|
||||
const decimals = outToken.decimals-inToken.decimals
|
||||
const decimals = inToken.decimals-outToken.decimals
|
||||
if( decimals > 0 )
|
||||
price /= 10 ** decimals
|
||||
else
|
||||
@@ -268,11 +268,14 @@ function describeTrancheTime(st, isStart, t) {
|
||||
}
|
||||
|
||||
function describeTrancheLine(st, isMin, b, m) {
|
||||
if( b===0 && m===0 ) return ''
|
||||
// todo slopes
|
||||
console.log('tranche line', isMin, b, m)
|
||||
// todo make this a PairPrice
|
||||
return (isMin === st.order.amountIsInput ? 'dont-chase ' : 'limit ') + pairPrice(st.order.tokenIn, st.order.tokenOut, s.vault, b)
|
||||
if( b===0 && m===0 ) return ''
|
||||
// console.log('tranche line', isMin, b, m)
|
||||
if( m !== 0 ) {
|
||||
const limit = b + m * s.time
|
||||
return 'diagonal ' + pairPrice(st.order.tokenIn, st.order.tokenOut, limit)
|
||||
}
|
||||
return (isMin === st.order.amountIsInput ? 'dont-chase ' : 'limit ') + pairPrice(st.order.tokenIn, st.order.tokenOut, b)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
45
src/components/PairPrice.vue
Normal file
45
src/components/PairPrice.vue
Normal file
@@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<span>{{adjValue}}</span>
|
||||
<!-- todo optional pair label and inversion button -->
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {usePrefStore, useStore} from "@/store/store";
|
||||
import {computed} from "vue";
|
||||
import {token} from "@/blockchain/token.js";
|
||||
|
||||
const props = defineProps(['value','tokenA','tokenB','addrA','addrB',])
|
||||
|
||||
const s = useStore()
|
||||
const prefs = usePrefStore()
|
||||
|
||||
const adjValue = computed(()=>{
|
||||
const a = props.tokenA ? props.tokenA : token(s.chainId,props.addrA)
|
||||
const b = props.tokenB ? props.tokenB : token(s.chainId,props.addrB)
|
||||
if( !a || !b )
|
||||
return ''
|
||||
let price = props.value
|
||||
const decimals = b.decimals-a.decimals
|
||||
if( decimals > 0 )
|
||||
price /= 10 ** decimals
|
||||
else
|
||||
price *= 10 ** -decimals
|
||||
const token0 = a.address < b.address ? a.address : b.address
|
||||
const token1 = a.address > b.address ? a.address : b.address
|
||||
const invertedKey = [token0, token1];
|
||||
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.toPrecision(5)
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use "src/styles/vars" as *;
|
||||
|
||||
</style>
|
||||
@@ -3,24 +3,27 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {useStore} from "@/store/store";
|
||||
import {useOrderStore, useStore} from "@/store/store";
|
||||
import {subPrices, unsubPrices, WIDE_PRICE_FORMAT} from "@/blockchain/prices.js";
|
||||
import {computed, onBeforeUnmount} from "vue";
|
||||
import {FixedNumber} from "ethers";
|
||||
import {routeInverted} from "@/misc.js";
|
||||
|
||||
const s = useStore()
|
||||
const os = useOrderStore()
|
||||
|
||||
const props = defineProps({
|
||||
route: {type: Object, required:true},
|
||||
inverted: {type: Boolean, required:true},
|
||||
route: {type: Object, required:false},
|
||||
inverted: {type: Boolean, required:false},
|
||||
precision: {type: Number, default:5, required:false},
|
||||
})
|
||||
|
||||
const route = computed(()=>props.route ? props.route : os.route)
|
||||
|
||||
const price = computed(()=>{
|
||||
const route = props.route;
|
||||
if( !route )
|
||||
if( !route.value )
|
||||
return ''
|
||||
const routeKey = [route.chainId, route.pool]
|
||||
const routeKey = [route.value.chainId, route.value.pool]
|
||||
if( !(routeKey in s.poolPrices) )
|
||||
return ''
|
||||
let p = s.poolPrices[routeKey]
|
||||
@@ -28,19 +31,20 @@ const price = computed(()=>{
|
||||
if( !p )
|
||||
return ''
|
||||
p = FixedNumber.fromString(p, WIDE_PRICE_FORMAT).toUnsafeFloat()
|
||||
if( props.inverted )
|
||||
const inverted = props.inverted === undefined ? routeInverted(route.value) : props.inverted;
|
||||
if( inverted )
|
||||
p = 1/p
|
||||
return p.toPrecision(props.precision)
|
||||
})
|
||||
|
||||
if( props.route )
|
||||
subPrices([props.route])
|
||||
if( route.value )
|
||||
subPrices([route.value])
|
||||
else
|
||||
console.log('route is empty: no price')
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if( props.route )
|
||||
unsubPrices([props.route])
|
||||
if( route.value )
|
||||
unsubPrices([route.value])
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -30,7 +30,18 @@ const year = computed({
|
||||
set(v) { update(v, month.value, day.value, time.value)},
|
||||
})
|
||||
const time = computed({
|
||||
get() { return '' + (s.utc ? `${props.modelValue.getUTCHours()}:${props.modelValue.getUTCMinutes()}` : `${props.modelValue.getHours()}:${props.modelValue.getMinutes()}` ) },
|
||||
get() {
|
||||
let hour, min
|
||||
if( s.utc ) {
|
||||
hour = props.modelValue.getUTCHours()
|
||||
min = props.modelValue.getUTCMinutes()
|
||||
}
|
||||
else {
|
||||
hour = props.modelValue.getHours()
|
||||
min = props.modelValue.getMinutes()
|
||||
}
|
||||
return hour.toString().padStart(2,'0') + ':' + min.toString().padStart(2,'0')
|
||||
},
|
||||
set(v) { update(year.value, month.value, day.value, v) }
|
||||
})
|
||||
|
||||
@@ -45,7 +56,6 @@ const monthItems = monthsForLocale(undefined, 'short').map((v)=>{return {title:v
|
||||
|
||||
function buildDate(y, m, d, t) {
|
||||
const [hours,minutes] = t.split(':')
|
||||
console.log('buildDate', y, m, d, hours, minutes)
|
||||
return s.utc ? new Date(Date.UTC(y, m, d, hours, minutes))
|
||||
: new Date(y, m, d, hours, minutes);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user