orderspec refactor for server and web

This commit is contained in:
Tim Olson
2023-12-07 18:37:11 -04:00
parent 545583586c
commit 83619ea248
12 changed files with 306 additions and 110 deletions

View File

@@ -2,11 +2,9 @@
<v-table>
<thead>
<tr>
<th class="num d-none d-md-table-cell">#</th> <!-- todo placement date instead -->
<th class="token d-none d-sm-table-cell">Buy</th>
<th class="token d-none d-sm-table-cell">Sell</th>
<th class="token d-sm-none">Pair</th>
<th class="amount d-none d-md-table-cell">Amount</th>
<th class="num d-none d-md-table-cell">Date</th> <!-- todo placement date instead -->
<th class="token d-none d-sm-table-cell">Input</th>
<th class="token d-none d-sm-table-cell">Output</th>
<th class="amount">Remaining</th>
<th class="amount">Filled</th>
<th class="amount d-none d-md-table-cell">Avg&nbsp;Price</th>
@@ -15,33 +13,32 @@
</tr>
</thead>
<tbody>
<tr v-for="[index, inTokenAddr, outTokenAddr, amount, amountTokenAddr, filled, avgPrice, state] in orders">
<td class="d-none d-md-table-cell" style="width: 1em">{{parseInt(index)+1}}</td>
<td class="token d-none d-sm-table-cell">{{tokenSymbol(inTokenAddr)}}</td>
<td class="token d-none d-sm-table-cell">{{tokenSymbol(outTokenAddr)}}</td>
<td class="pair d-sm-none">Buy {{tokenSymbol(inTokenAddr)}}<br/>Sell {{tokenSymbol(outTokenAddr)}}</td>
<td class="amount d-none d-md-table-cell">{{tokenAmount(amountTokenAddr, amount)}}</td>
<td class="amount">{{tokenAmount(amountTokenAddr, amount-filled)}}</td>
<td class="amount">{{tokenAmount(amountTokenAddr, filled)}}</td>
<td class="amount d-none d-md-table-cell">
{{pairPrice(inTokenAddr, outTokenAddr, vaultAddr, index, avgPrice)}}
<btn v-if="pairPrice(inTokenAddr, outTokenAddr, vaultAddr, index, avgPrice)!==''" size="small"
<tr v-for="st of orders">
<td class="">{{st.start}}</td>
<td class="amount"><suspense><token-amount :addr="st.order.tokenIn" :amount="st.order.amountIsInput ? st.order.amount : null"/></suspense></td>
<td class="amount"><suspense><token-amount :addr="st.order.tokenOut" :amount="!st.order.amountIsInput ? st.order.amount : null"/></suspense></td>
<td class="amount"><suspense><token-amount :addr="st.amountToken" :amount="st.order.amount-st.filled"/></suspense></td>
<td class="amount"><suspense><token-amount :addr="st.amountToken" :amount="st.filled"/></suspense></td>
<td class="amount">
{{pairPrice(st.order.tokenIn, st.order.tokenOut, vaultAddr, st.index, st.avg)}}
<btn v-if="pairPrice(st.order.tokenIn, st.order.tokenOut, vaultAddr, st.index, st.avg)!==''" size="small"
variant="plain"
@click="inverted[[vaultAddr,index]] = !inverted[[vaultAddr,index]]">
{{pair(inTokenAddr, outTokenAddr, vaultAddr,index)}}
@click="inverted[[vaultAddr,st.index]] = !inverted[[vaultAddr,st.index]]">
{{pair(st.order.tokenIn, st.order.tokenOut, vaultAddr, st.index)}}
</btn>
</td>
<td class="status">
<v-chip v-if="state===-1" prepend-icon="mdi-signature" color="yellow">Signing</v-chip>
<v-chip v-if="state===0" class="d-none d-lg-inline-flex" prepend-icon="mdi-dots-horizontal" color="green">Open</v-chip>
<btn v-if="state===0" class="d-none d-sm-inline-flex d-lg-none" icon="mdi-cancel" color="red" @click="cancelOrder(vaultAddr,index)">Cancel</btn>
<btn v-if="state===0" class="d-sm-none" variant="plain" icon="mdi-cancel" color="red" @click="cancelOrder(vaultAddr,index)"/>
<v-chip v-if="state===1" prepend-icon="mdi-cancel" color="red">Canceled</v-chip>
<v-chip v-if="state===2" prepend-icon="mdi-check-circle-outline" color="green">Completed</v-chip>
<v-chip v-if="state===3" prepend-icon="mdi-progress-check" color="grey-darken-1">Expired</v-chip>
<v-chip v-if="st.state===OrderState.Signing" prepend-icon="mdi-signature" color="yellow">Signing</v-chip>
<v-chip v-if="st.state===OrderState.Open" class="d-none d-lg-inline-flex" prepend-icon="mdi-dots-horizontal" color="green">Open</v-chip>
<btn v-if="st.state===OrderState.Open" class="d-none d-sm-inline-flex d-lg-none" icon="mdi-cancel" color="red" @click="cancelOrder(vaultAddr,st.index)">Cancel</btn>
<btn v-if="st.state===OrderState.Open" class="d-sm-none" variant="plain" icon="mdi-cancel" color="red" @click="cancelOrder(vaultAddr,st.index)"/>
<v-chip v-if="st.state===OrderState.Canceled" prepend-icon="mdi-cancel" color="red">Canceled</v-chip>
<v-chip v-if="st.state===OrderState.Filled" prepend-icon="mdi-check-circle-outline" color="green">Completed</v-chip>
<v-chip v-if="st.state===OrderState.Expired" prepend-icon="mdi-progress-check" color="grey-darken-1">Expired</v-chip>
<v-chip v-if="st.state===OrderState.Underfunded" prepend-icon="mdi-alert" color="warning">Underfunded</v-chip>
</td>
<td class="cancel d-none d-lg-table-cell">
<btn v-if="state===0" icon="mdi-cancel" color="red" @click="cancelOrder(vaultAddr,index)">Cancel</btn>
<btn v-if="st.state===OrderState.Open" icon="mdi-cancel" color="red" @click="cancelOrder(vaultAddr,st.index)">Cancel</btn>
</td>
</tr>
</tbody>
@@ -51,10 +48,13 @@
<script setup>
import {FixedNumber} from "ethers";
import {useStore} from "@/store/store";
import {computed, reactive} from "vue";
import {computed, defineAsyncComponent, reactive} from "vue";
import {token} from "@/blockchain/token.js";
import Btn from "@/components/Btn.vue"
import {cancelOrder} from "@/blockchain/wallet.js";
import {intervalString, dateString} from "@/misc.js";
import {OrderState} from "@/blockchain/orderlib.js";
const TokenAmount = defineAsyncComponent(()=>import('./TokenAmount.vue'))
const s = useStore()
const props = defineProps(['vault'])
@@ -66,15 +66,20 @@ function tokenSymbol(addr) {
return t ? t.symbol : addr
}
/*
function tokenAmount(tokenAddr, amount) {
if( !tokenAddr || !amount )
return ''
console.log('token amount', tokenAddr, amount)
if( typeof tokenAddr !== 'string' )
throw Error('broke')
const t = token(tokenAddr)
if( !t )
return ''
// console.log('tokenAmount amount', typeof amount, amount)
// console.log('tokenAmount decimals', typeof t.decimals, t.decimals)
const amt = FixedNumber.fromValue(amount, t.decimals, {width:256, decimals:t.decimals, signed:false})
return `${amt} ${t.symbol}`
}
*/
// todo create a Price component that keeps inversion flags in the store and defaults to stablecoins as the quote
function pairPrice(inTokenAddr, outTokenAddr, vaultAddr, index, price) {
@@ -110,43 +115,94 @@ function pair(inTokenAddr, outTokenAddr, vaultAddr, index) {
}
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 = []
// for( const [status] of pendingOrders.reverse() ) {
// console.log('adding pended order')
// const inTokenAddr = status[0]
// const outTokenAddr = status[1]
// const amountIsInput = !!(status[4])
// const amountTokenAddr = amountIsInput ? inTokenAddr : outTokenAddr
// const amount = 0
// const filled = 0
// const avg = ''
// const state = -1 // pending
// result.push(['...', inTokenAddr, outTokenAddr, amount, amountTokenAddr, filled, avg, state])
// }
if( vaultAddr.value in s.orders ) {
for (const [index, status] of Object.entries(s.orders[vaultAddr.value]).reverse()) {
// console.log('order status', status)
// [index, symbolA, symbolB, amount, amountSymbol, filled]
const inTokenAddr = status[0][0]
const outTokenAddr = status[0][1]
const amountIsInput = !!(status[0][4])
const amountTokenAddr = amountIsInput ? inTokenAddr : outTokenAddr
// console.log('getamount', status[0][3])
const amount = BigInt(status[0][3])
// console.log('amount', amount)
// console.log('getfilled', amountIsInput ? status[4] : status[5])
const filled = BigInt(amountIsInput ? status[4] : status[5])
// console.log('filled', filled)
const amountIn = BigInt(status[4])
const amountOut = BigInt(status[5])
const st = {...status}
console.log('order status', st)
const o = {...st.order}
st.order = o
result.push(st)
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
})
st.start = dateString(st.start)
const fmtX18 = {decimals: 18, width: 256, signed: false};
const avg = !amountIn || !amountOut ? null :
FixedNumber.fromValue(status[5], 0, fmtX18).div(FixedNumber.fromValue(status[4], 0, fmtX18))
const state = status[1]
result.push([index, inTokenAddr, outTokenAddr, amount, amountTokenAddr, filled, avg, state])
st.filled = st.amountIsInput ? st.filledIn : st.filledOut
st.avg = BigInt(st.filled) === 0n ? null :
FixedNumber.fromValue(status.filledOut, 0, fmtX18)
.div(FixedNumber.fromValue(status.filledIn, 0, fmtX18))
.toUnsafeFloat().toPrecision(5) // todo precision
st.trancheFilled = o.amountIsInput ? st.trancheFilledIn : st.trancheFilledOut
st.amountToken = o.amountIsInput ? o.tokenIn : o.tokenOut
// // [index, symbolA, symbolB, amount, amountSymbol, filled]
// const inTokenAddr = status[0][0]
// const outTokenAddr = status[0][1]
// const amountIsInput = !!(status[0][4])
// const amountTokenAddr = amountIsInput ? inTokenAddr : outTokenAddr
// // console.log('getamount', status[0][3])
// const amount = BigInt(status[0][3])
// // console.log('amount', amount)
// // console.log('getfilled', amountIsInput ? status[4] : status[5])
// const filled = BigInt(amountIsInput ? status[4] : status[5])
// // console.log('filled', filled)
// const amountIn = BigInt(status[4])
// const amountOut = BigInt(status[5])
// const avg = !amountIn || !amountOut ? null :
// FixedNumber.fromValue(status[5], 0, fmtX18).div(FixedNumber.fromValue(status[4], 0, fmtX18))
// const state = status[1]
// result.push([index, inTokenAddr, outTokenAddr, amount, amountTokenAddr, filled, avg, state])
}
}
// console.log('result', result)
console.log('orders', result)
return result
})

View File

@@ -0,0 +1,27 @@
<template>
<span>{{fmtAmount}} {{ token.symbol || '' }}</span>
</template>
<script setup>
import {useStore} from "@/store/store";
import {getToken} from "@/blockchain/token.js";
import {FixedNumber} from "ethers";
import {computed, ref} from "vue";
const s = useStore()
const props = defineProps(['addr', 'amount'])
const token = await getToken(props.addr)
const fmtAmount = computed(() => {
if( props.amount === null || props.amount === undefined )
return ''
return FixedNumber.fromValue(props.amount, token.decimals, {
width: 256,
decimals: token.decimals
}).toUnsafeFloat().toPrecision(5) // todo precision
})
</script>
<style scoped lang="scss">
@use "src/styles/vars" as *;
</style>

View File

@@ -36,7 +36,6 @@ const fixed = computed(() => FixedNumber.fromValue(props.amount, token.decimals,
decimals: token.decimals
}))
const imageSrc = computed(() => token.image)
const withdrawing = ref(false)
</script>
<style scoped lang="scss">

View File

@@ -83,10 +83,8 @@ import {computed, defineAsyncComponent, ref} from "vue";
import {vaultAddress} from "@/blockchain/contract.js";
import {ensureVault} from "@/blockchain/wallet.js";
import CopyButton from "@/components/CopyButton.vue";
import NeedsProvider from "@/components/NeedsProvider.vue";
import Withdraw from "@/components/Withdraw.vue";
import PhoneCard from "@/components/PhoneCard.vue";
import Btn from "@/components/Btn.vue";
const TokenRow = defineAsyncComponent(()=>import('./TokenRow.vue'))
const s = useStore()