From 1b771c8b3f9d18a89e4ee30a3df7af739ee43c1e Mon Sep 17 00:00:00 2001 From: Jan Michek <15363559+janmichek@users.noreply.github.com> Date: Mon, 13 Jan 2025 09:29:48 +0100 Subject: [PATCH] feat: Dex Trades per Token (#876) --- cypress/e2e/app/tokenDetail.cy.js | 3 + src/components/DexTradesTable.vue | 183 ++++++++++++++-------------- src/components/TimeToggleButton.vue | 6 +- src/components/TimestampLabel.vue | 4 +- src/components/TokenTradesPanel.vue | 39 ++++++ src/pages/tokens/[id].vue | 5 +- src/stores/app.js | 12 -- src/stores/dex.js | 1 - src/stores/tokenDetails.js | 25 +++- src/stores/ui.js | 8 ++ src/utils/adapters.js | 3 +- 11 files changed, 174 insertions(+), 115 deletions(-) create mode 100644 src/components/TokenTradesPanel.vue delete mode 100644 src/stores/app.js diff --git a/cypress/e2e/app/tokenDetail.cy.js b/cypress/e2e/app/tokenDetail.cy.js index 767db74d1..6893b1a24 100644 --- a/cypress/e2e/app/tokenDetail.cy.js +++ b/cypress/e2e/app/tokenDetail.cy.js @@ -7,6 +7,9 @@ describe('token detail', () => { cy.contains('.tabs__item', 'Events').click() cy.get('.token-events-panel .paginated-content').should('be.visible') + + cy.contains('.tabs__item', 'Trades').click() + cy.get('.token-trades-panel .paginated-content').should('be.visible') }) it('should display token not found', () => { diff --git a/src/components/DexTradesTable.vue b/src/components/DexTradesTable.vue index 241517f70..c50fccdb2 100644 --- a/src/components/DexTradesTable.vue +++ b/src/components/DexTradesTable.vue @@ -1,97 +1,100 @@ diff --git a/src/components/TimeToggleButton.vue b/src/components/TimeToggleButton.vue index a297ffa8e..89adad0d2 100644 --- a/src/components/TimeToggleButton.vue +++ b/src/components/TimeToggleButton.vue @@ -9,10 +9,10 @@ diff --git a/src/pages/tokens/[id].vue b/src/pages/tokens/[id].vue index f93f74b95..4d1c1664d 100644 --- a/src/pages/tokens/[id].vue +++ b/src/pages/tokens/[id].vue @@ -23,6 +23,9 @@ + + + @@ -40,7 +43,7 @@ const { tokenDetails, tokenHoldersCount } = storeToRefs(tokenDetailsStore) const { fetchTokenDetails } = tokenDetailsStore const { isLoading } = useLoading() -const TAB_KEYS = ['holders', 'events'] +const TAB_KEYS = ['holders', 'events', 'trades'] const activeTabIndex = computed({ get() { diff --git a/src/stores/app.js b/src/stores/app.js deleted file mode 100644 index 45aa336af..000000000 --- a/src/stores/app.js +++ /dev/null @@ -1,12 +0,0 @@ -export const useAppStore = defineStore('app', () => { - const timeFormat = ref('relative') - - function toggleTimeFormat() { - timeFormat.value = timeFormat.value === 'absolute' ? 'relative' : 'absolute' - } - - return { - timeFormat, - toggleTimeFormat, - } -}) diff --git a/src/stores/dex.js b/src/stores/dex.js index fe9ef9225..c456aeff3 100644 --- a/src/stores/dex.js +++ b/src/stores/dex.js @@ -14,7 +14,6 @@ export const useDexStore = defineStore('dex', () => { } const { data } = await axios.get(`${DEX_BACKEND_URL}/swap-routes/${tokenId}/${AE_TOKEN_ID}`) - if (data.length === 0) { return false } diff --git a/src/stores/tokenDetails.js b/src/stores/tokenDetails.js index b04ab11a2..a2f03f06f 100644 --- a/src/stores/tokenDetails.js +++ b/src/stores/tokenDetails.js @@ -2,7 +2,7 @@ import { defineStore, storeToRefs } from 'pinia' import { useRuntimeConfig } from 'nuxt/app' import { Contract } from '@aeternity/aepp-sdk' import useAxios from '@/composables/useAxios' -import { adaptTokenDetails, adaptTokenEvents, adaptTokenHolders } from '@/utils/adapters' +import { adaptTokenDetails, adaptTokenEvents, adaptTokenHolders, adaptTrades } from '@/utils/adapters' import { TOKEN_SUPPLY_ACI } from '@/utils/constants' import { useWalletStore } from '@/stores/wallet' import { useDexStore } from '@/stores/dex' @@ -22,6 +22,7 @@ export const useTokenDetailsStore = defineStore('tokenDetails', () => { const rawTotalSupply = ref(null) const rawTokenHolders = ref(null) const tokenHoldersCount = ref(null) + const rawTokenTrades = ref(null) const tokenDetails = computed(() => rawToken.value ? adaptTokenDetails( @@ -41,11 +42,16 @@ export const useTokenDetailsStore = defineStore('tokenDetails', () => { : null, ) - const tokenEvents = computed(() => { - return rawTokenEvents.value + const tokenEvents = computed(() => + rawTokenEvents.value ? adaptTokenEvents(rawTokenEvents.value) - : null - }) + : null, + ) + + const tokenTrades = computed(() => rawTokenTrades.value + ? adaptTrades(rawTokenTrades.value, price.value) + : null, + ) function fetchTokenDetails(id) { tokenId.value = id @@ -101,15 +107,24 @@ export const useTokenDetailsStore = defineStore('tokenDetails', () => { tokenHoldersCount.value = data.holders } + async function fetchTokenTrades({ queryParameters, limit, contractId } = {}) { + rawTokenTrades.value = null + const defaultParameters = `/v3/dex/${contractId}/swaps?limit=${limit ?? 10}` + const { data } = await axios.get(`${MIDDLEWARE_URL}${queryParameters || defaultParameters}`) + rawTokenTrades.value = data + } + return { fetchTokenDetails, fetchTokenHolders, tokenHoldersCount, fetchTokenEvents, fetchTokenHoldersCount, + fetchTokenTrades, tokenDetails, tokenHolders, tokenEvents, tokenEventsCount, + tokenTrades, } }) diff --git a/src/stores/ui.js b/src/stores/ui.js index 752c58fa5..a025ac3ae 100644 --- a/src/stores/ui.js +++ b/src/stores/ui.js @@ -1,8 +1,16 @@ import { defineStore } from 'pinia' + export const useUiStore = defineStore('ui', () => { const isMobileMenuOpen = ref(false) + const timeFormat = ref('relative') + + function toggleTimeFormat() { + timeFormat.value = timeFormat.value === 'absolute' ? 'relative' : 'absolute' + } return { isMobileMenuOpen, + timeFormat, + toggleTimeFormat, } }) diff --git a/src/utils/adapters.js b/src/utils/adapters.js index b4f76bc56..2f7bbd062 100644 --- a/src/utils/adapters.js +++ b/src/utils/adapters.js @@ -14,6 +14,7 @@ import { formatTemplateLimit, formatTokenLimit, formatTradeRate, + formatTradeValue, } from '@/utils/format' import { MINUTES_PER_BLOCK, SPECIAL_POINTERS_PRESET_KEYS } from '@/utils/constants' @@ -739,7 +740,7 @@ export function adaptTrades(trades, price) { height: trade.height, timestamp: DateTime.fromMillis(trade.microTime), rate: formatTradeRate(trade.action, fromAmount, toAmount), - value: formatTradeValue(trade.action, fromAmount, toAmount, price), + value: price ? formatTradeValue(trade.action, fromAmount, toAmount, price) : null, } }) return {