Skip to content

Commit b12f7c9

Browse files
authored
Merge branch 'main' into sohail/contracts
2 parents cc4a0fa + 35fa35d commit b12f7c9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+23120
-10328
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ This repo contains all the code that runs CazzPay - all smart contracts, subgrap
1212

1313
- [TestCoin ($TST)](https://rinkeby.etherscan.io/address/0x6A308Fb8391Cecd7bb9570840239956f25C101F9) - **0x6A308Fb8391Cecd7bb9570840239956f25C101F9**
1414
- [CazzPayToken ($CZP)](https://rinkeby.etherscan.io/address/0x8d7b5E919620D2C9742389bc1CeC671eaB0E3150) - **0x8d7b5E919620D2C9742389bc1CeC671eaB0E3150**
15-
- [CazzPay](https://rinkeby.etherscan.io/address/0xd057D5A7Bc5403436AAB3CeEBfE72E5d781577Dc) - **0xd057D5A7Bc5403436AAB3CeEBfE72E5d781577Dc**
15+
- [CazzPay](https://rinkeby.etherscan.io/address/0xd057D5A7Bc5403436AAB3CeEBfE72E5d781577Dc) - **0xDBbD3EF86b6F1a250f542F21362FeA46c28F037c**
1616

1717
## CazzPay graph
1818

client/README.md

+12-34
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,12 @@
1-
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
2-
3-
## Getting Started
4-
5-
First, run the development server:
6-
7-
```bash
8-
npm run dev
9-
# or
10-
yarn dev
11-
```
12-
13-
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
14-
15-
You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.
16-
17-
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
18-
19-
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
20-
21-
## Learn More
22-
23-
To learn more about Next.js, take a look at the following resources:
24-
25-
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
26-
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
27-
28-
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
29-
30-
## Deploy on Vercel
31-
32-
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
33-
34-
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
1+
# CazzPay
2+
3+
## Environement variables
4+
5+
- **NEXT_PUBLIC_DEPLOY_ENV** *("local", "development", or "production")*
6+
- **INFURA_PROJECT_ID**
7+
- **NEXT_PUBLIC_CAZZPAY_CONTRACT_ADDR**
8+
- **NEXT_PUBLIC_CZP_CONTRACT_ADDR**
9+
- **NEXT_PUBLIC_PAYPAL_CLIENT_ID**
10+
- **PAYPAL_CLIENT_SECRET**
11+
- **NEXT_PUBLIC_GRAPH_API_ENDPOINT**
12+
- **CAZZPAY_SIGNER_PRIVATE_KEY**

client/components/atoms/container/container.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
import { Box, BoxProps, useBreakpointValue } from "@chakra-ui/react";
2+
import { useMemo } from "react";
23

34
interface ContainerProps extends BoxProps {
45
adjustForAppBar?: boolean;
56
fullViewportHeight?: boolean;
67
forReading?: boolean;
78
}
89

9-
export default function Container(props: ContainerProps) {
10+
export default function Container({ adjustForAppBar, fullViewportHeight, forReading, ...props }: ContainerProps) {
1011

1112
const fullScreenHeightForAppBarAdjust = useBreakpointValue({ base: "calc(100vh - 4rem)", md: "calc(100vh - 4.5rem)" });
1213

1314
return (
14-
<Box width="full" maxWidth={props?.forReading ? "60ch" : "5xl"} marginX="auto" as="section" marginTop={{ base: props.adjustForAppBar ? "4rem" : "0", md: props.adjustForAppBar ? "4.5rem" : "0" }} minHeight={props.fullViewportHeight ? (props.adjustForAppBar ? fullScreenHeightForAppBarAdjust : "100vh") : "auto"} {...props}>
15+
<Box width="full" maxWidth={forReading ? "60ch" : "5xl"} marginX="auto" as="section" marginTop={{ base: adjustForAppBar ? "4rem" : "0", md: adjustForAppBar ? "4.5rem" : "0" }} minHeight={fullViewportHeight ? (adjustForAppBar ? fullScreenHeightForAppBarAdjust : "100vh") : "auto"} {...props}>
1516
{props?.children}
1617
</Box>
1718
)

client/components/organisms/appbar/appbar.tsx

+33-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1-
import { Button, Flex, Heading, Hide, IconButton, Menu, MenuButton, MenuDivider, MenuGroup, MenuItem, MenuItemProps, MenuList, Show, useBreakpointValue, useColorMode, useColorModeValue } from "@chakra-ui/react";
1+
import { Button, Flex, Heading, Hide, IconButton, Menu, MenuButton, MenuDivider, MenuGroup, MenuItem, MenuItemProps, MenuList, Show, useBreakpointValue, useColorMode, useColorModeValue, useTheme } from "@chakra-ui/react";
22
import { FiChevronDown as DownArrowIcon, FiSun as SunIcon, FiMoon as MoonIcon } from "react-icons/fi";
33
import { HiMenuAlt4 as MenuIcon } from "react-icons/hi";
44
import { BiHelpCircle as HelpIcon } from "react-icons/bi";
5+
import { FiLogOut as LogoutIcon } from "react-icons/fi";
56
import { AiOutlineLogin as LoginIcon } from "react-icons/ai";
67
import Link from "next/link";
7-
import { useEffect, useState } from "react";
8+
import { useCallback, useEffect, useState } from "react";
89
import { usePaypal } from "../../../hooks/usePaypal";
10+
import { useRouter } from "next/router";
911

1012
export default function AppBar() {
1113

14+
// For router
15+
const router = useRouter();
16+
1217
// For tracking first render
1318
const [isFirstRendered, setIsFirstRendered] = useState<boolean>(false);
1419
useEffect(() => {
@@ -19,7 +24,7 @@ export default function AppBar() {
1924
const { colorMode, toggleColorMode } = useColorMode();
2025

2126
// For Paypal
22-
const { paypalState } = usePaypal();
27+
const { paypalState, setPaypalLoggedInState, setPaypalUserInfo } = usePaypal();
2328

2429
// Icon Button size
2530
const menuIconButtonSize = useBreakpointValue({ base: "md", md: "lg" });
@@ -28,6 +33,16 @@ export default function AppBar() {
2833
// Navbar background
2934
const navbarBackgroundColor = useColorModeValue("gray.50", "gray.800");
3035

36+
// Handle logout
37+
const handleLogout = useCallback(async () => {
38+
setPaypalLoggedInState(false);
39+
setPaypalUserInfo(null);
40+
await router.push("/");
41+
}, [router]);
42+
43+
// Theme
44+
const theme = useTheme();
45+
3146
return (
3247
<Flex position="fixed" top="0" left="0" width="full" zIndex="docked" boxShadow="md" paddingX="6" paddingY="3" alignItems="center" backgroundColor={navbarBackgroundColor}>
3348
{/* Logo/name */}
@@ -74,6 +89,13 @@ export default function AppBar() {
7489
</MenuItem></a></Link>
7590
</MenuList>
7691
</Menu>
92+
93+
{/* Log out */}
94+
{paypalState.loggedIn &&
95+
<Button variant="unstyled" onClick={handleLogout} leftIcon={<LogoutIcon stroke={theme.colors.red["400"]} />} display="flex" color={theme.colors.red["400"]}>
96+
Logout
97+
</Button>
98+
}
7799
</Show>
78100

79101
{/* Nav menu (small screens) */}
@@ -103,6 +125,14 @@ export default function AppBar() {
103125
Know more
104126
</MenuItemCustom></a></Link>
105127
</MenuGroup>
128+
<MenuDivider />
129+
130+
{/* For logging out */}
131+
{paypalState.loggedIn &&
132+
<MenuItem icon={<LogoutIcon size={16} stroke={theme.colors.red["400"]} />} onClick={handleLogout} color={theme.colors.red["400"]} _focus={{ background: "red.400", color: "gray.50" }}>
133+
Logout
134+
</MenuItem>
135+
}
106136

107137
</MenuList>
108138
</Menu>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { Grid, GridItem, Modal, ModalBody, ModalCloseButton, ModalContent, ModalHeader, ModalOverlay, Text } from "@chakra-ui/react";
2+
import useWalletConnection from "../../../hooks/useWalletConnection";
3+
import MetamaskIcon from "../../../icons/MetamaskIcon";
4+
import WalletConnectIcon from "../../../icons/WalletConnectIcon";
5+
import WalletLinkIcon from "../../../icons/WalletLinkIcon";
6+
import OtherWalletIcon from "../../../icons/OtherWalletIcon";
7+
8+
export default function ConnectWalletDialog() {
9+
const { connectDialogVisible, hideConnectDialog, connect } = useWalletConnection();
10+
11+
return (
12+
<Modal isOpen={connectDialogVisible} onClose={hideConnectDialog} isCentered size="xl">
13+
<ModalOverlay />
14+
<ModalContent>
15+
<ModalHeader>Connect your wallet</ModalHeader>
16+
<ModalCloseButton />
17+
18+
{/* Connectors */}
19+
<ModalBody>
20+
<Grid templateColumns="repeat(2, 1fr)" gap="6">
21+
{/* Metamask */}
22+
<GridItem width="full" padding="4" display="flex" flexDirection="column" justifyContent="center" alignItems="center" role="button" onClick={() => { connect("metamask"); }}>
23+
<MetamaskIcon height="48" width="48" />
24+
<Text marginTop="4" textAlign="center">Metamask</Text>
25+
</GridItem>
26+
27+
{/* WalletConnect */}
28+
<GridItem width="full" padding="4" display="flex" flexDirection="column" justifyContent="center" alignItems="center" role="button" onClick={() => { connect("wallet-connect"); }}>
29+
<WalletConnectIcon height="48" width="48" />
30+
<Text marginTop="4" textAlign="center">WalletConnect</Text>
31+
</GridItem>
32+
33+
{/* WalletLink */}
34+
<GridItem width="full" padding="4" display="flex" flexDirection="column" justifyContent="center" alignItems="center" role="button" onClick={() => { connect("wallet-link"); }}>
35+
<WalletLinkIcon height="48" width="48" />
36+
<Text marginTop="4" textAlign="center">Coinbase</Text>
37+
</GridItem>
38+
39+
{/* Others */}
40+
<GridItem width="full" padding="4" display="flex" flexDirection="column" justifyContent="center" alignItems="center" role="button" onClick={() => { connect("injected"); }}>
41+
<OtherWalletIcon height="48" width="48" />
42+
<Text marginTop="4" textAlign="center">Others (injected)</Text>
43+
</GridItem>
44+
</Grid>
45+
</ModalBody>
46+
47+
</ModalContent>
48+
</Modal>
49+
)
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import ConnectWalletDialog from "./connectWalletDialog";
2+
export default ConnectWalletDialog;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import { Box, Button, ButtonProps, FormControl, FormHelperText, FormLabel, Input, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, Text, Tooltip, useToast } from "@chakra-ui/react";
2+
import { BsCoin as BuyCzpIcon } from "react-icons/bs";
3+
import { useLiquidityProvider } from "../../../../hooks/useLiquidityProvider";
4+
import useWalletConnection from "../../../../hooks/useWalletConnection";
5+
import { IoWallet as WalletIcon } from "react-icons/io5";
6+
import { PayPalButtons } from "@paypal/react-paypal-js";
7+
import axios from "axios";
8+
9+
interface ISellerQRCode {
10+
buttonProps: ButtonProps;
11+
}
12+
13+
export default function BuyCzp({ buttonProps }: ISellerQRCode) {
14+
15+
// For liquidity provider
16+
const { buyCzpDialogVisible, setBuyCzpDialogVisible, czpBuyAmt, setCzpBuyAmt } = useLiquidityProvider();
17+
18+
// For wallet connection
19+
const { isConnecting, isConnected, showConnectDialog, disconnect, signerAddr } = useWalletConnection();
20+
21+
// For toast
22+
const toast = useToast();
23+
24+
return (
25+
<>
26+
{/* Button to show Buy CZP dialog code */}
27+
<Tooltip label="Click here to buy $CZP!" aria-label='Buy $CZP to provide liquidity on CazzPay'>
28+
<Button {...buttonProps} leftIcon={<BuyCzpIcon size={24} />} variant="outline" colorScheme="blue" display="flex" onClick={() => { setBuyCzpDialogVisible(true); }}>
29+
Buy CZP
30+
</Button>
31+
</Tooltip>
32+
33+
{/* Buy CZP in a pop-up */}
34+
<Modal isOpen={buyCzpDialogVisible} onClose={() => { setBuyCzpDialogVisible(false); }} isCentered>
35+
<ModalOverlay />
36+
37+
<ModalContent>
38+
<ModalHeader>Buy $CZP</ModalHeader>
39+
<ModalCloseButton />
40+
41+
<ModalBody>
42+
43+
{/* Connect wallet button */}
44+
<Button isLoading={isConnecting} loadingText="Connecting" onClick={!isConnected ? showConnectDialog : disconnect} display="flex" marginX="auto" rightIcon={<WalletIcon size={24} />} colorScheme="blue" variant="outline">
45+
{isConnected ? "Connected" : "Connect wallet"}
46+
</Button>
47+
48+
{/* Input field for buy amount */}
49+
<FormControl marginTop={4}>
50+
<FormLabel>$CZP to buy</FormLabel>
51+
<Input value={czpBuyAmt} onChange={(e) => { setCzpBuyAmt(e.target.value) }} colorScheme="blue" type="number" placeholder="XX.XX" />
52+
<FormHelperText>$CZP:USD = 1:1</FormHelperText>
53+
</FormControl>
54+
55+
</ModalBody>
56+
57+
{/* Interaction buttons */}
58+
<ModalFooter flexDirection="column" alignItems="flex-end">
59+
60+
{/* Buy button */}
61+
<PayPalButtons style={{
62+
layout: "horizontal",
63+
color: "blue",
64+
shape: "pill",
65+
label: "pay"
66+
}} forceReRender={[czpBuyAmt, signerAddr, isConnected, setCzpBuyAmt, setBuyCzpDialogVisible]}
67+
disabled={!(isConnected && !!czpBuyAmt)}
68+
createOrder={async () => {
69+
try {
70+
const res = await fetch("/api/orders", {
71+
method: "POST",
72+
headers: {
73+
"Content-Type": "application/json",
74+
Accept: "application/json",
75+
},
76+
body: JSON.stringify({
77+
price: czpBuyAmt,
78+
}),
79+
});
80+
const data = await res.json();
81+
return data.id;
82+
} catch (e) {
83+
console.error(e);
84+
}
85+
}}
86+
onCancel={(data) => {
87+
console.error(data);
88+
toast({
89+
position: "bottom",
90+
status: "error",
91+
title: "Could not send payment!"
92+
});
93+
}}
94+
onApprove={async (data, actions) => {
95+
const resp = await axios.post(`/api/orders/${data.orderID}`, {
96+
mintTo: signerAddr
97+
}, {
98+
responseType: "json"
99+
});
100+
101+
setCzpBuyAmt("0");
102+
setBuyCzpDialogVisible(false);
103+
104+
toast({
105+
position: "bottom",
106+
status: "success",
107+
title: "Payment successful!"
108+
});
109+
110+
}}
111+
/>
112+
113+
<Text fontSize="sm" marginTop={2} fontWeight={500} color="gray.500">
114+
$CZP bought would be deposited to your wallet
115+
</Text>
116+
</ModalFooter>
117+
</ModalContent>
118+
</Modal>
119+
</>
120+
)
121+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import LiquidityProviderDashboardPage from "./liquidityProviderDashboard";
2+
export default LiquidityProviderDashboardPage;

0 commit comments

Comments
 (0)