diff --git a/packages/client/src/components/Actions/components/SignerThresholdView.js b/packages/client/src/components/Actions/components/SignerThresholdView.js index a9102dd..6fadc42 100644 --- a/packages/client/src/components/Actions/components/SignerThresholdView.js +++ b/packages/client/src/components/Actions/components/SignerThresholdView.js @@ -38,7 +38,7 @@ const SignerThresholdView = ({ actionView, safeData, isAdd }) => { Signature Threshold
- {newThreshold} of{safeOwners.length} owner(s) + {newThreshold} of {safeOwners.length} owner(s)
diff --git a/packages/client/src/components/Actions/components/ThresholdView.js b/packages/client/src/components/Actions/components/ThresholdView.js index 1063d8c..db4a9e7 100644 --- a/packages/client/src/components/Actions/components/ThresholdView.js +++ b/packages/client/src/components/Actions/components/ThresholdView.js @@ -8,7 +8,7 @@ const ThresholdView = ({ actionView, safeData }) => {
Signature Threshold
- {newThreshold} of{safeOwners?.length} owners + {newThreshold} of {safeOwners?.length} owners
diff --git a/packages/client/src/components/SafeSettings/components/EditThreshold/EditThresholdForm.js b/packages/client/src/components/SafeSettings/components/EditThreshold/EditThresholdForm.js index 8d968c8..26b1d26 100644 --- a/packages/client/src/components/SafeSettings/components/EditThreshold/EditThresholdForm.js +++ b/packages/client/src/components/SafeSettings/components/EditThreshold/EditThresholdForm.js @@ -42,7 +42,7 @@ const EditThresholdForm = ({
- {newThreshold} of{Math.max(safeOwners.length, 1)} owner(s) + {newThreshold} of {Math.max(safeOwners.length, 1)} owner(s)
{ const { openModal, closeModal } = useModalContext(); const history = useHistory(); const web3 = useContext(Web3Context); - const { setTreasury, proposeAddSigner, proposeRemoveSigner } = web3; + const { setAddressAlias, proposeAddSigner, proposeRemoveSigner } = web3; const { address, safeOwners, threshold } = treasury; const verifiedSafeOwners = safeOwners.filter((o) => o.verified); let allSafeOwners; @@ -36,15 +36,15 @@ const EditThreshold = ({ treasury, newOwner, ownerToBeRemoved }) => { const onChangeThreshold = (isIncrease) => { setNewThreshold((prevState) => - isIncrease ? prevState + 1 : prevState - 1 + (isIncrease ? prevState + 1 : prevState - 1) ); }; const onConfirmAddOwner = async () => { await proposeAddSigner(formatAddress(newOwner.address), newThreshold); - setTreasury(address, { - safeOwners: [...safeOwners, { ...newOwner, verified: false }], - }); + if (newOwner.name) { + setAddressAlias(newOwner.address, newOwner.name) + } closeModal(); history.push(`/safe/${address}`); }; @@ -110,3 +110,4 @@ const EditThreshold = ({ treasury, newOwner, ownerToBeRemoved }) => { }; export default EditThreshold; + \ No newline at end of file diff --git a/packages/client/src/components/SafeSettings/components/Owners/AddSafeOwner.js b/packages/client/src/components/SafeSettings/components/Owners/AddSafeOwner.js index 38fdd3e..3f0b948 100644 --- a/packages/client/src/components/SafeSettings/components/Owners/AddSafeOwner.js +++ b/packages/client/src/components/SafeSettings/components/Owners/AddSafeOwner.js @@ -6,7 +6,12 @@ import { formatAddress, isAddr } from 'utils'; import Svg from 'library/Svg'; import EditThreshold from '../EditThreshold'; -const AddSafeOwner = ({ treasury, safeOwners }) => { +const AddSafeOwner = ({ + treasury, + safeOwners, + addressAliases, + setAddressAlias, +}) => { const web3 = useContext(Web3Context); const { openModal, closeModal } = useModalContext(); const { isAddressValid } = useAddressValidation(web3.injectedProvider); @@ -22,6 +27,13 @@ const AddSafeOwner = ({ treasury, safeOwners }) => { addressValid ? 'has-text-weight-bold' : 'disabled' }`; + const isAddressExisting = (_safeOwners, newAddress) => { + const addr = formatAddress(newAddress); + return ( + _safeOwners.filter((obj) => obj.address === addr && obj.verified) + .length !== 0 + ); + }; const onAddressChange = async (newAddress) => { setAddress(newAddress); const isValid = @@ -29,17 +41,17 @@ const AddSafeOwner = ({ treasury, safeOwners }) => { (await isAddressValid(newAddress)) && !isAddressExisting(safeOwners, newAddress); setAddressValid(isValid); - }; - - const isAddressExisting = (safeOwners, newAddress) => { - const address = formatAddress(newAddress); - return ( - safeOwners.filter((obj) => obj.address === address && obj.verified) - .length !== 0 - ); + if (addressAliases[newAddress]) { + setName(addressAliases[newAddress]); + } }; const onNextClick = () => { + // Set Address Alias + if (name) { + setAddressAlias(address, name); + } + // Open Edit Threshold Modal openModal( , { headerTitle: 'Set A New Threshold' } diff --git a/packages/client/src/components/SafeSettings/components/Owners/index.js b/packages/client/src/components/SafeSettings/components/Owners/index.js index 6299ba4..815db18 100644 --- a/packages/client/src/components/SafeSettings/components/Owners/index.js +++ b/packages/client/src/components/SafeSettings/components/Owners/index.js @@ -5,7 +5,7 @@ import Svg from 'library/Svg'; import AddSafeOwner from './AddSafeOwner'; import RemoveSafeOwner from './RemoveSafeOwner'; -const Owners = ({ treasury }) => { +const Owners = ({ treasury, addressAliases, setAddressAlias }) => { const modalContext = useModalContext(); const { safeOwners } = treasury; const verifiedSafeOwners = safeOwners.filter((o) => o.verified); @@ -13,7 +13,12 @@ const Owners = ({ treasury }) => { const openAddOwnerModal = () => { modalContext.openModal( - , + , { headerTitle: 'Add Owner', } @@ -51,7 +56,7 @@ const Owners = ({ treasury }) => { verifiedSafeOwners.map((so, idx) => (
- {so.name ?? `Signer #${idx + 1}`} + {addressAliases[so.address] ?? `Signer #${idx + 1}`}
{so.address}
diff --git a/packages/client/src/components/SafeSettings/components/SafeDetailsSetting/EditSafeName.js b/packages/client/src/components/SafeSettings/components/SafeDetailsSetting/EditSafeName.js index 1968ede..ed4181f 100644 --- a/packages/client/src/components/SafeSettings/components/SafeDetailsSetting/EditSafeName.js +++ b/packages/client/src/components/SafeSettings/components/SafeDetailsSetting/EditSafeName.js @@ -1,7 +1,8 @@ import { useState } from 'react'; const EditSafeName = ({ name, onCancel, onSubmit }) => { - const [currSafeName, setCurrSafeName] = useState(name); + const [currSafeName, setCurrSafeName] = useState(name ?? ''); + const isNameValid = currSafeName.trim().length > 0; const onSubmitClick = () => { diff --git a/packages/client/src/components/SafeSettings/components/SafeDetailsSetting/index.js b/packages/client/src/components/SafeSettings/components/SafeDetailsSetting/index.js index f62452d..41919b3 100644 --- a/packages/client/src/components/SafeSettings/components/SafeDetailsSetting/index.js +++ b/packages/client/src/components/SafeSettings/components/SafeDetailsSetting/index.js @@ -1,12 +1,18 @@ import React from 'react'; import { useModalContext } from 'contexts'; -import { useClipboard } from 'hooks'; +import { useClipboard, useAddressAliases } from 'hooks'; import EditSafeName from './EditSafeName'; const SafeDetailsSetting = ({ treasury, setTreasury }) => { const modalContext = useModalContext(); const { name, address } = treasury; const safeAddressClipboard = useClipboard(); + const { setTreasuryAlias } = useAddressAliases(); + + const onEditNameSubmit = (newName) => { + setTreasuryAlias(address, newName); + modalContext.closeModal(); + }; const openEditNameModal = () => { modalContext.openModal( { /> ); }; - const onEditNameSubmit = (newName) => { - setTreasury(address, { name: newName }); - modalContext.closeModal(); - }; + return (
diff --git a/packages/client/src/components/SafeSettings/index.js b/packages/client/src/components/SafeSettings/index.js index c1ec070..ab75699 100644 --- a/packages/client/src/components/SafeSettings/index.js +++ b/packages/client/src/components/SafeSettings/index.js @@ -25,6 +25,8 @@ const SafeSettings = () => { addCollection, removeVault, removeCollection, + addressAliases, + setAddressAlias } = web3; useEffect(() => { (() => { @@ -38,7 +40,11 @@ const SafeSettings = () => { <> - +

@@ -24,7 +24,7 @@ function Safes(props) { return (

diff --git a/packages/client/src/components/SignatureRequirements.js b/packages/client/src/components/SignatureRequirements.js index b40a66d..cddc50b 100644 --- a/packages/client/src/components/SignatureRequirements.js +++ b/packages/client/src/components/SignatureRequirements.js @@ -54,7 +54,7 @@ function SignatureRequirements({
- {signersAmount} of{Math.max(safeOwners.length, 1)} owner(s) + {signersAmount} of {Math.max(safeOwners.length, 1)} owner(s)
() ?? panic("A DAOTreasuryV5 doesn't exist here.") + let signers = treasury.borrowManagerPublic().getSigners() + let safeOwners: [SafeOwner] = [] + for addr in signers.keys { + let owner = SafeOwner(address: addr) + safeOwners.append(owner) + } + return TreasuryInfo( uuid: treasury.uuid, - signers: treasury.borrowManagerPublic().getSigners(), + safeOwners: safeOwners, threshold: treasury.borrowManagerPublic().getThreshold() ) } diff --git a/packages/client/src/hooks/index.js b/packages/client/src/hooks/index.js index e3bbe32..2f63a32 100644 --- a/packages/client/src/hooks/index.js +++ b/packages/client/src/hooks/index.js @@ -9,3 +9,4 @@ export { default as useFlowFees } from './useFlowFees'; export { default as useErrorMessage } from './useErrorMessage'; export { default as useAccount } from './useAccount'; export { default as useContacts } from './useContacts'; +export { default as useAddressAliases } from './useAddressAliases'; diff --git a/packages/client/src/hooks/useAddressAliases.js b/packages/client/src/hooks/useAddressAliases.js new file mode 100644 index 0000000..e43e609 --- /dev/null +++ b/packages/client/src/hooks/useAddressAliases.js @@ -0,0 +1,70 @@ +import { useEffect, useMemo, useReducer } from 'react'; +import addressAliasReducer, { + ADDRESS_ALIAS_INITIAL_STATE, +} from 'reducers/addressAliasReducer'; + +const storageKey = 'vessel-addresses'; +const treasuryStorageKey = 'vessel-treasuries'; + +export default function useAddressAliases() { + const [state, dispatch] = useReducer(addressAliasReducer, [], (initial) => ({ + ...initial, + ...ADDRESS_ALIAS_INITIAL_STATE, + addressAliases: JSON.parse(localStorage.getItem(storageKey) || '{}'), + treasuryAliases: JSON.parse( + localStorage.getItem(treasuryStorageKey) || '{}' + ), + })); + + const addressAliases = useMemo( + () => state.addressAliases ?? {}, + [state.addressAliases] + ); + + const treasuryAliases = useMemo( + () => state.treasuryAliases ?? {}, + [state.treasuryAliases] + ); + + useEffect(() => { + localStorage.setItem(storageKey, JSON.stringify(addressAliases)); + }, [addressAliases]); + + useEffect(() => { + localStorage.setItem(treasuryStorageKey, JSON.stringify(treasuryAliases)); + }, [treasuryAliases]); + + const setTreasuryAlias = (addr, name) => { + dispatch({ + type: 'SET_TREASURY_ALIAS', + payload: { + [addr]: name, + }, + }); + }; + + const setAddressAlias = (addr, name) => { + console.log('set address alias!', addr, name); + dispatch({ + type: 'SET_ADDRESS_ALIAS', + payload: { + [addr]: name, + }, + }); + }; + + const removeAddressAlias = (addr) => { + dispatch({ + type: 'REMOVE_ADDRESS_ALIAS', + payload: addr, + }); + }; + + return { + addressAliases: JSON.parse(localStorage.getItem(storageKey)) ?? {}, + treasuryAliases: JSON.parse(localStorage.getItem(treasuryStorageKey)) ?? {}, + setAddressAlias, + removeAddressAlias, + setTreasuryAlias, + }; +} diff --git a/packages/client/src/hooks/useNFTs.js b/packages/client/src/hooks/useNFTs.js index f7a6877..7bca6de 100644 --- a/packages/client/src/hooks/useNFTs.js +++ b/packages/client/src/hooks/useNFTs.js @@ -1,4 +1,4 @@ -import { useEffect, useReducer } from 'react'; +import { useReducer } from 'react'; import { createSignature } from '../contexts/Web3'; import { REGULAR_LIMIT, SIGNED_LIMIT } from 'constants/constants'; import { formatAddress, parseIdentifier, removeAddressPrefix } from 'utils'; @@ -15,8 +15,6 @@ import { } from '../flow'; import nftReducer, { NFT_INITIAL_STATE } from '../reducers/nftReducer'; -const storageKey = 'vessel-collections'; - const doSendNFTToTreasury = async (treasuryAddr, tokenId) => await mutate({ cadence: SEND_NFT_TO_TREASURY, @@ -92,13 +90,8 @@ export default function useNFTs(treasuryAddr) { const [state, dispatch] = useReducer(nftReducer, [], (initial) => ({ ...initial, ...NFT_INITIAL_STATE, - NFTs: JSON.parse(localStorage.getItem(storageKey) || '{}'), })); - useEffect(() => { - localStorage.setItem(storageKey, JSON.stringify(state.NFTs)); - }, [state.NFTs]); - const checkCollection = async (treasuryAddr, identifier) => { let result = []; try { diff --git a/packages/client/src/hooks/useTreasury.js b/packages/client/src/hooks/useTreasury.js index 4088537..0111691 100644 --- a/packages/client/src/hooks/useTreasury.js +++ b/packages/client/src/hooks/useTreasury.js @@ -34,8 +34,6 @@ import treasuryReducer, { TREASURY_INITIAL_STATE, } from '../reducers/treasuryReducer'; -const storageKey = 'vessel-treasuries'; - const doQuery = async (cadence, address) => { const queryResp = await query({ cadence, @@ -246,11 +244,11 @@ const getAllVaultBalance = async (address) => { } return allBalance; }; -export default function useTreasury(treasuryAddr) { +export default function useTreasury(treasuryAddr, treasuryAliases) { const [state, dispatch] = useReducer(treasuryReducer, [], (initial) => ({ ...initial, ...TREASURY_INITIAL_STATE, - treasuries: JSON.parse(localStorage.getItem(storageKey)) || {}, + treasuries: {}, })); const refreshTreasury = async () => { @@ -260,6 +258,8 @@ export default function useTreasury(treasuryAddr) { return; } + treasuryData.name = treasuryAliases[treasuryAddr] || ''; + dispatch({ type: 'SET_TREASURY', payload: { @@ -304,20 +304,6 @@ export default function useTreasury(treasuryAddr) { }); }; - const updateOwnerList = async (treasuryAddr) => { - const { signers } = await getTreasury(treasuryAddr); - const { safeOwners } = state.treasuries[treasuryAddr]; - const updatedSafeOwners = syncSafeOwnersWithSigners(signers, safeOwners); - dispatch({ - type: 'SET_TREASURY', - payload: { - [treasuryAddr]: { - safeOwners: updatedSafeOwners, - }, - }, - }); - }; - useEffect(() => { if (!treasuryAddr) { if (state.loadingTreasuries) { @@ -333,10 +319,14 @@ export default function useTreasury(treasuryAddr) { // eslint-disable-next-line }, [state.loadingTreasuries, treasuryAddr]); - useEffect(() => { - localStorage.setItem(storageKey, JSON.stringify(state.treasuries)); - }, [state.treasuries]); - + const setTreasury = (_treasuryAddr, treasuryData) => { + dispatch({ + type: 'SET_TREASURY', + payload: { + [_treasuryAddr]: treasuryData, + }, + }); + }; const createTreasury = async (treasuryData) => { const { safeOwners, threshold } = treasuryData; const signerAddresses = safeOwners.map((is) => formatAddress(is.address)); @@ -349,14 +339,6 @@ export default function useTreasury(treasuryAddr) { setTreasury(creatorAddr, treasuryData); return res; }; - const setTreasury = (treasuryAddr, treasuryData) => { - dispatch({ - type: 'SET_TREASURY', - payload: { - [treasuryAddr]: treasuryData, - }, - }); - }; const proposeTransfer = async (recipientAddr, amount, coinType) => { const res = await doProposeTransfer( @@ -410,7 +392,6 @@ export default function useTreasury(treasuryAddr) { const res = await doExecuteAction(treasuryAddr, actionUUID); const result = await tx(res).onceSealed(); await refreshTreasury(); - await updateOwnerList(treasuryAddr); return result.events; }; diff --git a/packages/client/src/hooks/useVaults.js b/packages/client/src/hooks/useVaults.js index 9965ad4..cca7c10 100644 --- a/packages/client/src/hooks/useVaults.js +++ b/packages/client/src/hooks/useVaults.js @@ -1,4 +1,4 @@ -import { useEffect, useReducer } from 'react'; +import { useReducer } from 'react'; import { createSignature } from 'contexts/Web3'; import { SIGNED_LIMIT } from 'constants/constants'; import { COIN_TYPE_TO_META } from 'constants/maps'; @@ -7,8 +7,6 @@ import { config, mutate, query, tx } from '@onflow/fcl'; import { ADD_VAULT, GET_TREASURY_IDENTIFIERS, REMOVE_VAULT } from '../flow'; import vaultReducer, { VAULT_INITIAL_STATE } from '../reducers/vaultReducer'; -const storageKey = 'vessel-vaults'; - const doAddVault = async (treasuryAddr, contractName, contractAddress) => { const intent = `A.${removeAddressPrefix( contractAddress @@ -51,12 +49,8 @@ export default function useVaults(treasuryAddr) { const [state, dispatch] = useReducer(vaultReducer, [], (initial) => ({ ...initial, ...VAULT_INITIAL_STATE, - vaults: JSON.parse(localStorage.getItem(storageKey) || '{}'), })); - useEffect(() => { - localStorage.setItem(storageKey, JSON.stringify(state.vaults)); - }, [state.vaults]); const getTreasuryVaults = async (treasuryAddr) => { const identifiers = await query({ diff --git a/packages/client/src/modals/Transaction/BannerInfo.js b/packages/client/src/modals/Transaction/BannerInfo.js index 15e84e4..5153654 100644 --- a/packages/client/src/modals/Transaction/BannerInfo.js +++ b/packages/client/src/modals/Transaction/BannerInfo.js @@ -96,7 +96,7 @@ const BannerInfo = ({ {actionType === ACTION_TYPES.UPDATE_THRESHOLD && ( - {signers.length} of{newThreshold} owners + {signers.length} of {newThreshold} owners )} diff --git a/packages/client/src/modals/Transaction/Details.js b/packages/client/src/modals/Transaction/Details.js index 57acab1..33ae405 100644 --- a/packages/client/src/modals/Transaction/Details.js +++ b/packages/client/src/modals/Transaction/Details.js @@ -96,7 +96,7 @@ const TransactionDetails = ({ onClose, safeData = {}, transaction = {} }) => {
Signature Threshold
- {Object.keys(signers).length} of{threshold} owners + {Object.keys(signers).length} of {threshold} owners
)} diff --git a/packages/client/src/pages/LoadSafe.js b/packages/client/src/pages/LoadSafe.js index ca0a201..6a9500d 100644 --- a/packages/client/src/pages/LoadSafe.js +++ b/packages/client/src/pages/LoadSafe.js @@ -60,7 +60,15 @@ function LoadSafe({ web3 }) { const [threshold, setThreshold] = useState(0); const [safeOwners, setSafeOwners] = useState([]); const [safeOwnersValidByAddress, setSafeOwnersValidByAddress] = useState({}); - const { injectedProvider, getTreasury, setTreasury, address } = web3; + const { + injectedProvider, + getTreasury, + setTreasury, + address, + setAddressAlias, + setTreasuryAlias, + addressAliases, + } = web3; const { isAddressValid } = useAddressValidation(injectedProvider); if (!address) { return ; @@ -83,13 +91,10 @@ function LoadSafe({ web3 }) { const maybeValid = isAddr(e.target.value); if (maybeValid) { const treasury = await getTreasury(e.target.value); - const newSafeOwners = Object.keys(treasury?.signers ?? {}).map( - (signerAddr) => ({ - name: '', - address: signerAddr, - verified: true, - }) - ); + const newSafeOwners = (treasury?.safeOwners ?? []).map((owner) => ({ + name: addressAliases[owner.address], + address: owner.address, + })); setSafeOwners(newSafeOwners); checkSafeOwnerAddressesValidity(newSafeOwners); @@ -104,10 +109,20 @@ function LoadSafe({ web3 }) { const onOwnerNameChange = (value, idx) => { const newOwners = safeOwners.slice(0); newOwners[idx].name = value; - setSafeOwners([...newOwners]); }; const onSetTreasury = () => { + // Set Address Aliases + safeOwners.forEach((so) => { + if (so.name) { + setAddressAlias(so.address, so.name); + } + }); + + // Set Treasury Alias + setTreasuryAlias(safeAddress, safeName); + + // Set Treasury setTreasury(safeAddress, { name: safeName, type: 'Social', @@ -241,7 +256,7 @@ function LoadSafe({ web3 }) {
- {threshold} of{safeOwners.length} owner(s) + {threshold} of {safeOwners.length} owner(s)
diff --git a/packages/client/src/pages/Safe.js b/packages/client/src/pages/Safe.js index b58cbd8..678e8ce 100644 --- a/packages/client/src/pages/Safe.js +++ b/packages/client/src/pages/Safe.js @@ -117,9 +117,7 @@ function Safe({ web3 }) { }; const onExecuteAction = async ({ uuid }) => { - const events = await executeAction(uuid).catch((error) => - showErrorModal(error) - ); + const events = await executeAction(uuid).catch(showErrorModal); if (events) { const action = events.find((e) => e.type.endsWith('ActionExecuted')); showTransactionSuccessModal(action); diff --git a/packages/client/src/reducers/addressAliasReducer.js b/packages/client/src/reducers/addressAliasReducer.js new file mode 100644 index 0000000..ecff48e --- /dev/null +++ b/packages/client/src/reducers/addressAliasReducer.js @@ -0,0 +1,41 @@ +/* + * addressAliases is a dicitonary of address[name] + */ +export const ADDRESS_ALIAS_INITIAL_STATE = { + addressAliases: {}, +}; + +const addressAliasReducer = (state, action) => { + switch (action.type) { + case 'SET_ADDRESS_ALIAS': { + return { + ...state, + addressAliases: { + ...state.addressAliases, + ...action.payload, + }, + }; + } + case 'REMOVE_ADDRESS_ALIAS': { + const aliases = state.addressAliases; + delete aliases[action.payload]; + return { + ...state, + addressAliases: aliases, + }; + } + case 'SET_TREASURY_ALIAS': { + return { + ...state, + treasuryAliases: { + ...state.treasuryAliases, + ...action.payload, + }, + }; + } + default: + throw new Error(); + } +}; + +export default addressAliasReducer; diff --git a/packages/client/src/reducers/treasuryReducer.js b/packages/client/src/reducers/treasuryReducer.js index fc94a1b..36a1d4a 100644 --- a/packages/client/src/reducers/treasuryReducer.js +++ b/packages/client/src/reducers/treasuryReducer.js @@ -22,7 +22,6 @@ const treasuryReducer = (state, action) => { treasuries: { ...state.treasuries, [address]: { - ...state.treasuries[address], ...action.payload[address], }, },