Skip to content

Commit

Permalink
Add switch network page
Browse files Browse the repository at this point in the history
  • Loading branch information
lubej committed Nov 15, 2023
1 parent e9e3a07 commit f463153
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 20 deletions.
3 changes: 2 additions & 1 deletion src/components/Alert/index.module.css
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
.alert {
padding: .25rem;
padding: .5rem .25rem;
background-color: white;
font-size: 14px;
line-height: 120%;
border-radius: 10px;
margin-top: 1rem;
text-align: center;
word-wrap: break-word;
}

.alertDanger {
Expand Down
2 changes: 1 addition & 1 deletion src/components/Layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const Layout: FC<PropsWithChildren> = () => {
const { pathname } = useLocation()
const navigate = useNavigate()

// TODO: Unable to use hooks inside loader in react-router-dom
// TODO: Unable to use hooks inside loader in react-router-dom, needs refactoring
useEffect(() => {
// Route guard
// Ignore for tx
Expand Down
53 changes: 43 additions & 10 deletions src/pages/ConnectWallet/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,64 @@ import { FC, useState } from 'react'
import classes from './index.module.css'
import { useWeb3 } from '../../providers/Web3Provider'
import { Button } from '../../components/Button'
import { UnknownNetworkError } from '../../utils/errors'
import { Alert } from '../../components/Alert'

export const ConnectWallet: FC = () => {
const { connectWallet } = useWeb3()
const { connectWallet, switchNetwork } = useWeb3()
const [isLoading, setIsLoading] = useState(false)
const [error, setError] = useState('')
const [isUnknownNetwork, setIsUnknownNetwork] = useState(false)

const handleConnectWallet = async () => {
setIsLoading(true)
try {
await connectWallet()
} catch (ex) {
console.error(ex)
if (ex instanceof UnknownNetworkError) {
setIsUnknownNetwork(true)
} else {
setError(ex?.message || JSON.stringify(ex))
}
} finally {
setIsLoading(false)
}
}

const handleSwitchNetwork = async () => {
setIsLoading(true)
try {
await switchNetwork()
setIsUnknownNetwork(false)
} catch (ex) {
setError(ex?.message || JSON.stringify(ex))
} finally {
setIsLoading(false)
}
}

return (
<div>
<p className={classes.subHeader}>
Quickly wrap your ROSE into wROSE and vice versa with the (un)wrap ROSE tool.
<br />
Please connect your wallet to get started.
</p>
<>
{!isUnknownNetwork && (<div>
<p className={classes.subHeader}>
Quickly wrap your ROSE into wROSE and vice versa with the (un)wrap ROSE tool.
<br />
Please connect your wallet to get started.
</p>

<Button onClick={handleConnectWallet} disabled={isLoading} fullWidth>Connect wallet</Button>
{error && <Alert variant='danger'>{error}</Alert>}
</div>)}
{isUnknownNetwork && (<div>
<p className={classes.subHeader}>
Quickly wrap your ROSE into wROSE and vice versa with the (un)wrap ROSE tool.
<br />
Please switch to another network to get started.
</p>

<Button onClick={handleConnectWallet} disabled={isLoading} fullWidth>Connect wallet</Button>
</div>
<Button onClick={handleSwitchNetwork} disabled={isLoading} fullWidth>Switch Network</Button>
{error && <Alert variant='danger'>{error}</Alert>}
</div>)}
</>
)
}
55 changes: 52 additions & 3 deletions src/providers/Web3Provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { WROSE_CONTRACT_BY_NETWORK } from '../constants/config'
// https://repo.sourcify.dev/contracts/full_match/23295/0xB759a0fbc1dA517aF257D5Cf039aB4D86dFB3b94/
import WrappedRoseMetadata from '../contracts/WrappedROSE.json'
import { TransactionResponse } from '@ethersproject/abstract-provider'
import { UnknownNetworkError } from '../utils/errors'

const MAX_GAS_PRICE = utils.parseUnits('100', 'gwei').toNumber()
const MAX_GAS_LIMIT = 100000
Expand All @@ -28,6 +29,7 @@ interface Web3ProviderContext {
wrap: (amount: string) => Promise<TransactionResponse>
unwrap: (amount: string) => Promise<TransactionResponse>
connectWallet: () => Promise<void>
switchNetwork: () => Promise<void>
getBalance: () => Promise<BigNumber>
getBalanceOfWROSE: () => Promise<BigNumber>
getTransaction: (txHash: string) => Promise<TransactionResponse>
Expand Down Expand Up @@ -56,8 +58,7 @@ export const Web3ContextProvider: FC<PropsWithChildren> = ({ children }) => {
const network = await sapphireEthProvider.getNetwork()

if (!(network.chainId in WROSE_CONTRACT_BY_NETWORK)) {
// TODO: Propagate unsupported network error
throw new Error('[Web3Context] Unsupported network!')
return Promise.reject(new UnknownNetworkError('Unknown network!'))
}

const contractAddress = WROSE_CONTRACT_BY_NETWORK[network.chainId]
Expand Down Expand Up @@ -117,6 +118,53 @@ export const Web3ContextProvider: FC<PropsWithChildren> = ({ children }) => {
await _init(account)
}

const _addNetwork = async (chainId: number) => {
if (chainId === 0x5afe) {

// Default to Sapphire Mainnet
await window.ethereum.request?.({
method: 'wallet_addEthereumChain',
params: [
{
chainId: '0x5afe',
chainName: 'Sapphire Mainnet',
nativeCurrency: {
name: 'ROSE',
symbol: 'ROSE',
decimals: 18,
},
rpcUrls: ['https://sapphire.oasis.io/', 'wss://sapphire.oasis.io/ws'],
blockExplorerUrls: ['https://explorer.oasis.io/mainnet/sapphire'],
},
],
})
}

throw new Error('Unable to automatically add the network, please do it manually!')
}

const switchNetwork = async (toNetworkChainId = 0x5afe) => {
const ethProvider = new ethers.providers.Web3Provider(window.ethereum)
const sapphireEthProvider = sapphire.wrap(ethProvider) as (ethers.providers.Web3Provider & sapphire.SapphireAnnex)

const network = await sapphireEthProvider.getNetwork()

if (network.chainId === toNetworkChainId) return
try {
await window.ethereum.request?.({
method: 'wallet_switchEthereumChain',
params: [{ chainId: utils.hexlify(toNetworkChainId) }],
})
} catch (e) {
// Chain is not available in the Metamask
if (e?.code !== 4902) {
throw e
} else {
_addNetwork(toNetworkChainId)
}
}
}

const wrap = async (amount) => {
if (!amount) {
throw new Error('[amount] is required!')
Expand Down Expand Up @@ -164,11 +212,12 @@ export const Web3ContextProvider: FC<PropsWithChildren> = ({ children }) => {
const providerState: Web3ProviderContext = {
state,
connectWallet,
switchNetwork,
wrap,
unwrap,
getBalance,
getBalanceOfWROSE,
getTransaction
getTransaction,
}

return <Web3Context.Provider value={providerState}>{children}</Web3Context.Provider>
Expand Down
19 changes: 14 additions & 5 deletions src/providers/WrapFormProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export const WrapFormContextProvider: FC<PropsWithChildren> = ({ children }) =>
amount: amountBN,
}))
} catch (ex) {
// Ignore if invalid number
console.error(ex)
}
}
Expand All @@ -94,16 +95,24 @@ export const WrapFormContextProvider: FC<PropsWithChildren> = ({ children }) =>
const submit = async (amount: BigNumber) => {
_setIsLoading(true)

const { formType, wRoseBalance, balance } = state
const { formType } = state

let receipt: TransactionResponse | null = null

if (formType === WrapFormType.WRAP) {

receipt = await wrap(amount.toString())
try {
receipt = await wrap(amount.toString())
} catch (ex) {
_setIsLoading(false)
throw ex
}
} else if (formType === WrapFormType.UNWRAP) {

receipt = await unwrap(amount.toString())
try {
receipt = await unwrap(amount.toString())
} catch (ex) {
_setIsLoading(false)
throw ex
}
} else {
_setIsLoading(false)
return Promise.reject(new Error('[formType] Invalid form type'))
Expand Down
5 changes: 5 additions & 0 deletions src/utils/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export class UnknownNetworkError extends Error {
constructor(message: string) {
super(message);
}
}

0 comments on commit f463153

Please sign in to comment.