From aaae84395e7c3303b26a1b72a761d7240f25b9af Mon Sep 17 00:00:00 2001 From: Ksenija Blanusa Date: Thu, 13 Oct 2022 10:07:43 -0700 Subject: [PATCH 1/7] VSL-224: Moved ApprovalRequired to modals --- .../components/Actions/ActionsListTable.js | 2 +- .../components => modals}/ApprovalRequired.js | 20 +++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) rename packages/client/src/{components/Actions/components => modals}/ApprovalRequired.js (76%) diff --git a/packages/client/src/components/Actions/ActionsListTable.js b/packages/client/src/components/Actions/ActionsListTable.js index 7d24e3c..f6d45fa 100644 --- a/packages/client/src/components/Actions/ActionsListTable.js +++ b/packages/client/src/components/Actions/ActionsListTable.js @@ -1,11 +1,11 @@ import { useContext } from 'react'; import { useModalContext } from 'contexts'; import { Web3Context } from 'contexts/Web3'; -import ApprovalRequired from './components/ApprovalRequired'; import { useErrorMessage } from 'hooks'; import { SIGNER_RESPONSES } from 'constants/enums'; import { formatActionString } from 'utils'; import Svg from 'library/Svg'; +import ApprovalRequired from '../../modals/ApprovalRequired'; const Row = ({ threshold, action, displayIndex, onApprove, onSign }) => { const { intent } = action; diff --git a/packages/client/src/components/Actions/components/ApprovalRequired.js b/packages/client/src/modals/ApprovalRequired.js similarity index 76% rename from packages/client/src/components/Actions/components/ApprovalRequired.js rename to packages/client/src/modals/ApprovalRequired.js index d5accbe..71ce3a9 100644 --- a/packages/client/src/components/Actions/components/ApprovalRequired.js +++ b/packages/client/src/modals/ApprovalRequired.js @@ -1,9 +1,9 @@ +import NFTView from '../components/Actions/components/NFTView'; +import SignerThresholdView from '../components/Actions/components/SignerThresholdView'; +import ThresholdView from '../components/Actions/components/ThresholdView'; +import TokenView from '../components/Actions/components/TokenView'; import Signatures from 'components/Signatures'; import { ACTION_TYPES } from 'constants/enums'; -import NFTView from './NFTView'; -import SignerThresholdView from './SignerThresholdView'; -import ThresholdView from './ThresholdView'; -import TokenView from './TokenView'; const ApprovalRequired = ({ safeData, @@ -59,10 +59,18 @@ const ApprovalRequired = ({
- -
From a438125ea4d9bd3e11410522c98275fde3810382 Mon Sep 17 00:00:00 2001 From: Ksenija Blanusa Date: Thu, 13 Oct 2022 12:52:54 -0700 Subject: [PATCH 2/7] VSL-224: Reverted getNameByAddress to return empty when nothing is found --- packages/client/src/utils.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/client/src/utils.js b/packages/client/src/utils.js index 5a6e99f..3a4bd36 100644 --- a/packages/client/src/utils.js +++ b/packages/client/src/utils.js @@ -132,11 +132,9 @@ export const parseIdentifier = (identifier) => { }; }; -export const getNameByAddress = (nameAddressArray, address) => { - const nameAddress = nameAddressArray.find( - (nameAddress) => nameAddress.address === address - ); - return nameAddress?.name ?? address; +export const getNameByAddress = (nameAddressArray, addr) => { + const nameAddress = nameAddressArray.find(({ address }) => address === addr); + return nameAddress?.name; }; export const parseTimestamp = (timestamp) => { From 7c53185215ea7a18db8788d534df022b3a660b45 Mon Sep 17 00:00:00 2001 From: Ksenija Blanusa Date: Fri, 14 Oct 2022 11:04:43 -0700 Subject: [PATCH 3/7] VSL-224: Reused BannerInfo, deleted old components --- .../components/Actions/components/NFTView.js | 57 ------------ .../Actions/components/SignerThresholdView.js | 48 ---------- .../Actions/components/ThresholdView.js | 18 ---- .../Actions/components/TokenView.js | 30 ------- .../EditThreshold/EditThresholdForm.js | 2 +- .../components/SignatureThreshold.js | 2 +- .../src/components/SignatureRequirements.js | 2 +- .../client/src/modals/ApprovalRequired.js | 88 ++++++++++++------- .../src/modals/Transaction/BannerInfo.js | 24 +++-- .../client/src/modals/Transaction/Details.js | 2 +- packages/client/src/pages/LoadSafe.js | 2 +- packages/client/src/utils.js | 2 +- 12 files changed, 76 insertions(+), 201 deletions(-) delete mode 100644 packages/client/src/components/Actions/components/NFTView.js delete mode 100644 packages/client/src/components/Actions/components/SignerThresholdView.js delete mode 100644 packages/client/src/components/Actions/components/ThresholdView.js delete mode 100644 packages/client/src/components/Actions/components/TokenView.js diff --git a/packages/client/src/components/Actions/components/NFTView.js b/packages/client/src/components/Actions/components/NFTView.js deleted file mode 100644 index 45bcaa8..0000000 --- a/packages/client/src/components/Actions/components/NFTView.js +++ /dev/null @@ -1,57 +0,0 @@ -import { useContext, useEffect, useState } from 'react'; -import { Web3Context } from 'contexts/Web3'; -import { formatAddress, parseIdentifier } from 'utils'; -import ProposedDateView from './ProposedDateView'; -import SentFromToView from './SentFromToView'; - -const NFTView = ({ actionView, safeData }) => { - const { recipient, nftId, collectionId, timestamp } = actionView; - const { address: safeAddress } = safeData; - const { contractName: NFTName } = parseIdentifier(collectionId); - - const { getTreasuryNFTReference } = useContext(Web3Context); - const [image, setImage] = useState({}); - - const { name: imageName, imageURI } = image; - - useEffect(() => { - const getImageURL = async () => { - const result = await getTreasuryNFTReference( - NFTName, - formatAddress(safeAddress), - collectionId, - recipient, - nftId - ); - setImage(result); - }; - getImageURL().catch(console.error); - }, [ - NFTName, - safeAddress, - nftId, - collectionId, - recipient, - getTreasuryNFTReference, - ]); - - return ( - <> -
- {imageURI && ( - {imageName} - )} -
- #{nftId} -
- - {NFTName} - -
- - - - ); -}; - -export default NFTView; diff --git a/packages/client/src/components/Actions/components/SignerThresholdView.js b/packages/client/src/components/Actions/components/SignerThresholdView.js deleted file mode 100644 index a9102dd..0000000 --- a/packages/client/src/components/Actions/components/SignerThresholdView.js +++ /dev/null @@ -1,48 +0,0 @@ -import { useContacts } from 'hooks'; -import { getNameByAddress } from 'utils'; -import ProposedDateView from './ProposedDateView'; - -const SignerThresholdView = ({ actionView, safeData, isAdd }) => { - const { signerAddr, newThreshold, timestamp } = actionView; - const { address: safeAddress, safeOwners } = safeData; - - const { contacts } = useContacts(safeAddress); - const signerName = getNameByAddress(contacts, signerAddr); - - return ( - <> - {isAdd ? 'New Owner' : 'Remove Owner'} -
- {signerName && ( - <> -
- - {signerName} - -
-
- - {signerAddr} - -
- - )} - {!signerName && ( - - {signerAddr} - - )} -
- -
- Signature Threshold -
- - {newThreshold} of{safeOwners.length} owner(s) - -
-
- - ); -}; -export default SignerThresholdView; diff --git a/packages/client/src/components/Actions/components/ThresholdView.js b/packages/client/src/components/Actions/components/ThresholdView.js deleted file mode 100644 index 1063d8c..0000000 --- a/packages/client/src/components/Actions/components/ThresholdView.js +++ /dev/null @@ -1,18 +0,0 @@ -import ProposedDateView from './ProposedDateView'; - -const ThresholdView = ({ actionView, safeData }) => { - const { newThreshold, timestamp } = actionView; - const { safeOwners } = safeData; - - return ( -
-
Signature Threshold
-
- {newThreshold} of{safeOwners?.length} owners -
- -
- ); -}; - -export default ThresholdView; diff --git a/packages/client/src/components/Actions/components/TokenView.js b/packages/client/src/components/Actions/components/TokenView.js deleted file mode 100644 index 41abbaf..0000000 --- a/packages/client/src/components/Actions/components/TokenView.js +++ /dev/null @@ -1,30 +0,0 @@ -import { getTokenMeta } from 'utils'; -import Svg from 'library/Svg'; -import ProposedDateView from './ProposedDateView'; -import SentFromToView from './SentFromToView'; - -const TokenView = ({ actionView, safeData }) => { - const { recipient, vaultId, tokenAmount, timestamp } = actionView; - - const { displayName, tokenType } = getTokenMeta(vaultId) || {}; - - return ( -
-

Amount

-
- - {Number(tokenAmount).toLocaleString()} - -
- -
- - -
- - - -
- ); -}; -export default TokenView; 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)
{
- {threshold} out of{verifiedSafeOwners?.length} signatures are required + {threshold} out of {verifiedSafeOwners?.length} signatures are required to confirm a new transaction
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)
{ - const { type: actionType } = actionView; + const { type: actionType, newThreshold } = actionView; + const { contacts } = useContacts(); - const getActionView = () => { - switch (actionType) { - case ACTION_TYPES.TRANSFER_TOKEN: - return ; - case ACTION_TYPES.TRANSFER_NFT: - return ; - case ACTION_TYPES.ADD_SIGNER_UPDATE_THRESHOLD: - return ( - - ); - case ACTION_TYPES.REMOVE_SIGNER_UPDATE_THRESHOLD: - return ( - - ); - case ACTION_TYPES.UPDATE_THRESHOLD: - return ; - default: - return null; - } - }; + let title; + switch (actionType) { + case ACTION_TYPES.TRANSFER_TOKEN: + title = 'Amount'; + break; + case ACTION_TYPES.TRANSFER_NFT: + title = ''; + break; + case ACTION_TYPES.ADD_SIGNER_UPDATE_THRESHOLD: + title = 'New Owner'; + break; + case ACTION_TYPES.REMOVE_SIGNER_UPDATE_THRESHOLD: + title = 'Remove Owner'; + break; + case ACTION_TYPES.UPDATE_THRESHOLD: + title = 'Signature Threshold'; + break; + default: + break; + } return (
- {getActionView()} +

{title}

+ + + {actionType === ACTION_TYPES.TRANSFER_NFT || + (actionType === ACTION_TYPES.TRANSFER_TOKEN && ( + + ))} + {actionType === ACTION_TYPES.ADD_SIGNER_UPDATE_THRESHOLD || + (actionType === ACTION_TYPES.REMOVE_SIGNER_UPDATE_THRESHOLD && ( +
+ + Signature Threshold + +
+ + {newThreshold} of {safeData.safeOwners.length} owner(s) + +
+
+ ))} { - const { getAccountNFTReference } = useContext(Web3Context); + const { getTreasuryNFTReference } = useContext(Web3Context); const [nftMeta, setNFTMeta] = useState(); - const { recipient, nftId, collectionId, vaultId, tokenAmount, signerAddr } = - actionData; + const { + recipient, + nftId, + collectionId, + vaultId, + tokenAmount, + signerAddr, + newThreshold, + } = actionData; const { displayName, tokenType } = getTokenMeta(vaultId); const { contractName: NFTName, contractAddress: NFTAddress } = parseIdentifier(collectionId); - const { name: imageName, thumbnail: imageURI } = nftMeta || {}; + const { name: imageName, imageURI } = nftMeta || {}; const actionType = actionData.type; useEffect(() => { if (actionType === ACTION_TYPES.TRANSFER_NFT) { const getNFTMeta = async () => { - const result = await getAccountNFTReference( + const result = await getTreasuryNFTReference( NFTName, formatAddress(NFTAddress), + collectionId, recipient, nftId ); @@ -44,7 +52,7 @@ const BannerInfo = ({ NFTAddress, nftId, recipient, - getAccountNFTReference, + getTreasuryNFTReference, ]); const contactName = getNameByAddress(contacts, signerAddr); @@ -70,7 +78,7 @@ const BannerInfo = ({ )} {actionType === ACTION_TYPES.TRANSFER_TOKEN && ( <> - + {Number(tokenAmount).toLocaleString()} @@ -95,7 +103,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..ece244c 100644 --- a/packages/client/src/pages/LoadSafe.js +++ b/packages/client/src/pages/LoadSafe.js @@ -241,7 +241,7 @@ function LoadSafe({ web3 }) {
- {threshold} of{safeOwners.length} owner(s) + {threshold} of {safeOwners.length} owner(s)
diff --git a/packages/client/src/utils.js b/packages/client/src/utils.js index 3a4bd36..bafc952 100644 --- a/packages/client/src/utils.js +++ b/packages/client/src/utils.js @@ -134,7 +134,7 @@ export const parseIdentifier = (identifier) => { export const getNameByAddress = (nameAddressArray, addr) => { const nameAddress = nameAddressArray.find(({ address }) => address === addr); - return nameAddress?.name; + return nameAddress?.name ?? addr; }; export const parseTimestamp = (timestamp) => { From d4ab336694d21eb195f4375f0237a4cca8d49e8a Mon Sep 17 00:00:00 2001 From: Ksenija Blanusa Date: Fri, 14 Oct 2022 12:08:35 -0700 Subject: [PATCH 4/7] VSL-224: Added condition to render image uri --- packages/client/src/modals/Transaction/BannerInfo.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/client/src/modals/Transaction/BannerInfo.js b/packages/client/src/modals/Transaction/BannerInfo.js index cbd3b42..0de2770 100644 --- a/packages/client/src/modals/Transaction/BannerInfo.js +++ b/packages/client/src/modals/Transaction/BannerInfo.js @@ -29,8 +29,9 @@ const BannerInfo = ({ const { displayName, tokenType } = getTokenMeta(vaultId); const { contractName: NFTName, contractAddress: NFTAddress } = parseIdentifier(collectionId); - const { name: imageName, imageURI } = nftMeta || {}; + const { name: imageName, imageURI, thumbnail } = nftMeta || {}; const actionType = actionData.type; + const image = imageURI ?? thumbnail; useEffect(() => { if (actionType === ACTION_TYPES.TRANSFER_NFT) { @@ -61,11 +62,11 @@ const BannerInfo = ({
{actionType === ACTION_TYPES.TRANSFER_NFT && ( <> - {imageURI && ( + {image && ( {imageName} )} From 019861564aafd14b2ea41fd60a91df5277938520 Mon Sep 17 00:00:00 2001 From: Ksenija Blanusa Date: Fri, 14 Oct 2022 15:21:45 -0700 Subject: [PATCH 5/7] VSL-224: Updated threshold, text size --- packages/client/src/modals/ApprovalRequired.js | 2 +- packages/client/src/modals/Transaction/BannerInfo.js | 4 ++-- packages/client/src/modals/Transaction/Details.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/client/src/modals/ApprovalRequired.js b/packages/client/src/modals/ApprovalRequired.js index 428b923..4c7f309 100644 --- a/packages/client/src/modals/ApprovalRequired.js +++ b/packages/client/src/modals/ApprovalRequired.js @@ -13,7 +13,7 @@ const ApprovalRequired = ({ onApprove, }) => { const { type: actionType, newThreshold } = actionView; - const { contacts } = useContacts(); + const { contacts } = useContacts(safeData.address); let title; switch (actionType) { diff --git a/packages/client/src/modals/Transaction/BannerInfo.js b/packages/client/src/modals/Transaction/BannerInfo.js index 0de2770..0e4eb63 100644 --- a/packages/client/src/modals/Transaction/BannerInfo.js +++ b/packages/client/src/modals/Transaction/BannerInfo.js @@ -66,7 +66,7 @@ const BannerInfo = ({ {image} )} @@ -79,7 +79,7 @@ const BannerInfo = ({ )} {actionType === ACTION_TYPES.TRANSFER_TOKEN && ( <> - + {Number(tokenAmount).toLocaleString()} diff --git a/packages/client/src/modals/Transaction/Details.js b/packages/client/src/modals/Transaction/Details.js index 33ae405..79e64b6 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 + {threshold} of {Object.keys(signers).length} owners
)} From fa9b56ba6eff1d2f2c85ead269a12e800b0aac3a Mon Sep 17 00:00:00 2001 From: Ksenija Blanusa Date: Fri, 14 Oct 2022 15:25:28 -0700 Subject: [PATCH 6/7] VSL-224: Style and code improvements --- packages/client/src/modals/ApprovalRequired.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/client/src/modals/ApprovalRequired.js b/packages/client/src/modals/ApprovalRequired.js index 4c7f309..e214ea6 100644 --- a/packages/client/src/modals/ApprovalRequired.js +++ b/packages/client/src/modals/ApprovalRequired.js @@ -20,9 +20,7 @@ const ApprovalRequired = ({ case ACTION_TYPES.TRANSFER_TOKEN: title = 'Amount'; break; - case ACTION_TYPES.TRANSFER_NFT: - title = ''; - break; + case ACTION_TYPES.ADD_SIGNER_UPDATE_THRESHOLD: title = 'New Owner'; break; @@ -32,6 +30,7 @@ const ApprovalRequired = ({ case ACTION_TYPES.UPDATE_THRESHOLD: title = 'Signature Threshold'; break; + case ACTION_TYPES.TRANSFER_NFT: default: break; } @@ -39,7 +38,7 @@ const ApprovalRequired = ({ return (
-

{title}

+

{title}

Date: Fri, 14 Oct 2022 16:31:48 -0700 Subject: [PATCH 7/7] VSL-224: Updated banner info with correct nft method, fixed bug for sending nfts from nfts page --- packages/client/src/components/SafeNFTs.js | 16 ++++++---- .../TransferToken/components/ButtonGroup.js | 2 +- .../src/modals/Transaction/BannerInfo.js | 32 ++++++++++++++----- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/packages/client/src/components/SafeNFTs.js b/packages/client/src/components/SafeNFTs.js index 79f229c..3ed7173 100644 --- a/packages/client/src/components/SafeNFTs.js +++ b/packages/client/src/components/SafeNFTs.js @@ -37,6 +37,9 @@ function SafeNFTs({ web3, address }) { .filter((x) => x); const showNFTModal = (collection, token) => { + const { collectionName, key: collectionId } = collection; + const { tokenId } = token; + modalContext.openModal(
@@ -49,11 +52,11 @@ function SafeNFTs({ web3, address }) {

Collection

-

{collection.collectionName}

+

{collectionName}

Number

-

{token.tokenId}

+

{tokenId}

@@ -73,7 +76,7 @@ function SafeNFTs({ web3, address }) { sender={address} initialState={{ assetType: ASSET_TYPES.NFT, - selectedNFT: token, + selectedNFT: { ...token, collectionName: collectionId }, transactionType: TRANSACTION_TYPE.SEND, }} /> @@ -105,14 +108,15 @@ function SafeNFTs({ web3, address }) { ); } else { nftsToDisplay.forEach((collection) => { + const { collectionName, tokens } = collection; assetComponents.push(
-

{collection.collectionName}

+

{collectionName}

- {collection.tokens.map((token) => ( + {tokens.map((token) => (
{ const modalContext = useModalContext(); diff --git a/packages/client/src/modals/Transaction/BannerInfo.js b/packages/client/src/modals/Transaction/BannerInfo.js index 0e4eb63..5bc6087 100644 --- a/packages/client/src/modals/Transaction/BannerInfo.js +++ b/packages/client/src/modals/Transaction/BannerInfo.js @@ -15,7 +15,8 @@ const BannerInfo = ({ contacts = {}, signers = [], }) => { - const { getTreasuryNFTReference } = useContext(Web3Context); + const { getAccountNFTReference, getTreasuryNFTReference } = + useContext(Web3Context); const [nftMeta, setNFTMeta] = useState(); const { recipient, @@ -25,6 +26,7 @@ const BannerInfo = ({ tokenAmount, signerAddr, newThreshold, + txID, } = actionData; const { displayName, tokenType } = getTokenMeta(vaultId); const { contractName: NFTName, contractAddress: NFTAddress } = @@ -36,13 +38,27 @@ const BannerInfo = ({ useEffect(() => { if (actionType === ACTION_TYPES.TRANSFER_NFT) { const getNFTMeta = async () => { - const result = await getTreasuryNFTReference( - NFTName, - formatAddress(NFTAddress), - collectionId, - recipient, - nftId - ); + let result; + + // When the action needs to be approved or rejected, the NFT is in the treasury + // When transaction is done (txID is defined), the NFT will be located on the account + if (txID) { + result = await getAccountNFTReference( + NFTName, + formatAddress(NFTAddress), + recipient, + nftId + ); + } else { + result = await getTreasuryNFTReference( + NFTName, + formatAddress(NFTAddress), + collectionId, + recipient, + nftId + ); + } + setNFTMeta(result ?? {}); }; getNFTMeta().catch(console.error);