Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert from MetaMask -> AuthZN integration #14

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions .env.development
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
VITE_SAPPHIRE_JSONRPC=https://testnet.sapphire.oasis.dev
VITE_SAPPHIRE_CHAIN_ID=0x5aff
9 changes: 6 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Web3ContextProvider } from './providers/Web3Provider'
import { ConnectWallet } from './pages/ConnectWallet'
import { WrapFormContextProvider } from './providers/WrapFormProvider'
import { Transaction } from './pages/Transaction'
import { ConfigContextProvider } from './providers/ConfigProvider'

const router = createHashRouter([
{
Expand Down Expand Up @@ -33,7 +34,9 @@ const router = createHashRouter([
])

export const App: FC = () => (
<Web3ContextProvider>
<RouterProvider router={router} />
</Web3ContextProvider>
<ConfigContextProvider>
<Web3ContextProvider>
<RouterProvider router={router} />
</Web3ContextProvider>
</ConfigContextProvider>
)
16 changes: 14 additions & 2 deletions src/components/Account/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import classes from './index.module.css'
import { FC } from 'react'
import { FC, MouseEventHandler } from 'react'
import { StringUtils } from '../../utils/string.utils'
import { JazzIcon } from '../JazzIcon'
import { useMediaQuery } from 'react-responsive'
Expand All @@ -22,10 +22,22 @@ export const Account: FC<Props> = ({ address, networkName }) => {
}
}

const handleCopyAddressToClipboard: MouseEventHandler<HTMLParagraphElement> = async (e) => {
e.preventDefault()
e.stopPropagation()

try {
await navigator.clipboard.writeText(address)
window.alert('Copied to clipboard!')
} catch (ex) {
// Ignore
}
}

return (
<div className={classes.account} onClick={handleAccountClick}>
<JazzIcon size={isXlScreen ? 60 : 30} address={address} />
<p className={classes.accountDetails}>
<p onClick={handleCopyAddressToClipboard} className={classes.accountDetails}>
<abbr title={address} className={classes.accountAddress}>
{StringUtils.truncateAddress(address)}
</abbr>
Expand Down
4 changes: 2 additions & 2 deletions src/components/WrapForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ export const WrapForm: FC = () => {

try {
const amountBN = utils.parseUnits(value || '0', 'ether')
const txReceipt = await submit(amountBN)
const txHash = await submit(amountBN)

navigate(`/tx/${txReceipt.hash}?amount=${value}&action=${formType}`)
navigate(`/tx/${txHash}?amount=${value}&action=${formType}`)
} catch (ex) {
setError((ex as Error)?.message || JSON.stringify(ex))
}
Expand Down
1 change: 1 addition & 0 deletions src/constants/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ export const NETWORKS: Record<number, NetworkConfiguration> = {
}

export const METAMASK_HOME_PAGE = 'https://metamask.io/'
export const FAUCET_PAGE = 'https://faucet.testnet.oasis.dev/?paratime=sapphire'
11 changes: 11 additions & 0 deletions src/hooks/useConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { useContext } from 'react'
import { ConfigContext } from '../providers/ConfigProvider'

export const useConfig = () => {
const value = useContext(ConfigContext)
if (value === undefined) {
throw new Error('[useConfig] Component not wrapped within a Provider')
}

return value
}
5 changes: 5 additions & 0 deletions src/pages/ConnectWallet/index.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
margin-bottom: 34dvh;
}

.haveAccount {
margin: 0.5rem 0;
text-align: center;
}

.installMetaMaskBtn {
margin-bottom: 1.5rem;
}
Expand Down
102 changes: 26 additions & 76 deletions src/pages/ConnectWallet/index.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,34 @@
import { FC, useEffect, useState } from 'react'
import { FC, useState } from 'react'
import classes from './index.module.css'
import { Button } from '../../components/Button'
import { UnknownNetworkError } from '../../utils/errors'
import { Alert } from '../../components/Alert'
import { METAMASK_HOME_PAGE } from '../../constants/config'
import { AuthData, login, register } from '../../utils/authzn'
import { useWeb3 } from '../../hooks/useWeb3'

enum AuthType {
Login,
Register,
}

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

useEffect(() => {
const init = async () => {
setIsLoading(true)
setHasMetaMaskWallet(await isMetaMaskInstalled())
setIsLoading(false)
}

init()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [window.ethereum])

const handleConnectWallet = async () => {
const handleConnectWallet = async (type: AuthType) => {
setIsLoading(true)
try {
await connectWallet()
let authData: AuthData

if (type === AuthType.Register) {
authData = await register()
} else {
authData = await login()
}

await connectWallet(authData)
} catch (ex) {
if (ex instanceof UnknownNetworkError) {
setIsUnknownNetwork(true)
Expand All @@ -39,82 +40,31 @@ export const ConnectWallet: FC = () => {
}
}

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

const handleInstallMetaMask = async () => {
window.open(METAMASK_HOME_PAGE, '_blank', 'noopener,noreferrer')
}

return (
<>
{!hasMetaMaskWallet && (
{!isUnknownNetwork && (
<div>
<p className={classes.subHeader}>
Quickly wrap your ROSE into wROSE and vice versa with the (un)wrap ROSE tool.
<br />
MetaMask not detected, please install it.
Please connect with your AUTHZN account to get started.
</p>

<Button
className={classes.installMetaMaskBtn}
onClick={handleInstallMetaMask}
fullWidth
disabled={isLoading}
>
Install MetaMask
<Button onClick={() => handleConnectWallet(AuthType.Login)} disabled={isLoading} fullWidth>
Login
</Button>
<p className={classes.haveAccount}>Not signed up yet?</p>
<Button
variant="secondary"
onClick={() => setHasMetaMaskWallet(true)}
onClick={() => handleConnectWallet(AuthType.Register)}
disabled={isLoading}
fullWidth
>
Skip
Register
</Button>
{error && <Alert variant="danger">{error}</Alert>}
</div>
)}
{hasMetaMaskWallet && (
<>
{!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={handleSwitchNetwork} disabled={isLoading} fullWidth>
Switch Network
</Button>
{error && <Alert variant="danger">{error}</Alert>}
</div>
)}
</>
)}
</>
)
}
4 changes: 2 additions & 2 deletions src/pages/Wrapper/index.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
margin-bottom: 1.625rem;
}

.importWRoseBtn.importWRoseBtn {
.testTokensBtn.testTokensBtn {
display: flex;
justify-content: center;
padding: 0.5rem;
Expand All @@ -29,7 +29,7 @@
margin-bottom: 4.85rem;
}

.importWRoseBtn.importWRoseBtn {
.testTokensBtn.testTokensBtn {
justify-content: flex-end;
margin-left: auto;
}
Expand Down
16 changes: 8 additions & 8 deletions src/pages/Wrapper/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { BigNumber } from 'ethers'
import { Button } from '../../components/Button'
import { NumberUtils } from '../../utils/number.utils'
import { WrapForm } from '../../components/WrapForm'
import { useWeb3 } from '../../hooks/useWeb3'
import { FAUCET_PAGE } from '../../constants/config'
import { useWrapForm } from '../../hooks/useWrapForm'
import { WrapFormType } from '../../utils/types'

Expand Down Expand Up @@ -33,10 +33,6 @@ const percentageList: PercentageEntry[] = [
]

export const Wrapper: FC = () => {
const {
state: { account },
addTokenToWallet,
} = useWeb3()
const {
state: { isLoading, balance, wRoseBalance, formType },
init,
Expand All @@ -47,7 +43,7 @@ export const Wrapper: FC = () => {
useEffect(() => {
init()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [account])
}, [])

const handlePercentageCalc = (percentage: BigNumber) => {
if (formType === WrapFormType.WRAP) {
Expand All @@ -66,13 +62,17 @@ export const Wrapper: FC = () => {
}
}

const navigateToFaucet = () => {
window.open(FAUCET_PAGE, '_blank', 'noopener,noreferrer')
}

return (
<div>
<div className={classes.subHeader}>
<p>Quickly wrap your ROSE into wROSE and vice versa with the (un)wrap ROSE tool.</p>

<Button className={classes.importWRoseBtn} onClick={addTokenToWallet}>
Import WROSE to Wallet
<Button className={classes.testTokensBtn} onClick={navigateToFaucet}>
Request test tokens
</Button>
</div>

Expand Down
40 changes: 40 additions & 0 deletions src/providers/ConfigProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { createContext, FC, PropsWithChildren, useEffect, useState } from 'react'

export interface AppConfig {
sapphireJsonRpc: string
sapphireChainId: number
}

interface ConfigProviderState extends AppConfig {}

interface ConfigProviderContext {
readonly state: ConfigProviderState
}

const configProviderInitialState: ConfigProviderState = {
sapphireJsonRpc: '',
sapphireChainId: -1,
}

export const ConfigContext = createContext<ConfigProviderContext>({} as ConfigProviderContext)

export const ConfigContextProvider: FC<PropsWithChildren> = ({ children }) => {
const [state, setState] = useState<ConfigProviderState>({
...configProviderInitialState,
})

useEffect(() => {
const { VITE_SAPPHIRE_JSONRPC, VITE_SAPPHIRE_CHAIN_ID } = import.meta.env

setState({
sapphireJsonRpc: VITE_SAPPHIRE_JSONRPC,
sapphireChainId: parseInt(VITE_SAPPHIRE_CHAIN_ID, 16),
})
}, [])

const providerState: ConfigProviderContext = {
state,
}

return <ConfigContext.Provider value={providerState}>{children}</ConfigContext.Provider>
}
Loading