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.
Integrated Sign-In is a Paid Tier Option
Please reach out to [email protected]
or on Twitter @
wallet_chat
to learn more on pricing and integration steps! WalletChat can enable Integrated Sign-In/SSO for your domain for a short duration prior to payment if desired so you can try before you buy π
Paid Tier Customer Streamline Options
Paid Tier customers can set the username
and email
address of the user within WalletChat.fun if already entered on the customer site. Reach out to [email protected]
to learn more and get an API Key. Paid Tier API key enables the /name functions outlined in more details at the API documentation: https://api.v2.walletchat.fun/docs/index.html
Paid Tier customers also get access to create users within WalletChat, to streamline new user experience. Terms and conditions apply.
Integration Steps
0) Create the WalletChat User via your Backend (Optional)
If you are using Integrated/Single Sign On - Streamlining the user login to WalletChat upon account creation is possible by creating the WalletChat user prior to performing the SSO steps. This way, when a user creates a profile on your site, they can be fully setup within WalletChat without having to enter the same username/email details in WalletChat!
This step is optional, and requires an API key from WalletChat Labs, Inc. Its only required once during profile creation, or profile updates. By using this you agree to the Terms and conditions to only modify users signed up on your site, and only use email addresses you have verified. Any abuse of these terms will result in revoking the API key without warning.
This step only is required for new/update profile changes and must only be done via the customer backend. Any use of this API key in a Front-End will result in WalletChat having to revoke the API key to prevent any unauthorized access.
Here is an example of a curl POST request which will create a new user in WalletChat, with the given details. Curl is used to here simplify the example, use fetch or your favorite HTTP request library and ensure the Content-Type, Authorization and POST body (data-raw below) are set accordingly.
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": "[email protected]",
"signupsite": "app.excellent.com",
"domain": "excellent.com",
"name": "CyberTed" }'
1) Store the Message to Sign and Signature
After the SIWE message has been signed by the user, the integrating site must store the new message being signed, and signature. For example:
const [messageToSign, setMessageToSign] = useState('')
const [messageSignature, setMesssageSignature] = useState('')
//in event handler for your main site Sign-In
setMessageToSign(message.prepareMessage())
setMesssageSignature(signature)
2) Pass Signature Parameters to Widget
Then pass the following parameters to the widget within the :
<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>
After this state is set, the user which has signed a message on the customer site, should be auto-logged into WalletChat and can begin conversations!
Example Integration (React)
Example used live at https://sso.walletchat.fun using RainbowKit: (source: https://github.com/Wallet-Chat/nft-marketplace-demo/tree/TestingSIWEonMainPage)
//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>
)
Last updated