diff --git a/packages/instant/src/components/payment_method.tsx b/packages/instant/src/components/payment_method.tsx index ada9f7bab5..43c6718633 100644 --- a/packages/instant/src/components/payment_method.tsx +++ b/packages/instant/src/components/payment_method.tsx @@ -2,7 +2,7 @@ import * as _ from 'lodash'; import * as React from 'react'; import { ColorOption } from '../style/theme'; -import { Account, AccountState, Network } from '../types'; +import { Account, AccountState, Network, ProviderType } from '../types'; import { envUtil } from '../util/env'; import { CoinbaseWalletLogo } from './coinbase_wallet_logo'; @@ -20,21 +20,22 @@ export interface PaymentMethodProps { account: Account; network: Network; walletDisplayName: string; + providerType: ProviderType | undefined; onInstallWalletClick: () => void; - onUnlockWalletClick: () => void; + onUnlockWalletClick: (providerType?: ProviderType) => void; } export class PaymentMethod extends React.PureComponent { public render(): React.ReactNode { return ( - + {this._renderTitleText()} {this._renderTitleLabel()} - {this._renderMainContent()} + {this._renderMainContent()} ); } @@ -74,22 +75,34 @@ export class PaymentMethod extends React.PureComponent { const primaryColor = isMobile ? ColorOption.darkBlue : ColorOption.darkOrange; const secondaryColor = isMobile ? ColorOption.lightBlue : ColorOption.lightOrange; const colors = { primaryColor, secondaryColor }; + const onUnlockGenericWallet = () => this.props.onUnlockWalletClick(ProviderType.MetaMask); + const onUnlockFormatic = () => this.props.onUnlockWalletClick(ProviderType.Fortmatic); switch (account.state) { case AccountState.Loading: return null; case AccountState.Locked: return ( - - - - } - {...colors} - > - Click to Connect {this.props.walletDisplayName} - + + + + + } + {...colors} + > + Click to Connect Metamask + + + Connect with Fortmatic + + ); case AccountState.None: return ( diff --git a/packages/instant/src/constants.ts b/packages/instant/src/constants.ts index 5332414948..d84fad56bb 100644 --- a/packages/instant/src/constants.ts +++ b/packages/instant/src/constants.ts @@ -94,3 +94,5 @@ export const PROVIDER_TYPE_TO_NAME: { [key in ProviderType]: string } = { [ProviderType.Fortmatic]: 'Fortmatic', [ProviderType.Fallback]: 'Fallback', }; + +export const FORTMATIC_API_KEY = process.env.INSTANT_FORTMATIC_API_KEY; diff --git a/packages/instant/src/containers/connected_account_payment_method.ts b/packages/instant/src/containers/connected_account_payment_method.ts index 6c9b0a53d5..6f306e397c 100644 --- a/packages/instant/src/containers/connected_account_payment_method.ts +++ b/packages/instant/src/containers/connected_account_payment_method.ts @@ -1,3 +1,4 @@ +import * as Fortmatic from 'fortmatic'; import * as React from 'react'; import { connect } from 'react-redux'; import { Dispatch } from 'redux'; @@ -6,14 +7,23 @@ import { PaymentMethod, PaymentMethodProps } from '../components/payment_method' import { COINBASE_WALLET_ANDROID_APP_STORE_URL, COINBASE_WALLET_IOS_APP_STORE_URL, - COINBASE_WALLET_SITE_URL, + COINBASE_WALLET_SITE_URL, FORTMATIC_API_KEY, } from '../constants'; import { Action, actions } from '../redux/actions'; import { asyncData } from '../redux/async_data'; import { State } from '../redux/reducer'; -import { Network, Omit, OperatingSystem, ProviderState, StandardSlidingPanelContent, WalletSuggestion } from '../types'; +import { + Network, + Omit, + OperatingSystem, + ProviderState, + ProviderType, + StandardSlidingPanelContent, + WalletSuggestion, +} from '../types'; import { analytics } from '../util/analytics'; import { envUtil } from '../util/env'; +import { providerFactory } from '../util/provider_factory'; export interface ConnectedAccountPaymentMethodProps {} @@ -21,11 +31,12 @@ interface ConnectedState { network: Network; providerState: ProviderState; walletDisplayName?: string; + providerType?: ProviderType; } interface ConnectedDispatch { openInstallWalletPanel: () => void; - unlockWalletAndDispatchToStore: (providerState: ProviderState) => void; + unlockWalletAndDispatchToStore: (providerState: ProviderState, providerType?: ProviderType) => void; } type ConnectedProps = Omit; @@ -35,6 +46,7 @@ type FinalProps = ConnectedProps & ConnectedAccountPaymentMethodProps; const mapStateToProps = (state: State, _ownProps: ConnectedAccountPaymentMethodProps): ConnectedState => ({ network: state.network, providerState: state.providerState, + providerType: envUtil.getProviderType(state.providerState.provider), walletDisplayName: state.walletDisplayName, }); @@ -43,10 +55,43 @@ const mapDispatchToProps = ( ownProps: ConnectedAccountPaymentMethodProps, ): ConnectedDispatch => ({ openInstallWalletPanel: () => dispatch(actions.openStandardSlidingPanel(StandardSlidingPanelContent.InstallWallet)), - unlockWalletAndDispatchToStore: (providerState: ProviderState) => { + unlockWalletAndDispatchToStore: (providerState: ProviderState, providerType?: ProviderType) => { analytics.trackAccountUnlockRequested(); + let newProviderState: ProviderState = { + ...providerState, + }; + // Updates the provider state based on the provider type + if (providerType && providerType === ProviderType.Fortmatic) { + const web3Wrapper = providerState.web3Wrapper; + const fm = new Fortmatic(FORTMATIC_API_KEY); + const fmProvider = fm.getProvider(); + web3Wrapper.setProvider(fmProvider); + newProviderState = { + ...newProviderState, + provider: fmProvider, + web3Wrapper, + displayName: envUtil.getProviderDisplayName(fmProvider), + name: envUtil.getProviderName(fmProvider), + }; + } else { + // As default uses the injected provider + const injected = providerFactory.getInjectedProviderIfExists(); + const web3Wrapper = providerState.web3Wrapper; + if (injected) { + web3Wrapper.setProvider(injected); + newProviderState = { + ...newProviderState, + provider: injected, + web3Wrapper, + displayName: envUtil.getProviderDisplayName(injected), + name: envUtil.getProviderName(injected), + }; + } + } + // Updates provider state + dispatch(actions.setProviderState(newProviderState)); // tslint:disable-next-line:no-floating-promises - asyncData.fetchAccountInfoAndDispatchToStore2(providerState, dispatch, true); + asyncData.fetchAccountInfoAndDispatchToStore(newProviderState, dispatch, true); }, }); @@ -59,7 +104,9 @@ const mergeProps = ( network: connectedState.network, account: connectedState.providerState.account, walletDisplayName: connectedState.providerState.displayName, - onUnlockWalletClick: () => connectedDispatch.unlockWalletAndDispatchToStore(connectedState.providerState), + providerType: connectedState.providerType, + onUnlockWalletClick: (providerType?: ProviderType) => + connectedDispatch.unlockWalletAndDispatchToStore(connectedState.providerState, providerType), onInstallWalletClick: () => { const isMobile = envUtil.isMobileOperatingSystem(); const walletSuggestion: WalletSuggestion = isMobile diff --git a/packages/instant/src/redux/actions.ts b/packages/instant/src/redux/actions.ts index 47e0e45276..a8498be5c9 100644 --- a/packages/instant/src/redux/actions.ts +++ b/packages/instant/src/redux/actions.ts @@ -1,7 +1,14 @@ import { MarketBuySwapQuote } from '@0x/asset-swapper'; import { BigNumber } from '@0x/utils'; -import { ActionsUnion, AddressAndEthBalanceInWei, Asset, BaseCurrency, StandardSlidingPanelContent } from '../types'; +import { + ActionsUnion, + AddressAndEthBalanceInWei, + Asset, + BaseCurrency, + ProviderState, + StandardSlidingPanelContent, +} from '../types'; export interface PlainAction { type: T; @@ -43,6 +50,7 @@ export enum ActionTypes { OpenStandardSlidingPanel = 'OPEN_STANDARD_SLIDING_PANEL', CloseStandardSlidingPanel = 'CLOSE_STANDARD_SLIDING_PANEL', UpdateBaseCurrency = 'UPDATE_BASE_CURRENCY', + SetProviderState = 'SET_PROVIDER_STATE', } export const actions = { @@ -73,4 +81,5 @@ export const actions = { createAction(ActionTypes.OpenStandardSlidingPanel, content), closeStandardSlidingPanel: () => createAction(ActionTypes.CloseStandardSlidingPanel), updateBaseCurrency: (baseCurrency: BaseCurrency) => createAction(ActionTypes.UpdateBaseCurrency, baseCurrency), + setProviderState: (providerState: ProviderState) => createAction(ActionTypes.SetProviderState, providerState), }; diff --git a/packages/instant/src/redux/reducer.ts b/packages/instant/src/redux/reducer.ts index ebb7d9fbbf..fff3a0c042 100644 --- a/packages/instant/src/redux/reducer.ts +++ b/packages/instant/src/redux/reducer.ts @@ -252,6 +252,11 @@ export const createReducer = (initialState: State) => { ...state, baseCurrency: action.data, }; + case ActionTypes.SetProviderState: + return { + ...state, + providerState: action.data, + }; default: return state; } diff --git a/packages/instant/src/util/env.ts b/packages/instant/src/util/env.ts index 52e980a985..412e24725c 100644 --- a/packages/instant/src/util/env.ts +++ b/packages/instant/src/util/env.ts @@ -1,9 +1,9 @@ import * as bowser from 'bowser'; -import {ZeroExProvider} from 'ethereum-types'; +import { ZeroExProvider } from 'ethereum-types'; import * as _ from 'lodash'; -import {PROVIDER_TYPE_TO_NAME} from '../constants'; -import {Browser, OperatingSystem, ProviderType} from '../types'; +import { PROVIDER_TYPE_TO_NAME } from '../constants'; +import { Browser, OperatingSystem, ProviderType } from '../types'; export const envUtil = { getBrowser(): Browser {