diff --git a/src/components/trade/account/Account.svelte b/src/components/trade/account/Account.svelte deleted file mode 100644 index a589a71..0000000 --- a/src/components/trade/account/Account.svelte +++ /dev/null @@ -1,208 +0,0 @@ - - - - -
- -
- -
- - -
- -
- {#if panel == 'positions'}{/if} - {#if panel == 'orders'}{/if} - {#if panel == 'history'}{/if} -
- -
\ No newline at end of file diff --git a/src/components/trade/account/History.svelte b/src/components/trade/account/History.svelte index 68ee72e..a647060 100644 --- a/src/components/trade/account/History.svelte +++ b/src/components/trade/account/History.svelte @@ -1,429 +1,278 @@ - - - - -
- {#each formattedHistory as item} - - - - {#if $historyColumnsToShow.includes('id')} - {item.status == 'liquidated' ? 'liq' : item.orderId} - {/if} - - {#if $historyColumnsToShow.includes('timestamp')} - {formatDate(item.timestamp)} - {/if} - - {#if $historyColumnsToShow.includes('isLong')} - {formatSide(item.isLong, item.isReduceOnly)} - {/if} - - {#if $historyColumnsToShow.includes('market')} - {formatMarketName(item.market)} - {/if} - - {#if $historyColumnsToShow.includes('price')} - {item.price * 1 > 0 ? formatPriceForDisplay(item.price) : '-'} - {/if} - - {#if $historyColumnsToShow.includes('size')} - {formatForDisplay(item.size)} {item.asset} - {/if} - - {#if $historyColumnsToShow.includes('margin')} - {formatForDisplay(item.margin)} {item.asset} - {/if} - - {#if $historyColumnsToShow.includes('leverage')} - {item.leverage ? `${formatForDisplay(item.leverage)}×` : 'N/A'} - {/if} - - {#if $historyColumnsToShow.includes('orderType')} - {formatOrderType(item.orderType)} - {/if} - - {#if $historyColumnsToShow.includes('isReduceOnly')} - {item.isReduceOnly ? 'Yes' : 'No'} - {/if} - - {#if $historyColumnsToShow.includes('status')} - {item.status} - {/if} - - {#if $historyColumnsToShow.includes('reason')} - {item.reason || '-'} - {/if} - - {#if $historyColumnsToShow.includes('pnl')} - {#if !item.pnl} - - - {:else} - = 0 ? 'green' : 'red'}>{@html formatPnl(item.pnl)} ({@html formatPnl(100*item.pnl/item.margin, true)}) - {/if} - {/if} - - {#if $historyColumnsToShow.includes('fee')} - {formatForDisplay(item.fee)} {item.asset} - {/if} - - {#if $historyColumnsToShow.includes('expiry')} - {formatDate(item.expiry) || '-'} - {/if} - - {#if $historyColumnsToShow.includes('cancelOrderId')} - {item.cancelOrderId * 1 > 0 ? item.cancelOrderId : '-'} - {/if} - - - - - {/each} -
- -
- - \ No newline at end of file + diff --git a/src/components/trade/account/Orders.svelte b/src/components/trade/account/Orders.svelte deleted file mode 100644 index 9c85587..0000000 --- a/src/components/trade/account/Orders.svelte +++ /dev/null @@ -1,380 +0,0 @@ - - - - - - - -
- {#each formattedOrders as order} - - - - {#if $ordersColumnsToShow.includes('orderId')} - {order.orderId} - {/if} - - {#if $ordersColumnsToShow.includes('timestamp')} - {formatDate(order.timestamp)} - {/if} - - {#if $ordersColumnsToShow.includes('isLong')} - {formatSide(order.isLong, order.isReduceOnly)} - {/if} - - {#if $ordersColumnsToShow.includes('market')} - {formatMarketName(order.market)} - {/if} - - {#if $ordersColumnsToShow.includes('price')} - {order.price * 1 > 0 ? formatPriceForDisplay(order.price) : '-'} - {/if} - - {#if $ordersColumnsToShow.includes('size')} - {formatForDisplay(order.size)} {order.asset} - {/if} - - {#if $ordersColumnsToShow.includes('margin')} - {order.margin * 1 > 0 ? `${formatForDisplay(order.margin)} ${order.asset}` : '-'} - {/if} - - {#if $ordersColumnsToShow.includes('leverage')} - {order.leverage ? `${formatForDisplay(order.leverage)}×` : '-'} - {/if} - - {#if $ordersColumnsToShow.includes('orderType')} - {formatOrderType(order.orderType)} - {/if} - - {#if $ordersColumnsToShow.includes('isReduceOnly')} - {order.isReduceOnly ? 'Yes' : 'No'} - {/if} - - {#if $ordersColumnsToShow.includes('fee')} - {formatForDisplay(order.fee)} {order.asset} - {/if} - - {#if $ordersColumnsToShow.includes('expiry')} - {formatDate(order.expiry) || '-'} - {/if} - - {#if $ordersColumnsToShow.includes('cancelOrderId')} - {order.cancelOrderId * 1 > 0 ? order.cancelOrderId : '-'} - {/if} - - - {#if canSelfExecute[order.orderId]} - { _selfExecuteOrder(order.orderId) }}> - {#if ordersSelfExecuting[order.orderId]}{@html LOADING_ICON}{:else}{@html CHAINLINK_LOGO}{/if} - - {/if} - { _cancelOrder(order.orderId) }}> - {#if ordersCancelling[order.orderId]}{@html LOADING_ICON}{:else}{@html XMARK_ICON}{/if} - - - - - - {/each} -
- -
- - \ No newline at end of file diff --git a/src/components/trade/account/Positions.svelte b/src/components/trade/account/Positions.svelte deleted file mode 100644 index bc4ccbe..0000000 --- a/src/components/trade/account/Positions.svelte +++ /dev/null @@ -1,418 +0,0 @@ - - - - - - - -
- {#each formattedPositions as position} - - - - {#if $positionsColumnsToShow.includes('timestamp')} - {formatDate(position.timestamp)} - {/if} - - {#if $positionsColumnsToShow.includes('isLong')} - {formatSide(position.isLong)} - {/if} - - {#if $positionsColumnsToShow.includes('market')} - {formatMarketName(position.market)} - {/if} - - {#if $positionsColumnsToShow.includes('price')} - {formatPriceForDisplay(position.price)} - {/if} - - {#if $positionsColumnsToShow.includes('currentPrice')} - {formatPriceForDisplay($prices[position.market])} - {/if} - - {#if $positionsColumnsToShow.includes('size')} - {formatForDisplay(position.size)} {position.asset} - {/if} - - {#if $positionsColumnsToShow.includes('margin')} - {formatForDisplay(position.margin)} {position.asset} - {/if} - - {#if $positionsColumnsToShow.includes('leverage')} - {formatForDisplay(position.leverage)}× - {/if} - - {#if $positionsColumnsToShow.includes('upl')} - {#if !totalUpls[`${position.asset}:${position.market}`]} - 0.0 (0%) - {:else} - = 0 ? 'green' : 'red'}>{@html formatPnl(totalUpls[`${position.asset}:${position.market}`])} ({@html formatPnl(100*totalUpls[`${position.asset}:${position.market}`]/position.margin, true)}) - {/if} - {/if} - - {#if $positionsColumnsToShow.includes('funding')} - {formatForDisplay(fundings[`${position.asset}:${position.market}`])} {position.asset} - {/if} - - {#if $positionsColumnsToShow.includes('liqprice')} - {formatPriceForDisplay(liqPrices[`${position.asset}:${position.market}`])} - {/if} - - - { showModal('EditMargin', {position, funding: fundings[`${position.asset}:${position.market}`]}) }}>{@html PENCIL_ICON} - { showModal('ClosePosition', position) }}>{@html XMARK_ICON} - - - - - {/each} - -
- -
- - \ No newline at end of file diff --git a/src/workers/csv-export.worker.js b/src/workers/csv-export.worker.js new file mode 100644 index 0000000..d80c40a --- /dev/null +++ b/src/workers/csv-export.worker.js @@ -0,0 +1,71 @@ +/** + * Web Worker for CSV export — offloads CSV string generation from main thread. + * Receives { data: historyItems[], timeframe: string } + * Returns { csv: string, filename: string } + */ + +function formatCSVValue(value) { + if (value === null || value === undefined) return ''; + const str = String(value); + // Escape double quotes and wrap in quotes if contains comma, quote, or newline + if (str.includes(',') || str.includes('"') || str.includes('\n')) { + return '"' + str.replace(/"/g, '""') + '"'; + } + return str; +} + +function formatDate(ts) { + if (!ts) return ''; + const d = new Date(ts * 1000); + return d.toISOString().replace('T', ' ').substring(0, 19); +} + +function formatSide(isLong) { + return isLong ? 'Long' : 'Short'; +} + +function formatOrderType(type) { + const types = { 0: 'Market', 1: 'Limit', 2: 'Stop Market', 3: 'Stop Limit' }; + return types[type] || String(type); +} + +self.onmessage = function (e) { + const { items, timeframe } = e.data; + + // Filter by timeframe + let filtered = items; + if (timeframe && timeframe !== 'all') { + const now = Math.floor(Date.now() / 1000); + const days = parseInt(timeframe); + const cutoff = now - days * 86400; + filtered = items.filter(item => item.timestamp >= cutoff); + } + + // CSV header + const headers = [ + 'Order ID', 'Timestamp', 'Market', 'Side', 'Type', + 'Price', 'Size', 'Margin', 'Fee', 'PnL', 'Status' + ]; + + // CSV rows + const rows = filtered.map(item => [ + item.orderId || '', + formatDate(item.timestamp), + item.market || '', + formatSide(item.isLong), + formatOrderType(item.orderType), + item.price || '', + item.size || '', + item.margin || '', + item.fee || '', + item.pnl || item.upl || '', + item.status || item.orderStatus || '', + ].map(formatCSVValue)); + + const csv = [headers.join(','), ...rows.map(r => r.join(','))].join('\n'); + + const dateStr = new Date().toISOString().substring(0, 10); + const filename = `cap-trading-history-${dateStr}.csv`; + + self.postMessage({ csv, filename, count: filtered.length, total: items.length }); +};