Skip to content

Commit 9c87322

Browse files
author
iskanderandrews
committed
Adding MintPage and edit authentication for this page, also connecting it with capture button.
1 parent 1a3ebfe commit 9c87322

File tree

10 files changed

+8212
-9741
lines changed

10 files changed

+8212
-9741
lines changed

client/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"dotenv": "^8.2.0",
2121
"dotenv-expand": "^5.1.0",
2222
"gh-pages": "^2.2.0",
23+
"gulp-sass": "^3.1.0",
2324
"history": "4.9.0",
2425
"jsonwebtoken": "^8.5.1",
2526
"moment": "2.24.0",

client/src/App.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@ import ActivityPage from "./views/ActivityPage/ActivityPage";
2323

2424
import "assets/scss/material-kit-react.scss?v=1.8.0";
2525
import CreatePage from "./views/CreatePage/CreatePage";
26+
import MintPage from "./views/MintPage/MintPage";
2627

2728
const hist = createBrowserHistory();
2829

2930
export default function App(props) {
3031
const [authTokens, setAuthTokens] = useState(null);
3132
const [accountAddress, setAccountAddress] = useState(null);
33+
const [capturedImage, setCapturedImage] = useState(null);
3234

3335
const setTokens = (data) => {
3436
localStorage.setItem("Tokens", JSON.stringify(data));
@@ -40,6 +42,11 @@ export default function App(props) {
4042
setAccountAddress(data);
4143
};
4244

45+
const setThisCapturedImage = (data) => {
46+
localStorage.setItem("Public Address", JSON.stringify(data));
47+
setCapturedImage(data);
48+
};
49+
4350
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
4451

4552
const theme = React.useMemo(
@@ -58,7 +65,9 @@ export default function App(props) {
5865
authTokens,
5966
setAuthTokens: setTokens,
6067
accountAddress,
61-
setAccountAddress: setPublicAddress
68+
setAccountAddress: setPublicAddress,
69+
capturedImage,
70+
setCapturedImage: setThisCapturedImage
6271
}}>
6372
<Router history={hist}>
6473
<Switch>
@@ -69,6 +78,7 @@ export default function App(props) {
6978
<Route path="/activity" component={ActivityPage}/>
7079
<Route path="/offers" component={SalesPage}/>
7180
<Route path="/create" component={CreatePage}/>
81+
<PrivateRoute path="/mint" component={MintPage}/>
7282
<Route path={`/account/:publicAddress`} component={UserPage}/>
7383
<Route path="/token/:tokenId" component={ImageDetailsPage}/>
7484
<Route component={NotFoundPage}/>

client/src/PrivateRoute.js

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@ export default function PrivateRoute({ component: Component, ...rest }) {
66
const { authTokens } = useAuth();
77

88
return (
9-
<Route
10-
{...rest}
11-
render={props =>
12-
authTokens ? (
13-
<Component {...props} />
14-
) : (
15-
<Redirect to="/" />
16-
)
17-
}
18-
/>
9+
<Route
10+
{...rest}
11+
render={props =>
12+
(authTokens === null) ? (
13+
<Redirect to="/" />
14+
15+
) : (
16+
<Component {...props} />
17+
)
18+
}
19+
/>
1920
);
2021
}

client/src/assets/jss/material-kit-react/components/glitches.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ const glitchStyle = {
1616
height: "30px",
1717
borderRadius: "50%"
1818
},
19+
linkColor: {
20+
"&,&:hover,&:focus": {
21+
color: "inherit",
22+
textDecoration: "none",
23+
display: "block",
24+
}
25+
},
1926
root: {
2027
maxWidth: 550,
2128
maxHeight: 550,

client/src/components/Glitch/Glitch.js

Lines changed: 176 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, {useEffect, useRef, useState} from "react";
22
import {makeStyles, withStyles} from "@material-ui/core/styles";
3+
import Web3 from "web3";
34
//@material-ui/core
45
import Typography from '@material-ui/core/Typography';
56
import Slider from '@material-ui/core/Slider';
@@ -21,11 +22,14 @@ import Slide from "@material-ui/core/Slide";
2122
import GridContainer from "components/Grid/GridContainer";
2223
import GridItem from "components/Grid/GridItem";
2324
import Button from "components/CustomButtons/Button.js";
25+
import Danger from "components/Typography/Danger.js";
26+
import { useAuth } from "context/auth";
2427
import GlitchesImgCard from "components/ImageCards/GlitchesImgCard/GlitchesImgCard";
2528
//styles
2629
import styles from "assets/jss/material-kit-react/components/glitches";
2730
import CircularProgress from "@material-ui/core/CircularProgress";
2831
import Card from "@material-ui/core/Card";
32+
import {Link, Redirect} from "react-router-dom";
2933

3034
const useStyles = makeStyles(styles);
3135

@@ -40,10 +44,29 @@ const StyledCardMedia = withStyles({
4044
})(CardMedia);
4145

4246
export default function Glitch(props) {
47+
let img = props.faceImage;
48+
49+
let canvasRef = useRef(null);
50+
let canvas, ctx;
51+
52+
let width, height;
53+
54+
let bitmapData, animation;
55+
56+
let counter, startTime;
57+
58+
let buf, buf8, data;
59+
60+
let web3;
61+
62+
let captured;
63+
4364
const classes = useStyles();
4465

4566
const [showMagnitudeComponent, setShowMagnitudeComponent] = useState(true);
4667

68+
const { authTokens, setAuthTokens, accountAddress, setAccountAddress, capturedImage, setCapturedImage } = useAuth();
69+
4770
const showComponent = type => {
4871
const shouldShowBrokenComponent = type === "alpha-blended";
4972
if (shouldShowBrokenComponent !== showMagnitudeComponent) {
@@ -55,6 +78,7 @@ export default function Glitch(props) {
5578
};
5679

5780
const [currentImg, setCurrentImg] = useState(props.faceImage);
81+
const [captureImg, setCaptureImg] = useState();
5882

5983
// algorithms
6084
const [algorithm, setAlgorithm] = useState(null);
@@ -74,25 +98,6 @@ export default function Glitch(props) {
7498
// default selection
7599
//let comparator = COMP_BRIGHTNESS;
76100

77-
let img = props.faceImage;
78-
79-
let canvasRef = useRef(null);
80-
let canvas;
81-
let ctx;
82-
83-
let width;
84-
let height;
85-
86-
let bitmapData;
87-
let animation;
88-
89-
let counter;
90-
let startTime;
91-
92-
let buf;
93-
let buf8;
94-
let data;
95-
96101
useEffect(() => {
97102
canvas = canvasRef.current;
98103
ctx = canvas.getContext("2d");
@@ -377,7 +382,7 @@ export default function Glitch(props) {
377382
buf8.set(bitmapData.data);
378383
}
379384
function save() {
380-
openInNewTab(canvas.toDataURL("image/png"))
385+
setCapturedImage(canvas.toDataURL("image/png"));
381386
}
382387

383388
function openInNewTab(url) {
@@ -390,31 +395,139 @@ export default function Glitch(props) {
390395
setCurrentImg(token.image_url);
391396
};
392397

398+
const signInMetaMaskHandler = (publicAddress) => {
399+
console.log(`${process.env.REACT_APP_BACKEND_API}/accounts`);
400+
fetch(`${process.env.REACT_APP_BACKEND_API}/accounts`, {
401+
body: JSON.stringify({ publicAddress }),
402+
headers: {
403+
'Content-Type': 'application/json'
404+
},
405+
method: 'POST'
406+
})
407+
.then(res => {
408+
// TODO: validate Ethereum Address
409+
if (res.status !== 200 && res.status !== 201) {
410+
throw new Error('Creating a user failed!');
411+
}
412+
return res.json();
413+
})
414+
.then(account => {
415+
console.log('ACCOUNT:',account);
416+
})
417+
.catch(err => {
418+
console.log('ERROR', err);
419+
});
420+
};
421+
422+
const signMessageHandler = async (publicAddress, nonce) => {
423+
const signature = await web3.eth.personal.sign(
424+
`I am signing my one-time nonce: ${nonce}`,
425+
publicAddress,
426+
// MetaMask will ignore the password argument here
427+
);
428+
await authenticateHandler(publicAddress, signature);
429+
};
430+
431+
const authenticateHandler = (publicAddress, signature) => {
432+
console.log(`publicAddress: ${publicAddress}, \n signature: ${signature}`);
433+
434+
fetch(`${process.env.REACT_APP_BACKEND_API}/auth/signin`, {
435+
body: JSON.stringify({ publicAddress, signature }),
436+
headers: {
437+
'Content-Type': 'application/json'
438+
},
439+
method: 'POST'
440+
})
441+
.then(res => res.json())
442+
.then(resData => {
443+
console.log(`Tokens: ${resData.token}`);
444+
setAuthTokens(resData.token);
445+
setAccountAddress(resData.publicAddress);
446+
})
447+
.catch(err => console.log('authenticateHandlerError: ', err));
448+
};
449+
450+
const checkHandler = async (event) => {
451+
if (window.ethereum) {
452+
try {
453+
web3 = new Web3(window.ethereum);
454+
await window.ethereum.enable();
455+
456+
const publicAddress = await web3.eth.getCoinbase();
457+
458+
fetch(`${process.env.REACT_APP_BACKEND_API}/accounts/${publicAddress}`, {
459+
method: 'GET'
460+
})
461+
.then(res => {
462+
if (res.status === 404) {
463+
signInMetaMaskHandler(publicAddress);
464+
}
465+
return res.json();
466+
})
467+
.then(account => {
468+
signMessageHandler(account.account.publicAddress, account.account.nonce);
469+
})
470+
.catch(err => {
471+
console.log('checkHandlerError: ', err);
472+
})
473+
474+
} catch (error) {
475+
// User denied account access...
476+
console.log(error);
477+
}
478+
} else if (window.web3) {
479+
web3 = new Web3(window.web3.currentProvider);
480+
} else {
481+
// TODO: output warning msg when not having metamask
482+
console.log('Non-Ethereum browser detected. You should consider trying MetaMask!');
483+
}
484+
};
485+
393486
const fetchAccountCollectionsHandler = () => {
394-
fetch(`https://api.opensea.io/api/v1/assets?owner=0x7cef4b8a78b2b64749efa91094512ac2f65a0b1f&asset_contract_address=0x55a2525A0f4B0cAa2005fb83A3Aa3AC95683C661&limit=100`, {
487+
fetch(`https://api.opensea.io/api/v1/assets?owner=${accountAddress}&asset_contract_address=0x55a2525A0f4B0cAa2005fb83A3Aa3AC95683C661&limit=100`, {
395488
method: 'GET'
396489
})
397490
.then(res => res.json())
398491
.then(resData => {
399-
for (let [key, value] of Object.entries(resData)) {
400-
setTokenCard(value.map(token => {
401-
return (
402-
<GridItem xs={12} sm={12} md={4} lg={4} xl={4}>
403-
<Card className={classes.root}>
404-
<StyledCardMedia
405-
className={classes.imgMedia}
406-
component="img"
407-
image={token.image_url}
408-
title={token.name}
409-
onClick={() => {
410-
setCurrentImg(token.image_url);
411-
setClassicModal(false);
412-
console.log(token.image_url);
413-
}}
414-
/>
415-
</Card>
416-
</GridItem>)
417-
}))
492+
493+
if (resData.assets[0] === undefined || resData.assets.length == 0) {
494+
setTokenCard(
495+
<GridItem xs={12} sm={12} md={12} lg={12} xl={12}>
496+
<Danger>
497+
No Collections, go and pick your Weirdo.
498+
</Danger>
499+
<Link to="/gallery" className={classes.linkColor}>
500+
<Button
501+
simple
502+
color="facebook"
503+
size="lg">
504+
View All
505+
</Button>
506+
</Link>
507+
</GridItem>
508+
)
509+
} else {
510+
for (let [key, value] of Object.entries(resData)) {
511+
setTokenCard(value.map(token => {
512+
513+
return (
514+
<GridItem xs={12} sm={12} md={4} lg={4} xl={4}>
515+
<Card className={classes.root}>
516+
<StyledCardMedia
517+
className={classes.imgMedia}
518+
component="img"
519+
image={token.image_url}
520+
title={token.name}
521+
onClick={() => {
522+
setCurrentImg(token.image_url);
523+
setClassicModal(false);
524+
console.log(token.image_url);
525+
}}
526+
/>
527+
</Card>
528+
</GridItem>)
529+
}))
530+
}
418531
}
419532
})
420533
};
@@ -723,18 +836,22 @@ export default function Glitch(props) {
723836
className={classes.signInBtn}
724837
round
725838
color="primary"
726-
size="lg"
727-
onClick={save}>
839+
size="lg">
728840
Capture
729841
</Button> :
730-
<Button
731-
className={classes.signInBtn}
732-
round
733-
color="primary"
734-
size="lg"
735-
onClick={save}>
736-
Capture
737-
</Button>}
842+
<Link
843+
to="/mint"
844+
className={classes.linkColor}
845+
>
846+
<Button
847+
className={classes.signInBtn}
848+
round
849+
color="primary"
850+
size="lg"
851+
onClick={() => save()}>
852+
Capture
853+
</Button>
854+
</Link>}
738855
</GridItem>
739856
</GridContainer>
740857
<GridContainer justify="center" spacing="1">
@@ -744,7 +861,15 @@ export default function Glitch(props) {
744861
className={classes.signInBtn}
745862
round
746863
size="lg"
747-
onClick={() => {setClassicModal(true); fetchAccountCollectionsHandler();}}
864+
onClick={() => {
865+
setClassicModal(true);
866+
867+
if (authTokens === null) {
868+
checkHandler();
869+
}
870+
fetchAccountCollectionsHandler();
871+
}
872+
}
748873
>
749874
<LibraryBooks className={classes.icon} />
750875
Select Your Weirdo

0 commit comments

Comments
 (0)