import { CeloContract , CeloTokenContract } from '@celo/contractkit' ; import React , { ReactNode , useCallback , useEffect , useMemo , useReducer , } from 'react' ; import { CONNECTOR_TYPES , UnauthenticatedConnector } from './connectors' ; import { DEFAULT_NETWORKS , Mainnet } from './constants' ; import { Actions , ActionsMap , contractKitReducer , ReducerState , } from './contract-kit-reducer' ; import { ActionModal , ActionModalProps , ConnectModal , ConnectModalProps , } from './modals' ; import { Dapp , Network } from './types' ; import { ContractKitMethods , useContractKitMethods , } from './use-contract-kit-methods' ; import { loadPreviousConfig } from './utils/helpers' ; import { useIsMounted } from './utils/useIsMounted' ; export type Dispatcher = < Type extends Actions [ 'type' ] , Payload extends ActionsMap [ Type ] > ( type : Type , ... payload : Payload extends undefined ? [ undefined ? ] : [ Payload ] ) => void ; type ContractKitContextInterface = readonly [ ReducerState , Dispatcher , ContractKitMethods ] ; const initialState = { connector : new UnauthenticatedConnector ( Mainnet ) , connectorInitError : null , dapp : { name : 'Celo dApp' , description : 'Celo dApp' , url : 'https://celo.org' , icon : 'https://celo.org/favicon.ico' , } , network : Mainnet , networks : DEFAULT_NETWORKS , pendingActionCount : 0 , address : null , connectionCallback : null , feeCurrency : CeloContract . GoldToken , } ; export const [ useContractKitContext , ContextProvider ] = createContractKitContext ( ) ; function createContractKitContext ( ) { const contractKitContext = React . createContext < ContractKitContextInterface | undefined > ( undefined ) ; const useCtx = ( ) => { const c = React . useContext ( contractKitContext ) ; if ( ! c ) throw new Error ( 'Components using the use-contractkit hook must be a child of a ContractKitProvider' ) ; return c ; } ; return [ useCtx , contractKitContext . Provider ] as const ; } export const ContractKitProvider = ( { children , connectModal , actionModal , dapp , network = Mainnet , networks = DEFAULT_NETWORKS , feeCurrency = CeloContract . GoldToken , } ) => { const isMountedRef = useIsMounted ( ) ; const previousConfig = useMemo ( ( ) => loadPreviousConfig ( network ) , [ network ] ) ; const [ state , _dispatch ] = useReducer ( contractKitReducer , { ... initialState , ... previousConfig , network : previousConfig . network || network , networks , feeCurrency , dapp : { ... dapp , icon : dapp . icon ?? `${ dapp . url }/favicon.ico` , } , } ) ; const dispatch = useCallback ( ( type , ... payload ) => { if ( isMountedRef . current ) { _dispatch ( { type , payload : payload [ 0 ] } as Actions ) ; } } , [ isMountedRef ] ) ; const methods = useContractKitMethods ( state , dispatch ) ; useEffect ( ( ) => { if ( CONNECTOR_TYPES [ state . connector . type ] !== UnauthenticatedConnector ) { methods . initConnector ( state . connector ) . catch ( ( ) => { dispatch ( 'destroy' ) ; } ) ; } } , [ ] ) ; return ( < ContextProvider value = { [ state , dispatch , methods ] } > < ConnectModal { ... connectModal } / > < ActionModal { ... actionModal } / > { children } < /ContextProvider>); } ; interface ContractKitProviderProps { children : ReactNode ; dapp : Dapp ; network ? : Network ; networks ? : Network [ ] ; feeCurrency ? : CeloTokenContract ; connectModal ? : ConnectModalProps ; actionModal ? : { reactModalProps ? : Partial < ReactModal . Props > ; render ? : ( props : ActionModalProps ) => ReactNode ; } ; }