Development (#368)

* 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)
This commit is contained in:
Mikhail Mikheev 2019-12-17 20:56:19 +04:00 committed by Germán Martínez
parent fff057d8e6
commit c593c8edaa
17 changed files with 428 additions and 709 deletions

View File

@ -31,18 +31,18 @@
"dependencies": {
"@gnosis.pm/safe-contracts": "1.0.0",
"@gnosis.pm/util-contracts": "2.0.4",
"@material-ui/core": "4.7.2",
"@material-ui/core": "4.8.0",
"@material-ui/icons": "4.5.1",
"@portis/web3": "^2.0.0-beta.45",
"@testing-library/jest-dom": "4.2.4",
"@toruslabs/torus-embed": "0.2.9",
"@toruslabs/torus-embed": "0.2.10",
"@walletconnect/web3-provider": "^1.0.0-beta.37",
"@welldone-software/why-did-you-render": "3.3.9",
"@welldone-software/why-did-you-render": "3.4.1",
"axios": "0.19.0",
"bignumber.js": "9.0.0",
"connected-react-router": "6.6.1",
"date-fns": "2.8.1",
"currency-flags": "^2.1.1",
"date-fns": "2.8.1",
"dotenv": "^8.2.0",
"ethereum-ens": "0.7.8",
"final-form": "4.18.6",
@ -102,7 +102,7 @@
"@babel/preset-env": "7.7.6",
"@babel/preset-flow": "7.7.4",
"@babel/preset-react": "7.7.4",
"@testing-library/react": "9.3.3",
"@testing-library/react": "9.4.0",
"autoprefixer": "9.7.3",
"babel-core": "^7.0.0-bridge.0",
"babel-eslint": "10.0.3",
@ -113,7 +113,7 @@
"babel-plugin-transform-es3-property-literals": "^6.22.0",
"babel-polyfill": "^6.26.0",
"classnames": "^2.2.6",
"css-loader": "3.3.0",
"css-loader": "3.3.2",
"detect-port": "^1.3.0",
"eslint": "6.7.2",
"eslint-config-airbnb": "18.0.1",
@ -125,7 +125,7 @@
"ethereumjs-abi": "0.6.8",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"file-loader": "5.0.2",
"flow-bin": "0.113.0",
"flow-bin": "0.114.0",
"fs-extra": "8.1.0",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
@ -140,12 +140,12 @@
"prettier-eslint-cli": "5.0.0",
"run-with-testrpc": "0.3.1",
"style-loader": "1.0.1",
"terser-webpack-plugin": "2.2.3",
"truffle": "5.1.3",
"terser-webpack-plugin": "2.3.0",
"truffle": "5.1.4",
"truffle-contract": "4.0.31",
"truffle-solidity-loader": "0.1.32",
"url-loader": "3.0.0",
"webpack": "4.41.2",
"webpack": "4.41.3",
"webpack-bundle-analyzer": "3.6.0",
"webpack-cli": "3.3.10",
"webpack-dev-server": "3.9.0",

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="14" viewBox="0 0 18 14">
<path fill="#008C73" fill-rule="evenodd" d="M5.6 10.6L1.4 6.4 0 7.8l5.6 5.6 12-12L16.2 0z"/>
</svg>

After

Width:  |  Height:  |  Size: 188 B

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="15" viewBox="0 0 20 15">
<path fill="#B2B5B2" fill-rule="evenodd" d="M3 8l-1.562.01a.5.5 0 0 1-.315-.89L9.969.036 10 0l.007.006.008-.006.03.037 8.845 7.091a.5.5 0 0 1-.313.89H17V15h-6v-5H9v5H3V8zm2-1.624V13h2V8h6v5h2V6.61L9.975 2.55 5 6.377z"/>
</svg>

After

Width:  |  Height:  |  Size: 315 B

View File

@ -45,7 +45,6 @@ const SafeListHeader = ({ safesCount }: Props) => {
return (
<Col start="xs" middle="xs" className={classes.container}>
Safes
{' '}
<Paragraph size="xs" className={classes.counter}>
{safesCount}
</Paragraph>

View File

@ -4,20 +4,23 @@ import { makeStyles } from '@material-ui/core/styles'
import Img from '~/components/layout/Img'
import Block from '~/components/layout/Block'
import Paragraph from '~/components/layout/Paragraph'
import { primary, sm } from '~/theme/variables'
import StarIcon from './assets/star.svg'
import { primary, secondaryBackground, md } from '~/theme/variables'
import HomeIcon from '~/assets/icons/shape.svg'
const useStyles = makeStyles({
container: {
background: primary,
background: secondaryBackground,
padding: '5px',
boxSizing: 'border-box',
width: '73px',
width: '76px',
justifyContent: 'space-around',
marginLeft: sm,
marginLeft: md,
color: '#fff',
borderRadius: '3px',
},
defaultText: {
color: primary,
},
})
const DefaultBadge = () => {
@ -25,9 +28,9 @@ const DefaultBadge = () => {
return (
<Block justify="left" className={classes.container}>
<Img src={StarIcon} alt="Star Icon" />
<Paragraph noMargin size="xs">
default
<Img src={HomeIcon} alt="Home Icon" />
<Paragraph noMargin size="xs" className={classes.defaultText}>
Default
</Paragraph>
</Block>
)

View File

@ -12,18 +12,21 @@ import Paragraph from '~/components/layout/Paragraph'
import ButtonLink from '~/components/layout/ButtonLink'
import Identicon from '~/components/Identicon'
import {
mediumFontSize, sm, secondary, primary,
mediumFontSize, sm, primary, disabled, md,
} from '~/theme/variables'
import { formatAmount } from '~/logic/tokens/utils/formatAmount'
import { shortVersionOf, sameAddress } from '~/logic/wallets/ethAddresses'
import { type Safe } from '~/routes/safe/store/models/safe'
import { SAFELIST_ADDRESS } from '~/routes/routes'
import DefaultBadge from './DefaultBadge'
import Img from '~/components/layout/Img'
import check from '~/assets/icons/check.svg'
export const SIDEBAR_SAFELIST_ROW_TESTID = 'SIDEBAR_SAFELIST_ROW_TESTID'
type SafeListProps = {
safes: List<Safe>,
currentSafe: string,
onSafeClick: Function,
setDefaultSafe: Function,
defaultSafe: string,
@ -33,9 +36,12 @@ const useStyles = makeStyles({
icon: {
marginRight: sm,
},
checkIcon: {
marginRight: '10px',
},
list: {
overflow: 'hidden',
overflowY: 'scroll',
overflowY: 'hidden',
padding: 0,
height: '100%',
},
@ -50,21 +56,25 @@ const useStyles = makeStyles({
},
},
safeName: {
color: secondary,
color: primary,
},
safeAddress: {
color: primary,
color: disabled,
fontSize: mediumFontSize,
},
makeDefaultBtn: {
padding: 0,
marginLeft: sm,
marginLeft: md,
visibility: 'hidden',
},
noIcon: {
visibility: 'hidden',
width: '28px',
},
})
const SafeList = ({
safes, onSafeClick, setDefaultSafe, defaultSafe,
safes, onSafeClick, setDefaultSafe, defaultSafe, currentSafe,
}: SafeListProps) => {
const classes = useStyles()
@ -78,6 +88,11 @@ const SafeList = ({
data-testid={SIDEBAR_SAFELIST_ROW_TESTID}
>
<ListItem classes={{ root: classes.listItemRoot }}>
{ sameAddress(currentSafe, safe.address) ? (
<ListItemIcon>
<Img src={check} alt="check" className={classes.checkIcon} />
</ListItemIcon>
) : <div className={classes.noIcon}>placeholder</div> }
<ListItemIcon>
<Identicon address={safe.address} diameter={32} className={classes.icon} />
</ListItemIcon>

View File

@ -14,19 +14,21 @@ import Hairline from '~/components/layout/Hairline'
import Row from '~/components/layout/Row'
import { WELCOME_ADDRESS } from '~/routes/routes'
import { type Safe } from '~/routes/safe/store/models/safe'
import { defaultSafeSelector } from '~/routes/safe/store/selectors'
import {
defaultSafeSelector,
safeParamAddressFromStateSelector,
} from '~/routes/safe/store/selectors'
import setDefaultSafe from '~/routes/safe/store/actions/setDefaultSafe'
import { sortedSafeListSelector } from './selectors'
import SafeList from './SafeList'
import LegalLinks from './LegalLinks'
import useSidebarStyles from './style'
const { useState, useEffect, useMemo } = React
type TSidebarContext = {
isOpen: boolean,
toggleSidebar: Function,
toggleSidebar: Function
}
export const SidebarContext = React.createContext<TSidebarContext>({
@ -39,6 +41,7 @@ type SidebarProps = {
safes: List<Safe>,
setDefaultSafeAction: Function,
defaultSafe: string,
currentSafe: string
}
const filterBy = (filter: string, safes: List<Safe>): List<Safe> => safes.filter(
@ -48,7 +51,11 @@ const filterBy = (filter: string, safes: List<Safe>): List<Safe> => safes.filter
)
const Sidebar = ({
children, safes, setDefaultSafeAction, defaultSafe,
children,
safes,
setDefaultSafeAction,
defaultSafe,
currentSafe,
}: SidebarProps) => {
const [isOpen, setIsOpen] = useState<boolean>(false)
const [filter, setFilter] = useState<string>('')
@ -97,7 +104,6 @@ const Sidebar = ({
classes={{ paper: classes.sidebarPaper }}
ModalProps={{ onBackdropClick: toggleSidebar }}
>
<div className={classes.headerPlaceholder} />
<Row align="center">
<SearchIcon className={classes.searchIcon} />
<SearchBar
@ -108,7 +114,6 @@ const Sidebar = ({
onCancelSearch={handleFilterCancel}
value={filter}
/>
<Spacer />
<Divider />
<Spacer />
<Button
@ -130,6 +135,7 @@ const Sidebar = ({
onSafeClick={toggleSidebar}
setDefaultSafe={setDefaultSafeAction}
defaultSafe={defaultSafe}
currentSafe={currentSafe}
/>
<LegalLinks toggleSidebar={toggleSidebar} />
</Drawer>
@ -141,6 +147,10 @@ const Sidebar = ({
export default connect<Object, Object, ?Function, ?Object>(
// $FlowFixMe
(state) => ({ safes: sortedSafeListSelector(state), defaultSafe: defaultSafeSelector(state) }),
(state) => ({
safes: sortedSafeListSelector(state),
defaultSafe: defaultSafeSelector(state),
currentSafe: safeParamAddressFromStateSelector(state),
}),
{ setDefaultSafeAction: setDefaultSafe },
)(Sidebar)

View File

@ -5,13 +5,24 @@ import {
} from '~/theme/variables'
const sidebarWidth = '400px'
const sidebarMarginLeft = '12px'
const sidebarMarginTop = '12px'
const sidebarMarginBottom = '12px'
const sidebarBorderRadius = '8px'
const useSidebarStyles = makeStyles({
sidebar: {
width: sidebarWidth,
marginLeft: sidebarMarginLeft,
borderRadius: sidebarBorderRadius,
top: sidebarMarginTop,
},
sidebarPaper: {
width: sidebarWidth,
marginLeft: sidebarMarginLeft,
top: `calc(${headerHeight} + ${sidebarMarginTop})`,
maxHeight: `calc(100vh - ${headerHeight} - ${sidebarMarginTop} - ${sidebarMarginBottom})`,
borderRadius: sidebarBorderRadius,
},
headerPlaceholder: {
minHeight: headerHeight,
@ -37,7 +48,7 @@ const useSidebarStyles = makeStyles({
},
},
searchContainer: {
width: '180px',
width: '190px',
marginLeft: xs,
marginRight: xs,
},

View File

@ -25,22 +25,29 @@ const activateTokensByBalance = (safeAddress: string) => async (
// balances: tokens' balance returned by the backend
const { addresses, balances } = result.data.reduce((acc, { tokenAddress, balance }) => ({
addresses: [...acc.addresses, tokenAddress],
balances: [...acc.balances, balance],
}), { addresses: [], balances: [] })
balances: [[tokenAddress, balance]],
}), {
addresses: [],
balances: [],
})
// update balance list for the safe
dispatch(updateSafe({ address: safeAddress, balances: Set(balances) }))
dispatch(updateSafe({
address: safeAddress,
balances: Set(balances),
}))
// active tokens by balance, excluding those already blacklisted and the `null` address
const activeByBalance = addresses.filter((address) => address !== null && !blacklistedTokens.includes(address))
// need to persist those already active tokens, despite its balances
const activeTokens = alreadyActiveTokens.toSet().union(activeByBalance)
const activeTokens = alreadyActiveTokens.toSet()
.union(activeByBalance)
// update list of active tokens
dispatch(updateActiveTokens(safeAddress, activeTokens))
} catch (err) {
console.error('Error fetching token list', err)
console.error('Error fetching active token list', err)
}
return null

View File

@ -158,7 +158,7 @@ const AddCustomToken = (props: Props) => {
name="symbol"
component={TextField}
type="text"
validate={composeValidators(required, minMaxLength(3, 12))}
validate={composeValidators(required, minMaxLength(2, 12))}
placeholder="Token symbol*"
text="Token symbol"
className={classes.addressInput}

View File

@ -1,11 +1,16 @@
// @flow
import { List } from 'immutable'
import { type Token } from '~/logic/tokens/store/model/token'
import { buildOrderFieldFrom, FIXED, type SortRow } from '~/components/Table/sorting'
import {
buildOrderFieldFrom,
FIXED,
type SortRow,
} from '~/components/Table/sorting'
import { type Column } from '~/components/Table/TableHead'
import { formatAmount } from '~/logic/tokens/utils/formatAmount'
import type { BalanceCurrencyType } from '~/logic/currencyValues/store/model/currencyValues'
import { AVAILABLE_CURRENCIES } from '~/logic/currencyValues/store/model/currencyValues'
import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers'
export const BALANCE_TABLE_ASSET_ID = 'asset'
export const BALANCE_TABLE_BALANCE_ID = 'balance'
@ -13,19 +18,35 @@ export const BALANCE_TABLE_VALUE_ID = 'value'
type BalanceData = {
asset: Object,
balance: string,
balance: string
}
export type BalanceRow = SortRow<BalanceData>
// eslint-disable-next-line max-len
const getTokenPriceInCurrency = (token: Token, currencySelected: AVAILABLE_CURRENCIES, currencyValues: List<BalanceCurrencyType>): string => {
const getTokenPriceInCurrency = (
token: Token,
currencySelected: typeof AVAILABLE_CURRENCIES,
currencyValues: List<BalanceCurrencyType>,
): string => {
// eslint-disable-next-line no-restricted-syntax
for (const tokenPriceIterator of currencyValues) {
const { tokenAddress, balanceInSelectedCurrency, currencyName } = tokenPriceIterator
const {
tokenAddress,
balanceInSelectedCurrency,
currencyName,
} = tokenPriceIterator
if (token.address === tokenAddress && currencySelected === currencyName) {
const balance = balanceInSelectedCurrency ? parseFloat(balanceInSelectedCurrency, 10).toFixed(2) : balanceInSelectedCurrency
const balance = balanceInSelectedCurrency
? parseFloat(balanceInSelectedCurrency, 10).toFixed(2)
: balanceInSelectedCurrency
return `${balance} ${currencySelected}`
}
// ETH token
if (token.address === ETH_ADDRESS && !tokenAddress) {
const balance = balanceInSelectedCurrency
? parseFloat(balanceInSelectedCurrency, 10).toFixed(2)
: balanceInSelectedCurrency
return `${balance} ${currencySelected}`
}
}
@ -33,14 +54,28 @@ const getTokenPriceInCurrency = (token: Token, currencySelected: AVAILABLE_CURRE
}
// eslint-disable-next-line max-len
export const getBalanceData = (activeTokens: List<Token>, currencySelected: string, currencyValues: List<BalanceCurrencyType>): List<BalanceRow> => {
export const getBalanceData = (
activeTokens: List<Token>,
currencySelected: string,
currencyValues: List<BalanceCurrencyType>,
): List<BalanceRow> => {
const rows = activeTokens.map((token: Token) => ({
[BALANCE_TABLE_ASSET_ID]: { name: token.name, logoUri: token.logoUri, address: token.address },
[BALANCE_TABLE_ASSET_ID]: {
name: token.name,
logoUri: token.logoUri,
address: token.address,
},
[buildOrderFieldFrom(BALANCE_TABLE_ASSET_ID)]: token.name,
[BALANCE_TABLE_BALANCE_ID]: `${formatAmount(token.balance)} ${token.symbol}`,
[BALANCE_TABLE_BALANCE_ID]: `${formatAmount(token.balance)} ${
token.symbol
}`,
[buildOrderFieldFrom(BALANCE_TABLE_BALANCE_ID)]: Number(token.balance),
[FIXED]: token.get('symbol') === 'ETH',
[BALANCE_TABLE_VALUE_ID]: getTokenPriceInCurrency(token, currencySelected, currencyValues),
[BALANCE_TABLE_VALUE_ID]: getTokenPriceInCurrency(
token,
currencySelected,
currencyValues,
),
}))
return rows
@ -96,4 +131,7 @@ export const generateColumns = () => {
}
// eslint-disable-next-line max-len
export const filterByZero = (data: List<BalanceRow>, hideZero: boolean): List<BalanceRow> => data.filter((row: BalanceRow) => (hideZero ? row[buildOrderFieldFrom(BALANCE_TABLE_BALANCE_ID)] !== 0 : true))
export const filterByZero = (
data: List<BalanceRow>,
hideZero: boolean,
): List<BalanceRow> => data.filter((row: BalanceRow) => (hideZero ? row[buildOrderFieldFrom(BALANCE_TABLE_BALANCE_ID)] !== 0 : true))

View File

@ -24,7 +24,7 @@ type TxData = {
date: string,
dateOrder?: number,
amount: number | string,
tx: Transaction,
tx: Transaction | IncomingTransaction,
status?: string,
}
@ -64,7 +64,7 @@ const getIncomingTxTableData = (tx: IncomingTransaction): TransactionRow => ({
})
const getTransactionTableData = (tx: Transaction): TransactionRow => {
const txDate = tx.isExecuted ? tx.executionDate : tx.submissionDate
const txDate = tx.submissionDate
let txType = 'outgoing'
if (tx.modifySettingsTx) {
@ -80,9 +80,7 @@ const getTransactionTableData = (tx: Transaction): TransactionRow => {
return {
[TX_TABLE_ID]: tx.blockNumber,
[TX_TABLE_TYPE_ID]: <TxType txType={txType} />,
[TX_TABLE_DATE_ID]: tx.isExecuted
? tx.executionDate && formatDate(tx.executionDate)
: tx.submissionDate && formatDate(tx.submissionDate),
[TX_TABLE_DATE_ID]: txDate ? formatDate(txDate) : '',
[buildOrderFieldFrom(TX_TABLE_DATE_ID)]: txDate ? getTime(parseISO(txDate)) : null,
[TX_TABLE_AMOUNT_ID]: getTxAmount(tx),
[TX_TABLE_STATUS_ID]: tx.status,

View File

@ -19,7 +19,7 @@ import { getHumanFriendlyToken } from '~/logic/tokens/store/actions/fetchTokens'
import { isTokenTransfer } from '~/logic/tokens/utils/tokenHelpers'
import { decodeParamsFromSafeMethod } from '~/logic/contracts/methodIds'
import { ALTERNATIVE_TOKEN_ABI } from '~/logic/tokens/utils/alternativeAbi'
import { ZERO_ADDRESS } from '~/logic/wallets/ethAddresses'
import { ZERO_ADDRESS, sameAddress } from '~/logic/wallets/ethAddresses'
let web3
@ -77,10 +77,10 @@ export const buildTransactionFrom = async (
})
}),
)
const modifySettingsTx = tx.to === safeAddress && Number(tx.value) === 0 && !!tx.data
const cancellationTx = tx.to === safeAddress && Number(tx.value) === 0 && !tx.data
const modifySettingsTx = sameAddress(tx.to, safeAddress) && Number(tx.value) === 0 && !!tx.data
const cancellationTx = sameAddress(tx.to, safeAddress) && Number(tx.value) === 0 && !tx.data
const isSendTokenTx = await isTokenTransfer(tx.data, tx.value)
const customTx = tx.to !== safeAddress && !!tx.data && !isSendTokenTx
const customTx = !sameAddress(tx.to, safeAddress) && !!tx.data && !isSendTokenTx
let refundParams = null
if (tx.gasPrice > 0) {

View File

@ -70,6 +70,15 @@ export const safeTransactionsSelector: Selector<GlobalState, RouterProps, List<T
},
)
export const safeParamAddressFromStateSelector = (state: GlobalState): string => {
const match = matchPath(
state.router.location.pathname,
{ path: `${SAFELIST_ADDRESS}/:safeAddress` },
)
return match ? match.params.safeAddress : null
}
export const safeIncomingTransactionsSelector: Selector<GlobalState, RouterProps, List<IncomingTransaction>> = createSelector(
incomingTransactionsSelector,
safeParamAddressSelector,

View File

@ -13,6 +13,7 @@ const md = '16px'
const primary = '#001428'
const secondary = '#008C73'
const secondaryTextOrSvg = '#B2B5B2'
const secondaryBackground = '#f0efee'
const sm = '8px'
const warningColor = '#ffc05f'
const xl = '32px'
@ -57,6 +58,7 @@ module.exports = {
secondary,
secondaryFontFamily: 'Averta, monospace',
secondaryText: secondaryTextOrSvg,
secondaryBackground,
sm,
smallFontSize: '12px',
warning: warningColor,

View File

@ -8,7 +8,7 @@ import { getNetwork } from '~/config'
const stores = [IndexedDbStore, LocalStorageStore]
export const storage = new ImmortalStorage(stores)
const PREFIX = `v1_${getNetwork()}`
const PREFIX = `v2_${getNetwork()}`
export const loadFromStorage = async (key: string): Promise<*> => {
try {

919
yarn.lock

File diff suppressed because it is too large Load Diff