From f237433c4ae95ea161e511ececf4627d987ac729 Mon Sep 17 00:00:00 2001 From: Anton Date: Tue, 24 Dec 2024 17:13:21 +0300 Subject: [PATCH] [2039] Change sentio logic (#240) --- package.json | 2 +- pnpm-lock.yaml | 14 ++-- .../Pagination/Pagination-entity.tsx | 2 +- src/components/Pagination/Pagination.tsx | 6 +- src/components/SelectAssets/AssetBlock.tsx | 1 - src/components/SideBar.tsx | 2 +- src/constants/index.ts | 2 +- src/screens/Assets/MainAssets/MainAssets.tsx | 37 +++++---- src/screens/Dashboard/AssetsDashboard.tsx | 83 +++++++++++++++---- src/screens/Dashboard/InfoDataGraph/index.tsx | 4 +- .../Dashboard/MarketDataSection/index.tsx | 7 +- .../Dashboard/TradingViewScoreboardWidget.tsx | 4 +- .../BottomTables/SpotTable/SpotTableImpl.tsx | 4 +- .../Chart/TradingViewAdvanceWidget.tsx | 2 - src/stores/DashboardStore.ts | 61 ++++++++------ 15 files changed, 147 insertions(+), 84 deletions(-) diff --git a/package.json b/package.json index 89abd9a0..7d29881a 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "pnpm": ">=9.7.0" }, "dependencies": { - "@compolabs/spark-orderbook-ts-sdk": "https://registry.npmjs.org/@compolabs/spark-orderbook-ts-sdk/-/spark-orderbook-ts-sdk-1.14.7.tgz", + "@compolabs/spark-orderbook-ts-sdk": "https://registry.npmjs.org/@compolabs/spark-orderbook-ts-sdk/-/spark-orderbook-ts-sdk-1.14.9.tgz", "@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 926083f0..43a9844e 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.14.7.tgz - version: https://registry.npmjs.org/@compolabs/spark-orderbook-ts-sdk/-/spark-orderbook-ts-sdk-1.14.7.tgz(@types/react@18.3.13)(fuels@0.96.1)(graphql@16.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: https://registry.npmjs.org/@compolabs/spark-orderbook-ts-sdk/-/spark-orderbook-ts-sdk-1.14.9.tgz + version: https://registry.npmjs.org/@compolabs/spark-orderbook-ts-sdk/-/spark-orderbook-ts-sdk-1.14.9.tgz(@types/react@18.3.13)(fuels@0.96.1)(graphql@16.9.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 @@ -1000,12 +1000,12 @@ packages: '@coinbase/wallet-sdk@4.0.4': resolution: {integrity: sha512-74c040CRnGhfRjr3ArnkAgud86erIqdkPHNt5HR1k9u97uTIZCJww9eGYT67Qf7gHPpGS/xW8Be1D4dvRm63FA==} - '@compolabs/spark-orderbook-ts-sdk@https://registry.npmjs.org/@compolabs/spark-orderbook-ts-sdk/-/spark-orderbook-ts-sdk-1.14.7.tgz': - resolution: {tarball: https://registry.npmjs.org/@compolabs/spark-orderbook-ts-sdk/-/spark-orderbook-ts-sdk-1.14.7.tgz} - version: 1.14.7 + '@compolabs/spark-orderbook-ts-sdk@https://registry.npmjs.org/@compolabs/spark-orderbook-ts-sdk/-/spark-orderbook-ts-sdk-1.14.9.tgz': + resolution: {tarball: https://registry.npmjs.org/@compolabs/spark-orderbook-ts-sdk/-/spark-orderbook-ts-sdk-1.14.9.tgz} + version: 1.14.9 engines: {node: '>=18'} peerDependencies: - fuels: '>=0.96.1' + fuels: '>=0.97.1' '@compolabs/tradingview-chart@1.0.21': resolution: {integrity: sha512-efExlG9Ki5uqEe16nRF2A6FwQ8CnzmAwad2kMZxNFtNsbJTYhVC1SMSzkcBNQ50yzmijm3HAUUfaMzsXwtEkFQ==, tarball: https://npm.pkg.github.com/download/@compolabs/tradingview-chart/1.0.21/f9b8234ef67206216f98b5919ef16173c21f7fe9} @@ -8163,7 +8163,7 @@ snapshots: preact: 10.25.1 sha.js: 2.4.11 - '@compolabs/spark-orderbook-ts-sdk@https://registry.npmjs.org/@compolabs/spark-orderbook-ts-sdk/-/spark-orderbook-ts-sdk-1.14.7.tgz(@types/react@18.3.13)(fuels@0.96.1)(graphql@16.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@compolabs/spark-orderbook-ts-sdk@https://registry.npmjs.org/@compolabs/spark-orderbook-ts-sdk/-/spark-orderbook-ts-sdk-1.14.9.tgz(@types/react@18.3.13)(fuels@0.96.1)(graphql@16.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@apollo/client': 3.12.3(@types/react@18.3.13)(graphql-ws@5.16.0(graphql@16.9.0))(graphql@16.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) axios: 1.7.9 diff --git a/src/components/Pagination/Pagination-entity.tsx b/src/components/Pagination/Pagination-entity.tsx index b0023e7c..d23457e3 100644 --- a/src/components/Pagination/Pagination-entity.tsx +++ b/src/components/Pagination/Pagination-entity.tsx @@ -15,7 +15,7 @@ export const PaginationEntity = ({ selected, disabled, ...props }: PaginationBut const ButtonStyled = styled(Button)` border: none; height: 16px !important; - width: 16px !important; + min-width: 16px !important; padding: 0px !important; box-sizing: content-box; `; diff --git a/src/components/Pagination/Pagination.tsx b/src/components/Pagination/Pagination.tsx index 0f9af25e..ffadadb2 100644 --- a/src/components/Pagination/Pagination.tsx +++ b/src/components/Pagination/Pagination.tsx @@ -93,7 +93,10 @@ export const Pagination = observer(({ currentPage, onChange, lengthData, limit = ); })} - handleClick(currentPage + 1)}> + handleClick(currentPage + 1)} + > @@ -123,4 +126,5 @@ const PaginationContainer = styled.div` align-items: center; padding: 12px; border-radius: 0px 0px 10px 10px; + background: ${({ theme }) => theme.colors.bgSecondary}; `; diff --git a/src/components/SelectAssets/AssetBlock.tsx b/src/components/SelectAssets/AssetBlock.tsx index ec9a7222..6b6904d9 100644 --- a/src/components/SelectAssets/AssetBlock.tsx +++ b/src/components/SelectAssets/AssetBlock.tsx @@ -34,7 +34,6 @@ const AssetBlock: React.FC = observer( const { oracleStore } = useStores(); const price = BN.formatUnits(oracleStore.getTokenIndexPrice(token.asset.priceFeed), DEFAULT_DECIMALS); const theme = useTheme(); - if (!showNullBalance && new BN(token[showBalance]).isLessThanOrEqualTo(BN.ZERO)) return null; return ( diff --git a/src/components/SideBar.tsx b/src/components/SideBar.tsx index eb14537b..b1a6066f 100644 --- a/src/components/SideBar.tsx +++ b/src/components/SideBar.tsx @@ -28,7 +28,7 @@ const Backdrop = styled.div` right: 0; background-color: rgba(0, 0, 0, 0.1); backdrop-filter: blur(10px); - z-index: 2; + z-index: 3; `; const ModalDialog = styled.div` position: fixed; diff --git a/src/constants/index.ts b/src/constants/index.ts index 8d99e4dc..35c7854d 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -11,7 +11,7 @@ export const ROUTES = { export const BRIDGE_LINK = "https://app.fuel.network/bridge"; export const SWAP_LINK = "https://layerswap.io/app"; -export const POINTS_LINK = "https://app.fuel.network/earn-points"; +export const POINTS_LINK = "https://app.fuel.network/earn-points/phase-2/"; export const isProduction = window.location.host === "app.sprk.fi"; export const ARBITRUM_SEPOLIA_FAUCET = "https://faucet.quicknode.com/arbitrum/sepolia"; diff --git a/src/screens/Assets/MainAssets/MainAssets.tsx b/src/screens/Assets/MainAssets/MainAssets.tsx index db99931d..8fea3121 100644 --- a/src/screens/Assets/MainAssets/MainAssets.tsx +++ b/src/screens/Assets/MainAssets/MainAssets.tsx @@ -22,7 +22,7 @@ import { MIXPANEL_EVENTS } from "@stores/MixPanelStore"; import ConnectWalletDialog from "@screens/ConnectWallet"; -import { ROUTES } from "@constants"; +import { BRIDGE_LINK } from "@constants"; import BN from "@utils/BN"; interface MainAssetsProps { @@ -37,8 +37,7 @@ const MainAssets: React.FC = observer(({ setStep }) => { const theme = useTheme(); const balancesInfoList = balanceStore.formattedBalanceInfoList; - const hasPositiveBalance = balancesInfoList.some((item) => !new BN(item.balance).isZero()); - + const hasPositiveBalance = balancesInfoList.some((item) => !new BN(item.contractBalance).isZero()); const accumulateBalance = balancesInfoList.reduce( (acc, account) => { const balanceValue = new BN(account.balance).multipliedBy(account.price); @@ -84,23 +83,24 @@ const MainAssets: React.FC = observer(({ setStep }) => { primary onClick={() => mixPanelStore.trackEvent(MIXPANEL_EVENTS.CLICK_ASSETS, { page_name: location.pathname })} > - Assets in my wallet: ${accumulateBalance?.walletBalance.toSignificant(2)} + Assets in Spark - - *These are assets in your wallet, not in Spark - {isConnected ? ( - accumulateBalance.balance.isPositive() && ( + accumulateBalance.contractBalance.isGreaterThan(BN.ZERO) && ( <> - {balancesInfoList.map((el) => ( - - - - ))} - {renderOverallContent({ isConnected, balance: accumulateBalance.balance })} + {balancesInfoList.map((el) => { + const balance = new BN(el.contractBalance).isGreaterThan(BN.ZERO); + if (!balance) return <>; + return ( + + + + ); + })} + {renderOverallContent({ isConnected, balance: accumulateBalance.contractBalance })} ) ) : ( @@ -110,7 +110,7 @@ const MainAssets: React.FC = observer(({ setStep }) => { ))} - {renderOverallContent({ isConnected, balance: accumulateBalance.balance })} + {renderOverallContent({ isConnected, balance: accumulateBalance.contractBalance })} )} @@ -120,14 +120,15 @@ const MainAssets: React.FC = observer(({ setStep }) => { - It looks like your wallet is empty. Tap the{" "} + It looks like you don’t have assets in Spark. Tap the{" "} { quickAssetsStore.setQuickAssets(false); + window.open(BRIDGE_LINK, "_blank"); }} > - faucet + bridge {" "} to grab some tokens. diff --git a/src/screens/Dashboard/AssetsDashboard.tsx b/src/screens/Dashboard/AssetsDashboard.tsx index 471f4055..68c8922b 100644 --- a/src/screens/Dashboard/AssetsDashboard.tsx +++ b/src/screens/Dashboard/AssetsDashboard.tsx @@ -1,4 +1,5 @@ import React, { useState } from "react"; +import { Link } from "react-router-dom"; import styled from "@emotion/styled"; import { createColumnHelper } from "@tanstack/react-table"; import { observer } from "mobx-react"; @@ -13,12 +14,16 @@ import { SmartFlex } from "@components/SmartFlex"; import Table from "@components/Table"; import Text, { TEXT_TYPES } from "@components/Text"; +import DepositAssets from "@assets/icons/depositAssets.svg?react"; + import { useMedia } from "@hooks/useMedia"; import { useStores } from "@stores"; import { TRADE_TABLE_SIZE } from "@stores/SettingsStore.ts"; import { BaseTable } from "@screens/SpotScreen/BottomTables/BaseTable"; +import { BRIDGE_LINK } from "@constants"; + const orderColumnHelper = createColumnHelper(); const AssetsDashboard = observer(() => { @@ -26,15 +31,18 @@ const AssetsDashboard = observer(() => { const media = useMedia(); const { balanceStore } = useStores(); const balancesInfoList = balanceStore.formattedBalanceInfoList; - const data = balancesInfoList.map((el) => ({ - asset: el.asset, - amount: el, - value: new BN(el.balance).multipliedBy(el.price).toSignificant(el.asset.decimals), - currentPrice: new BN(el.price).toSignificant(2), - })); + const data = balancesInfoList + .map((el) => ({ + asset: el.asset, + amount: el, + value: new BN(el.contractBalance).multipliedBy(el.price), + currentPrice: new BN(el.price).toSignificant(2), + })) + .filter((item) => new BN(item.value).isGreaterThan(BN.ZERO)); const allContractBalance = balancesInfoList.reduce((acc, el) => { return acc.plus(el.contractBalance); }, BN.ZERO); + const hasPositiveBalance = balancesInfoList.some((item) => !new BN(item.contractBalance).isZero()); const columns = [ orderColumnHelper.accessor("asset", { header: "Name", @@ -53,7 +61,7 @@ const AssetsDashboard = observer(() => { const value = props.getValue(); return ( - {new BN(value.balance).toSignificant(value.asset.decimals)} + {new BN(value.contractBalance).toSignificant(value.asset.decimals)} {value.asset.symbol} ); @@ -138,9 +146,9 @@ const AssetsDashboard = observer(() => { - {ord.amount.balance} {ord.asset.symbol} + {ord.amount.contractBalance} {ord.asset.symbol} - ${new BN(ord.amount.balance).multipliedBy(ord.amount.price).toSignificant(2)} + ${new BN(ord.amount.contractBalance).multipliedBy(ord.amount.price).toSignificant(2)} @@ -175,15 +183,37 @@ const AssetsDashboard = observer(() => { return ( <> - Assets in my wallet + Assets in Spark - {media.desktop ? ( - {}}> - {renderTable()} - + {hasPositiveBalance ? ( + <> + {media.desktop ? ( + {}}> + {renderTable()} + + ) : ( + renderMobileRows() + )} + ) : ( - renderMobileRows() + <> + + + + It looks like you don’t have assets in Spark. Tap the{" "} + { + window.open(BRIDGE_LINK, "_blank"); + }} + > + bridge + {" "} + to grab some tokens. + + + )} @@ -192,6 +222,12 @@ const AssetsDashboard = observer(() => { export default AssetsDashboard; +const ColumnContainer = styled(Column)` + width: 100%; + align-items: center; + padding: 20px 0px; +`; + const TitleText = styled(Text)` padding-top: 32px; padding-bottom: 8px; @@ -274,3 +310,20 @@ const ButtonConfirm = styled(Button)` width: 100%; min-width: 90px; `; + +const TextTitle = styled(Text)` + width: 100%; + text-align: left; +`; + +const EmptyAsset = styled(TextTitle)` + text-align: center; +`; + +const LinkStyled = styled(Link)` + color: ${({ theme }) => theme.colors.greenLight}; + text-decoration: underline; + &:hover { + cursor: pointer; + } +`; diff --git a/src/screens/Dashboard/InfoDataGraph/index.tsx b/src/screens/Dashboard/InfoDataGraph/index.tsx index db91623e..35d57342 100644 --- a/src/screens/Dashboard/InfoDataGraph/index.tsx +++ b/src/screens/Dashboard/InfoDataGraph/index.tsx @@ -13,7 +13,7 @@ import { useStores } from "@stores"; import TradingViewScoreboardWidget from "@screens/Dashboard/TradingViewScoreboardWidget"; -interface TradeEvent { +export interface TradeEvent { time: number; value: number; } @@ -64,7 +64,7 @@ const InfoDataGraph: React.FC = observer(() => { const { dashboardStore } = useStores(); const data = dashboardStore.activeUserStat ? generateTradingData(dashboardStore.getChartDataTrading()) - : dashboardStore.getChartDataPortfolio(); + : generateTradingData(dashboardStore.getChartDataPortfolio()); return data.length > 0 ? : ; }); diff --git a/src/screens/Dashboard/MarketDataSection/index.tsx b/src/screens/Dashboard/MarketDataSection/index.tsx index 1656d45b..35802d64 100644 --- a/src/screens/Dashboard/MarketDataSection/index.tsx +++ b/src/screens/Dashboard/MarketDataSection/index.tsx @@ -43,14 +43,13 @@ export const MarketDataSection: React.FC = observer(() => { } const sumStatsUser = portfolioVolume[portfolioVolume.length - 1]; - const sumStatsTrading = tradingVolume[tradingVolume.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[0].value = `$${sumStatsUser.value.toFixed(4)}`; - updatedStats[1].value = `$${sumStatsTrading?.value?.toFixed(4) ?? "0.0000"}`; + updatedStats[0].value = `$${sumStatsUser?.value?.toFixed(4)}`; + updatedStats[1].value = `$${sumStatsTrading?.toFixed(4) ?? "0.0000"}`; const calculateChange = (data: DataPoint[]) => { if (data.length === 0) { return { diff --git a/src/screens/Dashboard/TradingViewScoreboardWidget.tsx b/src/screens/Dashboard/TradingViewScoreboardWidget.tsx index af1941a1..928eb1d9 100644 --- a/src/screens/Dashboard/TradingViewScoreboardWidget.tsx +++ b/src/screens/Dashboard/TradingViewScoreboardWidget.tsx @@ -39,11 +39,9 @@ const TradingViewScoreboardWidget: React.FC = useEffect(() => { if (!chartContainerRef.current || containerDimensions.width === 0 || containerDimensions.height === 0) return; - // Если график уже существует, обновляем его размеры if (chartRef.current) { chartRef.current.resize(containerDimensions.width, containerDimensions.height); } else { - // Создаем новый график const chart = createChart(chartContainerRef.current, { width: containerDimensions.width, height: containerDimensions.height, @@ -78,7 +76,9 @@ const TradingViewScoreboardWidget: React.FC = lineColor: "#04E78C", lineWidth: 2, }); + areaSeries.setData(data); + chart.timeScale().fitContent(); } return () => { diff --git a/src/screens/SpotScreen/BottomTables/SpotTable/SpotTableImpl.tsx b/src/screens/SpotScreen/BottomTables/SpotTable/SpotTableImpl.tsx index 55fa6a5e..57f3d38a 100644 --- a/src/screens/SpotScreen/BottomTables/SpotTable/SpotTableImpl.tsx +++ b/src/screens/SpotScreen/BottomTables/SpotTable/SpotTableImpl.tsx @@ -132,6 +132,8 @@ const SpotTableImpl: React.FC = observer(() => { const [page, setPage] = useState(startPage); const historyOrders = (vm.userOrdersStats?.closed ?? 0) + (vm.userOrdersStats?.canceled ?? 0); const openOrders = vm.userOrdersStats?.active ?? 0; + const closeOrders = (vm.userOrdersStats?.closed ?? 0) + (vm.userOrdersStats?.canceled ?? 0); + const PAGINATION_LENGTH = [openOrders, closeOrders]; const TABS = [ { title: "ORDERS", disabled: false, rowCount: openOrders }, { title: "HISTORY", disabled: false, rowCount: historyOrders }, @@ -277,7 +279,7 @@ const SpotTableImpl: React.FC = observer(() => { {renderTable()} {data.length >= minNeedLengthPagination || page > startPage - 1 ? ( - + ) : null} {/*{!!vm.userOrders.length && tabIndex === 0 && (*/} {/* //todo здесь была кнопка cancel all orders*/} diff --git a/src/screens/SpotScreen/Chart/TradingViewAdvanceWidget.tsx b/src/screens/SpotScreen/Chart/TradingViewAdvanceWidget.tsx index f37fde5e..e93d5525 100644 --- a/src/screens/SpotScreen/Chart/TradingViewAdvanceWidget.tsx +++ b/src/screens/SpotScreen/Chart/TradingViewAdvanceWidget.tsx @@ -60,8 +60,6 @@ const TradingViewChartAdvance = observer(() => { if (!window?.Datafeeds) return; const widgetOptions: ChartingLibraryWidgetOptions = { symbol: defaultProps.symbol as string, - // BEWARE: no trailing slash is expected in feed URL - // tslint:disable-next-line:no-any datafeed: new window.Datafeeds.UDFCompatibleDatafeed(defaultProps.datafeedUrl), interval: "5" as ResolutionString, container: chartContainerRef.current, diff --git a/src/stores/DashboardStore.ts b/src/stores/DashboardStore.ts index fc2dc9cb..d1645701 100644 --- a/src/stores/DashboardStore.ts +++ b/src/stores/DashboardStore.ts @@ -3,6 +3,7 @@ import { makeAutoObservable, reaction } from "mobx"; import { RowSnapshot, RowTradeEvent } from "@compolabs/spark-orderbook-ts-sdk"; import { filters } from "@screens/Dashboard/const"; +import { TradeEvent } from "@screens/Dashboard/InfoDataGraph"; import { CONFIG } from "@utils/getConfig"; @@ -10,8 +11,11 @@ import { FuelNetwork } from "@blockchain"; import RootStore from "./RootStore"; -export interface ISerializedDashboardStore { - data: string; +interface IRecord { + user: string; + market: string; + tvl: number; + timestamp: number; } export interface FiltersProps { @@ -69,37 +73,39 @@ class DashboardStore { this.activeFilter = filters[0]; }; - getCumulativeStats = () => { - return this.rowSnapshots.reduce( - (acc, cur) => { - acc.total_value_locked_score += cur.total_value_locked_score; - acc.tradeVolume += cur.tradeVolume; - return acc; - }, - { total_value_locked_score: 0, tradeVolume: 0 }, - ); - }; - getChartDataPortfolio = () => { - const groupedData = this.rowSnapshots.reduce((acc: Record, el) => { - const date = Math.floor(new Date(el.block_date).getTime() / 1000); - const value = el.total_value_locked_score; - - if (!acc[date]) { - acc[date] = { time: date, value: 0 }; - } - acc[date].value += value; - - return acc; - }, {}); - - return Object.values(groupedData); + const result: TradeEvent[] = []; + const lastValues: { [market: string]: { tvl: number; timestamp: number } } = {}; + + this.rowSnapshots.forEach((hourData) => { + const { hour, records_in_hour } = hourData; + const currentHourValues: { [market: string]: { tvl: number; timestamp: number } } = {}; + records_in_hour.forEach((record) => { + const { market, tvl, timestamp }: IRecord = JSON.parse(record); + if (!currentHourValues[market] || currentHourValues[market].timestamp < timestamp) { + currentHourValues[market] = { tvl, timestamp }; + } + }); + + let accumulatedValue = 0; + Object.keys(currentHourValues).forEach((market) => { + accumulatedValue += currentHourValues[market].tvl; + lastValues[market] = currentHourValues[market]; + }); + result.push({ + time: Math.floor(new Date(hour).getTime() / 1000), + value: accumulatedValue, + }); + }); + + return result; }; getChartDataTrading = () => { const groupedData = this.tradeEvents.reduce((acc: Record, el) => { const date = Math.floor(new Date(el.timestamp).getTime()); const value = el.volume; + if (!acc[date]) { acc[date] = { time: date, value: 0 }; } @@ -131,7 +137,8 @@ class DashboardStore { if (!accountStore?.address) return; const params = { userAddress: accountStore.address, - blockDate: this.activeTime, + fromTimestamp: this.activeTime, + toTimestamp: this.calculateTime(new Date(), 0), }; const config = { url: CONFIG.APP.sentioUrl,