orderspec refactor for server and web
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
export function applyFills( orderStatus, filled ) {
|
export function applyFills( orderStatus, filled ) {
|
||||||
// console.log('apply fills', orderStatus, filled)
|
console.log('apply fills', orderStatus, filled)
|
||||||
orderStatus[4] = filled[0][0]
|
orderStatus[4] = filled[0][0]
|
||||||
orderStatus[5] = filled[0][1]
|
orderStatus[5] = filled[0][1]
|
||||||
for( const i in filled[1] ) {
|
for( const i in filled[1] ) {
|
||||||
@@ -7,7 +7,7 @@ export function applyFills( orderStatus, filled ) {
|
|||||||
orderStatus[6][i] = filledIn
|
orderStatus[6][i] = filledIn
|
||||||
orderStatus[7][i] = filledOut
|
orderStatus[7][i] = filledOut
|
||||||
}
|
}
|
||||||
// console.log('applied fills', orderStatus)
|
console.log('applied fills', orderStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {useStore} from "@/store/store.js";
|
|||||||
|
|
||||||
export function vaultAddress( owner, num=0) {
|
export function vaultAddress( owner, num=0) {
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
// console.log('vaultAddress', owner, s.factory, s.vaultInitCodeHash)
|
console.log('vaultAddress', owner, s.factory, s.vaultInitCodeHash)
|
||||||
if( !owner )
|
if( !owner )
|
||||||
return null
|
return null
|
||||||
const salt = ethers.solidityPackedKeccak256(['address','uint8'],[owner,num])
|
const salt = ethers.solidityPackedKeccak256(['address','uint8'],[owner,num])
|
||||||
|
|||||||
@@ -86,16 +86,91 @@ export function newTranche({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// enum Exchange {
|
|
||||||
// UniswapV2,
|
|
||||||
// UniswapV3
|
|
||||||
// }
|
|
||||||
export const Exchange = {
|
export const Exchange = {
|
||||||
UniswapV2: 0,
|
UniswapV2: 0,
|
||||||
UniswapV3: 1,
|
UniswapV3: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sqrtX96(value) {
|
export const OrderState = {
|
||||||
return BigInt(Math.round(Math.sqrt(value * 2 ** (96*2))))
|
Signing: -1,
|
||||||
|
Unknown: 0,
|
||||||
|
Open: 1,
|
||||||
|
Canceled: 2,
|
||||||
|
Filled: 3,
|
||||||
|
Expired: 4,
|
||||||
|
Underfunded: 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function parseOrderStatus(status) {
|
||||||
|
let [
|
||||||
|
order,
|
||||||
|
state,
|
||||||
|
start,
|
||||||
|
ocoGroup,
|
||||||
|
filledIn,
|
||||||
|
filledOut,
|
||||||
|
trancheFilledIn,
|
||||||
|
trancheFilledOut,
|
||||||
|
] = status
|
||||||
|
order = parseOrder(order)
|
||||||
|
filledIn = BigInt(filledIn)
|
||||||
|
filledOut = BigInt(filledOut)
|
||||||
|
trancheFilledIn = trancheFilledIn.map((f)=>BigInt(f))
|
||||||
|
trancheFilledOut = trancheFilledOut.map((f)=>BigInt(f))
|
||||||
|
return {
|
||||||
|
order, state, start, ocoGroup, filledIn, filledOut, trancheFilledIn, trancheFilledOut,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function parseOrder(order) {
|
||||||
|
let [
|
||||||
|
tokenIn,
|
||||||
|
tokenOut,
|
||||||
|
route,
|
||||||
|
amount,
|
||||||
|
minFillAmount,
|
||||||
|
amountIsInput,
|
||||||
|
outputDirectlyToOwner,
|
||||||
|
chainOrder,
|
||||||
|
tranches,
|
||||||
|
] = order
|
||||||
|
route = parseRoute(route)
|
||||||
|
amount = BigInt(amount)
|
||||||
|
minFillAmount = BigInt(minFillAmount)
|
||||||
|
tranches = tranches.map(parseTranche)
|
||||||
|
return {
|
||||||
|
tokenIn, tokenOut, route, amount, minFillAmount, amountIsInput, outputDirectlyToOwner, chainOrder, tranches
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseRoute(route) {
|
||||||
|
let [exchange, fee] = route
|
||||||
|
return {exchange, fee} // todo enum?
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseTranche(tranche) {
|
||||||
|
let [
|
||||||
|
fraction,
|
||||||
|
startTimeIsRelative,
|
||||||
|
endTimeIsRelative,
|
||||||
|
minIsBarrier,
|
||||||
|
maxIsBarrier,
|
||||||
|
marketOrder,
|
||||||
|
_reserved5,
|
||||||
|
_reserved6,
|
||||||
|
_reserved7,
|
||||||
|
_reserved8,
|
||||||
|
_reserved16,
|
||||||
|
startTime,
|
||||||
|
endTime,
|
||||||
|
minIntercept,
|
||||||
|
minSlope,
|
||||||
|
maxIntercept,
|
||||||
|
maxSlope,
|
||||||
|
] = tranche
|
||||||
|
return {
|
||||||
|
fraction, startTimeIsRelative, endTimeIsRelative, minIsBarrier, maxIsBarrier, marketOrder,
|
||||||
|
startTime, endTime, minIntercept, minSlope, maxIntercept, maxSlope,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ import {ethers} from "ethers";
|
|||||||
|
|
||||||
// synchronous version may return null but will trigger a lookup
|
// synchronous version may return null but will trigger a lookup
|
||||||
export function token(addr) {
|
export function token(addr) {
|
||||||
|
if( !addr ) {
|
||||||
|
// console.log('ignoring call to token', addr)
|
||||||
|
return null
|
||||||
|
}
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
if( !(addr in s.tokens) ) {
|
if( !(addr in s.tokens) ) {
|
||||||
getToken(addr)
|
getToken(addr)
|
||||||
@@ -23,35 +27,48 @@ export async function getToken(addr) {
|
|||||||
return s.tokens[addr]
|
return s.tokens[addr]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const _inFlightLookups = {}
|
||||||
|
|
||||||
export async function addExtraToken(addr) {
|
export async function addExtraToken(addr) {
|
||||||
const prom = new Promise((resolve) => {
|
if( !addr ) {
|
||||||
const s = useStore()
|
console.log('ignoring call to add extra token', addr)
|
||||||
const chainId = s.chainId
|
return
|
||||||
console.log('querying token', addr)
|
}
|
||||||
socket.emit('lookupToken', chainId, addr, (info) => {
|
if( !_inFlightLookups[addr] ) {
|
||||||
console.log('server token info', info)
|
_inFlightLookups[addr] = true
|
||||||
if (info !== null) {
|
const prom = new Promise((resolve) => {
|
||||||
s.addToken(chainId, info)
|
const s = useStore()
|
||||||
resolve(info)
|
const chainId = s.chainId
|
||||||
}
|
console.log('querying token', addr)
|
||||||
else {
|
socket.emit('lookupToken', chainId, addr, (info) => {
|
||||||
if( s.provider===null ) {
|
console.log('server token info', addr, info)
|
||||||
console.log('warning: token lookup cancelled due to null provider', addr)
|
if (info !== null) {
|
||||||
resolve(null)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const token = new ethers.Contract(addr, erc20Abi, s.provider)
|
|
||||||
Promise.all( [token.symbol(), token.decimals()] ).then((symbol,decimals)=>{
|
|
||||||
info = {
|
|
||||||
address: addr,
|
|
||||||
symbol: symbol,
|
|
||||||
decimals: decimals,
|
|
||||||
}
|
|
||||||
s.addToken(chainId, info)
|
s.addToken(chainId, info)
|
||||||
resolve(info)
|
resolve(info)
|
||||||
})
|
}
|
||||||
}
|
else {
|
||||||
|
if( s.provider===null ) {
|
||||||
|
console.log('warning: token lookup cancelled due to null provider', addr)
|
||||||
|
resolve(null)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const token = new ethers.Contract(addr, erc20Abi, s.provider)
|
||||||
|
Promise.all( [token.symbol(), token.decimals()] ).then((symbol,decimals)=>{
|
||||||
|
info = {
|
||||||
|
address: addr,
|
||||||
|
symbol: symbol,
|
||||||
|
decimals: decimals,
|
||||||
|
}
|
||||||
|
s.addToken(chainId, info)
|
||||||
|
resolve(info)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
const result = await prom
|
||||||
return await prom
|
delete _inFlightLookups[addr]
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ let pendingOrders = []
|
|||||||
|
|
||||||
function discoverVaults(owner) {
|
function discoverVaults(owner) {
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
|
console.log('discoverVaults', owner)
|
||||||
if( owner === null )
|
if( owner === null )
|
||||||
s.vaults = []
|
s.vaults = []
|
||||||
else
|
else
|
||||||
@@ -112,6 +113,7 @@ function discoverVaults(owner) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function _discoverVaults(owner) {
|
async function _discoverVaults(owner) {
|
||||||
|
console.log('_discoverVaults',owner)
|
||||||
const result = []
|
const result = []
|
||||||
// todo multi-vault scan
|
// todo multi-vault scan
|
||||||
const num = 0
|
const num = 0
|
||||||
@@ -174,6 +176,7 @@ export async function pendOrder(order) {
|
|||||||
|
|
||||||
|
|
||||||
export async function cancelOrder(vault, orderIndex) {
|
export async function cancelOrder(vault, orderIndex) {
|
||||||
|
console.log('cancel order', vault, orderIndex)
|
||||||
pendTransaction(async (signer)=> {
|
pendTransaction(async (signer)=> {
|
||||||
const contract = contractOrNull(vault, vaultAbi, signer)
|
const contract = contractOrNull(vault, vaultAbi, signer)
|
||||||
if( contract === null ) {
|
if( contract === null ) {
|
||||||
|
|||||||
@@ -2,11 +2,9 @@
|
|||||||
<v-table>
|
<v-table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="num d-none d-md-table-cell">#</th> <!-- todo placement date instead -->
|
<th class="num d-none d-md-table-cell">Date</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">Input</th>
|
||||||
<th class="token d-none d-sm-table-cell">Sell</th>
|
<th class="token d-none d-sm-table-cell">Output</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">Remaining</th>
|
||||||
<th class="amount">Filled</th>
|
<th class="amount">Filled</th>
|
||||||
<th class="amount d-none d-md-table-cell">Avg Price</th>
|
<th class="amount d-none d-md-table-cell">Avg Price</th>
|
||||||
@@ -15,33 +13,32 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="[index, inTokenAddr, outTokenAddr, amount, amountTokenAddr, filled, avgPrice, state] in orders">
|
<tr v-for="st of orders">
|
||||||
<td class="d-none d-md-table-cell" style="width: 1em">{{parseInt(index)+1}}</td>
|
<td class="">{{st.start}}</td>
|
||||||
<td class="token d-none d-sm-table-cell">{{tokenSymbol(inTokenAddr)}}</td>
|
<td class="amount"><suspense><token-amount :addr="st.order.tokenIn" :amount="st.order.amountIsInput ? st.order.amount : null"/></suspense></td>
|
||||||
<td class="token d-none d-sm-table-cell">{{tokenSymbol(outTokenAddr)}}</td>
|
<td class="amount"><suspense><token-amount :addr="st.order.tokenOut" :amount="!st.order.amountIsInput ? st.order.amount : null"/></suspense></td>
|
||||||
<td class="pair d-sm-none">Buy {{tokenSymbol(inTokenAddr)}}<br/>Sell {{tokenSymbol(outTokenAddr)}}</td>
|
<td class="amount"><suspense><token-amount :addr="st.amountToken" :amount="st.order.amount-st.filled"/></suspense></td>
|
||||||
<td class="amount d-none d-md-table-cell">{{tokenAmount(amountTokenAddr, amount)}}</td>
|
<td class="amount"><suspense><token-amount :addr="st.amountToken" :amount="st.filled"/></suspense></td>
|
||||||
<td class="amount">{{tokenAmount(amountTokenAddr, amount-filled)}}</td>
|
<td class="amount">
|
||||||
<td class="amount">{{tokenAmount(amountTokenAddr, filled)}}</td>
|
{{pairPrice(st.order.tokenIn, st.order.tokenOut, vaultAddr, st.index, st.avg)}}
|
||||||
<td class="amount d-none d-md-table-cell">
|
<btn v-if="pairPrice(st.order.tokenIn, st.order.tokenOut, vaultAddr, st.index, st.avg)!==''" size="small"
|
||||||
{{pairPrice(inTokenAddr, outTokenAddr, vaultAddr, index, avgPrice)}}
|
|
||||||
<btn v-if="pairPrice(inTokenAddr, outTokenAddr, vaultAddr, index, avgPrice)!==''" size="small"
|
|
||||||
variant="plain"
|
variant="plain"
|
||||||
@click="inverted[[vaultAddr,index]] = !inverted[[vaultAddr,index]]">
|
@click="inverted[[vaultAddr,st.index]] = !inverted[[vaultAddr,st.index]]">
|
||||||
{{pair(inTokenAddr, outTokenAddr, vaultAddr,index)}}
|
{{pair(st.order.tokenIn, st.order.tokenOut, vaultAddr, st.index)}}
|
||||||
</btn>
|
</btn>
|
||||||
</td>
|
</td>
|
||||||
<td class="status">
|
<td class="status">
|
||||||
<v-chip v-if="state===-1" prepend-icon="mdi-signature" color="yellow">Signing</v-chip>
|
<v-chip v-if="st.state===OrderState.Signing" 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>
|
<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="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="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="state===0" class="d-sm-none" variant="plain" icon="mdi-cancel" color="red" @click="cancelOrder(vaultAddr,index)"/>
|
<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="state===1" prepend-icon="mdi-cancel" color="red">Canceled</v-chip>
|
<v-chip v-if="st.state===OrderState.Canceled" 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="st.state===OrderState.Filled" 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.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>
|
||||||
<td class="cancel d-none d-lg-table-cell">
|
<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>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
@@ -51,10 +48,13 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {FixedNumber} from "ethers";
|
import {FixedNumber} from "ethers";
|
||||||
import {useStore} from "@/store/store";
|
import {useStore} from "@/store/store";
|
||||||
import {computed, reactive} from "vue";
|
import {computed, defineAsyncComponent, reactive} from "vue";
|
||||||
import {token} from "@/blockchain/token.js";
|
import {token} from "@/blockchain/token.js";
|
||||||
import Btn from "@/components/Btn.vue"
|
import Btn from "@/components/Btn.vue"
|
||||||
import {cancelOrder} from "@/blockchain/wallet.js";
|
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 s = useStore()
|
||||||
const props = defineProps(['vault'])
|
const props = defineProps(['vault'])
|
||||||
@@ -66,15 +66,20 @@ function tokenSymbol(addr) {
|
|||||||
return t ? t.symbol : addr
|
return t ? t.symbol : addr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
function tokenAmount(tokenAddr, amount) {
|
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)
|
const t = token(tokenAddr)
|
||||||
if( !t )
|
if( !t )
|
||||||
return ''
|
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})
|
const amt = FixedNumber.fromValue(amount, t.decimals, {width:256, decimals:t.decimals, signed:false})
|
||||||
return `${amt} ${t.symbol}`
|
return `${amt} ${t.symbol}`
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// todo create a Price component that keeps inversion flags in the store and defaults to stablecoins as the quote
|
// 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) {
|
function pairPrice(inTokenAddr, outTokenAddr, vaultAddr, index, price) {
|
||||||
@@ -110,43 +115,94 @@ function pair(inTokenAddr, outTokenAddr, vaultAddr, index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const orders = computed(()=>{
|
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 = []
|
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 ) {
|
if( vaultAddr.value in s.orders ) {
|
||||||
for (const [index, status] of Object.entries(s.orders[vaultAddr.value]).reverse()) {
|
for (const [index, status] of Object.entries(s.orders[vaultAddr.value]).reverse()) {
|
||||||
// console.log('order status', status)
|
const st = {...status}
|
||||||
// [index, symbolA, symbolB, amount, amountSymbol, filled]
|
console.log('order status', st)
|
||||||
const inTokenAddr = status[0][0]
|
const o = {...st.order}
|
||||||
const outTokenAddr = status[0][1]
|
st.order = o
|
||||||
const amountIsInput = !!(status[0][4])
|
result.push(st)
|
||||||
const amountTokenAddr = amountIsInput ? inTokenAddr : outTokenAddr
|
st.index = parseInt(index)
|
||||||
// console.log('getamount', status[0][3])
|
o.tranches = o.tranches.map((tranche)=>{
|
||||||
const amount = BigInt(status[0][3])
|
const t = {...tranche}
|
||||||
// console.log('amount', amount)
|
t.startTime = t.startTimeIsRelative ? intervalString(t.startTime) : dateString(t.startTime)
|
||||||
// console.log('getfilled', amountIsInput ? status[4] : status[5])
|
t.endTime = t.endTimeIsRelative ? intervalString(t.endTime) : dateString(t.endTime)
|
||||||
const filled = BigInt(amountIsInput ? status[4] : status[5])
|
return t
|
||||||
// console.log('filled', filled)
|
})
|
||||||
const amountIn = BigInt(status[4])
|
st.start = dateString(st.start)
|
||||||
const amountOut = BigInt(status[5])
|
|
||||||
const fmtX18 = {decimals: 18, width: 256, signed: false};
|
const fmtX18 = {decimals: 18, width: 256, signed: false};
|
||||||
const avg = !amountIn || !amountOut ? null :
|
st.filled = st.amountIsInput ? st.filledIn : st.filledOut
|
||||||
FixedNumber.fromValue(status[5], 0, fmtX18).div(FixedNumber.fromValue(status[4], 0, fmtX18))
|
st.avg = BigInt(st.filled) === 0n ? null :
|
||||||
const state = status[1]
|
FixedNumber.fromValue(status.filledOut, 0, fmtX18)
|
||||||
result.push([index, inTokenAddr, outTokenAddr, amount, amountTokenAddr, filled, avg, state])
|
.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
|
return result
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
27
src/components/TokenAmount.vue
Normal file
27
src/components/TokenAmount.vue
Normal 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>
|
||||||
@@ -36,7 +36,6 @@ const fixed = computed(() => FixedNumber.fromValue(props.amount, token.decimals,
|
|||||||
decimals: token.decimals
|
decimals: token.decimals
|
||||||
}))
|
}))
|
||||||
const imageSrc = computed(() => token.image)
|
const imageSrc = computed(() => token.image)
|
||||||
const withdrawing = ref(false)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -83,10 +83,8 @@ import {computed, defineAsyncComponent, ref} from "vue";
|
|||||||
import {vaultAddress} from "@/blockchain/contract.js";
|
import {vaultAddress} from "@/blockchain/contract.js";
|
||||||
import {ensureVault} from "@/blockchain/wallet.js";
|
import {ensureVault} from "@/blockchain/wallet.js";
|
||||||
import CopyButton from "@/components/CopyButton.vue";
|
import CopyButton from "@/components/CopyButton.vue";
|
||||||
import NeedsProvider from "@/components/NeedsProvider.vue";
|
|
||||||
import Withdraw from "@/components/Withdraw.vue";
|
import Withdraw from "@/components/Withdraw.vue";
|
||||||
import PhoneCard from "@/components/PhoneCard.vue";
|
import PhoneCard from "@/components/PhoneCard.vue";
|
||||||
import Btn from "@/components/Btn.vue";
|
|
||||||
|
|
||||||
const TokenRow = defineAsyncComponent(()=>import('./TokenRow.vue'))
|
const TokenRow = defineAsyncComponent(()=>import('./TokenRow.vue'))
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
|
|||||||
18
src/misc.js
18
src/misc.js
@@ -59,3 +59,21 @@ export function routeInverted(route) {
|
|||||||
return route && (route.token0 === s.tokenA) === s.inverted
|
return route && (route.token0 === s.tokenA) === s.inverted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function intervalString(seconds) {
|
||||||
|
if( seconds < 1 )
|
||||||
|
return 'now'
|
||||||
|
else if( seconds < 60 )
|
||||||
|
return `${seconds} seconds`
|
||||||
|
else if( seconds < 3600 )
|
||||||
|
return `${(seconds/60).toFixed(1)} minutes`
|
||||||
|
else if( seconds < 86400 )
|
||||||
|
return `${(seconds/3600).toFixed(1)} hours`
|
||||||
|
else
|
||||||
|
return `${(seconds/86400).toFixed(1)} days`
|
||||||
|
}
|
||||||
|
|
||||||
|
const _dateFormat = new Intl.DateTimeFormat( undefined, {dateStyle: 'medium', timeStyle: 'short'})
|
||||||
|
export function dateString(seconds) {
|
||||||
|
const date = new Date(seconds*1000)
|
||||||
|
return _dateFormat.format(date)
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import {useStore} from "@/store/store.js";
|
|||||||
import {flushOrders, onChainChanged} from "@/blockchain/wallet.js";
|
import {flushOrders, onChainChanged} from "@/blockchain/wallet.js";
|
||||||
import {ethers} from "ethers";
|
import {ethers} from "ethers";
|
||||||
import {applyFills} from "@/blockchain/common.js";
|
import {applyFills} from "@/blockchain/common.js";
|
||||||
|
import {parseOrderStatus} from "@/blockchain/orderlib.js";
|
||||||
|
|
||||||
export const socket = io(import.meta.env.VITE_WS_URL || undefined, {transports: ["websocket"]})
|
export const socket = io(import.meta.env.VITE_WS_URL || undefined, {transports: ["websocket"]})
|
||||||
|
|
||||||
@@ -62,13 +63,16 @@ function handleOrderStatus(chainId, vault, orderIndex, status) {
|
|||||||
const s = useStore()
|
const s = useStore()
|
||||||
if( s.chainId.value !== chainId )
|
if( s.chainId.value !== chainId )
|
||||||
return
|
return
|
||||||
console.log('o', chainId, vault, orderIndex, status)
|
// message 'o' is a single order status
|
||||||
|
const parsed = parseOrderStatus(status);
|
||||||
|
console.log('o', chainId, vault, orderIndex, status, parsed)
|
||||||
if( !(vault in s.orders) )
|
if( !(vault in s.orders) )
|
||||||
s.orders[vault] = {}
|
s.orders[vault] = {}
|
||||||
s.orders[vault][orderIndex] = status
|
s.orders[vault][orderIndex] = parsed
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.on('os', (chainId, vault, orders) => {
|
socket.on('os', (chainId, vault, orders) => {
|
||||||
|
// message 'os' has multiple order statuses
|
||||||
console.log('os', orders)
|
console.log('os', orders)
|
||||||
for( const [orderIndex, status] of orders )
|
for( const [orderIndex, status] of orders )
|
||||||
handleOrderStatus(chainId, vault, orderIndex, status)
|
handleOrderStatus(chainId, vault, orderIndex, status)
|
||||||
|
|||||||
@@ -97,14 +97,13 @@ export const useStore = defineStore('app', ()=> {
|
|||||||
this.errors = result
|
this.errors = result
|
||||||
}
|
}
|
||||||
function addToken(chainId, info) {
|
function addToken(chainId, info) {
|
||||||
this.$patch(() => {
|
let extras = this.extraTokens[chainId]
|
||||||
let extras = extraTokens[chainId]
|
if (extras === undefined) {
|
||||||
if (extras === undefined) {
|
extras = {}
|
||||||
extras = {}
|
this.extraTokens[chainId] = extras
|
||||||
extraTokens[chainId] = extras
|
}
|
||||||
}
|
extras[info.address] = info
|
||||||
extras[info.address] = info
|
this.extraTokens = extras
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user