Skip to content

Commit

Permalink
Support democracy with preimages (#1973)
Browse files Browse the repository at this point in the history
* Add derive.democracy.proposals

* Preimage button

* Preimages work

* Allow Proposals, display referendums

* Update with height/width hack

* Bump deps
  • Loading branch information
jacogr authored Dec 2, 2019
1 parent 56029ff commit b05a01c
Showing 15 changed files with 370 additions and 325 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -10,10 +10,10 @@
"packages/*"
],
"resolutions": {
"@polkadot/api": "^0.98.0-beta.0",
"@polkadot/api-contract": "^0.98.0-beta.0",
"@polkadot/api": "^0.98.0-beta.1",
"@polkadot/api-contract": "^0.98.0-beta.1",
"@polkadot/keyring": "^1.7.1",
"@polkadot/types": "^0.98.0-beta.0",
"@polkadot/types": "^0.98.0-beta.1",
"@polkadot/util": "^1.7.1",
"@polkadot/util-crypto": "^1.7.1",
"babel-core": "^7.0.0-bridge.0",
2 changes: 1 addition & 1 deletion packages/app-contracts/package.json
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.7.4",
"@polkadot/api-contract": "^0.98.0-beta.0",
"@polkadot/api-contract": "^0.98.0-beta.1",
"@polkadot/react-components": "^0.38.0-beta.8"
}
}
87 changes: 87 additions & 0 deletions packages/app-democracy/src/Overview/PreImage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright 2017-2019 @polkadot/app-democracy authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

import { SubmittableExtrinsic } from '@polkadot/api/promise/types';
import { I18nProps } from '@polkadot/react-components/types';

import React, { useEffect, useState } from 'react';
import { Button, Input, InputAddress, Extrinsic, Modal, TxButton } from '@polkadot/react-components';
import { useApi } from '@polkadot/react-hooks';
import { Available } from '@polkadot/react-query';
import { blake2AsHex } from '@polkadot/util-crypto';

import translate from '../translate';

interface Props extends I18nProps {
onClose: () => void;
}

const ZERO_HASH = blake2AsHex('');

function PreImage ({ className, onClose, t }: Props): React.ReactElement<Props> {
const { apiDefaultTxSudo } = useApi();
const [accountId, setAccountId] = useState<string | null>(null);
const [{ hex, hash }, setHash] = useState<{ hex: string; hash: string }>({ hex: '', hash: ZERO_HASH });
const [proposal, setProposal] = useState<any>();

useEffect((): void => {
const hex = (proposal as SubmittableExtrinsic)?.method.toHex() || '';

setHash({ hex, hash: blake2AsHex(hex) });
}, [proposal]);

return (
<Modal
className={className}
dimmer='inverted'
open
>
<Modal.Header>{t('Submit preimage')}</Modal.Header>
<Modal.Content>
<InputAddress
help={t('The account you want to register the preimage from')}
label={t('send from account')}
labelExtra={<Available label={t('transferrable')} params={accountId} />}
onChange={setAccountId}
type='account'
/>
<Extrinsic
defaultValue={apiDefaultTxSudo}
label={t('propose')}
onChange={setProposal}
/>
<Input
help={t('The hash of the selected proposal, use it for submitting the proposal')}
isDisabled
label={t('preimage hash')}
value={hash}
/>
</Modal.Content>
<Modal.Actions>
<Button.Group>
<Button
isNegative
label={t('Cancel')}
icon='add'
onClick={onClose}
/>
<Button.Or />
<TxButton
accountId={accountId}
isDisabled={!proposal || !accountId}
isPrimary
label={t('Submit preimage')}
icon='add'
onStart={onClose}
params={[hex]}
tx='democracy.notePreimage'
withSpinner={false}
/>
</Button.Group>
</Modal.Actions>
</Modal>
);
}

export default translate(PreImage);
81 changes: 24 additions & 57 deletions packages/app-democracy/src/Overview/Proposal.tsx
Original file line number Diff line number Diff line change
@@ -1,82 +1,49 @@
/* eslint-disable @typescript-eslint/camelcase */
// Copyright 2017-2019 @polkadot/app-democracy authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

import { AccountId, Balance, Proposal as ProposalType } from '@polkadot/types/interfaces';
import { DeriveProposal } from '@polkadot/api-derive/types';
import { I18nProps } from '@polkadot/react-components/types';

import BN from 'bn.js';
import React from 'react';
import { Option, Tuple, Vec } from '@polkadot/types';
import { ActionItem, InputAddress, Labelled, Static } from '@polkadot/react-components';
import { withCalls, withMulti } from '@polkadot/react-api';
import { ActionItem, InputAddress, Static } from '@polkadot/react-components';
import { FormatBalance } from '@polkadot/react-query';

import translate from '../translate';
import Seconding from './Seconding';

interface Props extends I18nProps {
democracy_depositOf?: [Balance, Vec<AccountId>] | null;
idNumber: BN;
value: ProposalType;
value: DeriveProposal;
}

function renderProposal ({ democracy_depositOf, t }: Props): React.ReactNode {
if (!democracy_depositOf) {
return null;
}

const [balance, addresses] = democracy_depositOf;

return (
<div>
<Labelled label={t('depositors')}>
{addresses.map((address, index): React.ReactNode => (
<InputAddress
isDisabled
key={`${index}:${address}`}
defaultValue={address}
withLabel={false}
/>
))}
</Labelled>
<Static label={t('balance')}>
<FormatBalance value={balance} />
</Static>
</div>
);
}

function Proposal (props: Props): React.ReactElement<Props> {
const { className, democracy_depositOf, idNumber, value } = props;
const depositors = democracy_depositOf
? democracy_depositOf[1]
: [];

function Proposal ({ className, t, value: { balance, index, proposal, seconds } }: Props): React.ReactElement<Props> {
return (
<ActionItem
className={className}
idNumber={idNumber}
proposal={value}
idNumber={index}
proposal={proposal}
>
<Seconding
depositors={depositors}
proposalId={idNumber}
depositors={seconds || []}
proposalId={index}
/>
{renderProposal(props)}
{balance && seconds && (
<div>
{seconds.map((address, count): React.ReactNode => (
<InputAddress
isDisabled
label={count === 0 ? t('proposer') : t('depositor {{count}}', { replace: { count } })}
key={`${count}:${address}`}
defaultValue={address}
/>
))}
<Static label={t('balance')}>
<FormatBalance value={balance} />
</Static>
</div>
)}
</ActionItem>
);
}

export default withMulti(
Proposal,
translate,
withCalls<Props>(
['query.democracy.depositOf', {
paramName: 'idNumber',
transform: (value: Option<Tuple>): Tuple | null =>
value.unwrapOr(null)
}]
)
);
export default translate(Proposal);
47 changes: 20 additions & 27 deletions packages/app-democracy/src/Overview/Proposals.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,35 @@
/* eslint-disable @typescript-eslint/camelcase */
// Copyright 2017-2019 @polkadot/app-democracy authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

import { Proposal } from '@polkadot/types/interfaces';
import { I18nProps } from '@polkadot/react-components/types';
import { DeriveProposal } from '@polkadot/api-derive/types';
import { I18nProps as Props } from '@polkadot/react-components/types';

import BN from 'bn.js';
import React from 'react';
import { withCalls, withMulti } from '@polkadot/react-api';
import { Column } from '@polkadot/react-components';
import { useApi, trackStream } from '@polkadot/react-hooks';

import ProposalDisplay from './Proposal';
import translate from '../translate';

interface Props extends I18nProps {
democracy_publicProps?: [BN, Proposal][];
}
function Proposals ({ className, t }: Props): React.ReactElement<Props> {
const { api } = useApi();
const proposals = trackStream<DeriveProposal[]>(api.derive.democracy.proposals, []);

function Proposals ({ democracy_publicProps, t }: Props): React.ReactElement<Props> {
return (
<Column
emptyText={t('No available proposals')}
headerText={t('proposals')}
>
{democracy_publicProps && democracy_publicProps.map(([idNumber, proposal]): React.ReactNode => (
<ProposalDisplay
idNumber={idNumber}
key={idNumber.toString()}
value={proposal}
/>
))}
</Column>
<div className={`proposalSection ${className}`}>
<h1>{t('proposals')}</h1>
{
proposals?.length
? proposals.map((proposal): React.ReactNode => (
<ProposalDisplay
key={proposal.index.toString()}
value={proposal}
/>
))
: t('No active proposals')
}
</div>
);
}

export default withMulti(
Proposals,
translate,
withCalls<Props>('query.democracy.publicProps')
);
export default translate(Proposals);
Loading

0 comments on commit b05a01c

Please sign in to comment.