From bd0796378b7339e67eedcb62b7a000f727f465a0 Mon Sep 17 00:00:00 2001 From: Bran <52735957+brancoder@users.noreply.github.com> Date: Thu, 7 Nov 2024 10:42:59 +0100 Subject: [PATCH] feat(tooling-dashboard): organize migration stardust objects (#3826) * feat: fetch stardust basic and nft objects * feat: organize stardust objects on migratable and unmigratable * fix: migration constants and variable nameing * fix: variable naming * fix: move constants to core * fix: evert adding routes to barrel * fix: remove undefined object check --------- Co-authored-by: Marc Espin --- apps/core/src/constants/index.ts | 1 + .../src}/constants/migration.constants.ts | 1 + .../app/(protected)/migrations/page.tsx | 77 ++++++++++--------- apps/wallet-dashboard/lib/interfaces/index.ts | 1 + .../lib/interfaces/migration.interface.ts | 47 +++++++++++ apps/wallet-dashboard/lib/utils/index.ts | 1 + apps/wallet-dashboard/lib/utils/migration.ts | 51 ++++++++++++ 7 files changed, 143 insertions(+), 36 deletions(-) rename apps/{wallet-dashboard/lib => core/src}/constants/migration.constants.ts (99%) create mode 100644 apps/wallet-dashboard/lib/interfaces/migration.interface.ts create mode 100644 apps/wallet-dashboard/lib/utils/migration.ts diff --git a/apps/core/src/constants/index.ts b/apps/core/src/constants/index.ts index 93409fc03e9..baca8bd0d9a 100644 --- a/apps/core/src/constants/index.ts +++ b/apps/core/src/constants/index.ts @@ -5,4 +5,5 @@ export * from './staking.constants'; export * from './recognizedPackages.constants'; export * from './coins.constants'; export * from './timelock.constants'; +export * from './migration.constants'; export * from './features.enum'; diff --git a/apps/wallet-dashboard/lib/constants/migration.constants.ts b/apps/core/src/constants/migration.constants.ts similarity index 99% rename from apps/wallet-dashboard/lib/constants/migration.constants.ts rename to apps/core/src/constants/migration.constants.ts index 41c57144881..6086a758e0f 100644 --- a/apps/wallet-dashboard/lib/constants/migration.constants.ts +++ b/apps/core/src/constants/migration.constants.ts @@ -1,5 +1,6 @@ // Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 + export const STARDUST_PACKAGE_ID = '000000000000000000000000000000000000000000000000000000000000107a'; export const STARDUST_BASIC_OUTPUT_TYPE = `${STARDUST_PACKAGE_ID}::basic_output::BasicOutput<0x2::iota::IOTA>`; diff --git a/apps/wallet-dashboard/app/(protected)/migrations/page.tsx b/apps/wallet-dashboard/app/(protected)/migrations/page.tsx index 3549f4d2080..645497c4030 100644 --- a/apps/wallet-dashboard/app/(protected)/migrations/page.tsx +++ b/apps/wallet-dashboard/app/(protected)/migrations/page.tsx @@ -3,48 +3,43 @@ 'use client'; import { VirtualList } from '@/components'; +import { useGetCurrentEpochStartTimestamp } from '@/hooks'; +import { groupStardustObjectsByMigrationStatus } from '@/lib/utils'; import { STARDUST_BASIC_OUTPUT_TYPE, STARDUST_NFT_OUTPUT_TYPE, -} from '@/lib/constants/migration.constants'; -import { useGetOwnedObjects } from '@iota/core'; + useGetAllOwnedObjects, +} from '@iota/core'; import { useCurrentAccount, useIotaClientContext } from '@iota/dapp-kit'; import { getNetwork, IotaObjectData } from '@iota/iota-sdk/client'; function MigrationDashboardPage(): JSX.Element { const account = useCurrentAccount(); + const address = account?.address || ''; const { network } = useIotaClientContext(); const { explorer } = getNetwork(network); + const { data: currentEpochMs } = useGetCurrentEpochStartTimestamp(); - const { - data: basicOutputObjects, - fetchNextPage: fetchNextPageBasic, - hasNextPage: hasNextPageBasic, - isFetchingNextPage: isFetchingNextPageBasic, - } = useGetOwnedObjects(account?.address || '', { + const { data: basicOutputObjects } = useGetAllOwnedObjects(address, { StructType: STARDUST_BASIC_OUTPUT_TYPE, }); - const { - data: nftOutputObjects, - fetchNextPage: fetchNextPageNft, - hasNextPage: hasNextPageNft, - isFetchingNextPage: isFetchingNextPageNft, - } = useGetOwnedObjects(account?.address || '', { + const { data: nftOutputObjects } = useGetAllOwnedObjects(address, { StructType: STARDUST_NFT_OUTPUT_TYPE, }); - const basicOutputs = - basicOutputObjects?.pages - .flatMap((page) => page.data) - .filter((asset) => asset.data && asset.data.objectId) - .map((response) => response.data!) ?? []; - - const nftOutputs = - nftOutputObjects?.pages - .flatMap((page) => page.data) - .filter((asset) => asset.data && asset.data.objectId) - .map((response) => response.data!) ?? []; + const { migratable: migratableBasicOutputs, unmigratable: unmigratableBasicOutputs } = + groupStardustObjectsByMigrationStatus( + basicOutputObjects ?? [], + Number(currentEpochMs), + address, + ); + const { migratable: migratableNftOutputs, unmigratable: unmigratableNftOutputs } = + groupStardustObjectsByMigrationStatus( + nftOutputObjects ?? [], + Number(currentEpochMs), + address, + ); const virtualItem = (asset: IotaObjectData): JSX.Element => ( {asset.objectId} @@ -52,25 +47,35 @@ function MigrationDashboardPage(): JSX.Element { ); return ( -
+
+
+

Migratable Basic Outputs: {migratableBasicOutputs.length}

+ 30} + render={virtualItem} + /> +
+
+

Unmigratable Basic Outputs: {unmigratableBasicOutputs.length}

+ 30} + render={virtualItem} + /> +
-

Basic Outputs

+

Migratable NFT Outputs: {migratableNftOutputs.length}

30} render={virtualItem} />
-

Nft Outputs

+

Unmigratable NFT Outputs: {unmigratableNftOutputs.length}

30} render={virtualItem} /> diff --git a/apps/wallet-dashboard/lib/interfaces/index.ts b/apps/wallet-dashboard/lib/interfaces/index.ts index eeab2cb4f5c..679bc45212f 100644 --- a/apps/wallet-dashboard/lib/interfaces/index.ts +++ b/apps/wallet-dashboard/lib/interfaces/index.ts @@ -3,5 +3,6 @@ export * from './transactions.interface'; export * from './timelock.interface'; +export * from './migration.interface'; export * from './vesting.interface'; export * from './appRoute.interface'; diff --git a/apps/wallet-dashboard/lib/interfaces/migration.interface.ts b/apps/wallet-dashboard/lib/interfaces/migration.interface.ts new file mode 100644 index 00000000000..df35ae29112 --- /dev/null +++ b/apps/wallet-dashboard/lib/interfaces/migration.interface.ts @@ -0,0 +1,47 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +type ExpirationUnlockCondition = { + owner: string; + return_address: string; + unix_time: number; +}; +type StorageDepositReturnUnlockCondition = { + return_address: string; + return_amount: string; +}; +type TimelockUnlockCondition = { + unix_time: number; +}; + +export type CommonOutputObject = { + id: { id: string }; + balance: string; + native_tokens: { + type: string; + fields: { id: { id: string }; size: string }; + }; +}; + +export interface CommonOutputObjectWithUc extends CommonOutputObject { + expiration_uc?: { + type: string; + fields: ExpirationUnlockCondition; + }; + storage_deposit_return_uc?: { + type: string; + fields: StorageDepositReturnUnlockCondition; + }; + timelock_uc?: { + type: string; + fields: TimelockUnlockCondition; + }; +} + +export interface BasicOutputObject extends CommonOutputObjectWithUc { + metadata?: number[]; + tag?: number[]; + sender?: string; +} + +export interface NftOutputObject extends CommonOutputObjectWithUc {} diff --git a/apps/wallet-dashboard/lib/utils/index.ts b/apps/wallet-dashboard/lib/utils/index.ts index 78b0f2eb9c5..27ddc5bc265 100644 --- a/apps/wallet-dashboard/lib/utils/index.ts +++ b/apps/wallet-dashboard/lib/utils/index.ts @@ -5,5 +5,6 @@ export * from './indexGenerator'; export * from './vesting'; export * from './time'; export * from './timelock'; +export * from './migration'; export * from './transaction'; export * from './growthbook'; diff --git a/apps/wallet-dashboard/lib/utils/migration.ts b/apps/wallet-dashboard/lib/utils/migration.ts new file mode 100644 index 00000000000..e4a5cfa1f30 --- /dev/null +++ b/apps/wallet-dashboard/lib/utils/migration.ts @@ -0,0 +1,51 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import { IotaObjectData } from '@iota/iota-sdk/client'; +import { CommonOutputObjectWithUc } from '../interfaces/migration.interface'; + +export type StardustMigrationGroupedObjects = { + migratable: IotaObjectData[]; + unmigratable: IotaObjectData[]; +}; + +export function groupStardustObjectsByMigrationStatus( + stardustOutputObjects: IotaObjectData[], + epochTimestamp: number, + address: string, +): StardustMigrationGroupedObjects { + const migratable: IotaObjectData[] = []; + const unmigratable: IotaObjectData[] = []; + + const epochUnix = epochTimestamp / 1000; + + for (const outputObject of stardustOutputObjects) { + const outputObjectFields = ( + outputObject.content as unknown as { + fields: CommonOutputObjectWithUc; + } + ).fields; + + if (outputObjectFields.expiration_uc) { + const unlockableAddress = + outputObjectFields.expiration_uc.fields.unix_time <= epochUnix + ? outputObjectFields.expiration_uc.fields.return_address + : outputObjectFields.expiration_uc.fields.owner; + if (unlockableAddress !== address) { + unmigratable.push(outputObject); + continue; + } + } + if ( + outputObjectFields.timelock_uc && + outputObjectFields.timelock_uc.fields.unix_time > epochUnix + ) { + unmigratable.push(outputObject); + continue; + } + + migratable.push(outputObject); + } + + return { migratable, unmigratable }; +}