diff --git a/package.json b/package.json index 7d650ffb38..cf97954836 100644 --- a/package.json +++ b/package.json @@ -10,10 +10,10 @@ "packages/*" ], "resolutions": { - "@polkadot/api": "^0.96.0-beta.0", - "@polkadot/api-contract": "^0.96.0-beta.0", + "@polkadot/api": "^0.96.0-beta.2", + "@polkadot/api-contract": "^0.96.0-beta.2", "@polkadot/keyring": "^1.6.1", - "@polkadot/types": "^0.96.0-beta.0", + "@polkadot/types": "^0.96.0-beta.2", "@polkadot/util": "^1.6.1", "@polkadot/util-crypto": "^1.6.1", "babel-core": "^7.0.0-bridge.0", diff --git a/packages/app-accounts/src/modals/Create.tsx b/packages/app-accounts/src/modals/Create.tsx index 560f0fdc74..db2e891b1f 100644 --- a/packages/app-accounts/src/modals/Create.tsx +++ b/packages/app-accounts/src/modals/Create.tsx @@ -125,7 +125,7 @@ function Create ({ className, onClose, onStatusChange, seed: propsSeed, t, type: const { isDevelopment } = useContext(ApiContext); const [{ address, deriveError, derivePath, isSeedValid, pairType, seed, seedType }, setAddress] = useState(generateSeed(propsSeed, '', propsSeed ? 'raw' : 'bip', propsType)); const [isConfirmationOpen, setIsConfirmationOpen] = useState(false); - const [{ isNameValid, name }, setName] = useState({ isNameValid: true, name: 'new account' }); + const [{ isNameValid, name }, setName] = useState({ isNameValid: false, name: '' }); const [{ isPassValid, password }, setPassword] = useState({ isPassValid: false, password: '' }); const isValid = !!address && !deriveError && isNameValid && isPassValid && isSeedValid; @@ -142,7 +142,7 @@ function Create ({ className, onClose, onStatusChange, seed: propsSeed, t, type: setAddress(generateSeed(null, derivePath, newSeedType, pairType)); } }; - const _onChangeName = (name: string): void => setName({ isNameValid: !!name.trim(), name }); + const _onChangeName = (name: string): void => setName({ isNameValid: name.trim().length !== 0, name }); const _toggleConfirmation = (): void => setIsConfirmationOpen(!isConfirmationOpen); const _onCommit = (): void => { @@ -203,6 +203,7 @@ function Create ({ className, onClose, onStatusChange, seed: propsSeed, t, type: label={t('name')} onChange={_onChangeName} onEnter={_onCommit} + placeholder={t('new account')} value={name} /> { - const [{ isNameValid, name }, setName] = useState<{ isNameValid: boolean; name: string }>({ isNameValid: true, name: 'new address' }); + const [{ isNameValid, name }, setName] = useState<{ isNameValid: boolean; name: string }>({ isNameValid: false, name: '' }); const [{ address, isAddressExisting, isAddressValid }, setAddress] = useState<{ address: string; isAddressExisting: boolean; isAddressValid: boolean }>({ address: '', isAddressExisting: false, isAddressValid: false }); const isValid = isAddressValid && isNameValid; @@ -40,7 +40,7 @@ function Create ({ onClose, onStatusChange, t }: Props): React.ReactElement { export default withMulti( Propose, translate, - withApi, withCalls( - ['query.elections.members', { + ['query.electionsPhragmen.members', { + fallbacks: ['query.elections.members'], propName: 'memberCount', transform: (value: any[]): number => value.length diff --git a/packages/app-council/src/Overview/Member.tsx b/packages/app-council/src/Overview/Member.tsx index 6ae5b37752..a3b583a1e8 100644 --- a/packages/app-council/src/Overview/Member.tsx +++ b/packages/app-council/src/Overview/Member.tsx @@ -2,24 +2,21 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { BlockNumber } from '@polkadot/types/interfaces'; import { I18nProps } from '@polkadot/react-components/types'; +import { AccountId } from '@polkadot/types/interfaces'; import React from 'react'; import { AddressCard } from '@polkadot/react-components'; -import { formatNumber } from '@polkadot/util'; import translate from '../translate'; interface Props extends I18nProps { - address: string; - block: BlockNumber; + address: AccountId; } -function Member ({ address, block, t }: Props): React.ReactElement { +function Member ({ address, t }: Props): React.ReactElement { return ( #{formatNumber(block)}} defaultName={t('council member')} value={address} /> diff --git a/packages/app-council/src/Overview/Members.tsx b/packages/app-council/src/Overview/Members.tsx index 4869f3e7ab..8e0de3ae98 100644 --- a/packages/app-council/src/Overview/Members.tsx +++ b/packages/app-council/src/Overview/Members.tsx @@ -22,16 +22,15 @@ function Members ({ electionsInfo: { candidates, members }, t }: Props): React.R emptyText={t('No members found')} headerText={t('members')} > - {Object.entries(members).map(([address, block]): React.ReactNode => ( + {members.map((address): React.ReactNode => ( ))} {candidates.map((address): React.ReactNode => ( diff --git a/packages/app-council/src/Overview/SubmitCandidacy.tsx b/packages/app-council/src/Overview/SubmitCandidacy.tsx index 81277311f4..bcf7397bf6 100644 --- a/packages/app-council/src/Overview/SubmitCandidacy.tsx +++ b/packages/app-council/src/Overview/SubmitCandidacy.tsx @@ -2,16 +2,18 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. +import { ApiProps } from '@polkadot/react-api/types'; import { ComponentProps } from './types'; import BN from 'bn.js'; import React from 'react'; +import { withApi } from '@polkadot/react-api'; import { Button } from '@polkadot/react-components'; import TxModal, { TxModalState as State, TxModalProps } from '@polkadot/react-components/TxModal'; import translate from '../translate'; -interface Props extends ComponentProps, TxModalProps {} +interface Props extends ApiProps, ComponentProps, TxModalProps {} class SubmitCandidacy extends TxModal { protected headerText = (): string => this.props.t('Submit your council candidacy'); @@ -20,14 +22,17 @@ class SubmitCandidacy extends TxModal { protected accountHelp = (): string => this.props.t('This account will be nominated to fill the council slot you specify.'); - protected txMethod = (): string => 'elections.submitCandidacy'; + protected txMethod = (): string => + this.props.api.tx.electionsPhragmen + ? 'electionsPhragmen.submitCandidacy' + : 'elections.submitCandidacy'; - protected txParams = (): [BN] => { - const { electionsInfo: { candidateCount } } = this.props; + protected txParams = (): [BN] | [] => { + const { api, electionsInfo: { candidateCount } } = this.props; - return [ - candidateCount - ]; + return api.tx.electionsPhragmen + ? [] + : [candidateCount]; } protected isDisabled = (): boolean => { @@ -50,4 +55,4 @@ class SubmitCandidacy extends TxModal { } } -export default translate(SubmitCandidacy); +export default translate(withApi(SubmitCandidacy)); diff --git a/packages/app-council/src/Overview/Summary.tsx b/packages/app-council/src/Overview/Summary.tsx index cca11629bc..614b112cac 100644 --- a/packages/app-council/src/Overview/Summary.tsx +++ b/packages/app-council/src/Overview/Summary.tsx @@ -25,12 +25,13 @@ function Summary ({ electionsInfo: { members, candidateCount, desiredSeats, term {formatNumber(candidateCount)} -
- - #{formatNumber(voteCount)} - -
- + {voteCount && ( +
+ + #{formatNumber(voteCount)} + +
+ )}
{formatNumber(termDuration)} diff --git a/packages/app-council/src/Overview/Vote.tsx b/packages/app-council/src/Overview/Vote.tsx index c5de4e23c6..505280abf1 100644 --- a/packages/app-council/src/Overview/Vote.tsx +++ b/packages/app-council/src/Overview/Vote.tsx @@ -2,7 +2,7 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { VoteIndex } from '@polkadot/types/interfaces'; +import { AccountId, VoteIndex } from '@polkadot/types/interfaces'; import { DerivedVoterPositions } from '@polkadot/api-derive/types'; import { ApiProps } from '@polkadot/react-api/types'; import { ComponentProps } from './types'; @@ -11,8 +11,8 @@ import BN from 'bn.js'; import React from 'react'; import styled from 'styled-components'; import { createType } from '@polkadot/types'; -import { withApi, withCalls, withMulti } from '@polkadot/react-api'; -import { AddressRow, Button, Icon, Toggle, TxButton } from '@polkadot/react-components'; +import { withCalls, withMulti } from '@polkadot/react-api'; +import { AddressRow, Button, Icon, InputBalance, Toggle, TxButton } from '@polkadot/react-components'; import TxModal, { TxModalState, TxModalProps } from '@polkadot/react-components/TxModal'; import translate from '../translate'; @@ -24,6 +24,7 @@ interface Props extends ApiProps, ComponentProps, TxModalProps { interface State extends TxModalState { approvals: boolean[] | null; oldApprovals: boolean[] | null; + voteValue: BN; // voterPositions: DerivedVoterPositions; } @@ -78,26 +79,14 @@ class Vote extends TxModal { return [...new Array(length).keys()].map((): boolean => false); } - public static getDerivedStateFromProps ({ electionsInfo: { candidateCount } }: Props, { approvals }: State): Partial { - const state: Partial = {}; - // if (voterPositions) { - // state.voters = Object.keys(voterSets).reduce( - // (result: Record, accountId, globalIndex): Record => { - // result[accountId] = { - // setIndex: voterSets[accountId], - // globalIndex: new BN(globalIndex) - // }; - // return result; - // }, - // {} - // ); - // } - - if (candidateCount && !approvals) { - state.approvals = state.oldApprovals || Vote.emptyApprovals(candidateCount.toNumber()); + public static getDerivedStateFromProps ({ electionsInfo: { candidateCount } }: Props, { approvals }: State): Partial | null { + if (candidateCount && (!approvals || !candidateCount.eq(approvals.length))) { + return { + approvals: Vote.emptyApprovals(candidateCount.toNumber()) + }; } - return state; + return null; } public constructor (props: Props) { @@ -106,7 +95,8 @@ class Vote extends TxModal { this.defaultState = { ...this.defaultState, approvals: null, - oldApprovals: null + oldApprovals: null, + voteValue: new BN(0) }; this.state = { @@ -132,25 +122,40 @@ class Vote extends TxModal { protected accountHelp = (): string => this.props.t('This account will be use to approve or disapprove each candidate.'); - protected txMethod = (): string => 'elections.setApprovals'; + protected txMethod = (): string => + this.props.api.tx.electionsPhragmen + ? 'electionsPhragmen.vote' + : 'elections.setApprovals'; - protected txParams = (): [boolean[] | null, VoteIndex, BN | null] => { - const { electionsInfo: { nextVoterSet, voteCount }, voterPositions } = this.props; - const { accountId, approvals } = this.state; + protected txParams = (): [boolean[] | null, VoteIndex, BN | null] | [AccountId[], BN] => { + const { api, electionsInfo: { candidates, nextVoterSet, voteCount }, voterPositions } = this.props; + const { accountId, approvals, voteValue } = this.state; + + if (api.tx.electionsPhragmen) { + return [ + candidates.filter((candidate, index): boolean => !!approvals && approvals[index] === true), + voteValue + ]; + } return [ - approvals ? approvals.slice(0, 1 + approvals.lastIndexOf(true)) : [], + approvals + ? approvals.slice(0, 1 + approvals.lastIndexOf(true)) + : [], createType('VoteIndex', voteCount), voterPositions && accountId && voterPositions[accountId] ? voterPositions[accountId].setIndex - : nextVoterSet + : nextVoterSet || null ]; } protected isDisabled = (): boolean => { - const { accountId, oldApprovals } = this.state; + const { accountId, approvals, oldApprovals } = this.state; - return !accountId || !!oldApprovals; + return !accountId || + !!oldApprovals || + !approvals || + !approvals.some((val): boolean => val === true); } protected renderTrigger = (): React.ReactNode => { @@ -168,89 +173,70 @@ class Vote extends TxModal { } protected renderContent = (): React.ReactNode => { - const { electionsInfo: { candidates }, voterPositions, t } = this.props; + const { api, electionsInfo: { candidates }, voterPositions, t } = this.props; const { accountId, approvals, oldApprovals } = this.state; return ( <> - { - (oldApprovals && accountId && voterPositions && voterPositions[accountId]) && ( - -
- - {t('You have already voted in this round')} -
- - - -
- ) - } + {api.tx.electionsPhragmen && ( + + )} + {(oldApprovals && accountId && voterPositions && voterPositions[accountId]) && ( + +
+ + {t('You have already voted in this round')} +
+ + + +
+ )} - { - candidates.map((accountId, index): React.ReactNode => { - if (!approvals) { - return null; - } - const { [index]: isAye } = approvals; - return ( - this.onChangeVote(index)() } - : {} - )} + {approvals && candidates.map((accountId, index): React.ReactNode => { + const { [index]: isAye } = approvals; + + return ( + + - - {this.renderToggle(index)} - - - ); - }) - } + + + + ); + })} ); } - private renderToggle = (index: number): React.ReactNode => { - const { t } = this.props; - const { approvals, oldApprovals } = this.state; - - if (!approvals) { - return null; - } - - const { [index]: bool } = approvals; - - return ( - {t('Aye')} - ) - : ( - {t('No vote')} - ) - } - value={bool} - /> - ); + private setVoteValue = (voteValue?: BN): void => { + this.setState({ voteValue: voteValue || new BN(0) }); } private emptyApprovals = (): boolean[] => { @@ -263,7 +249,7 @@ class Vote extends TxModal { const { api, electionsInfo: { voteCount }, voterPositions } = this.props; const { accountId } = this.state; - if (!accountId) { + if (!accountId || !voteCount) { return; } @@ -291,16 +277,13 @@ class Vote extends TxModal { }); } - private onChangeVote = (index: number): (isChecked?: boolean) => void => - (isChecked?: boolean): void => { - this.setState(({ approvals }: State): Pick => { - if (!approvals) { - return {}; - } - return { - approvals: approvals.map((b, i): boolean => i === index ? isChecked || !approvals[index] : b) - }; - }); + private onChangeVote = (index: number): (isChecked: boolean) => void => + (isChecked: boolean): void => { + this.setState(({ approvals }: State): Pick => + approvals + ? { approvals: approvals.map((b, i): boolean => i === index ? isChecked : (b || false)) } + : {} + ); } private onRetractVote = (): void => { @@ -314,7 +297,6 @@ class Vote extends TxModal { export default withMulti( Vote, translate, - withApi, withCalls( ['derive.elections.voterPositions', { propName: 'voterPositions' }] ) diff --git a/packages/app-council/src/Overview/index.tsx b/packages/app-council/src/Overview/index.tsx index c6f9a4144e..2f102723b4 100644 --- a/packages/app-council/src/Overview/index.tsx +++ b/packages/app-council/src/Overview/index.tsx @@ -16,14 +16,11 @@ import Summary from './Summary'; import Vote from './Vote'; const NULL_INFO: DerivedElectionsInfo = { - members: {}, candidates: [], candidateCount: createType('u32'), desiredSeats: createType('u32'), - nextVoterSet: createType('SetIndex'), - termDuration: createType('BlockNumber'), - voteCount: createType('VoteIndex'), - voterCount: createType('SetIndex') + members: [], + termDuration: createType('BlockNumber') }; function Overview ({ electionsInfo = NULL_INFO }: Props): React.ReactElement { @@ -41,10 +38,7 @@ function Overview ({ electionsInfo = NULL_INFO }: Props): React.ReactElement( - [ - 'derive.elections.info', - { - propName: 'electionsInfo' - } - ] + ['derive.elections.info', { + propName: 'electionsInfo' + }] )(Overview); diff --git a/packages/apps-routing/src/council.ts b/packages/apps-routing/src/council.ts index 584f0401d4..c08651d3b0 100644 --- a/packages/apps-routing/src/council.ts +++ b/packages/apps-routing/src/council.ts @@ -11,7 +11,10 @@ export default ([ Component: Council, display: { needsApi: [ - 'query.elections.candidates' + [ + 'query.electionsPhragmen.candidates', + 'query.elections.candidates' + ] ] }, i18n: { diff --git a/packages/react-api/package.json b/packages/react-api/package.json index b10256947b..ee5d51aa1a 100644 --- a/packages/react-api/package.json +++ b/packages/react-api/package.json @@ -31,7 +31,7 @@ "homepage": "https://github.com/polkadot-js/ui/tree/master/packages/ui-reactive#readme", "dependencies": { "@babel/runtime": "^7.6.3", - "@polkadot/api": "^0.96.0-beta.0", + "@polkadot/api": "^0.96.0-beta.2", "@polkadot/extension-dapp": "^0.14.0-beta.0", "edgeware-node-types": "^1.0.10", "rxjs-compat": "^6.5.3" diff --git a/packages/react-params/src/Param/Vector.tsx b/packages/react-params/src/Param/Vector.tsx index 32230ef038..55ba136b89 100644 --- a/packages/react-params/src/Param/Vector.tsx +++ b/packages/react-params/src/Param/Vector.tsx @@ -102,7 +102,7 @@ function Vector ({ className, defaultValue, isDisabled = false, label, onChange, icon='add' />