From 576c23f865a56b7235bbc4f73d6ee88660706408 Mon Sep 17 00:00:00 2001 From: pillowboy Date: Tue, 28 Feb 2023 15:11:13 -0500 Subject: [PATCH] chore(profile): redirect from `/a/` to `/p/` (#1796) * chore(profile): profile from account * wip * fix(profile): connected addresses * chore(profile): default /p/ route * wip:comment * wip * fix(profile): getAccountFromAddress * feat(account): check accountURNs match * chore(account): accountURN validation in account trpc * fix(profile): veiw others profile when not logged-in --- .../app/components/profile/links/links.tsx | 45 +- apps/profile/app/helpers/nfts.ts | 46 +- apps/profile/app/helpers/profile.ts | 45 +- apps/profile/app/root.tsx | 13 +- apps/profile/app/routes/$type.$address.tsx | 51 +- .../collections/$collection.tsx | 101 - .../$type.$address/collections/index.tsx | 89 - .../app/routes/$type.$address/gallery.tsx | 3 +- apps/profile/app/routes/account/dashboard.tsx | 2 +- apps/profile/app/routes/account/gallery.tsx | 266 +- apps/profile/app/routes/account/links.tsx | 7 - apps/profile/app/routes/nfts/gallery.tsx | 13 +- apps/profile/app/utils/redirects.server.ts | 18 - packages/galaxy-client/gql/account.graphql | 59 +- packages/galaxy-client/gql/address.graphql | 4 + packages/galaxy-client/index.ts | 2168 ++++++----------- .../getAuthzHeaderConditionallyFromToken.ts | 7 + .../src/jsonrpc/methods/getAddresses.ts | 7 +- .../account/src/jsonrpc/methods/getProfile.ts | 8 +- .../account/src/jsonrpc/methods/setGallery.ts | 9 +- .../account/src/jsonrpc/methods/setLinks.ts | 8 +- .../account/src/jsonrpc/methods/setProfile.ts | 26 +- .../galaxy/src/schema/resolvers/account.ts | 237 +- .../galaxy/src/schema/resolvers/address.ts | 14 + platform/galaxy/src/schema/types/account.ts | 13 +- platform/galaxy/src/schema/types/address.ts | 1 + 26 files changed, 1088 insertions(+), 2172 deletions(-) delete mode 100644 apps/profile/app/routes/$type.$address/collections/$collection.tsx delete mode 100644 apps/profile/app/routes/$type.$address/collections/index.tsx delete mode 100644 apps/profile/app/utils/redirects.server.ts diff --git a/apps/profile/app/components/profile/links/links.tsx b/apps/profile/app/components/profile/links/links.tsx index bba79375be..e535207760 100644 --- a/apps/profile/app/components/profile/links/links.tsx +++ b/apps/profile/app/components/profile/links/links.tsx @@ -39,35 +39,26 @@ export const Links = ({ links, isOwner = false, displayName }: LinksProps) => { providerIcon: imageFromAddressType(link.provider), })) .map((link, i: number) => ( - + {link.providerIcon && ( + Something went wrong... + )} + + {link.name} + + ))} ) diff --git a/apps/profile/app/helpers/nfts.ts b/apps/profile/app/helpers/nfts.ts index 7e644d080f..591015e9d0 100644 --- a/apps/profile/app/helpers/nfts.ts +++ b/apps/profile/app/helpers/nfts.ts @@ -1,12 +1,10 @@ -import { - gatewayFromIpfs, - getAuthzHeaderConditionallyFromToken, -} from '@kubelt/utils' +import { gatewayFromIpfs } from '@kubelt/utils' import { getGalaxyClient } from './clients' -import { getAccountProfile, getAddressProfile } from './profile' +import { getAccountProfile } from './profile' -import type { AddressURN } from '@kubelt/urns/address' -import type { Nft } from '@kubelt/galaxy-client' +import type { AccountURN } from '@kubelt/urns/account' +import { AccountURNSpace } from '@kubelt/urns/account' +import type { Gallery, Nft } from '@kubelt/galaxy-client' /** * Nfts are being sorted server-side * this function then allows to merge client Nfts with newly-fetched Nfts @@ -131,19 +129,13 @@ export const decorateNfts = (ownedNfts: any) => { } /** - * Returns own gallery if JWT is provided or - * target address gallery for which only + * Returns target address gallery for which only * owner property is required. - * @param owner AddressURN of target profile. Can be undefined if JWT is provided. - * @param jwt JWT of requester + * @param owner AccountURN of target profile. Can be undefined if JWT is provided. * @returns Gallery or empty array */ -export const getGallery = async (owner: string, jwt?: string) => { - // TODO: get from account - const profile = jwt - ? await getAccountProfile(jwt) - : await getAddressProfile(owner as AddressURN) - +export const getGallery = async (accountURN: AccountURN) => { + const profile = await getAccountProfile({ accountURN }) const { gallery } = profile return gallery || [] @@ -166,7 +158,7 @@ const getMoreNfts = (fetcher: any, request: string) => { } export const getMoreNftsGallery = (fetcher: any, accountURN: string) => { - const query = generateQuery([{ name: 'owner', value: accountURN }]) + const query = generateQuery([{ name: 'accountURN', value: accountURN }]) const request = `/nfts/gallery?${query}` getMoreNfts(fetcher, request) } @@ -219,13 +211,17 @@ export const getMoreNftsAllCollections = ( // ------ end of the VERY HIGHLY IMPURE FUNCTIONS TO FETCH NFTS -export const getGalleryWithMetadata = async (owner: string, jwt?: string) => { - const gallery = await getGallery(owner, jwt) +export const getGalleryWithMetadata = async (accountURN: AccountURN) => { + const gallery = await getGallery(accountURN) if (!gallery || !gallery.length) { return { gallery: [] } } + return await getGalleryMetadata(gallery) +} + +export const getGalleryMetadata = async (gallery: Gallery[]) => { const galaxyClient = await getGalaxyClient() const { getNFTMetadataBatch: metadata } = await galaxyClient.getNFTMetadata( @@ -238,10 +234,11 @@ export const getGalleryWithMetadata = async (owner: string, jwt?: string) => { }) ), }, - // Optional for when called by - // a non authenticated visitor - // of a public profile - getAuthzHeaderConditionallyFromToken(jwt) + /** + * Since gallery exists in public-only mode + * we do not need to specify JWT here + */ + {} ) const ownedNfts: decoratedNft[] | undefined = metadata?.ownedNfts.map( @@ -249,7 +246,6 @@ export const getGalleryWithMetadata = async (owner: string, jwt?: string) => { return decorateNft(nft as Nft) } ) - // Setup og tag data // check generate and return og image diff --git a/apps/profile/app/helpers/profile.ts b/apps/profile/app/helpers/profile.ts index a8dc7755a7..f5c2b39212 100644 --- a/apps/profile/app/helpers/profile.ts +++ b/apps/profile/app/helpers/profile.ts @@ -1,25 +1,32 @@ -import type { Profile, Link, Gallery, Node } from '@kubelt/galaxy-client' import { CryptoAddressType, OAuthAddressType } from '@kubelt/types/address' import type { AddressURN } from '@kubelt/urns/address' import { getAuthzHeaderConditionallyFromToken } from '@kubelt/utils' import { getGalaxyClient } from '~/helpers/clients' import { imageFromAddressType } from './icons' - -export const getAccountProfile = async (jwt: string) => { +import type { FullProfile } from '~/types' +import type { AccountURN } from '@kubelt/urns/account' + +export const getAccountProfile = async ({ + jwt, + accountURN, +}: { + jwt?: string + accountURN?: AccountURN +}) => { const galaxyClient = await getGalaxyClient() const profileRes = await galaxyClient.getProfile( - undefined, + accountURN ? { targetAccountURN: accountURN } : undefined, getAuthzHeaderConditionallyFromToken(jwt) ) const { profile, links, gallery, connectedAddresses } = profileRes - return { profile, links, gallery, connectedAddresses } as { - profile: Profile - links: Link[] - gallery: Gallery[] - connectedAddresses: Node[] - } + return { + ...profile, + links, + gallery, + addresses: connectedAddresses, + } as FullProfile } export const getAuthorizedApps = async (jwt: string) => { @@ -40,26 +47,10 @@ export const getAccountAddresses = async (jwt: string) => { getAuthzHeaderConditionallyFromToken(jwt) ) - const addresses = addressesRes.connectedAddresses + const addresses = addressesRes.addresses return addresses } -export const getAddressProfile = async (addressURN: AddressURN) => { - const galaxyClient = await getGalaxyClient() - const addressProfile = await galaxyClient.getProfileFromAddress({ - addressURN, - }) - - const profile = addressProfile - - return { - ...profile.profile, - links: profile.links, - gallery: profile.gallery, - connectedAccounts: profile.connectedAddresses, - } -} - export const getAddressProfiles = async ( jwt: string, addressURNList: AddressURN[] diff --git a/apps/profile/app/root.tsx b/apps/profile/app/root.tsx index b00a7de8c3..a2a5a34fad 100644 --- a/apps/profile/app/root.tsx +++ b/apps/profile/app/root.tsx @@ -39,7 +39,7 @@ import HeadNav, { links as headNavLink } from '~/components/head-nav' import * as gtag from '~/utils/gtags.client' import { getProfileSession } from './utils/session.server' -import { getRedirectUrlForProfile } from './utils/redirects.server' +import { AccountURNSpace } from '@kubelt/urns/account' import { parseJwt } from './utils/session.server' import { getAccountProfile } from './helpers/profile' import type { AccountURN } from '@kubelt/urns/account' @@ -91,19 +91,14 @@ export const loader: LoaderFunction = async ({ request }) => { accountURN = parseJwt(jwt).sub as AccountURN - const fetchedLoggedInProfile = await getAccountProfile(jwt) + const fetchedLoggedInProfile = await getAccountProfile({ jwt }) if (!fetchedLoggedInProfile) throw new Error('Could not retrieve logged in use profile.') - loggedInUserProfile = { - ...fetchedLoggedInProfile.profile, - links: fetchedLoggedInProfile.links, - gallery: fetchedLoggedInProfile.gallery, - addresses: fetchedLoggedInProfile.connectedAddresses, - } + loggedInUserProfile = fetchedLoggedInProfile - basePath = getRedirectUrlForProfile(loggedInUserProfile) + basePath = `/p/${AccountURNSpace.decode(accountURN)}` } return json({ diff --git a/apps/profile/app/routes/$type.$address.tsx b/apps/profile/app/routes/$type.$address.tsx index 176d6e75bf..89526bb495 100644 --- a/apps/profile/app/routes/$type.$address.tsx +++ b/apps/profile/app/routes/$type.$address.tsx @@ -19,7 +19,7 @@ import { HiOutlineQuestionMarkCircle, } from 'react-icons/hi' -import { getProfileSession } from '~/utils/session.server' +import { getProfileSession, parseJwt } from '~/utils/session.server' import { getGalaxyClient } from '~/helpers/clients' import { ogImageFromProfile } from '~/helpers/ogImage' @@ -29,7 +29,6 @@ import { gatewayFromIpfs, getAuthzHeaderConditionallyFromToken, } from '@kubelt/utils' -import type { AddressURN } from '@kubelt/urns/address' import { AddressURNSpace } from '@kubelt/urns/address' import { Cover } from '~/components/profile/cover/Cover' @@ -37,7 +36,6 @@ import ProfileTabs from '~/components/profile/tabs/tabs' import ProfileLayout from '~/components/profile/layout' import defaultOG from '~/assets/Rollup_profiles_OG.png' -import { getRedirectUrlForProfile } from '~/utils/redirects.server' import { CryptoAddressType, NodeType, @@ -57,27 +55,26 @@ export const loader: LoaderFunction = async ({ request, params }) => { const session = await getProfileSession(request) if (!address) throw new Error('No address provided in URL') - // redirect from accountURN to first addressURNs - if (type === 'p') { - const { addresses } = await galaxyClient.getConnectedAddressesFromAccount({ - accountURN: AccountURNSpace.urn(address), - }) + // redirect from any addressURN to its addressURNs + if (type === 'a') { + const { account }: { account: AccountURN } = + await galaxyClient.getAccountUrnFromAddress({ + addressURN: AddressURNSpace.urn(address), + }) - return redirect( - `/a/${AddressURNSpace.decode(addresses?.[0].baseUrn as AddressURN)}` - ) + return redirect(`/p/${AccountURNSpace.decode(account)}`) } - const urn = AddressURNSpace.urn(address) + const accountURN = AccountURNSpace.urn(address) as AccountURN // if not handle is this let's assume this is an idref let profile, jwt try { const user = session.get('user') jwt = user?.accessToken - profile = await galaxyClient.getProfileFromAddress( + profile = await galaxyClient.getProfile( { - addressURN: urn, + targetAccountURN: accountURN, }, getAuthzHeaderConditionallyFromToken(jwt) ) @@ -93,14 +90,7 @@ export const loader: LoaderFunction = async ({ request, params }) => { addresses: profile.connectedAddresses || [], } - if (type === 'a') { - const redirectUrl = getRedirectUrlForProfile(profile) - const originalRoute = `/${type}/${address}` - //Redirect if we've found a better route - if (redirectUrl && originalRoute !== redirectUrl) - return redirect(redirectUrl) - //otherwise stay on current route - } else if (type === 'u') { + if (type === 'u') { //TODO: galaxy search by handle console.error('Not implemented') } else { @@ -115,7 +105,8 @@ export const loader: LoaderFunction = async ({ request, params }) => { const splittedUrl = request.url.split('/') const path = splittedUrl[splittedUrl.length - 1] - const matches = profile.addresses?.filter((addr) => urn === addr.baseUrn) + // Check if the accountURN in jwt matches with accountURN in URL + const isOwner = jwt ? parseJwt(jwt).sub === accountURN : false const cryptoAddresses = profile.addresses?.filter( (addr) => addr.rc.node_type === NodeType.Crypto @@ -125,14 +116,14 @@ export const loader: LoaderFunction = async ({ request, params }) => { uname: profile.handle || address, ogImage: ogImage || defaultOG, profile, - addressURN: urn, + accountURN, cryptoAddresses, path, - isOwner: jwt && matches && matches.length > 0 ? true : false, + isOwner, }) } catch (e) { console.log( - `Galaxy did not return a profile for address ${urn}. Moving on.` + `Galaxy did not return a profile for address ${accountURN}. Moving on.` ) throw new Response('No address found', { status: 404 }) } @@ -173,13 +164,13 @@ export const meta: MetaFunction = ({ const UserAddressLayout = () => { //TODO: this needs to be optimized so profile isn't fetched from the loader //but used from context alone. - const { profile, cryptoAddresses, path, isOwner, addressURN } = + const { profile, cryptoAddresses, path, isOwner, accountURN } = useLoaderData<{ profile: FullProfile cryptoAddresses: Node[] path: string isOwner: boolean - addressURN: string + accountURN: string }>() const ctx = useOutletContext<{ @@ -188,7 +179,6 @@ const UserAddressLayout = () => { // from root.tsx // but if not logged in // is null... - accountURN: AccountURN }>() const finalProfile = profile ?? ctx.profile @@ -305,10 +295,9 @@ const UserAddressLayout = () => { > diff --git a/apps/profile/app/routes/$type.$address/collections/$collection.tsx b/apps/profile/app/routes/$type.$address/collections/$collection.tsx deleted file mode 100644 index 7ab11be09f..0000000000 --- a/apps/profile/app/routes/$type.$address/collections/$collection.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import type { LoaderFunction } from '@remix-run/cloudflare' -import { json } from '@remix-run/cloudflare' -import { - useLoaderData, - useNavigate, - useOutletContext, - useFetcher, -} from '@remix-run/react' -import { useState, useEffect, useMemo } from 'react' - -import type { Profile } from '@kubelt/galaxy-client' - -import UnfilteredNftGrid from '~/components/nfts/grid/unfiltered' -import { getMoreNftsSingleCollection } from '~/helpers/nfts' - -export const loader: LoaderFunction = async (args) => { - const { params } = args - - return json({ - collection: params.collection, - }) -} - -const CollectionForProfileRoute = () => { - const { collection } = useLoaderData() - const { profile, isOwner, accountURN } = useOutletContext<{ - profile: Profile - isOwner: boolean - accountURN: string - }>() - - const { displayName } = profile - - /** STATE */ - const [refresh, setRefresh] = useState(true) - const [loadedNfts, setLoadedNfts] = useState([] as any[]) - const [pageKey, setPageLink] = useState() - const [loading, setLoading] = useState(true) - - const fetcher = useFetcher() - const navigate = useNavigate() - - /** HOOKS */ - useEffect(() => { - if (fetcher.data) { - // Do not need to sort them alphabetically here - setLoadedNfts([...loadedNfts, ...fetcher.data.ownedNfts]) - setPageLink(fetcher.data.pageKey ?? null) - - if (refresh) { - setRefresh(false) - } - } - }, [fetcher.data]) - - useEffect(() => { - if (pageKey) { - setLoading(true) - getMoreNftsSingleCollection(fetcher, accountURN, collection, pageKey) - } else if (pageKey === null) { - setLoading(false) - } - }, [pageKey]) - - useEffect(() => { - const asyncFn = async () => { - getMoreNftsSingleCollection(fetcher, accountURN, collection, pageKey) - } - - if (refresh) { - asyncFn() - } - }, [refresh]) - - useMemo(() => { - setRefresh(true) - setLoadedNfts([]) - setPageLink(undefined) - }, []) - - return ( - { - navigate(`/u/${cryptoAddresses[0].nss.split('/')[1]}/collections`, { - replace: true, - }) - }} - loadingConditions={loading || refresh} - isModalNft={true} - isOwner={isOwner} - displayText={`Looks like ${displayName} doesn't own any NFTs`} - detailsModal - filters={false} - collection={collection} - /> - ) -} - -export default CollectionForProfileRoute diff --git a/apps/profile/app/routes/$type.$address/collections/index.tsx b/apps/profile/app/routes/$type.$address/collections/index.tsx deleted file mode 100644 index 59e9afb6c7..0000000000 --- a/apps/profile/app/routes/$type.$address/collections/index.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import FilteredNftGrid from '~/components/nfts/grid/filtered' -import { mergeSortedNfts } from '~/helpers/nfts' -import { useState, useEffect, useMemo } from 'react' - -import type { Profile } from '@kubelt/galaxy-client' -import { useFetcher, useOutletContext, useNavigate } from '@remix-run/react' -import { getMoreNftsAllCollections } from '~/helpers/nfts' - -const ProfileRoute = () => { - const { profile, isOwner, accountURN } = useOutletContext<{ - profile: Profile - isOwner: boolean - accountURN: string - }>() - - // TODO: change the ProfileNFTGallery to take multiple addresses - - const { displayName, pfp } = profile - - const [refresh, setRefresh] = useState(true) - const [loadedNfts, setLoadedNfts] = useState([] as any[]) - const [pageKey, setPageLink] = useState() - const [loading, setLoading] = useState(true) - - const fetcher = useFetcher() - const navigate = useNavigate() - - const handleRedirect = (collection: string) => { - return navigate(`./${collection}`) - } - - /** HOOKS */ - useEffect(() => { - if (fetcher.data) { - /* We already have only 1 NFT per collection - ** No need to put it in additional set - */ - - setLoadedNfts(mergeSortedNfts(loadedNfts, fetcher.data.ownedNfts)) - setPageLink(fetcher.data.pageKey ?? null) - - if (refresh) { - setRefresh(false) - } - } - }, [fetcher.data]) - - useEffect(() => { - if (pageKey) { - setLoading(true) - getMoreNftsAllCollections(fetcher, accountURN, pageKey) - } else if (pageKey === null) { - setLoading(false) - } - }, [pageKey]) - - useMemo(() => { - setRefresh(true) - setLoadedNfts([]) - setPageLink(undefined) - }, []) - - useEffect(() => { - const asyncFn = async () => { - getMoreNftsAllCollections(fetcher, accountURN, pageKey) - } - if (refresh) { - asyncFn() - } - }, [refresh]) - - return ( - { - handleRedirect(nft.contract.address) - }} - isModal={false} - loadingConditions={loading || refresh} - nfts={loadedNfts} - pfp={(pfp as any).image as string} - isOwner={isOwner} - filters={true} - displayText={`Looks like ${displayName} doesn't own any NFTs`} - detailsModal - /> - ) -} - -export default ProfileRoute diff --git a/apps/profile/app/routes/$type.$address/gallery.tsx b/apps/profile/app/routes/$type.$address/gallery.tsx index 17ea0deab3..e0d5c38a29 100644 --- a/apps/profile/app/routes/$type.$address/gallery.tsx +++ b/apps/profile/app/routes/$type.$address/gallery.tsx @@ -6,12 +6,13 @@ import type { Profile } from '@kubelt/galaxy-client' import { getMoreNftsGallery } from '~/helpers/nfts' import { useFetcher, useOutletContext } from '@remix-run/react' +import type { AccountURN } from '@kubelt/urns/account' const ProfileRoute = () => { const { profile, isOwner, accountURN } = useOutletContext<{ profile: Profile isOwner: boolean - accountURN: string + accountURN: AccountURN }>() const { displayName, pfp } = profile diff --git a/apps/profile/app/routes/account/dashboard.tsx b/apps/profile/app/routes/account/dashboard.tsx index 9825d8a654..6f39ef527a 100644 --- a/apps/profile/app/routes/account/dashboard.tsx +++ b/apps/profile/app/routes/account/dashboard.tsx @@ -11,7 +11,7 @@ import dashboardChart from '~/assets/dashboard_chart.svg' import { normalizeProfileToLinks } from '~/helpers' import { NestedErrorPage } from '@kubelt/design-system/src/pages/nested-error/NestedErrorPage' import { Spinner } from '@kubelt/design-system/src/atoms/spinner/Spinner' -import { FullProfile } from '~/types' +import type { FullProfile } from '~/types' import CTA from '~/components/cta/cta' diff --git a/apps/profile/app/routes/account/gallery.tsx b/apps/profile/app/routes/account/gallery.tsx index c040c46ab5..6353e92792 100644 --- a/apps/profile/app/routes/account/gallery.tsx +++ b/apps/profile/app/routes/account/gallery.tsx @@ -44,7 +44,7 @@ import NoCryptoAddresses from '~/components/accounts/NoCryptoAddresses' // Other helpers import { getProfileSession } from '~/utils/session.server' import { getGalaxyClient } from '~/helpers/clients' -import type { Nft, Profile } from '@kubelt/galaxy-client' +import type { Profile, Node } from '@kubelt/galaxy-client' import { getMoreNftsModal } from '~/helpers/nfts' import type { decoratedNft } from '~/helpers/nfts' import { getAuthzHeaderConditionallyFromToken } from '@kubelt/utils' @@ -113,7 +113,7 @@ export const action: ActionFunction = async ({ request }) => { * you may take a quick look here: * https://codesandbox.io/s/dndkit-sortable-image-grid-py6ve?file=/src/App.jsx*/ -const Nft = forwardRef( +const NFT = forwardRef( ({ nft, url, index, faded, isDragging, style, ...props }: any, ref) => { /** * It re-renders this small component quite often @@ -167,7 +167,7 @@ const SortableNft = (props: any) => { } return ( - { const { profile, cryptoAddresses, accountURN } = useOutletContext<{ profile: Profile accountURN: string - cryptoAddresses: string[] + cryptoAddresses: Node[] }>() const { displayName } = profile @@ -194,7 +194,7 @@ const Gallery = () => { const [initialState, setInitialState] = useState([]) - const [curatedNfts, setCuratedNfts] = useState([] as Nft[]) + const [curatedNfts, setCuratedNfts] = useState([] as decoratedNft[]) const [curatedNftsSet, setCuratedNftsSet] = useState(new Set([] as string[])) const [isFormChanged, setFormChanged] = useState(false) @@ -208,12 +208,11 @@ const Gallery = () => { const curatedNftsLinks = curatedNfts.map((nft) => nft.url) // REACT HOOKS FOR DISPLAYING AND SORTING GALLERY - useEffect(() => { if (JSON.stringify(curatedNfts) !== JSON.stringify(initialState)) { setFormChanged(true) } - }, [curatedNfts]) + }, [curatedNfts, initialState]) useEffect(() => { if (transition.type === 'actionReload') { @@ -225,7 +224,7 @@ const Gallery = () => { useEffect(() => { ;(async () => { const addressQueryParams = new URLSearchParams({ - owner: accountURN, + accountURN: accountURN, }) const request = `/nfts/gallery?${addressQueryParams.toString()}` @@ -355,146 +354,151 @@ const Gallery = () => { setFormChanged(false) }} > - { - setIsOpen(false) - }} - handleSelectedNft={(nft: any) => { - const ID = nft.contract.address + nft.tokenId - if (!curatedNftsSet.has(ID)) { - setCuratedNftsSet(new Set([...curatedNftsSet, ID])) - setCuratedNfts([...curatedNfts, nft]) - setIsOpen(false) - } else { - toast('This NFT is already in your list', { - icon: '🤔', - }) +
+ - - - -
{ + setIsOpen(false) + }} + handleSelectedNft={(nft: any) => { + const ID = nft.contract.address + nft.tokenId + if (!curatedNftsSet.has(ID)) { + setCuratedNftsSet(new Set([...curatedNftsSet, ID])) + setCuratedNfts([...curatedNfts, nft]) + setIsOpen(false) + } else { + toast('This NFT is already in your gallery', { + icon: '🤔', + }) + } + }} + /> + + + - {galleryFetcher.state === 'loading' && !curatedNfts.length && ( - - )} - {curatedNfts.map((nft: any, i: number) => { - return ( -
- - -
- ) - })} - +
+ ) + })} + - -
- - {activeId ? ( - - ) : null} - -
- - - - {/* Form where this button is used should have + > + + Add NFT + + + + + + {activeId ? ( + + ) : null} + + + + + + {/* Form where this button is used should have an absolute relative position div below has relative - this way this button sticks to bottom right - This div with h-[4rem] prevents everything from overlapping with div with absolute position below */} -
-
- { - setCuratedNfts(initialState) - setCuratedNftsSet( - new Set( - initialState.map( - (nft: any) => nft.contract.address + nft.tokenId +
+
+ { + setCuratedNfts(initialState) + setCuratedNftsSet( + new Set( + initialState.map( + (nft: any) => nft.contract.address + nft.tokenId + ) ) ) - ) - }} - /> -
+ }} + /> +
+
) : ( void }>() - console.log({ - notificationHandler, - profile, - // cryptoAddresses, - // accountURN, - }) - const transition = useTransition() const actionData = useActionData() const fetcher = useFetcher() diff --git a/apps/profile/app/routes/nfts/gallery.tsx b/apps/profile/app/routes/nfts/gallery.tsx index 9e0bb207dc..f24477f471 100644 --- a/apps/profile/app/routes/nfts/gallery.tsx +++ b/apps/profile/app/routes/nfts/gallery.tsx @@ -1,23 +1,20 @@ +import type { AccountURN } from '@kubelt/urns/account' import type { LoaderFunction } from '@remix-run/cloudflare' import { json } from '@remix-run/cloudflare' import { getGalleryWithMetadata } from '~/helpers/nfts' -import { getProfileSession } from '~/utils/session.server' export const loader: LoaderFunction = async (args) => { const srcUrl = new URL(args.request.url) - const session = await getProfileSession(args.request) - const user = session.get('user') - - const jwt = user?.accessToken - /** * params.profile is called from `$profile/gallery` route * searchParams - from `account/gallery?owner=0x123..` */ - const owner = srcUrl.searchParams.get('owner') || args.params.profile - const { gallery } = await getGalleryWithMetadata(owner as string, jwt) + + const accountURN = srcUrl.searchParams.get('accountURN') + + const { gallery } = await getGalleryWithMetadata(accountURN as AccountURN) return json({ gallery, diff --git a/apps/profile/app/utils/redirects.server.ts b/apps/profile/app/utils/redirects.server.ts deleted file mode 100644 index df7ba8ce11..0000000000 --- a/apps/profile/app/utils/redirects.server.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { AddressURN } from '@kubelt/urns/address' -import { AddressURNSpace } from '@kubelt/urns/address' -import type { FullProfile } from '~/types' - -export const getRedirectUrlForProfile = ( - profile: FullProfile -): string | undefined => { - if (profile.handle) { - //TODO: when handle strategy is implemented, this should redirect to - //the URL: /u/${handle} which would do a galaxy lookup by that handle - //and load the profile corresponding to it - console.warn('Handle logic not implemented') - } - - const addressUrn = profile.addresses[0].baseUrn as AddressURN - const idref = AddressURNSpace.decode(addressUrn) - return `/a/${idref}` -} diff --git a/packages/galaxy-client/gql/account.graphql b/packages/galaxy-client/gql/account.graphql index 7f46f26861..2ebef5c475 100644 --- a/packages/galaxy-client/gql/account.graphql +++ b/packages/galaxy-client/gql/account.graphql @@ -1,5 +1,5 @@ -query getProfile { - profile { +query getProfile($targetAccountURN: URN) { + profile(targetAccountURN: $targetAccountURN) { pfp { ... on StandardPFP { image @@ -17,63 +17,26 @@ query getProfile { bio website } - links { + links(targetAccountURN: $targetAccountURN) { name url verified provider } - connectedAddresses { + connectedAddresses(targetAccountURN: $targetAccountURN) { baseUrn qc rc } - gallery { + gallery(targetAccountURN: $targetAccountURN) { contract tokenId chain } } -query getProfileFromAddress($addressURN: URN!) { - profile: profileFromAddress(addressURN: $addressURN) { - pfp { - ... on StandardPFP { - image - } - ... on NFTPFP { - image - isToken - } - } - displayName - handle - cover - location - job - bio - website - } - links: linksFromAddress(addressURN: $addressURN) { - name - url - verified - provider - } - gallery: galleryFromAddress(addressURN: $addressURN) { - contract - tokenId - chain - } - connectedAddresses: connectedAddressesFromAddress(addressURN: $addressURN) { - baseUrn - qc - rc - } -} - -query getConnectedAddressesFromAccount($accountURN: URN!) { - addresses: connectedAddressesFromAccount(accountURN: $accountURN) { +query getConnectedAddresses($targetAccountURN: URN) { + addresses: connectedAddresses(targetAccountURN: $targetAccountURN) { baseUrn qc rc @@ -89,14 +52,6 @@ query getAuthorizedApps { } } -query getConnectedAddresses { - connectedAddresses { - baseUrn - qc - rc - } -} - mutation updateProfile($profile: ProfileInput) { updateProfile(profile: $profile) } diff --git a/packages/galaxy-client/gql/address.graphql b/packages/galaxy-client/gql/address.graphql index 7105ee7f9e..4e30352591 100644 --- a/packages/galaxy-client/gql/address.graphql +++ b/packages/galaxy-client/gql/address.graphql @@ -114,6 +114,10 @@ query getAddressProfiles($addressURNList: [URN!]) { } } +query getAccountUrnFromAddress($addressURN: URN!) { + account(addressURN: $addressURN) +} + mutation updateAddressNickname($addressURN: URN!, $nickname: String!) { updateAddressNickname(addressURN: $addressURN, nickname: $nickname) } diff --git a/packages/galaxy-client/index.ts b/packages/galaxy-client/index.ts index 3070cc6daf..0805dc517d 100644 --- a/packages/galaxy-client/index.ts +++ b/packages/galaxy-client/index.ts @@ -1,1347 +1,894 @@ -import { GraphQLClient } from 'graphql-request' -import * as Dom from 'graphql-request/dist/types.dom' -import gql from 'graphql-tag' -export type Maybe = T | null -export type InputMaybe = Maybe -export type Exact = { - [K in keyof T]: T[K] -} -export type MakeOptional = Omit & { - [SubKey in K]?: Maybe -} -export type MakeMaybe = Omit & { - [SubKey in K]: Maybe -} +import { GraphQLClient } from 'graphql-request'; +import * as Dom from 'graphql-request/dist/types.dom'; +import gql from 'graphql-tag'; +export type Maybe = T | null; +export type InputMaybe = Maybe; +export type Exact = { [K in keyof T]: T[K] }; +export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; +export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { - ID: string - String: string - Boolean: boolean - Int: number - Float: number - JSON: any - URN: any -} + ID: string; + String: string; + Boolean: boolean; + Int: number; + Float: number; + JSON: any; + URN: any; +}; export type AddressProfile = { - __typename?: 'AddressProfile' - profile: AddressProfilesUnion - type: Scalars['String'] - urn: Scalars['URN'] -} + __typename?: 'AddressProfile'; + profile: AddressProfilesUnion; + type: Scalars['String']; + urn: Scalars['URN']; +}; -export type AddressProfilesUnion = - | CryptoAddressProfile - | OAuthAppleProfile - | OAuthDiscordProfile - | OAuthGithubProfile - | OAuthGoogleProfile - | OAuthMicrosoftProfile - | OAuthTwitterProfile +export type AddressProfilesUnion = CryptoAddressProfile | OAuthAppleProfile | OAuthDiscordProfile | OAuthGithubProfile | OAuthGoogleProfile | OAuthMicrosoftProfile | OAuthTwitterProfile; export type App = { - __typename?: 'App' - clientId: Scalars['String'] - icon: Scalars['String'] - timestamp: Scalars['Float'] - title: Scalars['String'] -} + __typename?: 'App'; + clientId: Scalars['String']; + icon: Scalars['String']; + timestamp: Scalars['Float']; + title: Scalars['String']; +}; export type Chain = { - __typename?: 'Chain' - chain?: Maybe - network?: Maybe -} + __typename?: 'Chain'; + chain?: Maybe; + network?: Maybe; +}; export type ConnectedAddressPropertiesUpdateInput = { - addressURN: Scalars['URN'] - public?: InputMaybe -} + addressURN: Scalars['URN']; + public?: InputMaybe; +}; export type Contract = { - __typename?: 'Contract' - address?: Maybe -} + __typename?: 'Contract'; + address?: Maybe; +}; export type ContractInput = { - address?: InputMaybe -} + address?: InputMaybe; +}; export type ContractMetadata = { - __typename?: 'ContractMetadata' - name?: Maybe - openSea: OpenSeaMetadata - symbol?: Maybe - tokenType?: Maybe - totalSupply?: Maybe -} + __typename?: 'ContractMetadata'; + name?: Maybe; + openSea: OpenSeaMetadata; + symbol?: Maybe; + tokenType?: Maybe; + totalSupply?: Maybe; +}; export type CryptoAddressProfile = { - __typename?: 'CryptoAddressProfile' - address: Scalars['String'] - avatar?: Maybe - displayName?: Maybe -} + __typename?: 'CryptoAddressProfile'; + address: Scalars['String']; + avatar?: Maybe; + displayName?: Maybe; +}; export type Edge = { - __typename?: 'Edge' - dst: Node - src: Node - tag: Scalars['String'] -} + __typename?: 'Edge'; + dst: Node; + src: Node; + tag: Scalars['String']; +}; export type Gallery = { - __typename?: 'Gallery' - chain: Scalars['String'] - contract: Scalars['String'] - tokenId: Scalars['String'] -} + __typename?: 'Gallery'; + chain: Scalars['String']; + contract: Scalars['String']; + tokenId: Scalars['String']; +}; export type GalleryInput = { - chain: Scalars['String'] - contract: Scalars['String'] - tokenId: Scalars['String'] -} + chain: Scalars['String']; + contract: Scalars['String']; + tokenId: Scalars['String']; +}; export type Id = { - __typename?: 'Id' - tokenId?: Maybe -} + __typename?: 'Id'; + tokenId?: Maybe; +}; export type Link = { - __typename?: 'Link' - name?: Maybe - provider?: Maybe - url?: Maybe - verified?: Maybe -} + __typename?: 'Link'; + name?: Maybe; + provider?: Maybe; + url?: Maybe; + verified?: Maybe; +}; export type LinkInput = { - name?: InputMaybe - provider?: InputMaybe - url?: InputMaybe - verified?: InputMaybe -} + name?: InputMaybe; + provider?: InputMaybe; + url?: InputMaybe; + verified?: InputMaybe; +}; export type Mutation = { - __typename?: 'Mutation' - disconnectAddress?: Maybe - updateAddressNickname?: Maybe - updateConnectedAddressesProperties?: Maybe - updateGallery?: Maybe - updateLinks?: Maybe - updateProfile?: Maybe -} + __typename?: 'Mutation'; + disconnectAddress?: Maybe; + updateAddressNickname?: Maybe; + updateConnectedAddressesProperties?: Maybe; + updateGallery?: Maybe; + updateLinks?: Maybe; + updateProfile?: Maybe; +}; + export type MutationDisconnectAddressArgs = { - addressURN: Scalars['URN'] -} + addressURN: Scalars['URN']; +}; + export type MutationUpdateAddressNicknameArgs = { - addressURN: Scalars['URN'] - nickname: Scalars['String'] -} + addressURN: Scalars['URN']; + nickname: Scalars['String']; +}; + export type MutationUpdateConnectedAddressesPropertiesArgs = { - addressURNList: Array -} + addressURNList: Array; +}; + export type MutationUpdateGalleryArgs = { - gallery?: InputMaybe> -} + gallery?: InputMaybe>; +}; + export type MutationUpdateLinksArgs = { - links?: InputMaybe> -} + links?: InputMaybe>; +}; + export type MutationUpdateProfileArgs = { - profile?: InputMaybe -} + profile?: InputMaybe; +}; export type Nft = { - __typename?: 'NFT' - balance?: Maybe - chain?: Maybe - contract?: Maybe - contractMetadata?: Maybe - description?: Maybe - error?: Maybe - id?: Maybe - media: Array - metadata?: Maybe - title?: Maybe - tokenUri?: Maybe -} + __typename?: 'NFT'; + balance?: Maybe; + chain?: Maybe; + contract?: Maybe; + contractMetadata?: Maybe; + description?: Maybe; + error?: Maybe; + id?: Maybe; + media: Array; + metadata?: Maybe; + title?: Maybe; + tokenUri?: Maybe; +}; export type NftContract = { - __typename?: 'NFTContract' - address?: Maybe - chain?: Maybe - contractDeployer?: Maybe - deployedBlockNumber?: Maybe - isSpam?: Maybe - media?: Maybe - name?: Maybe - numDistinctTokensOwned?: Maybe - opensea?: Maybe - ownedNfts?: Maybe> - symbol?: Maybe - title?: Maybe - tokenId?: Maybe - tokenType?: Maybe - totalBalance?: Maybe -} + __typename?: 'NFTContract'; + address?: Maybe; + chain?: Maybe; + contractDeployer?: Maybe; + deployedBlockNumber?: Maybe; + isSpam?: Maybe; + media?: Maybe; + name?: Maybe; + numDistinctTokensOwned?: Maybe; + opensea?: Maybe; + ownedNfts?: Maybe>; + symbol?: Maybe; + title?: Maybe; + tokenId?: Maybe; + tokenType?: Maybe; + totalBalance?: Maybe; +}; export type NftContracts = { - __typename?: 'NFTContracts' - contracts: Array - totalCount?: Maybe -} + __typename?: 'NFTContracts'; + contracts: Array; + totalCount?: Maybe; +}; export type NftInput = { - addressURN?: InputMaybe - contract?: InputMaybe - tokenId?: InputMaybe -} + addressURN?: InputMaybe; + contract?: InputMaybe; + tokenId?: InputMaybe; +}; export type NftMedia = { - __typename?: 'NFTMedia' - bytes?: Maybe - format?: Maybe - gateway?: Maybe - raw?: Maybe - thumbnail?: Maybe -} + __typename?: 'NFTMedia'; + bytes?: Maybe; + format?: Maybe; + gateway?: Maybe; + raw?: Maybe; + thumbnail?: Maybe; +}; export type NftMetadata = { - __typename?: 'NFTMetadata' - background_color?: Maybe - description?: Maybe - external_url?: Maybe - image?: Maybe - media: Array - name?: Maybe - properties?: Maybe>> - timeLastUpdated?: Maybe -} + __typename?: 'NFTMetadata'; + background_color?: Maybe; + description?: Maybe; + external_url?: Maybe; + image?: Maybe; + media: Array; + name?: Maybe; + properties?: Maybe>>; + timeLastUpdated?: Maybe; +}; export type NftMetadataInput = { - chain?: InputMaybe - contractAddress?: InputMaybe - tokenId?: InputMaybe -} + chain?: InputMaybe; + contractAddress?: InputMaybe; + tokenId?: InputMaybe; +}; export type NftNoProps = { - __typename?: 'NFTNoProps' - contract?: Maybe - contractMetadata?: Maybe - description?: Maybe - error?: Maybe - id?: Maybe - media: Array - title?: Maybe - tokenUri?: Maybe -} + __typename?: 'NFTNoProps'; + contract?: Maybe; + contractMetadata?: Maybe; + description?: Maybe; + error?: Maybe; + id?: Maybe; + media: Array; + title?: Maybe; + tokenUri?: Maybe; +}; export type Nftpfp = Pfp & { - __typename?: 'NFTPFP' - image?: Maybe - isToken?: Maybe -} + __typename?: 'NFTPFP'; + image?: Maybe; + isToken?: Maybe; +}; export type NftProperty = { - __typename?: 'NFTProperty' - display?: Maybe - name?: Maybe - value?: Maybe -} + __typename?: 'NFTProperty'; + display?: Maybe; + name?: Maybe; + value?: Maybe; +}; export type NfTs = { - __typename?: 'NFTs' - ownedNfts: Array -} + __typename?: 'NFTs'; + ownedNfts: Array; +}; export type NfTsNoProps = { - __typename?: 'NFTsNoProps' - ownedNfts: Array -} + __typename?: 'NFTsNoProps'; + ownedNfts: Array; +}; export type NfTsWithChain = { - __typename?: 'NFTsWithChain' - ownedNfts: Array -} + __typename?: 'NFTsWithChain'; + ownedNfts: Array; +}; export type Node = { - __typename?: 'Node' - baseUrn: Scalars['String'] - qc?: Maybe - rc?: Maybe -} + __typename?: 'Node'; + baseUrn: Scalars['String']; + qc?: Maybe; + rc?: Maybe; +}; export type NodeInput = { - baseUrn: Scalars['String'] - qc?: InputMaybe - rc?: InputMaybe -} + baseUrn: Scalars['String']; + qc?: InputMaybe; + rc?: InputMaybe; +}; export type OAuthAppleProfile = { - __typename?: 'OAuthAppleProfile' - email?: Maybe - name?: Maybe - picture: Scalars['String'] - sub?: Maybe -} + __typename?: 'OAuthAppleProfile'; + email?: Maybe; + name?: Maybe; + picture: Scalars['String']; + sub?: Maybe; +}; export type OAuthDiscordProfile = { - __typename?: 'OAuthDiscordProfile' - avatar?: Maybe - discriminator?: Maybe - email?: Maybe - id?: Maybe - username?: Maybe -} + __typename?: 'OAuthDiscordProfile'; + avatar?: Maybe; + discriminator?: Maybe; + email?: Maybe; + id?: Maybe; + username?: Maybe; +}; export type OAuthGithubProfile = { - __typename?: 'OAuthGithubProfile' - avatar_url: Scalars['String'] - bio?: Maybe - email?: Maybe - followers?: Maybe - following?: Maybe - html_url?: Maybe - id?: Maybe - location?: Maybe - login: Scalars['String'] - name?: Maybe - public_gists?: Maybe - public_repos?: Maybe -} + __typename?: 'OAuthGithubProfile'; + avatar_url: Scalars['String']; + bio?: Maybe; + email?: Maybe; + followers?: Maybe; + following?: Maybe; + html_url?: Maybe; + id?: Maybe; + location?: Maybe; + login: Scalars['String']; + name?: Maybe; + public_gists?: Maybe; + public_repos?: Maybe; +}; export type OAuthGoogleProfile = { - __typename?: 'OAuthGoogleProfile' - email?: Maybe - email_verified?: Maybe - family_name?: Maybe - given_name?: Maybe - locale?: Maybe - name?: Maybe - picture: Scalars['String'] - sub?: Maybe -} + __typename?: 'OAuthGoogleProfile'; + email?: Maybe; + email_verified?: Maybe; + family_name?: Maybe; + given_name?: Maybe; + locale?: Maybe; + name?: Maybe; + picture: Scalars['String']; + sub?: Maybe; +}; export type OAuthMicrosoftProfile = { - __typename?: 'OAuthMicrosoftProfile' - email?: Maybe - family_name?: Maybe - given_name?: Maybe - name?: Maybe - picture: Scalars['String'] - sub?: Maybe -} + __typename?: 'OAuthMicrosoftProfile'; + email?: Maybe; + family_name?: Maybe; + given_name?: Maybe; + name?: Maybe; + picture: Scalars['String']; + sub?: Maybe; +}; export type OAuthTwitterProfile = { - __typename?: 'OAuthTwitterProfile' - id?: Maybe - name?: Maybe - profile_image_url_https: Scalars['String'] - screen_name: Scalars['String'] -} + __typename?: 'OAuthTwitterProfile'; + id?: Maybe; + name?: Maybe; + profile_image_url_https: Scalars['String']; + screen_name: Scalars['String']; +}; export type OpenSeaMetadata = { - __typename?: 'OpenSeaMetadata' - collectionName?: Maybe - description?: Maybe - discordUrl?: Maybe - externalUrl?: Maybe - floorPrice?: Maybe - imageUrl?: Maybe - safeListRequestStatus?: Maybe - twitterUsername?: Maybe -} + __typename?: 'OpenSeaMetadata'; + collectionName?: Maybe; + description?: Maybe; + discordUrl?: Maybe; + externalUrl?: Maybe; + floorPrice?: Maybe; + imageUrl?: Maybe; + safeListRequestStatus?: Maybe; + twitterUsername?: Maybe; +}; export enum OpenSeaSafeListStatus { Approved = 'approved', NotRequested = 'not_requested', Requested = 'requested', - Verified = 'verified', + Verified = 'verified' } export type Pfp = { - image?: Maybe -} + image?: Maybe; +}; export type PfpInput = { - image: Scalars['String'] - isToken?: InputMaybe -} + image: Scalars['String']; + isToken?: InputMaybe; +}; export type Profile = { - __typename?: 'Profile' - bio?: Maybe - cover?: Maybe - displayName?: Maybe - handle?: Maybe - job?: Maybe - location?: Maybe - pfp?: Maybe - website?: Maybe -} + __typename?: 'Profile'; + bio?: Maybe; + cover?: Maybe; + displayName?: Maybe; + handle?: Maybe; + job?: Maybe; + location?: Maybe; + pfp?: Maybe; + website?: Maybe; +}; export type ProfileInput = { - bio?: InputMaybe - cover?: InputMaybe - displayName?: InputMaybe - job?: InputMaybe - location?: InputMaybe - pfp?: InputMaybe - website?: InputMaybe -} + bio?: InputMaybe; + cover?: InputMaybe; + displayName?: InputMaybe; + job?: InputMaybe; + location?: InputMaybe; + pfp?: InputMaybe; + website?: InputMaybe; +}; export type Query = { - __typename?: 'Query' - addressProfile: AddressProfile - addressProfiles: Array - authorizedApps?: Maybe>> - connectedAddresses?: Maybe> - connectedAddressesFromAccount?: Maybe> - connectedAddressesFromAddress?: Maybe> - contractsForAddress?: Maybe - ensProfile: CryptoAddressProfile - gallery?: Maybe> - galleryFromAddress?: Maybe> - getNFTMetadataBatch?: Maybe - links?: Maybe> - linksFromAddress?: Maybe> - nftsForAddress?: Maybe - profile?: Maybe - profileFromAddress?: Maybe - scopes: Array> -} + __typename?: 'Query'; + account: Scalars['URN']; + addressProfile: AddressProfile; + addressProfiles: Array; + authorizedApps?: Maybe>>; + connectedAddresses?: Maybe>; + contractsForAddress?: Maybe; + ensProfile: CryptoAddressProfile; + gallery?: Maybe>; + getNFTMetadataBatch?: Maybe; + links?: Maybe>; + nftsForAddress?: Maybe; + profile?: Maybe; + scopes: Array>; +}; + + +export type QueryAccountArgs = { + addressURN: Scalars['URN']; +}; + export type QueryAddressProfileArgs = { - addressURN: Scalars['URN'] -} + addressURN: Scalars['URN']; +}; + export type QueryAddressProfilesArgs = { - addressURNList?: InputMaybe> -} + addressURNList?: InputMaybe>; +}; -export type QueryConnectedAddressesFromAccountArgs = { - accountURN: Scalars['URN'] -} -export type QueryConnectedAddressesFromAddressArgs = { - addressURN: Scalars['URN'] -} +export type QueryConnectedAddressesArgs = { + targetAccountURN?: InputMaybe; +}; + export type QueryContractsForAddressArgs = { - excludeFilters?: InputMaybe>> - owner: Scalars['String'] - pageSize?: InputMaybe -} + excludeFilters?: InputMaybe>>; + owner: Scalars['String']; + pageSize?: InputMaybe; +}; + export type QueryEnsProfileArgs = { - addressOrEns: Scalars['String'] -} + addressOrEns: Scalars['String']; +}; + + +export type QueryGalleryArgs = { + targetAccountURN?: InputMaybe; +}; -export type QueryGalleryFromAddressArgs = { - addressURN: Scalars['URN'] -} export type QueryGetNftMetadataBatchArgs = { - input?: InputMaybe>> -} + input?: InputMaybe>>; +}; + + +export type QueryLinksArgs = { + targetAccountURN?: InputMaybe; +}; -export type QueryLinksFromAddressArgs = { - addressURN: Scalars['URN'] -} export type QueryNftsForAddressArgs = { - contractAddresses?: InputMaybe>> - owner: Scalars['String'] -} + contractAddresses?: InputMaybe>>; + owner: Scalars['String']; +}; + + +export type QueryProfileArgs = { + targetAccountURN?: InputMaybe; +}; -export type QueryProfileFromAddressArgs = { - addressURN: Scalars['URN'] -} export type QueryScopesArgs = { - clientId: Scalars['String'] -} + clientId: Scalars['String']; +}; export type Scope = { - __typename?: 'Scope' - permission: Scalars['String'] - scopes: Array> -} + __typename?: 'Scope'; + permission: Scalars['String']; + scopes: Array>; +}; export type StandardPfp = Pfp & { - __typename?: 'StandardPFP' - image?: Maybe -} + __typename?: 'StandardPFP'; + image?: Maybe; +}; export enum TokenType { Erc721 = 'ERC721', Erc1155 = 'ERC1155', - Unknown = 'UNKNOWN', + Unknown = 'UNKNOWN' } export type TokenUri = { - __typename?: 'TokenURI' - gateway?: Maybe - raw?: Maybe -} + __typename?: 'TokenURI'; + gateway?: Maybe; + raw?: Maybe; +}; export type TokenUriInput = { - gateway?: InputMaybe - raw?: InputMaybe -} + gateway?: InputMaybe; + raw?: InputMaybe; +}; -export type GetProfileQueryVariables = Exact<{ [key: string]: never }> - -export type GetProfileQuery = { - __typename?: 'Query' - profile?: { - __typename?: 'Profile' - displayName?: string | null - handle?: string | null - cover?: string | null - location?: string | null - job?: string | null - bio?: string | null - website?: string | null - pfp?: - | { - __typename?: 'NFTPFP' - image?: string | null - isToken?: boolean | null - } - | { __typename?: 'StandardPFP'; image?: string | null } - | null - } | null - links?: Array<{ - __typename?: 'Link' - name?: string | null - url?: string | null - verified?: boolean | null - provider?: string | null - }> | null - connectedAddresses?: Array<{ - __typename?: 'Node' - baseUrn: string - qc?: any | null - rc?: any | null - }> | null - gallery?: Array<{ - __typename?: 'Gallery' - contract: string - tokenId: string - chain: string - }> | null -} +export type GetProfileQueryVariables = Exact<{ + targetAccountURN?: InputMaybe; +}>; -export type GetProfileFromAddressQueryVariables = Exact<{ - addressURN: Scalars['URN'] -}> - -export type GetProfileFromAddressQuery = { - __typename?: 'Query' - profile?: { - __typename?: 'Profile' - displayName?: string | null - handle?: string | null - cover?: string | null - location?: string | null - job?: string | null - bio?: string | null - website?: string | null - pfp?: - | { - __typename?: 'NFTPFP' - image?: string | null - isToken?: boolean | null - } - | { __typename?: 'StandardPFP'; image?: string | null } - | null - } | null - links?: Array<{ - __typename?: 'Link' - name?: string | null - url?: string | null - verified?: boolean | null - provider?: string | null - }> | null - gallery?: Array<{ - __typename?: 'Gallery' - contract: string - tokenId: string - chain: string - }> | null - connectedAddresses?: Array<{ - __typename?: 'Node' - baseUrn: string - qc?: any | null - rc?: any | null - }> | null -} -export type GetConnectedAddressesFromAccountQueryVariables = Exact<{ - accountURN: Scalars['URN'] -}> - -export type GetConnectedAddressesFromAccountQuery = { - __typename?: 'Query' - addresses?: Array<{ - __typename?: 'Node' - baseUrn: string - qc?: any | null - rc?: any | null - }> | null -} - -export type GetAuthorizedAppsQueryVariables = Exact<{ [key: string]: never }> - -export type GetAuthorizedAppsQuery = { - __typename?: 'Query' - authorizedApps?: Array<{ - __typename?: 'App' - clientId: string - icon: string - title: string - timestamp: number - } | null> | null -} +export type GetProfileQuery = { __typename?: 'Query', profile?: { __typename?: 'Profile', displayName?: string | null, handle?: string | null, cover?: string | null, location?: string | null, job?: string | null, bio?: string | null, website?: string | null, pfp?: { __typename?: 'NFTPFP', image?: string | null, isToken?: boolean | null } | { __typename?: 'StandardPFP', image?: string | null } | null } | null, links?: Array<{ __typename?: 'Link', name?: string | null, url?: string | null, verified?: boolean | null, provider?: string | null }> | null, connectedAddresses?: Array<{ __typename?: 'Node', baseUrn: string, qc?: any | null, rc?: any | null }> | null, gallery?: Array<{ __typename?: 'Gallery', contract: string, tokenId: string, chain: string }> | null }; export type GetConnectedAddressesQueryVariables = Exact<{ - [key: string]: never -}> - -export type GetConnectedAddressesQuery = { - __typename?: 'Query' - connectedAddresses?: Array<{ - __typename?: 'Node' - baseUrn: string - qc?: any | null - rc?: any | null - }> | null -} + targetAccountURN?: InputMaybe; +}>; + + +export type GetConnectedAddressesQuery = { __typename?: 'Query', addresses?: Array<{ __typename?: 'Node', baseUrn: string, qc?: any | null, rc?: any | null }> | null }; + +export type GetAuthorizedAppsQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetAuthorizedAppsQuery = { __typename?: 'Query', authorizedApps?: Array<{ __typename?: 'App', clientId: string, icon: string, title: string, timestamp: number } | null> | null }; export type UpdateProfileMutationVariables = Exact<{ - profile?: InputMaybe -}> + profile?: InputMaybe; +}>; -export type UpdateProfileMutation = { - __typename?: 'Mutation' - updateProfile?: boolean | null -} + +export type UpdateProfileMutation = { __typename?: 'Mutation', updateProfile?: boolean | null }; export type UpdateLinksMutationVariables = Exact<{ - links?: InputMaybe | LinkInput> -}> + links?: InputMaybe | LinkInput>; +}>; -export type UpdateLinksMutation = { - __typename?: 'Mutation' - updateLinks?: boolean | null -} + +export type UpdateLinksMutation = { __typename?: 'Mutation', updateLinks?: boolean | null }; export type UpdateGalleryMutationVariables = Exact<{ - gallery?: InputMaybe | GalleryInput> -}> + gallery?: InputMaybe | GalleryInput>; +}>; -export type UpdateGalleryMutation = { - __typename?: 'Mutation' - updateGallery?: boolean | null -} + +export type UpdateGalleryMutation = { __typename?: 'Mutation', updateGallery?: boolean | null }; export type DisconnectAddressMutationVariables = Exact<{ - addressURN: Scalars['URN'] -}> + addressURN: Scalars['URN']; +}>; -export type DisconnectAddressMutation = { - __typename?: 'Mutation' - disconnectAddress?: boolean | null -} + +export type DisconnectAddressMutation = { __typename?: 'Mutation', disconnectAddress?: boolean | null }; export type GetAddressProfileQueryVariables = Exact<{ - addressURN: Scalars['URN'] -}> - -export type GetAddressProfileQuery = { - __typename?: 'Query' - addressProfile: { - __typename?: 'AddressProfile' - type: string - urn: any - profile: - | { - __typename: 'CryptoAddressProfile' - address: string - avatar?: string | null - displayName?: string | null - } - | { - __typename: 'OAuthAppleProfile' - name?: string | null - picture: string - } - | { - __typename: 'OAuthDiscordProfile' - email?: string | null - username?: string | null - discriminator?: string | null - avatar?: string | null - discordId?: string | null - } - | { - __typename: 'OAuthGithubProfile' - id?: number | null - name?: string | null - avatar_url: string - html_url?: string | null - followers?: number | null - following?: number | null - login: string - public_gists?: number | null - public_repos?: number | null - } - | { - __typename: 'OAuthGoogleProfile' - email?: string | null - name?: string | null - picture: string - } - | { - __typename: 'OAuthMicrosoftProfile' - name?: string | null - picture: string - email?: string | null - } - | { - __typename: 'OAuthTwitterProfile' - name?: string | null - screen_name: string - profile_image_url_https: string - } - } -} + addressURN: Scalars['URN']; +}>; + + +export type GetAddressProfileQuery = { __typename?: 'Query', addressProfile: { __typename?: 'AddressProfile', type: string, urn: any, profile: { __typename: 'CryptoAddressProfile', address: string, avatar?: string | null, displayName?: string | null } | { __typename: 'OAuthAppleProfile', name?: string | null, picture: string } | { __typename: 'OAuthDiscordProfile', email?: string | null, username?: string | null, discriminator?: string | null, avatar?: string | null, discordId?: string | null } | { __typename: 'OAuthGithubProfile', id?: number | null, name?: string | null, avatar_url: string, html_url?: string | null, followers?: number | null, following?: number | null, login: string, public_gists?: number | null, public_repos?: number | null } | { __typename: 'OAuthGoogleProfile', email?: string | null, name?: string | null, picture: string } | { __typename: 'OAuthMicrosoftProfile', name?: string | null, picture: string, email?: string | null } | { __typename: 'OAuthTwitterProfile', name?: string | null, screen_name: string, profile_image_url_https: string } } }; export type GetAddressProfilesQueryVariables = Exact<{ - addressURNList?: InputMaybe | Scalars['URN']> -}> - -export type GetAddressProfilesQuery = { - __typename?: 'Query' - addressProfiles: Array<{ - __typename?: 'AddressProfile' - type: string - urn: any - profile: - | { - __typename: 'CryptoAddressProfile' - address: string - avatar?: string | null - displayName?: string | null - } - | { - __typename: 'OAuthAppleProfile' - name?: string | null - picture: string - } - | { - __typename: 'OAuthDiscordProfile' - email?: string | null - username?: string | null - discriminator?: string | null - avatar?: string | null - discordId?: string | null - } - | { - __typename: 'OAuthGithubProfile' - id?: number | null - name?: string | null - avatar_url: string - html_url?: string | null - followers?: number | null - following?: number | null - login: string - public_gists?: number | null - public_repos?: number | null - } - | { - __typename: 'OAuthGoogleProfile' - email?: string | null - name?: string | null - picture: string - } - | { - __typename: 'OAuthMicrosoftProfile' - name?: string | null - picture: string - email?: string | null - } - | { - __typename: 'OAuthTwitterProfile' - name?: string | null - screen_name: string - profile_image_url_https: string - } - }> -} + addressURNList?: InputMaybe | Scalars['URN']>; +}>; + + +export type GetAddressProfilesQuery = { __typename?: 'Query', addressProfiles: Array<{ __typename?: 'AddressProfile', type: string, urn: any, profile: { __typename: 'CryptoAddressProfile', address: string, avatar?: string | null, displayName?: string | null } | { __typename: 'OAuthAppleProfile', name?: string | null, picture: string } | { __typename: 'OAuthDiscordProfile', email?: string | null, username?: string | null, discriminator?: string | null, avatar?: string | null, discordId?: string | null } | { __typename: 'OAuthGithubProfile', id?: number | null, name?: string | null, avatar_url: string, html_url?: string | null, followers?: number | null, following?: number | null, login: string, public_gists?: number | null, public_repos?: number | null } | { __typename: 'OAuthGoogleProfile', email?: string | null, name?: string | null, picture: string } | { __typename: 'OAuthMicrosoftProfile', name?: string | null, picture: string, email?: string | null } | { __typename: 'OAuthTwitterProfile', name?: string | null, screen_name: string, profile_image_url_https: string } }> }; + +export type GetAccountUrnFromAddressQueryVariables = Exact<{ + addressURN: Scalars['URN']; +}>; + + +export type GetAccountUrnFromAddressQuery = { __typename?: 'Query', account: any }; export type UpdateAddressNicknameMutationVariables = Exact<{ - addressURN: Scalars['URN'] - nickname: Scalars['String'] -}> + addressURN: Scalars['URN']; + nickname: Scalars['String']; +}>; -export type UpdateAddressNicknameMutation = { - __typename?: 'Mutation' - updateAddressNickname?: boolean | null -} + +export type UpdateAddressNicknameMutation = { __typename?: 'Mutation', updateAddressNickname?: boolean | null }; export type UpdateConnectedAddressesPropertiesMutationVariables = Exact<{ - addressURNList: - | Array - | ConnectedAddressPropertiesUpdateInput -}> - -export type UpdateConnectedAddressesPropertiesMutation = { - __typename?: 'Mutation' - updateConnectedAddressesProperties?: boolean | null -} + addressURNList: Array | ConnectedAddressPropertiesUpdateInput; +}>; + + +export type UpdateConnectedAddressesPropertiesMutation = { __typename?: 'Mutation', updateConnectedAddressesProperties?: boolean | null }; export type GetAuthorizedAppScopesQueryVariables = Exact<{ - clientId: Scalars['String'] -}> - -export type GetAuthorizedAppScopesQuery = { - __typename?: 'Query' - scopes: Array<{ - __typename?: 'Scope' - permission: string - scopes: Array - } | null> -} + clientId: Scalars['String']; +}>; + + +export type GetAuthorizedAppScopesQuery = { __typename?: 'Query', scopes: Array<{ __typename?: 'Scope', permission: string, scopes: Array } | null> }; export type GetEnsProfileQueryVariables = Exact<{ - addressOrEns: Scalars['String'] -}> - -export type GetEnsProfileQuery = { - __typename?: 'Query' - ensProfile: { - __typename?: 'CryptoAddressProfile' - address: string - avatar?: string | null - displayName?: string | null - } -} + addressOrEns: Scalars['String']; +}>; + + +export type GetEnsProfileQuery = { __typename?: 'Query', ensProfile: { __typename?: 'CryptoAddressProfile', address: string, avatar?: string | null, displayName?: string | null } }; export type GetNftsForAddressQueryVariables = Exact<{ - owner: Scalars['String'] - contractAddresses?: InputMaybe< - Array> | InputMaybe - > -}> - -export type GetNftsForAddressQuery = { - __typename?: 'Query' - nftsForAddress?: { - __typename?: 'NFTs' - ownedNfts: Array<{ - __typename?: 'NFT' - title?: string | null - description?: string | null - error?: string | null - contract?: { __typename?: 'Contract'; address?: string | null } | null - id?: { __typename?: 'Id'; tokenId?: string | null } | null - media: Array<{ - __typename?: 'NFTMedia' - raw?: string | null - thumbnail?: string | null - }> - metadata?: { - __typename?: 'NFTMetadata' - properties?: Array<{ - __typename?: 'NFTProperty' - name?: string | null - value?: string | null - display?: string | null - } | null> | null - } | null - contractMetadata?: { - __typename?: 'ContractMetadata' - name?: string | null - tokenType?: TokenType | null - } | null - chain?: { - __typename?: 'Chain' - chain?: string | null - network?: string | null - } | null - }> - } | null -} + owner: Scalars['String']; + contractAddresses?: InputMaybe> | InputMaybe>; +}>; + + +export type GetNftsForAddressQuery = { __typename?: 'Query', nftsForAddress?: { __typename?: 'NFTs', ownedNfts: Array<{ __typename?: 'NFT', title?: string | null, description?: string | null, error?: string | null, contract?: { __typename?: 'Contract', address?: string | null } | null, id?: { __typename?: 'Id', tokenId?: string | null } | null, media: Array<{ __typename?: 'NFTMedia', raw?: string | null, thumbnail?: string | null }>, metadata?: { __typename?: 'NFTMetadata', properties?: Array<{ __typename?: 'NFTProperty', name?: string | null, value?: string | null, display?: string | null } | null> | null } | null, contractMetadata?: { __typename?: 'ContractMetadata', name?: string | null, tokenType?: TokenType | null } | null, chain?: { __typename?: 'Chain', chain?: string | null, network?: string | null } | null }> } | null }; export type GetNftsPerCollectionQueryVariables = Exact<{ - owner: Scalars['String'] - excludeFilters?: InputMaybe< - Array> | InputMaybe - > - pageSize?: InputMaybe -}> - -export type GetNftsPerCollectionQuery = { - __typename?: 'Query' - contractsForAddress?: { - __typename?: 'NFTContracts' - contracts: Array<{ - __typename?: 'NFTContract' - address?: string | null - totalBalance?: number | null - numDistinctTokensOwned?: number | null - name?: string | null - symbol?: string | null - tokenType?: string | null - chain?: { - __typename?: 'Chain' - chain?: string | null - network?: string | null - } | null - ownedNfts?: Array<{ - __typename?: 'NFT' - title?: string | null - description?: string | null - error?: string | null - contract?: { __typename?: 'Contract'; address?: string | null } | null - id?: { __typename?: 'Id'; tokenId?: string | null } | null - media: Array<{ - __typename?: 'NFTMedia' - raw?: string | null - thumbnail?: string | null - }> - metadata?: { - __typename?: 'NFTMetadata' - properties?: Array<{ - __typename?: 'NFTProperty' - name?: string | null - value?: string | null - display?: string | null - } | null> | null - } | null - contractMetadata?: { - __typename?: 'ContractMetadata' - name?: string | null - tokenType?: TokenType | null - } | null - chain?: { - __typename?: 'Chain' - chain?: string | null - network?: string | null - } | null - }> | null - }> - } | null -} + owner: Scalars['String']; + excludeFilters?: InputMaybe> | InputMaybe>; + pageSize?: InputMaybe; +}>; + + +export type GetNftsPerCollectionQuery = { __typename?: 'Query', contractsForAddress?: { __typename?: 'NFTContracts', contracts: Array<{ __typename?: 'NFTContract', address?: string | null, totalBalance?: number | null, numDistinctTokensOwned?: number | null, name?: string | null, symbol?: string | null, tokenType?: string | null, chain?: { __typename?: 'Chain', chain?: string | null, network?: string | null } | null, ownedNfts?: Array<{ __typename?: 'NFT', title?: string | null, description?: string | null, error?: string | null, contract?: { __typename?: 'Contract', address?: string | null } | null, id?: { __typename?: 'Id', tokenId?: string | null } | null, media: Array<{ __typename?: 'NFTMedia', raw?: string | null, thumbnail?: string | null }>, metadata?: { __typename?: 'NFTMetadata', properties?: Array<{ __typename?: 'NFTProperty', name?: string | null, value?: string | null, display?: string | null } | null> | null } | null, contractMetadata?: { __typename?: 'ContractMetadata', name?: string | null, tokenType?: TokenType | null } | null, chain?: { __typename?: 'Chain', chain?: string | null, network?: string | null } | null }> | null }> } | null }; export type GetNftMetadataQueryVariables = Exact<{ - input?: InputMaybe< - Array> | InputMaybe - > -}> - -export type GetNftMetadataQuery = { - __typename?: 'Query' - getNFTMetadataBatch?: { - __typename?: 'NFTs' - ownedNfts: Array<{ - __typename?: 'NFT' - title?: string | null - description?: string | null - error?: string | null - contract?: { __typename?: 'Contract'; address?: string | null } | null - id?: { __typename?: 'Id'; tokenId?: string | null } | null - media: Array<{ - __typename?: 'NFTMedia' - raw?: string | null - thumbnail?: string | null - }> - metadata?: { - __typename?: 'NFTMetadata' - properties?: Array<{ - __typename?: 'NFTProperty' - name?: string | null - value?: string | null - display?: string | null - } | null> | null - } | null - contractMetadata?: { - __typename?: 'ContractMetadata' - name?: string | null - tokenType?: TokenType | null - } | null - chain?: { - __typename?: 'Chain' - chain?: string | null - network?: string | null - } | null - }> - } | null -} + input?: InputMaybe> | InputMaybe>; +}>; + + +export type GetNftMetadataQuery = { __typename?: 'Query', getNFTMetadataBatch?: { __typename?: 'NFTs', ownedNfts: Array<{ __typename?: 'NFT', title?: string | null, description?: string | null, error?: string | null, contract?: { __typename?: 'Contract', address?: string | null } | null, id?: { __typename?: 'Id', tokenId?: string | null } | null, media: Array<{ __typename?: 'NFTMedia', raw?: string | null, thumbnail?: string | null }>, metadata?: { __typename?: 'NFTMetadata', properties?: Array<{ __typename?: 'NFTProperty', name?: string | null, value?: string | null, display?: string | null } | null> | null } | null, contractMetadata?: { __typename?: 'ContractMetadata', name?: string | null, tokenType?: TokenType | null } | null, chain?: { __typename?: 'Chain', chain?: string | null, network?: string | null } | null }> } | null }; + export const GetProfileDocument = gql` - query getProfile { - profile { - pfp { - ... on StandardPFP { - image - } - ... on NFTPFP { - image - isToken - } + query getProfile($targetAccountURN: URN) { + profile(targetAccountURN: $targetAccountURN) { + pfp { + ... on StandardPFP { + image } - displayName - handle - cover - location - job - bio - website - } - links { - name - url - verified - provider - } - connectedAddresses { - baseUrn - qc - rc - } - gallery { - contract - tokenId - chain - } - } -` -export const GetProfileFromAddressDocument = gql` - query getProfileFromAddress($addressURN: URN!) { - profile: profileFromAddress(addressURN: $addressURN) { - pfp { - ... on StandardPFP { - image - } - ... on NFTPFP { - image - isToken - } + ... on NFTPFP { + image + isToken } - displayName - handle - cover - location - job - bio - website - } - links: linksFromAddress(addressURN: $addressURN) { - name - url - verified - provider - } - gallery: galleryFromAddress(addressURN: $addressURN) { - contract - tokenId - chain - } - connectedAddresses: connectedAddressesFromAddress(addressURN: $addressURN) { - baseUrn - qc - rc } + displayName + handle + cover + location + job + bio + website } -` -export const GetConnectedAddressesFromAccountDocument = gql` - query getConnectedAddressesFromAccount($accountURN: URN!) { - addresses: connectedAddressesFromAccount(accountURN: $accountURN) { - baseUrn - qc - rc - } + links(targetAccountURN: $targetAccountURN) { + name + url + verified + provider } -` -export const GetAuthorizedAppsDocument = gql` - query getAuthorizedApps { - authorizedApps { - clientId - icon - title - timestamp - } + connectedAddresses(targetAccountURN: $targetAccountURN) { + baseUrn + qc + rc + } + gallery(targetAccountURN: $targetAccountURN) { + contract + tokenId + chain } -` +} + `; export const GetConnectedAddressesDocument = gql` - query getConnectedAddresses { - connectedAddresses { - baseUrn - qc - rc - } + query getConnectedAddresses($targetAccountURN: URN) { + addresses: connectedAddresses(targetAccountURN: $targetAccountURN) { + baseUrn + qc + rc } -` -export const UpdateProfileDocument = gql` - mutation updateProfile($profile: ProfileInput) { - updateProfile(profile: $profile) +} + `; +export const GetAuthorizedAppsDocument = gql` + query getAuthorizedApps { + authorizedApps { + clientId + icon + title + timestamp } -` +} + `; +export const UpdateProfileDocument = gql` + mutation updateProfile($profile: ProfileInput) { + updateProfile(profile: $profile) +} + `; export const UpdateLinksDocument = gql` - mutation updateLinks($links: [LinkInput!]) { - updateLinks(links: $links) - } -` + mutation updateLinks($links: [LinkInput!]) { + updateLinks(links: $links) +} + `; export const UpdateGalleryDocument = gql` - mutation updateGallery($gallery: [GalleryInput!]) { - updateGallery(gallery: $gallery) - } -` + mutation updateGallery($gallery: [GalleryInput!]) { + updateGallery(gallery: $gallery) +} + `; export const DisconnectAddressDocument = gql` - mutation disconnectAddress($addressURN: URN!) { - disconnectAddress(addressURN: $addressURN) - } -` + mutation disconnectAddress($addressURN: URN!) { + disconnectAddress(addressURN: $addressURN) +} + `; export const GetAddressProfileDocument = gql` - query getAddressProfile($addressURN: URN!) { - addressProfile(addressURN: $addressURN) { - type - urn - profile { - __typename - ... on CryptoAddressProfile { - address - avatar - displayName - } - ... on OAuthGoogleProfile { - email - name - picture - } - ... on OAuthTwitterProfile { - name - screen_name - profile_image_url_https - } - ... on OAuthGithubProfile { - id - name - avatar_url - html_url - followers - following - login - public_gists - public_repos - } - ... on OAuthMicrosoftProfile { - name - picture - email - } - ... on OAuthAppleProfile { - name - picture - } - ... on OAuthDiscordProfile { - discordId: id - email - username - discriminator - avatar - } + query getAddressProfile($addressURN: URN!) { + addressProfile(addressURN: $addressURN) { + type + urn + profile { + __typename + ... on CryptoAddressProfile { + address + avatar + displayName + } + ... on OAuthGoogleProfile { + email + name + picture + } + ... on OAuthTwitterProfile { + name + screen_name + profile_image_url_https + } + ... on OAuthGithubProfile { + id + name + avatar_url + html_url + followers + following + login + public_gists + public_repos + } + ... on OAuthMicrosoftProfile { + name + picture + email + } + ... on OAuthAppleProfile { + name + picture + } + ... on OAuthDiscordProfile { + discordId: id + email + username + discriminator + avatar } } } -` +} + `; export const GetAddressProfilesDocument = gql` - query getAddressProfiles($addressURNList: [URN!]) { - addressProfiles(addressURNList: $addressURNList) { - type - urn - profile { - __typename - ... on CryptoAddressProfile { - address - avatar - displayName - } - ... on OAuthGoogleProfile { - email - name - picture - } - ... on OAuthTwitterProfile { - name - screen_name - profile_image_url_https - } - ... on OAuthGithubProfile { - id - name - avatar_url - html_url - followers - following - login - public_gists - public_repos - } - ... on OAuthMicrosoftProfile { - name - picture - email - } - ... on OAuthAppleProfile { - name - picture - } - ... on OAuthDiscordProfile { - discordId: id - email - username - discriminator - avatar - } + query getAddressProfiles($addressURNList: [URN!]) { + addressProfiles(addressURNList: $addressURNList) { + type + urn + profile { + __typename + ... on CryptoAddressProfile { + address + avatar + displayName + } + ... on OAuthGoogleProfile { + email + name + picture + } + ... on OAuthTwitterProfile { + name + screen_name + profile_image_url_https + } + ... on OAuthGithubProfile { + id + name + avatar_url + html_url + followers + following + login + public_gists + public_repos + } + ... on OAuthMicrosoftProfile { + name + picture + email + } + ... on OAuthAppleProfile { + name + picture + } + ... on OAuthDiscordProfile { + discordId: id + email + username + discriminator + avatar } } } -` +} + `; +export const GetAccountUrnFromAddressDocument = gql` + query getAccountUrnFromAddress($addressURN: URN!) { + account(addressURN: $addressURN) +} + `; export const UpdateAddressNicknameDocument = gql` - mutation updateAddressNickname($addressURN: URN!, $nickname: String!) { - updateAddressNickname(addressURN: $addressURN, nickname: $nickname) - } -` + mutation updateAddressNickname($addressURN: URN!, $nickname: String!) { + updateAddressNickname(addressURN: $addressURN, nickname: $nickname) +} + `; export const UpdateConnectedAddressesPropertiesDocument = gql` - mutation updateConnectedAddressesProperties( - $addressURNList: [ConnectedAddressPropertiesUpdateInput!]! - ) { - updateConnectedAddressesProperties(addressURNList: $addressURNList) - } -` + mutation updateConnectedAddressesProperties($addressURNList: [ConnectedAddressPropertiesUpdateInput!]!) { + updateConnectedAddressesProperties(addressURNList: $addressURNList) +} + `; export const GetAuthorizedAppScopesDocument = gql` - query getAuthorizedAppScopes($clientId: String!) { - scopes(clientId: $clientId) { - permission - scopes - } + query getAuthorizedAppScopes($clientId: String!) { + scopes(clientId: $clientId) { + permission + scopes } -` +} + `; export const GetEnsProfileDocument = gql` - query getEnsProfile($addressOrEns: String!) { - ensProfile(addressOrEns: $addressOrEns) { - address - avatar - displayName - } + query getEnsProfile($addressOrEns: String!) { + ensProfile(addressOrEns: $addressOrEns) { + address + avatar + displayName } -` +} + `; export const GetNftsForAddressDocument = gql` - query getNftsForAddress($owner: String!, $contractAddresses: [String]) { - nftsForAddress(owner: $owner, contractAddresses: $contractAddresses) { - ownedNfts { - contract { - address - } - title - description - id { - tokenId - } - media { - raw - thumbnail - } - metadata { - properties { - name - value - display - } - } - error - contractMetadata { + query getNftsForAddress($owner: String!, $contractAddresses: [String]) { + nftsForAddress(owner: $owner, contractAddresses: $contractAddresses) { + ownedNfts { + contract { + address + } + title + description + id { + tokenId + } + media { + raw + thumbnail + } + metadata { + properties { name - tokenType - } - chain { - chain - network + value + display } } - } - } -` -export const GetNftsPerCollectionDocument = gql` - query getNftsPerCollection( - $owner: String! - $excludeFilters: [String] - $pageSize: Int - ) { - contractsForAddress( - owner: $owner - excludeFilters: $excludeFilters - pageSize: $pageSize - ) { - contracts { - address - totalBalance - numDistinctTokensOwned + error + contractMetadata { name - symbol tokenType - chain { - chain - network - } - ownedNfts { - contract { - address - } - title - description - id { - tokenId - } - media { - raw - thumbnail - } - metadata { - properties { - name - value - display - } - } - error - contractMetadata { - name - tokenType - } - chain { - chain - network - } - } + } + chain { + chain + network } } } -` -export const GetNftMetadataDocument = gql` - query getNFTMetadata($input: [NFTMetadataInput]) { - getNFTMetadataBatch(input: $input) { +} + `; +export const GetNftsPerCollectionDocument = gql` + query getNftsPerCollection($owner: String!, $excludeFilters: [String], $pageSize: Int) { + contractsForAddress( + owner: $owner + excludeFilters: $excludeFilters + pageSize: $pageSize + ) { + contracts { + address + totalBalance + numDistinctTokensOwned + name + symbol + tokenType + chain { + chain + network + } ownedNfts { contract { address @@ -1374,292 +921,103 @@ export const GetNftMetadataDocument = gql` } } } -` - -export type SdkFunctionWrapper = ( - action: (requestHeaders?: Record) => Promise, - operationName: string, - operationType?: string -) => Promise - -const defaultWrapper: SdkFunctionWrapper = ( - action, - _operationName, - _operationType -) => action() - -export function getSdk( - client: GraphQLClient, - withWrapper: SdkFunctionWrapper = defaultWrapper -) { +} + `; +export const GetNftMetadataDocument = gql` + query getNFTMetadata($input: [NFTMetadataInput]) { + getNFTMetadataBatch(input: $input) { + ownedNfts { + contract { + address + } + title + description + id { + tokenId + } + media { + raw + thumbnail + } + metadata { + properties { + name + value + display + } + } + error + contractMetadata { + name + tokenType + } + chain { + chain + network + } + } + } +} + `; + +export type SdkFunctionWrapper = (action: (requestHeaders?:Record) => Promise, operationName: string, operationType?: string) => Promise; + + +const defaultWrapper: SdkFunctionWrapper = (action, _operationName, _operationType) => action(); + +export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper = defaultWrapper) { return { - getProfile( - variables?: GetProfileQueryVariables, - requestHeaders?: Dom.RequestInit['headers'] - ): Promise { - return withWrapper( - (wrappedRequestHeaders) => - client.request(GetProfileDocument, variables, { - ...requestHeaders, - ...wrappedRequestHeaders, - }), - 'getProfile', - 'query' - ) - }, - getProfileFromAddress( - variables: GetProfileFromAddressQueryVariables, - requestHeaders?: Dom.RequestInit['headers'] - ): Promise { - return withWrapper( - (wrappedRequestHeaders) => - client.request( - GetProfileFromAddressDocument, - variables, - { ...requestHeaders, ...wrappedRequestHeaders } - ), - 'getProfileFromAddress', - 'query' - ) - }, - getConnectedAddressesFromAccount( - variables: GetConnectedAddressesFromAccountQueryVariables, - requestHeaders?: Dom.RequestInit['headers'] - ): Promise { - return withWrapper( - (wrappedRequestHeaders) => - client.request( - GetConnectedAddressesFromAccountDocument, - variables, - { ...requestHeaders, ...wrappedRequestHeaders } - ), - 'getConnectedAddressesFromAccount', - 'query' - ) + getProfile(variables?: GetProfileQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(GetProfileDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'getProfile', 'query'); }, - getAuthorizedApps( - variables?: GetAuthorizedAppsQueryVariables, - requestHeaders?: Dom.RequestInit['headers'] - ): Promise { - return withWrapper( - (wrappedRequestHeaders) => - client.request( - GetAuthorizedAppsDocument, - variables, - { ...requestHeaders, ...wrappedRequestHeaders } - ), - 'getAuthorizedApps', - 'query' - ) + getConnectedAddresses(variables?: GetConnectedAddressesQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(GetConnectedAddressesDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'getConnectedAddresses', 'query'); }, - getConnectedAddresses( - variables?: GetConnectedAddressesQueryVariables, - requestHeaders?: Dom.RequestInit['headers'] - ): Promise { - return withWrapper( - (wrappedRequestHeaders) => - client.request( - GetConnectedAddressesDocument, - variables, - { ...requestHeaders, ...wrappedRequestHeaders } - ), - 'getConnectedAddresses', - 'query' - ) + getAuthorizedApps(variables?: GetAuthorizedAppsQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(GetAuthorizedAppsDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'getAuthorizedApps', 'query'); }, - updateProfile( - variables?: UpdateProfileMutationVariables, - requestHeaders?: Dom.RequestInit['headers'] - ): Promise { - return withWrapper( - (wrappedRequestHeaders) => - client.request( - UpdateProfileDocument, - variables, - { ...requestHeaders, ...wrappedRequestHeaders } - ), - 'updateProfile', - 'mutation' - ) + updateProfile(variables?: UpdateProfileMutationVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(UpdateProfileDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'updateProfile', 'mutation'); }, - updateLinks( - variables?: UpdateLinksMutationVariables, - requestHeaders?: Dom.RequestInit['headers'] - ): Promise { - return withWrapper( - (wrappedRequestHeaders) => - client.request(UpdateLinksDocument, variables, { - ...requestHeaders, - ...wrappedRequestHeaders, - }), - 'updateLinks', - 'mutation' - ) + updateLinks(variables?: UpdateLinksMutationVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(UpdateLinksDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'updateLinks', 'mutation'); }, - updateGallery( - variables?: UpdateGalleryMutationVariables, - requestHeaders?: Dom.RequestInit['headers'] - ): Promise { - return withWrapper( - (wrappedRequestHeaders) => - client.request( - UpdateGalleryDocument, - variables, - { ...requestHeaders, ...wrappedRequestHeaders } - ), - 'updateGallery', - 'mutation' - ) + updateGallery(variables?: UpdateGalleryMutationVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(UpdateGalleryDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'updateGallery', 'mutation'); }, - disconnectAddress( - variables: DisconnectAddressMutationVariables, - requestHeaders?: Dom.RequestInit['headers'] - ): Promise { - return withWrapper( - (wrappedRequestHeaders) => - client.request( - DisconnectAddressDocument, - variables, - { ...requestHeaders, ...wrappedRequestHeaders } - ), - 'disconnectAddress', - 'mutation' - ) + disconnectAddress(variables: DisconnectAddressMutationVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(DisconnectAddressDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'disconnectAddress', 'mutation'); }, - getAddressProfile( - variables: GetAddressProfileQueryVariables, - requestHeaders?: Dom.RequestInit['headers'] - ): Promise { - return withWrapper( - (wrappedRequestHeaders) => - client.request( - GetAddressProfileDocument, - variables, - { ...requestHeaders, ...wrappedRequestHeaders } - ), - 'getAddressProfile', - 'query' - ) + getAddressProfile(variables: GetAddressProfileQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(GetAddressProfileDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'getAddressProfile', 'query'); }, - getAddressProfiles( - variables?: GetAddressProfilesQueryVariables, - requestHeaders?: Dom.RequestInit['headers'] - ): Promise { - return withWrapper( - (wrappedRequestHeaders) => - client.request( - GetAddressProfilesDocument, - variables, - { ...requestHeaders, ...wrappedRequestHeaders } - ), - 'getAddressProfiles', - 'query' - ) + getAddressProfiles(variables?: GetAddressProfilesQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(GetAddressProfilesDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'getAddressProfiles', 'query'); }, - updateAddressNickname( - variables: UpdateAddressNicknameMutationVariables, - requestHeaders?: Dom.RequestInit['headers'] - ): Promise { - return withWrapper( - (wrappedRequestHeaders) => - client.request( - UpdateAddressNicknameDocument, - variables, - { ...requestHeaders, ...wrappedRequestHeaders } - ), - 'updateAddressNickname', - 'mutation' - ) + getAccountUrnFromAddress(variables: GetAccountUrnFromAddressQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(GetAccountUrnFromAddressDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'getAccountUrnFromAddress', 'query'); }, - updateConnectedAddressesProperties( - variables: UpdateConnectedAddressesPropertiesMutationVariables, - requestHeaders?: Dom.RequestInit['headers'] - ): Promise { - return withWrapper( - (wrappedRequestHeaders) => - client.request( - UpdateConnectedAddressesPropertiesDocument, - variables, - { ...requestHeaders, ...wrappedRequestHeaders } - ), - 'updateConnectedAddressesProperties', - 'mutation' - ) + updateAddressNickname(variables: UpdateAddressNicknameMutationVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(UpdateAddressNicknameDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'updateAddressNickname', 'mutation'); }, - getAuthorizedAppScopes( - variables: GetAuthorizedAppScopesQueryVariables, - requestHeaders?: Dom.RequestInit['headers'] - ): Promise { - return withWrapper( - (wrappedRequestHeaders) => - client.request( - GetAuthorizedAppScopesDocument, - variables, - { ...requestHeaders, ...wrappedRequestHeaders } - ), - 'getAuthorizedAppScopes', - 'query' - ) + updateConnectedAddressesProperties(variables: UpdateConnectedAddressesPropertiesMutationVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(UpdateConnectedAddressesPropertiesDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'updateConnectedAddressesProperties', 'mutation'); }, - getEnsProfile( - variables: GetEnsProfileQueryVariables, - requestHeaders?: Dom.RequestInit['headers'] - ): Promise { - return withWrapper( - (wrappedRequestHeaders) => - client.request(GetEnsProfileDocument, variables, { - ...requestHeaders, - ...wrappedRequestHeaders, - }), - 'getEnsProfile', - 'query' - ) + getAuthorizedAppScopes(variables: GetAuthorizedAppScopesQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(GetAuthorizedAppScopesDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'getAuthorizedAppScopes', 'query'); }, - getNftsForAddress( - variables: GetNftsForAddressQueryVariables, - requestHeaders?: Dom.RequestInit['headers'] - ): Promise { - return withWrapper( - (wrappedRequestHeaders) => - client.request( - GetNftsForAddressDocument, - variables, - { ...requestHeaders, ...wrappedRequestHeaders } - ), - 'getNftsForAddress', - 'query' - ) + getEnsProfile(variables: GetEnsProfileQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(GetEnsProfileDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'getEnsProfile', 'query'); }, - getNftsPerCollection( - variables: GetNftsPerCollectionQueryVariables, - requestHeaders?: Dom.RequestInit['headers'] - ): Promise { - return withWrapper( - (wrappedRequestHeaders) => - client.request( - GetNftsPerCollectionDocument, - variables, - { ...requestHeaders, ...wrappedRequestHeaders } - ), - 'getNftsPerCollection', - 'query' - ) + getNftsForAddress(variables: GetNftsForAddressQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(GetNftsForAddressDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'getNftsForAddress', 'query'); }, - getNFTMetadata( - variables?: GetNftMetadataQueryVariables, - requestHeaders?: Dom.RequestInit['headers'] - ): Promise { - return withWrapper( - (wrappedRequestHeaders) => - client.request( - GetNftMetadataDocument, - variables, - { ...requestHeaders, ...wrappedRequestHeaders } - ), - 'getNFTMetadata', - 'query' - ) + getNftsPerCollection(variables: GetNftsPerCollectionQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(GetNftsPerCollectionDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'getNftsPerCollection', 'query'); }, - } + getNFTMetadata(variables?: GetNftMetadataQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(GetNftMetadataDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'getNFTMetadata', 'query'); + } + }; } -export type Sdk = ReturnType +export type Sdk = ReturnType; \ No newline at end of file diff --git a/packages/utils/getAuthzHeaderConditionallyFromToken.ts b/packages/utils/getAuthzHeaderConditionallyFromToken.ts index ce7d54f30e..372d054639 100644 --- a/packages/utils/getAuthzHeaderConditionallyFromToken.ts +++ b/packages/utils/getAuthzHeaderConditionallyFromToken.ts @@ -1,3 +1,10 @@ +/** + * This method was created to work around TRPC encoding issue when passing + * empty value for the header which would get encoded as "null" string. + * @param token jwt token if specified + * @returns Valid optional header input for TRPC + */ + export default function (token: string | undefined): Record { return token ? { Authorization: `Bearer ${token}` } : {} } diff --git a/platform/account/src/jsonrpc/methods/getAddresses.ts b/platform/account/src/jsonrpc/methods/getAddresses.ts index fe25bffc9c..6020de7107 100644 --- a/platform/account/src/jsonrpc/methods/getAddresses.ts +++ b/platform/account/src/jsonrpc/methods/getAddresses.ts @@ -27,9 +27,10 @@ export const getAddressesMethod = async ({ }): Promise => { const caller = appRouter.createCaller(ctx) - const getAddressesCall = ctx.token - ? caller.getOwnAddresses - : caller.getPublicAddresses + const getAddressesCall = + ctx.accountURN === input.account + ? caller.getOwnAddresses + : caller.getPublicAddresses const addresses = await getAddressesCall({ account: input.account }) diff --git a/platform/account/src/jsonrpc/methods/getProfile.ts b/platform/account/src/jsonrpc/methods/getProfile.ts index fd9f35fe01..052f52a902 100644 --- a/platform/account/src/jsonrpc/methods/getProfile.ts +++ b/platform/account/src/jsonrpc/methods/getProfile.ts @@ -29,9 +29,11 @@ export const getProfileMethod = async ({ }): Promise => { const node = await initAccountNodeByName(input.account, ctx.Account) const caller = appRouter.createCaller(ctx) - const getAddressesCall = ctx.token - ? caller.getOwnAddresses - : caller.getPublicAddresses + + const getAddressesCall = + ctx.accountURN === input.account + ? caller.getOwnAddresses + : caller.getPublicAddresses const [profile, addresses] = await Promise.all([ node.class.getProfile(), diff --git a/platform/account/src/jsonrpc/methods/setGallery.ts b/platform/account/src/jsonrpc/methods/setGallery.ts index bad47b3eb3..b3d2e04bf0 100644 --- a/platform/account/src/jsonrpc/methods/setGallery.ts +++ b/platform/account/src/jsonrpc/methods/setGallery.ts @@ -15,6 +15,13 @@ export const setGalleryMethod = async ({ input: z.infer ctx: Context }): Promise => { - await ctx.account?.class.setGallery(input.gallery) + // if user is calling this method with the same accountURN in jwt + // TODO: validate JWT in "ValidateJWT" middleware + if (ctx.accountURN === input.name) { + // Don't need to await it + // Fire and go + ctx.account?.class.setGallery(input.gallery) + } + return } diff --git a/platform/account/src/jsonrpc/methods/setLinks.ts b/platform/account/src/jsonrpc/methods/setLinks.ts index ddc6f89c67..5ba651bfab 100644 --- a/platform/account/src/jsonrpc/methods/setLinks.ts +++ b/platform/account/src/jsonrpc/methods/setLinks.ts @@ -15,6 +15,12 @@ export const setLinksMethod = async ({ input: z.infer ctx: Context }): Promise => { - await ctx.account?.class.setLinks(input.links) + // if user is calling this method with the same accountURN in jwt + // TODO: validate JWT in "ValidateJWT" middleware + if (ctx.accountURN === input.name) { + // Don't need to await it + // Fire and go + ctx.account?.class.setLinks(input.links) + } return } diff --git a/platform/account/src/jsonrpc/methods/setProfile.ts b/platform/account/src/jsonrpc/methods/setProfile.ts index da20efd777..414c423758 100644 --- a/platform/account/src/jsonrpc/methods/setProfile.ts +++ b/platform/account/src/jsonrpc/methods/setProfile.ts @@ -16,21 +16,27 @@ export const setProfileMethod = async ({ input: z.infer ctx: Context }): Promise => { - await ctx.account?.class.setProfile(input.profile) + // if user is calling this method with the same accountURN in jwt + // TODO: validate JWT in "ValidateJWT" middleware + if (ctx.accountURN === input.name) { + await ctx.account?.class.setProfile(input.profile) + } const qcomps = { name: input.profile.displayName, picture: input.profile.pfp?.image, } - const enhancedUrn = AccountURNSpace.componentizedUrn( - AccountURNSpace.decode(ctx.accountURN!), - undefined, - qcomps - ) + if (ctx.accountURN) { + const enhancedUrn = AccountURNSpace.componentizedUrn( + AccountURNSpace.decode(ctx.accountURN), + undefined, + qcomps + ) - //TODO make this asynchornous so user's don't need to wait - //for the second leg of IO to complete - const edge = ctx.edges - await edge.updateNode.mutate({ urnOfNode: enhancedUrn }) + const edge = ctx.edges + // Don't need to await it + // Fire and go + edge.updateNode.mutate({ urnOfNode: enhancedUrn }) + } return } diff --git a/platform/galaxy/src/schema/resolvers/account.ts b/platform/galaxy/src/schema/resolvers/account.ts index 86f55dc0ab..fcff574a1d 100644 --- a/platform/galaxy/src/schema/resolvers/account.ts +++ b/platform/galaxy/src/schema/resolvers/account.ts @@ -22,22 +22,26 @@ import { Gallery, Links, Profile } from '@kubelt/platform.account/src/types' import { ResolverContext } from './common' import { PlatformAddressURNHeader } from '@kubelt/types/headers' import { getAuthzHeaderConditionallyFromToken } from '@kubelt/utils' -import { AccountURN } from '@kubelt/urns/account' +import type { AccountURN } from '@kubelt/urns/account' const accountResolvers: Resolvers = { Query: { profile: async ( _parent: any, - {}, + { targetAccountURN }: { targetAccountURN?: AccountURN }, { env, accountURN, jwt }: ResolverContext ) => { console.log(`galaxy:profile: getting profile for account: ${accountURN}`) + + const finalAccountURN = targetAccountURN || accountURN + const accountClient = createAccountClient( env.Account, getAuthzHeaderConditionallyFromToken(jwt) ) + let accountProfile = await accountClient.getProfile.query({ - account: accountURN, + account: finalAccountURN, }) return accountProfile @@ -83,16 +87,19 @@ const accountResolvers: Resolvers = { links: async ( _parent: any, - {}, + { targetAccountURN }: { targetAccountURN?: AccountURN }, { env, accountURN, jwt }: ResolverContext ) => { console.log(`galaxy:links: getting links for account: ${accountURN}`) + + const finalAccountURN = targetAccountURN || accountURN + const accountClient = createAccountClient( env.Account, getAuthzHeaderConditionallyFromToken(jwt) ) let links = await accountClient.getLinks.query({ - account: accountURN, + account: finalAccountURN, }) return links @@ -100,23 +107,26 @@ const accountResolvers: Resolvers = { gallery: async ( _parent: any, - {}, + { targetAccountURN }: { targetAccountURN?: AccountURN }, { env, accountURN, jwt }: ResolverContext ) => { console.log(`galaxy:gallery: getting gallery for account: ${accountURN}`) + + const finalAccountURN = targetAccountURN || accountURN + const accountClient = createAccountClient( env.Account, getAuthzHeaderConditionallyFromToken(jwt) ) const connectedAddresses = await getConnectedCryptoAddresses({ - accountURN, + accountURN: finalAccountURN, Account: env.Account, - jwt, + jwt: jwt, }) const gallery = await accountClient.getGallery.query({ - account: accountURN, + account: finalAccountURN, }) // Validation @@ -129,7 +139,7 @@ const accountResolvers: Resolvers = { // Removal if (gallery.length !== filteredGallery.length) { accountClient.setGallery.mutate({ - name: accountURN, + name: finalAccountURN, gallery: filteredGallery, }) } @@ -142,203 +152,19 @@ const accountResolvers: Resolvers = { connectedAddresses: async ( _parent: any, - {}, + { targetAccountURN }: { targetAccountURN?: AccountURN }, { env, accountURN, jwt }: ResolverContext ) => { - const addresses = await getConnectedAddresses({ - accountURN, - Account: env.Account, - jwt, - }) + const finalAccountURN = targetAccountURN || accountURN - return addresses - }, - - connectedAddressesFromAccount: async ( - _parent: any, - { accountURN }: { accountURN: AccountURN }, - { env }: ResolverContext - ) => { const addresses = await getConnectedAddresses({ - accountURN, + accountURN: finalAccountURN, Account: env.Account, + jwt, }) return addresses }, - - profileFromAddress: async ( - _parent: any, - { addressURN }: { addressURN: AddressURN }, - { env }: ResolverContext - ) => { - const addressClient = createAddressClient(env.Address, { - [PlatformAddressURNHeader]: addressURN, // note: ens names will be resolved - }) - const accountURN = await addressClient.getAccount.query() - - // return the address profile if no account is associated with the address - if (!accountURN) { - console.log( - 'galaxy.profileFromAddress: attempt to resolve profile from address w/o account' - ) - throw new GraphQLError("Address doesn't have an associated account") - } - - // get the account profile - const accountClient = createAccountClient(env.Account, {}) - - console.log("galaxy.profileFromAddress: getting account's profile") - // should also return the handle if it exists - let accountProfile = await accountClient.getProfile.query({ - account: accountURN, - }) - - const baseUrn = AddressURNSpace.urn( - AddressURNSpace.parse(addressURN).decoded - ) - - // check if the addressURN is in the account's connected addresses (if hidden it won't be) - if ( - accountProfile && - !accountProfile.addresses.filter( - (address) => baseUrn === address.baseUrn - ).length - ) { - console.log('galaxy.profileFromAddress: address is hidden') - throw new GraphQLError("Address doesn't have an associated account", { - extensions: { - code: 'Address not found', - http: { - status: 404, - }, - }, - }) - } - - return accountProfile - }, - - linksFromAddress: async ( - _parent: any, - { addressURN }: { addressURN: AddressURN }, - { env }: ResolverContext - ) => { - const addressClient = createAddressClient(env.Address, { - [PlatformAddressURNHeader]: addressURN, // note: ens names will be resolved - }) - const accountURN = await addressClient.getAccount.query() - - // return the address profile if no account is associated with the address - if (!accountURN) { - console.log( - 'galaxy.linksFromAddress: attempt to resolve profile from address w/o account' - ) - throw new GraphQLError("Address doesn't have an associated account") - } - - // get the account profile - const accountClient = createAccountClient(env.Account, {}) - - console.log("galaxy.linksFromAddress: getting account's links") - // should also return the handle if it exists - const linksFromAddress = await accountClient.getLinks.query({ - account: accountURN, - }) - - return linksFromAddress - }, - - galleryFromAddress: async ( - _parent: any, - { addressURN }: { addressURN: AddressURN }, - { env, jwt, accountURN }: ResolverContext - ) => { - console.log("galaxy.galleryFromAddress: getting account's gallery") - const addressClient = createAddressClient(env.Address, { - [PlatformAddressURNHeader]: addressURN, // note: ens names will be resolved - }) - const calledAccountURN = await addressClient.getAccount.query() - - // return the address profile if no account is associated with the address - if (!calledAccountURN) { - console.log( - 'galaxy.galleryFromAddress: attempt to resolve profile from address w/o account' - ) - throw new GraphQLError("Address doesn't have an associated account") - } - - // get the account profile - const accountClient = createAccountClient( - env.Account, - getAuthzHeaderConditionallyFromToken(jwt) - ) - - const connectedAddresses = await getConnectedCryptoAddresses({ - accountURN: calledAccountURN, - Account: env.Account, - }) - - // should also return the handle if it exists - const gallery = await accountClient.getGallery.query({ - account: calledAccountURN, - }) - if (gallery) { - // Validation - const filteredGallery = await validOwnership( - gallery, - env, - connectedAddresses - ) - - if ( - gallery.length !== filteredGallery.length && - calledAccountURN === accountURN - ) { - accountClient.setGallery.mutate({ - name: calledAccountURN, - gallery: filteredGallery, - }) - } - - return filteredGallery - } - // if there is no gallery - return [] - }, - - connectedAddressesFromAddress: async ( - _parent: any, - { addressURN }: { addressURN: AddressURN }, - { env, jwt, accountURN }: ResolverContext - ) => { - const addressClient = createAddressClient(env.Address, { - [PlatformAddressURNHeader]: addressURN, // note: ens names will be resolved - }) - const calledAccountURN = await addressClient.getAccount.query() - - const validJWT = accountURN === calledAccountURN ? jwt : undefined - - // return the address profile if no account is associated with the address - if (!calledAccountURN) { - console.log( - 'galaxy.connectedAddressesFromAddress: attempt to resolve profile from address w/o account' - ) - throw new GraphQLError("Address doesn't have an associated account") - } - - console.log( - "galaxy.connectedAddressesFromAddress: getting account's connected addresses" - ) - // should also return the handle if it exists - const connectedAddressesFromAddress = getConnectedAddresses({ - accountURN: calledAccountURN, - Account: env.Account, - jwt: validJWT, - }) - - return connectedAddressesFromAddress - }, }, Mutation: { disconnectAddress: async ( @@ -481,21 +307,6 @@ const ProfileResolverComposition = { logAnalytics(), temporaryConvertToPublic(), ], - 'Query.connectedAddressesFromAccount': [ - setupContext(), - hasApiKey(), - logAnalytics(), - temporaryConvertToPublic(), - ], - 'Query.profileFromAddress': [setupContext(), hasApiKey(), logAnalytics()], - 'Query.linksFromAddress': [setupContext(), hasApiKey(), logAnalytics()], - 'Query.galleryFromAddress': [setupContext(), hasApiKey(), logAnalytics()], - 'Query.connectedAddressesFromAddress': [ - setupContext(), - hasApiKey(), - logAnalytics(), - temporaryConvertToPublic(), - ], 'Mutation.updateProfile': [ setupContext(), hasApiKey(), diff --git a/platform/galaxy/src/schema/resolvers/address.ts b/platform/galaxy/src/schema/resolvers/address.ts index 0849b985a3..2306f5339d 100644 --- a/platform/galaxy/src/schema/resolvers/address.ts +++ b/platform/galaxy/src/schema/resolvers/address.ts @@ -25,6 +25,19 @@ const addressResolvers: Resolvers = { ensProfile: async (_parent, { addressOrEns }, { env }: ResolverContext) => { return new ENSUtils().getEnsEntry(addressOrEns) }, + account: async ( + _parent, + { addressURN }: { addressURN: AddressURN }, + { env } + ) => { + const addressClient = createAddressClient(env.Address, { + [PlatformAddressURNHeader]: addressURN, + }) + + const accountURN = await addressClient.getAccount.query() + + return accountURN + }, addressProfile: async ( _parent: any, { addressURN }: { addressURN: AddressURN }, @@ -132,6 +145,7 @@ const addressResolvers: Resolvers = { // TODO: add address middleware const AddressResolverComposition = { 'Query.ensProfile': [setupContext(), hasApiKey()], + 'Query.account': [setupContext(), hasApiKey()], 'Query.addressProfile': [setupContext(), hasApiKey()], 'Query.addressProfiles': [setupContext(), hasApiKey()], 'Mutation.updateAddressNickname': [ diff --git a/platform/galaxy/src/schema/types/account.ts b/platform/galaxy/src/schema/types/account.ts index 9a2641f013..df5da4c765 100644 --- a/platform/galaxy/src/schema/types/account.ts +++ b/platform/galaxy/src/schema/types/account.ts @@ -60,16 +60,11 @@ export default /* GraphQL */ ` } type Query { - profile: Profile - links: [Link!] - gallery: [Gallery!] - connectedAddresses: [Node!] - connectedAddressesFromAccount(accountURN: URN!): [Node!] + profile(targetAccountURN: URN): Profile + links(targetAccountURN: URN): [Link!] + gallery(targetAccountURN: URN): [Gallery!] + connectedAddresses(targetAccountURN: URN): [Node!] authorizedApps: [App] - profileFromAddress(addressURN: URN!): Profile - linksFromAddress(addressURN: URN!): [Link!] - galleryFromAddress(addressURN: URN!): [Gallery!] - connectedAddressesFromAddress(addressURN: URN!): [Node!] } type Mutation { diff --git a/platform/galaxy/src/schema/types/address.ts b/platform/galaxy/src/schema/types/address.ts index d127d5eac3..0cafc2aa88 100644 --- a/platform/galaxy/src/schema/types/address.ts +++ b/platform/galaxy/src/schema/types/address.ts @@ -84,6 +84,7 @@ export default /* GraphQL */ ` type Query { ensProfile(addressOrEns: String!): CryptoAddressProfile! + account(addressURN: URN!): URN! addressProfile(addressURN: URN!): AddressProfile! addressProfiles(addressURNList: [URN!]): [AddressProfile!]! }