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:
parent
ad864cc249
commit
a760935564
@ -3,4 +3,5 @@ GATSBY_NETWORK="rinkeby"
|
|||||||
|
|
||||||
#GATSBY_INFURA_PROJECT_ID="xxx"
|
#GATSBY_INFURA_PROJECT_ID="xxx"
|
||||||
#GATSBY_MARKET_FEE_ADDRESS="0xxx"
|
#GATSBY_MARKET_FEE_ADDRESS="0xxx"
|
||||||
#GATSBY_ANALYTICS_ID="xxx"
|
#GATSBY_ANALYTICS_ID="xxx"
|
||||||
|
#GATSBY_PORTIS_ID="xxx"
|
@ -32,5 +32,8 @@ module.exports = {
|
|||||||
classNameDark: 'dark',
|
classNameDark: 'dark',
|
||||||
classNameLight: 'light',
|
classNameLight: 'light',
|
||||||
storageKey: 'oceanDarkMode'
|
storageKey: 'oceanDarkMode'
|
||||||
}
|
},
|
||||||
|
|
||||||
|
// Wallets
|
||||||
|
portisId: process.env.GATSBY_PORTIS_ID || 'xxx'
|
||||||
}
|
}
|
||||||
|
1207
package-lock.json
generated
1207
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -30,12 +30,12 @@
|
|||||||
"@oceanprotocol/lib": "^0.10.1",
|
"@oceanprotocol/lib": "^0.10.1",
|
||||||
"@oceanprotocol/react": "^0.5.1",
|
"@oceanprotocol/react": "^0.5.1",
|
||||||
"@oceanprotocol/typographies": "^0.1.0",
|
"@oceanprotocol/typographies": "^0.1.0",
|
||||||
|
"@portis/web3": "^3.0.3",
|
||||||
"@sindresorhus/slugify": "^1.0.0",
|
"@sindresorhus/slugify": "^1.0.0",
|
||||||
"@tippyjs/react": "^4.2.0",
|
"@tippyjs/react": "^4.2.0",
|
||||||
"@toruslabs/torus-embed": "^1.9.5",
|
|
||||||
"@types/classnames": "^2.2.11",
|
"@types/classnames": "^2.2.11",
|
||||||
"@vercel/node": "^1.8.5",
|
"@vercel/node": "^1.8.5",
|
||||||
"@walletconnect/web3-provider": "^1.3.3",
|
"@walletconnect/web3-provider": "^1.3.4",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"chart.js": "^2.9.4",
|
"chart.js": "^2.9.4",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
transition: border 0.2s ease-out;
|
transition: border 0.2s ease-out;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
min-width: 190px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button,
|
.button,
|
||||||
|
@ -3,6 +3,7 @@ import { toDataUrl } from 'ethereum-blockies'
|
|||||||
import React, { FormEvent } from 'react'
|
import React, { FormEvent } from 'react'
|
||||||
import { ReactComponent as Caret } from '../../../images/caret.svg'
|
import { ReactComponent as Caret } from '../../../images/caret.svg'
|
||||||
import { accountTruncate } from '../../../utils/wallet'
|
import { accountTruncate } from '../../../utils/wallet'
|
||||||
|
import Loader from '../../atoms/Loader'
|
||||||
import Status from '../../atoms/Status'
|
import Status from '../../atoms/Status'
|
||||||
import styles from './Account.module.css'
|
import styles from './Account.module.css'
|
||||||
|
|
||||||
@ -23,7 +24,7 @@ const Blockies = ({ account }: { account: string | undefined }) => {
|
|||||||
// Forward ref for Tippy.js
|
// Forward ref for Tippy.js
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
const Account = React.forwardRef((props, ref: any) => {
|
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
|
const hasSuccess = status === 1 && networkId === 1
|
||||||
|
|
||||||
async function handleActivation(e: FormEvent<HTMLButtonElement>) {
|
async function handleActivation(e: FormEvent<HTMLButtonElement>) {
|
||||||
@ -33,7 +34,12 @@ const Account = React.forwardRef((props, ref: any) => {
|
|||||||
await connect()
|
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
|
<button
|
||||||
className={styles.button}
|
className={styles.button}
|
||||||
aria-label="Account"
|
aria-label="Account"
|
||||||
|
@ -4,6 +4,14 @@
|
|||||||
min-width: 17rem;
|
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'] {
|
.details > section[class*='feedback'] {
|
||||||
margin-top: calc(var(--spacer) / 2);
|
margin-top: calc(var(--spacer) / 2);
|
||||||
}
|
}
|
||||||
@ -46,10 +54,24 @@
|
|||||||
.actions button:hover {
|
.actions button:hover {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: var(--font-size-mini);
|
font-size: var(--font-size-mini);
|
||||||
margin-top: calc(var(--spacer) / 4);
|
margin-top: calc(var(--spacer) / 3);
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.actions button:first-child {
|
.actions button:first-child {
|
||||||
margin-top: calc(var(--spacer) / 8);
|
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;
|
||||||
|
}
|
||||||
|
@ -1,16 +1,37 @@
|
|||||||
import React, { ReactElement } from 'react'
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
import Button from '../../atoms/Button'
|
import Button from '../../atoms/Button'
|
||||||
import styles from './Details.module.css'
|
import styles from './Details.module.css'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
import { useOcean } from '@oceanprotocol/react'
|
||||||
import Web3Feedback from './Feedback'
|
import Web3Feedback from './Feedback'
|
||||||
import { getInjectedProviderName } from 'web3modal'
|
import { getProviderInfo, IProviderInfo } from 'web3modal'
|
||||||
import Conversion from '../../atoms/Price/Conversion'
|
import Conversion from '../../atoms/Price/Conversion'
|
||||||
import { formatCurrency } from '@coingecko/cryptoformat'
|
import { formatCurrency } from '@coingecko/cryptoformat'
|
||||||
import { useUserPreferences } from '../../../providers/UserPreferences'
|
import { useUserPreferences } from '../../../providers/UserPreferences'
|
||||||
|
|
||||||
export default function Details(): ReactElement {
|
export default function Details(): ReactElement {
|
||||||
const { balance, connect, logout } = useOcean()
|
const { balance, connect, logout, web3Provider } = useOcean()
|
||||||
const { locale } = useUserPreferences()
|
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 (
|
return (
|
||||||
<div className={styles.details}>
|
<div className={styles.details}>
|
||||||
@ -26,8 +47,30 @@ export default function Details(): ReactElement {
|
|||||||
))}
|
))}
|
||||||
|
|
||||||
<li className={styles.actions}>
|
<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>
|
<p>
|
||||||
|
{providerInfo?.name === 'Portis' && (
|
||||||
|
<Button
|
||||||
|
style="text"
|
||||||
|
size="small"
|
||||||
|
onClick={() => web3Provider._portis.showPortis()}
|
||||||
|
>
|
||||||
|
Show Portis
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
<Button
|
<Button
|
||||||
style="text"
|
style="text"
|
||||||
size="small"
|
size="small"
|
||||||
|
@ -12,22 +12,48 @@ div.web3modal-modal-card {
|
|||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
padding: var(--spacer);
|
padding: var(--spacer);
|
||||||
margin: var(--spacer) auto;
|
margin: var(--spacer) auto;
|
||||||
max-width: var(--break-point--small);
|
max-width: 100%;
|
||||||
border: 1px solid var(--border-color);
|
border: 1px solid var(--border-color);
|
||||||
box-shadow: 0 6px 15px 0 var(--box-shadow-color);
|
box-shadow: 0 6px 15px 0 var(--box-shadow-color);
|
||||||
animation: moveUp 0.2s ease-out backwards;
|
animation: moveUp 0.2s ease-out backwards;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.web3modal-provider-wrapper {
|
div.web3modal-provider-wrapper {
|
||||||
border: none;
|
border: 0;
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.web3modal-provider-wrapper:last-child {
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
div.web3modal-provider-container {
|
div.web3modal-provider-container {
|
||||||
|
border-radius: 0;
|
||||||
padding: var(--spacer);
|
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 {
|
div.web3modal-provider-icon {
|
||||||
filter: grayscale(1) contrast(150%);
|
filter: grayscale(1) contrast(150%);
|
||||||
transition: filter 0.2s ease-out;
|
transition: filter 0.2s ease-out;
|
||||||
|
@ -5,7 +5,14 @@ import { Logger } from '@oceanprotocol/lib'
|
|||||||
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
|
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
|
||||||
|
|
||||||
export function NetworkMonitor(): ReactElement {
|
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) {
|
async function handleNetworkChanged(chainId: string | number) {
|
||||||
const initialNewConfig = getOceanConfig(
|
const initialNewConfig = getOceanConfig(
|
||||||
@ -43,6 +50,7 @@ export function NetworkMonitor(): ReactElement {
|
|||||||
(config as ConfigHelperConfig).networkId
|
(config as ConfigHelperConfig).networkId
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
await handleNetworkChanged(networkId)
|
await handleNetworkChanged(networkId)
|
||||||
}
|
}
|
||||||
init()
|
init()
|
||||||
|
@ -19,6 +19,7 @@ const query = graphql`
|
|||||||
network
|
network
|
||||||
marketFeeAddress
|
marketFeeAddress
|
||||||
currencies
|
currencies
|
||||||
|
portisId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 WalletConnectProvider from '@walletconnect/web3-provider'
|
||||||
// import Torus from '@toruslabs/torus-embed'
|
|
||||||
|
|
||||||
const web3ModalTheme = {
|
const web3ModalTheme = {
|
||||||
background: 'var(--background-body)',
|
background: 'var(--background-body)',
|
||||||
@ -10,22 +13,33 @@ const web3ModalTheme = {
|
|||||||
hover: 'var(--background-highlight)'
|
hover: 'var(--background-highlight)'
|
||||||
}
|
}
|
||||||
|
|
||||||
const providerOptions = {
|
// HEADS UP! We inline-require some packages so the Gatsby SSR build does not break.
|
||||||
walletconnect: {
|
// We only need them client-side.
|
||||||
package: WalletConnectProvider,
|
const providerOptions =
|
||||||
options: { infuraId }
|
typeof window !== 'undefined'
|
||||||
}
|
? {
|
||||||
// torus: {
|
walletconnect: {
|
||||||
// package: Torus,
|
package: WalletConnectProvider,
|
||||||
// options: {
|
options: { infuraId }
|
||||||
// networkParams: {
|
},
|
||||||
// // host: oceanConfig.url // optional
|
portis: {
|
||||||
// // chainId: 1337, // optional
|
package: require('@portis/web3'),
|
||||||
// // networkId: 1337 // optional
|
options: {
|
||||||
// }
|
id: portisId
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
}
|
// torus: {
|
||||||
|
// package: require('@toruslabs/torus-embed')
|
||||||
|
// // options: {
|
||||||
|
// // networkParams: {
|
||||||
|
// // host: oceanConfig.url, // optional
|
||||||
|
// // chainId: 1337, // optional
|
||||||
|
// // networkId: 1337 // optional
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
|
||||||
export const web3ModalOpts = {
|
export const web3ModalOpts = {
|
||||||
cacheProvider: true,
|
cacheProvider: true,
|
||||||
|
Loading…
Reference in New Issue
Block a user