1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

Add Portis wallet connection (#291)

* add portis

* library loading tinkering

* bump packages

* typings fix

* pip as addon

* remove setuptools

* revert typings fix

* modal styling

* show portis button

* provider name workaround

* for faulty getInjectedProviderName()
* fixes https://github.com/oceanprotocol/market/issues/332

* more usage of provider info object

* output respective wallet logos

* add network switcher for Portis

* add functionality

* prototype for portis network switching

* improve user experience when reconnecting to cached provider

* support mainnet only, leave networking switching code commented out
This commit is contained in:
Matthias Kretschmann 2021-01-29 13:40:54 +01:00 committed by GitHub
parent ad864cc249
commit a760935564
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 911 additions and 487 deletions

View File

@ -3,4 +3,5 @@ GATSBY_NETWORK="rinkeby"
#GATSBY_INFURA_PROJECT_ID="xxx"
#GATSBY_MARKET_FEE_ADDRESS="0xxx"
#GATSBY_ANALYTICS_ID="xxx"
#GATSBY_ANALYTICS_ID="xxx"
#GATSBY_PORTIS_ID="xxx"

View File

@ -32,5 +32,8 @@ module.exports = {
classNameDark: 'dark',
classNameLight: 'light',
storageKey: 'oceanDarkMode'
}
},
// Wallets
portisId: process.env.GATSBY_PORTIS_ID || 'xxx'
}

1207
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -30,12 +30,12 @@
"@oceanprotocol/lib": "^0.10.1",
"@oceanprotocol/react": "^0.5.1",
"@oceanprotocol/typographies": "^0.1.0",
"@portis/web3": "^3.0.3",
"@sindresorhus/slugify": "^1.0.0",
"@tippyjs/react": "^4.2.0",
"@toruslabs/torus-embed": "^1.9.5",
"@types/classnames": "^2.2.11",
"@vercel/node": "^1.8.5",
"@walletconnect/web3-provider": "^1.3.3",
"@walletconnect/web3-provider": "^1.3.4",
"axios": "^0.21.1",
"chart.js": "^2.9.4",
"classnames": "^2.2.6",

View File

@ -11,6 +11,7 @@
margin: 0;
transition: border 0.2s ease-out;
cursor: pointer;
min-width: 190px;
}
.button,

View File

@ -3,6 +3,7 @@ import { toDataUrl } from 'ethereum-blockies'
import React, { FormEvent } from 'react'
import { ReactComponent as Caret } from '../../../images/caret.svg'
import { accountTruncate } from '../../../utils/wallet'
import Loader from '../../atoms/Loader'
import Status from '../../atoms/Status'
import styles from './Account.module.css'
@ -23,7 +24,7 @@ const Blockies = ({ account }: { account: string | undefined }) => {
// Forward ref for Tippy.js
// eslint-disable-next-line
const Account = React.forwardRef((props, ref: any) => {
const { accountId, status, connect, networkId } = useOcean()
const { accountId, status, connect, networkId, web3Modal } = useOcean()
const hasSuccess = status === 1 && networkId === 1
async function handleActivation(e: FormEvent<HTMLButtonElement>) {
@ -33,7 +34,12 @@ const Account = React.forwardRef((props, ref: any) => {
await connect()
}
return accountId ? (
return !accountId && web3Modal?.cachedProvider ? (
// Improve user experience for cached provider when connecting takes some time
<button className={styles.button} onClick={(e) => e.preventDefault()}>
<Loader message="Reconnecting wallet..." />
</button>
) : accountId ? (
<button
className={styles.button}
aria-label="Account"

View File

@ -4,6 +4,14 @@
min-width: 17rem;
}
@media (min-width: 40rem) {
.details {
padding: calc(var(--spacer) / 2);
margin-right: calc(var(--spacer) / 3);
min-width: 20rem;
}
}
.details > section[class*='feedback'] {
margin-top: calc(var(--spacer) / 2);
}
@ -46,10 +54,24 @@
.actions button:hover {
display: block;
font-size: var(--font-size-mini);
margin-top: calc(var(--spacer) / 4);
margin-top: calc(var(--spacer) / 3);
text-align: left;
}
.actions button:first-child {
margin-top: calc(var(--spacer) / 8);
}
.walletLogo {
width: 20px;
height: 20px;
display: inline-block;
vertical-align: middle;
margin-right: calc(var(--spacer) / 8);
margin-top: -0.2rem;
}
.actions select {
margin-top: calc(var(--spacer) / 4);
min-width: 6rem;
}

View File

@ -1,16 +1,37 @@
import React, { ReactElement } from 'react'
import React, { ReactElement, useEffect, useState } from 'react'
import Button from '../../atoms/Button'
import styles from './Details.module.css'
import { useOcean } from '@oceanprotocol/react'
import Web3Feedback from './Feedback'
import { getInjectedProviderName } from 'web3modal'
import { getProviderInfo, IProviderInfo } from 'web3modal'
import Conversion from '../../atoms/Price/Conversion'
import { formatCurrency } from '@coingecko/cryptoformat'
import { useUserPreferences } from '../../../providers/UserPreferences'
export default function Details(): ReactElement {
const { balance, connect, logout } = useOcean()
const { balance, connect, logout, web3Provider } = useOcean()
const { locale } = useUserPreferences()
const [providerInfo, setProviderInfo] = useState<IProviderInfo>()
// const [portisNetwork, setPortisNetwork] = useState<string>()
// Workaround cause getInjectedProviderName() always returns `MetaMask`
// https://github.com/oceanprotocol/market/issues/332
useEffect(() => {
if (!web3Provider) return
const providerInfo = getProviderInfo(web3Provider)
setProviderInfo(providerInfo)
}, [web3Provider])
// Handle network change for Portis
// async function handlePortisNetworkChange(e: ChangeEvent<HTMLSelectElement>) {
// setPortisNetwork(e.target.value)
// const portisNetworkName = e.target.value.toLowerCase()
// await web3Provider._portis.changeNetwork(portisNetworkName)
// // TODO: using our connect initializes a new Portis instance,
// // which then defaults back to initial network (Mainnet).
// // await connect()
// }
return (
<div className={styles.details}>
@ -26,8 +47,30 @@ export default function Details(): ReactElement {
))}
<li className={styles.actions}>
<span title="Connected provider">{getInjectedProviderName()}</span>
<span title="Connected provider">
<img className={styles.walletLogo} src={providerInfo?.logo} />
{providerInfo?.name}
{/* {providerInfo?.name === 'Portis' && (
<InputElement
name="network"
type="select"
options={['Mainnet', 'Ropsten', 'Rinkeby']}
size="mini"
value={portisNetwork}
onChange={handlePortisNetworkChange}
/>
)} */}
</span>
<p>
{providerInfo?.name === 'Portis' && (
<Button
style="text"
size="small"
onClick={() => web3Provider._portis.showPortis()}
>
Show Portis
</Button>
)}
<Button
style="text"
size="small"

View File

@ -12,22 +12,48 @@ div.web3modal-modal-card {
border-radius: var(--border-radius);
padding: var(--spacer);
margin: var(--spacer) auto;
max-width: var(--break-point--small);
max-width: 100%;
border: 1px solid var(--border-color);
box-shadow: 0 6px 15px 0 var(--box-shadow-color);
animation: moveUp 0.2s ease-out backwards;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-template-columns: 1fr;
}
div.web3modal-provider-wrapper {
border: none;
border: 0;
border-bottom: 1px solid var(--border-color);
padding: 0;
}
div.web3modal-provider-wrapper:last-child {
border-bottom: 0;
}
div.web3modal-provider-container {
border-radius: 0;
padding: var(--spacer);
}
@media (min-width: 40rem) {
div.web3modal-modal-card {
grid-template-columns: 1fr 1fr;
max-width: var(--break-point--small);
}
div.web3modal-provider-wrapper {
border-bottom: 0;
}
div.web3modal-provider-wrapper:nth-child(1),
div.web3modal-provider-wrapper:nth-child(2) {
border-bottom: 1px solid var(--border-color);
}
div.web3modal-provider-wrapper:nth-child(2n + 1) {
border-right: 1px solid var(--border-color);
}
}
div.web3modal-provider-icon {
filter: grayscale(1) contrast(150%);
transition: filter 0.2s ease-out;

View File

@ -5,7 +5,14 @@ import { Logger } from '@oceanprotocol/lib'
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
export function NetworkMonitor(): ReactElement {
const { connect, web3Provider, web3, networkId, config } = useOcean()
const {
connect,
web3Provider,
web3,
networkId,
config,
accountId
} = useOcean()
async function handleNetworkChanged(chainId: string | number) {
const initialNewConfig = getOceanConfig(
@ -43,6 +50,7 @@ export function NetworkMonitor(): ReactElement {
(config as ConfigHelperConfig).networkId
)
return
await handleNetworkChanged(networkId)
}
init()

View File

@ -19,6 +19,7 @@ const query = graphql`
network
marketFeeAddress
currencies
portisId
}
}
}

View File

@ -1,6 +1,9 @@
import { infuraProjectId as infuraId, network } from '../../app.config'
import {
infuraProjectId as infuraId,
portisId,
network
} from '../../app.config'
import WalletConnectProvider from '@walletconnect/web3-provider'
// import Torus from '@toruslabs/torus-embed'
const web3ModalTheme = {
background: 'var(--background-body)',
@ -10,22 +13,33 @@ const web3ModalTheme = {
hover: 'var(--background-highlight)'
}
const providerOptions = {
walletconnect: {
package: WalletConnectProvider,
options: { infuraId }
}
// torus: {
// package: Torus,
// options: {
// networkParams: {
// // host: oceanConfig.url // optional
// // chainId: 1337, // optional
// // networkId: 1337 // optional
// }
// }
// }
}
// HEADS UP! We inline-require some packages so the Gatsby SSR build does not break.
// We only need them client-side.
const providerOptions =
typeof window !== 'undefined'
? {
walletconnect: {
package: WalletConnectProvider,
options: { infuraId }
},
portis: {
package: require('@portis/web3'),
options: {
id: portisId
}
}
// torus: {
// package: require('@toruslabs/torus-embed')
// // options: {
// // networkParams: {
// // host: oceanConfig.url, // optional
// // chainId: 1337, // optional
// // networkId: 1337 // optional
// // }
// // }
// }
}
: {}
export const web3ModalOpts = {
cacheProvider: true,