import { JsonRpcSigner } from "ethers/providers" ; import { History } from "history" ; import { Action } from "redux" ; import { ThunkAction , ThunkDispatch } from "redux-thunk" ; import { RoutePath } from "../../types" ; import { buildRegistrationSignaturePayload , buildSignatureMessageForLogin , forMultisig , getIndexedCFBalances , getNodeAddress , getUserFromStoredToken , storeTokenFromUser } from "../../utils/counterfactual" ; import Hub , { ErrorDetail } from "../../utils/hub-api-client" ; import { ActionType , ApplicationState , StoreAction , User , UserState } from "../types" ; export const initialState = { user : { } , error : { } , status : "" } as UserState ; export const dispatchError = ( dispatch , error ) => { const { message , code , field } = ErrorDetail [ error . code ] || error ; dispatch ( { data : { error : { message , code , field } } , type : ActionType . UserError } ) ; } ; export enum UserAddTransition { CheckWallet = "USER_ADD_CHECK_WALLET" , CreatingAccount = "USER_ADD_CREATING_ACCOUNT" , DeployingContract = "USER_ADD_DEPLOYING_CONTRACT" } export const addUser = ( userData , signer , history ) : ThunkAction < void , ApplicationState , null , Action < ActionType | UserAddTransition > > => async ( dispatch ) => { try { userData . nodeAddress = await getNodeAddress ( ) ; const signableMessage = buildRegistrationSignaturePayload ( userData ) ; dispatch ( { type : UserAddTransition . CheckWallet } ) ; const signature = await signer . signMessage ( signableMessage ) ; dispatch ( { type : UserAddTransition . CreatingAccount } ) ; const user = await Hub . createAccount ( userData , signature ) ; await storeTokenFromUser ( user ) ; dispatch ( { type : UserAddTransition . DeployingContract } ) ; user . multisigAddress = await forMultisig ( ) ; dispatch ( { data : { user } , type : ActionType . UserAdd } ) ; history . push ( RoutePath . SetupDeposit ) ; } catch ( error ) { dispatchError ( dispatch , error ) ; } } ; export const loginUser = ( ethAddress , signer , history ) : ThunkAction < void , ApplicationState , null , Action < ActionType > > => async ( dispatch ) => { try { const signableMessage = buildSignatureMessageForLogin ( ethAddress ) ; const signature = await signer . signMessage ( signableMessage ) ; const user = await Hub . login ( ethAddress , signature ) ; await storeTokenFromUser ( user ) ; const tokenAddresses = await getIndexedCFBalances ( { multisigAddress : user . multisigAddress as string , nodeAddress : user . nodeAddress } ) ; dispatch ( { data : { tokenAddresses } , type : ActionType . WalletSetBalance } ) ; dispatch ( { data : { user } , type : ActionType . UserLogin } ) ; history . push ( RoutePath . Channels ) ; } catch ( error ) { dispatchError ( dispatch , error ) ; } } ; export const getUser = ( history ) : ThunkAction < void , ApplicationState , null , Action < ActionType > > => async ( dispatch ) => { try { const user = await getUserFromStoredToken ( ) ; if ( ! user || ! user . username ) { history . push ( RoutePath . Root ) ; return ; } const tokenAddresses = await getIndexedCFBalances ( { multisigAddress : user . multisigAddress as string , nodeAddress : user . nodeAddress } ) ; dispatch ( { data : { user } , type : ActionType . UserGet } ) ; dispatch ( { data : { tokenAddresses } , type : ActionType . WalletSetBalance } ) ; history . push ( RoutePath . Channels ) ; } catch ( error ) { dispatchError ( dispatch , error ) ; } } ; export const reducers = function ( state = initialState , action ) { switch ( action . type ) { case ActionType . UserAdd : case ActionType . UserGet : case ActionType . UserLogin : case ActionType . UserError : case UserAddTransition . CheckWallet : case UserAddTransition . CreatingAccount : case UserAddTransition . DeployingContract : return { ... state , ... action . data , status : action . type } ; default : return { ... state , status : action . type } ; } } ;