Skip to content

Commit

Permalink
Merge pull request #438 from WalletConnect/feat/w3m-email-alpha
Browse files Browse the repository at this point in the history
feat: initialize w3m email alpha
  • Loading branch information
enesozturk authored Feb 14, 2024
2 parents 4856a95 + ef6a250 commit ceff204
Show file tree
Hide file tree
Showing 13 changed files with 928 additions and 688 deletions.
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@
},
"dependencies": {
"@sentry/react": "^7.93.0",
"@tanstack/react-query": "^5.20.1",
"@walletconnect/core": "2.11.0",
"@walletconnect/identity-keys": "^1.0.1",
"@walletconnect/notify-client": "^0.16.5",
"@walletconnect/notify-message-decrypter": "^0.1.0",
"@web3modal/wagmi": "^3.5.7",
"@web3modal/wagmi": "4.0.4",
"classnames": "^2.3.2",
"date-fns": "^2.29.3",
"detect-browser": "^5.3.0",
Expand All @@ -40,9 +41,9 @@
"react-router-dom": "^6.4.4",
"react-select": "^5.7.0",
"rxjs": "^7.6.0",
"viem": "^1.11.0",
"viem": "2.7.8",
"vite-plugin-pwa": "^0.16.7",
"wagmi": "^1.4.13"
"wagmi": "2.5.5"
},
"devDependencies": {
"@playwright/test": "^1.40.1",
Expand Down
6 changes: 2 additions & 4 deletions src/Modals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const Modals = () => {
if (userPubkey && notifySignatureRequired) {
if (isWeb3ModalOpen) {
// Close web3modal in case user is switching accounts
closeWeb3Modal()
// closeWeb3Modal()
}
signatureModalService.openModal()
} else {
Expand Down Expand Up @@ -91,9 +91,7 @@ export const Modals = () => {

{shouldShowPreferencesModalOpen && <PreferencesModal />}

{shouldShowSignatureModal && (
<SignatureModal message={notifyRegisterMessage ?? ''} sender={'notify'} />
)}
{shouldShowSignatureModal && <SignatureModal message={notifyRegisterMessage ?? ''} />}

{shouldShowPWAModal && <PwaModal />}

Expand Down
2 changes: 1 addition & 1 deletion src/components/account/Avatar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const Avatar: React.FC<AvatarProps> = ({ address, width, height }) => {

const addressOrEnsDomain = address as `0x${string}` | undefined
const { data: ensName } = useEnsName({ address: addressOrEnsDomain })
const { data: ensAvatar } = useEnsAvatar({ name: ensName })
const { data: ensAvatar } = useEnsAvatar({ name: ensName ?? '' })

return (
<div
Expand Down
5 changes: 3 additions & 2 deletions src/components/messages/NewChat/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { Fragment, useCallback, useContext, useEffect, useMemo, useState } from 'react'

import { fetchEnsAddress } from '@wagmi/core'
import { getEnsAddress } from '@wagmi/core'
import debounce from 'lodash.debounce'
import { NavLink, useNavigate } from 'react-router-dom'

Expand All @@ -16,6 +16,7 @@ import { isValidAddressOrEnsDomain, isValidEnsDomain } from '@/utils/address'
import { useColorModeValue, useIsMobile } from '@/utils/hooks'
import { truncate } from '@/utils/string'
import { showErrorMessageToast } from '@/utils/toasts'
import { wagmiConfig } from '@/utils/wagmiConfig'

import SearchSuggestions from './SearchSuggestions'

Expand Down Expand Up @@ -46,7 +47,7 @@ const NewChat: React.FC = () => {
const resolveAddress = async (inviteeAddress: string) => {
// eslint-disable-next-line prefer-regex-literals
if (isValidEnsDomain(inviteeAddress)) {
const resolvedAddress = await fetchEnsAddress({
const resolvedAddress = await getEnsAddress(wagmiConfig, {
name: inviteeAddress
})

Expand Down
4 changes: 4 additions & 0 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,7 @@ video {
padding-bottom: 1rem;
}
}

#w3m-iframe {
border: none;
}
50 changes: 23 additions & 27 deletions src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,61 +1,57 @@
import React from 'react'

import { createWeb3Modal, defaultWagmiConfig } from '@web3modal/wagmi/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { createWeb3Modal } from '@web3modal/wagmi/react'
import ReactDOM from 'react-dom/client'
import { BrowserRouter } from 'react-router-dom'
import { WagmiConfig } from 'wagmi'
import { arbitrum, avalanche, bsc, mainnet, polygon } from 'wagmi/chains'
import { WagmiProvider } from 'wagmi'

import { PRIVACY_POLICY_URL, TERMS_OF_SERVICE_URL } from '@/constants/web3Modal'
import SettingsContextProvider from '@/contexts/SettingsContext'
import W3iContextProvider from '@/contexts/W3iContext'
import ConfiguredRoutes from '@/routes'
import { polyfill } from '@/utils/polyfill'
import { initSentry } from '@/utils/sentry'
import { metadata, wagmiConfig } from '@/utils/wagmiConfig'

import { Modals } from './Modals'
import DevTimeStamp from './components/dev/DevTimeStamp'

import './index.css'
import DevTimeStamp from './components/dev/DevTimeStamp'

polyfill()
initSentry()

const projectId = import.meta.env.VITE_PROJECT_ID
const chains = [mainnet, arbitrum, polygon, avalanche, bsc]

const metadata = {
name: 'Web3Inbox',
description: 'Notification Hub',
url: 'https://app.web3inbox.com',
icons: ['https://app.web3inbox.com/logo.png']
}
const wagmiConfig = defaultWagmiConfig({ chains, projectId, metadata })

createWeb3Modal({
wagmiConfig,
enableAnalytics: import.meta.env.PROD,
chains,
projectId,
termsConditionsUrl: TERMS_OF_SERVICE_URL,
privacyPolicyUrl: PRIVACY_POLICY_URL,
themeMode: 'light',
themeVariables: { '--w3m-z-index': 9999 },
termsConditionsUrl: TERMS_OF_SERVICE_URL,
privacyPolicyUrl: PRIVACY_POLICY_URL
metadata
})

const queryClient = new QueryClient()

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<WagmiConfig config={wagmiConfig}>
<SettingsContextProvider>
<BrowserRouter>
<W3iContextProvider>
<ConfiguredRoutes />
<DevTimeStamp />
<Modals />
</W3iContextProvider>
</BrowserRouter>
</SettingsContextProvider>
</WagmiConfig>
<WagmiProvider config={wagmiConfig}>
<QueryClientProvider client={queryClient}>
<SettingsContextProvider>
<BrowserRouter>
<W3iContextProvider>
<ConfiguredRoutes />
<DevTimeStamp />
<Modals />
</W3iContextProvider>
</BrowserRouter>
</SettingsContextProvider>
</QueryClientProvider>
</WagmiProvider>
</React.StrictMode>
)
36 changes: 15 additions & 21 deletions src/pages/Login/SignatureModal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import React, { useCallback } from 'react'
import React from 'react'

import { formatJsonRpcRequest } from '@walletconnect/jsonrpc-utils'
import { useDisconnect } from 'wagmi'
import { useAccount, useDisconnect } from 'wagmi'

import Button from '@/components/general/Button'
import CrossIcon from '@/components/general/Icon/CrossIcon'
import SignatureIcon from '@/components/general/Icon/SignatureIcon'
import Wallet from '@/components/general/Icon/Wallet'
import { Modal } from '@/components/general/Modal/Modal'
import Spinner from '@/components/general/Spinner'
import Text from '@/components/general/Text'
import { logError } from '@/utils/error'
import { useModals } from '@/utils/hooks'
import { signatureModalService } from '@/utils/store'

Expand All @@ -19,37 +19,31 @@ import './SignatureModal.scss'

export const SignatureModal: React.FC<{
message: string
sender: 'chat' | 'notify'
}> = ({ message, sender }) => {
}> = ({ message }) => {
const { status } = useAccount()
const connected = status === 'connected'

/*
* If identity was already signed, and sync was requested then we are in the
* final step.
*/
const { isSigning } = useModals()
const { disconnect } = useDisconnect()

const onSign = useCallback(() => {
const onSign = () => {
signatureModalService.startSigning()
window.web3inbox
.signMessage(message)
.then(signature => {
switch (sender) {
case 'chat':
console.warn('[Web3Inbox] Signing messages for chat is not supported.')
break
case 'notify':
window.web3inbox.notify.postMessage(
formatJsonRpcRequest('notify_signature_delivered', { signature })
)
break
default:
logError(new Error(`No correct sender for signature modal, sender: ${sender}`))
}
window.web3inbox.notify.postMessage(
formatJsonRpcRequest('notify_signature_delivered', { signature })
)
})
.catch(() => {
console.error('Failed to sign message')
signatureModalService.stopSigning()
})
}, [message, sender])
}

return (
<Modal onCloseModal={signatureModalService.closeModal}>
Expand Down Expand Up @@ -77,9 +71,9 @@ export const SignatureModal: React.FC<{
</Text>
<div className="SignatureModal__button">
<Button
disabled={isSigning}
disabled={isSigning || !connected}
textVariant="paragraph-600"
rightIcon={isSigning ? null : <Wallet />}
rightIcon={!connected ? <Spinner /> : isSigning ? null : <Wallet />}
onClick={onSign}
>
{isSigning ? 'Waiting for wallet...' : 'Sign in with wallet'}
Expand Down
2 changes: 1 addition & 1 deletion src/utils/ens.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PublicClient } from 'viem'
import { normalize } from 'viem/ens'
import type { PublicClient } from 'wagmi'

declare const localStorage: Storage | undefined

Expand Down
18 changes: 18 additions & 0 deletions src/utils/wagmiConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { arbitrum, avalanche, bsc, mainnet, polygon } from '@wagmi/core/chains'
import { defaultWagmiConfig } from '@web3modal/wagmi'

const projectId = import.meta.env.VITE_PROJECT_ID

export const metadata = {
name: 'Web3Inbox',
description: 'Web3Inbox App',
url: 'https://web3inbox.com',
icons: ['https://assets.web3inbox.com/images/w3i-app-logo.png']
}

export const wagmiConfig = defaultWagmiConfig({
chains: [mainnet, arbitrum, polygon, avalanche, bsc],
projectId,
metadata,
enableEmail: true
})
37 changes: 17 additions & 20 deletions src/w3iProxy/authProviders/internalAuthProvider.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,35 @@
import { getAccount, getNetwork, watchAccount, watchNetwork } from '@wagmi/core'
import { getAccount, watchAccount } from '@wagmi/core'
import type { JsonRpcRequest } from '@walletconnect/jsonrpc-types'
import type { EventEmitter } from 'events'

import { getEIPChainString } from '@/utils/chain'
import { wagmiConfig } from '@/utils/wagmiConfig'

export default class InternalAuthProvider {
private readonly methodsListenedTo = ['auth_set_account']
public providerName = 'InternalAuthProvider'
public account?: string = getAccount().address
public chain?: string = getEIPChainString(getNetwork().chain?.id)
public account?: string = getAccount(wagmiConfig).address
public chain?: string = getEIPChainString(getAccount(wagmiConfig).chain?.id)
protected readonly emitter: EventEmitter

public constructor(emitter: EventEmitter, _name = 'InternalAuthProvider') {
this.emitter = emitter

watchNetwork(network => {
const caip10Chain = getEIPChainString(getNetwork().chain?.id)
this.chain = caip10Chain
watchAccount(wagmiConfig, {
onChange: data => {
const chainId = getAccount(wagmiConfig).chainId

this.emitter.emit('auth_set_account', { account: this.account, chain: caip10Chain })
})

watchAccount(account => {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!account.address) {
this.emitter.emit('auth_set_account', { account: null, chain: null })
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!data.address) {
this.emitter.emit('auth_set_account', { account: null, chain: null })
return
}

return
const caip10Chain = getEIPChainString(chainId)
this.emitter.emit('auth_set_account', { account: data.address, chain: caip10Chain })
this.chain = caip10Chain
this.account = data.address
}

const caip10Chain = getEIPChainString(getNetwork().chain?.id)
this.emitter.emit('auth_set_account', { account: account.address, chain: caip10Chain })
this.chain = caip10Chain
this.account = account.address
})
}

Expand All @@ -52,7 +49,7 @@ export default class InternalAuthProvider {
}

public async initState() {
this.account = getAccount().address
this.account = getAccount(wagmiConfig).address
if (this.account) {
this.emitter.emit('auth_set_account', { account: this.account, chain: this.chain })
}
Expand Down
4 changes: 3 additions & 1 deletion src/w3iProxy/chatProviders/internalChatProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import type { ICore, IStore } from '@walletconnect/types'
import type { EventEmitter } from 'events'
import pino from 'pino'

import { wagmiConfig } from '@/utils/wagmiConfig'

import type { ChatClientTypes } from './types'
import type { W3iChatProvider } from './types'

Expand Down Expand Up @@ -89,7 +91,7 @@ export default class InternalChatProvider implements W3iChatProvider {
}

private getRequiredInternalAddress(): string {
const address = getAccount().address
const address = getAccount(wagmiConfig).address
if (!address) {
throw new Error('No address registered')
}
Expand Down
3 changes: 2 additions & 1 deletion src/w3iProxy/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type { Logger } from 'pino'

import type { UiEnabled } from '@/contexts/W3iContext/context'
import { identifyMixpanelUserAndInit } from '@/utils/mixpanel'
import { wagmiConfig } from '@/utils/wagmiConfig'
import W3iAuthFacade from '@/w3iProxy/w3iAuthFacade'
import type W3iChatFacade from '@/w3iProxy/w3iChatFacade'
import W3iNotifyFacade from '@/w3iProxy/w3iNotifyFacade'
Expand Down Expand Up @@ -101,7 +102,7 @@ class Web3InboxProxy {
this.dappOrigin = dappOrigin

this.signMessage = async (message: string) => {
return signMessage({ message })
return signMessage(wagmiConfig, { message })
}
}

Expand Down
Loading

0 comments on commit ceff204

Please sign in to comment.