This repository has been archived by the owner on Apr 19, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #302 from darwinia-network/connect-to-wallet
Connect wallet
- Loading branch information
Showing
12 changed files
with
603 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
import React, {useRef, useState} from 'react'; | ||
import styles from './styles.module.css'; | ||
import Notification from "../Notification"; | ||
import Dialog from "../Dialog"; | ||
|
||
|
||
|
||
const networksList = [ | ||
{ | ||
chainId: "0x2e", | ||
chainName: "Darwinia Smart Chain", | ||
nativeCurrency: { | ||
name: "RING", | ||
symbol: "RING", | ||
decimals: 18, | ||
}, | ||
rpcUrls: ["https://rpc.darwinia.network"], | ||
blockExplorerUrls: ["https://darwinia.subscan.io/"], | ||
}, | ||
{ | ||
chainId: "0x2d", | ||
chainName: "Pangoro Smart Chain", | ||
nativeCurrency: { | ||
name: "ORING", | ||
symbol: "ORING", | ||
decimals: 18, | ||
}, | ||
rpcUrls: ["https://pangoro-rpc.darwinia.network"], | ||
blockExplorerUrls: ["https://pangoro.subscan.io/"], | ||
}, | ||
]; | ||
|
||
const ellipsisAddress = (address) => { | ||
return `${address.substring(0, 6)}...${address.substring(address.length - 4)}`; | ||
}; | ||
|
||
const ConnectWalletButton = () => { | ||
const [connected, setConnected] = useState(null); | ||
const provider = useRef(); | ||
const notificationRef = useRef(null); | ||
const dialogRef = useRef(null); | ||
const handleConnectToWallet = () => { | ||
if(!dialogRef.current) { | ||
return; | ||
} | ||
dialogRef.current.show(); | ||
} | ||
|
||
const getMetamaskAccounts = async (networkIndex, chainName) => { | ||
const accounts = await provider.current.request({ | ||
method: "eth_requestAccounts", | ||
}); | ||
setConnected({ | ||
index: networkIndex, | ||
account: accounts[0], | ||
chainName, | ||
}); | ||
return true; | ||
} | ||
|
||
const onSelectNetwork = async (index) => { | ||
if (!provider.current) { | ||
provider.current = window.ethereum; | ||
} | ||
|
||
if (typeof provider.current !== 'undefined') { | ||
// Metamask is installed | ||
const networkParams = networksList[index]; | ||
try { | ||
const response = await provider.current.request({ | ||
method: "wallet_switchEthereumChain", | ||
params: [{chainId: networkParams.chainId}], | ||
}); | ||
// chainId already exists in Metamask | ||
if (!response) { | ||
await getMetamaskAccounts(index, networkParams.chainName); | ||
} | ||
} catch (switchNetworkError) { | ||
if (switchNetworkError.code === 4902) { | ||
// chainId doesn't exist in Metamask, add it with wallet_addEthereumChain | ||
try { | ||
const response = await provider.current.request({ | ||
method: "wallet_addEthereumChain", | ||
params: [ | ||
{ | ||
chainId: networkParams.chainId, | ||
chainName: networkParams.chainName, | ||
nativeCurrency: networkParams.nativeCurrency, | ||
rpcUrls: [...networkParams.rpcUrls], | ||
blockExplorerUrls: [...networkParams.blockExplorerUrls], | ||
}, | ||
], | ||
}); | ||
if (!response) { | ||
await getMetamaskAccounts(index, networkParams.chainName); | ||
} | ||
} catch (addNetworkError) { | ||
notificationRef.current.show({ | ||
title: "Oops, something wrong", | ||
message: (addNetworkError).message, | ||
type: 'danger' | ||
}); | ||
} | ||
} else { | ||
notificationRef.current.show({ | ||
title: "Oops, something wrong", | ||
message: (switchNetworkError).message, | ||
type: 'danger' | ||
}); | ||
} | ||
} | ||
} else { | ||
// Metamask is not installed | ||
notificationRef.current.show({ | ||
title: "Oops, something is not quite right.", | ||
message: ( | ||
<p> | ||
It looks like MetaMask hasn't been installed. Please{" "} | ||
<a target="_blank" rel="noopener noreferrer" href="https://metamask.io/download.html"> | ||
install MetaMask | ||
</a>{" "} | ||
and try again. | ||
</p> | ||
), | ||
}); | ||
} | ||
} | ||
|
||
|
||
const dialogBody = () => { | ||
return ( | ||
<ul> | ||
{ | ||
networksList.map((item, index) => { | ||
return ( | ||
<li key={index} className={styles.networkItem}> | ||
{ | ||
connected && connected.index === index ? ( | ||
<span className={styles.connectedTo}> | ||
Connected to {connected.chainName}: {ellipsisAddress(connected.account)} | ||
</span> | ||
): ( | ||
<button className={styles.networkOption} onClick={() => { | ||
onSelectNetwork(index) | ||
}}>{item.chainName}</button> | ||
) | ||
} | ||
</li> | ||
) | ||
}) | ||
} | ||
</ul> | ||
) | ||
} | ||
|
||
return ( | ||
<div> | ||
<Notification ref={notificationRef}/> | ||
<Dialog ref={dialogRef} | ||
title={<div className={styles.chainSelectModalTitle}>Please select a network to connect</div>} | ||
body={dialogBody()}/> | ||
<button className={styles.connectWalletBtn} onClick={() => { | ||
handleConnectToWallet() | ||
}}>Connect Wallet | ||
</button> | ||
</div> | ||
) | ||
} | ||
|
||
export default ConnectWalletButton; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
.connectWalletBtn { | ||
outline: none; | ||
border: 1px solid rgb(216,0,115); | ||
border-radius: 0.25rem; | ||
padding: 6px 15px; | ||
background: transparent; | ||
color: rgb(216,0,115); | ||
margin-right: 10px; | ||
font-size: medium; | ||
} | ||
.connectWalletBtn:hover { | ||
opacity: 0.7; | ||
cursor: pointer; | ||
} | ||
.chainSelectModalTitle { | ||
font-weight: 400; | ||
font-size: 19px; | ||
} | ||
.networkItem { | ||
margin: 10px 0; | ||
} | ||
.networkOption { | ||
padding: 8px 20px; | ||
display: inline-block; | ||
border: 1px solid rgb(216,0,115); | ||
border-radius: 0.25rem; | ||
min-width: 110px; | ||
text-align: center; | ||
background: transparent; | ||
font-size: 16px; | ||
} | ||
.networkOption:hover { | ||
opacity: 0.7; | ||
cursor: pointer; | ||
} | ||
.connectedTo { | ||
padding: 4.55px 0; | ||
display: inline-block; | ||
} | ||
|
||
@media (max-width: 996px) { | ||
.connectWalletBtn { | ||
margin-right: 0; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import React, {forwardRef, useImperativeHandle, useState} from "react"; | ||
import styles from './styles.module.css'; | ||
import {CSSTransition} from "react-transition-group"; | ||
|
||
const Dialog = forwardRef(({title, body}, ref) => { | ||
const [isVisible, setVisible] = useState(false); | ||
|
||
const show = () => { | ||
setVisible(true); | ||
} | ||
|
||
const hide = () => { | ||
setVisible(false); | ||
} | ||
|
||
useImperativeHandle(ref, ()=> { | ||
return { | ||
show | ||
} | ||
}) | ||
|
||
return ( | ||
<CSSTransition unmountOnExit timeout={200} in={isVisible} classNames={{ | ||
enter: styles.enter, | ||
enterActive: styles.enterActive, | ||
enterDone: styles.enterDone, | ||
exit: styles.exit, | ||
exitActive: styles.exitActive, | ||
exitDone: styles.exitDone | ||
}}> | ||
<div onClick={()=> {hide()}} className={styles.wrapper}> | ||
<div onClick={(e)=>{e.stopPropagation()}} className={`${styles.enterDone} ${styles.content}`}> | ||
<div className={styles.title}> | ||
{title} | ||
<div onClick={()=>{hide()}} className={styles.closeBtn}> | ||
<svg viewBox="64 64 896 896" focusable="false" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg> | ||
</div> | ||
</div> | ||
<div className={styles.body}>{body}</div> | ||
</div> | ||
</div> | ||
</CSSTransition> | ||
); | ||
}) | ||
|
||
export default Dialog |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
.wrapper { | ||
position: fixed; | ||
top: 0; | ||
right: 0; | ||
bottom: 0; | ||
left: 0; | ||
overflow: auto; | ||
outline: 0; | ||
background: rgba(0, 0, 0, 0.45); | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
z-index: 200; | ||
} | ||
html[data-theme='dark'] .content { | ||
background: #444444; | ||
color: white; | ||
} | ||
.content { | ||
position: absolute; | ||
width: 85%; | ||
max-width: 520px; | ||
background: white; | ||
border-radius: 8px; | ||
} | ||
.title { | ||
text-transform: capitalize; | ||
font-weight: bold; | ||
text-align: center; | ||
border-bottom: 1px solid #f0f0f0; | ||
padding: 15px 45px; | ||
position: relative; | ||
} | ||
html[data-theme='dark'] .title { | ||
border-bottom-color: #606770; | ||
} | ||
.closeBtn { | ||
position: absolute; | ||
right: 15px; | ||
top: 50%; | ||
transform: translateY(-50%); | ||
} | ||
.closeBtn:hover { | ||
opacity: 0.7; | ||
cursor: pointer; | ||
} | ||
.body { | ||
padding: 10px; | ||
} | ||
|
||
.enter { | ||
opacity: 0; | ||
} | ||
.enterActive { | ||
transition: opacity 200ms ease-in-out; | ||
opacity: 1; | ||
} | ||
.enterDone { | ||
opacity: 1; | ||
} | ||
.exit { | ||
opacity: 1; | ||
} | ||
.exitActive { | ||
transition: opacity 200ms ease-in-out; | ||
opacity: 0; | ||
} | ||
.exitDone { | ||
opacity: 0; | ||
} | ||
.enter .content { | ||
transform: scale(0.5); | ||
} | ||
.enterActive .content { | ||
transform: scale(1.15); | ||
transition: transform 150ms ease-in-out; | ||
transition-delay: 50ms; | ||
} | ||
.enterDone .content { | ||
transform: scale(1); | ||
transition: transform 150ms ease-in-out; | ||
} | ||
.exit .content { | ||
transform: scale(1); | ||
} | ||
.exitActive .content { | ||
transform: scale(0.5); | ||
transition: transform 150ms ease-in-out; | ||
} | ||
.exitDone .content { | ||
transform: scale(0.5); | ||
transition: transform 150ms ease-in-out; | ||
} |
Oops, something went wrong.