From 14c8fdba4351c4bd20be6d1e20ce16c03905ae41 Mon Sep 17 00:00:00 2001 From: Anton Rock Date: Wed, 5 Mar 2025 13:59:07 +0300 Subject: [PATCH 1/4] feat: add pnl to dashboard --- src/screens/Dashboard/Dashboard.tsx | 5 ++--- src/screens/Dashboard/MarketDataSection/index.tsx | 11 +++++++++++ src/screens/SpotScreen/BottomTables/BottomTables.tsx | 6 ++---- .../SpotScreen/BottomTables/SpotTable/SpotTable.tsx | 6 +++--- .../BottomTables/SpotTable/SpotTableImpl.tsx | 8 +++----- src/stores/AccountStore.ts | 1 + 6 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/screens/Dashboard/Dashboard.tsx b/src/screens/Dashboard/Dashboard.tsx index 514ebd2e..7d2d7df8 100644 --- a/src/screens/Dashboard/Dashboard.tsx +++ b/src/screens/Dashboard/Dashboard.tsx @@ -7,7 +7,6 @@ import { DashboardPoints } from "@components/Points/DashboardPoints"; import { SmartFlex } from "@components/SmartFlex"; import { media } from "@themes/breakpoints"; -import AssetsDashboard from "@screens/Dashboard/AssetsDashboard"; import InfoDataGraph from "@screens/Dashboard/InfoDataGraph"; import BottomTables from "@screens/SpotScreen/BottomTables"; import StatusBar from "@screens/SpotScreen/StatusBar"; @@ -25,9 +24,9 @@ const Dashboard = observer(() => { - + - + {/**/} diff --git a/src/screens/Dashboard/MarketDataSection/index.tsx b/src/screens/Dashboard/MarketDataSection/index.tsx index e6f209bb..cc36c487 100644 --- a/src/screens/Dashboard/MarketDataSection/index.tsx +++ b/src/screens/Dashboard/MarketDataSection/index.tsx @@ -18,6 +18,17 @@ const marketData = [ }, isShowDetails: true, }, + { + title: "PNL", + value: "$0", + period: "24h", + change: { + value: "+0", + percentage: "0", + direction: "up", + }, + isShowDetails: true, + }, { title: "Trading Volume", value: "$0", diff --git a/src/screens/SpotScreen/BottomTables/BottomTables.tsx b/src/screens/SpotScreen/BottomTables/BottomTables.tsx index 10c9ebeb..3ccd43e8 100644 --- a/src/screens/SpotScreen/BottomTables/BottomTables.tsx +++ b/src/screens/SpotScreen/BottomTables/BottomTables.tsx @@ -4,14 +4,12 @@ import { observer } from "mobx-react"; import { media } from "@themes/breakpoints"; -import { SpotTableImplProps } from "@screens/SpotScreen/BottomTables/SpotTable/SpotTableImpl"; - import SpotTable from "./SpotTable"; -const BottomTables: React.FC = observer(({ isShowBalance }) => { +const BottomTables = observer(() => { return ( - + ); }); diff --git a/src/screens/SpotScreen/BottomTables/SpotTable/SpotTable.tsx b/src/screens/SpotScreen/BottomTables/SpotTable/SpotTable.tsx index 1ebfaa04..b6bfd964 100644 --- a/src/screens/SpotScreen/BottomTables/SpotTable/SpotTable.tsx +++ b/src/screens/SpotScreen/BottomTables/SpotTable/SpotTable.tsx @@ -1,11 +1,11 @@ import React from "react"; -import SpotTableImpl, { SpotTableImplProps } from "./SpotTableImpl"; +import SpotTableImpl from "./SpotTableImpl"; import { SpotTableVMProvider } from "./SpotTableVM"; -const SpotTable: React.FC = ({ isShowBalance }) => ( +const SpotTable = () => ( - + ); diff --git a/src/screens/SpotScreen/BottomTables/SpotTable/SpotTableImpl.tsx b/src/screens/SpotScreen/BottomTables/SpotTable/SpotTableImpl.tsx index 185ce661..c7673016 100644 --- a/src/screens/SpotScreen/BottomTables/SpotTable/SpotTableImpl.tsx +++ b/src/screens/SpotScreen/BottomTables/SpotTable/SpotTableImpl.tsx @@ -210,10 +210,8 @@ const BALANCE_COLUMNS = ( const minNeedLengthPagination = 10; const startPage = 1; // todo: Упростить логику разделить формирование данных и рендер для декстопа и мобилок -export interface SpotTableImplProps { - isShowBalance?: boolean; -} -const SpotTableImpl: React.FC = observer(({ isShowBalance = true }) => { + +const SpotTableImpl = observer(() => { const { accountStore, settingsStore, balanceStore } = useStores(); const [isLoading, setLoading] = useState(null); const vm = useSpotTableVMProvider(); @@ -245,7 +243,7 @@ const SpotTableImpl: React.FC = observer(({ isShowBalance = const TABS = [ { title: "ORDERS", disabled: false, rowCount: openOrdersCount }, { title: "HISTORY", disabled: false, rowCount: historyOrdersCount }, - ...(isShowBalance ? [{ title: "BALANCES", disabled: false, rowCount: balancesInfoList.length }] : []), + { title: "BALANCES", disabled: false, rowCount: balancesInfoList.length }, ]; useEffect(() => { diff --git a/src/stores/AccountStore.ts b/src/stores/AccountStore.ts index 1e873564..091dc6af 100644 --- a/src/stores/AccountStore.ts +++ b/src/stores/AccountStore.ts @@ -70,6 +70,7 @@ class AccountStore { }; get address(): Nullable { + return "0x2a3a5d57e6e4173e159fcc40ca34deccd6c0ceeca92c7437c6fa8798a4a666c9"; const bcNetwork = FuelNetwork.getInstance(); return bcNetwork.getAddress(); } From 20e3f0da3c389d21bf8c9c7ef98fee74fbfa4ec3 Mon Sep 17 00:00:00 2001 From: Anton Rock Date: Wed, 5 Mar 2025 17:29:06 +0300 Subject: [PATCH 2/4] feat: pnl to dashboard --- package.json | 2 +- pnpm-lock.yaml | 11 ++-- src/blockchain/FuelNetwork.ts | 4 ++ .../MarketDataSection/MarketAttribute.tsx | 2 +- .../Dashboard/MarketDataSection/index.tsx | 15 ++++-- src/stores/DashboardStore.ts | 54 ++++++++++++++++++- 6 files changed, 76 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 9350338c..58dddb88 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "pnpm": ">=10.4.0" }, "dependencies": { - "@compolabs/spark-orderbook-ts-sdk": "https://registry.npmjs.org/@compolabs/spark-orderbook-ts-sdk/-/spark-orderbook-ts-sdk-1.16.1.tgz", + "@compolabs/spark-orderbook-ts-sdk": "file:../spark-orderbook-ts-sdk", "@compolabs/tradingview-chart": "^1.0.21", "@emotion/react": "^11.11.3", "@emotion/styled": "^11.11.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4c3ac7dd..8c799cf4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@compolabs/spark-orderbook-ts-sdk': - specifier: https://registry.npmjs.org/@compolabs/spark-orderbook-ts-sdk/-/spark-orderbook-ts-sdk-1.16.1.tgz - version: https://registry.npmjs.org/@compolabs/spark-orderbook-ts-sdk/-/spark-orderbook-ts-sdk-1.16.1.tgz(@types/react@18.3.18)(fuels@0.97.2(vitest@2.0.5(@types/node@22.13.4)))(graphql@16.10.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: file:../spark-orderbook-ts-sdk + version: file:../spark-orderbook-ts-sdk(@types/react@18.3.18)(fuels@0.97.2(vitest@2.0.5(@types/node@22.13.4)))(graphql@16.10.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@compolabs/tradingview-chart': specifier: ^1.0.21 version: 1.0.21 @@ -916,9 +916,8 @@ packages: '@coinbase/wallet-sdk@4.3.0': resolution: {integrity: sha512-T3+SNmiCw4HzDm4we9wCHCxlP0pqCiwKe4sOwPH3YAK2KSKjxPRydKu6UQJrdONFVLG7ujXvbd/6ZqmvJb8rkw==} - '@compolabs/spark-orderbook-ts-sdk@https://registry.npmjs.org/@compolabs/spark-orderbook-ts-sdk/-/spark-orderbook-ts-sdk-1.16.1.tgz': - resolution: {tarball: https://registry.npmjs.org/@compolabs/spark-orderbook-ts-sdk/-/spark-orderbook-ts-sdk-1.16.1.tgz} - version: 1.16.1 + '@compolabs/spark-orderbook-ts-sdk@file:../spark-orderbook-ts-sdk': + resolution: {directory: ../spark-orderbook-ts-sdk, type: directory} engines: {node: '>=18'} peerDependencies: fuels: '>=0.97.1' @@ -7264,7 +7263,7 @@ snapshots: eventemitter3: 5.0.1 preact: 10.26.0 - '@compolabs/spark-orderbook-ts-sdk@https://registry.npmjs.org/@compolabs/spark-orderbook-ts-sdk/-/spark-orderbook-ts-sdk-1.16.1.tgz(@types/react@18.3.18)(fuels@0.97.2(vitest@2.0.5(@types/node@22.13.4)))(graphql@16.10.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@compolabs/spark-orderbook-ts-sdk@file:../spark-orderbook-ts-sdk(@types/react@18.3.18)(fuels@0.97.2(vitest@2.0.5(@types/node@22.13.4)))(graphql@16.10.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@apollo/client': 3.13.1(@types/react@18.3.18)(graphql-ws@5.16.2(graphql@16.10.0))(graphql@16.10.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) axios: 1.7.9 diff --git a/src/blockchain/FuelNetwork.ts b/src/blockchain/FuelNetwork.ts index 3144783b..871a90f5 100644 --- a/src/blockchain/FuelNetwork.ts +++ b/src/blockchain/FuelNetwork.ts @@ -269,4 +269,8 @@ export class FuelNetwork { getCompetition = async (...params: Parameters) => { return await this.orderbookSdk.getCompetition(...params); }; + + fetchBalancePnl = async (...params: Parameters) => { + return await this.orderbookSdk.getBalancePnlByUser(...params); + }; } diff --git a/src/screens/Dashboard/MarketDataSection/MarketAttribute.tsx b/src/screens/Dashboard/MarketDataSection/MarketAttribute.tsx index 531e6d5f..7d3d7393 100644 --- a/src/screens/Dashboard/MarketDataSection/MarketAttribute.tsx +++ b/src/screens/Dashboard/MarketDataSection/MarketAttribute.tsx @@ -37,7 +37,7 @@ export const MarketAttribute: React.FC = observer( {isHaveRange && ( <> - {change.value} + {change.value !== "hide" && {change.value}} {change.percentage} diff --git a/src/screens/Dashboard/MarketDataSection/index.tsx b/src/screens/Dashboard/MarketDataSection/index.tsx index cc36c487..776b56ec 100644 --- a/src/screens/Dashboard/MarketDataSection/index.tsx +++ b/src/screens/Dashboard/MarketDataSection/index.tsx @@ -23,7 +23,7 @@ const marketData = [ value: "$0", period: "24h", change: { - value: "+0", + value: "none", percentage: "0", direction: "up", }, @@ -47,20 +47,24 @@ export const MarketDataSection: React.FC = observer(() => { const { dashboardStore } = useStores(); const portfolioVolume = dashboardStore.getChartDataPortfolio(); const tradingVolume = dashboardStore.getChartDataTrading(); + const totalBalancePnl = dashboardStore.totalPnl; useEffect(() => { if (dashboardStore.rowSnapshots.length === 0) { setUserStats(structuredClone(marketData)); return; } + console.log("totalBalancePnl", totalBalancePnl); const sumStatsUser = portfolioVolume[portfolioVolume.length - 1]; const sumStatsTrading = tradingVolume.reduce((sum, item) => sum + item.value, 0); const updatedStats = structuredClone(marketData); updatedStats[0].period = dashboardStore.activeFilter.description ?? dashboardStore.activeFilter.title; updatedStats[1].period = dashboardStore.activeFilter.description ?? dashboardStore.activeFilter.title; + updatedStats[2].period = dashboardStore.activeFilter.description ?? dashboardStore.activeFilter.title; updatedStats[0].value = `$${sumStatsUser?.value?.toFixed(2)}`; - updatedStats[1].value = `$${sumStatsTrading?.toFixed(2) ?? "0.00"}`; + updatedStats[1].value = `$${Number(totalBalancePnl?.pnl)?.toFixed(2) ?? "0.00"}`; + updatedStats[2].value = `$${sumStatsTrading?.toFixed(2) ?? "0.00"}`; const calculateChange = (data: DataPoint[]) => { if (data.length === 0) { return { @@ -81,7 +85,12 @@ export const MarketDataSection: React.FC = observer(() => { }; }; updatedStats[0].change = calculateChange(portfolioVolume); - updatedStats[1].change = calculateChange(tradingVolume); + updatedStats[1].change = { + value: "hide", + percentage: Number(totalBalancePnl?.pnlInPercent).toFixed(2) + "%", + direction: Number(totalBalancePnl?.pnlInPercent) > 0 ? "up" : "down", + }; + updatedStats[2].change = calculateChange(tradingVolume); setUserStats(updatedStats); }, [dashboardStore.rowSnapshots, dashboardStore.activeFilter, dashboardStore.tradeEvents]); diff --git a/src/stores/DashboardStore.ts b/src/stores/DashboardStore.ts index 06bd8571..0ccdc0fe 100644 --- a/src/stores/DashboardStore.ts +++ b/src/stores/DashboardStore.ts @@ -1,6 +1,6 @@ import { makeAutoObservable, reaction } from "mobx"; -import { RowSnapshot, RowTradeEvent } from "@compolabs/spark-orderbook-ts-sdk"; +import { BalancePnlByUserResponse, RowSnapshot, RowTradeEvent } from "@compolabs/spark-orderbook-ts-sdk"; import { filters } from "@screens/Dashboard/const"; import { TradeEvent } from "@screens/Dashboard/InfoDataGraph"; @@ -19,6 +19,10 @@ interface IRecord { timestamp: number; } +type SummedBalancePnl = { + [key: string]: string; +}; + export interface FiltersProps { title: string; value: number; @@ -35,6 +39,7 @@ class DashboardStore { initialized = false; rowSnapshots: RowSnapshot[] = []; tradeEvents: RowTradeEvent[] = []; + balancePnlByUser: BalancePnlByUserResponse[] = []; activeUserStat = 0; activeTime = 0; activeFilter = filters[0]; @@ -71,6 +76,7 @@ class DashboardStore { this.activeTime = this.calculateTime(date, 24); await this.fetchUserScoreSnapshot(); await this.fetchTradeEvent(); + await this.fetchBalancePnl(); }; disconnect = () => { @@ -84,7 +90,37 @@ class DashboardStore { private syncDashboardData = async () => { await this.fetchUserScoreSnapshot(); await this.fetchTradeEvent(); + await this.fetchBalancePnl(); + }; + + getPnlValues = (pnlData: SummedBalancePnl) => { + switch (this.activeFilter.title) { + case "24h": + return { pnl: pnlData.pnl1, pnlInPercent: pnlData.pnlInPersent1 }; + case "7d": + return { pnl: pnlData.pnl7, pnlInPercent: pnlData.pnlInPersent7 }; + case "30d": + return { pnl: pnlData.pnl31, pnlInPercent: pnlData.pnlInPersent31 }; + case "All Time": + return { pnl: pnlData.pnlAllTime, pnlInPercent: pnlData.pnlInPersentAllTime }; + default: + return null; + } }; + get totalPnl() { + const summedValues: SummedBalancePnl | any = {}; + this.balancePnlByUser.forEach((entry) => { + Object.keys(entry).forEach((key) => { + if (key !== "market") { + const currentValue = summedValues[key] || "0"; + const newValue = entry[key as keyof BalancePnlByUserResponse] as string; + summedValues[key] = Number(currentValue) + Number(newValue); + } + }); + }); + + return this.getPnlValues(summedValues); + } getChartDataPortfolio = () => { const result: TradeEvent[] = []; @@ -179,6 +215,22 @@ class DashboardStore { const data = await bcNetwork.getTradeEvent(params); this.tradeEvents = data?.result?.rows ?? []; }; + + private fetchBalancePnl = async () => { + const bcNetwork = FuelNetwork.getInstance(); + const { accountStore } = this.rootStore; + if (!accountStore?.address) return; + const params = { + user: accountStore.address, + }; + const config = { + url: CONFIG.APP.sentioUrl, + apiKey: "TLjw41s3DYbWALbwmvwLDM9vbVEDrD9BP", + }; + bcNetwork.setSentioConfig(config); + const data = await bcNetwork.fetchBalancePnl(params); + this.balancePnlByUser = data?.result?.rows ?? []; + }; } export default DashboardStore; From 766d313914e135592395d16b19ee435e943f4a0e Mon Sep 17 00:00:00 2001 From: Anton-rock Date: Mon, 10 Mar 2025 13:28:00 +0300 Subject: [PATCH 3/4] feat: fix trading graph --- src/screens/Dashboard/InfoDataGraph/index.tsx | 15 ++++++++++++--- .../BottomTables/SpotTable/SpotTableImpl.tsx | 2 -- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/screens/Dashboard/InfoDataGraph/index.tsx b/src/screens/Dashboard/InfoDataGraph/index.tsx index a784d217..5ebda232 100644 --- a/src/screens/Dashboard/InfoDataGraph/index.tsx +++ b/src/screens/Dashboard/InfoDataGraph/index.tsx @@ -62,9 +62,18 @@ const NoDataTrading = observer(() => { const InfoDataGraph: React.FC = observer(() => { const { dashboardStore } = useStores(); - const data = dashboardStore.activeUserStat - ? generateTradingData(dashboardStore.getChartDataTrading()) - : generateTradingData(dashboardStore.getChartDataPortfolio()); + const data = (() => { + switch (dashboardStore.activeUserStat) { + case 0: + return generateTradingData(dashboardStore.getChartDataTrading()); + case 1: + return []; + case 2: + return generateTradingData(dashboardStore.getChartDataPortfolio()); + default: + throw new Error(`Unexpected activeUserStat: ${dashboardStore.activeUserStat}`); + } + })(); return data.length > 0 ? : ; }); diff --git a/src/screens/SpotScreen/BottomTables/SpotTable/SpotTableImpl.tsx b/src/screens/SpotScreen/BottomTables/SpotTable/SpotTableImpl.tsx index ff52779d..5d420d52 100644 --- a/src/screens/SpotScreen/BottomTables/SpotTable/SpotTableImpl.tsx +++ b/src/screens/SpotScreen/BottomTables/SpotTable/SpotTableImpl.tsx @@ -209,8 +209,6 @@ const BALANCE_COLUMNS = ( header: "Total amount", cell: (props) => { const pnlPrecent = props.row.original.pnlPrecent; - // const one = props.getValue().toString(); - // console.log('props.getValue()', props.getValue()) return ( {generatePnl(props.getValue(), theme) ?? 0} From 7053965a01ac26c26a038d2b35b9a8ac2fe4778c Mon Sep 17 00:00:00 2001 From: Anton-rock Date: Mon, 10 Mar 2025 13:30:26 +0300 Subject: [PATCH 4/4] feat: fix pnl --- src/screens/SpotScreen/BottomTables/SpotTable/SpotTableImpl.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/screens/SpotScreen/BottomTables/SpotTable/SpotTableImpl.tsx b/src/screens/SpotScreen/BottomTables/SpotTable/SpotTableImpl.tsx index 5d420d52..1e25ecdd 100644 --- a/src/screens/SpotScreen/BottomTables/SpotTable/SpotTableImpl.tsx +++ b/src/screens/SpotScreen/BottomTables/SpotTable/SpotTableImpl.tsx @@ -206,7 +206,7 @@ const BALANCE_COLUMNS = ( }, }), balanceColumnHelper.accessor("pnl", { - header: "Total amount", + header: "PnL", cell: (props) => { const pnlPrecent = props.row.original.pnlPrecent; return (