Skip to content

Commit

Permalink
GAL-3568: View on Mirror and fix OpenSea link (#1684)
Browse files Browse the repository at this point in the history
* base

* OpenSea link should work on all chains on eth

* updated logic to detect mirror NFT

* cleanup

* logic to detect Mirror nft updated

* moved extractMirrorXyzUrl to sharedUtils

* minor

* added change to mobile as well

* added unit test + cleanup

* req changes

* lint

* lint

* lint

* lint

* lint

* lint

* lint

* lint part 1

* lint part 2

* final

* final

* minor + unit test

* test WIP

* Enable shared package tests (#1691)

* updated test run

* attempt 2

* updated test to use JSON object as input

---------

Co-authored-by: Robinnnnn <rokim8@gmail.com>
  • Loading branch information
Rohan-cp and Robinnnnn authored Jul 12, 2023
1 parent 63a46dc commit 501699e
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 18 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/web.unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,7 @@ jobs:
node-version: 16.18.1
cache: 'yarn'
- run: 'yarn install --immutable'
- name: Run unit tests
- name: Run web unit tests
run: node_modules/.bin/moon run web:codegen && node_modules/.bin/moon run web:test
- name: Run shared package tests
run: node_modules/.bin/moon run shared:relay-codegen && node_modules/.bin/moon run shared:test
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useFragment } from 'react-relay';
import { graphql } from 'relay-runtime';

import { NftAdditionalDetailsEthFragment$key } from '~/generated/NftAdditionalDetailsEthFragment.graphql';
import { extractMirrorXyzUrl } from '~/shared/utils/extractMirrorXyzUrl';
import { getOpenseaExternalUrl, hexHandler } from '~/shared/utils/getOpenseaExternalUrl';

import { EnsOrAddress } from '../../components/EnsOrAddress';
Expand All @@ -24,6 +25,7 @@ export function NftAdditionalDetailsEth({ tokenRef, showDetails }: NftAdditional
tokenId
chain
tokenMetadata
contract {
creatorAddress {
Expand All @@ -42,15 +44,23 @@ export function NftAdditionalDetailsEth({ tokenRef, showDetails }: NftAdditional
tokenRef
);

const { tokenId, contract, externalUrl } = token;
const { tokenId, contract, externalUrl, chain, tokenMetadata } = token;

const openSeaExternalUrl = useMemo(() => {
if (contract?.contractAddress?.address && tokenId) {
return getOpenseaExternalUrl(contract.contractAddress.address, tokenId);
if (chain && contract?.contractAddress?.address && tokenId) {
return getOpenseaExternalUrl(chain, contract.contractAddress.address, tokenId);
}

return null;
}, [contract?.contractAddress?.address, tokenId]);
}, [chain, contract?.contractAddress?.address, tokenId]);

const mirrorXyzUrl = useMemo(() => {
if (tokenMetadata) {
return extractMirrorXyzUrl(tokenMetadata);
}

return null;
}, [tokenMetadata]);

return (
<View className="flex flex-col space-y-4">
Expand Down Expand Up @@ -91,6 +101,14 @@ export function NftAdditionalDetailsEth({ tokenRef, showDetails }: NftAdditional
</DetailSection>
)}

{mirrorXyzUrl && (
<DetailSection>
<InteractiveLink href={mirrorXyzUrl} type="NFT Detail View on Mirror">
View on Mirror
</InteractiveLink>
</DetailSection>
)}

{openSeaExternalUrl && (
<DetailSection>
<InteractiveLink href={openSeaExternalUrl} type="NFT Detail View on Opensea">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export default function CommunityHolderGridItem({ holderRef, queryRef }: Props)
fragment CommunityHolderGridItemFragment on Token {
name
tokenId
chain
contract {
contractAddress {
address
Expand Down Expand Up @@ -64,7 +65,7 @@ export default function CommunityHolderGridItem({ holderRef, queryRef }: Props)

const { showModal } = useModalActions();

const { tokenId, contract, owner } = token;
const { tokenId, contract, owner, chain } = token;

const usernameWithFallback = owner ? graphqlTruncateUniversalUsername(owner) : null;

Expand All @@ -81,12 +82,12 @@ export default function CommunityHolderGridItem({ holderRef, queryRef }: Props)
}

const openSeaExternalUrl = useMemo(() => {
if (contract?.contractAddress?.address && tokenId) {
return getOpenseaExternalUrl(contract.contractAddress.address, tokenId);
if (chain && contract?.contractAddress?.address && tokenId) {
return getOpenseaExternalUrl(chain, contract.contractAddress.address, tokenId);
}

return '';
}, [contract?.contractAddress?.address, tokenId]);
}, [chain, contract?.contractAddress?.address, tokenId]);

const handleClick = useCallback(() => {
if (owner?.universal) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { EnsOrAddress } from '~/components/EnsOrAddress';
import { LinkableAddress } from '~/components/LinkableAddress';
import { NftAdditionalDetailsEthFragment$key } from '~/generated/NftAdditionalDetailsEthFragment.graphql';
import { useRefreshMetadata } from '~/scenes/NftDetailPage/NftAdditionalDetails/useRefreshMetadata';
import { extractMirrorXyzUrl } from '~/shared/utils/extractMirrorXyzUrl';
import { getOpenseaExternalUrl, hexHandler } from '~/shared/utils/getOpenseaExternalUrl';

type NftAdditionaDetailsNonPOAPProps = {
Expand All @@ -22,6 +23,8 @@ export function NftAdditionalDetailsEth({ tokenRef }: NftAdditionaDetailsNonPOAP
fragment NftAdditionalDetailsEthFragment on Token {
externalUrl
tokenId
chain
tokenMetadata
contract {
creatorAddress {
address
Expand All @@ -40,17 +43,25 @@ export function NftAdditionalDetailsEth({ tokenRef }: NftAdditionaDetailsNonPOAP
tokenRef
);

const { tokenId, contract, externalUrl } = token;
const { tokenId, contract, externalUrl, tokenMetadata, chain } = token;

const [refresh, isRefreshing] = useRefreshMetadata(token);

const openSeaExternalUrl = useMemo(() => {
if (contract?.contractAddress?.address && tokenId) {
return getOpenseaExternalUrl(contract.contractAddress.address, tokenId);
if (chain && contract?.contractAddress?.address && tokenId) {
return getOpenseaExternalUrl(chain, contract.contractAddress.address, tokenId);
}

return null;
}, [contract?.contractAddress?.address, tokenId]);
}, [chain, contract?.contractAddress?.address, tokenId]);

const mirrorXyzUrl = useMemo(() => {
if (tokenMetadata) {
return extractMirrorXyzUrl(tokenMetadata);
}

return null;
}, [tokenMetadata]);

return (
<VStack gap={16}>
Expand All @@ -76,6 +87,7 @@ export function NftAdditionalDetailsEth({ tokenRef }: NftAdditionaDetailsNonPOAP
)}

<StyledLinkContainer>
{mirrorXyzUrl && <InteractiveLink href={mirrorXyzUrl}>View on Mirror</InteractiveLink>}
{openSeaExternalUrl && (
<>
<InteractiveLink href={openSeaExternalUrl}>View on OpenSea</InteractiveLink>
Expand Down
6 changes: 3 additions & 3 deletions apps/web/src/scenes/NftDetailPage/NftDetailText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,12 @@ function NftDetailText({ tokenRef, queryRef }: Props) {
const horizontalLayout = breakpoint === size.desktop || breakpoint === size.tablet;

const openseaExternalUrl = useMemo(() => {
if (token.contract?.contractAddress?.address && token.tokenId) {
getOpenseaExternalUrl(token.contract.contractAddress.address, token.tokenId);
if (token.chain && token.contract?.contractAddress?.address && token.tokenId) {
getOpenseaExternalUrl(token.chain, token.contract.contractAddress.address, token.tokenId);
}

return '';
}, [token.contract?.contractAddress?.address, token.tokenId]);
}, [token.chain, token.contract?.contractAddress?.address, token.tokenId]);

const handleBuyNowClick = useCallback(() => {
track('Buy Now Button Click', {
Expand Down
18 changes: 18 additions & 0 deletions packages/shared/src/utils/extractMirrorXyz.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { extractMirrorXyzUrl } from './extractMirrorXyzUrl';

function generateData(description: string) {
return `{"animation_url":"https://mirror.xyz/10/0x9fe9f4b985234ff185ecddb980e7567262b71b6f/render","description":"${description}","external_url":"","format":"png","image_url":"ipfs://QmPj5kFNhugP1V7s6yMRJtKSQUagMb2iDcNsKXc2miJpdy","media_type":"png","name":"When the sun hits 3"}`;
}

describe('extractMirrorXyzUrl', () => {
test('extracts correctly', () => {
expect(extractMirrorXyzUrl(generateData('https://mirror.xyz/test/post'))).toEqual(
'https://mirror.xyz/test/post'
);
expect(extractMirrorXyzUrl(generateData('https://mirror.xyz/'))).toEqual('https://mirror.xyz/');
expect(extractMirrorXyzUrl(generateData('https://mirror'))).toEqual('');
expect(extractMirrorXyzUrl(generateData('https://mirror.xzy'))).toEqual('');
expect(extractMirrorXyzUrl(generateData('https://mirror.xyz/posts/235 is the link'))).toEqual('');
expect(extractMirrorXyzUrl(generateData('mirror.xyz'))).toEqual('');
});
});
10 changes: 10 additions & 0 deletions packages/shared/src/utils/extractMirrorXyzUrl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const extractMirrorXyzUrl = (tokenMetadata: string) => {
const metadataObj = JSON.parse(tokenMetadata);
const tokenDesc = metadataObj.description;
const startsWithMirrorXYZ = tokenDesc?.startsWith('https://mirror.xyz');
const hasWhitespaceInMiddle = /\s/.test(tokenDesc);
if (startsWithMirrorXYZ && !hasWhitespaceInMiddle) {
return tokenDesc;
}
return '';
};
9 changes: 7 additions & 2 deletions packages/shared/src/utils/getOpenseaExternalUrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@ export const hexHandler = (str: string) => {
return d;
};

export const getOpenseaExternalUrl = (contractAddress: string, tokenId: string) => {
export const getOpenseaExternalUrl = (
chainStr: string,
contractAddress: string,
tokenId: string
) => {
const chain = chainStr.toLocaleLowerCase();
const hexTokenId = hexHandler(tokenId);

// Allows us to get referral credit
const ref = GALLERY_OS_ADDRESS;

return `https://opensea.io/assets/ethereum/${contractAddress}/${hexTokenId}?ref=${ref}`;
return `https://opensea.io/assets/${chain}/${contractAddress}/${hexTokenId}?ref=${ref}`;
};

1 comment on commit 501699e

@vercel
Copy link

@vercel vercel bot commented on 501699e Jul 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.