From e961d8827777cf4b2520ce682a01c6a41359694d Mon Sep 17 00:00:00 2001 From: apane Date: Mon, 30 Sep 2019 15:42:54 -0300 Subject: [PATCH 01/29] Adds fortmatic dependency --- packages/instant/package.json | 1 + packages/instant/src/globals.d.ts | 1 + yarn.lock | 16 ++++++++++++++++ 3 files changed, 18 insertions(+) diff --git a/packages/instant/package.json b/packages/instant/package.json index 74ce2b5193..17f10ed205 100644 --- a/packages/instant/package.json +++ b/packages/instant/package.json @@ -53,6 +53,7 @@ "babel-runtime": "^6.26.0", "bowser": "^1.9.4", "copy-to-clipboard": "^3.0.8", + "fortmatic": "^0.8.2", "lodash": "^4.17.11", "polished": "^1.9.2", "react": "^16.5.2", diff --git a/packages/instant/src/globals.d.ts b/packages/instant/src/globals.d.ts index 1b5fa443df..b2cb51bc65 100644 --- a/packages/instant/src/globals.d.ts +++ b/packages/instant/src/globals.d.ts @@ -10,3 +10,4 @@ declare module '*.json' { export default json; /* tslint:enable */ } +declare module 'fortmatic'; diff --git a/yarn.lock b/yarn.lock index 596b623b34..9eaeb2e857 100644 --- a/yarn.lock +++ b/yarn.lock @@ -984,6 +984,12 @@ core-js "^2.6.5" regenerator-runtime "^0.13.2" +"@babel/runtime@7.3.4": + version "7.3.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.4.tgz#73d12ba819e365fcf7fd152aed56d6df97d21c83" + dependencies: + regenerator-runtime "^0.12.0" + "@babel/runtime@^7.1.5", "@babel/runtime@^7.3.1": version "7.5.5" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132" @@ -7759,6 +7765,12 @@ format-util@^1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/format-util/-/format-util-1.0.3.tgz#032dca4a116262a12c43f4c3ec8566416c5b2d95" +fortmatic@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/fortmatic/-/fortmatic-0.8.2.tgz#a93fc97d1a1808faf82210d6554e1ebdcb6c5379" + dependencies: + "@babel/runtime" "7.3.4" + forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" @@ -14102,6 +14114,10 @@ regenerator-runtime@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" +regenerator-runtime@^0.12.0: + version "0.12.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" + regenerator-runtime@^0.13.2: version "0.13.2" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz#32e59c9a6fb9b1a4aff09b4930ca2d4477343447" From 87b90bb04b789a7114950667a77fba926b8f8749 Mon Sep 17 00:00:00 2001 From: apane Date: Mon, 30 Sep 2019 17:41:05 -0300 Subject: [PATCH 02/29] Adds fortmatic button Adds fortmatic colors --- .../components/wallet_prompt_fortmatic.tsx | 38 +++++++++++++++++++ packages/instant/src/style/theme.ts | 4 ++ 2 files changed, 42 insertions(+) create mode 100644 packages/instant/src/components/wallet_prompt_fortmatic.tsx diff --git a/packages/instant/src/components/wallet_prompt_fortmatic.tsx b/packages/instant/src/components/wallet_prompt_fortmatic.tsx new file mode 100644 index 0000000000..dc46acfb6f --- /dev/null +++ b/packages/instant/src/components/wallet_prompt_fortmatic.tsx @@ -0,0 +1,38 @@ +import * as React from 'react'; + +import {Container} from './ui/container'; +import {Flex} from './ui/flex'; +import {Text} from './ui/text'; +import {Icon} from "./ui/icon"; +import {ColorOption} from "../style/theme"; + +export interface WalletPromptFortmaticProps { + onClick?: () => void; +} + +export const WalletPromptFortmatic: React.StatelessComponent = ({ + onClick +}) => ( + + + + + Connect with Fortmatic + + + + +); + + +WalletPromptFortmatic.displayName = 'WalletPromptFortmatic'; diff --git a/packages/instant/src/style/theme.ts b/packages/instant/src/style/theme.ts index 49f3c81e6b..a3427c0423 100644 --- a/packages/instant/src/style/theme.ts +++ b/packages/instant/src/style/theme.ts @@ -27,6 +27,8 @@ export enum ColorOption { red = 'red', darkBlue = 'darkBlue', lightBlue = 'lightBlue', + fortmaticPrimary = 'fortmaticPrimary', + fortmaticSecondary = 'fortmaticSecondary' } export const theme: Theme = { @@ -44,6 +46,8 @@ export const theme: Theme = { red: '#D00000', darkBlue: '#135df6', lightBlue: '#F2F7FF', + fortmaticPrimary: '#6851FF', + fortmaticSecondary: '#E2DCFF' }; export const transparentWhite = 'rgba(255,255,255,0.3)'; From 9f8cb9934044adbf51eede72edbae17e0c551388 Mon Sep 17 00:00:00 2001 From: apane Date: Tue, 1 Oct 2019 12:02:39 -0300 Subject: [PATCH 03/29] Removes prompt formatic Fixs wallet prompt, adds marginTop props, splits border into border and borderColor Adds fortmaticPrimary and fortmaticSecondary prop colors --- .../instant/src/components/wallet_prompt.tsx | 8 +++- .../components/wallet_prompt_fortmatic.tsx | 38 ------------------- .../connected_account_payment_method.ts | 2 +- packages/instant/src/style/theme.ts | 4 +- 4 files changed, 9 insertions(+), 43 deletions(-) delete mode 100644 packages/instant/src/components/wallet_prompt_fortmatic.tsx diff --git a/packages/instant/src/components/wallet_prompt.tsx b/packages/instant/src/components/wallet_prompt.tsx index 10433767f0..24c484533a 100644 --- a/packages/instant/src/components/wallet_prompt.tsx +++ b/packages/instant/src/components/wallet_prompt.tsx @@ -7,10 +7,11 @@ import { Flex } from './ui/flex'; import { Text } from './ui/text'; export interface WalletPromptProps { - image: React.ReactNode; + image?: React.ReactNode; onClick?: () => void; primaryColor: ColorOption; secondaryColor: ColorOption; + marginTop?: string; } export const WalletPrompt: React.StatelessComponent = ({ @@ -19,16 +20,19 @@ export const WalletPrompt: React.StatelessComponent = ({ children, secondaryColor, primaryColor, + marginTop, }) => ( {image} diff --git a/packages/instant/src/components/wallet_prompt_fortmatic.tsx b/packages/instant/src/components/wallet_prompt_fortmatic.tsx deleted file mode 100644 index dc46acfb6f..0000000000 --- a/packages/instant/src/components/wallet_prompt_fortmatic.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import * as React from 'react'; - -import {Container} from './ui/container'; -import {Flex} from './ui/flex'; -import {Text} from './ui/text'; -import {Icon} from "./ui/icon"; -import {ColorOption} from "../style/theme"; - -export interface WalletPromptFortmaticProps { - onClick?: () => void; -} - -export const WalletPromptFortmatic: React.StatelessComponent = ({ - onClick -}) => ( - - - - - Connect with Fortmatic - - - - -); - - -WalletPromptFortmatic.displayName = 'WalletPromptFortmatic'; diff --git a/packages/instant/src/containers/connected_account_payment_method.ts b/packages/instant/src/containers/connected_account_payment_method.ts index f648f0b545..6c9b0a53d5 100644 --- a/packages/instant/src/containers/connected_account_payment_method.ts +++ b/packages/instant/src/containers/connected_account_payment_method.ts @@ -46,7 +46,7 @@ const mapDispatchToProps = ( unlockWalletAndDispatchToStore: (providerState: ProviderState) => { analytics.trackAccountUnlockRequested(); // tslint:disable-next-line:no-floating-promises - asyncData.fetchAccountInfoAndDispatchToStore(providerState, dispatch, true); + asyncData.fetchAccountInfoAndDispatchToStore2(providerState, dispatch, true); }, }); diff --git a/packages/instant/src/style/theme.ts b/packages/instant/src/style/theme.ts index a3427c0423..874ca8e878 100644 --- a/packages/instant/src/style/theme.ts +++ b/packages/instant/src/style/theme.ts @@ -28,7 +28,7 @@ export enum ColorOption { darkBlue = 'darkBlue', lightBlue = 'lightBlue', fortmaticPrimary = 'fortmaticPrimary', - fortmaticSecondary = 'fortmaticSecondary' + fortmaticSecondary = 'fortmaticSecondary', } export const theme: Theme = { @@ -47,7 +47,7 @@ export const theme: Theme = { darkBlue: '#135df6', lightBlue: '#F2F7FF', fortmaticPrimary: '#6851FF', - fortmaticSecondary: '#E2DCFF' + fortmaticSecondary: '#E2DCFF', }; export const transparentWhite = 'rgba(255,255,255,0.3)'; From 85bdccbc0694faeeba7ba5dbfa0e74cd661bd299 Mon Sep 17 00:00:00 2001 From: apane Date: Tue, 1 Oct 2019 16:48:36 -0300 Subject: [PATCH 04/29] Adds Fortmatic to providerType Uses fortmatic as default provider --- packages/instant/src/constants.ts | 1 + packages/instant/src/types.ts | 1 + packages/instant/src/util/env.ts | 9 +++++---- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/instant/src/constants.ts b/packages/instant/src/constants.ts index 3fef55c4c7..5332414948 100644 --- a/packages/instant/src/constants.ts +++ b/packages/instant/src/constants.ts @@ -91,5 +91,6 @@ export const PROVIDER_TYPE_TO_NAME: { [key in ProviderType]: string } = { [ProviderType.Parity]: 'Parity', [ProviderType.TrustWallet]: 'Trust Wallet', [ProviderType.Opera]: 'Opera Wallet', + [ProviderType.Fortmatic]: 'Fortmatic', [ProviderType.Fallback]: 'Fallback', }; diff --git a/packages/instant/src/types.ts b/packages/instant/src/types.ts index 0115f3efc1..4300878376 100644 --- a/packages/instant/src/types.ts +++ b/packages/instant/src/types.ts @@ -185,6 +185,7 @@ export enum ProviderType { Cipher = 'CIPHER', TrustWallet = 'TRUST_WALLET', Opera = 'OPERA', + Fortmatic = 'Fortmatic', Fallback = 'FALLBACK', } diff --git a/packages/instant/src/util/env.ts b/packages/instant/src/util/env.ts index 600017fb97..52e980a985 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 { @@ -58,7 +58,8 @@ export const envUtil = { } else if (envUtil.getBrowser() === Browser.Opera && !anyProvider.isMetaMask) { return ProviderType.Opera; } - return; + // If the provider is not supported by 0x, use fortmatic + return ProviderType.Fortmatic; }, getProviderName(provider: ZeroExProvider): string { const providerTypeIfExists = envUtil.getProviderType(provider); From 762db417d7c0734e20ef2fa513e007cae7d00b4c Mon Sep 17 00:00:00 2001 From: apane Date: Wed, 2 Oct 2019 09:32:19 -0300 Subject: [PATCH 05/29] Adds setProviderState action unlockWalletAndDispatchToStore now changes the provider state based on the provider type Adds button to connect with fortmatic Adds FORTMATIC_API_KEY constant --- .../instant/src/components/payment_method.tsx | 43 +++++++++----- packages/instant/src/constants.ts | 2 + .../connected_account_payment_method.ts | 59 +++++++++++++++++-- packages/instant/src/redux/actions.ts | 11 +++- packages/instant/src/redux/reducer.ts | 5 ++ packages/instant/src/util/env.ts | 6 +- 6 files changed, 101 insertions(+), 25 deletions(-) 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 { From 78752f91781bae21de3473ccb9e179d85b50b401 Mon Sep 17 00:00:00 2001 From: apane Date: Thu, 3 Oct 2019 11:17:10 -0300 Subject: [PATCH 06/29] Adds connect to formatic button if the user does not have metamask installed --- .../instant/src/components/payment_method.tsx | 19 +++++++++++++++---- .../src/util/provider_state_factory.ts | 16 ++++++++++++++-- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/packages/instant/src/components/payment_method.tsx b/packages/instant/src/components/payment_method.tsx index 43c6718633..c2ccbff783 100644 --- a/packages/instant/src/components/payment_method.tsx +++ b/packages/instant/src/components/payment_method.tsx @@ -23,6 +23,7 @@ export interface PaymentMethodProps { providerType: ProviderType | undefined; onInstallWalletClick: () => void; onUnlockWalletClick: (providerType?: ProviderType) => void; + onUnlockWalletWithFortmaticProvider: () => void; } export class PaymentMethod extends React.PureComponent { @@ -76,7 +77,7 @@ export class PaymentMethod extends React.PureComponent { 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); + const onUnlockFormatic = () => this.props.onUnlockWalletWithFortmaticProvider(); switch (account.state) { case AccountState.Loading: return null; @@ -106,9 +107,19 @@ export class PaymentMethod extends React.PureComponent { ); case AccountState.None: return ( - - {isMobile ? 'Install Coinbase Wallet' : 'Install MetaMask'} - + + + {isMobile ? 'Install Coinbase Wallet' : 'Install MetaMask'} + + + Connect with Fortmatic + + ); case AccountState.Ready: return ( diff --git a/packages/instant/src/util/provider_state_factory.ts b/packages/instant/src/util/provider_state_factory.ts index fd59fa4a58..da5f32a5ec 100644 --- a/packages/instant/src/util/provider_state_factory.ts +++ b/packages/instant/src/util/provider_state_factory.ts @@ -1,9 +1,10 @@ import { providerUtils } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { SupportedProvider, ZeroExProvider } from 'ethereum-types'; +import * as Fortmatic from 'fortmatic'; import * as _ from 'lodash'; -import { LOADING_ACCOUNT, NO_ACCOUNT } from '../constants'; +import {FORTMATIC_API_KEY, LOADING_ACCOUNT, NO_ACCOUNT} from '../constants'; import { Maybe, Network, OrderSource, ProviderState } from '../types'; import { envUtil } from '../util/env'; @@ -72,7 +73,18 @@ export const providerStateFactory = { }; return providerState; } else { - return undefined; + // If there was no provider injected to the windows, uses fortmatic as default + const fm = new Fortmatic(FORTMATIC_API_KEY); + const fmProvider = fm.getProvider(); + const providerState: ProviderState = { + displayName: envUtil.getProviderDisplayName(fmProvider), + name: envUtil.getProviderName(fmProvider), + provider: fmProvider, + web3Wrapper: new Web3Wrapper(fmProvider), + assetBuyer: assetBuyerFactory.getAssetBuyer(fmProvider, orderSource, network), + account: LOADING_ACCOUNT, + }; + return providerState; } }, getInitialProviderStateFallback: ( From 51179d10ce10a2ab203bbd7ca7baca072f0ede67 Mon Sep 17 00:00:00 2001 From: apane Date: Thu, 3 Oct 2019 11:18:41 -0300 Subject: [PATCH 07/29] Adds webpack config to use env var Updates env example Adds unlockWalletWithFormaticProvider on connect --- packages/instant/.env_example | 3 +- .../connected_account_payment_method.ts | 56 ++++++++----------- packages/instant/webpack.config.js | 3 + 3 files changed, 28 insertions(+), 34 deletions(-) diff --git a/packages/instant/.env_example b/packages/instant/.env_example index bdb87ae175..abec4e5970 100644 --- a/packages/instant/.env_example +++ b/packages/instant/.env_example @@ -6,4 +6,5 @@ INSTANT_INFURA_PROJECT_ID_PRODUCTION= INSTANT_INFURA_PROJECT_ID_DEVELOPMENT= # if you want to report to heap or rollbar when building in development mode, you can use the following: # INSTANT_HEAP_FORCE_DEVELOPMENT=true -# INSTANT_ROLLBAR_FORCE_DEVELOPMENT=true \ No newline at end of file +# INSTANT_ROLLBAR_FORCE_DEVELOPMENT=true +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 6f306e397c..2d826fd171 100644 --- a/packages/instant/src/containers/connected_account_payment_method.ts +++ b/packages/instant/src/containers/connected_account_payment_method.ts @@ -7,7 +7,8 @@ import { PaymentMethod, PaymentMethodProps } from '../components/payment_method' import { COINBASE_WALLET_ANDROID_APP_STORE_URL, COINBASE_WALLET_IOS_APP_STORE_URL, - COINBASE_WALLET_SITE_URL, FORTMATIC_API_KEY, + COINBASE_WALLET_SITE_URL, + FORTMATIC_API_KEY, LOADING_ACCOUNT, } from '../constants'; import { Action, actions } from '../redux/actions'; import { asyncData } from '../redux/async_data'; @@ -23,7 +24,6 @@ import { } from '../types'; import { analytics } from '../util/analytics'; import { envUtil } from '../util/env'; -import { providerFactory } from '../util/provider_factory'; export interface ConnectedAccountPaymentMethodProps {} @@ -37,6 +37,7 @@ interface ConnectedState { interface ConnectedDispatch { openInstallWalletPanel: () => void; unlockWalletAndDispatchToStore: (providerState: ProviderState, providerType?: ProviderType) => void; + unlockWalletWithFormaticProvider: (providerState: ProviderState) => void; } type ConnectedProps = Omit; @@ -55,41 +56,29 @@ const mapDispatchToProps = ( ownProps: ConnectedAccountPaymentMethodProps, ): ConnectedDispatch => ({ openInstallWalletPanel: () => dispatch(actions.openStandardSlidingPanel(StandardSlidingPanelContent.InstallWallet)), - unlockWalletAndDispatchToStore: (providerState: ProviderState, providerType?: ProviderType) => { + unlockWalletAndDispatchToStore: (providerState: ProviderState) => { analytics.trackAccountUnlockRequested(); - let newProviderState: ProviderState = { - ...providerState, + // tslint:disable-next-line:no-floating-promises + asyncData.fetchAccountInfoAndDispatchToStore(providerState, dispatch, true); + }, + unlockWalletWithFormaticProvider: (providerState: ProviderState) => { + // Sets fortmatic as the new provider and updates the state + const web3Wrapper = providerState.web3Wrapper; + const fm = new Fortmatic(FORTMATIC_API_KEY); + const fmProvider = fm.getProvider(); + web3Wrapper.setProvider(fmProvider); + const newProviderState = { + name: envUtil.getProviderName(fmProvider), + displayName: envUtil.getProviderDisplayName(fmProvider), + provider: fmProvider, + web3Wrapper, + assetBuyer: providerState.assetBuyer, + account: LOADING_ACCOUNT, }; - // 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)); + // Unlocks wallet + analytics.trackAccountUnlockRequested(); // tslint:disable-next-line:no-floating-promises asyncData.fetchAccountInfoAndDispatchToStore(newProviderState, dispatch, true); }, @@ -132,6 +121,7 @@ const mergeProps = ( window.open(url, '_blank'); } }, + onUnlockWalletWithFortmaticProvider: () => connectedDispatch.unlockWalletWithFormaticProvider(connectedState.providerState), }); export const ConnectedAccountPaymentMethod: React.ComponentClass = connect( diff --git a/packages/instant/webpack.config.js b/packages/instant/webpack.config.js index e741d6c54f..b5e20d68c7 100644 --- a/packages/instant/webpack.config.js +++ b/packages/instant/webpack.config.js @@ -94,12 +94,15 @@ const generateConfig = (dischargeTarget, heapConfigOptions, rollbarConfigOptions ? process.env.INSTANT_INFURA_PROJECT_ID_PRODUCTION : process.env.INSTANT_INFURA_PROJECT_ID_DEVELOPMENT; + const fortmaticApiKey = process.env.INSTANT_FORTMATIC_API_KEY; + const envVars = { GIT_SHA: JSON.stringify(GIT_SHA), NPM_PACKAGE_VERSION: JSON.stringify(process.env.npm_package_version), ROLLBAR_ENABLED: rollbarEnabled, HEAP_ENABLED: heapEnabled, INSTANT_INFURA_PROJECT_ID: JSON.stringify(infuraProjectId), + INSTANT_FORTMATIC_API_KEY: fortmaticApiKey, }; if (dischargeTarget) { envVars.INSTANT_DISCHARGE_TARGET = JSON.stringify(dischargeTarget); From c0400fa98669c61f4f8bdb540da5a4f4594a7d4a Mon Sep 17 00:00:00 2001 From: apane Date: Thu, 3 Oct 2019 13:42:13 -0300 Subject: [PATCH 08/29] Removes onUnlockFormatic, just uses onUnlockGenericWallet Removes unlockWalletWithFormaticProvider, now just uses unlockWalletAndDispatchToStore with getProviderStateBasedOnProviderType Adds getProviderStateBasedOnProviderType Adds orderSource to providerState type --- .../instant/src/components/payment_method.tsx | 11 +-- .../connected_account_payment_method.ts | 35 ++----- packages/instant/src/redux/async_data.ts | 17 +++- packages/instant/src/types.ts | 1 + .../src/util/provider_state_factory.ts | 97 ++++++++++++++----- 5 files changed, 98 insertions(+), 63 deletions(-) diff --git a/packages/instant/src/components/payment_method.tsx b/packages/instant/src/components/payment_method.tsx index c2ccbff783..58071791ce 100644 --- a/packages/instant/src/components/payment_method.tsx +++ b/packages/instant/src/components/payment_method.tsx @@ -1,4 +1,3 @@ -import * as _ from 'lodash'; import * as React from 'react'; import { ColorOption } from '../style/theme'; @@ -20,10 +19,8 @@ export interface PaymentMethodProps { account: Account; network: Network; walletDisplayName: string; - providerType: ProviderType | undefined; onInstallWalletClick: () => void; - onUnlockWalletClick: (providerType?: ProviderType) => void; - onUnlockWalletWithFortmaticProvider: () => void; + onUnlockWalletClick: (providerType: ProviderType) => void; } export class PaymentMethod extends React.PureComponent { @@ -76,8 +73,10 @@ 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.onUnlockWalletWithFortmaticProvider(); + const onUnlockGenericWallet = () => { + this.props.onUnlockWalletClick(ProviderType.MetaMask); + }; + const onUnlockFormatic = () => this.props.onUnlockWalletClick(ProviderType.Fortmatic); switch (account.state) { case AccountState.Loading: return null; diff --git a/packages/instant/src/containers/connected_account_payment_method.ts b/packages/instant/src/containers/connected_account_payment_method.ts index 2d826fd171..534574cc5d 100644 --- a/packages/instant/src/containers/connected_account_payment_method.ts +++ b/packages/instant/src/containers/connected_account_payment_method.ts @@ -8,7 +8,6 @@ import { COINBASE_WALLET_ANDROID_APP_STORE_URL, COINBASE_WALLET_IOS_APP_STORE_URL, COINBASE_WALLET_SITE_URL, - FORTMATIC_API_KEY, LOADING_ACCOUNT, } from '../constants'; import { Action, actions } from '../redux/actions'; import { asyncData } from '../redux/async_data'; @@ -24,6 +23,7 @@ import { } from '../types'; import { analytics } from '../util/analytics'; import { envUtil } from '../util/env'; +import { providerStateFactory } from '../util/provider_state_factory'; export interface ConnectedAccountPaymentMethodProps {} @@ -31,13 +31,11 @@ interface ConnectedState { network: Network; providerState: ProviderState; walletDisplayName?: string; - providerType?: ProviderType; } interface ConnectedDispatch { openInstallWalletPanel: () => void; - unlockWalletAndDispatchToStore: (providerState: ProviderState, providerType?: ProviderType) => void; - unlockWalletWithFormaticProvider: (providerState: ProviderState) => void; + unlockWalletAndDispatchToStore: (providerState: ProviderState, providerType: ProviderType) => void; } type ConnectedProps = Omit; @@ -47,7 +45,6 @@ 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, }); @@ -56,25 +53,11 @@ const mapDispatchToProps = ( ownProps: ConnectedAccountPaymentMethodProps, ): ConnectedDispatch => ({ openInstallWalletPanel: () => dispatch(actions.openStandardSlidingPanel(StandardSlidingPanelContent.InstallWallet)), - unlockWalletAndDispatchToStore: (providerState: ProviderState) => { - analytics.trackAccountUnlockRequested(); - // tslint:disable-next-line:no-floating-promises - asyncData.fetchAccountInfoAndDispatchToStore(providerState, dispatch, true); - }, - unlockWalletWithFormaticProvider: (providerState: ProviderState) => { - // Sets fortmatic as the new provider and updates the state - const web3Wrapper = providerState.web3Wrapper; - const fm = new Fortmatic(FORTMATIC_API_KEY); - const fmProvider = fm.getProvider(); - web3Wrapper.setProvider(fmProvider); - const newProviderState = { - name: envUtil.getProviderName(fmProvider), - displayName: envUtil.getProviderDisplayName(fmProvider), - provider: fmProvider, - web3Wrapper, - assetBuyer: providerState.assetBuyer, - account: LOADING_ACCOUNT, - }; + unlockWalletAndDispatchToStore: (providerState: ProviderState, providerType: ProviderType) => { + const newProviderState: ProviderState = providerStateFactory.getProviderStateBasedOnProviderType( + providerState, + providerType, + ); // Updates provider state dispatch(actions.setProviderState(newProviderState)); // Unlocks wallet @@ -93,8 +76,7 @@ const mergeProps = ( network: connectedState.network, account: connectedState.providerState.account, walletDisplayName: connectedState.providerState.displayName, - providerType: connectedState.providerType, - onUnlockWalletClick: (providerType?: ProviderType) => + onUnlockWalletClick: (providerType: ProviderType) => connectedDispatch.unlockWalletAndDispatchToStore(connectedState.providerState, providerType), onInstallWalletClick: () => { const isMobile = envUtil.isMobileOperatingSystem(); @@ -121,7 +103,6 @@ const mergeProps = ( window.open(url, '_blank'); } }, - onUnlockWalletWithFortmaticProvider: () => connectedDispatch.unlockWalletWithFormaticProvider(connectedState.providerState), }); export const ConnectedAccountPaymentMethod: React.ComponentClass = connect( diff --git a/packages/instant/src/redux/async_data.ts b/packages/instant/src/redux/async_data.ts index 260b0538f2..db70bdc63d 100644 --- a/packages/instant/src/redux/async_data.ts +++ b/packages/instant/src/redux/async_data.ts @@ -66,14 +66,21 @@ export const asyncData = { if (shouldSetToLoading && providerState.account.state !== AccountState.Loading) { dispatch(actions.setAccountStateLoading()); } - let availableAddresses: string[]; + let availableAddresses: string[] = []; try { // TODO(bmillman): Add support at the web3Wrapper level for calling `eth_requestAccounts` instead of calling enable here const isPrivacyModeEnabled = (provider as any).enable !== undefined; - availableAddresses = - isPrivacyModeEnabled && shouldAttemptUnlock - ? await (provider as any).enable() - : await web3Wrapper.getAvailableAddressesAsync(); + if (providerState.name !== 'Fortmatic') { + availableAddresses = + isPrivacyModeEnabled && shouldAttemptUnlock + ? await (provider as any).enable() + : await web3Wrapper.getAvailableAddressesAsync(); + } else { + // If the provider is fortmatic don't try to get available addresses or it will prompt the user all the time on the heartbeat + if (shouldAttemptUnlock) { + availableAddresses = await web3Wrapper.getAvailableAddressesAsync(); + } + } } catch (e) { analytics.trackAccountUnlockDenied(); dispatch(actions.setAccountStateLocked()); diff --git a/packages/instant/src/types.ts b/packages/instant/src/types.ts index 4300878376..c37bd1d586 100644 --- a/packages/instant/src/types.ts +++ b/packages/instant/src/types.ts @@ -114,6 +114,7 @@ export interface ProviderState { swapQuoteConsumer: SwapQuoteConsumer; web3Wrapper: Web3Wrapper; account: Account; + orderSource: OrderSource; } export enum AccountState { diff --git a/packages/instant/src/util/provider_state_factory.ts b/packages/instant/src/util/provider_state_factory.ts index da5f32a5ec..d0ef800d71 100644 --- a/packages/instant/src/util/provider_state_factory.ts +++ b/packages/instant/src/util/provider_state_factory.ts @@ -2,10 +2,9 @@ import { providerUtils } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { SupportedProvider, ZeroExProvider } from 'ethereum-types'; import * as Fortmatic from 'fortmatic'; -import * as _ from 'lodash'; -import {FORTMATIC_API_KEY, LOADING_ACCOUNT, NO_ACCOUNT} from '../constants'; -import { Maybe, Network, OrderSource, ProviderState } from '../types'; +import { FORTMATIC_API_KEY, LOADING_ACCOUNT, LOCKED_ACCOUNT, NO_ACCOUNT } from '../constants'; +import { Maybe, Network, OrderSource, ProviderState, ProviderType } from '../types'; import { envUtil } from '../util/env'; import { assetSwapperFactory } from './asset_swapper_factory'; @@ -52,6 +51,7 @@ export const providerStateFactory = { swapQuoter: assetSwapperFactory.getSwapQuoter(provider, orderSource, network), swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(provider, network), account: LOADING_ACCOUNT, + orderSource, }; return providerState; }, @@ -70,21 +70,11 @@ export const providerStateFactory = { swapQuoter: assetSwapperFactory.getSwapQuoter(injectedProviderIfExists, orderSource, network), swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(injectedProviderIfExists, network), account: LOADING_ACCOUNT, + orderSource, }; return providerState; } else { - // If there was no provider injected to the windows, uses fortmatic as default - const fm = new Fortmatic(FORTMATIC_API_KEY); - const fmProvider = fm.getProvider(); - const providerState: ProviderState = { - displayName: envUtil.getProviderDisplayName(fmProvider), - name: envUtil.getProviderName(fmProvider), - provider: fmProvider, - web3Wrapper: new Web3Wrapper(fmProvider), - assetBuyer: assetBuyerFactory.getAssetBuyer(fmProvider, orderSource, network), - account: LOADING_ACCOUNT, - }; - return providerState; + return undefined; } }, getInitialProviderStateFallback: ( @@ -92,16 +82,73 @@ export const providerStateFactory = { network: Network, walletDisplayName?: string, ): ProviderState => { - const provider = providerFactory.getFallbackNoSigningProvider(network); - const providerState: ProviderState = { - name: 'Fallback', - displayName: walletDisplayName || envUtil.getProviderDisplayName(provider), - provider, - web3Wrapper: new Web3Wrapper(provider), - swapQuoter: assetSwapperFactory.getSwapQuoter(provider, orderSource, network), - swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(provider, network), - account: NO_ACCOUNT, - }; + // Uses fortmatic as default provider + const fm = new Fortmatic(FORTMATIC_API_KEY); + if (fm) { + const fmProvider = fm.getProvider(); + const providerState: ProviderState = { + displayName: envUtil.getProviderDisplayName(fmProvider), + name: envUtil.getProviderName(fmProvider), + provider: fmProvider, + web3Wrapper: new Web3Wrapper(fmProvider), + swapQuoter: assetSwapperFactory.getSwapQuoter(fm, orderSource, network), + swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(fm, network), + account: NO_ACCOUNT, + orderSource, + }; + return providerState; + } else { + const provider = providerFactory.getFallbackNoSigningProvider(network); + const providerState: ProviderState = { + name: 'Fallback', + displayName: walletDisplayName || envUtil.getProviderDisplayName(provider), + provider, + web3Wrapper: new Web3Wrapper(provider), + swapQuoter: assetSwapperFactory.getSwapQuoter(provider, orderSource, network), + swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(provider, network), + account: NO_ACCOUNT, + orderSource, + }; + return providerState; + } + }, + getProviderStateBasedOnProviderType: ( + currentProviderState: ProviderState, + providerType: ProviderType, + ): ProviderState => { + let providerState = currentProviderState; + const network = currentProviderState.swapQuoter.networkId; + const orderSource = currentProviderState.orderSource; + // Returns current provider if the provider type selected is not found + if (providerType === ProviderType.MetaMask) { + const provider = providerFactory.getInjectedProviderIfExists(); + if (provider) { + providerState = { + displayName: envUtil.getProviderDisplayName(provider), + name: envUtil.getProviderName(provider), + provider, + web3Wrapper: new Web3Wrapper(provider), + swapQuoter: assetSwapperFactory.getSwapQuoter(provider, orderSource, network), + swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(provider, network), + account: LOADING_ACCOUNT, + orderSource, + }; + } + } + if (providerType === ProviderType.Fortmatic) { + const fm = new Fortmatic(FORTMATIC_API_KEY); + const fmProvider = fm.getProvider(); + providerState = { + displayName: envUtil.getProviderDisplayName(fmProvider), + name: envUtil.getProviderName(fmProvider), + provider: fmProvider, + web3Wrapper: new Web3Wrapper(fmProvider), + swapQuoter: assetSwapperFactory.getSwapQuoter(fmProvider, orderSource, network), + swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(fmProvider, network), + account: LOADING_ACCOUNT, + orderSource, + }; + } return providerState; }, }; From ba5e19a01513d05f9fbb5d95db08f2ea6c37616e Mon Sep 17 00:00:00 2001 From: apane Date: Thu, 3 Oct 2019 14:20:14 -0300 Subject: [PATCH 09/29] Fix lint errors Remove icon --- packages/instant/src/components/payment_method.tsx | 2 +- .../instant/src/containers/connected_account_payment_method.ts | 1 - packages/instant/src/util/provider_state_factory.ts | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/instant/src/components/payment_method.tsx b/packages/instant/src/components/payment_method.tsx index 58071791ce..c0ecd9d7ef 100644 --- a/packages/instant/src/components/payment_method.tsx +++ b/packages/instant/src/components/payment_method.tsx @@ -116,7 +116,7 @@ export class PaymentMethod extends React.PureComponent { secondaryColor={ColorOption.fortmaticSecondary} marginTop="5px" > - Connect with Fortmatic + Connect with Fortmatic ); diff --git a/packages/instant/src/containers/connected_account_payment_method.ts b/packages/instant/src/containers/connected_account_payment_method.ts index 534574cc5d..479a164e35 100644 --- a/packages/instant/src/containers/connected_account_payment_method.ts +++ b/packages/instant/src/containers/connected_account_payment_method.ts @@ -1,4 +1,3 @@ -import * as Fortmatic from 'fortmatic'; import * as React from 'react'; import { connect } from 'react-redux'; import { Dispatch } from 'redux'; diff --git a/packages/instant/src/util/provider_state_factory.ts b/packages/instant/src/util/provider_state_factory.ts index d0ef800d71..a504453756 100644 --- a/packages/instant/src/util/provider_state_factory.ts +++ b/packages/instant/src/util/provider_state_factory.ts @@ -3,7 +3,7 @@ import { Web3Wrapper } from '@0x/web3-wrapper'; import { SupportedProvider, ZeroExProvider } from 'ethereum-types'; import * as Fortmatic from 'fortmatic'; -import { FORTMATIC_API_KEY, LOADING_ACCOUNT, LOCKED_ACCOUNT, NO_ACCOUNT } from '../constants'; +import { FORTMATIC_API_KEY, LOADING_ACCOUNT, NO_ACCOUNT } from '../constants'; import { Maybe, Network, OrderSource, ProviderState, ProviderType } from '../types'; import { envUtil } from '../util/env'; From 51302595526422718f8ea9cc2d6bd51efacfcac3 Mon Sep 17 00:00:00 2001 From: apane Date: Thu, 3 Oct 2019 14:25:20 -0300 Subject: [PATCH 10/29] Remove icon on connect button --- packages/instant/src/components/payment_method.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/instant/src/components/payment_method.tsx b/packages/instant/src/components/payment_method.tsx index c0ecd9d7ef..b9e9941eba 100644 --- a/packages/instant/src/components/payment_method.tsx +++ b/packages/instant/src/components/payment_method.tsx @@ -100,7 +100,7 @@ export class PaymentMethod extends React.PureComponent { secondaryColor={ColorOption.fortmaticSecondary} marginTop="5px" > - Connect with Fortmatic + Connect with Fortmatic ); From 1cf8663f20e6e81b32e76e2ed57ce8893a44d52c Mon Sep 17 00:00:00 2001 From: apane Date: Tue, 8 Oct 2019 16:38:03 -0300 Subject: [PATCH 11/29] Adds phone svg Updates design of payment methods --- .../instant/src/components/payment_method.tsx | 37 ++++++++++++------- .../instant/src/components/ui/container.tsx | 1 + packages/instant/src/components/ui/icon.tsx | 10 +++++ .../instant/src/components/wallet_prompt.tsx | 15 ++++++-- 4 files changed, 47 insertions(+), 16 deletions(-) diff --git a/packages/instant/src/components/payment_method.tsx b/packages/instant/src/components/payment_method.tsx index b9e9941eba..b07fdeb771 100644 --- a/packages/instant/src/components/payment_method.tsx +++ b/packages/instant/src/components/payment_method.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; +import PhoneIconSvg from '../assets/icons/phone.svg'; import { ColorOption } from '../style/theme'; import { Account, AccountState, Network, ProviderType } from '../types'; import { envUtil } from '../util/env'; @@ -11,7 +12,6 @@ import { SectionHeader } from './section_header'; import { Circle } from './ui/circle'; import { Container } from './ui/container'; import { Flex } from './ui/flex'; -import { Icon } from './ui/icon'; import { Text } from './ui/text'; import { WalletPrompt } from './wallet_prompt'; @@ -30,7 +30,6 @@ export class PaymentMethod extends React.PureComponent { {this._renderTitleText()} - {this._renderTitleLabel()} {this._renderMainContent()} @@ -70,7 +69,7 @@ export class PaymentMethod extends React.PureComponent { const { account, network } = this.props; const isMobile = envUtil.isMobileOperatingSystem(); const logo = isMobile ? : ; - const primaryColor = isMobile ? ColorOption.darkBlue : ColorOption.darkOrange; + const primaryColor = isMobile ? ColorOption.darkBlue : ColorOption.grey; const secondaryColor = isMobile ? ColorOption.lightBlue : ColorOption.lightOrange; const colors = { primaryColor, secondaryColor }; const onUnlockGenericWallet = () => { @@ -82,25 +81,32 @@ export class PaymentMethod extends React.PureComponent { return null; case AccountState.Locked: return ( - + - + + } {...colors} > - Click to Connect Metamask + Metamask + + + } + display="flex" + {...colors} > - Connect with Fortmatic + Use phone number ); @@ -112,11 +118,16 @@ export class PaymentMethod extends React.PureComponent { + + + } + display="flex" + {...colors} > - Connect with Fortmatic + Use phone number ); diff --git a/packages/instant/src/components/ui/container.tsx b/packages/instant/src/components/ui/container.tsx index 59b733f3e1..b9040cfccb 100644 --- a/packages/instant/src/components/ui/container.tsx +++ b/packages/instant/src/components/ui/container.tsx @@ -75,6 +75,7 @@ export const Container = styled.div` ${props => cssRuleIfExists(props, 'opacity')} ${props => cssRuleIfExists(props, 'cursor')} ${props => cssRuleIfExists(props, 'overflow')} + ${props => cssRuleIfExists(props, 'alignSelf')} ${props => (props.overflow === 'scroll' ? `-webkit-overflow-scrolling: touch` : '')}; ${props => (props.hasBoxShadow ? `box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.1)` : '')}; ${props => props.display && stylesForMedia('display', props.display)} diff --git a/packages/instant/src/components/ui/icon.tsx b/packages/instant/src/components/ui/icon.tsx index e251acf5e2..c669db60f1 100644 --- a/packages/instant/src/components/ui/icon.tsx +++ b/packages/instant/src/components/ui/icon.tsx @@ -19,6 +19,7 @@ interface IconInfoMapping { failed: IconInfo; success: IconInfo; chevron: IconInfo; + chevronRight: IconInfo; search: IconInfo; lock: IconInfo; } @@ -52,6 +53,14 @@ const ICONS: IconInfoMapping = { strokeLinecap: 'round', strokeLinejoin: 'round', }, + chevronRight: { + viewBox: '0 0 7 13', + path: 'M1 1.5L6 6.5L1 11.5', + strokeOpacity: 0.5, + strokeWidth: 1.5, + strokeLinecap: 'round', + strokeLinejoin: 'round', + }, search: { viewBox: '0 0 14 14', fillRule: 'evenodd', @@ -89,6 +98,7 @@ const PlainIcon: React.StatelessComponent = props => { viewBox={iconInfo.viewBox} fill="none" xmlns="http://www.w3.org/2000/svg" + stroke={props.stroke} > = ({ @@ -21,11 +24,13 @@ export const WalletPrompt: React.StatelessComponent = ({ secondaryColor, primaryColor, marginTop, + display, + alignText, }) => ( = ({ cursor={onClick ? 'pointer' : undefined} boxShadowOnHover={!!onClick} marginTop={marginTop} + display={display} > - + {image} - + {children} + + + ); From 0eaaddeb9563042a16b4778135b8d6af8e200e08 Mon Sep 17 00:00:00 2001 From: apane Date: Fri, 18 Oct 2019 09:31:48 -0300 Subject: [PATCH 12/29] Removes unused colors Adds white background Adds phone.svg --- packages/instant/src/assets/icons/phone.svg | 3 +++ packages/instant/src/components/payment_method.tsx | 4 ++-- packages/instant/src/constants.ts | 3 +-- packages/instant/src/style/theme.ts | 6 ++---- 4 files changed, 8 insertions(+), 8 deletions(-) create mode 100644 packages/instant/src/assets/icons/phone.svg diff --git a/packages/instant/src/assets/icons/phone.svg b/packages/instant/src/assets/icons/phone.svg new file mode 100644 index 0000000000..0986ef2eba --- /dev/null +++ b/packages/instant/src/assets/icons/phone.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/instant/src/components/payment_method.tsx b/packages/instant/src/components/payment_method.tsx index b07fdeb771..abfd6b1036 100644 --- a/packages/instant/src/components/payment_method.tsx +++ b/packages/instant/src/components/payment_method.tsx @@ -69,8 +69,8 @@ export class PaymentMethod extends React.PureComponent { const { account, network } = this.props; const isMobile = envUtil.isMobileOperatingSystem(); const logo = isMobile ? : ; - const primaryColor = isMobile ? ColorOption.darkBlue : ColorOption.grey; - const secondaryColor = isMobile ? ColorOption.lightBlue : ColorOption.lightOrange; + const primaryColor = ColorOption.grey; + const secondaryColor = ColorOption.whiteBackground; const colors = { primaryColor, secondaryColor }; const onUnlockGenericWallet = () => { this.props.onUnlockWalletClick(ProviderType.MetaMask); diff --git a/packages/instant/src/constants.ts b/packages/instant/src/constants.ts index d84fad56bb..d8700c6353 100644 --- a/packages/instant/src/constants.ts +++ b/packages/instant/src/constants.ts @@ -94,5 +94,4 @@ 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; +export const FORTMATIC_API_KEY = process.env.INSTANT_FORTMATIC_API_KEY || 'pk_live_43E27F282B16AA8C'; diff --git a/packages/instant/src/style/theme.ts b/packages/instant/src/style/theme.ts index 874ca8e878..04043f3596 100644 --- a/packages/instant/src/style/theme.ts +++ b/packages/instant/src/style/theme.ts @@ -27,8 +27,7 @@ export enum ColorOption { red = 'red', darkBlue = 'darkBlue', lightBlue = 'lightBlue', - fortmaticPrimary = 'fortmaticPrimary', - fortmaticSecondary = 'fortmaticSecondary', + whiteBackground = 'whiteBackground', } export const theme: Theme = { @@ -46,8 +45,7 @@ export const theme: Theme = { red: '#D00000', darkBlue: '#135df6', lightBlue: '#F2F7FF', - fortmaticPrimary: '#6851FF', - fortmaticSecondary: '#E2DCFF', + whiteBackground: '#FFFFFF', }; export const transparentWhite = 'rgba(255,255,255,0.3)'; From 8650cb5217b539932b22cb42a362cac2b707a0aa Mon Sep 17 00:00:00 2001 From: apane Date: Fri, 1 Nov 2019 15:29:17 -0300 Subject: [PATCH 13/29] Disables order details if no payment method is selected --- .../instant/src/components/order_details.tsx | 20 ++++++++++++------- .../latest_buy_quote_order_details.ts | 1 + 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/packages/instant/src/components/order_details.tsx b/packages/instant/src/components/order_details.tsx index 841390b77f..203d261b73 100644 --- a/packages/instant/src/components/order_details.tsx +++ b/packages/instant/src/components/order_details.tsx @@ -6,7 +6,7 @@ import { oc } from 'ts-optchain'; import { BIG_NUMBER_ZERO, DEFAULT_UNKOWN_ASSET_NAME } from '../constants'; import { ColorOption } from '../style/theme'; -import { BaseCurrency } from '../types'; +import {Account, AccountState, BaseCurrency} from '../types'; import { format } from '../util/format'; import { AmountPlaceholder } from './amount_placeholder'; @@ -25,16 +25,22 @@ export interface OrderDetailsProps { baseCurrency: BaseCurrency; onBaseCurrencySwitchEth: () => void; onBaseCurrencySwitchUsd: () => void; + account: Account; } export class OrderDetails extends React.PureComponent { public render(): React.ReactNode { const shouldShowUsdError = this.props.baseCurrency === BaseCurrency.USD && this._hadErrorFetchingUsdPrice(); - return ( - - {this._renderHeader()} - {shouldShowUsdError ? this._renderErrorFetchingUsdPrice() : this._renderRows()} - - ); + const { state } = this.props.account; + if (state === AccountState.None) { + return null; + } else { + return ( + + {this._renderHeader()} + {shouldShowUsdError ? this._renderErrorFetchingUsdPrice() : this._renderRows()} + + ); + } } private _renderRows(): React.ReactNode { diff --git a/packages/instant/src/containers/latest_buy_quote_order_details.ts b/packages/instant/src/containers/latest_buy_quote_order_details.ts index 3e5a68577c..b6b7fb5f4b 100644 --- a/packages/instant/src/containers/latest_buy_quote_order_details.ts +++ b/packages/instant/src/containers/latest_buy_quote_order_details.ts @@ -22,6 +22,7 @@ const mapStateToProps = (state: State, _ownProps: LatestBuyQuoteOrderDetailsProp isLoading: state.quoteRequestState === AsyncProcessState.Pending, assetName: assetUtils.bestNameForAsset(state.selectedAsset), baseCurrency: state.baseCurrency, + account: state.providerState.account, }); interface ConnectedDispatch extends Pick {} From d4e04dc71220fd4829f91c5d5a030f114ff4ac86 Mon Sep 17 00:00:00 2001 From: apane Date: Fri, 1 Nov 2019 15:43:51 -0300 Subject: [PATCH 14/29] Fix chevron icon Fixs metamask icon size --- packages/instant/src/assets/icons/chevronRight.svg | 3 +++ packages/instant/src/components/payment_method.tsx | 2 +- packages/instant/src/components/wallet_prompt.tsx | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 packages/instant/src/assets/icons/chevronRight.svg diff --git a/packages/instant/src/assets/icons/chevronRight.svg b/packages/instant/src/assets/icons/chevronRight.svg new file mode 100644 index 0000000000..f03eac2407 --- /dev/null +++ b/packages/instant/src/assets/icons/chevronRight.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/instant/src/components/payment_method.tsx b/packages/instant/src/components/payment_method.tsx index abfd6b1036..e2648c7cef 100644 --- a/packages/instant/src/components/payment_method.tsx +++ b/packages/instant/src/components/payment_method.tsx @@ -88,7 +88,7 @@ export class PaymentMethod extends React.PureComponent { alignText={'flex-start'} image={ - + } {...colors} diff --git a/packages/instant/src/components/wallet_prompt.tsx b/packages/instant/src/components/wallet_prompt.tsx index 87845e31eb..c3b98e69f4 100644 --- a/packages/instant/src/components/wallet_prompt.tsx +++ b/packages/instant/src/components/wallet_prompt.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; +import ChevronRightSvg from '../assets/icons/chevronRight.svg'; import { ColorOption } from '../style/theme'; import { Container } from './ui/container'; @@ -48,7 +49,7 @@ export const WalletPrompt: React.StatelessComponent = ({ - + From 001c7bfdbc0cbb63868aa0861d37770717344721 Mon Sep 17 00:00:00 2001 From: apane Date: Fri, 1 Nov 2019 16:00:07 -0300 Subject: [PATCH 15/29] Fixs order details only when a wallet is connected --- packages/instant/src/components/order_details.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/instant/src/components/order_details.tsx b/packages/instant/src/components/order_details.tsx index 203d261b73..a46ea5cb96 100644 --- a/packages/instant/src/components/order_details.tsx +++ b/packages/instant/src/components/order_details.tsx @@ -31,7 +31,7 @@ export class OrderDetails extends React.PureComponent { public render(): React.ReactNode { const shouldShowUsdError = this.props.baseCurrency === BaseCurrency.USD && this._hadErrorFetchingUsdPrice(); const { state } = this.props.account; - if (state === AccountState.None) { + if (state !== AccountState.Ready) { return null; } else { return ( From d18de4c541b3a4f899b859e93ee8fdbded0dcbd3 Mon Sep 17 00:00:00 2001 From: apane Date: Fri, 1 Nov 2019 16:47:23 -0300 Subject: [PATCH 16/29] Fixs styling Removes unused imports --- .../instant/src/components/payment_method.tsx | 35 +++++++++++-------- .../instant/src/components/wallet_prompt.tsx | 9 +++-- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/packages/instant/src/components/payment_method.tsx b/packages/instant/src/components/payment_method.tsx index e2648c7cef..5923e13cb3 100644 --- a/packages/instant/src/components/payment_method.tsx +++ b/packages/instant/src/components/payment_method.tsx @@ -1,19 +1,19 @@ import * as React from 'react'; import PhoneIconSvg from '../assets/icons/phone.svg'; -import { ColorOption } from '../style/theme'; -import { Account, AccountState, Network, ProviderType } from '../types'; -import { envUtil } from '../util/env'; +import {ColorOption} from '../style/theme'; +import {Account, AccountState, Network, ProviderType} from '../types'; +import {envUtil} from '../util/env'; -import { CoinbaseWalletLogo } from './coinbase_wallet_logo'; -import { MetaMaskLogo } from './meta_mask_logo'; -import { PaymentMethodDropdown } from './payment_method_dropdown'; -import { SectionHeader } from './section_header'; -import { Circle } from './ui/circle'; -import { Container } from './ui/container'; -import { Flex } from './ui/flex'; -import { Text } from './ui/text'; -import { WalletPrompt } from './wallet_prompt'; +import {CoinbaseWalletLogo} from './coinbase_wallet_logo'; +import {MetaMaskLogo} from './meta_mask_logo'; +import {PaymentMethodDropdown} from './payment_method_dropdown'; +import {SectionHeader} from './section_header'; +import {Circle} from './ui/circle'; +import {Container} from './ui/container'; +import {Flex} from './ui/flex'; +import {Text} from './ui/text'; +import {WalletPrompt} from './wallet_prompt'; export interface PaymentMethodProps { account: Account; @@ -25,8 +25,9 @@ export interface PaymentMethodProps { export class PaymentMethod extends React.PureComponent { public render(): React.ReactNode { + const marginBottom = this.props.account.state !== AccountState.Ready ? '77px' : null; return ( - + {this._renderTitleText()} @@ -86,6 +87,8 @@ export class PaymentMethod extends React.PureComponent { onClick={onUnlockGenericWallet} display="flex" alignText={'flex-start'} + marginLeft="16px" + fontWeight="normal" image={ @@ -98,6 +101,8 @@ export class PaymentMethod extends React.PureComponent { @@ -113,12 +118,14 @@ export class PaymentMethod extends React.PureComponent { case AccountState.None: return ( - + {isMobile ? 'Install Coinbase Wallet' : 'Install MetaMask'} diff --git a/packages/instant/src/components/wallet_prompt.tsx b/packages/instant/src/components/wallet_prompt.tsx index c3b98e69f4..198b642f69 100644 --- a/packages/instant/src/components/wallet_prompt.tsx +++ b/packages/instant/src/components/wallet_prompt.tsx @@ -5,7 +5,6 @@ import { ColorOption } from '../style/theme'; import { Container } from './ui/container'; import { Flex } from './ui/flex'; -import {Icon} from './ui/icon'; import { Text } from './ui/text'; export interface WalletPromptProps { @@ -16,6 +15,8 @@ export interface WalletPromptProps { marginTop?: string; display?: string; alignText?: string; + marginLeft?: string; + fontWeight?: string; } export const WalletPrompt: React.StatelessComponent = ({ @@ -27,6 +28,8 @@ export const WalletPrompt: React.StatelessComponent = ({ marginTop, display, alignText, + marginLeft = '10px', + fontWeight = '500', }) => ( = ({ > {image} - - + + {children} From 09706e4ae2f6459fc675a230efce5b5e572e7ca4 Mon Sep 17 00:00:00 2001 From: apane Date: Mon, 4 Nov 2019 09:36:12 -0300 Subject: [PATCH 17/29] Fix metamask logo size on connect and on install --- packages/instant/src/components/payment_method.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/instant/src/components/payment_method.tsx b/packages/instant/src/components/payment_method.tsx index 5923e13cb3..25774c5bad 100644 --- a/packages/instant/src/components/payment_method.tsx +++ b/packages/instant/src/components/payment_method.tsx @@ -69,7 +69,8 @@ export class PaymentMethod extends React.PureComponent { private readonly _renderMainContent = (): React.ReactNode => { const { account, network } = this.props; const isMobile = envUtil.isMobileOperatingSystem(); - const logo = isMobile ? : ; + const metamaskLogo = ; + const logo = isMobile ? : metamaskLogo; const primaryColor = ColorOption.grey; const secondaryColor = ColorOption.whiteBackground; const colors = { primaryColor, secondaryColor }; @@ -91,7 +92,7 @@ export class PaymentMethod extends React.PureComponent { fontWeight="normal" image={ - + {metamaskLogo} } {...colors} From 7ba754d2a48911fdd02372d22bdcdab807c7c97e Mon Sep 17 00:00:00 2001 From: apane Date: Mon, 4 Nov 2019 15:11:22 -0300 Subject: [PATCH 18/29] Fixs styling --- packages/instant/src/components/payment_method.tsx | 9 ++++++--- packages/instant/src/components/wallet_prompt.tsx | 4 +++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/instant/src/components/payment_method.tsx b/packages/instant/src/components/payment_method.tsx index 25774c5bad..0b0a6bacda 100644 --- a/packages/instant/src/components/payment_method.tsx +++ b/packages/instant/src/components/payment_method.tsx @@ -90,6 +90,7 @@ export class PaymentMethod extends React.PureComponent { alignText={'flex-start'} marginLeft="16px" fontWeight="normal" + padding="15px 18px" image={ {metamaskLogo} @@ -101,9 +102,10 @@ export class PaymentMethod extends React.PureComponent { @@ -119,14 +121,15 @@ export class PaymentMethod extends React.PureComponent { case AccountState.None: return ( - + {isMobile ? 'Install Coinbase Wallet' : 'Install MetaMask'} diff --git a/packages/instant/src/components/wallet_prompt.tsx b/packages/instant/src/components/wallet_prompt.tsx index 198b642f69..0df5f72e66 100644 --- a/packages/instant/src/components/wallet_prompt.tsx +++ b/packages/instant/src/components/wallet_prompt.tsx @@ -17,6 +17,7 @@ export interface WalletPromptProps { alignText?: string; marginLeft?: string; fontWeight?: string; + padding?: string; } export const WalletPrompt: React.StatelessComponent = ({ @@ -30,9 +31,10 @@ export const WalletPrompt: React.StatelessComponent = ({ alignText, marginLeft = '10px', fontWeight = '500', + padding = '10px', }) => ( Date: Thu, 19 Dec 2019 16:15:18 -0800 Subject: [PATCH 19/29] fixing + testing fortmatic integration --- packages/instant/package.json | 2 +- packages/instant/public/index.html | 2 +- .../instant/src/components/order_details.tsx | 1 + packages/instant/src/redux/async_data.ts | 5 +- packages/instant/src/redux/reducer.ts | 8 ++- .../src/util/provider_state_factory.ts | 52 +++++++------------ .../instant/src/util/swap_quote_updater.ts | 1 + 7 files changed, 30 insertions(+), 41 deletions(-) diff --git a/packages/instant/package.json b/packages/instant/package.json index 17f10ed205..5f12e25ee4 100644 --- a/packages/instant/package.json +++ b/packages/instant/package.json @@ -53,7 +53,7 @@ "babel-runtime": "^6.26.0", "bowser": "^1.9.4", "copy-to-clipboard": "^3.0.8", - "fortmatic": "^0.8.2", + "fortmatic": "^1.0.1", "lodash": "^4.17.11", "polished": "^1.9.2", "react": "^16.5.2", diff --git a/packages/instant/public/index.html b/packages/instant/public/index.html index ea2960f013..ca114cc15b 100644 --- a/packages/instant/public/index.html +++ b/packages/instant/public/index.html @@ -199,7 +199,7 @@ }; const render = renderOptionsOverrides => { const renderOptionsDefaults = { - orderSource: 'https://api.0x.org/sra/', + orderSource: 'https://api.0x.org/sra', onClose: () => { console.log('0x Instant Closed'); }, diff --git a/packages/instant/src/components/order_details.tsx b/packages/instant/src/components/order_details.tsx index a46ea5cb96..4c693385bd 100644 --- a/packages/instant/src/components/order_details.tsx +++ b/packages/instant/src/components/order_details.tsx @@ -45,6 +45,7 @@ export class OrderDetails extends React.PureComponent { private _renderRows(): React.ReactNode { const { swapQuoteInfo } = this.props; + console.log(swapQuoteInfo); return ( { const newSwapQuoteIfExists = action.data; const shouldUpdate = newSwapQuoteIfExists === undefined || doesSwapQuoteMatchState(newSwapQuoteIfExists, state); + console.log('shouldUpdate', newSwapQuoteIfExists, shouldUpdate); if (shouldUpdate) { return { ...state, @@ -280,9 +281,13 @@ const doesSwapQuoteMatchState = (swapQuote: MarketBuySwapQuote, state: State): b const selectedAssetIfExists = state.selectedAsset; const selectedAssetUnitAmountIfExists = state.selectedAssetUnitAmount; // if no selectedAsset or selectedAssetAmount exists on the current state, return false + console.log('hmmmm?'); if (selectedAssetIfExists === undefined || selectedAssetUnitAmountIfExists === undefined) { return false; } + console.log('lol wut', selectedAssetIfExists.assetData); + console.log(selectedAssetIfExists.assetData); + console.log(swapQuote.makerAssetData); // if swapQuote's assetData does not match that of the current selected asset, return false if (selectedAssetIfExists.assetData !== swapQuote.makerAssetData) { return false; @@ -290,13 +295,14 @@ const doesSwapQuoteMatchState = (swapQuote: MarketBuySwapQuote, state: State): b // if ERC20 and swapQuote's makerAssetFillAmount does not match selectedAssetAmount, return false // if ERC721, return true const selectedAssetMetaData = selectedAssetIfExists.metaData; + console.log('here then'); if (selectedAssetMetaData.assetProxyId === AssetProxyId.ERC20) { const selectedAssetAmountBaseUnits = Web3Wrapper.toBaseUnitAmount( selectedAssetUnitAmountIfExists, selectedAssetMetaData.decimals, ); const doesAssetAmountMatch = selectedAssetAmountBaseUnits.eq(swapQuote.makerAssetFillAmount); - + console.log('doesAssetAmountMatch', doesAssetAmountMatch); return doesAssetAmountMatch; } else { return true; diff --git a/packages/instant/src/util/provider_state_factory.ts b/packages/instant/src/util/provider_state_factory.ts index a504453756..65cf36e67b 100644 --- a/packages/instant/src/util/provider_state_factory.ts +++ b/packages/instant/src/util/provider_state_factory.ts @@ -82,42 +82,26 @@ export const providerStateFactory = { network: Network, walletDisplayName?: string, ): ProviderState => { - // Uses fortmatic as default provider - const fm = new Fortmatic(FORTMATIC_API_KEY); - if (fm) { - const fmProvider = fm.getProvider(); - const providerState: ProviderState = { - displayName: envUtil.getProviderDisplayName(fmProvider), - name: envUtil.getProviderName(fmProvider), - provider: fmProvider, - web3Wrapper: new Web3Wrapper(fmProvider), - swapQuoter: assetSwapperFactory.getSwapQuoter(fm, orderSource, network), - swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(fm, network), - account: NO_ACCOUNT, - orderSource, - }; - return providerState; - } else { - const provider = providerFactory.getFallbackNoSigningProvider(network); - const providerState: ProviderState = { - name: 'Fallback', - displayName: walletDisplayName || envUtil.getProviderDisplayName(provider), - provider, - web3Wrapper: new Web3Wrapper(provider), - swapQuoter: assetSwapperFactory.getSwapQuoter(provider, orderSource, network), - swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(provider, network), - account: NO_ACCOUNT, - orderSource, - }; - return providerState; - } + const provider = providerFactory.getFallbackNoSigningProvider(network); + const providerState: ProviderState = { + name: 'Fallback', + displayName: walletDisplayName || envUtil.getProviderDisplayName(provider), + provider, + web3Wrapper: new Web3Wrapper(provider), + swapQuoter: assetSwapperFactory.getSwapQuoter(provider, orderSource, network), + swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(provider, network), + account: NO_ACCOUNT, + orderSource, + }; + return providerState; }, getProviderStateBasedOnProviderType: ( currentProviderState: ProviderState, providerType: ProviderType, ): ProviderState => { let providerState = currentProviderState; - const network = currentProviderState.swapQuoter.networkId; + console.log('lets see', providerState, providerType); + const chainId = currentProviderState.swapQuoter.chainId; const orderSource = currentProviderState.orderSource; // Returns current provider if the provider type selected is not found if (providerType === ProviderType.MetaMask) { @@ -128,8 +112,8 @@ export const providerStateFactory = { name: envUtil.getProviderName(provider), provider, web3Wrapper: new Web3Wrapper(provider), - swapQuoter: assetSwapperFactory.getSwapQuoter(provider, orderSource, network), - swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(provider, network), + swapQuoter: assetSwapperFactory.getSwapQuoter(provider, orderSource, chainId), + swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(provider, chainId), account: LOADING_ACCOUNT, orderSource, }; @@ -143,8 +127,8 @@ export const providerStateFactory = { name: envUtil.getProviderName(fmProvider), provider: fmProvider, web3Wrapper: new Web3Wrapper(fmProvider), - swapQuoter: assetSwapperFactory.getSwapQuoter(fmProvider, orderSource, network), - swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(fmProvider, network), + swapQuoter: assetSwapperFactory.getSwapQuoter(fmProvider, orderSource, chainId), + swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(fmProvider, chainId), account: LOADING_ACCOUNT, orderSource, }; diff --git a/packages/instant/src/util/swap_quote_updater.ts b/packages/instant/src/util/swap_quote_updater.ts index 88f9b04188..f26bc499d6 100644 --- a/packages/instant/src/util/swap_quote_updater.ts +++ b/packages/instant/src/util/swap_quote_updater.ts @@ -69,6 +69,7 @@ export const swapQuoteUpdater = { // We have a successful new swap quote errorFlasher.clearError(dispatch); // invalidate the last swap quote. + console.log('newSwapQuote', newSwapQuote); dispatch(actions.updateLatestSwapQuote(newSwapQuote)); analytics.trackQuoteFetched(newSwapQuote, fetchOrigin); }, From f839a3087d00671b6c9f1c138ff84c914923e0ce Mon Sep 17 00:00:00 2001 From: David Sun Date: Thu, 19 Dec 2019 20:26:43 -0800 Subject: [PATCH 20/29] add yarn.lock --- yarn.lock | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 9eaeb2e857..b2b3fbac28 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7765,9 +7765,10 @@ format-util@^1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/format-util/-/format-util-1.0.3.tgz#032dca4a116262a12c43f4c3ec8566416c5b2d95" -fortmatic@^0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/fortmatic/-/fortmatic-0.8.2.tgz#a93fc97d1a1808faf82210d6554e1ebdcb6c5379" +fortmatic@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fortmatic/-/fortmatic-1.0.1.tgz#ecb2c6777cd25658befe5e86c5eeddcb6c4db472" + integrity sha512-D48g0talOofK6AdwppO2VL/rRjLZb69Qf6fBR1lYUZ2rqMCM8WbBqoEDgFgJyjO1YV7XCJGbm+mW0/y2RxxbEg== dependencies: "@babel/runtime" "7.3.4" From 02e21141c67b888a13ca774c820110ebe6b8b970 Mon Sep 17 00:00:00 2001 From: David Sun Date: Sun, 5 Jan 2020 19:00:59 -0800 Subject: [PATCH 21/29] added minor polish + bug fixes --- .../instant/src/components/buy_button.tsx | 8 +++ .../instant/src/components/order_details.tsx | 3 +- .../instant/src/components/payment_method.tsx | 52 +++++++------------ packages/instant/src/redux/reducer.ts | 7 --- .../src/util/provider_state_factory.ts | 1 - .../instant/src/util/swap_quote_updater.ts | 1 - 6 files changed, 29 insertions(+), 43 deletions(-) diff --git a/packages/instant/src/components/buy_button.tsx b/packages/instant/src/components/buy_button.tsx index cfd7a76cb8..677bd53d11 100644 --- a/packages/instant/src/components/buy_button.tsx +++ b/packages/instant/src/components/buy_button.tsx @@ -132,6 +132,14 @@ export class BuyButton extends React.PureComponent { this.props.onSignatureDenied(swapQuote); return; } + // Fortmatic specific error handling + if (e.message && e.message.includes('Fortmatic:')) { + if (e.message.includes('User denied transaction.')) { + analytics.trackBuySignatureDenied(swapQuote); + this.props.onSignatureDenied(swapQuote); + return; + } + } throw e; } const startTimeUnix = new Date().getTime(); diff --git a/packages/instant/src/components/order_details.tsx b/packages/instant/src/components/order_details.tsx index 4c693385bd..b0df6297c9 100644 --- a/packages/instant/src/components/order_details.tsx +++ b/packages/instant/src/components/order_details.tsx @@ -6,7 +6,7 @@ import { oc } from 'ts-optchain'; import { BIG_NUMBER_ZERO, DEFAULT_UNKOWN_ASSET_NAME } from '../constants'; import { ColorOption } from '../style/theme'; -import {Account, AccountState, BaseCurrency} from '../types'; +import { Account, AccountState, BaseCurrency } from '../types'; import { format } from '../util/format'; import { AmountPlaceholder } from './amount_placeholder'; @@ -45,7 +45,6 @@ export class OrderDetails extends React.PureComponent { private _renderRows(): React.ReactNode { const { swapQuoteInfo } = this.props; - console.log(swapQuoteInfo); return ( { return 'payment method'; } }; - private readonly _renderTitleLabel = (): React.ReactNode => { - const { account } = this.props; - if (account.state === AccountState.Ready || account.state === AccountState.Locked) { - const circleColor: ColorOption = account.state === AccountState.Ready ? ColorOption.green : ColorOption.red; - return ( - - - - - {this.props.walletDisplayName} - - - - ); - } - return null; - }; private readonly _renderMainContent = (): React.ReactNode => { const { account, network } = this.props; const isMobile = envUtil.isMobileOperatingSystem(); @@ -93,12 +74,12 @@ export class PaymentMethod extends React.PureComponent { padding="15px 18px" image={ - {metamaskLogo} + {logo} } {...colors} > - Metamask + {isMobile ? 'Coinbase Wallet' : 'MetaMask'} { case AccountState.None: return ( - + {isMobile ? 'Install Coinbase Wallet' : 'Install MetaMask'} { const newSwapQuoteIfExists = action.data; const shouldUpdate = newSwapQuoteIfExists === undefined || doesSwapQuoteMatchState(newSwapQuoteIfExists, state); - console.log('shouldUpdate', newSwapQuoteIfExists, shouldUpdate); if (shouldUpdate) { return { ...state, @@ -281,13 +280,9 @@ const doesSwapQuoteMatchState = (swapQuote: MarketBuySwapQuote, state: State): b const selectedAssetIfExists = state.selectedAsset; const selectedAssetUnitAmountIfExists = state.selectedAssetUnitAmount; // if no selectedAsset or selectedAssetAmount exists on the current state, return false - console.log('hmmmm?'); if (selectedAssetIfExists === undefined || selectedAssetUnitAmountIfExists === undefined) { return false; } - console.log('lol wut', selectedAssetIfExists.assetData); - console.log(selectedAssetIfExists.assetData); - console.log(swapQuote.makerAssetData); // if swapQuote's assetData does not match that of the current selected asset, return false if (selectedAssetIfExists.assetData !== swapQuote.makerAssetData) { return false; @@ -295,14 +290,12 @@ const doesSwapQuoteMatchState = (swapQuote: MarketBuySwapQuote, state: State): b // if ERC20 and swapQuote's makerAssetFillAmount does not match selectedAssetAmount, return false // if ERC721, return true const selectedAssetMetaData = selectedAssetIfExists.metaData; - console.log('here then'); if (selectedAssetMetaData.assetProxyId === AssetProxyId.ERC20) { const selectedAssetAmountBaseUnits = Web3Wrapper.toBaseUnitAmount( selectedAssetUnitAmountIfExists, selectedAssetMetaData.decimals, ); const doesAssetAmountMatch = selectedAssetAmountBaseUnits.eq(swapQuote.makerAssetFillAmount); - console.log('doesAssetAmountMatch', doesAssetAmountMatch); return doesAssetAmountMatch; } else { return true; diff --git a/packages/instant/src/util/provider_state_factory.ts b/packages/instant/src/util/provider_state_factory.ts index 65cf36e67b..4f63d49486 100644 --- a/packages/instant/src/util/provider_state_factory.ts +++ b/packages/instant/src/util/provider_state_factory.ts @@ -100,7 +100,6 @@ export const providerStateFactory = { providerType: ProviderType, ): ProviderState => { let providerState = currentProviderState; - console.log('lets see', providerState, providerType); const chainId = currentProviderState.swapQuoter.chainId; const orderSource = currentProviderState.orderSource; // Returns current provider if the provider type selected is not found diff --git a/packages/instant/src/util/swap_quote_updater.ts b/packages/instant/src/util/swap_quote_updater.ts index f26bc499d6..88f9b04188 100644 --- a/packages/instant/src/util/swap_quote_updater.ts +++ b/packages/instant/src/util/swap_quote_updater.ts @@ -69,7 +69,6 @@ export const swapQuoteUpdater = { // We have a successful new swap quote errorFlasher.clearError(dispatch); // invalidate the last swap quote. - console.log('newSwapQuote', newSwapQuote); dispatch(actions.updateLatestSwapQuote(newSwapQuote)); analytics.trackQuoteFetched(newSwapQuote, fetchOrigin); }, From d590b004c1b81aa9b2692956da16dd394c4dfaa2 Mon Sep 17 00:00:00 2001 From: David Sun Date: Wed, 8 Jan 2020 12:57:14 -0800 Subject: [PATCH 22/29] incomplete, fixes for heartbeater --- .../instant/src/components/coinbase_wallet_logo.tsx | 6 ++++-- packages/instant/src/components/payment_method.tsx | 2 +- packages/instant/src/redux/actions.ts | 2 ++ packages/instant/src/redux/async_data.ts | 7 ++++++- packages/instant/src/redux/reducer.ts | 4 +++- packages/instant/src/types.ts | 2 +- packages/instant/src/util/heartbeater_factory.ts | 1 + packages/instant/src/util/provider_state_factory.ts | 11 +++++++---- 8 files changed, 25 insertions(+), 10 deletions(-) diff --git a/packages/instant/src/components/coinbase_wallet_logo.tsx b/packages/instant/src/components/coinbase_wallet_logo.tsx index 845b96d732..4040a03dfb 100644 --- a/packages/instant/src/components/coinbase_wallet_logo.tsx +++ b/packages/instant/src/components/coinbase_wallet_logo.tsx @@ -2,10 +2,11 @@ import * as React from 'react'; export interface CoinbaseWalletLogoProps { width?: number; + height?: number; } -export const CoinbaseWalletLogo: React.StatelessComponent = ({ width }) => ( - +export const CoinbaseWalletLogo: React.StatelessComponent = ({ width, height }) => ( + { const { account, network } = this.props; const isMobile = envUtil.isMobileOperatingSystem(); const metamaskLogo = ; - const logo = isMobile ? : metamaskLogo; + const logo = isMobile ? : metamaskLogo; const primaryColor = ColorOption.grey; const secondaryColor = ColorOption.whiteBackground; const colors = { primaryColor, secondaryColor }; diff --git a/packages/instant/src/redux/actions.ts b/packages/instant/src/redux/actions.ts index a8498be5c9..a854fe2afc 100644 --- a/packages/instant/src/redux/actions.ts +++ b/packages/instant/src/redux/actions.ts @@ -30,6 +30,7 @@ export enum ActionTypes { SetAccountStateLoading = 'SET_ACCOUNT_STATE_LOADING', SetAccountStateLocked = 'SET_ACCOUNT_STATE_LOCKED', SetAccountStateReady = 'SET_ACCOUNT_STATE_READY', + SetAccountStateNone = 'SET_ACCOUNT_STATE_NONE', UpdateAccountEthBalance = 'UPDATE_ACCOUNT_ETH_BALANCE', UpdateEthUsdPrice = 'UPDATE_ETH_USD_PRICE', UpdateSelectedAssetUnitAmount = 'UPDATE_SELECTED_ASSET_UNIT_AMOUNT', @@ -56,6 +57,7 @@ export enum ActionTypes { export const actions = { setAccountStateLoading: () => createAction(ActionTypes.SetAccountStateLoading), setAccountStateLocked: () => createAction(ActionTypes.SetAccountStateLocked), + setAccountStateNone: () => createAction(ActionTypes.SetAccountStateNone), setAccountStateReady: (address: string) => createAction(ActionTypes.SetAccountStateReady, address), updateAccountEthBalance: (addressAndBalance: AddressAndEthBalanceInWei) => createAction(ActionTypes.UpdateAccountEthBalance, addressAndBalance), diff --git a/packages/instant/src/redux/async_data.ts b/packages/instant/src/redux/async_data.ts index c793289052..e1dd0a774a 100644 --- a/packages/instant/src/redux/async_data.ts +++ b/packages/instant/src/redux/async_data.ts @@ -66,6 +66,7 @@ export const asyncData = { if (shouldSetToLoading && providerState.account.state !== AccountState.Loading) { dispatch(actions.setAccountStateLoading()); } + console.log('providerState', providerState); let availableAddresses: string[] = []; try { // TODO(bmillman): Add support at the web3Wrapper level for calling `eth_requestAccounts` instead of calling enable here @@ -80,7 +81,11 @@ export const asyncData = { } } catch (e) { analytics.trackAccountUnlockDenied(); - dispatch(actions.setAccountStateLocked()); + if (e.message.includes('Fortmatic: User denied account access.')) { + dispatch(actions.setAccountStateNone()); + } else { + dispatch(actions.setAccountStateLocked()); + } return; } if (!_.isEmpty(availableAddresses)) { diff --git a/packages/instant/src/redux/reducer.ts b/packages/instant/src/redux/reducer.ts index e7d53778b2..343c4e6707 100644 --- a/packages/instant/src/redux/reducer.ts +++ b/packages/instant/src/redux/reducer.ts @@ -4,7 +4,7 @@ import { BigNumber } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; import * as _ from 'lodash'; -import { LOADING_ACCOUNT, LOCKED_ACCOUNT } from '../constants'; +import { LOADING_ACCOUNT, LOCKED_ACCOUNT, NO_ACCOUNT } from '../constants'; import { assetMetaDataMap } from '../data/asset_meta_data_map'; import { Account, @@ -77,6 +77,8 @@ export const createReducer = (initialState: State) => { return reduceStateWithAccount(state, LOADING_ACCOUNT); case ActionTypes.SetAccountStateLocked: return reduceStateWithAccount(state, LOCKED_ACCOUNT); + case ActionTypes.SetAccountStateNone: + return reduceStateWithAccount(state, NO_ACCOUNT); case ActionTypes.SetAccountStateReady: { const address = action.data; let newAccount: AccountReady = { diff --git a/packages/instant/src/types.ts b/packages/instant/src/types.ts index c37bd1d586..0b3ef2223d 100644 --- a/packages/instant/src/types.ts +++ b/packages/instant/src/types.ts @@ -118,7 +118,7 @@ export interface ProviderState { } export enum AccountState { - None = 'NONE,', + None = 'NONE', Loading = 'LOADING', Ready = 'READY', Locked = 'LOCKED', diff --git a/packages/instant/src/util/heartbeater_factory.ts b/packages/instant/src/util/heartbeater_factory.ts index c80eccd8b2..737ae1764d 100644 --- a/packages/instant/src/util/heartbeater_factory.ts +++ b/packages/instant/src/util/heartbeater_factory.ts @@ -11,6 +11,7 @@ export interface HeartbeatFactoryOptions { export const generateAccountHeartbeater = (options: HeartbeatFactoryOptions): Heartbeater => { const { store, shouldPerformImmediatelyOnStart } = options; return new Heartbeater(async () => { + console.log('beat'); await asyncData.fetchAccountInfoAndDispatchToStore(store.getState().providerState, store.dispatch, false); }, shouldPerformImmediatelyOnStart); }; diff --git a/packages/instant/src/util/provider_state_factory.ts b/packages/instant/src/util/provider_state_factory.ts index 4f63d49486..8e006d6dea 100644 --- a/packages/instant/src/util/provider_state_factory.ts +++ b/packages/instant/src/util/provider_state_factory.ts @@ -83,6 +83,7 @@ export const providerStateFactory = { walletDisplayName?: string, ): ProviderState => { const provider = providerFactory.getFallbackNoSigningProvider(network); + console.log(walletDisplayName, envUtil.getProviderDisplayName(provider)); const providerState: ProviderState = { name: 'Fallback', displayName: walletDisplayName || envUtil.getProviderDisplayName(provider), @@ -99,14 +100,13 @@ export const providerStateFactory = { currentProviderState: ProviderState, providerType: ProviderType, ): ProviderState => { - let providerState = currentProviderState; const chainId = currentProviderState.swapQuoter.chainId; const orderSource = currentProviderState.orderSource; // Returns current provider if the provider type selected is not found if (providerType === ProviderType.MetaMask) { const provider = providerFactory.getInjectedProviderIfExists(); if (provider) { - providerState = { + return { displayName: envUtil.getProviderDisplayName(provider), name: envUtil.getProviderName(provider), provider, @@ -121,7 +121,7 @@ export const providerStateFactory = { if (providerType === ProviderType.Fortmatic) { const fm = new Fortmatic(FORTMATIC_API_KEY); const fmProvider = fm.getProvider(); - providerState = { + return { displayName: envUtil.getProviderDisplayName(fmProvider), name: envUtil.getProviderName(fmProvider), provider: fmProvider, @@ -132,6 +132,9 @@ export const providerStateFactory = { orderSource, }; } - return providerState; + return providerStateFactory.getInitialProviderState( + orderSource, + chainId, + ); }, }; From f3b8ae0781a9e18919531476724f59a69f14a95d Mon Sep 17 00:00:00 2001 From: David Sun Date: Sun, 2 Feb 2020 18:28:26 -0500 Subject: [PATCH 23/29] fix for fortmatic --- packages/instant/src/redux/async_data.ts | 20 +++++++------ packages/instant/src/types.ts | 1 + packages/instant/src/util/env.ts | 5 ++-- .../instant/src/util/heartbeater_factory.ts | 1 - .../src/util/provider_state_factory.ts | 28 ++++++++++++++++++- 5 files changed, 42 insertions(+), 13 deletions(-) diff --git a/packages/instant/src/redux/async_data.ts b/packages/instant/src/redux/async_data.ts index e1dd0a774a..55b8fead36 100644 --- a/packages/instant/src/redux/async_data.ts +++ b/packages/instant/src/redux/async_data.ts @@ -13,6 +13,7 @@ import { swapQuoteUpdater } from '../util/swap_quote_updater'; import { actions } from './actions'; import { State } from './reducer'; +import { providerStateFactory } from '../util/provider_state_factory'; export const asyncData = { fetchEthPriceAndDispatchToStore: async (dispatch: Dispatch) => { @@ -71,18 +72,19 @@ export const asyncData = { try { // TODO(bmillman): Add support at the web3Wrapper level for calling `eth_requestAccounts` instead of calling enable here const isPrivacyModeEnabled = (provider as any).enable !== undefined; - if (providerState.name !== 'Fortmatic') { - availableAddresses = - isPrivacyModeEnabled && shouldAttemptUnlock - ? await (provider as any).enable() - : await web3Wrapper.getAvailableAddressesAsync(); - } else { - availableAddresses = await web3Wrapper.getAvailableAddressesAsync(); - } + availableAddresses = + isPrivacyModeEnabled && shouldAttemptUnlock + ? await (provider as any).enable() + : await web3Wrapper.getAvailableAddressesAsync(); + console.log(availableAddresses); } catch (e) { analytics.trackAccountUnlockDenied(); if (e.message.includes('Fortmatic: User denied account access.')) { - dispatch(actions.setAccountStateNone()); + // If Fortmatic is not used, revert to injected provider + const initialProviderState = providerStateFactory.getInitialProviderStateWithCurrentProviderState( + providerState, + ); + dispatch(actions.setProviderState(initialProviderState)); } else { dispatch(actions.setAccountStateLocked()); } diff --git a/packages/instant/src/types.ts b/packages/instant/src/types.ts index 0b3ef2223d..e1a9361a3e 100644 --- a/packages/instant/src/types.ts +++ b/packages/instant/src/types.ts @@ -115,6 +115,7 @@ export interface ProviderState { web3Wrapper: Web3Wrapper; account: Account; orderSource: OrderSource; + isProviderInjected: boolean; } export enum AccountState { diff --git a/packages/instant/src/util/env.ts b/packages/instant/src/util/env.ts index 412e24725c..fd5e36df22 100644 --- a/packages/instant/src/util/env.ts +++ b/packages/instant/src/util/env.ts @@ -51,6 +51,8 @@ export const envUtil = { return ProviderType.Parity; } else if (anyProvider.isMetaMask) { return ProviderType.MetaMask; + } else if (anyProvider.isFortmatic) { + return ProviderType.Fortmatic; } else if (_.get(window, 'SOFA') !== undefined) { return ProviderType.CoinbaseWallet; } else if (_.get(window, '__CIPHER__') !== undefined) { @@ -58,8 +60,7 @@ export const envUtil = { } else if (envUtil.getBrowser() === Browser.Opera && !anyProvider.isMetaMask) { return ProviderType.Opera; } - // If the provider is not supported by 0x, use fortmatic - return ProviderType.Fortmatic; + return undefined; }, getProviderName(provider: ZeroExProvider): string { const providerTypeIfExists = envUtil.getProviderType(provider); diff --git a/packages/instant/src/util/heartbeater_factory.ts b/packages/instant/src/util/heartbeater_factory.ts index 737ae1764d..c80eccd8b2 100644 --- a/packages/instant/src/util/heartbeater_factory.ts +++ b/packages/instant/src/util/heartbeater_factory.ts @@ -11,7 +11,6 @@ export interface HeartbeatFactoryOptions { export const generateAccountHeartbeater = (options: HeartbeatFactoryOptions): Heartbeater => { const { store, shouldPerformImmediatelyOnStart } = options; return new Heartbeater(async () => { - console.log('beat'); await asyncData.fetchAccountInfoAndDispatchToStore(store.getState().providerState, store.dispatch, false); }, shouldPerformImmediatelyOnStart); }; diff --git a/packages/instant/src/util/provider_state_factory.ts b/packages/instant/src/util/provider_state_factory.ts index 8e006d6dea..0b42bce3ef 100644 --- a/packages/instant/src/util/provider_state_factory.ts +++ b/packages/instant/src/util/provider_state_factory.ts @@ -52,6 +52,7 @@ export const providerStateFactory = { swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(provider, network), account: LOADING_ACCOUNT, orderSource, + isProviderInjected: false, }; return providerState; }, @@ -71,6 +72,7 @@ export const providerStateFactory = { swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(injectedProviderIfExists, network), account: LOADING_ACCOUNT, orderSource, + isProviderInjected: true, }; return providerState; } else { @@ -83,7 +85,6 @@ export const providerStateFactory = { walletDisplayName?: string, ): ProviderState => { const provider = providerFactory.getFallbackNoSigningProvider(network); - console.log(walletDisplayName, envUtil.getProviderDisplayName(provider)); const providerState: ProviderState = { name: 'Fallback', displayName: walletDisplayName || envUtil.getProviderDisplayName(provider), @@ -93,9 +94,32 @@ export const providerStateFactory = { swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(provider, network), account: NO_ACCOUNT, orderSource, + isProviderInjected: true, }; return providerState; }, + // function to call getInitialProviderState with parameters retreived from a provided ProviderState + getInitialProviderStateWithCurrentProviderState: ( + currentProviderState: ProviderState, + ): ProviderState => { + const orderSource = currentProviderState.orderSource; + const chainId = currentProviderState.swapQuoter.chainId; + // If provider is provided to instant, use that and the displayName + if (!currentProviderState.isProviderInjected) { + return providerStateFactory.getInitialProviderState( + orderSource, + chainId, + currentProviderState.provider, + currentProviderState.displayName, + ); + } + const newProviderState = providerStateFactory.getInitialProviderState( + orderSource, + chainId, + ); + newProviderState.account = NO_ACCOUNT; + return newProviderState; + }, getProviderStateBasedOnProviderType: ( currentProviderState: ProviderState, providerType: ProviderType, @@ -115,6 +139,7 @@ export const providerStateFactory = { swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(provider, chainId), account: LOADING_ACCOUNT, orderSource, + isProviderInjected: true, }; } } @@ -130,6 +155,7 @@ export const providerStateFactory = { swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(fmProvider, chainId), account: LOADING_ACCOUNT, orderSource, + isProviderInjected: true, }; } return providerStateFactory.getInitialProviderState( From 21058c22278b7d951e7f8d31eefbb205c5293174 Mon Sep 17 00:00:00 2001 From: David Sun Date: Sun, 2 Feb 2020 18:36:55 -0500 Subject: [PATCH 24/29] changes to fetch account state behavior --- packages/instant/src/redux/async_data.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/instant/src/redux/async_data.ts b/packages/instant/src/redux/async_data.ts index 55b8fead36..204599ed97 100644 --- a/packages/instant/src/redux/async_data.ts +++ b/packages/instant/src/redux/async_data.ts @@ -67,7 +67,6 @@ export const asyncData = { if (shouldSetToLoading && providerState.account.state !== AccountState.Loading) { dispatch(actions.setAccountStateLoading()); } - console.log('providerState', providerState); let availableAddresses: string[] = []; try { // TODO(bmillman): Add support at the web3Wrapper level for calling `eth_requestAccounts` instead of calling enable here @@ -76,7 +75,6 @@ export const asyncData = { isPrivacyModeEnabled && shouldAttemptUnlock ? await (provider as any).enable() : await web3Wrapper.getAvailableAddressesAsync(); - console.log(availableAddresses); } catch (e) { analytics.trackAccountUnlockDenied(); if (e.message.includes('Fortmatic: User denied account access.')) { From 3b0c8f6d9287341c0e422da3388d872706a6ba12 Mon Sep 17 00:00:00 2001 From: David Sun Date: Sun, 9 Feb 2020 20:45:24 -0500 Subject: [PATCH 25/29] fortmatic patches --- packages/instant/src/redux/async_data.ts | 29 ++++++++++++------- .../src/util/provider_state_factory.ts | 26 ++++++----------- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/packages/instant/src/redux/async_data.ts b/packages/instant/src/redux/async_data.ts index 204599ed97..70ee768ae2 100644 --- a/packages/instant/src/redux/async_data.ts +++ b/packages/instant/src/redux/async_data.ts @@ -9,11 +9,11 @@ import { assetUtils } from '../util/asset'; import { coinbaseApi } from '../util/coinbase_api'; import { errorFlasher } from '../util/error_flasher'; import { errorReporter } from '../util/error_reporter'; +import { providerStateFactory } from '../util/provider_state_factory'; import { swapQuoteUpdater } from '../util/swap_quote_updater'; import { actions } from './actions'; import { State } from './reducer'; -import { providerStateFactory } from '../util/provider_state_factory'; export const asyncData = { fetchEthPriceAndDispatchToStore: async (dispatch: Dispatch) => { @@ -60,21 +60,28 @@ export const asyncData = { providerState: ProviderState, dispatch: Dispatch, shouldAttemptUnlock: boolean = false, - shouldSetToLoading: boolean = false, ) => { const web3Wrapper = providerState.web3Wrapper; const provider = providerState.provider; - if (shouldSetToLoading && providerState.account.state !== AccountState.Loading) { + let availableAddresses: string[] = []; + if (shouldAttemptUnlock && providerState.account.state !== AccountState.Loading) { dispatch(actions.setAccountStateLoading()); } - let availableAddresses: string[] = []; try { - // TODO(bmillman): Add support at the web3Wrapper level for calling `eth_requestAccounts` instead of calling enable here - const isPrivacyModeEnabled = (provider as any).enable !== undefined; - availableAddresses = - isPrivacyModeEnabled && shouldAttemptUnlock - ? await (provider as any).enable() - : await web3Wrapper.getAvailableAddressesAsync(); + // HACK: Fortmatic's getAvailableAddressesAsync behaves in ways that default wallet behavior can't handle + if ((provider as any).isFortmatic) { + availableAddresses = + (provider as any).isLoggedIn || shouldAttemptUnlock + ? await web3Wrapper.getAvailableAddressesAsync() + : []; + } else { + // TODO(bmillman): Add support at the web3Wrapper level for calling `eth_requestAccounts` instead of calling enable here + const isPrivacyModeEnabled = (provider as any).enable !== undefined; + availableAddresses = + isPrivacyModeEnabled && shouldAttemptUnlock + ? await (provider as any).enable() + : await web3Wrapper.getAvailableAddressesAsync(); + } } catch (e) { analytics.trackAccountUnlockDenied(); if (e.message.includes('Fortmatic: User denied account access.')) { @@ -93,7 +100,7 @@ export const asyncData = { dispatch(actions.setAccountStateReady(activeAddress)); // tslint:disable-next-line:no-floating-promises asyncData.fetchAccountBalanceAndDispatchToStore(activeAddress, providerState.web3Wrapper, dispatch); - } else { + } else if (providerState.account.state !== AccountState.Loading) { dispatch(actions.setAccountStateLocked()); } }, diff --git a/packages/instant/src/util/provider_state_factory.ts b/packages/instant/src/util/provider_state_factory.ts index 0b42bce3ef..d32d0178ce 100644 --- a/packages/instant/src/util/provider_state_factory.ts +++ b/packages/instant/src/util/provider_state_factory.ts @@ -3,7 +3,7 @@ import { Web3Wrapper } from '@0x/web3-wrapper'; import { SupportedProvider, ZeroExProvider } from 'ethereum-types'; import * as Fortmatic from 'fortmatic'; -import { FORTMATIC_API_KEY, LOADING_ACCOUNT, NO_ACCOUNT } from '../constants'; +import { FORTMATIC_API_KEY, LOCKED_ACCOUNT, NO_ACCOUNT } from '../constants'; import { Maybe, Network, OrderSource, ProviderState, ProviderType } from '../types'; import { envUtil } from '../util/env'; @@ -50,7 +50,7 @@ export const providerStateFactory = { web3Wrapper: new Web3Wrapper(provider), swapQuoter: assetSwapperFactory.getSwapQuoter(provider, orderSource, network), swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(provider, network), - account: LOADING_ACCOUNT, + account: LOCKED_ACCOUNT, orderSource, isProviderInjected: false, }; @@ -70,7 +70,7 @@ export const providerStateFactory = { web3Wrapper: new Web3Wrapper(injectedProviderIfExists), swapQuoter: assetSwapperFactory.getSwapQuoter(injectedProviderIfExists, orderSource, network), swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(injectedProviderIfExists, network), - account: LOADING_ACCOUNT, + account: LOCKED_ACCOUNT, orderSource, isProviderInjected: true, }; @@ -99,9 +99,7 @@ export const providerStateFactory = { return providerState; }, // function to call getInitialProviderState with parameters retreived from a provided ProviderState - getInitialProviderStateWithCurrentProviderState: ( - currentProviderState: ProviderState, - ): ProviderState => { + getInitialProviderStateWithCurrentProviderState: (currentProviderState: ProviderState): ProviderState => { const orderSource = currentProviderState.orderSource; const chainId = currentProviderState.swapQuoter.chainId; // If provider is provided to instant, use that and the displayName @@ -113,11 +111,8 @@ export const providerStateFactory = { currentProviderState.displayName, ); } - const newProviderState = providerStateFactory.getInitialProviderState( - orderSource, - chainId, - ); - newProviderState.account = NO_ACCOUNT; + const newProviderState = providerStateFactory.getInitialProviderState(orderSource, chainId); + newProviderState.account = LOCKED_ACCOUNT; return newProviderState; }, getProviderStateBasedOnProviderType: ( @@ -137,7 +132,7 @@ export const providerStateFactory = { web3Wrapper: new Web3Wrapper(provider), swapQuoter: assetSwapperFactory.getSwapQuoter(provider, orderSource, chainId), swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(provider, chainId), - account: LOADING_ACCOUNT, + account: LOCKED_ACCOUNT, orderSource, isProviderInjected: true, }; @@ -153,14 +148,11 @@ export const providerStateFactory = { web3Wrapper: new Web3Wrapper(fmProvider), swapQuoter: assetSwapperFactory.getSwapQuoter(fmProvider, orderSource, chainId), swapQuoteConsumer: assetSwapperFactory.getSwapQuoteConsumer(fmProvider, chainId), - account: LOADING_ACCOUNT, + account: LOCKED_ACCOUNT, orderSource, isProviderInjected: true, }; } - return providerStateFactory.getInitialProviderState( - orderSource, - chainId, - ); + return providerStateFactory.getInitialProviderState(orderSource, chainId); }, }; From 5902d878d868a9a50b99d5e251a16a9f6a239f46 Mon Sep 17 00:00:00 2001 From: David Sun Date: Tue, 18 Feb 2020 12:13:38 -0500 Subject: [PATCH 26/29] fixed affiliate + fortmatic --- packages/instant/src/components/buy_button.tsx | 5 +++-- packages/instant/src/constants.ts | 10 ++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/instant/src/components/buy_button.tsx b/packages/instant/src/components/buy_button.tsx index 677bd53d11..b34bbc6521 100644 --- a/packages/instant/src/components/buy_button.tsx +++ b/packages/instant/src/components/buy_button.tsx @@ -13,7 +13,7 @@ import * as _ from 'lodash'; import * as React from 'react'; import { oc } from 'ts-optchain'; -import { WEB_3_WRAPPER_TRANSACTION_FAILED_ERROR_MSG_PREFIX } from '../constants'; +import { DEFAULT_AFFILIATE_INFO, WEB_3_WRAPPER_TRANSACTION_FAILED_ERROR_MSG_PREFIX } from '../constants'; import { ColorOption } from '../style/theme'; import { AffiliateInfo, Asset, ZeroExInstantError } from '../types'; import { analytics } from '../util/analytics'; @@ -77,7 +77,7 @@ export class BuyButton extends React.PureComponent { const { swapQuote, swapQuoteConsumer, - affiliateInfo, + affiliateInfo= DEFAULT_AFFILIATE_INFO, accountAddress, accountEthBalanceInWei, web3Wrapper, @@ -109,6 +109,7 @@ export class BuyButton extends React.PureComponent { takerAddress: accountAddress, }); } catch (e) { + console.log(e); if (e instanceof Error) { if (e.message === SwapQuoteConsumerError.TransactionValueTooLow) { analytics.trackBuySimulationFailed(swapQuote); diff --git a/packages/instant/src/constants.ts b/packages/instant/src/constants.ts index d8700c6353..69045b8bc7 100644 --- a/packages/instant/src/constants.ts +++ b/packages/instant/src/constants.ts @@ -1,6 +1,6 @@ import { BigNumber } from '@0x/utils'; -import { AccountNotReady, AccountState, Network, ProviderType } from './types'; +import { AccountNotReady, AccountState, AffiliateInfo, Network, ProviderType } from './types'; // TODO(dave4506) until we have /prices endpoint ready, we will use this whitelist for bridge order liquidity assets export const SUPPORTED_TOKEN_ASSET_DATA_WITH_BRIDGE_ORDERS = [ @@ -94,4 +94,10 @@ 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 || 'pk_live_43E27F282B16AA8C'; +export const NULL_ADDRESS = '0x0000000000000000000000000000000000000000'; +export const DEFAULT_AFFILIATE_INFO: AffiliateInfo = { + feeRecipient: NULL_ADDRESS, + feePercentage: 0, +}; + +export const FORTMATIC_API_KEY = process.env.INSTANT_FORTMATIC_API_KEY; From bc096554b5a617a42adf34c06c912c1cf636ddd5 Mon Sep 17 00:00:00 2001 From: David Sun Date: Tue, 18 Feb 2020 13:58:22 -0500 Subject: [PATCH 27/29] fixed webpack issues --- packages/instant/.env_example | 5 +++-- packages/instant/webpack.config.js | 7 +++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/instant/.env_example b/packages/instant/.env_example index abec4e5970..60c8fa70ef 100644 --- a/packages/instant/.env_example +++ b/packages/instant/.env_example @@ -2,9 +2,10 @@ INSTANT_ROLLBAR_PUBLISH_TOKEN= INSTANT_ROLLBAR_CLIENT_TOKEN= INSTANT_HEAP_ANALYTICS_ID_PRODUCTION= INSTANT_HEAP_ANALYTICS_ID_DEVELOPMENT= +INSTANT_FORTMATIC_API_KEY_PRODUCTION= +INSTANT_FORTMATIC_API_KEY_DEVELOPMENT= INSTANT_INFURA_PROJECT_ID_PRODUCTION= INSTANT_INFURA_PROJECT_ID_DEVELOPMENT= # if you want to report to heap or rollbar when building in development mode, you can use the following: # INSTANT_HEAP_FORCE_DEVELOPMENT=true -# INSTANT_ROLLBAR_FORCE_DEVELOPMENT=true -INSTANT_FORTMATIC_API_KEY= +# INSTANT_ROLLBAR_FORCE_DEVELOPMENT=true \ No newline at end of file diff --git a/packages/instant/webpack.config.js b/packages/instant/webpack.config.js index b5e20d68c7..d1f91a8f9d 100644 --- a/packages/instant/webpack.config.js +++ b/packages/instant/webpack.config.js @@ -94,15 +94,18 @@ const generateConfig = (dischargeTarget, heapConfigOptions, rollbarConfigOptions ? process.env.INSTANT_INFURA_PROJECT_ID_PRODUCTION : process.env.INSTANT_INFURA_PROJECT_ID_DEVELOPMENT; - const fortmaticApiKey = process.env.INSTANT_FORTMATIC_API_KEY; + const fortmaticApiKey = + dischargeTarget === 'production' + ? process.env.INSTANT_FORTMATIC_API_KEY_PRODUCTION + : process.env.INSTANT_FORTMATIC_API_KEY_DEVELOPMENT; const envVars = { GIT_SHA: JSON.stringify(GIT_SHA), NPM_PACKAGE_VERSION: JSON.stringify(process.env.npm_package_version), ROLLBAR_ENABLED: rollbarEnabled, HEAP_ENABLED: heapEnabled, + INSTANT_FORTMATIC_API_KEY: JSON.stringify(fortmaticApiKey), INSTANT_INFURA_PROJECT_ID: JSON.stringify(infuraProjectId), - INSTANT_FORTMATIC_API_KEY: fortmaticApiKey, }; if (dischargeTarget) { envVars.INSTANT_DISCHARGE_TARGET = JSON.stringify(dischargeTarget); From d329320fc2d5d51fae6a8a3b53e222a5563354fd Mon Sep 17 00:00:00 2001 From: David Sun Date: Tue, 18 Feb 2020 14:02:48 -0500 Subject: [PATCH 28/29] linted --- packages/instant/src/components/buy_button.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/instant/src/components/buy_button.tsx b/packages/instant/src/components/buy_button.tsx index b34bbc6521..7d57e4b3b5 100644 --- a/packages/instant/src/components/buy_button.tsx +++ b/packages/instant/src/components/buy_button.tsx @@ -109,7 +109,6 @@ export class BuyButton extends React.PureComponent { takerAddress: accountAddress, }); } catch (e) { - console.log(e); if (e instanceof Error) { if (e.message === SwapQuoteConsumerError.TransactionValueTooLow) { analytics.trackBuySimulationFailed(swapQuote); From a84b848ea9bdbdc7bb5e0c3fbf2a89d17ac55adc Mon Sep 17 00:00:00 2001 From: David Sun Date: Tue, 18 Feb 2020 14:20:30 -0500 Subject: [PATCH 29/29] prettier --- packages/instant/src/components/buy_button.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/instant/src/components/buy_button.tsx b/packages/instant/src/components/buy_button.tsx index 7d57e4b3b5..a0298626aa 100644 --- a/packages/instant/src/components/buy_button.tsx +++ b/packages/instant/src/components/buy_button.tsx @@ -77,7 +77,7 @@ export class BuyButton extends React.PureComponent { const { swapQuote, swapQuoteConsumer, - affiliateInfo= DEFAULT_AFFILIATE_INFO, + affiliateInfo = DEFAULT_AFFILIATE_INFO, accountAddress, accountEthBalanceInWei, web3Wrapper,