From acb299edbdc5dbac9d2d180d6aab2f7fa977026e Mon Sep 17 00:00:00 2001
From: Sikkra <159844544+Sikkra@users.noreply.github.com>
Date: Tue, 19 May 2026 07:04:52 -0500
Subject: [PATCH] Add trading history CSV export
---
src/api/history.js | 54 ++++-
src/components/layout/Modals.svelte | 7 +-
src/components/modals/ExportHistory.svelte | 238 ++++++++++++++++++++
src/components/trade/account/Account.svelte | 16 +-
4 files changed, 304 insertions(+), 11 deletions(-)
create mode 100644 src/components/modals/ExportHistory.svelte
diff --git a/src/api/history.js b/src/api/history.js
index ce1e5cb..22f9f6f 100644
--- a/src/api/history.js
+++ b/src/api/history.js
@@ -4,10 +4,15 @@ import { DEFAULT_HISTORY_COUNT } from '@lib/config'
import { address, history, lastHistoryItemsCount, historySortKey, historyOrderStatusToShow } from '@lib/stores'
import { getLabelForAsset, getChainData } from '@lib/utils'
+function getHistoryUrl(params) {
+ const dataEndpoint = getChainData('dataEndpoint');
+ const statusesToShow = get(historyOrderStatusToShow);
+
+ return `${dataEndpoint}/history/${params.address}?chain=arbitrum&limit=${params.first}&skip=${params.skip}&sortBy=${params.sortBy}&sortDirection=${params.sortDirection}&status=${statusesToShow.join(',')}`;
+}
+
export async function getUserHistory(params) {
- const dataEndpoint = getChainData('dataEndpoint');
-
let _address = get(address);
if (!_address) return;
@@ -24,15 +29,13 @@ export async function getUserHistory(params) {
if (!first) first = DEFAULT_HISTORY_COUNT;
if (!skip) skip = 0;
- const statusesToShow = get(historyOrderStatusToShow);
-
const sortKey = get(historySortKey); // [columnName, isDesc]
let sortBy = 'timestamp';
let sortDirection = 'desc';
try {
- const response = await fetch(`${dataEndpoint}/history/${_address}?chain=arbitrum&limit=${first}&skip=${skip}&sortBy=${sortBy}&sortDirection=${sortDirection}&status=${statusesToShow.join(',')}`);
+ const response = await fetch(getHistoryUrl({address: _address, first, skip, sortBy, sortDirection}));
const orders = await response.json() || [];
lastHistoryItemsCount.set(orders.length);
@@ -66,4 +69,43 @@ export async function getUserHistory(params) {
}
return true;
-}
\ No newline at end of file
+}
+
+export async function getUserHistoryForExport(params) {
+ let _address = get(address);
+ if (!_address) return [];
+
+ if (!params) params = {};
+
+ const fromTimestamp = params.fromTimestamp || 0;
+ const toTimestamp = params.toTimestamp || Date.now() / 1000;
+ const pageSize = 500;
+ const maxPages = 200;
+ const sortBy = 'timestamp';
+ const sortDirection = 'desc';
+
+ _address = _address.toLowerCase();
+
+ let skip = 0;
+ let rows = [];
+
+ for (let page = 0; page < maxPages; page++) {
+ const response = await fetch(getHistoryUrl({address: _address, first: pageSize, skip, sortBy, sortDirection}));
+ const pageRows = await response.json() || [];
+
+ for (const row of pageRows) {
+ const timestamp = row.timestamp * 1;
+ if (!timestamp || timestamp > toTimestamp) continue;
+ if (timestamp >= fromTimestamp) rows.push(row);
+ }
+
+ if (pageRows.length < pageSize) break;
+
+ const oldestTimestamp = pageRows[pageRows.length - 1]?.timestamp * 1;
+ if (fromTimestamp && oldestTimestamp && oldestTimestamp < fromTimestamp) break;
+
+ skip += pageSize;
+ }
+
+ return rows;
+}
diff --git a/src/components/layout/Modals.svelte b/src/components/layout/Modals.svelte
index 03b829d..fce09e6 100644
--- a/src/components/layout/Modals.svelte
+++ b/src/components/layout/Modals.svelte
@@ -12,6 +12,7 @@
import MarketInfo from '../modals/MarketInfo.svelte'
import StakeCAP from '../modals/StakeCAP.svelte'
import UnstakeCAP from '../modals/UnstakeCAP.svelte'
+ import ExportHistory from '../modals/ExportHistory.svelte'
import HistoryOrderStatus from '../modals/HistoryOrderStatus.svelte'
import Settings from '../modals/Settings.svelte'
@@ -65,6 +66,10 @@