Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0e2331a
Sdk-dapp-core migration (#264)
razvantomegea May 23, 2025
38430fa
Update imports (#341)
mgavrila May 26, 2025
cca5c98
Add unlock and logout route (#340)
mgavrila May 27, 2025
15e16ee
Update Home.tsx
arhtudormorar May 27, 2025
d69d513
Merge pull request #344 from multiversx/arhtudormorar-patch-1
arhtudormorar May 27, 2025
07cd8bf
Update routes.ts
arhtudormorar May 27, 2025
9b5c3e3
Merge branch 'main' into development
arhtudormorar May 27, 2025
43456e0
Remove token from requests (#346)
mgavrila May 27, 2025
1603a7f
Update routeNames.enums.ts
arhtudormorar May 27, 2025
b23453e
Minor renamings (#347)
arhtudormorar May 27, 2025
a98cadf
Merge branch 'main' into development
arhtudormorar May 27, 2025
0eb7bc6
Migration guide update (#349)
arhtudormorar May 28, 2025
66fa5ac
Update packages
arhtudormorar May 29, 2025
d18ac84
Fixed types (#350)
arhtudormorar May 30, 2025
4947eb7
Fix inMemoryProvider signature (#351)
mgavrila May 30, 2025
01cec26
Test callbacks
arhtudormorar Jun 25, 2025
b25fa98
Simplify initApp
arhtudormorar Jun 26, 2025
8034f43
Upgrade sdk-dapp
arhtudormorar Jun 26, 2025
83f9233
Remove unused
arhtudormorar Jun 26, 2025
6d4161c
Remove unused
arhtudormorar Jun 26, 2025
a145e7e
Merge pull request #353 from multiversx/tm/feature/session-callbacks
arhtudormorar Jun 26, 2025
423e782
Upgraded packages. (#354)
iuliacimpeanu Jul 2, 2025
51dada6
Upgrade migration guide
arhtudormorar Jul 4, 2025
d116ee3
Merge pull request #355 from multiversx/tm/feature/update-migration-g…
arhtudormorar Jul 4, 2025
6a5117a
Remove unused
arhtudormorar Jul 11, 2025
fa28a5f
Upgrade packages
arhtudormorar Jul 11, 2025
1ea30e9
Updates on components (#356)
iuliacimpeanu Jul 14, 2025
0ea442d
Update yarn lock
arhtudormorar Jul 14, 2025
7ce16e2
Merge branch 'main' into development
arhtudormorar Jul 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# @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(
<React.StrictMode>
<App />
</React.StrictMode>
);
});
```

## 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/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 (
<>
<Button onClick={() => setOpen(true)}>Connect</Button>
<UnlockPanel
open={open}
onLogin={(options) =>
handleLogin({
type: options.detail.provider,
anchor: options.detail.anchor
})
}
onClose={() => {
setOpen(false);
}}
>
<UnlockButton
label='In Memory Provider'
onClick={() =>
handleLogin({
type: ExtendedProviders.inMemoryProvider
})
}
/>
</UnlockButton>
</>
);
};
```

## 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`
23 changes: 12 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand All @@ -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",
Expand All @@ -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",
Expand Down
1 change: 1 addition & 0 deletions postcss.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module.exports = {
plugins: {
tailwindcss: {},
// '@tailwindcss/postcss': {} // NOTE: This is the new way to include Tailwind CSS V4.0.0+
Comment thread
arhtudormorar marked this conversation as resolved.
Outdated
autoprefixer: {}
}
};
100 changes: 21 additions & 79 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<DappProvider
environment={environment}
customNetworkConfig={{
name: 'customConfig',
apiTimeout,
walletConnectV2ProjectId
}}
dappConfig={{
shouldUseWebViewProvider: true,
logoutRoute: RouteNamesEnum.unlock
}}
customComponents={{
transactionTracker: {
// uncomment this to use the custom transaction tracker
// component: TransactionsTracker,
props: {
onSuccess: (sessionId: string) => {
console.log(`Session ${sessionId} successfully completed`);
},
onFail: (sessionId: string, errorMessage: string) => {
console.log(`Session ${sessionId} failed. ${errorMessage ?? ''}`);
}
}
}
}}
>
<AxiosInterceptorContext.Listener>
<Layout>
<TransactionsToastList />
<NotificationModal />
<SignTransactionsModals />
<Routes>
{routes.map((route) => (
<Route
path={route.path}
key={`route-key-'${route.path}`}
element={<route.component />}
/>
))}
<Route path='*' element={<PageNotFound />} />
</Routes>
</Layout>
</AxiosInterceptorContext.Listener>
</DappProvider>
);
};
import { AxiosInterceptors, BatchTransactionsContextProvider } from 'wrappers';
import { Layout } from './components';

export const App = () => {
return (
<AxiosInterceptorContext.Provider>
<AxiosInterceptorContext.Interceptor
authenticatedDomains={sampleAuthenticatedDomains}
>
<Router>
<BatchTransactionsContextProvider>
<AppContent />
</BatchTransactionsContextProvider>
</Router>
</AxiosInterceptorContext.Interceptor>
</AxiosInterceptorContext.Provider>
<Router>
<AxiosInterceptors>
<BatchTransactionsContextProvider>
<Layout>
<Routes>
{routes.map((route) => (
<Route
key={`route-key-'${route.path}`}
path={route.path}
element={<route.component />}
/>
))}
<Route path='*' element={<PageNotFound />} />
</Routes>
</Layout>
</BatchTransactionsContextProvider>
</AxiosInterceptors>
</Router>
);
};
2 changes: 1 addition & 1 deletion src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const Button = ({
return (
<button
id={id}
data-testid={otherProps['data-testid']}
{...otherProps}
disabled={disabled}
onClick={onClick}
className={className}
Expand Down
66 changes: 21 additions & 45 deletions src/components/Layout/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,20 @@
import { useMatch } from 'react-router-dom';
import { useNavigate } from 'react-router-dom';
import { Button, MxLink } from 'components';
import { environment } from 'config';
import { logout, useGetIsLoggedIn } from 'lib';
import { getAccountProvider, useGetIsLoggedIn } from 'lib';
import { RouteNamesEnum } from 'localConstants';
import MultiversXLogo from '../../../assets/img/multiversx-logo.svg?react';

const callbackUrl = `${window.location.origin}/unlock`;
const onRedirect = undefined; // use this to redirect with useNavigate to a specific page after logout
const shouldAttemptReLogin = false; // use for special cases where you want to re-login after logout
const options = {
/*
* @param {boolean} [shouldBroadcastLogoutAcrossTabs=true]
* @description If your dApp supports multiple accounts on multiple tabs,
* this param will broadcast the logout event across all tabs.
*/
shouldBroadcastLogoutAcrossTabs: true,
/*
* @param {boolean} [hasConsentPopup=false]
* @description Set it to true if you want to perform async calls before logging out on Safari.
* It will open a consent popup for the user to confirm the action before leaving the page.
*/
hasConsentPopup: false
};
import { ConnectButton } from './components';
import { NotificationsButton } from './components/NotificationsButton';

export const Header = () => {
const isLoggedIn = useGetIsLoggedIn();
const isUnlockRoute = Boolean(useMatch(RouteNamesEnum.unlock));
const navigate = useNavigate();
const provider = getAccountProvider();

const ConnectButton = isUnlockRoute ? null : (
<MxLink to={RouteNamesEnum.unlock}>Connect</MxLink>
);

const handleLogout = () => {
sessionStorage.clear();
logout(
callbackUrl,
/*
* following are optional params. Feel free to remove them in your implementation
*/
onRedirect,
shouldAttemptReLogin,
options
);
const handleLogout = async () => {
await provider.logout();
navigate(RouteNamesEnum.home);
};

return (
Expand All @@ -60,16 +33,19 @@ export const Header = () => {
<p className='text-gray-600'>{environment}</p>
</div>

{isLoggedIn ? (
<Button
onClick={handleLogout}
className='inline-block rounded-lg px-3 py-2 text-center hover:no-underline my-0 text-gray-600 hover:bg-slate-100 mx-0'
>
Close
</Button>
) : (
ConnectButton
{isLoggedIn && (
<>
<NotificationsButton />
<Button
onClick={handleLogout}
className='inline-block rounded-lg px-3 py-2 text-center hover:no-underline my-0 text-gray-600 hover:bg-slate-100 mx-0'
>
Close
</Button>
</>
)}

{!isLoggedIn && <ConnectButton />}
Comment thread
arhtudormorar marked this conversation as resolved.
Outdated
</div>
</nav>
</header>
Expand Down
Loading
Loading