Skip to content

Commit

Permalink
feat(#236): move data fetching to server and add single-step IPNS setup
Browse files Browse the repository at this point in the history
  • Loading branch information
adamazad committed Jan 17, 2023
1 parent 2244af8 commit af3ea79
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 26 deletions.
31 changes: 15 additions & 16 deletions src/components/CreateNimi/CreateNimi.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { useSignMessage } from 'wagmi';

import { usePublishNimiIPNS, useUpdateNimiIPNS } from '../../api/RestAPI/hooks/usePublishNimiIPNS';
import { useUploadImageToIPFS } from '../../api/RestAPI/hooks/useUploadImageToIPFS';
import PlaceholderMini from '../../assets/images/nimi-placeholder.png';
import nimiPlaceholderImage from '../../assets/images/nimi-placeholder.png';
// Partials
import { supportedImageTypes } from '../../constants';
import { useENSPublicResolverContract } from '../../hooks/useENSPublicResolverContract';
Expand Down Expand Up @@ -78,13 +78,7 @@ import { themes } from './themes';
export interface CreateNimiProps {
ensAddress: string;
ensName: string;
/**
* Available themes for the user to choose from
*/
availableThemes: NimiCuratedTheme[];
/**
* The initial Nimi to edit
*/
initialNimi: Nimi;
nimiIPNSKey?: string;
}
Expand Down Expand Up @@ -188,7 +182,7 @@ export function CreateNimi({ ensAddress, ensName, availableThemes, initialNimi,
chainId: 1, // always mainnet
signature,
});
if (!updateNimiResponse || !updateNimiResponse.cidV1) {
if (!updateNimiResponse || !updateNimiResponse.cid) {
throw new Error('No response from updateNimiAsync');
}

Expand All @@ -198,12 +192,13 @@ export function CreateNimi({ ensAddress, ensName, availableThemes, initialNimi,
}

// Publishing a new Nimi IPNS record
const { cidV1, ipns } = await publishNimiAsync({
const { cid, ipns } = await publishNimiAsync({
nimi,
chainId: 1, // always mainnet
chainId: chainId as number,
});

if (!cidV1) {
if (!cid) {
throw new Error('No CID returned from publishNimiViaIPNS');
}

Expand All @@ -222,7 +217,7 @@ export function CreateNimi({ ensAddress, ensName, availableThemes, initialNimi,
}

// Set the content
setPublishNimiResponseIpfsHash(cidV1);
setPublishNimiResponseIpfsHash(cid);
const setContentHashTransaction = await setENSNameContentHash({
contract: publicResolverContract,
name: nimi.ensName,
Expand Down Expand Up @@ -336,7 +331,11 @@ export function CreateNimi({ ensAddress, ensName, availableThemes, initialNimi,
<Toplabel>Profile Picture</Toplabel>
<ProfileImage
src={
customImg ? customImg : formWatchPayload.image?.url ? formWatchPayload.image.url : PlaceholderMini
customImg
? customImg
: formWatchPayload.image?.url
? formWatchPayload.image.url
: nimiPlaceholderImage.src
}
/>
{imgErrorMessage && <ErrorMessage>{imgErrorMessage}</ErrorMessage>}
Expand Down Expand Up @@ -565,10 +564,10 @@ export function CreateNimi({ ensAddress, ensName, availableThemes, initialNimi,
if (nftAsset) {
setValue('image', {
type: NimiImageType.ERC721,
contract: nftAsset.assetContract.address,
tokenId: nftAsset.tokenId as any,
tokenUri: nftAsset.externalLink,
url: nftAsset.imageUrl,
contract: nftAsset.asset_contract.address,
tokenId: nftAsset.token_id as any,
tokenUri: nftAsset.external_link,
url: nftAsset.image_url,
});
}

Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useDefaultNimiData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export function useInitialtNimiData({ ensName, account }: InitialNimiDataProps):
ensName,
]);

debug({ NimiObject: nimiObject });
debug({ nimiObject });

return {
loading: isDepoyedLoading || isGeneratedFetching,
Expand Down
142 changes: 133 additions & 9 deletions src/pages/domains/[domain]/index.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,150 @@
import { Nimi, POAPToken } from '@nimi.io/card/types';
import { GetServerSidePropsContext } from 'next';
import Head from 'next/head';
import { useRouter } from 'next/router';
import { useState } from 'react';

import { fetchUserPOAPs } from '../../../api/RestAPI/hooks/usePoapsFromUser';
import { nimiClient } from '../../../api/RestAPI/utils';
import { Container } from '../../../components/Container';
import { CreateNimi } from '../../../components/CreateNimi';
import { CreateNimiContainer } from '../../../components/CreateNimi/CreateNimiContainer';
import { getAvailableThemesByPOAPs } from '../../../hooks/useAvaliableThemesFromPoaps';
import { PageLayout } from '../../../layout';
import { insertPoapWidgetIntoNimi } from '../../../utils';

export default function CreateNimiPage() {
const router = useRouter();
const { domain } = router.query;
interface NimiSnapshot {
publisher: string;
cid: string | null;
nimi: Nimi;
createdAt: string;
updatedAt: string;
id: string;
}

export async function fetchNimiIPNS(ensName: string) {
const url = `http://127.0.0.1:4002/ens/has-nimi-ipns?domain=${ensName}`;

const rawResponse = await fetch(url, {
method: 'GET',
}).then();

// DOn't render anything on server side
if (typeof window === 'undefined') {
console.log('Server side rendering');
return null;
if (!rawResponse.ok) {
throw new Error('Network response was not ok');
}

const data = (await rawResponse.json()) as {
data: {
ipns?: string;
nimi?: NimiSnapshot;
};
};

return data.data;
}

export async function generateNimiFromENS(ensName: string) {
const { data } = await nimiClient.get<{
data: {
nimi: Nimi;
};
}>(`/nimi/generate`, {
params: {
domain: ensName,
},
});

return data.data;
}

interface CreateNimiPageProps {
availableThemes: ReturnType<typeof getAvailableThemesByPOAPs>;
domain: string;
ipnsKey?: string;
nimiSnapshot?: NimiSnapshot;
initialNimi: Nimi;
poapList: POAPToken[];
}

// This is the page that will be server side rendered
export async function getServerSideProps(
context: GetServerSidePropsContext<{
domain: string;
}>
): Promise<{
props: CreateNimiPageProps;
}> {
let props = {
availableThemes: [],
domain: context?.params?.domain,
initialNimi: {} as Nimi,
poapList: [],
} as CreateNimiPageProps;

try {
if (!context?.params?.domain || context?.params?.domain === '[object Object]') {
throw new Error('No domain provided');
}

const domain = context.params.domain;
// Nimi Snapshot from the API
const nimiIPNSSnapshot = await fetchNimiIPNS(domain);
// If the user has a Nimi IPNS, redirect to the Nimi page
if (nimiIPNSSnapshot.ipns && nimiIPNSSnapshot.nimi) {
props = {
...props,
ipnsKey: nimiIPNSSnapshot.ipns,
nimiSnapshot: nimiIPNSSnapshot.nimi,
initialNimi: nimiIPNSSnapshot.nimi.nimi,
};
} else {
const { nimi } = await generateNimiFromENS(domain);
props['initialNimi'] = nimi;
}

if (!props.initialNimi) {
throw new Error('No Nimi found');
}

// Attempt to load
const poapList = await fetchUserPOAPs(props.initialNimi.ensAddress as string);
const availableThemes = getAvailableThemesByPOAPs(poapList);

if (poapList) {
props = {
...props,
poapList,
availableThemes,
};
}
} catch (e) {
console.log(e);
}
// If the user doesn't have a Nimi IPNS, generate a Nimi from the ENS name
return { props };
}

export default function CreateNimiPage({
domain,
ipnsKey,
initialNimi,
poapList,
availableThemes,
}: Awaited<ReturnType<typeof getServerSideProps>>['props']) {
return (
<>
<Head>
<title>Create Nimi for {domain}</title>
</Head>
<PageLayout>
<CreateNimiContainer ensName={domain as string} />
<Container>
<CreateNimi
ensAddress={initialNimi?.ensAddress as string}
ensName={domain}
availableThemes={availableThemes}
initialNimi={insertPoapWidgetIntoNimi(initialNimi, poapList.length > 0, initialNimi?.ensAddress)}
nimiIPNSKey={ipnsKey}
/>
</Container>
</PageLayout>
</>
);
Expand Down

0 comments on commit af3ea79

Please sign in to comment.