mirror of
https://github.com/status-im/safe-react.git
synced 2025-02-20 05:28:08 +00:00
* Development (#378) * Adds cookie permissions to localStorage/redux state * Adds action * Adds files to git * (fix) linting issues * (update) flow-typed * (update) .eslint and .flowconfig * (add) cookie banner * Finish cookie banner implementation * (Add) checkbox's disabled style. * Removes redux for cookiesStorage * Fix cookieStore deletion * Fixs cookies acceptance * Fixs cookies banner verbiage Fix "x" in wrong place for snackbar messages * (remove) unused library * Adds cookies utils Replaces localStorage with cookies Adds js-cookie * (fix) added correct polished library and import, updated flow-typed * (update) removed polish flow type, added js-cookie flow type * Add link to cookie policy, use generic links for legal docs * Remove link to cookie policy from sidebar, link cookie policy in the banner * Let the user re-open the cookie banner * remove withMutations from cookies reducer, move utils/cookies to logic/cookies * Now the sidebar closes when the cookie banner is toggled * Feature #169: Intercom (#301) * Implements intercom Adds REACT_APP_INTERCOM_ID_MAINNET and REACT_APP_INTERCOM_ID_RINKEBY env vars * Adds .env.example * Adds intercom env vars * Updates env vars Replaces "rinkeby" and "mainnet" with "non-production" and "production" * Now loads intercom after the user accepted the analytics * Add env variable for production intercom id * Update .env.example * Removes react-intercom Fixs getIntercomId with default dev appID Now loads intercom as script * Renegerate flow-types * Remove 'Hide zero balances' (#310) * Use medium font size for 'select an asset' label (#312) * Feature #272: Google Analytics (#299) * Adds google analytics tracking for every route * Adds cookies acceptance check before tracking * Fix react-ga dependency * Fix cookieStore deletion * Merge with #189-cookie-banner * Fixs react ga version Refactored HOC with hooks * Fix TYPO * Fix path for cookies utils * Fix imports * remove flow type definition for polish * Add GA ID log * Fix load GA After cookies acceptance * Feature #224: Activate tokens automatically (#300) * Replace 'Manage Tokens' with 'Manage List' * prevent 301 redirects * Add `BLACKLISTED_TOKENS` key to persist through immortal * Add store/action to extract _activate tokens by its balance_ - keeps already activated tokens - discards blacklisted tokens - adds tokens whose vales are bigger than zero and are not blacklisted * Add `blacklistedTokens` list to safe's store * Display activeTokensByBalance in 'Balances' screen * Enable token's blacklisting functionality in Tokens List * Retrieve balance from API * Rename action to `activateTokensByBalance` * Fix linting errors - line too long - required return * Do not persist a separate list into `BLACKLISTED_TOKENS` * Typo fix (#326) * Fix security vulnerability: Remove uglifyjs, use terser plugin (#327) * Remove uglifyjs, use terser plugin * fix css-loader config * Feature #256: Sticky header (#308) * Add sticky header * Remove react-headroom, set position to fixed for header * Regenerate yarn lock * Remove unused headroom style from root.scss * Pull from dev, conflict fixes * Update welcome text (#323) * Feature #137: Tx list improvements (#222) * Fix swapOwners threshold displayed as hex in tx list * Refactor spinner in empty table * Fix number of rows per page in table pagination * Add use of EtherscanLink component * Set short version of strings in tx list * Adjust styles in tx list * Add more styles to table * WIP * An attempt to fix #204 by showing UNKNOWN instead of failed to fetch token symbol * Table pagination style fixes * Show confirm transaction button in owner list * Update dependencies * Add confirmation icons to owner list in tx list * exclude unneeded stuff from travis.yml * Adds cookie permissions to localStorage/redux state * Update dependencies * Adds action * Adds files to git * (fix) linting issues * (update) flow-typed * (update) .eslint and .flowconfig * (add) cookie banner * Finish cookie banner implementation * (Add) checkbox's disabled style. * Removes redux for cookiesStorage * Fix cookieStore deletion * Increase TO_EXP for bignumber.js * Fixs cookies acceptance * Fixs cookies banner verbiage Fix "x" in wrong place for snackbar messages * (fix) added correct polished library and import, updated flow-typed * (update) removed polish flow type, added js-cookie flow type * Add link to cookie policy, use generic links for legal docs * Remove link to cookie policy from sidebar, link cookie policy in the banner * Mock Safe creation transaction * Format code * Fix break statement * Remove deployment of storybook * Let the user re-open the cookie banner * Update tx status messages and visual confirmation progress * Fix svg in tx confirmation progress * Add styles to tx type in tx list * Replace nonce in tx list with tx id * Update opacity of cancelled tx * Fix short version of address * remove withMutations from cookies reducer, move utils/cookies to logic/cookies * Now the sidebar closes when the cookie banner is toggled * Fix styles in tx list * Add Pending status in tx description * (remove) unused library * Adds cookies utils Replaces localStorage with cookies Adds js-cookie * Set 25 rows per page in tx list by default * Align tx table * Adjust tx table and tx details borders * Fix fetching transactions to show Safe creation tx alone * Fix failed Safe creation transaction * Add styles to tx data * Refactor and fix owner list in transaction * Refactor use of theme variables * Remove storybook files * Update dependencies * Fix warnings * Fix dependencies * Update file-loader config * Fix owner colors in the tx confirmation progress * Fix transaction type icon height * Tx list adjustments * Update readme * (Feature) Etherscan button icon (#331) * (add) new open on etherscan button icon * (remove) unused asset * (fix) icon background * Feature #239: Replace early access label with network label (#311) * Remove early access label * Revert "Remove early access label" This reverts commit 34682f0f6d9c1974a6e45c2a31358864931d9c1e. * Replace early access label with network label * Capitalzie first letter of the network name * Adds threshold update on checkAndUpdateSafe (#320) * Feature #159: Pending transaction that requires user confirmation (#330) * Creates a new notification: waitingConfirmation Adds key as optional parameter for notification Implemented getAwaitingTransactions to get the transactions that needs to be confirmed by the current user Not fetchTransactions action also dispatch a notification for awaiting transactions Improved performance of routes/safe/container/index to avoid re-rendering * Removes notification logic on fetchTransactions Adds notificationsMiddleware * Moves fetchTransaction to container * Removes unused param on fetchTransactions * Fixs null safe check * Fixs middleware declaration * Removes lodash * Changes cancelled transaction detection logic * Feature #122: Multisig migration (#315) * Adds query-string package.json Parses query string on open layout * Implements load all the values on openSafe view from param querys * Adds query params validation * Moves query parse logic to open.jsx * Changes default no metamask component on open page * Replaces global isNaN * Fix threshold parsing validation * Updates the welcome component with new verbiage for open * Renames isOpenSafe to isOldMultisigMigration * Merge branch 'development' of https://github.com/gnosis/safe-react into 122-multisig-migration # Conflicts: # src/routes/open/components/Layout.jsx * Merge branch 'development' of https://github.com/gnosis/safe-react into 159-pending-transactions # Conflicts: # src/routes/safe/components/Transactions/index.jsx # yarn.lock * set anonymizeIp to true (#335) * Feature #180: Predict transaction nonce (#293) * Dep bump * Fetch transactions when safe view is mounted * eslint fix * Calculate new tx nonce from latest tx in service * Fix tx cancellation, allow passing nonce to createTransaction * dep bump * Refactor createTransaction/processTransaction to use object as argument * Adopting transactions table to new send tx flow with predicted nonces * dep bump, disable esModule in file-loader options after new v5 release * Don't show older tx annotation for already executed txs * sort tx by nonce * get new safe nonce after tx execution * Bugfixes * remove whitespace for showOlderTxAnnotation * Feature #329: Rename to Multisig (#334) * Rename to Multisig * migration text fix * replace safe for teams with multisig * Fixs race condition (#341) Fixs typo * (Feature) Incoming transactions (#333) * Add `blockNumber` to transactions model * Create `incomingTransaction` node in store and load it along with `transactions` * Add incoming transfers to the Transactions table * Rename `transactionHash` to `executionTxHash` for better incoming/outgoing txs unification in Transactions table * Add incoming transactions details * Add transaction type icon in table row * Add snackbar notification for incoming txs * Make incoming transaction snackbar to show on any tab * Use makeStyles hooks * Fix incoming amounts conversion from wei * Make concurrent promise calls * Use date to calculate transactions ids * Prevent repeating messages - also move logic to display snack bar into the notifications middleware * Merge transactions and incomingTxs to the transactions selector * Show 'Multiple incoming transfers' if they are more than 3 * Prevent incoming transactions snack bar for first-timer users * Set ID as the default order * Use constant for _incoming_ type * Feature #154: Fiat Balances (#290) * Adds DropdownCurrency Adds redux store for currencyValues Adds Value column on the assets table Adds mocked currency values * (add) base currency dropdown * (add) dropdown styles * Refactors data fetching of the balances list Now uses the endpoint * Fix column value styling * Adds support for ECB currency values * Fixs list overflow * Changes endpoint url Adds decimals for balance values * (fix) remove inline style * (add) currencies dropdown search field * (fix) list items' hover color * Implements filter search * Fix warning on dropdown template * Saves selected currency in localStorage * Remove spaces on curly braces Add alt Renames rowItem to cellItem Improves fetchCurrenciesRates handling * Removes withMutations * Removes middleware Export style to another file for dropdownCurrency * Adds classNames * Fix incomming transactions fetching (#346) * Feature: Activate fortmatic (#339) * Add fortmatic integration to web3connect * add fortmatic * Safe open form improvements: limit calling initContracts to 1 time * update .env.example * Feature #336: Confirmation required notification for non-owners fix (#338) * Refactors grantedSelector with isUserOwner function Checks if the user is owner of the safe before sending notification * Adds safeParamAddressFromStateSelector Refactors notificationsMiddleware with new selector * Remove old size check * safe notifications middleware fixes * add apt-get update to travis yml * (Fix) Incoming transactions inline-styles (#344) * Remove inline styles * Replace ternary with logical && operator * use cn as shortcut for classnames * Makes minMaxLength 2 to AddCustomToken (#363) * Fixs ETH display on balances list (#360) * Bug #348: Safelist entries get removed (#358) * Fix balances saved to localStorage not in format [tokenAdd, balance] but [balance] * Updates localStorage version value * Use submission instead of execution date to sort outgoing txs (#364) * Feature #190: Sidebar improvements (#347) * Change icons Adds checked icon * Adds safeParamAddressFromStateSelector for get current safe selected Implements check icon on sidebar * Remove overflow on sidebar Start alignments * Removes headerPlaceholder * Improves header * Improves header * Fix header style * use sameAddress function to check address eqaulity when fetching transactions (#365) * Bug #352: Owner shown multiple times (#367) * Ensure lowercased string comparison for owners' addresses * Use `sameAddress` for addresses comparison * Use transaction value as a string (#369) * Update isTokenTransfer to use value as a string * Rename error message * Update dependencies * Refactor * Fix alternative token abi and token address for incoming transactions (#373) * Bug #313: Payload breaks ui (#371) * Makes minMaxLength 2 to AddCustomToken * Fix styling * Fix typo * Feature #200: Show version number (#370) * Add `dotenv-expand` as a dependency * Add app version to sidebar * Add hardcoded latest safe version to env variables * Add `semver` to compare current vs latest version * Add Safe version to Safe Details * Adjustments in version number * Fix transaction description value (#377) * Fix transaction description value * Remove duplicated symbols * fix checkAndUpdateSafe logic (#379) * Update .env.example * update package json version * update package json version * Fix app version in side bar * add REACT_APP_APP_VERSION global env var * add react_app_version to build script * remove react_app_app_version from build-mainnet * Adds basic addressBook table * Implements redux and localStorage for addressBook * Disables loading page on empty address book * Fix address display * Adds logic for add entry * Implements update localStorage and redux state on new entry created * Updates default row per page * Renames createEntry modal to createEditEntryModal Implements edit entry logic * Fix save/edit entry notification verbiage * Implements delete entry * Finish delete entry implementation Moves update/remove/add entry logic to redux * Updates defaultRowsPerPage to 25 * Implements sendFunds modal within addressBook Refactors safeSelector with safeParamAddressFromStateSelector * Removes unused addressBook container * Moves loadAddressBook to safeContainer Adds <OwnerAddressTableCell/> in transaction details Adds userName (if available) on OwnerAddressTableCell * Removes unused pops Renames AddressBookEntry with AddressBookEntry * Replaces updateAddressBook with addAddressBook * Fixs transaction details styling with OwnerAddressTableCell Show menu off Edit/Add entry * Implements logic to add/edit addressBook entry from transaction details * Fix duplicated entry validation * Fix edit entry * Adds OwnerAddressTableCell in SettingsDescription and CustomDescription Shows owners name in addressboko from owner lists * Refactor redux addressBook, now saves the data for each safe * Fix addressbook url * Fix display addressbook names on transaction details * Fix entry exists validation * Refactors create/edit/delete entry, now the addressbook is global for all the safes * Refactor, uses immutable * Adds variable for hideBorderBottom * Adds disabled bin icon Disable the delete button for owner entries * Adds getAddressBookListSelector * Simplifies validator logic * Makes AddressBookEntry an immutable js list * Feedback fixes Co-authored-by: Germán Martínez <germartinez@users.noreply.github.com> Co-authored-by: Mikhail Mikheev <mmvsha73@gmail.com>
This commit is contained in:
parent
f37c3f9e61
commit
08e00a65ab
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,3 +4,4 @@ build_webpack/
|
|||||||
build/
|
build/
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
.env*
|
.env*
|
||||||
|
.idea/
|
||||||
|
@ -1,29 +1,36 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { withStyles } from '@material-ui/core/styles'
|
import { withStyles } from '@material-ui/core/styles'
|
||||||
|
import cn from 'classnames'
|
||||||
import Block from '~/components/layout/Block'
|
import Block from '~/components/layout/Block'
|
||||||
import Span from '~/components/layout/Span'
|
|
||||||
import CopyBtn from '~/components/CopyBtn'
|
import CopyBtn from '~/components/CopyBtn'
|
||||||
import EtherscanBtn from '~/components/EtherscanBtn'
|
import EtherscanBtn from '~/components/EtherscanBtn'
|
||||||
import { shortVersionOf } from '~/logic/wallets/ethAddresses'
|
import { shortVersionOf } from '~/logic/wallets/ethAddresses'
|
||||||
import { styles } from './style.js'
|
import { styles } from './style.js'
|
||||||
|
import EllipsisTransactionDetails from '~/routes/safe/components/AddressBook/EllipsisTransactionDetails'
|
||||||
|
import Span from '~/components/layout/Span'
|
||||||
|
|
||||||
type EtherscanLinkProps = {
|
type EtherscanLinkProps = {
|
||||||
type: 'tx' | 'address',
|
type: 'tx' | 'address',
|
||||||
value: string,
|
value: string,
|
||||||
cut?: number,
|
cut?: number,
|
||||||
|
knownAddress?: boolean,
|
||||||
classes: Object,
|
classes: Object,
|
||||||
}
|
}
|
||||||
|
|
||||||
const EtherscanLink = ({
|
const EtherscanLink = ({
|
||||||
type, value, cut, classes,
|
type, value, cut, classes, knownAddress,
|
||||||
}: EtherscanLinkProps) => (
|
}: EtherscanLinkProps) => (
|
||||||
<Block className={classes.etherscanLink}>
|
<Block className={classes.etherscanLink}>
|
||||||
<Span size="md">
|
<Span
|
||||||
|
size="md"
|
||||||
|
className={cn(knownAddress && classes.addressParagraph)}
|
||||||
|
>
|
||||||
{cut ? shortVersionOf(value, cut) : value}
|
{cut ? shortVersionOf(value, cut) : value}
|
||||||
</Span>
|
</Span>
|
||||||
<CopyBtn content={value} />
|
<CopyBtn content={value} />
|
||||||
<EtherscanBtn type={type} value={value} />
|
<EtherscanBtn type={type} value={value} />
|
||||||
|
{knownAddress !== undefined ? <EllipsisTransactionDetails knownAddress={knownAddress} address={value} /> : null}
|
||||||
</Block>
|
</Block>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -5,4 +5,7 @@ export const styles = () => ({
|
|||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
|
addressParagraph: {
|
||||||
|
fontSize: '13px',
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { List, Map } from 'immutable'
|
import { List, Map } from 'immutable'
|
||||||
import { createSelector, Selector } from 'reselect'
|
import { createSelector, Selector } from 'reselect'
|
||||||
|
import { useSelector } from 'react-redux'
|
||||||
import { ADDRESS_BOOK_REDUCER_ID } from '~/logic/addressBook/store/reducer/addressBook'
|
import { ADDRESS_BOOK_REDUCER_ID } from '~/logic/addressBook/store/reducer/addressBook'
|
||||||
import type { GlobalState } from '~/store'
|
import type { GlobalState } from '~/store'
|
||||||
import type { AddressBook } from '~/logic/addressBook/model/addressBook'
|
import type { AddressBook } from '~/logic/addressBook/model/addressBook'
|
||||||
@ -32,3 +33,15 @@ export const getAddressBookListSelector: Selector<GlobalState, {}, List<AddressB
|
|||||||
return result
|
return result
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export const getNameFromAddressBook = (userAddress: string): string | null => {
|
||||||
|
if (!userAddress) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const addressBook = useSelector(getAddressBook)
|
||||||
|
const result = addressBook.filter((addressBookItem) => addressBookItem.address === userAddress)
|
||||||
|
if (result.size > 0) {
|
||||||
|
return result.get(0).name
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
@ -19,3 +19,5 @@ export const saveAddressBook = async (addressBook: AddressBook) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const getAddressesListFromAdbk = (addressBook: AddressBook) => Array.from(addressBook).map((entry) => entry.address)
|
export const getAddressesListFromAdbk = (addressBook: AddressBook) => Array.from(addressBook).map((entry) => entry.address)
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ type Props = {
|
|||||||
newEntryModalHandler: Function,
|
newEntryModalHandler: Function,
|
||||||
editEntryModalHandler: Function,
|
editEntryModalHandler: Function,
|
||||||
entryToEdit?: AddressBookEntry,
|
entryToEdit?: AddressBookEntry,
|
||||||
|
newEntryDefaultAddress: string | null,
|
||||||
}
|
}
|
||||||
|
|
||||||
const CreateEditEntryModalComponent = ({
|
const CreateEditEntryModalComponent = ({
|
||||||
@ -43,6 +44,7 @@ const CreateEditEntryModalComponent = ({
|
|||||||
classes,
|
classes,
|
||||||
newEntryModalHandler,
|
newEntryModalHandler,
|
||||||
entryToEdit,
|
entryToEdit,
|
||||||
|
newEntryDefaultAddress,
|
||||||
editEntryModalHandler,
|
editEntryModalHandler,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const onFormSubmitted = (values) => {
|
const onFormSubmitted = (values) => {
|
||||||
@ -98,7 +100,7 @@ const CreateEditEntryModalComponent = ({
|
|||||||
text="Owner address*"
|
text="Owner address*"
|
||||||
className={classes.addressInput}
|
className={classes.addressInput}
|
||||||
testId={CREATE_ENTRY_INPUT_ADDRESS_ID}
|
testId={CREATE_ENTRY_INPUT_ADDRESS_ID}
|
||||||
defaultValue={entryToEdit ? entryToEdit.entry.address : undefined}
|
defaultValue={entryToEdit ? entryToEdit.entry.address : newEntryDefaultAddress}
|
||||||
/>
|
/>
|
||||||
</Row>
|
</Row>
|
||||||
</Block>
|
</Block>
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<g fill="none" fill-rule="evenodd">
|
||||||
|
<path fill="#B2B5B2" fill-rule="nonzero" d="M14 13h2V6h-5v2h2a1 1 0 0 1 1 1v4zM9 8V5a1 1 0 0 1 1-1h7a1 1 0 0 1 1 1v9a1 1 0 0 1-1 1h-3v3a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1h3zm-2 2v7h5v-7H7z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 351 B |
@ -0,0 +1,77 @@
|
|||||||
|
// @flow
|
||||||
|
import React from 'react'
|
||||||
|
import { useDispatch, useSelector } from 'react-redux'
|
||||||
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
|
import MoreHorizIcon from '@material-ui/icons/MoreHoriz'
|
||||||
|
import Menu from '@material-ui/core/Menu'
|
||||||
|
import MenuItem from '@material-ui/core/MenuItem'
|
||||||
|
import ClickAwayListener from '@material-ui/core/ClickAwayListener'
|
||||||
|
import { Divider } from '@material-ui/core'
|
||||||
|
import { push } from 'connected-react-router'
|
||||||
|
import { xs } from '~/theme/variables'
|
||||||
|
import { safeParamAddressFromStateSelector } from '~/routes/safe/store/selectors'
|
||||||
|
import { SAFELIST_ADDRESS } from '~/routes/routes'
|
||||||
|
|
||||||
|
|
||||||
|
const useStyles = makeStyles({
|
||||||
|
container: {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
cursor: 'pointer',
|
||||||
|
margin: `0 ${xs}`,
|
||||||
|
borderRadius: '50%',
|
||||||
|
transition: 'background-color .2s ease-in-out',
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: '#F0EFEE',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
increasedPopperZindex: {
|
||||||
|
zIndex: 2001,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
type EllipsisTransactionDetailsProps = {
|
||||||
|
knownAddress: boolean,
|
||||||
|
address: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
const EllipsisTransactionDetails = ({ knownAddress, address }: EllipsisTransactionDetailsProps) => {
|
||||||
|
const classes = useStyles()
|
||||||
|
const [anchorEl, setAnchorEl] = React.useState(null)
|
||||||
|
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
const currentSafeAddress = useSelector(safeParamAddressFromStateSelector)
|
||||||
|
|
||||||
|
const handleClick = (event) => {
|
||||||
|
setAnchorEl(event.currentTarget)
|
||||||
|
}
|
||||||
|
|
||||||
|
const closeMenuHandler = () => setAnchorEl(null)
|
||||||
|
|
||||||
|
const addOrEditEntryHandler = () => {
|
||||||
|
dispatch(push(`${SAFELIST_ADDRESS}/${currentSafeAddress}/address-book?entryAddress=${address}`))
|
||||||
|
closeMenuHandler()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ClickAwayListener onClickAway={closeMenuHandler}>
|
||||||
|
<div className={classes.container} onClick={handleClick}>
|
||||||
|
<MoreHorizIcon />
|
||||||
|
<Menu
|
||||||
|
id="simple-menu"
|
||||||
|
anchorEl={anchorEl}
|
||||||
|
keepMounted
|
||||||
|
open={Boolean(anchorEl)}
|
||||||
|
onClose={closeMenuHandler}
|
||||||
|
>
|
||||||
|
<MenuItem onClick={closeMenuHandler} disabled>Send Again</MenuItem>
|
||||||
|
<Divider />
|
||||||
|
{ knownAddress ? <MenuItem onClick={addOrEditEntryHandler}>Edit Address book Entry</MenuItem> : <MenuItem onClick={addOrEditEntryHandler}>Add to address book</MenuItem>}
|
||||||
|
</Menu>
|
||||||
|
</div>
|
||||||
|
</ClickAwayListener>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EllipsisTransactionDetails
|
@ -1,5 +1,5 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import React, { useState } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
|
|
||||||
import cn from 'classnames'
|
import cn from 'classnames'
|
||||||
import { List } from 'immutable'
|
import { List } from 'immutable'
|
||||||
@ -40,7 +40,7 @@ import { updateAddressBookEntry } from '~/logic/addressBook/store/actions/update
|
|||||||
import { removeAddressBookEntry } from '~/logic/addressBook/store/actions/removeAddressBookEntry'
|
import { removeAddressBookEntry } from '~/logic/addressBook/store/actions/removeAddressBookEntry'
|
||||||
import { addAddressBookEntry } from '~/logic/addressBook/store/actions/addAddressBookEntry'
|
import { addAddressBookEntry } from '~/logic/addressBook/store/actions/addAddressBookEntry'
|
||||||
import SendModal from '~/routes/safe/components/Balances/SendModal'
|
import SendModal from '~/routes/safe/components/Balances/SendModal'
|
||||||
import { safeSelector, safesListSelector } from '~/routes/safe/store/selectors'
|
import { safeSelector, safesListSelector, addressBookQueryParamsSelector } from '~/routes/safe/store/selectors'
|
||||||
import { extendedSafeTokensSelector } from '~/routes/safe/container/selector'
|
import { extendedSafeTokensSelector } from '~/routes/safe/container/selector'
|
||||||
import { isUserOwnerOnAnySafe } from '~/logic/wallets/ethAddresses'
|
import { isUserOwnerOnAnySafe } from '~/logic/wallets/ethAddresses'
|
||||||
|
|
||||||
@ -59,6 +59,31 @@ const AddressBookTable = ({ classes }: Props) => {
|
|||||||
)
|
)
|
||||||
const [deleteEntryModalOpen, setDeleteEntryModalOpen] = useState(false)
|
const [deleteEntryModalOpen, setDeleteEntryModalOpen] = useState(false)
|
||||||
const [sendFundsModalOpen, setSendFundsModalOpen] = useState(false)
|
const [sendFundsModalOpen, setSendFundsModalOpen] = useState(false)
|
||||||
|
const [defaultNewEntryAddress, setDefaultNewEntryAddress] = useState(null)
|
||||||
|
const entryAddressToEditOrCreateNew = useSelector(addressBookQueryParamsSelector)
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (entryAddressToEditOrCreateNew) {
|
||||||
|
setEditCreateEntryModalOpen(true)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (entryAddressToEditOrCreateNew) {
|
||||||
|
const key = addressBook.findKey((entry) => entry.address === entryAddressToEditOrCreateNew)
|
||||||
|
if (key >= 0) {
|
||||||
|
// Edit old entry
|
||||||
|
const value = addressBook.get(key)
|
||||||
|
setSelectedEntry({ entry: value, index: key })
|
||||||
|
} else {
|
||||||
|
// Create new entry
|
||||||
|
setDefaultNewEntryAddress(entryAddressToEditOrCreateNew)
|
||||||
|
setSelectedEntry(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[addressBook])
|
||||||
|
|
||||||
const safe = useSelector(safeSelector)
|
const safe = useSelector(safeSelector)
|
||||||
const safesList = useSelector(safesListSelector)
|
const safesList = useSelector(safesListSelector)
|
||||||
@ -68,6 +93,7 @@ const AddressBookTable = ({ classes }: Props) => {
|
|||||||
const newEntryModalHandler = (entry: AddressBookEntry) => {
|
const newEntryModalHandler = (entry: AddressBookEntry) => {
|
||||||
setEditCreateEntryModalOpen(false)
|
setEditCreateEntryModalOpen(false)
|
||||||
dispatch(addAddressBookEntry(entry))
|
dispatch(addAddressBookEntry(entry))
|
||||||
|
setDefaultNewEntryAddress(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
const editEntryModalHandler = (entry: AddressBookEntry) => {
|
const editEntryModalHandler = (entry: AddressBookEntry) => {
|
||||||
@ -198,6 +224,7 @@ const AddressBookTable = ({ classes }: Props) => {
|
|||||||
newEntryModalHandler={newEntryModalHandler}
|
newEntryModalHandler={newEntryModalHandler}
|
||||||
editEntryModalHandler={editEntryModalHandler}
|
editEntryModalHandler={editEntryModalHandler}
|
||||||
entryToEdit={selectedEntry}
|
entryToEdit={selectedEntry}
|
||||||
|
newEntryDefaultAddress={defaultNewEntryAddress}
|
||||||
/>
|
/>
|
||||||
<DeleteEntryModal
|
<DeleteEntryModal
|
||||||
onClose={() => setDeleteEntryModalOpen(false)}
|
onClose={() => setDeleteEntryModalOpen(false)}
|
||||||
|
@ -8,16 +8,21 @@ import EtherScanLink from '~/components/EtherscanLink'
|
|||||||
type Props = {
|
type Props = {
|
||||||
address: string,
|
address: string,
|
||||||
showLinks?: boolean,
|
showLinks?: boolean,
|
||||||
|
knownAddress?: boolean,
|
||||||
|
userName?: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
const OwnerAddressTableCell = (props: Props) => {
|
const OwnerAddressTableCell = (props: Props) => {
|
||||||
const { address, showLinks } = props
|
const {
|
||||||
|
address, userName, showLinks, knownAddress,
|
||||||
|
} = props
|
||||||
return (
|
return (
|
||||||
<Block justify="left">
|
<Block justify="left">
|
||||||
<Identicon address={address} diameter={32} />
|
<Identicon address={address} diameter={32} />
|
||||||
{ showLinks ? (
|
{ showLinks ? (
|
||||||
<div style={{ marginLeft: 10 }}>
|
<div style={{ marginLeft: 10 }}>
|
||||||
<EtherScanLink type="address" value={address} />
|
{ userName }
|
||||||
|
<EtherScanLink type="address" value={address} knownAddress={knownAddress} />
|
||||||
</div>
|
</div>
|
||||||
) : <Paragraph style={{ marginLeft: 10 }}>{address}</Paragraph> }
|
) : <Paragraph style={{ marginLeft: 10 }}>{address}</Paragraph> }
|
||||||
</Block>
|
</Block>
|
||||||
|
@ -7,12 +7,17 @@ import EtherscanLink from '~/components/EtherscanLink'
|
|||||||
import Block from '~/components/layout/Block'
|
import Block from '~/components/layout/Block'
|
||||||
import { md, lg } from '~/theme/variables'
|
import { md, lg } from '~/theme/variables'
|
||||||
import { getIncomingTxAmount } from '~/routes/safe/components/Transactions/TxsTable/columns'
|
import { getIncomingTxAmount } from '~/routes/safe/components/Transactions/TxsTable/columns'
|
||||||
|
import OwnerAddressTableCell from '~/routes/safe/components/Settings/ManageOwners/OwnerAddressTableCell'
|
||||||
|
import { getNameFromAddressBook } from '~/logic/addressBook/store/selectors'
|
||||||
|
|
||||||
|
|
||||||
export const TRANSACTIONS_DESC_INCOMING_TEST_ID = 'tx-description-incoming'
|
export const TRANSACTIONS_DESC_INCOMING_TEST_ID = 'tx-description-incoming'
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
const useStyles = makeStyles({
|
||||||
txDataContainer: {
|
txDataContainer: {
|
||||||
padding: `${lg} ${md}`,
|
paddingTop: lg,
|
||||||
|
paddingLeft: md,
|
||||||
|
paddingBottom: md,
|
||||||
borderRight: '2px solid rgb(232, 231, 230)',
|
borderRight: '2px solid rgb(232, 231, 230)',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -24,9 +29,10 @@ type Props = {
|
|||||||
type TransferDescProps = {
|
type TransferDescProps = {
|
||||||
value: string,
|
value: string,
|
||||||
from: string,
|
from: string,
|
||||||
|
txFromName?: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
const TransferDescription = ({ value = '', from }: TransferDescProps) => (
|
const TransferDescription = ({ value = '', from, txFromName }: TransferDescProps) => (
|
||||||
<Block data-testid={TRANSACTIONS_DESC_INCOMING_TEST_ID}>
|
<Block data-testid={TRANSACTIONS_DESC_INCOMING_TEST_ID}>
|
||||||
<Bold>
|
<Bold>
|
||||||
Received
|
Received
|
||||||
@ -36,16 +42,18 @@ const TransferDescription = ({ value = '', from }: TransferDescProps) => (
|
|||||||
from:
|
from:
|
||||||
</Bold>
|
</Bold>
|
||||||
<br />
|
<br />
|
||||||
<EtherscanLink type="address" value={from} />
|
{txFromName ? <OwnerAddressTableCell address={from} showLinks userName={txFromName} knownAddress />
|
||||||
|
: <EtherscanLink type="address" value={from} knownAddress={false} />}
|
||||||
</Block>
|
</Block>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
const IncomingTxDescription = ({ tx }: Props) => {
|
const IncomingTxDescription = ({ tx }: Props) => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
|
const txFromName = getNameFromAddressBook(tx.from)
|
||||||
return (
|
return (
|
||||||
<Block className={classes.txDataContainer}>
|
<Block className={classes.txDataContainer}>
|
||||||
<TransferDescription value={getIncomingTxAmount(tx)} from={tx.from} />
|
<TransferDescription value={getIncomingTxAmount(tx)} from={tx.from} txFromName={txFromName} />
|
||||||
</Block>
|
</Block>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@ import { styles } from './style'
|
|||||||
import ConfirmSmallGreyIcon from './assets/confirm-small-grey.svg'
|
import ConfirmSmallGreyIcon from './assets/confirm-small-grey.svg'
|
||||||
import ConfirmSmallGreenIcon from './assets/confirm-small-green.svg'
|
import ConfirmSmallGreenIcon from './assets/confirm-small-green.svg'
|
||||||
import ConfirmSmallFilledIcon from './assets/confirm-small-filled.svg'
|
import ConfirmSmallFilledIcon from './assets/confirm-small-filled.svg'
|
||||||
|
import { getNameFromAddressBook } from '~/logic/addressBook/store/selectors'
|
||||||
|
|
||||||
|
|
||||||
export const CONFIRM_TX_BTN_TEST_ID = 'confirm-btn'
|
export const CONFIRM_TX_BTN_TEST_ID = 'confirm-btn'
|
||||||
export const EXECUTE_TX_BTN_TEST_ID = 'execute-btn'
|
export const EXECUTE_TX_BTN_TEST_ID = 'execute-btn'
|
||||||
@ -40,65 +42,69 @@ const OwnerComponent = ({
|
|||||||
executor,
|
executor,
|
||||||
confirmed,
|
confirmed,
|
||||||
thresholdReached,
|
thresholdReached,
|
||||||
}: OwnerProps) => (
|
}: OwnerProps) => {
|
||||||
<Block className={classes.container}>
|
const nameInAdbk = getNameFromAddressBook(owner.address)
|
||||||
<div
|
const ownerName = owner.name === 'UNKNOWN' && nameInAdbk ? nameInAdbk : owner.name
|
||||||
className={
|
return (
|
||||||
confirmed || thresholdReached || executor
|
<Block className={classes.container}>
|
||||||
? classes.verticalLineProgressDone
|
<div
|
||||||
: classes.verticalLineProgressPending
|
className={
|
||||||
}
|
confirmed || thresholdReached || executor
|
||||||
/>
|
? classes.verticalLineProgressDone
|
||||||
<div className={classes.iconState}>
|
: classes.verticalLineProgressPending
|
||||||
{confirmed ? (
|
}
|
||||||
<Img src={ConfirmSmallFilledIcon} />
|
|
||||||
) : thresholdReached || executor ? (
|
|
||||||
<Img src={ConfirmSmallGreenIcon} />
|
|
||||||
) : (
|
|
||||||
<Img src={ConfirmSmallGreyIcon} />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<Identicon address={owner.address} diameter={32} className={classes.icon} />
|
|
||||||
<Block>
|
|
||||||
<Paragraph className={classes.name} noMargin>
|
|
||||||
{owner.name}
|
|
||||||
</Paragraph>
|
|
||||||
<EtherscanLink
|
|
||||||
className={classes.address}
|
|
||||||
type="address"
|
|
||||||
value={owner.address}
|
|
||||||
cut={4}
|
|
||||||
/>
|
/>
|
||||||
|
<div className={classes.iconState}>
|
||||||
|
{confirmed ? (
|
||||||
|
<Img src={ConfirmSmallFilledIcon} />
|
||||||
|
) : thresholdReached || executor ? (
|
||||||
|
<Img src={ConfirmSmallGreenIcon} />
|
||||||
|
) : (
|
||||||
|
<Img src={ConfirmSmallGreyIcon} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<Identicon address={owner.address} diameter={32} className={classes.icon} />
|
||||||
|
<Block>
|
||||||
|
<Paragraph className={classes.name} noMargin>
|
||||||
|
{ownerName}
|
||||||
|
</Paragraph>
|
||||||
|
<EtherscanLink
|
||||||
|
className={classes.address}
|
||||||
|
type="address"
|
||||||
|
value={owner.address}
|
||||||
|
cut={4}
|
||||||
|
/>
|
||||||
|
</Block>
|
||||||
|
<Block className={classes.spacer} />
|
||||||
|
{showConfirmBtn && owner.address === userAddress && (
|
||||||
|
<Button
|
||||||
|
className={classes.button}
|
||||||
|
variant="contained"
|
||||||
|
minWidth={140}
|
||||||
|
color="primary"
|
||||||
|
onClick={onTxConfirm}
|
||||||
|
testId={CONFIRM_TX_BTN_TEST_ID}
|
||||||
|
>
|
||||||
|
Confirm tx
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{showExecuteBtn && owner.address === userAddress && (
|
||||||
|
<Button
|
||||||
|
className={classes.button}
|
||||||
|
variant="contained"
|
||||||
|
minWidth={140}
|
||||||
|
color="primary"
|
||||||
|
onClick={onTxExecute}
|
||||||
|
testId={EXECUTE_TX_BTN_TEST_ID}
|
||||||
|
>
|
||||||
|
Execute tx
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{owner.address === executor && (
|
||||||
|
<Block className={classes.executor}>Executor</Block>
|
||||||
|
)}
|
||||||
</Block>
|
</Block>
|
||||||
<Block className={classes.spacer} />
|
)
|
||||||
{showConfirmBtn && owner.address === userAddress && (
|
}
|
||||||
<Button
|
|
||||||
className={classes.button}
|
|
||||||
variant="contained"
|
|
||||||
minWidth={140}
|
|
||||||
color="primary"
|
|
||||||
onClick={onTxConfirm}
|
|
||||||
testId={CONFIRM_TX_BTN_TEST_ID}
|
|
||||||
>
|
|
||||||
Confirm tx
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
{showExecuteBtn && owner.address === userAddress && (
|
|
||||||
<Button
|
|
||||||
className={classes.button}
|
|
||||||
variant="contained"
|
|
||||||
minWidth={140}
|
|
||||||
color="primary"
|
|
||||||
onClick={onTxExecute}
|
|
||||||
testId={EXECUTE_TX_BTN_TEST_ID}
|
|
||||||
>
|
|
||||||
Execute tx
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
{owner.address === executor && (
|
|
||||||
<Block className={classes.executor}>Executor</Block>
|
|
||||||
)}
|
|
||||||
</Block>
|
|
||||||
)
|
|
||||||
|
|
||||||
export default withStyles(styles)(OwnerComponent)
|
export default withStyles(styles)(OwnerComponent)
|
||||||
|
@ -11,6 +11,9 @@ import { md, lg } from '~/theme/variables'
|
|||||||
import { getTxData } from './utils'
|
import { getTxData } from './utils'
|
||||||
import { shortVersionOf } from '~/logic/wallets/ethAddresses'
|
import { shortVersionOf } from '~/logic/wallets/ethAddresses'
|
||||||
import LinkWithRef from '~/components/layout/Link'
|
import LinkWithRef from '~/components/layout/Link'
|
||||||
|
import OwnerAddressTableCell from '~/routes/safe/components/Settings/ManageOwners/OwnerAddressTableCell'
|
||||||
|
import { getNameFromAddressBook } from '~/logic/addressBook/store/selectors'
|
||||||
|
|
||||||
|
|
||||||
export const TRANSACTIONS_DESC_ADD_OWNER_TEST_ID = 'tx-description-add-owner'
|
export const TRANSACTIONS_DESC_ADD_OWNER_TEST_ID = 'tx-description-add-owner'
|
||||||
export const TRANSACTIONS_DESC_REMOVE_OWNER_TEST_ID = 'tx-description-remove-owner'
|
export const TRANSACTIONS_DESC_REMOVE_OWNER_TEST_ID = 'tx-description-remove-owner'
|
||||||
@ -21,7 +24,9 @@ export const TRANSACTIONS_DESC_CUSTOM_DATA_TEST_ID = 'tx-description-custom-data
|
|||||||
|
|
||||||
export const styles = () => ({
|
export const styles = () => ({
|
||||||
txDataContainer: {
|
txDataContainer: {
|
||||||
padding: `${lg} ${md}`,
|
paddingTop: lg,
|
||||||
|
paddingLeft: md,
|
||||||
|
paddingBottom: md,
|
||||||
},
|
},
|
||||||
txData: {
|
txData: {
|
||||||
wordBreak: 'break-all',
|
wordBreak: 'break-all',
|
||||||
@ -58,48 +63,62 @@ type CustomDescProps = {
|
|||||||
classes: Object,
|
classes: Object,
|
||||||
}
|
}
|
||||||
|
|
||||||
const TransferDescription = ({ amount = '', recipient }: TransferDescProps) => (
|
const TransferDescription = ({ amount = '', recipient }: TransferDescProps) => {
|
||||||
<Block data-testid={TRANSACTIONS_DESC_SEND_TEST_ID}>
|
const recipientName = getNameFromAddressBook(recipient)
|
||||||
<Bold>
|
return (
|
||||||
Send
|
<Block data-testid={TRANSACTIONS_DESC_SEND_TEST_ID}>
|
||||||
{' '}
|
<Bold>
|
||||||
{amount}
|
Send
|
||||||
{' '}
|
{' '}
|
||||||
to:
|
{amount}
|
||||||
</Bold>
|
{' '}
|
||||||
<EtherscanLink type="address" value={recipient} />
|
to:
|
||||||
</Block>
|
</Bold>
|
||||||
)
|
{recipientName ? <OwnerAddressTableCell address={recipient} showLinks knownAddress userName={recipientName} />
|
||||||
|
: <EtherscanLink type="address" value={recipient} knownAddress={false} />}
|
||||||
|
</Block>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const SettingsDescription = ({ removedOwner, addedOwner, newThreshold }: DescriptionDescProps) => (
|
const SettingsDescription = ({
|
||||||
<>
|
removedOwner, addedOwner, newThreshold,
|
||||||
{removedOwner && (
|
}: DescriptionDescProps) => {
|
||||||
<Block data-testid={TRANSACTIONS_DESC_REMOVE_OWNER_TEST_ID}>
|
const ownerChangedName = removedOwner ? getNameFromAddressBook(removedOwner) : getNameFromAddressBook(addedOwner)
|
||||||
<Bold>Remove owner:</Bold>
|
return (
|
||||||
<EtherscanLink type="address" value={removedOwner} />
|
<>
|
||||||
</Block>
|
{removedOwner && (
|
||||||
)}
|
<Block data-testid={TRANSACTIONS_DESC_REMOVE_OWNER_TEST_ID}>
|
||||||
{addedOwner && (
|
<Bold>Remove owner:</Bold>
|
||||||
<Block data-testid={TRANSACTIONS_DESC_ADD_OWNER_TEST_ID}>
|
{ownerChangedName
|
||||||
<Bold>Add owner:</Bold>
|
? <OwnerAddressTableCell address={removedOwner} showLinks knownAddress userName={ownerChangedName} />
|
||||||
<EtherscanLink type="address" value={addedOwner} />
|
: <EtherscanLink type="address" value={removedOwner} knownAddress={false} />}
|
||||||
</Block>
|
</Block>
|
||||||
)}
|
)}
|
||||||
{newThreshold && (
|
{addedOwner && (
|
||||||
<Block data-testid={TRANSACTIONS_DESC_CHANGE_THRESHOLD_TEST_ID}>
|
<Block data-testid={TRANSACTIONS_DESC_ADD_OWNER_TEST_ID}>
|
||||||
<Bold>Change required confirmations:</Bold>
|
<Bold>Add owner:</Bold>
|
||||||
<Paragraph size="md" noMargin>
|
{ownerChangedName
|
||||||
{newThreshold}
|
? <OwnerAddressTableCell address={addedOwner} showLinks knownAddress userName={ownerChangedName} />
|
||||||
</Paragraph>
|
: <EtherscanLink type="address" value={addedOwner} knownAddress={false} />}
|
||||||
</Block>
|
</Block>
|
||||||
)}
|
)}
|
||||||
</>
|
{newThreshold && (
|
||||||
)
|
<Block data-testid={TRANSACTIONS_DESC_CHANGE_THRESHOLD_TEST_ID}>
|
||||||
|
<Bold>Change required confirmations:</Bold>
|
||||||
|
<Paragraph size="md" noMargin>
|
||||||
|
{newThreshold}
|
||||||
|
</Paragraph>
|
||||||
|
</Block>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const CustomDescription = ({
|
const CustomDescription = ({
|
||||||
data, amount = 0, recipient, classes,
|
data, amount = 0, recipient, classes,
|
||||||
}: CustomDescProps) => {
|
}: CustomDescProps) => {
|
||||||
const [showTxData, setShowTxData] = useState(false)
|
const [showTxData, setShowTxData] = useState(false)
|
||||||
|
const recipientName = getNameFromAddressBook(recipient)
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Block data-testid={TRANSACTIONS_DESC_CUSTOM_VALUE_TEST_ID}>
|
<Block data-testid={TRANSACTIONS_DESC_CUSTOM_VALUE_TEST_ID}>
|
||||||
@ -110,7 +129,7 @@ const CustomDescription = ({
|
|||||||
{' '}
|
{' '}
|
||||||
to:
|
to:
|
||||||
</Bold>
|
</Bold>
|
||||||
<EtherscanLink type="address" value={recipient} />
|
{ recipientName ? <OwnerAddressTableCell address={recipient} showLinks knownAddress userName={recipientName} /> : <EtherscanLink type="address" value={recipient} knownAddress={false} />}
|
||||||
</Block>
|
</Block>
|
||||||
<Block className={classes.txData} data-testid={TRANSACTIONS_DESC_CUSTOM_DATA_TEST_ID}>
|
<Block className={classes.txData} data-testid={TRANSACTIONS_DESC_CUSTOM_DATA_TEST_ID}>
|
||||||
<Bold>Data (hex encoded):</Bold>
|
<Bold>Data (hex encoded):</Bold>
|
||||||
|
@ -70,6 +70,16 @@ export const safeTransactionsSelector: Selector<GlobalState, RouterProps, List<T
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export const addressBookQueryParamsSelector = (state: GlobalState): string => {
|
||||||
|
const { location } = state.router
|
||||||
|
let entryAddressToEditOrCreateNew = null
|
||||||
|
if (location && location.query) {
|
||||||
|
const { entryAddress } = location.query
|
||||||
|
entryAddressToEditOrCreateNew = entryAddress
|
||||||
|
}
|
||||||
|
return entryAddressToEditOrCreateNew
|
||||||
|
}
|
||||||
|
|
||||||
export const safeParamAddressFromStateSelector = (state: GlobalState): string => {
|
export const safeParamAddressFromStateSelector = (state: GlobalState): string => {
|
||||||
const match = matchPath(
|
const match = matchPath(
|
||||||
state.router.location.pathname,
|
state.router.location.pathname,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user