View on GitHub
File Changes
m
+17/-0
  // but this action updates the wallet state
  dispatch(updateHistory())
}
+

                      
+
export const checkForFlawedWallets = () => async (dispatch: Dispatch<any>) => {
+
  let isFlawed = false
+
  Logger.debug('actions::checkForFlawedWallets:: checking wallet...')
+
  try {
+
    isFlawed = await walletManager.checkForFlawedWallets()
+
    Logger.debug('actions::checkForFlawedWallets::isFlawed', isFlawed)
+
    dispatch({
+
      path: ['isFlawedWallet'],
+
      payload: isFlawed,
+
      reducer: (state, isFlawed) => isFlawed,
+
      type: 'SET_FLAWED_WALLET',
+
    })
+
  } catch (e) {
+
    Logger.warn('actions::checkForFlawedWallets error', e)
+
  }
+
}
  isFetchingPoolInfoSelector,
  totalDelegatedSelector,
  lastAccountStateFetchErrorSelector,
+
  isFlawedWalletSelector,
} from '../../selectors'
import DelegationNavigationButtons from './DelegationNavigationButtons'
import UtxoAutoRefresher from '../Send/UtxoAutoRefresher'
import {fetchAccountState} from '../../actions/account'
import {fetchUTXOs} from '../../actions/utxo'
import {fetchPoolInfo} from '../../actions/pools'
-
import {SHELLEY_WALLET_ROUTES} from '../../RoutesList'
+
import {checkForFlawedWallets} from '../../actions'
+
import {SHELLEY_WALLET_ROUTES, WALLET_INIT_ROUTES} from '../../RoutesList'
import walletManager from '../../crypto/wallet'
import globalMessages from '../../i18n/global-messages'
import {formatAdaWithText, formatAdaInteger} from '../../utils/format'
+
import FlawedWalletModal from '../TxHistory/FlawedWalletModal'

                      
import styles from './styles/DelegationSummary.style'

                      
  poolInfo: ?RemotePoolMetaSuccess,
  totalDelegated: BigNumber,
  lastAccountStateSyncError: any,
+
  checkForFlawedWallets: () => any,
+
  isFlawedWallet: boolean,
}

                      
type State = {
      1000,
    )
    this.props.fetchPoolInfo()
+
    this.props.checkForFlawedWallets()
  }

                      
  componentDidUpdate(prevProps) {
      lastAccountStateSyncError,
      isFetchingUtxos,
      intl,
+
      isFlawedWallet,
+
      navigation,
    } = this.props

                      
    const totalBalance =
      return num.toString()
    }

                      
+
    if (isFlawedWallet === true) {
+
      return (
+
        <FlawedWalletModal
+
          visible
+
          disableButtons={false}
+
          onPress={() =>
+
            navigation.navigate(WALLET_INIT_ROUTES.WALLET_SELECTION)
+
          }
+
          onRequestClose={() =>
+
            navigation.navigate(WALLET_INIT_ROUTES.WALLET_SELECTION)
+
          }
+
        />
+
      )
+
    }
+

                      
    return (
      <SafeAreaView style={styles.scrollView}>
        <StatusBar type="dark" />
        totalDelegated: totalDelegatedSelector(state),
        isOnline: isOnlineSelector(state),
        walletName: walletNameSelector(state),
+
        isFlawedWallet: isFlawedWalletSelector(state),
      }),
      {
        fetchPoolInfo,
        fetchAccountState,
        fetchUTXOs,
+
        checkForFlawedWallets,
      },
    ),
    withNavigation,
+
// @flow
+

                      
+
import React from 'react'
+
import {View, ScrollView, Image} from 'react-native'
+
import {injectIntl, defineMessages, intlShape} from 'react-intl'
+

                      
+
import {Text, Button, Modal} from '../UiKit'
+

                      
+
import styles from './styles/FlawedWalletModal.style'
+
// import image from '../../assets/img/[email protected]'
+
import image from '../../assets/img/mnemonic_explanation.png'
+

                      
+
import type {ComponentType} from 'react'
+

                      
+
const messages = defineMessages({
+
  title: {
+
    id: 'components.txhistory.flawedwalletmodal.title',
+
    defaultMessage: '!!!WARNING',
+
  },
+
  explanation1: {
+
    id: 'components.txhistory.flawedwalletmodal.explanation1',
+
    defaultMessage:
+
      '!!!It looks like you have accidentally created or restored a wallet ' +
+
      'that is only included in special versions for development. ' +
+
      'As a security mesure, we have disabled this wallet.',
+
  },
+
  explanation2: {
+
    id: 'components.txhistory.flawedwalletmodal.explanation2',
+
    defaultMessage:
+
      '!!!You still can create a new wallet or restore one without restrictions. ' +
+
      'If you were affected in some way by this issue, please contact Emurgo.',
+
  },
+
  okButton: {
+
    id: 'components.txhistory.flawedwalletmodal.okButton',
+
    defaultMessage: '!!!I understand',
+
  },
+
})
+

                      
+
type Props = {
+
  intl: intlShape,
+
  visible: boolean,
+
  onPress: () => any,
+
  onRequestClose: () => any,
+
  disableButtons: boolean,
+
}
+

                      
+
const FlawedWalletModal = ({
+
  intl,
+
  visible,
+
  onPress,
+
  onRequestClose,
+
  disableButtons,
+
}: Props) => {
+
  return (
+
    <Modal visible={visible} onRequestClose={onRequestClose}>
+
      <ScrollView style={styles.scrollView}>
+
        <View style={styles.content}>
+
          <View style={styles.heading}>
+
            <Text style={styles.title}>
+
              {intl.formatMessage(messages.title)}
+
            </Text>
+
            <Image source={image} />
+
          </View>
+
          <Text style={styles.paragraph}>
+
            {intl.formatMessage(messages.explanation1)}
+
          </Text>
+
          <Text style={styles.paragraph}>
+
            {intl.formatMessage(messages.explanation2)}
+
          </Text>
+
        </View>
+
        <View style={styles.buttons}>
+
          <Button
+
            block
+
            outlineShelley
+
            onPress={onPress}
+
            title={intl.formatMessage(messages.okButton)}
+
            style={styles.button}
+
            disabled={disableButtons}
+
          />
+
        </View>
+
      </ScrollView>
+
    </Modal>
+
  )
+
}
+

                      
+
export default injectIntl((FlawedWalletModal: ComponentType<Props>))
  availableAmountSelector,
  walletNameSelector,
  languageSelector,
+
  isFlawedWalletSelector,
} from '../../selectors'
import TxHistoryList from './TxHistoryList'
import TxNavigationButtons from './TxNavigationButtons'
import {updateHistory} from '../../actions/history'
+
import {checkForFlawedWallets} from '../../actions'
import {
  onDidMount,
  requireInitializedWallet,
  withNavigationTitle,
} from '../../utils/renderUtils'
+
import FlawedWalletModal from './FlawedWalletModal'
+
import {WALLET_INIT_ROUTES} from '../../RoutesList'

                      
import {formatAdaWithText} from '../../utils/format'
import image from '../../assets/img/no_transactions.png'
  updateHistory,
  lastSyncError,
  availableAmount,
+
  isFlawedWallet,
}) => (
  <SafeAreaView style={styles.scrollView}>
    <StatusBar type="dark" />
    <View style={styles.container}>
+
      <FlawedWalletModal
+
        visible={isFlawedWallet === true}
+
        disableButtons={false}
+
        onPress={() => navigation.navigate(WALLET_INIT_ROUTES.WALLET_SELECTION)}
+
        onRequestClose={() =>
+
          navigation.navigate(WALLET_INIT_ROUTES.WALLET_SELECTION)
+
        }
+
      />
      <OfflineBanner />
      {isOnline &&
        lastSyncError && <SyncErrorBanner showRefresh={!isSyncing} />}
        availableAmount: availableAmountSelector(state),
        walletName: walletNameSelector(state),
        key: languageSelector(state),
+
        isFlawedWallet: isFlawedWalletSelector(state),
      }),
      {
        updateHistory,
+
        checkForFlawedWallets,
      },
    ),
-
    onDidMount(({updateHistory}) => {
+
    onDidMount(({updateHistory, checkForFlawedWallets}) => {
+
      checkForFlawedWallets()
      updateHistory()
    }),
    withNavigationTitle(({walletName}) => walletName),
+
// @flow
+
import {StyleSheet} from 'react-native'
+

                      
+
import {spacing} from '../../../styles/config'
+

                      
+
export default StyleSheet.create({
+
  scrollView: {
+
    paddingRight: 10,
+
  },
+
  paragraph: {
+
    marginBottom: spacing.paragraphBottomMargin,
+
    fontSize: 14,
+
    lineHeight: 22,
+
  },
+
  content: {
+
    flex: 1,
+
    marginBottom: 24,
+
  },
+
  heading: {
+
    alignItems: 'center',
+
    justifyContent: 'center',
+
    marginBottom: spacing.paragraphBottomMargin,
+
  },
+
  title: {
+
    fontSize: 20,
+
    lineHeight: 22,
+
    fontWeight: 'bold',
+
    marginBottom: spacing.paragraphBottomMargin,
+
  },
+
  buttons: {
+
    flexDirection: 'row',
+
    marginTop: 12,
+
  },
+
  button: {
+
    marginHorizontal: 10,
+
  },
+
})
      : CONFIG.CARDANO
    return await api.getPoolInfo(pool, config)
  }
+

                      
+
  async checkForFlawedWallets(): Promise<boolean> {
+
    const mnemonics = [CONFIG.DEBUG.MNEMONIC1, CONFIG.DEBUG.MNEMONIC2]
+
    let affected = false
+
    for (const mnemonic of mnemonics) {
+
      Logger.debug('WalletManager::checkForFlawedWallets mnemonic:', mnemonic)
+
      let flawedAddresses
+
      if (this.isShelley) {
+
        const flawedAddressesBech32 = await shelleyUtil.getGroupAddressesFromMnemonics(
+
          mnemonic,
+
          'External',
+
          [0],
+
        )
+
        flawedAddresses = await Promise.all(
+
          flawedAddressesBech32.map(async (addr) => {
+
            return Buffer.from(
+
              await (await Address.from_string(addr)).as_bytes(),
+
            ).toString('hex')
+
          }),
+
        )
+
      } else {
+
        flawedAddresses = await util.getAddressesFromMnemonics(
+
          mnemonic,
+
          'External',
+
          [0],
+
          CARDANO_CONFIG.MAINNET,
+
        )
+
      }
+
      if (this._wallet == null) throw new WalletClosed()
+
      if (this._wallet._externalChain.isMyAddress(flawedAddresses[0])) {
+
        Logger.debug('WalletManager::checkForFlawedWallets: address match')
+
        affected = true
+
        return affected
+
      }
+
    }
+
    Logger.debug('WalletManager::checkForFlawedWallets:: no match')
+
    return affected
+
  }
}

                      
export default new WalletManager()
  "components.stakingcenter.confirmDelegation.title": "Confirm delegation",
  "components.stakingcenter.title": "Staking Center",
  "components.stakingcenter.delegationTxBuildError": "Error while building delegation transaction",
+
  "components.txhistory.flawedwalletmodal.title": "Warning",
+
  "components.txhistory.flawedwalletmodal.explanation1": "It looks like you have accidentally created or restored a wallet that is only included in special versions for development. As a security mesure, we have disabled this wallet.",
+
  "components.txhistory.flawedwalletmodal.explanation2": "You still can create a new wallet or restore one without restrictions. If you were affected in some way by this issue, please contact Emurgo.",
+
  "components.txhistory.flawedwalletmodal.okButton": "I understand",
  "components.txhistory.txdetails.addressPrefixChange": "/change",
  "components.txhistory.txdetails.addressPrefixNotMine": "not mine",
  "components.txhistory.txdetails.addressPrefixReceive": "/{idx}",

                      
export const isKeyboardOpenSelector = (state: State): boolean =>
  state.isKeyboardOpen
+

                      
+
export const isFlawedWalletSelector = (state: State): boolean =>
+
  state.isFlawedWallet
m
+4/-0
    sendCrashReports: boolean,
    canEnableBiometricEncryption: boolean,
  },
+
  // need to add as a non-wallet-specific property to avoid conflict with other
+
  // actions that may override this property (otherwise more refactoring is needed)
+
  isFlawedWallet: boolean,
}

                      
export const getInitialState = (): State => ({
    sendCrashReports: false,
    canEnableBiometricEncryption: false,
  },
+
  isFlawedWallet: false,
})

                      
export default getInitialState