Skip to content

Commit

Permalink
Sovereign transaction creation refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
razvantomegea committed Aug 9, 2024
1 parent 59fcbfa commit d17b97b
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 47 deletions.
2 changes: 2 additions & 0 deletions src/lib/sdkDapp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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';
Expand Down
12 changes: 6 additions & 6 deletions src/localConstants/dataTestIds.enum.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
export enum DataTestIdsEnum {
accessPass = 'accessPass',
accessWalletBtn = 'accessWalletBtn',
addTokenBtn = 'addTokenBtn',
amountError = 'amountError',
connectBtn = 'connectBtn',
amountInput = 'amountInput',
availableAmount = 'availableAmount',
backToWordsButton = 'backToWordsButton',
cancelBtn = 'cancelBtn',
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',
Expand All @@ -48,13 +46,15 @@ export enum DataTestIdsEnum {
receiverError = 'receiverError',
receiverInput = 'receiverInput',
recoverWalletBtn = 'recoverWalletBtn',
removeTokenBtn = 'removeTokenBtn',
sendBtn = 'sendBtn',
sendEsdtTypeInput = 'sendEsdtTypeInput',
sendNFtTypeInput = 'sendNFtTypeInput',
signBtn = 'signBtn',
signMessageBtn = 'signMessageBtn',
signMessagePage = 'signMessagePage',
signStepTitle = 'signStepTitle',
sovereignTransferBtn = 'sovereignTransferBtn',
submitButton = 'submitButton',
tokenError = 'tokenError',
transactionToastTitle = 'transactionToastTitle',
Expand Down
2 changes: 1 addition & 1 deletion src/pages/Dashboard/widgets/NFTs/components/NFTRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
3 changes: 1 addition & 2 deletions src/pages/Send/hooks/useSendForm.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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 = () => {
Expand Down
7 changes: 5 additions & 2 deletions src/pages/SignMessage/SignMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
14 changes: 10 additions & 4 deletions src/pages/SovereignTransfer/components/SovereignTransferForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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);
};
Expand Down
82 changes: 71 additions & 11 deletions src/pages/SovereignTransfer/helpers/getSovereignTransferTxData.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,75 @@
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') : '';

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
Expand All @@ -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}`;
})
Expand Down
28 changes: 7 additions & 21 deletions src/pages/SovereignTransfer/hooks/useSovereignTransferForm.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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();
Expand Down Expand Up @@ -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]);
Expand Down

0 comments on commit d17b97b

Please sign in to comment.