-
-
Notifications
You must be signed in to change notification settings - Fork 805
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* added web3-staking-dapp * removed files * removed artifacts files * modified gitignore * made the requested changes * edited readme files * resolved the problems * removed styles.css link Co-authored-by: Sachin Chaurasiya <sachinchaurasiyachotey87@gmail.com>
- Loading branch information
1 parent
266a6a8
commit 2d47b55
Showing
15 changed files
with
972 additions
and
0 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
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,3 @@ | ||
node_modules | ||
.env | ||
cache/* |
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,41 @@ | ||
# Web3 Staking Dapp | ||
|
||
It is a staking dapp built upon polygon testnet in which users can stake matic testnet tokens for a particular time period and gain interest after the completion of the period. | ||
|
||
## Play Demographic | ||
|
||
- Language: js | ||
- Level: Intermediate | ||
|
||
## Creator Information | ||
|
||
- User: nirban256 | ||
- Gihub Link: https://github.com/nirban256 | ||
- Blog: null | ||
- Video: https://www.youtube.com/watch?v=AjaHJicbPkM&ab_channel=NirbanChakraborty | ||
|
||
## Implementation Details | ||
|
||
The implementation of the Web3 staking dapp play is quite simple. | ||
|
||
- All start with `Navbar.js` component, every time when you run the play it will first check whether you have a wallet extension like Metamask in your browser or not, if not then the play will not work. If you have the extension then it will connect with your wallet. | ||
|
||
- `stakeMatic()` function in `smart-contract/contracts/Staking.sol` is responsible for staking matic tokens. whenever it gets called it stake the amount specified by you from your wallet to the dapps contract. | ||
|
||
- `withdrawToken` function in `smart-contract/contracts/Staking.sol` is responsible for withdrawing tokens from the dapp. | ||
|
||
- There are two cases that the user will get: | ||
|
||
- If you withdraw before the staking period completes then you will not receive the interest. | ||
- If you withdraw after the staking period then you will get the amount you staked along with the interest. | ||
|
||
|
||
## Consideration | ||
|
||
- Use the polygon testnet tokens to use the dapp. | ||
|
||
## Resources | ||
|
||
- A browser wallet like Metamask. | ||
- A little knowledge about Web3 dapps functionality. | ||
- Dependencies: HardHat, Ethers |
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,271 @@ | ||
import PlayHeader from 'common/playlists/PlayHeader'; | ||
import React, { useState, useEffect } from "react"; | ||
import artifact from "./artifacts/contracts/Staking.sol/Staking.json"; | ||
import { ethers } from "ethers"; | ||
import Navbar from "./components/Navbar"; | ||
import maticLogo from "./images/polygon-matic-logo.svg"; | ||
import { FaRupeeSign } from 'react-icons/fa'; | ||
import { ContractAddress } from './constant'; | ||
|
||
// WARNING: Do not change the entry componenet name | ||
function Web3StakingDapp(props) { | ||
|
||
// Your Code Start below. | ||
|
||
// frontend states | ||
const [provider, setProvider] = useState(); | ||
const [account, setAccount] = useState(); | ||
const [contract, setContract] = useState(); | ||
const [accountAddress, setAccountAddress] = useState(); | ||
|
||
// assets | ||
const [assetId, setAssetId] = useState([]); | ||
const [assets, setAssets] = useState([]); | ||
|
||
// staking | ||
const [stakeModal, setStakeModal] = useState(false); | ||
const [stakingLength, setStakingLength] = useState(); | ||
const [stakingPercent, setStakingPercent] = useState(); | ||
const [amount, setAmount] = useState(0); | ||
|
||
// functions | ||
const toWei = ether => ethers.utils.parseEther(ether); | ||
const toMatic = wei => ethers.utils.formatEther(wei); | ||
|
||
const onload = async () => { | ||
const provider = new ethers.providers.Web3Provider(window.ethereum); | ||
setProvider(provider); | ||
|
||
const contract = new ethers.Contract( | ||
ContractAddress, | ||
artifact.abi | ||
) | ||
setContract(contract); | ||
} | ||
|
||
useEffect(() => { | ||
onload(); | ||
}, []) | ||
|
||
const isConnected = () => account !== undefined; | ||
|
||
const getAssetIds = async (address, account) => { | ||
const assetIds = await contract.connect(account).getStakerIdsByAddresses(address); | ||
|
||
return assetIds; | ||
} | ||
|
||
const getAssets = async (ids, account) => { | ||
const loopedAssets = await Promise.all( | ||
ids.map(id => contract.connect(account).getStakersById(id)) | ||
) | ||
|
||
loopedAssets.map(async asset => { | ||
const parsedAsset = { | ||
stakersId: asset.stakerId, | ||
percentInterest: Number(asset.interestPercentage) / 100, | ||
daysRemaining: daysRemaining(Number(asset.dateUnlocked)), | ||
maticInterest: toMatic(asset.interest), | ||
maticStaked: toMatic(asset.amountStaked), | ||
open: asset.open | ||
} | ||
|
||
setAssets(prev => [...prev, parsedAsset]); | ||
}) | ||
} | ||
|
||
const getAccount = async () => { | ||
await provider.send("eth_requestAccounts", []) | ||
|
||
const account = provider.getSigner() | ||
return account; | ||
} | ||
|
||
const connectAndLoadWallet = async () => { | ||
const account = await getAccount(provider) | ||
setAccount(account); | ||
|
||
const accountAddress = await account.getAddress(); | ||
setAccountAddress(accountAddress); | ||
|
||
const assetIds = await getAssetIds(accountAddress, account); | ||
setAssetId(assetIds); | ||
|
||
getAssets(assetIds, account); | ||
} | ||
|
||
const stakeMatic = () => { | ||
const wei = toWei(amount); | ||
const data = { value: wei }; | ||
|
||
contract.connect(account).stakeMatic(stakingLength, data) | ||
} | ||
|
||
const stakingModal = (stakingLength, stakingPercent) => { | ||
setStakeModal(true); | ||
setStakingLength(stakingLength); | ||
setStakingPercent(stakingPercent); | ||
} | ||
|
||
const daysRemaining = (unlockDate) => { | ||
const currentTime = Date.now() / 1000; | ||
const remainingTime = unlockDate - currentTime; | ||
|
||
return Math.max((remainingTime / 60 / 60 / 24).toFixed(0), 0); | ||
} | ||
|
||
const withdraw = (stakersId) => { | ||
contract.connect(account).withdrawMatic(stakersId); | ||
} | ||
|
||
return ( | ||
<> | ||
<div className="play-details"> | ||
<PlayHeader play={props} /> | ||
<div className="play-details-body"> | ||
{/* Your Code Starts Here */} | ||
|
||
<div> | ||
<div> | ||
<Navbar isConnected={isConnected} connect={connectAndLoadWallet} /> | ||
</div> | ||
|
||
<div className=" bg-white rounded-xl md:rounded-3xl my-8 max-w-5xl block m-auto border-[0.5px] border-solid border-[#00f1fe80]"> | ||
<div className=" px-3 py-5 md:px-8 md:py-8"> | ||
<div className=" flex justify-center"> | ||
<span> | ||
<img src={maticLogo} alt="matic logo" className=" w-8 h-8 lg:w-12 lg:h-12" /> | ||
</span> | ||
<span className=" text-3xl lg:text-5xl font-semibold px-4 text-[#010326]">Matic Market</span> | ||
</div> | ||
|
||
<div className=" flex justify-between items-center my-6 md:my-8"> | ||
{stakeModal === false ? | ||
( | ||
<> | ||
<div className=" flex"> | ||
<button type='submit' className="bg-[#00f1fec5] hover:bg-[#00f1fe] px-2 rounded-lg" onClick={() => stakingModal(30, '7%')}> | ||
<FaRupeeSign color='#010326' className='w-8' /> | ||
</button> | ||
|
||
<div className="flex justify-center items-center flex-col-reverse font-bold px-2 text-[#010326]"> | ||
<span className='text-[#010326]'>1 Month</span> | ||
<span className="text-[#010326]">7%</span> | ||
</div> | ||
</div> | ||
|
||
<div className=" flex"> | ||
<button type='submit' className="bg-[#00f1fec5] hover:bg-[#00f1fe] px-2 rounded-lg" onClick={() => stakingModal(90, '10%')}> | ||
<FaRupeeSign color='#010326' className=' w-8' /> | ||
</button> | ||
|
||
<div className="flex justify-center items-center flex-col-reverse font-bold px-2"> | ||
<span className='text-[#010326]'>3 Months</span> | ||
<span className="text-[#010326]">10%</span> | ||
</div> | ||
</div> | ||
|
||
<div className=" flex"> | ||
<button type='submit' className="bg-[#00f1fec5] hover:bg-[#00f1fe] px-2 rounded-lg" onClick={() => stakingModal(180, '14%')}> | ||
<FaRupeeSign color='#010326' className=' w-8' /> | ||
</button> | ||
|
||
<div className="flex justify-center items-center flex-col-reverse font-bold px-2"> | ||
<span className='text-[#010326]'>6 Months</span> | ||
<span className="text-[#010326]">14%</span> | ||
</div> | ||
</div> | ||
</> | ||
) | ||
: | ||
( | ||
(isConnected !== undefined ? | ||
( | ||
<div className='flex flex-col justify-center items-center'> | ||
<div className="" onClick={e => e.stopPropagation()}> | ||
<div className=""> | ||
<h2 className='text-[#010326] font-medium text-3xl mb-2'>Stake Matic</h2> | ||
<div className="flex items-center text-[#010326] font-medium text-2xl"> | ||
<div className=""> | ||
<input className=' bg-slate-300 outline-none rounded-lg px-4 py-2' type="number" placeholder='0.0' onChange={e => setAmount(e.target.value)} /> | ||
</div> | ||
|
||
<div className='text-[#010326] font-medium text-3xl px-3'> | ||
<span>Matic</span> | ||
</div> | ||
</div> | ||
|
||
<div className=""> | ||
<h4 className='text-[#010326] font-medium text-2xl my-4'> | ||
{stakingLength} days @ {stakingPercent} APY | ||
</h4> | ||
</div> | ||
|
||
<div className=""> | ||
<button type='submit' className="bg-[#00f1fec5] hover:bg-[#00f1fe] rounded-3xl px-2 py-1 text-base md:px-5 md:py-2 md:text-xl font-semibold text-[#010326]" onClick={() => stakeMatic(amount)}> | ||
Stake Matic | ||
</button> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
) | ||
: | ||
( | ||
<p className='text-[#010326] font-medium text-lg'>Connect Wallet to stake matic</p> | ||
) | ||
) | ||
) | ||
} | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<div className="bg-white rounded-xl md:rounded-3xl my-8 max-w-5xl block m-auto border-[1px] border-solid border-[#00f1fe80] text-center md:px-4"> | ||
<div className="font-bold flex justify-center py-6"> | ||
<span className="text-[#010326] text-3xl">Staked Assets</span> | ||
</div> | ||
|
||
<div> | ||
<ul className="font-semibold flex justify-between px-3"> | ||
<li className="text-[#010326]">Staked</li> | ||
<li className="text-[#010326]">Interest</li> | ||
<li className="text-[#010326]">Time Left</li> | ||
<li className="text-[#010326]">Withdraw</li> | ||
</ul> | ||
</div> | ||
<br /> | ||
|
||
{assets.length > 0 && assets.map((asset, index) => ( | ||
<div className="flex justify-between font-medium px-3 py-3 items-center"> | ||
<div className="text-[#010326] text-center pl-4"> | ||
{asset.maticStaked} | ||
</div> | ||
<div className="text-[#010326] text-center pl-2"> | ||
{asset.percentInterest} % | ||
</div> | ||
<div className="text-[#010326] text-center pl-6"> | ||
{asset.daysRemaining} | ||
</div> | ||
<div className="pl-6"> | ||
{asset.open ? ( | ||
<button type='submit' className="bg-[#00f1fec5] hover:bg-[#00f1fe] rounded-2xl px-1 py-1 md:px-2 md:py-2 md:font-semibold text-[#010326]" onClick={() => withdraw(asset.stakersId)}> | ||
Withdraw | ||
</button> | ||
) : ( | ||
<span className='text-[#010326] bg-white'>Closed</span> | ||
)} | ||
</div> | ||
</div> | ||
))} | ||
</div> | ||
</div> | ||
|
||
{/* Your Code Ends Here */} | ||
</div> | ||
</div > | ||
</> | ||
); | ||
} | ||
|
||
export default Web3StakingDapp; |
1 change: 1 addition & 0 deletions
1
src/plays/web3-staking-dapp/artifacts/build-info/5faf9c6c2f8753632f3c7c13937cd196.json
Large diffs are not rendered by default.
Oops, something went wrong.
4 changes: 4 additions & 0 deletions
4
src/plays/web3-staking-dapp/artifacts/contracts/Staking.sol/Staking.dbg.json
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,4 @@ | ||
{ | ||
"_format": "hh-sol-dbg-1", | ||
"buildInfo": "..\\..\\build-info\\5faf9c6c2f8753632f3c7c13937cd196.json" | ||
} |
Oops, something went wrong.
2d47b55
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:
react-play – ./
react-play-reactplayio.vercel.app
reactoplay.vercel.app
react-play-git-main-reactplayio.vercel.app