diff --git a/docs/sdk-and-tools/sdk-dapp/sdk-dapp.md b/docs/sdk-and-tools/sdk-dapp/sdk-dapp.md
index 37a60a4be..31e5f3c70 100644
--- a/docs/sdk-and-tools/sdk-dapp/sdk-dapp.md
+++ b/docs/sdk-and-tools/sdk-dapp/sdk-dapp.md
@@ -6,16 +6,23 @@ title: sdk-dapp
Library used to build React dApps on MultiversX Network.
:::important
-The following documentation is for `sdk-dapp v2.0.0` and above.
+The following documentation is for `sdk-dapp v5.0.0` and above.
:::
[comment]: # (mx-abstract)
## Introduction
-**sdk-dapp** is a library that holds core functional logic that can be used to create a **dApp** on MultiversX Network.
+`sdk-dapp` is a library that holds core functional logic that can be used to create a dApp on MultiversX Network.
-It is built for applications that use **React**.
+It is built for applications that use any of the following technologies:
+
+- React (example: [React Template Dapp](https://github.com/multiversx/mx-template-dapp))
+- Angular (example: [Angular Template Dapp](https://github.com/multiversx/mx-template-dapp-angular))
+- Vue (example: [Vue Template Dapp](https://github.com/multiversx/mx-template-dapp-vue))
+- Any other JavaScript framework (e.g. Solid.js etc.) (example: [Solid.js Dapp](https://github.com/multiversx/mx-solidjs-template-dapp))
+- React Native
+- Next.js (example: [Next.js Dapp](https://github.com/multiversx/mx-template-dapp-nextjs))
[comment]: # (mx-context-auto)
@@ -25,30 +32,22 @@ The GitHub repository can be found here: [https://github.com/multiversx/mx-sdk-d
[comment]: # (mx-context-auto)
-### npmjs
-
-sdk-dapp can be found on npmjs as well: https://www.npmjs.com/package/@multiversx/sdk-dapp
-
-[comment]: # (mx-context-auto)
-
### Live demo: template-dapp
-The [mx-template-dapp](https://github.com/multiversx/mx-template-dapp) that is used in [Build a dApp in 15 minutes](/developers/tutorials/your-first-dapp) is based on `sdk-dapp`.
-
-A live demo of the template-dapp is available at [https://template-dapp.multiversx.com/](https://template-dapp.multiversx.com/).
+See [Template dApp](https://template-dapp.multiversx.com/) for live demo or checkout usage in the [Github repo](https://github.com/multiversx/mx-template-dapp)
[comment]: # (mx-context-auto)
### Requirements
-- Node.js version 12.16.2+
-- Npm version 6.14.4+
+- Node.js version 20.13.1+
+- Npm version 10.5.2+
[comment]: # (mx-context-auto)
-## Migration from sdk-dapp 1.x
+### Distribution
-If you're transitioning from sdk-dapp 1.x to sdk-dapp 2.0, please read the [Migration guide](https://github.com/multiversx/mx-sdk-dapp/wiki/Migration-guide-2.0).
+[npm](https://www.npmjs.com/package/@multiversx/sdk-dapp)
[comment]: # (mx-context-auto)
@@ -66,1019 +65,758 @@ or
yarn add @multiversx/sdk-dapp
```
-If you need only the sdk-dapp basic logic, without the additional UI, consider using the `--no-optional` flag.
-This will not install the packages needed for the optional UI components.
-
-```bash
-npm install @multiversx/sdk-dapp --no-optional
-```
-
-or
+> **Note:** Make sure you run your app on `https`, not `http`, otherwise some providers will not work.
-```bash
-yarn add @multiversx/sdk-dapp --no-optional
-```
+If you're transitioning from `@multiversx/sdk-dapp@4.x`, you can check out the [Migration guide](https://github.com/multiversx/mx-template-dapp/blob/main/MIGRATION_GUIDE.md) and [migration PR](https://github.com/multiversx/mx-template-dapp/pull/343) of Template Dapp
[comment]: # (mx-context-auto)
## Usage
-sdk-dapp aims to abstract and simplify the process of interacting with users' wallets and with the MultiversX Network, allowing developers to easily get started with a new application or integrate sdk-dapp into an existing application.
-
-This library covers two main areas: **User Identity** and **Transactions**. The API for interacting with library's logic is exposed via hooks and methods that can be called for logging in the user, getting the status of the user or sending transactions.
+sdk-dapp aims to abstract and simplify the process of interacting with users' wallets and with the MultiversX blockchain, allowing developers to easily get started with new applications.
-However, to simplify usage even further, the library also comes with a default UI that already uses these hooks and methods under the hood. These UI elements can be easily customized with custom css classes.
-
-```jsx
-import * as DappUI from "@multiversx/sdk-dapp/UI";
+```mermaid
+flowchart LR
+ A["Signing Providers & APIs"] <--> B["sdk-dapp"] <--> C["dApp"]
```
-**Please be aware that this style of importing might also import unused code.**
-To reduce the amount of dead code, you can use named imports for each component like
-
-```jsx
-import { UnlockPage } from "@multiversx/sdk-dapp/UI/pages";
-// or
-import { UnlockPage } from "@multiversx/sdk-dapp/UI/pages/UnlockPage";
-```
+The basic concepts you need to understand are configuration, provider interaction, transactions, and presenting data. These are the building blocks of any dApp, and they are abstracted in the `sdk-dapp` library.
-More on this below.
+Having this knowledge, we can consider several steps needed to put a dApp together:
-[comment]: # (mx-context-auto)
+**Table 1.** Steps to build a dApp
-### Prerequisites
+| # | Step | Description |
+|----|---------------------|-------------|
+| 1 | Configuration | storage configuration (e.g. sessionStorage, localStorage etc.); chain configuration; custom provider configuration (adding / disabling / changing providers) |
+| 2 | Provider interaction| logging in and out; signing transactions / messages |
+| 3 | Presenting data | get store data (e.g. account balance, account address etc.); use components to display data (e.g. balance, address, transactions list) |
+| 4 | Transactions | sending transactions; tracking transactions; displaying transactions history |
-There are a couple of requirements that need to be met for the application to work properly.
+Each of these steps will be explained in more detail in the following sections.
-
-
- React
-
+[comment]: # (mx-context-auto)
-**React**
+### 1. Configuration
-This library was built for applications that use React, it might not be suitable for usage with other libraries or frameworks.
+Before your application bootstraps, you need to configure the storage, the network, and the signing providers. This is done by calling the `initApp` method from the `methods` folder. It is recommended to call this method in the `index.tsx` to ensure the sdk-dapp internal functions are initialized before rendering the app.
-
+```typescript
+// index.tsx
+import { initApp } from '@multiversx/sdk-dapp/out/methods/initApp/initApp';
+import type { InitAppType } from '@multiversx/sdk-dapp/out/methods/initApp/initApp.types';
+import { EnvironmentsEnum } from '@multiversx/sdk-dapp/out/types/enums.types';
+import { App } from "./App";
+
+const config: InitAppType = {
+ storage: { getStorageCallback: () => sessionStorage },
+ dAppConfig: {
+ // nativeAuth: true, // optional
+ environment: EnvironmentsEnum.devnet,
+ // network: { // optional
+ // walletAddress: 'https://devnet-wallet.multiversx.com' // or other props you want to override
+ // },
+ // transactionTracking: { // optional
+ // successfulToastLifetime: 5000,
+ // onSuccess: async (sessionId) => {
+ // console.log('Transaction session successful', sessionId);
+ // },
+ // onFail: async (sessionId) => {
+ // console.log('Transaction session failed', sessionId);
+ // }
+ }
+ // customProviders: [myCustomProvider] // optional
+};
-
-
- DappProvider
-
+initApp(config).then(() => {
+ render(() => , root!); // render your app
+});
+```
-**DappProvider**
+[comment]: # (mx-context-auto)
-You need to wrap your application with the **DappProvider** component, which is exported by the library, as we need to create a global Context to be able to manipulate the data.
+### 2. Provider interaction
-- import the Provider:
+Once your dApp has loaded, the first user action is logging in with a chosen provider. There are two ways to perform a login, namely using the `UnlockPanelManager` and programmatic login using the `ProviderFactory`.
-```jsx
-import { DappProvider } from "@multiversx/sdk-dapp/wrappers/DappProvider";
-//or;
-import { DappProvider } from "@multiversx/sdk-dapp/wrappers";
-```
+#### 2.1 Using the `UnlockPanelManager`
+By using the provided UI, you get the benefit of having all supported providers ready for login in a side panel. You simply need to link the `unlockPanelManager.openUnlockPanel` to a user action.
-- Wrap your application with this Provider.
+```typescript
+import { UnlockPanelManager } from '@multiversx/sdk-dapp/out/managers/UnlockPanelManager';
+import { ProviderFactory } from '@multiversx/sdk-dapp/out/providers/ProviderFactory';
+
+export const ConnectButton = () => {
+ const unlockPanelManager = UnlockPanelManager.init({
+ loginHandler: () => {
+ navigate('/dashboard');
+ },
+ onClose: () => { // optional action to be performed when the user closes the Unlock Panel
+ navigate('/');
+ },
+ // allowedProviders: [ProviderTypeEnum.walletConnect, 'myCustomProvider'] // optionally, only show specific providers
+ });
+ const handleOpenUnlockPanel = () => {
+ unlockPanelManager.openUnlockPanel();
+ };
+ return ;
+};
-```jsx
-
```
-
-`environment` is a required key that is needed to configure the app's endpoints for a specific environment. Accepted values are `testnet`, `devnet` and `mainnet` (also configured in `EnvironmentsEnum`).
-
-DappProvider also accepts an optional `customNetworkConfig` object with a couple of keys.
-This allows using different APIs and different connection providers to configure your network configuration.
-
-**All keys are optional**
+Once the user has logged in, if `nativeAuth` is configured in the `initApp` method, an automatic logout will be performed upon native auth expiration. Before the actual logout is performed, the `LogoutManager` will show a warning toast to the user. This toast can be customized by passing a `tokenExpirationToastWarningSeconds` to the `nativeAuth` config.
```typescript
-{
- id?: string;
- name?: string;
- egldLabel?: string;
- decimals?: string;
- digits?: string;
- gasPerDataByte?: string;
- walletConnectDeepLink?: string; // a string that will create a deeplink for an application that is used on a mobile phone, instead of generating the login QR code.
- walletConnectV2ProjectId?: string; // a unique ProjectID needed to access the WalletConnect 2.0 Relay Cloud
- walletAddress?: string;
- apiAddress?: string;
- explorerAddress?: string;
- apiTimeout?: 4000;
+// in initAoo config
+const config: InitAppType = {
+ // ...
+ nativeAuth: {
+ expirySeconds: 30, // test auto logout after 30 seconds
+ tokenExpirationToastWarningSeconds: 10 // show warning toast 10 seconds before auto logout
+ },
}
```
-
-
-
-
- UI Wrappers
-
-
-**UI Wrappers**
-
-The library exposes a couple of Components that are connected to the redux store and are used to display various elements
-when something happens inside the app:
-
-- `TransactionsToastList` will display new transactions in nice toasts at the bottom of the screen. This component is fully customizable.
+You have the option to stop this behavior by calling `LogoutManager.getInstance().stop()` after the user has logged in.
-```jsx
- import {TransactionsToastList} from "@multiversx/sdk-dapp/UI/TransactionsToastList";
+```typescript
+import { LogoutManager } from '@multiversx/sdk-dapp/out/managers/LogoutManager/LogoutManager';
- // all properties are optional
-
+ loginHandler: () => {
+ navigate('/dashboard');
+ // optional, to stop the automatic logout upon native auth expiration
+ LogoutManager.getInstance().stop();
+ },
```
-- `SignTransactionsModals` will show a modal when a new transaction is submitted, prompting the user to verify and sign it.
-
-**Important! This is required** to make transactions work, except when you use hooks to sign the transactions manually (more on this below).
+If you want to perform some actions as soon as the user has logged in, you will need to call `ProviderFactory.create` inside a handler accepting arguments.
-```jsx
-import { SignTransactionsModals } from "@multiversx/sdk-dapp/UI/SignTransactionsModals";
+```typescript
+export const AdvancedConnectButton = () => {
+ const unlockPanelManager = UnlockPanelManager.init({
+ loginHandler: async ({ type, anchor }) => {
+ const provider = await ProviderFactory.create({
+ type,
+ anchor
+ });
+ const { address, signature } = await provider.login();
+ navigate(`/dashboard?address=${address}`;
+ },
+ });
+ const handleOpenUnlockPanel = () => {
+ unlockPanelManager.openUnlockPanel();
+ };
+ return ;
+};
-
-
-
-;
```
-`NotificationModal` Will show a modal to the user with various warnings and errors.
+#### 2.2 Programmatic login using the `ProviderFactory`
+If you want to login using your custom UI, you can link user actions to specific providers by calling the `ProviderFactory`.
-```jsx
-import { NotificationModal } from "@multiversx/sdk-dapp/UI/NotificationModal";
+```typescript
+import { ProviderTypeEnum } from '@multiversx/sdk-dapp/out/providers/types/providerFactory.types';
-
-
-
-;
+const provider = await ProviderFactory.create({
+ type: ProviderTypeEnum.extension
+});
+await provider.login();
```
-If you want to show custom notifications, you can use the `useGetNotification` hook to get the notifications (like insufficient funds, errors etc).
-
-
+> **Note:** Extension and Ledger login will only work if dApp is served over HTTPS protocol
[comment]: # (mx-context-auto)
-## User Identity
+### 3. Displaying app data
-sdk-dapp makes logging in and persisting user's session easy and hassle-free.
+Depending on the framework, you can either use hooks or selectors to get the user details:
-A handy component is AuthenticatedRoutesWrapper, which can be used to protect certain routes and redirect the user to login page if the user is not authenticated.
+#### 3.1 React hooks
-Import from sdk-dapp:
+If you are using React, all hooks can be found under the `/out/react` folder. All store information can be accessed via different hooks but below you will find the main hook related to most common use cases
-```jsx
-import { AuthenticatedRoutesWrapper } from "@multiversx/sdk-dapp/wrappers/AuthenticatedRoutesWrapper";
-// or
-import { AuthenticatedRoutesWrapper } from "@multiversx/sdk-dapp/wrappers";
+```bash
+out/react/
+├── account/useGetAccount ### access account data like address, balance and nonce
+├── loginInfo/useGetLoginInfo ### access login data like accessToken and provider type
+├── network/useGetNetworkConfig ### access network information like chainId and egldLabel
+├── store/useSelector ### make use of the useSelector hook for querying the store via selectors
+└── transactions/useGetTransactionSessions ### access all current and historic transaction sessions
```
-Use with routes:
+Below is an example of using the hooks to display the user address and balance.
-```jsx
-
- {appContent}
-
-```
+```typescript
+import { useGetAccount } from '@multiversx/sdk-dapp/out/react/account/useGetAccount';
+import { useGetNetworkConfig } from '@multiversx/sdk-dapp/out/react/network/useGetNetworkConfig';
-**routes** should be an array with objects with a signature similar to this:
+const account = useGetAccount();
+const {
+ network: { egldLabel }
+} = useGetNetworkConfig();
-```typescript
-{
- path: "/dashboard",
- title: "Dashboard",
- component: Dashboard,
- authenticatedRoute: true,
-}
+console.log(account.address);
+console.log(`${account.balance} ${egldLabel}`);
```
-The important parts that makes this component work are the flag **authenticatedRoute: true** and the key **path**, which means that this route should be accessible only to authenticated users.
+#### 3.2 Store selector functions:
-
-
- Login UI
-
+If you are not using the React ecosystem, you can use store selectors to get the store data, but note that information will not be reactive unless you subscribe to store changes.
-[comment]: # (mx-context)
+```typescript
+import { getAccount } from '@multiversx/sdk-dapp/out/methods/account/getAccount';
+import { getNetworkConfig } from '@multiversx/sdk-dapp/out/methods/network/getNetworkConfig';
-**Login UI**
+const account = getAccount();
+const { egldLabel } = getNetworkConfig();
+```
-There are a couple of very handy React components that can be used to login the user and protect certain routes if the user is not logged in.
+In order to get live updates you may need to subscribe to the store like this:
-Under the `DappUI` object mentioned above, you can find 4 buttons (one for each provider) which abstract away all the logic of logging in the user and render the default UI. These buttons can be easily customized with a custom css class.
-The exported buttons are:
+```typescript
+import { createSignal, onCleanup } from 'solid-js';
+import { getStore } from '@multiversx/sdk-dapp/out/store/store';
-- ExtensionLoginButton
-- WalletConnectLoginButton
-- LedgerLoginButton
-- WebWalletLoginButton
+export function useStore() {
+ const store = getStore();
+ const [state, setState] = createSignal(store.getState());
-example:
+ const unsubscribe = store.subscribe((newState) => {
+ setState(newState);
+ });
-```jsx
-
-```
+ onCleanup(() => unsubscribe());
-They can also be used with children
-
-```jsx
-
- <>
-
-
Login text
- <>
-
+ return state;
+}
```
-`WalletConnectLoginButton` and `LedgerLoginButton` will trigger a modal with a QR code and the ledger login UI, respectively.
-These are automatically triggered by the buttons.
-
-If, however, you want access to these containers without the buttons,
-you can easily import and use them.
-
-```jsx
-
-```
+[comment]: # (mx-context-auto)
-```jsx
-
-```
+### 4. Transactions
-All login buttons and hooks accept a prop called `redirectAfterLogin` which specifies of the user should be redirected automatically after login.
-The default value for this boolean is false, since most apps listen for the "isLoggedIn" boolean and redirect programmatically.
+#### 4.1 Signing transactions
-Another handly component is AuthenticatedRoutesWrapper, which can be used to protect certain routes and redirect the user to login page if the user is not authenticated.
+To sign transactions, you first need to create the `Transaction` object, then pass it to the initialized provider.
-Import from sdk-dapp:
+```typescript
+import { Address, Transaction } from '@multiversx/sdk-core';
+import {
+ GAS_PRICE,
+ GAS_LIMIT
+} from '@multiversx/sdk-dapp/out/constants/mvx.constants';
+import { getAccountProvider } from '@multiversx/sdk-dapp/out/providers/helpers/accountProvider';
+import { refreshAccount } from '@multiversx/sdk-dapp/out/utils/account/refreshAccount';
+
+const pongTransaction = new Transaction({
+ value: BigInt(0),
+ data: Buffer.from('pong'),
+ receiver: Address.newFromBech32(contractAddress),
+ gasLimit: BigInt(GAS_LIMIT),
+ gasPrice: BigInt(GAS_PRICE),
+ chainID: network.chainId,
+ nonce: BigInt(account.nonce),
+ sender: Address.newFromBech32(account.address),
+ version: 1
+});
-```jsx
-import { AuthenticatedRoutesWrapper } from "@multiversx/sdk-dapp/wrappers/AuthenticatedRoutesWrapper";
+await refreshAccount(); // optionally, to get the latest nonce
+const provider = getAccountProvider();
+const signedTransactions = await provider.signTransactions(transactions);
```
-Use with routes:
+#### 4.2 Sending and tracking transactions
-```jsx
-
- {appContent}
-
-```
+Then, to send the transactions, you need to use the `TransactionManager` class and pass in the `signedTransactions` to the `send` method. You can then track the transactions by using the `track` method. This will create a toast notification with the transaction hash and its status.
-**routes** should be an array with objects with a signature similar to this:
+> **Note:** You can set callbacks for the transaction manager to handle the session status, by using the `setCallbacks` method on the `TransactionManager` class. This can also be configured globally in the `initApp` method.
```typescript
-{
- path: "/dashboard",
- title: "Dashboard",
- component: Dashboard,
- authenticatedRoute: true,
-}
-```
+import { TransactionManager } from '@multiversx/sdk-dapp/out/managers/TransactionManager';
+import type { TransactionsDisplayInfoType } from '@multiversx/sdk-dapp/out/types/transactions.types';
-The important parts that makes this component work are the flag **authenticatedRoute: true** and the key **path**, which means that this route should be accessible only to authenticated users.
-
+const txManager = TransactionManager.getInstance();
-
-Login hooks
-
-
-[comment]: # (mx-context-auto)
+const sentTransactions = await txManager.send(signedTransactions);
-### Login hooks
-
-This area covers the login hooks, which expose a trigger function and the login data, ready to be rendered.
-
-These hooks are exposed as named exports, which can be imported from sdk-dapp:
+const toastInformation: TransactionsDisplayInfoType = {
+ processingMessage: 'Processing transactions',
+ errorMessage: 'An error has occurred during transaction execution',
+ successMessage: 'Transactions executed'
+}
-```jsx
-import { useExtensionLogin, useWalletConnectLogin, useLedgerLogin, useWebWalletLogin } from '@multiversx/sdk-dapp/hooks';
-// or
-import { useExtensionLogin } from '@multiversx/sdk-dapp/hooks/login/useExtensionLogin';
-import { useWalletConnectLogin } from '@multiversx/sdk-dapp/hooks/login/useWebWalletLogin';
-import { useLedgerLogin } from '@multiversx/sdk-dapp/hooks/login/useLedgerLogin';
-import { useWebWalletLogin } from '@multiversx/sdk-dapp/hooks/login/useWebWalletLogin';`
+const sessionId = await txManager.track(sentTransactions, {
+ transactionsDisplayInfo: toastInformation,
+});
```
-There are 4 available hooks:
-
-- useExtensionLogin
-- useWalletConnectLogin
-- useLedgerLogin
-- useWebWalletLogin
-
-All hooks have the same response signature:
-
-return type is as follows:
-
-```jsx
-const [initiateLogin, genericLoginReturnType, customLoginReturnType] =
- useLoginHook({
- callbackRoute,
- logoutRoute,
- onLoginRedirect,
- });
-```
+#### 4.3 Using the Notifications Feed
-- **initiateLogin** is a function that needs to be called for the login flow to be initiated;
-- **genericLoginReturnType** is an object that is exactly the same for all hooks:
+The Notifications Feed is a component that displays **session transactions** in a list. Internally it gets initialized in the `initApp` method. It can be accessed via the `NotificationManager.getInstance()` method.
+Once the user logs out of the dApp, all transactions displayed by the Notifications Feed are removed from the store. Note that you can switch between toast notifications and Notifications Feed by pressing the View All button above the current pending transaction toast in the UI.
```typescript
-{
- error: string,
- loginFailed: boolean,
- isLoading: boolean,
- isLoggedIn: boolean
-}
+const notificationManager = NotificationManager.getInstance();
+await notificationManager.openNotificationsFeed();
```
-- **customLoginReturnType** is an object that is custom for each hook and returns specific data for that login:
-
- - null for useExtensionLogin;
+#### 4.4 Inspecting transactions
- - null for useWebWalletConnect;
+You can find both methods and hooks to access transactions data, as seen in the table below.
- - `{ uriDeepLink: string, qrCodeSvg: svgElement }` for useWalletConnectLogin;
+**Table 2**. Inspectig transactions
+| # | Helper | Description | React hook equivalent |
+|---|------|-------------|----|
+| | `methods/transactions` | path | `react/transactions` |
+| 1 | `getTransactionSessions()` | returns all trabsaction sessions |`useGetTransactionSessions()` |
+| 2 | `getPendingTransactionsSessions()` | returns an record of pending sessions | `useGetPendingTransactionsSessions()`|
+| 3 | `getPendingTransactions()` | returns an array of signed transactions | `useGetPendingTransactions()` |
+| 4 | `getFailedTransactionsSessions()` | returns an record of failed sessions | `useGetFailedTransactionsSessions()`|
+| 5 | `getFailedTransactions()` | returns an array of failed transactions | `useGetFailedTransactions()`|
+| 6 | `getSuccessfulTransactionsSessions()` | returns an record of successful sessions | `useGetSuccessfulTransactionsSessions()`|
+| 7 | `getSuccessfulTransactions()` | returns an array of successful transactions | `useGetSuccessfulTransactions()`|
- -
+There is a way to inspect store information regarding a specific transaction, using the `transactionsSliceSelector`. An example is shown below:
```typescript
-{
- accounts: string[];
- showAddressList: boolean;
- startIndex: number;
- selectedAddress: SelectedAddress | null;
- onGoToPrevPage: () => void;
- onGoToNextPage: () => void;
- onSelectAddress: (address: SelectedAddress | null) => void;
- onConfirmSelectedAddress: () => void;
-}
-```
-
-for useLedgerLogin;
-
-
-
-
-
-Reading User State
-
-
-[comment]: # (mx-context-auto)
-
-### Reading User State
-
-Once logged in, the user's session is persisted and can be read and deleted via a couple of handy functions.
-
-For logging out, the library exposes a simple function called **logout**, which can be called to clear the user data.
-
-the function accepts 2 arguments:
-
-- `callbackUrl: string (optional)` the url to redirect the user to after logging him out
-- `onRedirect: (callbackUrl: string) => void (optional)` a function that will be called instead of redirecting the user.
- This allows you to control how the redirect is done, for example, with react-router-dom, instead of window.location.href assignment.
- _Important_ this function will not be called for web wallet logout
+import {
+ pendingTransactionsSessionsSelector,
+ transactionsSliceSelector
+} from '@multiversx/sdk-dapp/out/store/selectors/transactionsSelector';
+import { getStore } from '@multiversx/sdk-dapp/out/store/store';
-You can opt-in for using the `useIdleTimer` hook, which logs out the user after a period of inactivity (default set to 10 minutes). Optionally it accepts an `onLogout` function that fulfills your dapp's specific logout business logic. Make sure to call the above `logout` function inside this `onLogout` callback.
+const store = getStore(); // or use useStore hook for reactivity
+const pendingSessions = pendingTransactionsSessionsSelector(store.getState());
+const allTransactionSessions = transactionsSliceSelector(store.getState());
-There are 2 ways of reading the user current state: hooks (to be used inside components and for reacting to changes in the data) and simple functions (for reading data outside of React components or inside handlers).
+const isSessionIdPending =
+ Object.keys(pendingSessions).includes(sessionId);
+const currentSession = allTransactionSessions[sessionId];
+const currentSessionStatus = currentSession?.status;
+const currentTransaction = currentSession?.transactions?.[0];
+const currentTransactionStatus = currentTransaction?.status;
+```
-- hooks: `useGetLoginInfo, useGetAccountInfo, useGetNetworkConfig`;
-- functions: `getAccount, getAccountBalance, getAccountShard, getAddress, getIsLoggedIn;`
+#### 4.5 Logging out
+The user journey ends with calling the `provider.logout()` method.
-
+```typescript
+import { getAccountProvider } from '@multiversx/sdk-dapp/out/providers/helpers/accountProvider';
+const provider = getAccountProvider();
+await provider.logout();
+```
[comment]: # (mx-context-auto)
-## Transactions
+## Internal structure
-The sdk-dapp library exposes a straight-forward way of sending transactions and tracking their status, with a couple of handy UI components;
+We have seen in the previous chapter what are the minimal steps to get up and running with a blockchain interaction using sdk-dapp. Next we will detail each element mentioned above
-
-Sending Transactions
-
+**Table 3**. Elements needed to build a dApp
+| # | Type | Description |
+|---|------|-------------|
+| 1 | Network | Chain configuration |
+| 2 | Provider | The signing provider for logging in and singing transactions |
+| 3 | Account | Inspecting user address and balance |
+| 4 | Transactions Manager | Sending and tracking transactions |
+| 5 | UI Components | Displaying UI information like balance, public keys etc. |
-[comment]: # (mx-context-auto)
-
-### Sending Transactions
+Since these are mixtures of business logic and UI components, the library is split into several folders to make it easier to navigate.
+When inspecting the package, there is more content under `src`, but the folders of interest are:
-The API for sending transactions is a function called **sendTransactions**:
-```jsx
-import { sendTransactions } from "@multiversx/sdk-dapp";
-```
-
-It can be used to send a transaction with minimum information:
-
-```jsx
-const { sessionId, error } = await sendTransactions({
- transactions: [
- {
- value: '1000000000000000000',
- data: 'ping',
- receiver: contractAddress
- },
- ],
- callbackRoute?: string // (optional, defaults to window.location.pathname) the route to be redirected to after signing. Will not redirect if the user is already on the specified route;
- transactionsDisplayInfo: TransactionsDisplayInfoType // (optional, default to null) custom message for toasts texts;
- minGasLimit?: number (optional, defaults to 50_000);
- sessionInformation?: any (optional, defaults to null) extra sessionInformation that will be passed back to you via getSignedTransactions hook;
- signWithoutSending?: boolean // (optional, defaults to false), the transaction will be signed without being sent to the blockchain;
- completedTransactionsDelay?: number // delay the transaction status from going into "successful" state;
- redirectAfterSigning?: boolean // (optional, defaults to true), whether to redirect to the provided callbackRoute;
-});
+```bash
+src/
+├── apiCalls/ ### methods for interacting with the API
+├── constants/ ### useful constants from the ecosystem like ledger error codes, default gas limits for transactions etc.
+├── controllers/ ### business logic for UI elements that are not bound to the store
+├── managers/ ### business logic for UI elements that are bound to the store
+├── providers/ ### signing providers
+├── methods/ ### utility functions to query and update the store
+├── react/ ### react hooks to query the store
+└── store/ ### store initialization, middleware, slices, selectors and actions
```
-It returns a Promise that will be fulfilled with `{error?: string; sessionId: string | null;}`
-
-`sessionId` is the transaction's batch id which can be used to track a transaction's status and react to it.
+Conceptually, these can be split into 3 main parts:
-**Important! For the transaction to be signed, you will have to use either `SignTransactionsModals` defined above, in the `Prerequisites` section,
-or the `useSignTransactions` hook defined below. If you don't use one of these, the transactions won't be signed**
+- First is the business logic in `apiCalls`, `constants`, `providers` and `methods`
+- Then comes the persistence layer hosted in the `store` folder, using [Zustand](https://zustand.docs.pmnd.rs/) under the hood.
+- Last are the UI components hosted in [@multiversx/sdk-dapp-ui](https://github.com/multiversx/mx-sdk-dapp-ui) with some components controlled on demand by classes defined in `controlles` and `managers`
-
-
-
-Transaction Signing Flow
-
+Next, we will take the elements from Table 3 and detail them in the following sections.
[comment]: # (mx-context-auto)
-### Transaction Signing Flow
+### 1. Network
-Once a transaction has been submitted, you have to use either the `SignTransactionsModals` or the `useSignTransactions` hook,
-for the user to be prompted in his provider (Web Wallet, MultiversX Defi Wallet Extension, xPortal, Ledger etc) to sign the transaction.
+The network configuration is done in the `initApp` method, where you can make several configurations like:
-If you don't want to use the default modals that appear for the user when the signing process happens,
-you have to use the `useSignTransactions` hook to sign those transactions.
+- specifying the environment (`devnet`, `testnet`, `mainnet`)
+- overriding certain network parameters like wallet address, explorer address etc.
-```jsx
-const {
- callbackRoute,
- transactions,
- error,
- sessionId,
- onAbort,
- hasTransactions,
- canceledTransactionsMessage,
-} = useSignTransactions();
-```
+Once the network is configured, the `network` slice in the store will hold the network configuration.
-This hook will let you know if there are any transactions and you can programmatically abort the signing process.
+To query different network parameters, you can use the `getNetworkConfig` method from the `methods/network` folder.
-We suggest displaying a message on the screen that confirms the transaction that needs to be signed.
-
-You can also get the provider via
-
-```jsx
-const { providerType, provider } = useGetAccountProvider();
-```
-
-and use that to display an appropriate message to the user.
+[comment]: # (mx-context-auto)
-For ledger, signing a transaction is simple if you're using the `SignTransactionsModal` component.
+### 2. Provider
-It is fully customizable and will take care of walking the user through the signing flow.
+The provider is the main class that handles the signing of transactions and messages. It is initialized in the `initApp` method and can be accessed via the `getAccountProvider` method from the `providers/helpers` folder.
-If, however, you want to implement a different experience, you will have to use the `useSignTransactionsWithLedger` hook.
+#### Initialization
-it accepts the following props:
+An existing provider is initialized on app load (this is take care of by `initApp`), since it restores the session from the store and allows signing transactions without the need of making a new login.
-```typescript
-{
- onCancel: () => void;
-}
-```
+#### Creating a custom provider
-and returns an object with the following keys:
+If you need to create a custom signing provider, make sure to extend the `IProvider` interface and implement all required methods (see example [here](https://github.com/multiversx/mx-template-dapp/tree/main/src/provider)). Next step would be to include it in the `customProviders` array in the `initApp` method or add it to the [window object](https://github.com/multiversx/mx-template-dapp/tree/main/src/initConfig). Last step is to login using the custom provider.
```typescript
-{
- onSignTransaction: () => void;
- onNext: () => void;
- onPrev: () => void;
- waitingForDevice: boolean;
- onAbort: (e: React.MouseEvent) => void;
- isLastTransaction: boolean;
- currentStep: number;
- signedTransactions?: Record;
- currentTransaction: {
- transaction: Transaction;
- transactionTokenInfo: {
- tokenId: string;
- amount: string;
- receiver: string;
- type?: string;
- nonce?: string;
- multiTxData?: string;
- };
- isTokenTransaction: boolean;
- tokenDecimals: number;
- dataField: string;
- };
-}
+const provider = await ProviderFactory.create({
+ type: 'custom-provider'
+});
+await provider?.login();
```
-
+#### Accessing provider methods
-
-Tracking a transaction
-
+Once the provider is initialized, you can get a reference to it using the `getAccountProvider` method. Then you can call the `login`, `logout`, `signTransactions`, `signMessage` methods, or other custom methods depending on the initialized provider (see ledger for example).
[comment]: # (mx-context-auto)
-### Tracking a transaction
-
-The library exposes a hook called useTrackTransactionStatus;
-
-```jsx
-import {useTrackTransactionStatus} from @multiversx/sdk-dapp/hooks;
+### 3. Account
-const transactionStatus = useTrackTransactionStatus({
- transactionId: sessionId,
- onSuccess,
- onFail,
- onCancelled,
-});
-```
+#### Getting account data
-transactionStatus has the following information about the transaction:
+Once the user logs in, a call is made to the API for fetching the account data. This data is persisted in the store and is accessible through helpers found in `methods/account`. These functions are:
-```typescript
-{
- isPending,
- isSuccessful,
- isFailed,
- isCancelled,
- errorMessage,
- status,
- transactions,
-}
-```
-
-It's safe to pass in `null` as a sessionId, so if the transaction wasn't yet sent, the hook will just return an empty object.
+**Table 4**. Getting account data
+| # | Helper | Description | React hook equivalent |
+|---|------|-------------|----|
+| | `methods/account` | path | `react/account` |
+| 1 | `getAccount()` | returns all account data |`useGetAccount()` |
+| 2 | `getAddress()` | returns just the user's public key | `useGetAddress()`|
+| 3 | `getIsLoggedIn()` | returns a login status boolean | `useGetIsLoggedIn()` |
+| 4 | `getLatestNonce()` | returns the account nonce | `useGetLatestNonce()`
-
+#### Nonce management
-
-Tracking transactions' statuses
-
+`sdk-dapp` has a mechanism that does its best to manage the account nonce. For example, if the user sends a transaction, the nonce gets incremented on the client so that if a new transaction is sent, it will have the correct increased nonce. If you want to make sure the nonce is in sync with the API account, you can call `refreshAccount()` as shown above in the **Signing transactions** section.
[comment]: # (mx-context-auto)
-### Tracking transactions' statuses
-
-sdk-dapp also exposes a number of handy hooks for tracking all, pending, failed, successful and timed out transactions.
+### 4. Transactions Manager
-Use:
+#### Overview
-- `useGetPendingTransactions` to get a list of all pending transactions.
-- `useGetSuccessfulTransactions` to get a list of all successful transactions.
-- `useGetFailedTransactions` to get a list of all failed transactions.
+The `TransactionManager` is a class that handles sending and tracking transactions in the MultiversX ecosystem. It provides methods to send either single or batch transactions. It also handles tracking, error management, and toast notifications for user feedback. It is initialized in the `initApp` method and can be accessed via `TransactionManager.getInstance()`.
-An especially useful hook called `useGetActiveTransactionsStatus` will keep you updated with the status
-of all transactions at a certain point in time.
+#### Features
-it's return signature is
+- **Supports Single and Batch Transactions:** Handles individual transactions as well as grouped batch transactions.
+- **Automatic Tracking:** Monitors transaction status and updates accordingly through a webhook or polling fallback mechanism.
+- **Toast Notifications:** Displays status updates for user feedback, with options to disable notifications and customize toast titles.
+- **Error Handling:** Catches and processes errors during transaction submission
-```typescript
-{
- pending: boolean - at least one transaction is pending;
- hasPendingTransactions: boolean - the user has at least 1 pending transaction active;
- timedOut: boolean = there are no pending transactions and at least one has timed out;
- fail: boolean - there are no pending and no timedOut transactions and at least one has failed;
- success: boolean - all transactions are successful and all smart contract calls have been processed successfully;
-}
-```
+#### Transactions Lifecycle
-
+The transaction lifecycle consists of the following steps:
-
-Transaction Toasts UI
-
+1. **Creating** a `Transaction` object from `@multiversx/sdk-core`
+2. **Signing** the transaction with the initialized provider and receiving a `SignedTransactionType` object
+3. **Sending** the signed transaction using TransactionManager's `send()` function. Signed transactions can be sent in 2 ways:
-[comment]: # (mx-context-auto)
+**Table 5**. Sending signed transactions
+| # | Signature | Method | Description |
+|---|------|-------------|-------------|
+| 1 | `send([tx1, tx2])` | `POST` to `/transactions` | Transactions are executed in parallel
+| 2 | `send([[tx1, tx2], [tx3]])` | `POST` to `/batch` | **a)** 1st batch of two transactions is executed, **b)** the 2nd batch of one transaction waits for the finished results, **c)** and once the 1st batch is finished, the 2nd batch is executed
-### Transaction Toasts UI
+4. **Tracking** transactions is made by using `transactionManager.track()`. Since the `send()` function returns the same arguments it has received, the same array payload can be passed into the `track()` method. Under the hood, status updates are received via a WebSocket or polling mechanism.
+ Once a transaction array is tracked, it gets associated with a `sessionId`, returned by the `track()` method and stored in the `transactions` slice. Depending on the array's type (plain/batch), the session's status varies from initial (`pending`/`invalid`/`sent`) to final (`successful`/`failed`/`timedOut`).
-sdk-dapp also exposes a toast component for tracking transactions that uses the above mentioned hooks and displays toasts with transactions statuses.
+**Table 6**. Inspecting transaction sessions
+| # | Helper | Description | React hook equivalent |
+|---|------|-------------|----|
+| | `methods/transactions` | path | `react/transactions` |
+| 1 | `getTransactionSessions()` | returns all trabsaction sessions |`useGetTransactionSessions()` |
+| 2 | `getPendingTransactionsSessions()` | returns an record of pending sessions | `useGetPendingTransactionsSessions()`|
+| 3 | `getPendingTransactions()` | returns an array of signed transactions | `useGetPendingTransactions()` |
+| 4 | `getFailedTransactionsSessions()` | returns an record of failed sessions | `useGetFailedTransactionsSessions()`|
+| 5 | `getFailedTransactions()` | returns an array of failed transactions | `useGetFailedTransactions()`|
+| 6 | `getSuccessfulTransactionsSessions()` | returns an record of successful sessions | `useGetSuccessfulTransactionsSessions()`|
+| 7 | `getSuccessfulTransactions()` | returns an array of successful transactions | `useGetSuccessfulTransactions()`|
-The toasts list is exposed via **TransactionsToastList** UI component and can be used just by rendering it inside the application.
-`TransactionToastList` component renders also custom toasts. A custom toast can be added using the util function: `addNewCustomToast` and can be removed using `deleteCustomToast`
+5. **User feedback** is provided through toast notifications, which are triggered to inform about transactions' progress. Additional tracking details can be optionally displayed in the toast UI.
+There is an option to add custom toast messages by using the `createCustomToast` helper.
-When `TransactionToastList` is also used for displaying custom toasts, is enough to call `addNewCustomToast` to add new custom toast to the list;
+```ts
+import { createRoot } from 'react-dom/client';
+import { createCustomToast } from '@multiversx/sdk-dapp/out/store/actions/toasts/toastsActions';
-```jsx
-
-
-
-
-```
-
-**Important**: This has to be inside the `` children.
+// by creating a custom toast element containing a component
+createCustomToast({
+ toastId: 'username-toast',
+ instantiateToastElement: () => {
+ const toastBody = document.createElement('div');
+ const root = createRoot(toastBody);
+ root.render();
+ return toastBody;
+ }
+});
-In case you don't want to use `TransactionToastList` and just display a custom toast, then you have to import `CustomToast` component
+// or by creating a simple custom toast
+createCustomToast({
+ toastId: 'custom-toast',
+ icon: 'times',
+ iconClassName: 'warning',
+ message: 'This is a custom toast',
+ title: 'My custom toast'
+});
+
-```jsx
-const customToast = addNewCustomToast(
- {
- toastId: 'toast-id',
- message: '',
- type: 'custom',
- duration: 2000
- }
-);
- deleteCustomToast(toastId)
- />
```
-
+6. **Error Handling & Recovery** is done through a custom toast that prompts the user to take appropriate action.
-
-Removing transactions manually
-
+#### Methods
+___
-[comment]: # (mx-context-auto)
-
-### Removing transactions manually
+#### 1. Sending Transactions
-sdk-dapp takes care to change transactions' statuses and removes them when needed,
-but if you need to do this manually, you can use the exposed functions for this:
+In this way, all transactions are sent simultaneously. There is no limit to the number of transactions contained in the array.
```typescript
-removeTransactionsToSign(sessionId);
-removeSignedTransaction(sessionId);
-removeAllTransactionsToSign();
-removeAllSignedTransactions();
+const transactionManager = TransactionManager.getInstance();
+const parallelTransactions: SigendTransactionType[] = [tx1, tx2, tx3, tx4];
+const sentTransactions = await transactionManager.send(parallelTransactions);
```
-
-
-[comment]: # (mx-context-auto)
-
-## Unit testing with Jest
+#### 2. Sending Batch Transactions
-The sdk-dapp library exposes bundles for both CommonJS and ESModules, however, in some environments, Jest might require manual mapping of the CommonJS output. To implement it, add the following snippet inside your jest config file.
+In this sequential case, each batch waits for the previous one to complete.
```typescript
-moduleNameMapper: {
- '@multiversx/sdk-dapp/(.*)':
- '/node_modules/@multiversx/sdk-dapp/__commonjs/$1.js'
-}
+const transactionManager = TransactionManager.getInstance();
+const batchTransactions: SignedTransactionType[][] = [
+ [tx1, tx2],
+ [tx3, tx4]
+];
+const sentTransactions = await transactionManager.send(batchTransactions);
```
-[comment]: # (mx-context-auto)
-
-## sdk-dapp exports
-
-Since version 2.0, sdk-dapp does not have a default export object.
-You have to import everything from its own separate module. Below you can find all the exports.
-
-You can either import everything from a module, or if you really want to make sure you're not importing anything
-that is not used, you can import everything from its own file.
+#### 3. Tracking Transactions
-You can either go into their specific folder in the module for extra trimming, or import everything together.
+The basic option is to use the built-in tracking, which displays toast notifications with default messages.
-for example, these 2 imports are both valid:
+```typescript
+import { TransactionManagerTrackOptionsType } from '@multiversx/sdk-dapp/out/managers/TransactionManager/TransactionManager.types';
+
+const options: TransactionManagerTrackOptionsType = {
+ disableToasts: false, // `false` by default
+ transactionsDisplayInfo: { // `undefined` by default
+ errorMessage: 'Failed adding stake',
+ successMessage: 'Stake successfully added',
+ processingMessage: 'Staking in progress'
+ },
+ sessionInformation: { // `undefined` by default. Use to perform additional actions based on the session information
+ stakeAmount: '1000000000000000000000000'
+ }
+};
-```jsx
-import {
- useExtensionLogin,
- useGetAccountInfo,
-} from "@multiversx/sdk-dapp/hooks";
+const sessionId = await transactionManager.track(
+ sentTransactions,
+ options // optional
+);
```
-and
+If you want to provide more human-friendly messages to your users, you can enable tracking with custom toast messages:
-```jsx
-import { useExtensionLogin } from "@multiversx/sdk-dapp/hooks/login";
-import { useGetAccountInfo } from "@multiversx/sdk-dapp/hooks/account";
+```typescript
+const sessionId = await transactionManager.track(sentTransactions, {
+ transactionsDisplayInfo: {
+ errorMessage: 'Failed adding stake',
+ successMessage: 'Stake successfully added',
+ processingMessage: 'Staking in progress'
+ }
+});
```
-[comment]: # (mx-context-auto)
-
-### constants exports
+#### 3.1 Tracking transactions without being logged in
-```jsx
-import {
- GAS_PRICE_MODIFIER,
- GAS_PER_DATA_BYTE,
- GAS_LIMIT,
- GAS_PRICE,
- DECIMALS,
- DIGITS,
- mnemonicWords,
- ledgerErrorCodes,
- fallbackNetworkConfigurations,
-} from "@multiversx/sdk-dapp/constants";
-```
-
-[comment]: # (mx-context-auto)
+If your application needs to track transactions sent by a server and the user does not need to login to see the outcome of these transactions, there are several steps that you need to do to enable this process.
-### hooks exports
+Step 1. Enabling the tracking mechanism
-[comment]: # (mx-context-auto)
+By default the tracking mechanism is enabled only after the user logs in. That is the moment when the WebSocket connection is established. If you want to enable tracking before the user logs in, you need to call the `trackTransactions` method from the `methods/trackTransactions` folder. This method will enable a polling mechanism.
-#### Login
+```typescript
+import { trackTransactions } from '@multiversx/sdk-dapp/out/methods/trackTransactions/trackTransactions';
-```jsx
-import {
- useExtensionLogin,
- useLedgerLogin,
- useWalletConnectLogin,
- useWebWalletLogin,
-} from "@multiversx/sdk-dapp/hooks/login";
+initApp(config).then(async () => {
+ await trackTransactions(); // enable here since by default tracking will be enabled only after login
+ render(() => , root!);
+});
```
-[comment]: # (mx-context-auto)
+Step 2. Tracking transactions
-#### Account
+Then, you can track transactions by calling the `track` method from the `TransactionManager` class with a plain transaction containing the transaction hash.
-```jsx
-import {
- useGetAccountInfo,
- useGetAccountProvider,
- useGetLoginInfo,
-} from "@multiversx/sdk-dapp/hooks/accounts";
-```
+```typescript
+import { Transaction, TransactionsConverter } from '@multiversx/sdk-core';
-[comment]: # (mx-context-auto)
+const tManager = TransactionManager.getInstance();
+const txConverter = new TransactionsConverter();
+const transaction = txConverter.plainObjectToTransaction(signedTx);
-#### Transactions
+const hash = transaction.getHash().toString(); // get the transaction hash
-```jsx
-import {
- useCheckTransactionStatus,
- useGetActiveTransactionsStatus,
- useGetFailedTransactions,
- useGetPendingTransactions,
- useGetSignedTransactions,
- useGetSignTransactionsError,
- useGetSuccessfulTransactions,
- useGetTokenDetails,
- useGetTransactionDisplayInfo,
- useParseMultiEsdtTransferData,
- useParseSignedTransactions,
- useSignMultipleTransactions,
- useSignTransactions,
- useSignTransactionsWithDevice,
- useSignTransactionsWithLedger,
-} from "@multiversx/sdk-dapp/hooks/transactions";
+const plainTransaction = { ...transaction.toPlainObject(), hash };
+await tManager.track([plainTransaction]);
```
-[comment]: # (mx-context-auto)
-
-#### Misc
-
-```jsx
-import {
- useDebounce,
- useGetNetworkConfig,
- useGetNotification,
- useUpdateEffect,
-} from "@multiversx/sdk-dapp/hooks";
-```
+#### 3.2 Advanced Usage
-[comment]: # (mx-context-auto)
+If you need to check the status of the signed transactions, you can query the store directly using the `sessionId` returned by the `track()` method.
-### services exports
+```typescript
+import { getStore } from '@multiversx/sdk-dapp/out/store/store';
+import { transactionsSliceSelector } from '@multiversx/sdk-dapp/out/store/selectors/transactionsSelector';
-```jsx
-import {
- removeTransactionsToSign,
- removeSignedTransaction,
- removeAllSignedTransactions,
- removeAllTransactionsToSign,
- isCrossShardTransaction,
- sendTransactions,
- signTransactions,
- calcTotalFee,
-} from "@multiversx/sdk-dapp/services";
+const state = transactionsSliceSelector(getStore());
+Object.entries(state).forEach(([sessionKey, data]) => {
+ if (sessionKey === sessionId) {
+ console.log(data.status);
+ }
+});
```
[comment]: # (mx-context-auto)
-### utils exports
-
-[comment]: # (mx-context-auto)
-
-#### Account
+### 5. UI Components
-```jsx
-import {
- addressIsValid,
- getAccount,
- getAccountBalance,
- getAccountShard,
- getAddress,
- getLatestNonce,
- getShardOfAddress,
- refreshAccount,
- setNonce,
- signMessage,
-} from "@multiversx/sdk-dapp/utils/account";
-```
+`sdk-dapp` needs to make use of visual elements for allowing the user to interact with some providers (like the ledger), or to display messages to the user (like idle states or toasts). These visual elements consitst of webcomponents hosted in the `@multiversx/sdk-dapp-ui` package. Thus, `sdk-dapp` does not hold any UI elements, just business logic that controls external components. We can consider two types of UI components: internal and public. They are differentiated by the way they are controlled: internal components are controlled by `sdk-dapp`'s signing or logging in flows, while public components should be controlled by the dApp.
-[comment]: # (mx-context-auto)
+#### 5.1 Public components
-#### Operations
+The business logic for these components is served by a controller. The components are:
-```jsx
-import {
- calculateFeeLimit,
- formatAmount,
- nominate,
- getUsdValue,
-} from "@multiversx/sdk-dapp/utils/operations";
-```
+- `MvxTransactionsTable` - used to display the user's transactions
-[comment]: # (mx-context-auto)
+```tsx
+import { TransactionsTableController } from '@multiversx/sdk-dapp/out/controllers/TransactionsTableController';
+import { MvxTransactionsTable } from '@multiversx/sdk-dapp-ui/react';
+
+const processedTransactions = await TransactionsTableController.processTransactions({
+ address,
+ egldLabel: network.egldLabel,
+ explorerAddress: network.explorerAddress,
+ transactions
+ });
-#### Transactions
+// and use like this:
+;
-```jsx
-import {
- getTokenFromData,
- isTokenTransfer,
- parseMultiEsdtTransferData,
- parseTransactionAfterSigning,
-} from "@multiversx/sdk-dapp/utils/transactions";
```
-[comment]: # (mx-context-auto)
+- `MvxFormatAmount` - used to format the amount of the user's balance
-#### Validation
-```jsx
-import {
- getIdentifierType,
- stringIsFloat,
- stringIsInteger,
- isContract,
- isStringBase64,
-} from "@multiversx/sdk-dapp/utils";
-```
-
-[comment]: # (mx-context-auto)
+```tsx
+import { MvxFormatAmount } from '@multiversx/sdk-dapp-ui/react';
+import { MvxFormatAmountPropsType } from '@multiversx/sdk-dapp-ui/types';
+export { DECIMALS, DIGITS } from '@multiversx/sdk-dapp-utils/out/constants';
+import { FormatAmountController } from '@multiversx/sdk-dapp/out/controllers/FormatAmountController';
+export { useGetNetworkConfig } from '@multiversx/sdk-dapp/out/react/network/useGetNetworkConfig';
-#### Misc
-```jsx
-import {
- encodeToBase64,
- decodeBase64,
- logout,
- getTokenFromData,
- getIsLoggedIn,
- isSelfESDTContract,
- getAddressFromDataField,
-} from "@multiversx/sdk-dapp/utils";
-```
+interface IFormatAmountProps
+ extends Partial {
+ value: string;
+ className?: string;
+}
-[comment]: # (mx-context-auto)
+export const FormatAmount = (props: IFormatAmountProps) => {
+ const {
+ network: { egldLabel }
+ } = useGetNetworkConfig();
-### Wrappers
+ const { isValid, valueDecimal, valueInteger, label } =
+ FormatAmountController.getData({
+ digits: DIGITS,
+ decimals: DECIMALS,
+ egldLabel,
+ ...props,
+ input: props.value
+ });
-```jsx
-import {
- DappProvider,
- AuthenticatedRoutesWrapper,
- AppInitializer,
-} from "@multiversx/sdk-dapp/wrappers";
+ return (
+
+ );
+};
```
-[comment]: # (mx-context-auto)
-
-### Web-specific imports
-```jsx
-import { useIdleTimer } from "@multiversx/sdk-dapp/web";
-```
-
-[comment]: # (mx-context-auto)
+#### 5.2 Internal components (advanced usage)
-### UI
+The way internal components are controlled is through a [pub-sub pattern](https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern) called EventBus. Each webcomponent has a method of exposing its EventBus, thus allowing `sdk-dapp` to get a reference to it and use it for communication.
-```jsx
-import {
- CopyButton,
- FormatAmount,
- ExplorerLink,
- ExtensionLoginButton,
- LedgerLoginButton,
- LedgerLoginContainer,
- NotificationModal,
- PageState,
- ProgressSteps,
- SignTransactionsModals,
- SignWithDeviceModal,
- SignWithExtensionModal,
- SignWithLedgerModal,
- TransactionsToastList,
- TransactionToast,
- Trim,
- UsdValue,
- WalletConnectLoginButton,
- WalletConnectLoginContainer,
-} from "@multiversx/sdk-dapp/UI";
+```mermaid
+flowchart LR
+ A["Controller"] <--> B["Event Bus"] <--> C["webcomponent"]
```
-or
-
-```jsx
-import { CopyButton } from "@multiversx/sdk-dapp/UI/CopyButton";
-import { FormatAmount } from "@multiversx/sdk-dapp/UI/FormatAmount";
-import { ExplorerLink } from "@multiversx/sdk-dapp/UI/ExplorerLink";
+```typescript
+import { ComponentFactory } from '@multiversx/sdk-dapp/out/utils/ComponentFactory';
-// etc;
+const modalElement = await ComponentFactory.create(
+ 'mvx-ledger-connect-panel'
+);
+const eventBus = await modalElement.getEventBus();
+eventBus.publish('TRANSACTION_TOAST_DATA_UPDATE', someData);
```
-**Important**: `shouldRenderDefaultCss` was removed from all components.
+If you want to override private components and create your own, you can implement a similar strategy by respecting each webcomponent's API (see an interface example [here](https://github.com/multiversx/mx-sdk-dapp/blob/main/src/providers/strategies/LedgerProviderStrategy/types/ledger.types.ts)).
[comment]: # (mx-context-auto)
-## WalletConnect Setup
-
-Starting with the 2.0 version of the dApp SDK ( previously `@elrondnetwork/dapp-core@2.0.0` ) and `@multiversx/sdk-dapp@2.2.8` [WalletConnect 2.0](https://docs.walletconnect.com/2.0/) is available as a login and signing provider, allowing users to login by scanning a QR code with the Mobile App
+## Debugging your dApp
-This is an implementation of the [sdk-wallet-connect-provider](https://github.com/multiversx/mx-sdk-js-wallet-connect-provider) ( [docs](https://docs.multiversx.com/sdk-and-tools/sdk-js/sdk-js-signing-providers/#the-walletconnect-provider) ) signing provider
+> **Note:** For an advanced documentation on how internal flows are implemented, you can check out the [deepwiki](https://deepwiki.com/multiversx/mx-sdk-dapp) diagrams.
-A `Project ID` is required to enable the WalletConnect functionality.
-
-[comment]: # (mx-context-auto)
+The recommended way to debug your application is by using [lerna](https://lerna.js.org/). Make sure you have the same package version in sdk-dapp's package.json and in your project's package.json.
-### Set the Project ID
+If you prefer to use [npm link](https://docs.npmjs.com/cli/v11/commands/npm-link), make sure to use the `preserveSymlinks` option in the server configuration:
-In the [DappProvider](#dappprovider) wrapper a `walletConnectV2ProjectId` must be provided in the `customNetworkConfig`
-
-The Project ID can be generated for free here: [https://cloud.walletconnect.com/sign-in](https://cloud.walletconnect.com/sign-in)
-
-```jsx
-
+```js
+ resolve: {
+ preserveSymlinks: true, // 👈
+ alias: {
+ src: "/src",
+ },
+ },
```
-The WalletConnect Project ID grants you access to the [WalletConnect Cloud Relay](https://docs.walletconnect.com/2.0/cloud/relay) that securely manages communication between the device and the dApp.
+Crome Redux DevTools are by default enabled to help you debug your application. You can find the extension in the Chrome Extensions store.
-If the Project ID is valid, the new functionality will work out of the box with the [Transactions and Message signing](#transactions) flows.
+To build the library, run:
-[comment]: # (mx-context-auto)
-
-## React Native support
-
-We are aware that there are projects out there that would like to use this library to allow users to seamlessly authenticate with the xPortal App.
-
-You can use this library for its utility functions, like "formatAmount, parseAmount", mnemonic words list or its constants.
+```bash
+npm run build
+```
-However, certain architectural decisions that we made do not work out of the box with React Native runtime (neither Metro nor Re.pack).
-Due to this, you cannot yet use the DappProvider wrapping logic in a React Native application.
+To run the unit tests, run:
-We have a couple of solutions in mind and are actively working on exploring ways to overcome these limitations.
-Until then, you can use `@multiversx/sdk-*` libraries and @walletconnect to connect to the xPortal App.
-There are also guide for doing this from the [community](https://github.com/S4F-IT/maiar-integration/blob/master/README)
+```bash
+npm test
+```
\ No newline at end of file