From 2df0861a5f04b11624570c00fb70396ba23e9224 Mon Sep 17 00:00:00 2001 From: mumeen Date: Sat, 1 Oct 2022 14:33:50 +0100 Subject: [PATCH 1/5] read dao properties from blockchain instead of backend --- src/App.tsx | 140 +++++++--- src/abis/deployer.json | 249 ++++++++++++++++++ .../create/CreateKeyPermissions.tsx | 49 +++- src/components/daoProfile/About.tsx | 200 +++++++------- src/components/daoProfile/Members.tsx | 60 ++++- src/components/daoProfile/Proposals.tsx | 129 +++++---- src/components/proposal/ChooseDao.tsx | 129 +++++---- src/modals/ProposalVotingModal.tsx | 78 ++++-- src/pages/DaoProfile.tsx | 81 +++++- src/pages/Discover.tsx | 4 +- src/services/web3.ts | 22 +- 11 files changed, 856 insertions(+), 285 deletions(-) create mode 100644 src/abis/deployer.json diff --git a/src/App.tsx b/src/App.tsx index 0178c8d..78df7fc 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,107 +1,173 @@ -import React from 'react'; -import { ToastContainer } from 'react-toastify'; -import 'react-toastify/dist/ReactToastify.css'; -import { BrowserRouter, Routes, Route } from 'react-router-dom'; -import { ProfileProvider } from './context/ProfileContext' -import { CreateDaoContextProvider } from './context/CreateDaoContext' -import { CreateProposalContextProvider } from './context/CreateProposalContext' -import { DaoProposalProvider } from './context/DaoProposalContext' -import { DeployDaoProvider } from './context/DeployDaoContext' -import { Main, Vote, Governance, Create, Discover, Faq, AboutUs, UserProfile, DaoProfile } from './pages'; -import { Navbar, Footer } from './components'; - +import React from "react"; +import { ToastContainer } from "react-toastify"; +import "react-toastify/dist/ReactToastify.css"; +import { BrowserRouter, Routes, Route } from "react-router-dom"; +import { ProfileProvider } from "./context/ProfileContext"; +import { CreateDaoContextProvider } from "./context/CreateDaoContext"; +import { CreateProposalContextProvider } from "./context/CreateProposalContext"; +import { DaoProposalProvider } from "./context/DaoProposalContext"; +import { DeployDaoProvider } from "./context/DeployDaoContext"; +import { + Main, + Vote, + Governance, + Create, + Discover, + Faq, + AboutUs, + UserProfile, + DaoProfile, +} from "./pages"; +import { Navbar, Footer } from "./components"; const App: React.FC = () => { return ( {/* */} - +
- + -
- + } /> - - - - + + } /> - - - + + } /> - - + } /> - - + } /> - - + } /> - - + } /> - - + + + } + /> + + + } /> - - + } /> -
+
-
+
{/*
*/}
); diff --git a/src/abis/deployer.json b/src/abis/deployer.json new file mode 100644 index 0000000..007d28d --- /dev/null +++ b/src/abis/deployer.json @@ -0,0 +1,249 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Deployer", + "sourceName": "contracts/Deployer/Deployer.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_UNIVERSAL_PROFILE_DEPLOYER", + "type": "address" + }, + { + "internalType": "address", + "name": "_DAO_DEPLOYER", + "type": "address" + }, + { + "internalType": "address", + "name": "_MULTISIG_DEPLOYER", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_unviersalReceiverDelegateUPAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_universalProfileMetadata", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "_multisigQuorum", + "type": "bytes32" + }, + { + "internalType": "address[]", + "name": "_multisigParticipants", + "type": "address[]" + }, + { + "internalType": "bytes32[]", + "name": "_multisigParticipantsPermissions", + "type": "bytes32[]" + } + ], + "name": "deploy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_unviersalReceiverDelegateUPAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_universalProfileMetadata", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "_daoData", + "type": "bytes32[]" + }, + { + "internalType": "address[]", + "name": "_daoParticipants", + "type": "address[]" + }, + { + "internalType": "bytes32[]", + "name": "_daoParticipantsPermissions", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "_multisigQuorum", + "type": "bytes32" + }, + { + "internalType": "address[]", + "name": "_multisigParticipants", + "type": "address[]" + }, + { + "internalType": "bytes32[]", + "name": "_multisigParticipantsPermissions", + "type": "bytes32[]" + } + ], + "name": "deploy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_unviersalReceiverDelegateUPAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_universalProfileMetadata", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "_majority", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_participationRate", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_minimumVotingDelay", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_minimumVotingPeriod", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_minimumExecutionDelay", + "type": "bytes32" + }, + { + "internalType": "address[]", + "name": "_daoParticipants", + "type": "address[]" + }, + { + "internalType": "bytes32[]", + "name": "_daoParticipantsPermissions", + "type": "bytes32[]" + } + ], + "name": "deploy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAddresses", + "outputs": [ + { + "internalType": "address[6]", + "name": "", + "type": "address[6]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_caller", + "type": "address" + }, + { + "internalType": "bytes32[]", + "name": "dataKeys", + "type": "bytes32[]" + } + ], + "name": "getData", + "outputs": [ + { + "internalType": "bytes[]", + "name": "dataValues", + "type": "bytes[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_caller", + "type": "address" + }, + { + "internalType": "bytes32[]", + "name": "dataKeys", + "type": "bytes32[]" + }, + { + "internalType": "bytes[]", + "name": "dataValues", + "type": "bytes[]" + } + ], + "name": "setData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_UNIVERSAL_PROFILE", + "type": "address" + }, + { + "internalType": "bytes32[]", + "name": "dataKeys", + "type": "bytes32[]" + }, + { + "internalType": "bytes[]", + "name": "dataValues", + "type": "bytes[]" + } + ], + "name": "setDataOf", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x60806040523480156200001157600080fd5b5060405162001a8438038062001a84833981016040819052620000349162000094565b600280546001600160a01b039485166001600160a01b031991821617909155600080549385169382169390931790925560018054919093169116179055620000de565b80516001600160a01b03811681146200008f57600080fd5b919050565b600080600060608486031215620000aa57600080fd5b620000b58462000077565b9250620000c56020850162000077565b9150620000d56040850162000077565b90509250925092565b61199680620000ee6000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063a39fac121161005b578063a39fac12146100bd578063a5db9eb8146100db578063c038ac34146100ee578063d6b084821461010157600080fd5b8063455f9f2b14610082578063573baa421461009757806377a3fecc146100aa575b600080fd5b610095610090366004611064565b610121565b005b6100956100a5366004611109565b610145565b6100956100b836600461121a565b6101fd565b6100c56102fe565b6040516100d29190611304565b60405180910390f35b6100956100e936600461121a565b610375565b6100956100fc36600461133e565b610427565b61011461010f366004611408565b610453565b6040516100d29190611509565b61012b858561057e565b61013683838361065e565b61013e610750565b5050505050565b61014f888861057e565b6101e0866000815181106101655761016561151c565b6020026020010151876001815181106101805761018061151c565b60200260200101518860028151811061019b5761019b61151c565b6020026020010151896003815181106101b6576101b661151c565b60200260200101518a6004815181106101d1576101d161151c565b60200260200101518a8a610c83565b6101eb83838361065e565b6101f3610750565b5050505050505050565b6000546001600160a01b031633148061022057506001546001600160a01b031633145b8061023557506002546001600160a01b031633145b6102865760405162461bcd60e51b815260206004820152601460248201527f4e6f7420616c6c6f77656420616464726573732e00000000000000000000000060448201526064015b60405180910390fd5b6001600160a01b03808416600090815260036020526040908190205490516314a6e29360e01b81529116906314a6e293906102c7908590859060040161156d565b600060405180830381600087803b1580156102e157600080fd5b505af11580156102f5573d6000803e3d6000fd5b50505050505050565b610306610e6b565b506040805160c0810182523360008181526003602081815285832080546001600160a01b0390811687526001820154811683880152600282015481169787019790975280830154871660608701526004810154871660808701529390925290526005015490911660a082015290565b6000546001600160a01b031633148061039857506001546001600160a01b031633145b806103ad57506002546001600160a01b031633145b6103f95760405162461bcd60e51b815260206004820152601460248201527f4e6f7420616c6c6f77656420616464726573732e000000000000000000000000604482015260640161027d565b6040516314a6e29360e01b81526001600160a01b038416906314a6e293906102c7908590859060040161156d565b610431898961057e565b61044087878787878787610c83565b610448610750565b505050505050505050565b6000546060906001600160a01b031633148061047957506001546001600160a01b031633145b8061048e57506002546001600160a01b031633145b6104da5760405162461bcd60e51b815260206004820152601460248201527f4e6f7420616c6c6f77656420616464726573732e000000000000000000000000604482015260640161027d565b6001600160a01b03808416600090815260036020526040908190205490517f4e3e6e9c000000000000000000000000000000000000000000000000000000008152911690634e3e6e9c9061053290859060040161159b565b600060405180830381865afa15801561054f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261057791908101906115fb565b9392505050565b6002546040517fb086c4f200000000000000000000000000000000000000000000000000000000815260009182916001600160a01b039091169063b086c4f2906105ce90879087906004016116ac565b60408051808303816000875af11580156105ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061091906116ce565b33600090815260036020526040902080546001600160a01b0393841673ffffffffffffffffffffffffffffffffffffffff199182161782556001909101805492909316911617905550505050565b6001805433600081815260036020526040808220805495015490517f2354f4fb00000000000000000000000000000000000000000000000000000000815291946001600160a01b0394851694632354f4fb946106ca9492821693909116918a908a908a90600401611741565b6020604051808303816000875af11580156106e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070d919061179a565b336000908152600360205260409020600501805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039290921691909117905550505050565b60408051600380825260808201909252600091602082016060803683375050604080516003808252608082019092529293506000929150602082015b606081526020019060019003908161078c57905050336000908152600360205260408082205490517f54f6127f0000000000000000000000000000000000000000000000000000000081527fdf30dba06db6a30e65354d9a64c609861f089545ca58c6b4dbe31a5f338cb0e360048201529293506001600160a01b03169182919082906354f6127f90602401600060405180830381865afa158015610835573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261085d91908101906117b7565b9050600061086a826117ec565b90506000610879826001611813565b90507fdf30dba06db6a30e65354d9a64c609861f089545ca58c6b4dbe31a5f338cb0e360001b876000815181106108b2576108b261151c565b6020026020010181815250508060001b6040516020016108d491815260200190565b604051602081830303815290604052866000815181106108f6576108f661151c565b602090810291909101810191909152604080517fdf30dba06db6a30e65354d9a64c609860000000000000000000000000000000081840152608085901b7fffffffffffffffffffffffffffffffff000000000000000000000000000000001660308201528151808203909301835281019052610971906117ec565b876001815181106109845761098461151c565b6020026020010181815250503060601b6040516020016109b991906bffffffffffffffffffffffff1991909116815260140190565b604051602081830303815290604052866001815181106109db576109db61151c565b602090810291909101810191909152604080517f4b80742de2bf82acb36300000000000000000000000000000000000000000000818401523060601b6bffffffffffffffffffffffff1916602c8201528151808203909301835281019052610a42906117ec565b87600281518110610a5557610a5561151c565b602002602001018181525050600160001b604051602001610a7891815260200190565b60405160208183030381529060405286600281518110610a9a57610a9a61151c565b60209081029190910101526040516314a6e29360e01b81526001600160a01b038516906314a6e29390610ad3908a908a9060040161156d565b600060405180830381600087803b158015610aed57600080fd5b505af1158015610b01573d6000803e3d6000fd5b505033600090815260036020526040908190206001015490517ff2fde38b0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152908816925063f2fde38b9150602401600060405180830381600087803b158015610b7657600080fd5b505af1158015610b8a573d6000803e3d6000fd5b505033600090815260036020908152604091829020600101548251600480825260248201855292810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f4e71e0c80000000000000000000000000000000000000000000000000000000017905292517f09c5eabe0000000000000000000000000000000000000000000000000000000081526001600160a01b039190911694506309c5eabe9350610c3c929101611839565b6000604051808303816000875af1158015610c5b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526101f391908101906117b7565b60008054338083526003602052604080842080546001919091015491517f514ea9670000000000000000000000000000000000000000000000000000000081526001600160a01b039485169463514ea96794610cf79493821693909116918e908e908e908e908e908e908e9060040161184c565b6000604051808303816000875af1158015610d16573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d3e91908101906118c6565b905080600081518110610d5357610d5361151c565b60209081029190910181015133600090815260039092526040909120600201805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909216919091179055805181906001908110610db157610db161151c565b602002602001015160036000336001600160a01b03166001600160a01b0316815260200190815260200160002060030160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555080600281518110610e1857610e1861151c565b60209081029190910181015133600090815260039092526040909120600401805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039092169190911790555050505050505050565b6040518060c001604052806006906020820280368337509192915050565b6001600160a01b0381168114610e9e57600080fd5b50565b8035610eac81610e89565b919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610ef057610ef0610eb1565b604052919050565b600067ffffffffffffffff821115610f1257610f12610eb1565b50601f01601f191660200190565b600082601f830112610f3157600080fd5b8135610f44610f3f82610ef8565b610ec7565b818152846020838601011115610f5957600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff821115610f9057610f90610eb1565b5060051b60200190565b600082601f830112610fab57600080fd5b81356020610fbb610f3f83610f76565b82815260059290921b84018101918181019086841115610fda57600080fd5b8286015b84811015610ffe578035610ff181610e89565b8352918301918301610fde565b509695505050505050565b600082601f83011261101a57600080fd5b8135602061102a610f3f83610f76565b82815260059290921b8401810191818101908684111561104957600080fd5b8286015b84811015610ffe578035835291830191830161104d565b600080600080600060a0868803121561107c57600080fd5b853561108781610e89565b9450602086013567ffffffffffffffff808211156110a457600080fd5b6110b089838a01610f20565b95506040880135945060608801359150808211156110cd57600080fd5b6110d989838a01610f9a565b935060808801359150808211156110ef57600080fd5b506110fc88828901611009565b9150509295509295909350565b600080600080600080600080610100898b03121561112657600080fd5b61112f89610ea1565b9750602089013567ffffffffffffffff8082111561114c57600080fd5b6111588c838d01610f20565b985060408b013591508082111561116e57600080fd5b61117a8c838d01611009565b975060608b013591508082111561119057600080fd5b61119c8c838d01610f9a565b965060808b01359150808211156111b257600080fd5b6111be8c838d01611009565b955060a08b0135945060c08b01359150808211156111db57600080fd5b6111e78c838d01610f9a565b935060e08b01359150808211156111fd57600080fd5b5061120a8b828c01611009565b9150509295985092959890939650565b60008060006060848603121561122f57600080fd5b833561123a81610e89565b925060208481013567ffffffffffffffff8082111561125857600080fd5b61126488838901611009565b9450604087013591508082111561127a57600080fd5b818701915087601f83011261128e57600080fd5b813561129c610f3f82610f76565b81815260059190911b8301840190848101908a8311156112bb57600080fd5b8585015b838110156112f3578035858111156112d75760008081fd5b6112e58d89838a0101610f20565b8452509186019186016112bf565b508096505050505050509250925092565b60c08101818360005b60068110156113355781516001600160a01b031683526020928301929091019060010161130d565b50505092915050565b60008060008060008060008060006101208a8c03121561135d57600080fd5b6113668a610ea1565b985060208a013567ffffffffffffffff8082111561138357600080fd5b61138f8d838e01610f20565b995060408c0135985060608c0135975060808c0135965060a08c0135955060c08c0135945060e08c01359150808211156113c857600080fd5b6113d48d838e01610f9a565b93506101008c01359150808211156113eb57600080fd5b506113f88c828d01611009565b9150509295985092959850929598565b6000806040838503121561141b57600080fd5b823561142681610e89565b9150602083013567ffffffffffffffff81111561144257600080fd5b61144e85828601611009565b9150509250929050565b60005b8381101561147357818101518382015260200161145b565b83811115611482576000848401525b50505050565b600081518084526114a0816020860160208601611458565b601f01601f19169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b858110156114fc5782840389526114ea848351611488565b988501989350908401906001016114d2565b5091979650505050505050565b60208152600061057760208301846114b4565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561156257815187529582019590820190600101611546565b509495945050505050565b6040815260006115806040830185611532565b828103602084015261159281856114b4565b95945050505050565b6020815260006105776020830184611532565b600082601f8301126115bf57600080fd5b81516115cd610f3f82610ef8565b8181528460208386010111156115e257600080fd5b6115f3826020830160208701611458565b949350505050565b6000602080838503121561160e57600080fd5b825167ffffffffffffffff8082111561162657600080fd5b818501915085601f83011261163a57600080fd5b8151611648610f3f82610f76565b81815260059190911b8301840190848101908883111561166757600080fd5b8585015b8381101561169f578051858111156116835760008081fd5b6116918b89838a01016115ae565b84525091860191860161166b565b5098975050505050505050565b6001600160a01b03831681526040602082015260006115f36040830184611488565b600080604083850312156116e157600080fd5b82516116ec81610e89565b60208401519092506116fd81610e89565b809150509250929050565b600081518084526020808501945080840160005b838110156115625781516001600160a01b03168752958201959082019060010161171c565b60006001600160a01b038089168352808816602084015280871660408401525084606083015260c0608083015261177b60c0830185611708565b82810360a084015261178d8185611532565b9998505050505050505050565b6000602082840312156117ac57600080fd5b815161057781610e89565b6000602082840312156117c957600080fd5b815167ffffffffffffffff8111156117e057600080fd5b6115f3848285016115ae565b8051602080830151919081101561180d576000198160200360031b1b821691505b50919050565b6000821982111561183457634e487b7160e01b600052601160045260246000fd5b500190565b6020815260006105776020830184611488565b60006101406001600160a01b03808e168452808d166020850152808c166040850152508960608401528860808401528760a08401528660c08401528560e0840152806101008401526118a081840186611708565b90508281036101208401526118b58185611532565b9d9c50505050505050505050505050565b600060208083850312156118d957600080fd5b825167ffffffffffffffff8111156118f057600080fd5b8301601f8101851361190157600080fd5b805161190f610f3f82610f76565b81815260059190911b8201830190838101908783111561192e57600080fd5b928401925b8284101561195557835161194681610e89565b82529284019290840190611933565b97965050505050505056fea2646970667358221220c6e388cb8b44c34d34b40d796772dfc7d0c6535b6b70612e66b4887fad2ed30d64736f6c634300080a0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061007d5760003560e01c8063a39fac121161005b578063a39fac12146100bd578063a5db9eb8146100db578063c038ac34146100ee578063d6b084821461010157600080fd5b8063455f9f2b14610082578063573baa421461009757806377a3fecc146100aa575b600080fd5b610095610090366004611064565b610121565b005b6100956100a5366004611109565b610145565b6100956100b836600461121a565b6101fd565b6100c56102fe565b6040516100d29190611304565b60405180910390f35b6100956100e936600461121a565b610375565b6100956100fc36600461133e565b610427565b61011461010f366004611408565b610453565b6040516100d29190611509565b61012b858561057e565b61013683838361065e565b61013e610750565b5050505050565b61014f888861057e565b6101e0866000815181106101655761016561151c565b6020026020010151876001815181106101805761018061151c565b60200260200101518860028151811061019b5761019b61151c565b6020026020010151896003815181106101b6576101b661151c565b60200260200101518a6004815181106101d1576101d161151c565b60200260200101518a8a610c83565b6101eb83838361065e565b6101f3610750565b5050505050505050565b6000546001600160a01b031633148061022057506001546001600160a01b031633145b8061023557506002546001600160a01b031633145b6102865760405162461bcd60e51b815260206004820152601460248201527f4e6f7420616c6c6f77656420616464726573732e00000000000000000000000060448201526064015b60405180910390fd5b6001600160a01b03808416600090815260036020526040908190205490516314a6e29360e01b81529116906314a6e293906102c7908590859060040161156d565b600060405180830381600087803b1580156102e157600080fd5b505af11580156102f5573d6000803e3d6000fd5b50505050505050565b610306610e6b565b506040805160c0810182523360008181526003602081815285832080546001600160a01b0390811687526001820154811683880152600282015481169787019790975280830154871660608701526004810154871660808701529390925290526005015490911660a082015290565b6000546001600160a01b031633148061039857506001546001600160a01b031633145b806103ad57506002546001600160a01b031633145b6103f95760405162461bcd60e51b815260206004820152601460248201527f4e6f7420616c6c6f77656420616464726573732e000000000000000000000000604482015260640161027d565b6040516314a6e29360e01b81526001600160a01b038416906314a6e293906102c7908590859060040161156d565b610431898961057e565b61044087878787878787610c83565b610448610750565b505050505050505050565b6000546060906001600160a01b031633148061047957506001546001600160a01b031633145b8061048e57506002546001600160a01b031633145b6104da5760405162461bcd60e51b815260206004820152601460248201527f4e6f7420616c6c6f77656420616464726573732e000000000000000000000000604482015260640161027d565b6001600160a01b03808416600090815260036020526040908190205490517f4e3e6e9c000000000000000000000000000000000000000000000000000000008152911690634e3e6e9c9061053290859060040161159b565b600060405180830381865afa15801561054f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261057791908101906115fb565b9392505050565b6002546040517fb086c4f200000000000000000000000000000000000000000000000000000000815260009182916001600160a01b039091169063b086c4f2906105ce90879087906004016116ac565b60408051808303816000875af11580156105ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061091906116ce565b33600090815260036020526040902080546001600160a01b0393841673ffffffffffffffffffffffffffffffffffffffff199182161782556001909101805492909316911617905550505050565b6001805433600081815260036020526040808220805495015490517f2354f4fb00000000000000000000000000000000000000000000000000000000815291946001600160a01b0394851694632354f4fb946106ca9492821693909116918a908a908a90600401611741565b6020604051808303816000875af11580156106e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070d919061179a565b336000908152600360205260409020600501805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039290921691909117905550505050565b60408051600380825260808201909252600091602082016060803683375050604080516003808252608082019092529293506000929150602082015b606081526020019060019003908161078c57905050336000908152600360205260408082205490517f54f6127f0000000000000000000000000000000000000000000000000000000081527fdf30dba06db6a30e65354d9a64c609861f089545ca58c6b4dbe31a5f338cb0e360048201529293506001600160a01b03169182919082906354f6127f90602401600060405180830381865afa158015610835573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261085d91908101906117b7565b9050600061086a826117ec565b90506000610879826001611813565b90507fdf30dba06db6a30e65354d9a64c609861f089545ca58c6b4dbe31a5f338cb0e360001b876000815181106108b2576108b261151c565b6020026020010181815250508060001b6040516020016108d491815260200190565b604051602081830303815290604052866000815181106108f6576108f661151c565b602090810291909101810191909152604080517fdf30dba06db6a30e65354d9a64c609860000000000000000000000000000000081840152608085901b7fffffffffffffffffffffffffffffffff000000000000000000000000000000001660308201528151808203909301835281019052610971906117ec565b876001815181106109845761098461151c565b6020026020010181815250503060601b6040516020016109b991906bffffffffffffffffffffffff1991909116815260140190565b604051602081830303815290604052866001815181106109db576109db61151c565b602090810291909101810191909152604080517f4b80742de2bf82acb36300000000000000000000000000000000000000000000818401523060601b6bffffffffffffffffffffffff1916602c8201528151808203909301835281019052610a42906117ec565b87600281518110610a5557610a5561151c565b602002602001018181525050600160001b604051602001610a7891815260200190565b60405160208183030381529060405286600281518110610a9a57610a9a61151c565b60209081029190910101526040516314a6e29360e01b81526001600160a01b038516906314a6e29390610ad3908a908a9060040161156d565b600060405180830381600087803b158015610aed57600080fd5b505af1158015610b01573d6000803e3d6000fd5b505033600090815260036020526040908190206001015490517ff2fde38b0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152908816925063f2fde38b9150602401600060405180830381600087803b158015610b7657600080fd5b505af1158015610b8a573d6000803e3d6000fd5b505033600090815260036020908152604091829020600101548251600480825260248201855292810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f4e71e0c80000000000000000000000000000000000000000000000000000000017905292517f09c5eabe0000000000000000000000000000000000000000000000000000000081526001600160a01b039190911694506309c5eabe9350610c3c929101611839565b6000604051808303816000875af1158015610c5b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526101f391908101906117b7565b60008054338083526003602052604080842080546001919091015491517f514ea9670000000000000000000000000000000000000000000000000000000081526001600160a01b039485169463514ea96794610cf79493821693909116918e908e908e908e908e908e908e9060040161184c565b6000604051808303816000875af1158015610d16573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d3e91908101906118c6565b905080600081518110610d5357610d5361151c565b60209081029190910181015133600090815260039092526040909120600201805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909216919091179055805181906001908110610db157610db161151c565b602002602001015160036000336001600160a01b03166001600160a01b0316815260200190815260200160002060030160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555080600281518110610e1857610e1861151c565b60209081029190910181015133600090815260039092526040909120600401805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039092169190911790555050505050505050565b6040518060c001604052806006906020820280368337509192915050565b6001600160a01b0381168114610e9e57600080fd5b50565b8035610eac81610e89565b919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610ef057610ef0610eb1565b604052919050565b600067ffffffffffffffff821115610f1257610f12610eb1565b50601f01601f191660200190565b600082601f830112610f3157600080fd5b8135610f44610f3f82610ef8565b610ec7565b818152846020838601011115610f5957600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff821115610f9057610f90610eb1565b5060051b60200190565b600082601f830112610fab57600080fd5b81356020610fbb610f3f83610f76565b82815260059290921b84018101918181019086841115610fda57600080fd5b8286015b84811015610ffe578035610ff181610e89565b8352918301918301610fde565b509695505050505050565b600082601f83011261101a57600080fd5b8135602061102a610f3f83610f76565b82815260059290921b8401810191818101908684111561104957600080fd5b8286015b84811015610ffe578035835291830191830161104d565b600080600080600060a0868803121561107c57600080fd5b853561108781610e89565b9450602086013567ffffffffffffffff808211156110a457600080fd5b6110b089838a01610f20565b95506040880135945060608801359150808211156110cd57600080fd5b6110d989838a01610f9a565b935060808801359150808211156110ef57600080fd5b506110fc88828901611009565b9150509295509295909350565b600080600080600080600080610100898b03121561112657600080fd5b61112f89610ea1565b9750602089013567ffffffffffffffff8082111561114c57600080fd5b6111588c838d01610f20565b985060408b013591508082111561116e57600080fd5b61117a8c838d01611009565b975060608b013591508082111561119057600080fd5b61119c8c838d01610f9a565b965060808b01359150808211156111b257600080fd5b6111be8c838d01611009565b955060a08b0135945060c08b01359150808211156111db57600080fd5b6111e78c838d01610f9a565b935060e08b01359150808211156111fd57600080fd5b5061120a8b828c01611009565b9150509295985092959890939650565b60008060006060848603121561122f57600080fd5b833561123a81610e89565b925060208481013567ffffffffffffffff8082111561125857600080fd5b61126488838901611009565b9450604087013591508082111561127a57600080fd5b818701915087601f83011261128e57600080fd5b813561129c610f3f82610f76565b81815260059190911b8301840190848101908a8311156112bb57600080fd5b8585015b838110156112f3578035858111156112d75760008081fd5b6112e58d89838a0101610f20565b8452509186019186016112bf565b508096505050505050509250925092565b60c08101818360005b60068110156113355781516001600160a01b031683526020928301929091019060010161130d565b50505092915050565b60008060008060008060008060006101208a8c03121561135d57600080fd5b6113668a610ea1565b985060208a013567ffffffffffffffff8082111561138357600080fd5b61138f8d838e01610f20565b995060408c0135985060608c0135975060808c0135965060a08c0135955060c08c0135945060e08c01359150808211156113c857600080fd5b6113d48d838e01610f9a565b93506101008c01359150808211156113eb57600080fd5b506113f88c828d01611009565b9150509295985092959850929598565b6000806040838503121561141b57600080fd5b823561142681610e89565b9150602083013567ffffffffffffffff81111561144257600080fd5b61144e85828601611009565b9150509250929050565b60005b8381101561147357818101518382015260200161145b565b83811115611482576000848401525b50505050565b600081518084526114a0816020860160208601611458565b601f01601f19169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b858110156114fc5782840389526114ea848351611488565b988501989350908401906001016114d2565b5091979650505050505050565b60208152600061057760208301846114b4565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b8381101561156257815187529582019590820190600101611546565b509495945050505050565b6040815260006115806040830185611532565b828103602084015261159281856114b4565b95945050505050565b6020815260006105776020830184611532565b600082601f8301126115bf57600080fd5b81516115cd610f3f82610ef8565b8181528460208386010111156115e257600080fd5b6115f3826020830160208701611458565b949350505050565b6000602080838503121561160e57600080fd5b825167ffffffffffffffff8082111561162657600080fd5b818501915085601f83011261163a57600080fd5b8151611648610f3f82610f76565b81815260059190911b8301840190848101908883111561166757600080fd5b8585015b8381101561169f578051858111156116835760008081fd5b6116918b89838a01016115ae565b84525091860191860161166b565b5098975050505050505050565b6001600160a01b03831681526040602082015260006115f36040830184611488565b600080604083850312156116e157600080fd5b82516116ec81610e89565b60208401519092506116fd81610e89565b809150509250929050565b600081518084526020808501945080840160005b838110156115625781516001600160a01b03168752958201959082019060010161171c565b60006001600160a01b038089168352808816602084015280871660408401525084606083015260c0608083015261177b60c0830185611708565b82810360a084015261178d8185611532565b9998505050505050505050565b6000602082840312156117ac57600080fd5b815161057781610e89565b6000602082840312156117c957600080fd5b815167ffffffffffffffff8111156117e057600080fd5b6115f3848285016115ae565b8051602080830151919081101561180d576000198160200360031b1b821691505b50919050565b6000821982111561183457634e487b7160e01b600052601160045260246000fd5b500190565b6020815260006105776020830184611488565b60006101406001600160a01b03808e168452808d166020850152808c166040850152508960608401528860808401528760a08401528660c08401528560e0840152806101008401526118a081840186611708565b90508281036101208401526118b58185611532565b9d9c50505050505050505050505050565b600060208083850312156118d957600080fd5b825167ffffffffffffffff8111156118f057600080fd5b8301601f8101851361190157600080fd5b805161190f610f3f82610f76565b81815260059190911b8201830190838101908783111561192e57600080fd5b928401925b8284101561195557835161194681610e89565b82529284019290840190611933565b97965050505050505056fea2646970667358221220c6e388cb8b44c34d34b40d796772dfc7d0c6535b6b70612e66b4887fad2ed30d64736f6c634300080a0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/src/components/create/CreateKeyPermissions.tsx b/src/components/create/CreateKeyPermissions.tsx index 43aa667..fa76a81 100644 --- a/src/components/create/CreateKeyPermissions.tsx +++ b/src/components/create/CreateKeyPermissions.tsx @@ -1,4 +1,4 @@ -import React, { useContext, useState, useEffect } from "react"; +import React, { useContext, useState, useEffect, useCallback } from "react"; import { MdNavigateNext } from "react-icons/md"; import { AiOutlineUserAdd, @@ -32,7 +32,20 @@ const CreateKeyPermissions = (props: { handleSubmitCreate: any }) => { useState(false); const [addPermission, setAddPermission] = useState(false); const [removePermission, setRemovePermission] = useState(false); - + const [formValue, setForm] = useState({ + vote: false, + propose: false, + execute: false, + add: false, + remove: false, + registerVotes: false, + sendDeligate: false, + recieveDelegate: false, + }); + const onChange = useCallback((e: any) => { + const { name, checked }: { name: any; checked: any } = e.target; + setForm((prev) => ({ ...prev, [name]: checked })); + }, []); const handleAddKeyPermission = (event: any) => { event.preventDefault(); const validationResult = addKeyPermissionValidations(); @@ -57,6 +70,17 @@ const CreateKeyPermissions = (props: { handleSubmitCreate: any }) => { }, }, ]); + setForm({ + vote: false, + propose: false, + execute: false, + add: false, + remove: false, + registerVotes: false, + sendDeligate: false, + recieveDelegate: false, + }); + setUpAddress(""); console.log(JSON.stringify(keyPermissions)); }; @@ -158,7 +182,10 @@ const CreateKeyPermissions = (props: { handleSubmitCreate: any }) => { placeholder="" name="up_address" type="text" - handleChange={(e: any) => setUpAddress(e.target.value)} + handleChange={(e: any) => { + setUpAddress(e.target.value); + }} + value={upAddress} /> - + > +

Propose

+ + - + + ); }; @@ -167,21 +169,18 @@ const DaoCard = (props: { > {" "}
- - +
-
{" "}

{categoriesObject[0].label}

{" "}
{" "} -
{" "}

diff --git a/src/modals/ProposalVotingModal.tsx b/src/modals/ProposalVotingModal.tsx index 5008f09..b866e39 100644 --- a/src/modals/ProposalVotingModal.tsx +++ b/src/modals/ProposalVotingModal.tsx @@ -4,6 +4,7 @@ import React, { useState, useContext, useEffect, + useCallback, } from "react"; import { AiOutlineClose } from "react-icons/ai"; import { Dialog, Transition } from "@headlessui/react"; @@ -17,24 +18,28 @@ import { DaoProposalContext } from "../context/DaoProposalContext"; import dayjs from "dayjs"; import { toast } from "react-toastify"; import { ethers } from "ethers"; +import { universalProfileContract } from "../services/web3"; export default function ProposalVotingModal(props: { setShowModal: any; showModal: boolean; proposal: any; daoSelected: any; + votingParameters: any; }) { - const { setShowModal, showModal, proposal, daoSelected } = props; + const { setShowModal, showModal, proposal, daoSelected, votingParameters } = + props; const { getProposalHash, registerVotes, executeProposal } = useContext(DaoProposalContext); const { accountAddress } = useContext(ProfileContext); + const [permisions, setPermisions] = useState({}); + const universalProfile = getParsedJsonObj( + daoSelected.daoUpAddress + ).universalProfile; const [open, setOpen] = useState(true); const [isLoading, setIsLoading] = useState(false); const [votes, setVotes] = useState([]); - const [userCanVote, setUserCanVote] = useState(false); - const [userCanRegister, setUserCanRegister] = useState(false); - const [userCanExecute, setUserCanExecute] = useState(false); const [hasVoted, setHasVoted] = useState(false); const [voterChoice, setVoterChoice] = useState(10); const [voters, setVoters] = useState([]); @@ -209,6 +214,33 @@ export default function ProposalVotingModal(props: { }); } }; + const getPermissions = useCallback(async () => { + if (accountAddress) { + try { + let contract1 = await universalProfileContract(universalProfile) + ["getData(bytes32[])"]([ + "0x4b80742de2bfb3cc0e490000" + accountAddress.substring(2), + ]) + .call(); + const permissionBin = parseInt(contract1[0], 16).toString(2); + const permision = { + registerVotes: permissionBin[0] === "1", + removePermission: permissionBin[1] === "1", + addPermission: permissionBin[2] === "1", + receiveDelegate: permissionBin[3] === "1", + sendDelegate: permissionBin[4] === "1", + execute: permissionBin[5] === "1", + propose: permissionBin[6] === "1", + vote: permissionBin[7] === "1", + }; + setPermisions(permision); + } catch { + toast.error("An error ocurred, check your connection", { + position: toast.POSITION.BOTTOM_RIGHT, + }); + } + } + }, [universalProfile, accountAddress]); const handleRegister = async () => { setIsLoading(true); @@ -294,18 +326,11 @@ export default function ProposalVotingModal(props: { setVotes(result); console.log("votes", result); }; + + getPermissions(); const getVoterDetails = () => { const _voters: string[] = []; for (var i = 0; i < permissionsObject.length; i++) { - if (permissionsObject[i].upAddress === accountAddress) { - setUserCanVote(permissionsObject[i].keyPermissions.vote === "True"); - setUserCanRegister( - permissionsObject[i].keyPermissions.registerVotes === "True" - ); - setUserCanExecute( - permissionsObject[i].keyPermissions.execute === "True" - ); - } if (permissionsObject[i].keyPermissions.vote === "True") { _voters.push(permissionsObject[i].upAddress); } @@ -316,7 +341,13 @@ export default function ProposalVotingModal(props: { fetchData(); getVoterDetails(); // checkIfVoted(); - }, [isLoading, accountAddress]); + }, [ + isLoading, + accountAddress, + getPermissions, + permissionsObject, + proposal.identifier, + ]); useEffect(() => { const checkIfVoted = () => { @@ -358,9 +389,7 @@ export default function ProposalVotingModal(props: { const proposalDetailsObject = getParsedJsonObj(proposal.proposalDetails); const votingParametersObject = - daoSelected.length !== "" - ? getParsedJsonObj(daoSelected.votingParameters) - : ""; + daoSelected.length !== "" ? votingParameters : ""; const createdAt = dayjs(Number(proposal.createdAt)); const min_voting_delay = votingParametersObject.minVotingDelay; const min_voting_period = votingParametersObject.minVotingPeriod; @@ -640,7 +669,7 @@ export default function ProposalVotingModal(props: { {(proposalStatus === "Pending" || isLoading || - !userCanVote) && + !permisions?.vote) && proposalStatus !== "Closed" && !hasVoted && ( <> @@ -665,7 +694,7 @@ export default function ProposalVotingModal(props: { {proposalStatus === "Active" && !isLoading && - userCanVote && + permisions?.vote && !hasVoted && ( <>

VOTE

@@ -699,7 +728,7 @@ export default function ProposalVotingModal(props: { {proposalStatus === "Closed" && !isLoading && ( <>

Actions

- {userCanRegister ? ( + {permisions?.registerVotes ? (
)} - {userCanExecute ? ( + {permisions?.execute ? (
)} - {!userCanRegister && ( + {!permisions?.registerVotes && (

You don't have Register Votes permission

)} - {!userCanExecute && ( + {!permisions.execute && (

You don't have Execute Votes permission

@@ -752,7 +781,7 @@ export default function ProposalVotingModal(props: { secondaryColor="rgba(172, 5, 55, 1)" /> )} - {!userCanVote && proposalStatus !== "Closed" && ( + {!permisions?.vote && proposalStatus !== "Closed" && (

You don't have Vote permission

@@ -790,6 +819,7 @@ export default function ProposalVotingModal(props: { const VotingDetails = (props: { proposalDetailsObject: any }) => { const { proposalDetailsObject } = props; + console.log("obj", proposalDetailsObject); const votingDelay = votingDelayItems.find( (element: any) => element.value === proposalDetailsObject.minVotingDelay ) || { value: 0, label: "instant" }; diff --git a/src/pages/DaoProfile.tsx b/src/pages/DaoProfile.tsx index ecb352e..7df0394 100644 --- a/src/pages/DaoProfile.tsx +++ b/src/pages/DaoProfile.tsx @@ -1,4 +1,4 @@ -import React, { useContext, useState, useEffect } from "react"; +import React, { useContext, useState, useEffect, useCallback } from "react"; import { useNavigate, useLocation } from "react-router-dom"; import { ProfileContext } from "../context/ProfileContext"; import { @@ -11,6 +11,8 @@ import Skeleton from "@material-ui/lab/Skeleton"; import { getParsedJsonObj } from "../utils/getParsedJsonObj"; import { MdCreate } from "react-icons/md"; import MobileSideNav from "../components/MobileSideNav"; +import { universalProfileContract } from "../services/web3"; +import { toast } from "react-toastify"; //@ts-ignore type LocationProps = { state: { @@ -19,10 +21,15 @@ type LocationProps = { }; const DaoProfile = () => { + const [votingParameters, setVotingParams] = useState({}); const location = useLocation() as unknown as LocationProps; const { accountAddress } = useContext(ProfileContext); const [profileComponent, setProfileComponent] = useState("Proposals"); const daoDetail = location.state?.daoDetail; + const [permisions, setPermisions] = useState({}); + const universalProfile = getParsedJsonObj( + daoDetail.daoUpAddress + ).universalProfile; const navigate = useNavigate(); @@ -32,24 +39,66 @@ const DaoProfile = () => { }; const profileImageObj = getParsedJsonObj(daoDetail.profileImage); const profileImageUrl = profileImageObj.url.concat(profileImageObj.hash); - const keyPermissionObj = getParsedJsonObj(daoDetail.keyPermissions); - const user = keyPermissionObj.filter(function (e: any) { - return ( - e.upAddress === accountAddress && e.keyPermissions.propose === "True" - ); - }); // console.log(user.length); - const isMember: boolean = user.length > 0 ? true : false; + const isMember: boolean = permisions.vote ? true : false; + const getProfile = useCallback(async () => { + let contract = await universalProfileContract(universalProfile) + ["getData(bytes32[])"]([ + // DAO Settings + "0xbc776f168e7b9c60bb2a7180950facd372cd90c841732d963c31a93ff9f8c127", + "0xf89f507ecd9cb7646ce1514ec6ab90d695dac9314c3771f451fd90148a3335a9", + "0x799787138cc40d7a47af8e69bdea98db14e1ead8227cef96814fa51751e25c76", + "0xd3cf4cd71858ea36c3f5ce43955db04cbe9e1f42a2c7795c25c1d430c9bb280a", + "0xb207580c05383177027a90d6c298046d3d60dfa05a32b0bb48ea9015e11a3424", + ]) + .call(); + if (accountAddress) { + let contract1 = await universalProfileContract(universalProfile) + ["getData(bytes32[])"]([ + "0x4b80742de2bfb3cc0e490000" + accountAddress.substring(2), + ]) + .call(); + const permissionBin = parseInt(contract1[0], 16).toString(2); + const permision = { + registerVotes: permissionBin[0] === "1", + removePermission: permissionBin[1] === "1", + addPermission: permissionBin[2] === "1", + receiveDelegate: permissionBin[3] === "1", + sendDelegate: permissionBin[4] === "1", + execute: permissionBin[5] === "1", + propose: permissionBin[6] === "1", + vote: permissionBin[7] === "1", + }; + setPermisions(permision); + } + + const Params = { + votingMajority: parseInt(contract[0]), + participationRate: parseInt(contract[1]), + minVotingDelay: parseInt(contract[2]), + minVotingPeriod: parseInt(contract[3]) / (24 * 3600), + minExecutionDelay: parseInt(contract[4]) / (24 * 3600), + }; + setVotingParams(Params); + }, [universalProfile, accountAddress]); + // console.log(votingParameters); const handleCreateProposal = (event: any) => { navigate("/Governance", { state: { component: "ChooseTemplate", CID: daoDetail.CID }, }); }; - + toast.configure(); useEffect(() => { window.scrollTo(0, 0); - }, []); + try { + getProfile(); + } catch { + toast.error("An error ocurred, check your connection", { + position: toast.POSITION.BOTTOM_RIGHT, + }); + } + }, [getProfile]); return (
@@ -100,9 +149,17 @@ const DaoProfile = () => {
<> {profileComponent === "Proposals" && ( - + + )} + {profileComponent === "About" && ( + )} - {profileComponent === "About" && } {profileComponent === "Members" && ( )} diff --git a/src/pages/Discover.tsx b/src/pages/Discover.tsx index 0c0973d..f08ae39 100644 --- a/src/pages/Discover.tsx +++ b/src/pages/Discover.tsx @@ -172,7 +172,9 @@ const DaoCard = (props: { id: number; daoDetail: any }) => { +

+ + + + ); +}; diff --git a/src/components/individualProfile/ProfileSideBar.tsx b/src/components/individualProfile/ProfileSideBar.tsx new file mode 100644 index 0000000..38961fd --- /dev/null +++ b/src/components/individualProfile/ProfileSideBar.tsx @@ -0,0 +1,34 @@ +import React, {useEffect} from "react"; +import { AiFillHome, AiFillClockCircle, AiFillHeart } from "react-icons/ai"; + +const ProfileSideBar = (props: {handleComponent: any, profileComponent:string}) => { + const {handleComponent, profileComponent} = props; + + useEffect(() => { + window.scrollTo(0, 0) + }, []) + + return ( +
+
handleComponent("ProfileDetails")} + className={`flex justify-start items-center py-2 cursor-pointer ${profileComponent === 'ProfileDetails'? 'text-[#6341ff]' :'text-white'} hover:text-[#8168ff]`}> + +

Profile

+
+ +
handleComponent("UserActivity")} + className={`flex justify-start items-center py-2 cursor-pointer ${profileComponent === 'UserActivity'? 'text-[#6341ff]' :'text-white'} text-white hover:text-[#8168ff]`}> + +

Activity

+
+{/* +
handleComponent("POAPs")} + className={`flex justify-start items-center py-2 cursor-pointer ${profileComponent === 'POAPs'? 'text-[#6341ff]' :'text-white'} text-white hover:text-[#8168ff]`}> + +

POAPs

+
*/} +
+ ) +}; + +export default ProfileSideBar; \ No newline at end of file diff --git a/src/components/individualProfile/UserActivity.tsx b/src/components/individualProfile/UserActivity.tsx new file mode 100644 index 0000000..039a2a5 --- /dev/null +++ b/src/components/individualProfile/UserActivity.tsx @@ -0,0 +1,264 @@ +import React, { useEffect, useContext, useState } from "react"; +import { SingleSelect } from "../../components"; +// import { ProfileContext } from "../../context/ProfileContext"; +import { + getDaoByMember, + getVotesByMember, + getProposalsByCreator, +} from "../../services/keezBackend"; +import { getParsedJsonObj } from "../../utils/getParsedJsonObj"; +import { shortenAddress } from "../../utils/shortenAddress"; +import { fetchErc725Data } from "../../services/erc725"; +import dayjs from "dayjs"; +import { SiMetafilter } from "react-icons/si"; + +const UserActivity = (props: { + handleComponent: any; + accountAddress: string; +}) => { + const { handleComponent, accountAddress } = props; + const [profileData, setProfileData] = useState({}); + // const { accountAddress, profileData } = useContext(ProfileContext); + const [upName, setUpName] = useState(""); + const [filterState, setFilterState] = useState("All"); + const [allActivities, setAllActivities] = useState([]); + const [daoActivities, setDaoActivities] = useState([]); + const [proposalActivities, setProposalActivities] = useState([]); + const [voteActivities, setVoteActivities] = useState([]); + const [activities, setActivities] = useState([]); + const fetchProfile = async (account: string) => { + try { + const data = await fetchErc725Data(account); + setProfileData(data); + console.log("erc725profile = ", data); + } catch (error) { + console.log("This is not an ERC725 Contract"); + } + }; + + const state = [ + { + value: "all", + label: "All", + }, + { + value: "votes", + label: "Voted On", + }, + { + value: "daos", + label: "DAOs Created", + }, + { + value: "proposals", + label: "New Proposals", + }, + ]; + + const getUserProfile = async (upAddress: string) => { + try { + if (profileData.value.LSP3Profile) { + const profile = profileData?.value?.LSP3Profile; + setUpName(profile?.name); + } + } catch (error) { + setUpName(shortenAddress(upAddress)); + console.log(upAddress, "This is not an ERC725 Contract"); + } + }; + + const handleState = async (event: any) => { + // console.log(event.value) + setFilterState(event.value); + }; + + useEffect(() => { + window.scrollTo(0, 0); + }, []); + + useEffect(() => { + if (accountAddress) { + fetchProfile(accountAddress); + getUserProfile(accountAddress); + const fetchData = async () => { + if (accountAddress) { + const userDaosCreated = await getDaoByMember(accountAddress); + const userProposalsCreated = await getProposalsByCreator( + accountAddress + ); + const userVotes = await getVotesByMember(accountAddress); + const activity1 = userDaosCreated.map(function ( + dao: any, + index: number + ) { + return { + time: dao.createdAt, + type: "dao", + daoName: dao.daoName, + proposalName: "", + description: dao.description, + creator: dao.creator, + }; + }); + const activity2 = userProposalsCreated.map(function ( + proposal: any, + index: any + ) { + const forDaoProposalObject = getParsedJsonObj( + proposal.forDaoDetails + ); + return { + time: proposal.createdAt, + type: "proposal", + daoName: forDaoProposalObject.daoName, + proposalName: proposal.proposalName, + description: proposal.description, + creator: proposal.creator, + }; + }); + const activity3 = userVotes.map(function (vote: any, index: number) { + var detail = userProposalsCreated.filter(function (p: any) { + return p.identifier === vote.proposalSignature; + }); + const forDaoProposalObject = + detail[0] && detail[0].forDaoDetails + ? getParsedJsonObj(detail[0].forDaoDetails) + : { daoName: "" }; + const daoName = forDaoProposalObject + ? forDaoProposalObject.daoName + : ""; + const description = + detail[0] && detail[0].description ? detail[0].description : ""; + const creator = + detail[0] && detail[0].creator ? detail[0].creator : ""; + return { + time: vote.createdAt, + vote: "vote", + daoName: daoName, + proposalName: vote.proposalName, + description: description, + creator: creator, + }; + }); + // // Merge arrays + const merged = [...activity1, ...activity2, ...activity3]; + setActivities(merged); + setAllActivities(merged); + setDaoActivities(activity1); + setProposalActivities(activity2); + setVoteActivities(activity3); + } + }; + fetchData(); + } + window.scrollTo(0, 0); + }, [accountAddress]); + + useEffect(() => { + if (accountAddress) { + switch (filterState) { + case "all": + setActivities(allActivities); + break; + case "daos": + setActivities(daoActivities); + break; + case "proposals": + setActivities(proposalActivities); + break; + case "votes": + setActivities(voteActivities); + break; + } + } + }, [filterState]); + + return ( +
+
+

+ User Activity +

+
+
+ +
+
+ {[...activities] + .sort((a, b) => (a.time < b.time ? 1 : -1)) + .map((activity, i) => ( +
+
+

{upName}

+

+ {activity.type === "dao" + ? "created new DAO" + : activity.type === "proposal" + ? "proposed" + : "voted on"} +

+
+ +
+ ))} +
+
+ ); +}; + +export default UserActivity; + +const VotingCard = (props: { activity: any }) => { + const { activity } = props; + const [creatorName, setCreatorName] = useState(""); + + const getCreatorName = async (upAddress: string) => { + try { + const profileData: any = await fetchErc725Data(upAddress); + if (profileData.value.LSP3Profile) { + const name = profileData?.value?.LSP3Profile?.name; + setCreatorName(name); + } + } catch (error) { + setCreatorName(shortenAddress(upAddress)); + console.log(upAddress, "This is not an ERC725 Contract"); + } + }; + + useEffect(() => { + getCreatorName(activity.creator); + }, []); + return ( +
+
+
+

{activity.daoName}

+

+ {activity.proposalName} +

+
+
+
+

Date:

+

+ {dayjs(Number(activity.time)).format("YYYY-MM-DD, HH:mm")} +

+
+
+

+ {activity.type === "dao" ? "Created by" : "Proposed by"}: +

+

{creatorName}

+
+ +

{activity.description}

+
+
+
+ ); +}; diff --git a/src/components/individualProfile/index.ts b/src/components/individualProfile/index.ts new file mode 100644 index 0000000..bbff7f7 --- /dev/null +++ b/src/components/individualProfile/index.ts @@ -0,0 +1,4 @@ +export { default as Paops } from './Paops' +export { default as UserActivity } from './UserActivity' +export { default as ProfileDetails } from './ProfileDetails' +export { default as ProfileSideBar } from './ProfileSideBar' diff --git a/src/components/navbar/NavItems.tsx b/src/components/navbar/NavItems.tsx index f70cb94..5335d15 100644 --- a/src/components/navbar/NavItems.tsx +++ b/src/components/navbar/NavItems.tsx @@ -1,5 +1,5 @@ import { useState, useEffect, useRef } from "react"; -import { NavLink } from "react-router-dom"; +import { NavLink, useNavigate } from "react-router-dom"; const Dropdown = (props: { submenus: any; dropdown: boolean }) => { const { submenus, dropdown } = props; @@ -21,6 +21,7 @@ const Dropdown = (props: { submenus: any; dropdown: boolean }) => { const NavItems = (props: { items: any; depthLevel: number }) => { const { items, depthLevel } = props; const [dropdown, setDropdown] = useState(false); + const navigate = useNavigate(); let ref = useRef(); @@ -72,6 +73,18 @@ const NavItems = (props: { items: any; depthLevel: number }) => { + ) : items.title === "Governance" && + window.location.pathname === "/Governance" ? ( + ) : items.title !== "Docs" ? ( {items.title} diff --git a/src/components/profile/ProfileDetails.tsx b/src/components/profile/ProfileDetails.tsx index 9477a9d..bed620c 100644 --- a/src/components/profile/ProfileDetails.tsx +++ b/src/components/profile/ProfileDetails.tsx @@ -1,8 +1,8 @@ -import React, {useEffect, useState, useContext} from "react"; +import React, { useEffect, useState, useContext } from "react"; import { useLocation } from "react-router-dom"; import { shortenAddress } from "../../utils/shortenAddress"; import { IPFS_GATEWAY } from "../../constants/globals"; -import { ProfileContext } from '../../context/ProfileContext' +import { ProfileContext } from "../../context/ProfileContext"; import { AiOutlineLink, AiFillAppstore } from "react-icons/ai"; import { IoAppsSharp } from "react-icons/io5"; import { SingleSelect } from "../../components"; @@ -12,176 +12,190 @@ import Skeleton from "@material-ui/lab/Skeleton"; import ReactCardFlip from "react-card-flip"; import { useNavigate } from "react-router-dom"; +const ProfileDetails = (props: { accountAddress: string }) => { + const { accountAddress } = props; + const { profileData } = useContext(ProfileContext); + const [upName, setUpName] = useState(""); + const [upDescription, setUpDescription] = useState(""); + const [upLinks, setUpLinks] = useState<{ title: string; url: string }[]>([]); + const [upTags, setUpTags] = useState([]); + const [profileImageUrl, setProfileImageUrl] = useState(""); + const [backgroundImageUrl, setBackgroundImageUrl] = useState(""); + const [profileImageAvailable, setProfileImageAvailable] = + useState(false); + const [bgImageAvailable, setBgImageAvailable] = useState(false); + const [daoCardView, setDaoCardView] = useState(3); -const ProfileDetails = (props: {accountAddress: string}) => { - const {accountAddress} = props; - const { profileData } = useContext(ProfileContext); - const [upName, setUpName] = useState(''); - const [upDescription, setUpDescription] = useState(''); - const [upLinks, setUpLinks] = useState<{title: string, url: string}[]>([]); - const [upTags, setUpTags] = useState([]); - const [profileImageUrl, setProfileImageUrl] = useState(''); - const [backgroundImageUrl, setBackgroundImageUrl] = useState(''); - const [profileImageAvailable, setProfileImageAvailable] = useState(false); - const [bgImageAvailable, setBgImageAvailable] = useState(false); - const [daoCardView, setDaoCardView] = useState(3); - - const [daoSelected, setDaoSelected] = useState(0); - const [memberDaos, setMemberDaos] = useState([]); - const [filterString, setFilter] = useState(""); + const [daoSelected, setDaoSelected] = useState(0); + const [memberDaos, setMemberDaos] = useState([]); + const [filterString, setFilter] = useState(""); - const getUserProfile = async (upAddress:string) => { - try { - if (profileData.value.LSP3Profile) { - const profile = profileData?.value?.LSP3Profile; - const profileImgUrl = IPFS_GATEWAY.concat(profile?.profileImage[4]?.url.slice(7)); - const backgroundImgUrl = IPFS_GATEWAY.concat(profile?.backgroundImage[1]?.url.slice(7)); - // console.log(profile?.links); - setProfileImageAvailable(profile?.profileImage[4]?.url? true : false); - setBgImageAvailable(profile?.backgroundImage[0]?.url? true : false); - setProfileImageUrl(profileImgUrl); - setBackgroundImageUrl(backgroundImgUrl); - setUpName(profile?.name); - setUpDescription(profile?.description); - setUpLinks(profile?.links); - setUpTags(profile?.tags); - } - } catch (error) { - setUpName(shortenAddress(upAddress)); - console.log(upAddress,'This is not an ERC725 Contract'); - } + const getUserProfile = async (upAddress: string) => { + try { + if (profileData.value.LSP3Profile) { + const profile = profileData?.value?.LSP3Profile; + const profileImgUrl = IPFS_GATEWAY.concat( + profile?.profileImage[4]?.url.slice(7) + ); + const backgroundImgUrl = IPFS_GATEWAY.concat( + profile?.backgroundImage[1]?.url.slice(7) + ); + // console.log(profile?.links); + setProfileImageAvailable(profile?.profileImage[4]?.url ? true : false); + setBgImageAvailable(profile?.backgroundImage[0]?.url ? true : false); + setProfileImageUrl(profileImgUrl); + setBackgroundImageUrl(backgroundImgUrl); + setUpName(profile?.name); + setUpDescription(profile?.description); + setUpLinks(profile?.links); + setUpTags(profile?.tags); + } + } catch (error) { + setUpName(shortenAddress(upAddress)); + console.log(upAddress, "This is not an ERC725 Contract"); } - // const location = useLocation().pathname; - useEffect(() => { + }; + // const location = useLocation().pathname; + useEffect(() => { + if (accountAddress) { + getUserProfile(accountAddress); + const fetchData = async () => { if (accountAddress) { - getUserProfile(accountAddress); - const fetchData = async () => { - if (accountAddress) { - const result = await getDaoByMember(accountAddress); - setMemberDaos(result); - } - }; - fetchData(); + const result = await getDaoByMember(accountAddress); + setMemberDaos(result); } - window.scrollTo(0, 0) - }, [accountAddress]) + }; + fetchData(); + } + window.scrollTo(0, 0); + }, [accountAddress]); - useEffect(() => { - window.scrollTo(0, 0) - }, []) + useEffect(() => { + window.scrollTo(0, 0); + }, []); - const bg_imgfromurl = "url('".concat(backgroundImageUrl).concat("')"); - + const bg_imgfromurl = "url('".concat(backgroundImageUrl).concat("')"); - const filterParam = [ - "All", - "Investment", - "Grant", - "Protocol", - "Social", - "Research", - ]; + const filterParam = [ + "All", + "Investment", + "Grant", + "Protocol", + "Social", + "Research", + ]; - const filterByCategory = (category: string) => { + const filterByCategory = (category: string) => { if (category === "all") { - setFilter(""); + setFilter(""); } else { - // console.log(category) - setFilter(category); + // console.log(category) + setFilter(category); } - }; - - return ( -
-
-
-
-
- altimg -
- -
-

{upName}

-

{upDescription}

-
- - {upLinks.map((links:any, index:number) => ( - {links.title} - ))} -
-
- {/* */} - {upTags.map((tags:string, index:number) => ( -
- {tags} -
- ))} -
-
-
-
-
-
-

Joined DAOs

- {/*
+ }; + + return ( +
+
+
+
+ altimg +
+ +
+

{upName}

+

{upDescription}

+
+ + {upLinks.map((links: any, index: number) => ( + + {links.title} + + ))} +
+
+ {/* */} + {upTags.map((tags: string, index: number) => ( +
+ {tags} +
+ ))} +
+
+
+
+
+
+

Joined DAOs

+ {/*
setDaoCardView(2)} className="w-6 cursor-pointer hover:text-[#ac0537]" fontSize={20}/> setDaoCardView(3)} className="w-6 cursor-pointer hover:text-[#ac0537]" fontSize={18}/>
*/} -
-
-
- {filterParam.map((item,index) => ( -

filterByCategory(item.toLowerCase())} - > - {item} -

- ))} -
-
- {memberDaos.length != [] ? ( -
- {[...memberDaos] - .filter((dao: any) => - getParsedJsonObj(dao.categories)[0] - .value.toLowerCase() - .includes(filterString) - ) - .reverse() - .map( - (daoDetail, i) => ( - // console.log(getParsedJsonObj(daoDetail.categories)[0]), - () - ) - )} -
- ) : ( -
- {[1, 1, 1, 1].reverse().map((daoDetail, i) => ( - - ))} -
- )} -
-
- ); -} +
+
+
+ {filterParam.map((item, index) => ( +

filterByCategory(item.toLowerCase())} + > + {item} +

+ ))} +
+
+ {memberDaos.length !== 0 ? ( +
+ {[...memberDaos] + .filter((dao: any) => + getParsedJsonObj(dao.categories)[0] + .value.toLowerCase() + .includes(filterString) + ) + .reverse() + .map((daoDetail, i) => ( + // console.log(getParsedJsonObj(daoDetail.categories)[0]), + + ))} +
+ ) : ( +
+ {[1, 1, 1, 1].reverse().map((daoDetail, i) => ( + + ))} +
+ )} +
+
+ ); +}; export default ProfileDetails; @@ -212,16 +226,16 @@ const DaoCard = (props: { id: number; daoDetail: any }) => {
- Not Found { + alt="Not Found" + onError={({ currentTarget }) => { currentTarget.onerror = null; // prevents looping - currentTarget.src="https://i0.wp.com/zeevector.com/wp-content/uploads/2021/02/black-grey-gradient-background.jpg?resize=768%2C576&ssl=1"; + currentTarget.src = + "https://i0.wp.com/zeevector.com/wp-content/uploads/2021/02/black-grey-gradient-background.jpg?resize=768%2C576&ssl=1"; }} - - > - + >

diff --git a/src/components/proposal/AddUserPermissions.tsx b/src/components/proposal/AddUserPermissions.tsx new file mode 100644 index 0000000..05c3740 --- /dev/null +++ b/src/components/proposal/AddUserPermissions.tsx @@ -0,0 +1,479 @@ +import React, { useContext, useState, useEffect, useCallback } from "react"; +import { MdNavigateNext, MdOutlineNavigateBefore } from "react-icons/md"; +import { SingleSelect, Input } from "../../components"; +import { CreateProposalContext } from "../../context/CreateProposalContext"; +// import { daoCategoryItems } from "../../constants/daoCategoryItems"; +import Switch from "@material-ui/core/Switch"; +import { toast } from "react-toastify"; +import { VALIDATORS } from "../../constants/globals"; +import { getDaoByCID } from "../../services/keezBackend"; +import { getParsedJsonObj } from "../../utils/getParsedJsonObj"; +// import { StyledPopover } from "../../styles"; +import InfoPopOver from "../InfoPopOver"; +import { + permissionContract, + universalProfileContract, +} from "../../services/web3"; +import Select from "../Select"; +import { useLocation } from "react-router-dom"; + +const AddUserPermission = () => { + // const classes = StyledPopover(); + + // const { handleComponent } = props; + const { + proposalName, + setProposalName, + categories, + // setCategories, + description, + setDescription, + setKeyPermissions, + // setVaultPermissions, + keyPermissions, + // vaultPermissions, + membersOrVault, + // setMembersOrVault, + // daoCid, + } = useContext(CreateProposalContext); + + const location = useLocation() as any; + const daoCid = location.state.CID; + const [executePermission, setExecutePermission] = useState(false); + const [registerVotesPermission, setRegisterVotesPermission] = + useState(false); + const [addPermission, setAddPermission] = useState(false); + const [removePermission, setRemovePermission] = useState(false); + const [votePermission, setVotePermission] = useState(false); + const [proposePermission, setProposePermission] = useState(false); + const [sendDelegatePermission, setSendDelegatePermission] = + useState(false); + const [receiveDelegatePermission, setReceiveDelegatePermission] = + useState(false); + const [memberAddress, setMemberAddress] = useState(""); + // const [addOrRevoke, setAddOrRevoke] = useState("Add"); // true -> Add / false -> revoke + const daoSelected = location.state.dao; + const [memberExist, setMemberExists] = useState(false); + + toast.configure(); + + const formSubmitValidations = () => { + if (!memberAddress || memberAddress.length === 0) { + return "Please enter an address"; + } + if (memberExist) { + return "Member already exists"; + } + + // if (!categories || categories.length === 0) { + // return "Please select atleast one category for your proposal"; + // } + + // if (!description || description.length === 0) { + // return "Please add description for your proposal"; + // } + + return "success"; + }; + const universalProfile = getParsedJsonObj( + daoSelected?.daoUpAddress + )?.universalProfile; + const getPermissions = useCallback(async () => { + if (memberAddress) { + try { + let contract1 = await universalProfileContract(universalProfile) + ["getData(bytes32[])"]([ + "0x4b80742de2bfb3cc0e490000" + memberAddress.substring(2), + ]) + .call(); + const permissionBin = parseInt(contract1[0], 16).toString(2); + setRegisterVotesPermission(permissionBin[0] === "1"); + setRemovePermission(permissionBin[1] === "1"); + setAddPermission(permissionBin[2] === "1"); + setReceiveDelegatePermission(permissionBin[3] === "1"); + setSendDelegatePermission(permissionBin[4] === "1"); + setExecutePermission(permissionBin[5] === "1"); + setProposePermission(permissionBin[6] === "1"); + setVotePermission(permissionBin[7] === "1"); + } catch { + toast.error("An error ocurred, check your connection", { + position: toast.POSITION.BOTTOM_RIGHT, + }); + } + } + }, [universalProfile, memberAddress]); + const verifyExistence = useCallback(async () => { + try { + const contract1 = await universalProfileContract(universalProfile)[ + "getData(bytes32[])" + ](["0x4b80742de2bfb3cc0e490000" + memberAddress.substring(2)]); + if (contract1) { + setMemberExists(true); + } else { + setMemberExists(false); + } + } catch { + setMemberExists(false); + } + }, [memberAddress]); + + const handleSubmit = async (event: React.FormEvent) => { + event.preventDefault(); + + if (VALIDATORS) { + const validationResult = formSubmitValidations(); + + if (validationResult !== "success") { + return toast.error(validationResult, { + position: toast.POSITION.BOTTOM_RIGHT, + }); + } + } + // if (membersOrVault === "Members"){ + const permissionbyte = + (registerVotesPermission << 7) + + (removePermission << 6) + + (addPermission << 5) + + (receiveDelegatePermission << 4) + + (sendDelegatePermission << 3) + + (executePermission << 2) + + (proposePermission << 1) + + votePermission; + await permissionContract(universalProfile, memberAddress, permissionbyte); + setKeyPermissions({ + upAddress: memberAddress, + keyPermissions: { + vote: votePermission, + propose: proposePermission, + execute: executePermission, + registerVotes: registerVotesPermission, + addPermission: addPermission, + removePermission: removePermission, + sendDelegate: sendDelegatePermission, + receiveDelegate: receiveDelegatePermission, + }, + }); + // } else if (membersOrVault === "Vault"){ + // setVaultPermissions({vaultAddress:"", action:addOrRevoke}); + // } + // console.log(membersOrVault); + // console.log(addOrRevoke); + console.log("kp= ", keyPermissions); + // console.log(vaultPermissions); + }; + + const handleBack = async (event: React.FormEvent) => { + event.preventDefault(); + }; + + // const handleCategoriesChange = (selectedOption: any) => { + // setCategories(selectedOption); + // }; + + // const handleMemberChange = (selectedOption: any) => { + // const selection = membersList.find( + // (element: any) => element.label === selectedOption.label + // ); + // if (selection) setMemberAddress(selection.label); + // }; + + // const handleMasterKeyChange = () => { + // console.log(masterKeyPermission); + // setMasterKeyPermission(!masterKeyPermission); + // } + + // const onChangeAddOrRevoke = (event: any) => { + // console.log(event.target.value); + // setAddOrRevoke(event.target.value) + // } + + // const onChangeMembersOrVault = (event: any) => { + // console.log(event.target.value); + // setMembersOrVault(event.target.value) + // } + + useEffect(() => { + window.scrollTo(0, 0); + }, []); + useEffect(() => { + if (memberAddress) { + verifyExistence(); + } + }, [memberAddress, verifyExistence]); + + useEffect(() => { + if (daoCid) { + const fetchData = async () => { + const result = await getDaoByCID(daoCid); + console.log("doa selected set", result); + }; + fetchData(); + } + }, [daoCid]); + + useEffect(() => { + if (memberAddress) { + getPermissions(); + } + // for (var i = 0; i < permissionsObject.length; i++) { + // if (permissionsObject[i].upAddress == memberAddress) { + // setVotePermission(permissionsObject[i].keyPermissions.vote === "True"); + // setProposePermission( + // permissionsObject[i].keyPermissions.propose === "True" + // ); + // setSendDelegatePermission( + // permissionsObject[i].keyPermissions.sendDelegate === "True" + // ); + // setReceiveDelegatePermission( + // permissionsObject[i].keyPermissions.receiveDelegate === "True" + // ); + // setRegisterVotesPermission( + // permissionsObject[i].keyPermissions?.registerVotes === "True" + // ); + // setAddPermission( + // permissionsObject[i].keyPermissions?.addPermission === "True" + // ); + // setRemovePermission( + // permissionsObject[i].keyPermissions?.removePermission === "True" + // ); + // setExecutePermission( + // permissionsObject[i].keyPermissions?.execute === "True" + // ); + // } + // } + // console.log("member changes"); + // console.log(permissionsObject); + // console.log(daoSelected); + }, [memberAddress, getPermissions]); + + const permissionsObject = + daoSelected.length !== "" + ? getParsedJsonObj(daoSelected?.keyPermissions) + : ""; + // console.log(JSON.stringify(permissionsObject)); + const membersList: any = []; + + Object.keys(permissionsObject).forEach(function (key, index) { + membersList[key] = { + value: permissionsObject[key].upAddress, + label: permissionsObject[key].upAddress, + }; + }); + + toast.configure(); + return ( +
+ {/*

Step 1

*/} +
handleSubmit(event)}> + {/*
+

Create your Proposal

+ +
*/} +

+ Add Member Permission +

+
+
+ <> +
+ + +
+ + { + setMemberAddress(e.target.value); + }} + /> + + <> +
+ + +
+
+
+ {/* setVotePermission(e.target.checked)} className="accent-[#C3073F] focus:accent-[#ac0537]"/> */} + setVotePermission(!votePermission)} + name="maskerkey" + inputProps={{ "aria-label": "secondary checkbox" }} + /> + +
+
+ {/* setProposePermission(e.target.checked)} className="accent-[#C3073F] focus:accent-[#ac0537]"/> */} + + setProposePermission(!proposePermission) + } + name="propose" + inputProps={{ "aria-label": "secondary checkbox" }} + /> + +
+
+ {/* setReceiveDelegatePermission(e.target.checked)} className="accent-[#C3073F] focus:accent-[#ac0537]"/> */} + + setExecutePermission(!executePermission) + } + name="executePermission" + inputProps={{ "aria-label": "secondary checkbox" }} + /> + +
+
+ {/* setReceiveDelegatePermission(e.target.checked)} className="accent-[#C3073F] focus:accent-[#ac0537]"/> */} + + setRegisterVotesPermission(!registerVotesPermission) + } + name="registerVotesPermission" + inputProps={{ "aria-label": "secondary checkbox" }} + /> + +
+
+ {/* setReceiveDelegatePermission(e.target.checked)} className="accent-[#C3073F] focus:accent-[#ac0537]"/> */} + setAddPermission(!addPermission)} + name="addPermission" + inputProps={{ "aria-label": "secondary checkbox" }} + /> + +
+
+ {/* setReceiveDelegatePermission(e.target.checked)} className="accent-[#C3073F] focus:accent-[#ac0537]"/> */} + + setRemovePermission(!removePermission) + } + name="removePermission" + inputProps={{ "aria-label": "secondary checkbox" }} + /> + +
+
+ {/* setSendDelegatePermission(e.target.checked)} className="accent-[#C3073F] focus:accent-[#ac0537]"/> */} + + setSendDelegatePermission(!sendDelegatePermission) + } + name="sendDelegatePermission" + inputProps={{ "aria-label": "secondary checkbox" }} + /> + +
+
+ {/* setReceiveDelegatePermission(e.target.checked)} className="accent-[#C3073F] focus:accent-[#ac0537]"/> */} + + setReceiveDelegatePermission(!receiveDelegatePermission) + } + name="receiveDelegatePermission" + inputProps={{ "aria-label": "secondary checkbox" }} + /> + +
+
+ +
+ +
+
+
+
+
+ ); +}; + +export default AddUserPermission; diff --git a/src/components/proposal/ChooseDao.tsx b/src/components/proposal/ChooseDao.tsx index 620d320..eafa212 100644 --- a/src/components/proposal/ChooseDao.tsx +++ b/src/components/proposal/ChooseDao.tsx @@ -14,7 +14,7 @@ const ChooseDao = (props: { handleComponent: any }) => { const [daoSelected, setDaoSelected] = useState(0); const [zeroMember, setZeroMember] = useState(false); const [memberDaos, setMemberDaos] = useState([]); - const { setDaoCid } = useContext(CreateProposalContext); + const { setDaoCid, setDaoUpAddress } = useContext(CreateProposalContext); const { accountAddress } = useContext(ProfileContext); const handleSubmit = async (event: React.FormEvent) => { @@ -26,12 +26,14 @@ const ChooseDao = (props: { handleComponent: any }) => { const handleDaoSelection = async ( event: React.FormEvent, id: number, - CID: string + CID: string, + upAddress: string ) => { event.preventDefault(); setDaoSelected(id); // console.log("set dao cid", CID); setDaoCid(CID); + setDaoUpAddress(upAddress); }; useEffect(() => { @@ -42,10 +44,15 @@ const ChooseDao = (props: { handleComponent: any }) => { if (accountAddress) { const fetchData = async () => { const result = await getDaoByMember(accountAddress); + console.log(result); // console.log("x ->",result); setMemberDaos(result); if (result.length > 0) { setZeroMember(false); + setDaoUpAddress( + getParsedJsonObj(result[result.length - 1].daoUpAddress) + .universalProfile + ); setDaoCid(result[result.length - 1].CID); // console.log("CID",result[result.length - 1].CID) } else { @@ -151,11 +158,17 @@ const DaoCard = (props: { const navigate = useNavigate(); const profileImageObj = getParsedJsonObj(daoDetail.profileImage); const profileImageUrl = profileImageObj.url.concat(profileImageObj.hash); - return (
handleDaoSelection(event, id, daoDetail.CID)} + onClick={(event) => + handleDaoSelection( + event, + id, + daoDetail.CID, + getParsedJsonObj(daoDetail.daoUpAddress).universalProfile + ) + } onMouseLeave={handleMouseOut} onMouseEnter={handleMouseOver} > diff --git a/src/components/proposal/PermissionTemplate.tsx b/src/components/proposal/PermissionTemplate.tsx index 01ff66b..6e1e878 100644 --- a/src/components/proposal/PermissionTemplate.tsx +++ b/src/components/proposal/PermissionTemplate.tsx @@ -1,4 +1,4 @@ -import React, { useContext, useState, useEffect } from "react"; +import React, { useContext, useState, useEffect, useCallback } from "react"; import { MdNavigateNext, MdOutlineNavigateBefore } from "react-icons/md"; import { SingleSelect, Input } from "../../components"; import { CreateProposalContext } from "../../context/CreateProposalContext"; @@ -8,26 +8,28 @@ import { toast } from "react-toastify"; import { VALIDATORS } from "../../constants/globals"; import { getDaoByCID } from "../../services/keezBackend"; import { getParsedJsonObj } from "../../utils/getParsedJsonObj"; -import { StyledPopover } from "../../styles"; +// import { StyledPopover } from "../../styles"; import InfoPopOver from "../InfoPopOver"; +import { universalProfileContract } from "../../services/web3"; +import Select from "../Select"; const PermissionsTemplate = (props: { handleComponent: any }) => { - const classes = StyledPopover(); + // const classes = StyledPopover(); const { handleComponent } = props; const { proposalName, setProposalName, categories, - setCategories, + // setCategories, description, setDescription, setKeyPermissions, - setVaultPermissions, + // setVaultPermissions, keyPermissions, - vaultPermissions, + // vaultPermissions, membersOrVault, - setMembersOrVault, + // setMembersOrVault, daoCid, } = useContext(CreateProposalContext); @@ -43,8 +45,9 @@ const PermissionsTemplate = (props: { handleComponent: any }) => { const [receiveDelegatePermission, setReceiveDelegatePermission] = useState(false); const [memberAddress, setMemberAddress] = useState(""); - const [addOrRevoke, setAddOrRevoke] = useState("Add"); // true -> Add / false -> revoke + // const [addOrRevoke, setAddOrRevoke] = useState("Add"); // true -> Add / false -> revoke const [daoSelected, setDaoSelected] = useState([]); + const [addNewUser, setAddNewUser] = useState(false); toast.configure(); @@ -63,6 +66,33 @@ const PermissionsTemplate = (props: { handleComponent: any }) => { return "success"; }; + const universalProfile = getParsedJsonObj( + daoSelected?.daoUpAddress + )?.universalProfile; + const getPermissions = useCallback(async () => { + if (memberAddress) { + try { + let contract1 = await universalProfileContract(universalProfile) + ["getData(bytes32[])"]([ + "0x4b80742de2bfb3cc0e490000" + memberAddress.substring(2), + ]) + .call(); + const permissionBin = parseInt(contract1[0], 16).toString(2); + setRegisterVotesPermission(permissionBin[0] === "1"); + setRemovePermission(permissionBin[1] === "1"); + setAddPermission(permissionBin[2] === "1"); + setReceiveDelegatePermission(permissionBin[3] === "1"); + setSendDelegatePermission(permissionBin[4] === "1"); + setExecutePermission(permissionBin[5] === "1"); + setProposePermission(permissionBin[6] === "1"); + setVotePermission(permissionBin[7] === "1"); + } catch { + toast.error("An error ocurred, check your connection", { + position: toast.POSITION.BOTTOM_RIGHT, + }); + } + } + }, [universalProfile, memberAddress]); const handleSubmit = async (event: React.FormEvent) => { event.preventDefault(); @@ -106,9 +136,9 @@ const PermissionsTemplate = (props: { handleComponent: any }) => { handleComponent("ChooseTemplate"); }; - const handleCategoriesChange = (selectedOption: any) => { - setCategories(selectedOption); - }; + // const handleCategoriesChange = (selectedOption: any) => { + // setCategories(selectedOption); + // }; const handleMemberChange = (selectedOption: any) => { const selection = membersList.find( @@ -145,42 +175,45 @@ const PermissionsTemplate = (props: { handleComponent: any }) => { }; fetchData(); } - }, []); + }, [daoCid]); useEffect(() => { - for (var i = 0; i < permissionsObject.length; i++) { - if (permissionsObject[i].upAddress == memberAddress) { - setVotePermission(permissionsObject[i].keyPermissions.vote === "True"); - setProposePermission( - permissionsObject[i].keyPermissions.propose === "True" - ); - setSendDelegatePermission( - permissionsObject[i].keyPermissions.sendDelegate === "True" - ); - setReceiveDelegatePermission( - permissionsObject[i].keyPermissions.receiveDelegate === "True" - ); - setRegisterVotesPermission( - permissionsObject[i].keyPermissions?.registerVotes === "True" - ); - setAddPermission( - permissionsObject[i].keyPermissions?.addPermission === "True" - ); - setRemovePermission( - permissionsObject[i].keyPermissions?.removePermission === "True" - ); - setExecutePermission( - permissionsObject[i].keyPermissions?.execute === "True" - ); - } + if (memberAddress) { + getPermissions(); } - console.log("member changes"); - console.log(permissionsObject); - console.log(daoSelected); - }, [memberAddress]); + // for (var i = 0; i < permissionsObject.length; i++) { + // if (permissionsObject[i].upAddress == memberAddress) { + // setVotePermission(permissionsObject[i].keyPermissions.vote === "True"); + // setProposePermission( + // permissionsObject[i].keyPermissions.propose === "True" + // ); + // setSendDelegatePermission( + // permissionsObject[i].keyPermissions.sendDelegate === "True" + // ); + // setReceiveDelegatePermission( + // permissionsObject[i].keyPermissions.receiveDelegate === "True" + // ); + // setRegisterVotesPermission( + // permissionsObject[i].keyPermissions?.registerVotes === "True" + // ); + // setAddPermission( + // permissionsObject[i].keyPermissions?.addPermission === "True" + // ); + // setRemovePermission( + // permissionsObject[i].keyPermissions?.removePermission === "True" + // ); + // setExecutePermission( + // permissionsObject[i].keyPermissions?.execute === "True" + // ); + // } + // } + // console.log("member changes"); + // console.log(permissionsObject); + // console.log(daoSelected); + }, [memberAddress, getPermissions]); const permissionsObject = - daoSelected.length != "" + daoSelected.length !== "" ? getParsedJsonObj(daoSelected.keyPermissions) : ""; // console.log(JSON.stringify(permissionsObject)); @@ -296,15 +329,67 @@ const PermissionsTemplate = (props: { handleComponent: any }) => { htmlFor="minVotingPeriod" > Choose {membersOrVault === "Members" ? "Address" : "Vault"} from - List + List or Add new member
- { + setAddNewUser((value) => !value); + setMemberAddress(""); + }} + options={[ + { + value: true, + label: "Add new member", + }, + { + value: false, + label: "Choose from list", + }, + ]} /> + {!addNewUser ? ( + <> +
+ + +
+ + + ) : ( + <> +
+ + +
+ + { + setMemberAddress(e.target.value); + }} + /> + + )} {membersOrVault === "Members" && ( <> diff --git a/src/components/proposal/VotingTemplate.tsx b/src/components/proposal/VotingTemplate.tsx index 1103016..f5ddb2a 100644 --- a/src/components/proposal/VotingTemplate.tsx +++ b/src/components/proposal/VotingTemplate.tsx @@ -1,15 +1,18 @@ -import React, { useContext, useEffect } from "react"; +import React, { useCallback, useContext, useEffect, useState } from "react"; import { MdNavigateNext, MdOutlineNavigateBefore } from "react-icons/md"; -import { SingleSelect, Input } from "../../components"; +import { Input } from "../../components"; import { CreateProposalContext } from "../../context/CreateProposalContext"; // import { daoCategoryItems } from "../../constants/daoCategoryItems"; import { votingPeriodItems, votingDelayItems, + votingParams, } from "../../constants/votingPeriodItems"; import { toast } from "react-toastify"; import { VALIDATORS } from "../../constants/globals"; import InfoPopOver from "../InfoPopOver"; +import { universalProfileContract } from "../../services/web3"; +import Select from "../Select"; const VotingTemplate = (props: { handleComponent: any }) => { const { handleComponent } = props; @@ -24,15 +27,18 @@ const VotingTemplate = (props: { handleComponent: any }) => { setParticipationRate, votingMajority, setVotingMajority, - // minVotingDelay, setMinVotingDelay, - // minVotingPeriod, + minVotingDelay, + minExecutionDelay, + minVotingPeriod, setMinVotingPeriod, setMinExecutionDelay, + daoUpAddress, } = useContext(CreateProposalContext); toast.configure(); - + const [votingParameters, setVotingParams] = useState({}); + const [paramState, setParamState] = useState(true); const formSubmitValidations = () => { if (!proposalName || proposalName.length === 0) { return "Please enter a proposal title"; @@ -69,29 +75,53 @@ const VotingTemplate = (props: { handleComponent: any }) => { handleComponent("PreviewProposal"); }; - const handleMinVotingDelay = (selectedOption: any) => { - const selection = votingDelayItems.find( - (element) => element.label === selectedOption.label - ) || { value: 0, label: "instant" }; - setMinVotingDelay(selection.value); - console.log(selectedOption); - console.log(selection); + // const handleMinVotingDelay = (selectedOption: any) => { + // const selection = votingDelayItems.find( + // (element) => element.label === selectedOption.label + // ) || { value: 0, label: "instant" }; + // setMinVotingDelay(selection.value); + // console.log(selectedOption); + // console.log(selection); + // }; + const handleMinVotingDelay1 = (e: any) => { + setMinVotingDelay(parseInt(e.target.value)); + console.log(typeof e.target.value); + console.log(e.target.value); }; - const handleMinVotingPeriod = (selectedOption: any) => { - const selection = votingPeriodItems.find( - (element) => element.label === selectedOption.label - ) || { value: 1, label: "24 hrs" }; - setMinVotingPeriod(selection.value); - console.log(selection); + // const handleMinVotingPeriod = (selectedOption: any) => { + // const selection = votingPeriodItems.find( + // (element) => element.label === selectedOption.label + // ) || { value: 1, label: "24 hrs" }; + // setMinVotingPeriod(selection.value); + // console.log(selection); + // }; + const handleMinVotingPeriod1 = (e: any) => { + setMinVotingPeriod(parseInt(e.target.value)); + console.log(typeof e.target.value); + console.log(e.target.value); + }; + // const handleParamChange = (selectedOption: any) => { + // console.log(selectedOption); + // setParamState(selectedOption.value); + // }; + const handleParamChange1 = (e: any) => { + setParamState((prev) => !prev); + console.log(typeof Boolean(e.target.value)); + console.log(e.target.value); }; - const handleMinExecutionDelay = (selectedOption: any) => { - const selection = votingDelayItems.find( - (element) => element.label === selectedOption.label - ) || { value: 0, label: "instant" }; - setMinExecutionDelay(selection.value); - console.log(selection); + // const handleMinExecutionDelay = (selectedOption: any) => { + // const selection = votingDelayItems.find( + // (element) => element.label === selectedOption.label + // ) || { value: 0, label: "instant" }; + // setMinExecutionDelay(selection.value); + // console.log(selection); + // }; + const handleMinExecutionDelay1 = (e: any) => { + setMinExecutionDelay(parseInt(e.target.value)); + console.log(typeof e.target.value); + console.log(e.target.value); }; const handleBack = async (event: React.FormEvent) => { @@ -102,10 +132,57 @@ const VotingTemplate = (props: { handleComponent: any }) => { // const handleCategoriesChange = (selectedOption: any) => { // setCategories(selectedOption); // }; + const getProfile = useCallback(async () => { + let contract = await universalProfileContract(daoUpAddress) + ["getData(bytes32[])"]([ + // DAO Settings + "0xbc776f168e7b9c60bb2a7180950facd372cd90c841732d963c31a93ff9f8c127", + "0xf89f507ecd9cb7646ce1514ec6ab90d695dac9314c3771f451fd90148a3335a9", + "0x799787138cc40d7a47af8e69bdea98db14e1ead8227cef96814fa51751e25c76", + "0xd3cf4cd71858ea36c3f5ce43955db04cbe9e1f42a2c7795c25c1d430c9bb280a", + "0xb207580c05383177027a90d6c298046d3d60dfa05a32b0bb48ea9015e11a3424", + ]) + .call(); + const Params = { + votingMajority: parseInt(contract[0]), + participationRate: parseInt(contract[1]), + minVotingDelay: parseInt(contract[2]), + minVotingPeriod: parseInt(contract[3]) / (24 * 3600), + minExecutionDelay: parseInt(contract[4]) / (24 * 3600), + }; + setVotingParams(Params); + }, [daoUpAddress]); useEffect(() => { window.scrollTo(0, 0); - }, []); + console.log(daoUpAddress); + getProfile(); + }, [daoUpAddress, getProfile]); + useEffect(() => { + if (!paramState) { + setParticipationRate(votingParameters?.participationRate); + setVotingMajority(votingParameters?.votingMajority); + setMinVotingDelay(votingParameters?.minVotingDelay); + setMinExecutionDelay(votingParameters?.minExecutionDelay); + setMinVotingPeriod(votingParameters?.minVotingPeriod); + } + // else { + // setParticipationRate(0); + // setVotingMajority(0); + // setMinVotingDelay(0); + // setMinExecutionDelay(0); + // setMinVotingPeriod(0); + // } + }, [ + paramState, + votingParameters, + setParticipationRate, + setVotingMajority, + setMinVotingDelay, + setMinExecutionDelay, + setMinVotingPeriod, + ]); + console.log(votingParameters); toast.configure(); @@ -211,6 +288,32 @@ const VotingTemplate = (props: { handleComponent: any }) => { name="description" onChange={(e: any) => setDescription(e.target.value)} /> +
+ + +
+
+ {/* */} + handleMinVotingDelay1(e)} />
@@ -299,10 +408,16 @@ const VotingTemplate = (props: { handleComponent: any }) => { />

- */} + handleMinExecutionDelay1(e)} />
diff --git a/src/constants/votingPeriodItems.ts b/src/constants/votingPeriodItems.ts index 4e5d9cd..12f2535 100644 --- a/src/constants/votingPeriodItems.ts +++ b/src/constants/votingPeriodItems.ts @@ -1,49 +1,58 @@ export const votingPeriodItems = [ - { - value: "1", - label: "24 hrs", - }, - { - value: "2", - label: "48 hrs", - }, - { - value: "3", - label: "72 hrs", - }, - { - value: "7", - label: "One Week", - }, - { - value: "14", - label: "Two Weeks", - }, - ]; - - export const votingDelayItems = [ - { - value: "0", - label: "Instant", - }, - { - value: "1", - label: "24 hrs", - }, - { - value: "2", - label: "48 hrs", - }, - { - value: "3", - label: "72 hrs", - }, - { - value: "7", - label: "One Week", - }, - { - value: "14", - label: "Two Weeks", - }, - ]; \ No newline at end of file + { + value: "1", + label: "24 hrs", + }, + { + value: "2", + label: "48 hrs", + }, + { + value: "3", + label: "72 hrs", + }, + { + value: "7", + label: "One Week", + }, + { + value: "14", + label: "Two Weeks", + }, +]; +export const votingParams = [ + { + value: true, + label: "Custom Voting Parameters", + }, + { + value: false, + label: "Default Voting Parameters", + }, +]; +export const votingDelayItems = [ + { + value: "0", + label: "Instant", + }, + { + value: "1", + label: "24 hrs", + }, + { + value: "2", + label: "48 hrs", + }, + { + value: "3", + label: "72 hrs", + }, + { + value: "7", + label: "One Week", + }, + { + value: "14", + label: "Two Weeks", + }, +]; diff --git a/src/context/CreateProposalContext.tsx b/src/context/CreateProposalContext.tsx index 9a0c2ef..bba345d 100644 --- a/src/context/CreateProposalContext.tsx +++ b/src/context/CreateProposalContext.tsx @@ -1,181 +1,253 @@ -import React, {useState} from 'react'; +import React, { useState } from "react"; interface CreateProposalContextInterface { - proposalName: string; - setProposalName: any; - categories: {value:string, label:string}[]; - setCategories: any; - description: string; - setDescription: any; - participationRate: number; - setParticipationRate: any; - votingMajority: number; - setVotingMajority: any; - minVotingDelay: number; - setMinVotingDelay: any; - minVotingPeriod: number; - setMinVotingPeriod: any; - minExecutionDelay: number; - setMinExecutionDelay: any; - - selectedVault: string; - setSelectedVault: any; - selectedToken: string; - setSelectedToken: any; - tokenAmount: number; - setTokenAmount: any; - receivingAddress: string; - setReceivingAddress: any; - - coverImageFile: File|undefined; - setCoverImageFile: any; - votingOptions: string[]; - setVotingOptions: any; - - keyPermissions: {upAddress:string, action: string, keyPermissions:{vote:boolean, propose:boolean, execute:boolean, addPermission:boolean, removePermission:boolean, registerVotes:boolean, sendDelegate:boolean, receiveDelegate:boolean}}; - setKeyPermissions: any; - - vaultPermissions: {vaultAddress:string, action: string}; - setVaultPermissions: any; - - membersOrVault: string; - setMembersOrVault: any; - - proposer: string; - setProposer: any; - proposalType: string; - setProposalType: any; - daoCid: string; - setDaoCid: any; + proposalName: string; + setProposalName: any; + categories: { value: string; label: string }[]; + setCategories: any; + description: string; + setDescription: any; + participationRate: number; + setParticipationRate: any; + votingMajority: number; + setVotingMajority: any; + minVotingDelay: number; + setMinVotingDelay: any; + minVotingPeriod: number; + setMinVotingPeriod: any; + minExecutionDelay: number; + setMinExecutionDelay: any; + + selectedVault: string; + setSelectedVault: any; + selectedToken: string; + setSelectedToken: any; + tokenAmount: number; + setTokenAmount: any; + receivingAddress: string; + setReceivingAddress: any; + + coverImageFile: File | undefined; + setCoverImageFile: any; + votingOptions: string[]; + setVotingOptions: any; + + keyPermissions: { + upAddress: string; + action: string; + keyPermissions: { + vote: boolean; + propose: boolean; + execute: boolean; + addPermission: boolean; + removePermission: boolean; + registerVotes: boolean; + sendDelegate: boolean; + receiveDelegate: boolean; + }; + }; + setKeyPermissions: any; + + vaultPermissions: { vaultAddress: string; action: string }; + setVaultPermissions: any; + + membersOrVault: string; + setMembersOrVault: any; + + proposer: string; + setProposer: any; + proposalType: string; + setProposalType: any; + daoCid: string; + setDaoCid: any; + daoUpAddress: string; + setDaoUpAddress: any; } -export const CreateProposalContext = React.createContext( - { - proposalName: '', - setProposalName: () => {}, - categories: [{value: "DAO", label: "DAO"},{value: "Social", label: "Social"}], - setCategories: () => {}, - description: '', - setDescription: () => {}, - participationRate: 0, - setParticipationRate: () => {}, - votingMajority: 0, - setVotingMajority: () => {}, - minVotingDelay: 0, - setMinVotingDelay: () => {}, - minVotingPeriod: 1, - setMinVotingPeriod: () => {}, - minExecutionDelay: 0, - setMinExecutionDelay: () => {}, - - selectedVault: '', - setSelectedVault: () => {}, - selectedToken: '', - setSelectedToken: () => {}, - tokenAmount: 0, - setTokenAmount: () => {}, - receivingAddress: '', - setReceivingAddress: () => {}, - - - coverImageFile: null as any, - setCoverImageFile: () => {}, - votingOptions: [], - setVotingOptions: () => {}, - - keyPermissions: {upAddress:"", action: "", keyPermissions:{vote:false, propose:false, execute:false, addPermission:false, removePermission:false, registerVotes:false, sendDelegate:false, receiveDelegate:false}}, - setKeyPermissions: () => {}, - vaultPermissions: {vaultAddress:"", action:""}, - setVaultPermissions: () => {}, - membersOrVault: "", - setMembersOrVault: () => {}, - - proposer: '', - setProposer: () => {}, - proposalType: '', - setProposalType: () => {}, - daoCid: '', - setDaoCid: () => {}, - } -); - -export const CreateProposalContextProvider = ({children}:any) => { - const [proposalName, setProposalName] = useState(''); - const [categories, setCategories] = useState<{value:string, label:string}[]>([{value: "DAO", label: "DAO"},{value: "Social", label: "Social"}]); - const [description, setDescription] = useState(''); - const [participationRate, setParticipationRate] = useState(0); - const [votingMajority, setVotingMajority] = useState(0); - const [minVotingDelay, setMinVotingDelay] = useState(0); - const [minVotingPeriod, setMinVotingPeriod] = useState(1); - const [minExecutionDelay, setMinExecutionDelay] = useState(0); - - const [selectedVault, setSelectedVault] = useState(''); - const [selectedToken, setSelectedToken] = useState(''); - const [tokenAmount, setTokenAmount] = useState(0); - const [receivingAddress, setReceivingAddress] = useState(''); - - const [coverImageFile, setCoverImageFile] = useState(); - const [votingOptions, setVotingOptions] = useState(['For','Against', 'Abstain']); - - const [keyPermissions, setKeyPermissions] = useState<{upAddress:string, action:string, keyPermissions:{vote:boolean, propose:boolean, execute:boolean, addPermission:boolean, removePermission:boolean, registerVotes:boolean, sendDelegate:boolean, receiveDelegate:boolean}}> - ( {upAddress:"", action: "", keyPermissions:{vote:false, propose:false, execute:false, addPermission:false, removePermission:false, registerVotes:false, sendDelegate:false, receiveDelegate:false}}); - const [vaultPermissions, setVaultPermissions] = useState<{vaultAddress:string, action:string}>({vaultAddress:"", action:""}); - const [membersOrVault, setMembersOrVault] = useState("Members"); - - const [proposer, setProposer] = useState(''); - const [proposalType, setProposalType] = useState(''); - const [daoCid, setDaoCid] = useState(''); - - return ( - - {children} - - ); -} \ No newline at end of file +export const CreateProposalContext = + React.createContext({ + proposalName: "", + setProposalName: () => {}, + categories: [ + { value: "DAO", label: "DAO" }, + { value: "Social", label: "Social" }, + ], + setCategories: () => {}, + description: "", + setDescription: () => {}, + participationRate: 0, + setParticipationRate: () => {}, + votingMajority: 0, + setVotingMajority: () => {}, + minVotingDelay: 0, + setMinVotingDelay: () => {}, + minVotingPeriod: 1, + setMinVotingPeriod: () => {}, + minExecutionDelay: 0, + setMinExecutionDelay: () => {}, + + selectedVault: "", + setSelectedVault: () => {}, + selectedToken: "", + setSelectedToken: () => {}, + tokenAmount: 0, + setTokenAmount: () => {}, + receivingAddress: "", + setReceivingAddress: () => {}, + + coverImageFile: null as any, + setCoverImageFile: () => {}, + votingOptions: [], + daoUpAddress: "", + setDaoUpAddress: () => {}, + setVotingOptions: () => {}, + + keyPermissions: { + upAddress: "", + action: "", + keyPermissions: { + vote: false, + propose: false, + execute: false, + addPermission: false, + removePermission: false, + registerVotes: false, + sendDelegate: false, + receiveDelegate: false, + }, + }, + setKeyPermissions: () => {}, + vaultPermissions: { vaultAddress: "", action: "" }, + setVaultPermissions: () => {}, + membersOrVault: "", + setMembersOrVault: () => {}, + + proposer: "", + setProposer: () => {}, + proposalType: "", + setProposalType: () => {}, + daoCid: "", + setDaoCid: () => {}, + }); + +export const CreateProposalContextProvider = ({ children }: any) => { + const [proposalName, setProposalName] = useState(""); + const [categories, setCategories] = useState< + { value: string; label: string }[] + >([ + { value: "DAO", label: "DAO" }, + { value: "Social", label: "Social" }, + ]); + const [description, setDescription] = useState(""); + const [participationRate, setParticipationRate] = useState(0); + const [votingMajority, setVotingMajority] = useState(0); + const [minVotingDelay, setMinVotingDelay] = useState(0); + const [minVotingPeriod, setMinVotingPeriod] = useState(1); + const [minExecutionDelay, setMinExecutionDelay] = useState(0); + + const [selectedVault, setSelectedVault] = useState(""); + const [selectedToken, setSelectedToken] = useState(""); + const [tokenAmount, setTokenAmount] = useState(0); + const [receivingAddress, setReceivingAddress] = useState(""); + + const [coverImageFile, setCoverImageFile] = useState(); + const [votingOptions, setVotingOptions] = useState([ + "For", + "Against", + "Abstain", + ]); + + const [keyPermissions, setKeyPermissions] = useState<{ + upAddress: string; + action: string; + keyPermissions: { + vote: boolean; + propose: boolean; + execute: boolean; + addPermission: boolean; + removePermission: boolean; + registerVotes: boolean; + sendDelegate: boolean; + receiveDelegate: boolean; + }; + }>({ + upAddress: "", + action: "", + keyPermissions: { + vote: false, + propose: false, + execute: false, + addPermission: false, + removePermission: false, + registerVotes: false, + sendDelegate: false, + receiveDelegate: false, + }, + }); + const [vaultPermissions, setVaultPermissions] = useState<{ + vaultAddress: string; + action: string; + }>({ vaultAddress: "", action: "" }); + const [membersOrVault, setMembersOrVault] = useState("Members"); + + const [proposer, setProposer] = useState(""); + const [proposalType, setProposalType] = useState(""); + const [daoCid, setDaoCid] = useState(""); + const [daoUpAddress, setDaoUpAddress] = useState(""); + + return ( + + {children} + + ); +}; diff --git a/src/context/DeployDaoContext.tsx b/src/context/DeployDaoContext.tsx index 479ee91..6516351 100644 --- a/src/context/DeployDaoContext.tsx +++ b/src/context/DeployDaoContext.tsx @@ -1,152 +1,192 @@ -import React, { useEffect, useState } from 'react'; -import useWeb3 from '../hooks/useWeb3'; -import UniversalReceiverDelegateUPJSON from '../keezContracts/deps/UniversalReceiverDelegateUP.sol/UniversalReceiverDelegateUP.json'; -import UniversalProfileJSON from '../keezContracts/deps/UniversalProfile.sol/UniversalProfile.json'; -import DaoDeployerJSON from '../keezContracts/Deployer/Deployer.sol/Deployer.json'; +import React, { useEffect, useState } from "react"; +import useWeb3 from "../hooks/useWeb3"; +import UniversalReceiverDelegateUPJSON from "../keezContracts/deps/UniversalReceiverDelegateUP.sol/UniversalReceiverDelegateUP.json"; +import UniversalProfileJSON from "../keezContracts/deps/UniversalProfile.sol/UniversalProfile.json"; +import DaoDeployerJSON from "../keezContracts/Deployer/Deployer.sol/Deployer.json"; import { ethers } from "ethers"; interface DeployDaoContextInterface { - // deployUniversalReceiverDelegateUP: any, - executeDeployer: any + // deployUniversalReceiverDelegateUP: any, + executeDeployer: any; } -export const DeployDaoContext = React.createContext( - { - // deployUniversalReceiverDelegateUP: () => {}, - executeDeployer: () => {}, - } -); +export const DeployDaoContext = React.createContext({ + // deployUniversalReceiverDelegateUP: () => {}, + executeDeployer: () => {}, +}); -export const DeployDaoProvider = ({children}:any) => { - const web3 = useWeb3(); - const [owner, setOwner] = useState(''); - const [signer, setSigner] = useState([]); - const [provider, setProvider] = useState([]); - // const [universalReceiverDelegateUPState, setUniversalReceiverDelegateUPState] = useState([]); +export const DeployDaoProvider = ({ children }: any) => { + const web3 = useWeb3(); + const [owner, setOwner] = useState(""); + const [signer, setSigner] = useState([]); + const [provider, setProvider] = useState([]); + // const [universalReceiverDelegateUPState, setUniversalReceiverDelegateUPState] = useState([]); - useEffect(() => { - const fetchProvider = async () => { - const provider = new ethers.providers.Web3Provider(window.ethereum) - setProvider(provider); - console.log("provider ",provider); - - const signer = provider.getSigner(); - setSigner(signer); - console.log("provider ",signer); - - const owner = await signer.getAddress(); - setOwner(owner); - console.log("owner ",owner); - - } - fetchProvider(); - }, []); + useEffect(() => { + const fetchProvider = async () => { + const provider = new ethers.providers.Web3Provider(window.ethereum); + setProvider(provider); + console.log("provider ", provider); - - const executeDeployer = async (DaoUpMetadata: any, metalink:string) => { - try { - console.log("DaoUpMetadata",JSON.stringify(DaoUpMetadata)) - console.log("metalink",JSON.stringify(metalink)) - const votingParameters = DaoUpMetadata.votingParameters; - const voting_majority = Number(votingParameters.votingMajority); - const participation_rate = Number(votingParameters.participationRate); - const min_voting_delay = Number(votingParameters.minVotingDelay)*24*3600; - const min_voting_period = Number(votingParameters.minVotingPeriod)*24*3600; - const min_execution_delay = Number(votingParameters.minExecutionDelay)*24*3600; - console.log(typeof voting_majority,"voting_majority",voting_majority); - console.log(typeof participation_rate,"participation_rate",participation_rate); - console.log(typeof min_voting_delay,"min_voting_delay",min_voting_delay); - console.log(typeof min_voting_period,"min_voting_period",min_voting_period); - console.log(typeof min_execution_delay,"min_execution_delay",min_execution_delay); - - let addressArray = [] - let permissionArray = [] - for (let i=0; i { + try { + console.log("DaoUpMetadata", JSON.stringify(DaoUpMetadata)); + console.log("metalink", JSON.stringify(metalink)); + const votingParameters = DaoUpMetadata.votingParameters; + const voting_majority = Number(votingParameters.votingMajority); + const participation_rate = Number(votingParameters.participationRate); + const min_voting_delay = + Number(votingParameters.minVotingDelay) * 24 * 3600; + const min_voting_period = + Number(votingParameters.minVotingPeriod) * 24 * 3600; + const min_execution_delay = + Number(votingParameters.minExecutionDelay) * 24 * 3600; + console.log(typeof voting_majority, "voting_majority", voting_majority); + console.log( + typeof participation_rate, + "participation_rate", + participation_rate + ); + console.log( + typeof min_voting_delay, + "min_voting_delay", + min_voting_delay + ); + console.log( + typeof min_voting_period, + "min_voting_period", + min_voting_period + ); + console.log( + typeof min_execution_delay, + "min_execution_delay", + min_execution_delay + ); + + let addressArray = []; + let permissionArray = []; + for (let i = 0; i < DaoUpMetadata.keyPermissions.length; i++) { + const upAddress = DaoUpMetadata.keyPermissions[i].upAddress; + const permissions = DaoUpMetadata.keyPermissions[i].keyPermissions; + + addressArray.push(upAddress); + const permissionbyte = + (permissions.registerVotes << 7) + + (permissions.removePermission << 6) + + (permissions.addPermission << 5) + + (permissions.receiveDelegate << 4) + + (permissions.sendDelegate << 3) + + (permissions.execute << 2) + + (permissions.propose << 1) + + permissions.vote; + permissionArray.push( + ethers.utils.hexZeroPad(ethers.utils.hexValue(permissionbyte), 32) + ); + } + + console.log(addressArray); + console.log(permissionArray); + const universalReceiverDelegateUPAddress = + "0x718D6ceD390FAeC92Aff2d8581BD41255a7fE1Cb"; + const deployerAddress = "0xD8443C594CFC573406ca80a86e879D3aa1750d7E"; + const deployer = new ethers.Contract( + deployerAddress, + DaoDeployerJSON.abi, + signer + ); + const deployment = await deployer + .connect(signer) + [ + "deploy(address,bytes,bytes32,bytes32,bytes32,bytes32,bytes32,address[],bytes32[])" + ]( + universalReceiverDelegateUPAddress, + ethers.utils.hexlify(ethers.utils.toUtf8Bytes(metalink)), + ethers.utils.hexZeroPad(ethers.utils.hexValue(voting_majority), 32), + ethers.utils.hexZeroPad( + ethers.utils.hexValue(participation_rate), + 32 + ), + ethers.utils.hexZeroPad(ethers.utils.hexValue(min_voting_delay), 32), + ethers.utils.hexZeroPad(ethers.utils.hexValue(min_voting_period), 32), + ethers.utils.hexZeroPad( + ethers.utils.hexValue(min_execution_delay), + 32 + ), + addressArray, + permissionArray + ); + console.log("deployment done", deployment); + + const addresses = await deployer.connect(signer).getAddresses(); + const contractAddresses = { + UNIVERSAL_PROFILE: addresses[0], + KEY_MANAGER: addresses[1], + DAO_PERMISSIONS: addresses[2], + DAO_DELEGATES: addresses[3], + DAO_PROPOSALS: addresses[4], + MULTISIG: addresses[5], + UNIVERSALRECEIVER: universalReceiverDelegateUPAddress, + }; + const UniversalProfile = new ethers.ContractFactory( + UniversalProfileJSON.abi, + UniversalProfileJSON.bytecode, + signer + ); + const universalProfile = UniversalProfile.attach(addresses[0]); + console.log(await universalProfile.owner()); + console.log(contractAddresses); + return { hash: deployment.hash, contractAddresses: contractAddresses }; + } catch (error) { + console.log(error); + return "Stopped"; } + }; + + // const deployUniversalReceiverDelegateUP = async () => { + // try { + // let txHash:string = ""; + // //@ts-ignore + // const UniversalReceiverDelegateUP = new web3.eth.Contract(UniversalReceiverDelegateUPJSON.abi) + // const universalReceiverDelegateUP = UniversalReceiverDelegateUP.deploy({ + // data: UniversalReceiverDelegateUPJSON.bytecode, + // arguments: [] + // }) + // console.log("this") + // const newContractInstance = await universalReceiverDelegateUP.send({ + // from: owner, + // gas: 1500000 + // }).on('transactionHash', function(hash:string){ + // txHash = hash; + // }) - // const deployUniversalReceiverDelegateUP = async () => { - // try { - // let txHash:string = ""; - // //@ts-ignore - // const UniversalReceiverDelegateUP = new web3.eth.Contract(UniversalReceiverDelegateUPJSON.abi) - // const universalReceiverDelegateUP = UniversalReceiverDelegateUP.deploy({ - // data: UniversalReceiverDelegateUPJSON.bytecode, - // arguments: [] - // }) - // console.log("this") - // const newContractInstance = await universalReceiverDelegateUP.send({ - // from: owner, - // gas: 1500000 - // }).on('transactionHash', function(hash:string){ - // txHash = hash; - // }) - - // console.log("universalReceiverDelegateUP is deployed",newContractInstance.options.address); - // setUniversalReceiverDelegateUPState(newContractInstance.options); - // return {hash0: txHash , contractAddress0:newContractInstance.options.address} - // } catch (error) { - // console.log(error); - // return "Stopped" - // } - // } + // console.log("universalReceiverDelegateUP is deployed",newContractInstance.options.address); + // setUniversalReceiverDelegateUPState(newContractInstance.options); + // return {hash0: txHash , contractAddress0:newContractInstance.options.address} + // } catch (error) { + // console.log(error); + // return "Stopped" + // } + // } - - return ( - - {children} - - ); + return ( + + {children} + + ); }; diff --git a/src/context/ProfileContext.tsx b/src/context/ProfileContext.tsx index 292f457..78ef53d 100644 --- a/src/context/ProfileContext.tsx +++ b/src/context/ProfileContext.tsx @@ -1,115 +1,116 @@ -import React, { useEffect, useState } from 'react'; -import useWeb3 from '../hooks/useWeb3'; -import { requestAccount, getAccountBalance } from '../services/web3'; -import { fetchErc725Data } from '../services/erc725'; +import React, { useEffect, useState } from "react"; +import useWeb3 from "../hooks/useWeb3"; +import { requestAccount, getAccountBalance } from "../services/web3"; +import { fetchErc725Data } from "../services/erc725"; interface ProfileContextInterface { - accountAddress: string; - accountBalance: number; - connectWallet: any; - disconnectWallet: any; - profileData: any; - getProfileInfo: any; + accountAddress: string; + accountBalance: number; + connectWallet: any; + disconnectWallet: any; + profileData: any; + getProfileInfo: any; } -export const ProfileContext = React.createContext( - { - accountAddress: "", - accountBalance: 0, - connectWallet: () => {}, - disconnectWallet: () => {}, - profileData:{}, - getProfileInfo: () => {}, - } -); +export const ProfileContext = React.createContext({ + accountAddress: "", + accountBalance: 0, + connectWallet: () => {}, + disconnectWallet: () => {}, + profileData: {}, + getProfileInfo: () => {}, +}); +export const ProfileProvider = ({ children }: any) => { + const web3 = useWeb3(); + const [accountAddress, setAccountAddress] = useState(""); + const [accountBalance, setAccountBalance] = useState(0); + const [profileData, setProfileData] = useState({}); -export const ProfileProvider = ({children}:any) => { - const web3 = useWeb3(); - const [accountAddress, setAccountAddress] = useState(''); - const [accountBalance, setAccountBalance] = useState(0); - const [profileData, setProfileData] = useState({}); - - // const provider = new Web3.providers.HttpProvider(RPC_URL); - // const config = { ipfsGateway: IPFS_GATEWAY }; + // const provider = new Web3.providers.HttpProvider(RPC_URL); + // const config = { ipfsGateway: IPFS_GATEWAY }; - useEffect(() => { - if (!accountAddress || !web3) return; + useEffect(() => { + if (!accountAddress || !web3) return; - getAccountBalance(web3, accountAddress).then((balance:any) => { - setAccountBalance(balance); - // if (balance > 0) { - // setStep(STEP.DEPLOY_UP); - // } - }); - }, [accountAddress, web3]); + getAccountBalance(web3, accountAddress).then((balance: any) => { + setAccountBalance(balance); + // if (balance > 0) { + // setStep(STEP.DEPLOY_UP); + // } + }); + }, [accountAddress, web3]); - - const connectWallet = async () => { - // console.log("connect"); - try { - if (web3){ - const account = await requestAccount(web3); - console.log("this",account); - setAccountAddress(account); - fetchProfile(account); - } - } catch (error) { - window.open('https://docs.lukso.tech/guides/browser-extension/install-browser-extension','_blank')?.focus(); - console.log(error); - throw new Error("No object found") - } + const connectWallet = async () => { + // console.log("connect"); + try { + if (web3) { + const account = await requestAccount(web3); + console.log("this", account); + setAccountAddress(account); + fetchProfile(account); + } + } catch (error) { + window + .open( + "https://docs.lukso.tech/guides/browser-extension/install-browser-extension", + "_blank" + ) + ?.focus(); + console.log(error); + throw new Error("No object found"); } + }; - const disconnectWallet = async () => { - try { - if (!web3) return alert("Please install metamask") - setAccountAddress(""); - } catch (error) { - console.log(error); - throw new Error("No object found") - } + const disconnectWallet = async () => { + try { + if (!web3) return alert("Please install metamask"); + setAccountAddress(""); + } catch (error) { + console.log(error); + throw new Error("No object found"); } + }; - const fetchProfile = async (account: string) => { - try { - const data = await fetchErc725Data(account); - setProfileData(data); - console.log("erc725profile = ", data) - } catch (error) { - console.log('This is not an ERC725 Contract'); - } - } + const fetchProfile = async (account: string) => { + try { + const data = await fetchErc725Data(account); + setProfileData(data); + console.log("erc725profile = ", data); + } catch (error) { + console.log("This is not an ERC725 Contract"); + } + }; - const getProfileInfo = async (account: string) => { - try { - const data = await fetchErc725Data(account); - // setProfileData(data); - // console.log("erc725profile = ", data) - return data; - } catch (error) { - console.log('This is not an ERC725 Contract'); - return []; - } + const getProfileInfo = async (account: string) => { + try { + const data = await fetchErc725Data(account); + // setProfileData(data); + // console.log("erc725profile = ", data) + return data; + } catch (error) { + console.log("This is not an ERC725 Contract"); + return []; } - - // Debug - // fetchProfile(accountAddress).then((profileData) => - // console.log(JSON.stringify(profileData, undefined, 2)), - // ); + }; - return ( - - {children} - - ); -}; + // Debug + // fetchProfile(accountAddress).then((profileData) => + // console.log(JSON.stringify(profileData, undefined, 2)), + // ); + return ( + + {children} + + ); +}; diff --git a/src/modals/ProposalVotingModal.tsx b/src/modals/ProposalVotingModal.tsx index b866e39..fa1a1a0 100644 --- a/src/modals/ProposalVotingModal.tsx +++ b/src/modals/ProposalVotingModal.tsx @@ -357,7 +357,7 @@ export default function ProposalVotingModal(props: { const signature_array: string[] = []; const address_array: string[] = []; const choice_array: string[] = []; - for (var i = 0; i < votes.length; i++) { + for (var i = 0; i < votes.length; i++) { if (Number(votes[i].VoterChoice) !== 0) { signature_array.push(votes[i].VoterSignature); choice_array.push(votes[i].VoterChoice); diff --git a/src/pages/DaoProfile.tsx b/src/pages/DaoProfile.tsx index 7df0394..ecec065 100644 --- a/src/pages/DaoProfile.tsx +++ b/src/pages/DaoProfile.tsx @@ -9,9 +9,9 @@ import { } from "../components/daoProfile"; import Skeleton from "@material-ui/lab/Skeleton"; import { getParsedJsonObj } from "../utils/getParsedJsonObj"; -import { MdCreate } from "react-icons/md"; +import { MdCreate, MdOutlineAdd } from "react-icons/md"; import MobileSideNav from "../components/MobileSideNav"; -import { universalProfileContract } from "../services/web3"; +import { permissionContract, universalProfileContract } from "../services/web3"; import { toast } from "react-toastify"; //@ts-ignore type LocationProps = { @@ -30,6 +30,9 @@ const DaoProfile = () => { const universalProfile = getParsedJsonObj( daoDetail.daoUpAddress ).universalProfile; + const permissionProfile = getParsedJsonObj( + daoDetail.daoUpAddress + ).daoPermissions; const navigate = useNavigate(); @@ -41,6 +44,10 @@ const DaoProfile = () => { const profileImageUrl = profileImageObj.url.concat(profileImageObj.hash); // console.log(user.length); const isMember: boolean = permisions.vote ? true : false; + const changePermission: boolean = + permisions?.addPermission === true && permisions?.removePermission == true + ? true + : false; const getProfile = useCallback(async () => { let contract = await universalProfileContract(universalProfile) ["getData(bytes32[])"]([ @@ -52,6 +59,8 @@ const DaoProfile = () => { "0xb207580c05383177027a90d6c298046d3d60dfa05a32b0bb48ea9015e11a3424", ]) .call(); + // let Permision = await permissionContract(permissionProfile); + // console.log("perm", Permision); if (accountAddress) { let contract1 = await universalProfileContract(universalProfile) ["getData(bytes32[])"]([ @@ -88,6 +97,11 @@ const DaoProfile = () => { state: { component: "ChooseTemplate", CID: daoDetail.CID }, }); }; + const handleAddPermisson = (event: any) => { + navigate("/addmember", { + state: { CID: daoDetail.CID, dao: daoDetail }, + }); + }; toast.configure(); useEffect(() => { window.scrollTo(0, 0); @@ -112,7 +126,7 @@ const DaoProfile = () => { profileComponent={profileComponent} />
-
+
{profileImageObj ? (
{ />
)} -
+

{daoDetail.daoName}

-

{daoDetail.description}

+

{daoDetail.description}

+
+
+ {isMember && ( +
+ +

Create Proposal

+
+ )} + {changePermission && ( +
+ +

Add Member

+
+ )}
- {isMember && ( -
- -

Create Proposal

-
- )}
<> {profileComponent === "Proposals" && ( diff --git a/src/pages/Governance.tsx b/src/pages/Governance.tsx index 4531fb5..0d06e28 100644 --- a/src/pages/Governance.tsx +++ b/src/pages/Governance.tsx @@ -1,14 +1,23 @@ -import React, {useContext, useState,useEffect} from 'react' -import { useNavigate, useLocation } from "react-router-dom"; -import { ConnectProfileModal } from '../modals'; -import { CreateProposalContext } from '../context/CreateProposalContext' -import { ProfileContext } from '../context/ProfileContext' -import { ChooseDao, ChooseTemplate, GeneralTemplate, VotingTemplate, PermissionTemplate, DaoTransferTokenTemplate, PreviewProposal } from "../components/proposal"; +import React, { useContext, useState, useEffect } from "react"; +import { useLocation } from "react-router-dom"; +import { ConnectProfileModal } from "../modals"; +import { CreateProposalContext } from "../context/CreateProposalContext"; +import { ProfileContext } from "../context/ProfileContext"; +import { + ChooseDao, + ChooseTemplate, + GeneralTemplate, + VotingTemplate, + PermissionTemplate, + DaoTransferTokenTemplate, + PreviewProposal, +} from "../components/proposal"; type LocationProps = { state: { component: string; - CID:string; + CID: string; + page: string; }; }; @@ -16,44 +25,65 @@ const Governance: React.FC = () => { const location = useLocation() as unknown as LocationProps; const { accountAddress } = useContext(ProfileContext); const { setDaoCid } = useContext(CreateProposalContext); - const [formComponent, setFormComponent] = useState('ChooseDao'); - const [metalink, setMetalink] = useState(''); + const [formComponent, setFormComponent] = useState("ChooseDao"); const component = location.state?.component; + const page = location.state?.page; const CID = location.state?.CID; - const handleComponent = (NextForm:string) => { + const handleComponent = (NextForm: string) => { console.log(NextForm); setFormComponent(NextForm); - } + }; + // useEffect(() => { + // window.scrollTo(0, 0); + // if (page) { + // setFormComponent(page); + // } + // }, []); useEffect(() => { - window.scrollTo(0, 0) + window.scrollTo(0, 0); + if (component) { setFormComponent(component); setDaoCid(CID); } - }, []) + }, [component, CID, setDaoCid]); return (
- { !accountAddress ? ( + {!accountAddress ? (
- -

Connect your user profile

+ +

Connect your user profile

- ):( - <> - { (formComponent === "ChooseDao") && ()} - { (formComponent === "ChooseTemplate") && ()} - { (formComponent === "PermissionTemplate") && ()} - { (formComponent === "GeneralTemplate") && ()} - { (formComponent === "DaoTransferTokenTemplate") && ()} - { (formComponent === "VotingTemplate") && ()} - { (formComponent === "PreviewProposal") && ()} - - )} + ) : ( + <> + {formComponent === "ChooseDao" && ( + + )} + {formComponent === "ChooseTemplate" && ( + + )} + {formComponent === "PermissionTemplate" && ( + + )} + {formComponent === "GeneralTemplate" && ( + + )} + {formComponent === "DaoTransferTokenTemplate" && ( + + )} + {formComponent === "VotingTemplate" && ( + + )} + {formComponent === "PreviewProposal" && ( + + )} + + )}
); -} +}; export default Governance; diff --git a/src/pages/IndividualProfile.tsx b/src/pages/IndividualProfile.tsx new file mode 100644 index 0000000..c23029f --- /dev/null +++ b/src/pages/IndividualProfile.tsx @@ -0,0 +1,62 @@ +import React, { useContext, useState, useEffect } from "react"; +import { ConnectProfileModal } from "../modals"; +import { ProfileContext } from "../context/ProfileContext"; +import { + UserActivity, + ProfileDetails, + ProfileSideBar, + Paops, +} from "../components/individualProfile"; +import { useParams } from "react-router-dom"; + +const IndividualProfile: React.FC = () => { + // const { accountAddress } = useContext(ProfileContext); + const { address } = useParams(); + const accountAddress = address; + const [profileComponent, setProfileComponent] = + useState("ProfileDetails"); + + const handleComponent = (Component: string) => { + // console.log(Component); + setProfileComponent(Component); + // createDaoService(accountAddress); + }; + + useEffect(() => { + window.scrollTo(0, 0); + }, []); + + return ( +
+ {!accountAddress ? ( +
+ +

Connect your user profile

+
+ ) : ( +
+ + <> + {profileComponent === "ProfileDetails" && ( + + )} + {profileComponent === "UserActivity" && ( + + )} + {profileComponent === "POAPs" && ( + + )} + +
+ )} +
+ ); +}; + +export default IndividualProfile; diff --git a/src/services/web3.ts b/src/services/web3.ts index 69103f0..dbfe8aa 100644 --- a/src/services/web3.ts +++ b/src/services/web3.ts @@ -2,6 +2,7 @@ import { ethers } from "ethers"; import Web3 from "web3"; import web3 from "web3"; import deployer from "../keezContracts/deps/UniversalProfile.sol/UniversalProfile.json"; +import permission from "../keezContracts/Dao/DaoPermissions.sol/DaoPermissions.json"; export const getAccountBalance = async (web3: Web3, account: string) => { return parseFloat(web3.utils.fromWei(await web3.eth.getBalance(account))); @@ -18,11 +19,34 @@ export const universalProfileContract = (address: string) => { // const provider = new ethers.providers.JsonRpcProvider( // "https://rpc.l16.lukso.network/" // ); - const provider = new ethers.providers.Web3Provider(window.ethereum); - const signer = provider.getSigner(); + // const provider = new ethers.providers.Web3Provider(window.ethereum); + // const signer = provider.getSigner(); // const contract = new ethers.Contract("address", deployer.abi as any, signer); // let method: any = new Web3.eth.Contract(deployer.abi as any, address).methods; let method: any = new Web3.eth.Contract(deployer.abi as any, address).methods; // return contract; return method; }; +export const permissionContract = async ( + address: string, + profile: string, + permissionByte: number +) => { + // const Web3 = new web3("https://rpc.l16.lukso.network/"); + // const provider = new ethers.providers.JsonRpcProvider( + // "https://rpc.l16.lukso.network/" + // ); + const provider = new ethers.providers.Web3Provider(window.ethereum); + const signer = provider.getSigner(); + const contract = new ethers.Contract(address, permission.abi as any, signer); + contract.addPermissions( + profile, + ethers.utils.hexZeroPad(ethers.utils.hexValue(permissionByte), 32) + ); + + // let method: any = new Web3.eth.Contract(deployer.abi as any, address).methods; + // let method: any = new Web3.eth.Contract(permission.abi as any, address) + // .methods; + // return contract; + return contract; +}; From f08ab22b1bd74d30e4e3064f747e7a457e659712 Mon Sep 17 00:00:00 2001 From: mumeen Date: Tue, 11 Oct 2022 22:35:32 +0100 Subject: [PATCH 3/5] fix errors --- src/App.tsx | 290 +++++++++--------- src/components/navbar/NavItems.tsx | 14 +- .../proposal/PermissionTemplate.tsx | 39 ++- src/context/CreateProposalContext.tsx | 7 + src/pages/Governance.tsx | 17 +- 5 files changed, 199 insertions(+), 168 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 71c31d3..e401414 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -28,27 +28,27 @@ const App: React.FC = () => { {/* */} -
- - - -
- - - } - /> - - + +
+ + + +
+ + + } + /> + { autoClose={10000} /> - - - } - /> - - - - - } - /> - - - - - } - /> - - - - - } - /> - - - - - } - /> - - - - - } - /> - - - - - } - /> - - - - - } - /> - - - - - } - /> - - - - - } - /> - -
-
+ + } + /> + + + + + } + /> + + + + + } + /> + + + + + } + /> + + + + + } + /> + + + + + } + /> + + + + + } + /> + + + + + } + /> + + + + + } + /> + + + + + } + /> + +
+
+
{/* */} diff --git a/src/components/navbar/NavItems.tsx b/src/components/navbar/NavItems.tsx index 5335d15..aa3462e 100644 --- a/src/components/navbar/NavItems.tsx +++ b/src/components/navbar/NavItems.tsx @@ -1,5 +1,6 @@ -import { useState, useEffect, useRef } from "react"; +import { useState, useEffect, useRef, useContext } from "react"; import { NavLink, useNavigate } from "react-router-dom"; +import { CreateProposalContext } from "../../context/CreateProposalContext"; const Dropdown = (props: { submenus: any; dropdown: boolean }) => { const { submenus, dropdown } = props; @@ -22,6 +23,7 @@ const NavItems = (props: { items: any; depthLevel: number }) => { const { items, depthLevel } = props; const [dropdown, setDropdown] = useState(false); const navigate = useNavigate(); + const { setFormComponent } = useContext(CreateProposalContext); let ref = useRef(); @@ -76,12 +78,10 @@ const NavItems = (props: { items: any; depthLevel: number }) => { ) : items.title === "Governance" && window.location.pathname === "/Governance" ? ( diff --git a/src/components/proposal/PermissionTemplate.tsx b/src/components/proposal/PermissionTemplate.tsx index 6e1e878..43b484c 100644 --- a/src/components/proposal/PermissionTemplate.tsx +++ b/src/components/proposal/PermissionTemplate.tsx @@ -12,6 +12,7 @@ import { getParsedJsonObj } from "../../utils/getParsedJsonObj"; import InfoPopOver from "../InfoPopOver"; import { universalProfileContract } from "../../services/web3"; import Select from "../Select"; +import { ethers } from "ethers"; const PermissionsTemplate = (props: { handleComponent: any }) => { // const classes = StyledPopover(); @@ -48,6 +49,7 @@ const PermissionsTemplate = (props: { handleComponent: any }) => { // const [addOrRevoke, setAddOrRevoke] = useState("Add"); // true -> Add / false -> revoke const [daoSelected, setDaoSelected] = useState([]); const [addNewUser, setAddNewUser] = useState(false); + const [membersList, setMembers] = useState([]); toast.configure(); @@ -217,14 +219,35 @@ const PermissionsTemplate = (props: { handleComponent: any }) => { ? getParsedJsonObj(daoSelected.keyPermissions) : ""; // console.log(JSON.stringify(permissionsObject)); - const membersList: any = []; - - Object.keys(permissionsObject).forEach(function (key, index) { - membersList[key] = { - value: permissionsObject[key].upAddress, - label: permissionsObject[key].upAddress, - }; - }); + const getProfile = useCallback(async () => { + let contract = await universalProfileContract(universalProfile) + ["getData(bytes32[])"]([ + // DAO Settings + "0xf7f9c7410dd493d79ebdaee15bbc77fd163bd488f54107d1be6ed34b1e099004", + ]) + .call(); + let totalMembers: number = parseInt(contract[0]); + let members = []; + if (totalMembers >= 0) { + console.log(totalMembers); + for (let i = 0; i < totalMembers; i++) { + console.log(i); + let contract = await universalProfileContract(universalProfile) + ["getData(bytes32[])"]([ + "0xf7f9c7410dd493d79ebdaee15bbc77fd" + + ethers.utils + .hexZeroPad(ethers.utils.hexValue(i), 16) + .substring(2), + ]) + .call(); + members.push({ label: contract[0], value: contract[0] }); + } + setMembers(members); + } + }, [universalProfile]); + useEffect(() => { + getProfile(); + }, [getProfile]); toast.configure(); return ( diff --git a/src/context/CreateProposalContext.tsx b/src/context/CreateProposalContext.tsx index bba345d..5c5327b 100644 --- a/src/context/CreateProposalContext.tsx +++ b/src/context/CreateProposalContext.tsx @@ -62,6 +62,8 @@ interface CreateProposalContextInterface { setDaoCid: any; daoUpAddress: string; setDaoUpAddress: any; + formComponent: string; + setFormComponent?: any; } export const CreateProposalContext = @@ -128,6 +130,8 @@ export const CreateProposalContext = setProposalType: () => {}, daoCid: "", setDaoCid: () => {}, + formComponent: "", + setFormComponent: () => {}, }); export const CreateProposalContextProvider = ({ children }: any) => { @@ -151,6 +155,7 @@ export const CreateProposalContextProvider = ({ children }: any) => { const [receivingAddress, setReceivingAddress] = useState(""); const [coverImageFile, setCoverImageFile] = useState(); + const [formComponent, setFormComponent] = useState("ChooseDao"); const [votingOptions, setVotingOptions] = useState([ "For", "Against", @@ -245,6 +250,8 @@ export const CreateProposalContextProvider = ({ children }: any) => { setDaoCid: setDaoCid, daoUpAddress: daoUpAddress, setDaoUpAddress: setDaoUpAddress, + formComponent: formComponent, + setFormComponent: setFormComponent, }} > {children} diff --git a/src/pages/Governance.tsx b/src/pages/Governance.tsx index 0d06e28..06e3621 100644 --- a/src/pages/Governance.tsx +++ b/src/pages/Governance.tsx @@ -24,10 +24,11 @@ type LocationProps = { const Governance: React.FC = () => { const location = useLocation() as unknown as LocationProps; const { accountAddress } = useContext(ProfileContext); - const { setDaoCid } = useContext(CreateProposalContext); - const [formComponent, setFormComponent] = useState("ChooseDao"); + const { setDaoCid, formComponent, setFormComponent } = useContext( + CreateProposalContext + ); const component = location.state?.component; - const page = location.state?.page; + // const page = location.state?.page; const CID = location.state?.CID; const handleComponent = (NextForm: string) => { @@ -44,11 +45,11 @@ const Governance: React.FC = () => { useEffect(() => { window.scrollTo(0, 0); - if (component) { - setFormComponent(component); - setDaoCid(CID); - } - }, [component, CID, setDaoCid]); + // if (component) { + // // setFormComponent(component); + // setDaoCid(CID); + // } + }, []); return (
From 8b209bcc7647cb8f67b53a316618391a946179b1 Mon Sep 17 00:00:00 2001 From: mumeen Date: Wed, 12 Oct 2022 14:57:20 +0100 Subject: [PATCH 4/5] fix governance --- src/App.tsx | 295 +++++++++++++++-------------- src/components/navbar/NavItems.tsx | 1 + src/pages/Governance.tsx | 8 +- 3 files changed, 154 insertions(+), 150 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index e401414..5ff43c1 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -29,157 +29,160 @@ const App: React.FC = () => { -
- - - -
- - - } - /> - - - + +
+ + + +
- - - } - /> - - - - - } - /> - - - - - } - /> - - - - - } - /> - - - - - } - /> - - - - - } - /> - - - - - } - /> - - - - - } - /> - - - - - } - /> - - - - - } - /> - -
-
+ + } + /> + + + + + + + } + /> + + + + + //
+ } + /> + + + + + } + /> + + + + + } + /> + + + + + } + /> + + + + + } + /> + + + + + } + /> + + + + + } + /> + + + + + } + /> + + + + + } + /> + +
+
+
diff --git a/src/components/navbar/NavItems.tsx b/src/components/navbar/NavItems.tsx index aa3462e..78c6239 100644 --- a/src/components/navbar/NavItems.tsx +++ b/src/components/navbar/NavItems.tsx @@ -81,6 +81,7 @@ const NavItems = (props: { items: any; depthLevel: number }) => { onClick={() => { console.log("hello"); setFormComponent("ChooseDao"); + console.log(setFormComponent); }} > Governance diff --git a/src/pages/Governance.tsx b/src/pages/Governance.tsx index 06e3621..a6adc6a 100644 --- a/src/pages/Governance.tsx +++ b/src/pages/Governance.tsx @@ -45,10 +45,10 @@ const Governance: React.FC = () => { useEffect(() => { window.scrollTo(0, 0); - // if (component) { - // // setFormComponent(component); - // setDaoCid(CID); - // } + if (component) { + setFormComponent(component); + setDaoCid(CID); + } }, []); return ( From a88f8675caf0d299dc77d3b0212fb84c596a8c8d Mon Sep 17 00:00:00 2001 From: trendpeek Date: Mon, 7 Nov 2022 12:22:07 +0500 Subject: [PATCH 5/5] backendupdate --- src/components/create/CreateDao.tsx | 27 +- src/components/create/CreateDaoSummary.tsx | 12 +- src/components/daoProfile/Members.tsx | 2 +- .../proposal/AddUserPermissions.tsx | 25 +- .../proposal/PermissionTemplate.tsx | 6 +- src/components/proposal/PreviewProposal.tsx | 20 +- src/context/CreateDaoContext.tsx | 7 + src/context/CreateProposalContext.tsx | 7 + src/context/DaoProposalContext.tsx | 24 +- .../_DaoProposals.sol/DaoProposals.dbg.json | 4 + .../Dao/_DaoProposals.sol/DaoProposals.json | 235 ++++++++++++++++++ src/pages/DaoProfile.tsx | 13 +- src/services/keezBackend.ts | 17 ++ src/services/web3.ts | 2 +- src/utils/getParsedJsonObj.ts | 17 +- 15 files changed, 375 insertions(+), 43 deletions(-) create mode 100644 src/keezContracts/Dao/_DaoProposals.sol/DaoProposals.dbg.json create mode 100644 src/keezContracts/Dao/_DaoProposals.sol/DaoProposals.json diff --git a/src/components/create/CreateDao.tsx b/src/components/create/CreateDao.tsx index 6dc8b0c..45a4d95 100644 --- a/src/components/create/CreateDao.tsx +++ b/src/components/create/CreateDao.tsx @@ -16,6 +16,8 @@ const CreateDao = (props: { handleSubmitCreate: any }) => { const { daoName, setDaoName, + daoLink, + setDaoLink, logoImageFile, setLogoImageFile, categories, @@ -28,7 +30,7 @@ const CreateDao = (props: { handleSubmitCreate: any }) => { const handleCategoriesChange = (selectedOption: any) => { setCategories([selectedOption]); - console.log(selectedOption); + // console.log(selectedOption); }; const formSubmitValidations = () => { @@ -36,6 +38,10 @@ const CreateDao = (props: { handleSubmitCreate: any }) => { return "Please enter a DAO Name"; } + if (!daoLink || daoLink.length === 0) { + return "Please enter a DAO Link"; + } + if (!logoImageFile || logoImageFile.size === 0) { return "Please select a logo for the DAO"; } @@ -145,6 +151,25 @@ const CreateDao = (props: { handleSubmitCreate: any }) => { {/* Maximum three categories in following order [Primary, Secondary, Tertiary] */}

+
+ + +
+ setDaoLink(e.target.value)} + />