For
diff --git a/src/components/Guilds/ActionsBuilder/index.tsx b/src/components/Guilds/ActionsBuilder/index.tsx
index 24287e2801..51bbc80295 100644
--- a/src/components/Guilds/ActionsBuilder/index.tsx
+++ b/src/components/Guilds/ActionsBuilder/index.tsx
@@ -1,21 +1,12 @@
-import styled from 'styled-components';
import { useState } from 'react';
import { Header as CardHeader } from '../common/Card';
-import { Button as CommonButton } from '../common/Button';
import SidebarCard, {
SidebarCardHeaderSpaced,
} from 'components/Guilds/SidebarCard';
-import EditMode from './EditMode';
-import ViewMode from './ViewMode';
+import OptionsList from './OptionsList';
import { Option } from './types';
import { bulkEncodeCallsFromOptions } from 'hooks/Guilds/contracts/useEncodedCall';
-
-const Button = styled(CommonButton)`
- font-weight: ${({ theme }) => theme.fontWeights.medium};
- font-size: ${({ theme }) => theme.fontSizes.label};
- margin: 0;
- padding: 0.25rem 0.75rem;
-`;
+import EditButton from './common/EditButton';
interface ActionsBuilderProps {
options: Option[];
@@ -28,14 +19,14 @@ export const ActionsBuilder: React.FC
= ({
options,
onChange,
}) => {
- const [actionsEditMode, setActionsEditMode] = useState(editable);
+ const [isEditable, setIsEditable] = useState(editable);
- const onEdit = () => setActionsEditMode(true);
+ const onEdit = () => setIsEditable(true);
const onSave = () => {
const encodedOptions = bulkEncodeCallsFromOptions(options);
onChange(encodedOptions);
- setActionsEditMode(false);
+ setIsEditable(false);
};
return (
@@ -44,21 +35,21 @@ export const ActionsBuilder: React.FC = ({
Actions
{editable && (
-
+ {isEditable ? 'Save' : 'Edit'}
+
)}
}
>
- {actionsEditMode ? (
-
- ) : (
-
- )}
+
);
};
diff --git a/src/components/Guilds/ActionsBuilder/types.ts b/src/components/Guilds/ActionsBuilder/types.ts
index 84a2202f89..caf06a1f6f 100644
--- a/src/components/Guilds/ActionsBuilder/types.ts
+++ b/src/components/Guilds/ActionsBuilder/types.ts
@@ -3,6 +3,7 @@ import { utils } from 'ethers';
export enum SupportedAction {
ERC20_TRANSFER = 'ERC20_TRANSFER',
+ REP_MINT = 'REP_MINT',
GENERIC_CALL = 'GENERIC_CALL',
}
@@ -23,13 +24,15 @@ export interface DecodedCall {
}
export interface DecodedAction {
+ id: string;
decodedCall: DecodedCall;
contract: utils.Interface;
}
export interface Option {
- index: number;
+ id: string;
label: string;
+ color: string;
actions?: Call[];
decodedActions?: DecodedAction[];
}
diff --git a/src/components/Guilds/ActionsModal/ContractActionsList.tsx b/src/components/Guilds/ActionsModal/ContractActionsList.tsx
index b367a0b9aa..fcb6d0eb04 100644
--- a/src/components/Guilds/ActionsModal/ContractActionsList.tsx
+++ b/src/components/Guilds/ActionsModal/ContractActionsList.tsx
@@ -1,46 +1,12 @@
-import styled from 'styled-components';
-import { Flex } from '../common/Layout';
-import { ContainerText } from '../common/Layout/Text';
-import { Button } from '../common/Button';
import { RegistryContract } from 'hooks/Guilds/contracts/useContractRegistry';
-
-const Wrapper = styled(Flex)`
- margin: 16px auto;
-`;
-const WrapperText = styled(ContainerText).attrs(() => ({
- variant: 'bold',
-}))`
- justify-content: left;
- flex-direction: row;
- width: 85%;
- margin: 8px auto;
- color: ${({ theme }) => theme.colors.proposalText.grey};
-`;
-
-const ExternalWrapper = styled(Flex)`
- width: 100%;
- margin: 8px auto;
-`;
-
-const ButtonText = styled(ContainerText).attrs(() => ({
- variant: 'medium',
-}))`
- justify-content: space-between;
- flex-direction: row;
-`;
-
-const ActionsButton = styled(Button)`
- width: 90%;
- margin: 6px 0;
- flex-direction: column;
- justify-content: left;
- border-radius: 10px;
- &:active,
- &:focus {
- border: 2px solid ${({ theme }) => theme.colors.text};
- }
-`;
-
+import {
+ ActionsButton,
+ ButtonDetail,
+ ButtonLabel,
+ SectionTitle,
+ SectionWrapper,
+ Wrapper,
+} from './styles';
interface ContractActionsListProps {
contract: RegistryContract;
onSelect: (functionName: string) => void;
@@ -52,18 +18,32 @@ const ContractActionsList: React.FC = ({
}) => {
return (
-
- 6 Actions
+
+
+ {contract.functions.length}{' '}
+ {contract.functions.length >= 2 ? 'Actions' : 'Action'}
+
{contract.functions.map(contractFunction => (
onSelect(contractFunction.functionName)}
>
- {contractFunction.title}
- {contractFunction.functionName}
+ {contractFunction.title}
+
+ {contractFunction.functionName}(
+ {contractFunction.params.reduce(
+ (acc, cur, i) =>
+ acc.concat(
+ cur.type,
+ i === contractFunction.params.length - 1 ? '' : ', '
+ ),
+ ''
+ )}
+ )
+
))}
-
+
);
};
diff --git a/src/components/Guilds/ActionsModal/ContractsList.tsx b/src/components/Guilds/ActionsModal/ContractsList.tsx
index b9d922033d..178cc052fd 100644
--- a/src/components/Guilds/ActionsModal/ContractsList.tsx
+++ b/src/components/Guilds/ActionsModal/ContractsList.tsx
@@ -1,9 +1,6 @@
import React from 'react';
-import styled from 'styled-components';
-import { Flex } from '../common/Layout';
-import { ContainerText } from '../common/Layout/Text';
-import { Button } from '../common/Button';
import { ReactComponent as Vector } from '../../../assets/images/vector.svg';
+import { ReactComponent as Mint } from '../../../assets/images/mint.svg';
import StyledIcon from '../common/SVG';
import {
RegistryContract,
@@ -11,57 +8,16 @@ import {
} from 'hooks/Guilds/contracts/useContractRegistry';
import { useWeb3React } from '@web3-react/core';
import { SupportedAction } from '../ActionsBuilder/types';
-
-const CoreWrapper = styled(Flex)`
- width: 100%;
- margin-bottom: 16px;
-`;
-
-const ExternalWrapper = styled(Flex)`
- width: 100%;
-`;
-
-const Wrapper = styled(Flex)`
- width: 100%;
- margin: 24px auto;
-`;
-
-const ActionsButton = styled(Button).attrs(() => ({
- variant: 'secondary',
-}))`
- width: 90%;
- height: 40px;
- margin: 6px 0;
- flex-direction: row;
- justify-content: left;
- &:active,
- &:focus {
- border: 2px solid ${({ theme }) => theme.colors.text};
- }
-`;
-
-const WrapperText = styled(ContainerText).attrs(() => ({
- variant: 'bold',
-}))`
- justify-content: left;
- flex-direction: row;
- width: 85%;
- color: ${({ theme }) => theme.colors.proposalText.grey};
-`;
-
-const ButtonText = styled(ContainerText).attrs(() => ({
- variant: 'medium',
-}))`
- justify-content: space-between;
- flex-direction: row;
- color: ${({ theme }) => theme.colors.proposalText.grey};
-`;
-
-const ExternalButton = styled(ActionsButton).attrs(() => ({
- variant: 'secondary',
-}))`
- justify-content: space-between;
-`;
+import {
+ ActionsButton,
+ ButtonDetail,
+ ButtonLabel,
+ SectionTitle,
+ SectionWrapper,
+ Wrapper,
+} from './styles';
+import useGuildImplementationTypeConfig from 'hooks/Guilds/guild/useGuildImplementationType';
+import { useParams } from 'react-router-dom';
interface ContractsListProps {
onSelect: (contract: RegistryContract) => void;
@@ -74,32 +30,49 @@ const ContractsList: React.FC = ({
}) => {
const { chainId } = useWeb3React();
const { contracts } = useContractRegistry(chainId);
-
+ const { guild_id: guildAddress } =
+ useParams<{ chain_name?: string; guild_id?: string }>();
+ const { isRepGuild } = useGuildImplementationTypeConfig(guildAddress);
return (
-
- Core
+
+ Core
onSupportedActionSelect(SupportedAction.ERC20_TRANSFER)
}
>
-
- Transfer & Mint
+
+
+ Transfer & Mint
+
-
-
- External Contracts
+ {isRepGuild ? (
+ onSupportedActionSelect(SupportedAction.REP_MINT)}
+ >
+
+
+ Mint REP
+
+
+ ) : null}
+
+
+ External Contracts
{contracts?.map(contract => (
- onSelect(contract)}>
- {contract.title}
-
+ onSelect(contract)}
+ >
+ {contract.title}
+
{contract.functions?.length}{' '}
{contract.functions?.length > 1 ? 'Actions' : 'Action'}
-
-
+
+
))}
-
+
);
};
diff --git a/src/components/Guilds/ActionsModal/MintRepModal.tsx b/src/components/Guilds/ActionsModal/MintRepModal.tsx
deleted file mode 100644
index 3e539124ca..0000000000
--- a/src/components/Guilds/ActionsModal/MintRepModal.tsx
+++ /dev/null
@@ -1,69 +0,0 @@
-import styled from 'styled-components';
-import { Input } from '../../../components/Guilds/common/Form';
-import { useWeb3React } from '@web3-react/core';
-import { useState } from 'react';
-import { Flex } from '../common/Layout';
-import { ContainerText } from '../common/Layout/Text';
-import iconsByChain from '../common/ChainIcons';
-
-const RepWrapper = styled(Flex)`
- margin: 16px auto;
-`;
-const WrapperText = styled(ContainerText).attrs(() => ({
- variant: 'bold',
-}))`
- justify-content: left;
- flex-direction: row;
- width: 85%;
- margin: 8px auto;
- color: grey;
-`;
-
-const ExternalWrapper = styled(Flex)`
- width: 100%;
- margin: 8px auto;
-`;
-
-const MintReputationModal: React.FC = () => {
- const [address, setAddress] = useState('');
- const [repAmount, setRepAmount] = useState('');
- const [repPercent, setRepPercent] = useState('');
- const { chainId } = useWeb3React();
-
- return (
-
-
- Recipient
- setAddress(e.target.value)}
- icon={iconsByChain[chainId] || null}
- size={24}
- width="85%"
- />
-
-
- Reputation Amount
- setRepAmount(e.target.value)}
- size={24}
- width="85%"
- />
-
-
- Reputation in %
- setRepPercent(e.target.value)}
- width="85%"
- />
-
-
- );
-};
-
-export default MintReputationModal;
diff --git a/src/components/Guilds/ActionsModal/ParamsModal.tsx b/src/components/Guilds/ActionsModal/ParamsModal.tsx
new file mode 100644
index 0000000000..44e100f9ec
--- /dev/null
+++ b/src/components/Guilds/ActionsModal/ParamsModal.tsx
@@ -0,0 +1,42 @@
+import styled from 'styled-components';
+import { Input } from '../common/Form';
+import { useState } from 'react';
+import { ActionsButton, FormElement, FormLabel, Wrapper } from './styles';
+import { RegistryContractFunction } from 'hooks/Guilds/contracts/useContractRegistry';
+
+const SubmitButton = styled(ActionsButton).attrs(() => ({
+ variant: 'primary',
+}))`
+ background-color: ${({ theme }) => theme.colors.button.primary};
+ justify-content: center;
+`;
+
+interface ParamsModalProps {
+ fn: RegistryContractFunction;
+}
+
+const ParamsModal: React.FC = ({ fn }) => {
+ const [address, setAddress] = useState('');
+
+ return (
+
+ {fn.params.map(param => (
+
+ {param.description}
+ setAddress(e.target.value)}
+ size={24}
+ />
+
+ ))}
+
+
+ Add action
+
+
+ );
+};
+
+export default ParamsModal;
diff --git a/src/components/Guilds/ActionsModal/index.tsx b/src/components/Guilds/ActionsModal/index.tsx
index d00f02a0d9..44292ac376 100644
--- a/src/components/Guilds/ActionsModal/index.tsx
+++ b/src/components/Guilds/ActionsModal/index.tsx
@@ -1,11 +1,33 @@
+import { utils } from 'ethers';
import { RegistryContract } from 'hooks/Guilds/contracts/useContractRegistry';
import React, { useState } from 'react';
import { useParams } from 'react-router-dom';
-import { defaultValues } from '../ActionsBuilder/SupportedActions';
-import { DecodedAction, SupportedAction } from '../ActionsBuilder/types';
+import styled from 'styled-components';
+import {
+ defaultValues,
+ getEditor,
+ supportedActions,
+} from '../ActionsBuilder/SupportedActions';
+import {
+ DecodedAction,
+ DecodedCall,
+ SupportedAction,
+} from '../ActionsBuilder/types';
+import { Button } from '../common/Button';
import { Modal } from '../common/Modal';
import ContractActionsList from './ContractActionsList';
import ContractsList from './ContractsList';
+import ParamsModal from './ParamsModal';
+import { useWeb3React } from '@web3-react/core';
+
+export const EditorWrapper = styled.div`
+ margin: 1.25rem;
+`;
+
+export const BlockButton = styled(Button)`
+ margin-top: 1rem;
+ width: 100%;
+`;
interface ActionModalProps {
isOpen: boolean;
@@ -19,11 +41,19 @@ const ActionModal: React.FC = ({
onAddAction,
}) => {
const { guild_id: guildId } = useParams<{ guild_id?: string }>();
+ const { account: walletAddress } = useWeb3React();
+ // Supported Actions
+ const [selectedAction, setSelectedAction] = useState(null);
+ const [selectedActionContract, setSelectedActionContract] =
+ useState(null);
+ // Generic calls
const [selectedContract, setSelectedContract] =
useState(null);
const [selectedFunction, setSelectedFunction] = useState(null);
+ const [data, setData] = useState(null);
+
function getHeader() {
if (selectedFunction) {
return selectedContract.functions.find(
@@ -35,12 +65,22 @@ const ActionModal: React.FC = ({
return selectedContract?.title;
}
+ if (selectedAction) {
+ return supportedActions[selectedAction].title;
+ }
+
return 'Add action';
}
function getContent() {
if (selectedFunction) {
- return null;
+ return (
+ fn.functionName === selectedFunction
+ )}
+ />
+ );
}
if (selectedContract) {
@@ -52,10 +92,20 @@ const ActionModal: React.FC = ({
);
}
+ if (selectedAction) {
+ const Editor = getEditor(selectedAction);
+ return (
+
+
+ Save Action
+
+ );
+ }
+
return (
);
}
@@ -65,16 +115,41 @@ const ActionModal: React.FC = ({
setSelectedFunction(null);
} else if (selectedContract) {
setSelectedContract(null);
+ } else if (selectedAction) {
+ setSelectedAction(null);
+ setSelectedActionContract(null);
}
+
+ setData(null);
}
- function addSupportedAction(action: SupportedAction) {
- const defaultDecodedAction = defaultValues[action];
+ function setSupportedAction(action: SupportedAction) {
+ const defaultDecodedAction = defaultValues[action] as DecodedAction;
if (!defaultDecodedAction) return null;
defaultDecodedAction.decodedCall.from = guildId;
defaultDecodedAction.decodedCall.callType = action;
- onAddAction(defaultDecodedAction as DecodedAction);
+ switch (action) {
+ case SupportedAction.REP_MINT:
+ defaultDecodedAction.decodedCall.args.to = walletAddress;
+ break;
+ }
+ setData(defaultDecodedAction.decodedCall);
+ setSelectedAction(action);
+ setSelectedActionContract(defaultDecodedAction.contract);
+ }
+
+ function saveSupportedAction() {
+ if (!selectedAction || !data || !setSelectedActionContract) return;
+
+ const decodedAction: DecodedAction = {
+ id: `action-${Math.random()}`,
+ decodedCall: data,
+ contract: selectedActionContract,
+ };
+
+ onAddAction(decodedAction);
+ setIsOpen(false);
}
return (
@@ -83,7 +158,7 @@ const ActionModal: React.FC = ({
onDismiss={() => setIsOpen(false)}
header={getHeader()}
maxWidth={300}
- backnCross={!!selectedContract}
+ backnCross={!!selectedAction || !!selectedContract}
prevContent={goBack}
>
{getContent()}
diff --git a/src/components/Guilds/ActionsModal/styles.tsx b/src/components/Guilds/ActionsModal/styles.tsx
new file mode 100644
index 0000000000..f781cd85c7
--- /dev/null
+++ b/src/components/Guilds/ActionsModal/styles.tsx
@@ -0,0 +1,58 @@
+import styled from 'styled-components';
+import { Button } from '../common/Button';
+import { ContainerText } from '../common/Layout/Text';
+
+export const Wrapper = styled.div`
+ width: 100%;
+`;
+
+export const SectionWrapper = styled.div`
+ margin: 1.5rem;
+`;
+
+export const ActionsButton = styled(Button).attrs(() => ({
+ variant: 'secondary',
+}))`
+ background-color: transparent;
+ padding: ${({ vertical }) => (vertical ? '1rem' : '0.75rem 1rem')};
+ width: 100%;
+ display: flex;
+ align-items: ${({ vertical }) => (vertical ? 'flex-start' : 'center')};
+ justify-content: space-between;
+ flex-direction: ${({ vertical }) => (vertical ? 'column' : 'row')};
+ border-radius: ${({ vertical }) => (vertical ? '0.625rem' : '2rem')};
+ &:active,
+ &:focus {
+ border: 2px solid ${({ theme }) => theme.colors.text};
+ }
+`;
+
+export const SectionTitle = styled(ContainerText).attrs(() => ({
+ variant: 'bold',
+}))`
+ display: block;
+ color: ${({ theme }) => theme.colors.proposalText.grey};
+ margin-bottom: 0.75rem;
+ font-size: 0.875rem;
+`;
+
+export const ButtonLabel = styled.div`
+ display: flex;
+ align-items: center;
+`;
+
+export const ButtonDetail = styled(ContainerText).attrs(() => ({
+ variant: 'medium',
+}))`
+ margin: ${({ vertical }) => (vertical ? '0.5rem 0 0 0' : '0')};
+ color: ${({ theme }) => theme.colors.proposalText.grey};
+`;
+
+export const FormElement = styled.div`
+ margin: 1.5rem;
+`;
+
+export const FormLabel = styled.div`
+ color: ${({ theme }) => theme.colors.proposalText.grey};
+ margin-bottom: 0.75rem;
+`;
diff --git a/src/components/Guilds/ProposalPage/ProposalVoteCard/index.tsx b/src/components/Guilds/ProposalPage/ProposalVoteCard/index.tsx
index b84009e26e..992058c69f 100644
--- a/src/components/Guilds/ProposalPage/ProposalVoteCard/index.tsx
+++ b/src/components/Guilds/ProposalPage/ProposalVoteCard/index.tsx
@@ -101,7 +101,6 @@ const ProposalVoteCard = () => {
contract.setVote(proposalId, selectedAction, userVotingPower)
);
};
-
return (
{
const memberMenuRef = useRef(null);
useDetectBlur(memberMenuRef, () => setShowMenu(false));
+
+ const { isRepGuild } = useGuildImplementationType(guildAddress);
return (
<>
@@ -195,7 +198,7 @@ export const MemberActions = () => {
Increase Voting Power
- {isUnlockable && (
+ {isUnlockable && !isRepGuild && (
Withdraw
)}
diff --git a/src/components/Guilds/StakeTokensModal/StakeTokens.tsx b/src/components/Guilds/StakeTokensModal/StakeTokens.tsx
index 130557920f..f3094cbef9 100644
--- a/src/components/Guilds/StakeTokensModal/StakeTokens.tsx
+++ b/src/components/Guilds/StakeTokensModal/StakeTokens.tsx
@@ -2,6 +2,7 @@ import { useMemo, useState } from 'react';
import styled, { css } from 'styled-components';
import { FiArrowRight, FiInfo } from 'react-icons/fi';
import moment from 'moment';
+import { useHistory, useLocation } from 'react-router';
import { useParams } from 'react-router-dom';
import { useWeb3React } from '@web3-react/core';
@@ -20,6 +21,7 @@ import NumericalInput from '../common/Form/NumericalInput';
import useVotingPowerPercent from '../../../hooks/Guilds/guild/useVotingPowerPercent';
import useStringToBigNumber from '../../../hooks/Guilds/conversions/useStringToBigNumber';
import useBigNumberToNumber from '../../../hooks/Guilds/conversions/useBigNumberToNumber';
+import useGuildImplementationType from '../../../hooks/Guilds/guild/useGuildImplementationType';
import { Loading } from '../common/Loading';
const GuestContainer = styled.div`
@@ -51,7 +53,7 @@ const DaoTitle = styled(Heading)`
const InfoItem = styled.div`
display: flex;
font-size: ${({ theme }) => theme.fontSizes.body};
- color: ${({ theme }) => theme.colors.muted};
+ color: ${({ theme }) => theme.colors.card.grey};
margin-bottom: 0.4rem;
`;
@@ -84,7 +86,7 @@ const BaseFont = css`
const InfoLabel = styled.span`
${BaseFont}
- color: ${({ theme }) => theme.colors.muted};
+ color: ${({ theme }) => theme.colors.card.grey};
`;
const InfoValue = styled.span`
@@ -111,7 +113,7 @@ const StakeAmountInput = styled(NumericalInput)`
font-family: inherit;
`;
-const ButtonLock = styled(Button)`
+const ActionButton = styled(Button)`
width: 100%;
margin-top: 22px;
self-align: flex-end;
@@ -188,7 +190,9 @@ export const StakeTokens = () => {
stakeAmountParsed?.add(guildConfig?.totalLocked),
3
);
-
+ const history = useHistory();
+ const location = useLocation();
+ const { isRepGuild } = useGuildImplementationType(guildAddress);
return (
@@ -199,19 +203,51 @@ export const StakeTokens = () => {
)}
-
- {guildConfig?.lockTime ? (
- `${moment
- .duration(guildConfig.lockTime.toNumber(), 'seconds')
- .humanize()} staking period`
- ) : (
-
- )}{' '}
-
+ {!isRepGuild && (
+
+ {guildConfig?.lockTime ? (
+ `${moment
+ .duration(guildConfig.lockTime.toNumber(), 'seconds')
+ .humanize()} staking period`
+ ) : (
+
+ )}{' '}
+
+ )}
-
+ {!isRepGuild && (
+
+
+ Balance:
+
+ {tokenBalance && tokenInfo ? (
+ roundedBalance
+ ) : (
+
+ )}{' '}
+ {tokenInfo?.symbol || (
+
+ )}
+
+
+
+
+
+
+
+ )}
+ {isRepGuild && (
- Balance:
+ Balance
{tokenBalance && tokenInfo ? (
roundedBalance
@@ -223,17 +259,7 @@ export const StakeTokens = () => {
)}
-
-
-
-
-
+ )}
Your voting power
@@ -260,41 +286,51 @@ export const StakeTokens = () => {
)}
-
- Unlock Date
-
- {isStakeAmountValid ? (
- <>
-
- {moment()
- .add(guildConfig.lockTime.toNumber(), 'seconds')
- .format('MMM Do, YYYY - h:mm a')}
- {' '}
-
- >
- ) : (
- '-'
- )}
-
-
- {stakeAmountParsed && tokenAllowance?.gte(stakeAmountParsed) ? (
-
- Lock{' '}
- {tokenInfo?.symbol || (
-
- )}
-
+ {!isRepGuild && (
+
+ Unlock Date
+
+ {isStakeAmountValid ? (
+ <>
+
+ {moment()
+ .add(guildConfig.lockTime.toNumber(), 'seconds')
+ .format('MMM Do, YYYY - h:mm a')}
+ {' '}
+
+ >
+ ) : (
+ '-'
+ )}
+
+
+ )}
+ {!isRepGuild ? (
+ stakeAmountParsed && tokenAllowance?.gte(stakeAmountParsed) ? (
+
+ Lock{' '}
+ {tokenInfo?.symbol || (
+
+ )}
+
+ ) : (
+
+ Approve{' '}
+ {tokenInfo?.symbol || (
+
+ )}{' '}
+ Spending
+
+ )
) : (
- history.push(location.pathname + '/proposalType')}
>
- Approve{' '}
- {tokenInfo?.symbol || (
-
- )}{' '}
- Spending
-
+ Mint Rep
+
)}
);
diff --git a/src/components/Header/loadingNetwork.tsx b/src/components/Header/loadingNetwork.tsx
new file mode 100644
index 0000000000..8bd4712e77
--- /dev/null
+++ b/src/components/Header/loadingNetwork.tsx
@@ -0,0 +1,51 @@
+import { observer } from 'mobx-react';
+import styled from 'styled-components';
+import dxdaoIcon from 'assets/images/DXdao.svg';
+
+const NavWrapper = styled.div`
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ width: 100%;
+ padding: 20px 0px 0px 0px;
+`;
+
+const NavSection = styled.div`
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+`;
+
+const MenuItem = styled.div`
+ display: flex;
+ align-items: center;
+ color: var(--nav-text-light);
+ font-size: 16px;
+ line-height: 19px;
+ cursor: pointer;
+`;
+
+const WarningDev = styled.div`
+ margin-left: 5px;
+ padding-top: 3px;
+ color: red;
+`;
+
+const LoadingNetworkHeader = observer(() => {
+ const isTestingEnv = !window?.location?.href?.includes('dxvote.eth');
+
+ return (
+
+
+ <>
+
+ >
+
+
+ );
+});
+
+export default LoadingNetworkHeader;
diff --git a/src/components/Proposal/Votes/index.tsx b/src/components/Proposal/Votes/index.tsx
index a7f957f847..f601cda488 100644
--- a/src/components/Proposal/Votes/index.tsx
+++ b/src/components/Proposal/Votes/index.tsx
@@ -37,7 +37,6 @@ import {
verifySignedVote,
} from 'utils';
import { utils } from 'ethers';
-import useJsonRpcProvider from 'hooks/Guilds/web3/useJsonRpcProvider';
const Votes = () => {
const {
@@ -46,7 +45,6 @@ const Votes = () => {
daoStore,
providerStore,
daoService,
- messageLoggerService,
orbitDBService,
},
} = useContext();
@@ -56,8 +54,6 @@ const Votes = () => {
const [decision, setDecision] = useState(0);
const [votePercentage, setVotePercentage] = useState(0);
const [signedVotesOfProposal, setSignedVotesOfProposal] = useState([]);
- const [loadingSignedRinkebyVotes, setLoadingSignedRinkebyVotes] =
- useState(true);
const [loadingSignedOrbitDBVotes, setLoadingSignedOrbitDBVotes] =
useState(true);
@@ -77,57 +73,6 @@ const Votes = () => {
votingMachineOfProposal.address
].type == 'DXDVotingMachine';
- const rinkebyProvider = useJsonRpcProvider(4);
-
- messageLoggerService
- .getMessages(signedVoteMessageId, rinkebyProvider)
- .then(messagesEvents => {
- console.debug('[Rinkeby Proposal messages]', messagesEvents);
- messagesEvents.map(messagesEvent => {
- if (
- messagesEvent.args &&
- messagesEvent.args.message.length > 0 &&
- messagesEvent.args.message.split(':').length > 6
- ) {
- const signedVote = messagesEvent.args.message.split(':');
- const validSignature = verifySignedVote(
- signedVote[1],
- signedVote[2],
- signedVote[3],
- signedVote[4],
- signedVote[5],
- signedVote[6]
- );
-
- const alreadyAdded =
- signedVotesOfProposal.findIndex(s => s.voter == signedVote[3]) >
- -1 ||
- proposalEvents.votes.findIndex(s => s.voter == signedVote[3]) > -1;
-
- const repOfVoterForProposal = daoStore.getRepAt(
- signedVote[3],
- proposal.creationEvent.blockNumber
- ).userRep;
-
- if (
- validSignature &&
- !alreadyAdded &&
- repOfVoterForProposal >= bnum(signedVote[5])
- ) {
- signedVotesOfProposal.push({
- voter: signedVote[3],
- vote: signedVote[4],
- amount: bnum(signedVote[5]),
- signature: signedVote[6],
- source: 'rinkeby',
- });
- }
- }
- });
- setSignedVotesOfProposal(signedVotesOfProposal);
- setLoadingSignedRinkebyVotes(false);
- });
-
orbitDBService.getLogs(signedVoteMessageId).then(signedVoteMessages => {
console.debug('[OrbitDB messages]', signedVoteMessages);
signedVoteMessages.map(signedVoteMessageRaw => {
@@ -272,12 +217,6 @@ const Votes = () => {
utils.id(`dxvote:${proposalId}`),
`signedVote:${voteDetails.votingMachine}:${voteDetails.proposalId}:${voteDetails.voter}:${voteDetails.decision}:${voteDetails.repAmount}:${voteSignature}`
);
- if (voteDetails.networks[1])
- messageLoggerService.broadcast(
- utils.id(`dxvote:${proposalId}`),
- `signedVote:${voteDetails.votingMachine}:${voteDetails.proposalId}:${voteDetails.voter}:${voteDetails.decision}:${voteDetails.repAmount}:${voteSignature}`,
- rinkebyProvider
- );
}
} else {
daoService.vote(
@@ -358,7 +297,7 @@ const Votes = () => {
- {!loadingSignedRinkebyVotes && !loadingSignedOrbitDBVotes && (
+ {!loadingSignedOrbitDBVotes && (
diff --git a/src/components/Web3ReactManager/index.tsx b/src/components/Web3ReactManager/index.tsx
index 9cb116432b..5b006d3df8 100644
--- a/src/components/Web3ReactManager/index.tsx
+++ b/src/components/Web3ReactManager/index.tsx
@@ -7,6 +7,11 @@ import { useContext } from 'contexts';
import { DEFAULT_CHAIN_ID, useInterval, usePrevious } from 'utils';
import { InjectedConnector } from '@web3-react/injected-connector';
import { NetworkConnector } from '@web3-react/network-connector';
+import ThemeProvider, { GlobalStyle } from 'theme';
+import styled from 'styled-components';
+import LoadingNetworkHeader from '../Header/loadingNetwork';
+import { LoadingBox } from '../../pages/proposals/styles';
+import PulsingIcon from 'components/common/LoadingIcon';
const BLOKCHAIN_FETCH_INTERVAL = 10000;
@@ -142,21 +147,40 @@ const Web3ReactManager = ({ children }) => {
networkActive ? BLOKCHAIN_FETCH_INTERVAL : 10
);
+ const Content = styled.div`
+ margin: auto;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ width: 85%;
+ `;
+
// on page load, do nothing until we've tried to connect to the injected connector
if (!triedEager) {
console.debug('[Web3ReactManager] Render: Eager load not tried');
- return null;
- }
- if (networkError) {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+ } else if (networkError) {
console.debug(
'[Web3ReactManager] Render: Network error, showing modal error.'
);
return null;
} else {
- console.debug(
- '[Web3ReactManager] Render: Active network, render children',
- { networkActive }
- );
+ console.debug('[Web3ReactManager] Render: Render children', {
+ networkActive,
+ });
return children;
}
};
diff --git a/src/configs/arbitrum/config.json b/src/configs/arbitrum/config.json
index 6676fcf5e6..9598cbc5c2 100644
--- a/src/configs/arbitrum/config.json
+++ b/src/configs/arbitrum/config.json
@@ -1,8 +1,8 @@
{
"cache": {
"fromBlock": 338923,
- "ipfsHash": "QmbRTtmYg9GWD6stfcL618bxTbuZoFa3tyySUfaTzRjA1v",
- "toBlock": "6831600"
+ "ipfsHash": "QmRvp9A9FUVzoYdyDd7mbvz3x6oJSwRqPDcH7JFiNKFmRN",
+ "toBlock": "10026660"
},
"contracts": {
"avatar": "0x2B240b523f69b9aF3adb1C5924F6dB849683A394",
diff --git a/src/configs/arbitrumTestnet/config.json b/src/configs/arbitrumTestnet/config.json
index 465065a2e3..bc74ad5134 100644
--- a/src/configs/arbitrumTestnet/config.json
+++ b/src/configs/arbitrumTestnet/config.json
@@ -1,8 +1,8 @@
{
"cache": {
"fromBlock": 3995726,
- "ipfsHash": "QmRiUXQ1yGhsDVp5QrePqNxe7WFFqzuZzGrAYEgT3RFAvY",
- "toBlock": "10225604"
+ "ipfsHash": "QmXavj3tchxsqpXCPB4g18NikoyGd2c22syDF4Sijn3f8n",
+ "toBlock": "11296050"
},
"contracts": {
"avatar": "0x6370B3Ba7D9bAd94b35dC9073540E562bDe5Fdc3",
diff --git a/src/configs/default.json b/src/configs/default.json
index eca4d0c8f4..a7967d6975 100644
--- a/src/configs/default.json
+++ b/src/configs/default.json
@@ -1,7 +1,7 @@
{
- "mainnet": "QmPcDmifixW4Cdxk9UjVejnzgzBP9urdHG7nrN83FVE5Yz",
- "xdai": "QmdRR3roqvAW4iHbDCvoJQSCsqSobC8ngKAdtzsCAoDEh6",
- "arbitrum": "QmUoRz433SzvwBnWta86SjL2CPrT7tm1efFTVdmCnm5hQp",
- "rinkeby": "QmXwwMNZQEcabFCKmEfnyZNhBx9zCoNnD1Rkq5duvyMRku",
- "arbitrumTestnet": "QmNcir6bUdevg587ceYWKtQdj5P2q9ASnCRG7sFbyQkpXi"
+ "mainnet": "QmfLMqd4Skt8v89u5NuhYGzDbdQsfWPeM9gSTwzg1za46p",
+ "xdai": "QmTXxeSJCTgkBg9eYrBkHQqFfMFfJN6yrKqLUKodkSBDSt",
+ "arbitrum": "QmQTAtR3nteZpGAHjArUk9Zu9F3UnXVmWgccXrVzzE6PGB",
+ "rinkeby": "QmSq3xW8cL9yPzqVJyJLKsiRaxmAKNnQ5H4zXCZDxLynZG",
+ "arbitrumTestnet": "QmUuwGiETkoytzoABzBS37LHqBPqMYTDEFHVkio8VrQepm"
}
\ No newline at end of file
diff --git a/src/configs/mainnet/config.json b/src/configs/mainnet/config.json
index 62b624c7ca..22be8495df 100644
--- a/src/configs/mainnet/config.json
+++ b/src/configs/mainnet/config.json
@@ -1,8 +1,8 @@
{
"cache": {
"fromBlock": 7219912,
- "ipfsHash": "QmcFgHexZP5MygnFhJwHi5W7UFrSxGK5DSGNCTjmJM54NM",
- "toBlock": "14270378"
+ "ipfsHash": "QmSiUzqh2W8EvBJWJ5BUQbzBZiYwN5JsotrZ6RjEueMeJD",
+ "toBlock": "14831037"
},
"contracts": {
"avatar": "0x519b70055af55a007110b4ff99b0ea33071c720a",
diff --git a/src/configs/proposalTitles.json b/src/configs/proposalTitles.json
index 20fce928d0..9611fca8f2 100644
--- a/src/configs/proposalTitles.json
+++ b/src/configs/proposalTitles.json
@@ -1521,5 +1521,271 @@
"0xfa759273534d116b354a0a4d801d1de0b2dd0b8e773f52bd33a159f90cd2488d": "First Month Developer Proposal Levotiate",
"0xfb1fada10c1640cf81e8e0260370d4824b7edae31eab12be7ca6a93348bb2b61": "REP Boost - Discord: Kobello",
"0xff6c045d9ab8f514b7dce6317ac1ff16786cad69bd4ae4f75985ff0f8828b678": "xDXD Buyback Order #130 for 11.42 WETH",
- "0xffc0f4a64c8ec043238ca787e58177c2e798360c29893b7190f633116f6b4aab": "GP Relayer Trade: 300 xDAI for STAKE"
+ "0xffc0f4a64c8ec043238ca787e58177c2e798360c29893b7190f633116f6b4aab": "GP Relayer Trade: 300 xDAI for STAKE",
+ "0x168ca80db89e979aa8a54c64894b6ee8a86224e5d60a9526b36f022d88f88861": "1999 DXD Withdrawal from GPv1 Relayer",
+ "0x445db3d3973e01f6fca2018ffed0a982c91558d92c3fd02846c0adbdf55f87dc": "Decentral Labs Worker Proposal - 18th March to 18th May",
+ "0x6facdbca526b5eb3c4265c9d8e6bdadc5e7b5aeb8e5dd3d6d25fa3b2db1787d0": "Funding Gas Governance Refund Contract",
+ "0x818f357112024d61671175e650473b2dcfd5548f4a0f0975a1ccb71324d950bf": "1999 DXD Withdrawal Request from GPv1 Relayer",
+ "0xa3aab310917683f96a9546f0d87b1ecdf68550f04bb068c8ff66fb36d1b7aab7": "Update swapr.eth content hash to Swapr v1.0.0 Beta 11.1",
+ "0xadb3c9bfa7dc97d4ee93bb155c72ca27b35ac8d2d759074634e99fa3e2a746fb": "Sponsor The Global Governance Gathering (“GGG”) event by The DAOist in Amsterdam",
+ "0xae733d1e248b208b9f3bb1b9ba24b7b678dc6f9594afb018574e928787b6d7cc": "Decentral Labs Worker Proposal - 18th March to 18th May",
+ "0xddad4a2733571ab684c746477455983cdc0b336a6c8c54997e7500d3f25baa5e": "dlabs ETH Refund - MME",
+ "0xe328cc853e2b3040e827e933f708766de59e0edf304573197dcca49c377087c5": "(REDO) Sponsor The Global Governance Gathering (“GGG”) event by The DAOist in Amsterdam",
+ "0x073eb320293e2c3ef11eee02e6f2579e16265edc8f08e7d7e250107ab09e0689": "DAI payout Zett Period February 2022",
+ "0x093b73e99bb222a0c80e5b65c58ffe46b9d11fbe9a38f75b5a28ba8b2d7b4972": "LINK / GNO Epoch 12 - 13 SWPR farming campaign",
+ "0x122f3766bca165927f6696f2bed943198ca8a0f2f2ef420d22332319ab4027fd": "HAUS / WETH Epoch 12 - 13 SWPR farming campaign",
+ "0x1777d3d347124bc6d7f8337ea4066648bbc0173c57d3ae9c0e86e8f83f55924c": "Decentral Labs Worker Proposal - 18th of January to 18th of March (2nd part)",
+ "0x184630d11dad40bbe01e7714384ff1dff5ef736f451fb5381edef2803a1a1cf1": "WETH / XDAI Epoch 12 - 13 SWPR farming campaign",
+ "0x229079e05bdc9905fa1d8b19c33f7e4636ee31de809fe2b039284eabea8238a4": "MAI / XDAI Epoch 14 - 15 SWPR farming campaign",
+ "0x2a962b078d0452d70264772a05ff39b28163ae80c3b02a27b1e63bafba035c11": "0xKLOM.eth ETHDenver Stipend Update",
+ "0x2c8867dec2141c3d29060ba784d88296c67e545098e1eb7363035145579a1a8a": "Deposit 415 WETH & 1.1M xDai in Swapr Liquidity Relayer",
+ "0x316199049ec001cb1ed0afd4a7cdc4ee1921e57ba7994c7b0b8b520ccd7fc6bd": "Mirror Proposal of \"Sponsor The Global Governance Gathering (“GGG”) event by The DAOist in Amsterdam\" on Mainnet",
+ "0x39aa9535792dbd6d5365cf683a848c00d9c9b332b4286e0e4c53626f5844d613": "Dlabs Entity Formation and Maintenance Contributor Stipend",
+ "0x3b3c72675bb5459313a9f38e0408f0cd01e7706b83634ac9a95053904a4740dc": "RICE / XDAI Epoch 14 - 15 SWPR farming campaign",
+ "0x3cf57b232feda914d81261d4c0feb7a510b7858c107696af862a37601dc687f4": "0xKLOM.eth Arbitrum Gas and ETHDenver Stipend",
+ "0x3e6215137546560a24cc54bba94bba1ef3f3f348842287898f085eaa66e324d8": "Test Proposal to Withdraw LP Tokens from WETH/wxDai pool on Swapr [1/2]",
+ "0x3f131d40fb2c9e0d8d771ceeaa0fea5919261536152093fc0d02e8bd79e50438": "Approve Swapr farming campaign for COW/WETH pair",
+ "0x40f50475fca7988cf84c26733151cb2581f4ff6cdbced672ef8160d8679df6d1": "Provision 150 WETH and 390k xDai to Swapr",
+ "0x40f8b0847efd72688758d6ab7c58a84132bc5e68c57d91c8be1314bd2160e717": "Nathan, contributor proposal 3/5/22-4/30/22",
+ "0x43f857b195320e0464f53d8ecb33aab669dfe0e7f263419aa4ac2d10da193125": "Tammy -- Vested DXD Request (Dec. '20 - March '21)",
+ "0x477bd183f2a90a20252e183f5956266555659d392ed11266c39ce27c9c266cd9": "AGVE / XDAI Epoch 14 - 15 SWPR farming campaign",
+ "0x4bc42058824c4ca5f8cef6dd2b78716f54e9fa94dc021370009dffbcffa312b1": "Provision 150 WETH and 450k xDai to Swapr",
+ "0x4fd9fc08411a92fff1810b338806529a16d5a6b548df82c6b02c1d0a0b7aeb42": "HND / XDAI farming campaign",
+ "0x51e16df1dd0a6de9bacb6955e39366140160023e9306ac9a6268353ec6b2918c": "SkyMine Labs - Stipend and Reimbursement around ETHDenver",
+ "0x53fdeca53c7c6440f9006964293db70ac6d297dd2199043e5325f82882176fb2": "Dave - Stipend for Devconnect Amsterdam",
+ "0x58d1cf014cff7f19f921f4345bcc1ed9e3cbab9e6e6bee224c024c202fa5e0e2": "Test Proposal to Withdraw LP Tokens from WETH/xDai pool on Swapr [2/2]",
+ "0x59b36d189960953e0bce203532af7f717575387eeb0138d70b4d1fdbf743227a": "Milan V. Contributor Proposal [1/3/2022 - 14/3/2022]",
+ "0x5b7e7cdab1cc23e4c78e93cedef86c59278259dd5206d2674904fc1eae1a40e7": "Borisblock — Contributor Proposal [07/01/22 - 07/03/22] 2/2",
+ "0x5d258180fc5922f69c09de3963d3ff0688d4ab0a9a1b4763a33be0d33edd47ab": "xDXD Buyback Order #170 for 10.03 WETH",
+ "0x5eaa2e8fa9d38e928218a5f5aa23591cae0bbed5789710083e75e7647898f847": " Trade 50k WXDAI to USDC ",
+ "0x635cb345ad6242ef248cd4d1af4a6f4dfd279577d853db0f54a6461bf1d70dc3": "DXD / WETH Epoch 12 - 13 SWPR farming campaign",
+ "0x67a488fb18db9ffdd1f9af4d8c68bad02379a96595adba1808a5ca0d70d1adc1": " Provision 100 WETH and 260k xDai to Swapr ",
+ "0x6ae455e54c9684d3712476809ce97289cca71742160408a7d72c298fc9638663": "dlabs REP sync ",
+ "0x6c8eba77df089d83821b6dfda6dddb2327593d1fd3933d26a48c7baecb1db6c8": "Test Proposal to Withdraw LP Tokens from relayer to treasury",
+ "0x73e3ed3be86120677b2dd93401ce3c729f304bac6ba6b2164de0cdb9456882d5": "[Etherlabs AB] Payment Proposal [March 2022]",
+ "0x7571912e7a5c4b166d74468d44121bfa259a275ddc5124442708f5ba3dd55f7b": "Swap 34k WXDAI to USDC",
+ "0x7648bc00cdd1b9b46ebb928538aafd693bd300a2122f2215f0c7622671f39b40": "Luchux - Payment Proposal 15th Dec 2021 - 25th Jan 2022. ",
+ "0x7bc28c23bf1035d22b82b5b393f5dd7fc3280fa0e3a8e3d42da8647b62969807": "DXdao Discord Q4 REP Boost for Bodo#0453",
+ "0x80121caeb85c037f5fc606f489a4cff12622f6c05b0d85aa2ce8ce4469f5e3b2": "Second and Third Payments to Team Omega for Audit of DXgovernance",
+ "0x805a31ecf7626142b64e640d2475c5ce1cdd7b210df05f35fea4599cb44fc6c2": "HAUS / WETH Epoch 14 - 15 SWPR farming campaign",
+ "0x858bec2ad4bcd89c36c9380d4299b19be0512e2ab19b5ce961119a1c6ddc433b": "GNO / DXD Epoch 12 - 13 SWPR farming campaign",
+ "0x8bb1bef2c2e0a8c3dd8f45fae33cdcef0bf9063438427c3b35bb3436b7ba7dac": "GNO / XDAI Epoch 12 - 13 SWPR farming campaign",
+ "0x8c06598b21cce13359a28a4c52efdc3606103bd93340f27fc6061ffe50a4d3b4": "[DRAFT] Levotiate Contributor Proposal 10/01/2022 - 10/03/2022 - second half",
+ "0x8e744c18b25b75c4fa95881daa15bcd492ebd2ad3a16c212514c66e4064d0e50": "GNO / WETH Epoch 12 - 13 SWPR farming campaign",
+ "0x952d8b39ff8dd5f0620dbe426acb3d137d92819cbb0631c6f9de734ac1a93c9f": "[SWPR / XDAI] - Swap fee update to 1%",
+ "0x971bb957d01a52d68ac8d4a4ccf3e7fd0583e4528a665cfb6e99fa641da844c3": "AGVE / XDAI Epoch 12 - 13 SWPR farming campaign",
+ "0x982e4dcea86d80a72ea6da2dab6730e34b409bee35788b414ff032d265b03f9b": "Level K - Reimbursements for ETHDenver Expenses",
+ "0xa57ea0f9ba56d6677b71ca9ac705cdab6ae170a081d5329fad315c8d44f2fb49": "2nd Test Proposal to Withdraw LP Tokens from WETH/wxDai pool on Swapr",
+ "0xa7ae51e589abdda68f082f0ea3f1f51e8be0fa04fd1c75a5f45c855f5cfe97d5": "SWPR / XDAI Epoch 12 - 13 SWPR farming campaign",
+ "0xad3f172fe7897c78d8ee7aac2f67d32c9c39d00dae858c619e4bf268ccddb80c": "DXAmsterdam Contributor Stipend",
+ "0xb1c9bf50e3b89be56279e9576b6c1e2516434d9abf7a8924d638377e858b4af7": "AugustoL Ferburary 2022 Work Payout",
+ "0xb5c6c20600d0324cbe600cfc1874fa1570e58202130b032e9f7f5643f375aa1b": "December 2021",
+ "0xbb75003e90205f0b732008521af4b531e0774f851981dc02d480d3566f05b871": "Smute - Contributor Proposal ",
+ "0xbc458ca8240faacbdee78b4efb321789a875ad55ded1cfc5df2129159694089e": "HND / WETH Epoch 12 - 13 SWPR farming campaign",
+ "0xbc9570eb252d3c72b16f58e79f8f26ca081930db44be408320bf12630564a401": "MAI / XDAI Epoch 12 - 13 SWPR farming campaign",
+ "0xbfd76fa4faa658ce026a54fbb8baea741014cdcec964f7b7584ee71c52aa87c5": "[Swap Fee] - Update swap fee of DXD / WETH to 0.6%",
+ "0xcba81e2fa2af07bdfa3a68496839a4ef722747769e95a9b520afd1a3574e186d": "Swapr HND/WETH farming campaign cancelation",
+ "0xcdee5c66dc09174bbef55341eca5e917e8f9e1a5b4f0df03ee85acf23eb30fff": "AllyQ Contributor Stipend ETHDenver February 2022",
+ "0xcf22139313ac001366712573f84c680c2c69fbd60ac0fe0ef128a9aa9f37af94": "AugustoL - Reimbursements for ETHDenver Expenses",
+ "0xd0555152a26164e57d55484c0305f66fee84cd72967f7bc2f6cc4235216b8110": "Madusha - Contributor Proposal [01/03/2022 - 30/04/2022] - First Half",
+ "0xd4bb2bafc24e0fe9b1b1b58c08306e4dc3fce5a5ffd0dad4957bf879ef1c0a76": "[Etherlabs AB] Payment Proposal [ Jan / Feb / March 2022] - 2/2",
+ "0xdcc56db033ceaf0e8cba81b6583d7a0e7034572520b582535c20c78d29cdbd2f": "CRV / WETH Epoch 14 - 15 SWPR farming campaign",
+ "0xe2de5a2142a5e08a3a7513c758fe0955e52c3b13bf3c224b4cfdc32cbe585bed": "RICE / XDAI Epoch 12 - 13 SWPR farming campaign",
+ "0xe38ea8f4f843920e4f450ff0cfbc66d6158543a546119b72ce8493b732de007d": "Milton - ETH Denver Stipend",
+ "0xe41ab7ec3ac9cb672043efb936ca9993d5ca2d97c6aaa14e61945faacc65e2d6": "Violet Worker Proposal 31/01/2022-31/03/2022 2/2",
+ "0xea97c70d686535ad265bfee1396e629e85edb5d585055a60b8655cc37e542e22": "Send HNDXDAI TVL Carrot to Liquidity mining relayer",
+ "0xf3d30c8e23ad26f4e9a75dc4cd71fa6a08a4e665e52791f97726efb90f0da8a5": "Alchemy API Expenses",
+ "0xf4c3ff2d5bd8d2111491052da99755d12b5ae3989ec061f16ef1651726c8a739": "Vangrim Contributor Proposal [12 March - 11 May (2022)]",
+ "0xf6941ec63a38b5f2c6282f7629bb7c1ccccd45f1be11902d0fb0b077c3cc96d1": "Send 14.9 WETH to GP Relayer for xDXD buyback #6",
+ "0xf85a3a5d75d9772e60807e4f5bb0d0ceb8f6c65d0c93b92b2d2e42cd6cb25505": "Luchux - payment proposal - 15th December 2021, 25th January 2022",
+ "0xf8bb4742b850198584c7bee39437151f5a6f6987dd23c106080f437002d2a155": "[DRAFT] Levotiate Contributor Proposal 11/03/2022 - 11/05/2022",
+ "0xf9d1887b1308e51583c8064da44b5487817b36811368dc0fe9fe78454ed5e740": "CRV / WETH Epoch 12 - 13 SWPR farming campaign",
+ "0xfb1795ba0a2b4ee12007fabc5f1847f344b40fbce8476727a648814e2e802261": "WETH / WBTC Epoch 12 - 13 SWPR farming campaign",
+ "0xff32174f3f2ff80955d5075937f72d07f5bc18364946cc2f54bc57c5f42a29ec": "xDXD Buyback Order #8",
+ "0x21ced878e0a12ea293711f6ac88546a730bba9a35f4dc9347c0a589562329797": "Stake 2k ETH to StakeWise - Signal Proposal",
+ "0x3e8416ee56beef52e28ea49ebe2839db3e620e8d3c695cd9c9f19b83f79bff40": "Decentral Labs Worker Proposal - 18th March to 18th May (2nd Payment)",
+ "0x53c9666338692a720a3ee3841b49f58a4d580cf7ed11acb2d43a484c8d09bc88": "Transfer of Funds to GC Base 500k",
+ "0x545f71ed3ef6e9efbe9340f634bb480bafa50639edeb5df7b86e4061b9fcf726": "xDXD Buyback Order #155 for 13.46 WETH",
+ "0x556cc36c8b7f807ad9770df79199f53462b8f93c6060023d97ccb3efc532c38e": "Payout to Sigma Prime for Auditing Services",
+ "0x5b1fb2e66669ad69531309fcfe342f4a1bfd995eb6940de049a625a4948289a9": "Decentral Labs Worker Proposal - 18th March to 18th May (2nd Payment)",
+ "0x636be996d018fc346bcce52e41c1026d41cf5cfb6665418334606d19c6cd7625": "Claim Mainnet REP for SkyMine Labs - Nov-Dec 2021",
+ "0x69a881265303706f921c9c1ad25de4b0635ff288893455b34f18cdaf9e7f86de": "DXD Buyback Program Adjustments, Extension #8 and Transfer of 373 ETH",
+ "0x79fb75b821690a15eb00764020bdb32d08704a5d340ff32eeb46543ff1caadb3": "Update dxstats.eth content hash to DXstats v1.5.0",
+ "0x7cc440cc8f6026c15213c4c551721f85d00d3a0908915331d454a9a326bd23f1": "Madusha - Mainnet REP Sync",
+ "0x880d07de4907b66d72521faec4de98283b92e9beb093b8ff7cdcb6112363b334": "Caney Fork - ETH Denver Stipend + GEN reimbursement",
+ "0x9a1c901b918f40f48a9cc1344a7556526952d6b697a02fdb479bd1ded5ab7e39": "Movement of Funds to Gnosis Chain DAI",
+ "0x9c62869ae0347e7f65e18733e4bdf9f155e9d43b14250295757e88520e6a7043": "Movement of Funds to Gnosis Chain ETH",
+ "0xd2114f86cd669d2a34b529e822024d4b280f7427639f0399106c4ae81997a2d8": "DXD Buyback Extension #7 - 385 ETH",
+ "0xe41bca110d96136684a2e916521ea9201f5a3f273aeaa518ca479f36961285f4": "Update swapr.eth content hash to Swapr v1.0.0 Beta 12",
+ "0xec89d8b01cc2ff1c77e501d056f2c584fcf323b10488583ccfeaeba90a06fdc8": "(Venky) Sync REP from Gnosis chain to Mainnet",
+ "0x00d4d73fd9cf48d95c5456dbd9b367236128e92359d600d2b09ce4cc2cb95bd4": "Leonardo Berteotti Contributor Proposal [02/02/2022 - 18/02/2022]",
+ "0x020b7aa9daca82035281fedd3bcfb42b56a67122b5ff53301b2c34c4e1d4bfdc": "SkyMine Labs - Stipend and Reimbursement around ETH Week Amsterdam",
+ "0x027d890c43faf6a00c691e65bd57e0375fa29c60b6629a24906614db3f3954ba": "DXD Buyback Program Adjustments, Extension #8 and Transfer of 373 ETH [Mirror Proposal]",
+ "0x03633066a51aaa63db6da76fbb07f8835bad46d43f1f58e6805c937a94bafdf2": "xDXD Buyback Order #159 for 12.59 WETH",
+ "0x0437d812f9581c992c12cf015252ced24dcd475d34e0e41256cdb6abee45eb8a": "Zett Proposal April, May, June 2022, Payout Period #1 | Product Owner & UI/UX",
+ "0x06338668a6d047c452722c3cc5bf2aea39daec9e9f92a1c3b2338fbf0e9c9c74": "xDXD Buyback Order #180 for 11.04 WETH",
+ "0x0c86b647fc9f921b2d7594e80fcf9bb904a5cb09e526d8c423797f863c46d0a8": "DXdao Discord Q1 2022 REP Boost for Sarah",
+ "0x0dcf78fae64e3f5d105768fb4fbcf4fa021504c7254bd97966b3b81c59e85d5c": "xDXD Buyback Order #165 for 10.08 WETH",
+ "0x0df20cd1df98288189770f51c1ca09dfdb798a7701e0dca02b35b3dc6076fc97": "Member Balancer to Supply xDXdao with 10,000 xGEN for Continued Governance Operations",
+ "0x122e8aaf69ac6c2eb0b8576a01baa7f0b0d72775ac100e04fd111515686a182f": "Venky - DXAmsterdam - stipend",
+ "0x13f6f59e9684d54de3f27a16061f10a59f723d9fea5135510d6d3217d474102c": "xDXD Buyback Order #169 for 9.91 WETH",
+ "0x1b7634ab666c2a29bc85d830921c8c367a559b4c8bdcfa79b3e78e582f294e8c": "Adam Azad - Contributor Proposal March - April 2022 (late) - March payout",
+ "0x1cc9c1bc8f168029744113be1ea4205faf53a17983bfab722a42b72b3cf67457": "xDXD Buyback Order #181 for 10.81 WETH",
+ "0x1d7f784feb2ab279ce228be60672add5aab82aaf701762f4188f625efa8a15ee": "Signal Proposal: DXdao to commit to Ministry position in Dawn DAO organized by The DAOist",
+ "0x1ef0ceb197194b356d30b1acac18f4c6571563579f07e9bd2b122b68f3e10b48": "xDXD Buyback Order #166 for 10.17 WETH",
+ "0x1fe7d4a7baa0ccc75b3640d3be0abda448afcd6754f20b6cfe755a45b87e6aa4": "AllyQ Contributor Proposal 1/24/2022-3/18/2022 2/2",
+ "0x23ec0ba69003e9c8d0724a2b368c1d6d6a151e1f5a5673604f1097de28e966c6": "VanGrim (through Zanarkand AB) Contributor Proposal (12 May - 11 July 2022)",
+ "0x2497b482da5188cbd71cbc90dcceb1f3077142c55dab87f3107f4d3af31b9c1a": "CRV / WETH Epoch 16 - 17 SWPR farming campaign",
+ "0x269918338f757a7e4c56de96acf1e517282cab63f97485dc5ce38b8b6e374ede": "AllyQ Contributor Proposal 5/23/2022-7/15/2022 1/2",
+ "0x28e4d114cad1d9ef56d0e43953d44b7dee4786714b6d6429410e57bcf9f04d65": "AugustoL Contributor Work Proposal #4 Payout",
+ "0x2a8121413822a157f678e719ccdacbbf6a3faea752485c77685506aacc7feace": "Space Inch Development Work - April 2022",
+ "0x2afdb83c932c74bd5b39030a38c411c3afb8784a166dfb6bec0d2a4b7ee7212b": "xDXD Buyback Order #163 for 11.2 WETH",
+ "0x2f020d2fbb83b52923da248af446caa642de28af37d6f2a106e38bfdf050e162": "xDXD Buyback Order #194 for 13.99 WETH",
+ "0x328d33e198b9c4a882c647fdb1ea1469db89d631492260daecbc5bbde6956ea9": "xDXD Buyback Order #193 for 13.07 WETH",
+ "0x3453fe5a59e7c62ce400a8bba2c03d1b7f0792e513cc690ef3446bb2f9a17f2a": "xDXD Buyback Order #167 for 10.11 WETH",
+ "0x3495509fdd80bc85acbd43808c999fa67de371861579da4fad502f7d32b722ad": "Dino Crescimbeni - Contributor proposal [16/05/2022 - 15/08/2022]",
+ "0x34c95d7652e11caffc1dac7b885d0f2be28710b9012acbb651ce27bfefa45a04": "xDXD Buyback Order #189 for 11.97 WETH",
+ "0x36453048f17d2a6612da9380ee7526aba69976cf13637688b3beb6e701ff9cfb": "Melanie Contributor Proposal 2/1/2022-3/31/2022 - End",
+ "0x37feff80c278ccd50524730c81841678c7dc4710957626cfb25af517a22c8328": "xDXD Buyback Order #191 for 11.44 WETH",
+ "0x399c05f720af6db7dbb2ce7c539c3c48fdcefebbfeb2fc3a12ec65dba645249b": "Borisblock — Contributor Proposal [07/03/22 - 07/05/22] 2/2",
+ "0x3a8e9d0b5909b8dbaa1bc391c7f708dfa1432afa98a10e86a1197457d9037733": "SkyMine Labs - Contributor Proposal 5/22 to 6/22",
+ "0x3ad287fad8243f2ab939f0b5dee1b019ba8aeb80247f3719faf7ec87c6a7c153": "Nathan, beginning of new period 05/01/22 - 06/25/22",
+ "0x3c207c2cb2005382f4ee55b11949057df74e2914c3f66f172014736ea1a3207f": "0xKLOM.eth Contributor Proposal for 05/2022 to 06/2022 1/2",
+ "0x3c26e5af14f6c524ef8c8f32bb19fdbc86777acba84e70390cff89bb1e32e747": "xDXD Buyback Order #195 for 14.23 WETH",
+ "0x3d4de42fbdb25ede9391ab6c5e87985d524f7cd42f47c75fd75acb1e581b2cf1": "Wixzi Contributor Proposal [05/04/2022 - 18/06/2022]",
+ "0x3ea8a6cbf6c9f7c8087271473e098af2f16747f6e07408a1b5a6fab72580f7d4": "DXdao Discord Q1 2022 REP Boost for squidz",
+ "0x3fe2e55c745fba7e7f9ad5ee91e2bfd79ca13f4557cf2725247047b1c0a90849": "Madusha - Contributor Proposal [01/01/2022 - 01/03/2022] - Second Half",
+ "0x3fe35e33bfe91259ac39a0573d99f77042a695bbf5740c2c3c1d2549d3c3085f": "Space Inch Development Work in March 2022",
+ "0x41dc8a5d63f83d88227697b86954ae2d03891bc8996b592ffaa0897c4f9af82e": "xDXD Buyback Order #197 for 16.5 WETH",
+ "0x42984b06d80ce009f37621bad8bc85001497f6f3907562e9ff27f72f334a2c33": "DXdao Discord Q1 2022 REP Boost for TheThriller",
+ "0x42c0a5c0edd7b817c7d6e31e57c70ef3da70795ddf764fd4ac49b5dc7a6081e8": "xDXD Buyback Order #175 for 10.63 WETH",
+ "0x42d379b00f25079dd7964ebbc8c1fe6d44e03f1bd340aa68442c12df568cd909": "xDXD Buyback Order #185 for 11.62 WETH",
+ "0x4525007fb5948688f94c8db0644ca55ea5d3543ddedb8c8eeb3bfb954e982c60": "Space Inch Development Work in February 2022",
+ "0x45cdf73bb23f462aba74c8714b44784c7148bc953d59369dbe9c9fd6a65e5961": "xDXD Buyback Order #174 for 10.76 WETH",
+ "0x4a70402e1e43f472a7b58f52969390cd77cc7896cc8a9bb492f87303dc1c2e68": "Guerrap Contributor Proposal [14/03/2022 - 01/06/2022] [1/2]",
+ "0x4ad40975ba5bff960bdb7dfa1f6a7973ba84f4a70bd15e3b9313e48a075b2f2c": "xDXD Buyback Order #200 for 11.47 WETH",
+ "0x4b394e097059ecb4c3163c4e952f933ae8124072d19c3777b923087bef347fef": "Unwrap 65k WXDAI to Dai",
+ "0x4c48923b379c4910191f27c80dcd7148af588ca648f9304d3e7731f8f83f0b04": "(REDO) - Member Balancer to Supply xDXdao with 10,000 xGEN for Continued Governance Operations",
+ "0x4c87360f51d53256be331f459bdcebd659e2368d30ca9441c8b84cfe1bc38304": "Adam Azad - Contributor Proposal and DAI payout - Jan - Feb 2022",
+ "0x5031bca4a8f68ba19fdf6f2d302ba69b7eec3d5761c4f3420b391b035eda9ac6": "xDXD Buyback Order #184 for 11.18 WETH",
+ "0x5061ddc2fd7542b5119b3e6f6c651c17ef561f1b1e92d1023590b080ccc99784": "AGVE / XDAI Epoch 16 - 17 SWPR farming campaign",
+ "0x524dfaf6404411a9cab6635a99198ce127dcd1d398a0fd58f1432eb8802f225e": "xDXD Buyback Order #182 for 10.87 WETH",
+ "0x52a7e5f06b36a916e88e0e6c0adbc3fc8fb2b7e23970a0c5fcf81b41669a50b3": " Melanie Contributor Proposal 4/1/22 - 5/31/22",
+ "0x54e907e00b8897f6d67a8214bf735f84d655ca83f58783c2ec1639d4c64fd453": "Proposal: Carrot Awareness Activation During ETH week in Amsterdam (April 18-25, 2022)",
+ "0x55b61b9fea9a4f77fb6e4728437f1a8a306416f6cefe0067029eaa50efe90813": "Wayne’s Worker Proposal - Trial Period Late Jan 2022 to Early April 2022",
+ "0x55ff34c97949e067ed11379a5ebf2c032b146fd83b11b03d48e8685fde618761": "Wayne's Worker Proposal - Early April 2022 - Late May 2022 (signal)",
+ "0x5715b4637b8e32cf3f44dac8fbd78f38a87fc1563e5957e4eecbdd5723a03450": "Wayne - DXAmsterdam Contributor Stipend",
+ "0x57a0c98453a71eb8e745aa2bc1d3bf66a110cd2aeae9cbdfa62d750406b10766": "DXdao Discord Q1 2022 REP Boost for SpicySoup",
+ "0x57fd56a03e35d0b72b50bb594508352d7de0d5e3e42da36802916ac0573baf5e": "DXdao Discord Q1 2022 REP Boost for Tom-Fr",
+ "0x586578ee4810f82e5d9c7dbe43e430a56584924b9a0d99e23e3be1c4077a5c88": "xDXD Buyback Order #151 for 13.42 WETH",
+ "0x591e0bb6b2c5efa5b97f81d70784353ffc15a692ba58edca648bc147013c7511": "xDXD Buyback Order #156 for 13.93 WETH",
+ "0x594b2166099be1b5c99958b74c3fe46e5bfbf53020222b7134886d78287cfd7d": "xDXD Buyback Order #150 for 13.19 WETH",
+ "0x5cf0c076fc5cb1d7931cfbcb2988c9302494b5b967f87caa04cc01c4deee484a": "Carl B - DXamsterdam stipend",
+ "0x5e1617ca4b3b6d1ebed7c576eaaf428241e6a77c3407b578af82f4c71002c6bf": "Signal Proposal for DXdao Discord REP Boosts Q1 2022",
+ "0x610e201c8ac544589cd9d2743e3463344fe4d43065abe6726211eb59d53c4032": "SkyMine Labs - 1/22 to 2/22 Contribution Recap",
+ "0x615ab3d3e492672d555b01eecca68023ca5e8f1c014bcda6da5e4e4d79aea0df": "xDXD Buyback Order #173 for 10.75 WETH",
+ "0x62e0b3b82715547de7090f628f4c3bda4322226d664ef4e9f41a5cc4e8d7ab78": "December 2021",
+ "0x62f0b6b36f2071c93ed3b4b6cfcce354dadf9caf31fbfea64d95809195bc967f": "Diogo Ferreira Contributor Proposal [4/04/2022 - 15/04/2022]",
+ "0x62fb4da3c53ae8c70710acf49f9771a7f7b84ec36ce502a65dc2fd57f592bfc5": "DXColombia Contributor Stipend",
+ "0x651ae49a00ea204017b1dfb7ca7430bae1fad61a184ebbdb1b6ebc13b35f3ce0": "Worker proposal - 26/01/2022 to 25/03/2022 - luzzifoss",
+ "0x653fa2503a9d3fa394f234ec69e217270e12c0ace69880e4fb9f18509eb9303d": "DXdao Discord Q1 2022 REP Boost for Chiminiv9",
+ "0x6914b20e6c054d8787c6acb13ef1b61c5587a4912e2b7ced90f36b9aa09820e4": "xDXD Buyback Order #164 for 10.33 WETH",
+ "0x698c40183fd31e9df74d0a7d391c62b1475cd53b5cec730aa9090262876a79f0": "Caney Fork Feb/Mar 2022 Proposal (2/2) + DXAmsterdam stipend",
+ "0x6c2366402f1baa13661d68659ca4981c28c11078b67f9c6a10389a0d1e3fc922": " Borisblock — Contributor Proposal [07/03/22 - 07/05/22] 1/2",
+ "0x6cf3ce433d7d90f4f66486a9e09be8540bf0840e76a593b8e10f8a658897cf04": "xDXD Buyback Order #196 for 16.49 WETH",
+ "0x6da5d04d5cb90b4cf62cb609d6bf71524dcc0630e67063ee3746bf0c1e50977c": "xDXD Buyback Order #148 for 11.65 WETH",
+ "0x6f8961cbd277969e9d149d1220d26b678f5e7193dbdff9f136239c54c67c53b4": "VanGrim Contributor proposal 12 March - 11 May (2nd part)",
+ "0x728980d7a2086a78561c2b24b82a04957a2d31fb41e84373de77d85b423d93a2": "Jorge Lopes Contributor Proposal [18 April 2022 - 18 May 2022]",
+ "0x74cb0a9436ddd5810bb7dac8e537def758d2be703abcb6a93cc7125bf52c8266": "Caney Fork Proposal & Payout Dec '21 & Jan '22",
+ "0x753bfb5a08d34e80f87f31fa697f00f991d2e77e54d0509e49feb76539846e0b": "0xKLOM.eth Contributor Proposal for 03/2022 to 04/2022 1/2",
+ "0x775a93f01e24feb1707be6c9df8df89cb3e10fb2286c36c77409f0b4dfcdf668": "VanGrim (through Zanarkand AB) - DXAmsterdam Contributor Stipend",
+ "0x776ecd66631b9a0d97247c3300617450c56bbbe090746e3ddaab817a0f3cde4a": "xDXD Buyback Order #144 for 14.05 WETH",
+ "0x78da1d7655fc15a9d10eb4f6a434c9c2144fe44661296d3a6b7182e09eeb6e47": "xDXD Buyback Order #158 for 12.57 WETH",
+ "0x797e661cad50dfc6956c19e3e2538b3f36aed16e29d17f0a1d34cb90384ed9d0": "Leonardo Berteotti Contributor Proposal [21/02/2022 - 15/04/2022]",
+ "0x79a64e3beb29b46eb7c9dd192e13d8ac405b5a94e8b04392900497ba511ab2bc": "Dlabs Worker Proposal 23rd May 23rd June",
+ "0x7ac00c7b3e2b4c80084bba14ef50f75784a545f1b092a7247fb02ad46707632e": "xDXD Buyback Order #199 for 10.98 WETH",
+ "0x7c3b8569d7d196f5c2764bb4f7edf1e0c6fcdca10f1be153b8adb5dda4663609": "0xKLOM.eth Contributor Proposal for 03/2022 to 04/2022 2/2",
+ "0x7d706e5797f06b58d11fb7924856b55b0399fb4788447f23421cfdab16905f6e": "Violet Worker Proposal 31/03/2022-31/05/2022 1/2",
+ "0x7dd1a6275b358c040e113a069c88d3f44e4782ba1138cb8c30be2670e26d4b8a": "Tammy Vested DXD Proposal from periods 12.20-5.21",
+ "0x7e6b833973c06433dd53c04ed7664798fb11aae83881346d442c60279b087b71": "Carl B Contributor Proposal [2022-02-21 - 2022-05-09]",
+ "0x7fb7e060c4b6442e2cbd4fbd48bde7005c8553c9fa10f27d8d266793593fab6b": "SkyMine Labs - 3/22 to 4/22 Contribution Recap & Payment",
+ "0x817730e1c57f948c587a19b54177ab23ef7332a04c73986e1b66a06a5fc5983d": "xDXD Buyback Order #188 for 11.92 WETH",
+ "0x872704d2f1619dd5d83b9ca255348647b504322aac54bc4783712d6f6883020f": "Etherlabs AB - payment proposal - April 2022",
+ "0x8893d52df36f581cf2e30a17c5459380db55799d31fce85dd5e9b17e20a3251a": "Milton Contributor Proposal [04/04/2022 - 29/05/2022] (1/2)",
+ "0x88b8b7e41ea978cd9dad9fc9939ea56177813663d2d696ebe8a34bf147a1d17d": "MAI / XDAI Epoch 16 - 17 SWPR farming campaign",
+ "0x89fff26d1ddd066908be3072b78aad19225c79c78ab3753ce168113dd3be26a9": "xDXD Buyback Order #161 for 12.17 WETH",
+ "0x8bfde4ea88ff76a420a7cac5617cc500ac78c274a8c7787b5f5542562d0fb702": "xDXD Buyback Order #149 for 12.08 WETH",
+ "0x8e496a70764ca712c6444df8486024e5d88b98b97a0688c6ea2a325384e019c1": " Carl B Contributor Proposal [2022-02-21 - 2022-05-09]",
+ "0x9230fa1b8a5d6643c029a9259256e2d852c3a485b31694b9e0e33645ceeedbca": "AllyQ Contributor Proposal 3/28/2022-5/20/2022 2/2",
+ "0x929c071b90372dc4346cc7480290d00636dae64ba566562a8022afbcbd99477c": "xDXD Buyback Order #155 for 13.46 WETH",
+ "0x981f7ad155bb4d79fe963426b22d26bde961aa069b3afb6924968ac0325e1b08": "DAI payout (26/12/2021-25/01/2022) - luzzifoss",
+ "0x9897941fba1f7450d3c038868485ac4ca23b83cc695eb9326f9394e6a6ded43f": "Stake 255 GNO - Signal Proposal",
+ "0x991b4570a439520098f00d23755bce9e58a28d58ece5c54d2e4148b2d49fe5c8": "RICE / XDAI Epoch 16 - 17 SWPR farming campaign",
+ "0x9a9a8bd064b947fc9bb32f71b7813aee6fdbea0abe9cd620204f0d4b3731b979": "xDXD Buyback Order #147 for 11.83 WETH",
+ "0x9c05f686011ebb52a19955e2ffe63ba8ee0505dd29365b3a6a2490f2ab3ff714": "xDXD Buyback Order #146 for 13.99 WETH",
+ "0x9f5faacc7f41665b447e1423f3d79274a8434a7e7f2b4a2dd71b85d2146fb36c": "xDXD Buyback Order #171 for 9.79 WETH",
+ "0x9f66d49e0b800dca0de8d21044f7cdf67af8e12154d01b785253e29419a2eab2": "Nathan, proposal at end of period 3/5/22-4/30/22",
+ "0xa194a4b2ae0050d2396e030709e10b85daa13e6ba1d4f0642d2573e45c961e9d": "xDXD Buyback Order #154 for 13.66 WETH",
+ "0xa2be4abc07207c4a273cd977428078b3d81292522cd170d4e0f9c95091568427": "AllyQ Contributor Proposal 3/28/2022-5/20/2022 1/2",
+ "0xa59d47177919ce1121216ab29e6e1b15d0d1f5ebd238d8eda8c5ba54d6def171": "xDXD Buyback Order #190 for 11.36 WETH",
+ "0xa7523735a2f01afd953d4e7650c7323f2b3714d4b7b81133e471e734206f676a": "xDXD Buyback Order #162 for 11.9 WETH",
+ "0xa793418ec15a861296ddad02148bd28a6078e799ea605d299b7dd9c38656e5cb": "0xKLOM.eth Contributor Proposal for 01/2022 to 03/2022 2/2",
+ "0xa7eed37b53104a70aed9d73e811498ea0fee9a9e634230fd5745d94ebb3f7d4e": "xDXD Buyback Order #197 for 10.64 WETH",
+ "0xad91395f9ae6453c66819806237380cb9231812b2784ac727ad14aed5c348fe6": "xDXD Buyback Order #157 for 13.65 WETH",
+ "0xb0f303cda263824463740d66e310d06cf1a4f73bea67a6a8a51d95c37bcf532a": "Borisblock — Contributor Proposal [07/05/22 - 07/07/22] 1/2",
+ "0xb399905e93fcc1ea604cc965a2622b39a62318706965aa13319784ad20a069f1": "Ross Neilson Worker Proposal 18/4/2022-18/6/2022 1/2",
+ "0xb7804c3f333e5012a66be5027f0ee73c9d765b54bb086f836ac20a905a46e20e": "xDXD Buyback Order #168 for 10.53 WETH",
+ "0xb7eb202304dbf0b1fa2fda84a1b972ac8ebc7c2dff79661de8de67c5e4ee2b2a": "Diogo - Contributor Proposal [16/04/2022 - 16/06/2022]",
+ "0xb7fc6d125eed2595e715c4f857a6512748d2bc96bd4a1adbce9ff21f209152ab": "xDXD Buyback Order #192 for 12.44 WETH",
+ "0xbac6b0fed6d4e10445d27f03ebc424082bf4c6c5cf127ac2f89cac04e99671e9": "Madusha - Contributor Proposal [01/03/2022 - 30/04/2022] - Second Half",
+ "0xbc80c062bb326a303dfc363083471eb8d6bf4146a8b6ba02328906ddb4ee16b5": "Adam Azad - REP Sync Proposal for January 1st to April 30 2022",
+ "0xc0cfd98a9317b65cd4b5496247b36bdf8990cf72b570e1b5d1f53c2ce7b5bdd2": "DXdao Discord Q1 2022 REP Boost for Cantillon",
+ "0xc51721575e515e3028ecb37ea148926a9ae9738f81c91564c435ffbc3437a009": "xDXD Buyback Order #183 for 11.72 WETH",
+ "0xcba3e751dece5607735455eed9e19271f1ae108ffbdbf8edc88d64d1281d75fc": "AllyQ Contributor Proposal 3/28/2022-5/20/2022 2/2",
+ "0xcbba59861ced43a022b2bf0bb5e26151b2e1088c7b0198d63b414732f6cf0aea": "Ross Neilson Worker Proposal 18/2/2022-18/4/2022 2/2",
+ "0xce7c3c0de28ba9b1d1c4180234200a4da01c4c1a900e39fd9671f1ff5cdaa71a": "Adam - Stipend for Devconnect Amsterdam",
+ "0xd066e809f19e7fcba92fd4c99001be124525484f5d37725c21d64479a248cd08": "Milan V Contributor Proposal [14/3/2022 - 14/5/2022] - Second Half",
+ "0xd2784e9d5a06ecf3db3cbf49147a5fb80d329d0d2fbb450274e77a7dabd08bb3": "xDXD Buyback Order #176 for 11.21 WETH",
+ "0xd39d6107149aafeb24a41a252a93a0a034609585059a82ffe395a99df5030bcd": "xDXD Buyback Order #152 for 13.76 WETH",
+ "0xd41c033b50c0d32cbcd5d8a15a9ad528de8732cc6542f0aff6100b61e5893dac": "Milton Contributor Proposal [07/02/2022 - 03/04/2022]",
+ "0xd59ed2baa46fc4b325a434e7c86922cee46801f2003b53f17b090cad1ea725d5": "Etherlabs AB - payment proposal - April 2022 (REP and vesting)",
+ "0xd91c3ef93c3fde9be42d2cf4d9d44aab1e98aff1c21a077fe3f47fe8e73c1e42": "xDXD Buyback Order #145 for 14.95 WETH",
+ "0xd98e432717bd3cef5046d3b5db806133b8ac79878cf83ccecd4b809ac1154f2f": "xDXD Buyback Order #143 for 14.99 WETH",
+ "0xd9fdc37c352bd29e87198f5463aa4c5ae3144887124ae245db2715f7cea14e8b": "xDXD Buyback Order #186 for 11.47 WETH",
+ "0xe03d013efeca08f6d0949861290bb2e8332d5dfe35f9516674ef5c208d84a91c": "Leonardo Berteotti Contributor Proposal [21/02/2022 - 15/04/2022] [END]",
+ "0xe3209990432c23293332367fbe0a399ede709e42c1c9640c72d949819c1185f0": "Wayne’s Worker Proposal - Trial Period Late Jan 2022 to Early April 2022",
+ "0xe4a0e623a08639960a2936b6eb629a24f48578e2f520cfe32b25af84f70826c3": "Milan V Contributor Proposal [14/3/2022 - 14/5/2022]",
+ "0xe71fa634850a4a10c9eb2610c39d680c7dd216cc76ce9b22d3ff6136c72fa9f4": "xDXD Buyback Order #160 for 12.21 WETH",
+ "0xe7eb6799d28cd42071dd73930b997d1979734d1cac61c83b0bd186136f03d5b8": "xDXD Buyback Order #177 for 10.86 WETH",
+ "0xeb093a056d71e391917e06a2751e0bd23cd7ef06092b1db4e4c8adf88642b8b7": "SkyMine Labs - Contributor Proposal 3/22 to 4/22",
+ "0xebdbce1b34db36d21ef282f356ae4778fbfcb5501b494ba505d3b6be312ba191": "HAUS / WETH Epoch 16 - 17 SWPR farming campaign",
+ "0xec1661e91a40e16976d06c8240559f21cc92cd58c127763bc74747f7192404a8": "Int_blue - Contributor Proposal - April - May (Trial Period)",
+ "0xec9f0b6961fff3c12f7fa80745997311de28135cbb3a2e3c0798eb9c82fffc64": "DXdao Discord Q1 2022 REP Boost for Tom-FR",
+ "0xed3af1bfdbb6e6fef16a925c7117d173c311ba8ad53bd7bfde53a09f01b02f68": "Caney Fork Worker Proposal (Feb payout)",
+ "0xed8b701a21d8df816253ee7718c233efe3dcbdd0a48ccd1f003fcd0ed9685498": "DXdao Discord Q1 2022 REP Boost for snufkin#7489",
+ "0xee7d2df08b9870157259690aac89380acec49fc4587178481338e31c97428f30": "Leonardo Berteotti Contributor Proposal [18/04/2022 - 10/06/2022]",
+ "0xeed6b0b0d4364a7186cfb30269e601fffecb57dbd4a9a63a435178ad46ef8692": "xDXD Buyback Order #172 for 10.29 WETH",
+ "0xf1e9f9b94b4998a2eccd70505d17c5f340965dbad018a3da7dc26463efba0724": "Melanie DXAmsterdam Contributor Stipend + Swag",
+ "0xf2a22d0253b8d8fe8c9a5141437c153d3f1219a46bb52db2ff616e917a0afbc4": "xDXD Buyback Order #143 for 12.65 WETH",
+ "0xf361b3de6f65d49f95f274330698297c1f0f4fbeac230a1affc3dd739bfc2bec": "Send 15.4 WETH to GP Relayer for xDXD buyback #4",
+ "0xf37c8f2d3b91c335f17b32267b37ad95d4fb76123fb65f32bef87947067276d1": "Etherlabs AB - payment proposal for Jan and Feb 2022 - stables",
+ "0xf386d0a218f489df4649b345c9e248369e82685b23dffb895f8a4bfe2d9f268b": "Zett Amsterdam Stipend, Copenhagen, Merch & Other Costs",
+ "0xf637871828ab1b20f7551cba7f81cc211502468f2273e77f619073c49d5ea6ef": "DAI payout (26/11/2021-26/12/2021) - luzzifoss",
+ "0xf64ef8e41d77cd00750b7cf0f82d1d5dd6a72ff9589c8c0667490e9318dd15eb": "Violet Worker Proposal 31/03/2022-31/05/2022 2/2 + Amsterdam stipend",
+ "0xf7a30ab1df563e6327e7a1114ea16161e1baf3aee6d07c62d8bccdc7b26f97a2": "Send 16.4 WETH to GP Relayer for xDXD buyback #11",
+ "0xf844a99ab8cb5556dc19b3dc76dc55ce88f3ed63f1aae6604318a5ced2e8e80c": "xDXD Buyback Order #178 for 11.06 WETH",
+ "0xfa21c90ad70a9f2f804246f3746b5aef5036864f29158c298efe49a28d6578f3": "Caney Fork Worker Proposal Apr/May 2022 (1/2)",
+ "0xfa8db9098d406b2efb145366102a314fc852a40d3c4361f4a30f15783bbf639a": "Violet Worker Proposal 31/01/2022-31/03/2022 1/2",
+ "0xfb27a478ec614dea90f5e0b4b4caa828fded254d0d589b120a119e0ca097ebad": "DAI payout Zett Period March 2022",
+ "0xfc921ce24f2458a725f2928d82e82888839af71a3cc15a8a29c374a3cae9102d": "Trial Worker Proposal - Adam Azad - January 13-27th, 2021",
+ "0xfcdb52fff5bed18bbce359b3bdeb5ffe0431c0e29f60af08b85aef969cf7fe25": "Melanie - ETHDenver Stipend Request",
+ "0xfd10e5ac9711008d583f7c8d5da9aec232be4f3ee9b64c715df95ad8340c6ba5": "xDXD Buyback Order #189 for 11.8 WETH",
+ "0xfe0d7e6f7c22c11e19a32d40f7360ce0251f2122d4a2a9a114bbd1d90853ff8d": "Melanie Worker Proposal 2/1/2022-3/31/2022",
+ "0xfe2765f0bbd28a9d00e6c231d12e19235b4f471b02fea652bc6b5d5280069a4f": "Nathan, contributor proposal for end of 01/08/22-3/4/22",
+ "0xfe8dbe253824d26a023cfbe75ccfd01a15defa01fd7f2712fb2a33a2bcb6b1bd": "DXdao Hackathon & Retreat Colombia October 2022",
+ "0xfeb2d79cd1e17a3e3f1b22b15a3b86d6284a1415dea8d120df0fb0ae1bb19f77": "xDXD Buyback Order #153 for 12.88 WETH",
+ "0xfeea9d463a997be8e640ecfdc7b8179e7424ebe8c0d8201c65c2019a7d7baf67": "Worker Proposal 06/21-07/21 - Kaden Zipfel Software",
+ "0x17dcc4df80b1dcde1c7943ecb9aacab9f6d369177f9dffdcc95be231511da1be": "Cross chain Member Balancer to Supply xDXdao with 35,000 xGEN for Continued Governance Operations",
+ "0x52c90416b88701ea09a44b0bd9bed5c7ea6db5cece2d28cb1456a7da668afc16": "Caney Fork Worker Proposal Feb/Mar 2022 (1/2)",
+ "0xa8036392ff2da5486d287473a8f1490fe74461e1838c098920dedca73ed0ecdf": "xDXD Buyback Order #179 for 11.01 WETH"
}
\ No newline at end of file
diff --git a/src/configs/rinkeby/config.json b/src/configs/rinkeby/config.json
index b2ede7e0f1..15460865ef 100644
--- a/src/configs/rinkeby/config.json
+++ b/src/configs/rinkeby/config.json
@@ -1,8 +1,8 @@
{
"cache": {
"fromBlock": 9234792,
- "ipfsHash": "QmcQUUNkAy6V7PYH4wksHvhTmJbEiUGT6UyFik1FCAi8rE",
- "toBlock": "10225316"
+ "ipfsHash": "QmTear8HaHRnNNTAu9RRMpdPdRxqKFmXTkqwGMgu1eKJFj",
+ "toBlock": "10525725"
},
"contracts": {
"avatar": "0x1A639b50D807ce7e61Dc9eeB091e6Cea8EcB1595",
@@ -13,8 +13,8 @@
"utils": {
"dxDaoNFT": "0xF7A2f72E8f6aeb884905a1fE515c1BB5752D342f",
"dxdVestingFactory": "0xB5D42c8cA3B04479200E3782C41D99b46Cf8A6E1",
- "multicall": "0x1FDD273e0B7E0d921Bda044Ebf64811428A79f15",
- "guildRegistry": "0xA938DD7AEeF5F46BD9845882EAbA2ebF18e1b273"
+ "guildRegistry": "0xA938DD7AEeF5F46BD9845882EAbA2ebF18e1b273",
+ "multicall": "0x1FDD273e0B7E0d921Bda044Ebf64811428A79f15"
},
"votingMachines": {
"0xBa51391385A6bD5ECA0217d7e843B29227E72508": {
diff --git a/src/configs/xdai/config.json b/src/configs/xdai/config.json
index d3fafd1778..a61839cefe 100644
--- a/src/configs/xdai/config.json
+++ b/src/configs/xdai/config.json
@@ -1,8 +1,8 @@
{
"cache": {
"fromBlock": 13060713,
- "ipfsHash": "QmfRWx3A2G3gL1sauTknmLUwiKP6NP1vWteEqPBXYV17uC",
- "toBlock": "20806189"
+ "ipfsHash": "QmQgax9dCsQbWwovbLG6NA1A8Z1pfoh5kRq1asqYZ8ReTM",
+ "toBlock": "22297636"
},
"contracts": {
"avatar": "0xe716EC63C5673B3a4732D22909b38d779fa47c3F",
diff --git a/src/contexts/index.ts b/src/contexts/index.ts
index 4bb71cef4c..bc04b900b2 100644
--- a/src/contexts/index.ts
+++ b/src/contexts/index.ts
@@ -14,7 +14,6 @@ import CustomRpcService from '../services/CustomRpcService';
import ENSService from '../services/ENSService';
import TokenVestingService from '../services/TokenVestingService';
import SubgraphService from '../services/SubgraphService';
-import MessageLoggerService from '../services/MessageLoggerService';
import OrbitDBService from '../services/OrbitDBService';
import ProviderStore from '../stores/Provider';
@@ -62,7 +61,6 @@ export default class RootContext {
ensService: ENSService;
tokenVestingService: TokenVestingService;
subgraphService: SubgraphService;
- messageLoggerService: MessageLoggerService;
orbitDBService: OrbitDBService;
cacheService: CacheService;
@@ -89,7 +87,6 @@ export default class RootContext {
this.ensService = new ENSService(this);
this.tokenVestingService = new TokenVestingService(this);
this.subgraphService = new SubgraphService(this);
- this.messageLoggerService = new MessageLoggerService(this);
this.orbitDBService = new OrbitDBService(this);
this.cacheService = new CacheService(this);
}
diff --git a/src/contracts/ERC20SnapshotRep.json b/src/contracts/ERC20SnapshotRep.json
new file mode 100644
index 0000000000..0c9ed2433f
--- /dev/null
+++ b/src/contracts/ERC20SnapshotRep.json
@@ -0,0 +1,459 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "ERC20SnapshotRep",
+ "sourceName": "dxdao-contracts/contracts/utils/ERC20/ERC20SnapshotRep.sol",
+ "abi": [
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Approval",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "previousOwner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "newOwner",
+ "type": "address"
+ }
+ ],
+ "name": "OwnershipTransferred",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "id",
+ "type": "uint256"
+ }
+ ],
+ "name": "Snapshot",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Transfer",
+ "type": "event"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ }
+ ],
+ "name": "allowance",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "approve",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "snapshotId",
+ "type": "uint256"
+ }
+ ],
+ "name": "balanceOfAt",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "burn",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "decimals",
+ "outputs": [
+ {
+ "internalType": "uint8",
+ "name": "",
+ "type": "uint8"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "subtractedValue",
+ "type": "uint256"
+ }
+ ],
+ "name": "decreaseAllowance",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getCurrentSnapshotId",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "addedValue",
+ "type": "uint256"
+ }
+ ],
+ "name": "increaseAllowance",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "name",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "symbol",
+ "type": "string"
+ }
+ ],
+ "name": "initialize",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "mint",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "name",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "owner",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "renounceOwnership",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "snapshot",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "symbol",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "totalSupply",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "snapshotId",
+ "type": "uint256"
+ }
+ ],
+ "name": "totalSupplyAt",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "transfer",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "transferFrom",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "newOwner",
+ "type": "address"
+ }
+ ],
+ "name": "transferOwnership",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+ ]
+}
diff --git a/src/contracts/SnapshotERC20Guild.json b/src/contracts/SnapshotERC20Guild.json
new file mode 100644
index 0000000000..c9bba32d29
--- /dev/null
+++ b/src/contracts/SnapshotERC20Guild.json
@@ -0,0 +1,1145 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "SnapshotERC20Guild",
+ "sourceName": "dxdao-contracts/contracts/erc20guild/implementations/SnapshotERC20Guild.sol",
+ "abi": [
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "proposalId",
+ "type": "bytes32"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "newState",
+ "type": "uint256"
+ }
+ ],
+ "name": "ProposalStateChanged",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "voter",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "TokensLocked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "voter",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "TokensWithdrawn",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "proposalId",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "action",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "voter",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "votingPower",
+ "type": "uint256"
+ }
+ ],
+ "name": "VoteAdded",
+ "type": "event"
+ },
+ {
+ "stateMutability": "payable",
+ "type": "fallback"
+ },
+ {
+ "inputs": [],
+ "name": "ANY_SIGNATURE",
+ "outputs": [
+ {
+ "internalType": "bytes4",
+ "name": "",
+ "type": "bytes4"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "ERC20_APPROVE_SIGNATURE",
+ "outputs": [
+ {
+ "internalType": "bytes4",
+ "name": "",
+ "type": "bytes4"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "ERC20_TRANSFER_SIGNATURE",
+ "outputs": [
+ {
+ "internalType": "bytes4",
+ "name": "",
+ "type": "bytes4"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "to",
+ "type": "address[]"
+ },
+ {
+ "internalType": "bytes[]",
+ "name": "data",
+ "type": "bytes[]"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "value",
+ "type": "uint256[]"
+ },
+ {
+ "internalType": "uint256",
+ "name": "totalActions",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "title",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "contentHash",
+ "type": "string"
+ }
+ ],
+ "name": "createProposal",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "proposalId",
+ "type": "bytes32"
+ }
+ ],
+ "name": "endProposal",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "_data",
+ "type": "bytes"
+ }
+ ],
+ "name": "erc20TransferOrApproveDecode",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "pure",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getActiveProposalsNow",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getCurrentSnapshotId",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "_hash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getEIP1271SignedHash",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "name": "getFuncSignature",
+ "outputs": [
+ {
+ "internalType": "bytes4",
+ "name": "",
+ "type": "bytes4"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getLockTime",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getMaxActiveProposals",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getMaxGasPrice",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getName",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getPermissionRegistry",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "proposalId",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getProposal",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "creator",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "startTime",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "endTime",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address[]",
+ "name": "to",
+ "type": "address[]"
+ },
+ {
+ "internalType": "bytes[]",
+ "name": "data",
+ "type": "bytes[]"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "value",
+ "type": "uint256[]"
+ },
+ {
+ "internalType": "uint256",
+ "name": "totalActions",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "title",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "contentHash",
+ "type": "string"
+ },
+ {
+ "internalType": "enum ERC20Guild.ProposalState",
+ "name": "state",
+ "type": "uint8"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "totalVotes",
+ "type": "uint256[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "proposalId",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getProposalSnapshotId",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getProposalTime",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "proposalId",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "address",
+ "name": "voter",
+ "type": "address"
+ }
+ ],
+ "name": "getProposalVotesOfVoter",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "action",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "votingPower",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getProposalsIds",
+ "outputs": [
+ {
+ "internalType": "bytes32[]",
+ "name": "",
+ "type": "bytes32[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getProposalsIdsLength",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "signedVoteHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getSignedVote",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getTimeForExecution",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getToken",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getTokenVault",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getTotalLocked",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getTotalProposals",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getVoteGas",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "voter",
+ "type": "address"
+ }
+ ],
+ "name": "getVoterLockTimestamp",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getVotingPowerForProposalCreation",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getVotingPowerForProposalExecution",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "proposalId",
+ "type": "uint256"
+ }
+ ],
+ "name": "getVotingPowerForProposalExecution",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "voter",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "proposalId",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "action",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "votingPower",
+ "type": "uint256"
+ }
+ ],
+ "name": "hashVote",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "pure",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_token",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_proposalTime",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_timeForExecution",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_votingPowerForProposalExecution",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_votingPowerForProposalCreation",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "_name",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_voteGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_maxGasPrice",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_maxActiveProposals",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_lockTime",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "_permissionRegistry",
+ "type": "address"
+ }
+ ],
+ "name": "initialize",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "hash",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "name": "isValidSignature",
+ "outputs": [
+ {
+ "internalType": "bytes4",
+ "name": "magicValue",
+ "type": "bytes4"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenAmount",
+ "type": "uint256"
+ }
+ ],
+ "name": "lockTokens",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "_proposalTime",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_timeForExecution",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_votingPowerForProposalExecution",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_votingPowerForProposalCreation",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_voteGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_maxGasPrice",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_maxActiveProposals",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_lockTime",
+ "type": "uint256"
+ }
+ ],
+ "name": "setConfig",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "_hash",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bool",
+ "name": "isValid",
+ "type": "bool"
+ }
+ ],
+ "name": "setEIP1271SignedHash",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "asset",
+ "type": "address[]"
+ },
+ {
+ "internalType": "address[]",
+ "name": "to",
+ "type": "address[]"
+ },
+ {
+ "internalType": "bytes4[]",
+ "name": "functionSignature",
+ "type": "bytes4[]"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "valueAllowed",
+ "type": "uint256[]"
+ },
+ {
+ "internalType": "bool[]",
+ "name": "allowance",
+ "type": "bool[]"
+ }
+ ],
+ "name": "setPermission",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "permissionDelay",
+ "type": "uint256"
+ }
+ ],
+ "name": "setPermissionDelay",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "proposalId",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "action",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "votingPower",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "voter",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "name": "setSignedVote",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32[]",
+ "name": "proposalIds",
+ "type": "bytes32[]"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "actions",
+ "type": "uint256[]"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "votingPowers",
+ "type": "uint256[]"
+ },
+ {
+ "internalType": "address[]",
+ "name": "voters",
+ "type": "address[]"
+ },
+ {
+ "internalType": "bytes[]",
+ "name": "signatures",
+ "type": "bytes[]"
+ }
+ ],
+ "name": "setSignedVotes",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "proposalId",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "action",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "votingPower",
+ "type": "uint256"
+ }
+ ],
+ "name": "setVote",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32[]",
+ "name": "proposalIds",
+ "type": "bytes32[]"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "actions",
+ "type": "uint256[]"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "votingPowers",
+ "type": "uint256[]"
+ }
+ ],
+ "name": "setVotes",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "snapshotId",
+ "type": "uint256"
+ }
+ ],
+ "name": "totalLockedAt",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "votingPowerOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "snapshotId",
+ "type": "uint256"
+ }
+ ],
+ "name": "votingPowerOfAt",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "accounts",
+ "type": "address[]"
+ }
+ ],
+ "name": "votingPowerOfMultiple",
+ "outputs": [
+ {
+ "internalType": "uint256[]",
+ "name": "",
+ "type": "uint256[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "accounts",
+ "type": "address[]"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "snapshotIds",
+ "type": "uint256[]"
+ }
+ ],
+ "name": "votingPowerOfMultipleAt",
+ "outputs": [
+ {
+ "internalType": "uint256[]",
+ "name": "",
+ "type": "uint256[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenAmount",
+ "type": "uint256"
+ }
+ ],
+ "name": "withdrawTokens",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "stateMutability": "payable",
+ "type": "receive"
+ }
+ ]
+}
diff --git a/src/contracts/SnapshotRepERC20Guild.json b/src/contracts/SnapshotRepERC20Guild.json
new file mode 100644
index 0000000000..6726d51dba
--- /dev/null
+++ b/src/contracts/SnapshotRepERC20Guild.json
@@ -0,0 +1,1146 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "SnapshotRepERC20Guild",
+ "sourceName": "dxdao-contracts/contracts/erc20guild/implementations/SnapshotRepERC20Guild.sol",
+ "abi": [
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "previousOwner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "newOwner",
+ "type": "address"
+ }
+ ],
+ "name": "OwnershipTransferred",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "proposalId",
+ "type": "bytes32"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "newState",
+ "type": "uint256"
+ }
+ ],
+ "name": "ProposalStateChanged",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "voter",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "TokensLocked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "voter",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "TokensWithdrawn",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "proposalId",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "action",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "voter",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "votingPower",
+ "type": "uint256"
+ }
+ ],
+ "name": "VoteAdded",
+ "type": "event"
+ },
+ {
+ "stateMutability": "payable",
+ "type": "fallback"
+ },
+ {
+ "inputs": [],
+ "name": "ANY_SIGNATURE",
+ "outputs": [
+ {
+ "internalType": "bytes4",
+ "name": "",
+ "type": "bytes4"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "ERC20_APPROVE_SIGNATURE",
+ "outputs": [
+ {
+ "internalType": "bytes4",
+ "name": "",
+ "type": "bytes4"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "ERC20_TRANSFER_SIGNATURE",
+ "outputs": [
+ {
+ "internalType": "bytes4",
+ "name": "",
+ "type": "bytes4"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "to",
+ "type": "address[]"
+ },
+ {
+ "internalType": "bytes[]",
+ "name": "data",
+ "type": "bytes[]"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "value",
+ "type": "uint256[]"
+ },
+ {
+ "internalType": "uint256",
+ "name": "totalActions",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "title",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "contentHash",
+ "type": "string"
+ }
+ ],
+ "name": "createProposal",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "proposalId",
+ "type": "bytes32"
+ }
+ ],
+ "name": "endProposal",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "_data",
+ "type": "bytes"
+ }
+ ],
+ "name": "erc20TransferOrApproveDecode",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "pure",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getActiveProposalsNow",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "_hash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getEIP1271SignedHash",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "name": "getFuncSignature",
+ "outputs": [
+ {
+ "internalType": "bytes4",
+ "name": "",
+ "type": "bytes4"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getLockTime",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getMaxActiveProposals",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getMaxGasPrice",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getName",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getPermissionRegistry",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "proposalId",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getProposal",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "creator",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "startTime",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "endTime",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address[]",
+ "name": "to",
+ "type": "address[]"
+ },
+ {
+ "internalType": "bytes[]",
+ "name": "data",
+ "type": "bytes[]"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "value",
+ "type": "uint256[]"
+ },
+ {
+ "internalType": "uint256",
+ "name": "totalActions",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "title",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "contentHash",
+ "type": "string"
+ },
+ {
+ "internalType": "enum ERC20Guild.ProposalState",
+ "name": "state",
+ "type": "uint8"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "totalVotes",
+ "type": "uint256[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "proposalId",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getProposalSnapshotId",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getProposalTime",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "proposalId",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "address",
+ "name": "voter",
+ "type": "address"
+ }
+ ],
+ "name": "getProposalVotesOfVoter",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "action",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "votingPower",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getProposalsIds",
+ "outputs": [
+ {
+ "internalType": "bytes32[]",
+ "name": "",
+ "type": "bytes32[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getProposalsIdsLength",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "signedVoteHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getSignedVote",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getTimeForExecution",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getToken",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getTokenVault",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getTotalLocked",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getTotalProposals",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getVoteGas",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "voter",
+ "type": "address"
+ }
+ ],
+ "name": "getVoterLockTimestamp",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getVotingPowerForProposalCreation",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getVotingPowerForProposalExecution",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "voter",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "proposalId",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "action",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "votingPower",
+ "type": "uint256"
+ }
+ ],
+ "name": "hashVote",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "pure",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_token",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_proposalTime",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_timeForExecution",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_votingPowerForProposalExecution",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_votingPowerForProposalCreation",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "_name",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_voteGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_maxGasPrice",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_maxActiveProposals",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_lockTime",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "_permissionRegistry",
+ "type": "address"
+ }
+ ],
+ "name": "initialize",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "hash",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "name": "isValidSignature",
+ "outputs": [
+ {
+ "internalType": "bytes4",
+ "name": "magicValue",
+ "type": "bytes4"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenAmount",
+ "type": "uint256"
+ }
+ ],
+ "name": "lockTokens",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "owner",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "renounceOwnership",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "_proposalTime",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_timeForExecution",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_votingPowerForProposalExecution",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_votingPowerForProposalCreation",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_voteGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_maxGasPrice",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_maxActiveProposals",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_lockTime",
+ "type": "uint256"
+ }
+ ],
+ "name": "setConfig",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "_hash",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bool",
+ "name": "isValid",
+ "type": "bool"
+ }
+ ],
+ "name": "setEIP1271SignedHash",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "asset",
+ "type": "address[]"
+ },
+ {
+ "internalType": "address[]",
+ "name": "to",
+ "type": "address[]"
+ },
+ {
+ "internalType": "bytes4[]",
+ "name": "functionSignature",
+ "type": "bytes4[]"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "valueAllowed",
+ "type": "uint256[]"
+ },
+ {
+ "internalType": "bool[]",
+ "name": "allowance",
+ "type": "bool[]"
+ }
+ ],
+ "name": "setPermission",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "permissionDelay",
+ "type": "uint256"
+ }
+ ],
+ "name": "setPermissionDelay",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "proposalId",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "action",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "votingPower",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "voter",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "name": "setSignedVote",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32[]",
+ "name": "proposalIds",
+ "type": "bytes32[]"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "actions",
+ "type": "uint256[]"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "votingPowers",
+ "type": "uint256[]"
+ },
+ {
+ "internalType": "address[]",
+ "name": "voters",
+ "type": "address[]"
+ },
+ {
+ "internalType": "bytes[]",
+ "name": "signatures",
+ "type": "bytes[]"
+ }
+ ],
+ "name": "setSignedVotes",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "proposalId",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "action",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "votingPower",
+ "type": "uint256"
+ }
+ ],
+ "name": "setVote",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32[]",
+ "name": "proposalIds",
+ "type": "bytes32[]"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "actions",
+ "type": "uint256[]"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "votingPowers",
+ "type": "uint256[]"
+ }
+ ],
+ "name": "setVotes",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "newOwner",
+ "type": "address"
+ }
+ ],
+ "name": "transferOwnership",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "votingPowerOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "snapshotId",
+ "type": "uint256"
+ }
+ ],
+ "name": "votingPowerOfAt",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "accounts",
+ "type": "address[]"
+ }
+ ],
+ "name": "votingPowerOfMultiple",
+ "outputs": [
+ {
+ "internalType": "uint256[]",
+ "name": "",
+ "type": "uint256[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "accounts",
+ "type": "address[]"
+ },
+ {
+ "internalType": "uint256[]",
+ "name": "snapshotIds",
+ "type": "uint256[]"
+ }
+ ],
+ "name": "votingPowerOfMultipleAt",
+ "outputs": [
+ {
+ "internalType": "uint256[]",
+ "name": "",
+ "type": "uint256[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenAmount",
+ "type": "uint256"
+ }
+ ],
+ "name": "withdrawTokens",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "stateMutability": "payable",
+ "type": "receive"
+ }
+ ]
+}
diff --git a/src/hooks/Guilds/contracts/useContractInterface.ts b/src/hooks/Guilds/contracts/useContractInterface.ts
new file mode 100644
index 0000000000..3353e5d9b6
--- /dev/null
+++ b/src/hooks/Guilds/contracts/useContractInterface.ts
@@ -0,0 +1,9 @@
+import { utils } from 'ethers';
+
+const useContractInterface = (ABI: any) => {
+ let ERC20Contract = new utils.Interface(ABI);
+
+ return ERC20Contract;
+};
+
+export default useContractInterface;
diff --git a/src/hooks/Guilds/contracts/useDecodedCall.ts b/src/hooks/Guilds/contracts/useDecodedCall.ts
index 92a90ca805..db2809e765 100644
--- a/src/hooks/Guilds/contracts/useDecodedCall.ts
+++ b/src/hooks/Guilds/contracts/useDecodedCall.ts
@@ -117,6 +117,7 @@ const decodeCall = (
);
return {
+ id: `action-${Math.random()}`,
decodedCall,
contract: contractInterface,
};
@@ -143,5 +144,7 @@ export const useDecodedCall = (call: Call) => {
const { chainId } = useWeb3React();
const { contracts } = useContractRegistry();
- return decodeCall(call, contracts, chainId);
+ return call
+ ? decodeCall(call, contracts, chainId)
+ : { decodedCall: null, contract: null };
};
diff --git a/src/hooks/Guilds/ether-swr/erc20/useERC20Info.ts b/src/hooks/Guilds/ether-swr/erc20/useERC20Info.ts
index d5041fa784..428d5a50a9 100644
--- a/src/hooks/Guilds/ether-swr/erc20/useERC20Info.ts
+++ b/src/hooks/Guilds/ether-swr/erc20/useERC20Info.ts
@@ -1,11 +1,13 @@
import useEtherSWR from '../useEtherSWR';
import ERC20ABI from '../../../../abis/ERC20.json';
import { useMemo } from 'react';
+import { BigNumber } from 'ethers';
export type ERC20Info = {
name: string;
symbol: string;
decimals: number;
+ totalSupply: BigNumber;
};
export const useERC20Info = (contractAddress: string) => {
@@ -15,6 +17,7 @@ export const useERC20Info = (contractAddress: string) => {
[contractAddress, 'name'],
[contractAddress, 'symbol'],
[contractAddress, 'decimals'],
+ [contractAddress, 'totalSupply'],
]
: [],
{
@@ -29,6 +32,7 @@ export const useERC20Info = (contractAddress: string) => {
name: data[0],
symbol: data[1],
decimals: data[2],
+ totalSupply: data[3],
};
}, [data]);
diff --git a/src/hooks/Guilds/ether-swr/guild/useGuildConfig.ts b/src/hooks/Guilds/ether-swr/guild/useGuildConfig.ts
index 54034bc285..158e3bdc40 100644
--- a/src/hooks/Guilds/ether-swr/guild/useGuildConfig.ts
+++ b/src/hooks/Guilds/ether-swr/guild/useGuildConfig.ts
@@ -1,7 +1,10 @@
import { BigNumber } from 'ethers';
import { useMemo } from 'react';
+import { SWRResponse } from 'swr';
import ERC20GuildContract from 'contracts/ERC20Guild.json';
import useEtherSWR from '../useEtherSWR';
+import useTotalLocked from './useTotalLocked';
+import useGuildToken from './useGuildToken';
type GuildConfig = {
name: string;
@@ -17,11 +20,12 @@ type GuildConfig = {
totalLocked: BigNumber;
};
-export const useGuildConfig = (guildAddress: string) => {
+export const useGuildConfig = (
+ guildAddress: string
+): SWRResponse => {
const { data, error, isValidating, mutate } = useEtherSWR(
guildAddress
? [
- [guildAddress, 'getToken'], // Get the address of the ERC20Token used for voting
[guildAddress, 'getPermissionRegistry'], // Get the address of the permission registry contract
[guildAddress, 'getName'], // Get the name of the ERC20Guild
[guildAddress, 'getProposalTime'], // Get the proposalTime (seconds)
@@ -31,7 +35,6 @@ export const useGuildConfig = (guildAddress: string) => {
[guildAddress, 'getVotingPowerForProposalExecution'],
[guildAddress, 'getTokenVault'],
[guildAddress, 'getLockTime'],
- [guildAddress, 'getTotalLocked'],
]
: [],
{
@@ -39,13 +42,14 @@ export const useGuildConfig = (guildAddress: string) => {
refreshInterval: 0,
}
);
+ const { data: token } = useGuildToken(guildAddress);
+ const { data: totalLocked } = useTotalLocked(guildAddress);
// TODO: Move this into a SWR middleware
- const transformedData: GuildConfig = useMemo(() => {
+ const transformedData = useMemo(() => {
if (!data) return undefined;
const [
- token,
permissionRegistry,
name,
proposalTime,
@@ -55,11 +59,9 @@ export const useGuildConfig = (guildAddress: string) => {
votingPowerForProposalExecution,
tokenVault,
lockTime,
- totalLocked,
] = data;
return {
- token,
permissionRegistry,
name,
proposalTime: BigNumber.from(proposalTime),
@@ -73,7 +75,6 @@ export const useGuildConfig = (guildAddress: string) => {
),
tokenVault,
lockTime: BigNumber.from(lockTime),
- totalLocked: BigNumber.from(totalLocked),
};
}, [data]);
@@ -81,6 +82,8 @@ export const useGuildConfig = (guildAddress: string) => {
error,
isValidating,
mutate,
- data: transformedData,
+ data: transformedData
+ ? { ...transformedData, totalLocked, token }
+ : undefined,
};
};
diff --git a/src/hooks/Guilds/ether-swr/guild/useGuildToken.ts b/src/hooks/Guilds/ether-swr/guild/useGuildToken.ts
new file mode 100644
index 0000000000..fbc6617b1b
--- /dev/null
+++ b/src/hooks/Guilds/ether-swr/guild/useGuildToken.ts
@@ -0,0 +1,11 @@
+import useEtherSWR from '../useEtherSWR';
+import ERC20Guild from 'contracts/ERC20Guild.json';
+
+const useGuildToken = (guildAddress: string) => {
+ return useEtherSWR(guildAddress ? [guildAddress, 'getToken'] : [], {
+ ABIs: new Map([[guildAddress, ERC20Guild.abi]]),
+ refreshInterval: 0,
+ });
+};
+
+export default useGuildToken;
diff --git a/src/hooks/Guilds/ether-swr/guild/useSnapshotId.ts b/src/hooks/Guilds/ether-swr/guild/useSnapshotId.ts
new file mode 100644
index 0000000000..0b8f20e520
--- /dev/null
+++ b/src/hooks/Guilds/ether-swr/guild/useSnapshotId.ts
@@ -0,0 +1,24 @@
+import { BigNumber } from 'ethers';
+import { SWRResponse } from 'swr';
+import useEtherSWR from '../useEtherSWR';
+import SnapshotERC20Guild from 'contracts/SnapshotERC20Guild.json';
+
+interface UseSnapshotIdProps {
+ contractAddress: string;
+ proposalId: string;
+}
+
+type UseSnapshotIdHook = (args: UseSnapshotIdProps) => SWRResponse;
+
+const useSnapshotId: UseSnapshotIdHook = ({ contractAddress, proposalId }) => {
+ return useEtherSWR(
+ proposalId && contractAddress
+ ? [contractAddress, 'getProposalSnapshotId', proposalId]
+ : [],
+ {
+ ABIs: new Map([[contractAddress, SnapshotERC20Guild.abi]]),
+ }
+ );
+};
+
+export default useSnapshotId;
diff --git a/src/hooks/Guilds/ether-swr/guild/useTotalLocked.ts b/src/hooks/Guilds/ether-swr/guild/useTotalLocked.ts
new file mode 100644
index 0000000000..6f24e4d412
--- /dev/null
+++ b/src/hooks/Guilds/ether-swr/guild/useTotalLocked.ts
@@ -0,0 +1,51 @@
+import { useParams } from 'react-router-dom';
+import ERC20GuildContract from 'contracts/ERC20Guild.json';
+import useEtherSWR from '../useEtherSWR';
+import useTotalLockedAt from 'hooks/Guilds/ether-swr/guild/useTotalLockedAt';
+import useSnapshotId from 'hooks/Guilds/ether-swr/guild/useSnapshotId';
+import useGuildImplementationType from 'hooks/Guilds/guild/useGuildImplementationType';
+import useGuildToken from './useGuildToken';
+import useTotalSupplyAt from './useTotalSupplyAt';
+
+const useTotalLocked = (guildAddress: string, snapshotId?: string) => {
+ // Hooks call
+ const { proposal_id: proposalId } = useParams<{ proposal_id?: string }>();
+
+ const { data: _snapshotId } = useSnapshotId({
+ contractAddress: guildAddress,
+ proposalId,
+ });
+
+ const SNAPSHOT_ID = snapshotId ? snapshotId : _snapshotId?.toString();
+
+ const { isSnapshotGuild, isRepGuild, isSnapshotRepGuild } =
+ useGuildImplementationType(guildAddress);
+
+ const totalLockedResponse = useEtherSWR(
+ guildAddress ? [guildAddress, 'getTotalLocked'] : [],
+ {
+ ABIs: new Map([[guildAddress, ERC20GuildContract.abi]]),
+ refreshInterval: 0,
+ }
+ );
+
+ const totalLockedAtProposalSnapshotResponse = useTotalLockedAt({
+ contractAddress: guildAddress,
+ snapshotId: SNAPSHOT_ID,
+ });
+
+ const { data: guildTokenAddress } = useGuildToken(guildAddress);
+
+ const totalSupplyAtSnapshotResponse = useTotalSupplyAt({
+ contractAddress: guildTokenAddress,
+ snapshotId: SNAPSHOT_ID,
+ });
+
+ // Return response based on implementation type
+ if (isSnapshotGuild) return totalLockedAtProposalSnapshotResponse;
+ if (isSnapshotRepGuild) return totalSupplyAtSnapshotResponse;
+ if (isRepGuild) return totalLockedResponse;
+ return totalLockedResponse;
+};
+
+export default useTotalLocked;
diff --git a/src/hooks/Guilds/ether-swr/guild/useTotalLockedAt.ts b/src/hooks/Guilds/ether-swr/guild/useTotalLockedAt.ts
new file mode 100644
index 0000000000..4a732a1562
--- /dev/null
+++ b/src/hooks/Guilds/ether-swr/guild/useTotalLockedAt.ts
@@ -0,0 +1,32 @@
+import { BigNumber } from 'ethers';
+import { SWRResponse } from 'swr';
+import useEtherSWR from '../useEtherSWR';
+import SnapshotERC20Guild from 'contracts/SnapshotERC20Guild.json';
+
+interface UseTotalLockedAtProps {
+ contractAddress: string;
+ snapshotId: string;
+}
+
+type UseTotalLockedAtHook = (
+ args: UseTotalLockedAtProps
+) => SWRResponse;
+
+/**
+ * Get the total locked amount at snapshot
+ */
+const useTotalLockedAt: UseTotalLockedAtHook = ({
+ contractAddress,
+ snapshotId,
+}) => {
+ return useEtherSWR(
+ snapshotId && contractAddress
+ ? [contractAddress, 'totalLockedAt', snapshotId]
+ : [],
+ {
+ ABIs: new Map([[contractAddress, SnapshotERC20Guild.abi]]),
+ }
+ );
+};
+
+export default useTotalLockedAt;
diff --git a/src/hooks/Guilds/ether-swr/guild/useTotalSupplyAt.ts b/src/hooks/Guilds/ether-swr/guild/useTotalSupplyAt.ts
new file mode 100644
index 0000000000..2f1f913aa6
--- /dev/null
+++ b/src/hooks/Guilds/ether-swr/guild/useTotalSupplyAt.ts
@@ -0,0 +1,32 @@
+import { BigNumber } from 'ethers';
+import { SWRResponse } from 'swr';
+import useEtherSWR from '../useEtherSWR';
+import ERC20SnapshotRep from 'contracts/ERC20SnapshotRep.json';
+
+interface UseTotalSupplyAtProps {
+ contractAddress: string;
+ snapshotId: string;
+}
+
+type UseTotalSupplyAtHook = (
+ args: UseTotalSupplyAtProps
+) => SWRResponse;
+
+/**
+ * Get the total supply amount at snapshot
+ */
+const useTotalSupplyAt: UseTotalSupplyAtHook = ({
+ contractAddress, // tokenAddress,
+ snapshotId,
+}) => {
+ return useEtherSWR(
+ snapshotId && contractAddress
+ ? [contractAddress, 'totalSupplyAt', snapshotId]
+ : [],
+ {
+ ABIs: new Map([[contractAddress, ERC20SnapshotRep.abi]]),
+ }
+ );
+};
+
+export default useTotalSupplyAt;
diff --git a/src/hooks/Guilds/ether-swr/guild/useVotingPowerOfAt.ts b/src/hooks/Guilds/ether-swr/guild/useVotingPowerOfAt.ts
new file mode 100644
index 0000000000..bb979b1290
--- /dev/null
+++ b/src/hooks/Guilds/ether-swr/guild/useVotingPowerOfAt.ts
@@ -0,0 +1,31 @@
+import { BigNumber } from 'ethers';
+import { SWRResponse } from 'swr';
+import useEtherSWR from '../useEtherSWR';
+import SnapshotERC20Guild from 'contracts/SnapshotERC20Guild.json';
+
+interface useVotingPowerOfAtProps {
+ contractAddress: string;
+ userAddress: string;
+ snapshotId: string;
+}
+
+type useVotingPowerOfAtHook = (
+ args: useVotingPowerOfAtProps
+) => SWRResponse;
+
+/**
+ * Get the voting power of an account at snapshot id
+ */
+export const useVotingPowerOfAt: useVotingPowerOfAtHook = ({
+ contractAddress,
+ userAddress,
+ snapshotId,
+}) =>
+ useEtherSWR(
+ contractAddress && snapshotId && userAddress
+ ? [contractAddress, 'votingPowerOf', userAddress, snapshotId]
+ : [],
+ {
+ ABIs: new Map([[contractAddress, SnapshotERC20Guild.abi]]),
+ }
+ );
diff --git a/src/hooks/Guilds/guild/useGuildImplementationType.ts b/src/hooks/Guilds/guild/useGuildImplementationType.ts
index badd8406e4..4098514539 100644
--- a/src/hooks/Guilds/guild/useGuildImplementationType.ts
+++ b/src/hooks/Guilds/guild/useGuildImplementationType.ts
@@ -4,14 +4,47 @@ import useJsonRpcProvider from '../web3/useJsonRpcProvider';
import { GuildImplementationType } from '../../../types/types.guilds.d';
import deployedHashedBytecodes from '../../../bytecodes/config.json';
+const defaultImplementation = deployedHashedBytecodes.find(
+ ({ type }) => type === GuildImplementationType.IERC20Guild
+) ?? {
+ type: GuildImplementationType.IERC20Guild,
+ features: [],
+ bytecode_hash: '',
+};
+
+interface ImplementationTypeConfig {
+ type: string;
+ features: string[];
+ bytecode_hash: string;
+}
+
+interface ImplementationTypeConfigReturn extends ImplementationTypeConfig {
+ isRepGuild: boolean;
+ isSnapshotGuild: boolean;
+ isSnapshotRepGuild: boolean;
+}
+const parseConfig = (
+ config: ImplementationTypeConfig
+): ImplementationTypeConfigReturn => {
+ return {
+ ...config,
+ isRepGuild:
+ config.features.includes('REP') && !config.features.includes('SNAPSHOT'),
+ isSnapshotGuild:
+ config.features.includes('SNAPSHOT') && !config.features.includes('REP'),
+ isSnapshotRepGuild:
+ config.features.includes('SNAPSHOT') && config.features.includes('REP'),
+ };
+};
+
/**
* @function useGuildImplementationType
* @param {string} guildAddress
* @returns {string} GuildImplementationType. 'SnapshotRepERC20Guild' | 'DXDGuild' | 'ERC20Guild' | 'IERC20Guild'
*/
-export default function useGuildImplementationType(
+export default function useGuildImplementationTypeConfig(
guildAddress: string
-): GuildImplementationType {
+): ImplementationTypeConfigReturn {
const [guildBytecode, setGuildBytecode] = useState('');
const provider = useJsonRpcProvider();
@@ -23,15 +56,15 @@ export default function useGuildImplementationType(
getBytecode();
}, [guildAddress, provider]);
- const implementationType: GuildImplementationType = useMemo(() => {
- if (!guildBytecode) return GuildImplementationType.IERC20Guild;
+ const implementationTypeConfig: ImplementationTypeConfig = useMemo(() => {
+ if (!guildBytecode) return defaultImplementation;
const match = deployedHashedBytecodes.find(
({ bytecode_hash }) => guildBytecode === bytecode_hash
);
- return match ? match.type : GuildImplementationType.IERC20Guild; // default to IERC20Guild
- }, [guildBytecode]) as GuildImplementationType;
+ return match ? match : defaultImplementation; // default to IERC20Guild
+ }, [guildBytecode]);
- return implementationType;
+ return parseConfig(implementationTypeConfig);
}
diff --git a/src/hooks/Guilds/guild/useProposalCalls.ts b/src/hooks/Guilds/guild/useProposalCalls.ts
index 46b4441eed..768616f69c 100644
--- a/src/hooks/Guilds/guild/useProposalCalls.ts
+++ b/src/hooks/Guilds/guild/useProposalCalls.ts
@@ -1,3 +1,4 @@
+import { useTheme } from 'styled-components';
import { useWeb3React } from '@web3-react/core';
import { Call, Option } from 'components/Guilds/ActionsBuilder/types';
import { useMemo } from 'react';
@@ -12,6 +13,8 @@ const useProposalCalls = (guildId: string, proposalId: string) => {
const { contracts } = useContractRegistry();
const { chainId } = useWeb3React();
+ const theme = useTheme();
+
const options: Option[] = useMemo(() => {
if (!guildId || !proposalId || !proposal) return null;
@@ -40,15 +43,16 @@ const useProposalCalls = (guildId: string, proposalId: string) => {
}
const encodedOptions: Option[] = splitCalls.map((calls, index) => ({
- index,
+ id: `option-${index}`,
label: `Option ${index + 1}`,
+ color: theme?.colors?.votes?.[options.length],
actions: calls.filter(
call => call.data !== ZERO_HASH || !call.value?.isZero()
),
}));
return bulkDecodeCallsFromOptions(encodedOptions, contracts, chainId);
- }, [proposal, proposalId, guildId, chainId, contracts]);
+ }, [theme, proposal, proposalId, guildId, chainId, contracts]);
return {
options,
diff --git a/src/hooks/Guilds/guild/useTokenData.ts b/src/hooks/Guilds/guild/useTokenData.ts
new file mode 100644
index 0000000000..72d012edaf
--- /dev/null
+++ b/src/hooks/Guilds/guild/useTokenData.ts
@@ -0,0 +1,14 @@
+import { useParams } from 'react-router-dom';
+import { useGuildConfig } from '../ether-swr/guild/useGuildConfig';
+import { useERC20Info } from '../ether-swr/erc20/useERC20Info';
+
+export const useTokenData = () => {
+ const { guild_id: guildId } =
+ useParams<{ chain_name?: string; guild_id?: string }>();
+ const { data } = useGuildConfig(guildId);
+ const { data: tokenData } = useERC20Info(data?.token);
+
+ return {
+ tokenData,
+ };
+};
diff --git a/src/hooks/Guilds/guild/useTotalSupply.ts b/src/hooks/Guilds/guild/useTotalSupply.ts
new file mode 100644
index 0000000000..94af8143c6
--- /dev/null
+++ b/src/hooks/Guilds/guild/useTotalSupply.ts
@@ -0,0 +1,21 @@
+import { BigNumber } from 'ethers';
+import { useMemo } from 'react';
+
+interface REPMintState {
+ toAddress: string;
+ amount: BigNumber;
+}
+
+export const useTotalSupply = ({ decodedCall }) => {
+ const parsedData = useMemo(() => {
+ if (!decodedCall) return null;
+ return {
+ toAddress: decodedCall.args.to,
+ amount: decodedCall.args.amount,
+ };
+ }, [decodedCall]);
+
+ return {
+ parsedData,
+ };
+};
diff --git a/src/pages/Configuration.tsx b/src/pages/Configuration.tsx
index 468fc4a162..48f630a56f 100644
--- a/src/pages/Configuration.tsx
+++ b/src/pages/Configuration.tsx
@@ -110,6 +110,7 @@ const ConfigPage = observer(() => {
async function clearCache() {
localStorage.clear();
caches.delete(`dxvote-cache`);
+ window.location.reload();
}
return (
diff --git a/src/pages/ProposalSubmission/Custom.tsx b/src/pages/ProposalSubmission/Custom.tsx
index 58ad10e984..b8c456af1d 100644
--- a/src/pages/ProposalSubmission/Custom.tsx
+++ b/src/pages/ProposalSubmission/Custom.tsx
@@ -86,6 +86,7 @@ const NewProposalPage = observer(() => {
},
} = useContext();
+ const networkName = configStore.getActiveChainName();
const schemes = daoStore.getAllSchemes();
const networkContracts = configStore.getNetworkContracts();
const schemeInLocalStorage = localStorage.getItem(
@@ -720,7 +721,9 @@ const NewProposalPage = observer(() => {
active={submitionState}
/>
) : (
- Back to Proposals
+
+ Back to Proposals
+
)}
{submitionState > 1 ? (
diff --git a/src/pages/proposals/index.tsx b/src/pages/proposals/index.tsx
index 600aa11ab7..b801a05801 100644
--- a/src/pages/proposals/index.tsx
+++ b/src/pages/proposals/index.tsx
@@ -21,6 +21,7 @@ import {
formatNumberValue,
PendingAction,
isVoteNo,
+ VotingMachineProposalState,
} from '../../utils';
import {
FiFeather,
@@ -71,6 +72,12 @@ const ProposalsPage = observer(() => {
setSchemesFilter,
} = useFilteredProposals();
+ const allProposals = daoStore.getAllProposals();
+ const activeProposalsCount = allProposals.filter(
+ proposal =>
+ proposal.stateInVotingMachine > VotingMachineProposalState.Executed
+ ).length;
+
const history = useHistory();
return (
@@ -84,6 +91,12 @@ const ProposalsPage = observer(() => {
+
+ {allProposals.length} Total Proposals
+
+
+ {activeProposalsCount} Active Proposals
+
diff --git a/src/services/CacheService.ts b/src/services/CacheService.ts
index 61f15487e5..412437186e 100644
--- a/src/services/CacheService.ts
+++ b/src/services/CacheService.ts
@@ -1,5 +1,13 @@
import RootContext from '../contexts';
-import { getIPFSFile, NETWORK_NAMES } from '../utils';
+import {
+ batchPromisesOntarget,
+ getAppConfig,
+ getDefaultConfigHashes,
+ getIPFSFile,
+ getProposalTitles,
+ NETWORK_NAMES,
+ retryPromise,
+} from '../utils';
import Web3 from 'web3';
import _ from 'lodash';
import {
@@ -10,45 +18,22 @@ import {
decodePermission,
WalletSchemeProposalState,
VotingMachineProposalState,
- tryCacheUpdates,
isWalletScheme,
getEvents,
getRawEvents,
- sortEvents,
executeMulticall,
+ sortNetworkCache,
descriptionHashToIPFSHash,
ipfsHashToDescriptionHash,
getSchemeConfig,
} from '../utils';
-import WalletScheme1_0JSON from '../contracts/WalletScheme1_0.json';
-import WalletScheme1_1JSON from '../contracts/WalletScheme1_1.json';
-import ContributionRewardJSON from '../contracts/ContributionReward.json';
-import TokenVestingJSON from '../contracts/TokenVesting.json';
+
import { getContracts } from '../contracts';
+import { Contract } from 'ethers';
const Hash = require('ipfs-only-hash');
const jsonSort = require('json-keys-sort');
-const defaultConfigHashes = require('../configs/default.json');
-
-const arbitrum = require('../configs/arbitrum/config.json');
-const arbitrumTestnet = require('../configs/arbitrumTestnet/config.json');
-const mainnet = require('../configs/mainnet/config.json');
-const xdai = require('../configs/xdai/config.json');
-const rinkeby = require('../configs/rinkeby/config.json');
-const localhost = require('../configs/localhost/config.json');
-
-const proposalTitles = require('../configs/proposalTitles.json');
-
-const appConfig: AppConfig = {
- arbitrum,
- arbitrumTestnet,
- mainnet,
- xdai,
- rinkeby,
- localhost,
-};
-
export default class UtilsService {
context: RootContext;
@@ -56,6 +41,84 @@ export default class UtilsService {
this.context = context;
}
+ async getCacheFromIPFS(ipfsHash: string): Promise {
+ let jsonCache = await this.context.ipfsService.getContentFromIPFS(ipfsHash);
+
+ while (typeof jsonCache === 'string') {
+ console.log('Trying to get cache from ipfs again');
+ await sleep(100);
+ jsonCache = await this.context.ipfsService.getContentFromIPFS(ipfsHash);
+ }
+
+ return jsonCache;
+ }
+
+ async getUpdatedCacheConfig(
+ networksConfig: {
+ [netwokId: number]: {
+ toBlock: number;
+ rpcUrl: string;
+ reset: boolean;
+ };
+ },
+ updateProposalTitles: boolean
+ ): Promise<{
+ proposalTitles: {
+ [proposalId: string]: string;
+ };
+ configHashes: {
+ [networkName: string]: string;
+ };
+ configs: {
+ [networkName: string]: NetworkConfig;
+ };
+ caches: {
+ [networkName: string]: DaoNetworkCache;
+ };
+ }> {
+ const updatedCacheConfig = {
+ proposalTitles: getProposalTitles(),
+ configHashes: {},
+ configs: {},
+ caches: {},
+ };
+
+ // Update the cache and config for each network
+ for (let i = 0; i < Object.keys(networksConfig).length; i++) {
+ const networkId = Number(Object.keys(networksConfig)[i]);
+ const networkName = NETWORK_NAMES[networkId];
+
+ const cacheForNetwork = await this.buildCacheForNetwork(
+ new Web3(networksConfig[networkId].rpcUrl),
+ networkId,
+ networksConfig[networkId].toBlock,
+ networksConfig[networkId].reset
+ );
+
+ // Update the appConfig file that stores the hashes of the dapp config and network caches
+ updatedCacheConfig.configHashes[networkName] = cacheForNetwork.configHash;
+ updatedCacheConfig.configs[networkName] = cacheForNetwork.config;
+ updatedCacheConfig.caches[networkName] = cacheForNetwork.cache;
+
+ // Get proposal titles
+ if (updateProposalTitles) {
+ this.context.notificationStore.setGlobalLoading(
+ true,
+ `Getting proposal titles form ipfs`
+ );
+ updatedCacheConfig.proposalTitles = Object.assign(
+ updatedCacheConfig.proposalTitles,
+ await this.updateProposalTitles(
+ cacheForNetwork.cache,
+ getProposalTitles()
+ )
+ );
+ }
+ }
+
+ return updatedCacheConfig;
+ }
+
async buildCacheForNetwork(
web3: Web3,
chainId: number,
@@ -69,7 +132,7 @@ export default class UtilsService {
const networkName = NETWORK_NAMES[chainId];
// Get the network configuration
- let networkConfig = appConfig[networkName];
+ let networkConfig = getAppConfig()[networkName];
let networkCache: DaoNetworkCache;
const emptyCache: DaoNetworkCache = {
@@ -90,9 +153,12 @@ export default class UtilsService {
};
// Set network cache and config objects
+
+ // If network is localhost we use an empty cache to force the complete cache generation in each load
if (networkName === 'localhost') {
networkCache = emptyCache;
} else {
+ // If the cache is not reset, we load the cache from the local storage
if (resetCache) {
networkConfig.cache.toBlock = networkConfig.cache.fromBlock;
networkConfig.cache.ipfsHash = '';
@@ -100,54 +166,61 @@ export default class UtilsService {
emptyCache.blockNumber = networkConfig.cache.fromBlock;
networkCache = emptyCache;
} else {
+ this.context.notificationStore.setGlobalLoading(
+ true,
+ `Getting configuration file from IPFS`
+ );
console.log(
- `Getting config file from https://ipfs.io/ipfs/${defaultConfigHashes[networkName]}`
+ `Getting config file from https://ipfs.io/ipfs/${
+ getDefaultConfigHashes()[networkName]
+ }`
);
const networkConfigFileFetch = await getIPFSFile(
- defaultConfigHashes[networkName],
+ getDefaultConfigHashes()[networkName],
5000
);
+ this.context.notificationStore.setGlobalLoading(
+ true,
+ `Getting cache file from IPFS`
+ );
console.log(
`Getting cache file from https://ipfs.io/ipfs/${networkConfigFileFetch.data.cache.ipfsHash}`
);
- const networkCacheFetch = await getIPFSFile(
- networkConfigFileFetch.data.cache.ipfsHash,
- 60000
+ const networkCacheFetch = await retryPromise(
+ getIPFSFile(networkConfigFileFetch.data.cache.ipfsHash, 60000)
);
networkCache = networkCacheFetch.data;
}
}
- // Set block range for the script to run, if cache to block is set that value is used, if not we use last block
- const fromBlock = networkCache.blockNumber;
-
- if (Number(fromBlock) < toBlock) {
+ // Update the cache only if the toBlock is higher than the current networkCache block
+ if (Number(networkCache.blockNumber) + 1 < toBlock) {
// The cache file is updated with the data that had before plus new data in the network cache file
console.debug(
'Running cache script from block',
- fromBlock,
+ networkCache.blockNumber + 1,
'to block',
toBlock,
'in network',
networkName
);
networkCache = await this.getUpdatedCache(
- this.context,
networkCache,
networkConfig.contracts,
- fromBlock,
toBlock,
web3
);
}
- // Write network cache file
+ // Sort json obj and parse it to string
networkCache = await jsonSort.sortAsync(networkCache, true);
const networkCacheString = JSON.stringify(networkCache, null, 2);
- // Update appConfig file with the latest network config
+ // Update appConfig obj with the latest network config and networkCache hash
networkConfig.cache.toBlock = toBlock;
networkConfig.cache.ipfsHash = await Hash.of(networkCacheString);
+
+ // Sort config obj and parse it to string
networkConfig = await jsonSort.sortAsync(networkConfig, true);
return {
@@ -157,119 +230,44 @@ export default class UtilsService {
};
}
- async getUpdatedCacheConfig(
- networksConfig: {
- [netwokId: number]: {
- toBlock: number;
- rpcUrl: string;
- reset: boolean;
- };
- },
- updateProposalTitles: boolean
- ): Promise<{
- proposalTitles: {
- [proposalId: string]: string;
- };
- configHashes: {
- [networkName: string]: string;
- };
- configs: {
- [networkName: string]: NetworkConfig;
- };
- caches: {
- [networkName: string]: DaoNetworkCache;
- };
- }> {
- const updatedCacheConfig = {
- proposalTitles: proposalTitles,
- configHashes: {},
- configs: {},
- caches: {},
- };
- // Update the cache and config for each network
- for (let i = 0; i < Object.keys(networksConfig).length; i++) {
- const networkId = Number(Object.keys(networksConfig)[i]);
- const networkName = NETWORK_NAMES[networkId];
-
- const cacheForNetwork = await this.buildCacheForNetwork(
- new Web3(networksConfig[networkId].rpcUrl),
- networkId,
- networksConfig[networkId].toBlock,
- networksConfig[networkId].reset
- );
-
- // Update the appConfig file that stores the hashes of the dapp config and network caches
- updatedCacheConfig.configHashes[networkName] = cacheForNetwork.configHash;
- updatedCacheConfig.configs[networkName] = cacheForNetwork.config;
- updatedCacheConfig.caches[networkName] = cacheForNetwork.cache;
-
- // Get proposal titles
- if (updateProposalTitles) {
- this.context.notificationStore.setGlobalLoading(
- true,
- `Getting proposal titles form ipfs`
- );
- updatedCacheConfig.proposalTitles = Object.assign(
- updatedCacheConfig.proposalTitles,
- await this.getProposalTitlesFromIPFS(
- cacheForNetwork.cache,
- proposalTitles
- )
- );
- }
- }
-
- return updatedCacheConfig;
- }
-
async getUpdatedCache(
- context: RootContext,
networkCache: DaoNetworkCache,
- networkContractsConfig: NetworkContracts,
- fromBlock: number,
+ networkContracts: NetworkContracts,
toBlock: number,
- web3: any
+ web3: Web3
): Promise {
- const notificationStore = context.notificationStore;
+ const fromBlock = networkCache.blockNumber + 1;
+ const networkWeb3Contracts = await getContracts(networkContracts, web3);
console.debug(`[CACHE UPDATE] from ${fromBlock} to ${toBlock}`);
- const networkWeb3Contracts = await getContracts(
- networkContractsConfig,
- web3
- );
- notificationStore.setGlobalLoading(
+ this.context.notificationStore.setGlobalLoading(
true,
`Collecting reputation and governance events in blocks ${fromBlock} - ${toBlock}`
);
- networkCache = await tryCacheUpdates(
+ // The first promise round:
+ // - Reputation Events
+ // - Permission Registry
+ // - Vesting Contracts
+
+ networkCache = await batchPromisesOntarget(
[
this.updateReputationEvents(
networkCache,
networkWeb3Contracts.reputation,
- fromBlock,
- toBlock,
- web3
- ),
- this.updateVotingMachineEvents(
- networkCache,
- networkContractsConfig,
- fromBlock,
toBlock,
web3
),
this.updatePermissionRegistry(
networkCache,
- networkContractsConfig,
- fromBlock,
+ networkContracts,
toBlock,
web3
),
this.updateVestingContracts(
networkCache,
- networkContractsConfig,
- fromBlock,
+ networkContracts,
toBlock,
web3
),
@@ -277,71 +275,64 @@ export default class UtilsService {
networkCache
);
- notificationStore.setGlobalLoading(
- true,
- `Updating scheme data in blocks ${fromBlock} - ${toBlock}`
- );
-
- networkCache = await tryCacheUpdates(
+ // The second promise round:
+ // - Voting Machine Events
+ // - Update schemes
+ networkCache = await batchPromisesOntarget(
[
- this.updateSchemes(
+ this.updateVotingMachineEvents(
networkCache,
- networkContractsConfig,
- fromBlock,
+ networkContracts,
toBlock,
web3
),
+ this.updateSchemes(networkCache, networkContracts, toBlock, web3),
],
- networkCache
+ networkCache,
+ 0,
+ 1000
);
- notificationStore.setGlobalLoading(
+ this.context.notificationStore.setGlobalLoading(
true,
`Collecting proposals in blocks ${fromBlock} - ${toBlock}`
);
- networkCache = await tryCacheUpdates(
- [
- this.updateProposals(
- networkCache,
- networkContractsConfig,
- fromBlock,
- toBlock,
- web3
- ),
- ],
- networkCache
+ // The third promise round is just to update the proposals that needs the schemes udpated.
+ networkCache = await batchPromisesOntarget(
+ [this.updateProposals(networkCache, networkContracts, toBlock, web3)],
+ networkCache,
+ 0,
+ 1000,
+ 500
);
networkCache.blockNumber = Number(toBlock);
console.log('Total Proposals', Object.keys(networkCache.proposals).length);
- // Compare proposals data
- // Object.keys(networkCache.proposals).map((proposalId) => {
- // const mutableData = getProposalMutableData(networkCache, proposalId);
- // const cacheData = networkCache.proposals[proposalId];
- // console.debug(proposalId, mutableData, cacheData);
- // })
-
- return networkCache;
+ return sortNetworkCache(networkCache);
}
- // Get all Mint and Burn reputation events to calculate rep by time off chain
+ // Get all Mint and Burn reputation events
async updateReputationEvents(
networkCache: DaoNetworkCache,
- reputation: any,
- fromBlock: number,
+ reputation: Contract,
toBlock: number,
- web3: any
+ web3: Web3
): Promise {
if (!networkCache.reputation.events) networkCache.reputation.events = [];
-
- let reputationEvents = sortEvents(
- await getEvents(web3, reputation, fromBlock, toBlock, 'allEvents')
+ const fromBlock = networkCache.blockNumber + 1;
+
+ let reputationEvents = await getEvents(
+ web3,
+ reputation,
+ fromBlock,
+ toBlock,
+ 'allEvents'
);
- reputationEvents.map(reputationEvent => {
+ reputationEvents.forEach(reputationEvent => {
switch (reputationEvent.event) {
case 'Mint':
networkCache.reputation.events.push({
@@ -382,15 +373,11 @@ export default class UtilsService {
// Update all voting machines
async updateVotingMachineEvents(
networkCache: DaoNetworkCache,
- networkContractsConfig: NetworkContracts,
- fromBlock: number,
+ networkContracts: NetworkContracts,
toBlock: number,
- web3: any
+ web3: Web3
): Promise {
- const networkWeb3Contracts = await getContracts(
- networkContractsConfig,
- web3
- );
+ const networkWeb3Contracts = await getContracts(networkContracts, web3);
await Promise.all(
Object.keys(networkWeb3Contracts.votingMachines).map(
@@ -418,9 +405,8 @@ export default class UtilsService {
networkCache = await this.updateVotingMachine(
networkCache,
- networkContractsConfig,
+ networkContracts,
votingMachine,
- fromBlock,
toBlock,
web3
);
@@ -430,24 +416,28 @@ export default class UtilsService {
return networkCache;
}
- // Update all voting machine information, events, token and voting parameters used.
+
+ // Update a voting machine information, events, token and voting parameters used.
async updateVotingMachine(
networkCache: DaoNetworkCache,
- networkContractsConfig: NetworkContracts,
- votingMachine: any,
- fromBlock: number,
+ networkContracts: NetworkContracts,
+ votingMachine: Contract,
toBlock: number,
- web3: any
+ web3: Web3
): Promise {
- let newVotingMachineEvents = sortEvents(
- await getEvents(web3, votingMachine, fromBlock, toBlock, 'allEvents')
- );
- const avatarAddress = web3.utils.toChecksumAddress(
- networkContractsConfig.avatar
+ const fromBlock = networkCache.blockNumber + 1;
+
+ let newVotingMachineEvents = await getEvents(
+ web3,
+ votingMachine,
+ fromBlock,
+ toBlock,
+ 'allEvents'
);
+ const avatarAddress = web3.utils.toChecksumAddress(networkContracts.avatar);
const votingMachineEventsInCache =
networkCache.votingMachines[votingMachine._address].events;
- newVotingMachineEvents.map(votingMachineEvent => {
+ newVotingMachineEvents.forEach(votingMachineEvent => {
const proposalCreated =
votingMachineEventsInCache.newProposal.findIndex(
newProposalEvent =>
@@ -626,27 +616,23 @@ export default class UtilsService {
// Gets all the events form the permission registry and stores the permissions set.
async updatePermissionRegistry(
networkCache: DaoNetworkCache,
- networkContractsConfig: NetworkContracts,
- fromBlock: number,
+ networkContracts: NetworkContracts,
toBlock: number,
- web3: any
+ web3: Web3
): Promise {
- const networkWeb3Contracts = await getContracts(
- networkContractsConfig,
- web3
- );
+ const networkWeb3Contracts = await getContracts(networkContracts, web3);
+ const fromBlock = networkCache.blockNumber + 1;
+
if (networkWeb3Contracts.permissionRegistry._address !== ZERO_ADDRESS) {
- let permissionRegistryEvents = sortEvents(
- await getEvents(
- web3,
- networkWeb3Contracts.permissionRegistry,
- fromBlock,
- toBlock,
- 'allEvents'
- )
+ let permissionRegistryEvents = await getEvents(
+ web3,
+ networkWeb3Contracts.permissionRegistry,
+ fromBlock,
+ toBlock,
+ 'allEvents'
);
- permissionRegistryEvents.map(permissionRegistryEvent => {
+ permissionRegistryEvents.forEach(permissionRegistryEvent => {
const eventValues = permissionRegistryEvent.returnValues;
if (!networkCache.callPermissions[eventValues.asset])
@@ -684,25 +670,21 @@ export default class UtilsService {
async updateVestingContracts(
networkCache: DaoNetworkCache,
- networkContractsConfig: NetworkContracts,
- fromBlock: number,
+ networkContracts: NetworkContracts,
toBlock: number,
- web3: any
+ web3: Web3
): Promise {
- const networkWeb3Contracts = await getContracts(
- networkContractsConfig,
- web3
- );
+ const networkWeb3Contracts = await getContracts(networkContracts, web3);
+ const fromBlock = networkCache.blockNumber + 1;
+
if (networkWeb3Contracts.vestingFactory) {
try {
- const vestingFactoryEvents = sortEvents(
- await getEvents(
- web3,
- networkWeb3Contracts.vestingFactory,
- fromBlock,
- toBlock,
- 'allEvents'
- )
+ const vestingFactoryEvents = await getEvents(
+ web3,
+ networkWeb3Contracts.vestingFactory,
+ fromBlock,
+ toBlock,
+ 'allEvents'
);
console.debug(
@@ -711,35 +693,65 @@ export default class UtilsService {
);
for (let event of vestingFactoryEvents) {
- const tokenVestingContract = await new web3.eth.Contract(
- TokenVestingJSON.abi,
- event.returnValues.vestingContractAddress
- );
const callsToExecute = [
- [tokenVestingContract, 'beneficiary', []],
- [tokenVestingContract, 'cliff', []],
- [tokenVestingContract, 'duration', []],
- [tokenVestingContract, 'owner', []],
- [tokenVestingContract, 'start', []],
- [tokenVestingContract, 'isOwner', []],
- [tokenVestingContract, 'revocable', []],
+ [
+ event.returnValues.vestingContractAddress,
+ 'beneficiary()',
+ [],
+ ['address'],
+ ],
+ [
+ event.returnValues.vestingContractAddress,
+ 'cliff()',
+ [],
+ ['uint256'],
+ ],
+ [
+ event.returnValues.vestingContractAddress,
+ 'duration()',
+ [],
+ ['uint256'],
+ ],
+ [
+ event.returnValues.vestingContractAddress,
+ 'owner()',
+ [],
+ ['address'],
+ ],
+ [
+ event.returnValues.vestingContractAddress,
+ 'start()',
+ [],
+ ['uint256'],
+ ],
+ [
+ event.returnValues.vestingContractAddress,
+ 'isOwner()',
+ [],
+ ['bool'],
+ ],
+ [
+ event.returnValues.vestingContractAddress,
+ 'revocable()',
+ [],
+ ['bool'],
+ ],
];
const callsResponse = await executeMulticall(
- web3,
networkWeb3Contracts.multicall,
callsToExecute
);
const tokenContractInfo = {
address: event.returnValues.vestingContractAddress,
- beneficiary: callsResponse.decodedReturnData[0],
- cliff: callsResponse.decodedReturnData[1],
- duration: callsResponse.decodedReturnData[2],
- owner: callsResponse.decodedReturnData[3],
- start: callsResponse.decodedReturnData[4],
- isOwner: callsResponse.decodedReturnData[5],
- revocable: callsResponse.decodedReturnData[6],
+ beneficiary: callsResponse.decodedReturnData[0][0],
+ cliff: callsResponse.decodedReturnData[1][0],
+ duration: callsResponse.decodedReturnData[2][0],
+ owner: callsResponse.decodedReturnData[3][0],
+ start: callsResponse.decodedReturnData[4][0],
+ isOwner: callsResponse.decodedReturnData[5][0],
+ revocable: callsResponse.decodedReturnData[6][0],
};
networkCache.vestingContracts = [
@@ -758,1241 +770,117 @@ export default class UtilsService {
// Update all the schemes information
async updateSchemes(
networkCache: DaoNetworkCache,
- networkContractsConfig: NetworkContracts,
- fromBlock: number,
+ networkContracts: NetworkContracts,
toBlock: number,
- web3: any
+ web3: Web3
): Promise {
- const networkWeb3Contracts = await getContracts(
- networkContractsConfig,
- web3
- );
+ const networkWeb3Contracts = await getContracts(networkContracts, web3);
+ const fromBlock = networkCache.blockNumber + 1;
// Get all the events from the Controller
- let controllerEvents = sortEvents(
- await getEvents(
- web3,
- networkWeb3Contracts.controller,
- fromBlock,
- toBlock,
- 'allEvents'
- )
+ let controllerEvents = await getEvents(
+ web3,
+ networkWeb3Contracts.controller,
+ fromBlock,
+ toBlock,
+ 'allEvents'
);
- // Go over all controller events and add update or remove schemes depending on the event
- for (
- let controllerEventsIndex = 0;
- controllerEventsIndex < controllerEvents.length;
- controllerEventsIndex++
- ) {
- const controllerEvent = controllerEvents[controllerEventsIndex];
-
- const schemeAddress = controllerEvent.returnValues._scheme;
- // Add or update the scheme information,
- // register scheme is used to add a scheme or update the parametersHash of an existent one
- if (controllerEvent.event === 'RegisterScheme') {
- const schemeTypeData = getSchemeConfig(
- networkContractsConfig,
- schemeAddress
- );
+ // Process all the schemes that changed their registered state based on the events
+ await batchPromisesOntarget(
+ controllerEvents
+ .filter(controllerEvent => {
+ return (
+ (controllerEvent.event === 'UnregisterScheme' ||
+ controllerEvent.event === 'RegisterScheme') &&
+ controllerEvent.returnValues._sender !==
+ controllerEvent.returnValues._scheme
+ );
+ })
+ .map(controllerEvent => {
+ return this.processScheme(
+ controllerEvent.returnValues._scheme,
+ networkCache,
+ networkContracts,
+ web3,
+ toBlock,
+ controllerEvent.event === 'UnregisterScheme'
+ );
+ }),
+ networkCache,
+ 5
+ );
- console.debug(
- 'Register Scheme event for ',
- schemeAddress,
- schemeTypeData
- );
-
- let controllerAddress = networkWeb3Contracts.controller._address;
- let schemeName = schemeTypeData.name;
- let maxSecondsForExecution = bnum(0);
- let maxRepPercentageChange = bnum(0);
- let schemeType = schemeTypeData.type;
-
- let callsToExecute = [
- [
- networkWeb3Contracts.controller,
- 'getSchemePermissions',
- [schemeAddress, networkWeb3Contracts.avatar._address],
- ],
- [
- networkWeb3Contracts.controller,
- 'getSchemeParameters',
- [schemeAddress, networkWeb3Contracts.avatar._address],
- ],
- ];
-
- if (schemeType === 'WalletScheme') {
- const walletSchemeContract = await new web3.eth.Contract(
- WalletScheme1_0JSON.abi,
- schemeAddress
- );
- const walletSchemeType = await walletSchemeContract.methods
- .SCHEME_TYPE()
- .call();
-
- schemeType = walletSchemeType;
- if (schemeType == 'Wallet Scheme v1')
- schemeType = 'Wallet Scheme v1.0';
-
- switch (schemeType) {
- case 'Wallet Scheme v1.1':
- const walletSchemeContract1_1 = await new web3.eth.Contract(
- WalletScheme1_1JSON.abi,
- schemeAddress
- );
- callsToExecute.push([
- walletSchemeContract1_1,
- 'votingMachine',
- [],
- ]);
- callsToExecute.push([
- walletSchemeContract1_1,
- 'doAvatarGenericCalls',
- [],
- ]);
- callsToExecute.push([walletSchemeContract1_1, 'schemeName', []]);
- callsToExecute.push([
- walletSchemeContract1_1,
- 'maxSecondsForExecution',
- [],
- ]);
- callsToExecute.push([
- walletSchemeContract1_1,
- 'maxRepPercentageChange',
- [],
- ]);
- break;
- default:
- callsToExecute.push([walletSchemeContract, 'votingMachine', []]);
- callsToExecute.push([
- walletSchemeContract,
- 'controllerAddress',
- [],
- ]);
- callsToExecute.push([walletSchemeContract, 'schemeName', []]);
- callsToExecute.push([
- walletSchemeContract,
- 'maxSecondsForExecution',
- [],
- ]);
- callsToExecute.push([
- walletSchemeContract,
- 'maxRepPercentageChange',
- [],
- ]);
- break;
- }
- }
-
- const callsResponse1 = await executeMulticall(
- web3,
- networkWeb3Contracts.multicall,
- callsToExecute
- );
- callsToExecute = [];
-
- const permissions = decodePermission(
- callsResponse1.decodedReturnData[0]
- );
- const paramsHash =
- schemeTypeData.voteParams || callsResponse1.decodedReturnData[1];
-
- const votingMachineAddress =
- schemeTypeData.votingMachine || callsResponse1.decodedReturnData[2];
-
- const votingMachine =
- networkWeb3Contracts.votingMachines[votingMachineAddress].contract;
-
- if (schemeTypeData.type === 'WalletScheme') {
- switch (schemeType) {
- case 'Wallet Scheme v1.1':
- controllerAddress = callsResponse1.decodedReturnData[3]
- ? networkWeb3Contracts.controller._address
- : ZERO_ADDRESS;
- break;
- default:
- controllerAddress = callsResponse1.decodedReturnData[3];
- break;
- }
- schemeName = callsResponse1.decodedReturnData[4];
- maxSecondsForExecution = callsResponse1.decodedReturnData[5];
- maxRepPercentageChange = callsResponse1.decodedReturnData[6];
- }
-
- // Register the new voting parameters in the voting machine params
- const votingParameters = await votingMachine.methods
- .parameters(paramsHash)
- .call();
- networkCache.votingMachines[votingMachine._address].votingParameters[
- paramsHash
- ] = {
- queuedVoteRequiredPercentage:
- votingParameters.queuedVoteRequiredPercentage,
- queuedVotePeriodLimit: votingParameters.queuedVotePeriodLimit,
- boostedVotePeriodLimit: votingParameters.boostedVotePeriodLimit,
- preBoostedVotePeriodLimit: votingParameters.preBoostedVotePeriodLimit,
- thresholdConst: votingParameters.thresholdConst,
- limitExponentValue: votingParameters.limitExponentValue,
- quietEndingPeriod: votingParameters.quietEndingPeriod,
- proposingRepReward: votingParameters.proposingRepReward,
- votersReputationLossRatio: votingParameters.votersReputationLossRatio,
- minimumDaoBounty: votingParameters.minimumDaoBounty,
- daoBountyConst: votingParameters.daoBountyConst,
- activationTime: votingParameters.activationTime,
- };
-
- // If the scheme not exist, register it
- if (!networkCache.schemes[schemeAddress]) {
- networkCache.schemes[schemeAddress] = {
- address: schemeAddress,
- registered: true,
- controllerAddress,
- name: schemeName,
- type: schemeType,
- votingMachine: votingMachineAddress,
- paramsHash: paramsHash,
- permissions,
- boostedVoteRequiredPercentage: 0,
- proposalIds: [],
- boostedProposals: 0,
- maxSecondsForExecution,
- maxRepPercentageChange,
- newProposalEvents: [],
- };
- } else {
- networkCache.schemes[schemeAddress].paramsHash = paramsHash;
- networkCache.schemes[schemeAddress].permissions = permissions;
- }
-
- // Mark scheme as not registered but save all previous data
- } else if (
- controllerEvent.event === 'UnregisterScheme' &&
- // This condition is added to skip the first scheme added (that is the dao creator account)
- controllerEvent.returnValues._sender !== schemeAddress
- ) {
- const schemeTypeData = getSchemeConfig(
- networkContractsConfig,
- schemeAddress
- );
- const votingMachine =
- networkWeb3Contracts.votingMachines[
- networkCache.schemes[schemeAddress].votingMachine
- ].contract;
-
- console.debug('Unregister scheme event', schemeAddress, schemeTypeData);
- let callsToExecute = [
- [
- votingMachine,
- 'orgBoostedProposalsCnt',
- [
- web3.utils.soliditySha3(
- schemeAddress,
- networkWeb3Contracts.avatar._address
- ),
- ],
- ],
- ];
-
- if (isWalletScheme(networkCache.schemes[schemeAddress])) {
- callsToExecute.push([
- await new web3.eth.Contract(WalletScheme1_0JSON.abi, schemeAddress),
- 'maxSecondsForExecution',
- [],
- ]);
- }
- const callsResponse = await executeMulticall(
- web3,
- networkWeb3Contracts.multicall,
- callsToExecute
- );
-
- const maxSecondsForExecution = isWalletScheme(
- networkCache.schemes[schemeAddress]
- )
- ? callsResponse.decodedReturnData[2]
- : 0;
-
- // Update the scheme values a last time
- networkCache.schemes[schemeAddress].boostedProposals =
- callsResponse.decodedReturnData[0];
- networkCache.schemes[schemeAddress].maxSecondsForExecution =
- maxSecondsForExecution;
- networkCache.schemes[schemeAddress].registered = false;
- }
- }
- // Update registered schemes
- await Promise.all(
- Object.keys(networkCache.schemes).map(async schemeAddress => {
- if (networkCache.schemes[schemeAddress].registered) {
- const votingMachine =
- networkWeb3Contracts.votingMachines[
- networkCache.schemes[schemeAddress].votingMachine
- ].contract;
-
- let callsToExecute = [
- [
- votingMachine,
- 'orgBoostedProposalsCnt',
- [
- web3.utils.soliditySha3(
- schemeAddress,
- networkWeb3Contracts.avatar._address
- ),
- ],
- ],
- ];
-
- if (isWalletScheme(networkCache.schemes[schemeAddress])) {
- callsToExecute.push([
- await new web3.eth.Contract(
- WalletScheme1_0JSON.abi,
- schemeAddress
- ),
- 'maxSecondsForExecution',
- [],
- ]);
- callsToExecute.push([
- votingMachine,
- 'boostedVoteRequiredPercentage',
- [
- web3.utils.soliditySha3(
- schemeAddress,
- networkWeb3Contracts.avatar._address
- ),
- networkCache.schemes[schemeAddress].paramsHash,
- ],
- ]);
- }
- const callsResponse = await executeMulticall(
- web3,
- networkWeb3Contracts.multicall,
- callsToExecute
- );
-
- const maxSecondsForExecution = isWalletScheme(
- networkCache.schemes[schemeAddress]
- )
- ? callsResponse.decodedReturnData[1]
- : 0;
-
- const boostedVoteRequiredPercentage = isWalletScheme(
- networkCache.schemes[schemeAddress]
- )
- ? web3.eth.abi.decodeParameters(
- ['uint256'],
- callsResponse.returnData[2]
- )['0']
- : 0;
-
- networkCache.schemes[schemeAddress].boostedProposals =
- callsResponse.decodedReturnData[0];
- networkCache.schemes[schemeAddress].maxSecondsForExecution =
- maxSecondsForExecution;
- networkCache.schemes[schemeAddress].boostedVoteRequiredPercentage =
- boostedVoteRequiredPercentage;
- }
- })
- );
+ // Process all the registered schemes
+ await batchPromisesOntarget(
+ Object.keys(networkCache.schemes)
+ .filter(schemeAddress => {
+ return networkCache.schemes[schemeAddress].registered;
+ })
+ .map(schemeAddress => {
+ return this.processScheme(
+ schemeAddress,
+ networkCache,
+ networkContracts,
+ web3,
+ toBlock
+ );
+ }),
+ networkCache,
+ 5
+ );
return networkCache;
}
- // Update all the proposals information
+ // Update the proposals information
async updateProposals(
networkCache: DaoNetworkCache,
- networkContractsConfig: NetworkContracts,
- fromBlock: number,
+ networkContracts: NetworkContracts,
toBlock: number,
- web3: any
+ web3: Web3
): Promise {
- const networkWeb3Contracts = await getContracts(
- networkContractsConfig,
- web3
- );
- const avatarAddress = networkWeb3Contracts.avatar._address;
- const avatarAddressEncoded = web3.eth.abi.encodeParameter(
- 'address',
- avatarAddress
- );
-
- // Get new proposals
- await Promise.all(
- Object.keys(networkCache.schemes).map(async schemeAddress => {
- const schemeTypeData = getSchemeConfig(
- networkContractsConfig,
- schemeAddress
- );
- const votingMachine =
- networkWeb3Contracts.votingMachines[
- networkCache.schemes[schemeAddress].votingMachine
- ].contract;
-
- let schemeEvents = [];
- for (let i = 0; i < schemeTypeData.newProposalTopics.length; i++) {
- schemeEvents = schemeEvents.concat(
- await getRawEvents(
- web3,
- schemeAddress,
- fromBlock,
- toBlock,
- schemeTypeData.newProposalTopics[i]
- )
- );
- }
-
- let schemeEventsBatchs = [];
- let schemeEventsBatchsIndex = 0;
- for (var i = 0; i < schemeEvents.length; i += 50)
- schemeEventsBatchs.push(schemeEvents.slice(i, i + 50));
-
- while (schemeEventsBatchsIndex < schemeEventsBatchs.length) {
- try {
- console.debug(
- `Getting proposals of scheme ${schemeTypeData.name}: ${schemeAddress}, batch: ${schemeEventsBatchsIndex}`
- );
- await Promise.all(
- schemeEventsBatchs[schemeEventsBatchsIndex].map(
- async schemeEvent => {
- const proposalId =
- schemeEvent.topics[1] === avatarAddressEncoded
- ? web3.eth.abi.decodeParameter(
- 'bytes32',
- schemeEvent.topics[2]
- )
- : web3.eth.abi.decodeParameter(
- 'bytes32',
- schemeEvent.topics[1]
- );
- // Get all the proposal information from the scheme and voting machine
- let callsToExecute = [
- [votingMachine, 'proposals', [proposalId]],
- [votingMachine, 'voteStatus', [proposalId, 1]],
- [votingMachine, 'voteStatus', [proposalId, 2]],
- [votingMachine, 'proposalStatus', [proposalId]],
- [votingMachine, 'getProposalTimes', [proposalId]],
- ];
-
- if (schemeTypeData.type === 'WalletScheme') {
- callsToExecute.push([
- await new web3.eth.Contract(
- WalletScheme1_0JSON.abi,
- schemeAddress
- ),
- 'getOrganizationProposal',
- [proposalId],
- ]);
- } else if (schemeTypeData.type === 'ContributionReward') {
- callsToExecute.push([
- await new web3.eth.Contract(
- ContributionRewardJSON.abi,
- schemeAddress
- ),
- 'getRedeemedPeriods',
- [proposalId, networkWeb3Contracts.avatar._address, 0],
- ]);
- callsToExecute.push([
- await new web3.eth.Contract(
- ContributionRewardJSON.abi,
- schemeAddress
- ),
- 'getRedeemedPeriods',
- [proposalId, networkWeb3Contracts.avatar._address, 1],
- ]);
- callsToExecute.push([
- await new web3.eth.Contract(
- ContributionRewardJSON.abi,
- schemeAddress
- ),
- 'getRedeemedPeriods',
- [proposalId, networkWeb3Contracts.avatar._address, 2],
- ]);
- callsToExecute.push([
- await new web3.eth.Contract(
- ContributionRewardJSON.abi,
- schemeAddress
- ),
- 'getRedeemedPeriods',
- [proposalId, networkWeb3Contracts.avatar._address, 3],
- ]);
- }
-
- const callsResponse = await executeMulticall(
- web3,
- networkWeb3Contracts.multicall,
- callsToExecute
- );
-
- const votingMachineProposalInfo =
- web3.eth.abi.decodeParameters(
- [
- { type: 'bytes32', name: 'organizationId' },
- { type: 'address', name: 'callbacks' },
- { type: 'uint256', name: 'state' },
- { type: 'uint256', name: 'winningVote' },
- { type: 'address', name: 'proposer' },
- {
- type: 'uint256',
- name: 'currentBoostedVotePeriodLimit',
- },
- { type: 'bytes32', name: 'paramsHash' },
- { type: 'uint256', name: 'daoBountyRemain' },
- { type: 'uint256', name: 'daoBounty' },
- { type: 'uint256', name: 'totalStakes' },
- { type: 'uint256', name: 'confidenceThreshold' },
- {
- type: 'uint256',
- name: 'secondsFromTimeOutTillExecuteBoosted',
- },
- ],
- callsResponse.returnData[0]
- );
- const positiveVotes = callsResponse.returnData[1];
- const negativeVotes = callsResponse.returnData[2];
-
- const proposalStatusWithVotes = web3.eth.abi.decodeParameters(
- ['uint256', 'uint256', 'uint256', 'uint256'],
- callsResponse.returnData[3]
- );
- const proposalTimes = callsResponse.decodedReturnData[4];
-
- let schemeProposalInfo = {
- to: [],
- callData: [],
- value: [],
- state: WalletSchemeProposalState.Submitted,
- title: '',
- descriptionHash: '',
- submittedTime: 0,
- };
- let decodedProposer;
- let creationLogDecoded;
-
- if (schemeTypeData.type === 'WalletScheme') {
- schemeProposalInfo = web3.eth.abi.decodeParameters(
- [
- { type: 'address[]', name: 'to' },
- { type: 'bytes[]', name: 'callData' },
- { type: 'uint256[]', name: 'value' },
- { type: 'uint256', name: 'state' },
- { type: 'string', name: 'title' },
- { type: 'string', name: 'descriptionHash' },
- { type: 'uint256', name: 'submittedTime' },
- ],
- callsResponse.returnData[5]
- );
- } else {
- if (schemeTypeData.type === 'GenericMulticall') {
- const executionEvent = await web3.eth.getPastLogs({
- fromBlock: schemeEvent.blockNumber,
- address: schemeAddress,
- topics: [
- '0x253ad9614c337848bbe7dc3b18b439d139ef5787282b5a517ba7296513d1f533',
- avatarAddressEncoded,
- proposalId,
- ],
- });
- if (executionEvent.length > 0)
- schemeProposalInfo.state =
- WalletSchemeProposalState.ExecutionSucceded;
- else
- schemeProposalInfo.state =
- WalletSchemeProposalState.Submitted;
- } else if (schemeTypeData.type === 'ContributionReward') {
- if (
- callsResponse.decodedReturnData[5] > 0 ||
- callsResponse.decodedReturnData[6] > 0 ||
- callsResponse.decodedReturnData[7] > 0 ||
- callsResponse.decodedReturnData[8] > 0
- ) {
- schemeProposalInfo.state =
- WalletSchemeProposalState.ExecutionSucceded;
- } else if (
- votingMachineProposalInfo.state === '1' ||
- votingMachineProposalInfo.state === '2'
- ) {
- schemeProposalInfo.state =
- WalletSchemeProposalState.Rejected;
- } else {
- schemeProposalInfo.state =
- WalletSchemeProposalState.Submitted;
- }
- }
-
- const transactionReceipt =
- await web3.eth.getTransactionReceipt(
- schemeEvent.transactionHash
- );
- try {
- schemeTypeData.newProposalTopics.map(
- (newProposalTopic, i) => {
- transactionReceipt.logs.map(log => {
- if (
- log.topics[0] ===
- '0x75b4ff136cc5de5957574c797de3334eb1c141271922b825eb071e0487ba2c5c'
- ) {
- decodedProposer = web3.eth.abi.decodeParameters(
- [
- { type: 'uint256', name: '_numOfChoices' },
- { type: 'address', name: '_proposer' },
- { type: 'bytes32', name: '_paramsHash' },
- ],
- log.data
- )._proposer;
- }
- if (
- !creationLogDecoded &&
- log.topics[0] === newProposalTopic[0]
- ) {
- creationLogDecoded =
- web3.eth.abi.decodeParameters(
- schemeTypeData.creationLogEncoding[i],
- log.data
- );
- if (
- creationLogDecoded._descriptionHash.length >
- 0 &&
- creationLogDecoded._descriptionHash !==
- ZERO_HASH
- ) {
- schemeProposalInfo.descriptionHash =
- ipfsHashToDescriptionHash(
- creationLogDecoded._descriptionHash
- );
- }
- }
- });
- }
- );
- } catch (error) {
- console.error(
- 'Error in getting proposal data from creation event',
- error
- );
- }
-
- if (schemeTypeData.type === 'SchemeRegistrar') {
- schemeProposalInfo.to = [schemeTypeData.contractToCall];
- schemeProposalInfo.value = [0];
-
- if (creationLogDecoded._parametersHash) {
- schemeProposalInfo.callData = [
- web3.eth.abi.encodeFunctionCall(
- {
- name: 'registerScheme',
- type: 'function',
- inputs: [
- { type: 'address', name: '_scheme' },
- { type: 'bytes32', name: '_paramsHash' },
- { type: 'bytes4', name: '_permissions' },
- { type: 'address', name: '_avatar' },
- ],
- },
- [
- creationLogDecoded['_scheme '],
- creationLogDecoded._parametersHash,
- creationLogDecoded._permissions,
- avatarAddress,
- ]
- ),
- ];
- } else {
- schemeProposalInfo.callData = [
- web3.eth.abi.encodeFunctionCall(
- {
- name: 'unregisterScheme',
- type: 'function',
- inputs: [
- { type: 'address', name: '_scheme' },
- { type: 'address', name: '_avatar' },
- ],
- },
- [creationLogDecoded['_scheme '], avatarAddress]
- ),
- ];
- }
- } else if (schemeTypeData.type === 'ContributionReward') {
- if (creationLogDecoded._reputationChange > 0) {
- schemeProposalInfo.to.push(
- schemeTypeData.contractToCall
- );
- schemeProposalInfo.value.push(0);
- schemeProposalInfo.callData.push(
- web3.eth.abi.encodeFunctionCall(
- {
- name: 'mintReputation',
- type: 'function',
- inputs: [
- { type: 'uint256', name: '_amount' },
- { type: 'address', name: '_to' },
- { type: 'address', name: '_avatar' },
- ],
- },
- [
- creationLogDecoded._reputationChange,
- creationLogDecoded._beneficiary,
- avatarAddress,
- ]
- )
- );
- } else if (creationLogDecoded._reputationChange < 0) {
- schemeProposalInfo.to.push(
- schemeTypeData.contractToCall
- );
- schemeProposalInfo.value.push(0);
-
- // Remove the negative sign in the number
- if (creationLogDecoded._reputationChange[0] == '-')
- creationLogDecoded._reputationChange =
- creationLogDecoded._reputationChange.substring(1);
-
- schemeProposalInfo.callData.push(
- web3.eth.abi.encodeFunctionCall(
- {
- name: 'burnReputation',
- type: 'function',
- inputs: [
- { type: 'uint256', name: '_amount' },
- { type: 'address', name: '_from' },
- { type: 'address', name: '_avatar' },
- ],
- },
- [
- creationLogDecoded._reputationChange,
- creationLogDecoded._beneficiary,
- avatarAddress,
- ]
- )
- );
- }
-
- if (creationLogDecoded._rewards[0] > 0) {
- schemeProposalInfo.to.push(
- schemeTypeData.contractToCall
- );
- schemeProposalInfo.value.push(0);
- schemeProposalInfo.callData.push(
- web3.eth.abi.encodeFunctionCall(
- {
- name: 'mintTokens',
- type: 'function',
- inputs: [
- { type: 'uint256', name: '_amount' },
- { type: 'address', name: '_beneficiary' },
- { type: 'address', name: '_avatar' },
- ],
- },
- [
- creationLogDecoded._rewards[0],
- creationLogDecoded._beneficiary,
- avatarAddress,
- ]
- )
- );
- }
-
- if (creationLogDecoded._rewards[1] > 0) {
- schemeProposalInfo.to.push(
- schemeTypeData.contractToCall
- );
- schemeProposalInfo.value.push(0);
- schemeProposalInfo.callData.push(
- web3.eth.abi.encodeFunctionCall(
- {
- name: 'sendEther',
- type: 'function',
- inputs: [
- { type: 'uint256', name: '_amountInWei' },
- { type: 'address', name: '_to' },
- { type: 'address', name: '_avatar' },
- ],
- },
- [
- creationLogDecoded._rewards[1],
- creationLogDecoded._beneficiary,
- avatarAddress,
- ]
- )
- );
- }
-
- if (creationLogDecoded._rewards[2] > 0) {
- schemeProposalInfo.to.push(
- schemeTypeData.contractToCall
- );
- schemeProposalInfo.value.push(0);
- schemeProposalInfo.callData.push(
- web3.eth.abi.encodeFunctionCall(
- {
- name: 'externalTokenTransfer',
- type: 'function',
- inputs: [
- { type: 'address', name: '_externalToken' },
- { type: 'address', name: '_to' },
- { type: 'uint256', name: '_value' },
- { type: 'address', name: '_avatar' },
- ],
- },
- [
- creationLogDecoded._externalToken,
- creationLogDecoded._beneficiary,
- creationLogDecoded._rewards[2],
- avatarAddress,
- ]
- )
- );
- }
- } else if (schemeTypeData.type === 'GenericScheme') {
- schemeProposalInfo.to = [
- networkWeb3Contracts.controller._address,
- ];
- schemeProposalInfo.value = [0];
- schemeProposalInfo.callData = [
- web3.eth.abi.encodeFunctionCall(
- {
- name: 'genericCall',
- type: 'function',
- inputs: [
- { type: 'address', name: '_contract' },
- { type: 'bytes', name: '_data' },
- { type: 'address', name: '_avatar' },
- { type: 'uint256', name: '_value' },
- ],
- },
- [
- schemeTypeData.contractToCall,
- creationLogDecoded._data,
- avatarAddress,
- creationLogDecoded._value,
- ]
- ),
- ];
- } else if (schemeTypeData.type === 'GenericMulticall') {
- for (
- let callIndex = 0;
- callIndex < creationLogDecoded._contractsToCall.length;
- callIndex++
- ) {
- schemeProposalInfo.to.push(
- networkWeb3Contracts.controller._address
- );
- schemeProposalInfo.value.push(0);
- schemeProposalInfo.callData.push(
- web3.eth.abi.encodeFunctionCall(
- {
- name: 'genericCall',
- type: 'function',
- inputs: [
- { type: 'address', name: '_contract' },
- { type: 'bytes', name: '_data' },
- { type: 'address', name: '_avatar' },
- { type: 'uint256', name: '_value' },
- ],
- },
- [
- creationLogDecoded._contractsToCall[callIndex],
- creationLogDecoded._callsData[callIndex],
- avatarAddress,
- creationLogDecoded._values[callIndex],
- ]
- )
- );
- }
- }
- }
-
- // Register the new voting parameters in the voting machine params
- if (
- !networkCache.votingMachines[votingMachine._address]
- .votingParameters[votingMachineProposalInfo.paramsHash]
- ) {
- const votingParameters = await votingMachine.methods
- .parameters(votingMachineProposalInfo.paramsHash)
- .call();
- networkCache.votingMachines[
- votingMachine._address
- ].votingParameters[votingMachineProposalInfo.paramsHash] = {
- queuedVoteRequiredPercentage:
- votingParameters.queuedVoteRequiredPercentage,
- queuedVotePeriodLimit:
- votingParameters.queuedVotePeriodLimit,
- boostedVotePeriodLimit:
- votingParameters.boostedVotePeriodLimit,
- preBoostedVotePeriodLimit:
- votingParameters.preBoostedVotePeriodLimit,
- thresholdConst: votingParameters.thresholdConst,
- limitExponentValue: votingParameters.limitExponentValue,
- quietEndingPeriod: votingParameters.quietEndingPeriod,
- proposingRepReward: votingParameters.proposingRepReward,
- votersReputationLossRatio:
- votingParameters.votersReputationLossRatio,
- minimumDaoBounty: votingParameters.minimumDaoBounty,
- daoBountyConst: votingParameters.daoBountyConst,
- activationTime: votingParameters.activationTime,
- };
- }
-
- networkCache.proposals[proposalId] = {
- id: proposalId,
- scheme: schemeAddress,
- to: schemeProposalInfo.to,
- title: schemeProposalInfo.title || '',
- callData: schemeProposalInfo.callData,
- values: schemeProposalInfo.value.map(value => bnum(value)),
- stateInScheme: Number(schemeProposalInfo.state),
- stateInVotingMachine: Number(
- votingMachineProposalInfo.state
- ),
- descriptionHash: schemeProposalInfo.descriptionHash,
- creationEvent: {
- event: schemeEvent.event,
- signature: schemeEvent.signature,
- address: schemeEvent.address,
- tx: schemeEvent.transactionHash,
- blockNumber: schemeEvent.blockNumber,
- timestamp: schemeEvent.timestamp,
- transactionIndex: schemeEvent.transactionIndex,
- logIndex: schemeEvent.logIndex,
- },
- winningVote: votingMachineProposalInfo.winningVote,
- proposer: decodedProposer
- ? decodedProposer
- : votingMachineProposalInfo.proposer,
- currentBoostedVotePeriodLimit:
- votingMachineProposalInfo.currentBoostedVotePeriodLimit,
- paramsHash: votingMachineProposalInfo.paramsHash,
- daoBountyRemain: bnum(
- votingMachineProposalInfo.daoBountyRemain
- ),
- daoBounty: bnum(votingMachineProposalInfo.daoBounty),
- confidenceThreshold:
- votingMachineProposalInfo.confidenceThreshold,
- secondsFromTimeOutTillExecuteBoosted:
- votingMachineProposalInfo.secondsFromTimeOutTillExecuteBoosted,
- submittedTime: bnum(proposalTimes[0]),
- boostedPhaseTime: bnum(proposalTimes[1]),
- preBoostedPhaseTime: bnum(proposalTimes[2]),
- daoRedeemItsWinnings:
- votingMachineProposalInfo.daoRedeemItsWinnings,
- shouldBoost: false,
- positiveVotes: bnum(positiveVotes),
- negativeVotes: bnum(negativeVotes),
- positiveStakes: bnum(proposalStatusWithVotes[2]),
- negativeStakes: bnum(proposalStatusWithVotes[3]),
- };
-
- networkCache.schemes[schemeAddress].proposalIds.push(
- proposalId
- );
- networkCache.schemes[schemeAddress].newProposalEvents.push({
- proposalId: proposalId,
- event: schemeEvent.event,
- signature: schemeEvent.signature,
- address: schemeEvent.address,
- tx: schemeEvent.transactionHash,
- blockNumber: schemeEvent.blockNumber,
- timestamp: schemeEvent.timestamp,
- transactionIndex: schemeEvent.transactionIndex,
- logIndex: schemeEvent.logIndex,
- });
-
- if (schemeProposalInfo.descriptionHash.length > 1) {
- networkCache.ipfsHashes.push({
- hash: descriptionHashToIPFSHash(
- schemeProposalInfo.descriptionHash
- ),
- type: 'proposal',
- name: proposalId,
- });
- }
- }
- )
- );
-
- schemeEventsBatchsIndex++;
- } catch (error) {
- console.error(
- 'Error in getting proposal info of schemeEventsBatchs index',
- schemeEventsBatchsIndex,
- error
- );
- }
- }
- })
- );
+ const fromBlock = networkCache.blockNumber + 1;
// Update existent active proposals
- // @ts-ignore
- const activeProposals = [];
- Object.keys(networkCache.proposals).map(proposalId => {
- if (
- networkCache.proposals[proposalId].stateInVotingMachine >
- VotingMachineProposalState.Executed ||
- networkCache.proposals[proposalId].stateInScheme ===
- WalletSchemeProposalState.Submitted
- )
- activeProposals.push(networkCache.proposals[proposalId]);
- });
-
- let activeProposalsBatch = [];
- let activeProposalsBatchIndex = 0;
- for (var i = 0; i < activeProposals.length; i += 5)
- activeProposalsBatch.push(activeProposals.slice(i, i + 5));
-
- while (activeProposalsBatchIndex < activeProposalsBatch.length) {
- await Promise.all(
- activeProposalsBatch[activeProposalsBatchIndex].map(async proposal => {
- let retry = true;
- while (retry) {
- try {
- const schemeAddress = networkCache.proposals[proposal.id].scheme;
- const schemeTypeData = getSchemeConfig(
- networkContractsConfig,
- schemeAddress
- );
- const votingMachine =
- networkWeb3Contracts.votingMachines[
- networkCache.schemes[schemeAddress].votingMachine
- ].contract;
-
- // Get all the proposal information from the scheme and voting machine
- let callsToExecute = [
- [votingMachine, 'proposals', [proposal.id]],
- [votingMachine, 'voteStatus', [proposal.id, 1]],
- [votingMachine, 'voteStatus', [proposal.id, 2]],
- [votingMachine, 'proposalStatus', [proposal.id]],
- [votingMachine, 'getProposalTimes', [proposal.id]],
- [votingMachine, 'shouldBoost', [proposal.id]],
- ];
-
- if (schemeTypeData.type === 'WalletScheme') {
- callsToExecute.push([
- await new web3.eth.Contract(
- WalletScheme1_0JSON.abi,
- schemeAddress
- ),
- 'getOrganizationProposal',
- [proposal.id],
- ]);
- } else if (
- schemeTypeData.type === 'ContributionReward' &&
- networkCache.proposals[proposal.id].stateInVotingMachine ===
- VotingMachineProposalState.Executed &&
- networkCache.proposals[proposal.id].stateInScheme ===
- WalletSchemeProposalState.Submitted
- ) {
- callsToExecute.push([
- await new web3.eth.Contract(
- ContributionRewardJSON.abi,
- schemeAddress
- ),
- 'getRedeemedPeriods',
- [proposal.id, networkWeb3Contracts.avatar._address, 0],
- ]);
- callsToExecute.push([
- await new web3.eth.Contract(
- ContributionRewardJSON.abi,
- schemeAddress
- ),
- 'getRedeemedPeriods',
- [proposal.id, networkWeb3Contracts.avatar._address, 1],
- ]);
- callsToExecute.push([
- await new web3.eth.Contract(
- ContributionRewardJSON.abi,
- schemeAddress
- ),
- 'getRedeemedPeriods',
- [proposal.id, networkWeb3Contracts.avatar._address, 2],
- ]);
- callsToExecute.push([
- await new web3.eth.Contract(
- ContributionRewardJSON.abi,
- schemeAddress
- ),
- 'getRedeemedPeriods',
- [proposal.id, networkWeb3Contracts.avatar._address, 3],
- ]);
- }
-
- const callsResponse = await executeMulticall(
- web3,
- networkWeb3Contracts.multicall,
- callsToExecute
- );
-
- const votingMachineProposalInfo = web3.eth.abi.decodeParameters(
- [
- { type: 'bytes32', name: 'organizationId' },
- { type: 'address', name: 'callbacks' },
- { type: 'uint256', name: 'state' },
- { type: 'uint256', name: 'winningVote' },
- { type: 'address', name: 'proposer' },
- { type: 'uint256', name: 'currentBoostedVotePeriodLimit' },
- { type: 'bytes32', name: 'paramsHash' },
- { type: 'uint256', name: 'daoBountyRemain' },
- { type: 'uint256', name: 'daoBounty' },
- { type: 'uint256', name: 'totalStakes' },
- { type: 'uint256', name: 'confidenceThreshold' },
- {
- type: 'uint256',
- name: 'secondsFromTimeOutTillExecuteBoosted',
- },
- ],
- callsResponse.returnData[0]
- );
- const positiveVotes = callsResponse.returnData[1];
- const negativeVotes = callsResponse.returnData[2];
-
- const proposalStatusWithVotes = web3.eth.abi.decodeParameters(
- ['uint256', 'uint256', 'uint256', 'uint256'],
- callsResponse.returnData[3]
- );
- const proposalTimes = callsResponse.decodedReturnData[4];
- const proposalShouldBoost = callsResponse.decodedReturnData[5];
-
- if (schemeTypeData.type === 'WalletScheme') {
- networkCache.proposals[proposal.id].stateInScheme = Number(
- web3.eth.abi.decodeParameters(
- [
- { type: 'address[]', name: 'to' },
- { type: 'bytes[]', name: 'callData' },
- { type: 'uint256[]', name: 'value' },
- { type: 'uint256', name: 'state' },
- { type: 'string', name: 'title' },
- { type: 'string', name: 'descriptionHash' },
- { type: 'uint256', name: 'submittedTime' },
- ],
- callsResponse.returnData[6]
- ).state
- );
- } else if (
- schemeTypeData.type === 'ContributionReward' &&
- networkCache.proposals[proposal.id].stateInVotingMachine ===
- VotingMachineProposalState.Executed &&
- networkCache.proposals[proposal.id].stateInScheme ===
- WalletSchemeProposalState.Submitted
- ) {
- if (schemeTypeData.type === 'ContributionReward') {
- if (
- callsResponse.decodedReturnData[6] > 0 ||
- callsResponse.decodedReturnData[7] > 0 ||
- callsResponse.decodedReturnData[8] > 0 ||
- callsResponse.decodedReturnData[9] > 0
- ) {
- networkCache.proposals[proposal.id].stateInScheme =
- WalletSchemeProposalState.ExecutionSucceded;
- } else if (
- votingMachineProposalInfo.state === '1' ||
- votingMachineProposalInfo.state === '2'
- ) {
- networkCache.proposals[proposal.id].stateInScheme =
- WalletSchemeProposalState.Rejected;
- }
- }
- } else if (schemeTypeData.type === 'GenericMulticall') {
- const executionEvent = await web3.eth.getPastLogs({
- fromBlock:
- networkCache.proposals[proposal.id].creationEvent
- .blockNumber,
- address: schemeAddress,
- topics: [
- '0x6bc0cb9e9967b59a69ace442598e1df4368d38661bd5c0800fbcbc9fe855fbbe',
- avatarAddressEncoded,
- proposal.id,
- ],
- });
- if (executionEvent.length > 0)
- networkCache.proposals[proposal.id].stateInScheme =
- WalletSchemeProposalState.ExecutionSucceded;
- else
- networkCache.proposals[proposal.id].stateInScheme =
- WalletSchemeProposalState.Submitted;
- } else if (
- networkCache.proposals[proposal.id].stateInVotingMachine ===
- VotingMachineProposalState.Executed
- ) {
- networkCache.proposals[proposal.id].stateInScheme =
- WalletSchemeProposalState.ExecutionSucceded;
- }
-
- networkCache.proposals[proposal.id].stateInVotingMachine = Number(
- votingMachineProposalInfo.state
- );
- networkCache.proposals[proposal.id].winningVote =
- votingMachineProposalInfo.winningVote;
- networkCache.proposals[
- proposal.id
- ].currentBoostedVotePeriodLimit =
- votingMachineProposalInfo.currentBoostedVotePeriodLimit;
- networkCache.proposals[proposal.id].daoBountyRemain = bnum(
- votingMachineProposalInfo.daoBountyRemain
- );
- networkCache.proposals[proposal.id].daoBounty = bnum(
- votingMachineProposalInfo.daoBounty
- );
- networkCache.proposals[proposal.id].confidenceThreshold =
- votingMachineProposalInfo.confidenceThreshold;
- networkCache.proposals[
- proposal.id
- ].secondsFromTimeOutTillExecuteBoosted =
- votingMachineProposalInfo.secondsFromTimeOutTillExecuteBoosted;
- networkCache.proposals[proposal.id].boostedPhaseTime = bnum(
- proposalTimes[1]
- );
- networkCache.proposals[proposal.id].preBoostedPhaseTime = bnum(
- proposalTimes[2]
- );
- networkCache.proposals[proposal.id].daoRedeemItsWinnings =
- votingMachineProposalInfo.daoRedeemItsWinnings;
- networkCache.proposals[proposal.id].shouldBoost =
- proposalShouldBoost;
- networkCache.proposals[proposal.id].positiveVotes =
- bnum(positiveVotes);
- networkCache.proposals[proposal.id].negativeVotes =
- bnum(negativeVotes);
- networkCache.proposals[proposal.id].positiveStakes = bnum(
- proposalStatusWithVotes[2]
- );
- networkCache.proposals[proposal.id].negativeStakes = bnum(
- proposalStatusWithVotes[3]
- );
-
- retry = false;
- } catch (e) {
- console.error(
- 'Error on updating proposal (trying again)',
- proposal
- );
- console.error(e);
- retry = true;
- }
- }
+ await batchPromisesOntarget(
+ Object.keys(networkCache.proposals)
+ .filter(proposalId => {
+ const proposal = networkCache.proposals[proposalId];
+ const scheme = networkCache.schemes[proposal.scheme];
+ return (
+ // Only update proposals for registered schemes
+ scheme.registered &&
+ // This condition check that the proposal already existed in the current block range.
+ // If not, it means that the proposal was created in the current block range when processing the scheme,
+ // So there is no need to process it again.
+ proposal.creationEvent.blockNumber < fromBlock &&
+ // This condition check that the proposal is active
+ (proposal.stateInVotingMachine >
+ VotingMachineProposalState.Executed ||
+ proposal.stateInScheme === WalletSchemeProposalState.Submitted)
+ );
})
- );
-
- activeProposalsBatchIndex++;
- }
-
- // Sort cache data, so the IPFS hash is consistent
- Object.keys(networkCache.schemes).forEach(schemeId => {
- networkCache.schemes[schemeId].proposalIds.sort();
- networkCache.schemes[schemeId].newProposalEvents.sort((a, b) =>
- a.proposalId.localeCompare(b.proposalId)
- );
- });
- networkCache.proposals = Object.keys(networkCache.proposals)
- .sort()
- .reduce((obj, key) => {
- obj[key] = networkCache.proposals[key];
- return obj;
- }, {});
- networkCache.ipfsHashes = _.uniqBy(networkCache.ipfsHashes, 'name');
- networkCache.ipfsHashes.sort((a, b) => a.name.localeCompare(b.name));
+ .map(proposalId => {
+ return this.processProposal(
+ proposalId,
+ networkCache,
+ networkContracts,
+ web3,
+ fromBlock,
+ toBlock
+ );
+ }),
+ networkCache,
+ 5,
+ 1000,
+ 500
+ );
return networkCache;
}
- async getProposalTitlesFromIPFS(
+ async updateProposalTitles(
networkCache: DaoNetworkCache,
proposalTitles: Record
) {
@@ -2073,4 +961,968 @@ export default class UtilsService {
return proposalTitles;
}
+
+ // Process a scheme in the networkCache
+ // If the scheme does not exist in the cache it gets the immutable + mutable data
+ // The scheme already exists it gets the mutable data only
+ // At the end it process all the new proposals added in the scheme to the toBlock
+ async processScheme(
+ schemeAddress: string,
+ networkCache: DaoNetworkCache,
+ networkContracts: NetworkContracts,
+ web3: Web3,
+ toBlock: number,
+ removeScheme: boolean = false
+ ): Promise {
+ const networkWeb3Contracts = await getContracts(networkContracts, web3);
+ const isNewScheme = !networkCache.schemes[schemeAddress];
+ const schemeTypeData = getSchemeConfig(networkContracts, schemeAddress);
+ console.debug(
+ 'Processing Scheme',
+ schemeAddress,
+ schemeTypeData,
+ removeScheme
+ );
+
+ let controllerAddress = networkWeb3Contracts.controller._address;
+ let schemeName = schemeTypeData.name;
+ let maxSecondsForExecution = 0;
+ let maxRepPercentageChange = 0;
+ let schemeType = schemeTypeData.type;
+ const isWalletScheme = schemeType === 'WalletScheme';
+
+ let callsToExecute = [
+ [
+ controllerAddress,
+ 'getSchemePermissions(address,address)',
+ [schemeAddress, networkWeb3Contracts.avatar._address],
+ ['bytes4'],
+ ],
+ [
+ controllerAddress,
+ 'getSchemeParameters(address,address)',
+ [schemeAddress, networkWeb3Contracts.avatar._address],
+ ['bytes32'],
+ ],
+ ];
+
+ if (isWalletScheme) {
+ callsToExecute.push([
+ schemeAddress,
+ 'maxSecondsForExecution()',
+ [],
+ ['uint256'],
+ ]);
+ callsToExecute.push([
+ schemeAddress,
+ 'maxRepPercentageChange()',
+ [],
+ ['uint256'],
+ ]);
+
+ if (isNewScheme) {
+ schemeType = (
+ await executeMulticall(networkWeb3Contracts.multicall, [
+ [schemeAddress, 'SCHEME_TYPE()', [], ['string']],
+ ])
+ ).decodedReturnData[0][0];
+ if (schemeType === 'Wallet Scheme v1')
+ schemeType = 'Wallet Scheme v1.0';
+
+ callsToExecute.push([
+ schemeAddress,
+ 'votingMachine()',
+ [],
+ ['address'],
+ ]);
+ callsToExecute.push([schemeAddress, 'schemeName()', [], ['string']]);
+
+ switch (schemeType) {
+ case 'Wallet Scheme v1.0':
+ callsToExecute.push([
+ schemeAddress,
+ 'controllerAddress()',
+ [],
+ ['address'],
+ ]);
+ break;
+ default:
+ callsToExecute.push([
+ schemeAddress,
+ 'doAvatarGenericCalls()',
+ [],
+ ['bool'],
+ ]);
+ break;
+ }
+ }
+ }
+
+ const callsResponse1 = await executeMulticall(
+ networkWeb3Contracts.multicall,
+ callsToExecute
+ );
+
+ const permissions = decodePermission(
+ callsResponse1.decodedReturnData[0][0]
+ );
+ const paramsHash =
+ schemeTypeData.voteParams || callsResponse1.decodedReturnData[1][0];
+
+ const votingMachineAddress = !isNewScheme
+ ? networkCache.schemes[schemeAddress].votingMachine
+ : isWalletScheme
+ ? callsResponse1.decodedReturnData[4][0]
+ : schemeTypeData.votingMachine;
+
+ if (isWalletScheme) {
+ maxSecondsForExecution = callsResponse1.decodedReturnData[2][0];
+ maxRepPercentageChange = callsResponse1.decodedReturnData[3][0];
+
+ if (isNewScheme) {
+ schemeName = callsResponse1.decodedReturnData[5][0];
+
+ switch (schemeType) {
+ case 'Wallet Scheme v1.0':
+ controllerAddress = callsResponse1.decodedReturnData[6][0];
+ break;
+ default:
+ controllerAddress = callsResponse1.decodedReturnData[6][0]
+ ? networkWeb3Contracts.controller._address
+ : ZERO_ADDRESS;
+ break;
+ }
+ }
+ }
+
+ callsToExecute = [
+ [
+ votingMachineAddress,
+ 'orgBoostedProposalsCnt(bytes32)',
+ [
+ web3.utils.soliditySha3(
+ schemeAddress,
+ networkWeb3Contracts.avatar._address
+ ),
+ ],
+ ['uint256'],
+ ],
+ ];
+
+ // Register the new voting parameters in the voting machine params
+ if (
+ !networkCache.votingMachines[votingMachineAddress].votingParameters[
+ paramsHash
+ ]
+ ) {
+ callsToExecute.push([
+ votingMachineAddress,
+ 'parameters(bytes32)',
+ [paramsHash],
+ [
+ 'uint256',
+ 'uint256',
+ 'uint256',
+ 'uint256',
+ 'uint256',
+ 'uint256',
+ 'uint256',
+ 'uint256',
+ 'uint256',
+ 'uint256',
+ 'uint256',
+ 'uint256',
+ 'address',
+ ],
+ ]);
+ }
+
+ if (isWalletScheme) {
+ callsToExecute.push([
+ votingMachineAddress,
+ 'boostedVoteRequiredPercentage(bytes32,bytes32)',
+ [
+ web3.utils.soliditySha3(
+ schemeAddress,
+ networkWeb3Contracts.avatar._address
+ ),
+ paramsHash,
+ ],
+ ['uint256'],
+ ]);
+ }
+
+ const callsResponse2 = await executeMulticall(
+ networkWeb3Contracts.multicall,
+ callsToExecute
+ );
+
+ const boostedProposals = callsResponse2.decodedReturnData[0][0];
+
+ if (
+ !networkCache.votingMachines[votingMachineAddress].votingParameters[
+ paramsHash
+ ]
+ ) {
+ networkCache.votingMachines[votingMachineAddress].votingParameters[
+ paramsHash
+ ] = {
+ queuedVoteRequiredPercentage: callsResponse2.decodedReturnData[1][0],
+ queuedVotePeriodLimit: callsResponse2.decodedReturnData[1][1],
+ boostedVotePeriodLimit: callsResponse2.decodedReturnData[1][2],
+ preBoostedVotePeriodLimit: callsResponse2.decodedReturnData[1][3],
+ thresholdConst: callsResponse2.decodedReturnData[1][4],
+ limitExponentValue: callsResponse2.decodedReturnData[1][5],
+ quietEndingPeriod: callsResponse2.decodedReturnData[1][6],
+ proposingRepReward: callsResponse2.decodedReturnData[1][7],
+ votersReputationLossRatio: callsResponse2.decodedReturnData[1][8],
+ minimumDaoBounty: callsResponse2.decodedReturnData[1][9],
+ daoBountyConst: callsResponse2.decodedReturnData[1][10],
+ activationTime: callsResponse2.decodedReturnData[1][11],
+ };
+ }
+
+ const boostedVoteRequiredPercentage = isWalletScheme
+ ? callsResponse2.decodedReturnData[callsToExecute.length - 1][0]
+ : 0;
+
+ if (isNewScheme) {
+ networkCache.schemes[schemeAddress] = {
+ address: schemeAddress,
+ registered: true,
+ controllerAddress,
+ name: schemeName,
+ type: schemeType,
+ votingMachine: votingMachineAddress,
+ paramsHash: paramsHash,
+ permissions,
+ boostedVoteRequiredPercentage,
+ proposalIds: [],
+ boostedProposals: boostedProposals,
+ maxSecondsForExecution,
+ maxRepPercentageChange,
+ newProposalEvents: [],
+ };
+ } else {
+ networkCache.schemes[schemeAddress].boostedProposals = boostedProposals;
+ networkCache.schemes[schemeAddress].maxSecondsForExecution =
+ maxSecondsForExecution;
+ networkCache.schemes[schemeAddress].maxRepPercentageChange =
+ maxRepPercentageChange;
+ networkCache.schemes[schemeAddress].boostedVoteRequiredPercentage =
+ boostedVoteRequiredPercentage;
+ networkCache.schemes[schemeAddress].paramsHash = paramsHash;
+ networkCache.schemes[schemeAddress].permissions = permissions;
+ networkCache.schemes[schemeAddress].registered = !removeScheme;
+ }
+
+ // Get the new proposals submitted in the scheme and process it
+ const avatarAddressEncoded = web3.eth.abi.encodeParameter(
+ 'address',
+ networkCache.address
+ );
+ const fromBlock = networkCache.blockNumber + 1;
+
+ let schemeEvents = await getRawEvents(
+ web3,
+ schemeAddress,
+ fromBlock,
+ toBlock,
+ schemeTypeData.newProposalTopics
+ );
+
+ await batchPromisesOntarget(
+ schemeEvents.map(schemeEvent => {
+ const proposalId: string =
+ schemeEvent.topics[1] === avatarAddressEncoded
+ ? schemeEvent.topics[2]
+ : schemeEvent.topics[1];
+
+ schemeEvent.tx = schemeEvent.transactionHash;
+
+ return this.processProposal(
+ proposalId,
+ networkCache,
+ networkContracts,
+ web3,
+ fromBlock,
+ toBlock,
+ schemeEvent
+ );
+ }),
+ networkCache,
+ 50
+ );
+
+ return networkCache;
+ }
+
+ // Process a proposal in the networkCache
+ // If the proposal does not exist in the cache it gets the immutable + mutable data
+ // The proposal already exists it gets the mutable data only
+ async processProposal(
+ proposalId: string,
+ networkCache: DaoNetworkCache,
+ networkContracts: NetworkContracts,
+ web3: Web3,
+ fromBlock: number,
+ toBlock: number,
+ creationEvent?: BlockchainEvent
+ ): Promise {
+ const newProposal = !networkCache.proposals[proposalId];
+ const schemeAddress = newProposal
+ ? creationEvent.address
+ : networkCache.proposals[proposalId].scheme;
+ const schemeOfProposal = networkCache.schemes[schemeAddress];
+ const avatarAddress = networkCache.address;
+ const schemeTypeData = getSchemeConfig(networkContracts, schemeAddress);
+ const networkWeb3Contracts = await getContracts(networkContracts, web3);
+ const avatarAddressEncoded = web3.eth.abi.encodeParameter(
+ 'address',
+ avatarAddress
+ );
+
+ // These first calls target mainly the voting machine where most of the proposal information is mutable
+ let callsToExecute = [
+ [
+ networkCache.schemes[schemeAddress].votingMachine,
+ 'proposals(bytes32)',
+ [proposalId],
+ [
+ { type: 'bytes32', name: 'organizationId' },
+ { type: 'address', name: 'callbacks' },
+ { type: 'uint256', name: 'state' },
+ { type: 'uint256', name: 'winningVote' },
+ { type: 'address', name: 'proposer' },
+ {
+ type: 'uint256',
+ name: 'currentBoostedVotePeriodLimit',
+ },
+ { type: 'bytes32', name: 'paramsHash' },
+ { type: 'uint256', name: 'daoBountyRemain' },
+ { type: 'uint256', name: 'daoBounty' },
+ { type: 'uint256', name: 'totalStakes' },
+ { type: 'uint256', name: 'confidenceThreshold' },
+ {
+ type: 'uint256',
+ name: 'secondsFromTimeOutTillExecuteBoosted',
+ },
+ ],
+ ],
+ [
+ networkCache.schemes[schemeAddress].votingMachine,
+ 'voteStatus(bytes32,uint256)',
+ [proposalId, 1],
+ ['uint256'],
+ ],
+ [
+ networkCache.schemes[schemeAddress].votingMachine,
+ 'voteStatus(bytes32,uint256)',
+ [proposalId, 2],
+ ['uint256'],
+ ],
+ [
+ networkCache.schemes[schemeAddress].votingMachine,
+ 'proposalStatus(bytes32)',
+ [proposalId],
+ ['uint256', 'uint256', 'uint256', 'uint256'],
+ ],
+ [
+ networkCache.schemes[schemeAddress].votingMachine,
+ 'getProposalTimes(bytes32)',
+ [proposalId],
+ ['uint256', 'uint256', 'uint256'],
+ ],
+ [
+ networkCache.schemes[schemeAddress].votingMachine,
+ 'shouldBoost(bytes32)',
+ [proposalId],
+ ['bool'],
+ ],
+ ];
+
+ // The next calls added target ContributionReward and WalletScheme to get immutable and mutable data
+ if (schemeTypeData.type === 'ContributionReward') {
+ callsToExecute.push([
+ schemeAddress,
+ 'getRedeemedPeriods(bytes32,address,uint256)',
+ [proposalId, schemeAddress, 0],
+ ['uint256'],
+ ]);
+ callsToExecute.push([
+ schemeAddress,
+ 'getRedeemedPeriods(bytes32,address,uint256)',
+ [proposalId, avatarAddress, 1],
+ ['uint256'],
+ ]);
+ callsToExecute.push([
+ schemeAddress,
+ 'getRedeemedPeriods(bytes32,address,uint256)',
+ [proposalId, avatarAddress, 2],
+ ['uint256'],
+ ]);
+ callsToExecute.push([
+ schemeAddress,
+ 'getRedeemedPeriods(bytes32,address,uint256)',
+ [proposalId, avatarAddress, 3],
+ ['uint256'],
+ ]);
+ } else if (isWalletScheme(schemeOfProposal)) {
+ callsToExecute.push([
+ schemeAddress,
+ 'getOrganizationProposal(bytes32)',
+ [proposalId],
+ [
+ { type: 'address[]', name: 'to' },
+ { type: 'bytes[]', name: 'callData' },
+ { type: 'uint256[]', name: 'value' },
+ { type: 'uint256', name: 'state' },
+ { type: 'string', name: 'title' },
+ { type: 'string', name: 'descriptionHash' },
+ { type: 'uint256', name: 'submittedTime' },
+ ],
+ ]);
+ }
+
+ const callsResponse = await executeMulticall(
+ networkWeb3Contracts.multicall,
+ callsToExecute
+ );
+
+ const proposalTimes = callsResponse.decodedReturnData[4];
+
+ let schemeProposalInfo = {
+ to: [],
+ callData: [],
+ value: [],
+ state: WalletSchemeProposalState.Submitted,
+ title: '',
+ descriptionHash: '',
+ submittedTime: 0,
+ };
+ let decodedProposer;
+ let creationLogDecoded;
+
+ if (isWalletScheme(schemeOfProposal)) {
+ schemeProposalInfo.state = callsResponse.decodedReturnData[6].state;
+
+ if (newProposal) {
+ schemeProposalInfo.to = callsResponse.decodedReturnData[6].to;
+ schemeProposalInfo.callData =
+ callsResponse.decodedReturnData[6].callData;
+ schemeProposalInfo.value = callsResponse.decodedReturnData[6].value;
+ schemeProposalInfo.title = callsResponse.decodedReturnData[6].title;
+ schemeProposalInfo.descriptionHash =
+ callsResponse.decodedReturnData[6].descriptionHash;
+ schemeProposalInfo.submittedTime =
+ callsResponse.decodedReturnData[6].submittedTime;
+ }
+ } else {
+ // Here we get the events triggered in the GenericMulticall to get their final state
+ // When the proposal is executed by the voting machine we get if the proposal was rejected
+ // If the proposal was executed by teh voting machine and not rejected we get the ProposalEnded
+ // to know if it was executed by the WalletScheme
+ if (schemeOfProposal.type === 'GenericMulticall') {
+ // event ProposalExecutedByVotingMachine(address indexed _avatar,bytes32 indexed _proposalId,int256 _param)
+ const votingMachineExecutionEvent =
+ schemeProposalInfo.state === WalletSchemeProposalState.Submitted
+ ? await getRawEvents(
+ web3,
+ schemeAddress,
+ fromBlock,
+ toBlock,
+ [
+ '0x25d4c89430c1f10c60c292556941e3e624ec1ec04972a5da46cee1b352429cbe',
+ avatarAddressEncoded,
+ proposalId,
+ ],
+ 10000000
+ )
+ : [];
+ if (
+ votingMachineExecutionEvent.length > 0 &&
+ votingMachineExecutionEvent[0].data !==
+ '0x0000000000000000000000000000000000000000000000000000000000000001'
+ )
+ schemeProposalInfo.state = WalletSchemeProposalState.Rejected;
+
+ if (
+ callsResponse.decodedReturnData[0].state ===
+ VotingMachineProposalState.Executed &&
+ schemeProposalInfo.state === WalletSchemeProposalState.Submitted
+ ) {
+ // event ProposalDeleted(address indexed _avatar, bytes32 indexed _proposalId)
+ const executionEvent = await getRawEvents(
+ web3,
+ schemeAddress,
+ fromBlock,
+ toBlock,
+ [
+ '0x253ad9614c337848bbe7dc3b18b439d139ef5787282b5a517ba7296513d1f533',
+ avatarAddressEncoded,
+ proposalId,
+ ],
+ 10000000
+ );
+ if (executionEvent.length > 0) {
+ schemeProposalInfo.state =
+ WalletSchemeProposalState.ExecutionSucceded;
+ }
+ }
+
+ // If any of the values of the redeemPeriods of the contribution reward is higher than zero it means that it executed the reward
+ } else if (schemeOfProposal.type === 'ContributionReward') {
+ if (
+ callsResponse.decodedReturnData[0].winningVote === '2' &&
+ callsResponse.decodedReturnData[0].state === '2'
+ ) {
+ schemeProposalInfo.state = WalletSchemeProposalState.Rejected;
+ } else if (
+ callsResponse.decodedReturnData[6][0] > 0 ||
+ callsResponse.decodedReturnData[7][0] > 0 ||
+ callsResponse.decodedReturnData[8][0] > 0 ||
+ callsResponse.decodedReturnData[9][0] > 0
+ ) {
+ schemeProposalInfo.state =
+ WalletSchemeProposalState.ExecutionSucceded;
+ } else {
+ schemeProposalInfo.state = WalletSchemeProposalState.Submitted;
+ }
+ }
+ }
+
+ // If the proposal is processed with a creation event it means that it has to be added to the cache
+ // We will get the immutable data stored on the contracts by decoding the creation event logs
+ if (newProposal) {
+ if (creationEvent && !isWalletScheme(schemeOfProposal)) {
+ const transactionReceipt = await web3.eth.getTransactionReceipt(
+ creationEvent.tx
+ );
+ try {
+ // Decode the creation event data to get the num of choices, paramsHash and proposer
+ schemeTypeData.newProposalTopics.forEach((newProposalTopic, i) => {
+ transactionReceipt.logs.forEach(log => {
+ if (
+ log.topics[0] ===
+ '0x75b4ff136cc5de5957574c797de3334eb1c141271922b825eb071e0487ba2c5c'
+ ) {
+ decodedProposer = web3.eth.abi.decodeParameters(
+ [
+ { type: 'uint256', name: '_numOfChoices' },
+ { type: 'address', name: '_proposer' },
+ { type: 'bytes32', name: '_paramsHash' },
+ ],
+ log.data
+ )._proposer;
+ }
+ if (
+ !creationLogDecoded &&
+ log.topics[0] === newProposalTopic[0]
+ ) {
+ creationLogDecoded = web3.eth.abi.decodeParameters(
+ schemeTypeData.creationLogEncoding[i],
+ log.data
+ );
+ if (
+ creationLogDecoded._descriptionHash.length > 0 &&
+ creationLogDecoded._descriptionHash !== ZERO_HASH
+ ) {
+ schemeProposalInfo.descriptionHash =
+ ipfsHashToDescriptionHash(
+ creationLogDecoded._descriptionHash
+ );
+ }
+ }
+ });
+ });
+ } catch (error) {
+ console.error(
+ 'Error in getting proposal data from creation event',
+ error
+ );
+ }
+ }
+
+ // Try to decode as much as we can from the creation event, decoding creation logs.
+ // Depending the type of the scheme we have to decode different data and parse it to decoded calls
+ if (schemeTypeData.type === 'SchemeRegistrar') {
+ schemeProposalInfo.to = [schemeTypeData.contractToCall];
+ schemeProposalInfo.value = [0];
+
+ if (creationLogDecoded._parametersHash) {
+ schemeProposalInfo.callData = [
+ web3.eth.abi.encodeFunctionCall(
+ {
+ name: 'registerScheme',
+ type: 'function',
+ inputs: [
+ { type: 'address', name: '_scheme' },
+ { type: 'bytes32', name: '_paramsHash' },
+ { type: 'bytes4', name: '_permissions' },
+ { type: 'address', name: '_avatar' },
+ ],
+ },
+ [
+ creationLogDecoded['_scheme '],
+ creationLogDecoded._parametersHash,
+ creationLogDecoded._permissions,
+ avatarAddress,
+ ]
+ ),
+ ];
+ } else {
+ schemeProposalInfo.callData = [
+ web3.eth.abi.encodeFunctionCall(
+ {
+ name: 'unregisterScheme',
+ type: 'function',
+ inputs: [
+ { type: 'address', name: '_scheme' },
+ { type: 'address', name: '_avatar' },
+ ],
+ },
+ [creationLogDecoded['_scheme '], avatarAddress]
+ ),
+ ];
+ }
+ } else if (schemeTypeData.type === 'ContributionReward') {
+ if (creationLogDecoded._reputationChange > 0) {
+ schemeProposalInfo.to.push(schemeTypeData.contractToCall);
+ schemeProposalInfo.value.push(0);
+ schemeProposalInfo.callData.push(
+ web3.eth.abi.encodeFunctionCall(
+ {
+ name: 'mintReputation',
+ type: 'function',
+ inputs: [
+ { type: 'uint256', name: '_amount' },
+ { type: 'address', name: '_to' },
+ { type: 'address', name: '_avatar' },
+ ],
+ },
+ [
+ creationLogDecoded._reputationChange,
+ creationLogDecoded._beneficiary,
+ avatarAddress,
+ ]
+ )
+ );
+ } else if (creationLogDecoded._reputationChange < 0) {
+ schemeProposalInfo.to.push(schemeTypeData.contractToCall);
+ schemeProposalInfo.value.push(0);
+
+ // Remove the negative sign in the number
+ if (creationLogDecoded._reputationChange[0] === '-')
+ creationLogDecoded._reputationChange =
+ creationLogDecoded._reputationChange.substring(1);
+
+ schemeProposalInfo.callData.push(
+ web3.eth.abi.encodeFunctionCall(
+ {
+ name: 'burnReputation',
+ type: 'function',
+ inputs: [
+ { type: 'uint256', name: '_amount' },
+ { type: 'address', name: '_from' },
+ { type: 'address', name: '_avatar' },
+ ],
+ },
+ [
+ creationLogDecoded._reputationChange,
+ creationLogDecoded._beneficiary,
+ avatarAddress,
+ ]
+ )
+ );
+ }
+
+ if (creationLogDecoded._rewards[0] > 0) {
+ schemeProposalInfo.to.push(schemeTypeData.contractToCall);
+ schemeProposalInfo.value.push(0);
+ schemeProposalInfo.callData.push(
+ web3.eth.abi.encodeFunctionCall(
+ {
+ name: 'mintTokens',
+ type: 'function',
+ inputs: [
+ { type: 'uint256', name: '_amount' },
+ { type: 'address', name: '_beneficiary' },
+ { type: 'address', name: '_avatar' },
+ ],
+ },
+ [
+ creationLogDecoded._rewards[0],
+ creationLogDecoded._beneficiary,
+ avatarAddress,
+ ]
+ )
+ );
+ }
+
+ if (creationLogDecoded._rewards[1] > 0) {
+ schemeProposalInfo.to.push(schemeTypeData.contractToCall);
+ schemeProposalInfo.value.push(0);
+ schemeProposalInfo.callData.push(
+ web3.eth.abi.encodeFunctionCall(
+ {
+ name: 'sendEther',
+ type: 'function',
+ inputs: [
+ { type: 'uint256', name: '_amountInWei' },
+ { type: 'address', name: '_to' },
+ { type: 'address', name: '_avatar' },
+ ],
+ },
+ [
+ creationLogDecoded._rewards[1],
+ creationLogDecoded._beneficiary,
+ avatarAddress,
+ ]
+ )
+ );
+ }
+
+ if (creationLogDecoded._rewards[2] > 0) {
+ schemeProposalInfo.to.push(schemeTypeData.contractToCall);
+ schemeProposalInfo.value.push(0);
+ schemeProposalInfo.callData.push(
+ web3.eth.abi.encodeFunctionCall(
+ {
+ name: 'externalTokenTransfer',
+ type: 'function',
+ inputs: [
+ { type: 'address', name: '_externalToken' },
+ { type: 'address', name: '_to' },
+ { type: 'uint256', name: '_value' },
+ { type: 'address', name: '_avatar' },
+ ],
+ },
+ [
+ creationLogDecoded._externalToken,
+ creationLogDecoded._beneficiary,
+ creationLogDecoded._rewards[2],
+ avatarAddress,
+ ]
+ )
+ );
+ }
+ } else if (schemeTypeData.type === 'GenericScheme') {
+ schemeProposalInfo.to = [networkWeb3Contracts.controller._address];
+ schemeProposalInfo.value = [0];
+ schemeProposalInfo.callData = [
+ web3.eth.abi.encodeFunctionCall(
+ {
+ name: 'genericCall',
+ type: 'function',
+ inputs: [
+ { type: 'address', name: '_contract' },
+ { type: 'bytes', name: '_data' },
+ { type: 'address', name: '_avatar' },
+ { type: 'uint256', name: '_value' },
+ ],
+ },
+ [
+ schemeTypeData.contractToCall,
+ creationLogDecoded._data,
+ avatarAddress,
+ creationLogDecoded._value,
+ ]
+ ),
+ ];
+ } else if (schemeTypeData.type === 'GenericMulticall') {
+ for (
+ let callIndex = 0;
+ callIndex < creationLogDecoded._contractsToCall.length;
+ callIndex++
+ ) {
+ schemeProposalInfo.to.push(networkWeb3Contracts.controller._address);
+ schemeProposalInfo.value.push(0);
+ schemeProposalInfo.callData.push(
+ web3.eth.abi.encodeFunctionCall(
+ {
+ name: 'genericCall',
+ type: 'function',
+ inputs: [
+ { type: 'address', name: '_contract' },
+ { type: 'bytes', name: '_data' },
+ { type: 'address', name: '_avatar' },
+ { type: 'uint256', name: '_value' },
+ ],
+ },
+ [
+ creationLogDecoded._contractsToCall[callIndex],
+ creationLogDecoded._callsData[callIndex],
+ avatarAddress,
+ creationLogDecoded._values[callIndex],
+ ]
+ )
+ );
+ }
+ }
+
+ // Register the new voting parameters in the voting machine params if they dont exist in the cache
+ if (
+ !networkCache.votingMachines[
+ networkCache.schemes[schemeAddress].votingMachine
+ ].votingParameters[callsResponse.decodedReturnData[0].paramsHash]
+ ) {
+ const votingParameters = (
+ await executeMulticall(networkWeb3Contracts.multicall, [
+ [
+ networkCache.schemes[schemeAddress].votingMachine,
+ 'parameters(bytes32)',
+ [callsResponse.decodedReturnData[0].paramsHash],
+ [
+ 'uint256',
+ 'uint256',
+ 'uint256',
+ 'uint256',
+ 'uint256',
+ 'uint256',
+ 'uint256',
+ 'uint256',
+ 'uint256',
+ 'uint256',
+ 'uint256',
+ 'uint256',
+ 'address',
+ ],
+ ],
+ ])
+ ).decodedReturnData[0];
+ networkCache.votingMachines[
+ networkCache.schemes[schemeAddress].votingMachine
+ ].votingParameters[callsResponse.decodedReturnData[0].paramsHash] = {
+ queuedVoteRequiredPercentage: votingParameters[0],
+ queuedVotePeriodLimit: votingParameters[1],
+ boostedVotePeriodLimit: votingParameters[2],
+ preBoostedVotePeriodLimit: votingParameters[3],
+ thresholdConst: votingParameters[4],
+ limitExponentValue: votingParameters[5],
+ quietEndingPeriod: votingParameters[6],
+ proposingRepReward: votingParameters[7],
+ votersReputationLossRatio: votingParameters[8],
+ minimumDaoBounty: votingParameters[9],
+ daoBountyConst: votingParameters[10],
+ activationTime: votingParameters[11],
+ };
+ }
+
+ networkCache.proposals[proposalId] = {
+ id: proposalId,
+ scheme: schemeAddress,
+ to: schemeProposalInfo.to,
+ title: schemeProposalInfo.title || '',
+ callData: schemeProposalInfo.callData,
+ values: schemeProposalInfo.value.map(value => bnum(value)),
+ stateInScheme: Number(schemeProposalInfo.state),
+ stateInVotingMachine: Number(callsResponse.decodedReturnData[0].state),
+ descriptionHash: schemeProposalInfo.descriptionHash,
+ creationEvent: {
+ event: creationEvent.event,
+ signature: creationEvent.signature,
+ address: creationEvent.address,
+ tx: creationEvent.tx,
+ blockNumber: creationEvent.blockNumber,
+ timestamp: creationEvent.timestamp,
+ transactionIndex: creationEvent.transactionIndex,
+ logIndex: creationEvent.logIndex,
+ },
+ winningVote: callsResponse.decodedReturnData[0].winningVote,
+ proposer: decodedProposer
+ ? decodedProposer
+ : callsResponse.decodedReturnData[0].proposer,
+ currentBoostedVotePeriodLimit:
+ callsResponse.decodedReturnData[0].currentBoostedVotePeriodLimit,
+ paramsHash: callsResponse.decodedReturnData[0].paramsHash,
+ daoBountyRemain: bnum(
+ callsResponse.decodedReturnData[0].daoBountyRemain
+ ),
+ daoBounty: bnum(callsResponse.decodedReturnData[0].daoBounty),
+ confidenceThreshold:
+ callsResponse.decodedReturnData[0].confidenceThreshold,
+ secondsFromTimeOutTillExecuteBoosted:
+ callsResponse.decodedReturnData[0]
+ .secondsFromTimeOutTillExecuteBoosted,
+ submittedTime: bnum(proposalTimes[0]),
+ boostedPhaseTime: bnum(proposalTimes[1]),
+ preBoostedPhaseTime: bnum(proposalTimes[2]),
+ daoRedeemItsWinnings:
+ callsResponse.decodedReturnData[0].daoRedeemItsWinnings,
+ shouldBoost: callsResponse.decodedReturnData[5][0],
+ positiveVotes: bnum(callsResponse.decodedReturnData[1][0]),
+ negativeVotes: bnum(callsResponse.decodedReturnData[2][0]),
+ positiveStakes: bnum(callsResponse.decodedReturnData[3][2]),
+ negativeStakes: bnum(callsResponse.decodedReturnData[3][3]),
+ };
+
+ networkCache.schemes[schemeAddress].proposalIds.push(proposalId);
+ networkCache.schemes[schemeAddress].newProposalEvents.push({
+ proposalId: proposalId,
+ event: creationEvent.event,
+ signature: creationEvent.signature,
+ address: creationEvent.address,
+ tx: creationEvent.tx,
+ blockNumber: creationEvent.blockNumber,
+ timestamp: creationEvent.timestamp,
+ transactionIndex: creationEvent.transactionIndex,
+ logIndex: creationEvent.logIndex,
+ });
+
+ if (schemeProposalInfo.descriptionHash.length > 1) {
+ networkCache.ipfsHashes.push({
+ hash: descriptionHashToIPFSHash(schemeProposalInfo.descriptionHash),
+ type: 'proposal',
+ name: proposalId,
+ });
+ }
+
+ // Is the proposal is not new we only assign the values that are mutable
+ } else {
+ networkCache.proposals[proposalId].stateInScheme = Number(
+ schemeProposalInfo.state
+ );
+ networkCache.proposals[proposalId].stateInVotingMachine = Number(
+ callsResponse.decodedReturnData[0].state
+ );
+ networkCache.proposals[proposalId].winningVote =
+ callsResponse.decodedReturnData[0].winningVote;
+ networkCache.proposals[proposalId].currentBoostedVotePeriodLimit =
+ callsResponse.decodedReturnData[0].currentBoostedVotePeriodLimit;
+ networkCache.proposals[proposalId].daoBountyRemain = bnum(
+ callsResponse.decodedReturnData[0].daoBountyRemain
+ );
+ networkCache.proposals[proposalId].daoBounty = bnum(
+ callsResponse.decodedReturnData[0].daoBounty
+ );
+ networkCache.proposals[proposalId].confidenceThreshold =
+ callsResponse.decodedReturnData[0].confidenceThreshold;
+ networkCache.proposals[proposalId].secondsFromTimeOutTillExecuteBoosted =
+ callsResponse.decodedReturnData[0].secondsFromTimeOutTillExecuteBoosted;
+ networkCache.proposals[proposalId].boostedPhaseTime = bnum(
+ proposalTimes[1]
+ );
+ networkCache.proposals[proposalId].preBoostedPhaseTime = bnum(
+ proposalTimes[2]
+ );
+ networkCache.proposals[proposalId].daoRedeemItsWinnings =
+ callsResponse.decodedReturnData[0].daoRedeemItsWinnings;
+ networkCache.proposals[proposalId].shouldBoost =
+ callsResponse.decodedReturnData[5][0];
+ networkCache.proposals[proposalId].positiveVotes = bnum(
+ callsResponse.decodedReturnData[1][0]
+ );
+ networkCache.proposals[proposalId].negativeVotes = bnum(
+ callsResponse.decodedReturnData[2][0]
+ );
+ networkCache.proposals[proposalId].positiveStakes = bnum(
+ callsResponse.decodedReturnData[3][2]
+ );
+ networkCache.proposals[proposalId].negativeStakes = bnum(
+ callsResponse.decodedReturnData[3][3]
+ );
+ }
+
+ return networkCache;
+ }
}
diff --git a/src/services/IPFSService.ts b/src/services/IPFSService.ts
index d5bcff1bd1..20f4d59409 100644
--- a/src/services/IPFSService.ts
+++ b/src/services/IPFSService.ts
@@ -51,28 +51,34 @@ export default class IPFSService {
async getContentFromIPFS(hash: string) {
const response = await Promise.any([
axios.request({
- url: 'https://ipfs.io/ipfs/' + hash,
+ url: 'https://dxgov.mypinata.cloud/ipfs/' + hash,
method: 'GET',
+ timeout: 60000,
}),
axios.request({
- url: 'https://gateway.ipfs.io/ipfs/' + hash,
+ url: 'https://ipfs.io/ipfs/' + hash,
method: 'GET',
+ timeout: 60000,
}),
axios.request({
- url: 'https://cloudflare-ipfs.com/ipfs/' + hash,
+ url: 'https://gateway.ipfs.io/ipfs/' + hash,
method: 'GET',
+ timeout: 60000,
}),
axios.request({
- url: 'https://gateway.pinata.cloud/ipfs/' + hash,
+ url: 'https://cloudflare-ipfs.com/ipfs/' + hash,
method: 'GET',
+ timeout: 60000,
}),
axios.request({
url: 'https://dweb.link/ipfs/' + hash,
method: 'GET',
+ timeout: 60000,
}),
axios.request({
url: 'https://infura-ipfs.io/ipfs/' + hash,
method: 'GET',
+ timeout: 60000,
}),
]);
return response.data;
@@ -95,8 +101,10 @@ export default class IPFSService {
localStorage.setItem('dxvote-newProposal-hash', hash);
if (pinataService.auth) {
- const pinataPin = await this.pin(hash);
+ const pinataPin = await pinataService.pin(hash);
console.debug('[PINATA PIN]', pinataPin.toString());
+ } else {
+ console.debug('[PINATA PIN] NOT AUTHENTICATED');
}
const ipfsPin = await this.pin(hash);
console.debug('[IPFS PIN]', ipfsPin);
@@ -115,7 +123,7 @@ export default class IPFSService {
const hash = await this.add(content);
if (this.context.pinataService.auth) {
- const pinataPin = await this.pin(hash);
+ const pinataPin = await this.context.pinataService.pin(hash);
console.debug('[PINATA PIN]', pinataPin.toString());
}
const ipfsPin = await this.pin(hash);
diff --git a/src/services/MessageLoggerService.ts b/src/services/MessageLoggerService.ts
deleted file mode 100644
index 5343151725..0000000000
--- a/src/services/MessageLoggerService.ts
+++ /dev/null
@@ -1,109 +0,0 @@
-import Common, { Chain, Hardfork } from '@ethereumjs/common';
-import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx';
-import RootContext from '../contexts';
-import { arrayBufferHex } from 'utils';
-import { ethers, utils } from 'ethers';
-import { JsonRpcProvider } from '@ethersproject/providers';
-
-export default class MessageLoggerService {
- context: RootContext;
-
- messageLoggerAddress: string = '0xA490faF0DC4F26101a15bAc6ECad55b59db014a7';
- messageLoggerABI: ethers.utils.Interface = new ethers.utils.Interface([
- 'event Message(bytes32 indexed topic, string message, address sender)',
- 'function broadcast(bytes32 topic, string message)',
- ]);
- fromBlock: number = 9904867;
-
- constructor(context: RootContext) {
- this.context = context;
- }
-
- async broadcast(
- topic: string,
- message: string,
- rinkebyWeb3: JsonRpcProvider
- ) {
- const { account } = this.context.providerStore.getActiveWeb3React();
- const common = new Common({
- chain: Chain.Rinkeby,
- hardfork: Hardfork.London,
- });
-
- // Step 1: Create the TX to send in rinkeby with the signature of the vote.
- let txData = {
- from: account,
- data: this.messageLoggerABI.encodeFunctionData('broadcast', [
- topic,
- message,
- ]),
- nonce: await rinkebyWeb3.getTransactionCount(account),
- gasLimit: 50000,
- maxPriorityFeePerGas: 1000000000,
- maxFeePerGas: 1000000000,
- to: this.messageLoggerAddress,
- value: 0,
- type: '0x02',
- chainId: '0x04',
- DEFAULT_CHAIN: 'rinkeby',
- };
-
- const tx = FeeMarketEIP1559Transaction.fromTxData(txData, { common });
- const unsignedTx = tx.getMessageToSign(false);
- console.log('Unsigned Rinkeby tx:', tx);
-
- // Step 2: Sign the transaction with the vote signature to be shared in rinkeby executing a tx in rinkeby network
- let signature = await this.context.providerStore.sign(
- this.context.providerStore.getActiveWeb3React(),
- utils.keccak256('0x' + arrayBufferHex(unsignedTx))
- );
-
- // Step 3: Send the raw transaction signed to the rinkeby network
- if (signature.result) {
- signature = signature.result.substr(2);
- const r = '0x' + signature.substr(0, 64);
- const s = '0x' + signature.substr(64, 64);
- const v = signature.substr(128) == '1c' ? '0x1' : '0x0';
- console.log('Rinkeby tx object:', txData);
- console.log(`Rinkeby tx signature: ${v}${r}${s}`);
-
- const signedTx = FeeMarketEIP1559Transaction.fromTxData({
- ...txData,
- v,
- r,
- s,
- });
- const from = signedTx.getSenderAddress().toString();
- console.log(
- `Signed Rinkeby tx hex: ${signedTx
- .serialize()
- .toString('hex')}\n Rinkeby tx Signer: ${from}`
- );
-
- rinkebyWeb3.send('eth_sendRawTransaction', [
- '0x' + signedTx.serialize().toString('hex'),
- ]);
- }
- }
-
- async getMessages(topic: string, rinkebyWeb3: JsonRpcProvider) {
- const messageLogger = new ethers.Contract(
- this.messageLoggerAddress,
- this.messageLoggerABI,
- rinkebyWeb3
- );
-
- const filter = messageLogger.filters.Message(topic);
- try {
- const events = await messageLogger.queryFilter(
- filter,
- this.fromBlock,
- await rinkebyWeb3.getBlockNumber()
- );
- return events;
- } catch (error) {
- console.error('Error fetching message logger events', error);
- return [];
- }
- }
-}
diff --git a/src/services/PinataService.ts b/src/services/PinataService.ts
index 3624d98321..9a09b2ca77 100644
--- a/src/services/PinataService.ts
+++ b/src/services/PinataService.ts
@@ -10,7 +10,7 @@ export default class PinataService {
this.context = context;
}
defaultApiKey =
- 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mb3JtYXRpb24iOnsiaWQiOiI4ZTNlZjUzNi0wZWQ5LTQ4YzAtOTFlYS1kNzUwYjk0Nzk4ZDMiLCJlbWFpbCI6Im1lQHJvc3NuZWlsc29uLmRldiIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJwaW5fcG9saWN5Ijp7InJlZ2lvbnMiOlt7ImlkIjoiRlJBMSIsImRlc2lyZWRSZXBsaWNhdGlvbkNvdW50IjoxfV0sInZlcnNpb24iOjF9LCJtZmFfZW5hYmxlZCI6ZmFsc2V9LCJhdXRoZW50aWNhdGlvblR5cGUiOiJzY29wZWRLZXkiLCJzY29wZWRLZXlLZXkiOiJlNmM5ZDA4ZGY3ODY0YWRhZWIyMyIsInNjb3BlZEtleVNlY3JldCI6ImRmYmY4ZmNiNGQ0YjQxNWViODgyZDM1YjgyMDFlMDVjNjk1MjBkZDllOTg2MzgxZTY3YTI1YTk2N2YyOWQxOGQiLCJpYXQiOjE2Mzk1OTg2MTl9.tkenai9BlBubfnPJmIXz9DkjJg12aCyk3BAtAc-TU1A';
+ 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mb3JtYXRpb24iOnsiaWQiOiI4MTJmMzIwZC1iOTA1LTQwOTgtYmViZC1jMjMwNzhlNDNmM2MiLCJlbWFpbCI6ImZsdWlkZHJvcDU2NDgyM0BnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwicGluX3BvbGljeSI6eyJyZWdpb25zIjpbeyJpZCI6Ik5ZQzEiLCJkZXNpcmVkUmVwbGljYXRpb25Db3VudCI6MX1dLCJ2ZXJzaW9uIjoxfSwibWZhX2VuYWJsZWQiOmZhbHNlfSwiYXV0aGVudGljYXRpb25UeXBlIjoic2NvcGVkS2V5Iiwic2NvcGVkS2V5S2V5IjoiYmFhMjllYjUxZWYzZWQyMDY4MWEiLCJzY29wZWRLZXlTZWNyZXQiOiI0OTIyYzQ2MThhYWZlNzZmNzhiNWQzNzU0NzY4MjBiNTk1MWM5MjdkZjFiNzY3ZGI3OWUzMGY5OTI3MDBmYTc5IiwiaWF0IjoxNjUyMTg4MjAyfQ.c8CpCVxvdknULzW6dJALyWgHD_DMq5167Nlb1KkXNRI';
async updatePinList() {
// const pinList = await this.getPinList();
diff --git a/src/stores/BlockchainStore.ts b/src/stores/BlockchainStore.ts
index 1b5436a905..74de7ae043 100644
--- a/src/stores/BlockchainStore.ts
+++ b/src/stores/BlockchainStore.ts
@@ -4,6 +4,7 @@ import { Web3ReactContextInterface } from '@web3-react/core/dist/types';
import { isChainIdSupported } from '../provider/connectors';
import { CacheLoadError } from '../utils/errors';
import { bnum } from 'utils';
+import { getProposalTitles } from '../utils/cache';
const targetCacheVersion = 1;
@@ -37,7 +38,6 @@ export default class BlockchainStore {
const {
providerStore,
configStore,
- ipfsService,
daoStore,
notificationStore,
cacheService,
@@ -112,9 +112,10 @@ export default class BlockchainStore {
true,
'Fetching cached data from IPFS'
);
- networkCache = daoStore.parseCache(
- await ipfsService.getContentFromIPFS(newestCacheIpfsHash)
+ const ipfsCache = await cacheService.getCacheFromIPFS(
+ newestCacheIpfsHash
);
+ networkCache = daoStore.parseCache(ipfsCache);
networkCache.baseCacheIpfsHash = newestCacheIpfsHash;
}
@@ -127,15 +128,12 @@ export default class BlockchainStore {
chainId
);
- const fromBlock = lastCheckedBlockNumber + 1;
const toBlock = blockNumber;
const networkContracts = configStore.getNetworkContracts();
networkCache = await cacheService.getUpdatedCache(
- this.context,
networkCache,
networkContracts,
- fromBlock,
toBlock,
library
);
@@ -144,9 +142,9 @@ export default class BlockchainStore {
true,
`Getting proposal titles form ipfs`
);
- const proposalTitles = await cacheService.getProposalTitlesFromIPFS(
+ const proposalTitles = await cacheService.updateProposalTitles(
networkCache,
- configStore.getProposalTitlesInBuild()
+ getProposalTitles()
);
Object.keys(networkCache.proposals).map(proposalId => {
diff --git a/src/stores/ConfigStore.ts b/src/stores/ConfigStore.ts
index 4e1fc74d53..d2ab5c4d2d 100644
--- a/src/stores/ConfigStore.ts
+++ b/src/stores/ConfigStore.ts
@@ -10,26 +10,7 @@ import {
DEFAULT_CHAIN_ID,
} from '../utils';
import { ZERO_ADDRESS, ANY_ADDRESS, ANY_FUNC_SIGNATURE } from '../utils';
-
-const arbitrum = require('../configs/arbitrum/config.json');
-const arbitrumTestnet = require('../configs/arbitrumTestnet/config.json');
-const mainnet = require('../configs/mainnet/config.json');
-const xdai = require('../configs/xdai/config.json');
-const rinkeby = require('../configs/rinkeby/config.json');
-const localhost = require('../configs/localhost/config.json');
-const proposalTitles = require('../configs/proposalTitles.json');
-
-const defaultAppConfigs = {
- arbitrum,
- arbitrumTestnet,
- mainnet,
- xdai,
- rinkeby,
- localhost,
-};
-
-// Use the same content outside src folder in defaultConfigHashes.json or override
-const defaultCacheConfig = require('../configs/default.json');
+import { getDefaultConfigHashes, getAppConfig } from '../utils/cache';
export default class ConfigStore {
darkMode: boolean;
@@ -51,14 +32,14 @@ export default class ConfigStore {
}
reset() {
- this.networkConfig = defaultAppConfigs[this.getActiveChainName()];
+ this.networkConfig = getAppConfig()[this.getActiveChainName()];
this.networkConfigLoaded = false;
}
async loadNetworkConfig() {
const { ensService, ipfsService } = this.context;
- this.networkConfig = defaultAppConfigs[this.getActiveChainName()];
+ this.networkConfig = getAppConfig()[this.getActiveChainName()];
const isTestingEnv = !window?.location?.href?.includes('dxvote.eth');
if (this.getActiveChainName() !== 'localhost' && !this.networkConfigLoaded)
@@ -76,7 +57,7 @@ export default class ConfigStore {
);
const configRefs = isTestingEnv
- ? defaultCacheConfig
+ ? getDefaultConfigHashes()
: await ipfsService.getContentFromIPFS(metadataHash);
const configContentHash = configRefs[this.getActiveChainName()];
@@ -105,10 +86,6 @@ export default class ConfigStore {
return this.networkConfig;
}
- getProposalTitlesInBuild() {
- return proposalTitles;
- }
-
getActiveChainName() {
return NETWORK_NAMES[
this.context?.providerStore.getActiveWeb3React().chainId ||
@@ -124,6 +101,7 @@ export default class ConfigStore {
}
getLocalConfig() {
+ const defaultAppConfigs = getAppConfig();
const defaultConfig = {
etherscan: '',
pinata: '',
@@ -153,6 +131,7 @@ export default class ConfigStore {
}
resetLocalConfig() {
+ const defaultAppConfigs = getAppConfig();
localStorage.setItem(
'dxvote-config',
JSON.stringify({
diff --git a/src/stores/DaoStore.ts b/src/stores/DaoStore.ts
index 4a953584d5..3c9b254e93 100644
--- a/src/stores/DaoStore.ts
+++ b/src/stores/DaoStore.ts
@@ -59,7 +59,7 @@ export default class DaoStore {
].value = bnum(
unparsedCache.callPermissions[asset][from][to][
functionSignature
- ].value
+ ].value || 0
);
}
);
diff --git a/src/utils/cache.ts b/src/utils/cache.ts
index 162f2501da..2785a2500c 100644
--- a/src/utils/cache.ts
+++ b/src/utils/cache.ts
@@ -1,8 +1,62 @@
+import { Contract } from 'ethers';
import _ from 'lodash';
import { MAX_BLOCKS_PER_EVENTS_FETCH } from './constants';
import { sleep } from './helpers';
const Web3 = require('web3');
+const web3 = new Web3();
+
+const arbitrum = require('../configs/arbitrum/config.json');
+const arbitrumTestnet = require('../configs/arbitrumTestnet/config.json');
+const mainnet = require('../configs/mainnet/config.json');
+const xdai = require('../configs/xdai/config.json');
+const rinkeby = require('../configs/rinkeby/config.json');
+const localhost = require('../configs/localhost/config.json');
+
+const proposalTitles = require('../configs/proposalTitles.json');
+
+const defaultConfigHashes = require('../configs/default.json');
+
+export const getDefaultConfigHashes = (): Record => {
+ return defaultConfigHashes;
+};
+
+export const getProposalTitles = (): Record => {
+ return proposalTitles;
+};
+
+export const getAppConfig = (): AppConfig => {
+ return {
+ arbitrum,
+ arbitrumTestnet,
+ mainnet,
+ xdai,
+ rinkeby,
+ localhost,
+ };
+};
+
+// Sort cache data, so the IPFS hash is consistent
+export const sortNetworkCache = (
+ networkCache: DaoNetworkCache
+): DaoNetworkCache => {
+ Object.keys(networkCache.schemes).forEach(schemeId => {
+ networkCache.schemes[schemeId].proposalIds.sort();
+ networkCache.schemes[schemeId].newProposalEvents.sort((a, b) =>
+ a.proposalId.localeCompare(b.proposalId)
+ );
+ });
+ networkCache.proposals = Object.keys(networkCache.proposals)
+ .sort()
+ .reduce((obj, key) => {
+ obj[key] = networkCache.proposals[key];
+ return obj;
+ }, {});
+ networkCache.ipfsHashes = _.uniqBy(networkCache.ipfsHashes, 'name');
+ networkCache.ipfsHashes.sort((a, b) => a.name.localeCompare(b.name));
+
+ return networkCache;
+};
export const getEvents = async function (
web3,
@@ -33,6 +87,7 @@ export const getEvents = async function (
} catch (error) {
if ((error as Error).message.indexOf('Relay attempts exhausted') > -1) {
const blocksToLower = Math.max(Math.trunc((to - from) / 2), 10000);
+ console.error('Relay attempts exhausted');
console.debug('Lowering toBlock', blocksToLower, 'blocks');
to = to - blocksToLower;
await sleep(5000);
@@ -41,8 +96,11 @@ export const getEvents = async function (
'You cannot query logs for more than 100000 blocks at once.'
) > -1
) {
- maxBlocksPerFetch = 100000;
+ maxBlocksPerFetch = Number((maxBlocksPerFetch / 4).toFixed(0));
to = from + 100000;
+ console.error(
+ 'You cannot query logs for more than 100000 blocks at once.'
+ );
console.debug('Lowering toBlock to', to);
} else if (
(error as Error).message.indexOf('Relay attempts exhausted') === -1 &&
@@ -55,7 +113,7 @@ export const getEvents = async function (
}
}
}
- return events;
+ return sortEvents(events);
};
export const getRawEvents = async function (
@@ -73,7 +131,13 @@ export const getRawEvents = async function (
from = fromBlock;
while (from < to) {
console.debug(
- `Fetching logs of ${contractAddress} from blocks ${from} -> ${to}`
+ `Fetching logs of ${contractAddress} from blocks ${from} -> ${to}`,
+ {
+ address: contractAddress,
+ fromBlock: from,
+ toBlock: to,
+ topics: topicsToGet,
+ }
);
try {
let eventsFetched = await web3.eth.getPastLogs({
@@ -87,74 +151,53 @@ export const getRawEvents = async function (
from = to;
to = Math.min(from + maxBlocksPerFetch, toBlock);
} catch (error) {
- if (
- (error as Error).message.indexOf(
- 'You cannot query logs for more than 100000 blocks at once.'
- ) > -1
- ) {
+ if ((error as Error).message.indexOf('Relay attempts exhausted') > -1) {
const blocksToLower = Math.max(Math.trunc((to - from) / 2), 10000);
+ console.error('Relay attempts exhausted');
console.debug('Lowering toBlock', blocksToLower, 'blocks');
to = to - blocksToLower;
await sleep(5000);
+ } else if (
+ (error as Error).message.indexOf(
+ 'You cannot query logs for more than 100000 blocks at once.'
+ ) > -1
+ ) {
+ maxBlocksPerFetch = Number((maxBlocksPerFetch / 4).toFixed(0));
+ to = from + 100000;
+ console.error(
+ 'You cannot query logs for more than 100000 blocks at once.'
+ );
+ console.debug('Lowering toBlock to', to);
} else if (
(error as Error).message.indexOf('Relay attempts exhausted') === -1 &&
Math.trunc((to - from) / 2) > 10000
) {
- console.error('Error fetching blocks:', (error as Error).message);
+ console.error('Error fetching blocks:', error);
const blocksToLower = Math.max(Math.trunc((to - from) / 2), 10000);
console.debug('Lowering toBlock', blocksToLower, 'blocks');
to = to - blocksToLower;
}
}
}
- return events;
+ return sortEvents(events);
};
export const getTimestampOfEvents = async function (web3, events) {
- //// TODO: See how can we batch requests can be implemented
- // async function batchRequest(blocks) {
- // const batch = new web3.BatchRequest();
- // let requests = [];
- // for (let i = 0; i < blocks.length; i++) {
- // const request = new Promise((resolve, reject) => {
- // batch.add(web3.eth.getBlock.request(blocks[i], (err, data) => {
- // console.log(1)
- // if (err) return reject(err);
- // resolve(data);
- // }));
- // });
- // requests.push(request);
- // }
- // batch.execute();
- // console.log(batch)
- // await Promise.all(requests);
- // return batch;
- // };
-
- let blocksToFetch = [];
- let timestamps = [];
- events.map(event => {
- if (blocksToFetch.indexOf(event.blockNumber) < 0)
- blocksToFetch.push(event.blockNumber);
- });
- const totalLength = blocksToFetch.length;
- while (blocksToFetch.length > 0 && totalLength > timestamps.length) {
- // timestamps = (await batchRequest(blocksToFetch)).map((blockResult) => {
- // return blockResult.timestamp;
- // });
- const blocksToFetchBatch = blocksToFetch.splice(0, 500);
- await Promise.all(
- blocksToFetchBatch.map(async block => {
- const blockInfo = await web3.eth.getBlock(block);
- for (let i = 0; i < events.length; i++) {
- if (events[i].blockNumber === blockInfo.number)
- events[i].timestamp = blockInfo.timestamp;
- if (blockInfo.l2BlockNumber)
- events[i].blockNumber = Number(blockInfo.l2BlockNumber);
- }
- })
- );
- }
+ await batchPromises(
+ events.map(async (event, i) => {
+ const blockInfo = await web3.eth.getBlock(event.blockNumber);
+ if (!blockInfo) console.log(event.blockNumber);
+ for (let i = 0; i < events.length; i++) {
+ if (events[i].blockNumber === blockInfo.number)
+ events[i].timestamp = blockInfo.timestamp;
+ if (blockInfo.l2BlockNumber)
+ events[i].blockNumber = Number(blockInfo.l2BlockNumber);
+ }
+ }),
+ 100,
+ 1000,
+ 500
+ );
return events;
};
@@ -168,27 +211,30 @@ export const sortEvents = function (events) {
);
};
-export const executeMulticall = async function (web3, multicall, calls) {
+export const executeMulticall = async function (
+ multicall: Contract,
+ calls: any[]
+) {
const rawCalls = calls.map(call => {
+ const functionParams = [...call[1].matchAll(/\(([^)]+)\)/g)]
+ .flat()[1]
+ ?.split(',');
return [
- call[0]._address,
- web3.eth.abi.encodeFunctionCall(
- call[0]._jsonInterface.find(method => method.name === call[1]),
- call[2]
- ),
+ call[0],
+ web3.eth.abi.encodeFunctionSignature(call[1]) +
+ (functionParams
+ ? web3.eth.abi.encodeParameters(functionParams, call[2]).substring(2)
+ : ''),
];
});
-
const { returnData } = await multicall.methods.aggregate(rawCalls).call();
return {
returnData,
decodedReturnData: returnData.map((callResult, i) => {
- return web3.eth.abi.decodeParameters(
- calls[i][0]._jsonInterface.find(method => method.name === calls[i][1])
- .outputs,
- callResult
- )['0'];
+ return calls[i][3].length > 0
+ ? web3.eth.abi.decodeParameters(calls[i][3], callResult)
+ : '';
}),
};
};
@@ -230,7 +276,7 @@ export const getSchemeConfig = function (networkContracts, schemeAddress) {
newProposalTopics: [
[
Web3.utils.soliditySha3('ProposalStateChange(bytes32,uint256)'),
- null,
+ '0x0000000000000000000000000000000000000000000000000000000000000000',
'0x0000000000000000000000000000000000000000000000000000000000000001',
],
],
@@ -254,3 +300,64 @@ export async function tryCacheUpdates(promises, networkCache) {
}
return networkCache;
}
+
+export async function batchPromisesOntarget(
+ promises,
+ targetObject,
+ maxPromisesPerTry = 0,
+ maxTries = 10,
+ sleepTimeBetweenRetries = 100
+) {
+ let promisesBatch = maxPromisesPerTry === 0 ? [promises] : [];
+ let promisesBatchIndex = 0;
+
+ if (maxPromisesPerTry > 0)
+ for (var i = 0; i < promises.length; i += maxPromisesPerTry)
+ promisesBatch.push(promises.slice(i, i + maxPromisesPerTry));
+
+ while (promisesBatchIndex < promisesBatch.length && maxTries > 0) {
+ try {
+ (await Promise.all(promisesBatch[promisesBatchIndex])).map(
+ targetObjectUpdated => {
+ targetObject = Object.assign(targetObject, targetObjectUpdated);
+ }
+ );
+ promisesBatchIndex++;
+ } catch (e) {
+ console.error(e);
+ maxTries--;
+ await sleep(sleepTimeBetweenRetries);
+ if (maxTries === 0)
+ console.error('[BATCH PROMISES] (max errors reached)');
+ }
+ }
+ return targetObject;
+}
+
+export async function batchPromises(
+ promises,
+ maxPromisesPerTry = 0,
+ maxTries = 10,
+ sleepTimeBetweenRetries = 100
+) {
+ let promisesBatch = maxPromisesPerTry === 0 ? [promises] : [];
+ let promisesBatchIndex = 0;
+
+ if (maxPromisesPerTry > 0)
+ for (var i = 0; i < promises.length; i += maxPromisesPerTry)
+ promisesBatch.push(promises.slice(i, i + maxPromisesPerTry));
+
+ while (promisesBatchIndex < promisesBatch.length && maxTries > 0) {
+ try {
+ await Promise.all(promisesBatch[promisesBatchIndex]);
+ promisesBatchIndex++;
+ } catch (e) {
+ console.error(e);
+ maxTries--;
+ await sleep(sleepTimeBetweenRetries);
+ if (maxTries === 0)
+ console.error('[BATCH PROMISES] (max errors reached)');
+ }
+ }
+ return;
+}
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
index 9bfa25902f..ca1f59fcc7 100644
--- a/src/utils/constants.ts
+++ b/src/utils/constants.ts
@@ -39,7 +39,7 @@ export const NETWORKS: ChainConfig[] =
id: 1,
name: 'mainnet',
displayName: 'Ethereum Mainnet',
- defaultRpc: POKT_NETWORK_URLS['1'],
+ defaultRpc: `https://eth-mainnet.alchemyapi.io/v2/${defaultAlchemyKey}`,
nativeAsset: {
name: 'Ethereum',
symbol: 'ETH',
@@ -116,7 +116,7 @@ export const NETWORKS: ChainConfig[] =
id: 1,
name: 'mainnet',
displayName: 'Ethereum Mainnet',
- defaultRpc: POKT_NETWORK_URLS['1'],
+ defaultRpc: `https://eth-mainnet.alchemyapi.io/v2/${defaultAlchemyKey}`,
nativeAsset: {
name: 'Ethereum',
symbol: 'ETH',
diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts
index 1c857b62b3..acb9daf43b 100644
--- a/src/utils/helpers.ts
+++ b/src/utils/helpers.ts
@@ -87,3 +87,28 @@ export const appendEthAPIKey = (
export function escapeRegExp(string: string): string {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
+
+export async function retryPromise(
+ promise: Promise,
+ timeToWait: number = 0,
+ maxTries: number = 10
+): Promise {
+ let toReturn;
+ while (!toReturn && maxTries > 0) {
+ try {
+ toReturn = await promise;
+ if (!toReturn) {
+ await sleep(timeToWait);
+ maxTries--;
+ }
+ } catch (error) {
+ console.warn(error);
+ await sleep(timeToWait);
+ maxTries--;
+ } finally {
+ if (maxTries === 0) console.error('[RETRY PROMISE] (max errors reached)');
+ else maxTries = 0;
+ }
+ }
+ return toReturn;
+}
diff --git a/src/utils/proposals.ts b/src/utils/proposals.ts
index 0d2f65668e..57988b3ff3 100644
--- a/src/utils/proposals.ts
+++ b/src/utils/proposals.ts
@@ -200,29 +200,7 @@ export const decodeProposalStatus = function (
pendingAction: PendingAction.None,
};
case VotingMachineProposalState.Executed:
- if (
- proposal.stateInScheme === WalletSchemeProposalState.Rejected &&
- schemeType === 'ContributionReward'
- )
- return {
- status: 'Passed',
- boostTime: boostedPhaseTime,
- finishTime: proposalStateChangeEvents.find(
- event => Number(event.state) === VotingMachineProposalState.Executed
- )
- ? bnum(
- proposalStateChangeEvents.find(
- event =>
- Number(event.state) === VotingMachineProposalState.Executed
- ).timestamp
- )
- : bnum(0),
- pendingAction: PendingAction.Redeem,
- };
- else if (
- proposal.winningVote == '2' ||
- proposal.stateInScheme === WalletSchemeProposalState.Rejected
- )
+ if (proposal.stateInScheme === WalletSchemeProposalState.Rejected)
return {
status: 'Proposal Rejected',
boostTime: boostedPhaseTime,
@@ -236,11 +214,7 @@ export const decodeProposalStatus = function (
).timestamp
)
: bnum(0),
- pendingAction:
- schemeType === 'ContributionReward' &&
- proposal.stateInVotingMachine < 3
- ? PendingAction.Redeem
- : PendingAction.None,
+ pendingAction: PendingAction.None,
};
else if (
proposal.stateInScheme === WalletSchemeProposalState.ExecutionSucceded
diff --git a/yarn.lock b/yarn.lock
index 801e022b56..5a7f7c2e91 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1489,6 +1489,45 @@
debug "^3.1.0"
lodash.once "^4.1.1"
+"@dnd-kit/accessibility@^3.0.0":
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@dnd-kit/accessibility/-/accessibility-3.0.0.tgz#b56e3750414fd907b7d6972b3116aa8f96d07fde"
+ integrity sha512-QwaQ1IJHQHMMuAGOOYHQSx7h7vMZPfO97aDts8t5N/MY7n2QTDSnW+kF7uRQ1tVBkr6vJ+BqHWG5dlgGvwVjow==
+ dependencies:
+ tslib "^2.0.0"
+
+"@dnd-kit/core@^5.0.3":
+ version "5.0.3"
+ resolved "https://registry.yarnpkg.com/@dnd-kit/core/-/core-5.0.3.tgz#028d7e543e9fd3756f9cb857b34f818d73020810"
+ integrity sha512-IribcBLsaPqHdYLpc5xG0TqwYIaD+65offdEYxoKh38WDjzRxUjDmrt7hj9oa/ooUKL0epux20u+mBTd92i/zw==
+ dependencies:
+ "@dnd-kit/accessibility" "^3.0.0"
+ "@dnd-kit/utilities" "^3.1.0"
+ tslib "^2.0.0"
+
+"@dnd-kit/modifiers@^5.0.0":
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/@dnd-kit/modifiers/-/modifiers-5.0.0.tgz#c2ba0bfdb6bed994affcfc4c86834795b7a7f029"
+ integrity sha512-ZVOfa5dKmvAPBxjjnI4QTm8fHV4/gMdS6k0zY5Z8p/p9HkL/3QEHn2fYgqM2zVDpxf5maqrZ4MvqXILSPNQPMQ==
+ dependencies:
+ "@dnd-kit/utilities" "^3.1.0"
+ tslib "^2.0.0"
+
+"@dnd-kit/sortable@^6.0.1":
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/@dnd-kit/sortable/-/sortable-6.0.1.tgz#08d046efa85c546fd21979836b007d6fea1001f9"
+ integrity sha512-FGpRHBcflpwWpSP8bMJ4zNcDywDXssZDJBwGYuHd1RqUU/+JX43pEU0u0OHw06LabEZMOLBbyWoIaZJ0abCOEA==
+ dependencies:
+ "@dnd-kit/utilities" "^3.1.0"
+ tslib "^2.0.0"
+
+"@dnd-kit/utilities@^3.1.0":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@dnd-kit/utilities/-/utilities-3.1.0.tgz#330ef24303da05f85ff20bb8f74b385c96caee58"
+ integrity sha512-2JBdIgjJ7xjMRpKagdMuYKWJdDoVVw9Wc6lfMrLjrq8t4QlMEjtsab5JVUlzWvHgANn7w3Y3VhalFfbp4dQrKg==
+ dependencies:
+ tslib "^2.0.0"
+
"@electron/get@^1.13.0":
version "1.14.1"
resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.14.1.tgz#16ba75f02dffb74c23965e72d617adc721d27f40"
@@ -3142,15 +3181,15 @@
find-up "^4.1.0"
fs-extra "^8.1.0"
-"@openzeppelin/contracts-upgradeable@4.3.2":
- version "4.3.2"
- resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.3.2.tgz#92df481362e366c388fc02133cf793029c744cea"
- integrity sha512-i/pOaOtcqDk4UqsrOv735uYyTbn6dvfiuVu5hstsgV6c4ZKUtu88/31zT2BzkCg+3JfcwOfgg2TtRKVKKZIGkQ==
+"@openzeppelin/contracts-upgradeable@4.4.0":
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.4.0.tgz#85161d87c840c5bce2b6ed0c727b407e774852ae"
+ integrity sha512-hIEyWJHu7bDTv6ckxOaV+K3+7mVzhjtyvp3QSaz56Rk5PscXtPAbkiNTb3yz6UJCWHPWpxVyULVgZ6RubuFEZg==
-"@openzeppelin/contracts@4.3.2":
- version "4.3.2"
- resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.3.2.tgz#ff80affd6d352dbe1bbc5b4e1833c41afd6283b6"
- integrity sha512-AybF1cesONZStg5kWf6ao9OlqTZuPqddvprc0ky7lrUVOjXeKpmQ2Y9FK+6ygxasb+4aic4O5pneFBfwVsRRRg==
+"@openzeppelin/contracts@4.4.0":
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.4.0.tgz#4a1df71f736c31230bbbd634dfb006a756b51e6b"
+ integrity sha512-dlKiZmDvJnGRLHojrDoFZJmsQVeltVeoiRN7RK+cf2FmkhASDEblE0RiaYdxPNsUZa6mRG8393b9bfyp+V5IAw==
"@openzeppelin/test-helpers@^0.5.15":
version "0.5.15"
@@ -3238,11 +3277,6 @@
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
-"@realitio/realitio-contracts@>=0.0.0":
- version "2.2.9"
- resolved "https://registry.yarnpkg.com/@realitio/realitio-contracts/-/realitio-contracts-2.2.9.tgz#4274dd0ceca6d1b64a13553fe458312c920680d7"
- integrity sha512-Ka4oMm6a7+W4kVcDjPa4Ov0pstd4nGk+2/rt8ShL6COwLFIgeybJmoZYBSCqLDrqfYk9N1glCjpBbU0EojTRTg==
-
"@resolver-engine/core@^0.2.1":
version "0.2.1"
resolved "https://registry.yarnpkg.com/@resolver-engine/core/-/core-0.2.1.tgz#0d71803f6d3b8cb2e9ed481a1bf0ca5f5256d0c0"
@@ -9054,15 +9088,14 @@ duplexify@^3.4.2, duplexify@^3.6.0:
readable-stream "^2.0.0"
stream-shift "^1.0.0"
-"dxdao-contracts@https://github.com/DXGovernance/dxdao-contracts.git#develop":
- version "0.0.1"
- resolved "https://github.com/DXGovernance/dxdao-contracts.git#4361fd7270d275f8d046471b4bbfa3b1062d15ab"
+"dxdao-contracts@https://github.com/DXGovernance/dxdao-contracts.git#12ea7f4e1ea070699d148d8c4ced4aaa88f08627":
+ version "1.0.0"
+ resolved "https://github.com/DXGovernance/dxdao-contracts.git#12ea7f4e1ea070699d148d8c4ced4aaa88f08627"
dependencies:
"@maticnetwork/eth-decoder" "^0.0.4"
- "@openzeppelin/contracts" "4.3.2"
- "@openzeppelin/contracts-upgradeable" "4.3.2"
+ "@openzeppelin/contracts" "4.4.0"
+ "@openzeppelin/contracts-upgradeable" "4.4.0"
"@openzeppelin/test-helpers" "^0.5.15"
- "@realitio/realitio-contracts" ">=0.0.0"
"@truffle/hdwallet-provider" "^1.4.0"
arb-ethers-web3-bridge "^0.7.3"
chai "^4.2.0"