Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: expire trades based on blockNumber #11370

Merged
merged 3 commits into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions components/trade/TradeActivityTableRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,12 @@
<div class="flex-1">
<div class="h-[50px] flex items-center">
<template v-if="trade.expirationDate">
<div v-if="isExpired">
<div v-if="trade.isExpired">
<span>{{ $t('expired') }}</span>
</div>
<div v-else>
<span>{{ format(trade.expirationDate, EXPIRATION_FORMAT) }}</span>
<span class="text-k-grey ml-3">({{ formatToNow(trade.expirationDate, isExpired) }})</span>
<span class="text-k-grey ml-3">({{ formatToNow(trade.expirationDate, trade.isExpired) }})</span>
</div>
</template>
<span v-else>
Expand Down Expand Up @@ -147,12 +147,12 @@
{{ blank }}
</div>
<template v-if="trade.expirationDate">
<div v-if="isExpired">
<div v-if="trade.isExpired">
<span>{{ $t('expired') }}</span>
</div>
<div v-else>
<span>{{ format(trade.expirationDate, EXPIRATION_FORMAT) }}</span>
<span class="text-k-grey ml-3">({{ formatToNow(trade.expirationDate, isExpired) }})</span>
<span class="text-k-grey ml-3">({{ formatToNow(trade.expirationDate, trade.isExpired) }})</span>
</div>
</template>
<span v-else>
Expand Down Expand Up @@ -241,7 +241,6 @@ const image = ref()
const animationUrl = ref()

const isDesktop = computed(() => props.variant === 'Desktop')
const isExpired = computed(() => props.trade.status === TradeStatus.EXPIRED)

const isTradeCollection = computed(() => desiredType === TradeDesiredType.COLLECTION)
const itemPath = computed(() => isTradeCollection.value ? `/${urlPrefix.value}/collection/${item.id}` : `/${urlPrefix.value}/gallery/${item.id}`)
Expand Down
2 changes: 1 addition & 1 deletion components/trade/TradeOwnerButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const details = {
}

const buttonConfig = computed<ButtonConfig | null>(() => {
if (props.trade.status === TradeStatus.EXPIRED) {
if (props.trade.isExpired) {
return isCreatorOfTrade.value
? {
label: $i18n.t(details[props.trade.type].withdraw),
Expand Down
3 changes: 1 addition & 2 deletions components/trade/overviewModal/Details.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
{{ $t('expiration') }}
</span>

<span v-if="trade.status === TradeStatus.EXPIRED">
<span v-if="trade.isExpired">
{{ $t('expired') }}
</span>
<span v-else>
Expand All @@ -45,7 +45,6 @@
<script setup lang="ts">
import { useIsTradeOverview } from './utils'
import { formatToNow } from '@/utils/format/time'
import { TradeStatus } from '@/composables/useTrades'
import type { NFT } from '@/types'

const props = defineProps<{
Expand Down
4 changes: 3 additions & 1 deletion composables/transaction/transactionOffer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ export const getOfferCollectionId = (prefix: Prefix) => {

export const OFFER_MINT_PRICE = 5e8

export const BLOCKS_PER_DAY = 300 * 24 // 12sec /block --> 300blocks/hr
export const SECONDS_PER_BLOCK = 12 // 12 sec/block
const BLOCKS_PER_HOUR = (3600 / SECONDS_PER_BLOCK) // 300 blocks/hr
export const BLOCKS_PER_DAY = BLOCKS_PER_HOUR * 24

async function execMakingOffer(item: ActionOffer, api: ApiPromise, executeTransaction) {
const { accountId } = useAuth()
Expand Down
39 changes: 39 additions & 0 deletions composables/useCurrentBlock.ts
vikiival marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { SECONDS_PER_BLOCK } from '@/composables/transaction/transactionOffer'

const currentBlock = ref(0)
const interval = ref<NodeJS.Timeout>()
const syncCount = ref(0)

export default function useCurrentBlock() {
const { apiInstance } = useApi()

const getCurrentBlock = async () => {
const api = await apiInstance.value
const { number } = await api.rpc.chain.getHeader()
return number.toNumber()
}

const syncCurrentBlock = async () => {
currentBlock.value = await getCurrentBlock()
}

syncCount.value++

if (syncCount.value === 1) {
onBeforeMount(async () => {
await syncCurrentBlock()
interval.value = setInterval(syncCurrentBlock, SECONDS_PER_BLOCK * 1000)
})
}

onBeforeUnmount(() => {
syncCount.value--

if (syncCount.value === 0 && interval.value) {
clearInterval(interval.value)
interval.value = undefined
}
})

return currentBlock
}
17 changes: 6 additions & 11 deletions composables/useTrades.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export type TradeNftItem<T = Trade> = T & {
type: TradeType
desiredType: TradeDesiredType
isEntireCollectionDesired: boolean
isExpired: boolean
}

export const TRADES_QUERY_MAP: Record<TradeType, { queryDocument: DocumentNode, dataKey: string }> = {
Expand All @@ -78,7 +79,6 @@ export const TRADES_QUERY_MAP: Record<TradeType, { queryDocument: DocumentNode,
}

const BLOCKS_PER_HOUR = 300
const currentBlock = ref(0)

export default function ({ where = {}, limit = 100, disabled = computed(() => false), type = TradeType.SWAP }: {
where?: MaybeRef<Record<string, unknown>>
Expand All @@ -89,6 +89,8 @@ export default function ({ where = {}, limit = 100, disabled = computed(() => fa
const { queryDocument, dataKey } = TRADES_QUERY_MAP[type]

const { client } = usePrefix()
const currentBlock = useCurrentBlock()

const variables = computed(() => ({
where: unref(where),
limit: limit,
Expand Down Expand Up @@ -116,23 +118,16 @@ export default function ({ where = {}, limit = 100, disabled = computed(() => fa
offered: trade.nft,
desiredType: desiredType,
isEntireCollectionDesired: desiredType === TradeDesiredType.COLLECTION,
// Check block number to handle trades that are expired but not yet updated in indexer
// @see https://github.com/kodadot/stick/blob/9eac12938c47bf0e66e93760231208e4249d8637/src/mappings/utils/cache.ts#L127
isExpired: trade.status === TradeStatus.EXPIRED || currentBlock.value > Number(trade.expiration),
type,
} as TradeNftItem
}) || []
})

async function getCurrentBlock() {
const api = await useApi().apiInstance.value
const { number } = await api.rpc.chain.getHeader()
return number.toNumber()
}

const loading = computed(() => !currentBlock.value || fetching.value)

if (!currentBlock.value) {
getCurrentBlock().then(b => currentBlock.value = b)
}

return {
items,
loading,
Expand Down
Loading