From 3f6fb801617f9ae3ea7ee6b8bdb2c9ca93cc4c91 Mon Sep 17 00:00:00 2001 From: Sero <69639595+Seroxdesign@users.noreply.github.com> Date: Fri, 19 Jan 2024 08:49:13 -0500 Subject: [PATCH] fixes and clean up --- .../Dashboard/QuestChainsPinned.tsx | 10 +-- packages/web/components/EditProfileModal.tsx | 47 ----------- .../components/Guild/UnverifiedGuildForm.tsx | 9 ++- .../Player/Profile/EditAvatarImage.tsx | 2 +- .../components/QuestChain/QuestHeading.tsx | 2 +- packages/web/config.ts | 4 +- packages/web/contexts/Web3Context.tsx | 4 +- .../ceramic/usePlayerSetupSaveToComposeDB.ts | 7 +- packages/web/lib/hooks/useW3.ts | 4 +- packages/web/pages/api/w3s-delegation.ts | 77 ------------------- packages/web/pages/api/w3up-client.ts | 15 ++-- packages/web/pages/guild/[guildname]/edit.tsx | 8 +- packages/web/pages/join/guild/[guildname].tsx | 8 +- packages/web/pages/quest/[id]/edit.tsx | 6 +- packages/web/pages/quest/create.tsx | 7 +- packages/web/utils/uploadHelpers.ts | 37 --------- 16 files changed, 45 insertions(+), 202 deletions(-) delete mode 100644 packages/web/pages/api/w3s-delegation.ts delete mode 100644 packages/web/utils/uploadHelpers.ts diff --git a/packages/web/components/Dashboard/QuestChainsPinned.tsx b/packages/web/components/Dashboard/QuestChainsPinned.tsx index b6561e48..36752ff2 100644 --- a/packages/web/components/Dashboard/QuestChainsPinned.tsx +++ b/packages/web/components/Dashboard/QuestChainsPinned.tsx @@ -28,7 +28,7 @@ export const QuestChainsPinned: React.FC = () => { setIsLoading(false); } catch (error) { setIsLoading(false); - console.error('Failed to get pinned quest chains:', error); + console.error('Failed to get pinned Playbooks:', error); } }; if (user?.id) getPinnedQuestChains(user.id); @@ -49,7 +49,7 @@ export const QuestChainsPinned: React.FC = () => { Connect - to see your pinned Quest Chains + to see your pinned Playbooks ); @@ -59,7 +59,7 @@ export const QuestChainsPinned: React.FC = () => { return ( - Pinned Quest Chains + Pinned Playbooks @@ -69,7 +69,7 @@ export const QuestChainsPinned: React.FC = () => { return ( - Pinned Quest Chains + Pinned Playbooks {pinnedQuestChains.length > 0 ? ( @@ -107,7 +107,7 @@ export const QuestChainsPinned: React.FC = () => { ) : ( - You haven't started any Quest Chains yet. Visit the{' '} + You haven't started any Playbooks yet. Visit the{' '} Academy to get started! )} diff --git a/packages/web/components/EditProfileModal.tsx b/packages/web/components/EditProfileModal.tsx index 05445814..1ede319a 100644 --- a/packages/web/components/EditProfileModal.tsx +++ b/packages/web/components/EditProfileModal.tsx @@ -55,7 +55,6 @@ import { errorHandler } from 'utils/errorHandler'; import { getImageDimensions } from 'utils/imageHelpers'; import { isEmpty } from 'utils/objectHelpers'; import { hasuraToComposeDBProfile } from 'utils/playerHelpers'; -import { uploadFiles } from 'utils/uploadHelpers'; import { ConnectToProgress } from './ConnectToProgress'; import { EditAvatarImage } from './Player/Profile/EditAvatarImage'; @@ -63,7 +62,6 @@ import { EditBackgroundImage } from './Player/Profile/EditBackgroundImage'; import { EditDescription } from './Player/Profile/EditDescription'; import { Label } from './Player/Profile/Label'; import MeetWithWalletProfileEdition from './Player/Profile/MeetWithWalletProfileEdition'; -import { useW3upClient } from 'lib/hooks/useW3'; type EditProfileFields = { profileImageURL?: Maybe; @@ -187,7 +185,6 @@ export const EditProfileModal: React.FC = ({ if (Object.keys(pickedFiles).length > 0) { setStatus('Uploading images to web3.storage…'); - //const rootCID = await uploadFiles(Object.values(pickedFiles)); const rootCID = await w3storage?.uploadDirectory(Object.values(pickedFiles)) await Promise.all( Object.entries(pickedFileDataURLs).map(async ([key, val]) => { @@ -500,50 +497,6 @@ export const EditProfileModal: React.FC = ({ - {/* - - - - - - {errors.location?.message?.toString()} - - - - */} - {/* - - - - - - {errors.emoji?.message?.toString()} - - - - */} diff --git a/packages/web/components/Guild/UnverifiedGuildForm.tsx b/packages/web/components/Guild/UnverifiedGuildForm.tsx index 656afcd1..19a6b599 100644 --- a/packages/web/components/Guild/UnverifiedGuildForm.tsx +++ b/packages/web/components/Guild/UnverifiedGuildForm.tsx @@ -27,12 +27,12 @@ import { useAddGuildLinkMutation, useAddGuildMemberMutation, } from 'graphql/autogen/types'; +import { useWeb3 } from 'lib/hooks'; import { useImageReader } from 'lib/hooks/useImageReader'; import React, { useCallback, useState } from 'react'; import { Controller, useForm } from 'react-hook-form'; import { CombinedError } from 'urql'; import { errorHandler } from 'utils/errorHandler'; -import { uploadFile } from 'utils/uploadHelpers'; export type NewUnverifiedGuild = { error?: CombinedError; @@ -131,7 +131,7 @@ export const UnverifiedGuildForm: React.FC = ({ const [loading, setLoading] = useState(true); const [errored, setErrored] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false); - + const { w3storage } = useWeb3(); const [watchedFormValues, setWatchedFormValues] = useState(null); @@ -173,7 +173,8 @@ export const UnverifiedGuildForm: React.FC = ({ if (logoFile?.[0]) { try { - const ipfsHash = await uploadFile(logoFile[0]); + + const ipfsHash = await w3storage?.uploadFile(logoFile[0]) newLogoURL = `ipfs://${ipfsHash}`; } catch (error) { toast({ @@ -253,7 +254,7 @@ export const UnverifiedGuildForm: React.FC = ({ setIsSubmitting(false); } }, - [toast, onSubmit, hydratePlayer, addGuildMember, player?.id, addLink], + [toast, onSubmit, hydratePlayer, addGuildMember, player?.id, addLink, w3storage], ); return ( diff --git a/packages/web/components/Player/Profile/EditAvatarImage.tsx b/packages/web/components/Player/Profile/EditAvatarImage.tsx index a79e9b0d..12fb503a 100644 --- a/packages/web/components/Player/Profile/EditAvatarImage.tsx +++ b/packages/web/components/Player/Profile/EditAvatarImage.tsx @@ -28,7 +28,7 @@ export const EditAvatarImage = forwardRef< >(({ initialURL, onFilePicked }, ref) => { const toast = useToast(); const readFile = useImageReader(); - //const del = useW3upClient('did:key:z6MkgSqgKhSscJfmSWvcBf4DmmRhGHnb5L3E3h4gMbRoA5Cw') + // const del = useW3upClient('did:key:z6MkgSqgKhSscJfmSWvcBf4DmmRhGHnb5L3E3h4gMbRoA5Cw') const [active, setActive] = useState(false); const [loading, setLoading] = useState(true); const [url, setURL] = useState>( diff --git a/packages/web/components/QuestChain/QuestHeading.tsx b/packages/web/components/QuestChain/QuestHeading.tsx index 7c62d04f..d7cee9f9 100644 --- a/packages/web/components/QuestChain/QuestHeading.tsx +++ b/packages/web/components/QuestChain/QuestHeading.tsx @@ -140,7 +140,7 @@ const Heading: React.FC = ({ name, questChain, canMint, refresh }) => ( color="white" href={`${QUEST_CHAINS_HOST}/chain/${questChain.chainId}/${questChain.address}`} > - + ; @@ -164,7 +164,7 @@ export const Web3ContextProvider: React.FC = ({ resetUrqlClient?.(); }, - [resetUrqlClient], + [resetUrqlClient, w3storage], ); const connect = useCallback(async () => { diff --git a/packages/web/lib/hooks/ceramic/usePlayerSetupSaveToComposeDB.ts b/packages/web/lib/hooks/ceramic/usePlayerSetupSaveToComposeDB.ts index 31467249..5d2ed1a6 100644 --- a/packages/web/lib/hooks/ceramic/usePlayerSetupSaveToComposeDB.ts +++ b/packages/web/lib/hooks/ceramic/usePlayerSetupSaveToComposeDB.ts @@ -11,10 +11,10 @@ import { CeramicError } from 'lib/errors'; import { ReactElement, useCallback, useEffect, useState } from 'react'; import { errorHandler } from 'utils/errorHandler'; import { getImageDimensions } from 'utils/imageHelpers'; -import { uploadFile } from 'utils/uploadHelpers'; import { FileReaderData } from '../useImageReader'; import { useUser } from '../useUser'; +import { useWeb3 } from '../useWeb3'; import { useSaveToComposeDB } from './useSaveToComposeDB'; export type PlayerSetupSaveToComposeDBProps = { @@ -32,7 +32,7 @@ export function usePlayerSetupSaveToComposeDB({ const { user } = useUser(); const { onNextPress } = useSetupFlow(); const [status, setStatus] = useState>(); - + const { w3storage } = useWeb3(); const { save: saveToComposeDB, status: saveStatus } = useSaveToComposeDB(); const [, invalidateCache] = useInsertCacheInvalidationMutation(); @@ -62,7 +62,7 @@ export function usePlayerSetupSaveToComposeDB({ const { file, dataURL } = fileData; - const ipfsHash = await uploadFile(file); + const ipfsHash = await w3storage?.uploadFile(file); setStatus('Calculating image metadata…'); @@ -119,6 +119,7 @@ export function usePlayerSetupSaveToComposeDB({ saveToComposeDB, toast, user, + w3storage, ], ); diff --git a/packages/web/lib/hooks/useW3.ts b/packages/web/lib/hooks/useW3.ts index ef63faa9..8a0b70b5 100644 --- a/packages/web/lib/hooks/useW3.ts +++ b/packages/web/lib/hooks/useW3.ts @@ -1,7 +1,7 @@ -import { delegate } from "pages/api/w3up-client"; import { Client } from "@web3-storage/w3up-client"; -import { useState, useEffect } from "react"; import { CONFIG } from "config"; +import { delegate } from "pages/api/w3up-client"; +import { useEffect,useState } from "react"; export function useW3upClient() { const [w3upClient, setW3upClient] = useState(null); diff --git a/packages/web/pages/api/w3s-delegation.ts b/packages/web/pages/api/w3s-delegation.ts deleted file mode 100644 index 0344ea8b..00000000 --- a/packages/web/pages/api/w3s-delegation.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { CarReader } from '@ipld/car'; -import * as DID from '@ipld/dag-ucan/did'; -import * as Delegation from '@ucanto/core/delegation'; -import type { Block } from '@ucanto/interface'; -import { Signer } from '@ucanto/principal/ed25519'; -import * as Client from '@web3-storage/w3up-client'; -import { CONFIG } from 'config'; -import type { NextApiRequest, NextApiResponse } from 'next'; - -async function w3sDelegation(did: string) { - if (!CONFIG.web3StorageKey) { - throw new Error('$WEB3_STORAGE_KEY is not set.'); - } - const principal = Signer.parse(CONFIG.web3StorageKey); - console.debug({ principal }); - const client = await Client.create({ principal }); - - if (!CONFIG.web3StorageProof) { - throw new Error('$WEB3_STORAGE_PROOF is not set.'); - } - const proof = await parseProof(CONFIG.web3StorageProof); - console.debug({ proof }); - const space = await client.addSpace(proof); - await client.setCurrentSpace(space.did()); - console.debug({ space: space.did().toString(), audience: did }) -console.debug('proof parse', proof, space.did()) - const audience = DID.parse(did); - const abilities = ['store/add', 'upload/add']; - const expiration = Math.floor(Date.now() / 1000) + 60 * 60 * 24; // 24 hours from now - const delegation = await client.createDelegation(audience, abilities, { - expiration, - }); - const archive = await delegation.archive(); - console.debug({ archive, ok: archive.ok }); - return archive.ok; -} - -/** @param {string} data Base64 encoded CAR file */ -async function parseProof(proof: string) { - console.debug({ proof }); - const blocks = []; - const reader = await CarReader.fromBytes(Buffer.from(proof, 'base64')); - // eslint-disable-next-line no-restricted-syntax - for await (const block of reader.blocks()) { - blocks.push(block as Block); - } - console.debug({ blocks }); - return Delegation.importDAG(blocks); -} - -export const handler: ( - req: NextApiRequest, - res: NextApiResponse>, -) => Promise = async ( - req: NextApiRequest, - res: NextApiResponse>, -) => { - try { - const { did } = req.body; - if (!did) { - throw new Error('Missing `did` in request body.'); - } - console.debug({ did }); - const ucan = await w3sDelegation(did); - if (!ucan) { - throw new Error(`No UCAN generated for "${did}".`); - } - console.debug({ ucan }); - //@ts-ignore - res.status(201).send(ucan); - } catch (error) { - console.error({ 'error generating W3S UCAN': error }); - res.status(500).json({ error: (error as Error).message }); - } -}; - -export default handler; diff --git a/packages/web/pages/api/w3up-client.ts b/packages/web/pages/api/w3up-client.ts index 409c3cb0..7f6043c1 100644 --- a/packages/web/pages/api/w3up-client.ts +++ b/packages/web/pages/api/w3up-client.ts @@ -1,24 +1,27 @@ -import { DID, CAR } from "@ucanto/core"; +import { CAR,DID } from "@ucanto/core"; import { importDAG } from "@ucanto/core/delegation"; import * as Signer from "@ucanto/principal/ed25519"; -import * as Client from "@web3-storage/w3up-client"; import { StoreMemory } from "@web3-storage/access/stores/store-memory"; +import * as Client from "@web3-storage/w3up-client"; -const principal = Signer.parse("pLEASE FIX ME"); +const principal = process.env.NEXT_PUBLIC_WEB3_STORAGE_KEY && Signer.parse(process.env.NEXT_PUBLIC_WEB3_STORAGE_KEY); const initClient = async () => { + if (!principal) { + throw new Error("WEB3_STORAGE_KEY must be set"); + } // Add proof that this agent has been delegated capabilities on the space const client = await Client.create({ principal, store: new StoreMemory() }); - const space = client.spaces().find((space) => space.name === "metagame"); + const space = client.spaces().find((s) => s.name === "metagame"); if (!space) { - const proof = parseProof("ahhhhh"); + const proof = parseProof(process.env.NEXT_PUBLIC_WEB3_STORAGE_PROOF || ''); const space = await client.addSpace(proof); await client.setCurrentSpace(space.did()); } return client; }; -/**data is a Base64 encoded CAR file */ +/** data is a Base64 encoded CAR file */ function parseProof(data: string) { const car = CAR.decode(Buffer.from(data, "base64")); return importDAG(car.blocks.values()); diff --git a/packages/web/pages/guild/[guildname]/edit.tsx b/packages/web/pages/guild/[guildname]/edit.tsx index 86c218aa..41eae581 100644 --- a/packages/web/pages/guild/[guildname]/edit.tsx +++ b/packages/web/pages/guild/[guildname]/edit.tsx @@ -10,12 +10,12 @@ import { useUpdateGuildMutation, } from 'graphql/autogen/types'; import { getGuild } from 'graphql/queries/guild'; +import { useWeb3 } from 'lib/hooks'; import { useRouter } from 'next/router'; import Page404 from 'pages/404'; import React, { useCallback, useEffect, useState } from 'react'; import useSWR from 'swr'; import { errorHandler } from 'utils/errorHandler'; -import { uploadFile } from 'utils/uploadHelpers'; const EditGuild: React.FC = () => { const router = useRouter(); @@ -25,7 +25,7 @@ const EditGuild: React.FC = () => { const toast = useToast(); const guildNameRouter = router.query.guildname as string; - + const { w3storage } = useWeb3(); const { data: fetchedGuild, isValidating } = useSWR( guildNameRouter, getGuild, @@ -63,7 +63,7 @@ const EditGuild: React.FC = () => { if (logoFile?.[0]) { try { - const ipfsHash = await uploadFile(logoFile[0]); + const ipfsHash = await w3storage?.uploadFile(logoFile[0]); newLogoURL = `ipfs://${ipfsHash}`; } catch (error) { toast({ @@ -142,7 +142,7 @@ const EditGuild: React.FC = () => { }); } }, - [guild, router, toast, updateGuild, addLink], + [guild, router, toast, updateGuild, addLink, w3storage], ); if ( diff --git a/packages/web/pages/join/guild/[guildname].tsx b/packages/web/pages/join/guild/[guildname].tsx index 0ed88363..a62c81a6 100644 --- a/packages/web/pages/join/guild/[guildname].tsx +++ b/packages/web/pages/join/guild/[guildname].tsx @@ -9,11 +9,11 @@ import { useGetGuildQuery, useUpdateGuildMutation, } from 'graphql/autogen/types'; +import { useWeb3 } from 'lib/hooks'; import { useRouter } from 'next/router'; import Page404 from 'pages/404'; import React, { useCallback } from 'react'; import { errorHandler } from 'utils/errorHandler'; -import { uploadFile } from 'utils/uploadHelpers'; const SetupGuild: React.FC = () => { const router = useRouter(); @@ -24,7 +24,7 @@ const SetupGuild: React.FC = () => { const [updateGuildState, updateGuild] = useUpdateGuildMutation(); const [res] = useGetGuildQuery({ variables: { guildname: guildNameRouter } }); const guild = res.data?.guild[0]; - + const { w3storage } = useWeb3(); const onSubmit = useCallback( async (editGuildFormInputs: EditGuildFormInputs) => { if (!guild) return; @@ -50,7 +50,7 @@ const SetupGuild: React.FC = () => { if (logoFile?.[0]) { try { - const ipfsHash = await uploadFile(logoFile[0]); + const ipfsHash = await w3storage?.uploadFile(logoFile[0]); newLogoURL = `ipfs://${ipfsHash}`; } catch (error) { toast({ @@ -130,7 +130,7 @@ const SetupGuild: React.FC = () => { }); } }, - [guild, router, toast, updateGuild, addLink], + [guild, router, toast, updateGuild, addLink, w3storage], ); if (res.fetching || res.data == null) { diff --git a/packages/web/pages/quest/[id]/edit.tsx b/packages/web/pages/quest/[id]/edit.tsx index 7064f717..547afdab 100644 --- a/packages/web/pages/quest/[id]/edit.tsx +++ b/packages/web/pages/quest/[id]/edit.tsx @@ -12,14 +12,13 @@ import { getQuest } from 'graphql/getQuest'; import { getPlayerRoles } from 'graphql/queries/enums/getRoles'; import { getSkills } from 'graphql/queries/enums/getSkills'; import { getGuilds } from 'graphql/queries/guild'; -import { useUser } from 'lib/hooks'; +import { useUser , useWeb3 } from 'lib/hooks'; import { GetStaticPaths, GetStaticPropsContext } from 'next'; import { useRouter } from 'next/router'; import DefaultQuestImage from 'public/assets/QuestsDefaultImage_900x900.jpg'; import React from 'react'; import { transformCooldownForBackend } from 'utils/questHelpers'; import { CategoryOption, parseSkills } from 'utils/skillHelpers'; -import { uploadFile } from 'utils/uploadHelpers'; type Props = { image: string; @@ -38,13 +37,14 @@ const EditQuestPage: React.FC = ({ useUser({ redirectTo: '/quests' }); const router = useRouter(); const toast = useToast(); + const { w3storage } = useWeb3(); const [updateQuestResult, updateQuest] = useUpdateQuestMutation(); const onSubmit = async (data: CreateQuestFormInputs) => { let imageURL = DefaultQuestImage.src; if (data?.image?.[0]) { - const ipfsHash = await uploadFile(data.image[0]); + const ipfsHash = await w3storage?.uploadFile(data.image[0]); imageURL = `ipfs://${ipfsHash}`; } diff --git a/packages/web/pages/quest/create.tsx b/packages/web/pages/quest/create.tsx index f98b938d..f5a6166a 100644 --- a/packages/web/pages/quest/create.tsx +++ b/packages/web/pages/quest/create.tsx @@ -9,14 +9,13 @@ import { import { getPlayerRoles } from 'graphql/queries/enums/getRoles'; import { getSkills } from 'graphql/queries/enums/getSkills'; import { getGuilds } from 'graphql/queries/guild'; -import { useUser } from 'lib/hooks'; +import { useUser , useWeb3 } from 'lib/hooks'; import { InferGetStaticPropsType } from 'next'; import { useRouter } from 'next/router'; import DefaultQuestImage from 'public/assets/QuestsDefaultImage_900x900.jpg'; import React from 'react'; import { transformCooldownForBackend } from 'utils/questHelpers'; import { parseSkills } from 'utils/skillHelpers'; -import { uploadFile } from 'utils/uploadHelpers'; type Props = InferGetStaticPropsType; @@ -29,7 +28,7 @@ const CreateQuestPage: React.FC = ({ const router = useRouter(); const toast = useToast(); const [createQuestState, createQuest] = useCreateQuestMutation(); - + const { w3storage } = useWeb3(); const onSubmit = async (data: CreateQuestFormInputs) => { const { skills, @@ -43,7 +42,7 @@ const CreateQuestPage: React.FC = ({ let imageURL = DefaultQuestImage.src; if (data?.image?.[0]) { - const ipfsHash = await uploadFile(data.image[0]); + const ipfsHash = await w3storage?.uploadFile(data.image[0]); imageURL = `ipfs://${ipfsHash}`; } diff --git a/packages/web/utils/uploadHelpers.ts b/packages/web/utils/uploadHelpers.ts deleted file mode 100644 index e62814f9..00000000 --- a/packages/web/utils/uploadHelpers.ts +++ /dev/null @@ -1,37 +0,0 @@ -import * as Delegation from '@ucanto/core/delegation'; -import * as Client from '@web3-storage/w3up-client'; - -async function getW3SClient() { - const client = await Client.create(); - const response = await fetch('/api/w3s-delegation', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ did: client.did().toString() }), - }); - console.log('response', response) - const raw = await response.arrayBuffer(); - console.log('raw', raw); - const delegation = await Delegation.extract(new Uint8Array(raw)); - console.log('delegation', delegation); - if (!delegation.ok) { - throw new Error('Failed to extract delegation', { - cause: delegation.error, - }); - } - - const space = await client.addSpace(delegation.ok); - client.setCurrentSpace(space.did()); - console.log('space', space); - return client; -} - -export const uploadFile = async (file: File) => { - console.log(file, 'file') - const client = await getW3SClient(); - return client.uploadFile(file); -}; - -export const uploadFiles = async (files: Array) => { - const client = await getW3SClient(); - return client.uploadDirectory(files); -}; \ No newline at end of file