181 lines
6.8 KiB
Vue
181 lines
6.8 KiB
Vue
<template>
|
|
<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="amount">Remaining</th>
|
|
<th class="amount">Filled</th>
|
|
<th class="amount d-none d-md-table-cell">Avg Price</th>
|
|
<th class="status">Status</th>
|
|
<th class="cancel d-none d-lg-table-cell"> </th>
|
|
</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"
|
|
variant="plain"
|
|
@click="inverted[[vaultAddr,index]] = !inverted[[vaultAddr,index]]">
|
|
{{pair(inTokenAddr, outTokenAddr, vaultAddr,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" prepend-icon="mdi-dots-horizontal" color="green">Open</v-chip>
|
|
<btn v-if="state===0" class="d-none d-sm-inline-block 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>
|
|
</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>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</v-table>
|
|
</template>
|
|
|
|
<script setup>
|
|
import {FixedNumber} from "ethers";
|
|
import {useStore} from "@/store/store";
|
|
import {computed, reactive} from "vue";
|
|
import {token} from "@/blockchain/token.js";
|
|
import Btn from "@/components/Btn.vue"
|
|
import {cancelOrder} from "@/blockchain/wallet.js";
|
|
|
|
const s = useStore()
|
|
const props = defineProps(['vault'])
|
|
const vaultAddr = computed(()=>props.vault?props.vault:s.vault)
|
|
const inverted = reactive({})
|
|
|
|
function tokenSymbol(addr) {
|
|
const t = token(addr)
|
|
return t ? t.symbol : addr
|
|
}
|
|
|
|
function tokenAmount(tokenAddr, amount) {
|
|
const t = token(tokenAddr)
|
|
if( !t )
|
|
return ''
|
|
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) {
|
|
if( price === null )
|
|
return ''
|
|
const inToken = token(inTokenAddr)
|
|
const outToken = token(outTokenAddr)
|
|
if( !inToken || !outToken )
|
|
return ''
|
|
|
|
console.log('inout tokens', inToken, outToken)
|
|
console.log('price1', price, outToken.decimals, inToken.decimals)
|
|
const decimals = outToken.decimals-inToken.decimals
|
|
if( decimals > 0 )
|
|
price /= 10 ** decimals
|
|
else
|
|
price *= 10 ** -decimals
|
|
console.log('price2', price)
|
|
const invertedKey = [vaultAddr,index];
|
|
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
|
|
}
|
|
|
|
const orders = computed(()=>{
|
|
const result = []
|
|
console.log('computing orders')
|
|
// 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 = status[0][3]
|
|
console.log('amount', amount)
|
|
console.log('getfilled', amountIsInput ? status[4] : status[5])
|
|
const filled = amountIsInput ? status[4] : status[5]
|
|
console.log('filled', filled)
|
|
const amountIn = BigInt(status[4])
|
|
const amountOut = BigInt(status[5])
|
|
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])
|
|
}
|
|
}
|
|
console.log('result', result)
|
|
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;
|
|
}
|
|
.status {
|
|
max-width: 8em;
|
|
}
|
|
.cancel {
|
|
}
|
|
|
|
</style>
|