diff --git a/src/abis/sharesTimeLock.json b/src/abis/sharesTimeLock.json new file mode 100644 index 00000000..da9939dd --- /dev/null +++ b/src/abis/sharesTimeLock.json @@ -0,0 +1 @@ +[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"BoostedToMax","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"lockDuration","type":"uint32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"Ejected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newLockAmount","type":"uint256"}],"name":"MinLockAmountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"bool","name":"whitelisted","type":"bool"}],"name":"WhitelistedChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"Withdrawn","type":"event"},{"inputs":[{"internalType":"uint256","name":"lockId","type":"uint256"}],"name":"boostToMax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"lockId","type":"uint256"}],"name":"canEject","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"months","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"depositByMonths","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"lockAccounts","type":"address[]"},{"internalType":"uint256[]","name":"lockIds","type":"uint256[]"}],"name":"eject","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getLocksOfLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"duration","type":"uint32"}],"name":"getRewardsMultiplier","outputs":[{"internalType":"uint256","name":"multiplier","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getStakingData","outputs":[{"components":[{"internalType":"uint256","name":"totalStaked","type":"uint256"},{"internalType":"uint256","name":"rewardTokenTotalSupply","type":"uint256"},{"internalType":"uint256","name":"accountRewardTokenBalance","type":"uint256"},{"internalType":"uint256","name":"accountWithdrawableRewards","type":"uint256"},{"internalType":"uint256","name":"accountWithdrawnRewards","type":"uint256"},{"internalType":"uint256","name":"accountDepositTokenBalance","type":"uint256"},{"internalType":"uint256","name":"accountDepositTokenAllowance","type":"uint256"},{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint32","name":"lockedAt","type":"uint32"},{"internalType":"uint32","name":"lockDuration","type":"uint32"}],"internalType":"struct SharesTimeLock.Lock[]","name":"accountLocks","type":"tuple[]"}],"internalType":"struct SharesTimeLock.StakingData","name":"data","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"depositToken_","type":"address"},{"internalType":"contract ERC20NonTransferableRewardsOwned","name":"rewardsToken_","type":"address"},{"internalType":"uint32","name":"minLockDuration_","type":"uint32"},{"internalType":"uint32","name":"maxLockDuration_","type":"uint32"},{"internalType":"uint256","name":"minLockAmount_","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"locksOf","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint32","name":"lockedAt","type":"uint32"},{"internalType":"uint32","name":"lockDuration","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxLockDuration","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minLockAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minLockDuration","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardsToken","outputs":[{"internalType":"contract ERC20NonTransferableRewardsOwned","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"secPerMonth","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"minLockAmount_","type":"uint256"}],"name":"setMinLockAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"secondsPerMonth_","type":"uint256"}],"name":"setSecondsPerMonth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bool","name":"isWhitelisted","type":"bool"}],"name":"setWhitelisted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"lockId","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/src/abis/veDoughABI.json b/src/abis/veDoughABI.json new file mode 100644 index 00000000..cfd00b4a --- /dev/null +++ b/src/abis/veDoughABI.json @@ -0,0 +1 @@ +[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"collector","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"ClaimedFor","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"by","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardsDistributed","type":"uint256"}],"name":"RewardsDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"by","type":"address"},{"indexed":false,"internalType":"uint256","name":"fundsWithdrawn","type":"uint256"}],"name":"RewardsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAINTAINER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"claimFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"cumulativeRewardsOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"distributeRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getPointsCorrection","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"address","name":"token_","type":"address"},{"internalType":"address","name":"maintainer_","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"participationMerkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pointsPerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"bytes32[][]","name":"proofs","type":"bytes32[][]"}],"name":"redistribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"redistributeDust","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"newParticipationMerkleRoot","type":"bytes32"}],"name":"setParticipationMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"withdrawableRewardsOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"withdrawnRewardsOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/src/classes/MerkleTreeUtils.js b/src/classes/MerkleTreeUtils.js new file mode 100644 index 00000000..509baf6f --- /dev/null +++ b/src/classes/MerkleTreeUtils.js @@ -0,0 +1,146 @@ +import { ethers } from 'ethers'; + +class MerkleTree { + constructor(elements) { + // Filter empty strings and hash elements + // NOTE do not double has leafs + // this.elements = elements.filter(el => el).map(el => keccakFromString(el)); + this.elements = elements; + // Sort elements + this.elements.sort(); + // Deduplicate elements + // this.elements = this.bufDedup(this.elements); + + // Create layers + this.layers = this.getLayers(this.elements); + } + + getLayers(elements) { + if (elements.length === 0) { + return [['']]; + } + + const layers = []; + layers.push(elements); + + // Get next layer until we reach the root + while (layers[layers.length - 1].length > 1) { + layers.push(this.getNextLayer(layers[layers.length - 1])); + } + + return layers; + } + + getNextLayer(elements) { + return elements.reduce((layer, el, idx, arr) => { + if (idx % 2 === 0) { + // Hash the current element with its pair element + layer.push(this.combinedHash(el, arr[idx + 1])); + } + + return layer; + }, []); + } + + combinedHash(first, second) { + if (!first) { return second; } + if (!second) { return first; } + + return ethers.utils.solidityKeccak256(['bytes32', 'bytes32'], [first, second].sort()); + } + + getRoot() { + return this.layers[this.layers.length - 1][0]; + } + + getHexRoot() { + return bufferToHex(this.getRoot()); + } + + getProof(el) { + let idx = this.bufIndexOf(el, this.elements); + + if (idx === -1) { + throw new Error('Element does not exist in Merkle tree'); + } + + return this.layers.reduce((proof, layer) => { + const pairElement = this.getPairElement(idx, layer); + + if (pairElement) { + proof.push(pairElement); + } + + idx = Math.floor(idx / 2); + + return proof; + }, []); + } + + getHexProof(el) { + const proof = this.getProof(el); + + return this.bufArrToHexArr(proof); + } + + getPairElement(idx, layer) { + const pairIdx = idx % 2 === 0 ? idx + 1 : idx - 1; + + if (pairIdx < layer.length) { + return layer[pairIdx]; + } + return null; + } + + bufIndexOf(el, arr) { + let hash; + + hash = el; + + for (let i = 0; i < arr.length; i++) { + if (hash == arr[i]) { + return i; + } + } + + return -1; + } + + bufDedup(elements) { + return elements.filter((el, idx) => idx === 0 || !elements[idx - 1].equals(el)); + } + + bufArrToHexArr(arr) { + if (arr.some((el) => !Buffer.isBuffer(el))) { + throw new Error('Array is not an array of buffers'); + } + + return arr.map((el) => `0x${el.toString('hex')}`); + } +} + +const hashEntry = (entry) => ethers.utils.solidityKeccak256( + ['address', 'uint256'], + [ + entry.address, + entry.participation, + ], +); + +// eslint-disable-next-line import/prefer-default-export +export const createParticipationTree = (entries = []) => { + const entriesWithLeafs = entries.map((item) => { + const entryWithLeaf = { + ...item, + leaf: hashEntry(item), + }; + + return entryWithLeaf; + }); + + console.log('entriesWithLeafs', entriesWithLeafs) + return { + merkleTree: new MerkleTree(entriesWithLeafs.map((item) => item.leaf)), + leafs: entriesWithLeafs, + }; +}; diff --git a/src/config/env.json b/src/config/env.json index 52d38c55..86c224d1 100644 --- a/src/config/env.json +++ b/src/config/env.json @@ -1,6 +1,6 @@ { "blocknative": { "dappId": "523b279d-0fe0-42e8-8977-e688c3686e57", - "networkId": 1 + "networkId": 4 } } diff --git a/src/config/images.json b/src/config/images.json index 5613ea10..2f114df0 100644 --- a/src/config/images.json +++ b/src/config/images.json @@ -125,7 +125,9 @@ "earntogether": "https://raw.githubusercontent.com/pie-dao/brand/master/misc/earntogether2.png", "metavote": "https://raw.githubusercontent.com/pie-dao/brand/master/misc/metavote2.png", "InfoIcon": "https://raw.githubusercontent.com/pie-dao/brand/eaee121300a4c64c1293bb0f80723539357696c5/misc/Infoicon.svg", - "extLink": "https://raw.githubusercontent.com/pie-dao/brand/2deb3b9bb0c666a34dd715dce0f5a48e71ea3fe1/misc/external-link.svg" + "extLink": "https://raw.githubusercontent.com/pie-dao/brand/2deb3b9bb0c666a34dd715dce0f5a48e71ea3fe1/misc/external-link.svg", + "veDough": "https://raw.githubusercontent.com/pie-dao/brand/6adcf8b3a75380cc49ea119150b683a031afa016/PIE%20Tokens/veDOUGH.svg", + "rewardsPie": "https://raw.githubusercontent.com/pie-dao/brand/6adcf8b3a75380cc49ea119150b683a031afa016/PIE%20Tokens/RewardPie.svg" diff --git a/src/config/rewards/test.json b/src/config/rewards/test.json new file mode 100644 index 00000000..81d550c9 --- /dev/null +++ b/src/config/rewards/test.json @@ -0,0 +1,55 @@ +[ + { + "address": "0xd18a54f89603Fe4301b29EF6a8ab11b9Ba24f139", + "participation": 1 + }, + { + "address": "0xe89dEe662C94FfEE76d0942f4a4bAD27cC076dd2", + "participation": 0 + }, + + { + "address": "0xCB388d0f190496109316e0d5526DA46D72E52F61", + "participation": 1 + }, + { + "address": "0xc96265c36F6D77747f9c259946a1eF55FcE946b7", + "participation": 0 + }, + + { + "address": "0x16B89DF3B761D83D772376d3D18AeE63f7D74Dfd", + "participation": 1 + }, + { + "address": "0x51BB5E83a7e686e39ec0d6FCFe62A0402f7Ef8f6", + "participation": 0 + }, + + { + "address": "0x3d867dBbb7e5a448A6864DA063D9AB723Aec90c2", + "participation": 1 + }, + { + "address": "0x70E2402986807128Ff949579A8d444ec9465AEFf", + "participation": 0 + }, + + { + "address": "0x1e17A75616cd74f5846B1b71622Aa8e10ea26Cc0", + "participation": 1 + }, + { + "address": "0x9B83fb36D0c865E0C8a539759f1F97146D748DAb", + "participation": 0 + }, + + { + "address": "0x42556f667Dfc74704914F98d1e0c0aC4Ea2f492e", + "participation": 1 + }, + { + "address": "0x7884C447d5CD98e794c1A5c08e3107fbF29B2877", + "participation": 0 + } +] \ No newline at end of file diff --git a/src/config/smartcontracts.json b/src/config/smartcontracts.json index 26760d92..4b25333b 100644 --- a/src/config/smartcontracts.json +++ b/src/config/smartcontracts.json @@ -3,5 +3,8 @@ "recipe_old": "0xE1F9E100cbF4aD6D546b196Af33E1129Dd0866b3", "recipev1": "0x6cb4b8669e23295563d3b34df4a760c0cee993c7", "stakingPools": "0x6de77A304609472A4811a0BFD47d8682Aebc29df", - "eDOUGH": "0x63cbd1858bd79de1a06c3c26462db360b834912d" + "eDOUGH": "0x63cbd1858bd79de1a06c3c26462db360b834912d", + "doughStaking": "0x03508154Dd64aCe391D1f0bdaAe9e426Be4A9e05", + "veDOUGH": "0x6f64B2626939A313B831D435fc68238e35CA5f97", + "dough": "0x6503e51056C881Ebf463207f8E969fA45A1E0747" } \ No newline at end of file diff --git a/src/pages/DoughStaking.svelte b/src/pages/DoughStaking.svelte new file mode 100644 index 00000000..98512ea4 --- /dev/null +++ b/src/pages/DoughStaking.svelte @@ -0,0 +1,491 @@ + + +
+
DOUGH Staking
+
+ The new Stake, under development. +
+ + {#if !isLoading} +
+
+
+
Amount to Stake
+
+
{ + stakeAmount = toNum(data.accountDepositTokenBalance); + }} + > + Max balance: {toNum(data.accountDepositTokenBalance)} +
+
+
+
+ + + dough token + DOUGH + +
+
+ +
+
+
Stake Duration (Months)
+
+
{ + stakeDuration = 36; + }} + > + Max 36 Months +
+
+
+
+ + + dough token + 3 Years + +
+
+ +
+
+
Receiver
+
+
{ + receiver = $eth.address; + }} + > + {$eth.shortAddress} +
+
+
+
+ +
+
+ + {#if data.accountDepositTokenBalance.eq(0)} + + {:else} + {#if stakeAmount } + {#if toBN(stakeAmount).isGreaterThan(data.accountDepositTokenBalance)} + + {:else if toBN(stakeAmount).isGreaterThan(data.accountDepositTokenAllowance)} + + {:else} + {#if stakeDuration && stakeDuration > 5 && stakeDuration < 37} + + {:else} + + {/if} + {/if} + {:else} + + {/if} + {/if} + +
+ +
+
+
+ + Total Staked: {toNum(data.totalStaked)} + dough token + DOUGH + +
+ +
Account Reward Token Balance: {toNum(data.accountRewardTokenBalance)}
+
Account Withdrawable Rewards: {toNum(data.accountWithdrawableRewards)} + +
+
Account Withdrawn Rewards: {toNum(data.accountWithdrawnRewards)}
+
Select the item you wish to unstake from the list.
+
+ + +
+{:else} + Loading... +{/if} +
diff --git a/src/stores/eth.js b/src/stores/eth.js index b81a4fd3..42ee5601 100644 --- a/src/stores/eth.js +++ b/src/stores/eth.js @@ -108,9 +108,9 @@ export const trackGasPrice = async () => subject('gasPrice'); // Shortcuts -export const approve = async (address, spender, amount) => { +export const approve = async (address, spender, amount, overrides = {}) => { const erc20Contract = await contract({ address, abi: erc20 }); - const { hash } = await erc20Contract['approve(address,uint256)'](spender, amount); + const { hash } = await erc20Contract['approve(address,uint256)'](spender, amount, overrides); const { emitter } = displayNotification({ hash }); const symbol = await erc20Contract.symbol(); @@ -134,8 +134,9 @@ export const approve = async (address, spender, amount) => { if (currentBlockNumber > lastBlock) { eth.set({ ...get(eth), currentBlockNumber }); } -}; -export const approveMax = async (address, spender) => { - await approve(address, spender, ethers.constants.MaxUint256); + return true; }; + +// eslint-disable-next-line max-len +export const approveMax = async (address, spender, overrides = {}) => approve(address, spender, ethers.constants.MaxUint256, overrides); diff --git a/src/stores/routes.js b/src/stores/routes.js index 6a0a3e8a..1a13ca0c 100644 --- a/src/stores/routes.js +++ b/src/stores/routes.js @@ -22,6 +22,7 @@ import PiePageSwitch from '../pages/PiePageSwitch.svelte'; import Learn from '../pages/Learn.svelte'; import Integrations from '../pages/Integrations.svelte'; import Piefolio from '../pages/Piefolio.svelte'; +import DoughStaking from '../pages/DoughStaking.svelte'; import Farm from '../pages/Farm.svelte'; export const defaultRouteObj = { @@ -107,6 +108,8 @@ const formatRoute = (route) => { return { page: LPStakingV2 }; case 'farm': return { page: Farm }; + case 'new_staking': + return { page: DoughStaking }; case 'stake': referral = route[1] || null;