From 35af4d30df51fceb6caf70b2bb5d58e21fcc377e Mon Sep 17 00:00:00 2001 From: Branko Bosnic Date: Mon, 4 Nov 2024 10:56:39 +0100 Subject: [PATCH] feat:add migration popup --- .../app/(protected)/migrations/page.tsx | 50 ++++++++++- .../components/Popup/Popups/MigratePopup.tsx | 82 +++++++++++++++++++ .../hooks/useMigrationTransaction.ts | 32 ++++++++ 3 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 apps/wallet-dashboard/components/Popup/Popups/MigratePopup.tsx create mode 100644 apps/wallet-dashboard/hooks/useMigrationTransaction.ts diff --git a/apps/wallet-dashboard/app/(protected)/migrations/page.tsx b/apps/wallet-dashboard/app/(protected)/migrations/page.tsx index 37d89caaec7..567051ab9d2 100644 --- a/apps/wallet-dashboard/app/(protected)/migrations/page.tsx +++ b/apps/wallet-dashboard/app/(protected)/migrations/page.tsx @@ -3,19 +3,25 @@ 'use client'; import { VirtualList } from '@/components'; -import { useGetCurrentEpochStartTimestamp } from '@/hooks'; +import MigratePopup from '@/components/Popup/Popups/MigratePopup'; +import { useGetCurrentEpochStartTimestamp, usePopups } from '@/hooks'; import { STARDUST_BASIC_OUTPUT_TYPE, STARDUST_NFT_OUTPUT_TYPE, } from '@/lib/constants/migration.constants'; import { groupStardustObjectsByMigrationStatus } from '@/lib/utils'; +import { Button } from '@iota/apps-ui-kit'; import { useGetAllOwnedObjects } from '@iota/core'; -import { useCurrentAccount, useIotaClientContext } from '@iota/dapp-kit'; +import { useCurrentAccount, useIotaClient, useIotaClientContext } from '@iota/dapp-kit'; import { getNetwork, IotaObjectData } from '@iota/iota-sdk/client'; +import { useQueryClient } from '@tanstack/react-query'; function MigrationDashboardPage(): JSX.Element { const account = useCurrentAccount(); const address = account?.address || ''; + const { openPopup, closePopup } = usePopups(); + const queryClient = useQueryClient(); + const iotaClient = useIotaClient(); const { network } = useIotaClientContext(); const { explorer } = getNetwork(network); const { data: currentEpochMs } = useGetCurrentEpochStartTimestamp(); @@ -46,6 +52,45 @@ function MigrationDashboardPage(): JSX.Element { ); + function handleOnSuccess(digest: string): void { + iotaClient + .waitForTransaction({ + digest, + }) + .then(() => { + queryClient.invalidateQueries({ + queryKey: [ + 'get-all-owned-objects', + account?.address, + { + StructType: STARDUST_BASIC_OUTPUT_TYPE, + }, + ], + }); + queryClient.invalidateQueries({ + queryKey: [ + 'get-all-owned-objects', + account?.address, + { + StructType: STARDUST_NFT_OUTPUT_TYPE, + }, + ], + }); + }); + } + function openMigratePopup(): void { + const stardustOutputObjects = [...migratableBasicOutputs, ...migratableNftOutputs]; + if (stardustOutputObjects.length > 0) { + openPopup( + , + ); + } + } + return (
@@ -80,6 +125,7 @@ function MigrationDashboardPage(): JSX.Element { render={virtualItem} />
+
); } diff --git a/apps/wallet-dashboard/components/Popup/Popups/MigratePopup.tsx b/apps/wallet-dashboard/components/Popup/Popups/MigratePopup.tsx new file mode 100644 index 00000000000..281f8985e92 --- /dev/null +++ b/apps/wallet-dashboard/components/Popup/Popups/MigratePopup.tsx @@ -0,0 +1,82 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import React from 'react'; +import { VirtualList } from '@/components'; +import { + useCurrentAccount, + useIotaClientContext, + useSignAndExecuteTransaction, +} from '@iota/dapp-kit'; +import { getNetwork, IotaObjectData } from '@iota/iota-sdk/client'; +import { useMigrationTransaction } from '@/hooks/useMigrationTransaction'; +import { Button } from '@iota/apps-ui-kit'; +import { useNotifications } from '@/hooks'; +import { NotificationType } from '@/stores/notificationStore'; + +interface MigratePopupProps { + stardustOutputObjects: IotaObjectData[]; + closePopup: () => void; + onSuccess?: (digest: string) => void; +} + +function MigratePopup({ + stardustOutputObjects, + closePopup, + onSuccess, +}: MigratePopupProps): JSX.Element { + const account = useCurrentAccount(); + const { addNotification } = useNotifications(); + const { data: migrateData } = useMigrationTransaction( + stardustOutputObjects, + account?.address || '', + ); + const { network } = useIotaClientContext(); + const { explorer } = getNetwork(network); + const { mutateAsync: signAndExecuteTransaction, isPending } = useSignAndExecuteTransaction(); + + async function handleMigrate(): Promise { + if (!migrateData) return; + signAndExecuteTransaction( + { + transaction: migrateData.transaction, + }, + { + onSuccess: (tx) => { + if (onSuccess) { + onSuccess(tx.digest); + } + }, + }, + ) + .then(() => { + closePopup(); + addNotification('Migration transaction has been sent'); + }) + .catch(() => { + addNotification('Migration transaction was not sent', NotificationType.Error); + }); + } + + const virtualItem = (asset: IotaObjectData): JSX.Element => ( + + {asset.objectId} + + ); + return ( +
+
+

Migratable Outputs: {stardustOutputObjects.length}

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

Gas Fees: {migrateData?.gasBudget?.toString() || '--'}

+
+ ); +} + +export default MigratePopup; diff --git a/apps/wallet-dashboard/hooks/useMigrationTransaction.ts b/apps/wallet-dashboard/hooks/useMigrationTransaction.ts new file mode 100644 index 00000000000..028af412aaf --- /dev/null +++ b/apps/wallet-dashboard/hooks/useMigrationTransaction.ts @@ -0,0 +1,32 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import { useIotaClient } from '@iota/dapp-kit'; +import { IotaObjectData } from '@iota/iota-sdk/client'; +import { Transaction } from '@iota/iota-sdk/transactions'; +import { useQuery } from '@tanstack/react-query'; + +export function useMigrationTransaction( + stardustOutputObjects: IotaObjectData[], + senderAddress: string, +) { + const client = useIotaClient(); + return useQuery({ + // eslint-disable-next-line @tanstack/query/exhaustive-deps + queryKey: ['migration-transaction', senderAddress], + queryFn: async () => { + const transaction = new Transaction(); + transaction.setSender(senderAddress); + await transaction.build({ client }); + return transaction; + }, + enabled: !!stardustOutputObjects && !!senderAddress, + gcTime: 0, + select: (transaction) => { + return { + transaction, + gasBudget: transaction.getData().gasData.budget, + }; + }, + }); +}