bugfixes
This commit is contained in:
306
src/components/Status.vue
Normal file
306
src/components/Status.vue
Normal file
@@ -0,0 +1,306 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-data-table :headers="datatableHeaders" :items="orders" item-value="id"
|
||||
item-selectable="selectable" :show-select="false" :show-expand="true">
|
||||
<template v-slot:item.start="{ value }">{{ dateString(value) }}</template>
|
||||
<template v-slot:item.input="{ item }">
|
||||
<suspense>
|
||||
<span v-if="item.order.amountIsInput">
|
||||
<pulse :touch="item.filledIn">
|
||||
<token-amount :addr="item.order.tokenIn" :amount="item.filledIn" :raw="true"/>
|
||||
</pulse>
|
||||
/
|
||||
<token-amount :addr="item.order.tokenIn" :amount="item.order.amount"/>
|
||||
</span>
|
||||
</suspense>
|
||||
<suspense>
|
||||
<token-symbol :addr="item.order.tokenIn" v-if="!item.order.amountIsInput"/>
|
||||
</suspense>
|
||||
</template>
|
||||
<template v-slot:item.output="{ item }">
|
||||
<suspense>
|
||||
<span v-if="!item.order.amountIsInput">
|
||||
<pulse :touch="item.filledOut">
|
||||
<token-amount :addr="item.order.tokenOut" :amount="item.filledOut" :raw="true"/>
|
||||
</pulse>
|
||||
/
|
||||
<token-amount :addr="item.order.tokenOut" :amount="item.order.amount"/>
|
||||
</span>
|
||||
</suspense>
|
||||
<suspense>
|
||||
<token-symbol :addr="item.order.tokenOut" v-if="item.order.amountIsInput"/>
|
||||
</suspense>
|
||||
</template>
|
||||
<!--
|
||||
<template v-slot:item.remaining="{ item }">
|
||||
<suspense>
|
||||
<token-amount :addr="item.amountToken" :amount="item.remaining"/>
|
||||
</suspense>
|
||||
</template>
|
||||
<template v-slot:item.filled="{ item }">
|
||||
<suspense>
|
||||
<token-amount :addr="item.amountToken" :amount="item.filled"/>
|
||||
</suspense>
|
||||
</template>
|
||||
-->
|
||||
<template v-slot:item.avg="{ item }">
|
||||
<suspense>
|
||||
<pair-price :base="item.order.tokenIn" :quote="item.order.tokenOut" :value="item.avg" :show-btn="true"/>
|
||||
</suspense>
|
||||
</template>
|
||||
<template v-slot:item.state="{ item }">
|
||||
<v-chip v-if="item.state===PendingOrderState.Submitted || item.state===PendingOrderState.Signing"
|
||||
prepend-icon="mdi-signature">Wallet Signing</v-chip>
|
||||
<v-chip v-if="item.state===PendingOrderState.Rejected" prepend-icon="mdi-cancel">Rejected</v-chip>
|
||||
<v-chip v-if="item.state===PendingOrderState.Sent" prepend-icon="mdi-send">Sent</v-chip>
|
||||
<v-chip v-if="item.state===OrderState.Open" class="d-none d-lg-inline-flex" prepend-icon="mdi-dots-horizontal"
|
||||
color="green">Open
|
||||
</v-chip>
|
||||
<btn v-if="isOpen(item.state)" class="d-none d-sm-inline-flex" icon="mdi-cancel" color="red"
|
||||
@click="cancelOrder(vaultAddr,item.index)">Cancel
|
||||
</btn>
|
||||
<btn v-if="isOpen(item.state)" class="d-sm-none" variant="plain" icon="mdi-cancel" color="red"
|
||||
@click="cancelOrder(vaultAddr,item.index)"/>
|
||||
<v-chip v-if="item.state===OrderState.Canceled" prepend-icon="mdi-cancel" color="red">Canceled</v-chip>
|
||||
<v-chip v-if="item.state===OrderState.Filled" prepend-icon="mdi-check-circle-outline" color="green">Completed
|
||||
</v-chip>
|
||||
<v-chip v-if="item.state===OrderState.Expired" prepend-icon="mdi-progress-check" color="grey-darken-1">Expired
|
||||
</v-chip>
|
||||
<v-chip v-if="item.state===OrderState.Underfunded" prepend-icon="mdi-alert" color="warning">Underfunded</v-chip>
|
||||
</template>
|
||||
<!-- <template v-slot:item.action="{item}">-->
|
||||
<!-- <btn v-if="item.state===OrderState.Open" icon="mdi-cancel" color="red"-->
|
||||
<!-- @click="cancelOrder(vaultAddr,item.index)">Cancel-->
|
||||
<!-- </btn>-->
|
||||
<!-- </template>-->
|
||||
<template v-slot:expanded-row="{item}">
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td colspan="100">
|
||||
<v-table>
|
||||
<!--
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Filled</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
-->
|
||||
<tbody>
|
||||
<tr v-for="(t, i) in item.order.tranches">
|
||||
<td class="text-right">Tranche {{ i + 1 }}</td>
|
||||
<td class="text-center w-33">
|
||||
<suspense>
|
||||
<span v-if="item.state > OrderState.Signing">
|
||||
<pulse :touch="item.trancheFilled[i]">
|
||||
<token-amount :addr="item.amountToken" :amount="item.trancheFilled[i]" :raw="true"/>
|
||||
</pulse>
|
||||
/
|
||||
</span>
|
||||
</suspense>
|
||||
<suspense>
|
||||
<span>
|
||||
<token-amount :addr="item.amountToken" :amount="item.order.amount*BigInt(t.fraction)/65535n"/>
|
||||
</span>
|
||||
</suspense>
|
||||
</td>
|
||||
<td class="text-left">
|
||||
<span class="mx-3">{{ describeTrancheTime(item, true, t) }}</span>
|
||||
<span class="mx-3">{{ describeTrancheTime(item, false, t) }}</span>
|
||||
<span class="mx-3" v-if="t.marketOrder">market order</span>
|
||||
<line-price class="mx-3" v-if="!t.marketOrder"
|
||||
:base="item.token0" :quote="item.token1"
|
||||
:b="t.minIntercept" :m="t.minSlope" :is-min="true"
|
||||
:buy="item.order.tokenIn===item.token1" :show-btn="true"/>
|
||||
<line-price class="mx-3" v-if="!t.marketOrder"
|
||||
:base="item.token0" :quote="item.token1"
|
||||
:b="t.maxIntercept" :m="t.maxSlope" :is-min="false"
|
||||
:buy="item.order.tokenIn===item.token1" :show-btn="true"/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</v-table>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</v-data-table>
|
||||
<btn icon="mdi-delete-alert" color="red" class="mx-3 mb-3" @click="cancelAll(vaultAddr)">Cancel All Orders</btn>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import LinePrice from "@/components/LinePrice.vue";
|
||||
|
||||
const PairPrice = defineAsyncComponent(()=>import("@/components/PairPrice.vue"))
|
||||
const TokenAmount = defineAsyncComponent(()=>import('./TokenAmount.vue'))
|
||||
const TokenSymbol = defineAsyncComponent(()=>import('./TokenSymbol.vue'))
|
||||
import {FixedNumber} from "ethers";
|
||||
import {useStore} from "@/store/store";
|
||||
import {computed, defineAsyncComponent, ref} from "vue";
|
||||
import Btn from "@/components/Btn.vue"
|
||||
import {cancelAll, cancelOrder, PendingOrderState, useWalletStore} from "@/blockchain/wallet.js";
|
||||
import {dateString, pairPriceAddr} from "@/misc.js";
|
||||
import {isOpen, OrderState} from "@/blockchain/orderlib.js";
|
||||
import Pulse from "@/components/Pulse.vue";
|
||||
|
||||
const s = useStore()
|
||||
const ws = useWalletStore()
|
||||
const props = defineProps(['vault'])
|
||||
const vaultAddr = computed(()=>props.vault?props.vault:s.vault)
|
||||
const inverted = ref({})
|
||||
|
||||
|
||||
const datatableHeaders = [
|
||||
{title: 'Date', align: 'start', key: 'start'},
|
||||
{title: 'Input', align: 'end', key: 'input'},
|
||||
{title: 'Output', align: 'end', key: 'output'},
|
||||
{title: 'Avg Price', align: 'end', key: 'avg'},
|
||||
{title: 'Status', align: 'end', key: 'state'},
|
||||
// {title: '', align: 'end', key: 'action'},
|
||||
];
|
||||
|
||||
const orders = computed(()=>{
|
||||
// example twap
|
||||
// status = [
|
||||
// [ order
|
||||
// "0x52412507302F6bAB17f56370b6a8F304CbB30Ce1", in token
|
||||
// "0x63e187162a4c33A4D14465eA3859fFe423647710", out token
|
||||
// [1, 500], route
|
||||
// "100000000", amount
|
||||
// "1000000", min amount
|
||||
// false, amount is input
|
||||
// false, output to owner
|
||||
// 18446744073709552000, chain order
|
||||
// [ tranches
|
||||
// [21845, fraction
|
||||
// true, start time relative
|
||||
// true, end time relative
|
||||
// false, min is barrier
|
||||
// false, max is barrier
|
||||
// false, market order
|
||||
// false, reserved
|
||||
// false, reserved
|
||||
// false, reserved
|
||||
// 0, reserved
|
||||
// 0, reserved
|
||||
// 0, start time
|
||||
// 20, end time
|
||||
// 730643660, min intercept
|
||||
// 0, min slope
|
||||
// 0, max intercept
|
||||
// 0 max slope
|
||||
// ],
|
||||
// [...],
|
||||
// [...],
|
||||
// ]
|
||||
// ],
|
||||
// 4, state
|
||||
// 1701809053, started at
|
||||
// null, oco group
|
||||
// "0", filled in
|
||||
// "0", filled out
|
||||
// ["0", "0", "0"], tranche filled in
|
||||
// ["0", "0", "0"] tranche filled out
|
||||
// ]
|
||||
const result = []
|
||||
|
||||
// in-flight orders
|
||||
for (const pend of ws.pendingOrders) {
|
||||
console.log('pended order', pend)
|
||||
result.push({
|
||||
id: pend.id,
|
||||
start: pend.placementTime,
|
||||
order: pend.order,
|
||||
filled: 0,
|
||||
state: pend.state,
|
||||
amountToken: pend.order.amountIsInput ? pend.order.tokenIn : pend.order.tokenOut
|
||||
})
|
||||
}
|
||||
|
||||
// historical orders
|
||||
const vault = vaultAddr.value;
|
||||
if( vault in s.orders ) {
|
||||
for (const [index, status] of Object.entries(s.orders[vault]).reverse()) {
|
||||
const st = {...status}
|
||||
const o = {...st.order}
|
||||
st.order = o
|
||||
console.log('order status', st)
|
||||
result.push(st)
|
||||
st.id = `${vault}|${index}`
|
||||
st.index = parseInt(index)
|
||||
o.tranches = o.tranches.map((tranche)=>{
|
||||
const t = {...tranche}
|
||||
// t.startTime = t.startTimeIsRelative ? intervalString(t.startTime) : dateString(t.startTime)
|
||||
// t.endTime = t.endTimeIsRelative ? intervalString(t.endTime) : dateString(t.endTime)
|
||||
return t
|
||||
})
|
||||
const fmtX18 = {decimals: 18, width: 256, signed: false};
|
||||
st.filled = o.amountIsInput ? st.filledIn : st.filledOut
|
||||
if(BigInt(st.filled) === 0n)
|
||||
st.avg = null
|
||||
else {
|
||||
st.avg = FixedNumber.fromValue(status.filledOut, 0, fmtX18)
|
||||
.div(FixedNumber.fromValue(status.filledIn, 0, fmtX18)).toUnsafeFloat();
|
||||
}
|
||||
st.trancheFilled = o.amountIsInput ? st.trancheFilledIn : st.trancheFilledOut
|
||||
st.amountToken = o.amountIsInput ? o.tokenIn : o.tokenOut
|
||||
st.input = o.amountIsInput ? o.amount : 0
|
||||
st.output = !o.amountIsInput ? o.amount : 0
|
||||
st.remaining = o.amount - st.filled
|
||||
st.selectable = st.state===OrderState.Open
|
||||
st.token0 = o.tokenIn < o.tokenOut ? o.tokenIn : o.tokenOut
|
||||
st.token1 = o.tokenIn < o.tokenOut ? o.tokenOut : o.tokenIn
|
||||
}
|
||||
}
|
||||
console.log('orders', result)
|
||||
return result
|
||||
})
|
||||
|
||||
function describeTrancheTime(st, isStart, t) {
|
||||
let result = ''
|
||||
if( t.minIsBarrier || t.maxIsBarrier )
|
||||
return 'barrier'
|
||||
if( isStart && t.startTime > 0 ) {
|
||||
const started = t.startTimeIsRelative ? st.start + t.startTime : t.startTime
|
||||
result += started*1000 < Date.now() ? 'Activated ' : 'Activates '
|
||||
result += dateString(started) + ' '
|
||||
}
|
||||
if( !isStart && t.endTime < 4294967295 ) {
|
||||
const ended = t.endTimeIsRelative ? st.start + t.endTime : t.endTime
|
||||
result += ended*1000 < Date.now() ? 'Expired ' : 'Expires '
|
||||
result += dateString(ended)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use "src/styles/vars" as *;
|
||||
|
||||
// columns
|
||||
.num {
|
||||
min-width: 1em;
|
||||
}
|
||||
.token {
|
||||
min-width: 3em;
|
||||
max-width: 5em;
|
||||
}
|
||||
.pair {
|
||||
min-width: 5em;
|
||||
}
|
||||
.amount {
|
||||
min-width: 3em;
|
||||
max-width: 6em;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.state {
|
||||
max-width: 8em;
|
||||
}
|
||||
.cancel {
|
||||
}
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user