diff --git a/src/lib/sdkDapp.ts b/src/lib/sdkDapp.ts index 4f886bb9..47ef958b 100644 --- a/src/lib/sdkDapp.ts +++ b/src/lib/sdkDapp.ts @@ -20,6 +20,7 @@ export { loginWithExternalProvider } from '@multiversx/sdk-dapp/utils/account/lo export { addressIsValid } from '@multiversx/sdk-dapp/utils/account/addressIsValid'; export { getInterpretedTransaction } from '@multiversx/sdk-dapp/utils/transactions/getInterpretedTransaction'; export { formatAmount } from '@multiversx/sdk-dapp/utils/operations/formatAmount'; +export { parseAmount } from '@multiversx/sdk-dapp/utils/operations/parseAmount'; export { getIsProviderEqualTo } from '@multiversx/sdk-dapp/utils/account/getIsProviderEqualTo'; export { removeTransactionsToSign } from '@multiversx/sdk-dapp/services/transactions/clearTransactions'; export { extractSessionId } from '@multiversx/sdk-dapp/hooks/transactions/helpers/extractSessionId'; @@ -35,6 +36,7 @@ export { useGetIsLoggedIn } from '@multiversx/sdk-dapp/hooks/account/useGetIsLog export { useGetIsWalletConnectV2Initialized } from '@multiversx/sdk-dapp/hooks/account/useGetIsWalletConnectV2Initialized'; export { useGetLastPendingTransactionHash } from '@multiversx/sdk-dapp/hooks/transactions/useGetLastPendingTransactionHash'; export { useGetLastSignedMessageSession } from '@multiversx/sdk-dapp/hooks/signMessage/useGetLastSignedMessageSession'; +export { useGetSignMessageSession } from '@multiversx/sdk-dapp/hooks/signMessage/useGetSignMessageSession'; export { useGetLoginInfo } from '@multiversx/sdk-dapp/hooks/account/useGetLoginInfo'; export { useGetNetworkConfig } from '@multiversx/sdk-dapp/hooks/useGetNetworkConfig'; export { useGetPendingTransactions } from '@multiversx/sdk-dapp/hooks/transactions/useGetPendingTransactions'; diff --git a/src/localConstants/dataTestIds.enum.ts b/src/localConstants/dataTestIds.enum.ts index 4ddb4ca1..9e41ea8c 100644 --- a/src/localConstants/dataTestIds.enum.ts +++ b/src/localConstants/dataTestIds.enum.ts @@ -1,8 +1,8 @@ export enum DataTestIdsEnum { accessPass = 'accessPass', accessWalletBtn = 'accessWalletBtn', + addTokenBtn = 'addTokenBtn', amountError = 'amountError', - connectBtn = 'connectBtn', amountInput = 'amountInput', availableAmount = 'availableAmount', backToWordsButton = 'backToWordsButton', @@ -10,22 +10,20 @@ export enum DataTestIdsEnum { cancelSignMessageBtn = 'cancelSignMessageBtn', check = 'check', checkNetwork = 'checkNetwork', - contractError = 'contractError', - contractInput = 'contractInput', closeButton = 'closeButton', confirmAmount = 'confirmAmount', - addTokenBtn = 'addTokenBtn', - removeTokenBtn = 'removeTokenBtn', confirmBtn = 'confirmBtn', confirmData = 'confirmData', confirmFee = 'confirmFee', confirmReceiver = 'confirmReceiver', + connectBtn = 'connectBtn', + contractError = 'contractError', + contractInput = 'contractInput', createPasswordForm = 'createPasswordForm', createWalletBtn = 'createWalletBtn', createWalletModal = 'createWalletModal', dappModal = 'dappModal', dataInput = 'dataInput', - sovereignTransferBtn = 'sovereignTransferBtn', disclaimerCheck = 'disclaimerCheck', gasLimitError = 'gasLimitError', gasLimitInput = 'gasLimitInput', @@ -48,6 +46,7 @@ export enum DataTestIdsEnum { receiverError = 'receiverError', receiverInput = 'receiverInput', recoverWalletBtn = 'recoverWalletBtn', + removeTokenBtn = 'removeTokenBtn', sendBtn = 'sendBtn', sendEsdtTypeInput = 'sendEsdtTypeInput', sendNFtTypeInput = 'sendNFtTypeInput', @@ -55,6 +54,7 @@ export enum DataTestIdsEnum { signMessageBtn = 'signMessageBtn', signMessagePage = 'signMessagePage', signStepTitle = 'signStepTitle', + sovereignTransferBtn = 'sovereignTransferBtn', submitButton = 'submitButton', tokenError = 'tokenError', transactionToastTitle = 'transactionToastTitle', diff --git a/src/pages/Dashboard/widgets/NFTs/components/NFTRow.tsx b/src/pages/Dashboard/widgets/NFTs/components/NFTRow.tsx index 98d82751..0bad9736 100644 --- a/src/pages/Dashboard/widgets/NFTs/components/NFTRow.tsx +++ b/src/pages/Dashboard/widgets/NFTs/components/NFTRow.tsx @@ -9,7 +9,7 @@ import { NftEnumType, PartialNftType } from 'types'; export const NFTRow = ({ nft }: { nft: PartialNftType }) => { const navigate = useNavigate(); const nftType = - CollectionTypeByNftEnum[nft.type as NftEnumType].toUpperCase(); + CollectionTypeByNftEnum[nft.type as NftEnumType]?.toUpperCase(); const handleSend = (event: MouseEvent) => { event.preventDefault(); diff --git a/src/pages/Send/hooks/useSendForm.ts b/src/pages/Send/hooks/useSendForm.ts index 2f1d130d..8f88f423 100644 --- a/src/pages/Send/hooks/useSendForm.ts +++ b/src/pages/Send/hooks/useSendForm.ts @@ -1,5 +1,4 @@ import { ChangeEventHandler, useEffect, useState } from 'react'; -import { PartialNftType } from '@multiversx/sdk-dapp-form'; import BigNumber from 'bignumber.js'; import { useFormik } from 'formik'; import { useSearchParams } from 'react-router-dom'; @@ -23,7 +22,7 @@ import { GAS_PRICE, SearchParamsEnum } from 'localConstants'; -import { SendTypeEnum, TokenOptionType } from 'types'; +import { SendTypeEnum, TokenOptionType, PartialNftType } from 'types'; import { FormFieldsEnum } from '../types'; export const useSendForm = () => { diff --git a/src/pages/SignMessage/SignMessage.tsx b/src/pages/SignMessage/SignMessage.tsx index a1c4094c..e2ebd95f 100644 --- a/src/pages/SignMessage/SignMessage.tsx +++ b/src/pages/SignMessage/SignMessage.tsx @@ -2,13 +2,16 @@ import { useEffect, useState } from 'react'; import type { MouseEvent } from 'react'; import { faBroom, faArrowsRotate } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { useGetSignMessageSession } from '@multiversx/sdk-dapp/hooks/signMessage/useGetSignMessageSession'; import { useSelector } from 'react-redux'; import { useNavigate } from 'react-router-dom'; import { Button } from 'components/Button'; import { OutputContainer } from 'components/OutputContainer'; import { useReplyWithCancelled } from 'hooks'; -import { parseQueryParams, useSignMessage } from 'lib'; +import { + parseQueryParams, + useSignMessage, + useGetSignMessageSession +} from 'lib'; import { CANCELLED, DataTestIdsEnum, HooksEnum } from 'localConstants'; import { hookSelector } from 'redux/selectors'; import { routeNames } from 'routes'; diff --git a/src/pages/SovereignTransfer/components/SovereignTransferForm.tsx b/src/pages/SovereignTransfer/components/SovereignTransferForm.tsx index 66c8f86c..c32ce447 100644 --- a/src/pages/SovereignTransfer/components/SovereignTransferForm.tsx +++ b/src/pages/SovereignTransfer/components/SovereignTransferForm.tsx @@ -113,9 +113,7 @@ export const SovereignTransferForm = () => { token: token[SovereignTransferFormFieldsEnum.token]?.value }); - const canEditNftAmount = getCanEditNftAmount( - token[SovereignTransferFormFieldsEnum.amount] - ); + const canEditNftAmount = getCanEditNftAmount(availableAmount); const tokenOptions = getTokenOptionsByType( token[SovereignTransferFormFieldsEnum.type] @@ -128,7 +126,15 @@ export const SovereignTransferForm = () => { formik.setFieldValue(typeFieldName, selectedType); const options = getTokenOptionsByType(selectedType); formik.setFieldValue(tokenFieldName, options[0]); - formik.setFieldValue(amountFieldName, 0); + const amount = getTokenAvailableAmount({ + sendType: selectedType, + token: options[0].value + }); + + formik.setFieldValue( + amountFieldName, + amount === '1' && getIsNFT(selectedType) ? '1' : 0 + ); return formik.handleChange(event); }; diff --git a/src/pages/SovereignTransfer/helpers/getSovereignTransferTxData.ts b/src/pages/SovereignTransfer/helpers/getSovereignTransferTxData.ts index c9445c26..15ddd9af 100644 --- a/src/pages/SovereignTransfer/helpers/getSovereignTransferTxData.ts +++ b/src/pages/SovereignTransfer/helpers/getSovereignTransferTxData.ts @@ -1,16 +1,19 @@ -import { Address } from '@multiversx/sdk-core/out'; +import { + SmartContractTransactionsFactory, + TransactionsFactoryConfig, + Token +} from '@multiversx/sdk-core'; +import { Address, AddressValue, TokenTransfer } from '@multiversx/sdk-core/out'; import { addressToHex, numberToPaddedHex } from '@multiversx/sdk-core/out/utils.codec'; -import { TokenType } from '@multiversx/sdk-dapp/types/tokens.types'; -import { parseAmount } from '@multiversx/sdk-dapp/utils'; -import { PartialNftType } from '@multiversx/sdk-dapp-form'; import BigNumber from 'bignumber.js'; -import { TransactionTypesEnum } from 'types'; -import { SovereignTransferFormType } from '../types'; -import { getEgldLabel } from 'lib'; import { WEGLDID } from 'config'; +import { getEgldLabel, parseAmount } from 'lib'; +import { SOVEREIGN_TRANSFER_GAS_LIMIT } from 'localConstants'; +import { TransactionTypesEnum, PartialNftType, TokenType } from 'types'; +import { SovereignTransferFormType } from '../types'; export const stringToHex = (stringTopEncode?: string) => stringTopEncode ? Buffer.from(stringTopEncode).toString('hex') : ''; @@ -18,6 +21,55 @@ export const stringToHex = (stringTopEncode?: string) => export const numberToHex = (numberToEncode: number | string) => numberToPaddedHex(new BigNumber(numberToEncode).toNumber()); +export const getSovereignTransferTransaction = ({ + address, + chainId, + values, + tokens +}: { + address: string; + chainId: string; + values: SovereignTransferFormType; + tokens: (PartialNftType | TokenType)[]; +}) => { + const egldLabel = getEgldLabel(); + const factoryConfig = new TransactionsFactoryConfig({ chainID: chainId }); + const factory = new SmartContractTransactionsFactory({ + config: factoryConfig + }); + + return factory.createTransactionForExecute({ + sender: new Address(address), + contract: Address.fromBech32(values.contract), + function: 'deposit', + gasLimit: BigInt(SOVEREIGN_TRANSFER_GAS_LIMIT), + arguments: [new AddressValue(Address.fromBech32(values.receiver))], + tokenTransfers: values.tokens.map((token) => { + const realToken = tokens.find((t) => t.identifier === token.token?.value); + + if (!realToken) { + return new TokenTransfer({ + token: new Token({ identifier: token.token?.value }), + amount: BigInt(token.amount) + }); + } + + const nonce = (realToken as PartialNftType).nonce; + + return new TokenTransfer({ + token: new Token({ + identifier: + realToken.identifier === egldLabel ? WEGLDID : realToken.identifier, + nonce: nonce ? BigInt(nonce) : undefined + }), + amount: BigInt( + nonce ? token.amount : parseAmount(token.amount, realToken.decimals) + ) + }); + }) + }); +}; + export const getSovereignTransferTxData = ({ values, tokens @@ -36,15 +88,23 @@ export const getSovereignTransferTxData = ({ return ''; } + const tokenNonce = (realToken as PartialNftType).nonce; + const identifierItems = realToken.identifier.split('-'); + identifierItems.pop(); + const identifier = tokenNonce + ? identifierItems.join('-') + : realToken.identifier; const encodedTokenId = stringToHex( - egldLabel === egldLabel ? WEGLDID : egldLabel + identifier === egldLabel ? WEGLDID : identifier ); + const encodedNonce = tokenNonce ? numberToHex(tokenNonce) : ''; + const encodedAmount = numberToHex( - parseAmount(token.amount, realToken.decimals) + encodedNonce + ? token.amount + : parseAmount(token.amount, realToken.decimals) ); - const tokenNonce = (realToken as PartialNftType).nonce; - const encodedNonce = tokenNonce ? numberToHex(tokenNonce) : ''; return `${encodedTokenId}@${encodedNonce}@${encodedAmount}`; }) diff --git a/src/pages/SovereignTransfer/hooks/useSovereignTransferForm.ts b/src/pages/SovereignTransfer/hooks/useSovereignTransferForm.ts index 9f559010..4da310f9 100644 --- a/src/pages/SovereignTransfer/hooks/useSovereignTransferForm.ts +++ b/src/pages/SovereignTransfer/hooks/useSovereignTransferForm.ts @@ -1,5 +1,3 @@ -import { TokenType } from '@multiversx/sdk-dapp/types/tokens.types'; -import { PartialNftType } from '@multiversx/sdk-dapp-form'; import BigNumber from 'bignumber.js'; import { useFormik } from 'formik'; import { array, number, object, string } from 'yup'; @@ -9,17 +7,15 @@ import { useSendTransactions, useTokenOptions } from 'hooks'; import { addressIsValid, getEgldLabel, - prepareTransaction, useGetAccountInfo, useGetNetworkConfig } from 'lib'; -import { GAS_PRICE, SOVEREIGN_TRANSFER_GAS_LIMIT } from 'localConstants'; -import { SendTypeEnum } from 'types'; -import { getSovereignTransferTxData } from '../helpers'; +import { SendTypeEnum, TokenType, PartialNftType } from 'types'; +import { getSovereignTransferTransaction } from '../helpers'; import { SovereignTransferFormFieldsEnum } from '../types'; export const useSovereignTransferForm = () => { - const { address, account } = useGetAccountInfo(); + const { address } = useGetAccountInfo(); const { network: { chainId } } = useGetNetworkConfig(); @@ -115,21 +111,11 @@ export const useSovereignTransferForm = () => { ) }), onSubmit: async (values) => { - const data = getSovereignTransferTxData({ - values, - tokens: allTokens - }); - - const transaction = prepareTransaction({ - amount: '0', - balance: account.balance, + const transaction = getSovereignTransferTransaction({ + address, chainId, - data, - gasLimit: String(SOVEREIGN_TRANSFER_GAS_LIMIT), - gasPrice: String(GAS_PRICE), - nonce: account.nonce, - receiver: address, - sender: address + tokens: allTokens, + values }); await sendTransactions([transaction]);