From 0235530e55e269d40fed9ba1f2b6b168cdd7a1c4 Mon Sep 17 00:00:00 2001 From: Daniel Somoza Date: Mon, 20 Dec 2021 12:10:59 +0100 Subject: [PATCH 1/3] Added safe apps endpoint from gateway --- package.json | 2 +- src/logic/config/utils/index.ts | 21 -------- src/logic/safe/api/fetchSafeApps.ts | 8 +++ .../Apps/components/AppCard/index.stories.tsx | 1 + .../Apps/components/AppsList.test.tsx | 52 ++++++++++--------- .../Apps/hooks/appList/useRemoteSafeApps.ts | 2 +- src/routes/safe/components/Apps/types.ts | 7 +-- src/routes/safe/components/Apps/utils.ts | 1 + src/utils/constants.ts | 4 -- yarn.lock | 10 ++-- 10 files changed, 47 insertions(+), 61 deletions(-) create mode 100644 src/logic/safe/api/fetchSafeApps.ts diff --git a/package.json b/package.json index d0d6262bab..074172c651 100644 --- a/package.json +++ b/package.json @@ -170,7 +170,7 @@ "@gnosis.pm/safe-core-sdk": "^1.1.1", "@gnosis.pm/safe-deployments": "^1.5.0", "@gnosis.pm/safe-react-components": "^0.9.0", - "@gnosis.pm/safe-react-gateway-sdk": "^2.5.8", + "@gnosis.pm/safe-react-gateway-sdk": "^2.6.0", "@ledgerhq/hw-transport-node-hid-singleton": "6.3.0", "@material-ui/core": "^4.12.3", "@material-ui/icons": "^4.11.0", diff --git a/src/logic/config/utils/index.ts b/src/logic/config/utils/index.ts index 6671b4c5eb..869c5fde2d 100644 --- a/src/logic/config/utils/index.ts +++ b/src/logic/config/utils/index.ts @@ -1,29 +1,8 @@ -import axios from 'axios' import { _getChainId, _setChainId } from 'src/config' import { ChainId } from 'src/config/chain.d' import { store } from 'src/store' -import { CONFIG_SERVICE_URL } from 'src/utils/constants' import { setChainIdAction } from 'src/logic/config/store/actions' -export type RemoteAppData = { - id: number - url: string - name: string - iconUrl: string - description: string - chainIds: number[] -} - -const enum Endpoints { - SAFE_APPS = '/safe-apps/', -} - -// TODO: Migrate to GATEWAY_URL when CGW exposes it -export const fetchSafeAppsList = async (): Promise => { - const { data } = await axios.get(`${CONFIG_SERVICE_URL}${Endpoints.SAFE_APPS}?chainId=${_getChainId()}`) - return data -} - export const setChainId = (newChainId: ChainId) => { _setChainId(newChainId) store.dispatch(setChainIdAction(newChainId)) diff --git a/src/logic/safe/api/fetchSafeApps.ts b/src/logic/safe/api/fetchSafeApps.ts new file mode 100644 index 0000000000..52dd02bedb --- /dev/null +++ b/src/logic/safe/api/fetchSafeApps.ts @@ -0,0 +1,8 @@ +import { getSafeApps, SafeAppData } from '@gnosis.pm/safe-react-gateway-sdk' + +import { _getChainId } from 'src/config' +import { GATEWAY_URL } from 'src/utils/constants' + +export const fetchSafeAppsList = async (): Promise => { + return getSafeApps(GATEWAY_URL, _getChainId()) +} diff --git a/src/routes/safe/components/Apps/components/AppCard/index.stories.tsx b/src/routes/safe/components/Apps/components/AppCard/index.stories.tsx index a4d49f5bc2..752ffbe295 100644 --- a/src/routes/safe/components/Apps/components/AppCard/index.stories.tsx +++ b/src/routes/safe/components/Apps/components/AppCard/index.stories.tsx @@ -21,6 +21,7 @@ export const LoadedApp = (): React.ReactElement => ( iconUrl: 'https://cryptologos.cc/logos/versions/gnosis-gno-gno-logo-circle.svg?v=007', description: 'Gnosis safe app', fetchStatus: FETCH_STATUS.SUCCESS, + chainIds: ['4'], }} /> ) diff --git a/src/routes/safe/components/Apps/components/AppsList.test.tsx b/src/routes/safe/components/Apps/components/AppsList.test.tsx index dea8b77964..7ae68ef21d 100644 --- a/src/routes/safe/components/Apps/components/AppsList.test.tsx +++ b/src/routes/safe/components/Apps/components/AppsList.test.tsx @@ -1,6 +1,8 @@ +// import * as gateway from '@gnosis.pm/safe-react-gateway-sdk' + import AppsList, { PINNED_APPS_LIST_TEST_ID, ALL_APPS_LIST_TEST_ID } from './AppsList' import { render, screen, fireEvent, within, act, waitFor } from 'src/utils/test-utils' -import * as configServiceApi from 'src/logic/config/utils' + import * as appUtils from 'src/routes/safe/components/Apps/utils' import { FETCH_STATUS } from 'src/utils/requests' import { loadFromStorage, saveToStorage } from 'src/utils/storage' @@ -16,23 +18,9 @@ jest.mock('src/routes/routes', () => { const spyTrackEventGA = jest.fn() -beforeEach(async () => { - // Includes an id that doesn't exist in the remote apps to check that there's no error - await saveToStorage(appUtils.PINNED_SAFE_APP_IDS, ['14', '24', '228']) - - // populate custom app - await saveToStorage(appUtils.APPS_STORAGE_KEY, [ - { - url: 'https://apps.gnosis-safe.io/drain-safe', - }, - ]) - - jest.spyOn(googleAnalytics, 'useAnalytics').mockImplementation(() => ({ - trackPage: jest.fn(), - trackEvent: spyTrackEventGA, - })) - - jest.spyOn(configServiceApi, 'fetchSafeAppsList').mockImplementation(() => +jest.mock('@gnosis.pm/safe-react-gateway-sdk', () => ({ + __esModule: true, + getSafeApps: () => Promise.resolve([ { id: 13, @@ -42,7 +30,7 @@ beforeEach(async () => { error: false, description: 'Money markets on the Ethereum blockchain', fetchStatus: 'SUCCESS', - chainIds: [1, 4], + chainIds: ['1', '4'], provider: null, }, { @@ -53,7 +41,7 @@ beforeEach(async () => { description: 'Decentralised naming for wallets, websites, & more.', fetchStatus: 'SUCCESS', - chainIds: [1, 4], + chainIds: ['1', '4'], provider: null, }, { @@ -63,7 +51,7 @@ beforeEach(async () => { iconUrl: 'https://cloudflare-ipfs.com/ipfs/QmXLxxczMH4MBEYDeeN9zoiHDzVkeBmB5rBjA3UniPEFcA/Synthetix.png', description: 'Trade synthetic assets on Ethereum', fetchStatus: 'SUCCESS', - chainIds: [1, 4], + chainIds: ['1', '4'], provider: null, }, { @@ -73,11 +61,27 @@ beforeEach(async () => { iconUrl: 'https://cloudflare-ipfs.com/ipfs/QmdVaZxDov4bVARScTLErQSRQoxgqtBad8anWuw3YPQHCs/tx-builder.png', description: 'A Safe app to compose custom transactions', fetchStatus: 'SUCCESS', - chainIds: [1, 4, 56, 100, 137, 246, 73799], + chainIds: ['1', '4', '56', '100', '137', '246', '73799'], provider: null, }, ]), - ) +})) + +beforeEach(async () => { + // Includes an id that doesn't exist in the remote apps to check that there's no error + await saveToStorage(appUtils.PINNED_SAFE_APP_IDS, ['14', '24', '228']) + + // populate custom app + await saveToStorage(appUtils.APPS_STORAGE_KEY, [ + { + url: 'https://apps.gnosis-safe.io/drain-safe', + }, + ]) + + jest.spyOn(googleAnalytics, 'useAnalytics').mockImplementation(() => ({ + trackPage: jest.fn(), + trackEvent: spyTrackEventGA, + })) jest.spyOn(appUtils, 'getAppInfoFromUrl').mockReturnValueOnce( Promise.resolve({ @@ -87,7 +91,7 @@ beforeEach(async () => { iconUrl: 'https://apps.gnosis-safe.io/drain-safe/logo.svg', error: false, description: 'Transfer all your assets in batch', - chainIds: [4], + chainIds: ['4'], provider: null, fetchStatus: FETCH_STATUS.SUCCESS, }), diff --git a/src/routes/safe/components/Apps/hooks/appList/useRemoteSafeApps.ts b/src/routes/safe/components/Apps/hooks/appList/useRemoteSafeApps.ts index 993d550829..fa596474a1 100644 --- a/src/routes/safe/components/Apps/hooks/appList/useRemoteSafeApps.ts +++ b/src/routes/safe/components/Apps/hooks/appList/useRemoteSafeApps.ts @@ -5,7 +5,7 @@ import enqueueSnackbar from 'src/logic/notifications/store/actions/enqueueSnackb import { NOTIFICATIONS } from 'src/logic/notifications' import { FETCH_STATUS } from 'src/utils/requests' import { SafeApp } from '../../types' -import { fetchSafeAppsList } from 'src/logic/config/utils' +import { fetchSafeAppsList } from 'src/logic/safe/api/fetchSafeApps' type ReturnType = { remoteSafeApps: SafeApp[] diff --git a/src/routes/safe/components/Apps/types.ts b/src/routes/safe/components/Apps/types.ts index e4e5c3ae4f..16c7de1fd6 100644 --- a/src/routes/safe/components/Apps/types.ts +++ b/src/routes/safe/components/Apps/types.ts @@ -1,12 +1,9 @@ +import { SafeAppData } from '@gnosis.pm/safe-react-gateway-sdk' import { FETCH_STATUS } from 'src/utils/requests' -export type SafeApp = { +export type SafeApp = Omit & { id: string - url: string - name: string - iconUrl: string disabled?: boolean - description: string fetchStatus: FETCH_STATUS custom?: boolean } diff --git a/src/routes/safe/components/Apps/utils.ts b/src/routes/safe/components/Apps/utils.ts index 725d582874..fa1f3faead 100644 --- a/src/routes/safe/components/Apps/utils.ts +++ b/src/routes/safe/components/Apps/utils.ts @@ -46,6 +46,7 @@ export const getEmptySafeApp = (url = ''): SafeApp => { iconUrl: appsIconSvg, description: '', fetchStatus: FETCH_STATUS.LOADING, + chainIds: [], } } diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 8cae022b40..b55608a692 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -29,10 +29,6 @@ export const COLLECTIBLES_SOURCE = process.env.REACT_APP_COLLECTIBLES_SOURCE || export const SAFE_POLLING_INTERVAL = process.env.NODE_ENV === 'test' ? 4500 : 15000 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 CONFIG_SERVICE_URL = - process.env.CONFIG_SERVICE_URL || IS_PRODUCTION - ? 'https://safe-config.gnosis.io/api/v1' - : 'https://safe-config.staging.gnosisdev.com/api/v1' export const GATEWAY_URL = IS_PRODUCTION || window.location.hash === '#prod' ? 'https://safe-client.gnosis.io/v1' diff --git a/yarn.lock b/yarn.lock index 593c98be3a..bd1f39d687 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2150,7 +2150,7 @@ "@gnosis.pm/safe-deployments" "^1.4.0" ethereumjs-util "^7.1.3" -"@gnosis.pm/safe-deployments@^1.5.0": +"@gnosis.pm/safe-deployments@^1.4.0", "@gnosis.pm/safe-deployments@^1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@gnosis.pm/safe-deployments/-/safe-deployments-1.5.0.tgz#5e01ccc2e2d78bf91ecb4453a64d1cac3a5ba2d6" integrity sha512-IDU7I+IQr1zUU94/uD8shDVI+/nUA1unQUg8jtbTG0YGcmm49Lu8G01rqtWt2mhLxZWzFsgbLWGnU+/BzUqk7g== @@ -2170,10 +2170,10 @@ dependencies: isomorphic-unfetch "^3.1.0" -"@gnosis.pm/safe-react-gateway-sdk@^2.5.8": - version "2.5.8" - resolved "https://registry.yarnpkg.com/@gnosis.pm/safe-react-gateway-sdk/-/safe-react-gateway-sdk-2.5.8.tgz#e43b1346829a127f5e87c3e45bfc0afb3d28773c" - integrity sha512-ZMVblmKe4YEGoznNzZxKr2coXS3ZIRpLX80ErlcAauv1YbJgdIGpRyloiGkOtwshwI3y5pRm0FI1QU8mrcUlwg== +"@gnosis.pm/safe-react-gateway-sdk@^2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@gnosis.pm/safe-react-gateway-sdk/-/safe-react-gateway-sdk-2.6.0.tgz#347122ad67aa4a38caa40758ebf35a8f9e98358c" + integrity sha512-mGse0EJ4e77sgf5gtTvaYIToLmjxdIQ6YlV0VgLHTXb3WLm1dQ5bTiynU4Nr4guc27qu45puDx4sqXBUmuMybQ== dependencies: isomorphic-unfetch "^3.1.0" From 679dc85f812aa722cd60e68686e075b80821d78c Mon Sep 17 00:00:00 2001 From: Daniel Somoza Date: Mon, 20 Dec 2021 12:15:50 +0100 Subject: [PATCH 2/3] Updated getAppInfoFromUrl provider key mock --- src/routes/safe/components/Apps/components/AppsList.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/safe/components/Apps/components/AppsList.test.tsx b/src/routes/safe/components/Apps/components/AppsList.test.tsx index 7ae68ef21d..85a003613c 100644 --- a/src/routes/safe/components/Apps/components/AppsList.test.tsx +++ b/src/routes/safe/components/Apps/components/AppsList.test.tsx @@ -92,7 +92,7 @@ beforeEach(async () => { error: false, description: 'Transfer all your assets in batch', chainIds: ['4'], - provider: null, + provider: undefined, fetchStatus: FETCH_STATUS.SUCCESS, }), ) From 42708ed23326ee2f3e2b056341d84c12944000c2 Mon Sep 17 00:00:00 2001 From: Daniel Somoza Date: Mon, 20 Dec 2021 16:07:15 +0100 Subject: [PATCH 3/3] removed no needed import in AppList unit tests --- src/routes/safe/components/Apps/components/AppsList.test.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/routes/safe/components/Apps/components/AppsList.test.tsx b/src/routes/safe/components/Apps/components/AppsList.test.tsx index 27ab912967..375d05afc6 100644 --- a/src/routes/safe/components/Apps/components/AppsList.test.tsx +++ b/src/routes/safe/components/Apps/components/AppsList.test.tsx @@ -1,5 +1,3 @@ -// import * as gateway from '@gnosis.pm/safe-react-gateway-sdk' - import AppsList, { PINNED_APPS_LIST_TEST_ID, ALL_APPS_LIST_TEST_ID } from './AppsList' import { render, screen, fireEvent, within, act, waitFor } from 'src/utils/test-utils'