Skip to content

Commit

Permalink
Merge branch 'develop' into feature/ddw-452-show-ada-amounts-in-other…
Browse files Browse the repository at this point in the history
…-currencies
  • Loading branch information
thedanheller committed Jan 11, 2021
2 parents 6279fb5 + 68ff0e0 commit 67260fa
Show file tree
Hide file tree
Showing 32 changed files with 634 additions and 443 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Expand Up @@ -5,8 +5,13 @@ Changelog

### Features

- Improve Mnemonic Phrase Input UX [PR 2280](https://github.com/input-output-hk/daedalus/pull/2280)
- Added wallet public key viewing feature ([PR 2271](https://github.com/input-output-hk/daedalus/pull/2271))

### Chores

- Update `axios` package ([PR 2291](https://github.com/input-output-hk/daedalus/pull/2291))

## 3.1.0

### Features
Expand All @@ -15,6 +20,7 @@ Changelog

### Fixes

- Fixed Daedalus development environment issues on OSX Big Sur ([PR 2288](https://github.com/input-output-hk/daedalus/pull/2288))
- Added initial loading state to UTXO screen ([PR 2265](https://github.com/input-output-hk/daedalus/pull/2265))

### Chores
Expand Down
2 changes: 1 addition & 1 deletion installers/overlays/required.nix
Expand Up @@ -8,5 +8,5 @@ self: super: {
dhall = dontCheck (doJailbreak (self.callPackage ./dhall.nix {}));
universum = dontCheck (self.callPackage ./universum.nix {});
nsis = self.callPackage ./nsis.nix {};
github = self.callHackage "github" "0.23" {};
github = self.callHackage "github" "0.26" {};
}
8 changes: 4 additions & 4 deletions nix/sources.json
Expand Up @@ -61,15 +61,15 @@
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"iohk-nix": {
"branch": "master",
"branch": "nixpkgs-bump",
"description": "nix scripts shared across projects",
"homepage": null,
"owner": "input-output-hk",
"repo": "iohk-nix",
"rev": "5b86d63a0b59b7666d19901b654d8fbde27d9500",
"sha256": "1mfb93nnw0x4gyq93v6lh6h7imliw4j0wp5l9gpdafy3rw621xzb",
"rev": "940f3b7c16b9e7d4493d400280eedf2c936aa5c0",
"sha256": "1m5c8abw3bi5ij99vbcb5bpjywljy72yig5bbm4158r1mck7hljd",
"type": "tarball",
"url": "https://github.com/input-output-hk/iohk-nix/archive/5b86d63a0b59b7666d19901b654d8fbde27d9500.tar.gz",
"url": "https://github.com/input-output-hk/iohk-nix/archive/940f3b7c16b9e7d4493d400280eedf2c936aa5c0.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"js-chain-libs": {
Expand Down
5 changes: 3 additions & 2 deletions package.json
Expand Up @@ -93,7 +93,7 @@
"@storybook/react": "5.3.14",
"asar": "2.1.0",
"autodll-webpack-plugin": "0.4.2",
"axios": "0.20.0",
"axios": "0.21.1",
"babel-eslint": "10.1.0",
"babel-loader": "8.0.4",
"babel-plugin-react-intl": "3.0.1",
Expand Down Expand Up @@ -152,6 +152,7 @@
"regenerator-runtime": "0.13.7",
"resolve-url": "0.2.1",
"sass-loader": "7.1.0",
"sinon": "9.2.2",
"spawn-sync": "2.0.0",
"spectron": "10.0.1",
"style-loader": "0.23.1",
Expand Down Expand Up @@ -227,7 +228,7 @@
"react-intl": "2.7.2",
"react-lottie": "1.2.3",
"react-markdown": "4.3.1",
"react-polymorph": "0.9.7-rc.6",
"react-polymorph": "0.9.7-rc.10",
"react-router": "5.2.0",
"react-router-dom": "5.2.0",
"react-svg-inline": "2.1.1",
Expand Down
Expand Up @@ -18,6 +18,10 @@ import {
} from 'react-intl';
import { BigNumber } from 'bignumber.js';
import Wallet from '../../../domains/Wallet';
import {
errorOrIncompleteMarker,
validateMnemonics,
} from '../../../utils/validations';
import DialogCloseButton from '../../widgets/DialogCloseButton';
import WalletsDropdown from '../../widgets/forms/WalletsDropdown';
import Dialog from '../../widgets/Dialog';
Expand Down Expand Up @@ -163,26 +167,18 @@ export default class Step1ConfigurationDialog extends Component<Props> {
recoveryPhrase: {
value: [...(this.props.recoveryPhrase || [])],
label: this.context.intl.formatMessage(messages.recoveryPhraseLabel),
validators: ({ field }) => {
const { intl } = this.context;
const enteredWords = field.value;
const wordCount = enteredWords.length;
const expectedWordCount = ITN_WALLET_RECOVERY_PHRASE_WORD_COUNT;
const value = enteredWords.join(' ');
const isPhraseComplete = wordCount === expectedWordCount;
if (!isPhraseComplete) {
return [
false,
intl.formatMessage(globalMessages.incompleteMnemonic, {
expected: expectedWordCount,
}),
];
}
return [
this.props.mnemonicValidator(value, expectedWordCount),
this.context.intl.formatMessage(messages.invalidRecoveryPhrase),
];
},
validators: ({ field }) =>
validateMnemonics({
requiredWords: ITN_WALLET_RECOVERY_PHRASE_WORD_COUNT,
providedWords: field.value,
validator: (providedWords) => [
this.props.mnemonicValidator(
providedWords.join(' '),
providedWords.length
),
this.context.intl.formatMessage(messages.invalidRecoveryPhrase),
],
}),
},
walletsDropdown: {
type: 'select',
Expand Down Expand Up @@ -356,8 +352,15 @@ export default class Step1ConfigurationDialog extends Component<Props> {
this.recoveryPhraseAutocomplete = autocomplete;
}}
options={suggestedMnemonics}
requiredSelections={[ITN_WALLET_RECOVERY_PHRASE_WORD_COUNT]}
requiredSelectionsInfo={(required, actual) =>
intl.formatMessage(globalMessages.knownMnemonicWordCount, {
actual,
required,
})
}
maxSelections={ITN_WALLET_RECOVERY_PHRASE_WORD_COUNT}
error={recoveryPhraseField.error}
error={errorOrIncompleteMarker(recoveryPhraseField.error)}
maxVisibleOptions={5}
noResultsMessage={intl.formatMessage(messages.noResults)}
className={styles.recoveryPhrase}
Expand Down
49 changes: 25 additions & 24 deletions source/renderer/app/components/wallet/WalletRestoreDialog.js
Expand Up @@ -20,6 +20,8 @@ import {
isValidWalletName,
isValidSpendingPassword,
isValidRepeatPassword,
errorOrIncompleteMarker,
validateMnemonics,
} from '../../utils/validations';
import globalMessages from '../../i18n/global-messages';
import LocalizableError from '../../i18n/LocalizableError';
Expand Down Expand Up @@ -245,30 +247,22 @@ export default class WalletRestoreDialog extends Component<Props, State> {
recoveryPhrase: {
value: [],
validators: ({ field }) => {
const { intl } = this.context;
const { walletType } = this.state;
const enteredWords = field.value;
const wordCount = enteredWords.length;
const expectedWordCount =
RECOVERY_PHRASE_WORD_COUNT_OPTIONS[walletType];
const value = join(enteredWords, ' ');
// Regular mnemonics have 12 and paper wallet recovery needs 27 words
const isPhraseComplete = wordCount === expectedWordCount;
if (!isPhraseComplete) {
return [
false,
intl.formatMessage(globalMessages.incompleteMnemonic, {
expected: expectedWordCount,
}),
];
}
return [
// TODO: we should also validate paper wallets mnemonics here!
!this.isCertificate()
? this.props.mnemonicValidator(value, expectedWordCount)
: true,
this.context.intl.formatMessage(messages.invalidRecoveryPhrase),
];
RECOVERY_PHRASE_WORD_COUNT_OPTIONS[this.state.walletType];
return validateMnemonics({
requiredWords: expectedWordCount,
providedWords: field.value,
validator: (providedWords) => [
// TODO: we should also validate paper wallets mnemonics here!
!this.isCertificate()
? this.props.mnemonicValidator(
providedWords,
expectedWordCount
)
: true,
this.context.intl.formatMessage(messages.invalidRecoveryPhrase),
],
});
},
},
spendingPassword: {
Expand Down Expand Up @@ -587,8 +581,15 @@ export default class WalletRestoreDialog extends Component<Props, State> {
})
}
options={suggestedMnemonics}
requiredSelections={[RECOVERY_PHRASE_WORD_COUNT_OPTIONS[walletType]]}
requiredSelectionsInfo={(required, actual) =>
intl.formatMessage(globalMessages.knownMnemonicWordCount, {
actual,
required,
})
}
maxSelections={RECOVERY_PHRASE_WORD_COUNT_OPTIONS[walletType]}
error={recoveryPhraseField.error}
error={errorOrIncompleteMarker(recoveryPhraseField.error)}
maxVisibleOptions={5}
noResultsMessage={intl.formatMessage(
messages.recoveryPhraseNoResults
Expand Down
@@ -1,7 +1,6 @@
// @flow
import React, { Component } from 'react';
import { observer } from 'mobx-react';
import { join } from 'lodash';
import classnames from 'classnames';
import vjf from 'mobx-react-form/lib/validators/VJF';
import { Autocomplete } from 'react-polymorph/lib/components/Autocomplete';
Expand All @@ -13,6 +12,10 @@ import { WALLET_RECOVERY_PHRASE_WORD_COUNT } from '../../../config/cryptoConfig'
import suggestedMnemonics from '../../../../../common/config/crypto/valid-words.en';
import { isValidMnemonic } from '../../../../../common/config/crypto/decrypt';
import ReactToolboxMobxForm from '../../../utils/ReactToolboxMobxForm';
import {
errorOrIncompleteMarker,
validateMnemonics,
} from '../../../utils/validations';
import WalletRecoveryPhraseMnemonic from './WalletRecoveryPhraseMnemonic';
import DialogCloseButton from '../../widgets/DialogCloseButton';
import DialogBackButton from '../../widgets/DialogBackButton';
Expand Down Expand Up @@ -115,32 +118,20 @@ export default class WalletRecoveryPhraseEntryDialog extends Component<Props> {
recoveryPhrase: {
value: [],
validators: ({ field }) => {
const { intl } = this.context;
const enteredWords = field.value;
const wordCount = enteredWords.length;
const expectedWordCount = WALLET_RECOVERY_PHRASE_WORD_COUNT;
const value = join(enteredWords, ' ');

this.props.onUpdateVerificationPhrase({
verificationPhrase: enteredWords,
});

// Check if recovery phrase contains the expected words
if (wordCount !== expectedWordCount) {
return [
false,
intl.formatMessage(globalMessages.incompleteMnemonic, {
expected: expectedWordCount,
}),
];
}

return [
isValidMnemonic(value, wordCount),
this.context.intl.formatMessage(
messages.recoveryPhraseInvalidMnemonics
),
];
return validateMnemonics({
requiredWords: WALLET_RECOVERY_PHRASE_WORD_COUNT,
providedWords: field.value,
validator: () => [
isValidMnemonic(enteredWords.join(' '), enteredWords.length),
this.context.intl.formatMessage(
messages.recoveryPhraseInvalidMnemonics
),
],
});
},
},
},
Expand Down Expand Up @@ -227,8 +218,15 @@ export default class WalletRecoveryPhraseEntryDialog extends Component<Props> {
}
)}
options={suggestedMnemonics}
requiredSelections={[wordCount]}
requiredSelectionsInfo={(required, actual) =>
intl.formatMessage(globalMessages.knownMnemonicWordCount, {
actual,
required,
})
}
maxSelections={wordCount}
error={recoveryPhraseField.error}
error={errorOrIncompleteMarker(recoveryPhraseField.error)}
maxVisibleOptions={5}
noResultsMessage={intl.formatMessage(
messages.recoveryPhraseNoResults
Expand Down
@@ -1,14 +1,17 @@
// @flow
import React, { Component } from 'react';
import { observer } from 'mobx-react';
import { join } from 'lodash';
import { defineMessages, intlShape } from 'react-intl';
import vjf from 'mobx-react-form/lib/validators/VJF';
import { Autocomplete } from 'react-polymorph/lib/components/Autocomplete';
import { AutocompleteSkin } from 'react-polymorph/lib/skins/simple/AutocompleteSkin';
import suggestedMnemonics from '../../../../../common/config/crypto/valid-words.en';
import { isValidMnemonic } from '../../../../../common/config/crypto/decrypt';
import ReactToolboxMobxForm from '../../../utils/ReactToolboxMobxForm';
import {
errorOrIncompleteMarker,
validateMnemonics,
} from '../../../utils/validations';
import DialogCloseButton from '../../widgets/DialogCloseButton';
import Dialog from '../../widgets/Dialog';
import styles from './WalletRecoveryPhraseStepDialogs.scss';
Expand Down Expand Up @@ -86,37 +89,17 @@ export default class WalletRecoveryPhraseStep2Dialog extends Component<
fields: {
recoveryPhrase: {
value: [],
validators: ({ field }) => {
const { intl } = this.context;
const enteredWords = field.value;
const enteredWordCount = enteredWords.length;
const value = join(enteredWords, ' ');
const { expectedWordCount } = this.props;

const isPhraseComplete = Array.isArray(expectedWordCount)
? expectedWordCount.includes(enteredWordCount)
: enteredWordCount === expectedWordCount;

// Check if recovery phrase contains the expected words
if (!isPhraseComplete) {
const expected = Array.isArray(expectedWordCount)
? ''
: expectedWordCount;

return [
false,
intl.formatMessage(globalMessages.incompleteMnemonic, {
expected,
}),
];
}
return [
isValidMnemonic(value, enteredWords.length),
this.context.intl.formatMessage(
messages.recoveryPhraseStep2InvalidMnemonics
),
];
},
validators: ({ field }) =>
validateMnemonics({
requiredWords: this.props.expectedWordCount,
providedWords: field.value,
validator: (enteredWords) => [
isValidMnemonic(enteredWords.join(' '), enteredWords.length),
this.context.intl.formatMessage(
messages.recoveryPhraseStep2InvalidMnemonics
),
],
}),
},
},
},
Expand Down Expand Up @@ -178,8 +161,23 @@ export default class WalletRecoveryPhraseStep2Dialog extends Component<
label={intl.formatMessage(messages.recoveryPhraseStep2Subtitle)}
placeholder={intl.formatMessage(messages.recoveryPhraseInputHint)}
options={suggestedMnemonics}
requiredSelections={
Array.isArray(expectedWordCount)
? expectedWordCount
: [expectedWordCount]
}
requiredSelectionsInfo={(required, actual) =>
Array.isArray(expectedWordCount)
? intl.formatMessage(globalMessages.unknownMnemonicWordCount, {
actual,
})
: intl.formatMessage(globalMessages.knownMnemonicWordCount, {
actual,
required,
})
}
maxSelections={maxSelections}
error={recoveryPhraseField.error}
error={errorOrIncompleteMarker(recoveryPhraseField.error)}
maxVisibleOptions={5}
noResultsMessage={intl.formatMessage(
messages.recoveryPhraseNoResults
Expand Down

0 comments on commit 67260fa

Please sign in to comment.