From 0e2331a310c127a0b46c88e02168ae3f287f8d46 Mon Sep 17 00:00:00 2001 From: Razvan Tomegea Date: Fri, 23 May 2025 16:53:38 +0300 Subject: [PATCH 01/23] Sdk-dapp-core migration (#264) * Migrate * Login and sign message * Ping transactions * Removed ping pong abi and service * Batch transactions * Transactons * Added transaction interpretation helpers * Added transaction interpretation UI and helpers * Added transaction interpretation UI and helpers * fix build * Fix build * Refactor * Added reactive store subscription * Fix * Update versions * Improve useStore * Local working * Work on reactivity * Removed logs * Track transactions * Use selector from sdk-dapp-core * Remove unused * Fix rerenders * Remove unused * Remove dependecy * Added formatAmount * Integrate hooks * Upgrade sdk-dapp-core * remove selector * Remove unused * Bring back useSendBatchTransaction * Restore features * Added FormatAmount.tsx * Added FormatAmount.tsx * Remove unused hooks * Custom provider implementation (#272) * Create inmemoryprovider * Improve-in-memory-provider (#274) * Refactor model * Remove unnecessary persistence * Update packages * add toast lifetime (#275) * Added transactions table from sdk-dapp-core/ui (#273) * Added transactions table * Added transactions table * use react output (#279) * Transactions table (#278) * Added transactions table * Added transactions table * Updated TransactionsTable.tsx * Removed unused components * Log * Fixed build and added missing UI elements (#280) * Fixed build and lint issues * Fix * Fixed lint and build * Merged development * Fixed build * Added sdk-core back * Fixed import * Remove unnecessary refresh account (#283) * Refactor * Renamed props type * Refactor * Refactor and comments (#284) * Refactor and comments * Revert * Added back batch transactions functions (#286) * Fix import * Added back batch transactions functions * Fix * Fix * Refactor imports * Conflicts * Revert * Refactor explorerlink * Fixed build and added AuthenticatedRoutesWrapper * Revert AuthenticatedRouteWrapper * Fixed build * Tm/feature/sdk-dapp-core/merge-1 (#291) * Updated Button prop (#289) * Remove AuthenticatedRoutesWrapper dependency (#290) * Fix header imports * Minor change * Minor change * FIx imports * Upgrade imports * Major refactor lib * Fix changes * Fix types * Refactor lib (#292) Refactor imports * Unite imports --------- Co-authored-by: Razvan Tomegea * Fix sort imports * Fixed sort exports * Revert import type * Move components * lint * Added PageNotFound * Move components (#298) * Move components * lint * Updates * Updated SignSuccess * Minor refactor * Minor changes * Tm/feature/sdk dapp core/refactor 2 (#309) * Minor refactor * Minor changes * Minor refactor * Refactor * Fix errors * Revert * Revert * Some updates * Some updates (#313) * Implement changes * Added missing code * Remove immer (#316) * Latest versions * added sdk-dapp-core-ui to optimizeDeps * Added axios interceptors (#318) * Work on migration guide * Added unlock panel (#321) * Added unlock panel * resolve comments * close panel after login * Migration guide * Refactor * extract connect logic (#322) * extract connect logic * fix imports * remove sdk from name * Hide UnlockButton * resolve comments * fix login --------- Co-authored-by: Tudor Morar * Fix login modal * Added wallet connect config * Update ui * Added notifications feed side panel (#327) * Added notifications feed button * Refactor * Increase versions * Migrated to sdk-core 14 * fix sdk-dapp-core-ui bundle config (#328) * Fixed build * Resolve conflict with core-ui tailwind v4 (#330) * Fixed build * Updated core ui components prefix * Sdk core v14 (#333) * Upgrade sdk-core to v.14 and sdk-dapp to v.4 * Revert * Revert * Use parseAmount * Remove unused formatAmount * Sign message error * Fied sign success * Fixed sign transactions via URL * Fixed start --------- Co-authored-by: Tudor Morar * Update sdk-core-ui to LTS * Move unlock logic to manager (#335) * move unlock panel logic to manager * clean up connect button * change naming * update login * fix custom provider * change in memory provider iconUrl * Added sidepanel login for inMemoryProvider (#336) * Added sidepanel login for inMemoryProvider * Remove log * Upgrade sdk-dapp-core * Update versions * Upgrade packages * Change to EGLD tx instead of WEGLD * Add multi transfer tx * update sdk-dapp-packages (#338) * Update transactions (#339) * Update transactions * Updates * Remove from ignore * Update transaction for service * Upgrade sdk-core to v.14 and sdk-dapp to v.4 (#331) * Upgrade sdk-core to v.14 and sdk-dapp to v.4 * Revert * Update sdk to 5x * Add sdk-ui 0x * Update pingPong * Update time to pong * Update transactions * Remove duplicate file * Fix time * Remove log * Fix type --------- Co-authored-by: Tudor Morar Co-authored-by: DanutIlie <42973343+DanutIlie@users.noreply.github.com> Co-authored-by: Danut Co-authored-by: Miro Co-authored-by: Gavrila Andrei --- MIGRATION_GUIDE.md | 118 ++ package.json | 23 +- postcss.config.js | 1 + src/App.tsx | 100 +- src/components/Button/Button.tsx | 2 +- src/components/Layout/Header/Header.tsx | 66 +- .../Header/components/ConnectButton.tsx | 19 + .../Header/components/NotificationsButton.tsx | 19 + .../Layout/Header/components/index.ts | 1 + src/components/Loader/Loader.tsx | 14 + src/components/Loader/index.tsx | 1 + .../OutputContainer/OutputContainer.tsx | 3 +- .../components/TransactionsOutput.tsx | 5 +- .../TransactionsTable/TransactionsTable.tsx | 43 + src/components/TransactionsTable/index.ts | 1 + .../TransactionsTracker.ts | 35 - src/components/TransactionsTracker/index.ts | 1 - src/components/index.ts | 3 +- src/helpers/signAndSendTransactions.ts | 31 +- src/hooks/index.ts | 2 - .../useSendPingPongTransaction.ts | 299 ++-- src/hooks/useIsWebProvider.ts | 8 - src/hooks/useScrollToElement.ts | 22 - src/index.tsx | 16 +- src/initConfig.ts | 54 + src/lib/index.ts | 2 + src/lib/sdkCore.ts | 10 +- .../components/CopyButton/CopyButton.tsx | 20 + .../sdkDapp/components/CopyButton/index.ts | 1 + .../components/ExplorerLink/ExplorerLink.tsx | 29 + .../sdkDapp/components/ExplorerLink/index.ts | 1 + .../components/FormatAmount/FormatAmount.tsx | 40 + .../sdkDapp/components/FormatAmount/index.ts | 1 + src/lib/sdkDapp/components/index.tsx | 3 + src/lib/sdkDapp/index.ts | 2 +- src/lib/sdkDapp/sdkDapp.components.ts | 26 - src/lib/sdkDapp/sdkDapp.constants.ts | 11 +- src/lib/sdkDapp/sdkDapp.helpers.ts | 37 +- src/lib/sdkDapp/sdkDapp.hooks.ts | 27 +- src/lib/sdkDapp/sdkDapp.types.ts | 27 +- src/lib/sdkDappCoreUI/index.ts | 2 + .../sdkDappCoreUI/sdkDappCoreUI.components.ts | 7 + src/lib/sdkDappCoreUI/sdkDappCoreUI.types.ts | 5 + src/lib/sdkDappUtils/index.ts | 2 + src/lib/sdkDappUtils/sdkDappUtils.ts | 3 + src/lib/sdkDappUtils/sdkDappUtils.types.ts | 6 + src/localConstants/index.ts | 1 - src/localConstants/routes/routeNames.enums.ts | 1 - src/localConstants/session/index.ts | 5 - src/localConstants/session/session.enums.ts | 8 - src/pages/Dashboard/Dashboard.tsx | 18 +- src/pages/Dashboard/components/Widget.tsx | 9 +- .../BatchTransactions/BatchTransactions.tsx | 100 +- .../helpers/getBatchTransactions.ts | 41 +- .../helpers/getSwapAndLockTransactions.ts | 70 +- .../helpers/sendBatchTransactions.ts | 44 +- .../signAndAutoSendBatchTransactions.ts | 53 +- .../helpers/swapAndLockTokens.ts | 48 +- .../helpers/transactionsHandler.ts | 24 + .../widgets/BatchTransactions/hooks/index.ts | 1 - .../hooks/useSendSignedTransactions.ts | 105 -- .../widgets/BatchTransactions/types.ts | 5 - .../widgets/PingPongAbi/PingPongAbi.tsx | 36 +- .../PingPongAbi/hooks/useGetTimeToPong.ts | 6 +- .../widgets/PingPongRaw/PingPongRaw.tsx | 37 +- .../hooks/tests/useGetTimeToPong.test.ts | 64 - .../PingPongService/PingPongService.tsx | 42 +- .../hooks/useGetPingTransaction.ts | 15 +- .../hooks/useGetPongTransaction.ts | 15 +- .../PingPongService/hooks/useGetTimeToPong.ts | 8 +- .../widgets/SignMessage/SignMessage.tsx | 116 +- .../SignMessage/components/SignFailure.tsx | 6 +- .../SignMessage/components/SignSuccess.tsx | 28 +- .../helpers/tests/decodeMessage.test.ts | 15 +- .../widgets/Transactions/Transactions.tsx | 34 +- .../Transactions/hooks/useGetTransactions.ts | 1 + src/pages/Home/Home.tsx | 4 +- src/pages/Unlock/Unlock.tsx | 100 -- .../Unlock/components/DualLoginButton.tsx | 107 -- .../components/IframeButton/IframeButton.tsx | 23 - .../Unlock/components/IframeButton/index.ts | 1 - .../components/WebWalletLoginWrapper.tsx | 23 - .../Unlock/components/XaliasLoginWrapper.tsx | 23 - src/pages/Unlock/components/index.tsx | 3 - src/pages/Unlock/index.ts | 1 - src/pages/index.ts | 1 - src/provider/LoginModal.tsx | 193 +++ src/provider/inMemoryProvider.ts | 189 +++ src/react-app-env.d.ts | 1 - src/routes/routes.ts | 7 +- src/styles/globals.css | 20 - src/types/componentsTypes.ts | 4 + src/types/index.ts | 2 + src/types/routes.types.ts | 5 + src/types/widget.types.ts | 10 +- src/utils/getCallbackRoute.ts | 21 - src/utils/index.ts | 1 - .../AuthRedirectWrapper.tsx | 2 +- .../AxiosInterceptors/AxiosInterceptors.tsx | 16 + src/wrappers/AxiosInterceptors/index.ts | 1 + src/wrappers/index.ts | 1 + tsconfig.json | 9 +- vite.config.ts | 2 +- yarn.lock | 1481 +++++++++++------ 104 files changed, 2325 insertions(+), 2031 deletions(-) create mode 100644 MIGRATION_GUIDE.md create mode 100644 src/components/Layout/Header/components/ConnectButton.tsx create mode 100644 src/components/Layout/Header/components/NotificationsButton.tsx create mode 100644 src/components/Layout/Header/components/index.ts create mode 100644 src/components/Loader/Loader.tsx create mode 100644 src/components/Loader/index.tsx create mode 100644 src/components/TransactionsTable/TransactionsTable.tsx create mode 100644 src/components/TransactionsTable/index.ts delete mode 100644 src/components/TransactionsTracker/TransactionsTracker.ts delete mode 100644 src/components/TransactionsTracker/index.ts delete mode 100644 src/hooks/useIsWebProvider.ts delete mode 100644 src/hooks/useScrollToElement.ts create mode 100644 src/initConfig.ts create mode 100644 src/lib/sdkDapp/components/CopyButton/CopyButton.tsx create mode 100644 src/lib/sdkDapp/components/CopyButton/index.ts create mode 100644 src/lib/sdkDapp/components/ExplorerLink/ExplorerLink.tsx create mode 100644 src/lib/sdkDapp/components/ExplorerLink/index.ts create mode 100644 src/lib/sdkDapp/components/FormatAmount/FormatAmount.tsx create mode 100644 src/lib/sdkDapp/components/FormatAmount/index.ts create mode 100644 src/lib/sdkDapp/components/index.tsx delete mode 100644 src/lib/sdkDapp/sdkDapp.components.ts create mode 100644 src/lib/sdkDappCoreUI/index.ts create mode 100644 src/lib/sdkDappCoreUI/sdkDappCoreUI.components.ts create mode 100644 src/lib/sdkDappCoreUI/sdkDappCoreUI.types.ts create mode 100644 src/lib/sdkDappUtils/index.ts create mode 100644 src/lib/sdkDappUtils/sdkDappUtils.ts create mode 100644 src/lib/sdkDappUtils/sdkDappUtils.types.ts delete mode 100644 src/localConstants/session/index.ts delete mode 100644 src/localConstants/session/session.enums.ts create mode 100644 src/pages/Dashboard/widgets/BatchTransactions/helpers/transactionsHandler.ts delete mode 100644 src/pages/Dashboard/widgets/BatchTransactions/hooks/index.ts delete mode 100644 src/pages/Dashboard/widgets/BatchTransactions/hooks/useSendSignedTransactions.ts delete mode 100644 src/pages/Dashboard/widgets/BatchTransactions/types.ts delete mode 100644 src/pages/Dashboard/widgets/PingPongRaw/hooks/tests/useGetTimeToPong.test.ts delete mode 100644 src/pages/Unlock/Unlock.tsx delete mode 100644 src/pages/Unlock/components/DualLoginButton.tsx delete mode 100644 src/pages/Unlock/components/IframeButton/IframeButton.tsx delete mode 100644 src/pages/Unlock/components/IframeButton/index.ts delete mode 100644 src/pages/Unlock/components/WebWalletLoginWrapper.tsx delete mode 100644 src/pages/Unlock/components/XaliasLoginWrapper.tsx delete mode 100644 src/pages/Unlock/components/index.tsx delete mode 100644 src/pages/Unlock/index.ts create mode 100644 src/provider/LoginModal.tsx create mode 100644 src/provider/inMemoryProvider.ts delete mode 100644 src/react-app-env.d.ts create mode 100644 src/types/componentsTypes.ts create mode 100644 src/types/routes.types.ts delete mode 100644 src/utils/getCallbackRoute.ts delete mode 100644 src/utils/index.ts create mode 100644 src/wrappers/AxiosInterceptors/AxiosInterceptors.tsx create mode 100644 src/wrappers/AxiosInterceptors/index.ts diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md new file mode 100644 index 00000000..7dca6a20 --- /dev/null +++ b/MIGRATION_GUIDE.md @@ -0,0 +1,118 @@ +# @multiversx/template-dapp + +Migrating your application to the new SDK will probably require more code removal than insertion. Of course, each application is different, so this guide will have a generic character, pointing to you the main areas where you might need to change your code. +The main areas that might need code restructuring are: +- package.json library dependencies +- index.tsx file where the app bootstraps +- App.tsx, the main file of your application +- logging in and out +- sending and signing transactions +- component imports related to displaying data +- types + +A typical migration can be seen in this [pull request](https://github.com/multiversx/mx-template-dapp/pull/264). + +Next, we will make a brief overview of the main changes required. + +## 1. Changes in [`package.json`](https://github.com/multiversx/mx-template-dapp/pull/264/files#diff-7ae45ad102eab3b6d7e7896acd08c427a9b25b346470d7bc6507b6481575d519) + +#### Dependencies +- Removed: + - `@multiversx/sdk-dapp` +- Added: + - `@multiversx/sdk-dapp-core` (version `0.0.0-alpha.12`) + - `@multiversx/sdk-dapp-core-ui` (version `0.0.0-alpha.2`) + - `@multiversx/sdk-dapp-utils` (version `1.0.5`) + +## 2. Changes in [`index.tsx`](https://github.com/multiversx/mx-template-dapp/pull/264/files#diff-0b5adbfe7b36e4ae2f479291e20152e33e940f7f265162d77f40f6bdb5da7405) + +You will need to wrap your application in a call to `initApp`: + +```tsx +initApp(config).then(() => { + ReactDOM.createRoot(document.getElementById('root')!).render( + + + + ); +}); +``` + +## 2. Summary of Changes in [`App.tsx`](https://github.com/multiversx/mx-template-dapp/pull/264/files#diff-26ad4b834941d9b19ebf9db8082bd202aaf72ea0ddea85f5a8a0cb3c729cc6f2) + +- AxiosInterceptorContext is now created as a local component +- DappProvider was removed and initialization is now made in initApp +- NotificationModal, SignTransactionsModals and TransactionsToastList are removed and functionality is handled under the hood + +## 3. Logging in and out: + +Login buttons have been removed and there is a universal Unlock side panel, which can be inserted in the DOM at a desired location. + +Example of how to use the Unlock side panel: + +```tsx +import { Button } from 'components'; +import { useState } from 'react'; +import { ProviderFactory } from 'lib'; +export { UnlockPanel, UnlockButton } from '@multiversx/sdk-dapp-core-ui/react'; +import { ExtendedProviders } from 'initConfig'; +import { IProviderFactory } from '@multiversx/sdk-dapp-core/out/core/providers/types/providerFactory.types'; +import { useNavigate } from 'react-router-dom'; +import { RouteNamesEnum } from 'localConstants'; + +export const ConnectButton = () => { + const [open, setOpen] = useState(false); + const navigate = useNavigate(); + + const handleLogin = async ({ type, anchor }: IProviderFactory) => { + const provider = await ProviderFactory.create({ + type, + anchor + }); + await provider?.login(); + navigate(RouteNamesEnum.dashboard); + }; + + return ( + <> + + + handleLogin({ + type: options.detail.provider, + anchor: options.detail.anchor + }) + } + onClose={() => { + setOpen(false); + }} + > + + handleLogin({ + type: ExtendedProviders.inMemoryProvider + }) + } + /> + + + ); +}; +``` + +## 4. [Sending transactions](https://github.com/multiversx/mx-template-dapp/pull/264/files#diff-1eadd6ccf43da9c2a8c30f5dfddbb56f3daeec28f04e43b41c134811bec478fb) + - `sendTransactions` has been replaced by `provider.signTransactions`, `txManager.send` and `txManager.track` + - `newTransaction` function has been removed and you need to create `Transaction` objects directly + +## 5. [UI components get imported from sdk-dapp-core-ui](https://github.com/multiversx/mx-template-dapp/pull/264/files#diff-e07cb98fcda2927e31f2a0f6cc5db5cb9a364c8da43d8df70597321bb1558336) + - see `src/lib/sdkDapp/components/CopyButton/CopyButton.tsx` + +### URL login is no longer supported + - see TODO how to login with PostMessage + +## 6. [Types](https://github.com/multiversx/mx-template-dapp/pull/264/files#diff-bd634780b000031ebfffb83de483b66a93ed12fde321950128e31a794ce96057) + - `LoginMethodsEnum` is replaced by `ProviderTypeEnum` + - `RawTransactionType` was removed + - some new types were added, related to UI elements, like `FormatAmountControllerPropsType` \ No newline at end of file diff --git a/package.json b/package.json index 1daff106..385896a4 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,9 @@ "@fortawesome/free-solid-svg-icons": "6.5.1", "@fortawesome/react-fontawesome": "0.2.0", "@multiversx/sdk-core": "^14.x", - "@multiversx/sdk-dapp": "^4.x", + "@multiversx/sdk-dapp": "^5.x", + "@multiversx/sdk-dapp-ui": "^0.x", + "@multiversx/sdk-dapp-utils": "2.0.0", "axios": "1.7.4", "classnames": "2.3.2", "moment": "2.29.4", @@ -21,12 +23,12 @@ "scripts": { "lint": "eslint --ext js,ts,tsx src --fix", "run-cypress": "npx cypress run", - "start:devnet": "yarn run copy:devnet-config & vite dev", - "start:testnet": "yarn run copy:testnet-config & vite dev", - "start:mainnet": "yarn run copy:mainnet-config & vite dev", - "build:devnet": "yarn run copy:devnet-config & vite build", - "build:testnet": "yarn run copy:testnet-config & vite build", - "build:mainnet": "yarn run copy:mainnet-config & vite build", + "start:devnet": "yarn run copy:devnet-config && vite dev", + "start:testnet": "yarn run copy:testnet-config && vite dev", + "start:mainnet": "yarn run copy:mainnet-config && vite dev", + "build:devnet": "tsc & yarn run copy:devnet-config && vite build", + "build:testnet": "tsc & yarn run copy:testnet-config && vite build", + "build:mainnet": "tsc & yarn run copy:mainnet-config && vite build", "copy:devnet-config": "cp ./src/config/config.devnet.ts ./src/config/index.ts", "copy:testnet-config": "cp ./src/config/config.testnet.ts ./src/config/index.ts", "copy:mainnet-config": "cp ./src/config/config.mainnet.ts ./src/config/index.ts", @@ -49,13 +51,12 @@ "@types/jest": "29.5.5", "@types/node": "20.7.1", "@types/react": "18.2.23", - "@types/react-dom": "18.2.8", "@types/react-router-dom": "5.3.3", "@typescript-eslint/eslint-plugin": "6.7.0", "@typescript-eslint/parser": "6.7.0", - "@vitejs/plugin-basic-ssl": "^1.0.1", + "@vitejs/plugin-basic-ssl": "1.0.1", "@vitejs/plugin-react": "4.1.0", - "@wdio/cli": "^8.33.1", + "@wdio/cli": "8.33.1", "@wdio/concise-reporter": "8.32.4", "@wdio/local-runner": "8.32.4", "@wdio/mocha-framework": "8.32.4", @@ -68,7 +69,7 @@ "eslint-plugin-prettier": "5.0.0", "eslint-plugin-react": "7.33.2", "eslint-plugin-react-hooks": "4.6.0", - "eslint-plugin-sort-exports": "^0.9.1", + "eslint-plugin-sort-exports": "0.9.1", "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", "jest-watch-typeahead": "2.2.2", diff --git a/postcss.config.js b/postcss.config.js index 5cbc2c7d..83d8b227 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,6 +1,7 @@ module.exports = { plugins: { tailwindcss: {}, + // '@tailwindcss/postcss': {} // NOTE: This is the new way to include Tailwind CSS V4.0.0+ autoprefixer: {} } }; diff --git a/src/App.tsx b/src/App.tsx index b4240d1f..6154c67a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,86 +1,28 @@ import { Route, BrowserRouter as Router, Routes } from 'react-router-dom'; -import { Layout } from 'components'; -import { - apiTimeout, - environment, - sampleAuthenticatedDomains, - walletConnectV2ProjectId -} from 'config'; -import { - AxiosInterceptorContext, // using this is optional - DappProvider, - NotificationModal, - SignTransactionsModals, - TransactionsToastList - // uncomment this to use the custom transaction tracker - // TransactionsTracker -} from 'lib'; -import { RouteNamesEnum } from 'localConstants'; -import { PageNotFound } from 'pages'; +import { PageNotFound } from 'pages/PageNotFound/PageNotFound'; import { routes } from 'routes'; -import { BatchTransactionsContextProvider } from 'wrappers'; - -const AppContent = () => { - return ( - { - console.log(`Session ${sessionId} successfully completed`); - }, - onFail: (sessionId: string, errorMessage: string) => { - console.log(`Session ${sessionId} failed. ${errorMessage ?? ''}`); - } - } - } - }} - > - - - - - - - {routes.map((route) => ( - } - /> - ))} - } /> - - - - - ); -}; +import { AxiosInterceptors, BatchTransactionsContextProvider } from 'wrappers'; +import { Layout } from './components'; export const App = () => { return ( - - - - - - - - - + + + + + + {routes.map((route) => ( + } + /> + ))} + } /> + + + + + ); }; diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx index da7ff94b..5a6b35ba 100644 --- a/src/components/Button/Button.tsx +++ b/src/components/Button/Button.tsx @@ -22,7 +22,7 @@ export const Button = ({ return ( - ) : ( - ConnectButton + {isLoggedIn && ( + <> + + + )} + + {!isLoggedIn && } diff --git a/src/components/Layout/Header/components/ConnectButton.tsx b/src/components/Layout/Header/components/ConnectButton.tsx new file mode 100644 index 00000000..51c2fa43 --- /dev/null +++ b/src/components/Layout/Header/components/ConnectButton.tsx @@ -0,0 +1,19 @@ +import { useNavigate } from 'react-router-dom'; +import { Button } from 'components'; +import { UnlockPanelManager } from 'lib'; +import { RouteNamesEnum } from 'localConstants'; + +export const ConnectButton = () => { + const navigate = useNavigate(); + const unlockPanelManager = UnlockPanelManager.init({ + loginHandler: () => { + navigate(RouteNamesEnum.dashboard); + } + }); + + const handleOpenUnlockPanel = () => { + unlockPanelManager.openUnlockPanel(); + }; + + return ; +}; diff --git a/src/components/Layout/Header/components/NotificationsButton.tsx b/src/components/Layout/Header/components/NotificationsButton.tsx new file mode 100644 index 00000000..6454469a --- /dev/null +++ b/src/components/Layout/Header/components/NotificationsButton.tsx @@ -0,0 +1,19 @@ +import { faBell } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Button } from 'components'; +import { NotificationsFeedManager } from 'lib'; + +export const NotificationsButton = () => { + const handleOpenNotificationsFeed = () => { + NotificationsFeedManager.getInstance().openNotificationsFeed(); + }; + + return ( + + ); +}; diff --git a/src/components/Layout/Header/components/index.ts b/src/components/Layout/Header/components/index.ts new file mode 100644 index 00000000..916bf3f7 --- /dev/null +++ b/src/components/Layout/Header/components/index.ts @@ -0,0 +1 @@ +export * from './ConnectButton'; diff --git a/src/components/Loader/Loader.tsx b/src/components/Loader/Loader.tsx new file mode 100644 index 00000000..c40a4641 --- /dev/null +++ b/src/components/Loader/Loader.tsx @@ -0,0 +1,14 @@ +import { faSpinner } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; + +export const Loader = () => { + return ( +
+ +
+ ); +}; diff --git a/src/components/Loader/index.tsx b/src/components/Loader/index.tsx new file mode 100644 index 00000000..d5ce9811 --- /dev/null +++ b/src/components/Loader/index.tsx @@ -0,0 +1 @@ +export * from './Loader'; diff --git a/src/components/OutputContainer/OutputContainer.tsx b/src/components/OutputContainer/OutputContainer.tsx index 1f9c03cc..6381b1c3 100644 --- a/src/components/OutputContainer/OutputContainer.tsx +++ b/src/components/OutputContainer/OutputContainer.tsx @@ -1,6 +1,7 @@ import classNames from 'classnames'; import { PropsWithChildren } from 'react'; -import { Loader, WithClassnameType } from 'lib'; +import { Loader } from 'components'; +import { WithClassnameType } from 'types'; interface OutputContainerPropsType extends PropsWithChildren, diff --git a/src/components/OutputContainer/components/TransactionsOutput.tsx b/src/components/OutputContainer/components/TransactionsOutput.tsx index a21c6e81..03f576f3 100644 --- a/src/components/OutputContainer/components/TransactionsOutput.tsx +++ b/src/components/OutputContainer/components/TransactionsOutput.tsx @@ -10,10 +10,7 @@ export const TransactionsOutput = ({
{transactions?.map((transaction) => { return ( - + ); })}
diff --git a/src/components/TransactionsTable/TransactionsTable.tsx b/src/components/TransactionsTable/TransactionsTable.tsx new file mode 100644 index 00000000..86e90374 --- /dev/null +++ b/src/components/TransactionsTable/TransactionsTable.tsx @@ -0,0 +1,43 @@ +import { useEffect, useState } from 'react'; +import { + ITransactionsTableRow, + MvxTransactionsTable, + ServerTransactionType, + TransactionsTableController, + useGetAccount, + useGetNetworkConfig +} from 'lib'; + +interface TransactionsTablePropsType { + transactions?: ServerTransactionType[]; +} + +export const TransactionsTable = ({ + transactions = [] +}: TransactionsTablePropsType) => { + const { address } = useGetAccount(); + const { network } = useGetNetworkConfig(); + const [processedTransaction, setProcessedTransactions] = useState< + ITransactionsTableRow[] + >([]); + + useEffect(() => { + processTransactions(); + }, []); + + const processTransactions = async () => { + const transactionsData = + await TransactionsTableController.processTransactions({ + address, + egldLabel: network.egldLabel, + explorerAddress: network.explorerAddress, + transactions + }); + + setProcessedTransactions( + transactionsData as unknown as ITransactionsTableRow[] + ); + }; + + return ; +}; diff --git a/src/components/TransactionsTable/index.ts b/src/components/TransactionsTable/index.ts new file mode 100644 index 00000000..41036d18 --- /dev/null +++ b/src/components/TransactionsTable/index.ts @@ -0,0 +1 @@ +export * from './TransactionsTable'; diff --git a/src/components/TransactionsTracker/TransactionsTracker.ts b/src/components/TransactionsTracker/TransactionsTracker.ts deleted file mode 100644 index 081e94de..00000000 --- a/src/components/TransactionsTracker/TransactionsTracker.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { useBatchTransactionsTracker, useTransactionsTracker } from 'lib'; - -export const TransactionsTracker = () => { - useTransactionsTracker({ - onSuccess: (sessionId: string) => { - console.log(`Session ${sessionId} successfully completed`); - }, - onFail: (sessionId: string, errorMessage?: string) => { - if (errorMessage) { - console.log(`Session ${sessionId} failed, ${errorMessage}`); - return; - } - - console.log(`Session ${sessionId} failed`); - } - }); - // We do this in order to have full control of the implementation - // Default tracker sends signedTransactions automatically and we don't want to do that - // By doing this it will enable the tracker but without the sendTransactions logic - useBatchTransactionsTracker({ - onSuccess: (sessionId) => { - console.log(`Batch with session ${sessionId} successfully completed`); - }, - onFail: (sessionId, errorMessage) => { - if (errorMessage) { - console.log(`Batch with session ${sessionId} failed, ${errorMessage}`); - return; - } - - console.log(`Batch with session ${sessionId} failed`); - } - }); - - return null; -}; diff --git a/src/components/TransactionsTracker/index.ts b/src/components/TransactionsTracker/index.ts deleted file mode 100644 index 4e1911f7..00000000 --- a/src/components/TransactionsTracker/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './TransactionsTracker'; diff --git a/src/components/index.ts b/src/components/index.ts index ad6b41fd..de768795 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -3,7 +3,8 @@ export * from './Card'; export * from './ContractAddress'; export * from './Label'; export * from './Layout'; +export * from './Loader'; export * from './MissingNativeAuthError'; export * from './MxLink'; export * from './OutputContainer'; -export * from './TransactionsTracker'; +export * from './TransactionsTable'; diff --git a/src/helpers/signAndSendTransactions.ts b/src/helpers/signAndSendTransactions.ts index 4dc48f14..2cf97d90 100644 --- a/src/helpers/signAndSendTransactions.ts +++ b/src/helpers/signAndSendTransactions.ts @@ -1,30 +1,27 @@ -import { refreshAccount, sendTransactions } from 'lib'; -import { isSafari } from 'localConstants'; -import { Transaction, TransactionsDisplayInfoType } from 'types'; +import { + getAccountProvider, + Transaction, + TransactionManager, + TransactionsDisplayInfoType +} from 'lib'; type SignAndSendTransactionsProps = { transactions: Transaction[]; - callbackRoute: string; - transactionsDisplayInfo: TransactionsDisplayInfoType; + transactionsDisplayInfo?: TransactionsDisplayInfoType; }; export const signAndSendTransactions = async ({ transactions, - callbackRoute, transactionsDisplayInfo }: SignAndSendTransactionsProps) => { - await refreshAccount(); + const provider = getAccountProvider(); + const txManager = TransactionManager.getInstance(); - const { sessionId } = await sendTransactions({ - transactions, - transactionsDisplayInfo, - redirectAfterSign: false, - callbackRoute, - // NOTE: performing async calls (eg: `await refreshAccount()`) before opening a new tab - // can cause the new tab to be blocked by Safari's popup blocker. - // To support this feature, we can set `hasConsentPopup` to `true` - hasConsentPopup: isSafari + const signedTransactions = await provider.signTransactions(transactions); + const sentTransactions = await txManager.send(signedTransactions); + const sessionId = await txManager.track(sentTransactions, { + transactionsDisplayInfo }); - return sessionId; + return { sentTransactions, sessionId }; }; diff --git a/src/hooks/index.ts b/src/hooks/index.ts index d57e8f41..4ba6c2eb 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -1,4 +1,2 @@ export * from './transactions'; -export * from './useIsWebProvider'; -export * from './useScrollToElement'; export * from './useWindowSize'; diff --git a/src/hooks/transactions/useSendPingPongTransaction.ts b/src/hooks/transactions/useSendPingPongTransaction.ts index dcb87fb8..50905c69 100644 --- a/src/hooks/transactions/useSendPingPongTransaction.ts +++ b/src/hooks/transactions/useSendPingPongTransaction.ts @@ -1,34 +1,16 @@ -import { - AbiRegistry, - SmartContractTransactionsFactory, - TransactionsFactoryConfig -} from '@multiversx/sdk-core/out'; -import { useCallback, useState } from 'react'; +import axios from 'axios'; import { contractAddress } from 'config'; -import pingPongAbi from 'contracts/ping-pong.abi.json'; -import { signAndSendTransactions } from 'helpers/signAndSendTransactions'; +import { signAndSendTransactions } from 'helpers'; import { + AbiRegistry, Address, - deleteTransactionToast, GAS_PRICE, - newTransaction, - removeAllSignedTransactions, - removeAllTransactionsToSign, - useGetAccountInfo, - useGetNetworkConfig, - useTrackTransactionStatus, - VERSION + SmartContractTransactionsFactory, + Transaction, + TransactionsFactoryConfig, + useGetAccount, + useGetNetworkConfig } from 'lib'; -import { SessionEnum } from 'localConstants'; -import { - PingPongServiceProps, - PingRawProps, - PongRawProps -} from 'types/pingPong.types'; - -type PingPongTransactionProps = { - type: SessionEnum; -}; const PING_TRANSACTION_INFO = { processingMessage: 'Processing Ping transaction', @@ -42,59 +24,13 @@ const PONG_TRANSACTION_INFO = { successMessage: 'Pong transaction successful' }; -export const useSendPingPongTransaction = ({ - type -}: PingPongTransactionProps) => { - // Needed in order to differentiate widgets between each other - // By default sdk-dapp takes the last sessionId available which will display on every widget the same transaction - // this usually appears on page refreshes - const [pingPongSessionId, setPingPongSessionId] = useState( - sessionStorage.getItem(type) - ); - +export const useSendPingPongTransaction = () => { const { network } = useGetNetworkConfig(); - const { address, account } = useGetAccountInfo(); - - const transactionStatus = useTrackTransactionStatus({ - transactionId: pingPongSessionId ?? '0' - }); - - const clearAllTransactions = () => { - removeAllSignedTransactions(); - removeAllTransactionsToSign(); - deleteTransactionToast(pingPongSessionId ?? ''); - }; - - const sendPingTransaction = useCallback( - async ({ amount, callbackRoute }: PingRawProps) => { - clearAllTransactions(); - - const pingTransaction = newTransaction({ - value: amount, - data: 'ping', - receiver: contractAddress, - gasLimit: 60000000, - gasPrice: GAS_PRICE, - chainID: network.chainId, - nonce: account.nonce, - sender: address, - version: VERSION - }); - - const sessionId = await signAndSendTransactions({ - transactions: [pingTransaction], - callbackRoute, - transactionsDisplayInfo: PING_TRANSACTION_INFO - }); - - sessionStorage.setItem(type, sessionId); - setPingPongSessionId(sessionId); - }, - [] - ); + const { address } = useGetAccount(); const getSmartContractFactory = async () => { - const abi = AbiRegistry.create(pingPongAbi); + const response = await axios.get('src/contracts/ping-pong.abi.json'); + const abi = AbiRegistry.create(response.data); const scFactory = new SmartContractTransactionsFactory({ config: new TransactionsFactoryConfig({ chainID: network.chainId @@ -105,119 +41,101 @@ export const useSendPingPongTransaction = ({ return scFactory; }; - const sendPingTransactionFromAbi = useCallback( - async ({ amount, callbackRoute }: PingRawProps) => { - clearAllTransactions(); - - const scFactory = await getSmartContractFactory(); - const pingTransaction = scFactory.createTransactionForExecute( - new Address(address), - { - gasLimit: BigInt(60000000), - function: 'ping', - contract: new Address(contractAddress), - nativeTransferAmount: BigInt(amount) - } - ); - - const sessionId = await signAndSendTransactions({ - transactions: [pingTransaction], - callbackRoute, - transactionsDisplayInfo: PING_TRANSACTION_INFO - }); - - sessionStorage.setItem(type, sessionId); - setPingPongSessionId(sessionId); - }, - [] - ); - - const sendPingTransactionFromService = useCallback( - async ({ transactions, callbackRoute }: PingPongServiceProps) => { - clearAllTransactions(); - - const sessionId = await signAndSendTransactions({ - transactions, - callbackRoute, - transactionsDisplayInfo: PING_TRANSACTION_INFO - }); - - sessionStorage.setItem(type, sessionId); - setPingPongSessionId(sessionId); - }, - [] - ); - - const sendPongTransaction = useCallback( - async ({ callbackRoute }: PongRawProps) => { - clearAllTransactions(); - - const pongTransaction = newTransaction({ - value: '0', - data: 'pong', - receiver: contractAddress, - gasLimit: 60000000, - gasPrice: GAS_PRICE, - chainID: network.chainId, - nonce: account.nonce, - sender: address, - version: VERSION - }); - - const sessionId = await signAndSendTransactions({ - transactions: [pongTransaction], - callbackRoute, - transactionsDisplayInfo: PONG_TRANSACTION_INFO - }); - - sessionStorage.setItem(type, sessionId); - setPingPongSessionId(sessionId); - }, - [] - ); - - const sendPongTransactionFromAbi = useCallback( - async ({ callbackRoute }: PongRawProps) => { - clearAllTransactions(); - - const scFactory = await getSmartContractFactory(); - const pongTransaction = scFactory.createTransactionForExecute( - new Address(address), - { - gasLimit: BigInt(60000000), - function: 'pong', - contract: new Address(contractAddress), - nativeTransferAmount: BigInt(0) - } - ); - - const sessionId = await signAndSendTransactions({ - transactions: [pongTransaction], - callbackRoute, - transactionsDisplayInfo: PONG_TRANSACTION_INFO - }); - - sessionStorage.setItem(type, sessionId); - setPingPongSessionId(sessionId); - }, - [] - ); - - const sendPongTransactionFromService = useCallback( - async ({ transactions, callbackRoute }: PingPongServiceProps) => { - clearAllTransactions(); - - const sessionId = await signAndSendTransactions({ - transactions, - callbackRoute, - transactionsDisplayInfo: PONG_TRANSACTION_INFO - }); - - sessionStorage.setItem(type, sessionId); - setPingPongSessionId(sessionId); - }, - [] - ); + const sendPingTransaction = async (amount: string) => { + const pingTransaction = new Transaction({ + value: BigInt(amount), + data: Buffer.from('ping'), + receiver: new Address(contractAddress), + gasLimit: BigInt(6000000), + gasPrice: BigInt(GAS_PRICE), + chainID: network.chainId, + sender: new Address(address), + version: 1 + }); + + await signAndSendTransactions({ + transactions: [pingTransaction], + transactionsDisplayInfo: PING_TRANSACTION_INFO + }); + }; + + const sendPingTransactionFromAbi = async (amount: string) => { + const scFactory = await getSmartContractFactory(); + const pingTransaction = scFactory.createTransactionForExecute( + new Address(address), + { + gasLimit: BigInt(6000000), + function: 'ping', + contract: new Address(contractAddress), + nativeTransferAmount: BigInt(amount) + } + ); + + const sessionId = await signAndSendTransactions({ + transactions: [pingTransaction], + transactionsDisplayInfo: PING_TRANSACTION_INFO + }); + + return sessionId; + }; + + const sendPingTransactionFromService = async ( + transactions: Transaction[] + ) => { + await signAndSendTransactions({ + transactions, + transactionsDisplayInfo: PING_TRANSACTION_INFO + }); + }; + + const sendPongTransaction = async () => { + const pongTransaction = new Transaction({ + value: BigInt(0), + data: Buffer.from('pong'), + receiver: new Address(contractAddress), + gasLimit: BigInt(6000000), + gasPrice: BigInt(GAS_PRICE), + chainID: network.chainId, + sender: new Address(address), + version: 1 + }); + + await signAndSendTransactions({ + transactions: [pongTransaction], + transactionsDisplayInfo: PONG_TRANSACTION_INFO + }); + }; + + const sendPongTransactionFromAbi = async () => { + const scFactory = await getSmartContractFactory(); + const pongTransaction = scFactory.createTransactionForExecute( + new Address(address), + { + gasLimit: BigInt(6000000), + function: 'pong', + contract: new Address(contractAddress), + nativeTransferAmount: BigInt(0) + } + ); + + const sessionId = await signAndSendTransactions({ + transactions: [pongTransaction], + transactionsDisplayInfo: PONG_TRANSACTION_INFO + }); + + return sessionId; + }; + + const sendPongTransactionFromService = async ( + transactions: Transaction[] + ) => { + const sessionId = await signAndSendTransactions({ + transactions, + transactionsDisplayInfo: PONG_TRANSACTION_INFO + }); + + return sessionId; + }; return { sendPingTransaction, @@ -225,7 +143,6 @@ export const useSendPingPongTransaction = ({ sendPongTransaction, sendPongTransactionFromAbi, sendPingTransactionFromService, - sendPongTransactionFromService, - transactionStatus + sendPongTransactionFromService }; }; diff --git a/src/hooks/useIsWebProvider.ts b/src/hooks/useIsWebProvider.ts deleted file mode 100644 index 3b41ea78..00000000 --- a/src/hooks/useIsWebProvider.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { LoginMethodsEnum, useGetAccountProvider } from 'lib'; - -export const useIsWebProvider = () => { - const { providerType } = useGetAccountProvider(); - const isWebProvider = providerType === LoginMethodsEnum.wallet; - - return { isWebProvider }; -}; diff --git a/src/hooks/useScrollToElement.ts b/src/hooks/useScrollToElement.ts deleted file mode 100644 index 62489666..00000000 --- a/src/hooks/useScrollToElement.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { useEffect } from 'react'; -import { useLocation } from 'react-router-dom'; - -export const useScrollToElement = () => { - const location = useLocation(); - - useEffect(() => { - const [, anchor] = location.hash.split('#'); - - if (!anchor) { - return; - } - - const element = document.getElementById(anchor); - - if (!element) { - return; - } - - element.scrollIntoView(); - }, [location.hash]); -}; diff --git a/src/index.tsx b/src/index.tsx index 44bfaf02..da6a66f7 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,7 +1,13 @@ -import { createRoot } from 'react-dom/client'; -import './styles/globals.css'; +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import { initApp } from 'lib'; import { App } from './App'; +import { config } from './initConfig'; -const container = document.getElementById('root'); -const root = createRoot(container as HTMLElement); -root.render(() as any); +initApp(config).then(() => { + ReactDOM.createRoot(document.getElementById('root')!).render( + + + + ); +}); diff --git a/src/initConfig.ts b/src/initConfig.ts new file mode 100644 index 00000000..23c7c4a4 --- /dev/null +++ b/src/initConfig.ts @@ -0,0 +1,54 @@ +import './styles/globals.css'; + +import { walletConnectV2ProjectId } from 'config'; +import { + EnvironmentsEnum, + ICustomProvider, + InitAppType, + ProviderTypeEnum +} from './lib'; +import { InMemoryProvider } from './provider/inMemoryProvider'; + +const ADDITIONAL_PROVIDERS = { + inMemoryProvider: 'inMemoryProvider' +} as const; + +export const ExtendedProviders = { + ...ProviderTypeEnum, + ...ADDITIONAL_PROVIDERS +} as const; + +const DEFAULT_TOAST_LIEFTIME = 5000; + +const providers: ICustomProvider[] = [ + { + name: 'In Memory Provider', + type: ExtendedProviders.inMemoryProvider, + iconUrl: `${window.location.origin}/multiversx-white.svg`, + constructor: async (options) => new InMemoryProvider(options) + } +]; + +(window as any).multiversx = {}; +// Option 1: Add providers using the `window.providers` array +(window as any).multiversx.providers = providers; + +export const config: InitAppType = { + storage: { getStorageCallback: () => sessionStorage }, + dAppConfig: { + nativeAuth: true, + environment: EnvironmentsEnum.devnet, + network: { + walletAddress: 'https://devnet-wallet.multiversx.com' + }, + providers: { + walletConnect: { + walletConnectV2ProjectId + } + }, + successfulToastLifetime: DEFAULT_TOAST_LIEFTIME + } + + // Option 2: Add providers using the config `customProviders` array + // customProviders: [customWalletProvider] +}; diff --git a/src/lib/index.ts b/src/lib/index.ts index 6a1ace50..b5605906 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -1,2 +1,4 @@ export * from './sdkCore'; export * from './sdkDapp'; +export * from './sdkDappCoreUI'; +export * from './sdkDappUtils'; diff --git a/src/lib/sdkCore.ts b/src/lib/sdkCore.ts index 88751e24..a7b28c49 100644 --- a/src/lib/sdkCore.ts +++ b/src/lib/sdkCore.ts @@ -4,9 +4,17 @@ export { AddressValue, ContractFunction, Message, + MessageComputer, ProxyNetworkProvider, SmartContract, SmartContractController, + SmartContractTransactionsFactory, + Token, TokenTransfer, - Transaction + Transaction, + TransactionComputer, + TransactionsFactoryConfig, + TransferTransactionsFactory, + UserSecretKey, + UserSigner } from '@multiversx/sdk-core'; diff --git a/src/lib/sdkDapp/components/CopyButton/CopyButton.tsx b/src/lib/sdkDapp/components/CopyButton/CopyButton.tsx new file mode 100644 index 00000000..49524cb2 --- /dev/null +++ b/src/lib/sdkDapp/components/CopyButton/CopyButton.tsx @@ -0,0 +1,20 @@ +import { MvxCopyButton } from 'lib/sdkDappCoreUI/sdkDappCoreUI.components'; +import { MvxCopyButtonPropsType } from 'lib/sdkDappCoreUI/sdkDappCoreUI.types'; + +export const CopyButton = ({ + className, + text, + copyIcon, + iconClass, + successIcon +}: Partial) => { + return ( + + ); +}; diff --git a/src/lib/sdkDapp/components/CopyButton/index.ts b/src/lib/sdkDapp/components/CopyButton/index.ts new file mode 100644 index 00000000..367e65cb --- /dev/null +++ b/src/lib/sdkDapp/components/CopyButton/index.ts @@ -0,0 +1 @@ +export * from './CopyButton'; diff --git a/src/lib/sdkDapp/components/ExplorerLink/ExplorerLink.tsx b/src/lib/sdkDapp/components/ExplorerLink/ExplorerLink.tsx new file mode 100644 index 00000000..5f51447d --- /dev/null +++ b/src/lib/sdkDapp/components/ExplorerLink/ExplorerLink.tsx @@ -0,0 +1,29 @@ +import { PropsWithChildren } from 'react'; +import { useGetNetworkConfig } from 'lib/sdkDapp/sdkDapp.hooks'; +import { MvxExplorerLink } from 'lib/sdkDappCoreUI/sdkDappCoreUI.components'; +import { WithClassnameType } from 'types/componentsTypes'; + +export const ExplorerLink = ({ + children, + page, + className, + 'data-testid': dataTestId +}: ExplorerLinkPropsType) => { + const { network } = useGetNetworkConfig(); + + return ( + + {children ? {children} : null} + + ); +}; + +export interface ExplorerLinkPropsType + extends WithClassnameType, + PropsWithChildren { + page: string; +} diff --git a/src/lib/sdkDapp/components/ExplorerLink/index.ts b/src/lib/sdkDapp/components/ExplorerLink/index.ts new file mode 100644 index 00000000..0c7d53d6 --- /dev/null +++ b/src/lib/sdkDapp/components/ExplorerLink/index.ts @@ -0,0 +1 @@ +export * from './ExplorerLink'; diff --git a/src/lib/sdkDapp/components/FormatAmount/FormatAmount.tsx b/src/lib/sdkDapp/components/FormatAmount/FormatAmount.tsx new file mode 100644 index 00000000..fdbf3f49 --- /dev/null +++ b/src/lib/sdkDapp/components/FormatAmount/FormatAmount.tsx @@ -0,0 +1,40 @@ +import { WithClassnameType } from 'types'; +import { MvxFormatAmount } from '../../../sdkDappCoreUI/sdkDappCoreUI.components'; +import { MvxFormatAmountPropsType } from '../../../sdkDappCoreUI/sdkDappCoreUI.types'; +import { DECIMALS, DIGITS } from '../../../sdkDappUtils'; +import { FormatAmountController } from '../../sdkDapp.helpers'; +import { useGetNetworkConfig } from '../../sdkDapp.hooks'; + +interface FormatAmountPropsType + extends Partial, + WithClassnameType { + egldLabel?: string; + value: string; +} + +export const FormatAmount = (props: FormatAmountPropsType) => { + const { + network: { egldLabel } + } = useGetNetworkConfig(); + + const { isValid, valueDecimal, valueInteger, label } = + FormatAmountController.getData({ + digits: DIGITS, + decimals: DECIMALS, + egldLabel, + ...props, + input: props.value + }); + + return ( + + ); +}; diff --git a/src/lib/sdkDapp/components/FormatAmount/index.ts b/src/lib/sdkDapp/components/FormatAmount/index.ts new file mode 100644 index 00000000..3578b893 --- /dev/null +++ b/src/lib/sdkDapp/components/FormatAmount/index.ts @@ -0,0 +1 @@ +export * from './FormatAmount'; diff --git a/src/lib/sdkDapp/components/index.tsx b/src/lib/sdkDapp/components/index.tsx new file mode 100644 index 00000000..b4193d3b --- /dev/null +++ b/src/lib/sdkDapp/components/index.tsx @@ -0,0 +1,3 @@ +export * from './CopyButton'; +export * from './ExplorerLink'; +export * from './FormatAmount'; diff --git a/src/lib/sdkDapp/index.ts b/src/lib/sdkDapp/index.ts index 4f89aa43..b347b18f 100644 --- a/src/lib/sdkDapp/index.ts +++ b/src/lib/sdkDapp/index.ts @@ -1,4 +1,4 @@ -export * from './sdkDapp.components'; +export * from './components'; export * from './sdkDapp.constants'; export * from './sdkDapp.helpers'; export * from './sdkDapp.hooks'; diff --git a/src/lib/sdkDapp/sdkDapp.components.ts b/src/lib/sdkDapp/sdkDapp.components.ts deleted file mode 100644 index eec2024e..00000000 --- a/src/lib/sdkDapp/sdkDapp.components.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * components get re-exported because it makes the build size smaller - * and allows testing with Jest (see `moduleNameMapper` in package.json) - */ -export { ACCOUNTS_ENDPOINT } from '@multiversx/sdk-dapp/apiCalls/endpoints'; -export { AxiosInterceptorContext } from '@multiversx/sdk-dapp/wrappers/AxiosInterceptorContext/AxiosInterceptorContext'; -export { CopyButton } from '@multiversx/sdk-dapp/UI/CopyButton/CopyButton'; -export { CrossWindowLoginButton } from '@multiversx/sdk-dapp/UI/webWallet/CrossWindowLoginButton/CrossWindowLoginButton'; -export { DappProvider } from '@multiversx/sdk-dapp/wrappers/DappProvider/DappProvider'; -export { ExplorerLink } from '@multiversx/sdk-dapp/UI/ExplorerLink'; -export { ExtensionLoginButton } from '@multiversx/sdk-dapp/UI/extension/ExtensionLoginButton/ExtensionLoginButton'; -export { FormatAmount } from '@multiversx/sdk-dapp/UI/FormatAmount/FormatAmount'; -export { IframeButton } from '@multiversx/sdk-dapp/UI/iframe/IframeLoginButton/IframeButton'; -export { LedgerLoginButton } from '@multiversx/sdk-dapp/UI/ledger/LedgerLoginButton/LedgerLoginButton'; -export { Loader } from '@multiversx/sdk-dapp/UI/Loader/Loader'; -export { NotificationModal } from '@multiversx/sdk-dapp/UI/NotificationModal/NotificationModal'; -export { OperaWalletLoginButton } from '@multiversx/sdk-dapp/UI/operaWallet/OperaWalletLoginButton/OperaWalletLoginButton'; -export { PageState } from '@multiversx/sdk-dapp/UI/PageState/PageState'; -export { SignTransactionsModals } from '@multiversx/sdk-dapp/UI/SignTransactionsModals/SignTransactionsModals'; -export { TransactionRow } from '@multiversx/sdk-dapp/UI/TransactionsTable/components/TransactionRow'; -export { TransactionsTable } from '@multiversx/sdk-dapp/UI/TransactionsTable/TransactionsTable'; -export { TransactionsToastList } from '@multiversx/sdk-dapp/UI/TransactionsToastList/TransactionsToastList'; -export { WalletConnectLoginButton } from '@multiversx/sdk-dapp/UI/walletConnect/WalletConnectLoginButton/WalletConnectLoginButton'; -export { WebWalletLoginButton } from '@multiversx/sdk-dapp/UI/webWallet/WebWalletLoginButton/WebWalletLoginButton'; -export { XaliasCrossWindowLoginButton } from '@multiversx/sdk-dapp/UI/webWallet/XaliasCrossWindowLoginButton/XaliasCrossWindowLoginButton'; -export { XaliasLoginButton } from '@multiversx/sdk-dapp/UI/webWallet/XaliasLoginButton/XaliasLoginButton'; diff --git a/src/lib/sdkDapp/sdkDapp.constants.ts b/src/lib/sdkDapp/sdkDapp.constants.ts index e5e48aec..047d4ed6 100644 --- a/src/lib/sdkDapp/sdkDapp.constants.ts +++ b/src/lib/sdkDapp/sdkDapp.constants.ts @@ -1,9 +1,10 @@ export { - DECIMALS, + ACCOUNTS_ENDPOINT, + TRANSACTIONS_ENDPOINT +} from '@multiversx/sdk-dapp/out/apiCalls/endpoints'; +export { EXTRA_GAS_LIMIT_GUARDED_TX, GAS_LIMIT, GAS_PRICE, - VERSION, - WALLET_PROVIDER_SEND_TRANSACTION_URL -} from '@multiversx/sdk-dapp/constants'; -export { TRANSACTIONS_ENDPOINT } from '@multiversx/sdk-dapp/apiCalls/endpoints'; + VERSION +} from '@multiversx/sdk-dapp/out/constants/mvx.constants'; diff --git a/src/lib/sdkDapp/sdkDapp.helpers.ts b/src/lib/sdkDapp/sdkDapp.helpers.ts index 45edd1fc..7870a752 100644 --- a/src/lib/sdkDapp/sdkDapp.helpers.ts +++ b/src/lib/sdkDapp/sdkDapp.helpers.ts @@ -1,22 +1,15 @@ -export { addressIsValid } from '@multiversx/sdk-dapp/utils/account/addressIsValid'; -export { - deleteTransactionToast, - removeAllSignedTransactions, - removeAllTransactionsToSign -} from '@multiversx/sdk-dapp/services/transactions/clearTransactions'; -export { getInterpretedTransaction } from '@multiversx/sdk-dapp/utils/transactions/getInterpretedTransaction'; -export { getIsProviderEqualTo } from '@multiversx/sdk-dapp/utils/account/getIsProviderEqualTo'; -export { getTransactions } from '@multiversx/sdk-dapp/apiCalls/transactions/getTransactions'; -export { logout } from '@multiversx/sdk-dapp/utils/logout'; -export { newTransaction } from '@multiversx/sdk-dapp/models'; -export { parseAmount } from '@multiversx/sdk-dapp/utils/operations/parseAmount'; -export { refreshAccount } from '@multiversx/sdk-dapp/utils/account/refreshAccount'; -export { sendBatchTransactions } from '@multiversx/sdk-dapp/services/transactions/sendBatchTransactions'; -export { sendTransactions } from '@multiversx/sdk-dapp/services/transactions/sendTransactions'; -export { - setTransactionsDisplayInfoState, - setTransactionsToSignedState -} from '@multiversx/sdk-dapp/services/transactions/updateSignedTransactions'; -export { signTransactions } from '@multiversx/sdk-dapp/services/transactions/signTransactions'; -export { trimUsernameDomain } from '@multiversx/sdk-dapp/hooks/account/helpers'; -export { verifyMessage } from '@multiversx/sdk-dapp/hooks/signMessage/verifyMessage'; +export { FormatAmountController } from '@multiversx/sdk-dapp/out/controllers/FormatAmountController'; +export { NotificationsFeedManager } from '@multiversx/sdk-dapp/out/core/managers/NotificationsFeedManager/NotificationsFeedManager'; +export { ProviderFactory } from '@multiversx/sdk-dapp/out/core/providers/ProviderFactory'; +export { TransactionManager } from '@multiversx/sdk-dapp/out/core/managers/TransactionManager'; +export { TransactionsTableController } from '@multiversx/sdk-dapp/out/controllers/TransactionsTableController'; +export { UnlockPanelManager } from '@multiversx/sdk-dapp/out/core/managers/UnlockPanelManager'; +export { WALLET_PROVIDER_SEND_TRANSACTION_URL } from '@multiversx/sdk-dapp/out/constants/webWalletProvider.constants'; +export { getAccountProvider } from '@multiversx/sdk-dapp/out/core/providers/helpers/accountProvider'; +export { getActiveTransactionsStatus } from '@multiversx/sdk-dapp/out/utils/transactions/getActiveTransactionsStatus'; +export { getInterpretedTransaction } from '@multiversx/sdk-dapp/out/utils/transactions/getInterpretedTransaction'; +export { getTransactions } from '@multiversx/sdk-dapp/out/apiCalls/transactions/getTransactions'; +export { initApp } from '@multiversx/sdk-dapp/out/core/methods/initApp/initApp'; +export { setAxiosInterceptors } from '@multiversx/sdk-dapp/out/utils/network/setAxiosInterceptors'; +export { signTransactions } from '@multiversx/sdk-dapp/out/core/providers/strategies/helpers/signTransactions/signTransactions'; +export { trimUsernameDomain } from '@multiversx/sdk-dapp/out/utils/account/trimUsernameDomain'; diff --git a/src/lib/sdkDapp/sdkDapp.hooks.ts b/src/lib/sdkDapp/sdkDapp.hooks.ts index 0dffc93a..724e8fd1 100644 --- a/src/lib/sdkDapp/sdkDapp.hooks.ts +++ b/src/lib/sdkDapp/sdkDapp.hooks.ts @@ -1,21 +1,6 @@ -export { useBatchTransactionsTracker } from '@multiversx/sdk-dapp/hooks/transactions/batch/tracker/useBatchTransactionsTracker'; -export { useCheckBatch } from '@multiversx/sdk-dapp/hooks/transactions/batch/tracker/useCheckBatch'; -export { useGetAccount } from '@multiversx/sdk-dapp/hooks/account/useGetAccount'; -export { useGetAccountInfo } from '@multiversx/sdk-dapp/hooks/account/useGetAccountInfo'; -export { useGetAccountProvider } from '@multiversx/sdk-dapp/hooks/account/useGetAccountProvider'; -export { useGetActiveTransactionsStatus } from '@multiversx/sdk-dapp/hooks/transactions/useGetActiveTransactionsStatus'; -export { useGetBatches } from '@multiversx/sdk-dapp/hooks/transactions/batch/useGetBatches'; -export { useGetIsLoggedIn } from '@multiversx/sdk-dapp/hooks/account/useGetIsLoggedIn'; -export { useGetLastSignedMessageSession } from '@multiversx/sdk-dapp/hooks/signMessage/useGetLastSignedMessageSession'; -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'; -export { useGetSignMessageInfoStatus } from '@multiversx/sdk-dapp/hooks/signMessage/useGetSignedMessageStatus'; -export { useGetSignMessageSession } from '@multiversx/sdk-dapp/hooks/signMessage/useGetSignMessageSession'; -export { useGetSignedTransactions } from '@multiversx/sdk-dapp/hooks/transactions/useGetSignedTransactions'; -export { useParseSignedTransactions } from '@multiversx/sdk-dapp/hooks/transactions/useParseSignedTransactions'; -export { useSendBatchTransactions } from '@multiversx/sdk-dapp/hooks/transactions/batch/useSendBatchTransactions'; -export { useSignMessage } from '@multiversx/sdk-dapp/hooks/signMessage/useSignMessage'; -export { useSignTransactions } from '@multiversx/sdk-dapp/hooks/transactions/useSignTransactions'; -export { useTrackTransactionStatus } from '@multiversx/sdk-dapp/hooks/transactions/useTrackTransactionStatus'; -export { useTransactionsTracker } from '@multiversx/sdk-dapp/hooks/transactions/useTransactionsTracker'; +export { useGetAccount } from '@multiversx/sdk-dapp/out/store/selectors/hooks/account/useGetAccount'; +export { useGetAccountInfo } from '@multiversx/sdk-dapp/out/store/selectors/hooks/account/useGetAccountInfo'; +export { useGetIsLoggedIn } from '@multiversx/sdk-dapp/out/store/selectors/hooks/account/useGetIsLoggedIn'; +export { useGetLoginInfo } from '@multiversx/sdk-dapp/out/store/selectors/hooks/loginInfo/useGetLoginInfo'; +export { useGetNetworkConfig } from '@multiversx/sdk-dapp/out/store/selectors/hooks/network/useGetNetworkConfig'; +export { useGetPendingTransactions } from '@multiversx/sdk-dapp/out/store/selectors/hooks/transactions/useGetPendingTransactions'; diff --git a/src/lib/sdkDapp/sdkDapp.types.ts b/src/lib/sdkDapp/sdkDapp.types.ts index 8fb27cc2..560df90c 100644 --- a/src/lib/sdkDapp/sdkDapp.types.ts +++ b/src/lib/sdkDapp/sdkDapp.types.ts @@ -1,15 +1,14 @@ -export type { AccountType } from '@multiversx/sdk-dapp/types/account.types'; -export { - EnvironmentsEnum, - LoginMethodsEnum, - SignedMessageStatusesEnum -} from '@multiversx/sdk-dapp/types/enums.types'; +export type { AccountType } from '@multiversx/sdk-dapp/out/types/account.types'; +export { EnvironmentsEnum } from '@multiversx/sdk-dapp/out/types/enums.types'; +export type { FormatAmountControllerPropsType } from '@multiversx/sdk-dapp/out/controllers/FormatAmountController/types'; +export type { ICustomProvider } from '@multiversx/sdk-dapp/out/core/providers/types/providerFactory.types'; +export type { IProvider } from '@multiversx/sdk-dapp/out/core/providers/types/providerFactory.types'; +export type { IProviderFactory } from '@multiversx/sdk-dapp/out/core/providers/types/providerFactory.types'; +export type { InitAppType } from '@multiversx/sdk-dapp/out/core/methods/initApp/initApp.types'; export type { - RawTransactionType, - SignedTransactionType, - TransactionsDisplayInfoType -} from '@multiversx/sdk-dapp/types/transactions.types'; -export type { RouteType } from '@multiversx/sdk-dapp/types/index'; -export type { ServerTransactionType } from '@multiversx/sdk-dapp/types/serverTransactions.types'; -export { TransactionBatchStatusesEnum } from '@multiversx/sdk-dapp/types/enums.types'; -export type { WithClassnameType } from '@multiversx/sdk-dapp/UI/types'; + InterpretedTransactionType, + ServerTransactionType +} from '@multiversx/sdk-dapp/out/types/serverTransactions.types'; +export { ProviderTypeEnum } from '@multiversx/sdk-dapp/out/core/providers/types/providerFactory.types'; +export type { SignedTransactionType } from '@multiversx/sdk-dapp/out/types/transactions.types'; +export type { TransactionsDisplayInfoType } from '@multiversx/sdk-dapp/out/types/transactions.types'; diff --git a/src/lib/sdkDappCoreUI/index.ts b/src/lib/sdkDappCoreUI/index.ts new file mode 100644 index 00000000..9de7bbad --- /dev/null +++ b/src/lib/sdkDappCoreUI/index.ts @@ -0,0 +1,2 @@ +export * from './sdkDappCoreUI.components'; +export * from './sdkDappCoreUI.types'; diff --git a/src/lib/sdkDappCoreUI/sdkDappCoreUI.components.ts b/src/lib/sdkDappCoreUI/sdkDappCoreUI.components.ts new file mode 100644 index 00000000..ec5d3e68 --- /dev/null +++ b/src/lib/sdkDappCoreUI/sdkDappCoreUI.components.ts @@ -0,0 +1,7 @@ +export { + MvxCopyButton, + MvxExplorerLink, + MvxFormatAmount, + MvxTransactionsTable, + MvxUnlockButton +} from '@multiversx/sdk-dapp-ui/react'; diff --git a/src/lib/sdkDappCoreUI/sdkDappCoreUI.types.ts b/src/lib/sdkDappCoreUI/sdkDappCoreUI.types.ts new file mode 100644 index 00000000..f29d69dd --- /dev/null +++ b/src/lib/sdkDappCoreUI/sdkDappCoreUI.types.ts @@ -0,0 +1,5 @@ +export type { ITransactionsTableRow } from '@multiversx/sdk-dapp-ui'; +export type { MvxCopyButton as MvxCopyButtonPropsType } from '@multiversx/sdk-dapp-ui/web-components/mvx-copy-button'; +export type { MvxExplorerLink as MvxExplorerLinkPropsType } from '@multiversx/sdk-dapp-ui/web-components/mvx-explorer-link'; +export type { MvxFormatAmount as MvxFormatAmountPropsType } from '@multiversx/sdk-dapp-ui/web-components/mvx-format-amount'; +export type { MvxTransactionsTable as MvxTransactionsTablePropsType } from '@multiversx/sdk-dapp-ui/web-components/mvx-transactions-table'; diff --git a/src/lib/sdkDappUtils/index.ts b/src/lib/sdkDappUtils/index.ts new file mode 100644 index 00000000..5e18c9ec --- /dev/null +++ b/src/lib/sdkDappUtils/index.ts @@ -0,0 +1,2 @@ +export * from './sdkDappUtils'; +export * from './sdkDappUtils.types'; diff --git a/src/lib/sdkDappUtils/sdkDappUtils.ts b/src/lib/sdkDappUtils/sdkDappUtils.ts new file mode 100644 index 00000000..53640edd --- /dev/null +++ b/src/lib/sdkDappUtils/sdkDappUtils.ts @@ -0,0 +1,3 @@ +export { DECIMALS, DIGITS } from '@multiversx/sdk-dapp-utils/out/constants'; +export { formatAmount } from '@multiversx/sdk-dapp-utils/out/helpers/formatAmount'; +export { parseAmount } from '@multiversx/sdk-dapp-utils/out/helpers/parseAmount'; diff --git a/src/lib/sdkDappUtils/sdkDappUtils.types.ts b/src/lib/sdkDappUtils/sdkDappUtils.types.ts new file mode 100644 index 00000000..a7e87f62 --- /dev/null +++ b/src/lib/sdkDappUtils/sdkDappUtils.types.ts @@ -0,0 +1,6 @@ +export type { + IDAppProviderAccount, + IDAppProviderOptions +} from '@multiversx/sdk-dapp-utils/out/models'; +export type { Nullable } from '@multiversx/sdk-dapp-utils/out/types'; +export { SignMessageStatusEnum } from '@multiversx/sdk-dapp-utils/out/enums'; diff --git a/src/localConstants/index.ts b/src/localConstants/index.ts index be49925f..ace81441 100644 --- a/src/localConstants/index.ts +++ b/src/localConstants/index.ts @@ -1,4 +1,3 @@ export * from './dataTestIds.enum'; export * from './routes'; -export * from './session'; export * from './signMessage'; diff --git a/src/localConstants/routes/routeNames.enums.ts b/src/localConstants/routes/routeNames.enums.ts index f728b432..2906ce1e 100644 --- a/src/localConstants/routes/routeNames.enums.ts +++ b/src/localConstants/routes/routeNames.enums.ts @@ -1,6 +1,5 @@ export enum RouteNamesEnum { home = '/', dashboard = '/dashboard', - unlock = '/unlock', disclaimer = '/disclaimer' } diff --git a/src/localConstants/session/index.ts b/src/localConstants/session/index.ts deleted file mode 100644 index 82def9ba..00000000 --- a/src/localConstants/session/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from './session.enums'; - -export const isSafari = /^((?!chrome|android).)*safari/i.test( - navigator.userAgent -); diff --git a/src/localConstants/session/session.enums.ts b/src/localConstants/session/session.enums.ts deleted file mode 100644 index 38228a12..00000000 --- a/src/localConstants/session/session.enums.ts +++ /dev/null @@ -1,8 +0,0 @@ -export enum SessionEnum { - batchSessionId = 'batchSessionId', - signedSessionId = 'signedSessionId', - rawPingPongSessionId = 'rawPingPongSessionId', - abiPingPongSessionId = 'abiPingPongSessionId', - abiPingPongServiceSessionId = 'abiPingPongServiceSessionId', - batchId = 'batchId' -} diff --git a/src/pages/Dashboard/Dashboard.tsx b/src/pages/Dashboard/Dashboard.tsx index e61553e5..8bc779f9 100644 --- a/src/pages/Dashboard/Dashboard.tsx +++ b/src/pages/Dashboard/Dashboard.tsx @@ -1,5 +1,4 @@ import { contractAddress } from 'config'; -import { useScrollToElement } from 'hooks'; import { WidgetType } from 'types/widget.types'; import { Widget } from './components'; import { @@ -26,8 +25,7 @@ const WIDGETS: WidgetType[] = [ description: 'Smart Contract interactions using manually formulated transactions', reference: - 'https://docs.multiversx.com/sdk-and-tools/indices/es-index-transactions/', - anchor: 'ping-pong-manual' + 'https://docs.multiversx.com/sdk-and-tools/indices/es-index-transactions/' }, { title: 'Ping & Pong (ABI)', @@ -35,23 +33,20 @@ const WIDGETS: WidgetType[] = [ description: 'Smart Contract interactions using the ABI generated transactions', reference: - 'https://docs.multiversx.com/sdk-and-tools/sdk-js/sdk-js-cookbook/#using-interaction-when-the-abi-is-available', - anchor: 'ping-pong-abi' + 'https://docs.multiversx.com/sdk-and-tools/sdk-js/sdk-js-cookbook/#using-interaction-when-the-abi-is-available' }, { title: 'Ping & Pong (Backend)', widget: PingPongService, description: 'Smart Contract interactions using the backend generated transactions', - reference: 'https://github.com/multiversx/mx-ping-pong-service', - anchor: 'ping-pong-backend' + reference: 'https://github.com/multiversx/mx-ping-pong-service' }, { title: 'Sign message', widget: SignMessage, description: 'Message signing using the connected account', - reference: 'https://docs.multiversx.com/sdk-and-tools/sdk-dapp/#account-1', - anchor: 'sign-message' + reference: 'https://docs.multiversx.com/sdk-and-tools/sdk-dapp/#account-1' }, { title: 'Native auth', @@ -66,8 +61,7 @@ const WIDGETS: WidgetType[] = [ description: 'For complex scenarios transactions can be sent in the desired group/sequence', reference: - 'https://github.com/multiversx/mx-sdk-dapp#sending-transactions-synchronously-in-batches', - anchor: 'batch-transactions' + 'https://github.com/multiversx/mx-sdk-dapp#sending-transactions-synchronously-in-batches' }, { title: 'Transactions (All)', @@ -87,8 +81,6 @@ const WIDGETS: WidgetType[] = [ ]; export const Dashboard = () => { - useScrollToElement(); - return (
{WIDGETS.map((element) => ( diff --git a/src/pages/Dashboard/components/Widget.tsx b/src/pages/Dashboard/components/Widget.tsx index 3177d7b5..9b7a7a90 100644 --- a/src/pages/Dashboard/components/Widget.tsx +++ b/src/pages/Dashboard/components/Widget.tsx @@ -1,7 +1,5 @@ import { Card } from 'components'; -import { useIsWebProvider } from 'hooks'; import { WidgetType } from 'types/widget.types'; -import { getCallbackRoute } from 'utils/getCallbackRoute'; export const Widget = ({ title, @@ -11,11 +9,6 @@ export const Widget = ({ widget: MxWidget, props = {} }: WidgetType) => { - const { isWebProvider } = useIsWebProvider(); - const callbackRoute = anchor - ? getCallbackRoute({ anchor, isWebProvider }) - : ''; - return ( - + ); }; diff --git a/src/pages/Dashboard/widgets/BatchTransactions/BatchTransactions.tsx b/src/pages/Dashboard/widgets/BatchTransactions/BatchTransactions.tsx index 3e61b578..0db48c91 100644 --- a/src/pages/Dashboard/widgets/BatchTransactions/BatchTransactions.tsx +++ b/src/pages/Dashboard/widgets/BatchTransactions/BatchTransactions.tsx @@ -3,106 +3,57 @@ import { faPaperPlane } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { useEffect, useState } from 'react'; import { Button, OutputContainer, TransactionsOutput } from 'components'; import { - useGetAccountInfo, - useGetBatches, + useGetAccount, useGetNetworkConfig, useGetPendingTransactions } from 'lib'; -import { SessionEnum } from 'localConstants/session'; -import { SignedTransactionType, WidgetProps } from 'types'; -import { useBatchTransactionContext } from 'wrappers'; import { sendBatchTransactions, signAndAutoSendBatchTransactions, swapAndLockTokens } from './helpers'; -import { useSendSignedTransactions } from './hooks'; -export const BatchTransactions = ({ callbackRoute }: WidgetProps) => { - const { setSendBatchTransactionsOnDemand } = useBatchTransactionContext(); - const { address, account } = useGetAccountInfo(); +export const BatchTransactions = () => { + const { address, nonce } = useGetAccount(); const { network } = useGetNetworkConfig(); - const { batches } = useGetBatches(); - const { hasPendingTransactions } = useGetPendingTransactions(); - const [trackBatchId, setTrackBatchId] = useState( - sessionStorage.getItem(SessionEnum.batchId) - ); - - const [stateTransactions, setStateTransactions] = useState< - SignedTransactionType[] | null - >(null); - const [currentSessionId, setCurrentSessionId] = useState( - sessionStorage.getItem(SessionEnum.signedSessionId) || '' - ); - - const { batchId, setBatchSessionId } = useSendSignedTransactions({ - signedSessionId: currentSessionId - }); - - // If manual batch transactions are executed, track the batchId - useEffect(() => { - if (batchId) { - setTrackBatchId(batchId); - } - }, [batchId]); - - useEffect(() => { - if (trackBatchId && batches[trackBatchId]) { - setStateTransactions(batches[trackBatchId].transactions.flat()); - } - }, [trackBatchId, batches]); + const transactions = useGetPendingTransactions(); + const hasPendingTransactions = transactions.length > 0; const executeSignAndAutoSendBatchTransactions = async () => { - setSendBatchTransactionsOnDemand(false); - - const { batchId: batchIdResult } = await signAndAutoSendBatchTransactions({ + await signAndAutoSendBatchTransactions({ address, - nonce: account.nonce, + nonce, chainID: network.chainId, - callbackRoute + transactionsDisplayInfo: { + processingMessage: 'Processing batch transactions', + errorMessage: + 'An error has occurred during batch transaction execution', + successMessage: 'Batch transactions successful' + } }); - - if (!batchIdResult) { - return; - } - - setTrackBatchId(batchIdResult); }; const executeBatchTransactions = async () => { - setSendBatchTransactionsOnDemand(true); - const { newBatchSessionId, sessionId } = await sendBatchTransactions({ + await sendBatchTransactions({ address, - nonce: account.nonce, - chainID: network.chainId, - callbackRoute + nonce, + chainID: network.chainId }); - - if (!newBatchSessionId || !sessionId) { - return; - } - - setBatchSessionId(newBatchSessionId); - setCurrentSessionId(sessionId); }; const executeSwapAndLockTokens = async () => { - setSendBatchTransactionsOnDemand(true); - const { batchId: currentBatchId } = await swapAndLockTokens({ + await swapAndLockTokens({ address, - nonce: account.nonce, + nonce, chainID: network.chainId, - callbackRoute + transactionsDisplayInfo: { + processingMessage: 'Processing swap and lock', + errorMessage: 'An error has occurred during swap and lock', + successMessage: 'Swap and lock successful' + } }); - - if (!currentBatchId) { - return; - } - - setTrackBatchId(currentBatchId); }; return ( @@ -124,7 +75,6 @@ export const BatchTransactions = ({ callbackRoute }: WidgetProps) => { Sign batch & controlled sending -
- {stateTransactions && ( - - )} + ); diff --git a/src/pages/Dashboard/widgets/BatchTransactions/helpers/getBatchTransactions.ts b/src/pages/Dashboard/widgets/BatchTransactions/helpers/getBatchTransactions.ts index b1dcc856..9aa6e7cf 100644 --- a/src/pages/Dashboard/widgets/BatchTransactions/helpers/getBatchTransactions.ts +++ b/src/pages/Dashboard/widgets/BatchTransactions/helpers/getBatchTransactions.ts @@ -1,41 +1,32 @@ +import BigNumber from 'bignumber.js'; import { - DECIMALS, - EXTRA_GAS_LIMIT_GUARDED_TX, - GAS_LIMIT, - GAS_PRICE, - newTransaction, - TokenTransfer, + Address, Transaction, - VERSION + TransactionsFactoryConfig, + TransferTransactionsFactory } from 'lib'; -import { TransactionProps } from 'types/transaction.types'; +import { TransactionProps } from 'types'; const NUMBER_OF_TRANSACTIONS = 5; export const getBatchTransactions = ({ address, - nonce, chainID }: TransactionProps): Transaction[] => { const transactions = Array.from(Array(NUMBER_OF_TRANSACTIONS).keys()); + const factoryConfig = new TransactionsFactoryConfig({ chainID }); + const factory = new TransferTransactionsFactory({ config: factoryConfig }); + return transactions.map((id) => { - const amount = TokenTransfer.fungibleFromAmount( - '', - id + 1, - DECIMALS - ).toString(); + const tokenTransfer = factory.createTransactionForNativeTokenTransfer( + Address.newFromBech32(address), + { + receiver: Address.newFromBech32(address), + nativeAmount: BigInt(new BigNumber(id).plus(1).shiftedBy(18).toFixed()) + } + ); - return newTransaction({ - sender: address, - receiver: address, - data: `batch-tx-${id + 1}`, - value: amount, - chainID, - gasLimit: GAS_LIMIT + EXTRA_GAS_LIMIT_GUARDED_TX, - gasPrice: GAS_PRICE, - nonce, - version: VERSION - }); + return tokenTransfer; }); }; diff --git a/src/pages/Dashboard/widgets/BatchTransactions/helpers/getSwapAndLockTransactions.ts b/src/pages/Dashboard/widgets/BatchTransactions/helpers/getSwapAndLockTransactions.ts index 0c15d064..4393ec37 100644 --- a/src/pages/Dashboard/widgets/BatchTransactions/helpers/getSwapAndLockTransactions.ts +++ b/src/pages/Dashboard/widgets/BatchTransactions/helpers/getSwapAndLockTransactions.ts @@ -1,5 +1,5 @@ import { BATCH_TRANSACTIONS_SC } from 'config'; -import { GAS_PRICE, newTransaction, Transaction, VERSION } from 'lib'; +import { Address, GAS_PRICE, Transaction, VERSION } from 'lib'; import { TransactionProps } from 'types'; export const getSwapAndLockTransactions = ({ @@ -8,49 +8,53 @@ export const getSwapAndLockTransactions = ({ nonce }: TransactionProps): Transaction[] => { return [ - newTransaction({ + new Transaction({ chainID, - gasLimit: 4200000, - gasPrice: GAS_PRICE, - nonce, - receiver: BATCH_TRANSACTIONS_SC.egld_wEGLD.contract, - sender: address, - value: '1000000000000000000', + gasLimit: BigInt(4200000), + gasPrice: BigInt(GAS_PRICE), + nonce: BigInt(nonce), + receiver: Address.newFromBech32( + BATCH_TRANSACTIONS_SC.egld_wEGLD.contract + ), + sender: Address.newFromBech32(address), + value: BigInt('1000000000000000000'), version: VERSION, - data: BATCH_TRANSACTIONS_SC.egld_wEGLD.data + data: Uint8Array.from(Buffer.from(BATCH_TRANSACTIONS_SC.egld_wEGLD.data)) }), - newTransaction({ + new Transaction({ chainID, - gasLimit: 25500000, - gasPrice: GAS_PRICE, - nonce, - receiver: BATCH_TRANSACTIONS_SC.wEGLD_USDC.contract, - sender: address, - value: '0', + gasLimit: BigInt(25500000), + gasPrice: BigInt(GAS_PRICE), + nonce: BigInt(nonce), + receiver: Address.newFromBech32( + BATCH_TRANSACTIONS_SC.wEGLD_USDC.contract + ), + sender: Address.newFromBech32(address), + value: BigInt('0'), version: VERSION, - data: BATCH_TRANSACTIONS_SC.wEGLD_USDC.data + data: Uint8Array.from(Buffer.from(BATCH_TRANSACTIONS_SC.wEGLD_USDC.data)) }), - newTransaction({ + new Transaction({ chainID, - gasLimit: 25500000, - gasPrice: GAS_PRICE, - nonce, - receiver: BATCH_TRANSACTIONS_SC.wEGLD_MEX.contract, - sender: address, - value: '0', + gasLimit: BigInt(25500000), + gasPrice: BigInt(GAS_PRICE), + nonce: BigInt(nonce), + receiver: Address.newFromBech32(BATCH_TRANSACTIONS_SC.wEGLD_MEX.contract), + sender: Address.newFromBech32(address), + value: BigInt('0'), version: VERSION, - data: BATCH_TRANSACTIONS_SC.wEGLD_MEX.data + data: Uint8Array.from(Buffer.from(BATCH_TRANSACTIONS_SC.wEGLD_MEX.data)) }), - newTransaction({ + new Transaction({ chainID, - gasLimit: 10000000, - gasPrice: GAS_PRICE, - nonce, - receiver: BATCH_TRANSACTIONS_SC.lock_MEX.contract, - sender: address, - value: '0', + gasLimit: BigInt(10000000), + gasPrice: BigInt(GAS_PRICE), + nonce: BigInt(nonce), + receiver: Address.newFromBech32(BATCH_TRANSACTIONS_SC.lock_MEX.contract), + sender: Address.newFromBech32(address), + value: BigInt('0'), version: VERSION, - data: BATCH_TRANSACTIONS_SC.lock_MEX.data + data: Uint8Array.from(Buffer.from(BATCH_TRANSACTIONS_SC.lock_MEX.data)) }) ]; }; diff --git a/src/pages/Dashboard/widgets/BatchTransactions/helpers/sendBatchTransactions.ts b/src/pages/Dashboard/widgets/BatchTransactions/helpers/sendBatchTransactions.ts index dedb0830..e879ea0c 100644 --- a/src/pages/Dashboard/widgets/BatchTransactions/helpers/sendBatchTransactions.ts +++ b/src/pages/Dashboard/widgets/BatchTransactions/helpers/sendBatchTransactions.ts @@ -1,38 +1,32 @@ -import { sendTransactions } from 'lib/sdkDapp/sdkDapp.helpers'; -import { isSafari, SessionEnum } from 'localConstants/session'; -import { getBatchTransactions } from '../helpers'; -import { SendTransactionProps } from '../types'; +import { getAccountProvider } from 'lib'; +import { TransactionProps } from 'types'; +import { getBatchTransactions } from './getBatchTransactions'; +import { transactionsHandler } from './transactionsHandler'; export const sendBatchTransactions = async ({ address, chainID, - nonce, - callbackRoute -}: SendTransactionProps) => { - const transactions = getBatchTransactions({ + nonce +}: TransactionProps) => { + const provider = getAccountProvider(); + + const transactionsToSign = getBatchTransactions({ address, chainID, nonce }); - const { sessionId, error } = await sendTransactions({ - transactions, - signWithoutSending: true, - customTransactionInformation: { redirectAfterSign: true }, - callbackRoute, - hasConsentPopup: isSafari - }); + const transactions = await provider.signTransactions(transactionsToSign); - if (error) { - console.error('Could not execute transactions', error); - return {}; - } + const groupedTransactions = [ + [transactions[0]], + [transactions[1], transactions[2]], + [transactions[3], transactions[4]] + ]; - const newBatchSessionId = Date.now().toString(); - // sdk-dapp by default takes the last session id from sdk-dapp’s redux store on page refresh - // in order to differentiate the transactions between widgets, a persistence of sessionId is needed - sessionStorage.setItem(SessionEnum.batchSessionId, newBatchSessionId); - sessionStorage.setItem(SessionEnum.signedSessionId, sessionId); + const { sentTransactions, sessionId } = await transactionsHandler({ + transactions: groupedTransactions + }); - return { newBatchSessionId, sessionId }; + return { sentTransactions, sessionId }; }; diff --git a/src/pages/Dashboard/widgets/BatchTransactions/helpers/signAndAutoSendBatchTransactions.ts b/src/pages/Dashboard/widgets/BatchTransactions/helpers/signAndAutoSendBatchTransactions.ts index 8d1b8ea2..1c8e41f1 100644 --- a/src/pages/Dashboard/widgets/BatchTransactions/helpers/signAndAutoSendBatchTransactions.ts +++ b/src/pages/Dashboard/widgets/BatchTransactions/helpers/signAndAutoSendBatchTransactions.ts @@ -1,47 +1,42 @@ -import { refreshAccount, sendBatchTransactions } from 'lib'; -import { isSafari, SessionEnum } from 'localConstants/session'; -import { getBatchTransactions } from '../helpers'; -import { SendTransactionProps } from '../types'; +import { getAccountProvider, TransactionsDisplayInfoType } from 'lib'; +import { TransactionProps } from 'types'; +import { getBatchTransactions } from './getBatchTransactions'; +import { transactionsHandler } from './transactionsHandler'; -// this process will not go through useSendSignedTransactions -// it will automatically sign and send transactions export const signAndAutoSendBatchTransactions = async ({ address, nonce, chainID, - callbackRoute -}: SendTransactionProps) => { + transactionsDisplayInfo = { + processingMessage: 'Processing transactions', + errorMessage: 'An error has occurred during transaction execution', + successMessage: 'Batch transactions successful' + } +}: TransactionProps & { + transactionsDisplayInfo?: TransactionsDisplayInfoType; +}) => { + const provider = getAccountProvider(); + const transactions = getBatchTransactions({ address, nonce, chainID }); + const signedTransactions = await provider.signTransactions(transactions); + const groupedTransactions = [ - [transactions[0]], - [transactions[1], transactions[2]], - [transactions[3], transactions[4]] + [signedTransactions[0]], + [signedTransactions[1], signedTransactions[2]], + [signedTransactions[3], signedTransactions[4]] ]; - await refreshAccount(); - - const { batchId, error } = await sendBatchTransactions({ + const { sentTransactions, sessionId } = await transactionsHandler({ transactions: groupedTransactions, - customTransactionInformation: { redirectAfterSign: true }, - transactionsDisplayInfo: { - processingMessage: 'Processing transactions', - errorMessage: 'An error has occurred during transaction execution', - successMessage: 'Batch transactions successful' - }, - callbackRoute, - hasConsentPopup: isSafari + options: { + transactionsDisplayInfo + } }); - if (error) { - console.error('Could not execute transactions', error); - return {}; - } - - sessionStorage.setItem(SessionEnum.batchId, batchId); - return { batchId }; + return { sentTransactions, sessionId }; }; diff --git a/src/pages/Dashboard/widgets/BatchTransactions/helpers/swapAndLockTokens.ts b/src/pages/Dashboard/widgets/BatchTransactions/helpers/swapAndLockTokens.ts index 2454718b..4086072c 100644 --- a/src/pages/Dashboard/widgets/BatchTransactions/helpers/swapAndLockTokens.ts +++ b/src/pages/Dashboard/widgets/BatchTransactions/helpers/swapAndLockTokens.ts @@ -1,46 +1,42 @@ -import { refreshAccount, sendBatchTransactions } from 'lib'; -import { isSafari, SessionEnum } from 'localConstants/session'; -import { getSwapAndLockTransactions } from '../helpers'; -import { SendTransactionProps } from '../types'; +import { getAccountProvider, TransactionsDisplayInfoType } from 'lib'; +import { TransactionProps } from 'types'; +import { getSwapAndLockTransactions } from './getSwapAndLockTransactions'; +import { transactionsHandler } from './transactionsHandler'; export const swapAndLockTokens = async ({ address, nonce, chainID, - callbackRoute -}: SendTransactionProps) => { - const transactions = getSwapAndLockTransactions({ + transactionsDisplayInfo = { + processingMessage: 'Processing transactions', + errorMessage: 'An error has occurred during transaction execution', + successMessage: 'Swap and lock transactions successful' + } +}: TransactionProps & { + transactionsDisplayInfo?: TransactionsDisplayInfoType; +}) => { + const provider = getAccountProvider(); + + const transactionsToSign = getSwapAndLockTransactions({ address, chainID, nonce }); + const transactions = await provider.signTransactions(transactionsToSign); + const groupedTransactions = [ [transactions[0]], [transactions[1], transactions[2]], [transactions[3]] ]; - await refreshAccount(); - - const { batchId, error } = await sendBatchTransactions({ + const { sentTransactions, sessionId } = await transactionsHandler({ transactions: groupedTransactions, - customTransactionInformation: { redirectAfterSign: true }, - transactionsDisplayInfo: { - processingMessage: 'Processing transactions', - errorMessage: 'An error has occurred during transaction execution', - successMessage: 'Batch transactions successful' - }, - callbackRoute, - hasConsentPopup: isSafari + options: { + transactionsDisplayInfo + } }); - if (error) { - console.error('Could not execute transactions', error); - return {}; - } - - sessionStorage.setItem(SessionEnum.batchId, batchId); - - return { batchId }; + return { sentTransactions, sessionId }; }; diff --git a/src/pages/Dashboard/widgets/BatchTransactions/helpers/transactionsHandler.ts b/src/pages/Dashboard/widgets/BatchTransactions/helpers/transactionsHandler.ts new file mode 100644 index 00000000..25f13638 --- /dev/null +++ b/src/pages/Dashboard/widgets/BatchTransactions/helpers/transactionsHandler.ts @@ -0,0 +1,24 @@ +import { + Transaction, + TransactionManager, + TransactionsDisplayInfoType +} from 'lib'; + +type TransactionsHandlerType = { + transactions: Transaction[] | Transaction[][]; + options?: { + disableToasts?: boolean; + transactionsDisplayInfo?: TransactionsDisplayInfoType; + }; +}; + +export const transactionsHandler = async ({ + transactions +}: TransactionsHandlerType) => { + const txManager = TransactionManager.getInstance(); + + const sentTransactions = await txManager.send(transactions); + const sessionId = await txManager.track(sentTransactions); + + return { sentTransactions, sessionId }; +}; diff --git a/src/pages/Dashboard/widgets/BatchTransactions/hooks/index.ts b/src/pages/Dashboard/widgets/BatchTransactions/hooks/index.ts deleted file mode 100644 index e60e6be1..00000000 --- a/src/pages/Dashboard/widgets/BatchTransactions/hooks/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './useSendSignedTransactions'; diff --git a/src/pages/Dashboard/widgets/BatchTransactions/hooks/useSendSignedTransactions.ts b/src/pages/Dashboard/widgets/BatchTransactions/hooks/useSendSignedTransactions.ts deleted file mode 100644 index 8e001544..00000000 --- a/src/pages/Dashboard/widgets/BatchTransactions/hooks/useSendSignedTransactions.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { useEffect, useState } from 'react'; -import { - deleteTransactionToast, - removeAllSignedTransactions, - removeAllTransactionsToSign, - setTransactionsDisplayInfoState, - setTransactionsToSignedState, - TransactionBatchStatusesEnum, - useGetSignedTransactions, - useSendBatchTransactions -} from 'lib'; -import { SessionEnum } from 'localConstants'; -import { useBatchTransactionContext } from 'wrappers'; - -export const useSendSignedTransactions = ({ - signedSessionId = '' -}: { - signedSessionId: string; -}) => { - const [batchSessionId, setBatchSessionId] = useState( - sessionStorage.getItem(SessionEnum.batchSessionId) - ); - const { signedTransactions } = useGetSignedTransactions(); - const { send: sendBatchToBlockchain, batchId } = useSendBatchTransactions(); - const { sendBatchTransactionsOnDemand } = useBatchTransactionContext(); - - const clearTransactionsInformation = () => { - removeAllSignedTransactions(); - removeAllTransactionsToSign(); - deleteTransactionToast(batchSessionId ?? ''); - sessionStorage.removeItem(SessionEnum.batchSessionId); - setBatchSessionId(null); - }; - - const sendTransactions = async () => { - if (!batchSessionId || !signedSessionId) { - return; - } - - const signedSession = signedTransactions?.[signedSessionId]; - const signedSessionTransactions = signedSession?.transactions; - - if (!signedSession || signedSessionTransactions?.length === 0) { - return; - } - - // Cancel flow - if (signedSession?.status !== TransactionBatchStatusesEnum.signed) { - clearTransactionsInformation(); - return; - } - - setTransactionsToSignedState({ - sessionId: batchSessionId, - status: TransactionBatchStatusesEnum.signed, - transactions: signedSessionTransactions - }); - - // In order to reuse the current flow for batch transactions in sdk-dapp we need to use this function - // in order to set the toast display info because the last signed sessionId is not used anymore - // but the new sessionId from the batchId is used - setTransactionsDisplayInfoState({ - sessionId: batchSessionId, - transactionsDisplayInfo: { - processingMessage: 'Processing transactions', - errorMessage: 'An error has occurred during transaction execution', - successMessage: 'Batch transactions successful' - } - }); - - const { error } = await sendBatchToBlockchain({ - transactions: [signedSessionTransactions], - sessionId: batchSessionId - }); - - setBatchSessionId(null); - sessionStorage.removeItem(SessionEnum.batchSessionId); - - if (error) { - clearTransactionsInformation(); - console.log('Failed to send batch', batchSessionId); - } - }; - - const status = signedTransactions[signedSessionId]?.status; - - useEffect(() => { - if (!sendBatchTransactionsOnDemand) { - return; - } - - if (!batchSessionId) { - return; - } - - if (status === TransactionBatchStatusesEnum.signed) { - sendTransactions(); - } - }, [batchSessionId, status]); - - return { - batchId, - setBatchSessionId - }; -}; diff --git a/src/pages/Dashboard/widgets/BatchTransactions/types.ts b/src/pages/Dashboard/widgets/BatchTransactions/types.ts deleted file mode 100644 index 0d3c5070..00000000 --- a/src/pages/Dashboard/widgets/BatchTransactions/types.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { TransactionProps } from 'types/transaction.types'; - -export type SendTransactionProps = TransactionProps & { - callbackRoute: string; -}; diff --git a/src/pages/Dashboard/widgets/PingPongAbi/PingPongAbi.tsx b/src/pages/Dashboard/widgets/PingPongAbi/PingPongAbi.tsx index 77cbae22..2ce6e3d2 100644 --- a/src/pages/Dashboard/widgets/PingPongAbi/PingPongAbi.tsx +++ b/src/pages/Dashboard/widgets/PingPongAbi/PingPongAbi.tsx @@ -12,26 +12,18 @@ import { import { getCountdownSeconds, setTimeRemaining } from 'helpers'; import { useSendPingPongTransaction } from 'hooks'; import { useGetPendingTransactions } from 'lib'; -import { SessionEnum } from 'localConstants'; -import { SignedTransactionType, WidgetProps } from 'types'; import { useGetPingAmount, useGetTimeToPong } from './hooks'; -export const PingPongAbi = ({ callbackRoute }: WidgetProps) => { - const { hasPendingTransactions } = useGetPendingTransactions(); +export const PingPongAbi = () => { + const transactions = useGetPendingTransactions(); + const hasPendingTransactions = transactions.length > 0; + const getTimeToPong = useGetTimeToPong(); - const { - sendPingTransactionFromAbi, - sendPongTransactionFromAbi, - transactionStatus - } = useSendPingPongTransaction({ - type: SessionEnum.abiPingPongSessionId - }); + const { sendPingTransactionFromAbi, sendPongTransactionFromAbi } = + useSendPingPongTransaction(); const pingAmount = useGetPingAmount(); - const [stateTransactions, setStateTransactions] = useState< - SignedTransactionType[] | null - >(null); - const [hasPing, setHasPing] = useState(true); + const [hasPing, setHasPing] = useState(true); const [secondsLeft, setSecondsLeft] = useState(0); const setSecondsRemaining = async () => { @@ -45,11 +37,11 @@ export const PingPongAbi = ({ callbackRoute }: WidgetProps) => { }; const onSendPingTransaction = async () => { - await sendPingTransactionFromAbi({ amount: pingAmount, callbackRoute }); + await sendPingTransactionFromAbi(pingAmount); }; const onSendPongTransaction = async () => { - await sendPongTransactionFromAbi({ callbackRoute }); + await sendPongTransactionFromAbi(); }; const timeRemaining = moment() @@ -63,12 +55,6 @@ export const PingPongAbi = ({ callbackRoute }: WidgetProps) => { getCountdownSeconds({ secondsLeft, setSecondsLeft }); }, [hasPing]); - useEffect(() => { - if (transactionStatus.transactions) { - setStateTransactions(transactionStatus.transactions); - } - }, [transactionStatus]); - useEffect(() => { setSecondsRemaining(); }, [hasPendingTransactions]); @@ -102,7 +88,7 @@ export const PingPongAbi = ({ callbackRoute }: WidgetProps) => { - {!stateTransactions && ( + {!hasPendingTransactions && ( <> {!pongAllowed && ( @@ -116,7 +102,7 @@ export const PingPongAbi = ({ callbackRoute }: WidgetProps) => { )} diff --git a/src/pages/Dashboard/widgets/PingPongAbi/hooks/useGetTimeToPong.ts b/src/pages/Dashboard/widgets/PingPongAbi/hooks/useGetTimeToPong.ts index 0bd57aa3..baef9e3b 100644 --- a/src/pages/Dashboard/widgets/PingPongAbi/hooks/useGetTimeToPong.ts +++ b/src/pages/Dashboard/widgets/PingPongAbi/hooks/useGetTimeToPong.ts @@ -29,14 +29,14 @@ export const useGetTimeToPong = () => { abi }); - const [result] = await scController.query({ + const result = await scController.query({ contract: Address.newFromBech32(contractAddress), function: 'getTimeToPong', arguments: [new AddressValue(new Address(address))] }); - const value = result?.valueOf(); - const secondsRemaining: number = Number(value); + const time = result.toString(); + const secondsRemaining = time ? Number(result.toString()) : null; return secondsRemaining; } catch (err) { diff --git a/src/pages/Dashboard/widgets/PingPongRaw/PingPongRaw.tsx b/src/pages/Dashboard/widgets/PingPongRaw/PingPongRaw.tsx index e2299102..f02b679f 100644 --- a/src/pages/Dashboard/widgets/PingPongRaw/PingPongRaw.tsx +++ b/src/pages/Dashboard/widgets/PingPongRaw/PingPongRaw.tsx @@ -12,26 +12,21 @@ import { import { getCountdownSeconds, setTimeRemaining } from 'helpers'; import { useSendPingPongTransaction } from 'hooks'; import { useGetPendingTransactions } from 'lib'; -import { SignedTransactionType } from 'lib'; -import { SessionEnum } from 'localConstants'; -import { WidgetProps } from 'types'; import { useGetPingAmount, useGetTimeToPong } from './hooks'; // Raw transaction are being done by directly requesting to API instead of calling the smartcontract -export const PingPongRaw = ({ callbackRoute }: WidgetProps) => { +export const PingPongRaw = () => { const getTimeToPong = useGetTimeToPong(); - const { hasPendingTransactions } = useGetPendingTransactions(); - const { sendPingTransaction, sendPongTransaction, transactionStatus } = - useSendPingPongTransaction({ - type: SessionEnum.rawPingPongSessionId - }); + + const { sendPingTransaction, sendPongTransaction } = + useSendPingPongTransaction(); + + const transactions = useGetPendingTransactions(); + const hasPendingTransactions = transactions.length > 0; const pingAmount = useGetPingAmount(); - const [stateTransactions, setStateTransactions] = useState< - SignedTransactionType[] | null - >(null); - const [hasPing, setHasPing] = useState(true); - const [secondsLeft, setSecondsLeft] = useState(0); + const [hasPing, setHasPing] = useState(true); + const [secondsLeft, setSecondsLeft] = useState(0); const setSecondsRemaining = async () => { const secondsRemaining = await getTimeToPong(); @@ -44,11 +39,11 @@ export const PingPongRaw = ({ callbackRoute }: WidgetProps) => { }; const onSendPingTransaction = async () => { - await sendPingTransaction({ amount: pingAmount, callbackRoute }); + await sendPingTransaction(pingAmount); }; const onSendPongTransaction = async () => { - await sendPongTransaction({ callbackRoute }); + await sendPongTransaction(); }; const timeRemaining = moment() @@ -62,12 +57,6 @@ export const PingPongRaw = ({ callbackRoute }: WidgetProps) => { getCountdownSeconds({ secondsLeft, setSecondsLeft }); }, [hasPing]); - useEffect(() => { - if (transactionStatus.transactions) { - setStateTransactions(transactionStatus.transactions); - } - }, [transactionStatus]); - useEffect(() => { setSecondsRemaining(); }, [hasPendingTransactions]); @@ -99,7 +88,7 @@ export const PingPongRaw = ({ callbackRoute }: WidgetProps) => { - {!stateTransactions && ( + {!hasPendingTransactions && ( <> {!pongAllowed && ( @@ -112,7 +101,7 @@ export const PingPongRaw = ({ callbackRoute }: WidgetProps) => { )} diff --git a/src/pages/Dashboard/widgets/PingPongRaw/hooks/tests/useGetTimeToPong.test.ts b/src/pages/Dashboard/widgets/PingPongRaw/hooks/tests/useGetTimeToPong.test.ts deleted file mode 100644 index 85ca219e..00000000 --- a/src/pages/Dashboard/widgets/PingPongRaw/hooks/tests/useGetTimeToPong.test.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { renderHook } from '@testing-library/react'; -import axios from 'axios'; -import { useGetTimeToPong } from '../useGetTimeToPong'; - -beforeEach(() => { - jest.mock('@multiversx/sdk-dapp/hooks/useGetNetworkConfig', () => ({ - useGetNetworkConfig: jest.fn().mockReturnValue({ - network: { apiAddress: 'https://devnet-api.multiversx.com' } - }) - })); -}); - -describe('useGetTimeToPong', () => { - it('should return 180 seconds', async () => { - jest.spyOn(axios, 'post').mockResolvedValueOnce({ - data: { - data: { - data: { - returnData: ['tA=='] // 180 converted from b64 to hexa and from hexa to decimal - } - } - } - }); - - const { result } = renderHook(() => useGetTimeToPong()); - const timeToPong = await result.current(); - // Assert the result is correct based on your mock data - expect(timeToPong).toBe(180); - }); - - it('should return 0', async () => { - jest.spyOn(axios, 'post').mockResolvedValueOnce({ - data: { - data: { - data: { - returnData: [''] - } - } - } - }); - - const { result } = renderHook(() => useGetTimeToPong()); - const timeToPong = await result.current(); - // Assert the result is correct based on your mock data - expect(timeToPong).toBe(0); - }); - - it('should return null', async () => { - jest.spyOn(axios, 'post').mockResolvedValueOnce({ - data: { - data: { - data: { - returnData: [] - } - } - } - }); - - const { result } = renderHook(() => useGetTimeToPong()); - const timeToPong = await result.current(); - // Assert the result is correct based on your mock data - expect(timeToPong).toBe(null); - }); -}); diff --git a/src/pages/Dashboard/widgets/PingPongService/PingPongService.tsx b/src/pages/Dashboard/widgets/PingPongService/PingPongService.tsx index 725c8193..11be404c 100644 --- a/src/pages/Dashboard/widgets/PingPongService/PingPongService.tsx +++ b/src/pages/Dashboard/widgets/PingPongService/PingPongService.tsx @@ -13,8 +13,6 @@ import { import { getCountdownSeconds, setTimeRemaining } from 'helpers'; import { useSendPingPongTransaction } from 'hooks'; import { useGetLoginInfo, useGetPendingTransactions } from 'lib'; -import { SessionEnum } from 'localConstants'; -import { SignedTransactionType, WidgetProps } from 'types'; import { useGetPingTransaction, useGetPongTransaction, @@ -22,24 +20,18 @@ import { } from './hooks'; // The transactions are being done by directly requesting to template-dapp service -export const PingPongService = ({ callbackRoute }: WidgetProps) => { - const [stateTransactions, setStateTransactions] = useState< - SignedTransactionType[] | null - >(null); - const [hasPing, setHasPing] = useState(true); +export const PingPongService = () => { + const [hasPing, setHasPing] = useState(true); const [secondsLeft, setSecondsLeft] = useState(0); - const { - sendPingTransactionFromService, - sendPongTransactionFromService, - transactionStatus - } = useSendPingPongTransaction({ - type: SessionEnum.abiPingPongServiceSessionId - }); + const { sendPingTransactionFromService, sendPongTransactionFromService } = + useSendPingPongTransaction(); const getTimeToPong = useGetTimeToPong(); const getPingTransaction = useGetPingTransaction(); const getPongTransaction = useGetPongTransaction(); - const { hasPendingTransactions } = useGetPendingTransactions(); + const transactions = useGetPendingTransactions(); + const hasPendingTransactions = transactions.length > 0; + const { tokenLogin } = useGetLoginInfo(); const setSecondsRemaining = async () => { @@ -63,10 +55,7 @@ export const PingPongService = ({ callbackRoute }: WidgetProps) => { return; } - await sendPingTransactionFromService({ - transactions: [pingTransaction], - callbackRoute - }); + await sendPingTransactionFromService([pingTransaction]); }; const onSendPongTransaction = async () => { @@ -76,10 +65,7 @@ export const PingPongService = ({ callbackRoute }: WidgetProps) => { return; } - await sendPongTransactionFromService({ - transactions: [pongTransaction], - callbackRoute - }); + await sendPongTransactionFromService([pongTransaction]); }; const timeRemaining = moment() @@ -93,12 +79,6 @@ export const PingPongService = ({ callbackRoute }: WidgetProps) => { getCountdownSeconds({ secondsLeft, setSecondsLeft }); }, [hasPing]); - useEffect(() => { - if (transactionStatus.transactions) { - setStateTransactions(transactionStatus.transactions); - } - }, [transactionStatus]); - useEffect(() => { setSecondsRemaining(); }, [hasPendingTransactions]); @@ -134,7 +114,7 @@ export const PingPongService = ({ callbackRoute }: WidgetProps) => { - {!stateTransactions && ( + {!hasPendingTransactions && ( <> {!pongAllowed && ( @@ -147,7 +127,7 @@ export const PingPongService = ({ callbackRoute }: WidgetProps) => { )} diff --git a/src/pages/Dashboard/widgets/PingPongService/hooks/useGetPingTransaction.ts b/src/pages/Dashboard/widgets/PingPongService/hooks/useGetPingTransaction.ts index 6e81994e..17c4bcd5 100644 --- a/src/pages/Dashboard/widgets/PingPongService/hooks/useGetPingTransaction.ts +++ b/src/pages/Dashboard/widgets/PingPongService/hooks/useGetPingTransaction.ts @@ -1,19 +1,26 @@ import axios from 'axios'; import { API_URL } from 'config'; -import { Transaction } from 'lib'; +import { Transaction, useGetLoginInfo } from 'lib'; export const useGetPingTransaction = () => { + const { tokenLogin } = useGetLoginInfo(); + return async () => { try { - const { data } = await axios.post( + const { data } = await axios.post( '/ping-pong/abi/ping', {}, { - baseURL: API_URL + baseURL: API_URL, + headers: { + Authorization: `Bearer ${tokenLogin?.nativeAuthToken}` + } } ); - return data; + const pingTransaction = Transaction.newFromPlainObject(data); + + return pingTransaction; } catch (err) { console.error('Unable to get Ping Transaction', err); return null; diff --git a/src/pages/Dashboard/widgets/PingPongService/hooks/useGetPongTransaction.ts b/src/pages/Dashboard/widgets/PingPongService/hooks/useGetPongTransaction.ts index ce4ce8d5..d7385474 100644 --- a/src/pages/Dashboard/widgets/PingPongService/hooks/useGetPongTransaction.ts +++ b/src/pages/Dashboard/widgets/PingPongService/hooks/useGetPongTransaction.ts @@ -1,19 +1,26 @@ import axios from 'axios'; import { API_URL } from 'config'; -import { Transaction } from 'lib'; +import { Transaction, useGetLoginInfo } from 'lib'; export const useGetPongTransaction = () => { + const { tokenLogin } = useGetLoginInfo(); + return async () => { try { - const { data } = await axios.post( + const { data } = await axios.post( '/ping-pong/abi/pong', {}, { - baseURL: API_URL + baseURL: API_URL, + headers: { + Authorization: `Bearer ${tokenLogin?.nativeAuthToken}` + } } ); - return data; + const pongTransaction = Transaction.newFromPlainObject(data); + + return pongTransaction; } catch (err) { console.error('Unable to get Pong Transaction', err); return null; diff --git a/src/pages/Dashboard/widgets/PingPongService/hooks/useGetTimeToPong.ts b/src/pages/Dashboard/widgets/PingPongService/hooks/useGetTimeToPong.ts index e6d46ab1..98ae0d96 100644 --- a/src/pages/Dashboard/widgets/PingPongService/hooks/useGetTimeToPong.ts +++ b/src/pages/Dashboard/widgets/PingPongService/hooks/useGetTimeToPong.ts @@ -1,14 +1,20 @@ import axios from 'axios'; import { API_URL } from 'config'; +import { useGetLoginInfo } from 'lib'; import { TimeToPongResponseType } from '../types'; export const useGetTimeToPong = () => { + const { tokenLogin } = useGetLoginInfo(); + const getTimeToPong = async () => { try { const { data } = await axios.get( '/ping-pong/abi/time-to-pong', { - baseURL: API_URL + baseURL: API_URL, + headers: { + Authorization: `Bearer ${tokenLogin?.nativeAuthToken}` + } } ); diff --git a/src/pages/Dashboard/widgets/SignMessage/SignMessage.tsx b/src/pages/Dashboard/widgets/SignMessage/SignMessage.tsx index ff2f8fa9..d8048220 100644 --- a/src/pages/Dashboard/widgets/SignMessage/SignMessage.tsx +++ b/src/pages/Dashboard/widgets/SignMessage/SignMessage.tsx @@ -4,96 +4,102 @@ import { faFileSignature } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { MouseEvent } from 'react'; -import { useState } from 'react'; +import { MouseEvent, useState } from 'react'; import { Button, OutputContainer } from 'components'; -import { - SignedMessageStatusesEnum, - useGetSignMessageSession, - useSignMessage -} from 'lib'; -import { WidgetProps } from 'types'; +import { Address, getAccountProvider, Message, useGetAccount } from 'lib'; import { SignFailure, SignSuccess } from './components'; -export const SignMessage = ({ callbackRoute }: WidgetProps) => { - const { sessionId, signMessage, onAbort } = useSignMessage(); - const messageSession = useGetSignMessageSession(sessionId); - +export const SignMessage = () => { const [message, setMessage] = useState(''); + const [signedMessage, setSignedMessage] = useState(null); + const [state, setState] = useState<'pending' | 'success' | 'error'>( + 'pending' + ); - const handleSubmit = (e: MouseEvent) => { - e.preventDefault(); + const [signatrue, setSignatrue] = useState(''); + const { address } = useGetAccount(); + const provider = getAccountProvider(); - if (messageSession) { - onAbort(); - } + const handleSubmit = async () => { + try { + const messageToSign = new Message({ + address: new Address(address), + data: new Uint8Array(Buffer.from(message)) + }); - if (!message.trim()) { - return; - } + const signedMessageResult = await provider.signMessage(messageToSign); - signMessage({ - message, - callbackRoute - }); + if (!signedMessageResult?.signature) { + setState('error'); + return; + } - setMessage(''); + setState('success'); + setSignatrue(Buffer.from(signedMessageResult?.signature).toString('hex')); + setSignedMessage(signedMessageResult); + setMessage(''); + } catch (error) { + console.error(error); + setState('error'); + } }; const handleClear = (e: MouseEvent) => { e.preventDefault(); e.stopPropagation(); - onAbort(); + setSignatrue(''); + setState('pending'); }; - const isError = messageSession - ? [ - (SignedMessageStatusesEnum.cancelled, SignedMessageStatusesEnum.failed) - ].includes(messageSession.status) && messageSession?.message - : false; - - const isSuccess = - messageSession?.message && - messageSession?.status === SignedMessageStatusesEnum.signed; - return (
- - - {(isSuccess || isError) && ( + {['success', 'error'].includes(state) ? ( + ) : ( + )}
- {!isSuccess && !isError && ( + {!['success', 'error'].includes(state) && (