Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate getChains and setChains #5

Merged
merged 6 commits into from
Apr 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 6 additions & 31 deletions pages/[safeAddress]/balances.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,14 @@
import {useEffect} from "react";
import Head from "next/head";
import type {NextPage} from "next";
import type {SafeInfo} from "@gnosis.pm/safe-react-gateway-sdk";

import {useAppDispatch, useAppSelector} from "store";
import {selectSafeInfo, setSafeInfo} from "store/safeInfoSlice";
import {initSafeInfoService} from "services/safeInfoService";
import {selectSafeInfo} from "store/safeInfoSlice";
import SafeHeader from "components/common/SafeHeader";
import useSafeAddress from "services/useSafeAddress";
import { useAppSelector } from "store";

const Home: NextPage = () => {
const Balances: NextPage = () => {
const { address, chainId } = useSafeAddress()
const dispatch = useAppDispatch()

const safeInfo = useAppSelector(selectSafeInfo);

useEffect(() => {
if (!address || !chainId) return

const {onSuccess, onError, unsubscribe} = initSafeInfoService(chainId, address)

const handleSuccess = (data: SafeInfo) => {
dispatch(setSafeInfo(data))
}
const handleError = (error: Error) => {
console.error("Error loading Safe info", error)
}

onSuccess(handleSuccess)
onError(handleError)

return () => {
unsubscribe()
}
}, [dispatch, address, chainId])
const safeInfo = useAppSelector(selectSafeInfo)

return (
<div>
Expand All @@ -45,10 +20,10 @@ const Home: NextPage = () => {

<SafeHeader />

<main>Hello Balances of {address}</main>
<main>Hello Balances of {address} on chainId {chainId}</main>
<pre>{JSON.stringify(safeInfo, null, 2)}</pre>
</div>
);
};

export default Home;
export default Balances;
20 changes: 16 additions & 4 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
import "../styles/globals.css";
import { ReactElement } from "react";
import type { AppProps } from "next/app";
import { Provider } from "react-redux";
import { store } from "../store";
import useChains from "services/useChains";
import useSafeInfo from "services/useSafeInfo";
import "../styles/globals.css";

const Consumer = ({ children }: { children: ReactElement }): ReactElement => {
useChains();
useSafeInfo();

return children
}

function MyApp({ Component, pageProps }: AppProps) {
function SafeWebCore({ Component, pageProps }: AppProps) {
return (
<Provider store={store}>
<Component {...pageProps} />
<Consumer>
<Component {...pageProps} />
</Consumer>
</Provider>
);
}

export default MyApp;
export default SafeWebCore;
17 changes: 8 additions & 9 deletions pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { NextPage } from 'next'
import Head from 'next/head'
import styles from '../styles/Home.module.css'
import type { NextPage } from "next";
import Head from "next/head";

import styles from "../styles/Home.module.css";

const Home: NextPage = () => {
return (
Expand All @@ -11,11 +12,9 @@ const Home: NextPage = () => {
<link rel="icon" href="/favicon.ico" />
</Head>

<main>
Hello web-core
</main>
<main>Hello web-core</main>
</div>
)
}
);
};

export default Home
export default Home;
3 changes: 1 addition & 2 deletions services/safeInfoService.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import EventEmitter from "events";
import {getSafeInfo, SafeInfo} from '@gnosis.pm/safe-react-gateway-sdk'

import {GATEWAY_URL, POLLING_INTERVAL} from "config/constants";

export enum SAFE_INFO_EVENTS {
Expand Down Expand Up @@ -48,4 +47,4 @@ export const initSafeInfoService = (chainId: string, address: string): SafeInfoD
onError,
unsubscribe
}
}
}
40 changes: 40 additions & 0 deletions services/useAsync.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { useEffect, useState } from 'react'

type AsyncResult<T> = [
result: T | undefined,
error: Error | undefined,
loading: boolean,
]

const useAsync = <T>(asyncCall: () => Promise<T>): AsyncResult<T> => {
const [result, setResult] = useState<T>()
const [error, setError] = useState<Error>()
const [loading, setLoading] = useState<boolean>(true)

useEffect(() => {
let isCurrent = true

setResult(undefined)
setError(undefined)
setLoading(true)

asyncCall()
.then((val: T) => {
isCurrent && setResult(val)
})
.catch((err) => {
isCurrent && setError(err)
})
.finally(() => {
isCurrent && setLoading(false)
})

return () => {
isCurrent = false
}
}, [asyncCall])

return [ result, error, loading ]
}

export default useAsync
28 changes: 28 additions & 0 deletions services/useChains.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {
ChainInfo,
getChainsConfig,
type ChainListResponse,
} from "@gnosis.pm/safe-react-gateway-sdk";
import { GATEWAY_URL } from "config/constants";
import { useEffect } from "react";
import { useAppDispatch } from "store";
import { setChains } from "store/chainsSlice";
import useAsync from "./useAsync";

const getChainConfigs = (): Promise<ChainListResponse> => {
return getChainsConfig(GATEWAY_URL);
}

const useChains = (): { chains: ChainInfo[], error?: Error, loading: boolean } => {
const dispatch = useAppDispatch()
const [ data, error, loading ] = useAsync<ChainListResponse>(getChainConfigs)
const chains = data?.results || []

useEffect(() => {
dispatch(setChains(chains))
}, [chains, dispatch])

return { chains, error, loading }
}

export default useChains
34 changes: 34 additions & 0 deletions services/useSafeInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {useEffect} from "react";
import type {SafeInfo} from "@gnosis.pm/safe-react-gateway-sdk";
import {useAppDispatch} from "store";
import {setSafeInfo} from "store/safeInfoSlice";
import {initSafeInfoService} from "services/safeInfoService";
import useSafeAddress from "./useSafeAddress";

const useSafeInfo = (): void => {
const { address, chainId } = useSafeAddress()
const dispatch = useAppDispatch()

useEffect(() => {
if (!address || !chainId) return

const {onSuccess, onError, unsubscribe} = initSafeInfoService(chainId, address)

const handleSuccess = (data: SafeInfo) => {
dispatch(setSafeInfo(data))
}

const handleError = (error: Error) => {
console.error("Error loading Safe info", error)
}

onSuccess(handleSuccess)
onError(handleError)

return () => {
unsubscribe()
}
}, [dispatch, address, chainId])
};

export default useSafeInfo;
38 changes: 38 additions & 0 deletions store/chainsSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { type ChainInfo } from "@gnosis.pm/safe-react-gateway-sdk";
import { createSelector, createSlice, type PayloadAction } from "@reduxjs/toolkit";
import type { RootState } from ".";

type ChainsState = {
chains: ChainInfo[]
}

const initialState: ChainsState = {
chains: [],
};

export const chainsSlice = createSlice({
name: "chains",
initialState,
reducers: {
setChains: (_: RootState, action: PayloadAction<ChainsState>): ChainsState => {
return action.payload;
},
}
});

export const { setChains } = chainsSlice.actions;

export const selectChains = (state: RootState): ChainsState => {
return state[chainsSlice.name].chains;
};

export const selectChainById = createSelector(
[
selectChains,
(_: RootState, chainId: string) => chainId,
],

(chains: ChainInfo[], chainId: string): ChainInfo | undefined => {
return chains.find((item) => item.chainId === chainId);
}
);
12 changes: 9 additions & 3 deletions store/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import {
configureStore,
ThunkAction,
Action,
combineReducers,
type ThunkAction,
type Action,
} from "@reduxjs/toolkit";
import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
import {
useDispatch,
useSelector,
type TypedUseSelectorHook,
} from "react-redux";
import { chainsSlice } from "./chainsSlice";
import { safeInfoSlice } from "./safeInfoSlice";

const rootReducer = combineReducers({
[chainsSlice.name]: chainsSlice.reducer,
[safeInfoSlice.name]: safeInfoSlice.reducer,
});

Expand Down