-
Notifications
You must be signed in to change notification settings - Fork 132
Send EM transaction from Audius client for connect wallet feature [C-3604] [C-3605] #7168
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,6 +27,7 @@ | |
|
|
||
| .manageAccountContainer { | ||
| margin-top: var(--unit-5); | ||
| margin-bottom: var(--unit-4); | ||
| } | ||
|
|
||
| .manageBtns { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,49 +1,58 @@ | ||
| import { OAUTH_URL, DecodedUserToken } from '@audius/sdk' | ||
| import { useQueryClient } from '@tanstack/react-query' | ||
| import { getDashboardWalletUserQueryKey } from 'hooks/useDashboardWalletUsers' | ||
| import { useEffect } from 'react' | ||
| import { useDispatch } from 'react-redux' | ||
| import { audiusSdk } from 'services/Audius/sdk' | ||
| import { useUser } from 'store/cache/user/hooks' | ||
| import { | ||
| AUDIUS_NETWORK_ID, | ||
| ETH_NETWORK_ID, | ||
| disableRefreshAfterNetworkChange, | ||
| switchNetwork | ||
| } from 'utils/switchNetwork' | ||
| import { disableAudiusProfileRefetch } from 'store/account/slice' | ||
|
|
||
| const env = import.meta.env.VITE_ENVIRONMENT | ||
|
|
||
| let resolveUserHandle = null | ||
| let receiveUserHandlePromise = null | ||
|
|
||
| const receiveUserId = async (event: MessageEvent) => { | ||
| const sdk = await audiusSdk() | ||
| const oauthOrigin = new URL(OAUTH_URL[env]).origin | ||
| if ( | ||
| event.origin !== oauthOrigin || | ||
| event.source !== sdk.oauth.activePopupWindow || | ||
| !event.data.state | ||
| ) { | ||
| return | ||
| } | ||
| if (sdk.oauth.getCsrfToken() !== event.data.state) { | ||
| console.error('State mismatch.') | ||
| return | ||
| } | ||
| if (event.data.userHandle != null) { | ||
| resolveUserHandle(event.data.userHandle) | ||
| } | ||
| } | ||
|
|
||
| export const useConnectAudiusProfile = (wallet: string) => { | ||
| const { user } = useUser({ wallet }) | ||
| const queryClient = useQueryClient() | ||
|
|
||
| const handleSuccess = async profile => { | ||
| const dispatch = useDispatch() | ||
| const handleSuccess = async (profile: DecodedUserToken) => { | ||
| window.removeEventListener('message', receiveUserId) | ||
| const sdk = await audiusSdk() | ||
| disableRefreshAfterNetworkChange.value = true | ||
| const switched = await switchNetwork(AUDIUS_NETWORK_ID) | ||
| if (switched) { | ||
| await sdk.dashboardWalletUsers.connectUserToDashboardWallet({ | ||
| wallet: user?.wallet ?? wallet, | ||
| userId: profile.userId, | ||
| userSignature: profile.txSignature | ||
| }) | ||
| // Optimistically set user | ||
| await queryClient.cancelQueries({ queryKey: ['todos'] }) | ||
| const audiusUser = await sdk.users.getUser({ id: profile.userId }) | ||
| queryClient.setQueryData(getDashboardWalletUserQueryKey(wallet), { | ||
| wallet, | ||
| user: audiusUser | ||
| }) | ||
|
|
||
| const switchedBack = await switchNetwork(ETH_NETWORK_ID) | ||
| if (switchedBack) { | ||
| window.ethereum.on('chainChanged', () => { | ||
| disableRefreshAfterNetworkChange.value = false | ||
| // Optimistically set user | ||
| await queryClient.cancelQueries({ | ||
| queryKey: getDashboardWalletUserQueryKey(wallet) | ||
| }) | ||
| dispatch(disableAudiusProfileRefetch()) | ||
|
|
||
| try { | ||
| const audiusUser = await sdk.users.getUser({ id: profile.userId }) | ||
| if (audiusUser?.data) { | ||
| queryClient.setQueryData(getDashboardWalletUserQueryKey(wallet), { | ||
| wallet, | ||
| user: audiusUser.data | ||
| }) | ||
| } else { | ||
| disableRefreshAfterNetworkChange.value = false | ||
| } | ||
| } else { | ||
| disableRefreshAfterNetworkChange.value = false | ||
| } catch { | ||
| console.error("Couldn't fetch Audius profile data.") | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -53,13 +62,18 @@ export const useConnectAudiusProfile = (wallet: string) => { | |
| env: env === 'production' ? 'production' : 'staging', | ||
| successCallback: handleSuccess, | ||
| errorCallback: (errorMessage: string) => { | ||
| // Error calllback | ||
| window.removeEventListener('message', receiveUserId) | ||
| console.error(errorMessage) | ||
| } | ||
| }) | ||
| } | ||
|
|
||
| const loginWithAudius = async () => { | ||
| window.removeEventListener('message', receiveUserId) | ||
| receiveUserHandlePromise = new Promise(resolve => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sneaky
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just double checking we can get back to a repeatable state if something fails/want to try again, if those are actual requirements
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes we can! |
||
| resolveUserHandle = resolve | ||
| }) | ||
| window.addEventListener('message', receiveUserId, false) | ||
| const sdk = await audiusSdk() | ||
| sdk.oauth.login({ | ||
| scope: 'write_once', | ||
|
|
@@ -68,6 +82,21 @@ export const useConnectAudiusProfile = (wallet: string) => { | |
| wallet | ||
| } | ||
| }) | ||
|
|
||
| // Leg 1: Receive Audius user id from OAuth popup | ||
| const userHandle = await receiveUserHandlePromise | ||
| // Sign wallet signature from EM transaction | ||
| const message = `Connecting Audius user @${userHandle} at ${Math.round( | ||
| new Date().getTime() / 1000 | ||
| )}` | ||
| const signature = await window.audiusLibs.web3Manager.sign(message) | ||
|
|
||
| const walletSignature = { message, signature } | ||
| // Leg 2: Send wallet signature to OAuth popup | ||
| sdk.oauth.activePopupWindow.postMessage( | ||
| { state: sdk.oauth.getCsrfToken(), walletSignature }, | ||
| new URL(OAUTH_URL[env]).origin | ||
| ) | ||
| } | ||
|
|
||
| useEffect(() => { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we maybe have a reject case here so the hook doesn't stall forever in the case where userHandle is null?