Skip to content

Commit

Permalink
feat: implement network switch in UI (#175)
Browse files Browse the repository at this point in the history
* feat: implement network switch in UI

* feat: apply enableAutherize in switch network
  • Loading branch information
stanleyyconsensys authored Nov 28, 2023
1 parent 6907f29 commit 4b4ace7
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 20 deletions.
18 changes: 10 additions & 8 deletions packages/starknet-snap/src/switchNetwork.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,16 @@ export async function switchNetwork(params: ApiParams) {
}
const components = getNetworkTxt(network);

const response = await wallet.request({
method: 'snap_dialog',
params: {
type: DialogType.Confirmation,
content: panel([heading('Do you want to switch to this network?'), ...components]),
},
});
if (!response) return false;
if (requestParamsObj.enableAutherize === true) {
const response = await wallet.request({
method: 'snap_dialog',
params: {
type: DialogType.Confirmation,
content: panel([heading('Do you want to switch to this network?'), ...components]),
},
});
if (!response) return false;
}

logger.log(`switchNetwork: network:\n${toJson(network, 2)}`);
await setCurrentNetwork(network, wallet, saveMutex, state);
Expand Down
15 changes: 9 additions & 6 deletions packages/starknet-snap/src/types/snapApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export interface ExtractPublicKeyRequestParams extends BaseRequestParams {
userAddress: string;
}

export interface SignMessageRequestParams extends SignRequestParams, BaseRequestParams {
export interface SignMessageRequestParams extends Autherizeable, SignRequestParams, BaseRequestParams {
typedDataMessage: typedData.TypedData;
}

Expand Down Expand Up @@ -181,25 +181,28 @@ export interface RpcV4GetTransactionReceiptResponse {
finality_status?: string;
}

export interface Autherizeable {
enableAutherize?: boolean;
}

export interface SignRequestParams {
signerAddress: string;
enableAutherize?: boolean;
}

export interface SignTransactionRequestParams extends SignRequestParams, BaseRequestParams {
export interface SignTransactionRequestParams extends Autherizeable, SignRequestParams, BaseRequestParams {
transactions: Call[];
transactionsDetail: InvocationsSignerDetails;
abis?: Abi[];
}

export interface SignDeployAccountTransactionRequestParams extends SignRequestParams, BaseRequestParams {
export interface SignDeployAccountTransactionRequestParams extends Autherizeable, SignRequestParams, BaseRequestParams {
transaction: DeployAccountSignerDetails;
}

export interface SignDeclareTransactionRequestParams extends SignRequestParams, BaseRequestParams {
export interface SignDeclareTransactionRequestParams extends Autherizeable, SignRequestParams, BaseRequestParams {
transaction: DeclareSignerDetails;
}

export interface SwitchNetworkRequestParams extends BaseRequestParams {
export interface SwitchNetworkRequestParams extends Autherizeable, BaseRequestParams {
chainId: string;
}
16 changes: 16 additions & 0 deletions packages/starknet-snap/test/src/switchNetwork.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ describe('Test function: switchNetwork', function () {
it('should switch the network correctly', async function () {
const requestObject: SwitchNetworkRequestParams = {
chainId: STARKNET_MAINNET_NETWORK.chainId,
enableAutherize: true,
};
apiParams.requestParams = requestObject;
const result = await switchNetwork(apiParams);
Expand All @@ -54,9 +55,23 @@ describe('Test function: switchNetwork', function () {
expect(state.networks.length).to.be.eql(2);
});

it('should skip autherize when enableAutherize is false or omit', async function () {
const requestObject: SwitchNetworkRequestParams = {
chainId: STARKNET_MAINNET_NETWORK.chainId,
};
apiParams.requestParams = requestObject;
const result = await switchNetwork(apiParams);
expect(result).to.be.eql(true);
expect(stateStub).to.be.calledOnce;
expect(dialogStub).to.be.callCount(0);
expect(state.currentNetwork).to.be.eql(STARKNET_MAINNET_NETWORK);
expect(state.networks.length).to.be.eql(2);
});

it('should throw an error if network not found', async function () {
const requestObject: SwitchNetworkRequestParams = {
chainId: '123',
enableAutherize: true,
};
apiParams.requestParams = requestObject;
let result;
Expand All @@ -76,6 +91,7 @@ describe('Test function: switchNetwork', function () {
sandbox.stub(snapUtils, 'setCurrentNetwork').throws(new Error());
const requestObject: SwitchNetworkRequestParams = {
chainId: STARKNET_TESTNET_NETWORK.chainId,
enableAutherize: true,
};
apiParams.requestParams = requestObject;
let result;
Expand Down
13 changes: 9 additions & 4 deletions packages/wallet-ui/src/components/ui/organism/Menu/Menu.view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { Menu } from '@headlessui/react';
import { theme } from 'theme/default';
import { Radio, Skeleton } from '@mui/material';
import { useAppDispatch, useAppSelector } from 'hooks/redux';
import { useStarkNetSnap } from 'services';
import { setWalletConnection, setForceReconnect, resetWallet, clearAccounts } from 'slices/walletSlice';
import { resetNetwork, setActiveNetwork } from 'slices/networkSlice';

Expand All @@ -27,12 +28,16 @@ interface IProps extends HTMLAttributes<HTMLElement> {
}

export const MenuView = ({ connected, ...otherProps }: IProps) => {
const { switchNetwork } = useStarkNetSnap();
const networks = useAppSelector((state) => state.networks);
const dispatch = useAppDispatch();

const changeNetwork = (network: number) => {
dispatch(clearAccounts());
dispatch(setActiveNetwork(network));
const changeNetwork = async (network: number, chainId: string) => {
const result = await switchNetwork(chainId);
if (result) {
dispatch(clearAccounts());
dispatch(setActiveNetwork(network));
}
};
/*
There is no way to disconnect the snap from a dapp it must be done from MetaMask.
Expand Down Expand Up @@ -80,7 +85,7 @@ export const MenuView = ({ connected, ...otherProps }: IProps) => {
<MenuSection>
{networks.items.map((network, index) => (
<Menu.Item key={network.chainId + '_' + index}>
<NetworkMenuItem onClick={() => changeNetwork(index)}>
<NetworkMenuItem onClick={() => changeNetwork(index, network.chainId)}>
<Radio
checked={Number(networks.activeNetwork) === index}
name="radio-buttons"
Expand Down
52 changes: 50 additions & 2 deletions packages/wallet-ui/src/services/useStarkNetSnap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ import { Transaction } from 'types';
import { ethers } from 'ethers';
import { getAssetPriceUSD } from './coinGecko';
import semver from 'semver/preload';
import { setActiveNetwork } from 'slices/networkSlice';

export const useStarkNetSnap = () => {
const dispatch = useAppDispatch();
const { loader } = useAppSelector((state) => state.UI);
const { transactions, erc20TokenBalances, provider } = useAppSelector((state) => state.wallet);
const { activeNetwork } = useAppSelector((state) => state.networks);
const snapId = process.env.REACT_APP_SNAP_ID ? process.env.REACT_APP_SNAP_ID : 'local:http://localhost:8081/';
const snapVersion = process.env.REACT_APP_SNAP_VERSION ? process.env.REACT_APP_SNAP_VERSION : '*';
const minSnapVersion = process.env.REACT_APP_MIN_SNAP_VERSION ? process.env.REACT_APP_MIN_SNAP_VERSION : '2.0.1';
Expand Down Expand Up @@ -199,7 +199,10 @@ export const useStarkNetSnap = () => {
if (nets.length === 0) {
return;
}
const chainId = nets[activeNetwork].chainId;
const net = await getCurrentNetwork();
const idx = nets.findIndex((e) => e.chainId === net.chainId);
dispatch(setActiveNetwork(idx));
const chainId = net.chainId;
await getWalletData(chainId, nets);
} catch (err: any) {
if (err.code && err.code === 4100) {
Expand Down Expand Up @@ -529,6 +532,49 @@ export const useStarkNetSnap = () => {
}
};

const switchNetwork = async (chainId: string) => {
dispatch(enableLoadingWithMessage('Switching Network...'));
try {
const result = await provider.request({
method: 'wallet_invokeSnap',
params: {
snapId,
request: {
method: 'starkNet_switchNetwork',
params: {
...defaultParam,
chainId,
},
},
},
});
dispatch(disableLoading());
return result;
} catch (err) {
dispatch(disableLoading());
return false;
}
};

const getCurrentNetwork = async () => {
try {
return await provider.request({
method: 'wallet_invokeSnap',
params: {
snapId,
request: {
method: 'starkNet_getCurrentNetwork',
params: {
...defaultParam,
},
},
},
});
} catch (err) {
throw err;
}
};

return {
connectToSnap,
getNetworks,
Expand All @@ -547,6 +593,8 @@ export const useStarkNetSnap = () => {
initSnap,
getWalletData,
refreshTokensUSDPrice,
switchNetwork,
getCurrentNetwork,
satisfiesVersion: oldVersionDetected,
};
};

0 comments on commit 4b4ace7

Please sign in to comment.