From 9db445acf8954fcc5c84a3ad5d5678d8d4ba7813 Mon Sep 17 00:00:00 2001 From: lilnounsDAO Date: Tue, 4 Feb 2025 01:26:48 +0000 Subject: [PATCH] hotfix for rendering nouns with traits missing from nouns/assets --- .../src/components/StandaloneNoun/index.tsx | 17 ++++++++++++++++- packages/nouns-webapp/src/wrappers/nounToken.ts | 13 ++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/packages/nouns-webapp/src/components/StandaloneNoun/index.tsx b/packages/nouns-webapp/src/components/StandaloneNoun/index.tsx index 6f8db1d7c2..e4765a1535 100644 --- a/packages/nouns-webapp/src/components/StandaloneNoun/index.tsx +++ b/packages/nouns-webapp/src/components/StandaloneNoun/index.tsx @@ -1,7 +1,7 @@ import { ImageData as data, getNounData } from '@nouns/assets'; import { buildSVG } from '@nouns/sdk'; import { BigNumber as EthersBN } from 'ethers'; -import { INounSeed, useNounSeed } from '../../wrappers/nounToken'; +import { INounSeed, useGenerateSVGImage, useNounSeed } from '../../wrappers/nounToken'; import Noun from '../Noun'; import { Link } from 'react-router-dom'; import classes from './StandaloneNoun.module.css'; @@ -29,6 +29,21 @@ export const getNoun = (nounId: string | EthersBN, seed: INounSeed) => { const name = `Noun ${id}`; const description = `Noun ${id} is a member of the Nouns DAO`; const { parts, background } = getNounData(seed); + + // eslint-disable-next-line react-hooks/rules-of-hooks + const svg = useGenerateSVGImage(seed); + + // if some parts are undefined, call nounsDescriptor.generateSVGImage and return the image + if (parts.some(part => part === undefined)) { + + return { + name, + description, + image: `data:image/svg+xml;base64,${svg}` + }; + + } + const image = `data:image/svg+xml;base64,${btoa(buildSVG(parts, data.palette, background))}`; return { diff --git a/packages/nouns-webapp/src/wrappers/nounToken.ts b/packages/nouns-webapp/src/wrappers/nounToken.ts index 36f6f2314e..aa96c6dc56 100644 --- a/packages/nouns-webapp/src/wrappers/nounToken.ts +++ b/packages/nouns-webapp/src/wrappers/nounToken.ts @@ -1,6 +1,6 @@ import { useContractCall, useContractFunction, useEthers } from '@usedapp/core'; import { BigNumber as EthersBN, ethers, utils } from 'ethers'; -import { NounsTokenABI, NounsTokenFactory } from '@nouns/contracts'; +import { NounsDescriptorABI, NounsTokenABI, NounsTokenFactory } from '@nouns/contracts'; import config, { cache, cacheKey, CHAIN_ID } from '../config'; import { useQuery } from '@apollo/client'; import { @@ -42,6 +42,7 @@ export enum NounsTokenContractFunction { } const abi = new utils.Interface(NounsTokenABI); +const descriptorAbi = new utils.Interface(NounsDescriptorABI); const seedCacheKey = cacheKey(cache.seed, CHAIN_ID, config.addresses.nounsToken); const nounsTokenContract = NounsTokenFactory.connect(config.addresses.nounsToken, undefined!); const isSeedValid = (seed: Record | undefined) => { @@ -130,6 +131,16 @@ export const useNounSeed = (nounId: EthersBN): INounSeed => { return seed; }; +export const useGenerateSVGImage = (seed: INounSeed) => { + const image = useContractCall({ + abi: descriptorAbi, + address: config.addresses.nounsDescriptor, + method: 'generateSVGImage', + args: [seed], + }); + return image; +}; + export const useUserVotes = (): number | undefined => { const { account } = useEthers(); return useAccountVotes(account ?? ethers.constants.AddressZero);