components/migrate/steps/SignLoader2.vue
<template>
<div class="mb-5">
<div class="flex items-center mb-4">
<div class="mr-5">
<NeoIcon
v-bind="whichIcon()"
class="fa-2x"
/>
</div>
<div>
<p class="font-bold text-xl">
{{ $t('migrate.signStep.migratingItems') }}
</p>
<p class="text-k-grey">
{{ $t('migrate.signStep.signtx') }}
</p>
</div>
</div>
<div class="flex">
<div class="v-border" />
<div class="mb-4">
<p v-if="iterations">
{{ iterations }}/{{ maxIterations }} {{ $t('migrate.signStep.left') }}
</p>
<p v-else>
{{ $t('migrate.signStep.done') }}
</p>
</div>
</div>
<div
v-for="(_, index) in maxIterations"
:key="index"
class="flex"
>
<div class="v-border" />
<div class="mb-4 flex w-full">
<NeoIcon
v-bind="itemLeftIcons(index)"
class="mr-4"
/>
<div :class="itemLeftIcons(index).textColor">
<p>{{ $t('migrate.signStep.migratingNItems', itemLeft(index)) }}</p>
</div>
<div
v-if="isError || status === TransactionStatus.Cancelled"
class="flex-1 text-right"
>
<NeoButton
variant="outlined-rounded"
size="small"
@click="tryAgain()"
>
{{ $t('helper.tryAgain') }}
</NeoButton>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import type { Prefix } from '@kodadot1/static'
import { NeoButton, NeoIcon } from '@kodadot1/brick'
import {
BATCH_SIZE,
type Steps,
calculateIterations,
iconIdle,
iconLoading,
iconSuccess,
useCollectionReady,
} from '@/composables/useMigrate'
import waifuApi from '@/services/waifu'
const { accountId } = useAuth()
const { apiInstance } = useApi()
const { howAboutToExecute, status, isError } = useMetaTransaction()
const { $consola } = useNuxtApp()
const route = useRoute()
const router = useRouter()
const from = route.query.source as Prefix
const fromAccountId = route.query.accountId?.toString()
const itemCount = route.query.itemCount?.toString()
const collectionOwner = route.query.collectionOwner?.toString()
const collectionId = route.query.collectionId
const { collections } = await useCollectionReady(from, fromAccountId)
const fromCollection = collections.value.find(
collection => collection.id === route.query.collectionId,
)
const api = await apiInstance.value
const { steps, updateSteps } = inject('steps') as {
steps: Ref<Steps>
updateSteps: (step: Steps) => void
}
const maxIterations = calculateIterations(itemCount)
const iterations = ref(maxIterations)
const batchPresigned = reactive({})
const itemLeft = (index) => {
if (index === maxIterations - 1) {
return parseInt(itemCount || '0') % BATCH_SIZE
}
return BATCH_SIZE
}
const itemLeftIcons = (index) => {
if (isError.value || status.value === TransactionStatus.Cancelled) {
return iconError
}
if (steps.value.includes('init') || steps.value.includes('step1')) {
return iconIdle
}
if (iterations.value < maxIterations - index) {
return iconSuccess
}
if (iterations.value <= maxIterations - index) {
return iconLoading
}
return iconIdle
}
const tryAgain = () => {
iterations.value += 1
startStep2()
}
const startStep2 = async () => {
let nextCollectionId
try {
for (let index = 0; index < iterations.value; index++) {
const fromCollectionId = collectionOwner
? collectionId
: fromCollection?.id
const checkSign = await waifuApi(
`/relocations/${from}/${fromCollectionId}/iterations/${index}`,
{
method: 'PUT',
},
)
const ownerSign = checkSign.data.filter(
item => item.account === accountId.value,
)
if (!nextCollectionId) {
nextCollectionId = ownerSign[0]?.to_collection
}
const presigned = ownerSign.map((item) => {
const preSignInfo = api.createType('PalletNftsPreSignedMint', item.data)
const create = api.tx.nfts.mintPreSigned(
preSignInfo,
{
Ed25519: item.signature,
},
item.signer,
)
return create
})
batchPresigned[index] = presigned
}
if (collectionOwner && nextCollectionId) {
router.push({
query: {
...route.query,
nextCollectionId,
},
})
}
executeStep2()
}
catch (error) {
$consola.error('error step2', error)
}
}
const executeStep2 = async () => {
updateSteps('step2-migrate')
if (
status.value
&& status.value !== TransactionStatus.Finalized
&& status.value !== TransactionStatus.Cancelled
) {
await delay(DETAIL_TIMEOUT)
executeStep2()
return
}
if (iterations.value) {
const cb = api.tx.utility.batch
const args = [toRaw(batchPresigned[maxIterations - iterations.value])]
iterations.value -= 1
await howAboutToExecute(accountId.value, cb, args)
await delay(DETAIL_TIMEOUT)
if (iterations.value) {
executeStep2()
}
}
}
watchEffect(() => {
$consola.info('SignLoader2.vue', steps.value, status.value)
if (steps.value === 'step2') {
startStep2()
}
// Done, move to step3
if (
steps.value === 'step2-migrate'
&& !iterations.value
&& status.value === TransactionStatus.Finalized
) {
updateSteps('step3')
}
})
const whichIcon = () => {
if (isError.value || status.value === TransactionStatus.Cancelled) {
return iconError
}
if (iterations.value === 0) {
return iconSuccess
}
if (steps.value.includes('step2')) {
return iconLoading
}
return iconIdle
}
</script>