Skip to content

Commit

Permalink
Merge branch 'V4' of github.com:WalletConnect/web3modal into fix/siwe…
Browse files Browse the repository at this point in the history
…-email
  • Loading branch information
tomiir committed May 7, 2024
2 parents 539ec43 + 9396ca1 commit 4194208
Show file tree
Hide file tree
Showing 48 changed files with 1,635 additions and 197 deletions.
2 changes: 1 addition & 1 deletion apps/demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"tailwind-merge": "2.2.1",
"vaul": "0.9.0",
"viem": "2.7.19",
"wagmi": "2.5.7",
"wagmi": "2.5.19",
"zustand": "4.5.2"
},
"devDependencies": {
Expand Down
10 changes: 9 additions & 1 deletion apps/laboratory/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,15 @@ const nextConfig = {
reactStrictMode: true,
trailingSlash: true,
distDir: 'out',
cleanDistDir: true
cleanDistDir: true,
async headers() {
return [
{
source: '/.well-known/apple-app-site-association',
headers: [{ key: 'content-type', value: 'application/json' }]
}
]
}
}

module.exports = nextConfig
4 changes: 2 additions & 2 deletions apps/laboratory/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@
"next": "14.0.4",
"next-auth": "4.24.5",
"react-icons": "4.12.0",
"siwe": "2.1.4",
"@walletconnect/utils": "2.12.0",
"valtio": "1.11.2",
"viem": "2.9.3",
"wagmi": "2.5.7"
"wagmi": "2.5.19"
},
"devDependencies": {
"@aws-sdk/client-cloudwatch": "3.509.0",
Expand Down
15 changes: 15 additions & 0 deletions apps/laboratory/src/components/Ethers/EthersModalInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import * as React from 'react'
import { useWeb3ModalAccount } from '@web3modal/ethers/react'

import { Web3ModalInfo } from '../Web3ModalInfo'

export function EthersModalInfo() {
const { isConnected, address, chainId } = useWeb3ModalAccount()
const [ready, setReady] = React.useState(false)

React.useEffect(() => {
setReady(true)
}, [])

return ready && isConnected ? <Web3ModalInfo address={address} chainId={chainId} /> : null
}
17 changes: 12 additions & 5 deletions apps/laboratory/src/components/Ethers/EthersSignMessageTest.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Button } from '@chakra-ui/react'
import { useState } from 'react'
import { useWeb3ModalAccount, useWeb3ModalProvider } from '@web3modal/ethers/react'
import { BrowserProvider, JsonRpcSigner } from 'ethers'
import { ConstantsUtil } from '../../utils/ConstantsUtil'
Expand All @@ -8,6 +9,7 @@ export function EthersSignMessageTest() {
const toast = useChakraToast()
const { address, chainId } = useWeb3ModalAccount()
const { walletProvider } = useWeb3ModalProvider()
const [signature, setSignature] = useState<string | undefined>()

async function onSignMessage() {
try {
Expand All @@ -16,8 +18,8 @@ export function EthersSignMessageTest() {
}
const provider = new BrowserProvider(walletProvider, chainId)
const signer = new JsonRpcSigner(provider, address)
const signature = await signer?.signMessage('Hello Web3Modal Ethers')

const sig = await signer?.signMessage('Hello Web3Modal!')
setSignature(sig)
toast({
title: ConstantsUtil.SigningSucceededToastTitle,
description: signature,
Expand All @@ -33,8 +35,13 @@ export function EthersSignMessageTest() {
}

return (
<Button data-testid="sign-message-button" onClick={onSignMessage}>
Sign Message
</Button>
<>
<Button data-testid="sign-message-button" onClick={onSignMessage} width="auto">
Sign Message
</Button>
<div data-testid="w3m-signature" hidden>
{signature}
</div>
</>
)
}
10 changes: 10 additions & 0 deletions apps/laboratory/src/components/Wagmi/WagmiModalInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as React from 'react'

import { useAccount } from 'wagmi'
import { Web3ModalInfo } from '../Web3ModalInfo'

export function WagmiModalInfo() {
const { isConnected, address, chainId } = useAccount()

return isConnected ? <Web3ModalInfo address={address} chainId={chainId} /> : null
}
17 changes: 12 additions & 5 deletions apps/laboratory/src/components/Wagmi/WagmiSignMessageTest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ export function WagmiSignMessageTest() {
const { signMessageAsync } = useSignMessage()
const { status } = useAccount()
const isConnected = status === 'connected'
const [signature, setSignature] = React.useState<string | undefined>()

async function onSignMessage() {
try {
const signature = await signMessageAsync({ message: 'Hello Web3Modal!' })
const sig = await signMessageAsync({ message: 'Hello Web3Modal!' })
setSignature(sig)
toast({
title: ConstantsUtil.SigningSucceededToastTitle,
description: signature,
description: sig,
type: 'success'
})
} catch {
Expand All @@ -29,8 +31,13 @@ export function WagmiSignMessageTest() {
}

return (
<Button data-testid="sign-message-button" onClick={onSignMessage} isDisabled={!isConnected}>
Sign Message
</Button>
<>
<Button data-testid="sign-message-button" onClick={onSignMessage} isDisabled={!isConnected}>
Sign Message
</Button>
<div data-testid="w3m-signature" hidden>
{signature}
</div>
</>
)
}
40 changes: 40 additions & 0 deletions apps/laboratory/src/components/Web3ModalInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import * as React from 'react'

import {
StackDivider,
Card,
CardHeader,
Heading,
CardBody,
Box,
Stack,
Text
} from '@chakra-ui/react'

export function Web3ModalInfo({ address, chainId }: { address?: string; chainId?: number }) {
return (
<Card marginTop={10} marginBottom={10}>
<CardHeader>
<Heading size="md">Account Information</Heading>
</CardHeader>

<CardBody>
<Stack divider={<StackDivider />} spacing="4">
<Box>
<Heading size="xs" textTransform="uppercase" pb="2">
Address
</Heading>
<Text data-testid="w3m-address">{address}</Text>
</Box>

<Box>
<Heading size="xs" textTransform="uppercase" pb="2">
Chain Id
</Heading>
<Text data-testid="w3m-chain-id">{chainId}</Text>
</Box>
</Stack>
</CardBody>
</Card>
)
}
32 changes: 13 additions & 19 deletions apps/laboratory/src/pages/api/auth/[...nextauth].ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import type { SIWESession } from '@web3modal/siwe'
import type { NextApiRequest, NextApiResponse } from 'next'
import nextAuth from 'next-auth'
import credentialsProvider from 'next-auth/providers/credentials'
import { getCsrfToken } from 'next-auth/react'
import { SiweMessage } from 'siwe'
import { ethers } from 'ethers'
import {
type SIWESession,
verifySignature,
getChainIdFromMessage,
getAddressFromMessage
} from '@web3modal/siwe'

declare module 'next-auth' {
interface Session extends SIWESession {
address: string
chainId: number
}
}

/*
* For more information on each option (and a full list of options) go to
* https://next-auth.js.org/configuration/options
Expand Down Expand Up @@ -47,22 +48,15 @@ export default async function auth(req: NextApiRequest, res: NextApiResponse) {
if (!credentials?.message) {
throw new Error('SiweMessage is undefined')
}
const siwe = new SiweMessage(credentials.message)
const provider = new ethers.JsonRpcProvider(
`https://rpc.walletconnect.com/v1?chainId=eip155:${siwe.chainId}&projectId=${projectId}`
)
const nonce = await getCsrfToken({ req: { headers: req.headers } })
const result = await siwe.verify(
{
signature: credentials?.signature || '',
nonce
},
{ provider }
)
const { message, signature } = credentials
const address = getAddressFromMessage(message)
const chainId = getChainIdFromMessage(message)

const isValid = await verifySignature({ address, message, signature, chainId, projectId })

if (result.success) {
if (isValid) {
return {
id: `eip155:${siwe.chainId}:${siwe.address}`
id: `${chainId}:${address}`
}
}

Expand Down
2 changes: 2 additions & 0 deletions apps/laboratory/src/pages/library/ethers-email.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { EthersConstants } from '../../utils/EthersConstants'
import { ConstantsUtil } from '../../utils/ConstantsUtil'
import { EthersTests } from '../../components/Ethers/EthersTests'
import { Web3ModalButtons } from '../../components/Web3ModalButtons'
import { EthersModalInfo } from '../../components/Ethers/EthersModalInfo'

const modal = createWeb3Modal({
ethersConfig: defaultConfig({
Expand All @@ -28,6 +29,7 @@ export default function Ethers() {
return (
<>
<Web3ModalButtons />
<EthersModalInfo />
<EthersTests />
</>
)
Expand Down
2 changes: 2 additions & 0 deletions apps/laboratory/src/pages/library/ethers-wallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { EthersConstants } from '../../utils/EthersConstants'
import { ConstantsUtil } from '../../utils/ConstantsUtil'
import { EthersTests } from '../../components/Ethers/EthersTests'
import { Web3ModalButtons } from '../../components/Web3ModalButtons'
import { EthersModalInfo } from '../../components/Ethers/EthersModalInfo'

const modal = createWeb3Modal({
ethersConfig: defaultConfig({
Expand All @@ -29,6 +30,7 @@ export default function Ethers() {
return (
<>
<Web3ModalButtons />
<EthersModalInfo />
<EthersTests />
</>
)
Expand Down
2 changes: 2 additions & 0 deletions apps/laboratory/src/pages/library/ethers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { createWeb3Modal, defaultConfig } from '@web3modal/ethers/react'
import { ThemeStore } from '../../utils/StoreUtil'
import { EthersConstants } from '../../utils/EthersConstants'
import { ConstantsUtil } from '../../utils/ConstantsUtil'
import { EthersModalInfo } from '../../components/Ethers/EthersModalInfo'

const modal = createWeb3Modal({
ethersConfig: defaultConfig({
Expand All @@ -27,6 +28,7 @@ export default function Ethers() {
return (
<>
<Web3ModalButtons />
<EthersModalInfo />
<EthersTests />
</>
)
Expand Down
2 changes: 2 additions & 0 deletions apps/laboratory/src/pages/library/wagmi-email.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { WagmiTests } from '../../components/Wagmi/WagmiTests'
import { ThemeStore } from '../../utils/StoreUtil'
import { WagmiConstantsUtil } from '../../utils/WagmiConstants'
import { ConstantsUtil } from '../../utils/ConstantsUtil'
import { WagmiModalInfo } from '../../components/Wagmi/WagmiModalInfo'

const queryClient = new QueryClient()

Expand Down Expand Up @@ -43,6 +44,7 @@ export default function Wagmi() {
<WagmiProvider config={wagmiConfig}>
<QueryClientProvider client={queryClient}>
<Web3ModalButtons />
<WagmiModalInfo />
<WagmiTests />
</QueryClientProvider>
</WagmiProvider>
Expand Down
1 change: 0 additions & 1 deletion apps/laboratory/src/pages/library/wagmi-siwe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export const wagmiConfig = defaultWagmiConfig({
metadata: ConstantsUtil.Metadata,
ssr: true
})

const modal = createWeb3Modal({
wagmiConfig,
projectId: ConstantsUtil.ProjectId,
Expand Down
2 changes: 2 additions & 0 deletions apps/laboratory/src/pages/library/wagmi-wallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { WagmiTests } from '../../components/Wagmi/WagmiTests'
import { ThemeStore } from '../../utils/StoreUtil'
import { WagmiConstantsUtil } from '../../utils/WagmiConstants'
import { ConstantsUtil } from '../../utils/ConstantsUtil'
import { WagmiModalInfo } from '../../components/Wagmi/WagmiModalInfo'

const queryClient = new QueryClient()

Expand Down Expand Up @@ -44,6 +45,7 @@ export default function Wagmi() {
<WagmiProvider config={wagmiConfig}>
<QueryClientProvider client={queryClient}>
<Web3ModalButtons />
<WagmiModalInfo />
<WagmiTests />
</QueryClientProvider>
</WagmiProvider>
Expand Down
2 changes: 2 additions & 0 deletions apps/laboratory/src/pages/library/wagmi.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { WagmiTests } from '../../components/Wagmi/WagmiTests'
import { ThemeStore } from '../../utils/StoreUtil'
import { WagmiConstantsUtil } from '../../utils/WagmiConstants'
import { ConstantsUtil } from '../../utils/ConstantsUtil'
import { WagmiModalInfo } from '../../components/Wagmi/WagmiModalInfo'

const queryClient = new QueryClient()

Expand Down Expand Up @@ -35,6 +36,7 @@ export default function Wagmi() {
<WagmiProvider config={wagmiConfig}>
<QueryClientProvider client={queryClient}>
<Web3ModalButtons />
<WagmiModalInfo />
<WagmiTests />
</QueryClientProvider>
</WagmiProvider>
Expand Down
33 changes: 19 additions & 14 deletions apps/laboratory/src/utils/SiweUtils.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import { SiweMessage } from 'siwe'
import { getCsrfToken, signIn, signOut, getSession } from 'next-auth/react'
import type { SIWEVerifyMessageArgs, SIWECreateMessageArgs, SIWESession } from '@web3modal/siwe'
import { createSIWEConfig } from '@web3modal/siwe'
import { createSIWEConfig, formatMessage } from '@web3modal/siwe'
import { WagmiConstantsUtil } from '../utils/WagmiConstants'

export const siweConfig = createSIWEConfig({
createMessage: ({ nonce, address, chainId }: SIWECreateMessageArgs) =>
new SiweMessage({
version: '1',
domain: window.location.host,
uri: window.location.origin,
address,
chainId,
nonce,
// Human-readable ASCII assertion that the user will sign, and it must not contain `\n`.
statement: 'Sign in With Ethereum.'
}).prepareMessage(),
// We don't require any async action to populate params but other apps might
// eslint-disable-next-line @typescript-eslint/require-await
getMessageParams: async () => ({
domain: window.location.host,
uri: window.location.origin,
chains: WagmiConstantsUtil.chains.map(chain => chain.id),
statement: 'Please sign with your account'
}),
createMessage: ({ address, ...args }: SIWECreateMessageArgs) => formatMessage(args, address),
getNonce: async () => {
const nonce = await getCsrfToken()
if (!nonce) {
Expand All @@ -33,8 +31,15 @@ export const siweConfig = createSIWEConfig({

return { address, chainId }
},
verifyMessage: async ({ message, signature }: SIWEVerifyMessageArgs) => {
verifyMessage: async ({ message, signature, cacao }: SIWEVerifyMessageArgs) => {
try {
/*
* Signed Cacao (CAIP-74) will be available for further validations if the wallet supports caip-222 signing
* When personal_sign fallback is used, cacao will be undefined
*/
if (cacao) {
// Do something
}
const success = await signIn('credentials', {
message,
redirect: false,
Expand Down
Loading

0 comments on commit 4194208

Please sign in to comment.