Integrated Sign-In (Single-Sign-On)
Many dApps already use Sign-In With Ethereum (SIWE) to authenticate their users. The WalletChat widget supports integrated sign-in so users do not have to sign-in to both the main site and widget.
Last updated
curl --location 'https://api.v2.walletchat.fun/v1/name'
--header 'Content-Type: application/json'
--header 'Authorization: Bearer <Paid_API_Key>'
--data-raw '{ "address": "0x8077EAceF1695548902Bc1dE0e62DA1f1bAf92e8",
"email": "billAndTed@universe.com",
"signupsite": "app.excellent.com",
"domain": "excellent.com",
"name": "CyberTed" }'const [messageToSign, setMessageToSign] = useState('')
const [messageSignature, setMesssageSignature] = useState('')
//in event handler for your main site Sign-In
setMessageToSign(message.prepareMessage())
setMesssageSignature(signature)<WalletChatProvider>
<FunctionalComponent {...pageProps} />
<...your wallet handler>
<WalletChatWidget
connectedWallet={
address && activeConnector && chainId
? {
walletName: activeConnector.name,
account: address,
chainId: chain.id,
}
: undefined
}
signedMessageData={
messageToSign && messageSignature
? {
signature: messageSignature,
msgToSign: messageToSign,
}
: undefined
}
/>
</WalletChatProvider>//using RainbowKit (see github for full example)
const { address, connector: activeConnector } = useAccount()
const { chain } = useNetwork()
const [ authStatus, setAuthStatus ] = useState<AuthenticationStatus>('unauthenticated')
const chainId = chain?.id
const [messageToSign, setMessageToSign] = useState('')
const [messageSignature, setMesssageSignature] = useState('')
const authenticationAdapter = createAuthenticationAdapter({
//using WalletChat nonce is optional currently (we accept SIWE nonce)
getNonce: async () => {
let _nonce = ""
const response = await fetch(`https://api.v2.walletchat.fun/users/${address}/nonce`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
})
.then((response) => response.json())
.then(async (usersData: { Nonce: string }) => {
console.log('β
[GET][Nonce]:', usersData)
_nonce = usersData.Nonce
})
.catch((error) => {
console.log('π¨[GET][Nonce]:', error)
})
return _nonce;
},
createMessage: ({ nonce, address, chainId }) => {
setAuthStatus('loading')
return new SiweMessage({
domain: window.location.host,
address,
statement: 'Sign in with Ethereum to the app.',
uri: window.location.origin,
version: '1',
chainId,
nonce,
});
},
getMessageBody: ({ message }) => {
return message.prepareMessage();
},
verify: async ({ message, signature }) => {
// const verifyRes = await fetch('/api/verify', {
// method: 'POST',
// headers: { 'Content-Type': 'application/json' },
// body: JSON.stringify({ message, signature }),
// });
//TODO: customer needs to set these two items
setMessageToSign(message.prepareMessage())
setMesssageSignature(signature)
setAuthStatus('authenticated')
return true;
},
signOut: async () => {
//await fetch('/api/logout');
setAuthStatus('unauthenticated')
},
});
return (
<HotkeysProvider>
<ThemeProvider
attribute="class"
defaultTheme="dark"
value={{
dark: darkTheme.className,
light: 'light',
}}
>
<snip...>
<CartProvider>
<Tooltip.Provider>
<RainbowKitProvider
chains={chains}
theme={rainbowKitTheme}
modalSize="compact"
>
<ToastContextProvider>
<WalletChatProvider>
<FunctionalComponent {...pageProps} />
<WagmiConfig client={wagmiClient}>
<RainbowKitAuthenticationProvider
adapter={authenticationAdapter}
status={authStatus}
>
<RainbowKitProvider chains={chains}>
<Component {...pageProps} />
</RainbowKitProvider>
</RainbowKitAuthenticationProvider>
</WagmiConfig>
<WalletChatWidget
connectedWallet={
address && activeConnector && chainId
? {
walletName: activeConnector.name,
account: address,
chainId: chain.id,
}
: undefined
}
signedMessageData={
messageToSign && messageSignature
? {
signature: messageSignature,
msgToSign: messageToSign,
}
: undefined
}
/>
</WalletChatProvider>
</ToastContextProvider>
</RainbowKitProvider>
</Tooltip.Provider>
</CartProvider>
</ReservoirKitProvider>
</ThemeProvider>
</HotkeysProvider>
)