diff --git a/apps/core/package.json b/apps/core/package.json index fd24dd7be3d..0a8cd7acfeb 100644 --- a/apps/core/package.json +++ b/apps/core/package.json @@ -26,12 +26,16 @@ "@amplitude/analytics-types": "^0.20.0", "@growthbook/growthbook-react": "^1.0.0", "@hookform/resolvers": "^3.9.0", + "@iota/apps-ui-kit": "workspace:*", "@iota/dapp-kit": "workspace:*", "@iota/iota-sdk": "workspace:*", "@iota/kiosk": "workspace:*", + "@iota/ui-icons": "workspace:*", "@sentry/react": "^7.59.2", "@tanstack/react-query": "^5.50.1", "bignumber.js": "^9.1.1", + "clsx": "^2.1.1", + "formik": "^2.4.2", "qrcode.react": "^4.0.1", "react": "^18.3.1", "react-dom": "^18.3.1", diff --git a/apps/core/src/components/Inputs/AddressInput.tsx b/apps/core/src/components/Inputs/AddressInput.tsx new file mode 100644 index 00000000000..63920a9afe0 --- /dev/null +++ b/apps/core/src/components/Inputs/AddressInput.tsx @@ -0,0 +1,67 @@ +// Copyright (c) Mysten Labs, Inc. +// Modifications Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import { Input, InputType } from '@iota/apps-ui-kit'; +import { Close } from '@iota/ui-icons'; +import { useIotaAddressValidation } from '../../hooks'; +import React, { useCallback } from 'react'; +import { useField, useFormikContext } from 'formik'; + +export interface AddressInputProps { + name: string; + disabled?: boolean; + placeholder?: string; + label?: string; +} + +export function AddressInput({ + name, + disabled, + placeholder = '0x...', + label = 'Enter Recipient Address', +}: AddressInputProps) { + const { validateField } = useFormikContext(); + const [field, meta, helpers] = useField(name); + const iotaAddressValidation = useIotaAddressValidation(); + + const formattedValue = iotaAddressValidation.cast(field.value); + + const handleOnChange = useCallback( + async (e: React.ChangeEvent) => { + const address = e.currentTarget.value; + await helpers.setValue(iotaAddressValidation.cast(address)); + validateField(name); + }, + [name, iotaAddressValidation], + ); + + const clearAddress = () => { + helpers.setValue(''); + }; + + return ( + + + + ) : undefined + } + /> + ); +} diff --git a/apps/core/src/components/Inputs/SendTokenFormInput.tsx b/apps/core/src/components/Inputs/SendTokenFormInput.tsx new file mode 100644 index 00000000000..b0fffbc2ea3 --- /dev/null +++ b/apps/core/src/components/Inputs/SendTokenFormInput.tsx @@ -0,0 +1,80 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import { ButtonPill, Input, InputType } from '@iota/apps-ui-kit'; +import { CoinStruct } from '@iota/iota-sdk/client'; +import { useGasBudgetEstimation } from '../../hooks'; +import { useEffect } from 'react'; +import { useField, useFormikContext } from 'formik'; +import { TokenForm } from '../../forms'; + +export interface SendTokenInputProps { + coins: CoinStruct[]; + symbol: string; + coinDecimals: number; + activeAddress: string; + to: string; + onActionClick: () => Promise; + isMaxActionDisabled?: boolean; + name: string; +} + +export function SendTokenFormInput({ + coins, + to, + symbol, + coinDecimals, + activeAddress, + onActionClick, + isMaxActionDisabled, + name, +}: SendTokenInputProps) { + const { values, setFieldValue, isSubmitting, validateField } = useFormikContext(); + const gasBudgetEstimation = useGasBudgetEstimation({ + coinDecimals, + coins: coins ?? [], + activeAddress, + to: to, + amount: values.amount, + isPayAllIota: values.isPayAllIota, + }); + + const [field, meta, helpers] = useField(name); + const errorMessage = meta.error; + const isActionButtonDisabled = isSubmitting || isMaxActionDisabled; + + const renderAction = () => ( + + Max + + ); + + // gasBudgetEstimation should change when the amount above changes + useEffect(() => { + setFieldValue('gasBudgetEst', gasBudgetEstimation, false); + }, [gasBudgetEstimation, setFieldValue, values.amount]); + + return ( + { + await helpers.setValue(values.value); + validateField(name); + }} + /> + ); +} diff --git a/apps/core/src/components/Inputs/index.ts b/apps/core/src/components/Inputs/index.ts new file mode 100644 index 00000000000..5ab7c849a28 --- /dev/null +++ b/apps/core/src/components/Inputs/index.ts @@ -0,0 +1,5 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +export * from './AddressInput'; +export * from './SendTokenFormInput'; diff --git a/apps/wallet/src/ui/app/components/coin-icon/index.tsx b/apps/core/src/components/coin/CoinIcon.tsx similarity index 87% rename from apps/wallet/src/ui/app/components/coin-icon/index.tsx rename to apps/core/src/components/coin/CoinIcon.tsx index 5214a1e7420..77dd5e2a43c 100644 --- a/apps/wallet/src/ui/app/components/coin-icon/index.tsx +++ b/apps/core/src/components/coin/CoinIcon.tsx @@ -2,10 +2,11 @@ // Modifications Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -import { ImageIcon, ImageIconSize } from '_app/shared/image-icon'; -import { useCoinMetadata } from '@iota/core'; -import { IOTA_TYPE_ARG } from '@iota/iota-sdk/utils'; +import React from 'react'; +import { useCoinMetadata } from '../../hooks'; import { IotaLogoMark } from '@iota/ui-icons'; +import { IOTA_TYPE_ARG } from '@iota/iota-sdk/utils'; +import { ImageIcon, ImageIconSize } from '../icon'; import cx from 'clsx'; interface NonIotaCoinProps { @@ -28,7 +29,6 @@ function NonIotaCoin({ coinType, size = ImageIconSize.Full, rounded }: NonIotaCo ); } - export interface CoinIconProps { coinType: string; size?: ImageIconSize; @@ -37,7 +37,7 @@ export interface CoinIconProps { export function CoinIcon({ coinType, size = ImageIconSize.Full, rounded }: CoinIconProps) { return coinType === IOTA_TYPE_ARG ? ( -
+
) : ( diff --git a/apps/core/src/components/coin/CoinSelector.tsx b/apps/core/src/components/coin/CoinSelector.tsx new file mode 100644 index 00000000000..254b0180982 --- /dev/null +++ b/apps/core/src/components/coin/CoinSelector.tsx @@ -0,0 +1,61 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import { IOTA_TYPE_ARG } from '@iota/iota-sdk/utils'; +import { Select, SelectOption } from '@iota/apps-ui-kit'; +import { CoinBalance } from '@iota/iota-sdk/client'; +import { useFormatCoin } from '../../hooks'; +import { CoinIcon } from './CoinIcon'; +import { ImageIconSize } from '../icon'; + +interface CoinSelectorProps { + activeCoinType: string; + coins: CoinBalance[]; + onClick: (coinType: string) => void; +} + +export function CoinSelector({ + activeCoinType = IOTA_TYPE_ARG, + coins, + onClick, +}: CoinSelectorProps) { + const activeCoin = coins?.find(({ coinType }) => coinType === activeCoinType) ?? coins?.[0]; + const initialValue = activeCoin?.coinType; + const coinsOptions: SelectOption[] = + coins?.map((coin) => ({ + id: coin.coinType, + renderLabel: () => , + })) || []; + + return ( + - {placeholder && ( - - )} - - {options.map((option, index) => ( - - ))} - - ); -} - -export default Dropdown; diff --git a/apps/wallet-dashboard/components/Popup/Popups/SendCoinPopup/SendCoinPopup.tsx b/apps/wallet-dashboard/components/Popup/Popups/SendCoinPopup/SendCoinPopup.tsx deleted file mode 100644 index c3f917df955..00000000000 --- a/apps/wallet-dashboard/components/Popup/Popups/SendCoinPopup/SendCoinPopup.tsx +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -import React, { useState } from 'react'; -import { EnterValuesFormView, ReviewValuesFormView } from './views'; -import { CoinBalance } from '@iota/iota-sdk/client'; -import { useSendCoinTransaction, useNotifications } from '@/hooks'; -import { useSignAndExecuteTransaction } from '@iota/dapp-kit'; -import { NotificationType } from '@/stores/notificationStore'; -import { Dropdown } from '@/components'; -import { useGetAllCoins } from '@iota/core'; - -export interface FormDataValues { - amount: string; - recipientAddress: string; -} - -interface SendCoinPopupProps { - coin: CoinBalance; - senderAddress: string; - onClose: () => void; - coins: CoinBalance[]; -} - -enum FormStep { - EnterValues, - ReviewValues, -} - -function SendCoinPopup({ - coin, - senderAddress, - onClose, - coins, -}: SendCoinPopupProps): React.JSX.Element { - const [step, setStep] = useState(FormStep.EnterValues); - const [selectedCoin, setCoin] = useState(coin); - const [formData, setFormData] = useState({ - amount: '', - recipientAddress: '', - }); - const { addNotification } = useNotifications(); - - const { data: coinsData } = useGetAllCoins(selectedCoin.coinType, senderAddress); - - const { - mutateAsync: signAndExecuteTransaction, - error, - isPending, - } = useSignAndExecuteTransaction(); - const { data: sendCoinData } = useSendCoinTransaction( - coinsData || [], - selectedCoin.coinType, - senderAddress, - formData.recipientAddress, - formData.amount, - selectedCoin.totalBalance === formData.amount, - ); - - function handleTransfer() { - if (!sendCoinData?.transaction) { - addNotification('There was an error with the transaction', NotificationType.Error); - return; - } else { - signAndExecuteTransaction({ - transaction: sendCoinData.transaction, - }) - .then(() => { - onClose(); - addNotification('Transfer transaction has been sent'); - }) - .catch(() => { - addNotification('Transfer transaction was not sent', NotificationType.Error); - }); - } - } - - function onNext(): void { - setStep(FormStep.ReviewValues); - } - - function onBack(): void { - setStep(FormStep.EnterValues); - } - - function handleSelectedCoin(coin: CoinBalance): void { - setCoin(coin); - setFormData({ - amount: '', - recipientAddress: '', - }); - } - - return ( - <> - _selectedCoin.coinType} - /> - {step === FormStep.EnterValues && ( - - )} - {step === FormStep.ReviewValues && ( - - )} - - ); -} - -export default SendCoinPopup; diff --git a/apps/wallet-dashboard/components/Popup/Popups/SendCoinPopup/views/EnterValuesFormView.tsx b/apps/wallet-dashboard/components/Popup/Popups/SendCoinPopup/views/EnterValuesFormView.tsx deleted file mode 100644 index 8c094ac8a90..00000000000 --- a/apps/wallet-dashboard/components/Popup/Popups/SendCoinPopup/views/EnterValuesFormView.tsx +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -import { CoinBalance } from '@iota/iota-sdk/client'; -import { FormDataValues } from '../SendCoinPopup'; -import { Button } from '@/components'; -import { useFormatCoin } from '@iota/core'; - -interface EnterValuesFormProps { - coin: CoinBalance; - formData: FormDataValues; - gasBudget: string; - setFormData: React.Dispatch>; - onClose: () => void; - onNext: () => void; -} - -function EnterValuesFormView({ - coin: { totalBalance, coinType }, - formData: { amount, recipientAddress }, - gasBudget, - setFormData, - onClose, - onNext, -}: EnterValuesFormProps): JSX.Element { - const handleChange = (e: React.ChangeEvent) => { - const { name, value } = e.target; - setFormData((prevFormData) => ({ - ...prevFormData, - [name]: value, - })); - }; - const [formattedCoin, coinSymbol, { data: coinMeta }] = useFormatCoin(totalBalance, coinType); - - return ( -
-

Send

-
-

{coinMeta?.name.toUpperCase() ?? coinType}

-

- Balance: {formattedCoin} {coinSymbol} -

- - - - -

Gas fee: {gasBudget}

-
-
- - -
-
- ); -} - -export default EnterValuesFormView; diff --git a/apps/wallet-dashboard/components/Popup/Popups/SendCoinPopup/views/index.ts b/apps/wallet-dashboard/components/Popup/Popups/SendCoinPopup/views/index.ts deleted file mode 100644 index 57e3b376e7b..00000000000 --- a/apps/wallet-dashboard/components/Popup/Popups/SendCoinPopup/views/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -export { default as EnterValuesFormView } from './EnterValuesFormView'; -export { default as ReviewValuesFormView } from './ReviewValuesFormView'; diff --git a/apps/wallet-dashboard/components/Popup/Popups/index.ts b/apps/wallet-dashboard/components/Popup/Popups/index.ts index f6dcf9b3a31..e0e4a17db69 100644 --- a/apps/wallet-dashboard/components/Popup/Popups/index.ts +++ b/apps/wallet-dashboard/components/Popup/Popups/index.ts @@ -3,8 +3,6 @@ export { default as TransactionDetailsPopup } from './TransactionDetailsPopup'; export { default as UnstakePopup } from './UnstakePopup'; -export { default as SendCoinPopup } from './SendCoinPopup/SendCoinPopup'; export { default as SendAssetPopup } from './SendAssetPopup'; -export * from './SendCoinPopup'; export * from './VestingPopup'; diff --git a/apps/wallet-dashboard/components/account-balance/AccountBalance.tsx b/apps/wallet-dashboard/components/account-balance/AccountBalance.tsx index 55ac2567f89..151a46d473f 100644 --- a/apps/wallet-dashboard/components/account-balance/AccountBalance.tsx +++ b/apps/wallet-dashboard/components/account-balance/AccountBalance.tsx @@ -1,56 +1,29 @@ // Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -import { useCurrentAccount, useIotaClientContext, useIotaClientQuery } from '@iota/dapp-kit'; +import { useCurrentAccount, useIotaClientContext } from '@iota/dapp-kit'; import { formatAddress, IOTA_TYPE_ARG } from '@iota/iota-sdk/utils'; -import { - COINS_QUERY_REFETCH_INTERVAL, - COINS_QUERY_STALE_TIME, - filterAndSortTokenBalances, - useBalance, - useFormatCoin, -} from '@iota/core'; +import { useBalance, useFormatCoin } from '@iota/core'; import { Address, Button, ButtonSize, ButtonType, Panel } from '@iota/apps-ui-kit'; -import { CoinBalance, getNetwork } from '@iota/iota-sdk/client'; -import { SendCoinPopup } from '../Popup'; -import { ReceiveFundsDialog } from '../Dialogs'; -import { usePopups } from '@/hooks'; +import { getNetwork } from '@iota/iota-sdk/client'; +import { ReceiveFundsDialog, SendTokenDialog } from '../Dialogs'; import toast from 'react-hot-toast'; import { useState } from 'react'; export function AccountBalance() { const account = useCurrentAccount(); const address = account?.address; - const { openPopup, closePopup } = usePopups(); const [isReceiveDialogOpen, setIsReceiveDialogOpen] = useState(false); const { network } = useIotaClientContext(); const { explorer } = getNetwork(network); const { data: coinBalance, isPending } = useBalance(address!); const formattedAddress = formatAddress(address!); const [formatted, symbol] = useFormatCoin(coinBalance?.totalBalance, IOTA_TYPE_ARG); - const { data: coinBalances } = useIotaClientQuery( - 'getAllBalances', - { owner: address! }, - { - enabled: !!address, - staleTime: COINS_QUERY_STALE_TIME, - refetchInterval: COINS_QUERY_REFETCH_INTERVAL, - select: filterAndSortTokenBalances, - }, - ); + const [isSendTokenDialogOpen, setIsSendTokenDialogOpen] = useState(false); const explorerLink = `${explorer}/address/${address}`; - function openSendTokenPopup(coin: CoinBalance, address: string): void { - if (coinBalances) { - openPopup( - , - ); - } + function openSendTokenPopup(): void { + setIsSendTokenDialogOpen(true); } function openReceiveTokenPopup(): void { @@ -64,30 +37,26 @@ export function AccountBalance() { return ( <> - {isPending &&

Loading...

} - {!isPending && ( + {isPending ? ( +

Loading...

+ ) : (
-
- {address && ( -
- )} - - {formatted} {symbol} - -
+ {address && ( +
+ )} + + {formatted} {symbol} +
)} + {address && ( + <> + + + + )}
- ); } diff --git a/apps/wallet-dashboard/components/coins/CoinIcon.tsx b/apps/wallet-dashboard/components/coins/CoinIcon.tsx deleted file mode 100644 index a5c24107baa..00000000000 --- a/apps/wallet-dashboard/components/coins/CoinIcon.tsx +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -import { useCoinMetadata } from '@iota/core'; -import { IOTA_TYPE_ARG } from '@iota/iota-sdk/utils'; -import { IotaLogoMark } from '@iota/ui-icons'; -import cx from 'clsx'; -import { ImageIcon, ImageIconSize } from '../ImageIcon'; - -interface NonIotaCoinProps { - coinType: string; - size?: ImageIconSize; - rounded?: boolean; -} - -function NonIotaCoin({ coinType, size = ImageIconSize.Full, rounded }: NonIotaCoinProps) { - const { data: coinMeta } = useCoinMetadata(coinType); - return ( -
- -
- ); -} - -export interface CoinIconProps { - coinType: string; - size?: ImageIconSize; - rounded?: boolean; -} - -export function CoinIcon({ coinType, size = ImageIconSize.Full, rounded }: CoinIconProps) { - return coinType === IOTA_TYPE_ARG ? ( -
- -
- ) : ( - - ); -} diff --git a/apps/wallet-dashboard/components/coins/CoinItem.tsx b/apps/wallet-dashboard/components/coins/CoinItem.tsx index 29e8be5aa35..01528cb5ac1 100644 --- a/apps/wallet-dashboard/components/coins/CoinItem.tsx +++ b/apps/wallet-dashboard/components/coins/CoinItem.tsx @@ -10,11 +10,9 @@ import { CardType, ImageType, } from '@iota/apps-ui-kit'; -import { useFormatCoin } from '@iota/core'; +import { CoinIcon, useFormatCoin, ImageIconSize } from '@iota/core'; import { IOTA_TYPE_ARG } from '@iota/iota-sdk/utils'; import { type ReactNode } from 'react'; -import { ImageIconSize } from '../ImageIcon'; -import { CoinIcon } from './CoinIcon'; interface CoinItemProps { coinType: string; diff --git a/apps/wallet-dashboard/components/coins/MyCoins.tsx b/apps/wallet-dashboard/components/coins/MyCoins.tsx index bf3a3d6a8f7..9ba3810ff98 100644 --- a/apps/wallet-dashboard/components/coins/MyCoins.tsx +++ b/apps/wallet-dashboard/components/coins/MyCoins.tsx @@ -3,8 +3,7 @@ import React, { useState } from 'react'; import { useCurrentAccount, useIotaClientQuery } from '@iota/dapp-kit'; -import { CoinItem, SendCoinPopup } from '@/components'; -import { usePopups } from '@/hooks'; +import { CoinItem, SendTokenDialog } from '@/components'; import { CoinBalance } from '@iota/iota-sdk/client'; import { COINS_QUERY_REFETCH_INTERVAL, @@ -44,8 +43,9 @@ const TOKEN_CATEGORIES = [ function MyCoins(): React.JSX.Element { const [selectedTokenCategory, setSelectedTokenCategory] = useState(TokenCategory.All); + const [isSendTokenDialogOpen, setIsSendTokenDialogOpen] = useState(false); + const [selectedCoin, setSelectedCoin] = useState(); - const { openPopup, closePopup } = usePopups(); const account = useCurrentAccount(); const activeAccountAddress = account?.address; @@ -61,16 +61,10 @@ function MyCoins(): React.JSX.Element { ); const { recognized, unrecognized } = useSortedCoinsByCategories(coinBalances ?? []); - function openSendTokenPopup(coin: CoinBalance, address: string): void { + function openSendTokenDialog(coin: CoinBalance): void { if (coinBalances) { - openPopup( - , - ); + setIsSendTokenDialogOpen(true); + setSelectedCoin(coin); } } @@ -111,9 +105,7 @@ function MyCoins(): React.JSX.Element { key={index} coinType={coin.coinType} balance={BigInt(coin.totalBalance)} - onClick={() => - openSendTokenPopup(coin, account?.address ?? '') - } + onClick={() => openSendTokenDialog(coin)} icon={ } @@ -129,15 +121,21 @@ function MyCoins(): React.JSX.Element { key={index} coinType={coin.coinType} balance={BigInt(coin.totalBalance)} - onClick={() => - openSendTokenPopup(coin, account?.address ?? '') - } + onClick={() => openSendTokenDialog(coin)} /> ); })}
+ {selectedCoin && activeAccountAddress && ( + + )} ); } diff --git a/apps/wallet-dashboard/components/coins/index.ts b/apps/wallet-dashboard/components/coins/index.ts index 51468194c31..d1519105eec 100644 --- a/apps/wallet-dashboard/components/coins/index.ts +++ b/apps/wallet-dashboard/components/coins/index.ts @@ -3,4 +3,3 @@ export { default as MyCoins } from './MyCoins'; export { default as CoinItem } from './CoinItem'; -export * from './CoinIcon'; diff --git a/apps/wallet-dashboard/components/index.ts b/apps/wallet-dashboard/components/index.ts index 9907b82ea25..83697f63914 100644 --- a/apps/wallet-dashboard/components/index.ts +++ b/apps/wallet-dashboard/components/index.ts @@ -8,7 +8,6 @@ export { default as AmountBox } from './AmountBox'; export { default as Input } from './Input'; export { default as VirtualList } from './VirtualList'; export { default as ExternalImage } from './ExternalImage'; -export { default as Dropdown } from './Dropdown'; export * from './PageSizeSelector'; export * from './PaginationOptions'; @@ -21,6 +20,5 @@ export * from './Buttons'; export * from './transactions'; export * from './staking-overview'; export * from './Dialogs'; -export * from './ImageIcon'; export * from './ValidatorStakingData'; export * from './tiles'; diff --git a/apps/wallet-dashboard/hooks/useSendCoinTransaction.ts b/apps/wallet-dashboard/hooks/useSendCoinTransaction.ts index 8b793e6405d..b439c27a2df 100644 --- a/apps/wallet-dashboard/hooks/useSendCoinTransaction.ts +++ b/apps/wallet-dashboard/hooks/useSendCoinTransaction.ts @@ -45,11 +45,5 @@ export function useSendCoinTransaction( }, enabled: !!recipientAddress && !!amount && !!coins && !!senderAddress && !!coinType, gcTime: 0, - select: (transaction) => { - return { - transaction, - gasBudget: transaction.getData().gasData.budget, - }; - }, }); } diff --git a/apps/wallet-dashboard/package.json b/apps/wallet-dashboard/package.json index 9093f6da53e..44066a00ef1 100644 --- a/apps/wallet-dashboard/package.json +++ b/apps/wallet-dashboard/package.json @@ -25,6 +25,7 @@ "@tanstack/react-query": "^5.50.1", "@tanstack/react-virtual": "^3.5.0", "clsx": "^2.1.1", + "formik": "^2.4.2", "next": "14.2.10", "react": "^18.3.1", "react-hot-toast": "^2.4.1", diff --git a/apps/wallet/src/ui/app/components/active-coins-card/CoinItem.tsx b/apps/wallet/src/ui/app/components/active-coins-card/CoinItem.tsx index 5e7dce765f5..b5fe3327917 100644 --- a/apps/wallet/src/ui/app/components/active-coins-card/CoinItem.tsx +++ b/apps/wallet/src/ui/app/components/active-coins-card/CoinItem.tsx @@ -2,8 +2,7 @@ // Modifications Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -import { CoinIcon } from '_components'; -import { useFormatCoin } from '@iota/core'; +import { CoinIcon, useFormatCoin } from '@iota/core'; import { type ReactNode } from 'react'; import { Card, diff --git a/apps/wallet/src/ui/app/components/address-input/index.tsx b/apps/wallet/src/ui/app/components/address-input/index.tsx deleted file mode 100644 index e5d61c02b22..00000000000 --- a/apps/wallet/src/ui/app/components/address-input/index.tsx +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -import { useField, useFormikContext } from 'formik'; -import { useCallback, useMemo } from 'react'; -import type { ChangeEventHandler } from 'react'; -import { useIotaAddressValidation } from '@iota/core'; -import { Input, InputType } from '@iota/apps-ui-kit'; -import { Close } from '@iota/ui-icons'; - -export interface AddressInputProps { - disabled?: boolean; - placeholder?: string; - name: string; - label?: string; - shouldValidateManually?: boolean; -} - -export function AddressInput({ - disabled: forcedDisabled, - placeholder = '0x...', - name = 'to', - label = 'Enter Recipient Address', -}: AddressInputProps) { - const [field, meta] = useField(name); - - const { isSubmitting, setFieldValue, validateField } = useFormikContext(); - const iotaAddressValidation = useIotaAddressValidation(); - - const disabled = forcedDisabled !== undefined ? forcedDisabled : isSubmitting; - const handleOnChange = useCallback>( - (e) => { - const address = e.currentTarget.value; - setFieldValue(name, iotaAddressValidation.cast(address)).then(() => { - validateField(name); - }); - }, - [setFieldValue, name, iotaAddressValidation], - ); - const formattedValue = useMemo( - () => iotaAddressValidation.cast(field?.value), - [field?.value, iotaAddressValidation], - ); - - const clearAddress = useCallback(() => { - setFieldValue('to', ''); - }, [setFieldValue]); - - return ( - <> - - - - ) : undefined - } - /> - - ); -} diff --git a/apps/wallet/src/ui/app/components/index.ts b/apps/wallet/src/ui/app/components/index.ts index b4261f15214..418c14428a2 100644 --- a/apps/wallet/src/ui/app/components/index.ts +++ b/apps/wallet/src/ui/app/components/index.ts @@ -14,8 +14,6 @@ export * from './WalletListSelect'; export * from './accounts'; export * from './active-coins-card'; export * from './active-coins-card/CoinItem'; -export * from './address-input'; -export * from './coin-icon'; export * from './error-boundary'; export * from './explorer-link'; export * from './explorer-link/Explorer'; diff --git a/apps/wallet/src/ui/app/components/receipt-card/TxnAmount.tsx b/apps/wallet/src/ui/app/components/receipt-card/TxnAmount.tsx index 623ed671b9a..ceaa4ead1e2 100644 --- a/apps/wallet/src/ui/app/components/receipt-card/TxnAmount.tsx +++ b/apps/wallet/src/ui/app/components/receipt-card/TxnAmount.tsx @@ -2,7 +2,7 @@ // Modifications Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -import { useFormatCoin } from '@iota/core'; +import { CoinIcon, useFormatCoin } from '@iota/core'; import { Card, CardAction, @@ -12,7 +12,6 @@ import { CardType, ImageType, } from '@iota/apps-ui-kit'; -import { CoinIcon } from '../coin-icon'; import { ImageIconSize } from '../../shared/image-icon'; interface TxnAmountProps { diff --git a/apps/wallet/src/ui/app/pages/home/nft-transfer/TransferNFTForm.tsx b/apps/wallet/src/ui/app/pages/home/nft-transfer/TransferNFTForm.tsx index 59d02cf434e..9e4801aa3cb 100644 --- a/apps/wallet/src/ui/app/pages/home/nft-transfer/TransferNFTForm.tsx +++ b/apps/wallet/src/ui/app/pages/home/nft-transfer/TransferNFTForm.tsx @@ -2,16 +2,15 @@ // Modifications Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -import { AddressInput } from '_components'; import { ampli } from '_src/shared/analytics/ampli'; import { getSignerOperationErrorMessage } from '_src/ui/app/helpers/errorMessages'; import { useActiveAddress } from '_src/ui/app/hooks'; import { useActiveAccount } from '_src/ui/app/hooks/useActiveAccount'; import { useSigner } from '_src/ui/app/hooks/useSigner'; -import { createNftSendValidationSchema, useGetKioskContents } from '@iota/core'; +import { createNftSendValidationSchema, useGetKioskContents, AddressInput } from '@iota/core'; import { Transaction } from '@iota/iota-sdk/transactions'; import { useMutation, useQueryClient } from '@tanstack/react-query'; -import { Field, Form, Formik } from 'formik'; +import { Form, Formik } from 'formik'; import { toast } from 'react-hot-toast'; import { useNavigate } from 'react-router-dom'; @@ -96,12 +95,7 @@ export function TransferNFTForm({ objectId, objectType }: TransferNFTFormProps) {({ isValid, dirty, isSubmitting }) => (
- +