diff --git a/src/blockchain/ohlcs.js b/src/blockchain/ohlcs.js
index afafc14..ef5e987 100644
--- a/src/blockchain/ohlcs.js
+++ b/src/blockchain/ohlcs.js
@@ -30,6 +30,7 @@ export function refreshOHLCSubs() {
}
keys.push(`${pool}|${period}`)
}
+ console.log('refreshing OHLC subs', keys)
socket.emit('subOHLCs', chainId, keys)
}
diff --git a/src/charts/shape.js b/src/charts/shape.js
index c21a7c7..2a27548 100644
--- a/src/charts/shape.js
+++ b/src/charts/shape.js
@@ -46,8 +46,6 @@ export function allocationText(buy, weight, amount, baseSymbol, amountSymbol = n
const hasWeight = weight !== null && weight !== undefined && weight !== 1
if (hasWeight)
weight = Number(weight)
- if (buy===undefined)
- console.error('allocation text buy', buy)
let text = buy === undefined ? '' : buy ? 'Buy ' : 'Sell '
if (hasWeight)
text += `${(weight * 100).toFixed(1)}%`
diff --git a/src/components/chart/ChartOrder.vue b/src/components/chart/ChartOrder.vue
index 4243461..ac0d571 100644
--- a/src/components/chart/ChartOrder.vue
+++ b/src/components/chart/ChartOrder.vue
@@ -70,7 +70,7 @@ import BuilderFactory from "@/components/chart/BuilderFactory.vue";
import {builderFuncs, newBuilder, orderFuncs, useChartOrderStore} from "@/orderbuild.js";
import {useOrderStore, useStore} from "@/store/store.js";
import {computed, onUnmounted, onUpdated, ref, watchEffect} from "vue";
-import {lightenColor, lightenColor2} from "@/misc.js";
+import {lightenColor, lightenColor2, toPrecision} from "@/misc.js";
import {useTheme} from "vuetify";
import RowBar from "@/components/chart/RowBar.vue";
import ColorBand from "@/components/chart/ColorBand.vue";
@@ -114,7 +114,38 @@ function buildOrder() {
const order = props.order
console.log('buildOrder', order)
- if (!order.amount) return null
+ if (!order.amount)
+ return {order: null, warnings: ['Amount must be greater than 0']}
+
+ const symbol = co.selectedSymbol
+ const amountDec = order.amountIsTokenA ? symbol.base.d : symbol.quote.d
+ const amount = BigInt(Math.trunc(order.amount * 10 ** amountDec))
+
+ let warnings = []
+ const inAddr = order.buy ? symbol.quote.a : symbol.base.a
+ const inDec = order.buy ? symbol.quote.d : symbol.base.d
+ const available = s.getBalance(inAddr) / 10 ** inDec
+
+ let needed
+ if (order.amountIsTokenA && order.buy)
+ // need quote currency to buy an amount of base
+ needed = order.amount * co.price
+ else if (order.amountIsTokenA && !order.buy)
+ // sell an exact amount of base
+ needed = order.amount
+ else if (!order.amountIsTokenA && order.buy)
+ // need an exact amount of quote
+ needed = order.amount
+ else if (!order.amountIsTokenA && !order.buy)
+ // sell a quote amount worth of base
+ needed = order.amount / co.price
+ else
+ throw new Error('Invalid order')
+ const deficit = needed - available
+ if (deficit > 0) {
+ const inSymbol = order.buy ? symbol.quote.s : symbol.base.s
+ warnings.push(`Insufficient funds. Add ${toPrecision(deficit, 5)} ${inSymbol} to your vault to complete this order.`)
+ }
// struct SwapOrder {
// address tokenIn;
@@ -127,20 +158,24 @@ function buildOrder() {
// uint64 conditionalOrder; // use NO_CONDITIONAL_ORDER for no chaining. conditionalOrder index must be < than this order's index for safety (written first) and conditionalOrder state must be Template
// Tranche[] tranches;
// }
- const symbol = co.selectedSymbol
- const amountDec = order.amountIsTokenA ? symbol.base.d : symbol.quote.d
- const amount = BigInt(Math.trunc(order.amount * 10 ** amountDec))
const amountIsInput = !!(order.amountIsTokenA ^ order.buy)
let tranches = []
for (const builder of builders.value) {
console.log('builder', builder)
- const ts = builderFuncs[builder.id]()
+ const built = builderFuncs[builder.id]()
+ const ts = built.tranches
+ const ws = built.warnings
console.log('tranches', ts)
tranches = [...tranches, ...ts]
+ warnings = [...warnings, ...ws]
}
- return newOrder(tokenIn.value.a, tokenOut.value.a, symbol.exchangeId, symbol.fee, amount, amountIsInput, symbol.inverted, tranches)
+ return {
+ warnings,
+ order: newOrder(tokenIn.value.a, tokenOut.value.a, symbol.exchangeId, symbol.fee,
+ amount, amountIsInput, symbol.inverted, tranches),
+ }
}
diff --git a/src/components/chart/ChartPlaceOrder.vue b/src/components/chart/ChartPlaceOrder.vue
index a9622a9..767aa19 100644
--- a/src/components/chart/ChartPlaceOrder.vue
+++ b/src/components/chart/ChartPlaceOrder.vue
@@ -7,7 +7,7 @@
Place Dexorder
Reset
+ :disabled="!orderChanged" @click="resetOrder">Reset
@@ -19,7 +19,21 @@
showResetDialog=false">Keep Existing
- {co.resetOrders(); showResetDialog=false}" color="red" text="Reset Order"/>
+
+
+
+
+
+
+
+
+ {{w}}
+
+
+
+
+ showWarnings=false">Back
+ Place Order
@@ -78,10 +92,19 @@ const valid = computed(()=>{
const orderChanged = computed(()=>!(co.orders.length===1 && co.orders[0].builders.length===0 && !co.orders[0].amount))
-function cancelOrder() {
+const showWarnings = ref(false)
+const orderWarnings = ref([])
+
+function resetOrder() {
showResetDialog.value = true
}
+function doResetOrder() {
+ co.resetOrders();
+ orderWarnings.value = []
+ showResetDialog.value = false
+}
+
watchEffect(()=>{
const removable = []
for (const order of ws.pendingOrders) {
@@ -108,17 +131,31 @@ watchEffect(()=>{
}
})
+let built = []
async function placeOrder() {
const chartOrders = co.orders;
- const built = []
+ const allWarns = []
+ built = []
for (const chartOrder of chartOrders) {
console.log('chartOrder', chartOrder)
const buildOrder = orderFuncs[chartOrder.id]
- const order = buildOrder()
+ const {order, warnings} = buildOrder()
built.push(order)
+ allWarns.push(...warnings)
}
- console.log('place orders', built)
+
+ if (allWarns.length > 0) {
+ orderWarnings.value = allWarns
+ showWarnings.value = true
+ return
+ }
+
+ await doPlaceOrder()
+}
+
+async function doPlaceOrder() {
+ console.log('place orders')
if (ws.transaction!==null) {
console.error('Transaction already in progress')
}
diff --git a/src/components/chart/DCABuilder.vue b/src/components/chart/DCABuilder.vue
index dad28ed..b714b2f 100644
--- a/src/components/chart/DCABuilder.vue
+++ b/src/components/chart/DCABuilder.vue
@@ -85,8 +85,6 @@ const amountSymbol = computed(()=>props.order.amountIsTokenA ? co.selectedSymbol
const allocationTexts = computed(()=>weights.value.map((w)=>allocationText(props.order.buy, w, w * props.order.amount, co.selectedSymbol.base.s, amountSymbol.value)))
const endTimes = computed(()=>{
- if (props.builder.rungs === 1)
- return DISTANT_FUTURE
const ts = times.value
const window = Math.max(MIN_EXECUTION_TIME, Math.floor((ts[ts.length-1]-ts[0])/props.builder.rungs))
return ts.map((t)=>t+window)
@@ -151,28 +149,28 @@ const timeEndpoints = computed({
get() { return _timeEndpoints.value},
set(v) {
const [a, b] = v
- update(a,b)
+ update(a,b, true, true)
}
})
function updateA(a) {
- update(a, _timeEndpoints.value[1], true)
+ update(a, _timeEndpoints.value[1], true, false)
}
function updateB(b) {
- update(_timeEndpoints.value[0], b, false)
+ update(_timeEndpoints.value[0], b, false, true)
}
-function update(a, b, updatingA) {
- if (updatingA) {
+function update(a, b, updateA, updateB) {
+ if (updateA) {
const minB = a + minWidth.value
if (b < minB)
b = minB
}
- else {
+ if (updateB) {
const maxA = b - minWidth.value
if (a > maxA)
a = maxA
@@ -194,21 +192,27 @@ function buildTranches() {
const order = props.order
const builder = props.builder
const tranches = []
+ const warnings = []
console.log('buildTranches', builder, order, tranches)
const ts = times.value
const ets = endTimes.value
const ws = weights.value
+ console.log('buildTranches times ends weights', ts, ets, ws)
for(let i=0; i builderFuncs[props.builder.id] = buildTranches)
diff --git a/src/components/chart/RungBuilder.vue b/src/components/chart/RungBuilder.vue
index 0331641..b0d0e15 100644
--- a/src/components/chart/RungBuilder.vue
+++ b/src/components/chart/RungBuilder.vue
@@ -102,7 +102,6 @@ watchEffect(()=>{
})
function setEndpoints(a, b) {
- // console.log('rb setting endpoints', devectorize(a), devectorize(b))
endpoints.value = [devectorize(a), devectorize(b)]
}
@@ -125,8 +124,7 @@ const rungs = computed({
r = Number(r)
const prevR = Number(props.builder.rungs)
props.builder.rungs = r
- // console.log('set rungs', prevR, r, a, b)
- if ( r > 0 && vectorIsNull(b) ) {
+ if ( prevR === 1 && r > 1 ) {
// convert single shape to a range
if (props.mode===0) {
const width = vectorize(props.stdWidth)
@@ -143,7 +141,7 @@ const rungs = computed({
else
throw Error(`Unknown rung mode ${props.mode}`)
}
- else if ( r === 1 && !vectorIsNull(b) ) {
+ else if ( prevR > 1 && r === 1 ) {
// convert from a range to a single shape
if (props.mode===0)
a = vectorDiv(vectorAdd(a,b), 2)
diff --git a/src/orderbuild.js b/src/orderbuild.js
index a59c0d5..b3e98e5 100644
--- a/src/orderbuild.js
+++ b/src/orderbuild.js
@@ -56,7 +56,8 @@ export const useChartOrderStore = defineStore('chart_orders', () => {
if (!selectedSymbol.value)
return null
const s = useStore()
- let result = s.poolPrices[[s.chainId, selectedSymbol.address]]
+ const key = [s.chainId, selectedSymbol.value.address];
+ let result = s.poolPrices[key]
if (selectedSymbol.value.inverted)
result = 1 / result
return result
diff --git a/src/store/store.js b/src/store/store.js
index 5963dba..74320ee 100644
--- a/src/store/store.js
+++ b/src/store/store.js
@@ -133,6 +133,11 @@ export const useStore = defineStore('app', ()=> {
this.extraTokens = extras
}
+ function getBalance(tokenAddr) {
+ const found = this.balances[tokenAddr]
+ return found === undefined ? 0 : found
+ }
+
return {
connected,
nav, chainId, chainInfo, chain, provider, providerRef, vaultInitCodeHash, account, vaults, vaultVersions,
@@ -141,6 +146,7 @@ export const useStore = defineStore('app', ()=> {
mockenv, mockCoins,
removeTransactionSender, error, closeError, addToken, clock, timeZone, balances,
approved, regionApproved, walletApproved,
+ getBalance
}
})