├── .gitignore
├── .prettierignore
├── .prettierrc
├── README.md
├── components
├── Header.js
├── StakeDetails.js
└── StakeForm.js
├── constants
├── index.js
├── rewardTokenAbi.json
└── stakingAbi.json
├── next.config.js
├── package.json
├── pages
├── _app.js
├── api
│ └── hello.js
└── index.js
├── postcss.config.js
├── public
├── favicon.ico
└── vercel.svg
├── styles
├── Home.module.css
└── globals.css
├── tailwind.config.js
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | *.pem
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 | .pnpm-debug.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | artifacts
3 | cache
4 | coverage*
5 | gasReporterOutput.json
6 | package.json
7 | img
8 | .env
9 | .*
10 | README.md
11 | coverage.json
12 | deployments
13 | .next
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "tabWidth": 4,
3 | "useTabs": false,
4 | "semi": false,
5 | "singleQuote": false,
6 | "printWidth": 99
7 | }
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
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.js`. 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.js`.
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.
35 |
--------------------------------------------------------------------------------
/components/Header.js:
--------------------------------------------------------------------------------
1 | import { ConnectButton } from "web3uikit"
2 |
3 | export default function Header() {
4 | return (
5 |
11 | )
12 | }
13 |
--------------------------------------------------------------------------------
/components/StakeDetails.js:
--------------------------------------------------------------------------------
1 | // how many tokens are in our wallet
2 | // how many tokens are staked
3 | // how many tokens we have earned
4 | import { useMoralis, useWeb3Contract } from "react-moralis"
5 | import { stakingAddress, stakingAbi, rewardTokenAbi, rewardTokenAddress } from "../constants"
6 | import { useState, useEffect } from "react"
7 | import { ethers } from "ethers"
8 |
9 | export default function StakeDetails() {
10 | const { account, isWeb3Enabled } = useMoralis()
11 | const [rtBalance, setRtBalance] = useState("0")
12 | const [stakedBalance, setStakedBalance] = useState("0")
13 | const [earnedBalance, setEarned] = useState("0")
14 |
15 | const { runContractFunction: getRtBalance } = useWeb3Contract({
16 | abi: rewardTokenAbi,
17 | contractAddress: rewardTokenAddress,
18 | functionName: "balanceOf",
19 | params: {
20 | account: account,
21 | },
22 | })
23 |
24 | const { runContractFunction: getStakedBalance } = useWeb3Contract({
25 | abi: stakingAbi,
26 | contractAddress: stakingAddress,
27 | functionName: "getStaked",
28 | params: {
29 | account: account,
30 | },
31 | })
32 |
33 | const { runContractFunction: getEarned } = useWeb3Contract({
34 | abi: stakingAbi,
35 | contractAddress: stakingAddress,
36 | functionName: "earned",
37 | params: {
38 | account: account,
39 | },
40 | })
41 |
42 | useEffect(() => {
43 | // update the UI and get balances
44 | if (isWeb3Enabled && account) {
45 | updateUiValues()
46 | }
47 | }, [account, isWeb3Enabled])
48 |
49 | async function updateUiValues() {
50 | const rtBalanceFromContract = (
51 | await getRtBalance({ onError: (error) => console.log(error) })
52 | ).toString()
53 | const formatttedRtBalanceFromContract = ethers.utils.formatUnits(
54 | rtBalanceFromContract,
55 | "ether"
56 | )
57 | setRtBalance(formatttedRtBalanceFromContract)
58 |
59 | const stakedFromContract = (
60 | await getStakedBalance({ onError: (error) => console.log(error) })
61 | ).toString()
62 | const formatttedstakedFromContract = ethers.utils.formatUnits(stakedFromContract, "ether")
63 | setStakedBalance(formatttedstakedFromContract)
64 |
65 | const earnedFromContract = (
66 | await getEarned({ onError: (error) => console.log(error) })
67 | ).toString()
68 |
69 | console.log(`Earned: ${earnedFromContract}`)
70 |
71 | const formatttedEarnedFromContract = ethers.utils.formatUnits(earnedFromContract, "ether")
72 | setEarned(formatttedEarnedFromContract)
73 | }
74 |
75 | return (
76 |
77 |
RT Balance is: {rtBalance}
78 |
Earned Balance is: {earnedBalance}
79 |
Staked Balance is: {stakedBalance}
80 |
81 | )
82 | }
83 |
--------------------------------------------------------------------------------
/components/StakeForm.js:
--------------------------------------------------------------------------------
1 | // staking abi
2 | // staking address
3 | // how much they want to stake
4 | // approve our reward token
5 | import { useWeb3Contract } from "react-moralis"
6 | import { rewardTokenAbi, rewardTokenAddress, stakingAbi, stakingAddress } from "../constants"
7 | import { Form } from "web3uikit"
8 | import { ethers } from "ethers"
9 |
10 | export default function StakeForm() {
11 | const { runContractFunction } = useWeb3Contract()
12 | let approveOptions = {
13 | abi: rewardTokenAbi,
14 | contractAddress: rewardTokenAddress,
15 | functionName: "approve",
16 | }
17 | let stakeOptions = {
18 | abi: stakingAbi,
19 | contractAddress: stakingAddress,
20 | functionName: "stake",
21 | }
22 |
23 | async function handleStakeSubmit(data) {
24 | const amountToApprove = data.data[0].inputResult
25 | approveOptions.params = {
26 | amount: ethers.utils.parseUnits(amountToApprove, "ether").toString(),
27 | spender: stakingAddress,
28 | }
29 | console.log("Approving...")
30 | const tx = await runContractFunction({
31 | params: approveOptions,
32 | onError: (error) => console.log(error),
33 | onSuccess: () => {
34 | handleApproveSuccess(approveOptions.params.amount)
35 | },
36 | })
37 | }
38 |
39 | async function handleApproveSuccess(amountToStakeFormatted) {
40 | stakeOptions.params = {
41 | amount: amountToStakeFormatted,
42 | }
43 | console.log(`Staking ${stakeOptions.params.amount} RT Token...`)
44 | const tx = await runContractFunction({
45 | params: stakeOptions,
46 | onError: (error) => console.log(error),
47 | })
48 | await tx.wait(1)
49 | console.log("Transaction has been confirmed by 1 block")
50 | }
51 |
52 | return (
53 |
54 |
67 |
68 | )
69 | }
70 |
--------------------------------------------------------------------------------
/constants/index.js:
--------------------------------------------------------------------------------
1 | const stakingAddress = "0x0165878A594ca255338adfa4d48449f69242Eb8F"
2 | const rewardTokenAddress = "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707"
3 |
4 | const stakingAbi = require("./stakingAbi.json")
5 | const rewardTokenAbi = require("./rewardTokenAbi.json")
6 |
7 | module.exports = {
8 | stakingAbi,
9 | rewardTokenAbi,
10 | stakingAddress,
11 | rewardTokenAddress,
12 | }
13 |
--------------------------------------------------------------------------------
/constants/rewardTokenAbi.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [],
4 | "stateMutability": "nonpayable",
5 | "type": "constructor"
6 | },
7 | {
8 | "anonymous": false,
9 | "inputs": [
10 | {
11 | "indexed": true,
12 | "internalType": "address",
13 | "name": "owner",
14 | "type": "address"
15 | },
16 | {
17 | "indexed": true,
18 | "internalType": "address",
19 | "name": "spender",
20 | "type": "address"
21 | },
22 | {
23 | "indexed": false,
24 | "internalType": "uint256",
25 | "name": "value",
26 | "type": "uint256"
27 | }
28 | ],
29 | "name": "Approval",
30 | "type": "event"
31 | },
32 | {
33 | "anonymous": false,
34 | "inputs": [
35 | {
36 | "indexed": true,
37 | "internalType": "address",
38 | "name": "from",
39 | "type": "address"
40 | },
41 | {
42 | "indexed": true,
43 | "internalType": "address",
44 | "name": "to",
45 | "type": "address"
46 | },
47 | {
48 | "indexed": false,
49 | "internalType": "uint256",
50 | "name": "value",
51 | "type": "uint256"
52 | }
53 | ],
54 | "name": "Transfer",
55 | "type": "event"
56 | },
57 | {
58 | "inputs": [
59 | {
60 | "internalType": "address",
61 | "name": "owner",
62 | "type": "address"
63 | },
64 | {
65 | "internalType": "address",
66 | "name": "spender",
67 | "type": "address"
68 | }
69 | ],
70 | "name": "allowance",
71 | "outputs": [
72 | {
73 | "internalType": "uint256",
74 | "name": "",
75 | "type": "uint256"
76 | }
77 | ],
78 | "stateMutability": "view",
79 | "type": "function"
80 | },
81 | {
82 | "inputs": [
83 | {
84 | "internalType": "address",
85 | "name": "spender",
86 | "type": "address"
87 | },
88 | {
89 | "internalType": "uint256",
90 | "name": "amount",
91 | "type": "uint256"
92 | }
93 | ],
94 | "name": "approve",
95 | "outputs": [
96 | {
97 | "internalType": "bool",
98 | "name": "",
99 | "type": "bool"
100 | }
101 | ],
102 | "stateMutability": "nonpayable",
103 | "type": "function"
104 | },
105 | {
106 | "inputs": [
107 | {
108 | "internalType": "address",
109 | "name": "account",
110 | "type": "address"
111 | }
112 | ],
113 | "name": "balanceOf",
114 | "outputs": [
115 | {
116 | "internalType": "uint256",
117 | "name": "",
118 | "type": "uint256"
119 | }
120 | ],
121 | "stateMutability": "view",
122 | "type": "function"
123 | },
124 | {
125 | "inputs": [],
126 | "name": "decimals",
127 | "outputs": [
128 | {
129 | "internalType": "uint8",
130 | "name": "",
131 | "type": "uint8"
132 | }
133 | ],
134 | "stateMutability": "view",
135 | "type": "function"
136 | },
137 | {
138 | "inputs": [
139 | {
140 | "internalType": "address",
141 | "name": "spender",
142 | "type": "address"
143 | },
144 | {
145 | "internalType": "uint256",
146 | "name": "subtractedValue",
147 | "type": "uint256"
148 | }
149 | ],
150 | "name": "decreaseAllowance",
151 | "outputs": [
152 | {
153 | "internalType": "bool",
154 | "name": "",
155 | "type": "bool"
156 | }
157 | ],
158 | "stateMutability": "nonpayable",
159 | "type": "function"
160 | },
161 | {
162 | "inputs": [
163 | {
164 | "internalType": "address",
165 | "name": "spender",
166 | "type": "address"
167 | },
168 | {
169 | "internalType": "uint256",
170 | "name": "addedValue",
171 | "type": "uint256"
172 | }
173 | ],
174 | "name": "increaseAllowance",
175 | "outputs": [
176 | {
177 | "internalType": "bool",
178 | "name": "",
179 | "type": "bool"
180 | }
181 | ],
182 | "stateMutability": "nonpayable",
183 | "type": "function"
184 | },
185 | {
186 | "inputs": [],
187 | "name": "name",
188 | "outputs": [
189 | {
190 | "internalType": "string",
191 | "name": "",
192 | "type": "string"
193 | }
194 | ],
195 | "stateMutability": "view",
196 | "type": "function"
197 | },
198 | {
199 | "inputs": [],
200 | "name": "symbol",
201 | "outputs": [
202 | {
203 | "internalType": "string",
204 | "name": "",
205 | "type": "string"
206 | }
207 | ],
208 | "stateMutability": "view",
209 | "type": "function"
210 | },
211 | {
212 | "inputs": [],
213 | "name": "totalSupply",
214 | "outputs": [
215 | {
216 | "internalType": "uint256",
217 | "name": "",
218 | "type": "uint256"
219 | }
220 | ],
221 | "stateMutability": "view",
222 | "type": "function"
223 | },
224 | {
225 | "inputs": [
226 | {
227 | "internalType": "address",
228 | "name": "to",
229 | "type": "address"
230 | },
231 | {
232 | "internalType": "uint256",
233 | "name": "amount",
234 | "type": "uint256"
235 | }
236 | ],
237 | "name": "transfer",
238 | "outputs": [
239 | {
240 | "internalType": "bool",
241 | "name": "",
242 | "type": "bool"
243 | }
244 | ],
245 | "stateMutability": "nonpayable",
246 | "type": "function"
247 | },
248 | {
249 | "inputs": [
250 | {
251 | "internalType": "address",
252 | "name": "from",
253 | "type": "address"
254 | },
255 | {
256 | "internalType": "address",
257 | "name": "to",
258 | "type": "address"
259 | },
260 | {
261 | "internalType": "uint256",
262 | "name": "amount",
263 | "type": "uint256"
264 | }
265 | ],
266 | "name": "transferFrom",
267 | "outputs": [
268 | {
269 | "internalType": "bool",
270 | "name": "",
271 | "type": "bool"
272 | }
273 | ],
274 | "stateMutability": "nonpayable",
275 | "type": "function"
276 | }
277 | ]
--------------------------------------------------------------------------------
/constants/stakingAbi.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [
4 | {
5 | "internalType": "address",
6 | "name": "stakingToken",
7 | "type": "address"
8 | },
9 | {
10 | "internalType": "address",
11 | "name": "rewardsToken",
12 | "type": "address"
13 | }
14 | ],
15 | "stateMutability": "nonpayable",
16 | "type": "constructor"
17 | },
18 | {
19 | "inputs": [],
20 | "name": "NeedsMoreThanZero",
21 | "type": "error"
22 | },
23 | {
24 | "inputs": [],
25 | "name": "TransferFailed",
26 | "type": "error"
27 | },
28 | {
29 | "anonymous": false,
30 | "inputs": [
31 | {
32 | "indexed": true,
33 | "internalType": "address",
34 | "name": "user",
35 | "type": "address"
36 | },
37 | {
38 | "indexed": true,
39 | "internalType": "uint256",
40 | "name": "amount",
41 | "type": "uint256"
42 | }
43 | ],
44 | "name": "RewardsClaimed",
45 | "type": "event"
46 | },
47 | {
48 | "anonymous": false,
49 | "inputs": [
50 | {
51 | "indexed": true,
52 | "internalType": "address",
53 | "name": "user",
54 | "type": "address"
55 | },
56 | {
57 | "indexed": true,
58 | "internalType": "uint256",
59 | "name": "amount",
60 | "type": "uint256"
61 | }
62 | ],
63 | "name": "Staked",
64 | "type": "event"
65 | },
66 | {
67 | "anonymous": false,
68 | "inputs": [
69 | {
70 | "indexed": true,
71 | "internalType": "address",
72 | "name": "user",
73 | "type": "address"
74 | },
75 | {
76 | "indexed": true,
77 | "internalType": "uint256",
78 | "name": "amount",
79 | "type": "uint256"
80 | }
81 | ],
82 | "name": "WithdrewStake",
83 | "type": "event"
84 | },
85 | {
86 | "inputs": [],
87 | "name": "REWARD_RATE",
88 | "outputs": [
89 | {
90 | "internalType": "uint256",
91 | "name": "",
92 | "type": "uint256"
93 | }
94 | ],
95 | "stateMutability": "view",
96 | "type": "function"
97 | },
98 | {
99 | "inputs": [],
100 | "name": "claimReward",
101 | "outputs": [],
102 | "stateMutability": "nonpayable",
103 | "type": "function"
104 | },
105 | {
106 | "inputs": [
107 | {
108 | "internalType": "address",
109 | "name": "account",
110 | "type": "address"
111 | }
112 | ],
113 | "name": "earned",
114 | "outputs": [
115 | {
116 | "internalType": "uint256",
117 | "name": "",
118 | "type": "uint256"
119 | }
120 | ],
121 | "stateMutability": "view",
122 | "type": "function"
123 | },
124 | {
125 | "inputs": [
126 | {
127 | "internalType": "address",
128 | "name": "account",
129 | "type": "address"
130 | }
131 | ],
132 | "name": "getStaked",
133 | "outputs": [
134 | {
135 | "internalType": "uint256",
136 | "name": "",
137 | "type": "uint256"
138 | }
139 | ],
140 | "stateMutability": "view",
141 | "type": "function"
142 | },
143 | {
144 | "inputs": [],
145 | "name": "rewardPerToken",
146 | "outputs": [
147 | {
148 | "internalType": "uint256",
149 | "name": "",
150 | "type": "uint256"
151 | }
152 | ],
153 | "stateMutability": "view",
154 | "type": "function"
155 | },
156 | {
157 | "inputs": [
158 | {
159 | "internalType": "address",
160 | "name": "",
161 | "type": "address"
162 | }
163 | ],
164 | "name": "s_balances",
165 | "outputs": [
166 | {
167 | "internalType": "uint256",
168 | "name": "",
169 | "type": "uint256"
170 | }
171 | ],
172 | "stateMutability": "view",
173 | "type": "function"
174 | },
175 | {
176 | "inputs": [],
177 | "name": "s_lastUpdateTime",
178 | "outputs": [
179 | {
180 | "internalType": "uint256",
181 | "name": "",
182 | "type": "uint256"
183 | }
184 | ],
185 | "stateMutability": "view",
186 | "type": "function"
187 | },
188 | {
189 | "inputs": [],
190 | "name": "s_rewardPerTokenStored",
191 | "outputs": [
192 | {
193 | "internalType": "uint256",
194 | "name": "",
195 | "type": "uint256"
196 | }
197 | ],
198 | "stateMutability": "view",
199 | "type": "function"
200 | },
201 | {
202 | "inputs": [
203 | {
204 | "internalType": "address",
205 | "name": "",
206 | "type": "address"
207 | }
208 | ],
209 | "name": "s_rewards",
210 | "outputs": [
211 | {
212 | "internalType": "uint256",
213 | "name": "",
214 | "type": "uint256"
215 | }
216 | ],
217 | "stateMutability": "view",
218 | "type": "function"
219 | },
220 | {
221 | "inputs": [],
222 | "name": "s_rewardsToken",
223 | "outputs": [
224 | {
225 | "internalType": "contract IERC20",
226 | "name": "",
227 | "type": "address"
228 | }
229 | ],
230 | "stateMutability": "view",
231 | "type": "function"
232 | },
233 | {
234 | "inputs": [],
235 | "name": "s_stakingToken",
236 | "outputs": [
237 | {
238 | "internalType": "contract IERC20",
239 | "name": "",
240 | "type": "address"
241 | }
242 | ],
243 | "stateMutability": "view",
244 | "type": "function"
245 | },
246 | {
247 | "inputs": [
248 | {
249 | "internalType": "address",
250 | "name": "",
251 | "type": "address"
252 | }
253 | ],
254 | "name": "s_userRewardPerTokenPaid",
255 | "outputs": [
256 | {
257 | "internalType": "uint256",
258 | "name": "",
259 | "type": "uint256"
260 | }
261 | ],
262 | "stateMutability": "view",
263 | "type": "function"
264 | },
265 | {
266 | "inputs": [
267 | {
268 | "internalType": "uint256",
269 | "name": "amount",
270 | "type": "uint256"
271 | }
272 | ],
273 | "name": "stake",
274 | "outputs": [],
275 | "stateMutability": "nonpayable",
276 | "type": "function"
277 | },
278 | {
279 | "inputs": [
280 | {
281 | "internalType": "uint256",
282 | "name": "amount",
283 | "type": "uint256"
284 | }
285 | ],
286 | "name": "withdraw",
287 | "outputs": [],
288 | "stateMutability": "nonpayable",
289 | "type": "function"
290 | }
291 | ]
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | reactStrictMode: true,
4 | }
5 |
6 | module.exports = nextConfig
7 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "staking-ui",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "dependencies": {
12 | "moralis": "^1.6.0",
13 | "next": "12.1.6",
14 | "react": "18.1.0",
15 | "react-dom": "18.1.0",
16 | "react-moralis": "^1.3.5",
17 | "web3uikit": "^0.1.140"
18 | },
19 | "devDependencies": {
20 | "autoprefixer": "^10.4.7",
21 | "eslint": "8.14.0",
22 | "eslint-config-next": "12.1.6",
23 | "postcss": "^8.4.13",
24 | "prettier": "^2.6.2",
25 | "tailwindcss": "^3.0.24"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/pages/_app.js:
--------------------------------------------------------------------------------
1 | import "../styles/globals.css"
2 | import { MoralisProvider } from "react-moralis"
3 |
4 | function MyApp({ Component, pageProps }) {
5 | return (
6 |
7 |
8 |
9 | )
10 | }
11 |
12 | export default MyApp
13 |
--------------------------------------------------------------------------------
/pages/api/hello.js:
--------------------------------------------------------------------------------
1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction
2 |
3 | export default function handler(req, res) {
4 | res.status(200).json({ name: "John Doe" })
5 | }
6 |
--------------------------------------------------------------------------------
/pages/index.js:
--------------------------------------------------------------------------------
1 | import styles from "../styles/Home.module.css"
2 | import Header from "../components/Header"
3 | import StakeDetails from "../components/StakeDetails"
4 | import StakeForm from "../components/StakeForm"
5 | import { useChain } from "react-moralis"
6 |
7 | export default function Home() {
8 | const { switchNetwork, chainId, chain, account } = useChain()
9 | return (
10 |
11 |
12 |
13 |
14 |
15 | )
16 | }
17 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PatrickAlphaC/staking-ui-demo/f49bb5917c4469b03994762219a0f2b29f342607/public/favicon.ico
--------------------------------------------------------------------------------
/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/styles/Home.module.css:
--------------------------------------------------------------------------------
1 | .container {
2 | padding: 0 2rem;
3 | }
4 |
5 | .main {
6 | min-height: 100vh;
7 | padding: 4rem 0;
8 | flex: 1;
9 | display: flex;
10 | flex-direction: column;
11 | justify-content: center;
12 | align-items: center;
13 | }
14 |
15 | .footer {
16 | display: flex;
17 | flex: 1;
18 | padding: 2rem 0;
19 | border-top: 1px solid #eaeaea;
20 | justify-content: center;
21 | align-items: center;
22 | }
23 |
24 | .footer a {
25 | display: flex;
26 | justify-content: center;
27 | align-items: center;
28 | flex-grow: 1;
29 | }
30 |
31 | .title a {
32 | color: #0070f3;
33 | text-decoration: none;
34 | }
35 |
36 | .title a:hover,
37 | .title a:focus,
38 | .title a:active {
39 | text-decoration: underline;
40 | }
41 |
42 | .title {
43 | margin: 0;
44 | line-height: 1.15;
45 | font-size: 4rem;
46 | }
47 |
48 | .title,
49 | .description {
50 | text-align: center;
51 | }
52 |
53 | .description {
54 | margin: 4rem 0;
55 | line-height: 1.5;
56 | font-size: 1.5rem;
57 | }
58 |
59 | .code {
60 | background: #fafafa;
61 | border-radius: 5px;
62 | padding: 0.75rem;
63 | font-size: 1.1rem;
64 | font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
65 | Bitstream Vera Sans Mono, Courier New, monospace;
66 | }
67 |
68 | .grid {
69 | display: flex;
70 | align-items: center;
71 | justify-content: center;
72 | flex-wrap: wrap;
73 | max-width: 800px;
74 | }
75 |
76 | .card {
77 | margin: 1rem;
78 | padding: 1.5rem;
79 | text-align: left;
80 | color: inherit;
81 | text-decoration: none;
82 | border: 1px solid #eaeaea;
83 | border-radius: 10px;
84 | transition: color 0.15s ease, border-color 0.15s ease;
85 | max-width: 300px;
86 | }
87 |
88 | .card:hover,
89 | .card:focus,
90 | .card:active {
91 | color: #0070f3;
92 | border-color: #0070f3;
93 | }
94 |
95 | .card h2 {
96 | margin: 0 0 1rem 0;
97 | font-size: 1.5rem;
98 | }
99 |
100 | .card p {
101 | margin: 0;
102 | font-size: 1.25rem;
103 | line-height: 1.5;
104 | }
105 |
106 | .logo {
107 | height: 1em;
108 | margin-left: 0.5rem;
109 | }
110 |
111 | @media (max-width: 600px) {
112 | .grid {
113 | width: 100%;
114 | flex-direction: column;
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/styles/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | content: ["./pages/**/*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}"],
3 | theme: {
4 | extend: {},
5 | },
6 | plugins: [],
7 | }
8 |
--------------------------------------------------------------------------------