Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch Quest Chains from ethers to Viem for Contract Access #1761

Merged
merged 41 commits into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
aa2109f
converting PNGs to WebP 🚁
dysbulic Jul 9, 2024
c353420
replacing `ethers` with Viem for Quest Chains contract access 🪡
dysbulic Jul 9, 2024
6230eb3
displaying ENS name for Quest Chain author 🈴
dysbulic Jul 9, 2024
b07ada6
fixing submission 🏈
dysbulic Jul 9, 2024
e4fec00
adding `onComplete` handler for uploading 🥕
dysbulic Jul 9, 2024
fbeef7f
in the process of upgrading `ethers` to `v6`
dysbulic Jul 9, 2024
d7369f0
trying to upgrade `yarn` b/c `yarn` classic was crapping out 🪇
dysbulic Jul 9, 2024
0dfe315
updating dependencies 🫛
dysbulic Jul 9, 2024
0207ed4
almost running; need to check another branch 🎤
dysbulic Jul 10, 2024
d725c5c
disabled `yarn` PnP 🥏
dysbulic Jul 10, 2024
fa37b69
pushing so I can reinstall my OS 🧙‍♂️
dysbulic Jul 12, 2024
11d9c91
switching to `package.json` import munging from TypeScript `paths` 🥔
dysbulic Jul 15, 2024
4163b66
fixing ERC-20 contract read using WAGMI 👛
dysbulic Jul 15, 2024
235ad17
criminey, much finessing to hopefully cause the test instance to buil…
dysbulic Jul 15, 2024
e7b8c04
moving Markdown component to `design-system` 🧱
dysbulic Jul 15, 2024
7193bbf
upgrading `eslint` 🪢
dysbulic Jul 16, 2024
6b511b1
switching to `yarn workspaces focus` for production dependencies 🔱
dysbulic Jul 16, 2024
09e495e
removing unneeded `node_modules/`? ✊🏻
dysbulic Jul 16, 2024
cb07eff
enable `corepack` for `yarn` `berry` 🪮
dysbulic Jul 16, 2024
a3c3058
fighting with `docker` ⛑️
dysbulic Jul 16, 2024
298c4ef
finagling `package.json` `imports` to work in dev & prod 🥫
dysbulic Jul 18, 2024
9773e46
allowing Discord bot to start w/o credentials 🏺
dysbulic Jul 18, 2024
83e942c
frontend container building & should deploy 🦥
dysbulic Jul 19, 2024
1204ce2
working on auth & fixing all-category playbooks 🍂
dysbulic Jul 19, 2024
ace7ab6
improving login experience 🪴
dysbulic Jul 19, 2024
18addfd
working on relative paths & saving to Ceramic 🧇
dysbulic Jul 25, 2024
b5f28bd
matching [a recent example](https://github.com/ceramicstudio/walletco…
dysbulic Jul 25, 2024
56707ef
debugging Ceramic & winnowing down `ethers` presence 🏎️
dysbulic Jul 25, 2024
a9e45c4
cleaning up save error messages 🌀
dysbulic Jul 25, 2024
34f2279
Merge branch 'develop' into fix/quest-chains-ethers
dysbulic Jul 30, 2024
12d63d6
testing `yarn` install error on GitHub 🐦‍🔥
dysbulic Jul 30, 2024
6701d92
🪆 Merge branch 'fix/quest-chains-ethers' of github.com:MetaFam/TheGam…
dysbulic Jul 30, 2024
f3aa8a4
trying to get `yarn` to not die when installing from GitHub 🥕
dysbulic Jul 30, 2024
3283e13
missed updating `yarn.lock` 🦞
dysbulic Jul 30, 2024
d944743
reenabling EAS & switching `node-ts` to `tsx` 🏚️
dysbulic Aug 13, 2024
f0aec1f
tweaking Discord bot GraphQL codegen 🏔️
dysbulic Aug 13, 2024
36d41d9
tweaking backend GraphQL codegen 🚒
dysbulic Aug 13, 2024
82e4b09
trying DAOHaus v3 Graph endpoint 🚜
dysbulic Aug 13, 2024
207a713
trying DAOHaus Graph endpoint from [the docs]('https://docs.daohaus.c…
dysbulic Aug 13, 2024
7cde476
maybe this Graph will work 🛰️
dysbulic Aug 13, 2024
c509513
making attestations non-conditional 🚤
dysbulic Aug 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Binary file added packages/web/assets/academy/biases.webp
Binary file not shown.
Binary file added packages/web/assets/academy/bridgebuilder.webp
Binary file not shown.
Binary file added packages/web/assets/academy/builder.webp
Binary file not shown.
Binary file added packages/web/assets/academy/coordinape.webp
Binary file not shown.
Binary file added packages/web/assets/academy/daos.webp
Binary file not shown.
Binary file added packages/web/assets/academy/daosummoner.webp
Binary file not shown.
Binary file added packages/web/assets/academy/daowriter.webp
Binary file not shown.
Binary file added packages/web/assets/academy/dapps.webp
Binary file not shown.
Binary file added packages/web/assets/academy/defi.webp
Binary file not shown.
Binary file added packages/web/assets/academy/designer.webp
Binary file not shown.
Binary file not shown.
Binary file added packages/web/assets/academy/ethereum.webp
Binary file not shown.
Binary file added packages/web/assets/academy/gameb.webp
Binary file not shown.
Binary file added packages/web/assets/academy/goodquests.webp
Binary file not shown.
Binary file added packages/web/assets/academy/guilder.webp
Binary file not shown.
Binary file added packages/web/assets/academy/impact-networks.webp
Binary file not shown.
Binary file added packages/web/assets/academy/imposter.webp
Binary file not shown.
Binary file added packages/web/assets/academy/journaling.webp
Binary file not shown.
Binary file added packages/web/assets/academy/master-tabs.webp
Binary file not shown.
Binary file added packages/web/assets/academy/memedriven.webp
Binary file not shown.
Binary file added packages/web/assets/academy/metacrisis.webp
Binary file not shown.
Binary file added packages/web/assets/academy/metamodernist.webp
Binary file not shown.
Binary file added packages/web/assets/academy/moloch.webp
Binary file not shown.
Binary file added packages/web/assets/academy/nfts.webp
Binary file not shown.
Binary file added packages/web/assets/academy/patron.webp
Binary file not shown.
Binary file added packages/web/assets/academy/play-twitter.webp
Binary file not shown.
Binary file not shown.
Binary file added packages/web/assets/academy/player.webp
Binary file not shown.
Binary file added packages/web/assets/academy/riteofpassage.webp
Binary file not shown.
Binary file removed packages/web/assets/academy/submit-playbook.png
Binary file not shown.
Binary file removed packages/web/assets/academy/submit-playbook.webp
Binary file not shown.
Binary file added packages/web/assets/academy/team.webp
Binary file not shown.
Binary file added packages/web/assets/academy/time.webp
Binary file not shown.
Binary file added packages/web/assets/academy/web3builder.webp
Binary file not shown.
76 changes: 43 additions & 33 deletions packages/web/components/QuestChain/MintNFTTile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import {
UseToastOptions,
VStack,
} from '@metafam/ds';
import { contracts, graphql, helpers } from '@quest-chains/sdk';
import { graphql, helpers } from '@quest-chains/sdk';
import { useWeb3 } from 'lib/hooks';
import React, { useCallback, useRef, useState } from 'react';
import { errorHandler } from 'utils/errorHandler';
import {
getQuestChainContract,
QuestChainPlaybooksDetails,
QuestChainType,
useQuestChainContract,
} from 'utils/questChains';

type MintNFTTileProps = {
Expand All @@ -30,10 +30,10 @@ export const MintNFTTile: React.FC<MintNFTTileProps> = ({
completed,
onSuccess,
}) => {
const { provider, chainId, address } = useWeb3();
const { viemClients, chainId, address } = useWeb3();

const toast = useToast();
const toastIdRef = useRef<ToastId | undefined>(undefined);
const toast = useToast({ isClosable: true });
const toastIdRef = useRef<ToastId>();

const addToast = useCallback(
(options: UseToastOptions) => {
Expand All @@ -46,58 +46,68 @@ export const MintNFTTile: React.FC<MintNFTTileProps> = ({
);

const [isMinting, setMinting] = useState(false);
const contract = useQuestChainContract(questChain.address);
const onMint = useCallback(async () => {
if (!chainId || questChain.chainId !== chainId || !address || !provider)
return;
setMinting(true);
addToast({
description:
'Waiting for Confirmation - Confirm the transaction in your Wallet',
duration: null,
isClosable: true,
});
try {
const contract = getQuestChainContract(
questChain.address,
questChain.version,
await provider.getSigner(),
);
if (!chainId || questChain.chainId !== chainId) {
throw new Error(`Wrong chain id: "${chainId}".`);
}
if (!address) {
throw new Error('No client address found.');
}
if (!viemClients?.public) {
throw new Error('Viem public client not initialized.');
}

const tx = await (questChain.version === '0'
? (contract as contracts.V0.QuestChain).mintToken(address)
: (contract as contracts.V1.QuestChain).mintToken());
setMinting(true);
addToast({
description: 'Transaction submitted. Waiting for 1 block confirmation',
description:
'Waiting for Confirmation: Confirm the transaction in your wallet.',
duration: null,
isClosable: true,
});
const receipt = await tx.wait(1);

const txHash = await contract.write.mintToken();
addToast({
description: 'Transaction submitted. Waiting for 1 block confirmation.',
duration: null,
});
const receipt = await viemClients.public.waitForTransactionReceipt({
hash: txHash,
});
addToast({
description:
'Transaction confirmed. Waiting for The Graph to index the transaction data.',
duration: null,
isClosable: true,
});
await helpers.waitUntilSubgraphIndexed(chainId, receipt.blockNumber);
await helpers.waitUntilSubgraphIndexed(
chainId,
Number(receipt.blockNumber),
);
addToast({
description: `Successfully minted your NFT`,
duration: 5000,
isClosable: true,
description: `Successfully minted your NFT.`,
duration: 5_000,
});
onSuccess?.();
} catch (error) {
addToast({
description:
(error as { error?: Error }).error?.message ??
(error as Error).message,
duration: 2000,
isClosable: true,
duration: 7_000,
});
errorHandler(error as Error);
} finally {
setMinting(false);
}
}, [onSuccess, questChain, address, chainId, provider, addToast]);
}, [
chainId,
questChain.chainId,
address,
viemClients?.public,
addToast,
contract.write,
onSuccess,
]);

const details = QuestChainPlaybooksDetails[name];
const image = details?.image;
Expand Down
44 changes: 22 additions & 22 deletions packages/web/components/QuestChain/QuestChainDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,16 @@ import { BsArrowRight, BsCheck } from 'react-icons/bs';
import { QuestChainType } from 'utils/questChains';

type Props = {
inputQuestChain: graphql.QuestChainInfoFragment;
questChain: graphql.QuestChainInfoFragment;
name: QuestChainType;
};

const PageContainer = lazy(() => import('components/Container'));

const QuestChainDisplay: React.FC<Props> = ({ inputQuestChain, name }) => {
const QuestChainDisplay: React.FC<Props> = ({
questChain: inputQuestChain,
name,
}) => {
const { address } = useWeb3();
const { user } = useUser();
const toast = useToast();
Expand Down Expand Up @@ -114,9 +117,8 @@ const QuestChainDisplay: React.FC<Props> = ({ inputQuestChain, name }) => {

const handleQuestClick = (questId: React.SetStateAction<string>) => {
setSelected(questId);
// Check if the markdownViewerRef is set and scroll it into view
if (markdownViewerRef.current !== null) {
(markdownViewerRef.current as any).scrollIntoView({ behavior: 'smooth' });
markdownViewerRef.current.scrollIntoView({ behavior: 'smooth' });
}
};

Expand All @@ -130,7 +132,7 @@ const QuestChainDisplay: React.FC<Props> = ({ inputQuestChain, name }) => {

if (pin.error) {
toast({
title: 'Error pinning quest chain!',
title: 'Error Pinning Quest Chain',
description: pin.error.message,
status: 'error',
duration: 9000,
Expand All @@ -139,15 +141,15 @@ const QuestChainDisplay: React.FC<Props> = ({ inputQuestChain, name }) => {
} else {
setIsPinned(true);
toast({
title: 'Quest Chain pinned!',
title: 'Quest Chain Pinned',
description: (
<chakra.a
href={`https://discord.com/channels/629411177947987986/1045714403351339018`}
target="_blank"
rel="noreferrer"
style={{ textDecoration: 'underline' }}
>
You can now see this quest chain on your Dashboard. Join the
You can now see this Quest Chain on your Dashboard. Join the
conversation on Discord.
</chakra.a>
),
Expand All @@ -168,13 +170,13 @@ const QuestChainDisplay: React.FC<Props> = ({ inputQuestChain, name }) => {
if (user && questChain) {
try {
const pin = await deletePlayerQuestchainPin({
playerId: user?.id,
playerId: user.id,
questchainId: `${questChain.address}-${questChain.name}`,
});

if (pin.error) {
toast({
title: 'Error unpinning quest chain!',
title: 'Error Unpinning Quest Chain',
description: pin.error.message,
status: 'error',
duration: 9000,
Expand All @@ -183,8 +185,7 @@ const QuestChainDisplay: React.FC<Props> = ({ inputQuestChain, name }) => {
} else {
setIsPinned(false);
toast({
title: 'Quest Chain unpinned!',

title: 'Quest Chain Unpinned',
description:
'The quest chain has been removed from your Dashboard.',
status: 'success',
Expand Down Expand Up @@ -218,7 +219,7 @@ const QuestChainDisplay: React.FC<Props> = ({ inputQuestChain, name }) => {
if (!questChain) {
return (
<PageContainer>
<Text> Quest Chain not found! </Text>
<Text>Quest Chain not found!</Text>
</PageContainer>
);
}
Expand All @@ -243,7 +244,7 @@ const QuestChainDisplay: React.FC<Props> = ({ inputQuestChain, name }) => {
href={`https://app.questchains.xyz/profile/${creator}`}
target="_blank"
>
{`${creator?.slice(0, 4)}...${creator?.slice(-2)}`}
{`${creator?.slice(0, 4)}${creator?.slice(-2)}`}
</MetaLink>
</Box>
<Flex
Expand Down Expand Up @@ -279,18 +280,18 @@ const QuestChainDisplay: React.FC<Props> = ({ inputQuestChain, name }) => {
<Box w={{ base: 'full', lg: 338 }} mt={{ base: 5, lg: 0 }}>
{isMobile ? (
<HStack w="full">
<ChainStats progress={progress} isMobile={isMobile} />
<ChainStats {...{ progress, isMobile }} />
<IconButton
variant="outline"
aria-label="Pin"
icon={<Image src={Pin.src} alt="Pin" w={5} h={5} />}
onClick={() => handlePinPlayerQuestchain()}
onClick={handlePinPlayerQuestchain}
isRound
backgroundColor={isPinned ? 'purple.500' : ''}
justifyContent="center"
ml={4}
/>
<Tooltip label="Coming soon">
<Tooltip label="Coming Soon">
<IconButton
variant="outline"
aria-label="Seed"
Expand All @@ -307,9 +308,9 @@ const QuestChainDisplay: React.FC<Props> = ({ inputQuestChain, name }) => {
isRound
justifyContent="center"
onClick={() => {
navigator.clipboard.writeText(`${window.location.href}`);
navigator.clipboard.writeText(window.location.href);
toast({
title: 'Copied to clipboard!',
title: 'Copied to Clipboard',
description: 'Share this link with your friends!',
status: 'success',
duration: 4000,
Expand All @@ -335,7 +336,7 @@ const QuestChainDisplay: React.FC<Props> = ({ inputQuestChain, name }) => {
>
{isPinned ? 'Unpin' : 'Pin'}
</Button>
<Tooltip label="Coming soon">
<Tooltip label="Coming Soon">
<Button
variant="outline"
w="full"
Expand All @@ -354,9 +355,9 @@ const QuestChainDisplay: React.FC<Props> = ({ inputQuestChain, name }) => {
<Image src={Share.src} alt="Share" w={5} h={5} mr={2} />
}
onClick={() => {
navigator.clipboard.writeText(`${window.location.href}`);
navigator.clipboard.writeText(window.location.href);
toast({
title: 'Copied to clipboard!',
title: 'Copied to Clipboard',
description: 'Share this link with your friends!',
status: 'success',
duration: 4000,
Expand All @@ -383,7 +384,6 @@ const QuestChainDisplay: React.FC<Props> = ({ inputQuestChain, name }) => {
<Spinner my={20} />
) : (
<Flex w="full" gap={8} direction={{ base: 'column', md: 'row' }}>
{/* content */}
<Flex
direction="column"
height="fit-content"
Expand Down
Loading
Loading