Skip to content

Commit

Permalink
add multi transfer hook
Browse files Browse the repository at this point in the history
  • Loading branch information
juliancwirko committed Nov 5, 2023
1 parent 457b888 commit 49dab89
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 38 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
### [0.11.0](https://github.com/useElven/core/releases/tag/v0.11.0) (2023-11-04)
- add useMultiEsdtTransfer
- some changes in the useTransaction hook. Now you can also pass the whole Transaction object to triggerTx function (in such a case other param are not required). This is optional. Previous functionality stays the same. In some cases, it can be a breaking change.

### [0.10.3](https://github.com/useElven/core/releases/tag/v0.10.3) (2023-11-01)
- update MulitversX sdk-core lib

Expand Down
53 changes: 31 additions & 22 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@useelven/core",
"version": "0.10.3",
"version": "0.11.0",
"description": "Core React hooks for MultiversX DApps",
"license": "MIT",
"author": "Julian Ćwirko <julian.io>",
Expand Down Expand Up @@ -73,15 +73,15 @@
"@multiversx/sdk-web-wallet-provider": "3.1.0",
"lodash.clonedeep": "4.5.0",
"swr": "2.2.4",
"valtio": "1.11.3"
"valtio": "1.12.0"
},
"devDependencies": {
"@types/lodash.clonedeep": "4.5.8",
"@types/node": "20.8.10",
"@types/react": "18.2.33",
"@types/react": "18.2.35",
"@typescript-eslint/eslint-plugin": "6.9.1",
"@typescript-eslint/parser": "6.9.1",
"eslint": "8.52.0",
"eslint": "8.53.0",
"eslint-config-prettier": "9.0.0",
"eslint-plugin-prettier": "5.0.1",
"eslint-plugin-react": "7.33.2",
Expand Down
127 changes: 127 additions & 0 deletions src/hooks/useMultiTokenTransfer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import {
Address,
TokenTransfer,
TransferTransactionsFactory,
GasEstimator,
} from '@multiversx/sdk-core';
import { useTransaction, TransactionArgs } from './useTransaction';
import { useAccount } from './useAccount';
import { apiCall } from 'src/utils/apiCall';
import { useConfig } from './useConfig';

export enum MultiTransferTokenType {
FungibleESDT = 'FungibleESDT',
MetaESDT = 'MetaESDT',
NonFungibleESDT = 'NonFungibleESDT',
SemiFungibleESDT = 'SemiFungibleESDT',
}

export interface MultiTransferToken {
type: MultiTransferTokenType;
tokenId: string;
amount: string;
}

export interface MultiTokenTransferArgs {
tokens: MultiTransferToken[];
receiver: string;
}

export interface MultiTokenTransferHookProps {
webWalletRedirectUrl?: TransactionArgs['webWalletRedirectUrl'];
cb?: TransactionArgs['cb'];
}

export const useMultiTokenTransfer = (
{ webWalletRedirectUrl, cb }: MultiTokenTransferHookProps = {
webWalletRedirectUrl: undefined,
cb: undefined,
}
) => {
const { address: accountAddress } = useAccount();
const { shortId } = useConfig();
const { nonce } = useAccount();
const { triggerTx, pending, transaction, txResult, error } = useTransaction({
webWalletRedirectUrl,
cb,
});

const transfer = async ({ tokens, receiver }: MultiTokenTransferArgs) => {
const transfers: TokenTransfer[] = [];

for (const token of tokens) {
let result;
if (token.type === MultiTransferTokenType.FungibleESDT) {
try {
result = await apiCall.get(`/tokens/${token.tokenId.trim()}`);
transfers.push(
TokenTransfer.fungibleFromAmount(
token.tokenId,
token.amount,
result.decimals
)
);
} catch (e) {
console.log((e as Error)?.message);
}
}

if (
[
MultiTransferTokenType.NonFungibleESDT,
MultiTransferTokenType.MetaESDT,
MultiTransferTokenType.SemiFungibleESDT,
].includes(token.type)
) {
try {
result = await apiCall.get(`/nfts/${token.tokenId.trim()}`);
} catch (e) {
console.log((e as Error)?.message);
}
}

if (token.type === MultiTransferTokenType.NonFungibleESDT) {
transfers.push(TokenTransfer.nonFungible(result.ticker, result.nonce));
}
if (token.type === MultiTransferTokenType.SemiFungibleESDT) {
transfers.push(
TokenTransfer.semiFungible(
result.ticker,
result.nonce,
parseInt(token.amount, 10)
)
);
}
if (token.type === MultiTransferTokenType.MetaESDT) {
transfers.push(
TokenTransfer.metaEsdtFromAmount(
result.ticker,
result.nonce,
parseFloat(token.amount),
result.decimals
)
);
}
}

const factory = new TransferTransactionsFactory(new GasEstimator());

const tx = factory.createMultiESDTNFTTransfer({
tokenTransfers: transfers,
nonce,
sender: new Address(accountAddress),
destination: new Address(receiver),
chainID: shortId || 'D',
});

triggerTx({ tx });
};

return {
transfer,
pending,
transaction,
txResult,
error,
};
};
34 changes: 22 additions & 12 deletions src/hooks/useTransaction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ import { useAccount } from './useAccount';
import { useNetwork } from './useNetwork';

export interface TransactionParams {
address: string;
gasLimit: IGasLimit;
address?: string;
gasLimit?: IGasLimit;
data?: ITransactionPayload;
value?: ITransactionValue;
tx?: Transaction; // When provided other params are not needed
}

export interface TransactionArgs {
Expand Down Expand Up @@ -56,11 +57,17 @@ export function useTransaction(
data,
gasLimit,
value,
tx,
}: TransactionParams) => {
setTransaction(null);
setTxResult(null);
setError('');

if (!tx && !gasLimit) {
setError('You need to provide the gas limit in the triggerTx function!');
return;
}

if (
networkStateSnap.dappProvider &&
networkStateSnap.apiNetworkProvider &&
Expand All @@ -73,19 +80,22 @@ export function useTransaction(
const sender = new Address(accountSnap.address);
const activeGuardianAddress = accountSnap.activeGuardianAddress;

const tx = new Transaction({
nonce: currentNonce,
receiver: new Address(address),
gasLimit,
chainID: configStateSnap.shortId || 'D',
data,
value: value || 0,
sender,
});
// You can pass whole Transaction object or you can create it
const transaction =
tx ||
new Transaction({
nonce: currentNonce,
receiver: new Address(address),
gasLimit: gasLimit!,
chainID: configStateSnap.shortId || 'D',
data,
value: value || 0,
sender,
});

signAndSendTxOperations(
networkStateSnap.dappProvider as DappProvider,
tx,
transaction,
loginInfoSnap,
networkStateSnap.apiNetworkProvider as ApiNetworkProvider,
setTransaction,
Expand Down
1 change: 1 addition & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export * from './hooks/useAccount';
export * from './hooks/useConfig';
export * from './hooks/useNetwork';
export * from './hooks/useTokenTransfer';
export * from './hooks/useMultiTokenTransfer';
export { useApiCall } from './hooks/useApiCall';
export { useScQuery } from './hooks/useScQuery';

Expand Down

0 comments on commit 49dab89

Please sign in to comment.