new pool selection dialog and liquidity
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import {useChartOrderStore} from "@/orderbuild.js";
|
import {useChartOrderStore} from "@/orderbuild.js";
|
||||||
import {invokeCallbacks, prototype} from "@/common.js";
|
import {invokeCallbacks, prototype} from "@/common.js";
|
||||||
import {DataFeed, defaultSymbol, feelessTickerKey, getAllSymbols, lookupSymbol} from "@/charts/datafeed.js";
|
import {DataFeed, defaultSymbol, feelessTickerKey, getAllSymbols, lookupSymbol} from "@/charts/datafeed.js";
|
||||||
import {intervalToSeconds, SingletonCoroutine} from "@/misc.js";
|
import {intervalToSeconds, SingletonCoroutine, toHuman, toPrecision} from "@/misc.js";
|
||||||
import {usePrefStore, useStore} from "@/store/store.js";
|
import {usePrefStore, useStore} from "@/store/store.js";
|
||||||
import {tvCustomThemes} from "../../theme.js";
|
import {tvCustomThemes} from "../../theme.js";
|
||||||
|
|
||||||
@@ -83,51 +83,49 @@ const subscribeEvents = [
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
let feeDropdown = null
|
let poolButtonTextElement = null
|
||||||
|
|
||||||
export function initFeeDropdown(w) {
|
export function initFeeDropdown() {
|
||||||
widget = w
|
const button = widget.createButton()
|
||||||
widget.createDropdown(
|
button.setAttribute('title', 'See Pool Info and Choose Fee');
|
||||||
{
|
button.addEventListener('click', function() { co.showPoolSelection = true });
|
||||||
title: 'Fees',
|
button.style.height = '34px';
|
||||||
tooltip: 'Choose Fee Tier',
|
button.style.display = 'flex';
|
||||||
items: [/*{title: 'Automatic Fee Selection', onSelect: () => {log('autofees')}}*/],
|
button.style.alignItems = 'center';
|
||||||
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28"><g fill="none" stroke="currentColor"><circle cx="10" cy="10" r="2.5"/><circle cx="18" cy="18" r="2.5"/><path stroke-linecap="square" d="M17.5 7.5l-7 13"/></g></svg>`,
|
button.addEventListener('mouseover', () => {
|
||||||
}
|
button.style.backgroundColor = 'rgb(60,60,60)';
|
||||||
).then(dropdown => {
|
});
|
||||||
feeDropdown = dropdown;
|
button.addEventListener('mouseout', () => {
|
||||||
updateFeeDropdown()
|
button.style.backgroundColor = '';
|
||||||
})
|
});
|
||||||
|
button.id = 'pool-button'
|
||||||
|
button.style.margin = '2px 0';
|
||||||
|
button.style.borderRadius = '4px';
|
||||||
|
button.classList.add('pool-button')
|
||||||
|
|
||||||
|
const span = document.createElement('span');
|
||||||
|
span.textContent = 'Pool';
|
||||||
|
span.style.marginY = 'auto';
|
||||||
|
button.appendChild(span);
|
||||||
|
poolButtonTextElement = span
|
||||||
|
|
||||||
|
updateFeeDropdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateFeeDropdown() {
|
export function updateFeeDropdown() {
|
||||||
if (feeDropdown === null) return
|
if (poolButtonTextElement===null) return
|
||||||
const symbolItem = useChartOrderStore().selectedSymbol
|
const symbolItem = useChartOrderStore().selectedSymbol
|
||||||
let items
|
let text = 'Pool '
|
||||||
if (symbolItem === null)
|
text += (symbolItem.fee / 10000).toFixed(2) + '%'
|
||||||
items = [{title: '0.00%'}]
|
const index = symbolItem.feeGroup.findIndex((p) => p[1] === symbolItem.fee)
|
||||||
else {
|
if (symbolItem.liquiditySymbol) {
|
||||||
const feeGroup = symbolItem.feeGroup
|
const liq = symbolItem.liquidities[index]
|
||||||
items = feeGroup.map((p) => {
|
if (symbolItem.liquiditySymbol === 'USD')
|
||||||
const [_addr, fee] = p
|
text += ` $${toHuman(liq)}`
|
||||||
return {
|
else
|
||||||
title: (fee / 10000).toFixed(2) + '%',
|
text = ` ${toHuman(liq)} ${symbolItem.liquiditySymbol}`
|
||||||
onSelect: ()=>{
|
|
||||||
if (fee !== symbolItem.fee)
|
|
||||||
selectPool(fee)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
feeDropdown.applyOptions({items})
|
poolButtonTextElement.textContent = text
|
||||||
}
|
|
||||||
|
|
||||||
function selectPool(fee) {
|
|
||||||
const co = useChartOrderStore();
|
|
||||||
const s = co.selectedSymbol;
|
|
||||||
const ticker = feelessTickerKey(s.ticker) + '|' + fee
|
|
||||||
if (ticker !== s.ticker)
|
|
||||||
setSymbolTicker(ticker).catch((e)=>console.error('Could not change TV symbol to', ticker))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initWidget(el) {
|
export function initWidget(el) {
|
||||||
@@ -145,9 +143,9 @@ export function initWidget(el) {
|
|||||||
container: el,
|
container: el,
|
||||||
datafeed: DataFeed, // use this for ohlc
|
datafeed: DataFeed, // use this for ohlc
|
||||||
locale: "en",
|
locale: "en",
|
||||||
disabled_features: [],
|
disabled_features: ['main_series_scale_menu',],
|
||||||
enabled_features: ['saveload_separate_drawings_storage'],
|
enabled_features: ['saveload_separate_drawings_storage',],
|
||||||
drawings_access: {type: 'white', tools: [],}, // show no tools
|
// drawings_access: {type: 'white', tools: [],}, // show no tools
|
||||||
custom_themes: tvCustomThemes,
|
custom_themes: tvCustomThemes,
|
||||||
theme: useStore().theme,
|
theme: useStore().theme,
|
||||||
timezone: prefs.timezone,
|
timezone: prefs.timezone,
|
||||||
@@ -155,7 +153,7 @@ export function initWidget(el) {
|
|||||||
// Chart Overrides
|
// Chart Overrides
|
||||||
// https://www.tradingview.com/charting-library-docs/latest/customization/overrides/chart-overrides
|
// https://www.tradingview.com/charting-library-docs/latest/customization/overrides/chart-overrides
|
||||||
overrides: {
|
overrides: {
|
||||||
// "mainSeriesProperties.priceAxisProperties.log": false,
|
"mainSeriesProperties.priceAxisProperties.log": false,
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -168,7 +166,7 @@ export function initWidget(el) {
|
|||||||
widget.subscribe('onSelectedLineToolChanged', onSelectedLineToolChanged)
|
widget.subscribe('onSelectedLineToolChanged', onSelectedLineToolChanged)
|
||||||
widget.subscribe('mouse_down', mouseDown)
|
widget.subscribe('mouse_down', mouseDown)
|
||||||
widget.subscribe('mouse_up', mouseUp)
|
widget.subscribe('mouse_up', mouseUp)
|
||||||
widget.headerReady().then(()=>initFeeDropdown(widget))
|
widget.headerReady().then(()=>initFeeDropdown())
|
||||||
widget.onChartReady(initChart)
|
widget.onChartReady(initChart)
|
||||||
console.log('tv widget initialized')
|
console.log('tv widget initialized')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import {useStore} from "@/store/store.js";
|
|||||||
import {subOHLC, unsubOHLC} from "@/blockchain/ohlcs.js";
|
import {subOHLC, unsubOHLC} from "@/blockchain/ohlcs.js";
|
||||||
import {ohlcStart} from "@/charts/chart-misc.js";
|
import {ohlcStart} from "@/charts/chart-misc.js";
|
||||||
|
|
||||||
import {timestamp} from "@/common.js";
|
import {timestamp, USD_FIAT} from "@/common.js";
|
||||||
|
import {erc20Contract} from "@/blockchain/contract.js";
|
||||||
|
import {provider} from "@/blockchain/wallet.js";
|
||||||
|
|
||||||
const DEBUG_LOGGING = false
|
const DEBUG_LOGGING = false
|
||||||
const log = DEBUG_LOGGING ? console.log : ()=>{}
|
const log = DEBUG_LOGGING ? console.log : ()=>{}
|
||||||
@@ -131,9 +133,9 @@ function addSymbol(chainId, p, base, quote, inverted) {
|
|||||||
else
|
else
|
||||||
feeGroups[feelessKey] = [[symbolInfo.address, symbolInfo.fee]]
|
feeGroups[feelessKey] = [[symbolInfo.address, symbolInfo.fee]]
|
||||||
symbolInfo.feeGroup = feeGroups[feelessKey]
|
symbolInfo.feeGroup = feeGroups[feelessKey]
|
||||||
if (defaultSymbol===null) {
|
// if (defaultSymbol===null) {
|
||||||
console.log(`invertedDefault(${symbolInfo.base.s}, ${symbolInfo.quote.s})`,invertedDefault(symbolInfo.base.a, symbolInfo.quote.a))
|
// console.log(`invertedDefault(${symbolInfo.base.s}, ${symbolInfo.quote.s})`,invertedDefault(symbolInfo.base.a, symbolInfo.quote.a))
|
||||||
}
|
// }
|
||||||
if (defaultSymbol===null && !invertedDefault(symbolInfo.base.a, symbolInfo.quote.a)) {
|
if (defaultSymbol===null && !invertedDefault(symbolInfo.base.a, symbolInfo.quote.a)) {
|
||||||
console.log('setting default symbol', symbolInfo.base.s, symbolInfo.quote.s, symbolInfo.base.a, symbolInfo.quote.a)
|
console.log('setting default symbol', symbolInfo.base.s, symbolInfo.quote.s, symbolInfo.base.a, symbolInfo.quote.a)
|
||||||
defaultSymbol = _symbols[ticker]
|
defaultSymbol = _symbols[ticker]
|
||||||
@@ -384,12 +386,45 @@ export const DataFeed = {
|
|||||||
}
|
}
|
||||||
const co = useChartOrderStore();
|
const co = useChartOrderStore();
|
||||||
co.selectedSymbol = symbolItem
|
co.selectedSymbol = symbolItem
|
||||||
const feelessKey = feelessTickerKey(symbolItem.ticker)
|
|
||||||
const symbolsByFee = feeGroups[feelessKey]
|
let ticker = symbolItem.ticker
|
||||||
symbolsByFee.sort((a,b)=>a.fee-b.fee)
|
try {
|
||||||
const pool = symbolsByFee[Math.floor((symbolsByFee.length - 1)/2)] // median rounded down
|
if (!symbolItem.liquiditySymbol) {
|
||||||
// noinspection JSValidateTypes
|
// fetch liquidities and cache on the symbolItem
|
||||||
co.selectedPool = pool // todo remove
|
const inv = invertedDefault(symbolItem.base.a, symbolItem.quote.a)
|
||||||
|
const markToken = inv ? symbolItem.base : symbolItem.quote
|
||||||
|
const mark = useStore().markPrice(markToken.a)
|
||||||
|
const token = await erc20Contract(markToken.a, provider)
|
||||||
|
const liquidities = await Promise.all(symbolItem.feeGroup.map(
|
||||||
|
async ([addr, fee]) => await token.balanceOf(addr)
|
||||||
|
))
|
||||||
|
symbolItem.liquidities = liquidities.map(l => Number(l / 10n ** BigInt(markToken.d)))
|
||||||
|
if (mark) {
|
||||||
|
symbolItem.liquidities = symbolItem.liquidities.map(l => l * mark)
|
||||||
|
symbolItem.liquiditySymbol = 'USD'
|
||||||
|
} else {
|
||||||
|
symbolItem.liquiditySymbol = symbolItem.quote.s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const liqsAndFees = []
|
||||||
|
for (let i=0; i<symbolItem.feeGroup.length; i++) {
|
||||||
|
const [addr, fee] = symbolItem.feeGroup[i]
|
||||||
|
const liq = symbolItem.liquidities[i]
|
||||||
|
liqsAndFees.push([liq, fee])
|
||||||
|
if (fee === symbolItem.fee)
|
||||||
|
symbolItem.liquidity = liq
|
||||||
|
}
|
||||||
|
liqsAndFees.sort((a,b) => b[0] - a[0])
|
||||||
|
const highestLiquidityFee = liqsAndFees[0][1]
|
||||||
|
// console.log('liquidities', liqsAndFees)
|
||||||
|
// console.log('best liquidity', highestLiquidityFee, liqsAndFees[0][0], symbolItem.liquiditySymbol)
|
||||||
|
ticker = feelessTickerKey(ticker) + '|' + highestLiquidityFee
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
// use the median fee group instead
|
||||||
|
console.log('liquidity fetch error', error)
|
||||||
|
}
|
||||||
|
|
||||||
// LibrarySymbolInfo
|
// LibrarySymbolInfo
|
||||||
// https://www.tradingview.com/charting-library-docs/latest/api/interfaces/Charting_Library.LibrarySymbolInfo
|
// https://www.tradingview.com/charting-library-docs/latest/api/interfaces/Charting_Library.LibrarySymbolInfo
|
||||||
const symbolInfo = {
|
const symbolInfo = {
|
||||||
|
|||||||
@@ -339,7 +339,7 @@ export class Shape {
|
|||||||
|
|
||||||
onPoints(points) {} // the control points of an existing shape were changed
|
onPoints(points) {} // the control points of an existing shape were changed
|
||||||
|
|
||||||
onDrag(points) { console.log('shape ondrag'); this.onPoints(points) }
|
onDrag(points) { this.onPoints(points) }
|
||||||
|
|
||||||
setProps(props) {
|
setProps(props) {
|
||||||
if (!props || Object.keys(props).length===0) return
|
if (!props || Object.keys(props).length===0) return
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
export const NATIVE_TOKEN = '0x0000000000000000000000000000000000000001'
|
export const NATIVE_TOKEN = '0x0000000000000000000000000000000000000001'
|
||||||
|
export const USD_FIAT = '0x0000000000000000000000000000000000000055' // We use 0x55 (ASCII 'U') to indicate the use of fiat USD
|
||||||
|
|
||||||
export function mixin(child, ...parents) {
|
export function mixin(child, ...parents) {
|
||||||
// child is modified directly, assigning fields from parents that are missing in child. parents fields are
|
// child is modified directly, assigning fields from parents that are missing in child. parents fields are
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-tooltip :model-value="!error&&copied" :open-on-hover="false" location="top">
|
<v-tooltip :model-value="!error&&copied" :open-on-hover="false" location="top">
|
||||||
<template v-slot:activator="{ props }">
|
<template v-slot:activator="{ props }">
|
||||||
<span v-bind="props" style="cursor: pointer" @click="copy()">
|
<div class="d-inline-flex align-center" v-bind="props" style="cursor: pointer" @click="copy()">
|
||||||
|
<slot>
|
||||||
|
<span :style="{maxWidth:width}" style="display: inline-block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">{{ text }}</span>
|
||||||
|
</slot>
|
||||||
<v-btn v-bind="props" v-if="permitted" rounded variant="text" size="small" density="compact" @click="copy()"
|
<v-btn v-bind="props" v-if="permitted" rounded variant="text" size="small" density="compact" @click="copy()"
|
||||||
:class="error?'error':copied?'success':''"
|
:class="error?'error':copied?'success':''"
|
||||||
:icon="error?'mdi-close-box-outline':copied?'mdi-check-circle-outline':'mdi-content-copy'"
|
:icon="error?'mdi-close-box-outline':copied?'mdi-check-circle-outline':'mdi-content-copy'"
|
||||||
:text="showText?text:''"
|
:text="showText?text:''"
|
||||||
/>
|
/>
|
||||||
<slot>{{text}}</slot>
|
</div>
|
||||||
</span>
|
|
||||||
</template>
|
</template>
|
||||||
<span>Copied!</span>
|
<span>Copied!</span>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
@@ -17,7 +19,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref} from "vue";
|
import {ref} from "vue";
|
||||||
|
|
||||||
const props = defineProps({text:String, showText:{default:false}})
|
const props = defineProps({text:String, showText:{default:false}, width: {default:null}})
|
||||||
const permitted = ref(true)
|
const permitted = ref(true)
|
||||||
const copied = ref(false)
|
const copied = ref(false)
|
||||||
const error = ref(false)
|
const error = ref(false)
|
||||||
|
|||||||
78
src/components/PoolSelectionDialog.vue
Normal file
78
src/components/PoolSelectionDialog.vue
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
<template>
|
||||||
|
<v-dialog v-model="co.showPoolSelection" max-width="300">
|
||||||
|
<v-card title="Pool Selection">
|
||||||
|
<v-card-text>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>Pool</td><td><scanner-button :addr="co.selectedSymbol.address"/></td></tr>
|
||||||
|
<tr><td>{{ co.selectedSymbol.base.s }}</td><td><scanner-button :addr="co.selectedSymbol.base.a"/></td></tr>
|
||||||
|
<tr><td>{{ co.selectedSymbol.quote.s }}</td><td><scanner-button :addr="co.selectedSymbol.quote.a"/></td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<v-table class="mt-4">
|
||||||
|
<thead>
|
||||||
|
<tr><th>Selected</th><th>Fee</th><td>Liquidity</td></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="([addr,fee],i) in co.selectedSymbol.feeGroup"
|
||||||
|
:class="co.selectedSymbol.fee === fee ? 'selected' : 'selectable'" @click="selectFee(fee)">
|
||||||
|
<td><v-icon v-if="co.selectedSymbol.fee===fee" icon="mdi-check"/></td>
|
||||||
|
<td>{{(fee/10_000).toFixed(2)}}%</td>
|
||||||
|
<td>{{ !co.selectedSymbol.liquiditySymbol ? '' :
|
||||||
|
co.selectedSymbol.liquiditySymbol === 'USD' ?
|
||||||
|
`$${toHuman(co.selectedSymbol.liquidities[i])}` :
|
||||||
|
toHuman(co.selectedSymbol.liquidities[i]) +' '+co.selectedSymbol.liquiditySymbol }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</v-table>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
|
||||||
|
import {toHuman} from "@/misc.js";
|
||||||
|
import ScannerButton from "@/components/ScannerButton.vue";
|
||||||
|
import {useChartOrderStore} from "@/orderbuild.js";
|
||||||
|
import {feelessTickerKey} from "@/charts/datafeed.js";
|
||||||
|
import {setSymbolTicker} from "@/charts/chart.js";
|
||||||
|
|
||||||
|
const co = useChartOrderStore()
|
||||||
|
|
||||||
|
|
||||||
|
function selectFee(fee) {
|
||||||
|
if (fee === co.selectedSymbol.fee) return
|
||||||
|
const symbol = co.selectedSymbol;
|
||||||
|
const ticker = feelessTickerKey(symbol.ticker) + '|' + fee
|
||||||
|
if (ticker !== symbol.ticker)
|
||||||
|
setSymbolTicker(ticker).catch((e) => console.error('Could not change TV symbol to', ticker))
|
||||||
|
co.showPoolSelection = false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@use "src/styles/vars" as *;
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
tr.selected {
|
||||||
|
|
||||||
|
}
|
||||||
|
tr.selectable {
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
background-color: #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.pool-button {
|
||||||
|
color: blue;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
34
src/components/ScannerButton.vue
Normal file
34
src/components/ScannerButton.vue
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<template>
|
||||||
|
<div class="d-inline-flex align-center" style="cursor: pointer">
|
||||||
|
<span @click='click'
|
||||||
|
:style="{maxWidth: width, width}" style="white-space: nowrap; display: inline-block; overflow: hidden; text-overflow: ellipsis">{{addr}}</span>
|
||||||
|
<v-icon icon="mdi-open-in-new" size="x-small"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {computed} from "vue";
|
||||||
|
import {useStore} from "@/store/store.js";
|
||||||
|
|
||||||
|
const props = defineProps({chainId: {type: Number, default:null}, addr:String, width: {default:'5em'}})
|
||||||
|
const s = useStore()
|
||||||
|
|
||||||
|
function click() {
|
||||||
|
window.open(url.value, '_blank')
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = computed(()=>{
|
||||||
|
const chain = props.chainId ? props.chainId: s.chainId
|
||||||
|
switch (chain) {
|
||||||
|
case 31337:
|
||||||
|
case 1337:
|
||||||
|
case 42161:
|
||||||
|
return `https://arbiscan.io/address/${props.addr}`
|
||||||
|
}
|
||||||
|
throw new Error(`No scanner defined for chain ${chain}`)
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
</style>
|
||||||
@@ -75,7 +75,7 @@ function changeSymbol(symbol) {
|
|||||||
console.log('changeSymbol', symbol)
|
console.log('changeSymbol', symbol)
|
||||||
os.tokenA = symbol.base
|
os.tokenA = symbol.base
|
||||||
os.tokenB = symbol.quote
|
os.tokenB = symbol.quote
|
||||||
routeFinder.invoke()
|
// routeFinder.invoke()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
<v-card-text v-if="s.vault && !s.creatingVault && ws.transaction !== null && ws.transaction.state !== TransactionState.Proposed">Signed and sent! Waiting for blockchain confirmation...</v-card-text>
|
<v-card-text v-if="s.vault && !s.creatingVault && ws.transaction !== null && ws.transaction.state !== TransactionState.Proposed">Signed and sent! Waiting for blockchain confirmation...</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
|
<pool-selection-dialog/>
|
||||||
</v-app>
|
</v-app>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -20,6 +21,7 @@ import {computed} from "vue";
|
|||||||
import {useWalletStore} from "@/blockchain/wallet.js";
|
import {useWalletStore} from "@/blockchain/wallet.js";
|
||||||
import {TransactionState, TransactionType} from "@/blockchain/transaction.js";
|
import {TransactionState, TransactionType} from "@/blockchain/transaction.js";
|
||||||
import {FixedNumber} from "ethers";
|
import {FixedNumber} from "ethers";
|
||||||
|
import PoolSelectionDialog from "@/components/PoolSelectionDialog.vue";
|
||||||
|
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
const ws = useWalletStore()
|
const ws = useWalletStore()
|
||||||
|
|||||||
20
src/misc.js
20
src/misc.js
@@ -41,7 +41,7 @@ export class SingletonCoroutine {
|
|||||||
// console.log('invoke', arguments)
|
// console.log('invoke', arguments)
|
||||||
if (this.timeout === null)
|
if (this.timeout === null)
|
||||||
// noinspection JSCheckFunctionSignatures
|
// noinspection JSCheckFunctionSignatures
|
||||||
this.timeout = setTimeout(this.onTimeout, this.delay, this)
|
this.timeout = setTimeout(this.onTimeout, this.delay, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
async onTimeout(self) {
|
async onTimeout(self) {
|
||||||
@@ -260,6 +260,24 @@ export function toPrecision(value, significantDigits = 3) {
|
|||||||
return value.toFixed(decimalsNeeded); // Use toFixed to completely avoid scientific notation
|
return value.toFixed(decimalsNeeded); // Use toFixed to completely avoid scientific notation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function toHuman(value, significantDigits = 2) {
|
||||||
|
if (!isFinite(value)) return value.toString(); // Handle Infinity and NaN
|
||||||
|
let suffix = ''
|
||||||
|
if (value >= 1_000_000_000) {
|
||||||
|
value /= 1_000_000_000
|
||||||
|
suffix = 'B'
|
||||||
|
}
|
||||||
|
else if (value >= 1_000_000) {
|
||||||
|
value /= 1_000_000
|
||||||
|
suffix = 'M'
|
||||||
|
}
|
||||||
|
else if (value >= 1_000) {
|
||||||
|
value /= 1_000
|
||||||
|
suffix = 'K'
|
||||||
|
}
|
||||||
|
return toPrecision(value, significantDigits) + suffix
|
||||||
|
}
|
||||||
|
|
||||||
export function errorSuggestsMissingVault(e) {
|
export function errorSuggestsMissingVault(e) {
|
||||||
return e.value === '0x' && e.code === 'BAD_DATA' || e.revert === null && e.code === 'CALL_EXCEPTION';
|
return e.value === '0x' && e.code === 'BAD_DATA' || e.revert === null && e.code === 'CALL_EXCEPTION';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ function newDefaultOrder() {
|
|||||||
export const useChartOrderStore = defineStore('chart_orders', () => {
|
export const useChartOrderStore = defineStore('chart_orders', () => {
|
||||||
const chartReady = ref(false)
|
const chartReady = ref(false)
|
||||||
|
|
||||||
|
const showPoolSelection = ref(false) // if true, the pool information / fee choosing dialog is shown
|
||||||
const defaultOrder = newDefaultOrder()
|
const defaultOrder = newDefaultOrder()
|
||||||
const orders = ref([defaultOrder]) // order models in UI format
|
const orders = ref([defaultOrder]) // order models in UI format
|
||||||
const selectedOrder = ref(null)
|
const selectedOrder = ref(null)
|
||||||
@@ -96,6 +97,7 @@ export const useChartOrderStore = defineStore('chart_orders', () => {
|
|||||||
return {
|
return {
|
||||||
chartReady, selectedSymbol, intervalSecs, baseToken, quoteToken, price,
|
chartReady, selectedSymbol, intervalSecs, baseToken, quoteToken, price,
|
||||||
orders, drawing, newOrder, removeOrder, resetOrders, meanRange,
|
orders, drawing, newOrder, removeOrder, resetOrders, meanRange,
|
||||||
|
showPoolSelection,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user