From 4552260c65c8db877a58f908f2ac731142ca9cd1 Mon Sep 17 00:00:00 2001 From: simodrws Date: Thu, 22 Jun 2023 17:17:38 +0200 Subject: [PATCH] feat: refactor masa session, update other entities --- src/refactor/masa-client/query-client.ts | 14 - src/refactor/masa/use-identity-listen.ts | 24 +- src/refactor/masa/use-session-connect.ts | 81 ++++ src/refactor/masa/use-session-listen.ts | 89 +++-- src/refactor/masa/use-session.ts | 352 ++++-------------- src/refactor/masanew.stories.tsx | 112 +++--- .../provider/masa-client-provider.tsx | 21 +- 7 files changed, 289 insertions(+), 404 deletions(-) create mode 100644 src/refactor/masa/use-session-connect.ts diff --git a/src/refactor/masa-client/query-client.ts b/src/refactor/masa-client/query-client.ts index 30bd1701..580c190b 100644 --- a/src/refactor/masa-client/query-client.ts +++ b/src/refactor/masa-client/query-client.ts @@ -58,19 +58,5 @@ export const createQueryClient = () => { }, }); - // const test = new QueryClient({ - // defaultOptions: { - // queries: { - // refetchOnWindowFocus: false, - // cacheTime: 1000 * 60 * 60 * 24, // 24 hours - // }, - // }, - // }); - - // const testPersist = createSyncStoragePersister({ - // storage: window.localStorage, - // }); - - // return test; return queryClient; }; diff --git a/src/refactor/masa/use-identity-listen.ts b/src/refactor/masa/use-identity-listen.ts index 67033c81..de4cda98 100644 --- a/src/refactor/masa/use-identity-listen.ts +++ b/src/refactor/masa/use-identity-listen.ts @@ -1,6 +1,5 @@ import { useAsync } from 'react-use'; import { useMasaClient } from '../masa-client/use-masa-client'; -import { useNetwork } from '../wallet-client/network'; import type { useSession } from './use-session'; import type { useIdentity } from './use-identity'; @@ -13,26 +12,13 @@ export const useIdentityListen = ({ getIdentity: ReturnType['getIdentity']; sessionAddress?: ReturnType['sessionAddress']; }) => { - const { masaAddress, masaNetwork } = useMasaClient(); - const { activeNetwork } = useNetwork(); - // const { identity, getIdentity } = useIdentity(); - + const { masaAddress } = useMasaClient(); useAsync(async () => { - if ( - masaAddress === sessionAddress && - masaNetwork === activeNetwork && - identity?.address !== masaAddress - ) - // * NOTE: we need to make sure the states are in sync before loading the identity + // * NOTE: we need to make sure the states are in sync before loading the identity + if (masaAddress === sessionAddress && identity?.address !== masaAddress) { await getIdentity(); + } return undefined; - }, [ - getIdentity, - masaAddress, - activeNetwork, - masaNetwork, - sessionAddress, - identity, - ]); + }, [getIdentity, masaAddress, sessionAddress, identity]); }; diff --git a/src/refactor/masa/use-session-connect.ts b/src/refactor/masa/use-session-connect.ts new file mode 100644 index 00000000..48b2a3ff --- /dev/null +++ b/src/refactor/masa/use-session-connect.ts @@ -0,0 +1,81 @@ +import { useAsyncFn } from 'react-use'; +import type { ISession } from '@masa-finance/masa-sdk'; +import { useWallet } from '../wallet-client/wallet/use-wallet'; +import { useMasaClient } from '../masa-client/use-masa-client'; +import { useMasaQueryClient } from '../masa-client/use-masa-query-client'; + +export const useSessionConnect = () => { + const { address, isDisconnected } = useWallet(); + const { sdk: masa, masaAddress } = useMasaClient(); + const queryClient = useMasaQueryClient(); + + const [{ loading: isLoggingIn }, loginSessionAsync] = useAsyncFn(async () => { + if (!masa) return null; + if (!masaAddress) return null; + if (masaAddress !== address) return null; + if (isDisconnected) return null; + + const loginObj = await masa.session.login(); + + await queryClient.invalidateQueries([ + 'session-new-check', + { masaAddress, persist: true }, + ]); + await queryClient.invalidateQueries([ + 'session-new', + { masaAddress, persist: false }, + ]); + + if (!loginObj) { + return null; + } + + await queryClient.fetchQuery([ + 'session-new-check', + { persist: true, masaAddress }, + ]); + await queryClient.fetchQuery([ + 'session-new', + { persist: false, masaAddress }, + ]); + + return loginObj as unknown as ISession & { + userId: string; + address: string; + }; + }, [queryClient, masa, address, masaAddress, isDisconnected]); + + const [{ loading: isLoggingOut }, logoutSession] = useAsyncFn(async () => { + // if (!masa) return null; + // if (!masaAddress) return null; + // if (masaAddress !== address) return null; + // if (isDisconnected) return null; + + const result = await masa?.session.logout(); + await Promise.all([ + queryClient.invalidateQueries([ + 'session-new-check', + { masaAddress, persist: true }, + ]), + queryClient.invalidateQueries([ + 'session-new', + { masaAddress, persist: false }, + ]), + ]); + + queryClient.setQueryData(['session-new-check', { masaAddress }], false); + queryClient.setQueryData( + ['session-new', { masaAddress, persist: false }], + null + ); + + return result; + }, [masa, queryClient, masaAddress]); + + return { + loginSessionAsync, + logoutSession, + isLoggingIn, + isLoggingOut, + }; +}; diff --git a/src/refactor/masa/use-session-listen.ts b/src/refactor/masa/use-session-listen.ts index 10dba6f1..31c9d8fd 100644 --- a/src/refactor/masa/use-session-listen.ts +++ b/src/refactor/masa/use-session-listen.ts @@ -1,52 +1,71 @@ import { useAsync } from 'react-use'; -import { useSession } from './use-session'; -import { useWallet } from '../wallet-client/wallet/use-wallet'; +import { useState } from 'react'; import { useMasaClient } from '../masa-client/use-masa-client'; +import { useMasaQueryClient } from '../masa-client/use-masa-query-client'; +import type { useSession } from './use-session'; -export const useSessionListen = () => { +export const useSessionListen = ({ + sessionAddress, + hasSession, + logoutSession, + checkLogin, +}: { + hasSession?: boolean | null; + sessionAddress?: string; + logoutSession: ReturnType['logoutSession']; + checkLogin: ReturnType['checkLogin']; +}) => { + const [isUpdatingSession, setUpdating] = useState(false); const { masaAddress } = useMasaClient(); - const { - session, - sessionAddress, - isLoadingSession, - logoutSession, - hasSession, - } = useSession(); - const { isDisconnected } = useWallet(); + const queryClient = useMasaQueryClient(); // * useEffect to handle account switches and disconnect useAsync(async () => { - if (isLoadingSession) return; - - if ( - session && - masaAddress && - masaAddress === session?.user.address && - hasSession - ) { - return; - } + if (isUpdatingSession) return; - if (isDisconnected) { - await logoutSession(); - return; + if (!isUpdatingSession) { + setUpdating(true); } - if ( - hasSession && - sessionAddress && - masaAddress && - sessionAddress !== masaAddress - ) { + if (!!sessionAddress && sessionAddress !== masaAddress && hasSession) { + await Promise.all([ + // queryClient.setQueryData( + // ['session-new', { masaAddress, persist: false }], + // null + // ), + queryClient.setQueryData( + ['session-new-check', { masaAddress, persist: true }], + false + ), + ]); + + await queryClient.invalidateQueries([ + 'session-new-check', + { masaAddress: sessionAddress, persist: true }, + ]); + await queryClient.invalidateQueries([ + 'session-new', + { masaAddress: sessionAddress, persist: false }, + ]); + await logoutSession(); + + await checkLogin(); } + + setUpdating(false); }, [ - isLoadingSession, - sessionAddress, + isUpdatingSession, + setUpdating, + queryClient, masaAddress, - isDisconnected, - logoutSession, + sessionAddress, hasSession, - session, + logoutSession, + checkLogin, ]); + + return { + isUpdatingSession, + }; }; diff --git a/src/refactor/masa/use-session.ts b/src/refactor/masa/use-session.ts index a6e0be13..d19144e0 100644 --- a/src/refactor/masa/use-session.ts +++ b/src/refactor/masa/use-session.ts @@ -1,318 +1,130 @@ +import { useAsync, useAsyncFn } from 'react-use'; import { useQuery } from '@tanstack/react-query'; -import { useAsyncFn } from 'react-use'; -import type { ISession } from '@masa-finance/masa-sdk'; import { useMemo } from 'react'; -import { useWallet } from '../wallet-client/wallet/use-wallet'; import { useMasaClient } from '../masa-client/use-masa-client'; import { useMasaQueryClient } from '../masa-client/use-masa-query-client'; - +import { useWallet } from '../wallet-client/wallet/use-wallet'; import { MasaQueryClientContext } from '../provider/masa-state-provider'; +import { useSessionConnect } from './use-session-connect'; -// * NOTE: react-query does not allow us to pass undefined as a function return, -// * NOTE: so we need to convert an undefined result in every query to null export const useSession = () => { - const { address, isDisconnected, previousAddress, isConnected } = useWallet(); - const { masa, masaAddress } = useMasaClient(); + const { address } = useWallet(); const queryClient = useMasaQueryClient(); - - // * callbacks - const [{ loading: isCheckingSession }, checkSessionAsync] = - useAsyncFn(async () => { - if (!masaAddress) return null; - if (!masa) return null; - if (isDisconnected) return null; - - const hasSesh = await masa?.session.checkLogin(); - if (hasSesh !== undefined || hasSesh !== null) return hasSesh; - - return null; - }, [masa, masaAddress, isDisconnected]); - - const [, loginSessionAsync] = useAsyncFn(async () => { - if (!masa) return null; - if (!masaAddress) return null; - if (masaAddress !== address) return null; - if (isDisconnected) return null; - const loginObj = await masa.session.login(); - - if (!loginObj) { - return null; - } - - return loginObj as unknown as ISession & { - userId: string; - address: string; - }; - }, [masa, address, masaAddress, isDisconnected]); - + const { sdk: masa, masaAddress } = useMasaClient(); + const { isLoggingIn, isLoggingOut, loginSessionAsync, logoutSession } = + useSessionConnect(); const [, getSessionAsync] = useAsyncFn(async () => { - if (!masa) return null; - if (!masaAddress) return null; - const seshFromGet = await masa?.session.getSession(); + return seshFromGet ?? null; + }, [masa]); - if (seshFromGet === undefined || seshFromGet === null) { - return null; - } - - return seshFromGet; - }, [masaAddress, masa]); - - const [, onSettledGetSession] = useAsyncFn( - async (data: ISession | null | undefined) => { - if (!data) return; + const [, checkSessionAsync] = useAsyncFn(async () => { + const hasSesh = await masa?.session.checkLogin(); - if (data?.user.address !== masaAddress) { - await queryClient.invalidateQueries([ - 'session', - { masaAddress, persist: false }, - ]); - queryClient.setQueryData( - ['session', { masaAddress, persist: false }], - null - ); + return hasSesh ?? null; + }, [masa]); - await queryClient.invalidateQueries([ - 'session-check', - { masaAddress, persist: false }, - ]); - queryClient.setQueryData( - ['session', { masaAddress, persist: false }], - false - ); - } - }, - [masaAddress, queryClient] - ); // * queries - const { - data: session, - isFetching: isFetchingSession, - refetch: getSession, - } = useQuery({ - queryKey: ['session', { masaAddress, persist: false }], - enabled: false, - cacheTime: 0, - context: MasaQueryClientContext, - onSettled: onSettledGetSession, - queryFn: getSessionAsync, - }); - - // * logout callback - const [{ loading: isLoggingOut }, logoutSession] = useAsyncFn(async () => { - await masa?.session.logout(); - - await queryClient.invalidateQueries([ - 'session-check', - { masaAddress, persist: false }, - ]); - await queryClient.invalidateQueries(['session-login', { masaAddress }]); - await queryClient.invalidateQueries([ - 'session', - { masaAddress, persist: false }, - ]); - queryClient.setQueryData( - ['session-check', { masaAddress, persist: false }], - null - ); - queryClient.setQueryData(['session-login', { masaAddress }], null); - queryClient.setQueryData( - ['session', { masaAddress, persist: false }], - null - ); - }, [masa, queryClient, masaAddress]); - - // * session address - const sessionAddress = useMemo(() => { - if (!session) return undefined; - if (!session.user) return undefined; - return session.user.address as `0x${string}`; - }, [session]); - - // * callback to handle succesful login to sync session state - const [, onSuccessLogin] = useAsyncFn( - async (data: boolean) => { - switch (data) { - case true: { - if (isLoggingOut) break; - - if (session && masaAddress === session?.user.address) { - break; - } - - if ( - previousAddress === undefined || - previousAddress !== masaAddress - ) { - await queryClient.invalidateQueries([ - 'session', - { masaAddress, persist: false }, - ]); - await queryClient.fetchQuery([ - 'session', - { masaAddress, persist: false }, - ]); - break; - } - - const checkedLogin = await checkSessionAsync(); - - if (!checkedLogin) { - await logoutSession(); - break; - } - - // * we are in a valid session but our session data needs to be updated. - await queryClient.fetchQuery([ - 'session', - { masaAddress, persist: false }, - ]); - break; - } - - case false: { - await queryClient.invalidateQueries([ - 'session', - { masaAddress, persist: false }, - ]); - await queryClient.invalidateQueries([ - 'session-login', - { masaAddress }, - ]); - queryClient.setQueryData( - ['session', { masaAddress, persist: false }], - null - ); - queryClient.setQueryData(['session-login', { masaAddress }], null); - break; - } - case undefined: { - await queryClient.invalidateQueries([ - 'session', - { masaAddress, persist: false }, - ]); - await queryClient.invalidateQueries([ - 'session-login', - { masaAddress }, - ]); - queryClient.setQueryData( - ['session', { masaAddress, persist: false }], - null - ); - queryClient.setQueryData(['session-login', { masaAddress }], null); - break; - } - default: { - break; - } - } - }, - [ - masaAddress, - previousAddress, - checkSessionAsync, - queryClient, - session, - isLoggingOut, - logoutSession, - ] - ); - const { data: hasSession, refetch: checkLogin, isFetching: isCheckingLogin, } = useQuery({ - queryKey: ['session-check', { masaAddress, persist: false }], - enabled: !!masa && !!masaAddress, + queryKey: ['session-new-check', { masaAddress, persist: true }], + enabled: !!masaAddress, context: MasaQueryClientContext, cacheTime: 0, - onSuccess: onSuccessLogin, - queryFn: async () => { - if (!isConnected) return false; - if (!masa) return false; - - if (masaAddress !== address) { - await queryClient.invalidateQueries([ - 'session', - { masaAddress, persist: false }, - ]); - await queryClient.invalidateQueries([ - 'session-login', - { masaAddress, persist: false }, - ]); - - return false; + if (!checkSessionAsync) { + return null; } const hasSesh = await checkSessionAsync(); - if (hasSesh) { - return hasSesh; - } - - return false; + return hasSesh ?? false; }, }); - const [, onSettledLogin] = useAsyncFn(async () => { - if (!masa) return; - if (!address) return; - if (!masaAddress) return; - if (masaAddress === sessionAddress) return; - await checkLogin(); - }, [masa, address, masaAddress, sessionAddress, checkLogin]); - - const { refetch: loginSession, isFetching: isLoggingIn } = useQuery({ - queryKey: ['session-login', { masaAddress }], - enabled: false, - context: MasaQueryClientContext, - refetchOnMount: false, + const { + data: session, + isFetching: isFetchingSession, + refetch: getSession, + } = useQuery({ + queryKey: ['session-new', { masaAddress, persist: false }], + enabled: + !!hasSession && + masaAddress === address && + !isLoggingOut && + !!getSessionAsync, cacheTime: 0, - onSettled: onSettledLogin, - + context: MasaQueryClientContext, queryFn: async () => { - if (isDisconnected) return null; - if (hasSession) return null; + const sesh = await getSessionAsync(); - await loginSessionAsync(); - - return null; + return sesh ?? null; }, }); + const sessionAddress = useMemo(() => { + if (address === masaAddress && session?.user.address) { + return session.user.address; + } + + return undefined; + }, [session, address, masaAddress]); + + useAsync(async () => { + if (!!sessionAddress && sessionAddress !== masaAddress && hasSession) { + console.log('useAsync', { + sessionAddress, + masaAddress, + hasSession, + }); + await Promise.all([ + // queryClient.setQueryData( + // ['session-new', { masaAddress, persist: false }], + // null + // ), + queryClient.setQueryData( + ['session-new-check', { masaAddress, persist: true }], + false + ), + ]); + + await logoutSession(); + // await queryClient.invalidateQueries([ + // 'session-new-check', + // { masaAddress: sessionAddress, persist: true }, + // ]); + + await checkLogin(); + } + }, [ + queryClient, + masaAddress, + sessionAddress, + hasSession, + logoutSession, + checkLogin, + ]); + const isLoadingSession = useMemo( - () => - isLoggingIn || - isLoggingOut || - isFetchingSession || - isCheckingLogin || - isCheckingSession, - [ - isLoggingIn, - isLoggingOut, - isFetchingSession, - isCheckingLogin, - isCheckingSession, - ] + () => isFetchingSession || isCheckingLogin || isLoggingIn || isLoggingOut, + [isFetchingSession, isCheckingLogin, isLoggingIn, isLoggingOut] ); return { + hasSession, session, sessionAddress, - getSession, isFetchingSession, - hasSession, - checkSessionAsync, - isCheckingSession, isCheckingLogin, - loginSession, - logoutSession, + getSession, + checkLogin, isLoggingIn, isLoggingOut, - isLoggedIn: hasSession, - checkLogin, + loginSessionAsync, + logoutSession, isLoadingSession, }; }; diff --git a/src/refactor/masanew.stories.tsx b/src/refactor/masanew.stories.tsx index b8516237..0c2ecbcd 100644 --- a/src/refactor/masanew.stories.tsx +++ b/src/refactor/masanew.stories.tsx @@ -1,4 +1,4 @@ -import * as buffer from 'buffer'; +import buffer from 'buffer'; import { ReactQueryDevtoolsPanel } from '@tanstack/react-query-devtools'; // eslint-disable-line import/no-extraneous-dependencies import type { Args, Meta } from '@storybook/react'; import type { Chain } from 'wagmi'; @@ -9,8 +9,6 @@ import { useConfig } from './base-provider'; import { useWallet } from './wallet-client/wallet/use-wallet'; import { useNetwork } from './wallet-client/network/use-network'; -// import { useIdentity } from './masa-feature/use-identity'; -import { useSession } from './masa/use-session'; import { useMasaClient } from './masa-client/use-masa-client'; import { useIdentity } from './masa/use-identity'; import { useSoulNames } from './masa/use-soulnames'; @@ -19,6 +17,8 @@ import { useGreen } from './masa/use-green'; import { useSBT } from './masa/use-sbt'; import MasaProvider from './masa-provider'; import { MasaQueryClientContext } from './provider/masa-state-provider'; +import { useSession } from './masa/use-session'; +// import { useIdentity } from './masa-feature/use-identity'; // * nextjs fix // * TODO: move this to index.ts file at some point @@ -235,7 +235,7 @@ const SessionInfo = () => { session, // loginSession, // logoutSession, - // sessionAddress, + sessionAddress, isLoggingIn, isLoggingOut, hasSession, @@ -250,6 +250,7 @@ const SessionInfo = () => {

Session

  • isLoadingSession: {String(isLoadingSession)}
  • hasSession: {String(hasSession)}
  • +
  • sessionAddress: {String(sessionAddress)}
  • isLoggingIn: {String(isLoggingIn)}
  • isLoggingOut: {String(isLoggingOut)}
  • @@ -337,17 +338,54 @@ const SBTInfo = () => { ); }; + +const SessionButtons = () => { + const { loginSessionAsync, logoutSession, checkLogin } = useSession(); + + return ( +
      +

      Session

      +
    • + +
    • + {/*
    • + +
    • */} +
    • + +
    • +
    • + +
    • +
    + ); +}; + const MasaInfo = () => { - // const { identity, isLoadingIdentity } = useIdentity(); - const { - loginSession, - logoutSession, - sessionAddress, - hasSession, - isLoadingSession, - checkLogin, - } = useSession(); - const { isDisconnected } = useWallet(); const { activeNetwork, activeChainId } = useNetwork(); const { masaAddress, masaNetwork } = useMasaClient(); @@ -371,7 +409,7 @@ const MasaInfo = () => {

      Masa

    • masaAddress: {masaAddress}
    • -
    • sessionAddress: {sessionAddress}
    • +
    • masaNetwork: {masaNetwork}
    • activeNetwork: {activeNetwork}
    • activeChainId: {activeChainId}
    • @@ -383,45 +421,6 @@ const MasaInfo = () => {
    -
      -

      Session

      -
    • - -
    • - {/*
    • - -
    • */} -
    • - -
    • -
    • - -
    • -
    {/*

      Identity

    • @@ -473,11 +472,14 @@ const Component = (): JSX.Element => { + {/* */} + + + -

        Config

      • diff --git a/src/refactor/provider/masa-client-provider.tsx b/src/refactor/provider/masa-client-provider.tsx index 9f8e8e1b..ec4fc387 100644 --- a/src/refactor/provider/masa-client-provider.tsx +++ b/src/refactor/provider/masa-client-provider.tsx @@ -5,7 +5,6 @@ import { useIdentity } from '../masa/use-identity'; import { useSession } from '../masa/use-session'; import { useCreditScores } from '../masa/use-credit-scores'; import { useSoulNames } from '../masa/use-soulnames'; -import { useSessionListen } from '../masa/use-session-listen'; import { useGreen } from '../masa/use-green'; export interface MasaClientProviderValue { @@ -21,22 +20,22 @@ export const MasaClientContext = createContext({} as MasaClientProviderValue); export const MasaClientProvider = ({ children }: { children: ReactNode }) => { const { masa } = useMasaClient(); - const { session, loginSession, logoutSession, sessionAddress } = useSession(); + // const { session, loginSession, logoutSession, sessionAddress } = useSession(); const { identity } = useIdentity(); const { creditScores } = useCreditScores(); const { soulnames } = useSoulNames(); const { greens } = useGreen(); - useSessionListen(); + // useSessionListen(); const masaClientProviderValue: MasaClientProviderValue = useMemo( () => ({ masa, - session, - sessionAddress, - loginSession, - logoutSession, + // session, + // sessionAddress, + // loginSession, + // logoutSession, identity, soulnames, creditScores, @@ -44,11 +43,11 @@ export const MasaClientProvider = ({ children }: { children: ReactNode }) => { } as MasaClientProviderValue), [ masa, - session, identity, - sessionAddress, - loginSession, - logoutSession, + // session, + // sessionAddress, + // loginSession, + // logoutSession, soulnames, creditScores, greens,