-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
34 changed files
with
2,406 additions
and
993 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,47 +1,24 @@ | ||
# TypeScript Next.js example | ||
# my nextjs web3 template | ||
|
||
This is a really simple project that shows the usage of Next.js with TypeScript. | ||
Uses tailwind, typescript and ethers.js to connect to metamask / hana. | ||
|
||
## Deploy your own | ||
## GlobalContext | ||
In utils/context/GlobalContext.tsx you can find the global context. The global context is provided | ||
in _app.tsx and can be used in any component. | ||
|
||
Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example) or preview live with [StackBlitz](https://stackblitz.com/github/vercel/next.js/tree/canary/examples/with-typescript) | ||
## Index.tsx | important! | ||
pages/index.tsx is where the global logic regarding the connection to metamask / hana is handled. | ||
It checks if: | ||
- the connected device is a mobile device and if so, if it the hana or metamask app. | ||
- if not mobile, is hana or metamask installed? If so, connect to on of them. | ||
|
||
[](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-typescript&project-name=with-typescript&repository-name=with-typescript) | ||
On connecting the users pick is stored in the localStorage. When creating a provider and | ||
signer, the localStorage is checked to see it it should use window.ethereum or window.hanaWallet. | ||
|
||
## How to use it? | ||
## Custom Fonts | ||
To import a custom font you have to import it at _document.tsx and add it to the font array in the | ||
in the tailwind config file. | ||
|
||
Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init), [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/), or [pnpm](https://pnpm.io) to bootstrap the example: | ||
## Custom Theme | ||
To add a custom theme you have to add it to the tailwind config file. | ||
|
||
```bash | ||
npx create-next-app --example with-typescript with-typescript-app | ||
``` | ||
|
||
```bash | ||
yarn create next-app --example with-typescript with-typescript-app | ||
``` | ||
|
||
```bash | ||
pnpm create next-app --example with-typescript with-typescript-app | ||
``` | ||
|
||
Deploy it to the cloud with [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)). | ||
|
||
## Notes | ||
|
||
This example shows how to integrate the TypeScript type system into Next.js. Since TypeScript is supported out of the box with Next.js, all we have to do is to install TypeScript. | ||
|
||
``` | ||
npm install --save-dev typescript | ||
``` | ||
|
||
To enable TypeScript's features, we install the type declarations for React and Node. | ||
|
||
``` | ||
npm install --save-dev @types/react @types/react-dom @types/node | ||
``` | ||
|
||
When we run `next dev` the next time, Next.js will start looking for any `.ts` or `.tsx` files in our project and builds it. It even automatically creates a `tsconfig.json` file for our project with the recommended settings. | ||
|
||
Next.js has built-in TypeScript declarations, so we'll get autocompletion for Next.js' modules straight away. | ||
|
||
A `type-check` script is also added to `package.json`, which runs TypeScript's `tsc` CLI in `noEmit` mode to run type-checking separately. You can then include this, for example, in your `test` scripts. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import React, {useState} from 'react' | ||
import { ethers } from 'ethers' | ||
import lotteryAbi from '../utils/contracts/lottery_abi.json' | ||
import { ContractAddresses } from '../utils/constants/addresses' | ||
import { useGlobalContext } from '../utils/context/globalContext' | ||
|
||
type LotteryInstanceProps = { | ||
id: number, | ||
ticketPrice: number, | ||
totalTickets: number, | ||
ticketsSold: number, | ||
closed: boolean, | ||
exists: boolean, | ||
owner: string, | ||
} | ||
|
||
type Props = { | ||
modalOpen: boolean, | ||
setModalOpen: React.Dispatch<React.SetStateAction<boolean>> | ||
lottery: LotteryInstanceProps | ||
} | ||
|
||
const BuyTicketsModal = (props: Props) => { | ||
const { signer, setTransactionToCheck, lotteryId } = useGlobalContext() | ||
const contractSigner = new ethers.Contract(ContractAddresses.lotteryContract, lotteryAbi.abi, signer) | ||
const [amountOfTickets, setAmountOfTickets] = useState<number>(1) | ||
|
||
const handleAmountOfTicketsChange = (e: React.ChangeEvent<HTMLInputElement>) => { | ||
setAmountOfTickets(parseInt(e.target.value)) | ||
if (parseInt(e.target.value) > props.lottery.totalTickets) { | ||
setAmountOfTickets(props.lottery.totalTickets) | ||
} | ||
} | ||
|
||
const handleBuyTickets = async () => { | ||
const options = { | ||
value: ethers.parseEther((amountOfTickets * props.lottery.ticketPrice).toString()), | ||
gasLimit: 10000000 | ||
} | ||
try{ | ||
const tx:ethers.ContractTransactionResponse = await contractSigner.buyTickets(lotteryId, amountOfTickets, options) | ||
setTransactionToCheck(tx) | ||
} catch (e) { | ||
console.log(e) | ||
} | ||
|
||
} | ||
|
||
|
||
return ( | ||
<div className='fixed top-0 left-0 backdrop-blur-sm w-screen h-screen absolute z-20 flex justify-center items-center' | ||
onClick={()=>{props.setModalOpen(false)}} | ||
> | ||
<div className=' bg-funPurple rounded md:p-12 border-8 border-white z-40' onClick={(e) => e.stopPropagation()}> | ||
<div className='font-bold text-5xl text-white'> | ||
get your tickets! | ||
</div> | ||
<div className='mt-4'> | ||
price per ticket {props.lottery.ticketPrice} ICZ | ||
</div> | ||
<div className='mt-2'> | ||
total tickets left: {props.lottery.totalTickets} | ||
</div> | ||
<div className='mt-2'> | ||
total tickets to buy: {isNaN(amountOfTickets) ? 0 : amountOfTickets} | ||
</div> | ||
<div className='mt-2 '> | ||
<input | ||
type='number' | ||
className='w-full bg-funPurple text-white border rounded-md p-2 ' | ||
value={amountOfTickets} | ||
onChange={(e) => handleAmountOfTicketsChange(e)} | ||
/> | ||
</div> | ||
|
||
<div className='mt-2'> | ||
cost: {isNaN(amountOfTickets) ? 0 : amountOfTickets * props.lottery.ticketPrice} ICZ | ||
</div> | ||
<div className='mt-2'> | ||
<button className=' | ||
hover:bg-funBlue hover:text-funPurple border | ||
border-white text-white rounded-md p-2 font-bold | ||
' | ||
onClick={() => handleBuyTickets()} | ||
> | ||
buy tickets | ||
</button> | ||
</div> | ||
</div> | ||
</div> | ||
) | ||
} | ||
|
||
export default BuyTicketsModal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { useGlobalContext } from '../utils/context/globalContext'; | ||
|
||
export default function ConnectButton() { | ||
const { setConnectModalOpen } = useGlobalContext(); | ||
|
||
return ( | ||
<div className=' | ||
fixed top-4 right-4 font-bold p-4 | ||
bg-funPurple text-white flex justify-center items-center rounded-md cursor-pointer | ||
' | ||
onClick={()=>setConnectModalOpen(true)} | ||
> | ||
QNect | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import React from 'react' | ||
import { useGlobalContext } from '../utils/context/globalContext' | ||
|
||
const ConnectedAddress = () => { | ||
const { account } = useGlobalContext() | ||
|
||
// format the account address | ||
const formatAddress = (address: string) => { | ||
if (!address) return '' | ||
address = address[0] | ||
return address.slice(0, 6) + '...' + address.slice(-4) | ||
} | ||
|
||
return ( | ||
<div>Connected: {formatAddress(account)}</div> | ||
) | ||
} | ||
|
||
export default ConnectedAddress |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import React,{useEffect, useState} from 'react' | ||
import { useGlobalContext } from '../utils/context/globalContext' | ||
import { ethers } from 'ethers' | ||
import lotteryAbi from '../utils/contracts/lottery_abi.json' | ||
import { ContractAddresses } from '../utils/constants/addresses' | ||
|
||
type Ticket = { | ||
address: string, | ||
id: number, | ||
} | ||
|
||
const TicketOwner = (props:Ticket) => { | ||
return ( | ||
<div> | ||
ticket #{props.id} - {props.address.slice(0, 6) + '...' + props.address.slice(-4)} | ||
</div> | ||
) | ||
} | ||
|
||
const ListTicketOwners = ({ticketOwners}) => { | ||
const { provider, lotteryId } = useGlobalContext() | ||
// const [ticketOwners, setTicketOwners] = useState<Ticket[]>([]) | ||
|
||
return ( | ||
<div className='mt-4 bg-funBlue p-2 rounded'> | ||
<div className='text-xl mb-2'>Entries:</div> | ||
<div className='h-48 overflow-scroll bg-funRed rounded p-2'> | ||
{ticketOwners.length > 0 && ticketOwners.map((ticket, index) => { | ||
return <TicketOwner key={index} address={ticket.address} id={ticket.id}/> | ||
})} | ||
</div> | ||
</div> | ||
) | ||
} | ||
|
||
export default ListTicketOwners |
Oops, something went wrong.
e9350bd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
snowlottery – ./
snowlottery.vercel.app
snowlottery-paulrouge.vercel.app
snowlottery-git-main-paulrouge.vercel.app