From d9e719547cc729e624baeecaf5d3d0537a2962f9 Mon Sep 17 00:00:00 2001
From: yawn <69970183+yawn-c111@users.noreply.github.com>
Date: Tue, 3 Dec 2024 12:31:35 +0900
Subject: [PATCH 1/3] fix: IPFS upload
---
pkgs/frontend/.env.example | 4 +-
pkgs/frontend/app/routes/_index.tsx | 79 +++++++++++++++++++++--------
pkgs/frontend/hooks/useIpfs.ts | 68 ++++++++++++++++---------
pkgs/frontend/utils/ipfs.ts | 46 +++++++++++++++++
4 files changed, 151 insertions(+), 46 deletions(-)
create mode 100644 pkgs/frontend/utils/ipfs.ts
diff --git a/pkgs/frontend/.env.example b/pkgs/frontend/.env.example
index b1024c6..86c625b 100644
--- a/pkgs/frontend/.env.example
+++ b/pkgs/frontend/.env.example
@@ -12,4 +12,6 @@ VITE_SPLITS_CREATOR_ADDRESS=0x9c3648df4bb82fdf067a9b083900a986f9b27e9a
VITE_PIMLICO_API_KEY=
-VITE_PINATA_JWT=
\ No newline at end of file
+VITE_PINATA_JWT=
+
+VITE_PINATA_GATEWAY=
\ No newline at end of file
diff --git a/pkgs/frontend/app/routes/_index.tsx b/pkgs/frontend/app/routes/_index.tsx
index cdcf4ba..b5c4880 100644
--- a/pkgs/frontend/app/routes/_index.tsx
+++ b/pkgs/frontend/app/routes/_index.tsx
@@ -1,7 +1,11 @@
-import { Box } from "@chakra-ui/react";
+import { Box, Input } from "@chakra-ui/react";
import type { MetaFunction } from "@remix-run/node";
import { CommonButton } from "~/components/CommonButton";
import { useBigBang } from "hooks/useBigBang";
+import {
+ useUploadMetadataToIpfs,
+ useUploadImageFileToIpfs,
+} from "hooks/useIpfs";
export const meta: MetaFunction = () => {
return [
@@ -11,26 +15,61 @@ export const meta: MetaFunction = () => {
};
export default function Index() {
- const { bigbang, isLoading } = useBigBang();
+ const { bigbang, isLoading } = useBigBang();
+ const { uploadMetadataToIpfs, isLoading: isUploadingMetadataToIpfs } =
+ useUploadMetadataToIpfs();
+ const {
+ uploadImageFileToIpfs,
+ setImageFile,
+ isLoading: isUploadingImageFileToIpfs,
+ } = useUploadImageFileToIpfs();
- const handleBigBang = async () => {
- const res = await bigbang({
- owner: "0xdCb93093424447bF4FE9Df869750950922F1E30B",
- topHatDetails: "Top Hat Details",
- topHatImageURI: "https://example.com/top-hat.png",
- hatterHatDetails: "Hatter Hat Details",
- hatterHatImageURI: "https://example.com/hatter-hat.png",
- trustedForwarder: "0x1234567890123456789012345678901234567890",
- });
+ const handleBigBang = async () => {
+ const res = await bigbang({
+ owner: "0xdCb93093424447bF4FE9Df869750950922F1E30B",
+ topHatDetails: "Top Hat Details",
+ topHatImageURI: "https://example.com/top-hat.png",
+ hatterHatDetails: "Hatter Hat Details",
+ hatterHatImageURI: "https://example.com/hatter-hat.png",
+ trustedForwarder: "0x1234567890123456789012345678901234567890",
+ });
- console.log(res);
- };
+ console.log(res);
+ };
- return (
-
-
- BigBang
-
-
- );
+ const metadata = {
+ name: "Toban test",
+ description: "Toban test",
+ responsibilities: "Toban test",
+ authorities: "Toban test",
+ eligibility: true,
+ toggle: true,
+ };
+
+ return (
+
+
+ BigBang
+
+ uploadMetadataToIpfs(metadata)}
+ >
+ Upload Metadata to IPFS
+
+ ) =>
+ setImageFile(e.target.files?.[0] || null)
+ }
+ />
+
+ Upload Image File to IPFS
+
+
+ );
}
diff --git a/pkgs/frontend/hooks/useIpfs.ts b/pkgs/frontend/hooks/useIpfs.ts
index 127c718..6b18ffa 100644
--- a/pkgs/frontend/hooks/useIpfs.ts
+++ b/pkgs/frontend/hooks/useIpfs.ts
@@ -1,9 +1,9 @@
import { useState } from "react";
-import { PinataSDK } from "pinata-web3";
-import { Readable } from "stream";
+import { ipfsUploadJson, ipfsUploadFile } from "utils/ipfs";
export const useUploadMetadataToIpfs = () => {
const [isLoading, setIsLoading] = useState(false);
+ const [error, setError] = useState(null);
const uploadMetadataToIpfs = async ({
name,
@@ -19,13 +19,12 @@ export const useUploadMetadataToIpfs = () => {
authorities: string;
eligibility: boolean;
toggle: boolean;
- }) => {
+ }): Promise<{ ipfsCid: string; ipfsUri: string } | null> => {
setIsLoading(true);
+ setError(null);
try {
- const pinata = new PinataSDK({ pinataJwt: process.env.VITE_PINATA_JWT });
-
- const upload = await pinata.upload.json({
+ const upload = await ipfsUploadJson({
type: "1.0",
data: {
name,
@@ -37,45 +36,64 @@ export const useUploadMetadataToIpfs = () => {
},
});
- console.log("CID:", upload.IpfsHash);
- console.log("URI:", `ipfs://${upload.IpfsHash}`);
- } catch (error) {
- console.error(error);
+ const ipfsCid = upload.IpfsHash;
+ const ipfsUri = `ipfs://${ipfsCid}`;
+
+ console.log("Successfully uploaded metadata to IPFS");
+ console.log("IPFS CID:", ipfsCid);
+ console.log("IPFS URI:", ipfsUri);
+
+ return { ipfsCid, ipfsUri };
+ } catch (err) {
+ setError(
+ err instanceof Error ? err : new Error("Unknown error occurred")
+ );
+ return null;
} finally {
setIsLoading(false);
}
};
- return { uploadMetadataToIpfs, isLoading };
+ return { uploadMetadataToIpfs, isLoading, error };
};
-export const useUploadImageToIpfs = () => {
+export const useUploadImageFileToIpfs = () => {
const [isLoading, setIsLoading] = useState(false);
const [imageFile, setImageFile] = useState(null);
+ const [error, setError] = useState(null);
- const uploadImageToIpfs = async () => {
- if (!imageFile) return;
+ const uploadImageFileToIpfs = async (): Promise<{
+ ipfsCid: string;
+ ipfsUri: string;
+ } | null> => {
+ if (!imageFile || !imageFile.type.startsWith("image/")) {
+ setError(new Error("Invalid or no image file selected"));
+ return null;
+ }
setIsLoading(true);
+ setError(null);
try {
- const pinata = new PinataSDK({ pinataJwt: process.env.VITE_PINATA_JWT });
+ const upload = await ipfsUploadFile(imageFile);
- const buffer = await imageFile.arrayBuffer();
- const stream = Readable.from(Buffer.from(buffer));
+ const ipfsCid = upload.IpfsHash;
+ const ipfsUri = `ipfs://${ipfsCid}`;
- const upload = await pinata.upload.stream(stream, {
- metadata: { name: `TobanFrontend_${new Date().getTime()}` },
- });
+ console.log("Successfully uploaded image file to IPFS");
+ console.log("IPFS CID:", ipfsCid);
+ console.log("IPFS URI:", ipfsUri);
- console.log("CID:", upload.IpfsHash);
- console.log("URI:", `ipfs://${upload.IpfsHash}`);
- } catch (error) {
- console.error(error);
+ return { ipfsCid, ipfsUri };
+ } catch (err) {
+ setError(
+ err instanceof Error ? err : new Error("Unknown error occurred")
+ );
+ return null;
} finally {
setIsLoading(false);
}
};
- return { uploadImageToIpfs, setImageFile, isLoading };
+ return { uploadImageFileToIpfs, imageFile, setImageFile, isLoading, error };
};
diff --git a/pkgs/frontend/utils/ipfs.ts b/pkgs/frontend/utils/ipfs.ts
new file mode 100644
index 0000000..690f734
--- /dev/null
+++ b/pkgs/frontend/utils/ipfs.ts
@@ -0,0 +1,46 @@
+import { PinataSDK } from "pinata-web3";
+
+const validateEnvVariables = () => {
+ if (!import.meta.env.VITE_PINATA_JWT) {
+ throw new Error("VITE_PINATA_JWT is not defined");
+ }
+ if (!import.meta.env.VITE_PINATA_GATEWAY) {
+ throw new Error("VITE_PINATA_GATEWAY is not defined");
+ }
+};
+
+let ipfsClient: PinataSDK | null = null;
+
+export const createIpfsClient = () => {
+ if (ipfsClient) return ipfsClient;
+
+ validateEnvVariables();
+ ipfsClient = new PinataSDK({
+ pinataJwt: import.meta.env.VITE_PINATA_JWT as string,
+ pinataGateway: import.meta.env.VITE_PINATA_GATEWAY as string,
+ });
+
+ return ipfsClient;
+};
+
+export const ipfsUploadJson = async (object: object) => {
+ try {
+ const ipfsClient = createIpfsClient();
+ const upload = await ipfsClient.upload.json(object);
+ return upload;
+ } catch (error) {
+ console.error("Failed to upload JSON to IPFS:", error);
+ throw error;
+ }
+};
+
+export const ipfsUploadFile = async (file: File) => {
+ try {
+ const ipfsClient = createIpfsClient();
+ const upload = await ipfsClient.upload.file(file);
+ return upload;
+ } catch (error) {
+ console.error("Failed to upload file to IPFS:", error);
+ throw error;
+ }
+};
From 56da258fa5c4529b24db10922edb7dabde970a5d Mon Sep 17 00:00:00 2001
From: yawn <69970183+yawn-c111@users.noreply.github.com>
Date: Tue, 3 Dec 2024 12:37:31 +0900
Subject: [PATCH 2/3] fix: conflict fix mistake in _idex.tsx
---
pkgs/frontend/app/routes/_index.tsx | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/pkgs/frontend/app/routes/_index.tsx b/pkgs/frontend/app/routes/_index.tsx
index ad01d41..dabd1c3 100644
--- a/pkgs/frontend/app/routes/_index.tsx
+++ b/pkgs/frontend/app/routes/_index.tsx
@@ -24,15 +24,6 @@ export default function Index() {
isLoading: isUploadingImageFileToIpfs,
} = useUploadImageFileToIpfs();
- const handleBigBang = async () => {
- const res = await bigbang({
- owner: "0xdCb93093424447bF4FE9Df869750950922F1E30B",
- topHatDetails: "Top Hat Details",
- topHatImageURI: "https://example.com/top-hat.png",
- hatterHatDetails: "Hatter Hat Details",
- hatterHatImageURI: "https://example.com/hatter-hat.png",
- trustedForwarder: "0x1234567890123456789012345678901234567890",
- });
const handleBigBang = async () => {
const res = await bigbang({
owner: "0xdCb93093424447bF4FE9Df869750950922F1E30B",
From 4c0825c764ad9cb1ec6a429f865e46529f7c9f9d Mon Sep 17 00:00:00 2001
From: yawn <69970183+yawn-c111@users.noreply.github.com>
Date: Tue, 3 Dec 2024 12:49:16 +0900
Subject: [PATCH 3/3] refactor: get pinata config
---
pkgs/frontend/utils/ipfs.ts | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/pkgs/frontend/utils/ipfs.ts b/pkgs/frontend/utils/ipfs.ts
index 690f734..d22d008 100644
--- a/pkgs/frontend/utils/ipfs.ts
+++ b/pkgs/frontend/utils/ipfs.ts
@@ -1,12 +1,17 @@
import { PinataSDK } from "pinata-web3";
-const validateEnvVariables = () => {
- if (!import.meta.env.VITE_PINATA_JWT) {
+const getPinataConfig = () => {
+ const pinataJwt = import.meta.env.VITE_PINATA_JWT;
+ const pinataGateway = import.meta.env.VITE_PINATA_GATEWAY;
+
+ if (!pinataJwt) {
throw new Error("VITE_PINATA_JWT is not defined");
}
- if (!import.meta.env.VITE_PINATA_GATEWAY) {
+ if (!pinataGateway) {
throw new Error("VITE_PINATA_GATEWAY is not defined");
}
+
+ return { pinataJwt, pinataGateway };
};
let ipfsClient: PinataSDK | null = null;
@@ -14,10 +19,10 @@ let ipfsClient: PinataSDK | null = null;
export const createIpfsClient = () => {
if (ipfsClient) return ipfsClient;
- validateEnvVariables();
+ const { pinataJwt, pinataGateway } = getPinataConfig();
ipfsClient = new PinataSDK({
- pinataJwt: import.meta.env.VITE_PINATA_JWT as string,
- pinataGateway: import.meta.env.VITE_PINATA_GATEWAY as string,
+ pinataJwt,
+ pinataGateway,
});
return ipfsClient;