fixes and clean up

This commit is contained in:
Sero
2024-01-19 08:49:13 -05:00
parent 4585b47423
commit 3f6fb80161
16 changed files with 45 additions and 202 deletions

View File

@@ -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 = () => {
<Flex direction="column" align="center" justify="center" h="17rem">
<Text textAlign="center">
<MetaButton onClick={connect}>Connect</MetaButton>
<Text>to see your pinned Quest Chains</Text>
<Text>to see your pinned Playbooks</Text>
</Text>
</Flex>
);
@@ -59,7 +59,7 @@ export const QuestChainsPinned: React.FC = () => {
return (
<Stack p={6} w="100%" gap={4}>
<Text fontSize="lg" fontWeight="bold" textTransform="uppercase">
Pinned Quest Chains
Pinned Playbooks
</Text>
<Spinner />
</Stack>
@@ -69,7 +69,7 @@ export const QuestChainsPinned: React.FC = () => {
return (
<Stack p={6} w="100%" gap={4}>
<Text fontSize="lg" fontWeight="bold" textTransform="uppercase">
Pinned Quest Chains
Pinned Playbooks
</Text>
{pinnedQuestChains.length > 0 ? (
<Stack spacing={3}>
@@ -107,7 +107,7 @@ export const QuestChainsPinned: React.FC = () => {
</Stack>
) : (
<Text>
You haven't started any Quest Chains yet. Visit the{' '}
You haven't started any Playbooks yet. Visit the{' '}
<MetaLink href="/academy">Academy</MetaLink> to get started!
</Text>
)}

View File

@@ -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<string>;
@@ -187,7 +185,6 @@ export const EditProfileModal: React.FC<EditProfileModalProps> = ({
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<EditProfileModalProps> = ({
</Box>
</FormControl>
</GridItem>
{/* <GridItem flex={1} alignItems="center">
<FormControl isInvalid={!!errors.location}>
<Label htmlFor="location">Location</Label>
<Input
id="location"
w="100%"
placeholder="Laniakea Supercluster"
{...register('location', {
maxLength: {
value: 140,
message: 'Maximum length is 140 characters.',
},
})}
/>
<Box minH="3em">
<FormErrorMessage>
{errors.location?.message?.toString()}
</FormErrorMessage>
</Box>
</FormControl>
</GridItem> */}
{/* <GridItem flex={1} alignItems="center">
<FormControl isInvalid={!!errors.emoji}>
<Label htmlFor="emoji">Spirit Emoji</Label>
<Input
id="emoji"
placeholder="🗽"
_placeholder={{ opacity: 0.75 }}
minW="inherit"
w="100%"
{...register('emoji', {
maxLength: {
value: 2,
message: 'Maximum length is 2 characters.',
},
})}
/>
<Box minH="3em">
<FormErrorMessage>
{errors.emoji?.message?.toString()}
</FormErrorMessage>
</Box>
</FormControl>
</GridItem> */}
<GridItem gridColumn={'1/-1'} alignItems="center">
<FormControl>
<Label>Meeting Calendar</Label>

View File

@@ -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<Props> = ({
const [loading, setLoading] = useState(true);
const [errored, setErrored] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const { w3storage } = useWeb3();
const [watchedFormValues, setWatchedFormValues] =
useState<CreateGuildFormInputs | null>(null);
@@ -173,7 +173,8 @@ export const UnverifiedGuildForm: React.FC<Props> = ({
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<Props> = ({
setIsSubmitting(false);
}
},
[toast, onSubmit, hydratePlayer, addGuildMember, player?.id, addLink],
[toast, onSubmit, hydratePlayer, addGuildMember, player?.id, addLink, w3storage],
);
return (

View File

@@ -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<Optional<string>>(

View File

@@ -140,7 +140,7 @@ const Heading: React.FC<Props> = ({ name, questChain, canMint, refresh }) => (
color="white"
href={`${QUEST_CHAINS_HOST}/chain/${questChain.chainId}/${questChain.address}`}
>
<Tooltip label="View on Quest Chains">
<Tooltip label="View on Playbooks">
<Flex w="full" gap={4} role="group" position="relative">
<Text
fontSize={{ base: '3xl', lg: '7xl' }}

View File

@@ -25,8 +25,8 @@ export const CONFIG = {
ceramicNetwork:
process.env.NEXT_PUBLIC_CERAMIC_NETWORK || 'mainnet' || 'testnet-clay',
googleDataAPIKey: process.env.NEXT_PUBLIC_YOUTUBE_API_KEY,
web3StorageToken: process.env.WEB3_STORAGE_TOKEN,
web3StorageKey: process.env.WEB3_STORAGE_KEY,
web3StorageToken: process.env.NEXT_PUBLIC_WEB3_STORAGE_TOKEN,
web3StorageKey: process.env.NEXT_PUBLIC_WEB3_STORAGE_KEY,
web3StorageDID: process.env.NEXT_PUBLIC_WEB3_STORAGE_DID,
web3StorageProof: process.env.WEB3_STORAGE_PROOF,
openseaAPIKey: process.env.OPENSEA_API_KEY,

View File

@@ -8,6 +8,7 @@ import {
getTokenFromStore,
setTokenInStore,
} from 'lib/auth';
import { useW3upClient } from 'lib/hooks/useW3';
import React, {
createContext,
PropsWithChildren,
@@ -19,7 +20,6 @@ import React, {
import { errorHandler } from 'utils/errorHandler';
import { providerOptions } from 'utils/walletOptions';
import Web3Modal from 'web3modal';
import { useW3upClient } from 'lib/hooks/useW3';
export type Web3ContextType = {
provider: Maybe<Web3Provider>;
@@ -164,7 +164,7 @@ export const Web3ContextProvider: React.FC<Web3ContextProviderOptions> = ({
resetUrqlClient?.();
},
[resetUrqlClient],
[resetUrqlClient, w3storage],
);
const connect = useCallback(async () => {

View File

@@ -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<Maybe<string | ReactElement>>();
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,
],
);

View File

@@ -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<Client | null>(null);

View File

@@ -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<unknown, number, number, 1>);
}
console.debug({ blocks });
return Delegation.importDAG(blocks);
}
export const handler: (
req: NextApiRequest,
res: NextApiResponse<Record<string, string>>,
) => Promise<void> = async (
req: NextApiRequest,
res: NextApiResponse<Record<string, string>>,
) => {
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;

View File

@@ -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());

View File

@@ -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 (

View File

@@ -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) {

View File

@@ -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<Props> = ({
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}`;
}

View File

@@ -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<typeof getStaticProps>;
@@ -29,7 +28,7 @@ const CreateQuestPage: React.FC<Props> = ({
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<Props> = ({
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}`;
}

View File

@@ -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<File>) => {
const client = await getW3SClient();
return client.uploadDirectory(files);
};