diff --git a/src/refactor/masa-client-provider.tsx b/src/refactor/masa-client-provider.tsx index 54e2db98..27d55bc6 100644 --- a/src/refactor/masa-client-provider.tsx +++ b/src/refactor/masa-client-provider.tsx @@ -1,10 +1,10 @@ import React, { ReactNode, createContext, useContext, useMemo } from 'react'; import { useAsync } from 'react-use'; import { useMasaClient } from './masa-client/use-masa-client'; -import { useIdentity } from './masa-feature/use-identity'; +import { useIdentity } from './masa/use-identity'; import { useWallet } from './wallet-client/wallet/use-wallet'; -import { useSession } from './masa-feature/use-session'; +import { useSession } from './masa/use-session'; export interface MasaClientProviderValue { masa?: ReturnType['sdk']; diff --git a/src/refactor/masa-client/use-masa-client.ts b/src/refactor/masa-client/use-masa-client.ts index 305b392a..d1eeb5e1 100644 --- a/src/refactor/masa-client/use-masa-client.ts +++ b/src/refactor/masa-client/use-masa-client.ts @@ -47,7 +47,9 @@ export const useMasaClient = () => { const { value: masaChainId } = useAsync(async () => { if (masa) { const mChainId = await masa.config.signer?.getChainId(); + if (mChainId !== activeChainId) return undefined; + return mChainId; } @@ -56,10 +58,12 @@ export const useMasaClient = () => { const { value: masaNetwork } = useAsync(async () => { if (!masa) return undefined; + if (masaChainId !== activeChainId) return undefined; + const network = await masa.config.signer?.provider?.getNetwork(); - if (network?.name !== activeNetwork) return undefined; - return network?.name; - }, [masa, activeNetwork]); + + return network?.name === 'unknown' ? activeNetwork : network?.name; + }, [masa, activeNetwork, activeChainId, masaChainId]); const masaClient = useMemo(() => { if (address !== masaAddress) { diff --git a/src/refactor/masa-client/use-masa-query-client.ts b/src/refactor/masa-client/use-masa-query-client.ts new file mode 100644 index 00000000..b319d8d0 --- /dev/null +++ b/src/refactor/masa-client/use-masa-query-client.ts @@ -0,0 +1,12 @@ +import { useQueryClient } from '@tanstack/react-query'; +import { useClient } from 'wagmi'; +import { QcContext } from '../masa-provider'; + +export const useMasaQueryClient = () => { + const queryClient = useQueryClient({ context: QcContext }); + const client = useClient(); + + console.log('wagmiclient', { client }); + + return queryClient; +}; diff --git a/src/refactor/masa-client/use-masa-sdk.ts b/src/refactor/masa-client/use-masa-sdk.ts index a5f77b3e..30568196 100644 --- a/src/refactor/masa-client/use-masa-sdk.ts +++ b/src/refactor/masa-client/use-masa-sdk.ts @@ -107,6 +107,7 @@ export const useMasaSDK = ( verbose, }); }, [ + address, signer, apiUrl, environmentName, diff --git a/src/refactor/masa/use-identity-listen.ts b/src/refactor/masa/use-identity-listen.ts new file mode 100644 index 00000000..67033c81 --- /dev/null +++ b/src/refactor/masa/use-identity-listen.ts @@ -0,0 +1,38 @@ +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'; + +export const useIdentityListen = ({ + identity, + getIdentity, + sessionAddress, +}: { + identity?: ReturnType['identity']; + getIdentity: ReturnType['getIdentity']; + sessionAddress?: ReturnType['sessionAddress']; +}) => { + const { masaAddress, masaNetwork } = useMasaClient(); + const { activeNetwork } = useNetwork(); + // const { identity, getIdentity } = useIdentity(); + + 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 + await getIdentity(); + + return undefined; + }, [ + getIdentity, + masaAddress, + activeNetwork, + masaNetwork, + sessionAddress, + identity, + ]); +}; diff --git a/src/refactor/masa/use-identity-purchase.ts b/src/refactor/masa/use-identity-purchase.ts new file mode 100644 index 00000000..ffc58a10 --- /dev/null +++ b/src/refactor/masa/use-identity-purchase.ts @@ -0,0 +1,50 @@ +import { useAsyncFn } from 'react-use'; +import type { PaymentMethod } from '@masa-finance/masa-sdk'; +import { useMasaClient } from '../masa-client/use-masa-client'; + + +export const useIdentityPurchase = () => { + const { sdk: masa } = useMasaClient(); + const [ + { loading: isPurchasingIdentity, value: hasPurchasedIdentity }, + purchaseIdentity, + ] = useAsyncFn(async () => { + const purchasedIdentity = await masa?.identity.create(); + return purchasedIdentity?.success; + }, [masa]); + + const [ + { + value: hasPurchasedIdentityWithSoulName, + loading: isPurchasingIdentityWithSoulName, + }, + purchaseIdentityWithSoulName, + ] = useAsyncFn( + async ( + paymentMethod: PaymentMethod, + soulname: string, + registrationPeriod: number, + style?: string + ) => { + const result = await masa?.identity.createWithSoulName( + paymentMethod, + soulname, + registrationPeriod, + style + ); + + return !!result?.success; + }, + [masa] + ); + + return { + purchaseIdentity, + isPurchasingIdentity, + hasPurchasedIdentity, + + purchaseIdentityWithSoulName, + isPurchasingIdentityWithSoulName, + hasPurchasedIdentityWithSoulName, + }; +}; diff --git a/src/refactor/masa-feature/use-identity.ts b/src/refactor/masa/use-identity.ts similarity index 72% rename from src/refactor/masa-feature/use-identity.ts rename to src/refactor/masa/use-identity.ts index ce4ae01f..0e0319af 100644 --- a/src/refactor/masa-feature/use-identity.ts +++ b/src/refactor/masa/use-identity.ts @@ -1,19 +1,20 @@ -import { useAsync, useAsyncFn } from 'react-use'; +import { useAsyncFn } from 'react-use'; import { useQuery } from '@tanstack/react-query'; +import { useMemo } from 'react'; import { useMasaClient } from '../masa-client/use-masa-client'; import { useSession } from './use-session'; import { QcContext } from '../masa-provider'; import { useNetwork } from '../wallet-client/network'; import { useWallet } from '../wallet-client/wallet/use-wallet'; +import { isIdentityContractAvailible } from './utils'; +import { useIdentityListen } from './use-identity-listen'; // import { useWallet } from '../wallet-client/wallet/use-wallet'; export const useIdentity = () => { - // const queryClient = useQueryClient({ context: QcContext }); const { masaAddress, sdk: masa, masaNetwork } = useMasaClient(); const { isDisconnected } = useWallet(); const { sessionAddress, hasSession } = useSession(); const { activeNetwork } = useNetwork(); - // const { address } = useWallet(); const [{ loading: isLoadingIdentity }, loadIdentity] = useAsyncFn(async () => { @@ -25,8 +26,8 @@ export const useIdentity = () => { if (!hasSession) return null; return await masa.identity.load(masaAddress); } catch (error) { - console.log('IM IN THIS ERROR', { error }); - throw error; + console.error('ERROR loading identity', error); + return null; } }, [ masaAddress, @@ -48,32 +49,23 @@ export const useIdentity = () => { 'identity', { masaAddress, sessionAddress, masaNetwork, persist: false }, ], - onSettled: () => console.log('settled identity'), queryFn: async () => loadIdentity(), }); - useAsync(async () => { - if ( - masaAddress === sessionAddress && - masaNetwork === activeNetwork && - identity?.address !== masaAddress - ) - await loadIdentity(); + const hasIdentity = useMemo(() => !!identity, [identity]); + const isIdentityAvailibleInNetwork = useMemo( + () => isIdentityContractAvailible(masa), + [masa] + ); - return undefined; - }, [ - loadIdentity, - masaAddress, - activeNetwork, - masaNetwork, - sessionAddress, - identity, - ]); + useIdentityListen({ identity, getIdentity, sessionAddress }); return { identity, + hasIdentity, isLoadingIdentity, isFetchingIdentity, + isIdentityAvailibleInNetwork, getIdentity, }; }; diff --git a/src/refactor/masa-feature/use-session.ts b/src/refactor/masa/use-session.ts similarity index 97% rename from src/refactor/masa-feature/use-session.ts rename to src/refactor/masa/use-session.ts index 632d8112..36e217a3 100644 --- a/src/refactor/masa-feature/use-session.ts +++ b/src/refactor/masa/use-session.ts @@ -1,18 +1,18 @@ -import { useQuery, useQueryClient } from '@tanstack/react-query'; +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 { QcContext } from '../masa-provider'; // * 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 -// * TODO: split up the queries, pass context via function variable to avoid dependency cycle export const useSession = () => { const { address, isDisconnected, previousAddress, isConnected } = useWallet(); const { masa, masaAddress } = useMasaClient(); - const queryClient = useQueryClient({ context: QcContext }); + const queryClient = useMasaQueryClient(); // * callbacks const [{ loading: isCheckingSession }, checkSessionAsync] = diff --git a/src/refactor/masa/use-soulnames-purchase.ts b/src/refactor/masa/use-soulnames-purchase.ts new file mode 100644 index 00000000..99fe75c1 --- /dev/null +++ b/src/refactor/masa/use-soulnames-purchase.ts @@ -0,0 +1,37 @@ +import type { PaymentMethod } from '@masa-finance/masa-sdk'; +import { useAsyncFn } from 'react-use'; +import { useMasaClient } from '../masa-client/use-masa-client'; +import { useMasaQueryClient } from '../masa-client/use-masa-query-client'; + +export const useSoulNamesPurchase = () => { + const { sdk: masa } = useMasaClient(); + const queryClient = useMasaQueryClient(); + const [ + { loading: isPurchasingSoulName, value: hasPurchasedSoulName }, + purchaseSoulName, + ] = useAsyncFn( + async ( + soulname: string, + registrationPeriod: number, + paymentMethod: PaymentMethod, + style?: string + ) => { + const result = await masa?.soulName.create( + paymentMethod, + soulname, + registrationPeriod, + undefined, + style + ); + await queryClient.invalidateQueries(['soulnames']); + return !!result?.success; + }, + [masa, queryClient] + ); + + return { + isPurchasingSoulName, + hasPurchasedSoulName, + purchaseSoulName, + }; +}; diff --git a/src/refactor/masa/use-soulnames.ts b/src/refactor/masa/use-soulnames.ts new file mode 100644 index 00000000..19fe8355 --- /dev/null +++ b/src/refactor/masa/use-soulnames.ts @@ -0,0 +1,25 @@ +import { useQuery } from '@tanstack/react-query'; +import { useAsync } from 'react-use'; +import { QcContext } from '../masa-provider'; +import { useMasaClient } from '../masa-client/use-masa-client'; + +export const useSoulNames = () => { + const { masaAddress, masaNetwork, sdk: masa } = useMasaClient(); + const { + data: soulnames, + isFetching: isLoadingSoulnames, + refetch: getSoulnames, + } = useQuery({ + enabled: !!masa && !!masaAddress && !!masaNetwork, + context: QcContext, + queryKey: ['soulnames', { masaAddress, masaNetwork, persist: false }], + queryFn: async () => masa?.soulName.list(), + }); + + useAsync(async () => getSoulnames(), [getSoulnames]); + return { + soulnames, + isLoadingSoulnames, + getSoulnames, + }; +}; diff --git a/src/refactor/masa/utils.ts b/src/refactor/masa/utils.ts new file mode 100644 index 00000000..c73325e9 --- /dev/null +++ b/src/refactor/masa/utils.ts @@ -0,0 +1,15 @@ +import type { Masa } from '@masa-finance/masa-sdk'; +import { constants } from 'ethers'; + +export const isIdentityContractAvailible = (masa?: Masa) => { + if (!masa) return false; + if ( + masa?.contracts.instances.SoulboundIdentityContract.address === + constants.AddressZero || + !masa?.contracts.instances.SoulboundIdentityContract.hasAddress + ) { + return false; + } + + return true; +}; diff --git a/src/refactor/masanew.stories.tsx b/src/refactor/masanew.stories.tsx index e7e588d3..18ad8bd7 100644 --- a/src/refactor/masanew.stories.tsx +++ b/src/refactor/masanew.stories.tsx @@ -11,9 +11,10 @@ import MasaProvider, { QcContext } from './masa-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-feature/use-session'; +import { useSession } from './masa/use-session'; import { useMasaClient } from './masa-client/use-masa-client'; -import { useIdentity } from './masa-feature/use-identity'; +import { useIdentity } from './masa/use-identity'; +import { useSoulNames } from './masa/use-soulnames'; // * nextjs fix // * TODO: move this to index.ts file at some point @@ -237,12 +238,23 @@ const MasaInfo = () => { checkLogin, } = useSession(); const { isDisconnected } = useWallet(); - const { activeChain, activeNetwork, activeChainId } = useNetwork(); + const { activeNetwork, activeChainId } = useNetwork(); const { masaAddress, masaNetwork } = useMasaClient(); - const { identity, isLoadingIdentity } = useIdentity(); + const { identity, isLoadingIdentity, isIdentityAvailibleInNetwork } = + useIdentity(); + const { soulnames } = useSoulNames(); + console.log({ soulnames }); // console.log('STORY', { hasSession, session }); return ( <> + {}} + onDragStart={() => {}} + isOpen + className="rq-debug" + style={{ color: 'white' }} + />

    Masa

  • @@ -251,7 +263,6 @@ const MasaInfo = () => {
  • masaAddress: {masaAddress}
  • sessionAddress: {sessionAddress}
  • masaNetwork: {masaNetwork}
  • -
  • activeChain: {JSON.stringify(activeChain, null, 4)}
  • activeNetwork: {activeNetwork}
  • activeChainId: {activeChainId}
  • {/*

    Identity

    @@ -280,10 +291,26 @@ const MasaInfo = () => {

    Identity

    +
  • + isIdentityAvailibleInNetwork: {String(isIdentityAvailibleInNetwork)} +
  • isLoadingIdentity: {String(isLoadingIdentity)}
  • Identity: {String(JSON.stringify(identity, null, 4))}
    +

    Soulnames

    +
  • +
      + {soulnames?.map((sn) => ( +
    • + {JSON.stringify(sn, null, 4)} +
    • + ))} +
    +
  • +
+
    +

    Session

- - {}} - onDragStart={() => {}} - isOpen - className="rq-debug" - style={{ color: 'white' }} - /> +
    +

    Identity

    +
  • + +
  • +
  • + +
  • +
); }; diff --git a/src/refactor/ui/styles.scss b/src/refactor/ui/styles.scss index d64b30e6..4c61d23a 100644 --- a/src/refactor/ui/styles.scss +++ b/src/refactor/ui/styles.scss @@ -23,6 +23,7 @@ display: flex; flex-direction: column; } + * { box-sizing: border-box; margin: 0;