From 09ef4c5f43c2df607dbce686489df4f1f54f4f6c Mon Sep 17 00:00:00 2001 From: tim Date: Sun, 15 Sep 2024 00:59:47 -0400 Subject: [PATCH] ordershapes --- src/blockchain/orderlib.js | 25 +++- src/blockchain/wallet.js | 2 +- src/charts/chart.js | 8 +- src/charts/datafeed.js | 4 +- src/charts/ordershapes.js | 122 ++++++++++++++++++ src/common.js | 2 + src/components/Status.vue | 167 ++++++++++++++++--------- src/components/chart/MarketBuilder.vue | 2 +- src/orderbuild.js | 23 ++-- src/socket.js | 32 +++-- 10 files changed, 295 insertions(+), 92 deletions(-) create mode 100644 src/charts/ordershapes.js diff --git a/src/blockchain/orderlib.js b/src/blockchain/orderlib.js index 17e319c..6bd3589 100644 --- a/src/blockchain/orderlib.js +++ b/src/blockchain/orderlib.js @@ -159,11 +159,22 @@ export function parseOrderStatus(chainId, status) { return result } -function parseTrancheStatus(obj) { - let [filledIn, filledOut, activationTime, startTime, endTime,] = obj +function parseFill(obj) { + let [tx, time, filledIn, filledOut, fee] = obj filledIn = BigInt(filledIn) filledOut = BigInt(filledOut) - return {filledIn, filledOut, activationTime, startTime, endTime} + fee = BigInt(fee) + return {tx, time, filledIn, filledOut, fee} +} + +function parseTrancheStatus(obj) { + let [filledIn, filledOut, activationTime, startTime, endTime, rawFills,] = obj + filledIn = BigInt(filledIn) + filledOut = BigInt(filledOut) + const fills = [] + for (const fill of rawFills) + fills.push(parseFill(fill)) + return {filledIn, filledOut, activationTime, startTime, endTime, fills} } export function parseOrder(order) { @@ -210,14 +221,16 @@ export function parseTranche(tranche) { minLine, maxLine, ] = tranche - minLine = {intercept: minLine.intercept, slope: minLine.slope } - maxLine = {intercept: maxLine.intercept, slope: maxLine.slope } + const [minB,minS] = minLine + minLine = {intercept: minB, slope: minS } + const [maxB,maxS] = maxLine + maxLine = {intercept: maxB, slope: maxS } const result = { fraction, startTimeIsRelative, endTimeIsRelative, minIsBarrier, maxIsBarrier, marketOrder, minIsRatio, maxIsRatio, rateLimitFraction, rateLimitPeriod, startTime, endTime, minLine, maxLine, } - console.log('parseTranche', tranche, result) + // console.log('parseTranche', tranche, result) return result } diff --git a/src/blockchain/wallet.js b/src/blockchain/wallet.js index f7a1f13..18ae466 100644 --- a/src/blockchain/wallet.js +++ b/src/blockchain/wallet.js @@ -384,7 +384,7 @@ function pendOrderAsTransaction(pend) { const [orderFee, gasFee] = await placementFee(pend.vault, pend.order) pend.fee = orderFee + gasFee } - console.log('placing order', pend.id, pend.order) + console.log('placing order', pend.id, pend.fee, pend.order) const tx = await contract.placeDexorder(pend.order, {value:pend.fee}) pend.tx = tx pend.state = PendingOrderState.Sent diff --git a/src/charts/chart.js b/src/charts/chart.js index 259ea72..fa186e2 100644 --- a/src/charts/chart.js +++ b/src/charts/chart.js @@ -3,7 +3,6 @@ import {invokeCallbacks, prototype} from "@/common.js"; import {DataFeed, initFeeDropdown, lookupSymbol} from "@/charts/datafeed.js"; import {intervalToSeconds, SingletonCoroutine} from "@/misc.js"; import {useStore} from "@/store/store.js"; -import {dirtyPoints} from "@/charts/chart-misc.js"; export let widget = null export let chart = null @@ -162,12 +161,17 @@ export function drawShape(shapeType, ...callbacks) { export function createShape(shapeType, points, options={}, ...callbacks) { + const chart = widget.activeChart() drawingCallbacks = null cancelDrawing() - options.shape = shapeType.code + if (typeof shapeType === 'string' ) + options.shape = shapeType + else + options.shape = shapeType.code // programatically adds a shape to the chart let shapeId try { + console.log('creating shape', points, options) if (points.time || points.price) shapeId = chart.createShape(points, options) else if (points.length === 1) diff --git a/src/charts/datafeed.js b/src/charts/datafeed.js index 7c1c96f..c9a122e 100644 --- a/src/charts/datafeed.js +++ b/src/charts/datafeed.js @@ -144,7 +144,7 @@ function addSymbol(p, base, quote, inverted) { const description = `${base.n} / ${quote.n}` const type = 'swap' const pools = [[p.a, p.f]] - const decimals = p.d + const decimals = inverted ? -p.d : p.d _symbols[key] = { ticker: key, full_name, symbol, description, exchange, type, inverted, base, quote, pools, decimals, x:p.x @@ -221,7 +221,7 @@ function getAllSymbols() { return _symbols } -export function lookupSymbol(key) { // lookup by fullname +export function lookupSymbol(key) { // lookup by ticker which is "0xbaseAddress/0xquoteAddress" return getAllSymbols()[key] } diff --git a/src/charts/ordershapes.js b/src/charts/ordershapes.js new file mode 100644 index 0000000..7ab3ddc --- /dev/null +++ b/src/charts/ordershapes.js @@ -0,0 +1,122 @@ +import {DISTANT_FUTURE, DISTANT_PAST} from "@/blockchain/orderlib.js"; +import {DLine, HLine} from "@/charts/shape.js"; +import {createShape, deleteShapeId} from "@/charts/chart.js"; +import {allocationText} from "@/orderbuild.js"; + +export class OrderShapes { + constructor(symbol, orderStatus) { + this.symbol = symbol + this.status = orderStatus + this.trancheShapes = []; + this.update(orderStatus) + } + + update(orderStatus) { + // todo delete old shapes + for (const old of this.trancheShapes) + old.delete() + this.status = orderStatus + this.trancheShapes = []; + for (let i = 0; i < orderStatus.trancheStatus.length; i++) + this.trancheShapes.push(new TrancheShapes(this.symbol, this.status, i)); + // todo TV shape group + } + + show() {for (const t of this.trancheShapes) t.show();} + hide() {for (const t of this.trancheShapes) t.hide();} + delete() {for (const t of this.trancheShapes) t.delete(); this.shapes=[]} +} + + +class TrancheShapes { + constructor(symbol, orderStatus, trancheIndex) { + this.symbol = symbol + this.status = orderStatus + this.trancheIndex = trancheIndex + this.tranche = orderStatus.order.tranches[trancheIndex] + this.shapes = [] + this.fills = [] + this.createShapes(); + } + + createShapes() { + // todo amounts + const t = this.tranche + // console.log('create tranche shapes', t) + if (t.marketOrder) { + if (t.startTime !== DISTANT_PAST) { + // todo vertical line + } + } else { + // check lines + this.createLine(t.minLine.slope, t.minLine.intercept); + this.createLine(t.maxLine.slope, t.maxLine.intercept); + } + for (const f of this.status.trancheStatus[this.trancheIndex].fills) + this.createFillPoint(f) + } + + createFillPoint(f) { + // console.log('draw fill', f, this.symbol) + const order = this.status.order; + let buy = order.tokenIn === this.symbol.quote.a + if (this.symbol.inverted) + buy = !buy + const time = f.time + const out = Number(f.filledOut) * (1+this.status.order.route.fee/1000000) + let price = buy ? + Number(f.filledIn) / out * 10**this.symbol.decimals : + out / Number(f.filledIn) * 10**this.symbol.decimals + // console.log('price', price) + const channel = buy?'low':'high'; + const text = (buy ? 'Buy ' : 'Sell ') + allocationText(null, f.filled, '') + const s = createShape(buy?'arrow_up':'arrow_down', {time, price}, {channel,text}) + console.log('created fill shape at', time, price) + this.fills.push(s) + } + + createLine(slope, intercept) { + const t = this.tranche + const status = this.status + const symbol = this.symbol + const scale = 10**symbol.decimals; + const buy = status.order.tokenIn === this.symbol.quote.a + const color = buy ? 'green' : 'red' + if (intercept !== 0 || slope !== 0) { + // line active + if (slope === 0) { + // horizontal line + const s = new HLine({ + price: intercept * scale, + color, + // todo allocation maxAllocation amount amountSymbol + }) + this.shapes.push(s) + } else { + // diagonal line + const startPrice = intercept + slope * t.startTime; + const endPrice = intercept + slope * t.endTime; + const s = new DLine({ + pointA: {time: t.startTime, price: startPrice}, + pointB: {time: t.endTime, price: endPrice}, + extendLeft: t.startTime === DISTANT_PAST, + extendRight: t.endTime === DISTANT_FUTURE, + color, + // todo allocation maxAllocation amount amountSymbol + }) + this.shapes.push(s) + } + } + } + + // todo like this? + show() {for (const s of this.shapes) s.show();} + hide() {for (const s of this.shapes) s.hide();} + delete() { + for (const s of this.shapes) + s.delete(); + this.shapes=[] + for (const s of this.fills) + deleteShapeId(s) + } +} diff --git a/src/common.js b/src/common.js index 575be02..0978d3d 100644 --- a/src/common.js +++ b/src/common.js @@ -131,3 +131,5 @@ export function abiPath(name) { const file = files[name] return `${file??name}.sol/${name}.json` } + + diff --git a/src/components/Status.vue b/src/components/Status.vue index 4feefad..a8acab8 100644 --- a/src/components/Status.vue +++ b/src/components/Status.vue @@ -1,7 +1,7 @@