@visualizevalue/mint-app-base 0.1.42 → 0.1.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/components/MintToken.vue
CHANGED
|
@@ -81,10 +81,7 @@ const mintRequest = computed(() => async () => {
|
|
|
81
81
|
})
|
|
82
82
|
|
|
83
83
|
const minted = async () => {
|
|
84
|
-
await
|
|
85
|
-
store.fetchTokenBalance(props.token, address.value),
|
|
86
|
-
// store.fetchTokenMints(props.token),
|
|
87
|
-
])
|
|
84
|
+
await store.fetchTokenBalance(props.token, address.value)
|
|
88
85
|
|
|
89
86
|
emit('minted')
|
|
90
87
|
}
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
:key="mint.tx"
|
|
11
11
|
:block="currentBlock"
|
|
12
12
|
/>
|
|
13
|
-
<TokenMintTimelineItem v-if="
|
|
13
|
+
<TokenMintTimelineItem v-if="backfillComplete">
|
|
14
14
|
<Account :address="collection.owner" class="account" />
|
|
15
15
|
|
|
16
16
|
<span class="amount">1<span>×</span></span>
|
|
17
17
|
<span class="price">Artist Mint</span>
|
|
18
18
|
|
|
19
|
-
<span class="time-ago"><BlocksTimeAgo v-if="currentBlock" :blocks="currentBlock -
|
|
19
|
+
<span class="time-ago"><BlocksTimeAgo v-if="currentBlock" :blocks="currentBlock - mintedAtBlock" /></span>
|
|
20
20
|
|
|
21
21
|
<span class="links">
|
|
22
22
|
<NuxtLink :to="`${config.public.blockExplorer}/nft/${token.collection}/${token.tokenId}`" target="_blank">
|
|
@@ -26,12 +26,17 @@
|
|
|
26
26
|
</TokenMintTimelineItem>
|
|
27
27
|
</div>
|
|
28
28
|
|
|
29
|
+
<div v-if="! backfillComplete" v-show="! loading" ref="loadMore" class="load-more">
|
|
30
|
+
<Button @click="backfill">Load more</Button>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
29
33
|
<Loading v-if="loading || ! currentBlock" txt="Mint History..." />
|
|
30
34
|
</slot>
|
|
31
35
|
</section>
|
|
32
36
|
</template>
|
|
33
37
|
|
|
34
38
|
<script setup>
|
|
39
|
+
import { useElementVisibility } from '@vueuse/core'
|
|
35
40
|
import { useBlockNumber } from '@wagmi/vue'
|
|
36
41
|
|
|
37
42
|
const config = useRuntimeConfig()
|
|
@@ -45,11 +50,14 @@ const { token, collection } = defineProps({
|
|
|
45
50
|
const state = useOnchainStore()
|
|
46
51
|
|
|
47
52
|
const mints = computed(() => state.tokenMints(token.collection, token.tokenId))
|
|
53
|
+
const mintedAtBlock = computed(() => token.untilBlock - MINT_BLOCKS)
|
|
54
|
+
const backfillComplete = computed(() => token.mintsBackfilledUntilBlock <= mintedAtBlock.value)
|
|
48
55
|
|
|
49
|
-
const loading = ref(
|
|
56
|
+
const loading = ref(true)
|
|
50
57
|
onMounted(async () => {
|
|
51
58
|
loading.value = true
|
|
52
59
|
try {
|
|
60
|
+
console.info(`Attempting to load + backfill token mints for #${token.tokenId}`)
|
|
53
61
|
await state.fetchTokenMints(token)
|
|
54
62
|
await state.backfillTokenMints(token)
|
|
55
63
|
} catch (e) {
|
|
@@ -58,7 +66,25 @@ onMounted(async () => {
|
|
|
58
66
|
loading.value = false
|
|
59
67
|
})
|
|
60
68
|
|
|
61
|
-
watch(currentBlock, () =>
|
|
69
|
+
watch(currentBlock, () => {
|
|
70
|
+
if (loading.value) return
|
|
71
|
+
|
|
72
|
+
state.fetchTokenMints(token)
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
const backfill = async () => {
|
|
76
|
+
loading.value = true
|
|
77
|
+
await state.backfillTokenMints(token)
|
|
78
|
+
loading.value = false
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const loadMore = ref()
|
|
82
|
+
const loadMoreVisible = useElementVisibility(loadMore)
|
|
83
|
+
watch(loadMoreVisible, () => {
|
|
84
|
+
if (! loadMoreVisible.value) return
|
|
85
|
+
|
|
86
|
+
backfill()
|
|
87
|
+
})
|
|
62
88
|
</script>
|
|
63
89
|
|
|
64
90
|
<style scoped>
|
|
@@ -80,4 +106,11 @@ h1 {
|
|
|
80
106
|
display: grid;
|
|
81
107
|
gap: var(--spacer);
|
|
82
108
|
}
|
|
109
|
+
|
|
110
|
+
.load-more {
|
|
111
|
+
.button {
|
|
112
|
+
display: block;
|
|
113
|
+
width: 100%;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
83
116
|
</style>
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="token-mint-timeline-item">
|
|
3
3
|
<slot :mint="mint" :formatted-price="formattedPrice">
|
|
4
|
-
<
|
|
4
|
+
<NuxtLink :to="{ name: 'profile-address', params: { address: mint.address } }">
|
|
5
|
+
<Account :address="mint.address" class="account" />
|
|
6
|
+
</NuxtLink>
|
|
5
7
|
|
|
6
8
|
<span class="amount">{{ mint.amount.toString() }}<span>×</span></span>
|
|
7
9
|
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { getBalance, getPublicClient, readContract } from '@wagmi/core'
|
|
2
2
|
import { type GetBalanceReturnType } from '@wagmi/core'
|
|
3
|
-
import { parseAbiItem } from 'viem'
|
|
4
|
-
import type { MintEvent } from '~/
|
|
3
|
+
import { parseAbiItem, type PublicClient } from 'viem'
|
|
4
|
+
import type { MintEvent } from '~/utils/types'
|
|
5
5
|
|
|
6
|
-
export const CURRENT_STATE_VERSION =
|
|
6
|
+
export const CURRENT_STATE_VERSION = 4
|
|
7
|
+
export const MAX_BLOCK_RANGE = 2500n
|
|
8
|
+
export const MINT_BLOCKS = BLOCKS_PER_DAY
|
|
7
9
|
|
|
8
10
|
export const useOnchainStore = () => {
|
|
9
11
|
const { $wagmi } = useNuxtApp()
|
|
@@ -94,7 +96,7 @@ export const useOnchainStore = () => {
|
|
|
94
96
|
},
|
|
95
97
|
|
|
96
98
|
async fetchArtistProfile (address: `0x${string}`): Promise<Artist> {
|
|
97
|
-
const client = getPublicClient($wagmi, { chainId: 1 })
|
|
99
|
+
const client = getPublicClient($wagmi, { chainId: 1 }) as PublicClient
|
|
98
100
|
const block = await client.getBlockNumber()
|
|
99
101
|
|
|
100
102
|
// Only update once per hour
|
|
@@ -149,7 +151,7 @@ export const useOnchainStore = () => {
|
|
|
149
151
|
functionName: 'getCreatorCollections',
|
|
150
152
|
args: [artist],
|
|
151
153
|
chainId,
|
|
152
|
-
})).map((a: `0x${string}`) => a.toLowerCase())
|
|
154
|
+
})).map((a: `0x${string}`) => a.toLowerCase() as `0x${string}`)
|
|
153
155
|
|
|
154
156
|
if (this.artists[artist].collections.length === collectionAddresses.length) {
|
|
155
157
|
console.info(`Collections fetched already (${collectionAddresses.length} collections)`)
|
|
@@ -318,67 +320,62 @@ export const useOnchainStore = () => {
|
|
|
318
320
|
},
|
|
319
321
|
|
|
320
322
|
async fetchTokenMints (token: Token) {
|
|
321
|
-
const client = getPublicClient($wagmi)
|
|
323
|
+
const client = getPublicClient($wagmi) as PublicClient
|
|
324
|
+
const currentBlock = await client.getBlockNumber()
|
|
325
|
+
const mintedAtBlock = token.untilBlock - MINT_BLOCKS
|
|
326
|
+
const storedToken = this.collections[token.collection].tokens[token.tokenId.toString()]
|
|
322
327
|
|
|
323
|
-
// We want to sync
|
|
324
|
-
const currentBlock = await client.getBlockNumber({ chainId })
|
|
325
|
-
|
|
326
|
-
// Until when
|
|
328
|
+
// We want to sync until now, or when the mint closed
|
|
327
329
|
const toBlock = currentBlock > token.untilBlock ? token.untilBlock : currentBlock
|
|
328
330
|
|
|
329
|
-
if (token.mintsFetchedUntilBlock >= toBlock)
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
this.collections[token.collection].tokens[token.tokenId.toString()].mints = [
|
|
342
|
-
...await this.loadMintEvents(
|
|
343
|
-
token,
|
|
344
|
-
fromBlock,
|
|
345
|
-
toBlock
|
|
346
|
-
),
|
|
347
|
-
...(this.collections[token.collection].tokens[token.tokenId.toString()].mints) || [],
|
|
348
|
-
]
|
|
331
|
+
if (token.mintsFetchedUntilBlock >= toBlock) {
|
|
332
|
+
return console.info(`mints for #${token.tokenId} already fetched`)
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Initially, we want to sync backwards,
|
|
336
|
+
// but at most 5000 blocks (the general max range for an event query)
|
|
337
|
+
const maxRangeBlock = toBlock - MAX_BLOCK_RANGE
|
|
338
|
+
const fromBlock = token.mintsFetchedUntilBlock > maxRangeBlock // If we've already fetched
|
|
339
|
+
? token.mintsFetchedUntilBlock + 1n // we want to continue where we left off
|
|
340
|
+
: maxRangeBlock > mintedAtBlock // Otherwise we'll go back as far as possible
|
|
341
|
+
? maxRangeBlock // (to our max range)
|
|
342
|
+
: mintedAtBlock // (or all the way to when the token minted)
|
|
349
343
|
|
|
350
|
-
|
|
344
|
+
// Load mints in range
|
|
345
|
+
this.addTokenMints(token, await this.loadMintEvents(token, fromBlock, toBlock))
|
|
351
346
|
|
|
352
347
|
// Set sync status
|
|
353
|
-
|
|
348
|
+
storedToken.mintsFetchedUntilBlock = toBlock
|
|
354
349
|
|
|
355
350
|
// If this is our first fetch, mark until when we have backfilled
|
|
356
351
|
if (! token.mintsBackfilledUntilBlock) {
|
|
357
|
-
|
|
352
|
+
storedToken.mintsBackfilledUntilBlock = fromBlock
|
|
358
353
|
}
|
|
359
354
|
},
|
|
360
355
|
|
|
361
356
|
async backfillTokenMints (token: Token) {
|
|
362
|
-
const mintedAtBlock = token.untilBlock -
|
|
357
|
+
const mintedAtBlock = token.untilBlock - MINT_BLOCKS
|
|
358
|
+
const storedToken = this.collections[token.collection].tokens[token.tokenId.toString()]
|
|
363
359
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
) {
|
|
367
|
-
const toBlock = this.collections[token.collection].tokens[token.tokenId.toString()].mintsBackfilledUntilBlock
|
|
368
|
-
const fromBlock = toBlock - 5000n > mintedAtBlock ? toBlock - 5000n : mintedAtBlock
|
|
369
|
-
console.log(`Backfilling token mints blocks ${fromBlock}-${toBlock}`)
|
|
360
|
+
// If we've backfilled all the way;
|
|
361
|
+
if (storedToken.mintsBackfilledUntilBlock <= mintedAtBlock) return
|
|
370
362
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
...await this.loadMintEvents(token, fromBlock, toBlock)
|
|
374
|
-
]
|
|
363
|
+
// We want to fetch the tokens up until where we stopped backfilling (excluding the last block)
|
|
364
|
+
const toBlock = storedToken.mintsBackfilledUntilBlock - 1n
|
|
375
365
|
|
|
376
|
-
|
|
377
|
-
|
|
366
|
+
// We want to fetch until our max range (5000), or until when the token minted
|
|
367
|
+
const fromBlock = toBlock - MAX_BLOCK_RANGE > mintedAtBlock ? toBlock - MAX_BLOCK_RANGE : mintedAtBlock
|
|
368
|
+
console.log(`Backfilling token mints blocks ${fromBlock}-${toBlock}`)
|
|
369
|
+
|
|
370
|
+
// Finally, we update our database
|
|
371
|
+
this.addTokenMints(token, await this.loadMintEvents(token, fromBlock, toBlock), 'append')
|
|
372
|
+
|
|
373
|
+
// And save until when we have backfilled our tokens.
|
|
374
|
+
storedToken.mintsBackfilledUntilBlock = fromBlock
|
|
378
375
|
},
|
|
379
376
|
|
|
380
|
-
async loadMintEvents (token: Token, fromBlock: bigint, toBlock: bigint) {
|
|
381
|
-
const client = getPublicClient($wagmi, { chainId })
|
|
377
|
+
async loadMintEvents (token: Token, fromBlock: bigint, toBlock: bigint): Promise<MintEvent[]> {
|
|
378
|
+
const client = getPublicClient($wagmi, { chainId }) as PublicClient
|
|
382
379
|
|
|
383
380
|
const logs = await client.getLogs({
|
|
384
381
|
address: token.collection,
|
|
@@ -390,6 +387,8 @@ export const useOnchainStore = () => {
|
|
|
390
387
|
toBlock,
|
|
391
388
|
})
|
|
392
389
|
|
|
390
|
+
console.info(`Token mints fetched from ${fromBlock}-${toBlock}`)
|
|
391
|
+
|
|
393
392
|
return logs.map(l => ({
|
|
394
393
|
tokenId: token.tokenId,
|
|
395
394
|
address: l.args.minter,
|
|
@@ -398,8 +397,16 @@ export const useOnchainStore = () => {
|
|
|
398
397
|
tx: l.transactionHash,
|
|
399
398
|
unitPrice: l.args.unitPrice,
|
|
400
399
|
amount: l.args.amount,
|
|
401
|
-
price: l.args.amount * l.args.unitPrice,
|
|
402
|
-
})).reverse()
|
|
400
|
+
price: ( l.args.amount || 0n ) * ( l.args.unitPrice || 0n ),
|
|
401
|
+
}) as MintEvent).reverse()
|
|
402
|
+
},
|
|
403
|
+
|
|
404
|
+
async addTokenMints (token: Token, mints: MintEvent[], location: 'prepend'|'append' = 'prepend') {
|
|
405
|
+
const storedToken = this.collections[token.collection].tokens[token.tokenId.toString()]
|
|
406
|
+
|
|
407
|
+
storedToken.mints = location === 'prepend'
|
|
408
|
+
? [ ...mints, ...storedToken.mints ]
|
|
409
|
+
: [ ...storedToken.mints, ...mints ]
|
|
403
410
|
},
|
|
404
411
|
|
|
405
412
|
async addCollection (collection: Collection) {
|