Initial commit: add .gitignore and README
This commit is contained in:
3
dapps/quorumToken/frontend/.eslintrc.json
Normal file
3
dapps/quorumToken/frontend/.eslintrc.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "next/core-web-vitals"
|
||||
}
|
||||
6
dapps/quorumToken/frontend/next.config.js
Normal file
6
dapps/quorumToken/frontend/next.config.js
Normal file
@@ -0,0 +1,6 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
reactStrictMode: true,
|
||||
}
|
||||
|
||||
module.exports = nextConfig
|
||||
5612
dapps/quorumToken/frontend/package-lock.json
generated
Normal file
5612
dapps/quorumToken/frontend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
29
dapps/quorumToken/frontend/package.json
Normal file
29
dapps/quorumToken/frontend/package.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "webapp",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev -p 3001",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@chakra-ui/react": "^2.8.0",
|
||||
"@emotion/react": "^11.11.1",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"ethers": "6.7.1",
|
||||
"framer-motion": "^10.16.1",
|
||||
"next": "13.4.19",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "20.5.4",
|
||||
"@types/react": "18.2.21",
|
||||
"@types/react-dom": "18.2.7",
|
||||
"eslint": "8.47.0",
|
||||
"eslint-config-next": "13.4.19",
|
||||
"typescript": "5.1.6"
|
||||
}
|
||||
}
|
||||
14
dapps/quorumToken/frontend/public/favicon.svg
Normal file
14
dapps/quorumToken/frontend/public/favicon.svg
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg width="313" height="311" viewBox="0 0 313 311" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
path {
|
||||
fill: black;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
path {
|
||||
fill: white;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<path d="M 297 155.5 C 297 233.1 234.1 296 156.5 296 C 78.9 296 16 233.1 16 155.5 C 16 77.9 78.9 15 156.5 15 C 234.1 15 297 77.9 297 155.5 Z M 235.952 170.863 C 228.56 170.91 222.596 176.865 222.632 184.184 C 222.632 184.196 222.632 184.196 222.632 184.208 C 222.596 191.515 228.56 197.47 235.952 197.505 C 243.345 197.458 249.297 191.504 249.273 184.208 C 249.333 176.9 243.381 170.922 235.988 170.863 C 235.976 170.863 235.964 170.863 235.952 170.863 Z M 232.204 155.603 C 238.57 151.928 240.766 143.779 237.09 137.415 C 233.414 131.051 225.263 128.855 218.897 132.531 C 212.554 136.182 210.358 144.272 213.964 150.636 L 214.046 150.754 C 217.722 157.106 225.838 159.278 232.192 155.603 C 232.192 155.615 232.204 155.615 232.204 155.603 Z M 94.567 132.603 C 88.198 128.915 80.042 131.076 76.352 137.442 C 72.662 143.808 74.824 151.959 81.194 155.646 C 87.563 159.334 95.719 157.173 99.409 150.808 L 99.409 150.761 C 103.076 144.407 100.913 136.279 94.567 132.603 Z M 116.395 128.926 C 123.761 128.914 129.726 122.935 129.714 115.581 C 129.714 113.279 129.114 111.023 127.973 109.026 C 124.361 102.648 116.242 100.392 109.842 104.01 C 109.83 104.01 109.83 104.022 109.818 104.022 L 109.595 104.151 C 103.265 107.91 101.182 116.086 104.947 122.406 C 107.348 126.435 111.689 128.914 116.395 128.926 Z M 156.385 91.42 C 149.032 91.42 143.064 97.387 143.064 104.741 C 143.064 112.094 149.032 118.062 156.385 118.062 C 163.739 118.062 169.706 112.094 169.706 104.741 C 169.706 97.387 163.739 91.42 156.385 91.42 Z M 113.889 170.873 C 106.535 170.873 100.568 176.84 100.568 184.194 C 100.568 191.547 106.535 197.515 113.889 197.515 C 121.242 197.515 127.21 191.547 127.21 184.194 C 127.21 176.84 121.242 170.873 113.889 170.873 Z M 178.656 134.517 C 171.303 134.517 165.335 140.484 165.335 147.838 C 165.335 155.191 171.303 161.159 178.656 161.159 C 186.01 161.159 191.977 155.191 191.977 147.838 C 191.977 140.484 186.01 134.517 178.656 134.517 Z M 189.788 127.625 L 189.96 127.721 C 196.823 131.132 205.197 128.432 208.672 121.696 C 211.876 115.479 209.801 107.887 203.846 104.079 C 197.007 100.621 188.609 103.248 185.085 109.96 C 181.819 116.165 183.845 123.781 189.788 127.625 Z M 77.307 170.863 C 69.957 170.745 63.88 176.59 63.727 183.942 C 63.727 184.024 63.727 184.13 63.727 184.213 C 63.75 191.577 69.722 197.527 77.083 197.504 C 84.444 197.48 90.392 191.506 90.369 184.142 C 90.345 176.908 84.538 171.005 77.307 170.863 Z M 198.428 170.833 C 191.074 170.833 185.107 176.801 185.107 184.154 C 185.107 191.508 191.074 197.475 198.428 197.475 C 205.781 197.475 211.749 191.508 211.749 184.154 C 211.749 176.801 205.781 170.833 198.428 170.833 Z M 142.078 158.915 C 148.201 154.855 149.866 146.594 145.808 140.469 C 142.113 134.895 134.852 132.935 128.858 135.88 L 128.776 135.927 C 122.196 139.19 119.51 147.181 122.771 153.764 C 126.031 160.347 134.019 163.034 140.6 159.772 C 141.116 159.525 141.608 159.232 142.078 158.915 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
1
dapps/quorumToken/frontend/public/next.svg
Normal file
1
dapps/quorumToken/frontend/public/next.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
27
dapps/quorumToken/frontend/src/components/Layout.tsx
Normal file
27
dapps/quorumToken/frontend/src/components/Layout.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import React, { ReactNode } from 'react'
|
||||
import { Container, Flex, useColorModeValue, Spacer, Heading, Center, Text } from '@chakra-ui/react'
|
||||
|
||||
interface LayoutProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export default function Layout({ children }: LayoutProps) {
|
||||
return (
|
||||
<div>
|
||||
|
||||
<Flex w="100%" bg={useColorModeValue('gray.100', 'gray.900')} px="6" py="5" align="center" justify="space-between">
|
||||
<Heading size="md">Quorum Quickstart DApp</Heading>
|
||||
<Spacer />
|
||||
</Flex>
|
||||
|
||||
<Container maxW="container.lg" py='8'>
|
||||
{children}
|
||||
</Container>
|
||||
|
||||
<Center as="footer" bg={useColorModeValue('gray.100', 'gray.700')} p={6}>
|
||||
<Text fontSize="md"> © {new Date().getFullYear()} ConsenSys Software, Inc. All rights reserved.</Text>
|
||||
</Center>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
25
dapps/quorumToken/frontend/src/components/MMAccount.tsx
Normal file
25
dapps/quorumToken/frontend/src/components/MMAccount.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
import React, {useEffect, useState } from 'react';
|
||||
import { Heading, Text, VStack, Box, Button, Input, Spacer, Flex } from '@chakra-ui/react'
|
||||
|
||||
interface MMAccountProps {
|
||||
balance: string | undefined,
|
||||
chainId: number | undefined
|
||||
erc20ContractAddress: string
|
||||
deployedAddressHandler: any
|
||||
}
|
||||
|
||||
export default function MMAccount(props:MMAccountProps){
|
||||
|
||||
return (
|
||||
<Box mb={0} p={4} w='100%' borderWidth="1px" borderRadius="lg">
|
||||
<Heading my={4} fontSize='xl'>Account</Heading>
|
||||
<Text my={4}>Details of the account connected to Metamask</Text>
|
||||
<Text><b>Balance of current account (ETH)</b>: {props.balance}</Text>
|
||||
<Text><b>ChainId</b>: {props.chainId} </Text>
|
||||
{/* todo: fix formatting here */}
|
||||
<Text><b>Address that the QuorumToken was deployed to</b>: </Text>
|
||||
<Input value={props.erc20ContractAddress} name="erc20ContractAddress" onChange={props.deployedAddressHandler} />
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// In order to interact with a contract from js, we need the contract's ABI
|
||||
// Im using a human readable format here, but you can just as easily use the compiled output from HardHat
|
||||
|
||||
export const QuorumTokenABI = [
|
||||
// Read-Only Functions
|
||||
"function balanceOf(address owner) view returns (uint256)",
|
||||
"function totalSupply() view returns (uint256)",
|
||||
"function decimals() view returns (uint8)",
|
||||
"function symbol() view returns (string)",
|
||||
// Authenticated Functions
|
||||
"function transfer(address to, uint amount) returns (bool)",
|
||||
// Events
|
||||
"event Transfer(address indexed from, address indexed to, uint amount)"
|
||||
];
|
||||
@@ -0,0 +1,88 @@
|
||||
import React, {useEffect, useState } from 'react';
|
||||
import {Text} from '@chakra-ui/react'
|
||||
import {QuorumTokenABI as abi} from './QuorumTokenABI'
|
||||
import {ethers, Contract} from 'ethers'
|
||||
|
||||
declare let window: any;
|
||||
|
||||
interface ReadQuorumTokenProps {
|
||||
addressContract: string,
|
||||
currentAccount: string | undefined
|
||||
}
|
||||
|
||||
export default function ReadQuorumToken(props:ReadQuorumTokenProps){
|
||||
const addressContract = props.addressContract
|
||||
const currentAccount = props.currentAccount
|
||||
const [totalSupply,setTotalSupply]=useState<string>()
|
||||
const [symbol,setSymbol]= useState<string>("")
|
||||
const [balance, setBalance] =useState<number|undefined>(undefined)
|
||||
|
||||
useEffect( () => {
|
||||
if(!window.ethereum) return;
|
||||
const provider = new ethers.BrowserProvider(window.ethereum);
|
||||
const erc20:Contract = new ethers.Contract(addressContract, abi, provider);
|
||||
|
||||
provider.getCode(addressContract).then((result:string)=>{
|
||||
//check whether it is a contract
|
||||
if(result === '0x') return
|
||||
|
||||
erc20.symbol().then((result:string)=>{
|
||||
setSymbol(result)
|
||||
}).catch('error', console.error)
|
||||
erc20.totalSupply().then((result:string)=>{
|
||||
setTotalSupply(ethers.formatEther(result))
|
||||
}).catch('error', console.error);
|
||||
|
||||
})
|
||||
},[])
|
||||
|
||||
// when currentAccount changes, we call this hook ie useEffect(()=>{ .... },[currentAccount]
|
||||
//
|
||||
useEffect(()=>{
|
||||
if(!window.ethereum) return
|
||||
if(!currentAccount) return
|
||||
|
||||
queryTokenBalance(window);
|
||||
const provider = new ethers.BrowserProvider(window.ethereum);
|
||||
const erc20:Contract = new ethers.Contract(addressContract, abi, provider);
|
||||
|
||||
// listen for changes on an Ethereum address
|
||||
console.log(`listening for Transfer...`)
|
||||
const fromMe = erc20.filters.Transfer(currentAccount, null)
|
||||
erc20.on(fromMe, (from, to, amount, event) => {
|
||||
console.log('Transfer|sent', {from, to, amount, event} )
|
||||
queryTokenBalance(window)
|
||||
})
|
||||
|
||||
const toMe = erc20.filters.Transfer(null, currentAccount)
|
||||
erc20.on(toMe, (from, to, amount, event) => {
|
||||
console.log('Transfer|received', {from, to, amount, event} )
|
||||
queryTokenBalance(window)
|
||||
})
|
||||
|
||||
// remove listener when the component is unmounted
|
||||
return () => {
|
||||
erc20.removeAllListeners(toMe)
|
||||
erc20.removeAllListeners(fromMe)
|
||||
}
|
||||
}, [currentAccount])
|
||||
|
||||
|
||||
async function queryTokenBalance(window:any){
|
||||
const provider = new ethers.BrowserProvider(window.ethereum);
|
||||
const erc20:Contract = new ethers.Contract(addressContract, abi, provider);
|
||||
|
||||
erc20.balanceOf(currentAccount)
|
||||
.then((result:string)=>{
|
||||
setBalance(Number(ethers.formatEther(result)))
|
||||
}).catch((e:Error)=>console.log(e))
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Text><b>ERC20 Contract Address</b>: {addressContract}</Text>
|
||||
<Text><b>QuorumToken totalSupply</b>: {totalSupply} {symbol}</Text>
|
||||
<Text><b>QuorumToken in current account</b>: {balance} {symbol}</Text>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Text, Button, Input , NumberInput, NumberInputField, FormControl, FormLabel } from '@chakra-ui/react';
|
||||
import {ethers, Contract} from 'ethers';
|
||||
import {QuorumTokenABI as abi} from './QuorumTokenABI';
|
||||
import { TransactionResponse,TransactionReceipt } from "@ethersproject/abstract-provider";
|
||||
|
||||
declare let window: any;
|
||||
|
||||
interface Props {
|
||||
addressContract: string,
|
||||
currentAccount: string | undefined
|
||||
}
|
||||
|
||||
export default function TransferQuorumToken(props:Props){
|
||||
const addressContract = props.addressContract
|
||||
const currentAccount = props.currentAccount
|
||||
const [amount, setAmount]=useState<string>('100')
|
||||
const [toAddress, setToAddress]=useState<string>("")
|
||||
|
||||
const handleChange = (value:string) => setAmount(value)
|
||||
|
||||
// https://docs.ethers.org/v6/getting-started/#starting-contracts
|
||||
async function transfer(event:React.FormEvent) {
|
||||
event.preventDefault()
|
||||
// const provider = new ethers.JsonRpcProvider('http://127.0.0.1:8545');
|
||||
const provider = new ethers.BrowserProvider(window.ethereum);
|
||||
const signer = await provider.getSigner();
|
||||
const erc20:Contract = new ethers.Contract(addressContract, abi, signer);
|
||||
|
||||
erc20.transfer(toAddress, ethers.parseEther(amount))
|
||||
.then((tr: TransactionResponse) => {
|
||||
console.log(`TransactionResponse TX hash: ${tr.hash}`)
|
||||
// todo: maybe put this in a modal thing?
|
||||
tr.wait().then((receipt:TransactionReceipt)=>{console.log("transfer receipt",receipt)})
|
||||
})
|
||||
.catch((e:Error)=>console.log(e))
|
||||
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<form onSubmit={transfer}>
|
||||
<FormControl>
|
||||
<FormLabel htmlFor='amount'>Amount: </FormLabel>
|
||||
<NumberInput defaultValue={amount} min={10} max={1000} onChange={handleChange}>
|
||||
<NumberInputField />
|
||||
</NumberInput>
|
||||
<FormLabel htmlFor='toaddress'>To address: </FormLabel>
|
||||
<Input id="toaddress" type="text" required onChange={(e) => setToAddress(e.target.value)} my={3}/>
|
||||
<Button type="submit" isDisabled={!currentAccount}>Transfer</Button>
|
||||
</FormControl>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
19
dapps/quorumToken/frontend/src/pages/_app.tsx
Normal file
19
dapps/quorumToken/frontend/src/pages/_app.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
import type { AppProps } from "next/app";
|
||||
import { ChakraProvider } from "@chakra-ui/react";
|
||||
import "../../styles/globals.css";
|
||||
import Layout from '../components/Layout';
|
||||
|
||||
function MyApp({ Component, pageProps, router }: AppProps) {
|
||||
|
||||
return (
|
||||
<ChakraProvider>
|
||||
<title>Quorum Quickstart DApp</title>
|
||||
<Layout>
|
||||
<Component {...pageProps} />
|
||||
</Layout>
|
||||
</ChakraProvider>
|
||||
)
|
||||
}
|
||||
|
||||
export default MyApp;
|
||||
19
dapps/quorumToken/frontend/src/pages/_document.js
Normal file
19
dapps/quorumToken/frontend/src/pages/_document.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import { ColorModeScript } from "@chakra-ui/react";
|
||||
import NextDocument, { Html, Head, Main, NextScript } from "next/document";
|
||||
|
||||
export default class Document extends NextDocument {
|
||||
render() {
|
||||
return (
|
||||
<Html lang="en">
|
||||
<Head>
|
||||
<link rel="shortcut icon" href="/explorer/images/favicon.svg" />
|
||||
</Head>
|
||||
<body>
|
||||
<ColorModeScript />
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
);
|
||||
}
|
||||
}
|
||||
106
dapps/quorumToken/frontend/src/pages/index.tsx
Normal file
106
dapps/quorumToken/frontend/src/pages/index.tsx
Normal file
@@ -0,0 +1,106 @@
|
||||
import type { NextPage } from 'next'
|
||||
import { Heading, Text, VStack, Box, Button, Input, Spacer, Flex } from '@chakra-ui/react'
|
||||
import { useState, useEffect} from 'react'
|
||||
import {ethers} from "ethers"
|
||||
import ReadQuorumToken from "../components/quorumToken/ReadQuorumToken"
|
||||
import TransferQuorumToken from "../components/quorumToken/TransferQuorumToken"
|
||||
import MMAccount from "../components/MMAccount"
|
||||
|
||||
declare let window:any
|
||||
|
||||
export default function Home() {
|
||||
|
||||
const [balance, setBalance] = useState<string | undefined>();
|
||||
const [currentAccount, setCurrentAccount] = useState<string | undefined>();
|
||||
const [erc20ContractAddress, setErc20ContractAddress] = useState<string>("0x");
|
||||
const [chainId, setChainId] = useState<number | undefined>();
|
||||
|
||||
useEffect( () => {
|
||||
if(!currentAccount || !ethers.isAddress(currentAccount)) return;
|
||||
if(!window.ethereum) return;
|
||||
const provider = new ethers.BrowserProvider(window.ethereum);
|
||||
provider.getBalance(currentAccount).then((result)=> {
|
||||
setBalance(ethers.formatEther(result));
|
||||
})
|
||||
provider.getNetwork().then((result)=>{
|
||||
setChainId(ethers.toNumber(result.chainId));
|
||||
})
|
||||
|
||||
},[currentAccount])
|
||||
|
||||
const onClickConnect = () => {
|
||||
if(!window.ethereum) {
|
||||
console.log("please install MetaMask");
|
||||
return;
|
||||
}
|
||||
|
||||
const provider = new ethers.BrowserProvider(window.ethereum);
|
||||
// MetaMask requires requesting permission to connect users accounts
|
||||
provider.send("eth_requestAccounts", [])
|
||||
.then((accounts)=>{
|
||||
if(accounts.length>0) setCurrentAccount(accounts[0])
|
||||
})
|
||||
.catch((e)=>console.log(e))
|
||||
}
|
||||
|
||||
const onClickDisconnect = () => {
|
||||
setBalance(undefined)
|
||||
setCurrentAccount(undefined)
|
||||
}
|
||||
|
||||
const deployedAddressHandler = (e: any) => {
|
||||
setErc20ContractAddress(e.target.value);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Heading as="h3" my={4}>QuorumToken</Heading>
|
||||
<VStack>
|
||||
<Box w='100%' my={4}>
|
||||
{currentAccount
|
||||
? <Button type="button" w='100%' onClick={onClickDisconnect}>
|
||||
Connected to Metamask with account: {currentAccount}
|
||||
</Button>
|
||||
: <Button type="button" w='100%' onClick={onClickConnect}>
|
||||
Connect to MetaMask
|
||||
</Button>
|
||||
}
|
||||
</Box>
|
||||
{currentAccount
|
||||
?<MMAccount
|
||||
balance={balance}
|
||||
chainId={chainId}
|
||||
erc20ContractAddress={erc20ContractAddress}
|
||||
deployedAddressHandler={deployedAddressHandler} />
|
||||
:<></>
|
||||
}
|
||||
|
||||
{(erc20ContractAddress!="0x")
|
||||
?<Box mb={0} p={4} w='100%' borderWidth="1px" borderRadius="lg">
|
||||
<Heading my={4} fontSize='xl'>Read QuorumToken</Heading>
|
||||
<Text my={4}>Query the smart contract info at address provided</Text>
|
||||
<Spacer />
|
||||
<ReadQuorumToken
|
||||
addressContract={erc20ContractAddress}
|
||||
currentAccount={currentAccount}
|
||||
/>
|
||||
</Box>
|
||||
:<></>
|
||||
}
|
||||
|
||||
{(erc20ContractAddress!="0x")
|
||||
?<Box mb={0} p={4} w='100%' borderWidth="1px" borderRadius="lg">
|
||||
<Heading my={4} fontSize='xl'>Transfer QuorumToken</Heading>
|
||||
<Text my={4}>Interact with the token</Text>
|
||||
<TransferQuorumToken
|
||||
addressContract={erc20ContractAddress}
|
||||
currentAccount={currentAccount}
|
||||
/>
|
||||
</Box>
|
||||
:<></>
|
||||
}
|
||||
|
||||
</VStack>
|
||||
</>
|
||||
)
|
||||
}
|
||||
21
dapps/quorumToken/frontend/styles/globals.css
Normal file
21
dapps/quorumToken/frontend/styles/globals.css
Normal file
@@ -0,0 +1,21 @@
|
||||
:root,
|
||||
body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#__next {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
main {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
}
|
||||
20
dapps/quorumToken/frontend/tsconfig.json
Normal file
20
dapps/quorumToken/frontend/tsconfig.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
"baseUrl": "./src"
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
Reference in New Issue
Block a user