Files
web/src/components/chart/ChartOrder.vue
2024-03-28 15:34:37 -04:00

138 lines
5.4 KiB
Vue

<template>
<row-bar :color="color">
<color-band :color="color"/>
<div :style="faintColorStyle" style="width: 100%" class="justify-start align-content-start">
<v-text-field type="number" inputmode="numeric" pattern="[0-9]*\.?[0-9]*" v-model="order.amount" variant="outlined" density="compact" hide-details
min="0" :step="order.amount?Math.floor(order.amount/1000):1"
style="max-width:24em; display: inline-grid"
class="py-2" :color="color"
:label="order.amountIsTokenA ? 'Amount':('Value in '+co.selectedSymbol.quote.s)"
>
<template v-slot:prepend>
<v-btn variant="outlined" :color="color" class="ml-3"
:text="(order.buy ? 'Buy ' : 'Sell ') + co.selectedSymbol.base.s"
@click="order.buy=!order.buy"/>
</template>
<template v-slot:append-inner>
<v-btn :text="order.amountIsTokenA?co.selectedSymbol.base.s:co.selectedSymbol.quote.s+' worth'"
:color="color" variant="text" @click="order.amountIsTokenA=!order.amountIsTokenA"/>
</template>
</v-text-field>
<template v-for="b in builders">
<builder-factory :order="order" :builder="b"/>
</template>
<div class="my-3">
<div v-if="order.builders.length===0"> <!--todo remove gralpha limitation of one builder-->
<span :style="colorStyle" class="ma-3">Add condition:</span>
<!-- <v-btn variant="flat" prepend-icon="mdi-clock-outline" @click="build('DCABuilder')">DCA</v-btn>-->
<v-btn :color="color" variant="text" prepend-icon="mdi-ray-vertex" @click="build(order,'LimitBuilder')">Limit</v-btn>
<!-- <v-btn variant="flat" prepend-icon="mdi-vector-line">Line</v-btn>-->
<!--
mdi-ray-start-end
mdi-vector-polyline
-->
</div>
</div>
</div>
</row-bar>
</template>
<script setup>
import BuilderFactory from "@/components/chart/BuilderFactory.vue";
import {builderFuncs, newBuilder, orderFuncs, useChartOrderStore} from "@/orderbuild.js";
import {useOrderStore} from "@/store/store.js";
import {computed, onMounted, onUnmounted, onUpdated, watch} from "vue";
import {lightenColor, lightenColor2} from "@/misc.js";
import {useTheme} from "vuetify";
import RowBar from "@/components/chart/RowBar.vue";
import ColorBand from "@/components/chart/ColorBand.vue";
import Color from "color";
import {Exchange, newOrder} from "@/blockchain/orderlib.js";
const props = defineProps(['order'])
const co = useChartOrderStore()
const os = useOrderStore()
const marketBuilder = newBuilder('MarketBuilder')
const builders = computed(()=>props.order.builders.length > 0 ? props.order.builders : [marketBuilder])
console.log('order', props.order)
function build(order, component, options={}) {
order.builders.push(newBuilder(component, options))
}
function buildOrder() {
const order = props.order
console.log('buildOrder', order)
// struct SwapOrder {
// address tokenIn;
// address tokenOut;
// Route route;
// uint256 amount;
// uint256 minFillAmount; // if a tranche has less than this amount available to fill, it is considered completed
// bool amountIsInput;
// bool outputDirectlyToOwner;
// uint64 chainOrder; // use NO_CHAIN for no chaining. chainOrder index must be < than this order's index for safety (written first) and chainOrder state must be Template
// Tranche[] tranches;
// }
const symbol = co.selectedSymbol
const fee = co.selectedPool[1]
const tokenIn = order.buy ? symbol.quote : symbol.base
const tokenOut = order.buy ? symbol.base : symbol.quote
const amountDec = order.amountIsTokenA ? symbol.base.d : symbol.quote.d
const amount = BigInt(Math.trunc(order.amount * 10 ** amountDec))
const amountIsInput = !!(order.amountIsTokenA ^ order.buy)
let tranches = []
for (const builder of builders.value) {
console.log('builder', builder)
const ts = builderFuncs[builder.id]()
console.log('tranches', ts)
tranches = [...tranches, ...ts]
}
return newOrder(tokenIn.a, tokenOut.a, Exchange.UniswapV3, fee, amount, amountIsInput, tranches)
}
let lastId = props.order.id
orderFuncs[lastId] = buildOrder
onUpdated(()=>{
console.log('onUpdated', lastId, ...arguments)
delete orderFuncs[lastId]
orderFuncs[props.order.id] = buildOrder
lastId = props.order.id
})
onUnmounted(() => delete orderFuncs[lastId])
const theme = useTheme().current
const color = computed(()=>new Color(props.order.buy?theme.value.colors.success:theme.value.colors.error).darken(0.2).string())
const lightColor = computed(() => lightenColor(color.value))
const faintColor = computed(() => lightenColor2(color.value))
const colorStyle = computed(() => { return {'color': color.value} })
const bgColorStyle = computed(() => { return {'background-color': color.value} })
const lightColorStyle = computed(() => { return {'background-color': lightColor.value} })
const faintColorStyle = computed(() => { return {'background-color': faintColor.value} })
const inToken = computed( ()=>props.order.buy ? co.selectedSymbol.quote : co.selectedSymbol.base )
const maxAmount = computed(()=>{
const balance = s.balances[inToken.value]
if( !balance )
return 0
const divisor = os.amountIsTotal ? 1 : os.tranches
return balance / 10**inToken.value.d / divisor
})
</script>
<style scoped lang="scss">
</style>