From 32d6fcc14de9acdba89793c4a4ae0fac7e4dbbdd Mon Sep 17 00:00:00 2001 From: unlocker Date: Mon, 2 Aug 2021 07:32:25 -0700 Subject: [PATCH 1/4] Add network and remove apps, etc --- .env.example | 32 -- src/components/App/index.tsx | 12 +- src/config/assets/token-one.png | Bin 0 -> 19011 bytes src/config/assets/token_eth.svg | 18 - src/config/assets/token_ewc.svg | 18 - src/config/assets/token_xdai.svg | 22 -- src/config/index.ts | 26 +- src/config/networks/energy_web_chain.ts | 65 ---- src/config/networks/index.ts | 12 +- src/config/networks/local.ts | 42 --- src/config/networks/mainnet.ts | 34 +- src/config/networks/network.d.ts | 27 +- src/config/networks/rinkeby.ts | 53 --- src/config/networks/testnet.ts | 48 +++ src/config/networks/volta.ts | 62 ---- src/config/networks/xdai.ts | 59 ---- src/logic/collectibles/utils/index.ts | 18 - src/logic/contracts/safeContracts.ts | 64 +++- src/logic/wallets/store/model/provider.ts | 6 +- src/logic/wallets/store/selectors/index.ts | 13 +- src/logic/wallets/utils/walletList.ts | 54 +-- .../components/Apps/__tests__/utils.test.ts | 48 --- .../components/Apps/api/fetchSafeAppsList.ts | 21 -- .../safe/components/Apps/assets/addApp.svg | 31 -- .../safe/components/Apps/communicator.ts | 114 ------ .../components/AddAppForm/AppAgreement.tsx | 30 -- .../Apps/components/AddAppForm/AppUrl.tsx | 89 ----- .../components/AddAppForm/FormButtons.tsx | 31 -- .../Apps/components/AddAppForm/index.tsx | 140 -------- .../Apps/components/AppCard/index.stories.tsx | 25 -- .../Apps/components/AppCard/index.tsx | 108 ------ .../Apps/components/AppCard/skeleton.tsx | 41 --- .../components/Apps/components/AppFrame.tsx | 331 ------------------ .../components/Apps/components/AppsList.tsx | 190 ---------- .../ConfirmTxModal/DecodedTxDetail.tsx | 62 ---- .../ConfirmTxModal/ReviewConfirm.tsx | 267 -------------- .../ConfirmTxModal/SafeAppLoadError.tsx | 47 --- .../Apps/components/ConfirmTxModal/index.tsx | 72 ---- .../Apps/components/LegalDisclaimer.tsx | 34 -- .../safe/components/Apps/hooks/useAppList.ts | 97 ----- .../Apps/hooks/useIframeMessageHandler.ts | 147 -------- .../components/Apps/hooks/useLegalConsent.ts | 31 -- src/routes/safe/components/Apps/index.tsx | 17 - src/routes/safe/components/Apps/utils.ts | 316 +++++------------ src/utils/constants.ts | 29 +- src/utils/googleAnalytics.ts | 86 ----- src/utils/intercom.ts | 35 -- 47 files changed, 227 insertions(+), 2897 deletions(-) delete mode 100644 .env.example create mode 100644 src/config/assets/token-one.png delete mode 100644 src/config/assets/token_eth.svg delete mode 100644 src/config/assets/token_ewc.svg delete mode 100644 src/config/assets/token_xdai.svg delete mode 100644 src/config/networks/energy_web_chain.ts delete mode 100644 src/config/networks/local.ts delete mode 100644 src/config/networks/rinkeby.ts create mode 100644 src/config/networks/testnet.ts delete mode 100644 src/config/networks/volta.ts delete mode 100644 src/config/networks/xdai.ts delete mode 100644 src/routes/safe/components/Apps/__tests__/utils.test.ts delete mode 100644 src/routes/safe/components/Apps/api/fetchSafeAppsList.ts delete mode 100644 src/routes/safe/components/Apps/assets/addApp.svg delete mode 100644 src/routes/safe/components/Apps/communicator.ts delete mode 100644 src/routes/safe/components/Apps/components/AddAppForm/AppAgreement.tsx delete mode 100644 src/routes/safe/components/Apps/components/AddAppForm/AppUrl.tsx delete mode 100644 src/routes/safe/components/Apps/components/AddAppForm/FormButtons.tsx delete mode 100644 src/routes/safe/components/Apps/components/AddAppForm/index.tsx delete mode 100644 src/routes/safe/components/Apps/components/AppCard/index.stories.tsx delete mode 100644 src/routes/safe/components/Apps/components/AppCard/index.tsx delete mode 100644 src/routes/safe/components/Apps/components/AppCard/skeleton.tsx delete mode 100644 src/routes/safe/components/Apps/components/AppFrame.tsx delete mode 100644 src/routes/safe/components/Apps/components/AppsList.tsx delete mode 100644 src/routes/safe/components/Apps/components/ConfirmTxModal/DecodedTxDetail.tsx delete mode 100644 src/routes/safe/components/Apps/components/ConfirmTxModal/ReviewConfirm.tsx delete mode 100644 src/routes/safe/components/Apps/components/ConfirmTxModal/SafeAppLoadError.tsx delete mode 100644 src/routes/safe/components/Apps/components/ConfirmTxModal/index.tsx delete mode 100644 src/routes/safe/components/Apps/components/LegalDisclaimer.tsx delete mode 100644 src/routes/safe/components/Apps/hooks/useAppList.ts delete mode 100644 src/routes/safe/components/Apps/hooks/useIframeMessageHandler.ts delete mode 100644 src/routes/safe/components/Apps/hooks/useLegalConsent.ts delete mode 100644 src/routes/safe/components/Apps/index.tsx delete mode 100644 src/utils/googleAnalytics.ts delete mode 100644 src/utils/intercom.ts diff --git a/.env.example b/.env.example deleted file mode 100644 index 28c8161cdc..0000000000 --- a/.env.example +++ /dev/null @@ -1,32 +0,0 @@ -# You can leave this empty for rinkeby or use "mainnet" -REACT_APP_NETWORK= - -# For all environments -REACT_APP_GOOGLE_ANALYTICS= -REACT_APP_INFURA_TOKEN= -REACT_APP_IPFS_GATEWAY=https://ipfs.io/ipfs -REACT_APP_SENTRY_DSN= - -# For production environments -REACT_APP_BLOCKNATIVE_KEY= -REACT_APP_INTERCOM_ID= -REACT_APP_PORTIS_ID= -REACT_APP_SQUARELINK_ID= -REACT_APP_FORTMATIC_KEY= -REACT_APP_OPENSEA_API_KEY= -REACT_APP_COLLECTIBLES_SOURCE= -REACT_APP_ETHERSCAN_API_KEY= -REACT_APP_ETHGASSTATION_API_KEY= - -# Versions -REACT_APP_LATEST_SAFE_VERSION= - -# Leave it untouched, version will set using dotenv-expand -REACT_APP_APP_VERSION=$npm_package_version - -# For Apps -REACT_APP_GNOSIS_APPS_URL=https://safe-apps.staging.gnosisdev.com - -# Contracts Addresses -REACT_APP_SPENDING_LIMIT_MODULE_ADDRESS=0x9e9Bf12b5a66c0f0A7435835e0365477E121B110 - diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index 2c26a45533..bfb08aba10 100644 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -17,7 +17,7 @@ import Notifier from 'src/components/Notifier' import Backdrop from 'src/components/layout/Backdrop' import Img from 'src/components/layout/Img' import { getNetworkId } from 'src/config' -import { ETHEREUM_NETWORK } from 'src/config/networks/network.d' +import { HARMONY_NETWORK } from 'src/config/networks/network.d' import { networkSelector } from 'src/logic/wallets/store/selectors' import { SAFELIST_ADDRESS, WELCOME_ADDRESS } from 'src/routes/routes' import { currentSafeWithNames, safeAddressFromUrl } from 'src/logic/safe/store/selectors' @@ -62,13 +62,15 @@ const useStyles = makeStyles(notificationStyles) const App: React.FC = ({ children }) => { const classes = useStyles() const currentNetwork = useSelector(networkSelector) - const isWrongNetwork = currentNetwork !== ETHEREUM_NETWORK.UNKNOWN && currentNetwork !== desiredNetwork + const isWrongNetwork = currentNetwork !== HARMONY_NETWORK.UNKNOWN && currentNetwork !== desiredNetwork const { toggleSidebar } = useContext(SafeListSidebarContext) const matchSafe = useRouteMatch({ path: `${SAFELIST_ADDRESS}`, strict: false }) const history = useHistory() - const { address: safeAddress, name: safeName, totalFiatBalance: currentSafeBalance } = useSelector( - currentSafeWithNames, - ) + const { + address: safeAddress, + name: safeName, + totalFiatBalance: currentSafeBalance, + } = useSelector(currentSafeWithNames) const addressFromUrl = useSelector(safeAddressFromUrl) const { safeActionsState, onShow, onHide, showSendFunds, hideSendFunds } = useSafeActions() const currentCurrency = useSelector(currentCurrencySelector) diff --git a/src/config/assets/token-one.png b/src/config/assets/token-one.png new file mode 100644 index 0000000000000000000000000000000000000000..62abd95c1f22504563e9ad6d2552c4b1188a233e GIT binary patch literal 19011 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 literal 0 HcmV?d00001 diff --git a/src/config/assets/token_eth.svg b/src/config/assets/token_eth.svg deleted file mode 100644 index 235beb548b..0000000000 --- a/src/config/assets/token_eth.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - diff --git a/src/config/assets/token_ewc.svg b/src/config/assets/token_ewc.svg deleted file mode 100644 index f52e22854d..0000000000 --- a/src/config/assets/token_ewc.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - -ewf_logo - - diff --git a/src/config/assets/token_xdai.svg b/src/config/assets/token_xdai.svg deleted file mode 100644 index 044b3395a7..0000000000 --- a/src/config/assets/token_xdai.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - -Group 6 -Created with Sketch. - - - - - - - - - - - - diff --git a/src/config/index.ts b/src/config/index.ts index 0eec893d68..734c7f66ee 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -2,7 +2,7 @@ import memoize from 'lodash.memoize' import networks from 'src/config/networks' import { EnvironmentSettings, - ETHEREUM_NETWORK, + HARMONY_NETWORK, FEATURES, GasPriceOracle, NetworkInfo, @@ -10,14 +10,12 @@ import { SafeFeatures, Wallets, } from 'src/config/networks/network.d' -import { APP_ENV, ETHERSCAN_API_KEY, GOOGLE_ANALYTICS_ID, INFURA_TOKEN, NETWORK, NODE_ENV } from 'src/utils/constants' +import { APP_ENV, NETWORK, NODE_ENV } from 'src/utils/constants' import { ensureOnce } from 'src/utils/singleton' -export const getNetworkId = (): ETHEREUM_NETWORK => ETHEREUM_NETWORK[NETWORK] +export const getNetworkId = (): HARMONY_NETWORK => HARMONY_NETWORK[NETWORK] -export const getNetworkName = (): string => ETHEREUM_NETWORK[getNetworkId()] - -export const usesInfuraRPC = [ETHEREUM_NETWORK.MAINNET, ETHEREUM_NETWORK.RINKEBY].includes(getNetworkId()) +export const getNetworkName = (): string => HARMONY_NETWORK[getNetworkId()] const getCurrentEnvironment = (): string => { switch (NODE_ENV) { @@ -44,7 +42,7 @@ const configuration = (): NetworkSpecificConfiguration => { // special case for test environment if (currentEnvironment === 'test') { - const configFile = networks.local + const configFile = networks.testnet return { ...configFile.environment.production, @@ -69,7 +67,7 @@ const configuration = (): NetworkSpecificConfiguration => { const getConfig: () => NetworkSpecificConfiguration = ensureOnce(configuration) export const getNetworks = (): NetworkInfo[] => { - const { local, ...usefulNetworks } = networks + const { ...usefulNetworks } = networks return Object.values(usefulNetworks).map((networkObj) => ({ id: networkObj.network.id, label: networkObj.network.label, @@ -91,14 +89,15 @@ export const getGasPrice = (): number | undefined => getConfig()?.gasPrice export const getGasPriceOracle = (): GasPriceOracle | undefined => getConfig()?.gasPriceOracle -export const getRpcServiceUrl = (): string => - usesInfuraRPC ? `${getConfig().rpcServiceUrl}/${INFURA_TOKEN}` : getConfig().rpcServiceUrl - export const getSafeClientGatewayBaseUrl = (safeAddress: string) => `${getClientGatewayUrl()}/safes/${safeAddress}` export const getTxDetailsUrl = (clientGatewayTxId: string) => `${getClientGatewayUrl()}/transactions/${clientGatewayTxId}` +export const getRpcServiceUrl = (): string => { + return getConfig().rpcServiceUrl +} + export const getSafeServiceBaseUrl = (safeAddress: string) => `${getTxServiceUrl()}/safes/${safeAddress}` export const getTokensServiceBaseUrl = () => `${getTxServiceUrl()}/tokens` @@ -125,8 +124,6 @@ export const getNetworkConfigDisabledWallets = (): Wallets => getConfig()?.disab export const getNetworkInfo = (): NetworkSettings => getConfig().network -export const getGoogleAnalyticsTrackingID = (): string => GOOGLE_ANALYTICS_ID - const fetchContractABI = memoize( async (url: string, contractAddress: string, apiKey?: string) => { let params: Record = { @@ -152,9 +149,6 @@ const fetchContractABI = memoize( const getNetworkExplorerApiKey = (networkExplorerName: string): string | undefined => { switch (networkExplorerName.toLowerCase()) { - case 'etherscan': { - return ETHERSCAN_API_KEY - } default: { return undefined } diff --git a/src/config/networks/energy_web_chain.ts b/src/config/networks/energy_web_chain.ts deleted file mode 100644 index f8423b6747..0000000000 --- a/src/config/networks/energy_web_chain.ts +++ /dev/null @@ -1,65 +0,0 @@ -import EwcLogo from 'src/config/assets/token_ewc.svg' -import { EnvironmentSettings, ETHEREUM_NETWORK, NetworkConfig, WALLETS } from 'src/config/networks/network.d' - -// @todo (agustin) we need to use fixed gasPrice because the oracle is not working right now and it's returning 0 -// once the oracle is fixed we need to remove the fixed value -const baseConfig: EnvironmentSettings = { - clientGatewayUrl: 'https://safe-client.ewc.gnosis.io/v1', - txServiceUrl: 'https://safe-transaction.ewc.gnosis.io/api/v1', - safeUrl: 'https://ewc.gnosis-safe.io/app', - safeAppsUrl: 'https://safe-apps-ewc.staging.gnosisdev.com', - gasPriceOracle: { - url: 'https://station.energyweb.org', - gasParameter: 'standard', - }, - gasPrice: 1e6, - rpcServiceUrl: 'https://rpc.energyweb.org', - networkExplorerName: 'Energy web explorer', - networkExplorerUrl: 'https://explorer.energyweb.org', - networkExplorerApiUrl: 'https://explorer.energyweb.org/api', -} - -const mainnet: NetworkConfig = { - environment: { - dev: { - ...baseConfig, - }, - staging: { - ...baseConfig, - }, - production: { - ...baseConfig, - safeAppsUrl: 'https://apps-ewc.gnosis-safe.io', - }, - }, - network: { - id: ETHEREUM_NETWORK.ENERGY_WEB_CHAIN, - backgroundColor: '#A566FF', - textColor: '#ffffff', - label: 'EWC', - isTestNet: false, - nativeCoin: { - address: '0x0000000000000000000000000000000000000000', - name: 'Energy web token', - symbol: 'EWT', - decimals: 18, - logoUri: EwcLogo, - }, - }, - disabledWallets: [ - WALLETS.TREZOR, - WALLETS.LEDGER, - WALLETS.COINBASE, - WALLETS.FORTMATIC, - WALLETS.OPERA, - WALLETS.OPERA_TOUCH, - WALLETS.PORTIS, - WALLETS.TORUS, - WALLETS.TRUST, - WALLETS.WALLET_LINK, - WALLETS.AUTHEREUM, - WALLETS.LATTICE, - ], -} - -export default mainnet diff --git a/src/config/networks/index.ts b/src/config/networks/index.ts index 03ef405b11..68cbf41314 100644 --- a/src/config/networks/index.ts +++ b/src/config/networks/index.ts @@ -1,15 +1,7 @@ -import local from './local' import mainnet from './mainnet' -import rinkeby from './rinkeby' -import xdai from './xdai' -import energy_web_chain from './energy_web_chain' -import volta from './volta' +import testnet from './testnet' export default { - local, mainnet, - rinkeby, - xdai, - energy_web_chain, - volta, + testnet, } diff --git a/src/config/networks/local.ts b/src/config/networks/local.ts deleted file mode 100644 index eaaed47bbf..0000000000 --- a/src/config/networks/local.ts +++ /dev/null @@ -1,42 +0,0 @@ -import EtherLogo from 'src/config/assets/token_eth.svg' -import { EnvironmentSettings, ETHEREUM_NETWORK, NetworkConfig } from 'src/config/networks/network.d' - -const baseConfig: EnvironmentSettings = { - clientGatewayUrl: 'http://localhost:8001/v1', - txServiceUrl: 'http://localhost:8000/api/v1', - relayApiUrl: 'https://safe-relay.staging.gnosisdev.com/api/v1', - safeUrl: 'http://localhost:3000/app', - safeAppsUrl: 'http://localhost:3002', - gasPriceOracle: { - url: 'https://ethgasstation.info/json/ethgasAPI.json', - gasParameter: 'average', - }, - rpcServiceUrl: 'http://localhost:4447', - networkExplorerName: 'Etherscan', - networkExplorerUrl: 'https://rinkeby.etherscan.io', - networkExplorerApiUrl: 'https://api-rinkeby.etherscan.io/api', -} - -const local: NetworkConfig = { - environment: { - production: { - ...baseConfig, - }, - }, - network: { - id: ETHEREUM_NETWORK.LOCAL, - backgroundColor: '#E8673C', - textColor: '#ffffff', - label: 'LocalRPC', - isTestNet: true, - nativeCoin: { - address: '0x0000000000000000000000000000000000000000', - name: 'Ether', - symbol: 'ETH', - decimals: 18, - logoUri: EtherLogo, - }, - }, -} - -export default local diff --git a/src/config/networks/mainnet.ts b/src/config/networks/mainnet.ts index 86566f47b4..b867174131 100644 --- a/src/config/networks/mainnet.ts +++ b/src/config/networks/mainnet.ts @@ -1,19 +1,16 @@ -import EtherLogo from 'src/config/assets/token_eth.svg' -import { EnvironmentSettings, ETHEREUM_NETWORK, NetworkConfig } from 'src/config/networks/network.d' -import { ETHGASSTATION_API_KEY } from 'src/utils/constants' +import HarmonyLogo from 'src/config/assets/token-one.png' +import { EnvironmentSettings, HARMONY_NETWORK, NetworkConfig } from 'src/config/networks/network.d' const baseConfig: EnvironmentSettings = { - clientGatewayUrl: 'https://safe-client.mainnet.staging.gnosisdev.com/v1', - txServiceUrl: 'https://safe-transaction.mainnet.staging.gnosisdev.com/api/v1', - safeUrl: 'https://gnosis-safe.io/app', - safeAppsUrl: 'https://safe-apps.dev.gnosisdev.com', + txServiceUrl: 'https://multisig.t.hmny.io/api/v1', + safeAppsUrl: 'https://multisig.harmony.one', gasPriceOracle: { url: 'https://ethgasstation.info/json/ethgasAPI.json', gasParameter: 'average', }, - rpcServiceUrl: 'https://mainnet.infura.io:443/v3', - networkExplorerName: 'Etherscan', - networkExplorerUrl: 'https://etherscan.io', + rpcServiceUrl: 'https://api.s0.t.hmny.io', + networkExplorerName: 'Harmony Explorer', + networkExplorerUrl: 'https://explorer.harmony.one/#', networkExplorerApiUrl: 'https://api.etherscan.io/api', } @@ -24,27 +21,26 @@ const mainnet: NetworkConfig = { }, staging: { ...baseConfig, - safeAppsUrl: 'https://safe-apps.staging.gnosisdev.com', + safeAppsUrl: 'https://multisig.harmony.one', }, production: { ...baseConfig, - clientGatewayUrl: 'https://safe-client.mainnet.gnosis.io/v1', - txServiceUrl: 'https://safe-transaction.mainnet.gnosis.io/api/v1', - safeAppsUrl: 'https://apps.gnosis-safe.io', + txServiceUrl: 'https://multisig.t.hmny.io/api/v1', + safeAppsUrl: 'https://multisig.harmony.one', }, }, network: { - id: ETHEREUM_NETWORK.MAINNET, + id: HARMONY_NETWORK.MAINNET, backgroundColor: '#E8E7E6', textColor: '#001428', label: 'Mainnet', isTestNet: false, nativeCoin: { - address: '0x0000000000000000000000000000000000000000', - name: 'Ether', - symbol: 'ETH', + address: '0x000', + name: 'Harmony', + symbol: 'ONE', decimals: 18, - logoUri: EtherLogo, + logoUri: HarmonyLogo, }, }, } diff --git a/src/config/networks/network.d.ts b/src/config/networks/network.d.ts index bdde60c74c..ba81f31d37 100644 --- a/src/config/networks/network.d.ts +++ b/src/config/networks/network.d.ts @@ -2,19 +2,6 @@ export enum WALLETS { METAMASK = 'metamask', - WALLET_CONNECT = 'walletConnect', - TREZOR = 'trezor', - LEDGER = 'ledger', - TRUST = 'trust', - FORTMATIC = 'fortmatic', - PORTIS = 'portis', - AUTHEREUM = 'authereum', - TORUS = 'torus', - COINBASE = 'coinbase', - WALLET_LINK = 'walletLink', - OPERA = 'opera', - OPERA_TOUCH = 'operaTouch', - LATTICE = 'lattice', } export enum FEATURES { @@ -33,18 +20,10 @@ type Token = { logoUri?: string } -export enum ETHEREUM_NETWORK { +export enum HARMONY_NETWORK { + MAINNET = 1666600000, + TESTNET = 1666700000, UNKNOWN = 0, - MAINNET = 1, - MORDEN = 2, - ROPSTEN = 3, - RINKEBY = 4, - GOERLI = 5, - KOVAN = 42, - XDAI = 100, - ENERGY_WEB_CHAIN = 246, - LOCAL = 4447, - VOLTA = 73799, } export type NetworkSettings = { diff --git a/src/config/networks/rinkeby.ts b/src/config/networks/rinkeby.ts deleted file mode 100644 index 4cb16b488c..0000000000 --- a/src/config/networks/rinkeby.ts +++ /dev/null @@ -1,53 +0,0 @@ -import EtherLogo from 'src/config/assets/token_eth.svg' -import { EnvironmentSettings, ETHEREUM_NETWORK, NetworkConfig, WALLETS } from 'src/config/networks/network.d' -import { ETHGASSTATION_API_KEY } from 'src/utils/constants' - -const baseConfig: EnvironmentSettings = { - clientGatewayUrl: 'https://safe-client.rinkeby.staging.gnosisdev.com/v1', - txServiceUrl: 'https://safe-transaction.rinkeby.staging.gnosisdev.com/api/v1', - safeUrl: 'https://rinkeby.gnosis-safe.io/app', - safeAppsUrl: 'https://safe-apps.dev.gnosisdev.com', - gasPriceOracle: { - url: `https://ethgasstation.info/json/ethgasAPI.json?api-key=${ETHGASSTATION_API_KEY}`, - gasParameter: 'average', - }, - rpcServiceUrl: 'https://rinkeby.infura.io:443/v3', - networkExplorerName: 'Etherscan', - networkExplorerUrl: 'https://rinkeby.etherscan.io', - networkExplorerApiUrl: 'https://api-rinkeby.etherscan.io/api', -} - -const rinkeby: NetworkConfig = { - environment: { - dev: { - ...baseConfig, - }, - staging: { - ...baseConfig, - safeAppsUrl: 'https://safe-apps.staging.gnosisdev.com', - }, - production: { - ...baseConfig, - clientGatewayUrl: 'https://safe-client.rinkeby.gnosis.io/v1', - txServiceUrl: 'https://safe-transaction.rinkeby.gnosis.io/api/v1', - safeAppsUrl: 'https://apps.gnosis-safe.io', - }, - }, - network: { - id: ETHEREUM_NETWORK.RINKEBY, - backgroundColor: '#E8673C', - textColor: '#ffffff', - label: 'Rinkeby', - isTestNet: true, - nativeCoin: { - address: '0x0000000000000000000000000000000000000000', - name: 'Ether', - symbol: 'ETH', - decimals: 18, - logoUri: EtherLogo, - }, - }, - disabledWallets: [WALLETS.FORTMATIC], -} - -export default rinkeby diff --git a/src/config/networks/testnet.ts b/src/config/networks/testnet.ts new file mode 100644 index 0000000000..9238ebcf2a --- /dev/null +++ b/src/config/networks/testnet.ts @@ -0,0 +1,48 @@ +import HarmonyLogo from 'src/config/assets/token-one.png' +import { EnvironmentSettings, HARMONY_NETWORK, NetworkConfig } from 'src/config/networks/network.d' + +const baseConfig: EnvironmentSettings = { + txServiceUrl: 'https://multisig-staging.hmny.io/api/v1', + safeAppsUrl: 'https://testnet.multisig.harmony.one', + gasPriceOracle: { + url: 'https://ethgasstation.info/json/ethgasAPI.json', + gasParameter: 'average', + }, + rpcServiceUrl: 'https://api.s0.b.hmny.io', + networkExplorerName: 'Harmony Explorer', + networkExplorerUrl: 'https://explorer.pops.one/#', + networkExplorerApiUrl: 'https://api-rinkeby.etherscan.io/api', +} + +const testnet: NetworkConfig = { + environment: { + dev: { + ...baseConfig, + }, + staging: { + ...baseConfig, + safeAppsUrl: 'https://testnet.multisig.harmony.one', + }, + production: { + ...baseConfig, + txServiceUrl: 'https://multisig-staging.hmny.io/api/v1', + safeAppsUrl: 'https://testnet.multisig.harmony.one', + }, + }, + network: { + id: HARMONY_NETWORK.TESTNET, + backgroundColor: '#E8673C', + textColor: '#ffffff', + label: 'Testnet', + isTestNet: true, + nativeCoin: { + address: '0x000', + name: 'Harmony', + symbol: 'ONE', + decimals: 18, + logoUri: HarmonyLogo, + }, + }, +} + +export default testnet diff --git a/src/config/networks/volta.ts b/src/config/networks/volta.ts deleted file mode 100644 index 70601edf1c..0000000000 --- a/src/config/networks/volta.ts +++ /dev/null @@ -1,62 +0,0 @@ -import EwcLogo from 'src/config/assets/token_ewc.svg' -import { EnvironmentSettings, ETHEREUM_NETWORK, NetworkConfig, WALLETS } from 'src/config/networks/network.d' - -const baseConfig: EnvironmentSettings = { - clientGatewayUrl: 'https://safe-client.volta.gnosis.io/v1', - txServiceUrl: 'https://safe-transaction.volta.gnosis.io/api/v1', - safeUrl: 'https://volta.gnosis-safe.io/app', - safeAppsUrl: 'https://safe-apps-volta.staging.gnosisdev.com', - gasPriceOracle: { - url: 'https://station.energyweb.org', - gasParameter: 'standard', - }, - rpcServiceUrl: 'https://volta-rpc.energyweb.org', - networkExplorerName: 'Volta explorer', - networkExplorerUrl: 'https://volta-explorer.energyweb.org', - networkExplorerApiUrl: 'https://volta-explorer.energyweb.org/api', -} - -const mainnet: NetworkConfig = { - environment: { - dev: { - ...baseConfig, - }, - staging: { - ...baseConfig, - }, - production: { - ...baseConfig, - safeAppsUrl: 'https://apps-volta.gnosis-safe.io', - }, - }, - network: { - id: ETHEREUM_NETWORK.VOLTA, - backgroundColor: '#514989', - textColor: '#ffffff', - label: 'Volta', - isTestNet: true, - nativeCoin: { - address: '0x0000000000000000000000000000000000000000', - name: 'Volta Token', - symbol: 'VT', - decimals: 18, - logoUri: EwcLogo, - }, - }, - disabledWallets: [ - WALLETS.TREZOR, - WALLETS.LEDGER, - WALLETS.COINBASE, - WALLETS.FORTMATIC, - WALLETS.OPERA, - WALLETS.OPERA_TOUCH, - WALLETS.PORTIS, - WALLETS.TORUS, - WALLETS.TRUST, - WALLETS.WALLET_LINK, - WALLETS.AUTHEREUM, - WALLETS.LATTICE, - ], -} - -export default mainnet diff --git a/src/config/networks/xdai.ts b/src/config/networks/xdai.ts deleted file mode 100644 index 3dee3d8e1a..0000000000 --- a/src/config/networks/xdai.ts +++ /dev/null @@ -1,59 +0,0 @@ -import xDaiLogo from 'src/config/assets/token_xdai.svg' -import { EnvironmentSettings, ETHEREUM_NETWORK, FEATURES, NetworkConfig, WALLETS } from 'src/config/networks/network.d' - -const baseConfig: EnvironmentSettings = { - clientGatewayUrl: 'https://safe-client.xdai.gnosis.io/v1', - txServiceUrl: 'https://safe-transaction.xdai.gnosis.io/api/v1', - safeUrl: 'https://xdai.gnosis-safe.io/app', - safeAppsUrl: 'https://safe-apps-xdai.staging.gnosisdev.com', - gasPrice: 1e9, - rpcServiceUrl: 'https://dai.poa.network/', - networkExplorerName: 'Blockscout', - networkExplorerUrl: 'https://blockscout.com/poa/xdai', - networkExplorerApiUrl: 'https://blockscout.com/poa/xdai/api', -} - -const xDai: NetworkConfig = { - environment: { - dev: { - ...baseConfig, - }, - staging: { - ...baseConfig, - }, - production: { - ...baseConfig, - safeAppsUrl: 'https://apps-xdai.gnosis-safe.io', - }, - }, - network: { - id: ETHEREUM_NETWORK.XDAI, - backgroundColor: '#48A8A6', - textColor: '#ffffff', - label: 'xDai', - isTestNet: false, - nativeCoin: { - address: '0x0000000000000000000000000000000000000000', - name: 'xDai', - symbol: 'xDai', - decimals: 18, - logoUri: xDaiLogo, - }, - }, - disabledWallets: [ - WALLETS.TREZOR, - WALLETS.LEDGER, - WALLETS.COINBASE, - WALLETS.FORTMATIC, - WALLETS.OPERA, - WALLETS.OPERA_TOUCH, - WALLETS.TORUS, - WALLETS.TRUST, - WALLETS.WALLET_LINK, - WALLETS.AUTHEREUM, - WALLETS.LATTICE, - ], - disabledFeatures: [FEATURES.DOMAIN_LOOKUP], -} - -export default xDai diff --git a/src/logic/collectibles/utils/index.ts b/src/logic/collectibles/utils/index.ts index 6aae4ff236..756618f0ea 100644 --- a/src/logic/collectibles/utils/index.ts +++ b/src/logic/collectibles/utils/index.ts @@ -1,18 +1,6 @@ -import { getNetworkId } from 'src/config' -import { ETHEREUM_NETWORK } from 'src/config/networks/network.d' import { getERC721TokenContract, getStandardTokenContract } from 'src/logic/tokens/store/actions/fetchTokens' -import { sameAddress } from 'src/logic/wallets/ethAddresses' import { CollectibleTx } from 'src/routes/safe/components/Balances/SendModal/screens/ReviewCollectible' -// CryptoKitties Contract Addresses by network -// This is an exception made for a popular NFT that's not ERC721 standard-compatible, -// so we can allow the user to transfer the assets by using `transferFrom` instead of -// the standard `safeTransferFrom` method. -export const CK_ADDRESS = { - [ETHEREUM_NETWORK.MAINNET]: '0x06012c8cf97bead5deae237070f9587f8e7a266d', - [ETHEREUM_NETWORK.RINKEBY]: '0x16baf0de678e52367adc69fd067e5edd1d33e3bf', -} - // safeTransferFrom(address,address,uint256) export const SAFE_TRANSFER_FROM_WITHOUT_DATA_HASH = '42842e0e' @@ -22,12 +10,6 @@ export const SAFE_TRANSFER_FROM_WITHOUT_DATA_HASH = '42842e0e' * @returns string */ export const getTransferMethodByContractAddress = (contractAddress: string): string => { - if (sameAddress(contractAddress, CK_ADDRESS[getNetworkId()])) { - // on mainnet `transferFrom` seems to work fine but we can assure that `transfer` will work on both networks - // so that's the reason why we're falling back to `transfer` for CryptoKitties - return 'transfer' - } - return `0x${SAFE_TRANSFER_FROM_WITHOUT_DATA_HASH}` } diff --git a/src/logic/contracts/safeContracts.ts b/src/logic/contracts/safeContracts.ts index a886ba67f0..c489abc02d 100644 --- a/src/logic/contracts/safeContracts.ts +++ b/src/logic/contracts/safeContracts.ts @@ -3,7 +3,8 @@ import GnosisSafeSol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafe. import ProxyFactorySol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafeProxyFactory.json' import Web3 from 'web3' -import { ETHEREUM_NETWORK } from 'src/config/networks/network.d' +import { HARMONY_NETWORK } from 'src/config/networks/network.d' +import { getNetworkId } from 'src/config/index' import { ZERO_ADDRESS } from 'src/logic/wallets/ethAddresses' import { calculateGasOf, EMPTY_DATA } from 'src/logic/wallets/ethTransactions' import { getWeb3, getNetworkIdFrom } from 'src/logic/wallets/getWeb3' @@ -15,41 +16,68 @@ import { SPENDING_LIMIT_MODULE_ADDRESS } from 'src/utils/constants' import SpendingLimitModule from './artifacts/AllowanceModule.json' +const MULTI_SEND_ADDRESSES = { + [HARMONY_NETWORK.MAINNET]: '0xDEff67e9A02b4Ce60ff62F3CB5FFB41d48856285', + [HARMONY_NETWORK.TESTNET]: '0xF39E79A7B8B319a2554abd3469463f6620C117Bb', +} + +const SAFE_MASTER_COPY_ADDRESSES = { + [HARMONY_NETWORK.MAINNET]: '0x3736aC8400751bf07c6A2E4db3F4f3D9D422abB2', + [HARMONY_NETWORK.TESTNET]: '0x0F2f043DBc72D3948bB7E392E6E3258dc2743376', +} + +const DEFAULT_FALLBACK_HANDLER_ADDRESSES = { + [HARMONY_NETWORK.MAINNET]: '0xC5d654bcE1220241FCe1f0F1D6b9E04f75175452', + [HARMONY_NETWORK.TESTNET]: '0x6B0d84741F7EE66B72bF262A1eDB772d01E2aFE6', +} + +const SAFE_MASTER_COPY_ADDRESS_V10ES = { + [HARMONY_NETWORK.MAINNET]: '0x3736aC8400751bf07c6A2E4db3F4f3D9D422abB2', + [HARMONY_NETWORK.TESTNET]: '0x0F2f043DBc72D3948bB7E392E6E3258dc2743376', +} + export const SENTINEL_ADDRESS = '0x0000000000000000000000000000000000000001' -export const MULTI_SEND_ADDRESS = '0x8d29be29923b68abfdd21e541b9374737b49cdad' -export const SAFE_MASTER_COPY_ADDRESS = '0x34CfAC646f301356fAa8B21e94227e3583Fe3F5F' -export const DEFAULT_FALLBACK_HANDLER_ADDRESS = '0xd5D82B6aDDc9027B22dCA772Aa68D5d74cdBdF44' -export const SAFE_MASTER_COPY_ADDRESS_V10 = '0xb6029EA3B2c51D09a50B53CA8012FeEB05bDa35A' +export const MULTI_SEND_ADDRESS = MULTI_SEND_ADDRESSES[HARMONY_NETWORK[getNetworkId()]] +export const SAFE_MASTER_COPY_ADDRESS = SAFE_MASTER_COPY_ADDRESSES[HARMONY_NETWORK[getNetworkId()]] +export const DEFAULT_FALLBACK_HANDLER_ADDRESS = DEFAULT_FALLBACK_HANDLER_ADDRESSES[HARMONY_NETWORK[getNetworkId()]] +export const SAFE_MASTER_COPY_ADDRESS_V10 = SAFE_MASTER_COPY_ADDRESS_V10ES[HARMONY_NETWORK[getNetworkId()]] let proxyFactoryMaster: GnosisSafeProxyFactory let safeMaster: GnosisSafe +const SAFE_CONTRACTS = { + [HARMONY_NETWORK.MAINNET]: '0x3736aC8400751bf07c6A2E4db3F4f3D9D422abB2', + [HARMONY_NETWORK.TESTNET]: '0x0F2f043DBc72D3948bB7E392E6E3258dc2743376', +} + +const PROXY_CONTRACTS = { + [HARMONY_NETWORK.MAINNET]: '0x4f9b1dEf3a0f6747bF8C870a27D3DeCdf029100e', + [HARMONY_NETWORK.TESTNET]: '0xAaCf9eb6614f7C110EF9b7D832BCe2E67EEC08c1', +} /** * Creates a Contract instance of the GnosisSafe contract * @param {Web3} web3 - * @param {ETHEREUM_NETWORK} networkId + * @param {HARMONY_NETWORK} networkId */ -export const getGnosisSafeContract = (web3: Web3, networkId: ETHEREUM_NETWORK) => { - const networks = GnosisSafeSol.networks +export const getGnosisSafeContract = (web3: Web3, networkId: HARMONY_NETWORK) => { // TODO: this may not be the most scalable approach, // but up until v1.2.0 the address is the same for all the networks. // So, if we can't find the network in the Contract artifact, we fallback to MAINNET. - const contractAddress = networks[networkId]?.address ?? networks[ETHEREUM_NETWORK.MAINNET].address - return (new web3.eth.Contract(GnosisSafeSol.abi as AbiItem[], contractAddress) as unknown) as GnosisSafe + const contractAddress = SAFE_CONTRACTS[networkId] ?? SAFE_CONTRACTS[HARMONY_NETWORK.MAINNET] + return new web3.eth.Contract(GnosisSafeSol.abi as AbiItem[], contractAddress) as unknown as GnosisSafe } /** * Creates a Contract instance of the GnosisSafeProxyFactory contract * @param {Web3} web3 - * @param {ETHEREUM_NETWORK} networkId + * @param {HARMONY_NETWORK} networkId */ -const getProxyFactoryContract = (web3: Web3, networkId: ETHEREUM_NETWORK): GnosisSafeProxyFactory => { - const networks = ProxyFactorySol.networks +const getProxyFactoryContract = (web3: Web3, networkId: HARMONY_NETWORK): GnosisSafeProxyFactory => { // TODO: this may not be the most scalable approach, // but up until v1.2.0 the address is the same for all the networks. // So, if we can't find the network in the Contract artifact, we fallback to MAINNET. - const contractAddress = networks[networkId]?.address ?? networks[ETHEREUM_NETWORK.MAINNET].address - return (new web3.eth.Contract(ProxyFactorySol.abi as AbiItem[], contractAddress) as unknown) as GnosisSafeProxyFactory + const contractAddress = PROXY_CONTRACTS[networkId] ?? PROXY_CONTRACTS[HARMONY_NETWORK.MAINNET] + return new web3.eth.Contract(ProxyFactorySol.abi as AbiItem[], contractAddress) as unknown as GnosisSafeProxyFactory } export const getMasterCopyAddressFromProxyAddress = async (proxyAddress: string): Promise => { @@ -132,7 +160,7 @@ export const estimateGasForDeployingSafe = async ( export const getGnosisSafeInstanceAt = (safeAddress: string): GnosisSafe => { const web3 = getWeb3() - return (new web3.eth.Contract(GnosisSafeSol.abi as AbiItem[], safeAddress) as unknown) as GnosisSafe + return new web3.eth.Contract(GnosisSafeSol.abi as AbiItem[], safeAddress) as unknown as GnosisSafe } /** @@ -141,8 +169,8 @@ export const getGnosisSafeInstanceAt = (safeAddress: string): GnosisSafe => { export const getSpendingLimitContract = () => { const web3 = getWeb3() - return (new web3.eth.Contract( + return new web3.eth.Contract( SpendingLimitModule.abi as AbiItem[], SPENDING_LIMIT_MODULE_ADDRESS, - ) as unknown) as AllowanceModule + ) as unknown as AllowanceModule } diff --git a/src/logic/wallets/store/model/provider.ts b/src/logic/wallets/store/model/provider.ts index 146b2ddb70..7298b804c5 100644 --- a/src/logic/wallets/store/model/provider.ts +++ b/src/logic/wallets/store/model/provider.ts @@ -1,13 +1,13 @@ import { Record, RecordOf } from 'immutable' -import { ETHEREUM_NETWORK } from 'src/config/networks/network.d' +import { HARMONY_NETWORK } from 'src/config/networks/network.d' export type ProviderProps = { name: string loaded: boolean available: boolean account: string - network: ETHEREUM_NETWORK + network: HARMONY_NETWORK smartContractWallet: boolean hardwareWallet: boolean } @@ -17,7 +17,7 @@ export const makeProvider = Record({ loaded: false, available: false, account: '', - network: ETHEREUM_NETWORK.UNKNOWN, + network: HARMONY_NETWORK.UNKNOWN, smartContractWallet: false, hardwareWallet: false, }) diff --git a/src/logic/wallets/store/selectors/index.ts b/src/logic/wallets/store/selectors/index.ts index 56e41f67c8..fb8d3848d0 100644 --- a/src/logic/wallets/store/selectors/index.ts +++ b/src/logic/wallets/store/selectors/index.ts @@ -1,6 +1,6 @@ import { createSelector } from 'reselect' -import { ETHEREUM_NETWORK } from 'src/config/networks/network.d' +import { HARMONY_NETWORK } from 'src/config/networks/network.d' import { PROVIDER_REDUCER_ID, ProviderState } from 'src/logic/wallets/store/reducer/provider' import { AppReduxState } from 'src/store' @@ -16,14 +16,11 @@ export const providerNameSelector = createSelector(providerSelector, (provider: return name ? name.toLowerCase() : undefined }) -export const networkSelector = createSelector( - providerSelector, - (provider: ProviderState): ETHEREUM_NETWORK => { - const networkId = provider.get('network') +export const networkSelector = createSelector(providerSelector, (provider: ProviderState): HARMONY_NETWORK => { + const networkId = provider.get('network') - return networkId ?? ETHEREUM_NETWORK.UNKNOWN - }, -) + return networkId ?? HARMONY_NETWORK.UNKNOWN +}) export const loadedSelector = createSelector(providerSelector, (provider: ProviderState): boolean => provider.get('loaded'), diff --git a/src/logic/wallets/utils/walletList.ts b/src/logic/wallets/utils/walletList.ts index 49f6ad6d43..efeffe6e49 100644 --- a/src/logic/wallets/utils/walletList.ts +++ b/src/logic/wallets/utils/walletList.ts @@ -1,8 +1,7 @@ import { WalletInitOptions } from 'bnc-onboard/dist/src/interfaces' -import { getNetworkId, getRpcServiceUrl, getNetworkConfigDisabledWallets } from 'src/config' +import { getNetworkId, getNetworkConfigDisabledWallets } from 'src/config' import { WALLETS } from 'src/config/networks/network.d' -import { FORTMATIC_KEY, PORTIS_ID } from 'src/utils/constants' const networkId = getNetworkId() const disabledWallets = getNetworkConfigDisabledWallets() @@ -12,56 +11,7 @@ type Wallet = WalletInitOptions & { walletName: WALLETS } -const rpcUrl = getRpcServiceUrl() -const wallets: Wallet[] = [ - { walletName: WALLETS.METAMASK, preferred: true, desktop: false }, - { - walletName: WALLETS.WALLET_CONNECT, - preferred: true, - // as stated in the documentation, `infuraKey` is not mandatory if rpc is provided - rpc: { [networkId]: rpcUrl }, - desktop: true, - bridge: 'https://safe-walletconnect.gnosis.io/', - }, - { - walletName: WALLETS.TREZOR, - appUrl: 'gnosis-safe.io', - preferred: true, - email: 'safe@gnosis.io', - desktop: true, - rpcUrl, - }, - { - walletName: WALLETS.LEDGER, - desktop: true, - preferred: true, - rpcUrl, - LedgerTransport: (window as any).TransportNodeHid, - }, - { walletName: WALLETS.TRUST, preferred: true, desktop: false }, - { - walletName: WALLETS.LATTICE, - rpcUrl, - appName: 'Gnosis Safe', - desktop: false, - }, - { - walletName: WALLETS.FORTMATIC, - apiKey: FORTMATIC_KEY, - desktop: true, - }, - { - walletName: WALLETS.PORTIS, - apiKey: PORTIS_ID, - desktop: true, - }, - { walletName: WALLETS.AUTHEREUM, desktop: false }, - { walletName: WALLETS.TORUS, desktop: true }, - { walletName: WALLETS.COINBASE, desktop: false }, - { walletName: WALLETS.WALLET_LINK, rpcUrl, desktop: false }, - { walletName: WALLETS.OPERA, desktop: false }, - { walletName: WALLETS.OPERA_TOUCH, desktop: false }, -] +const wallets: Wallet[] = [{ walletName: WALLETS.METAMASK, preferred: true, desktop: false }] export const getSupportedWallets = (): WalletInitOptions[] => { const { isDesktop } = window diff --git a/src/routes/safe/components/Apps/__tests__/utils.test.ts b/src/routes/safe/components/Apps/__tests__/utils.test.ts deleted file mode 100644 index 795f53ef68..0000000000 --- a/src/routes/safe/components/Apps/__tests__/utils.test.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { isAppManifestValid } from '../utils' -import { SafeApp } from '../types' - -describe('SafeApp manifest', () => { - it('It should return true given a manifest with mandatory values supplied', async () => { - const manifest = { - name: 'test', - description: 'a test', - error: false, - } - - const result = isAppManifestValid(manifest as SafeApp) - expect(result).toBe(true) - }) - - it('It should return false given a manifest without name', async () => { - const manifest = { - name: '', - description: 'a test', - error: false, - } - - const result = isAppManifestValid(manifest as SafeApp) - expect(result).toBe(false) - }) - - it('It should return false given a manifest without description', async () => { - const manifest = { - name: 'test', - description: '', - error: false, - } - - const result = isAppManifestValid(manifest as SafeApp) - expect(result).toBe(false) - }) - - it('It should return false given a manifest with error', async () => { - const manifest = { - name: 'test', - description: 'a test', - error: true, - } - - const result = isAppManifestValid(manifest as SafeApp) - expect(result).toBe(false) - }) -}) diff --git a/src/routes/safe/components/Apps/api/fetchSafeAppsList.ts b/src/routes/safe/components/Apps/api/fetchSafeAppsList.ts deleted file mode 100644 index fe3981dc44..0000000000 --- a/src/routes/safe/components/Apps/api/fetchSafeAppsList.ts +++ /dev/null @@ -1,21 +0,0 @@ -import axios from 'axios' - -import { SAFE_APPS_LIST_URL } from 'src/utils/constants' - -export type TokenListResult = { - name: string - timestamp: string - apps: AppData[] -} - -export type AppData = { - url: string - name?: string - disabled?: boolean - description?: string - networks: number[] -} - -export const fetchSafeAppsList = async (): Promise => { - return axios.get(SAFE_APPS_LIST_URL).then(({ data }) => data) -} diff --git a/src/routes/safe/components/Apps/assets/addApp.svg b/src/routes/safe/components/Apps/assets/addApp.svg deleted file mode 100644 index 76500778d3..0000000000 --- a/src/routes/safe/components/Apps/assets/addApp.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/routes/safe/components/Apps/communicator.ts b/src/routes/safe/components/Apps/communicator.ts deleted file mode 100644 index ae1d21f043..0000000000 --- a/src/routes/safe/components/Apps/communicator.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { MutableRefObject, useEffect, useState } from 'react' -import { - getSDKVersion, - SDKMessageEvent, - MethodToResponse, - Methods, - ErrorResponse, - MessageFormatter, - METHODS, - RequestId, -} from '@gnosis.pm/safe-apps-sdk' -import { trackError, Errors } from 'src/logic/exceptions/CodedException' -import { SafeApp } from './types' - -type MessageHandler = ( - msg: SDKMessageEvent, -) => void | MethodToResponse[Methods] | ErrorResponse | Promise - -type LegacyMethods = 'getEnvInfo' -type SDKMethods = Methods | LegacyMethods - -class AppCommunicator { - private iframeRef: MutableRefObject - private handlers = new Map() - private app: SafeApp - - constructor(iframeRef: MutableRefObject, app: SafeApp) { - this.iframeRef = iframeRef - this.app = app - - window.addEventListener('message', this.handleIncomingMessage) - } - - on = (method: SDKMethods, handler: MessageHandler): void => { - this.handlers.set(method, handler) - } - - private isValidMessage = (msg: SDKMessageEvent): boolean => { - // @ts-expect-error .parent doesn't exist on some possible types - const sentFromIframe = msg.source.parent === window.parent - const knownMethod = Object.values(METHODS).includes(msg.data.method) - - return sentFromIframe && knownMethod - } - - private canHandleMessage = (msg: SDKMessageEvent): boolean => { - return Boolean(this.handlers.get(msg.data.method)) - } - - send = (data: unknown, requestId: RequestId, error = false): void => { - const sdkVersion = getSDKVersion() - const msg = error - ? MessageFormatter.makeErrorResponse(requestId, data as string, sdkVersion) - : MessageFormatter.makeResponse(requestId, data, sdkVersion) - - this.iframeRef.current?.contentWindow?.postMessage(msg, '*') - } - - handleIncomingMessage = async (msg: SDKMessageEvent): Promise => { - const validMessage = this.isValidMessage(msg) - const hasHandler = this.canHandleMessage(msg) - - if (validMessage && hasHandler) { - const handler = this.handlers.get(msg.data.method) - try { - // @ts-expect-error Handler existence is checked in this.canHandleMessage - const response = await handler(msg) - - // If response is not returned, it means the response will be send somewhere else - if (typeof response !== 'undefined') { - this.send(response, msg.data.id) - } - } catch (err) { - this.send(err.message, msg.data.id, true) - trackError(Errors._901, err.message, { - contexts: { - safeApp: this.app, - request: msg.data, - }, - }) - } - } - } - - clear = (): void => { - window.removeEventListener('message', this.handleIncomingMessage) - } -} - -const useAppCommunicator = ( - iframeRef: MutableRefObject, - app?: SafeApp, -): AppCommunicator | undefined => { - const [communicator, setCommunicator] = useState(undefined) - useEffect(() => { - let communicatorInstance - const initCommunicator = (iframeRef: MutableRefObject, app: SafeApp) => { - communicatorInstance = new AppCommunicator(iframeRef, app) - setCommunicator(communicatorInstance) - } - - if (app) { - initCommunicator(iframeRef as MutableRefObject, app) - } - - return () => { - communicatorInstance?.clear() - } - }, [app, iframeRef]) - - return communicator -} - -export { useAppCommunicator } diff --git a/src/routes/safe/components/Apps/components/AddAppForm/AppAgreement.tsx b/src/routes/safe/components/Apps/components/AddAppForm/AppAgreement.tsx deleted file mode 100644 index f4330e7091..0000000000 --- a/src/routes/safe/components/Apps/components/AddAppForm/AppAgreement.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { Checkbox, Text } from '@gnosis.pm/safe-react-components' -import React from 'react' -import { useFormState } from 'react-final-form' -import styled from 'styled-components' - -import { required } from 'src/components/forms/validator' -import Field from 'src/components/forms/Field' - -const StyledCheckbox = styled(Checkbox)` - margin: 0; -` - -const AppAgreement = (): React.ReactElement => { - const { visited } = useFormState({ subscription: { visited: true } }) - - // trick to prevent having the field validated by default. Not sure why this happens in this form - const validate = !visited?.agreementAccepted ? undefined : required - - return ( - This app is not a Gnosis product and I agree to use this app at my own risk.} - name="agreementAccepted" - type="checkbox" - validate={validate} - /> - ) -} - -export default AppAgreement diff --git a/src/routes/safe/components/Apps/components/AddAppForm/AppUrl.tsx b/src/routes/safe/components/Apps/components/AddAppForm/AppUrl.tsx deleted file mode 100644 index 4e1a7e44df..0000000000 --- a/src/routes/safe/components/Apps/components/AddAppForm/AppUrl.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import { TextField } from '@gnosis.pm/safe-react-components' -import createDecorator from 'final-form-calculate' -import React from 'react' -import { useField, useFormState } from 'react-final-form' -import styled from 'styled-components' - -import { SafeApp } from 'src/routes/safe/components/Apps/types' -import { getAppInfoFromUrl, getIpfsLinkFromEns, uniqueApp } from 'src/routes/safe/components/Apps/utils' -import { composeValidators, required } from 'src/components/forms/validator' -import Field from 'src/components/forms/Field' -import { isValidURL } from 'src/utils/url' -import { isValidEnsName } from 'src/logic/wallets/ethAddresses' -import { useDebounce } from 'src/logic/hooks/useDebounce' - -const validateUrl = (url: string): string | undefined => (isValidURL(url) ? undefined : 'Invalid URL') - -export const appUrlResolver = createDecorator({ - field: 'appUrl', - updates: { - appUrl: async (appUrl: string): Promise => { - const ensContent = !isValidURL(appUrl) && isValidEnsName(appUrl) && (await getIpfsLinkFromEns(appUrl)) - - if (ensContent) { - return ensContent - } - - return appUrl - }, - }, -}) - -type AppInfoUpdaterProps = { - onAppInfo: (appInfo: SafeApp) => void - onLoading: (isLoading: boolean) => void -} - -export const AppInfoUpdater = ({ onAppInfo, onLoading }: AppInfoUpdaterProps): null => { - const { - input: { value: appUrl }, - } = useField('appUrl', { subscription: { value: true } }) - - const debouncedValue = useDebounce(appUrl, 500) - - React.useEffect(() => { - const updateAppInfo = async () => { - try { - onLoading(true) - const appInfo = await getAppInfoFromUrl(debouncedValue) - onAppInfo({ ...appInfo }) - onLoading(false) - } catch (error) { - onLoading(false) - } - } - - if (isValidURL(debouncedValue)) { - updateAppInfo() - } - }, [debouncedValue, onAppInfo, onLoading]) - - return null -} - -const StyledAppUrlField = styled(Field)` - && { - width: 100%; - } -` - -const AppUrl = ({ appList }: { appList: SafeApp[] }): React.ReactElement => { - const { visited } = useFormState({ subscription: { visited: true } }) - - // trick to prevent having the field validated by default. Not sure why this happens in this form - const validate = !visited?.appUrl ? undefined : composeValidators(required, validateUrl, uniqueApp(appList)) - - return ( - - ) -} - -export default AppUrl diff --git a/src/routes/safe/components/Apps/components/AddAppForm/FormButtons.tsx b/src/routes/safe/components/Apps/components/AddAppForm/FormButtons.tsx deleted file mode 100644 index 24b936352a..0000000000 --- a/src/routes/safe/components/Apps/components/AddAppForm/FormButtons.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import React, { ReactElement, useMemo } from 'react' -import { useFormState } from 'react-final-form' - -import { Modal } from 'src/components/Modal' -import { SafeApp } from 'src/routes/safe/components/Apps/types' -import { isAppManifestValid } from 'src/routes/safe/components/Apps/utils' - -interface Props { - appInfo: SafeApp - onCancel: () => void -} - -export const FormButtons = ({ appInfo, onCancel }: Props): ReactElement => { - const { valid, validating, visited } = useFormState({ - subscription: { valid: true, validating: true, visited: true }, - }) - - const isSubmitDisabled = useMemo(() => { - // if non visited, fields were not evaluated yet. Then, the default value is considered invalid - const fieldsVisited = visited?.agreementAccepted && visited?.appUrl - - return validating || !valid || !fieldsVisited || !isAppManifestValid(appInfo) - }, [validating, valid, visited, appInfo]) - - return ( - - ) -} diff --git a/src/routes/safe/components/Apps/components/AddAppForm/index.tsx b/src/routes/safe/components/Apps/components/AddAppForm/index.tsx deleted file mode 100644 index 12eadd5854..0000000000 --- a/src/routes/safe/components/Apps/components/AddAppForm/index.tsx +++ /dev/null @@ -1,140 +0,0 @@ -import { Icon, Link, Loader, Text, TextField } from '@gnosis.pm/safe-react-components' -import React, { useState, ReactElement } from 'react' -import styled from 'styled-components' - -import { SafeApp } from 'src/routes/safe/components/Apps/types' -import GnoForm from 'src/components/forms/GnoForm' -import Img from 'src/components/layout/Img' -import { Modal } from 'src/components/Modal' - -import AppAgreement from './AppAgreement' -import AppUrl, { AppInfoUpdater, appUrlResolver } from './AppUrl' -import { FormButtons } from './FormButtons' -import { APPS_STORAGE_KEY, getEmptySafeApp } from 'src/routes/safe/components/Apps/utils' -import { saveToStorage } from 'src/utils/storage' -import { SAFELIST_ADDRESS } from 'src/routes/routes' -import { useHistory, useRouteMatch } from 'react-router-dom' - -const FORM_ID = 'add-apps-form' - -const StyledTextFileAppName = styled(TextField)` - && { - width: 385px; - } -` - -const AppInfo = styled.div` - display: flex; - margin: 36px 0 24px 0; - - img { - margin-right: 10px; - } -` -const AppDocsInfo = styled.div` - display: flex; - margin-bottom: 24px; - flex-direction: column; - svg { - position: relative; - top: 4px; - left: 4px; - } -` - -const WrapperLoader = styled.div` - height: 55px; - width: 65px; - display: flex; - align-items: center; - justify-content: center; -` - -const StyledLoader = styled(Loader)` - margin-right: 15px; -` - -interface AddAppFormValues { - appUrl: string - agreementAccepted: boolean -} - -const INITIAL_VALUES: AddAppFormValues = { - appUrl: '', - agreementAccepted: false, -} - -const APP_INFO = getEmptySafeApp() - -interface AddAppProps { - appList: SafeApp[] - closeModal: () => void -} - -const AddApp = ({ appList, closeModal }: AddAppProps): ReactElement => { - const [appInfo, setAppInfo] = useState(APP_INFO) - const history = useHistory() - const matchSafeWithAddress = useRouteMatch<{ safeAddress: string }>({ path: `${SAFELIST_ADDRESS}/:safeAddress` }) - const [isLoading, setIsLoading] = useState(false) - - const handleSubmit = () => { - const newAppList = [ - { url: appInfo.url, disabled: false }, - ...appList.map(({ url, disabled }) => ({ url, disabled })), - ] - saveToStorage(APPS_STORAGE_KEY, newAppList) - const goToApp = `${matchSafeWithAddress?.url}/apps?appUrl=${encodeURI(appInfo.url)}` - history.push(goToApp) - } - - return ( - - {() => ( - <> - - - - Safe Apps are third-party extensions. - - - - Learn more about building Safe Apps. - - - - - - {/* Fetch app from url and return a SafeApp */} - - - {isLoading ? ( - - - - ) : ( - Token image - )} - {}} - /> - - - - - - - - )} - - ) -} - -export default AddApp diff --git a/src/routes/safe/components/Apps/components/AppCard/index.stories.tsx b/src/routes/safe/components/Apps/components/AppCard/index.stories.tsx deleted file mode 100644 index 32020d3ee2..0000000000 --- a/src/routes/safe/components/Apps/components/AppCard/index.stories.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react' - -import AppCard from './index' - -import AddAppIcon from 'src/routes/safe/components/Apps/assets/addApp.svg' - -export default { - title: 'Apps/AppCard', - component: AppCard, -} - -export const Loading = (): React.ReactElement => - -export const AddCustomApp = (): React.ReactElement => ( - -) - -export const LoadedApp = (): React.ReactElement => ( - -) diff --git a/src/routes/safe/components/Apps/components/AppCard/index.tsx b/src/routes/safe/components/Apps/components/AppCard/index.tsx deleted file mode 100644 index 234e6116d3..0000000000 --- a/src/routes/safe/components/Apps/components/AppCard/index.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import React, { SyntheticEvent } from 'react' -import styled from 'styled-components' -import { fade } from '@material-ui/core/styles/colorManipulator' -import { Title, Text, Button, Card } from '@gnosis.pm/safe-react-components' - -import appsIconSvg from 'src/assets/icons/apps.svg' -import { AppIconSK, DescriptionSK, TitleSK } from './skeleton' - -const StyledAppCard = styled(Card)` - display: flex; - align-items: center; - flex-direction: column; - justify-content: space-evenly; - box-shadow: 1px 2px 10px 0 ${({ theme }) => fade(theme.colors.shadow.color, 0.18)}; - height: 232px !important; - box-sizing: border-box; - cursor: pointer; - color: ${({ theme }) => theme.colors.secondary}; - - :hover { - box-shadow: 1px 2px 16px 0 ${({ theme }) => fade(theme.colors.shadow.color, 0.35)}; - transition: box-shadow 0.3s ease-in-out; - background-color: ${({ theme }) => theme.colors.background}; - cursor: pointer; - - h5 { - color: ${({ theme }) => theme.colors.primary}; - } - } -` - -const IconImg = styled.img<{ size: 'md' | 'lg'; src: string | undefined }>` - width: ${({ size }) => (size === 'md' ? '60px' : '102px')}; - height: ${({ size }) => (size === 'md' ? '60px' : '92px')}; - margin-top: ${({ size }) => (size === 'md' ? '0' : '-16px')}; - object-fit: contain; -` - -const AppName = styled(Title)` - text-align: center; - margin: 16px 0 9px 0; -` - -const AppDescription = styled(Text)` - height: 71px; - text-align: center; -` - -export const setAppImageFallback = (error: SyntheticEvent): void => { - error.currentTarget.onerror = null - error.currentTarget.src = appsIconSvg -} - -export enum TriggerType { - Button, - Content, -} - -type Props = { - onClick?: () => void - isLoading?: boolean - className?: string - name?: string - description?: string - iconUrl?: string - iconSize?: 'md' | 'lg' - buttonText?: string -} - -const AppCard = ({ - isLoading = false, - className, - name, - description, - iconUrl, - iconSize = 'md', - buttonText, - onClick = () => undefined, -}: Props): React.ReactElement => { - if (isLoading) { - return ( - - - - - - - ) - } - - return ( - - - - {name && {name}} - - {description && {description} } - - {buttonText && ( - - )} - - ) -} - -export default AppCard diff --git a/src/routes/safe/components/Apps/components/AppCard/skeleton.tsx b/src/routes/safe/components/Apps/components/AppCard/skeleton.tsx deleted file mode 100644 index 92ef8718d2..0000000000 --- a/src/routes/safe/components/Apps/components/AppCard/skeleton.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import styled, { keyframes } from 'styled-components' - -const gradientSK = keyframes` - 0% { - background-position: 0% 54%; - } - 50% { - background-position: 100% 47%; - } - 100% { - background-position: 0% 54%; - } -` - -export const AppIconSK = styled.div` - height: 60px; - width: 60px; - border-radius: 30px; - margin: 0 auto; - background-color: lightgrey; - background: linear-gradient(84deg, lightgrey, transparent); - background-size: 400% 400%; - animation: ${gradientSK} 1.5s ease infinite; -` -export const TitleSK = styled.div` - height: 24px; - width: 160px; - margin: 24px auto; - background-color: lightgrey; - background: linear-gradient(84deg, lightgrey, transparent); - background-size: 400% 400%; - animation: ${gradientSK} 1.5s ease infinite; -` -export const DescriptionSK = styled.div` - height: 16px; - width: 200px; - background-color: lightgrey; - background: linear-gradient(84deg, lightgrey, transparent); - background-size: 400% 400%; - animation: ${gradientSK} 1.5s ease infinite; -` diff --git a/src/routes/safe/components/Apps/components/AppFrame.tsx b/src/routes/safe/components/Apps/components/AppFrame.tsx deleted file mode 100644 index 471648ed54..0000000000 --- a/src/routes/safe/components/Apps/components/AppFrame.tsx +++ /dev/null @@ -1,331 +0,0 @@ -import React, { ReactElement, useState, useRef, useCallback, useEffect } from 'react' -import styled from 'styled-components' -import { FixedIcon, Loader, Title, Card } from '@gnosis.pm/safe-react-components' -import { GetBalanceParams, GetTxBySafeTxHashParams, MethodToResponse, RPCPayload } from '@gnosis.pm/safe-apps-sdk' -import { useHistory } from 'react-router-dom' -import { useSelector } from 'react-redux' -import { INTERFACE_MESSAGES, Transaction, RequestId, LowercaseNetworks } from '@gnosis.pm/safe-apps-sdk-v1' - -import { currentSafeWithNames } from 'src/logic/safe/store/selectors' -import { grantedSelector } from 'src/routes/safe/container/selector' -import { getNetworkId, getNetworkName, getTxServiceUrl } from 'src/config' -import { SAFELIST_ADDRESS } from 'src/routes/routes' -import { isSameURL } from 'src/utils/url' -import { useAnalytics, SAFE_NAVIGATION_EVENT } from 'src/utils/googleAnalytics' -import { useAppList } from '../hooks/useAppList' -import { LoadingContainer } from 'src/components/LoaderContainer/index' -import { TIMEOUT } from 'src/utils/constants' -import { web3ReadOnly } from 'src/logic/wallets/getWeb3' - -import { ConfirmTxModal } from './ConfirmTxModal' -import { useIframeMessageHandler } from '../hooks/useIframeMessageHandler' -import { useLegalConsent } from '../hooks/useLegalConsent' -import LegalDisclaimer from './LegalDisclaimer' -import { getAppInfoFromUrl } from '../utils' -import { SafeApp } from '../types' -import { useAppCommunicator } from '../communicator' -import { fetchTokenCurrenciesBalances } from 'src/logic/safe/api/fetchTokenCurrenciesBalances' -import { fetchSafeTransaction } from 'src/logic/safe/transactions/api/fetchSafeTransaction' - -const OwnerDisclaimer = styled.div` - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - height: 476px; -` - -const AppWrapper = styled.div` - display: flex; - flex-direction: column; - height: calc(100% + 59px); - margin: 0 -16px; -` - -const StyledCard = styled(Card)` - flex-grow: 1; - padding: 0; - border-radius: 0; -` - -const StyledIframe = styled.iframe<{ isLoading: boolean }>` - height: 100%; - width: 100%; - overflow: auto; - box-sizing: border-box; - display: ${({ isLoading }) => (isLoading ? 'none' : 'block')}; -` - -export type TransactionParams = { - safeTxGas?: number -} - -type ConfirmTransactionModalState = { - isOpen: boolean - txs: Transaction[] - requestId: RequestId - params?: TransactionParams -} - -type Props = { - appUrl: string -} - -const NETWORK_NAME = getNetworkName() -const NETWORK_ID = getNetworkId() - -const INITIAL_CONFIRM_TX_MODAL_STATE: ConfirmTransactionModalState = { - isOpen: false, - txs: [], - requestId: '', - params: undefined, -} - -const AppFrame = ({ appUrl }: Props): ReactElement => { - const granted = useSelector(grantedSelector) - const { address: safeAddress, ethBalance, name: safeName } = useSelector(currentSafeWithNames) - const { trackEvent } = useAnalytics() - const history = useHistory() - const { consentReceived, onConsentReceipt } = useLegalConsent() - const { staticAppsList } = useAppList() - - const iframeRef = useRef(null) - const [confirmTransactionModal, setConfirmTransactionModal] = useState( - INITIAL_CONFIRM_TX_MODAL_STATE, - ) - const [appIsLoading, setAppIsLoading] = useState(true) - const [safeApp, setSafeApp] = useState() - - const redirectToBalance = () => history.push(`${SAFELIST_ADDRESS}/${safeAddress}/balances`) - const timer = useRef() - const [appTimeout, setAppTimeout] = useState(false) - - useEffect(() => { - if (appIsLoading) { - timer.current = window.setTimeout(() => { - setAppTimeout(true) - }, TIMEOUT) - } else { - clearTimeout(timer.current) - setAppTimeout(false) - } - - return () => { - clearTimeout(timer.current) - } - }, [appIsLoading]) - - const openConfirmationModal = useCallback( - (txs: Transaction[], params: TransactionParams | undefined, requestId: RequestId) => - setConfirmTransactionModal({ - isOpen: true, - txs, - requestId, - params, - }), - [setConfirmTransactionModal], - ) - const closeConfirmationModal = useCallback(() => setConfirmTransactionModal(INITIAL_CONFIRM_TX_MODAL_STATE), [ - setConfirmTransactionModal, - ]) - - const { sendMessageToIframe } = useIframeMessageHandler( - safeApp, - openConfirmationModal, - closeConfirmationModal, - iframeRef, - ) - - const onIframeLoad = useCallback(() => { - const iframe = iframeRef.current - if (!iframe || !isSameURL(iframe.src, appUrl as string)) { - return - } - - setAppIsLoading(false) - sendMessageToIframe({ - messageId: INTERFACE_MESSAGES.ON_SAFE_INFO, - data: { - safeAddress: safeAddress as string, - network: NETWORK_NAME.toLowerCase() as LowercaseNetworks, - ethBalance: ethBalance as string, - }, - }) - }, [ethBalance, safeAddress, appUrl, sendMessageToIframe]) - - const communicator = useAppCommunicator(iframeRef, safeApp) - - useEffect(() => { - communicator?.on('getEnvInfo', () => ({ - txServiceUrl: getTxServiceUrl(), - })) - - communicator?.on('getTxBySafeTxHash', async (msg) => { - const { safeTxHash } = msg.data.params as GetTxBySafeTxHashParams - - const tx = await fetchSafeTransaction(safeTxHash) - - return tx - }) - - communicator?.on('getSafeInfo', () => ({ - safeAddress, - network: NETWORK_NAME, - chainId: NETWORK_ID, - })) - - communicator?.on('getSafeBalances', async (msg) => { - const { currency = 'usd' } = msg.data.params as GetBalanceParams - - const balances = await fetchTokenCurrenciesBalances({ safeAddress, selectedCurrency: currency }) - - return balances - }) - - communicator?.on('rpcCall', async (msg) => { - const params = msg.data.params as RPCPayload - - try { - const response = new Promise((resolve, reject) => { - if ( - web3ReadOnly.currentProvider !== null && - typeof web3ReadOnly.currentProvider !== 'string' && - 'send' in web3ReadOnly.currentProvider - ) { - web3ReadOnly.currentProvider?.send?.( - { - jsonrpc: '2.0', - method: params.call, - params: params.params, - id: '1', - }, - (err, res) => { - if (err || res?.error) { - reject(err || res?.error) - } - - resolve(res?.result) - }, - ) - } - }) - - return response - } catch (err) { - return err - } - }) - - communicator?.on('sendTransactions', (msg) => { - // @ts-expect-error explore ways to fix this - openConfirmationModal(msg.data.params.txs as Transaction[], msg.data.params.params, msg.data.id) - }) - }, [communicator, openConfirmationModal, safeAddress]) - - const onUserTxConfirm = (safeTxHash: string) => { - // Safe Apps SDK V1 Handler - sendMessageToIframe( - { messageId: INTERFACE_MESSAGES.TRANSACTION_CONFIRMED, data: { safeTxHash } }, - confirmTransactionModal.requestId, - ) - - // Safe Apps SDK V2 Handler - communicator?.send({ safeTxHash }, confirmTransactionModal.requestId as string) - } - - const onTxReject = () => { - // Safe Apps SDK V1 Handler - sendMessageToIframe( - { messageId: INTERFACE_MESSAGES.TRANSACTION_REJECTED, data: {} }, - confirmTransactionModal.requestId, - ) - - // Safe Apps SDK V2 Handler - communicator?.send('Transaction was rejected', confirmTransactionModal.requestId as string, true) - } - - useEffect(() => { - const loadApp = async () => { - const app = await getAppInfoFromUrl(appUrl) - - setSafeApp(app) - } - if (staticAppsList.length) { - loadApp() - } - }, [appUrl, staticAppsList]) - - //track GA - useEffect(() => { - if (safeApp) { - trackEvent({ category: SAFE_NAVIGATION_EVENT, action: 'Apps', label: safeApp.name }) - } - }, [safeApp, trackEvent]) - - if (!appUrl) { - throw Error('App url No provided or it is invalid.') - } - - if (!safeApp) { - return ( - - - - ) - } - - if (consentReceived === false) { - return - } - - if (NETWORK_NAME === 'UNKNOWN' || !granted) { - return ( - - - To use apps, you must be an owner of this Safe - - ) - } - - return ( - - - {appIsLoading && ( - - {appTimeout && ( - - The safe app is taking longer than usual to load. There might be a problem with the app provider. - - )} - - - )} - - - - - - - ) -} - -export default AppFrame diff --git a/src/routes/safe/components/Apps/components/AppsList.tsx b/src/routes/safe/components/Apps/components/AppsList.tsx deleted file mode 100644 index 0ed603b7bb..0000000000 --- a/src/routes/safe/components/Apps/components/AppsList.tsx +++ /dev/null @@ -1,190 +0,0 @@ -import React, { useState } from 'react' -import styled, { css } from 'styled-components' -import { useSelector } from 'react-redux' -import { IconText, Loader, Menu, Text, Icon } from '@gnosis.pm/safe-react-components' -import IconButton from '@material-ui/core/IconButton' - -import { Modal } from 'src/components/Modal' -import { safeAddressFromUrl } from 'src/logic/safe/store/selectors' -import AppCard from 'src/routes/safe/components/Apps/components/AppCard' -import AddAppIcon from 'src/routes/safe/components/Apps/assets/addApp.svg' -import { useRouteMatch, Link } from 'react-router-dom' -import { SAFELIST_ADDRESS } from 'src/routes/routes' - -import { useAppList } from '../hooks/useAppList' -import { SAFE_APP_FETCH_STATUS, SafeApp } from '../types' -import AddAppForm from './AddAppForm' -import { AppData } from '../api/fetchSafeAppsList' - -const Wrapper = styled.div` - height: 100%; - display: flex; - flex-direction: column; -` - -const StyledLink = styled(Link)` - text-decoration: none; -` - -const centerCSS = css` - display: flex; - align-items: center; - justify-content: center; -` - -const LoadingContainer = styled.div` - width: 100%; - height: 100%; - ${centerCSS}; -` - -const CardsWrapper = styled.div` - width: 100%; - display: grid; - grid-template-columns: repeat(auto-fill, minmax(243px, 1fr)); - column-gap: 20px; - row-gap: 20px; - justify-content: space-evenly; - margin: 0 0 16px 0; -` - -const ContentWrapper = styled.div` - display: flex; - flex-direction: column; - justify-content: space-between; - flex-grow: 1; - align-items: center; -` -const Breadcrumb = styled.div` - height: 51px; -` - -const IconBtn = styled(IconButton)` - position: absolute; - top: 10px; - right: 10px; - z-index: 10; - padding: 5px; - opacity: 0; - - transition: opacity 0.2s ease-in-out; -` - -const AppContainer = styled.div` - position: relative; - - &:hover { - ${IconBtn} { - opacity: 1; - } - } -` - -const isAppLoading = (app: SafeApp) => SAFE_APP_FETCH_STATUS.LOADING === app.fetchStatus -const isCustomApp = (appUrl: string, staticAppsList: AppData[]) => !staticAppsList.some(({ url }) => url === appUrl) - -const AppsList = (): React.ReactElement => { - const matchSafeWithAddress = useRouteMatch<{ safeAddress: string }>({ path: `${SAFELIST_ADDRESS}/:safeAddress` }) - const safeAddress = useSelector(safeAddressFromUrl) - const { appList, removeApp, staticAppsList } = useAppList() - const [isAddAppModalOpen, setIsAddAppModalOpen] = useState(false) - const [appToRemove, setAppToRemove] = useState(null) - - const openAddAppModal = () => setIsAddAppModalOpen(true) - - const closeAddAppModal = () => setIsAddAppModalOpen(false) - - if (!appList.length || !safeAddress) { - return ( - - - - ) - } - - return ( - - - {/* TODO: Add navigation breadcrumb. Empty for now to give some top margin */} - - - - - - - - {appList - .filter((a) => a.fetchStatus !== SAFE_APP_FETCH_STATUS.ERROR) - .map((a) => ( - - - - - {isCustomApp(a.url, staticAppsList) && ( - { - e.stopPropagation() - - setAppToRemove(a) - }} - > - - - )} - - ))} - - - - - - {isAddAppModalOpen && ( - - - Add custom app - - - - )} - - {appToRemove && ( - setAppToRemove(null)}> - setAppToRemove(null)}> - Remove app - - - - This action will remove{' '} - - {appToRemove.name} - {' '} - from the interface - - - - setAppToRemove(null) }} - confirmButtonProps={{ - color: 'error', - onClick: () => { - removeApp(appToRemove.url) - setAppToRemove(null) - }, - text: 'Remove', - }} - /> - - - )} - - ) -} - -export default AppsList diff --git a/src/routes/safe/components/Apps/components/ConfirmTxModal/DecodedTxDetail.tsx b/src/routes/safe/components/Apps/components/ConfirmTxModal/DecodedTxDetail.tsx deleted file mode 100644 index 8bf9bb6a73..0000000000 --- a/src/routes/safe/components/Apps/components/ConfirmTxModal/DecodedTxDetail.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import React, { ReactElement } from 'react' -import styled from 'styled-components' - -import { getNetworkInfo } from 'src/config' -import { fromTokenUnit } from 'src/logic/tokens/utils/humanReadableValue' -import { md, lg } from 'src/theme/variables' -import ModalTitle from 'src/components/ModalTitle' -import Hairline from 'src/components/layout/Hairline' -import { DecodedDataParameterValue, DecodedData } from 'src/types/transactions/decode.d' -import { BasicTxInfo, getParameterElement } from 'src/components/DecodeTxs' - -const { nativeCoin } = getNetworkInfo() - -const Container = styled.div` - max-width: 480px; - padding: ${md} ${lg}; - word-break: break-word; -` - -function isDataDecodedParameterValue(arg: any): arg is DecodedDataParameterValue { - return arg.operation !== undefined -} - -type Props = { - hideDecodedTxData: () => void - onClose: () => void - decodedTxData: DecodedDataParameterValue | DecodedData -} - -export const DecodedTxDetail = ({ hideDecodedTxData, onClose, decodedTxData: tx }: Props): ReactElement => { - let body - // If we are dealing with a multiSend - // decodedTxData is of type DataDecodedParameter - if (isDataDecodedParameterValue(tx)) { - const txValue = fromTokenUnit(tx.value, nativeCoin.decimals) - - body = ( - <> - - {tx.dataDecoded?.parameters.map((p, index) => getParameterElement(p, index))} - - ) - } else { - // If we are dealing with a single tx - // decodedTxData is of type DecodedData - body = <>{tx.parameters.map((p, index) => getParameterElement(p, index))} - } - - return ( - <> - - - - - {body} - - ) -} diff --git a/src/routes/safe/components/Apps/components/ConfirmTxModal/ReviewConfirm.tsx b/src/routes/safe/components/Apps/components/ConfirmTxModal/ReviewConfirm.tsx deleted file mode 100644 index 5b67522fa1..0000000000 --- a/src/routes/safe/components/Apps/components/ConfirmTxModal/ReviewConfirm.tsx +++ /dev/null @@ -1,267 +0,0 @@ -import React, { ReactElement, useEffect, useMemo, useState } from 'react' -import { EthHashInfo, Text } from '@gnosis.pm/safe-react-components' -import styled from 'styled-components' -import { useDispatch } from 'react-redux' - -import ModalTitle from 'src/components/ModalTitle' -import { createTransaction } from 'src/logic/safe/store/actions/createTransaction' -import { MULTI_SEND_ADDRESS } from 'src/logic/contracts/safeContracts' -import { CALL, DELEGATE_CALL, TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions' -import { encodeMultiSendCall } from 'src/logic/safe/transactions/multisend' -import { getExplorerInfo, getNetworkInfo } from 'src/config' -import { web3ReadOnly } from 'src/logic/wallets/getWeb3' -import { EstimationStatus, useEstimateTransactionGas } from 'src/logic/hooks/useEstimateTransactionGas' -import { TransactionFees } from 'src/components/TransactionsFees' -import { EditableTxParameters } from 'src/routes/safe/components/Transactions/helpers/EditableTxParameters' -import { TxParametersDetail } from 'src/routes/safe/components/Transactions/helpers/TxParametersDetail' -import { lg, md, sm } from 'src/theme/variables' -import { useEstimationStatus } from 'src/logic/hooks/useEstimationStatus' -import { TxParameters } from 'src/routes/safe/container/hooks/useTransactionParameters' -import { BasicTxInfo, DecodeTxs } from 'src/components/DecodeTxs' -import { fetchTxDecoder } from 'src/utils/decodeTx' -import { DecodedData } from 'src/types/transactions/decode.d' -import { fromTokenUnit } from 'src/logic/tokens/utils/humanReadableValue' -import Block from 'src/components/layout/Block' -import Divider from 'src/components/Divider' - -import { ConfirmTxModalProps, DecodedTxDetail } from '.' -import Hairline from 'src/components/layout/Hairline' -import { ButtonStatus, Modal } from 'src/components/Modal' - -const { nativeCoin } = getNetworkInfo() - -const Container = styled.div` - max-width: 480px; - padding: ${md} ${lg} 0; -` -const TransactionFeesWrapper = styled.div` - background-color: ${({ theme }) => theme.colors.background}; - padding: ${sm} ${lg}; -` - -const DecodeTxsWrapper = styled.div` - margin: 24px -24px; -` - -const StyledBlock = styled(Block)` - background-color: ${({ theme }) => theme.colors.separator}; - width: fit-content; - padding: 5px 10px; - border-radius: 3px; - margin: 4px 0 0 40px; - - display: flex; - - > :nth-child(1) { - margin-right: 5px; - } -` - -type Props = ConfirmTxModalProps & { - areTxsMalformed: boolean - showDecodedTxData: (decodedTxDetails: DecodedTxDetail) => void - hidden: boolean // used to prevent re-rendering the modal each time a tx is inspected -} - -const parseTxValue = (value: string | number): string => { - return web3ReadOnly.utils.toBN(value).toString() -} - -export const ReviewConfirm = ({ - app, - txs, - safeAddress, - ethBalance, - safeName, - params, - hidden, - onUserConfirm, - onClose, - onTxReject, - areTxsMalformed, - showDecodedTxData, -}: Props): ReactElement => { - const isMultiSend = txs.length > 1 - const [decodedData, setDecodedData] = useState(null) - const dispatch = useDispatch() - const explorerUrl = getExplorerInfo(safeAddress) - - const txRecipient: string | undefined = useMemo(() => (isMultiSend ? MULTI_SEND_ADDRESS : txs[0]?.to), [ - txs, - isMultiSend, - ]) - const txData: string | undefined = useMemo(() => (isMultiSend ? encodeMultiSendCall(txs) : txs[0]?.data), [ - txs, - isMultiSend, - ]) - const txValue: string | undefined = useMemo( - () => (isMultiSend ? '0' : txs[0]?.value && parseTxValue(txs[0]?.value)), - [txs, isMultiSend], - ) - const operation = useMemo(() => (isMultiSend ? DELEGATE_CALL : CALL), [isMultiSend]) - const [manualSafeTxGas, setManualSafeTxGas] = useState(0) - const [manualGasPrice, setManualGasPrice] = useState() - const [manualGasLimit, setManualGasLimit] = useState() - - const { - gasLimit, - gasPriceFormatted, - gasEstimation, - isOffChainSignature, - isCreation, - isExecution, - gasCostFormatted, - txEstimationExecutionStatus, - } = useEstimateTransactionGas({ - txData: txData || '', - txRecipient, - operation, - txAmount: txValue, - safeTxGas: manualSafeTxGas, - manualGasPrice, - manualGasLimit, - }) - - const [buttonStatus, setButtonStatus] = useEstimationStatus(txEstimationExecutionStatus) - - // Decode tx data. - useEffect(() => { - const decodeTxData = async () => { - const res = await fetchTxDecoder(txData) - setDecodedData(res) - } - - decodeTxData() - }, [txData]) - - const handleTxRejection = () => { - onTxReject() - onClose() - } - - const handleUserConfirmation = (safeTxHash: string): void => { - onUserConfirm(safeTxHash) - onClose() - } - - const confirmTransactions = async (txParameters: TxParameters) => { - setButtonStatus(ButtonStatus.LOADING) - - await dispatch( - createTransaction( - { - safeAddress, - to: txRecipient, - valueInWei: txValue, - txData, - operation, - origin: app.id, - navigateToTransactionsTab: false, - txNonce: txParameters.safeNonce, - safeTxGas: txParameters.safeTxGas ? Number(txParameters.safeTxGas) : undefined, - ethParameters: txParameters, - notifiedTransaction: TX_NOTIFICATION_TYPES.STANDARD_TX, - }, - handleUserConfirmation, - handleTxRejection, - ), - ) - - setButtonStatus(ButtonStatus.READY) - } - - const closeEditModalCallback = (txParameters: TxParameters) => { - const oldGasPrice = Number(gasPriceFormatted) - const newGasPrice = Number(txParameters.ethGasPrice) - const oldSafeTxGas = Number(gasEstimation) - const newSafeTxGas = Number(txParameters.safeTxGas) - - if (newGasPrice && oldGasPrice !== newGasPrice) { - setManualGasPrice(txParameters.ethGasPrice) - } - - if (txParameters.ethGasLimit && gasLimit !== txParameters.ethGasLimit) { - setManualGasLimit(txParameters.ethGasLimit) - } - - if (newSafeTxGas && oldSafeTxGas !== newSafeTxGas) { - setManualSafeTxGas(newSafeTxGas) - } - } - - return ( - - {(txParameters, toggleEditMode) => ( - - )} - - ) -} diff --git a/src/routes/safe/components/Apps/components/ConfirmTxModal/SafeAppLoadError.tsx b/src/routes/safe/components/Apps/components/ConfirmTxModal/SafeAppLoadError.tsx deleted file mode 100644 index feddb41212..0000000000 --- a/src/routes/safe/components/Apps/components/ConfirmTxModal/SafeAppLoadError.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import React, { ReactElement } from 'react' -import { Icon, Text, Title, ModalFooterConfirmation } from '@gnosis.pm/safe-react-components' -import styled from 'styled-components' -import { ConfirmTxModalProps } from '.' - -const IconText = styled.div` - display: flex; - align-items: center; - - span { - margin-right: 4px; - } -` - -const FooterWrapper = styled.div` - margin-top: 15px; -` - -export const SafeAppLoadError = ({ onTxReject, onClose }: ConfirmTxModalProps): ReactElement => { - const handleTxRejection = () => { - onTxReject() - onClose() - } - - return ( - <> - - - Transaction error - - - This Safe App initiated a transaction which cannot be processed. Please get in touch with the developer of this - Safe App for more information. - - - - handleTxRejection()} - handleOk={() => {}} - okDisabled={true} - okText="Submit" - /> - - - ) -} diff --git a/src/routes/safe/components/Apps/components/ConfirmTxModal/index.tsx b/src/routes/safe/components/Apps/components/ConfirmTxModal/index.tsx deleted file mode 100644 index 13fa73544c..0000000000 --- a/src/routes/safe/components/Apps/components/ConfirmTxModal/index.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import React, { ReactElement, useState } from 'react' -import { Transaction } from '@gnosis.pm/safe-apps-sdk-v1' - -import Modal from 'src/components/Modal' -import { SafeApp } from 'src/routes/safe/components/Apps/types' -import { TransactionParams } from 'src/routes/safe/components/Apps/components/AppFrame' -import { mustBeEthereumAddress } from 'src/components/forms/validator' -import { SafeAppLoadError } from './SafeAppLoadError' -import { ReviewConfirm } from './ReviewConfirm' -import { DecodedDataParameterValue, DecodedData } from 'src/types/transactions/decode' -import { DecodedTxDetail } from './DecodedTxDetail' - -export type ConfirmTxModalProps = { - isOpen: boolean - app: SafeApp - txs: Transaction[] - params?: TransactionParams - safeAddress: string - safeName: string - ethBalance: string - onUserConfirm: (safeTxHash: string) => void - onTxReject: () => void - onClose: () => void -} - -const isTxValid = (t: Transaction): boolean => { - if (!['string', 'number'].includes(typeof t.value)) { - return false - } - - if (typeof t.value === 'string' && !/^(0x)?[0-9a-f]+$/i.test(t.value)) { - return false - } - - const isAddressValid = mustBeEthereumAddress(t.to) === undefined - return isAddressValid && !!t.data && typeof t.data === 'string' -} - -export type DecodedTxDetail = DecodedDataParameterValue | DecodedData | undefined - -export const ConfirmTxModal = (props: ConfirmTxModalProps): ReactElement | null => { - const [decodedTxDetails, setDecodedTxDetails] = useState() - const areTxsMalformed = props.txs.some((t) => !isTxValid(t)) - - const showDecodedTxData = setDecodedTxDetails - const hideDecodedTxData = () => setDecodedTxDetails(undefined) - - const closeDecodedTxDetail = () => { - hideDecodedTxData() - props.onClose() - } - - return ( - - {areTxsMalformed && } - {decodedTxDetails && ( - - )} - - - ) -} diff --git a/src/routes/safe/components/Apps/components/LegalDisclaimer.tsx b/src/routes/safe/components/Apps/components/LegalDisclaimer.tsx deleted file mode 100644 index bc711b9dd8..0000000000 --- a/src/routes/safe/components/Apps/components/LegalDisclaimer.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react' -import { FixedDialog, Text } from '@gnosis.pm/safe-react-components' - -interface OwnProps { - onCancel: () => void - onConfirm: () => void -} - -const LegalDisclaimer = ({ onCancel, onConfirm }: OwnProps): JSX.Element => ( - - - You are now accessing third-party apps, which we do not own, control, maintain or audit. We are not liable for - any loss you may suffer in connection with interacting with the apps, which is at your own risk. You must read - our Terms, which contain more detailed provisions binding on you relating to the apps. - -
- - I have read and understood the{' '} - - Terms - {' '} - and this Disclaimer, and agree to be bound by them. - - - } - onCancel={onCancel} - onConfirm={onConfirm} - title="Disclaimer" - /> -) - -export default LegalDisclaimer diff --git a/src/routes/safe/components/Apps/hooks/useAppList.ts b/src/routes/safe/components/Apps/hooks/useAppList.ts deleted file mode 100644 index 68c7f19cda..0000000000 --- a/src/routes/safe/components/Apps/hooks/useAppList.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { useState, useEffect, useCallback } from 'react' -import { loadFromStorage, saveToStorage } from 'src/utils/storage' -import { APPS_STORAGE_KEY, getAppInfoFromUrl, getAppsList, getEmptySafeApp } from '../utils' -import { AppData } from '../api/fetchSafeAppsList' -import { SafeApp, StoredSafeApp, SAFE_APP_FETCH_STATUS } from '../types' -import { getNetworkId } from 'src/config' - -type UseAppListReturnType = { - appList: SafeApp[] - removeApp: (appUrl: string) => void - staticAppsList: AppData[] -} - -const useAppList = (): UseAppListReturnType => { - const [appList, setAppList] = useState([]) - const [staticAppsList, setStaticAppsList] = useState([]) - - useEffect(() => { - const loadAppsList = async () => { - const remoteAppsList = await getAppsList() - setStaticAppsList(remoteAppsList) - } - - if (!staticAppsList.length) { - loadAppsList() - } - }, [staticAppsList]) - - // Load apps list - // for each URL we return a mocked safe-app with a loading status - // it was developed to speed up initial page load, otherwise the - // app renders a loading until all the safe-apps are fetched. - useEffect(() => { - const fetchAppCallback = (res: SafeApp) => { - setAppList((prevStatus) => { - const cpPrevStatus = [...prevStatus] - const appIndex = cpPrevStatus.findIndex((a) => a.url === res.url) - const newStatus = res.error ? SAFE_APP_FETCH_STATUS.ERROR : SAFE_APP_FETCH_STATUS.SUCCESS - cpPrevStatus[appIndex] = { ...res, fetchStatus: newStatus } - return cpPrevStatus.sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase())) - }) - } - - const loadApps = async () => { - // recover apps from storage (third-party apps added by the user) - const persistedAppList = - (await loadFromStorage<(StoredSafeApp & { networks?: number[] })[]>(APPS_STORAGE_KEY)) || [] - - // backward compatibility. In a previous implementation a safe app could be disabled, that state was - // persisted in the storage. - const customApps = persistedAppList.filter( - (persistedApp) => !staticAppsList.some((staticApp) => staticApp.url === persistedApp.url), - ) - - const apps: SafeApp[] = [...staticAppsList, ...customApps] - // if the app does not expose supported networks, include them. (backward compatible) - .filter((app) => (!app.networks ? true : app.networks.includes(getNetworkId()))) - .map((app) => ({ - ...getEmptySafeApp(), - ...app, - url: app.url.trim(), - })) - - setAppList(apps) - - apps.forEach((app) => { - if (!app.name || app.name === 'unknown') { - // We are using legacy mode, we have to fetch info from manifest - getAppInfoFromUrl(app.url).then(fetchAppCallback) - } else { - // We already have manifest information so we directly add the app - fetchAppCallback(app) - } - }) - } - - loadApps() - }, [staticAppsList]) - - const removeApp = useCallback((appUrl: string): void => { - setAppList((list) => { - const newList = list.filter(({ url }) => url !== appUrl) - const persistedAppList = newList.map(({ url, disabled }) => ({ url, disabled })) - saveToStorage(APPS_STORAGE_KEY, persistedAppList) - - return newList - }) - }, []) - - return { - appList, - staticAppsList, - removeApp, - } -} - -export { useAppList } diff --git a/src/routes/safe/components/Apps/hooks/useIframeMessageHandler.ts b/src/routes/safe/components/Apps/hooks/useIframeMessageHandler.ts deleted file mode 100644 index e40c97fec5..0000000000 --- a/src/routes/safe/components/Apps/hooks/useIframeMessageHandler.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { useSnackbar } from 'notistack' -import { - InterfaceMessageIds, - InterfaceMessageToPayload, - SDKMessageIds, - SDKMessageToPayload, - SDK_MESSAGES, - INTERFACE_MESSAGES, - RequestId, - Transaction, - LowercaseNetworks, -} from '@gnosis.pm/safe-apps-sdk-v1' -import { useDispatch, useSelector } from 'react-redux' -import { useEffect, useCallback, MutableRefObject } from 'react' - -import { getNetworkName, getTxServiceUrl } from 'src/config/' -import { currentSafeWithNames } from 'src/logic/safe/store/selectors' -import { TransactionParams } from '../components/AppFrame' -import { SafeApp } from 'src/routes/safe/components/Apps/types' - -type InterfaceMessageProps = { - messageId: T - data: InterfaceMessageToPayload[T] -} - -type ReturnType = { - sendMessageToIframe: (message: InterfaceMessageProps, requestId?: RequestId) => void -} - -const NETWORK_NAME = getNetworkName() - -const useIframeMessageHandler = ( - selectedApp: SafeApp | undefined, - openConfirmationModal: (txs: Transaction[], params: TransactionParams | undefined, requestId: RequestId) => void, - closeModal: () => void, - iframeRef: MutableRefObject, -): ReturnType => { - const { enqueueSnackbar, closeSnackbar } = useSnackbar() - const { address: safeAddress, ethBalance, name: safeName } = useSelector(currentSafeWithNames) - const dispatch = useDispatch() - - const sendMessageToIframe = useCallback( - function (message: InterfaceMessageProps, requestId?: RequestId) { - const requestWithMessage = { - ...message, - requestId: requestId || Math.trunc(window.performance.now()), - version: '0.4.2', - } - - if (iframeRef && selectedApp) { - iframeRef.current?.contentWindow?.postMessage(requestWithMessage, selectedApp.url) - } - }, - [iframeRef, selectedApp], - ) - - useEffect(() => { - const handleIframeMessage = ( - messageId: SDKMessageIds, - messagePayload: SDKMessageToPayload[typeof messageId], - requestId: RequestId, - ): void => { - if (!messageId) { - return - } - - switch (messageId) { - // typescript doesn't narrow type in switch/case statements - // issue: https://github.com/microsoft/TypeScript/issues/20375 - // possible solution: https://stackoverflow.com/a/43879897/7820085 - case SDK_MESSAGES.SEND_TRANSACTIONS: { - if (messagePayload) { - openConfirmationModal( - messagePayload as SDKMessageToPayload[typeof SDK_MESSAGES.SEND_TRANSACTIONS], - undefined, - requestId, - ) - } - break - } - - case SDK_MESSAGES.SAFE_APP_SDK_INITIALIZED: { - const safeInfoMessage = { - messageId: INTERFACE_MESSAGES.ON_SAFE_INFO, - data: { - safeAddress: safeAddress as string, - network: NETWORK_NAME.toLowerCase() as LowercaseNetworks, - ethBalance: ethBalance as string, - }, - } - const envInfoMessage = { - messageId: INTERFACE_MESSAGES.ENV_INFO, - data: { - txServiceUrl: getTxServiceUrl(), - }, - } - - sendMessageToIframe(safeInfoMessage) - sendMessageToIframe(envInfoMessage) - break - } - default: { - console.error(`ThirdPartyApp: A message was received with an unknown message id ${messageId}.`) - break - } - } - } - const onIframeMessage = async ( - message: MessageEvent<{ - requestId: RequestId - messageId: SDKMessageIds - data: SDKMessageToPayload[SDKMessageIds] - }>, - ) => { - if (message.origin === window.origin) { - return - } - if (!selectedApp?.url.includes(message.origin)) { - console.error(`ThirdPartyApp: A message was received from an unknown origin ${message.origin}`) - return - } - handleIframeMessage(message.data.messageId, message.data.data, message.data.requestId) - } - - window.addEventListener('message', onIframeMessage) - return () => { - window.removeEventListener('message', onIframeMessage) - } - }, [ - closeModal, - closeSnackbar, - dispatch, - enqueueSnackbar, - ethBalance, - openConfirmationModal, - safeAddress, - safeName, - selectedApp, - sendMessageToIframe, - ]) - - return { - sendMessageToIframe, - } -} - -export { useIframeMessageHandler } diff --git a/src/routes/safe/components/Apps/hooks/useLegalConsent.ts b/src/routes/safe/components/Apps/hooks/useLegalConsent.ts deleted file mode 100644 index c9bbf86ada..0000000000 --- a/src/routes/safe/components/Apps/hooks/useLegalConsent.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { useState, useEffect, useCallback } from 'react' -import { loadFromStorage, saveToStorage } from 'src/utils/storage' - -const APPS_LEGAL_CONSENT_RECEIVED = 'APPS_LEGAL_CONSENT_RECEIVED' - -const useLegalConsent = (): { consentReceived: boolean | undefined; onConsentReceipt: () => void } => { - const [consentReceived, setConsentReceived] = useState() - - useEffect(() => { - const checkLegalDisclaimer = async () => { - const storedConsentReceived = await loadFromStorage(APPS_LEGAL_CONSENT_RECEIVED) - - if (storedConsentReceived) { - setConsentReceived(true) - } else { - setConsentReceived(false) - } - } - - checkLegalDisclaimer() - }, []) - - const onConsentReceipt = useCallback((): void => { - setConsentReceived(true) - saveToStorage(APPS_LEGAL_CONSENT_RECEIVED, true) - }, []) - - return { consentReceived, onConsentReceipt } -} - -export { useLegalConsent } diff --git a/src/routes/safe/components/Apps/index.tsx b/src/routes/safe/components/Apps/index.tsx deleted file mode 100644 index f9301b7830..0000000000 --- a/src/routes/safe/components/Apps/index.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react' -import { useSafeAppUrl } from 'src/logic/hooks/useSafeAppUrl' - -import AppFrame from './components/AppFrame' -import AppsList from './components/AppsList' - -const Apps = (): React.ReactElement => { - const { getAppUrl } = useSafeAppUrl() - const url = getAppUrl() - if (url) { - return - } else { - return - } -} - -export default Apps diff --git a/src/routes/safe/components/Apps/utils.ts b/src/routes/safe/components/Apps/utils.ts index feb0d6daf9..f2f10be572 100644 --- a/src/routes/safe/components/Apps/utils.ts +++ b/src/routes/safe/components/Apps/utils.ts @@ -5,7 +5,7 @@ import { SafeApp, SAFE_APP_FETCH_STATUS } from './types' import { getContentFromENS } from 'src/logic/wallets/getWeb3' import appsIconSvg from 'src/assets/icons/apps.svg' -import { ETHEREUM_NETWORK } from 'src/config/networks/network.d' +import { HARMONY_NETWORK } from 'src/config/networks/network.d' import { logError, Errors } from 'src/logic/exceptions/CodedException' import { AppData, fetchSafeAppsList } from './api/fetchSafeAppsList' @@ -23,159 +23,7 @@ export type StaticAppInfo = { disabled: boolean networks: number[] } -export const staticAppsList: Array = [ - // 1inch - { - url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmUXF1yVGdqUfMbhNyfM3jpP6Bw66cYnKPoWq6iHkhd3Aw`, - disabled: false, - networks: [ETHEREUM_NETWORK.MAINNET], - }, - // Aave - { - url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmQ3w2ezp2zx3u2LYQHyuNzMrLDJFjyL1rjAFTjNMcQ4cK`, - disabled: false, - networks: [ETHEREUM_NETWORK.MAINNET], - }, - // Aave v2 - { - url: `https://app.aave.com/`, - disabled: false, - networks: [ETHEREUM_NETWORK.MAINNET], - }, - //Balancer Exchange - { - url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmRb2VfPVYBrv6gi2zDywgVgTg3A19ZCRMqwL13Ez5f5AS`, - disabled: false, - networks: [ETHEREUM_NETWORK.MAINNET], - }, - // Balancer Pool - { - url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmVaxypk2FTyfcTS9oZKxmpQziPUTu2VRhhW7sso1mGysf`, - disabled: false, - networks: [ETHEREUM_NETWORK.MAINNET], - }, - // CMM - // Point to a static server to allow app update without Safe deployment - { - url: `https://safe-cmm.gnosis.io`, - disabled: false, - networks: [ETHEREUM_NETWORK.RINKEBY, ETHEREUM_NETWORK.XDAI], - }, - // Compound - { - url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmX31xCdhFDmJzoVG33Y6kJtJ5Ujw8r5EJJBrsp8Fbjm7k`, - disabled: false, - networks: [ETHEREUM_NETWORK.MAINNET, ETHEREUM_NETWORK.RINKEBY], - }, - // dHedge - { - url: `https://app.dhedge.org/`, - disabled: false, - networks: [ETHEREUM_NETWORK.MAINNET], - }, - // ENS - { - url: `https://app.ens.domains/`, - disabled: false, - networks: [ETHEREUM_NETWORK.MAINNET, ETHEREUM_NETWORK.RINKEBY], - }, - // Gnosis Starter - { - url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmdCwUutYH8GXXNgTShB4cKJ8YJq4PqZ55QxMznKc9DbeS`, - disabled: false, - networks: [ETHEREUM_NETWORK.MAINNET, ETHEREUM_NETWORK.RINKEBY], - }, - // Idle - { - url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmTvrLwJtyjG8QFHgvqdPhcV5DBMQ7oZceSU4uvPw9vQaj`, - disabled: false, - networks: [ETHEREUM_NETWORK.MAINNET, ETHEREUM_NETWORK.RINKEBY], - }, - // Lido finance - { - url: `${process.env.REACT_APP_IPFS_GATEWAY}/Qmde8dsa9r8bB59CNGww6LRiaZABuKaJfuzvu94hFkatJC`, - disabled: false, - networks: [ETHEREUM_NETWORK.MAINNET], - }, - // Liquity - { - url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmYzTAH6Nzexu35tbWmhVrLYwWj9MdbD1iECejgaGHFk8P`, - disabled: false, - networks: [ETHEREUM_NETWORK.MAINNET, ETHEREUM_NETWORK.RINKEBY], - }, - // Mushrooms finance - { - url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmT96aES2YA9BssByc6DVizQDkofmKRErs8gJyqWipjyS8`, - disabled: false, - networks: [ETHEREUM_NETWORK.MAINNET], - }, - // Pooltogether - { - url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmTa21pi77hiT1sLCGy5BeVwcyzExUSp2z7byxZukye8hr`, - disabled: false, - networks: [ETHEREUM_NETWORK.MAINNET, ETHEREUM_NETWORK.RINKEBY], - }, - // Request - { - url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmTBBaiDQyGa17DJ7DdviyHbc51fTVgf6Z5PW5w2YUTkgR`, - disabled: false, - networks: [ETHEREUM_NETWORK.MAINNET], - }, - // Sablier - { - url: `${process.env.REACT_APP_IPFS_GATEWAY}/Qmb1Xpfu9mnX4A3trpoVeBZ9sTiNtEuRoFKEiaVXWntDxB`, - disabled: false, - networks: [ETHEREUM_NETWORK.MAINNET, ETHEREUM_NETWORK.RINKEBY], - }, - // Synthetix - { - url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmXLxxczMH4MBEYDeeN9zoiHDzVkeBmB5rBjA3UniPEFcA`, - disabled: false, - networks: [ETHEREUM_NETWORK.MAINNET, ETHEREUM_NETWORK.RINKEBY], - }, - // OpenZeppelin - { - url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmQovvfYYMUXjZfNbysQDUEXR8nr55iJRwcYgJQGJR7KEA`, - disabled: false, - networks: [ - ETHEREUM_NETWORK.MAINNET, - ETHEREUM_NETWORK.RINKEBY, - //ETHEREUM_NETWORK.ENERGY_WEB_CHAIN, - //ETHEREUM_NETWORK.VOLTA, - // ETHEREUM_NETWORK.XDAI, - ], - }, - // TX-Builder - { - url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmZBgEvjqi9Jg8xATr9uUgNUVmnfYiECNxZv9Taux7mzgV`, - disabled: false, - networks: [ - ETHEREUM_NETWORK.MAINNET, - ETHEREUM_NETWORK.RINKEBY, - ETHEREUM_NETWORK.ENERGY_WEB_CHAIN, - ETHEREUM_NETWORK.VOLTA, - ETHEREUM_NETWORK.XDAI, - ], - }, - // Wallet-Connect - { - url: `${process.env.REACT_APP_IPFS_GATEWAY}/QmX9B982ZAaBzbm6yBoZUS3uLgcizYA6wW65RCXVRZkG6f`, - disabled: false, - networks: [ - ETHEREUM_NETWORK.MAINNET, - ETHEREUM_NETWORK.RINKEBY, - ETHEREUM_NETWORK.ENERGY_WEB_CHAIN, - ETHEREUM_NETWORK.VOLTA, - ETHEREUM_NETWORK.XDAI, - ], - }, - // Yearn Vaults - { - url: `${process.env.REACT_APP_IPFS_GATEWAY}/Qme9HuPPhgCtgfj1CktvaDKhTesMueGCV2Kui1Sqna3Xs9`, - disabled: false, - networks: [ETHEREUM_NETWORK.MAINNET], - }, -] +export const staticAppsList: Array = [] export const getAppsList = async (): Promise => { let result @@ -219,97 +67,95 @@ export const getEmptySafeApp = (): SafeApp => { } } -export const getAppInfoFromUrl = memoize( - async (appUrl: string): Promise => { - let res = { - ...getEmptySafeApp(), - error: true, - loadingStatus: SAFE_APP_FETCH_STATUS.ERROR, - } - - if (!appUrl?.length) { - return res - } +export const getAppInfoFromUrl = memoize(async (appUrl: string): Promise => { + let res = { + ...getEmptySafeApp(), + error: true, + loadingStatus: SAFE_APP_FETCH_STATUS.ERROR, + } - res.url = appUrl.trim() - const noTrailingSlashUrl = removeLastTrailingSlash(res.url) + if (!appUrl?.length) { + return res + } - try { - const appInfo = await axios.get(`${noTrailingSlashUrl}/manifest.json`, { timeout: 5_000 }) + res.url = appUrl.trim() + const noTrailingSlashUrl = removeLastTrailingSlash(res.url) - // verify imported app fulfil safe requirements - if (!appInfo?.data || !isAppManifestValid(appInfo.data)) { - throw Error('The app does not fulfil the structure required.') - } + try { + const appInfo = await axios.get(`${noTrailingSlashUrl}/manifest.json`, { timeout: 5_000 }) - // the DB origin field has a limit of 100 characters - const originFieldSize = 100 - const jsonDataLength = 20 - const remainingSpace = originFieldSize - res.url.length - jsonDataLength + // verify imported app fulfil safe requirements + if (!appInfo?.data || !isAppManifestValid(appInfo.data)) { + throw Error('The app does not fulfil the structure required.') + } - const appInfoData = { - name: appInfo.data.name, - iconPath: appInfo.data.iconPath, - description: appInfo.data.description, - providedBy: appInfo.data.providedBy, - } + // the DB origin field has a limit of 100 characters + const originFieldSize = 100 + const jsonDataLength = 20 + const remainingSpace = originFieldSize - res.url.length - jsonDataLength - res = { - ...res, - ...appInfoData, - id: JSON.stringify({ url: res.url, name: appInfo.data.name.substring(0, remainingSpace) }), - error: false, - loadingStatus: SAFE_APP_FETCH_STATUS.SUCCESS, - } + const appInfoData = { + name: appInfo.data.name, + iconPath: appInfo.data.iconPath, + description: appInfo.data.description, + providedBy: appInfo.data.providedBy, + } - if (appInfo.data.iconPath) { - try { - const iconInfo = await axios.get(`${noTrailingSlashUrl}/${appInfo.data.iconPath}`, { timeout: 1000 * 10 }) - if (/image\/\w/gm.test(iconInfo.headers['content-type'])) { - res.iconUrl = `${noTrailingSlashUrl}/${appInfo.data.iconPath}` - } - } catch (error) { - console.error(`It was not possible to fetch icon from app ${res.url}`) - } - } - return res - } catch (error) { - logError(Errors._900, error.message, { - contexts: { - safeApp: { - url: appUrl, - }, - }, - }) - return res + res = { + ...res, + ...appInfoData, + id: JSON.stringify({ url: res.url, name: appInfo.data.name.substring(0, remainingSpace) }), + error: false, + loadingStatus: SAFE_APP_FETCH_STATUS.SUCCESS, } - }, -) -export const getIpfsLinkFromEns = memoize( - async (name: string): Promise => { - try { - const content = await getContentFromENS(name) - if (content && content.protocolType === 'ipfs') { - return `${process.env.REACT_APP_IPFS_GATEWAY}/${content.decoded}/` + if (appInfo.data.iconPath) { + try { + const iconInfo = await axios.get(`${noTrailingSlashUrl}/${appInfo.data.iconPath}`, { timeout: 1000 * 10 }) + if (/image\/\w/gm.test(iconInfo.headers['content-type'])) { + res.iconUrl = `${noTrailingSlashUrl}/${appInfo.data.iconPath}` + } + } catch (error) { + console.error(`It was not possible to fetch icon from app ${res.url}`) } - } catch (error) { - console.error(error) - return } - }, -) + return res + } catch (error) { + logError(Errors._900, error.message, { + contexts: { + safeApp: { + url: appUrl, + }, + }, + }) + return res + } +}) -export const uniqueApp = (appList: SafeApp[]) => (url: string): string | undefined => { - const newUrl = new URL(url) - const exists = appList.some((a) => { - try { - const currentUrl = new URL(a.url) - return currentUrl.href === newUrl.href - } catch (error) { - console.error('There was a problem trying to validate the URL existence.', error.message) - return false +export const getIpfsLinkFromEns = memoize(async (name: string): Promise => { + try { + const content = await getContentFromENS(name) + if (content && content.protocolType === 'ipfs') { + return `${process.env.REACT_APP_IPFS_GATEWAY}/${content.decoded}/` } - }) - return exists ? 'This app is already registered.' : undefined -} + } catch (error) { + console.error(error) + return + } +}) + +export const uniqueApp = + (appList: SafeApp[]) => + (url: string): string | undefined => { + const newUrl = new URL(url) + const exists = appList.some((a) => { + try { + const currentUrl = new URL(a.url) + return currentUrl.href === newUrl.href + } catch (error) { + console.error('There was a problem trying to validate the URL existence.', error.message) + return false + } + }) + return exists ? 'This app is already registered.' : undefined + } diff --git a/src/utils/constants.ts b/src/utils/constants.ts index cebef6481f..c2878c6a9f 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -1,35 +1,16 @@ export const APP_ENV = process.env.REACT_APP_ENV export const NODE_ENV = process.env.NODE_ENV export const IS_PRODUCTION = process.env.NODE_ENV === 'production' -export const NETWORK = process.env.REACT_APP_NETWORK?.toUpperCase() || 'RINKEBY' -export const INTERCOM_ID = APP_ENV === 'production' ? process.env.REACT_APP_INTERCOM_ID : 'plssl1fl' -export const GOOGLE_ANALYTICS_ID = process.env.REACT_APP_GOOGLE_ANALYTICS || '' -export const SENTRY_DSN = process.env.REACT_APP_SENTRY_DSN || '' -export const PORTIS_ID = process.env.REACT_APP_PORTIS_ID ?? '852b763d-f28b-4463-80cb-846d7ec5806b' -export const FORTMATIC_KEY = process.env.REACT_APP_FORTMATIC_KEY ?? 'pk_test_CAD437AA29BE0A40' -/* - * Not being used -export const SQUARELINK_ID = { - [ETHEREUM_NETWORK.RINKEBY]: '46ce08fe50913cfa1b78', - [ETHEREUM_NETWORK.MAINNET]: process.env.REACT_APP_SQUARELINK_ID, - [ETHEREUM_NETWORK.XDAI]: process.env.REACT_APP_SQUARELINK_ID, -} - */ -export const INFURA_TOKEN = process.env.REACT_APP_INFURA_TOKEN || '' +export const NETWORK = process.env.REACT_APP_NETWORK?.toUpperCase() || 'MAINNET' + export const LATEST_SAFE_VERSION = process.env.REACT_APP_LATEST_SAFE_VERSION || '1.1.1' -export const LOADED_SAFE_KEY = 'Gnosis Safe' + export const APP_VERSION = process.env.REACT_APP_APP_VERSION || 'not-defined' -export const OPENSEA_API_KEY = process.env.REACT_APP_OPENSEA_API_KEY || '' export const COLLECTIBLES_SOURCE = process.env.REACT_APP_COLLECTIBLES_SOURCE || 'Gnosis' export const TIMEOUT = process.env.NODE_ENV === 'test' ? 1500 : 5000 -export const ETHERSCAN_API_KEY = process.env.REACT_APP_ETHERSCAN_API_KEY -export const ETHGASSTATION_API_KEY = process.env.REACT_APP_ETHGASSTATION_API_KEY -export const SAFE_APPS_LIST_URL = - process.env.REACT_APP_SAFE_APPS_LIST_URL || - 'https://raw.githubusercontent.com/gnosis/safe-apps-list/main/public/gnosis-default.applist.json' -export const IPFS_GATEWAY = process.env.REACT_APP_IPFS_GATEWAY + export const SPENDING_LIMIT_MODULE_ADDRESS = - process.env.REACT_APP_SPENDING_LIMIT_MODULE_ADDRESS || '0xCFbFaC74C26F8647cBDb8c5caf80BB5b32E43134' + process.env.REACT_APP_SPENDING_LIMIT_MODULE_ADDRESS || '0x965179FbFcf7410634C7A0a258545E136A890cD7' export const KNOWN_MODULES = { [SPENDING_LIMIT_MODULE_ADDRESS]: 'Spending limit', } diff --git a/src/utils/googleAnalytics.ts b/src/utils/googleAnalytics.ts deleted file mode 100644 index 8f29667fc6..0000000000 --- a/src/utils/googleAnalytics.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { useCallback, useEffect, useState } from 'react' -import ReactGA, { EventArgs } from 'react-ga' -import { getNetworkInfo } from 'src/config' - -import { getGoogleAnalyticsTrackingID } from 'src/config' -import { COOKIES_KEY } from 'src/logic/cookies/model/cookie' -import { loadFromCookie, removeCookie } from 'src/logic/cookies/utils' - -export const SAFE_NAVIGATION_EVENT = 'Safe Navigation' - -export const COOKIES_LIST = [ - { name: '_ga', path: '/' }, - { name: '_gat', path: '/' }, - { name: '_gid', path: '/' }, -] - -let analyticsLoaded = false -export const loadGoogleAnalytics = (): void => { - if (analyticsLoaded) { - return - } - // eslint-disable-next-line no-console - console.log('Loading google analytics...') - const trackingID = getGoogleAnalyticsTrackingID() - const networkInfo = getNetworkInfo() - if (!trackingID) { - console.error('[GoogleAnalytics] - In order to use google analytics you need to add an trackingID') - } else { - ReactGA.initialize(trackingID) - ReactGA.set({ - anonymizeIp: true, - appName: `Gnosis Safe Multisig (${networkInfo.label})`, - appId: `io.gnosis.safe.${networkInfo.label.toLowerCase()}`, - appVersion: process.env.REACT_APP_APP_VERSION, - }) - analyticsLoaded = true - } -} - -type UseAnalyticsResponse = { - trackPage: (path: string) => void - trackEvent: (event: EventArgs) => void -} - -export const useAnalytics = (): UseAnalyticsResponse => { - const [analyticsAllowed, setAnalyticsAllowed] = useState(false) - - useEffect(() => { - async function fetchCookiesFromStorage() { - const cookiesState = await loadFromCookie(COOKIES_KEY) - if (cookiesState) { - const { acceptedAnalytics } = cookiesState - setAnalyticsAllowed(acceptedAnalytics) - } - } - fetchCookiesFromStorage() - }, []) - - const trackPage = useCallback( - (page) => { - if (!analyticsAllowed || !analyticsLoaded) { - return - } - ReactGA.pageview(page) - }, - [analyticsAllowed], - ) - - const trackEvent = useCallback( - (event: EventArgs) => { - if (!analyticsAllowed || !analyticsLoaded) { - return - } - ReactGA.event(event) - }, - [analyticsAllowed], - ) - - return { trackPage, trackEvent } -} - -// we remove GA cookies manually as react-ga does not provides a utility for it. -export const removeCookies = (): void => { - const subDomain = location.host.split('.').slice(-2).join('.') - COOKIES_LIST.forEach((cookie) => removeCookie(cookie.name, cookie.path, `.${subDomain}`)) -} diff --git a/src/utils/intercom.ts b/src/utils/intercom.ts deleted file mode 100644 index 605ac63d39..0000000000 --- a/src/utils/intercom.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { INTERCOM_ID } from 'src/utils/constants' - -let intercomLoaded = false - -export const isIntercomLoaded = () => intercomLoaded - -// eslint-disable-next-line consistent-return -export const loadIntercom = (): void => { - const APP_ID = INTERCOM_ID - if (!APP_ID) { - console.error('[Intercom] - In order to use Intercom you need to add an appID') - return - } - const d = document - const s = d.createElement('script') - s.type = 'text/javascript' - s.async = true - s.src = `https://widget.intercom.io/widget/${APP_ID}` - const x = d.getElementsByTagName('script')[0] - x?.parentNode?.insertBefore(s, x) - - s.onload = () => { - ;(window as any).Intercom('boot', { - app_id: APP_ID, - consent: true, - }) - intercomLoaded = true - } -} - -export const closeIntercom = (): void => { - if (!isIntercomLoaded()) return - intercomLoaded = false - ;(window as any).Intercom('shutdown') -} From 585e746da77cee8fb9be42d708bc7652edc1d24c Mon Sep 17 00:00:00 2001 From: unlocker Date: Mon, 2 Aug 2021 07:37:50 -0700 Subject: [PATCH 2/4] Remove apps router --- src/index.tsx | 10 ---------- src/routes/safe/components/Apps/utils.ts | 12 ------------ src/routes/safe/container/index.tsx | 11 ----------- 3 files changed, 33 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 7a3aeb82fa..5d204adf34 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,15 +1,12 @@ import { BigNumber } from 'bignumber.js' import React from 'react' import ReactDOM from 'react-dom' -import * as Sentry from '@sentry/react' -import { Integrations } from '@sentry/tracing' import Root from 'src/components/Root' import loadCurrentSessionFromStorage from 'src/logic/currentSession/store/actions/loadCurrentSessionFromStorage' import loadDefaultSafe from 'src/logic/safe/store/actions/loadDefaultSafe' import loadSafesFromStorage from 'src/logic/safe/store/actions/loadSafesFromStorage' import { store } from 'src/store' -import { SENTRY_DSN } from './utils/constants' import { disableMMAutoRefreshWarning } from './utils/mm_warnings' disableMMAutoRefreshWarning() @@ -20,13 +17,6 @@ store.dispatch(loadSafesFromStorage()) store.dispatch(loadDefaultSafe()) store.dispatch(loadCurrentSessionFromStorage()) -Sentry.init({ - dsn: SENTRY_DSN, - release: `safe-react@${process.env.REACT_APP_APP_VERSION}`, - integrations: [new Integrations.BrowserTracing()], - sampleRate: 0.01, -}) - const root = document.getElementById('root') if (root !== null) { diff --git a/src/routes/safe/components/Apps/utils.ts b/src/routes/safe/components/Apps/utils.ts index f2f10be572..2a198c05fa 100644 --- a/src/routes/safe/components/Apps/utils.ts +++ b/src/routes/safe/components/Apps/utils.ts @@ -7,7 +7,6 @@ import { getContentFromENS } from 'src/logic/wallets/getWeb3' import appsIconSvg from 'src/assets/icons/apps.svg' import { HARMONY_NETWORK } from 'src/config/networks/network.d' import { logError, Errors } from 'src/logic/exceptions/CodedException' -import { AppData, fetchSafeAppsList } from './api/fetchSafeAppsList' export const APPS_STORAGE_KEY = 'APPS_STORAGE_KEY' @@ -25,17 +24,6 @@ export type StaticAppInfo = { } export const staticAppsList: Array = [] -export const getAppsList = async (): Promise => { - let result - try { - result = await fetchSafeAppsList() - } catch (error) { - console.error('Could not fetch remote apps list', error) - } - - return result?.apps && result?.apps.length ? result.apps : staticAppsList -} - export const getAppInfoFromOrigin = (origin: string): { url: string; name: string } | null => { try { return JSON.parse(origin) diff --git a/src/routes/safe/container/index.tsx b/src/routes/safe/container/index.tsx index 4368281bf3..096bf68b02 100644 --- a/src/routes/safe/container/index.tsx +++ b/src/routes/safe/container/index.tsx @@ -17,7 +17,6 @@ export const ADDRESS_BOOK_TAB_BTN_TEST_ID = 'address-book-tab-btn' export const SAFE_VIEW_NAME_HEADING_TEST_ID = 'safe-name-heading' export const TRANSACTIONS_TAB_NEW_BTN_TEST_ID = 'transactions-tab-new-btn' -const Apps = React.lazy(() => import('src/routes/safe/components/Apps')) const Settings = React.lazy(() => import('src/routes/safe/components/Settings')) const Balances = React.lazy(() => import('src/routes/safe/components/Balances')) const TxList = React.lazy(() => import('src/routes/safe/components/Transactions/TxList')) @@ -70,16 +69,6 @@ const Container = (): React.ReactElement => { path={`${matchSafeWithAddress?.path}/transactions`} render={() => wrapInSuspense(, null)} /> - { - if (!featuresEnabled.includes(FEATURES.SAFE_APPS)) { - history.push(`${matchSafeWithAddress?.url}/balances`) - } - return wrapInSuspense(, null) - }} - /> Date: Mon, 2 Aug 2021 07:58:19 -0700 Subject: [PATCH 3/4] Update harmony Logo and a lot more --- public/favicon.ico | Bin 110088 -> 10408 bytes public/index.html | 4 +- public/resources/background.png | Bin 84944 -> 0 bytes public/resources/harmony.png | Bin 0 -> 6033 bytes public/resources/icon.icns | Bin 77985 -> 0 bytes public/resources/icon.ico | Bin 109037 -> 0 bytes public/resources/safe.png | Bin 3641 -> 0 bytes src/components/App/index.tsx | 2 - src/components/AppLayout/Footer/index.tsx | 41 +-- .../assets/gnosis-safe-multisig-logo.svg | 5 - .../AppLayout/Header/assets/logo.png | Bin 0 -> 6271 bytes .../AppLayout/Header/components/Layout.tsx | 18 +- .../ProviderDetails/UserDetails.tsx | 4 +- .../CookiesBanner/assets/alert-red.svg | 11 - .../CookiesBanner/assets/intercom.png | Bin 20681 -> 0 bytes src/components/CookiesBanner/index.tsx | 283 ------------------ src/components/DecodeTxs/index.tsx | 202 ------------- src/components/SafeListSidebar/index.tsx | 5 - src/config/networks/mainnet.ts | 2 + src/config/networks/testnet.ts | 2 + src/logic/addressBook/model/addressBook.ts | 4 +- src/logic/cookies/model/cookie.ts | 1 - .../cookies/store/actions/openCookieBanner.ts | 7 - src/logic/cookies/store/reducer/cookies.ts | 18 -- src/logic/cookies/store/selectors/index.ts | 3 - src/logic/cookies/utils/index.ts | 33 -- src/routes/index.tsx | 6 +- src/routes/open/container/Open.tsx | 7 - .../safe/components/AddressBook/index.tsx | 7 +- .../safe/components/Balances/Coins/index.tsx | 14 +- .../Balances/Collectibles/index.tsx | 6 - .../components/Settings/Advanced/index.tsx | 6 - .../Settings/ManageOwners/index.tsx | 6 - .../components/Settings/SafeDetails/index.tsx | 6 - .../Settings/ThresholdSettings/index.tsx | 7 - src/store/index.ts | 3 - 36 files changed, 21 insertions(+), 692 deletions(-) delete mode 100644 public/resources/background.png create mode 100644 public/resources/harmony.png delete mode 100644 public/resources/icon.icns delete mode 100644 public/resources/icon.ico delete mode 100644 public/resources/safe.png delete mode 100644 src/components/AppLayout/Header/assets/gnosis-safe-multisig-logo.svg create mode 100644 src/components/AppLayout/Header/assets/logo.png delete mode 100644 src/components/CookiesBanner/assets/alert-red.svg delete mode 100644 src/components/CookiesBanner/assets/intercom.png delete mode 100644 src/components/CookiesBanner/index.tsx delete mode 100644 src/components/DecodeTxs/index.tsx delete mode 100644 src/logic/cookies/model/cookie.ts delete mode 100644 src/logic/cookies/store/actions/openCookieBanner.ts delete mode 100644 src/logic/cookies/store/reducer/cookies.ts delete mode 100644 src/logic/cookies/store/selectors/index.ts delete mode 100644 src/logic/cookies/utils/index.ts diff --git a/public/favicon.ico b/public/favicon.ico index 85cacafc911b21d9ef58729cdd752dac828a38f4..97d02f875c041f19967ab085287602cce64e52e7 100644 GIT binary patch literal 10408 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 diff --git a/public/index.html b/public/index.html index ac3e48c24c..725affffef 100644 --- a/public/index.html +++ b/public/index.html @@ -5,7 +5,7 @@ - Gnosis Safe + Harmony Multisig Wallet -
+
diff --git a/public/resources/background.png b/public/resources/background.png deleted file mode 100644 index 4c0b9ba39112f0218d3d35b34465abd5e08e8715..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 84944 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ℜU#1 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
vZSWGdBr|7D>?qL57%B(~>pOD63KZLCx?a>zL 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 literal 0 HcmV?d00001 diff --git a/public/resources/icon.icns b/public/resources/icon.icns deleted file mode 100644 index 4c5e25718194d01dd74caf469351ba3db392fda4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77985 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 W5xJ^RLE{8?Ll(ns;Zr&exBuCYR%xXG diff --git a/public/resources/icon.ico b/public/resources/icon.ico deleted file mode 100644 index 8039e7963dcf3e9fb45bb7fb2dbbd93ed9b46b4e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 109037 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 diff --git a/public/resources/safe.png b/public/resources/safe.png deleted file mode 100644 index fec10acfd3354e5a99b7170dba23882806b9c28b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3641 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 diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index bfb08aba10..7c1521f11e 100644 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -12,7 +12,6 @@ import InfoIcon from 'src/assets/icons/info.svg' import AppLayout from 'src/components/AppLayout' import { SafeListSidebar, SafeListSidebarContext } from 'src/components/SafeListSidebar' -import CookiesBanner from 'src/components/CookiesBanner' import Notifier from 'src/components/Notifier' import Backdrop from 'src/components/layout/Backdrop' import Img from 'src/components/layout/Img' @@ -151,7 +150,6 @@ const App: React.FC = ({ children }) => { )} - ) } diff --git a/src/components/AppLayout/Footer/index.tsx b/src/components/AppLayout/Footer/index.tsx index 598041bfbf..42f9d22fac 100644 --- a/src/components/AppLayout/Footer/index.tsx +++ b/src/components/AppLayout/Footer/index.tsx @@ -1,11 +1,7 @@ import { makeStyles } from '@material-ui/core/styles' import cn from 'classnames' import * as React from 'react' -import { useDispatch } from 'react-redux' - -import GnoButtonLink from 'src/components/layout/ButtonLink' import Link from 'src/components/layout/Link' -import { openCookieBanner } from 'src/logic/cookies/store/actions/openCookieBanner' import { screenSm, secondary, sm } from 'src/theme/variables' const useStyles = makeStyles({ @@ -42,52 +38,21 @@ const useStyles = makeStyles({ }, } as any) -const appVersion = process.env.REACT_APP_APP_VERSION ? `v${process.env.REACT_APP_APP_VERSION} ` : 'Versions' - const Footer = (): React.ReactElement => { const date = new Date() const classes = useStyles() - const dispatch = useDispatch() - - const openCookiesHandler = () => { - dispatch(openCookieBanner({ cookieBannerOpen: true })) - } return (
- ©{date.getFullYear()} Gnosis + ©{date.getFullYear()} Harmony One | - + Terms | - + Privacy - | - - Licenses - - | - - Imprint - - | - - Cookie Policy - - - - - Preferences - - | - - {appVersion} -
) } diff --git a/src/components/AppLayout/Header/assets/gnosis-safe-multisig-logo.svg b/src/components/AppLayout/Header/assets/gnosis-safe-multisig-logo.svg deleted file mode 100644 index 62ed0fd93d..0000000000 --- a/src/components/AppLayout/Header/assets/gnosis-safe-multisig-logo.svg +++ /dev/null @@ -1,5 +0,0 @@ - - horizontal_left_small_black - - - diff --git a/src/components/AppLayout/Header/assets/logo.png b/src/components/AppLayout/Header/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..df3aeb60d3fcc52a798ae183405a3846f8e6aa7c GIT binary patch literal 6271 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 ({ root: { @@ -65,14 +62,11 @@ const styles = () => ({ const Layout = ({ classes, providerDetails, providerInfo }) => { const { clickAway, open, toggle } = useStateHandler() - const { clickAway: clickAwayNetworks, open: openNetworks, toggle: toggleNetworks } = useStateHandler() - const networks = getNetworks() - const { isDesktop } = window return ( - Gnosis Team Safe + Harmony Multisig @@ -102,14 +96,6 @@ const Layout = ({ classes, providerDetails, providerInfo }) => { )} /> - {!isDesktop && ( - - )} ) } diff --git a/src/components/AppLayout/Header/components/ProviderDetails/UserDetails.tsx b/src/components/AppLayout/Header/components/ProviderDetails/UserDetails.tsx index 83e832ee11..c339709a76 100644 --- a/src/components/AppLayout/Header/components/ProviderDetails/UserDetails.tsx +++ b/src/components/AppLayout/Header/components/ProviderDetails/UserDetails.tsx @@ -14,7 +14,7 @@ import Img from 'src/components/layout/Img' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' import { background, connected as connectedBg, lg, md, sm, warning, xs } from 'src/theme/variables' -import { ETHEREUM_NETWORK } from 'src/config/networks/network.d' +import { HARMONY_NETWORK } from 'src/config/networks/network.d' import { getExplorerInfo } from 'src/config' import { KeyRing } from 'src/components/AppLayout/Header/components/KeyRing' import WalletIcon from '../../assets/wallet.svg' @@ -95,7 +95,7 @@ const StyledCard = styled(Card)` ` type Props = { connected: boolean - network: ETHEREUM_NETWORK + network: HARMONY_NETWORK onDisconnect: () => void openDashboard?: (() => void | null) | boolean provider?: string diff --git a/src/components/CookiesBanner/assets/alert-red.svg b/src/components/CookiesBanner/assets/alert-red.svg deleted file mode 100644 index 6a20c41cc3..0000000000 --- a/src/components/CookiesBanner/assets/alert-red.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/src/components/CookiesBanner/assets/intercom.png b/src/components/CookiesBanner/assets/intercom.png deleted file mode 100644 index 74eb6efac15b691c9ac3e5f1446eb49f99dcf89b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20681 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%0ABXwCx$pVxAO?25{nxEf6koS=S|8=umzW6t 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 { - const classes = useStyles() - const dispatch = useRef(useDispatch()) - const intercomLoaded = isIntercomLoaded() - - const [showAnalytics, setShowAnalytics] = useState(false) - const [showIntercom, setShowIntercom] = useState(false) - const [localNecessary, setLocalNecessary] = useState(true) - const [localAnalytics, setLocalAnalytics] = useState(false) - const [localIntercom, setLocalIntercom] = useState(false) - const { getAppUrl } = useSafeAppUrl() - - const showBanner = useSelector(cookieBannerOpen) - const newAppUrl = getAppUrl() - const isSafeAppView = newAppUrl !== null - - useEffect(() => { - if (intercomLoaded && isSafeAppView) { - closeIntercom() - } - }, [isSafeAppView, intercomLoaded]) - - useEffect(() => { - async function fetchCookiesFromStorage() { - const cookiesState = await loadFromCookie(COOKIES_KEY) - if (!cookiesState) { - dispatch.current(openCookieBanner({ cookieBannerOpen: true })) - } else { - const { acceptedIntercom, acceptedAnalytics, acceptedNecessary } = cookiesState - if (acceptedIntercom === undefined) { - const newState = { - acceptedNecessary, - acceptedAnalytics, - acceptedIntercom: acceptedAnalytics, - } - const expDays = acceptedAnalytics ? 365 : 7 - await saveCookie(COOKIES_KEY, newState, expDays) - setLocalIntercom(newState.acceptedIntercom) - setShowIntercom(newState.acceptedIntercom) - } else { - setLocalIntercom(acceptedIntercom) - setShowIntercom(acceptedIntercom) - } - setLocalAnalytics(acceptedAnalytics) - setLocalNecessary(acceptedNecessary) - - if (acceptedAnalytics && !isDesktop) { - loadGoogleAnalytics() - } - } - } - fetchCookiesFromStorage() - }, [showAnalytics, showIntercom]) - - const acceptCookiesHandler = async () => { - const newState = { - acceptedNecessary: true, - acceptedAnalytics: !isDesktop, - acceptedIntercom: true, - } - await saveCookie(COOKIES_KEY, newState, 365) - setShowAnalytics(!isDesktop) - setShowIntercom(true) - dispatch.current(openCookieBanner({ cookieBannerOpen: false })) - } - - const closeCookiesBannerHandler = async () => { - const newState = { - acceptedNecessary: true, - acceptedAnalytics: localAnalytics, - acceptedIntercom: localIntercom, - } - const expDays = localAnalytics ? 365 : 7 - await saveCookie(COOKIES_KEY, newState, expDays) - setShowAnalytics(localAnalytics) - setShowIntercom(localIntercom) - - if (!localAnalytics) { - removeCookies() - } - - if (!localIntercom && isIntercomLoaded()) { - closeIntercom() - } - dispatch.current(openCookieBanner({ cookieBannerOpen: false })) - } - - if (showIntercom && !isSafeAppView) { - loadIntercom() - } - - const CookiesBannerForm = (props: CookiesBannerFormProps) => { - const { alertMessage } = props - return ( -
-
- {alertMessage && ( -
- - You attempted to open the customer support chat. Please accept the customer support cookie. -
- )} -

- We use cookies to provide you with the best experience and to help improve our website and application. - Please read our{' '} - - Cookie Policy - {' '} - for more information. By clicking "Accept all", you agree to the storing of cookies on your device - to enhance site navigation, analyze site usage and provide customer support. -

-
-
- } - disabled - label="Necessary" - name="Necessary" - onChange={() => setLocalNecessary((prev) => !prev)} - value={localNecessary} - /> -
-
- } - label="Customer support" - name="Customer support" - onChange={() => setLocalIntercom((prev) => !prev)} - value={localIntercom} - /> -
-
- } - label="Analytics" - name="Analytics" - onChange={() => setLocalAnalytics((prev) => !prev)} - value={localAnalytics} - /> -
-
- -
-
- -
-
-
-
- ) - } - - return ( - <> - {!isDesktop && !showIntercom && !isSafeAppView && ( - dispatch.current(openCookieBanner({ cookieBannerOpen: true, intercomAlertDisplayed: true }))} - /> - )} - {!isDesktop && showBanner?.cookieBannerOpen && ( - - )} - - ) -} - -export default CookiesBanner diff --git a/src/components/DecodeTxs/index.tsx b/src/components/DecodeTxs/index.tsx deleted file mode 100644 index deb5f4747e..0000000000 --- a/src/components/DecodeTxs/index.tsx +++ /dev/null @@ -1,202 +0,0 @@ -import React, { ReactElement } from 'react' -import styled from 'styled-components' -import { Transaction } from '@gnosis.pm/safe-apps-sdk-v1' -import { Text, EthHashInfo, CopyToClipboardBtn, IconText, FixedIcon } from '@gnosis.pm/safe-react-components' -import get from 'lodash.get' - -import { web3ReadOnly as web3 } from 'src/logic/wallets/getWeb3' -import { getExplorerInfo, getNetworkInfo } from 'src/config' -import { DecodedData, DecodedDataBasicParameter, DecodedDataParameterValue } from 'src/types/transactions/decode.d' -import { DecodedTxDetail } from 'src/routes/safe/components/Apps/components/ConfirmTxModal' - -const FlexWrapper = styled.div<{ margin: number }>` - display: flex; - align-items: center; - - > :nth-child(2) { - margin-left: ${({ margin }) => margin}px; - } -` - -const BasicTxInfoWrapper = styled.div` - margin-bottom: 15px; - - > :nth-child(2) { - margin-bottom: 15px; - } -` - -const TxList = styled.div` - width: 100%; - max-height: 260px; - overflow-y: auto; - border-top: 2px solid ${({ theme }) => theme.colors.separator}; -` - -const TxListItem = styled.div` - display: flex; - justify-content: space-between; - - padding: 0 24px; - height: 50px; - border-bottom: 2px solid ${({ theme }) => theme.colors.separator}; - - :hover { - cursor: pointer; - } -` -const ElementWrapper = styled.div` - margin-bottom: 15px; -` - -export const BasicTxInfo = ({ - txRecipient, - txData, - txValue, -}: { - txRecipient: string - txData: string - txValue: string -}): ReactElement => { - const { nativeCoin } = getNetworkInfo() - - return ( - - {/* TO */} - <> - - {`Send ${txValue} ${nativeCoin.symbol} to:`} - - - - <> - {/* Data */} - - Data (hex encoded): - - - {txData ? web3.utils.hexToBytes(txData).length : 0} bytes - - - - - ) -} - -export const getParameterElement = (parameter: DecodedDataBasicParameter, index: number): ReactElement => { - let valueElement - - if (parameter.type === 'address') { - valueElement = ( - - ) - } - - if (parameter.type.startsWith('bytes')) { - valueElement = ( - - {web3.utils.hexToBytes(parameter.value).length} bytes - - - ) - } - - if (!valueElement) { - let value = parameter.value - if (parameter.type.endsWith('[]')) { - try { - value = JSON.stringify(parameter.value) - } catch (e) {} - } - valueElement = {value} - } - - return ( - - - {parameter.name} ({parameter.type}) - - {valueElement} - - ) -} - -const SingleTx = ({ - decodedData, - onTxItemClick, -}: { - decodedData: DecodedData | null - onTxItemClick: (decodedTxDetails: DecodedData) => void -}): ReactElement | null => { - if (!decodedData) { - return null - } - - return ( - - onTxItemClick(decodedData)}> - - - - {decodedData.method} - - - - - ) -} - -const MultiSendTx = ({ - decodedData, - onTxItemClick, -}: { - decodedData: DecodedData | null - onTxItemClick: (decodedTxDetails: DecodedDataParameterValue) => void -}): ReactElement | null => { - const txs: DecodedDataParameterValue[] | undefined = get(decodedData, 'parameters[0].valueDecoded') - - if (!txs) { - return null - } - - return ( - - {txs.map((tx, index) => ( - onTxItemClick(tx)}> - - - - {tx.dataDecoded && {tx.dataDecoded.method}} - - - - ))} - - ) -} - -type Props = { - txs: Transaction[] - decodedData: DecodedData | null - onTxItemClick: (decodedTxDetails: DecodedTxDetail) => void -} - -export const DecodeTxs = ({ txs, decodedData, onTxItemClick }: Props): ReactElement => { - return txs.length > 1 ? ( - - ) : ( - - ) -} diff --git a/src/components/SafeListSidebar/index.tsx b/src/components/SafeListSidebar/index.tsx index 9113230652..3c1cf41954 100644 --- a/src/components/SafeListSidebar/index.tsx +++ b/src/components/SafeListSidebar/index.tsx @@ -15,7 +15,6 @@ import Hairline from 'src/components/layout/Hairline' import Link from 'src/components/layout/Link' import Row from 'src/components/layout/Row' import { WELCOME_ADDRESS } from 'src/routes/routes' -import { useAnalytics, SAFE_NAVIGATION_EVENT } from 'src/utils/googleAnalytics' import { safeAddressFromUrl, defaultSafe as defaultSafeSelector } from 'src/logic/safe/store/selectors' @@ -44,7 +43,6 @@ export const SafeListSidebar = ({ children }: Props): ReactElement => { const safeAddress = useSelector(safeAddressFromUrl) const classes = useSidebarStyles() - const { trackEvent } = useAnalytics() const searchClasses = { input: classes.searchInput, @@ -54,9 +52,6 @@ export const SafeListSidebar = ({ children }: Props): ReactElement => { } const toggleSidebar = () => { - if (!isOpen) { - trackEvent({ category: SAFE_NAVIGATION_EVENT, action: 'Safe List Sidebar' }) - } setIsOpen((prevIsOpen) => !prevIsOpen) } diff --git a/src/config/networks/mainnet.ts b/src/config/networks/mainnet.ts index b867174131..d1320934e3 100644 --- a/src/config/networks/mainnet.ts +++ b/src/config/networks/mainnet.ts @@ -2,7 +2,9 @@ import HarmonyLogo from 'src/config/assets/token-one.png' import { EnvironmentSettings, HARMONY_NETWORK, NetworkConfig } from 'src/config/networks/network.d' const baseConfig: EnvironmentSettings = { + clientGatewayUrl: 'https://safe-client.t.hmny.io/v1', txServiceUrl: 'https://multisig.t.hmny.io/api/v1', + safeUrl: 'https://multisig.harmony.one', safeAppsUrl: 'https://multisig.harmony.one', gasPriceOracle: { url: 'https://ethgasstation.info/json/ethgasAPI.json', diff --git a/src/config/networks/testnet.ts b/src/config/networks/testnet.ts index 9238ebcf2a..7d137eabd3 100644 --- a/src/config/networks/testnet.ts +++ b/src/config/networks/testnet.ts @@ -2,7 +2,9 @@ import HarmonyLogo from 'src/config/assets/token-one.png' import { EnvironmentSettings, HARMONY_NETWORK, NetworkConfig } from 'src/config/networks/network.d' const baseConfig: EnvironmentSettings = { + clientGatewayUrl: 'https://safe-client.b.hmny.io/v1', txServiceUrl: 'https://multisig-staging.hmny.io/api/v1', + safeUrl: 'https://testnet.multisig.harmony.one', safeAppsUrl: 'https://testnet.multisig.harmony.one', gasPriceOracle: { url: 'https://ethgasstation.info/json/ethgasAPI.json', diff --git a/src/logic/addressBook/model/addressBook.ts b/src/logic/addressBook/model/addressBook.ts index d6ddcaeb2a..a136a550bf 100644 --- a/src/logic/addressBook/model/addressBook.ts +++ b/src/logic/addressBook/model/addressBook.ts @@ -1,4 +1,4 @@ -import { ETHEREUM_NETWORK } from 'src/config/networks/network.d' +import { HARMONY_NETWORK } from 'src/config/networks/network.d' import { getNetworkId } from 'src/config' export const ADDRESS_BOOK_DEFAULT_NAME = 'UNKNOWN' @@ -6,7 +6,7 @@ export const ADDRESS_BOOK_DEFAULT_NAME = 'UNKNOWN' export type AddressBookEntry = { address: string // the contact address name: string // human-readable name - chainId: ETHEREUM_NETWORK // see https://chainid.network + chainId: HARMONY_NETWORK // see https://chainid.network } const networkId = getNetworkId() diff --git a/src/logic/cookies/model/cookie.ts b/src/logic/cookies/model/cookie.ts deleted file mode 100644 index a119ac0d35..0000000000 --- a/src/logic/cookies/model/cookie.ts +++ /dev/null @@ -1 +0,0 @@ -export const COOKIES_KEY = 'COOKIES' diff --git a/src/logic/cookies/store/actions/openCookieBanner.ts b/src/logic/cookies/store/actions/openCookieBanner.ts deleted file mode 100644 index e3db9cb702..0000000000 --- a/src/logic/cookies/store/actions/openCookieBanner.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { createAction } from 'redux-actions' - -import { OpenCookieBannerPayload } from 'src/logic/cookies/store/reducer/cookies' - -export const OPEN_COOKIE_BANNER = 'OPEN_COOKIE_BANNER' - -export const openCookieBanner = createAction(OPEN_COOKIE_BANNER) diff --git a/src/logic/cookies/store/reducer/cookies.ts b/src/logic/cookies/store/reducer/cookies.ts deleted file mode 100644 index e8411153de..0000000000 --- a/src/logic/cookies/store/reducer/cookies.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Map } from 'immutable' -import { handleActions } from 'redux-actions' -import { OPEN_COOKIE_BANNER } from 'src/logic/cookies/store/actions/openCookieBanner' -import { AppReduxState } from 'src/store' - -export const COOKIES_REDUCER_ID = 'cookies' - -export type OpenCookieBannerPayload = { cookieBannerOpen: boolean; intercomAlertDisplayed?: boolean } - -export default handleActions( - { - [OPEN_COOKIE_BANNER]: (state, action) => { - const { intercomAlertDisplayed = false, cookieBannerOpen } = action.payload - return state.set('cookieBannerOpen', { intercomAlertDisplayed, cookieBannerOpen }) - }, - }, - Map(), -) diff --git a/src/logic/cookies/store/selectors/index.ts b/src/logic/cookies/store/selectors/index.ts deleted file mode 100644 index 9104be6934..0000000000 --- a/src/logic/cookies/store/selectors/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { COOKIES_REDUCER_ID } from 'src/logic/cookies/store/reducer/cookies' - -export const cookieBannerOpen = (state) => state[COOKIES_REDUCER_ID].get('cookieBannerOpen') diff --git a/src/logic/cookies/utils/index.ts b/src/logic/cookies/utils/index.ts deleted file mode 100644 index 3d894b517c..0000000000 --- a/src/logic/cookies/utils/index.ts +++ /dev/null @@ -1,33 +0,0 @@ -import Cookies from 'js-cookie' - -import { getNetworkName } from 'src/config' -import { Errors, logError } from 'src/logic/exceptions/CodedException' - -const PREFIX = `v1_${getNetworkName()}` - -export const loadFromCookie = async (key: string, withoutPrefix = false): Promise> => { - const prefix = withoutPrefix ? '' : `${PREFIX}__` - try { - const stringifiedValue = await Cookies.get(`${prefix}${key}`) - if (stringifiedValue === null || stringifiedValue === undefined) { - return undefined - } - - return JSON.parse(stringifiedValue) - } catch (err) { - logError(Errors._700, `cookie ${key} – ${err.message}`) - return undefined - } -} - -export const saveCookie = async (key: string, value: Record, expirationDays: number): Promise => { - try { - const stringifiedValue = JSON.stringify(value) - const expiration = expirationDays ? { expires: expirationDays } : undefined - await Cookies.set(`${PREFIX}__${key}`, stringifiedValue, expiration) - } catch (err) { - logError(Errors._701, `cookie ${key} – ${err.message}`) - } -} - -export const removeCookie = (key: string, path: string, domain: string): void => Cookies.remove(key, { path, domain }) diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 3a04fce160..1b872832d9 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -6,7 +6,6 @@ import { LOAD_ADDRESS, OPEN_ADDRESS, SAFELIST_ADDRESS, SAFE_PARAM_ADDRESS, WELCO import { Loader } from '@gnosis.pm/safe-react-components' import { defaultSafe as defaultSafeSelector } from 'src/logic/safe/store/selectors' -import { useAnalytics } from 'src/utils/googleAnalytics' import { DEFAULT_SAFE_INITIAL_STATE } from 'src/logic/safe/store/reducer/safe' import { LoadingContainer } from 'src/components/LoaderContainer' @@ -28,7 +27,6 @@ const Routes = (): React.ReactElement => { }) const defaultSafe = useSelector(defaultSafeSelector) - const { trackPage } = useAnalytics() useEffect(() => { if (isInitialLoad && location.pathname !== '/') { @@ -43,12 +41,10 @@ const Routes = (): React.ReactElement => { if (matchSafeWithAction.params?.safeAction) { safePage += `/${matchSafeWithAction.params?.safeAction}` } - trackPage(safePage) } else { const page = `${location.pathname}${location.search}` - trackPage(page) } - }, [location, matchSafeWithAction, trackPage]) + }, [location, matchSafeWithAction]) return ( diff --git a/src/routes/open/container/Open.tsx b/src/routes/open/container/Open.tsx index 94cd28cd11..9e452814d8 100644 --- a/src/routes/open/container/Open.tsx +++ b/src/routes/open/container/Open.tsx @@ -27,7 +27,6 @@ import { makeAddressBookEntry } from 'src/logic/addressBook/model/addressBook' import { addressBookSafeLoad } from 'src/logic/addressBook/store/actions' import { userAccountSelector } from 'src/logic/wallets/store/selectors' import { addOrUpdateSafe } from 'src/logic/safe/store/actions/addOrUpdateSafe' -import { useAnalytics } from 'src/utils/googleAnalytics' import { sleep } from 'src/utils/timer' const SAFE_PENDING_CREATION_STORAGE_KEY = 'SAFE_PENDING_CREATION_STORAGE_KEY' @@ -104,7 +103,6 @@ const Open = (): ReactElement => { const userAccount = useSelector(userAccountSelector) const dispatch = useDispatch() const location = useLocation() - const { trackEvent } = useAnalytics() useEffect(() => { // #122: Allow to migrate an old Multisig by passing the parameters to the URL. @@ -173,11 +171,6 @@ const Open = (): ReactElement => { const safeProps = await buildSafe(safeAddress) await dispatch(addOrUpdateSafe(safeProps)) - trackEvent({ - category: 'User', - action: 'Created a safe', - }) - // a default 5s wait before starting to request safe information await sleep(5000) diff --git a/src/routes/safe/components/AddressBook/index.tsx b/src/routes/safe/components/AddressBook/index.tsx index 5f96809f62..143c23ee3e 100644 --- a/src/routes/safe/components/AddressBook/index.tsx +++ b/src/routes/safe/components/AddressBook/index.tsx @@ -35,7 +35,7 @@ import SendModal from 'src/routes/safe/components/Balances/SendModal' import { safesAsList } from 'src/logic/safe/store/selectors' import { checksumAddress } from 'src/utils/checksumAddress' import { grantedSelector } from 'src/routes/safe/container/selector' -import { useAnalytics, SAFE_NAVIGATION_EVENT } from 'src/utils/googleAnalytics' + import ImportEntriesModal from './ImportEntriesModal' import { isValidAddress } from 'src/utils/isValidAddress' @@ -81,11 +81,6 @@ const AddressBookTable = (): ReactElement => { const [deleteEntryModalOpen, setDeleteEntryModalOpen] = useState(false) const [exportEntriesModalOpen, setExportEntriesModalOpen] = useState(false) const [sendFundsModalOpen, setSendFundsModalOpen] = useState(false) - const { trackEvent } = useAnalytics() - - useEffect(() => { - trackEvent({ category: SAFE_NAVIGATION_EVENT, action: 'AddressBook' }) - }, [trackEvent]) useEffect(() => { if (entryAddressToEditOrCreateNew) { diff --git a/src/routes/safe/components/Balances/Coins/index.tsx b/src/routes/safe/components/Balances/Coins/index.tsx index 2ca8f901c5..9d99fc0e7c 100644 --- a/src/routes/safe/components/Balances/Coins/index.tsx +++ b/src/routes/safe/components/Balances/Coins/index.tsx @@ -26,7 +26,6 @@ import { BalanceData, } from 'src/routes/safe/components/Balances/dataFetcher' import { extendedSafeTokensSelector, grantedSelector } from 'src/routes/safe/container/selector' -import { useAnalytics, SAFE_NAVIGATION_EVENT } from 'src/utils/googleAnalytics' import { makeStyles } from '@material-ui/core/styles' import { styles } from './styles' import { currentCurrencySelector } from 'src/logic/currencyValues/store/selectors' @@ -79,16 +78,11 @@ const Coins = (props: Props): React.ReactElement => { const selectedCurrency = useSelector(currentCurrencySelector) const safeTokens = useSelector(extendedSafeTokensSelector) const granted = useSelector(grantedSelector) - const { trackEvent } = useAnalytics() - useEffect(() => { - trackEvent({ category: SAFE_NAVIGATION_EVENT, action: 'Coins' }) - }, [trackEvent]) - - const filteredData: List = useMemo(() => getBalanceData(safeTokens, selectedCurrency), [ - safeTokens, - selectedCurrency, - ]) + const filteredData: List = useMemo( + () => getBalanceData(safeTokens, selectedCurrency), + [safeTokens, selectedCurrency], + ) return ( diff --git a/src/routes/safe/components/Balances/Collectibles/index.tsx b/src/routes/safe/components/Balances/Collectibles/index.tsx index 1d25c0e117..6f95d6e966 100644 --- a/src/routes/safe/components/Balances/Collectibles/index.tsx +++ b/src/routes/safe/components/Balances/Collectibles/index.tsx @@ -9,7 +9,6 @@ import Paragraph from 'src/components/layout/Paragraph' import { nftAssetsFromNftTokensSelector, orderedNFTAssets } from 'src/logic/collectibles/store/selectors' import SendModal from 'src/routes/safe/components/Balances/SendModal' import { fontColor, lg, screenSm, screenXs } from 'src/theme/variables' -import { useAnalytics, SAFE_NAVIGATION_EVENT } from 'src/utils/googleAnalytics' import { NFTToken } from 'src/logic/collectibles/sources/collectibles.d' const useStyles = makeStyles( @@ -78,7 +77,6 @@ const useStyles = makeStyles( ) const Collectibles = (): React.ReactElement => { - const { trackEvent } = useAnalytics() const classes = useStyles() const [selectedToken, setSelectedToken] = React.useState() const [sendNFTsModalOpen, setSendNFTsModalOpen] = React.useState(false) @@ -86,10 +84,6 @@ const Collectibles = (): React.ReactElement => { const nftTokens = useSelector(orderedNFTAssets) const nftAssetsFromNftTokens = useSelector(nftAssetsFromNftTokensSelector) - useEffect(() => { - trackEvent({ category: SAFE_NAVIGATION_EVENT, action: 'Collectibles' }) - }, [trackEvent]) - const handleItemSend = (nftToken: NFTToken) => { setSelectedToken(nftToken) setSendNFTsModalOpen(true) diff --git a/src/routes/safe/components/Settings/Advanced/index.tsx b/src/routes/safe/components/Settings/Advanced/index.tsx index 41284e6b84..bfa38c730b 100644 --- a/src/routes/safe/components/Settings/Advanced/index.tsx +++ b/src/routes/safe/components/Settings/Advanced/index.tsx @@ -9,7 +9,6 @@ import { ModulesTable } from './ModulesTable' import Block from 'src/components/layout/Block' import { currentSafe } from 'src/logic/safe/store/selectors' -import { useAnalytics, SAFE_NAVIGATION_EVENT } from 'src/utils/googleAnalytics' const InfoText = styled(Text)` margin-top: 16px; @@ -29,11 +28,6 @@ export const Advanced = (): React.ReactElement => { const classes = useStyles() const { nonce, modules } = useSelector(currentSafe) ?? {} const moduleData = modules ? getModuleData(modules) ?? null : null - const { trackEvent } = useAnalytics() - - useEffect(() => { - trackEvent({ category: SAFE_NAVIGATION_EVENT, action: 'Settings', label: 'Advanced' }) - }, [trackEvent]) return ( <> diff --git a/src/routes/safe/components/Settings/ManageOwners/index.tsx b/src/routes/safe/components/Settings/ManageOwners/index.tsx index b75d90886c..0c1d617a9e 100644 --- a/src/routes/safe/components/Settings/ManageOwners/index.tsx +++ b/src/routes/safe/components/Settings/ManageOwners/index.tsx @@ -23,7 +23,6 @@ import Hairline from 'src/components/layout/Hairline' import Heading from 'src/components/layout/Heading' import Paragraph from 'src/components/layout/Paragraph/index' import Row from 'src/components/layout/Row' -import { useAnalytics, SAFE_NAVIGATION_EVENT } from 'src/utils/googleAnalytics' import { AddressBookState } from 'src/logic/addressBook/model/addressBook' export const RENAME_OWNER_BTN_TEST_ID = 'rename-owner-btn' @@ -38,7 +37,6 @@ type Props = { } const ManageOwners = ({ granted, owners }: Props): ReactElement => { - const { trackEvent } = useAnalytics() const classes = useStyles() const [selectedOwner, setSelectedOwner] = useState() @@ -67,10 +65,6 @@ const ManageOwners = ({ granted, owners }: Props): ReactElement => { setSelectedOwner(undefined) } - useEffect(() => { - trackEvent({ category: SAFE_NAVIGATION_EVENT, action: 'Settings', label: 'Owners' }) - }, [trackEvent]) - const columns = generateColumns() const autoColumns = columns.filter((c) => !c.custom) const ownerData = getOwnerData(owners) diff --git a/src/routes/safe/components/Settings/SafeDetails/index.tsx b/src/routes/safe/components/Settings/SafeDetails/index.tsx index c5e4b25aa2..37bb8cdeea 100644 --- a/src/routes/safe/components/Settings/SafeDetails/index.tsx +++ b/src/routes/safe/components/Settings/SafeDetails/index.tsx @@ -31,7 +31,6 @@ import { currentSafeWithNames, latestMasterContractVersion as latestMasterContractVersionSelector, } from 'src/logic/safe/store/selectors' -import { useAnalytics, SAFE_NAVIGATION_EVENT } from 'src/utils/googleAnalytics' import { fetchMasterCopies, MasterCopy, MasterCopyDeployer } from 'src/logic/contracts/api/masterCopies' import { getMasterCopyAddressFromProxyAddress } from 'src/logic/contracts/safeContracts' @@ -61,7 +60,6 @@ const SafeDetails = (): ReactElement => { currentVersion: safeCurrentVersion, } = useSelector(currentSafeWithNames) const dispatch = useDispatch() - const { trackEvent } = useAnalytics() const [isModalOpen, setModalOpen] = useState(false) const [safeInfo, setSafeInfo] = useState() @@ -101,10 +99,6 @@ const SafeDetails = (): ReactElement => { : '' } - useEffect(() => { - trackEvent({ category: SAFE_NAVIGATION_EVENT, action: 'Settings', label: 'Details' }) - }, [trackEvent]) - useEffect(() => { const getMasterCopyInfo = async () => { const masterCopies = await fetchMasterCopies() diff --git a/src/routes/safe/components/Settings/ThresholdSettings/index.tsx b/src/routes/safe/components/Settings/ThresholdSettings/index.tsx index f487e4c9db..3c9a68fd9e 100644 --- a/src/routes/safe/components/Settings/ThresholdSettings/index.tsx +++ b/src/routes/safe/components/Settings/ThresholdSettings/index.tsx @@ -11,7 +11,6 @@ import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' import { grantedSelector } from 'src/routes/safe/container/selector' import { currentSafe } from 'src/logic/safe/store/selectors' -import { useAnalytics, SAFE_NAVIGATION_EVENT } from 'src/utils/googleAnalytics' import { ChangeThresholdModal } from './ChangeThreshold' import { styles } from './style' @@ -28,12 +27,6 @@ const ThresholdSettings = (): React.ReactElement => { setModalOpen((prevOpen) => !prevOpen) } - const { trackEvent } = useAnalytics() - - useEffect(() => { - trackEvent({ category: SAFE_NAVIGATION_EVENT, action: 'Settings', label: 'Owners' }) - }, [trackEvent]) - return ( <> diff --git a/src/store/index.ts b/src/store/index.ts index 390285732f..53313bdf2a 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -13,7 +13,6 @@ import { nftAssetReducer, nftTokensReducer, } from 'src/logic/collectibles/store/reducer/collectibles' -import cookies, { COOKIES_REDUCER_ID } from 'src/logic/cookies/store/reducer/cookies' import currentSession, { CURRENT_SESSION_REDUCER_ID, CurrentSessionState, @@ -67,7 +66,6 @@ const reducers = combineReducers({ [GATEWAY_TRANSACTIONS_ID]: gatewayTransactions, [NOTIFICATIONS_REDUCER_ID]: notifications, [CURRENCY_VALUES_KEY]: currencyValues, - [COOKIES_REDUCER_ID]: cookies, [ADDRESS_BOOK_REDUCER_ID]: addressBook, [CURRENT_SESSION_REDUCER_ID]: currentSession, }) @@ -81,7 +79,6 @@ export type AppReduxState = CombinedState<{ [GATEWAY_TRANSACTIONS_ID]: Record [NOTIFICATIONS_REDUCER_ID]: Map [CURRENCY_VALUES_KEY]: CurrencyValuesState - [COOKIES_REDUCER_ID]: Map [ADDRESS_BOOK_REDUCER_ID]: AddressBookState [CURRENT_SESSION_REDUCER_ID]: CurrentSessionState router: RouterState From 0b8cfb0d8f0b8d6e071efcbb795b5e2ceb8a37a4 Mon Sep 17 00:00:00 2001 From: unlocker Date: Mon, 2 Aug 2021 08:02:38 -0700 Subject: [PATCH 4/4] + --- README.md | 118 ++++++++++-------- .../AppLayout/Header/components/Layout.tsx | 2 - 2 files changed, 66 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index 3949e4e0e9..52ecfc14d9 100644 --- a/README.md +++ b/README.md @@ -1,115 +1,129 @@ -# Gnosis Safe +# Harmony Safe Multisig -The most trusted platform to store digital assets on Ethereum. More info at [gnosis-safe.io](https://gnosis-safe.io/) - -This repository contains the code for the frontend code hosted at [https://gnosis-safe.io/app/] - -Besides the Ethereum Mainnet, the following networks are supported: - -- [Rinkeby Testnet](https://rinkeby.gnosis-safe.io/app/) -- [xDai](https://xdai.gnosis-safe.io/app/) -- [Energy Web Chain](https://ewc.gnosis-safe.io/app/) -- [Volta Testnet](https://volta.gnosis-safe.io/app/) - -For technical information please refer to the [Gnosis Developer Portal](https://docs.gnosis.io/safe/). - -For support requests, please open up a [bug issue](https://github.com/gnosis/safe-react/issues/new?template=bug-report.md) or reach out via [Discord](https://discordapp.com/invite/FPMRAwK). +The most trusted platform to store digital assets on Harmony ## Getting Started -These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See [Deployment](#deployment) for notes on how to deploy the project on a live system. +These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system. ### Prerequisites -We use [yarn](https://yarnpkg.com) in our infrastructure, so we decided to go with yarn in the README. -Please install yarn globally if you haven't already. +What things you need to install the software and how to install them -### Environment variables -The app grabs environment variables from the `.env` file. Copy our template to your own local file: ``` -cp .env.example .env +yarn add truffle // recommended usage of -g flag +yarn add ganache-cli // recommended usage of -g flag +yarn add flow-type // recommended usage of -g flag ``` -To execute transactions, you'll need to create an [Infura](https://infura.io) project and set the project ID in the `.env` you've just created: -``` -REACT_APP_INFURA_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -``` -Once done, you'll need to restart the app if it's already running. +We use [yarn](https://yarnpkg.com) in our infrastacture, so we decided to go with yarn in the README ### Installing and running +A step by step series of examples that tell you have to get a development env running + Install dependencies for the project: + ``` yarn install ``` -To use the Rinkeby services: +For using the Testnet services: + ``` yarn start ``` -If you prefer using the Mainnet ones: +If you prefer using Mainnet ones: + ``` yarn start-mainnet ``` ### Building -For Rinkeby: + +For Testnet: + ``` yarn build ``` For Mainnet: + ``` yarn build-mainnet ``` ## Running the tests -To run the tests: +1. Run `transaction-history-service` + ``` -yarn test +git clone https://github.com/harmony-one/multisig-react.git +cd safe-transaction-service +git checkout develop +docker-compose build +# it comes enabled by default in docker-compose +sudo service postgresql stop +docker-compose up -d ``` -### Lint +Check that the service is running at https://localhost:8000 -ESLint will be run automatically before you commit. To run it manually: +2. Migrate Safe Contracts: ``` -yarn lint:fix +git clone https://github.com/harmony-one/multisig-contracts.git +cd safe-contracts +yarn +npx truffle migrate ``` -## Deployment +3. Migrate Token Contracts for the tests: + Inside `safe-react` directory + +``` +npx truffle migrate +``` -### Dev & staging -The code is deployed to a testing website automatically on each push via a GitHub Action. -The GitHub Action will create a new subdomain and post the link as a comment in the PR. +4. Run the tests: -When pushing to the `master` branch, the code will be automatically deployed to [staging](https://safe-team-rinkeby.staging.gnosisdev.com/). +``` +yarn test +``` -### Production -Deployment to production is done manually. Please see the [release procedure](docs/release-procedure.md) notes for details. +### Break down into end to end tests -## Configuring the app for running on different networks +Explain what these tests test and why -[Please check the network configuration documentation](./docs/networks.md) +``` +Give an example +``` -## Built With +### And coding style tests -* [React](https://reactjs.org/) - A JS library for building user interfaces -* [Material UI 4.X](https://material-ui.com/) - React components that implement Google's Material Design -* [redux, immutable, reselect, final-form](https://redux.js.org/) - React ecosystem libraries +Explain what these tests test and why -![app diagram](https://user-images.githubusercontent.com/381895/121764528-e5e2e900-cb44-11eb-8643-483d41040349.png) +``` +Give an example +``` -## Contributing +## Deployment -Please read [CONTRIBUTING.md](https://gist.github.com/PurpleBooth/b24679402957c63ec426) for details on our code of conduct, and the process for submitting pull requests to us. +Add additional notes about how to deploy this on a live system + +## Configuring the app for running on different networks + +[Please check the network configuration documentation](./docs/networks.md) -## Versioning +## Contributing -We use [SemVer](https://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/gnosis/gnosis-team-safe/tags). +Please read [CONTRIBUTING.md](https://gist.github.com/PurpleBooth/b24679402957c63ec426) for details on our code of conduct, and the process for submitting pull requests to us. ## License This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details + +## Acknowledgments + +- Thanks for Gnosis Team for providing the Safe contracts. diff --git a/src/components/AppLayout/Header/components/Layout.tsx b/src/components/AppLayout/Header/components/Layout.tsx index 0f2587963a..7383e80418 100644 --- a/src/components/AppLayout/Header/components/Layout.tsx +++ b/src/components/AppLayout/Header/components/Layout.tsx @@ -35,10 +35,8 @@ const styles = () => ({ zIndex: 1301, }, logo: { - flexBasis: '140px', flexShrink: '0', flexGrow: '0', - maxWidth: '55px', padding: sm, marginTop: '4px', [`@media (min-width: ${screenSm}px)`]: {