Skip to content

Commit

Permalink
feat: Dex Trades per Token (#876)
Browse files Browse the repository at this point in the history
  • Loading branch information
janmichek authored Jan 13, 2025
1 parent d0f8737 commit 1b771c8
Show file tree
Hide file tree
Showing 11 changed files with 174 additions and 115 deletions.
3 changes: 3 additions & 0 deletions cypress/e2e/app/tokenDetail.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down
183 changes: 93 additions & 90 deletions src/components/DexTradesTable.vue
Original file line number Diff line number Diff line change
@@ -1,97 +1,100 @@
<template>
<table class="dex-trades-table">
<tr>
<th>
Hash
<hint-tooltip>
{{ dexTradesHints.hash }}
</hint-tooltip>
</th>
<th>
<time-toggle-button>Executed</time-toggle-button>
<hint-tooltip>
{{ dexTradesHints.executed }}
</hint-tooltip>
</th>
<th>
Action
<hint-tooltip>
{{ dexTradesHints.action }}
</hint-tooltip>
</th>
<thead>
<tr>
<th>
Hash
<hint-tooltip>
{{ dexTradesHints.hash }}
</hint-tooltip>
</th>
<th>
<time-toggle-button>Executed</time-toggle-button>
<hint-tooltip>
{{ dexTradesHints.executed }}
</hint-tooltip>
</th>
<th>
Action
<hint-tooltip>
{{ dexTradesHints.action }}
</hint-tooltip>
</th>

<th>
Token Amount (Out)
<hint-tooltip>
{{ dexTradesHints.tokenAmountOut }}
</hint-tooltip>
</th>
<th>
Token Amount (Out)
<hint-tooltip>
{{ dexTradesHints.tokenAmountOut }}
</hint-tooltip>
</th>

<th>
Token Amount (In)
<hint-tooltip>
{{ dexTradesHints.tokenAmountIn }}
</hint-tooltip>
</th>
<th>
Swapped Rate
<hint-tooltip>
{{ dexTradesHints.swappedRate }}
</hint-tooltip>
</th>
<th>
Value
<hint-tooltip>
{{ dexTradesHints.value }}
</hint-tooltip>
</th>
</tr>

<tr
v-for="trade in trades.data"
:key="trade.txHash">
<td>
<value-hash-ellipsed
:link-to="`/transactions/${trade.txHash}`"
:hash="trade.txHash"/>
</td>
<td>
<block-time-cell
:height="trade.height"
:timestamp="trade.timestamp"/>
</td>
<td>
<app-chip :variant="getChipVariant(trade.action)">
{{ trade.action }}
</app-chip>
</td>
<td>
<price-label
:contract-id="trade.fromContract"
:currency="trade.fromToken"
:price="trade.fromAmount"
:max-digits="4"
:has-link="true"/>
</td>
<td>
<price-label
:contract-id="trade.toContract"
:currency="trade.toToken"
:price="trade.toAmount"
:max-digits="4"
:has-link="true"/>
</td>
<td>
<not-available-label v-if="!trade.rate"/>
{{ trade.rate }}
</td>
<td>
<not-available-label v-if="!trade.value"/>
<template v-else>
$ {{ trade.value }}
</template>
</td>
</tr>
<th>
Token Amount (In)
<hint-tooltip>
{{ dexTradesHints.tokenAmountIn }}
</hint-tooltip>
</th>
<th>
Swapped Rate
<hint-tooltip>
{{ dexTradesHints.swappedRate }}
</hint-tooltip>
</th>
<th>
Value
<hint-tooltip>
{{ dexTradesHints.value }}
</hint-tooltip>
</th>
</tr>
</thead>
<tbody>
<tr
v-for="trade in trades.data"
:key="trade.txHash">
<td>
<value-hash-ellipsed
:link-to="`/transactions/${trade.txHash}`"
:hash="trade.txHash"/>
</td>
<td>
<block-time-cell
:height="trade.height"
:timestamp="trade.timestamp"/>
</td>
<td>
<app-chip :variant="getChipVariant(trade.action)">
{{ trade.action }}
</app-chip>
</td>
<td>
<price-label
:contract-id="trade.fromContract"
:currency="trade.fromToken"
:price="trade.fromAmount"
:max-digits="4"
:has-link="true"/>
</td>
<td>
<price-label
:contract-id="trade.toContract"
:currency="trade.toToken"
:price="trade.toAmount"
:max-digits="4"
:has-link="true"/>
</td>
<td>
<not-available-label v-if="!trade.rate"/>
{{ trade.rate }}
</td>
<td>
<not-available-label v-if="!trade.value"/>
<template v-else>
$ {{ trade.value }}
</template>
</td>
</tr>
</tbody>
</table>
</template>

Expand Down
6 changes: 3 additions & 3 deletions src/components/TimeToggleButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
</template>

<script setup>
import { useAppStore } from '@/stores/app'
import { useUiStore } from '@/stores/ui'
const { toggleTimeFormat } = useAppStore()
const { timeFormat } = storeToRefs(useAppStore())
const { toggleTimeFormat } = useUiStore()
const { timeFormat } = storeToRefs(useUiStore())
const suffix = computed(() => {
return timeFormat.value === 'relative' ? 'Age' : 'Time'
})
Expand Down
4 changes: 2 additions & 2 deletions src/components/TimestampLabel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
import { DateTime, Duration } from 'luxon'
import { DATETIME_UNITS } from '@/utils/constants'
import { useAppStore } from '@/stores/app'
import { useUiStore } from '@/stores/ui'
const { timeFormat } = storeToRefs(useAppStore())
const { timeFormat } = storeToRefs(useUiStore())
const props = defineProps({
timestamp: {
Expand Down
39 changes: 39 additions & 0 deletions src/components/TokenTradesPanel.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<template>
<app-panel class="token-trades-panel">
<paginated-content
:entities="tokenTrades"
pagination-style="history"
@prev-clicked="loadPrevTrades"
@next-clicked="loadNextTrades">
<dex-trades-table
:trades="tokenTrades"
class="u-hidden-mobile"/>
<dex-trades-table-condensed
:trades="tokenTrades"
class="u-hidden-desktop"/>
</paginated-content>
</app-panel>
</template>
<script setup>
const tokenDetailsStore = useTokenDetailsStore()
const { tokenTrades } = storeToRefs(tokenDetailsStore)
const { fetchTokenTrades } = tokenDetailsStore
const route = useRoute()
function loadPrevTrades() {
fetchTokenTrades({ queryParameters: tokenTrades.value.prev })
}
function loadNextTrades() {
fetchTokenTrades({ queryParameters: tokenTrades.value.next })
}
if (process.client) {
const limit = computed(() => isDesktop() ? 10 : 3)
await fetchTokenTrades({
contractId: route.params.id,
limit: limit.value,
})
}
</script>
5 changes: 4 additions & 1 deletion src/pages/tokens/[id].vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
<app-tab title="Events">
<token-events-panel/>
</app-tab>
<app-tab title="Trades">
<token-trades-panel/>
</app-tab>
</app-tabs>
</template>
<loader-panel v-else/>
Expand All @@ -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() {
Expand Down
12 changes: 0 additions & 12 deletions src/stores/app.js

This file was deleted.

1 change: 0 additions & 1 deletion src/stores/dex.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
25 changes: 20 additions & 5 deletions src/stores/tokenDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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(
Expand All @@ -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
Expand Down Expand Up @@ -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,
}
})
8 changes: 8 additions & 0 deletions src/stores/ui.js
Original file line number Diff line number Diff line change
@@ -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,
}
})
Loading

0 comments on commit 1b771c8

Please sign in to comment.