Skip to content

Commit e3c64a7

Browse files
WIP
1 parent 728f99a commit e3c64a7

File tree

7 files changed

+171
-138
lines changed

7 files changed

+171
-138
lines changed

backend/expressServer.js

Lines changed: 66 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ expressServer.js
33
Upload a SVG file to Pinata, get a hash,
44
Update metaData, upload metaData to Pinata
55
*/
6-
const express = require('express');
7-
const axios = require('axios');
8-
const cors = require('cors');
9-
const FormData = require('form-data');
10-
require('dotenv').config();
6+
const express = require("express");
7+
const axios = require("axios");
8+
const cors = require("cors");
9+
const FormData = require("form-data");
10+
require("dotenv").config();
1111

12-
const PINATA_API_KEY = process.env.PINATA_API_KEY || '';
13-
const PINATA_SECRET_API_KEY = process.env.PINATA_SECRET_API_KEY || '';
12+
const PINATA_API_KEY = process.env.PINATA_API_KEY || "";
13+
const PINATA_SECRET_API_KEY = process.env.PINATA_SECRET_API_KEY || "";
1414

1515
const app = express();
1616
app.use(cors());
17-
app.use(express.json({ limit: '50mb' }));
17+
app.use(express.json({ limit: "50mb" }));
1818
const port = 5000;
1919

2020
const metadata = {
@@ -32,58 +32,75 @@ const metadata = {
3232
},
3333
],
3434
};
35-
app.get('/server_status', (req, res) => {
35+
app.get("/server_status", (req, res) => {
3636
const uptime = process.uptime(); // Server uptime in seconds
3737
const status = {
38-
message: 'Server is running',
39-
uptime: `${Math.floor(uptime / 60)} minutes ${Math.floor(uptime % 60)} seconds`
38+
message: "Server is running",
39+
uptime: `${Math.floor(uptime / 60)} minutes ${Math.floor(
40+
uptime % 60
41+
)} seconds`,
4042
};
41-
console.log('Server status check');
43+
console.log("Server status check");
4244
res.json(status);
4345
});
44-
app.post('/server', async (req, res) => {
46+
app.post("/server", async (req, res) => {
4547
try {
46-
// const { name, svgString, description, artistName } = req.body;
47-
// metadata.name = name;
48-
// metadata.description = description;
49-
// metadata.attributes[1].value = artistName;
48+
const { name, svgString, description, artistName } = req.body;
49+
metadata.name = name;
50+
metadata.description = description;
51+
metadata.attributes[1].value = artistName;
5052

51-
// // SVG file, upload to Pinata, get a hash
52-
// const formDataSVG = new FormData();
53-
// formDataSVG.append('file', Buffer.from(svgString), 'image.svg');
54-
// formDataSVG.append('pinataMetadata', JSON.stringify({ name: `Aaarto: ${name}` }));
55-
// formDataSVG.append('pinataOptions', JSON.stringify({ cidVersion: 1 }));
56-
// const response = await axios.post('https://api.pinata.cloud/pinning/pinFileToIPFS', formDataSVG, {
57-
// headers: {
58-
// ...formDataSVG.getHeaders(),
59-
// pinata_api_key: PINATA_API_KEY,
60-
// pinata_secret_api_key: PINATA_SECRET_API_KEY,
61-
// },
62-
// });
63-
// const ipfsHash = response.data.IpfsHash;
53+
// SVG file, upload to Pinata, get a hash
54+
const formDataSVG = new FormData();
55+
formDataSVG.append("file", Buffer.from(svgString), "image.svg");
56+
formDataSVG.append(
57+
"pinataMetadata",
58+
JSON.stringify({ name: `Aaarto: ${name}` })
59+
);
60+
formDataSVG.append("pinataOptions", JSON.stringify({ cidVersion: 1 }));
61+
const response = await axios.post(
62+
"https://api.pinata.cloud/pinning/pinFileToIPFS",
63+
formDataSVG,
64+
{
65+
headers: {
66+
...formDataSVG.getHeaders(),
67+
pinata_api_key: PINATA_API_KEY,
68+
pinata_secret_api_key: PINATA_SECRET_API_KEY,
69+
},
70+
}
71+
);
72+
const ipfsHash = response.data.IpfsHash;
6473

65-
// // Update metadata image field with the retrieved IPFS hash
66-
// metadata.image = `ipfs://${ipfsHash}`;
74+
// Update metadata image field with the retrieved IPFS hash
75+
metadata.image = `ipfs://${ipfsHash}`;
6776

68-
// // MetaData MD, upload to Pintata
69-
// const formDataMD = new FormData();
70-
// const jsonBuffer = Buffer.from(JSON.stringify(metadata));
71-
// formDataMD.append("file", jsonBuffer, "data.json");
72-
// formDataMD.append('pinataMetadata', JSON.stringify({ name: `Aaarto: ${name} metaData` }));
73-
// formDataMD.append('pinataOptions', JSON.stringify({ cidVersion: 1 }));
74-
// const responseMD = await axios.post('https://api.pinata.cloud/pinning/pinFileToIPFS', formDataMD, {
75-
// headers: {
76-
// ...formDataMD.getHeaders(),
77-
// pinata_api_key: PINATA_API_KEY,
78-
// pinata_secret_api_key: PINATA_SECRET_API_KEY,
79-
// },
80-
// });
81-
// const ipfsHashMD = responseMD.data.IpfsHash;
77+
// MetaData MD, upload to Pintata
78+
const formDataMD = new FormData();
79+
const jsonBuffer = Buffer.from(JSON.stringify(metadata));
80+
formDataMD.append("file", jsonBuffer, "data.json");
81+
formDataMD.append(
82+
"pinataMetadata",
83+
JSON.stringify({ name: `Aaarto: ${name} metaData` })
84+
);
85+
formDataMD.append("pinataOptions", JSON.stringify({ cidVersion: 1 }));
86+
const responseMD = await axios.post(
87+
"https://api.pinata.cloud/pinning/pinFileToIPFS",
88+
formDataMD,
89+
{
90+
headers: {
91+
...formDataMD.getHeaders(),
92+
pinata_api_key: PINATA_API_KEY,
93+
pinata_secret_api_key: PINATA_SECRET_API_KEY,
94+
},
95+
}
96+
);
97+
const ipfsHashMD = responseMD.data.IpfsHash;
8298

83-
return res.status(200).json({ ipfsHashMD:"XXX" })
99+
return res.status(200).json({ ipfsHashMD });
84100
} catch (error) {
85-
86-
return res.status(500).json({ error: `${error}Failed to upload to Pinata` });
101+
return res
102+
.status(500)
103+
.json({ error: `${error}Failed to upload to Pinata` });
87104
}
88105
});
89106

src/components/App.tsx

Lines changed: 43 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import Header from "@components/Header";
44
import CanvasControl from "@components/CanvasControl";
55
import TitleControl from "@components/TitleControl";
66
import Message from "./Message";
7-
import MintControl, { MintControlProps } from "./MintControl";
7+
import MintControl from "./MintControl";
88
import { mergeStyleSets } from "@fluentui/react";
99
import AaartoModal from "@components/AaartoModal";
1010
import AboutInfo from "./AboutInfo";
@@ -45,50 +45,43 @@ const App: React.FC = () => {
4545
const [artistName, setArtistName] = useState<string>("");
4646
const [svgString, setSvgString] = useState<string>("");
4747
const [isModalOpen, setIsModalOpen] = useState(false);
48-
const [minting, setMinting] = useState(false);
48+
const [isMinting, setIsMinting] = useState(false);
4949
const [mintingError, setMintingError] = useState<string | null>(null);
50-
const [account, setAccount] = useState(null);
50+
const [account, setAccount] = useState<null | string>(null);
51+
const [transactionHash, setTransactionHash] = useState<string | null>(null);
5152

5253
type ModalContent = "about" | "minting";
5354
const modalContents = {
5455
about: <AboutInfo />,
55-
minting: <MintingInfo mintingError={mintingError} />,
56+
minting: (
57+
<MintingInfo
58+
account={account}
59+
transactionHash={transactionHash}
60+
mintingError={mintingError}
61+
/>
62+
),
5663
};
5764
const [modalContent, setModalContent] = useState<ModalContent>("about");
58-
// const handleUpload = async (): Promise<void> => {
59-
// const ipfsHashMD = await uploadToServer(
60-
// svgString,
61-
// name,
62-
// description,
63-
// artistName
64-
// );
65-
// if (ipfsHashMD) {
66-
// await mintNFT(`ipfs://${ipfsHashMD}`);
67-
// }
68-
// };
69-
// useEffect(() => {
70-
// const a = async () => {
71-
// // Check it MetaMask is installed
72-
// if (typeof window.ethereum === "undefined") {
73-
// throw new Error(errorMessages.notInstalled);
74-
// setM("not installed");
75-
// }
76-
// // Request account access
77-
// setM(errorMessages.accountAccess);
78-
// const userAccount = await window.ethereum.request({
79-
// method: "eth_requestAccounts",
80-
// });
81-
// setM("userAccount: " + userAccount);
82-
// };
83-
// a();
84-
// }, []);
65+
useEffect(() => {
66+
(async () => {
67+
// Check if MetaMask is installed, if not throw error
68+
checkMetaMaskInstall();
69+
// Get the users account
70+
const account = await requestAccounts();
71+
setAccount(account);
72+
})();
73+
}, []);
8574

86-
const useUploadMintV2 = async (
75+
const useUploadMint = async (
8776
svgString: string,
8877
name: string,
8978
description: string,
9079
artistName: string
9180
) => {
81+
setIsMinting(true);
82+
setAccount(null);
83+
setTransactionHash(null);
84+
setMintingError(null);
9285
try {
9386
const ipfsHashMD = await uploadData(
9487
svgString,
@@ -101,19 +94,32 @@ const App: React.FC = () => {
10194
// Get the users account
10295
const account = await requestAccounts();
10396
setAccount(account);
104-
await mintNFT(`ipfs://${ipfsHashMD}`);
97+
const transactionHash = await mintNFT(`ipfs://${ipfsHashMD}`);
98+
if (transactionHash) {
99+
setTransactionHash(transactionHash);
100+
}
101+
setIsMinting(false);
105102
} catch (error: any) {
106103
setMintingError(`Minting Error: ${error.message}`);
107104
}
108105
};
106+
useEffect(() => {
107+
if (!isModalOpen) {
108+
setIsMinting(false);
109+
setMintingError(null);
110+
}
111+
}, [isModalOpen]);
109112
return (
110113
<>
111114
<AaartoModal isModalOpen={isModalOpen} setIsModalOpen={setIsModalOpen}>
112115
{modalContents[modalContent]}
113116
</AaartoModal>
114117
<Header>
115118
<button
116-
onClick={() => setIsModalOpen(true)}
119+
onClick={() => {
120+
setModalContent("about");
121+
setIsModalOpen(true);
122+
}}
117123
className={aboutStyles.button}
118124
>
119125
About
@@ -122,9 +128,9 @@ const App: React.FC = () => {
122128
handleMint={() => {
123129
setModalContent("minting");
124130
setIsModalOpen(true);
125-
useUploadMintV2(svgString, name, description, artistName);
131+
useUploadMint(svgString, name, description, artistName);
126132
}}
127-
isMinting={minting}
133+
isMinting={isMinting}
128134
/>
129135
</Header>
130136
<Canvas
@@ -171,14 +177,7 @@ const App: React.FC = () => {
171177
/>
172178
</label>
173179
</section>
174-
<Message
175-
account={account}
176-
uploading={false}
177-
loading={false}
178-
transactionHash={"x"}
179-
errorMessage={"x"}
180-
uploadError={"x"}
181-
/>
180+
<Message account={account} transactionHash={transactionHash} />
182181
</section>
183182
</>
184183
);

src/components/Message.tsx

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,12 @@
11
import React from "react";
2+
import MintSuccess from "@components/MintSuccess";
23

34
type MessageProps = {
45
account: string | null;
5-
uploading: boolean;
6-
loading: boolean;
76
transactionHash: string | null;
8-
errorMessage: string | null;
9-
uploadError: string | null;
107
};
118

12-
const Message: React.FC<MessageProps> = ({
13-
account,
14-
uploading,
15-
loading,
16-
transactionHash,
17-
errorMessage,
18-
uploadError,
19-
}) => {
9+
const Message: React.FC<MessageProps> = ({ account, transactionHash }) => {
2010
return (
2111
<section>
2212
<section>
@@ -25,24 +15,7 @@ const Message: React.FC<MessageProps> = ({
2515
</h3>
2616
</section>
2717
<section>
28-
{uploading && <p>Status: Uploading</p>}
29-
{loading && <p>Status: Minting</p>}
30-
{transactionHash && (
31-
<p className="success_message">
32-
{/* Minting Success! Transaction Hash: */}
33-
<a
34-
href={`https://polygonscan.com/tx/${transactionHash}`}
35-
target="_blank"
36-
rel="noopener noreferrer"
37-
>
38-
{transactionHash}
39-
</a>
40-
</p>
41-
)}
42-
</section>
43-
<section>
44-
{errorMessage && <p>{errorMessage}</p>}
45-
{uploadError && <p>{uploadError}</p>}
18+
{transactionHash && <MintSuccess transactionHash={transactionHash} />}
4619
</section>
4720
</section>
4821
);

src/components/MintSuccess.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import React = require("react");
2+
3+
type MintSuccessProps = {
4+
transactionHash: string;
5+
};
6+
const MintSuccess: React.FC<MintSuccessProps> = ({ transactionHash }) => {
7+
return (
8+
<section>
9+
<h3>Minting Success!</h3>
10+
<p className="success_message">
11+
<a
12+
href={`https://polygonscan.com/tx/${transactionHash}`}
13+
target="_blank"
14+
rel="noopener noreferrer"
15+
>
16+
{transactionHash}
17+
</a>
18+
</p>
19+
</section>
20+
);
21+
};
22+
23+
export default MintSuccess;

0 commit comments

Comments
 (0)