Skip to content

Commit 5e4e9ff

Browse files
committed
Integrated Pera Web connect and resolved rerendering issues
1 parent 52b14ff commit 5e4e9ff

31 files changed

+902
-412
lines changed

.DS_Store

-6 KB
Binary file not shown.

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules
2+
build
3+
.DS_Store
4+
Backend/node_modules
5+
Frontend/node_modules

Frontend/.DS_Store

0 Bytes
Binary file not shown.

Frontend/package.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"version": "0.1.0",
44
"private": true,
55
"dependencies": {
6-
"@perawallet/connect": "^0.2.2",
6+
"@perawallet/connect": "1.2.3",
77
"@randlabs/myalgo-connect": "^1.4.0",
88
"@react-hook/window-size": "^3.1.1",
99
"@szhsin/react-menu": "^3.2.0",
@@ -19,6 +19,7 @@
1919
"javascript-time-ago": "^2.5.7",
2020
"lodash": "^4.17.21",
2121
"millify": "^5.0.1",
22+
"phosphor-react": "^1.4.1",
2223
"react": "^18.2.0",
2324
"react-csv-downloader": "^2.8.0",
2425
"react-dom": "^18.2.0",
@@ -27,6 +28,8 @@
2728
"react-router-dom": "^6.4.2",
2829
"react-scripts": "5.0.1",
2930
"react-time-ago": "^7.2.1",
31+
"react-tooltip": "^5.11.1",
32+
"react-use": "^17.4.0",
3033
"recoil": "^0.7.6",
3134
"recoil-persist": "^4.2.0",
3235
"spinners-react": "^1.0.7",

Frontend/src/App.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const App = () => {
3535
.catch(err => {
3636
// console.log(err);
3737
});
38-
// eslint-disable-next-line react-hooks/exhaustive-deps
38+
// eslint-disable-next-line
3939
}, []);
4040

4141
return (

Frontend/src/atoms/appState.js

-8
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,6 @@ import { recoilPersist } from "recoil-persist";
33

44
const { persistAtom } = recoilPersist();
55

6-
const storageEffect =
7-
key =>
8-
({ onSet }) => {
9-
onSet(newValue => {
10-
localStorage.setItem(key, newValue);
11-
});
12-
};
13-
146
export const addressAtom = atom({
157
default: "",
168
key: "address",

Frontend/src/components/AppTable/BetHistoryDetails.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { Link } from "react-router-dom";
1010
const BetHistoryDetails = ({ bet, closeHistoryTab }) => {
1111
const { fetching, errorHistory } = useApp();
1212
const { gameParams } = bet || {};
13-
console.log(bet);
1413

1514
return (
1615
<>
@@ -102,6 +101,7 @@ const BetHistoryDetails = ({ bet, closeHistoryTab }) => {
102101
<li className="bet-details__list-item">
103102
<p className="key">Transaction Id</p>
104103
<a
104+
aria-label="transaction-id"
105105
target="_blank"
106106
rel="noreferrer"
107107
className="value"

Frontend/src/components/AppTable/ProfileBetDetails.jsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ import Icon from "../common/Icon";
77
const ProfileBetDetails = ({ details, closeDetailsTab }) => {
88
const { lottoParams, userInteractions } = details || {};
99

10-
console.log(details);
11-
1210
return (
1311
<>
1412
<div className="app-modal__header">
@@ -28,6 +26,7 @@ const ProfileBetDetails = ({ details, closeDetailsTab }) => {
2826

2927
{key === "gameMaster" ? (
3028
<a
29+
aria-label="game-master"
3130
target="_blank"
3231
rel="noreferrer"
3332
className="value"
@@ -103,6 +102,7 @@ const ProfileBetDetails = ({ details, closeDetailsTab }) => {
103102
action?.action?.replaceAll("_", " ")}
104103
</p>
105104
<a
105+
aria-label="transaction-id"
106106
target="_blank"
107107
rel="noreferrer"
108108
href={

Frontend/src/components/layout/ConnectedWallet.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ const ConnectedWallet = () => {
5151
align="end"
5252
transition
5353
menuButton={
54-
<button className="options-btn">
54+
<button className="options-btn" aria-label="disconnect-menu-btn">
5555
<Icon.CaretDown />
5656
</button>
5757
}

Frontend/src/components/layout/Navbar.jsx

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const Navbar = () => {
3232
<button
3333
className="connect-wallet-btn"
3434
onClick={openConnectModal}
35+
aria-label="connect-wallet"
3536
style={{
3637
width: windowWidth > 570 ? "auto" : "34px",
3738
height: windowWidth > 570 ? "auto" : "34px",

Frontend/src/components/modals/NewGameModal.jsx

+84-54
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import axios from "axios";
2+
import millify from "millify";
23
import Icon from "../common/Icon";
34
import { useRecoilValue } from "recoil";
5+
import { MultiSigner } from "../../utils";
6+
import { useNetworkState } from "react-use";
47
import { useEffect, useState } from "react";
8+
import { SpinnerCircular } from "spinners-react";
9+
import { useApp } from "../../context/AppContext";
510
import { Menu, MenuItem } from "@szhsin/react-menu";
11+
import { getMinAmountToStartGame } from "../../utils/helpers";
612
import { addressAtom, providerAtom } from "../../atoms/appState";
7-
import { SpinnerCircular } from "spinners-react";
8-
import { MultiSigner } from "../../utils";
9-
import algosdk from "algosdk";
1013

1114
const ticketingOptions = [
1215
"In 10 minutes",
@@ -15,13 +18,16 @@ const ticketingOptions = [
1518
"In 2 hours",
1619
];
1720
const withdrawalOptions = [
21+
"15 minutes after",
1822
"1 hour after",
1923
"2 hours after",
2024
"3 hours after",
2125
"4 hours after",
2226
];
2327

2428
const NewGameModal = ({ closeNewGameModal, refetchCurrentGame }) => {
29+
const network = useNetworkState();
30+
const { acctBalance } = useApp();
2531
const address = useRecoilValue(addressAtom);
2632
const provider = useRecoilValue(providerAtom);
2733

@@ -35,9 +41,9 @@ const NewGameModal = ({ closeNewGameModal, refetchCurrentGame }) => {
3541
const [maxGuessNumber, setMaxGuessNumber] = useState(10000);
3642
const [maxPlayersAllowed, setMaxPlayersAllowed] = useState(2);
3743
const [ticketingStart, setTicketStart] = useState("In 10 minutes");
38-
const [withdrawalStart, setWithdrawalStart] = useState("1 hour after");
44+
const [withdrawalStart, setWithdrawalStart] = useState("15 minutes after");
3945

40-
const ticketingValue = () =>
46+
const ticketingDateValue = () =>
4147
Math.round(
4248
Date.now() / 1000 +
4349
(ticketingStart === "In 10 minutes"
@@ -49,7 +55,7 @@ const NewGameModal = ({ closeNewGameModal, refetchCurrentGame }) => {
4955
: 7200)
5056
);
5157

52-
const withdrawalValue = () =>
58+
const withdrawalDateValue = () =>
5359
Math.round(
5460
Date.now() / 1000 +
5561
(ticketingStart === "In 10 minutes"
@@ -60,7 +66,9 @@ const NewGameModal = ({ closeNewGameModal, refetchCurrentGame }) => {
6066
? 3600
6167
: 7200)
6268
) +
63-
(withdrawalStart === "1 hour after"
69+
(withdrawalStart === "15 minutes after"
70+
? 900
71+
: withdrawalStart === "1 hour after"
6472
? 3600
6573
: withdrawalStart === "2 hours after"
6674
? 7200
@@ -69,12 +77,16 @@ const NewGameModal = ({ closeNewGameModal, refetchCurrentGame }) => {
6977
: 14400);
7078

7179
const startNewGame = async () => {
80+
if (acctBalance < gameCost) {
81+
setError("Insufficient balance!");
82+
return;
83+
}
84+
7285
if (loading) return;
7386
if (!address) return setError("Please connect your wallet first!");
7487

7588
const params = {
76-
winMultiplier:
77-
winMultiplier > 10 ? 10 : winMultiplier < 0 ? 2 : winMultiplier,
89+
winMultiplier: winMultiplier < 0 ? 2 : winMultiplier,
7890
ticketFee: (ticketFee > 10 ? 10 : ticketFee < 0 ? 1 : ticketFee) * 1e6,
7991
ticketingDuration:
8092
durationType === "m"
@@ -87,16 +99,11 @@ const NewGameModal = ({ closeNewGameModal, refetchCurrentGame }) => {
8799
: maxGuessNumber < 0
88100
? 100
89101
: maxGuessNumber,
90-
maxPlayersAllowed:
91-
maxPlayersAllowed > 50
92-
? 50
93-
: maxPlayersAllowed < 2
94-
? 2
95-
: maxPlayersAllowed,
102+
maxPlayersAllowed: maxPlayersAllowed < 2 ? 2 : maxPlayersAllowed,
96103

97104
gameMasterAddr: address,
98-
ticketingStart: ticketingValue(),
99-
withdrawalStart: withdrawalValue(),
105+
ticketingStart: ticketingDateValue(),
106+
withdrawalStart: withdrawalDateValue(),
100107
};
101108

102109
setError("");
@@ -105,12 +112,14 @@ const NewGameModal = ({ closeNewGameModal, refetchCurrentGame }) => {
105112
const txnsArr = await axios
106113
.post(`/endCurrentAndCreateNewGame`, params)
107114
.then(response => {
108-
console.log(response);
109115
return response?.data?.txns;
110116
});
111117

112118
if (txnsArr?.length) await MultiSigner(txnsArr, provider);
113-
refetchCurrentGame();
119+
120+
console.log("New game started successfully!");
121+
122+
await refetchCurrentGame();
114123
closeNewGameModal();
115124
} catch (error) {
116125
console.log(error);
@@ -140,9 +149,29 @@ const NewGameModal = ({ closeNewGameModal, refetchCurrentGame }) => {
140149

141150
useEffect(() => {
142151
handleDurationChange();
143-
// eslint-disable-next-line react-hooks/exhaustive-deps
152+
// eslint-disable-next-line
144153
}, [durationType]);
145154

155+
// Calculate the minimum amount required to start a game
156+
const [gameCost, setGameCost] = useState(0);
157+
useEffect(() => {
158+
if (!network?.online) return;
159+
const getMinCost = async () => {
160+
const cost = await getMinAmountToStartGame(
161+
isNaN(ticketFee) || ticketFee < 1 ? 1 * 1e6 : ticketFee * 1e6,
162+
isNaN(winMultiplier) || winMultiplier < 2 ? 2 : winMultiplier,
163+
isNaN(maxPlayersAllowed) || maxPlayersAllowed < 2
164+
? 2
165+
: maxPlayersAllowed
166+
);
167+
168+
setGameCost(cost);
169+
};
170+
171+
getMinCost();
172+
// eslint-disable-next-line
173+
}, [winMultiplier, ticketFee, maxPlayersAllowed]);
174+
146175
return (
147176
<>
148177
<div className="app-modal__header no-capitalize">
@@ -162,29 +191,16 @@ const NewGameModal = ({ closeNewGameModal, refetchCurrentGame }) => {
162191
<div className="input-block sm">
163192
<input
164193
min={0}
165-
max={10}
166194
type="number"
167195
maxLength={3}
168196
onBlur={e => {
169-
setMaxPlayersAllowed(
170-
e.target.value > 10
171-
? 10
172-
: e.target.value < 0
173-
? 0
174-
: e.target.value
175-
);
197+
setWinMultiplier(e.target.value < 2 ? 2 : e.target.value);
176198
}}
177-
placeholder="max 10"
199+
placeholder="Min 2"
178200
name="winMultiplier"
179201
value={winMultiplier}
180202
onChange={e =>
181-
setWinMultiplier(
182-
e.target.value > 10
183-
? 50
184-
: e.target.value < 0
185-
? 2
186-
: e.target.value
187-
)
203+
setWinMultiplier(e.target.value < 0 ? 0 : e.target.value)
188204
}
189205
/>
190206
</div>
@@ -195,29 +211,16 @@ const NewGameModal = ({ closeNewGameModal, refetchCurrentGame }) => {
195211
<div className="input-block sm">
196212
<input
197213
min={2}
198-
max={50}
199214
type="number"
200215
maxLength={3}
201216
onBlur={e => {
202-
setMaxPlayersAllowed(
203-
e.target.value > 50
204-
? 50
205-
: e.target.value < 2
206-
? 2
207-
: e.target.value
208-
);
217+
setMaxPlayersAllowed(e.target.value < 2 ? 2 : e.target.value);
209218
}}
210-
placeholder="max 50"
219+
placeholder="Min 2"
211220
name="maxPlayersAllowed"
212221
value={maxPlayersAllowed}
213222
onChange={e =>
214-
setMaxPlayersAllowed(
215-
e.target.value > 50
216-
? 50
217-
: e.target.value < 0
218-
? 0
219-
: e.target.value
220-
)
223+
setMaxPlayersAllowed(e.target.value < 0 ? 0 : e.target.value)
221224
}
222225
/>
223226
</div>
@@ -242,7 +245,7 @@ const NewGameModal = ({ closeNewGameModal, refetchCurrentGame }) => {
242245
);
243246
}}
244247
value={maxGuessNumber}
245-
placeholder="max 10000"
248+
placeholder="Max 10000"
246249
onChange={e =>
247250
setMaxGuessNumber(
248251
e.target.value > 10000 ? 10000 : e.target.value
@@ -257,7 +260,7 @@ const NewGameModal = ({ closeNewGameModal, refetchCurrentGame }) => {
257260
<div className="input-block ticket">
258261
<input
259262
type="number"
260-
placeholder="min 1"
263+
placeholder="Min 1"
261264
name="ticketFee"
262265
maxLength={3}
263266
value={ticketFee}
@@ -429,6 +432,33 @@ const NewGameModal = ({ closeNewGameModal, refetchCurrentGame }) => {
429432
</div>
430433
</div>
431434

435+
<div className="calculations">
436+
<div className="calculations-row">
437+
<p className="key">Account balance: </p>
438+
439+
<div className="amount">
440+
<Icon.Algo size={15} />
441+
<p className="value">
442+
{millify(acctBalance, {
443+
precision: 2,
444+
})}
445+
</p>
446+
</div>
447+
</div>
448+
<div
449+
className={`calculations-row ${
450+
gameCost < acctBalance ? "valid" : "error"
451+
}`}
452+
>
453+
<p className="key">Min amount required: </p>
454+
455+
<div className="amount">
456+
<Icon.Algo size={15} />
457+
<p className="value">{gameCost}</p>
458+
</div>
459+
</div>
460+
</div>
461+
432462
{loading && (
433463
<div className="loading-overlay">
434464
<SpinnerCircular size={50} color="#777" secondaryColor="#ccc" />

0 commit comments

Comments
 (0)