Skip to content

Commit 7bb13aa

Browse files
committed
tutorial finished.
1 parent 792ca0b commit 7bb13aa

24 files changed

Lines changed: 2393 additions & 132 deletions

frontend/components/content.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
import React from 'react';
3+
4+
export default function Content({ children }: { children: React.ReactNode }) {
5+
return (
6+
<div className="container px-4 mx-auto">
7+
<main className="pt-4">{children}</main>
8+
</div>
9+
);
10+
}

frontend/components/layout.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
import React from 'react';
3+
4+
export default function Layout({ children }: { children: React.ReactNode }) {
5+
return (
6+
<div className="container px-4 mx-auto">
7+
<main className="pt-4">{children}</main>
8+
</div>
9+
);
10+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"TutorialToken": "0x5FbDB2315678afecb367f032d93F642f64180aa3"
2+
"TutorialToken": "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6"
33
}

frontend/hooks/useAllowList.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { db } from '../lib/firebase';
2+
import { doc, setDoc } from "firebase/firestore";
3+
4+
type useAllowListType = () => {
5+
sendRequestAllowList: (address: string, mailaddress: string) => Promise<void>;
6+
}
7+
8+
export const useAllowList: useAllowListType = () => {
9+
async function sendRequestAllowList(address: string, mailaddress: string): Promise<void> {
10+
await setDoc(doc(db, "allowList", address), {
11+
address,
12+
mailaddress,
13+
});
14+
}
15+
16+
return {
17+
sendRequestAllowList,
18+
}
19+
};
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { useModal } from 'react-hooks-use-modal';
2+
import React from 'react';
3+
import { useAllowList } from '../hooks/useAllowList';
4+
5+
export const useRequestAllowListFormModal= () => {
6+
const [Modal, open, close, isOpen] = useModal('__next');
7+
const { sendRequestAllowList } = useAllowList();
8+
9+
const modalStyle: React.CSSProperties = {
10+
backgroundColor: '#fff',
11+
padding: '60px 100px',
12+
borderRadius: '10px',
13+
};
14+
15+
async function onSubmit(e: React.FormEvent<HTMLFormElement>) {
16+
e.preventDefault();
17+
const target = e.target as typeof e.target & {
18+
address: { value: string };
19+
email: { value: string };
20+
};
21+
const address = target.address.value;
22+
const email = target.email.value;
23+
await sendRequestAllowList(address, email);
24+
close();
25+
};
26+
27+
function RequestAllowListFormModal() {
28+
return (
29+
<Modal>
30+
<div style={modalStyle}>
31+
<form onSubmit={onSubmit} className="flex flex-col">
32+
<input id="address" type="text" placeholder="Address" className="p-2 border rounded soild"/>
33+
<input id="email" type="text" placeholder="hogemoge@example.com" className="p-2 mt-4 border rounded solid" />
34+
<button className="p-2 mt-4 text-white bg-blue-400 border border-solid rounded">申し込み</button>
35+
</form>
36+
</div>
37+
</Modal>
38+
);
39+
}
40+
return {
41+
RequestAllowListFormModal,
42+
openRequestAllowListFormModal: open,
43+
closeRequestAllowListFormModal: close,
44+
}
45+
}

frontend/hooks/useTutorialToken.ts

Lines changed: 85 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
11
import { ethers } from "ethers";
22
import TutorialTokenArtifact from "../contracts/TutorialToken.json";
33
import contractAddress from "../contracts/contract-address.json";
4-
import { useState } from "react";
4+
import { db } from '../lib/firebase';
5+
import { doc, getDocs, query, collection } from "firebase/firestore";
6+
import { StandardMerkleTree } from "@openzeppelin/merkle-tree";
57

68
type useTutorialTokenReturnType = () => {
7-
mint: () => Promise<string>;
8-
getBalance: () => Promise<number>;
9-
ownerOf: () => Promise<number>;
9+
preMint: (address: string, callBack: () => {}) => Promise<void>;
10+
publicMint: (callBack: () => {}) => Promise<void>;
11+
totalSuply: () => Promise<number>;
12+
tokenOfOwnerByIndex: () => Promise<number>;
13+
getTokenIdList: () => Promise<number[]>;
14+
setPreSale: (preSale: boolean) => Promise<void>;
15+
setPublicSale: (publicSale: boolean) => Promise<void>;
1016
}
1117

1218
export const useTutorialToken: useTutorialTokenReturnType = () => {
13-
// const [provider, setProvider] = useState<ethers.providers.Web3Provider|null>(null);
14-
// const [token, setToken] = useState<ethers.Contract|null>(null);
1519
let provider: ethers.providers.Web3Provider|null = null;
1620
let token: ethers.Contract|null = null;
1721

1822
async function _initializeEthers() {
1923
provider = new ethers.providers.Web3Provider(window.ethereum);
20-
// console.log(_provider);
21-
// setProvider(_provider);
22-
console.log(provider);
2324

2425
token = await new ethers.Contract(
2526
contractAddress.TutorialToken,
@@ -29,30 +30,81 @@ export const useTutorialToken: useTutorialTokenReturnType = () => {
2930
console.log(token);
3031
}
3132

33+
async function preMint(address: string, callBack: () => {}): Promise<void> {
34+
if (token === null && provider === null) await _initializeEthers();
35+
const q = query(collection(db, "allowList"));
36+
const querySnapshot = await getDocs(q);
37+
const treeValues = [];
38+
querySnapshot.forEach((doc) => {
39+
const data = doc.data();
40+
data.address && treeValues.push([data.address]);
41+
});
42+
const tree = StandardMerkleTree.of(treeValues, ["address"]);
43+
let proof: string[]|undefined;
44+
for (const [i, v] of tree.entries()) {
45+
if (v[0] === address) {
46+
proof = tree.getProof(i);
47+
}
48+
}
49+
console.log(proof);
50+
const transaction = await token.preMint(proof);
51+
const res = await transaction.wait();
52+
console.log(res);
53+
callBack();
54+
}
55+
56+
async function publicMint(callBack: () => {}): Promise<void> {
57+
if (token === null && provider === null) await _initializeEthers();
58+
const transaction = await token.mint();
59+
const res = await transaction.wait();
60+
console.log(res);
61+
callBack();
62+
}
63+
64+
async function totalSuply(): Promise<number> {
65+
if (token === null && provider === null) await _initializeEthers();
66+
const totalSuply = await token.totalSupply();
67+
console.log(totalSuply);
68+
return totalSuply.toNumber();
69+
}
70+
71+
async function tokenOfOwnerByIndex(): Promise<number> {
72+
if (token === null && provider === null) await _initializeEthers();
73+
const address = await provider.getSigner().getAddress();
74+
const count = await token.tokenOfOwnerByIndex(address, 1);
75+
console.log('tokenOfOwnerByIndex', count.toNumber());
76+
return count.toNumber();
77+
}
78+
79+
async function getTokenIdList(): Promise<number[]> {
80+
if (token === null && provider === null) await _initializeEthers();
81+
const address = await provider.getSigner().getAddress();
82+
const count = await token.balanceOf(address);
83+
const tokenIdList = [];
84+
for (let i = 0; i < count.toNumber(); i++) {
85+
const tokenId = await token.tokenOfOwnerByIndex(address, i);
86+
tokenIdList.push(tokenId.toNumber());
87+
}
88+
return tokenIdList;
89+
}
90+
91+
async function setPreSale(preSale: boolean): Promise<void> {
92+
if (token === null && provider === null) await _initializeEthers();
93+
await token.setPreSale(preSale);
94+
}
95+
96+
async function setPublicSale(publicSale: boolean): Promise<void> {
97+
if (token === null && provider === null) await _initializeEthers();
98+
await token.setPublicSale(publicSale);
99+
}
100+
32101
return {
33-
mint: async () => {
34-
await _initializeEthers();
35-
const res = await token.mint();
36-
console.log(res);
37-
const receipt = await res?.wait();
38-
console.log(receipt);
39-
// return tokenId;
40-
return 'hogehoge';
41-
},
42-
43-
ownerOf: async () => {
44-
if (token === null && provider === null) await _initializeEthers();
45-
const address = await token.ownerOf(1);
46-
console.log(address);
47-
},
48-
49-
getBalance: async () => {
50-
if (token === null && provider === null) await _initializeEthers();
51-
const address = await provider.getSigner().getAddress();
52-
console.log(address);
53-
const balance = await token.hoge();
54-
console.log(balance);
55-
return 1;
56-
},
102+
preMint,
103+
publicMint,
104+
totalSuply,
105+
tokenOfOwnerByIndex,
106+
getTokenIdList,
107+
setPreSale,
108+
setPublicSale,
57109
}
58110
};

frontend/lib/firebase.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Import the functions you need from the SDKs you need
2+
import { initializeApp } from "firebase/app";
3+
import { getFirestore } from 'firebase/firestore';
4+
5+
const firebaseConfig = {};
6+
7+
// Initialize Firebase
8+
const app = initializeApp(firebaseConfig);
9+
const db = getFirestore(app);
10+
11+
export { app, db };

frontend/package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,19 @@
66
"start": "next start"
77
},
88
"dependencies": {
9+
"@openzeppelin/merkle-tree": "^1.0.1",
910
"ethers": "^5.7.2",
11+
"firebase": "^9.15.0",
1012
"next": "latest",
1113
"react": "18.2.0",
1214
"react-dom": "18.2.0",
13-
"autoprefixer": "^10.4.13",
14-
"postcss": "^8.4.20"
15+
"react-hooks-use-modal": "^3.2.0"
1516
},
1617
"devDependencies": {
1718
"@types/node": "^18.11.15",
1819
"@types/react": "^18.0.26",
20+
"autoprefixer": "^10.4.13",
21+
"postcss": "^8.4.20",
1922
"sass": "^1.56.2",
2023
"tailwindcss": "^3.2.4",
2124
"typescript": "^4.9.4"

frontend/pages/_app.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import '../styles/globals.css'
2+
import type { AppProps } from 'next/app'
3+
4+
function MyApp({ Component, pageProps }: AppProps) {
5+
return <Component {...pageProps} />
6+
}
7+
8+
export default MyApp

0 commit comments

Comments
 (0)