Skip to content

Commit

Permalink
Added ability to switch networks (#39)
Browse files Browse the repository at this point in the history
* Fixes

* fixed TokenRow.tsx

* Removed EGLD from sovereign transfer

* Refactor

* Fixed tests

* Added ability to switch networks

* Merge conflicts
  • Loading branch information
razvantomegea authored Aug 22, 2024
1 parent 74654a5 commit 58148bb
Show file tree
Hide file tree
Showing 27 changed files with 519 additions and 71 deletions.
21 changes: 10 additions & 11 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Provider } from 'react-redux';
import { Provider, useSelector } from 'react-redux';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import { PersistGate } from 'redux-persist/integration/react';

Expand All @@ -9,27 +9,24 @@ import {
Utilities
} from 'components';

import {
apiTimeout,
walletConnectV2ProjectId,
environment,
sampleAuthenticatedDomains,
API_URL
} from 'config';
import { apiTimeout, walletConnectV2ProjectId } from 'config';
import { provider } from 'helpers/app';
import { PageNotFound, Unlock } from 'pages';
import { routeNames, routes } from 'routes';
import { BatchTransactionsContextProvider } from 'wrappers';
import { networkSelector } from './redux/selectors';
import { persistor, store } from './redux/store';

const AppContent = () => {
const { activeNetwork } = useSelector(networkSelector);

return (
<DappProvider
environment={environment}
environment={activeNetwork.id}
externalProvider={provider}
customNetworkConfig={{
name: 'customConfig',
apiAddress: API_URL,
apiAddress: activeNetwork.apiAddress,
apiTimeout,
walletConnectV2ProjectId
}}
Expand Down Expand Up @@ -72,10 +69,12 @@ const AppContent = () => {
};

export const MainApp = () => {
const { activeNetwork } = useSelector(networkSelector);

return (
<AxiosInterceptorContext.Provider>
<AxiosInterceptorContext.Interceptor
authenticatedDomains={sampleAuthenticatedDomains}
authenticatedDomains={activeNetwork.sampleAuthenticatedDomains}
>
<BatchTransactionsContextProvider>
<AppContent />
Expand Down
1 change: 1 addition & 0 deletions src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const Button = ({
id={id}
onClick={onClick}
type={type}
{...otherProps}
>
{children}
</button>
Expand Down
71 changes: 71 additions & 0 deletions src/components/Dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { useState } from 'react';
import { faChevronDown } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Button } from '../Button';

export interface DropdownOption {
label: string;
value: string;
}

interface DropdownPropsType {
initialOption: DropdownOption;
onSelectOption: (option: DropdownOption) => void;
options: DropdownOption[];
}

export const Dropdown = ({
initialOption,
onSelectOption,
options
}: DropdownPropsType) => {
const [isOpen, setIsOpen] = useState(false);
const [selectedOption, setSelectedOption] = useState(initialOption.label);

const toggleDropdown = () => {
setIsOpen(!isOpen);
};

const handleSelectOption = (option: DropdownOption) => () => {
setSelectedOption(option.label);
onSelectOption(option);
toggleDropdown();
};

return (
<div className='relative inline-block text-left'>
<Button
aria-expanded='true'
aria-haspopup='true'
className='flex flex-row flex-nowrap items-center justify-center w-full px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-indigo-500'
onClick={toggleDropdown}
>
{selectedOption}
<FontAwesomeIcon className='-mr-1 ml-2' icon={faChevronDown} />
</Button>

{isOpen && (
<div
className='origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none'
role='menu'
aria-orientation='vertical'
aria-labelledby='menu-button'
tabIndex={-1}
>
<div className='py-1' role='none'>
{options.map((option, index) => (
<Button
className='block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900'
data-testid={option.value}
key={`${option.value}-${index}`}
onClick={handleSelectOption(option)}
>
{option.label}
</Button>
))}
</div>
</div>
)}
</div>
);
};
1 change: 1 addition & 0 deletions src/components/Dropdown/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Dropdown';
7 changes: 2 additions & 5 deletions src/components/Layout/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useMatch } from 'react-router-dom';
import { MxLink } from 'components/MxLink';
import { environment } from 'config';
import { useGetIsLoggedIn } from 'lib';
import { DataTestIdsEnum, RouteNamesEnum } from 'localConstants';
import { routeNames } from 'routes';
import MultiversXLogo from '../../../assets/img/multiversx-logo.svg?react';
import { NetworkSwitcher } from '../../NetworkSwitcher';

export const Header = () => {
const isLoggedIn = useGetIsLoggedIn();
Expand All @@ -27,10 +27,7 @@ export const Header = () => {

<nav className='h-full w-full text-sm sm:relative sm:left-auto sm:top-auto sm:flex sm:w-auto sm:flex-row sm:justify-end sm:bg-transparent'>
<div className='flex justify-end container mx-auto items-center gap-2'>
<div className='flex gap-1 items-center'>
<div className='w-2 h-2 rounded-full bg-green-500' />
<p className='text-gray-600'>{environment}</p>
</div>
<NetworkSwitcher />

{isLoggedIn ? (
<MxLink
Expand Down
39 changes: 39 additions & 0 deletions src/components/NetworkSwitcher/NetworkSwitcher.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { useDispatch, useSelector } from 'react-redux';
import { networks } from 'config';
import { networkSelector } from 'redux/selectors';
import { changeNetwork } from 'redux/slices';
import { Dropdown, DropdownOption } from '../Dropdown';

export const NetworkSwitcher = () => {
const { activeNetwork } = useSelector(networkSelector);
const dispatch = useDispatch();
const networkOptions = networks.map((network) => ({
label: network.name,
value: network.id
}));

const currentNetwork = {
label: activeNetwork.name,
value: activeNetwork.id
};

const handleNetworkSwitch = (option: DropdownOption) => {
const selectedNetwork = networks.find(
(network) => network.id === option.value
);

if (!selectedNetwork) {
return;
}

dispatch(changeNetwork(selectedNetwork));
};

return (
<Dropdown
initialOption={currentNetwork}
options={networkOptions}
onSelectOption={handleNetworkSwitch}
/>
);
};
1 change: 1 addition & 0 deletions src/components/NetworkSwitcher/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './NetworkSwitcher';
2 changes: 2 additions & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ export * from './PasswordVisibilityToggle';
export * from './PrivateKeyCheckWrapper';
export * from './ProgressBar';
export * from './TransactionsTracker';
export * from './Dropdown';
export * from './NetworkSwitcher';
export * from './Utilities';
export * from './sdkDapp.components';
60 changes: 54 additions & 6 deletions src/config/config.devnet.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,58 @@
import { NetworkType } from 'redux/slices';
import { EnvironmentsEnum } from 'types';

export * from './sharedConfig';

export const API_URL = 'https://devnet-api.multiversx.com';
export const GATEWAY_URL = ''; // either GATEWAY_URL or API_URL must be set
export const sampleAuthenticatedDomains = [API_URL];
export const environment = EnvironmentsEnum.devnet;
export const sovereignContractAddress = '';
export const WEGLDID = '';
export const networks: NetworkType[] = [
{
default: true,
id: EnvironmentsEnum.devnet,
name: 'Devnet',
apiAddress: 'https://devnet-api.multiversx.com',
gatewayUrl: '',
sampleAuthenticatedDomains: ['https://devnet-api.multiversx.com'],
sovereignContractAddress: '',
WEGLDid: ''
},
{
default: false,
id: EnvironmentsEnum.devnet,
name: 'Gateway',
apiAddress: '',
gatewayUrl: 'https://devnet-gateway.multiversx.com',
sampleAuthenticatedDomains: [''],
sovereignContractAddress: '',
WEGLDid: ''
},
{
default: false,
id: EnvironmentsEnum.mainnet,
name: 'Mainnet',
apiAddress: 'https://api.multiversx.com',
gatewayUrl: '',
sampleAuthenticatedDomains: ['https://api.multiversx.com'],
sovereignContractAddress: '',
WEGLDid: ''
},
{
default: false,
id: 'sovereign',
name: 'Sovereign',
apiAddress: 'https://api-sovereign-test.elrond.ro',
gatewayUrl: '',
sampleAuthenticatedDomains: ['https://api-sovereign-test.elrond.ro'],
sovereignContractAddress:
'erd1qqqqqqqqqqqqqpgqfcm6l6rd42hwhskmk4thlp9kz58npfq50gfqdrthqa',
WEGLDid: 'WEGLD-bd4d79'
},
{
default: false,
id: EnvironmentsEnum.testnet,
name: 'Testnet',
apiAddress: 'https://testnet-api.multiversx.com',
gatewayUrl: '',
sampleAuthenticatedDomains: ['https://testnet-api.multiversx.com'],
sovereignContractAddress: '',
WEGLDid: ''
}
];
60 changes: 54 additions & 6 deletions src/config/config.gateway.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,58 @@
import { EnvironmentsEnum } from 'types';
import { NetworkType } from '../redux/slices';

export * from './sharedConfig';

export const API_URL = ''; // either GATEWAY_URL or API_URL must be set
export const GATEWAY_URL = 'https://devnet-gateway.multiversx.com';
export const sampleAuthenticatedDomains = [API_URL];
export const environment = EnvironmentsEnum.devnet;
export const sovereignContractAddress = '';
export const WEGLDID = '';
export const networks: NetworkType[] = [
{
default: false,
id: EnvironmentsEnum.devnet,
name: 'Devnet',
apiAddress: 'https://devnet-api.multiversx.com',
gatewayUrl: '',
sampleAuthenticatedDomains: ['https://devnet-api.multiversx.com'],
sovereignContractAddress: '',
WEGLDid: ''
},
{
default: true,
id: EnvironmentsEnum.devnet,
name: 'Gateway',
apiAddress: '',
gatewayUrl: 'https://devnet-gateway.multiversx.com',
sampleAuthenticatedDomains: [''],
sovereignContractAddress: '',
WEGLDid: ''
},
{
default: false,
id: EnvironmentsEnum.mainnet,
name: 'Mainnet',
apiAddress: 'https://api.multiversx.com',
gatewayUrl: '',
sampleAuthenticatedDomains: ['https://api.multiversx.com'],
sovereignContractAddress: '',
WEGLDid: ''
},
{
default: false,
id: 'sovereign',
name: 'Sovereign',
apiAddress: 'https://api-sovereign-test.elrond.ro',
gatewayUrl: '',
sampleAuthenticatedDomains: ['https://api-sovereign-test.elrond.ro'],
sovereignContractAddress:
'erd1qqqqqqqqqqqqqpgqfcm6l6rd42hwhskmk4thlp9kz58npfq50gfqdrthqa',
WEGLDid: 'WEGLD-bd4d79'
},
{
default: false,
id: EnvironmentsEnum.testnet,
name: 'Testnet',
apiAddress: 'https://testnet-api.multiversx.com',
gatewayUrl: '',
sampleAuthenticatedDomains: ['https://testnet-api.multiversx.com'],
sovereignContractAddress: '',
WEGLDid: ''
}
];
Loading

0 comments on commit 58148bb

Please sign in to comment.