Expand available extrinsic methods (#7)
* Public/Private extrinsics * Better dropdown displays * Expand definition with name * Pass actual full selected extrinsic around * Create param layout from parameters * u32 encoding * Re-introduce Params component * Proposal & params display operational * Parameter-drive method construction * s/Method/Extrinsic/ * Cleanup locations
This commit is contained in:
parent
6ec84ca16c
commit
79dcf5ab54
@ -15,7 +15,7 @@ import InputAddress from './InputAddress';
|
||||
|
||||
type Props = BaseProps & {
|
||||
label: string,
|
||||
subject: rxjs$BehaviorSubject<*>
|
||||
subject: rxjs$BehaviorSubject<Uint8Array>
|
||||
};
|
||||
|
||||
function Account ({ className, label, subject, style, t }: Props): React$Node {
|
||||
|
||||
@ -3,30 +3,33 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps } from './types';
|
||||
import type { BaseProps, QueueTx } from './types';
|
||||
|
||||
import React from 'react';
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
import withObservable from '@polkadot/rx-react/with/observable';
|
||||
|
||||
import CallDisplay from './CallDisplay';
|
||||
import CallSelect from './CallSelect';
|
||||
import Nonce from './Nonce';
|
||||
import Sender from './Sender';
|
||||
import Submission from './Submission';
|
||||
import Signer from './Signer';
|
||||
import translate from './translate';
|
||||
|
||||
type Props = BaseProps & {};
|
||||
|
||||
const queue: rxjs$BehaviorSubject<QueueTx> = new BehaviorSubject(({
|
||||
isValid: false,
|
||||
status: 'incomplete'
|
||||
}: $Shape<QueueTx>));
|
||||
|
||||
const QueuedSigner = withObservable(queue)(Signer);
|
||||
|
||||
function App ({ className, style }: Props): React$Node {
|
||||
return (
|
||||
<div
|
||||
className={['extrinsics--App', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<Sender />
|
||||
<CallSelect />
|
||||
<Nonce />
|
||||
<CallDisplay />
|
||||
<Signer />
|
||||
<Submission subject={queue} />
|
||||
<QueuedSigner subject={queue} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
/* Copyright 2017-2018 Jaco Greeff
|
||||
/* This software may be modified and distributed under the terms
|
||||
/* of the ISC license. See the LICENSE file for details. */
|
||||
|
||||
.extrinsics--CallDisplay {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.extrinsics--CallDisplay-error {
|
||||
color: red;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.extrinsics--CallDisplay-Component {
|
||||
margin: 1.5rem 0;
|
||||
}
|
||||
|
||||
.extrinsics--CallDisplay-Button {}
|
||||
@ -1,27 +0,0 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps } from '../types';
|
||||
|
||||
import './CallDisplay.css';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import translate from '../translate';
|
||||
|
||||
function ErrorDisplay ({ className, style, t }: BaseProps): React$Node {
|
||||
return (
|
||||
<div
|
||||
className={['extrinsics--CallDisplay-error', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
{t('calldisplay.error', {
|
||||
defaultValue: 'ERROR: Invalid or unimplemented extrinsic function'
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default translate(ErrorDisplay);
|
||||
@ -1,69 +0,0 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps } from '../types';
|
||||
|
||||
import './CallDisplay.css';
|
||||
|
||||
import React from 'react';
|
||||
import Button from 'semantic-ui-react/dist/es/elements/Button';
|
||||
import withObservable from '@polkadot/rx-react/with/observable';
|
||||
|
||||
import translate from '../translate';
|
||||
import StakingStake from '../Staking/Stake';
|
||||
import StakingTransfer from '../Staking/Transfer';
|
||||
import StakingUnstake from '../Staking/Unstake';
|
||||
import { extrinsicName } from '../subjects';
|
||||
import ErrorComponent from './Error';
|
||||
import queueExtrinsic from './queue';
|
||||
|
||||
type ValueGetter = {
|
||||
getValues: () => Array<mixed>
|
||||
}
|
||||
|
||||
type Props = BaseProps & {
|
||||
value?: string;
|
||||
};
|
||||
|
||||
const COMPONENTS = {
|
||||
'staking_stake': StakingStake,
|
||||
'staking_transfer': StakingTransfer,
|
||||
'staking_unstake': StakingUnstake
|
||||
};
|
||||
|
||||
function CallDisplay ({ className, style, t, value }: Props): React$Node {
|
||||
// flowlint-next-line sketchy-null-string:off
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const Component = COMPONENTS[value] || ErrorComponent;
|
||||
const onSubmit = () => {
|
||||
// flowlint-next-line unclear-type:off
|
||||
queueExtrinsic(value, ((Component: any): ValueGetter).getValues());
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['extrinsics--CallDisplay', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<Component className='extrinsics--CallDisplay-Component' />
|
||||
<Button
|
||||
className='extrinsics--CallDisplay-Execute'
|
||||
onClick={onSubmit}
|
||||
primary
|
||||
>
|
||||
{t('calldisplay.submit', {
|
||||
defaultValue: 'Submit Extrinsic'
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default translate(
|
||||
withObservable(extrinsicName)(CallDisplay)
|
||||
);
|
||||
@ -1,25 +0,0 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import encode from '../encode';
|
||||
import extrinsics from '../extrinsics';
|
||||
import { senderAddr, senderIndex, queueTx } from '../subjects';
|
||||
|
||||
export default function queue (method: string, values: Array<mixed>): void {
|
||||
// flowlint-next-line unclear-type:off
|
||||
const publicKey = ((senderAddr.getValue(): any): Uint8Array);
|
||||
const message = encode(
|
||||
extrinsics.get(method),
|
||||
publicKey,
|
||||
senderIndex.getValue() || 0,
|
||||
values
|
||||
);
|
||||
|
||||
queueTx.next({
|
||||
message,
|
||||
method,
|
||||
publicKey
|
||||
});
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps } from '../types';
|
||||
|
||||
import './CallSelect.css';
|
||||
|
||||
import React from 'react';
|
||||
import Dropdown from 'semantic-ui-react/dist/es/modules/Dropdown';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
|
||||
import translate from '../translate';
|
||||
import { extrinsicName } from '../subjects';
|
||||
import extrinsics from '../extrinsics';
|
||||
|
||||
type Props = BaseProps & {};
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const onChange = (event: SyntheticEvent<*>, { value }): void => {
|
||||
extrinsicName.next(value);
|
||||
};
|
||||
|
||||
const options = [];
|
||||
|
||||
extrinsics.sections.forEach(({ description, methods, name }) => {
|
||||
options.push({
|
||||
disabled: true,
|
||||
text: description,
|
||||
value: name
|
||||
});
|
||||
|
||||
methods.forEach(({ description, name }) => {
|
||||
options.push({
|
||||
className: 'extrinsics--CallSelect-indent',
|
||||
text: description,
|
||||
value: name
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function CallSelect ({ className, style, t }: Props): React$Node {
|
||||
return (
|
||||
<div
|
||||
className={['extrinsics--CallSelect', 'extrinsics--split', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='large'>
|
||||
<Label>
|
||||
{t('callselect.label', {
|
||||
defaultValue: 'submit the following extrinsic'
|
||||
})}
|
||||
</Label>
|
||||
<Dropdown
|
||||
selection
|
||||
onChange={onChange}
|
||||
options={options}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default translate(CallSelect);
|
||||
43
packages/app-extrinsics/src/Extrinsic/index.js
Normal file
43
packages/app-extrinsics/src/Extrinsic/index.js
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BareProps, EncodedParams } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
import withObservable from '@polkadot/rx-react/with/observable';
|
||||
|
||||
import InputExtrinsic from '../InputExtrinsic';
|
||||
import Params from '../Params';
|
||||
import createSubjects from './subjects';
|
||||
|
||||
type Props = BareProps & {
|
||||
isPrivate?: boolean,
|
||||
label: string,
|
||||
subject: rxjs$BehaviorSubject<EncodedParams>
|
||||
};
|
||||
|
||||
export default function ExtrinsicMethod ({ className, isPrivate, label, style, subject }: Props): React$Node {
|
||||
const subjects = createSubjects(subject);
|
||||
const MethodParams = withObservable(subjects.method)(Params);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['extrinsics--Extrinsic', 'extrinsics--split', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='full'>
|
||||
<Label>{label}</Label>
|
||||
<InputExtrinsic
|
||||
isPrivate={isPrivate}
|
||||
subject={subjects.method}
|
||||
/>
|
||||
</div>
|
||||
<MethodParams
|
||||
subject={subjects.params}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
45
packages/app-extrinsics/src/Extrinsic/subjects.js
Normal file
45
packages/app-extrinsics/src/Extrinsic/subjects.js
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { Extrinsic } from '../extrinsics/types';
|
||||
import type { EncodedParams, RawParam } from '../types';
|
||||
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
import isUndefined from '@polkadot/util/is/undefined';
|
||||
|
||||
import encodeExtrinsic from '../encode/extrinsic';
|
||||
|
||||
type Subjects = {
|
||||
method: rxjs$BehaviorSubject<Extrinsic>,
|
||||
params: rxjs$BehaviorSubject<Array<RawParam>>
|
||||
};
|
||||
|
||||
export default function subjects (subject: rxjs$BehaviorSubject<EncodedParams>): Subjects {
|
||||
const subjects = {
|
||||
method: new BehaviorSubject(({}: $Shape<Extrinsic>)),
|
||||
params: new BehaviorSubject([])
|
||||
};
|
||||
|
||||
const onChange = (): void => {
|
||||
const extrinsic = subjects.method.getValue();
|
||||
const values = subjects.params.getValue();
|
||||
const isValid = !!extrinsic.params && extrinsic.params.reduce((isValid, param, index) => {
|
||||
return isValid && !isUndefined(values[index]) && !isUndefined(values[index].value) && values[index].isValid;
|
||||
}, !!values);
|
||||
const raw = values.map((param) => param && param.value);
|
||||
const data = extrinsic.params && encodeExtrinsic(extrinsic, raw);
|
||||
|
||||
subject.next({
|
||||
data,
|
||||
extrinsic,
|
||||
isValid
|
||||
});
|
||||
};
|
||||
|
||||
subjects.method.subscribe(onChange);
|
||||
subjects.params.subscribe(onChange);
|
||||
|
||||
return subjects;
|
||||
}
|
||||
@ -3,6 +3,9 @@
|
||||
/* of the ISC license. See the LICENSE file for details. */
|
||||
|
||||
.ui--InputyAddress-PairDisplay {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
white-space: nowrap;
|
||||
}
|
||||
@ -19,14 +22,19 @@
|
||||
}
|
||||
|
||||
.ui--InputyAddress-PairDisplay-address {
|
||||
flex: 1;
|
||||
font-family: monospace;
|
||||
margin-left: 1rem;
|
||||
opacity: 0.5;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
overflow: hidden;
|
||||
text-align: right;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.ui--InputyAddress-PairDisplay-name {
|
||||
flex: 1 0;
|
||||
margin-left: 3rem;
|
||||
overflow: hidden;
|
||||
text-transform: uppercase;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
// TODO: This is a useful, shared component, move out
|
||||
|
||||
import './InputAddress.css';
|
||||
|
||||
import React from 'react';
|
||||
@ -44,9 +46,9 @@ export default function InputAddress (props: Props): React$Node {
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
selection
|
||||
{...props}
|
||||
className={['ui--InputAddress', props.className].join(' ')}
|
||||
selection
|
||||
options={options}
|
||||
onChange={onChange}
|
||||
/>
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
/* Copyright 2017-2018 Jaco Greeff
|
||||
/* This software may be modified and distributed under the terms
|
||||
/* of the ISC license. See the LICENSE file for details. */
|
||||
|
||||
.ui--InputExtrinsic {}
|
||||
|
||||
.ui--InputExtrinsic-Header {}
|
||||
|
||||
.ui--InputExtrinsic .text {
|
||||
box-sizing: border-box;
|
||||
display: flex !important;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.ui--InputExtrinsic-Item > .text {
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.ui--InputExtrinsic-Item-text,
|
||||
.ui--InputExtrinsic-Item-call {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.ui--InputExtrinsic-Item-call {
|
||||
flex: 1;
|
||||
font-family: monospace;
|
||||
margin-left: 1rem;
|
||||
opacity: 0.5;
|
||||
overflow: hidden;
|
||||
text-align: right;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.ui--InputExtrinsic-Item-text {
|
||||
flex: 1 0;
|
||||
}
|
||||
60
packages/app-extrinsics/src/InputExtrinsic/index.js
Normal file
60
packages/app-extrinsics/src/InputExtrinsic/index.js
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
// TODO: This is a useful, shared component, move out
|
||||
|
||||
import type { Extrinsic } from '../extrinsics/types';
|
||||
|
||||
import './InputExtrinsic.css';
|
||||
|
||||
import React from 'react';
|
||||
import Dropdown from 'semantic-ui-react/dist/es/modules/Dropdown';
|
||||
|
||||
import extrinsics from '../extrinsics';
|
||||
import options from './options';
|
||||
|
||||
type Props = {
|
||||
className?: string,
|
||||
isPrivate?: boolean,
|
||||
onChange?: (event: SyntheticEvent<*>, value: Extrinsic) => void,
|
||||
style?: {
|
||||
[string]: string
|
||||
},
|
||||
subject?: rxjs$Subject<Extrinsic>
|
||||
};
|
||||
|
||||
export default function InputExtrinsic (props: Props): React$Node {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const onChange = (event: SyntheticEvent<*>, { value }): void => {
|
||||
const extrinsic = extrinsics.get(value);
|
||||
|
||||
if (props.subject) {
|
||||
props.subject.next(extrinsic);
|
||||
}
|
||||
|
||||
if (props.onChange) {
|
||||
props.onChange(event, extrinsic);
|
||||
}
|
||||
};
|
||||
|
||||
const _props = Object.assign({}, props);
|
||||
|
||||
delete _props.isPrivate;
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
selection
|
||||
{..._props}
|
||||
className={['ui--InputExtrinsic', props.className].join(' ')}
|
||||
onChange={onChange}
|
||||
options={
|
||||
// flowlint-next-line sketchy-null-bool:off
|
||||
props.isPrivate
|
||||
? options.private
|
||||
: options.public
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
44
packages/app-extrinsics/src/InputExtrinsic/options.js
Normal file
44
packages/app-extrinsics/src/InputExtrinsic/options.js
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import extrinsics from '../extrinsics';
|
||||
|
||||
const options = {
|
||||
private: [],
|
||||
public: []
|
||||
};
|
||||
|
||||
extrinsics.sections.forEach(({ description, hasPrivate, hasPublic, methods, name }) => {
|
||||
const header = {
|
||||
className: 'ui--InputExtrinsic-Header',
|
||||
disabled: true,
|
||||
text: description,
|
||||
value: name
|
||||
};
|
||||
|
||||
hasPublic && options.public.push(header);
|
||||
hasPrivate && options.private.push(header);
|
||||
|
||||
methods.forEach(({ description, name, params, isPrivate }) => {
|
||||
const inputs = params.map(({ name }) => name).join(', ');
|
||||
|
||||
options[isPrivate ? 'private' : 'public'].push({
|
||||
className: 'ui--InputExtrinsic-Item',
|
||||
text: [
|
||||
<div className='ui--InputExtrinsic-Item-text' key='name'>
|
||||
{description}
|
||||
</div>,
|
||||
<div className='ui--InputExtrinsic-Item-call' key='call'>
|
||||
{name}({inputs})
|
||||
</div>
|
||||
],
|
||||
value: name
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
export default options;
|
||||
29
packages/app-extrinsics/src/Params/Account.js
Normal file
29
packages/app-extrinsics/src/Params/Account.js
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { Props } from './types';
|
||||
|
||||
import React from 'react';
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
|
||||
import BaseAccount from '../Account';
|
||||
|
||||
export default function Account ({ label, subject }: Props): React$Node {
|
||||
const account: rxjs$BehaviorSubject<Uint8Array> = new BehaviorSubject(new Uint8Array([]));
|
||||
|
||||
account.subscribe((value: Uint8Array) => {
|
||||
subject.next({
|
||||
isValid: !!(value && value.length),
|
||||
value
|
||||
});
|
||||
});
|
||||
|
||||
return (
|
||||
<BaseAccount
|
||||
label={label}
|
||||
subject={account}
|
||||
/>
|
||||
);
|
||||
}
|
||||
40
packages/app-extrinsics/src/Params/Amount.js
Normal file
40
packages/app-extrinsics/src/Params/Amount.js
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { Props } from './types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React from 'react';
|
||||
import Input from 'semantic-ui-react/dist/es/elements/Input';
|
||||
|
||||
import Base from './Base';
|
||||
|
||||
export default function Amount ({ label, subject, t, value: { options: { initValue = 0, maxValue, minValue = 0 } = {} }, type }: Props): React$Node {
|
||||
// flowlint-next-line sketchy-null-mixed:off, sketchy-null-number:off
|
||||
const defaultValue = initValue || minValue;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const onChange = (event: SyntheticEvent<*>, { value }): void => {
|
||||
subject.next({
|
||||
isValid: true,
|
||||
// flowlint-next-line sketchy-null-mixed:off, sketchy-null-number:off
|
||||
value: new BN(value || minValue || 0)
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Base
|
||||
label={label}
|
||||
size='small'
|
||||
>
|
||||
<Input
|
||||
defaultValue={defaultValue}
|
||||
max={maxValue}
|
||||
min={minValue}
|
||||
onChange={onChange}
|
||||
type='number'
|
||||
/>
|
||||
</Base>
|
||||
);
|
||||
}
|
||||
31
packages/app-extrinsics/src/Params/Base.js
Normal file
31
packages/app-extrinsics/src/Params/Base.js
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
|
||||
type Props = {
|
||||
className?: string,
|
||||
children: React$Node,
|
||||
label?: string,
|
||||
size?: 'full' | 'large' | 'medium' | 'small',
|
||||
style?: {
|
||||
[string]: string
|
||||
}
|
||||
};
|
||||
|
||||
export default function Base ({ children, className, label, size = 'medium', style }: Props): React$Node {
|
||||
return (
|
||||
<div
|
||||
className={['extrinsics--split', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className={size}>
|
||||
<Label>{label}</Label>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
43
packages/app-extrinsics/src/Params/Param.js
Normal file
43
packages/app-extrinsics/src/Params/Param.js
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps } from './types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import Account from './Account';
|
||||
import Amount from './Amount';
|
||||
import Proposal from './Proposal';
|
||||
import Unknown from './Unknown';
|
||||
|
||||
type Props = BaseProps & {
|
||||
label?: string;
|
||||
}
|
||||
|
||||
const Components = {
|
||||
'AccountId': Account,
|
||||
'Balance': Amount,
|
||||
'BlockNumber': Amount,
|
||||
'Bytes': Unknown,
|
||||
'Proposal': Proposal,
|
||||
'u32': Amount,
|
||||
'u64': Amount
|
||||
};
|
||||
|
||||
export default function Param ({ className, label, style, subject, value }: Props): React$Node {
|
||||
// flowlint-next-line sketchy-null-string:off
|
||||
const defaultLabel = label || `${value.name}: ${value.type}`;
|
||||
const Component = Components[value.type];
|
||||
|
||||
return (
|
||||
<Component
|
||||
className={className}
|
||||
label={defaultLabel}
|
||||
style={style}
|
||||
subject={subject}
|
||||
value={value}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -2,8 +2,11 @@
|
||||
/* This software may be modified and distributed under the terms
|
||||
/* of the ISC license. See the LICENSE file for details. */
|
||||
|
||||
.extrinsics--CallSelect {}
|
||||
.extrinsics--Params {}
|
||||
|
||||
.extrinsics--CallSelect-indent > span.text {
|
||||
padding-left: 1.25em;
|
||||
.extrinsics--Params-Content {
|
||||
box-sizing: border-box;
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
.extrinsics--Params-Param {}
|
||||
31
packages/app-extrinsics/src/Params/Proposal.js
Normal file
31
packages/app-extrinsics/src/Params/Proposal.js
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { EncodedParams } from '../types';
|
||||
import type { Props } from './types';
|
||||
|
||||
import React from 'react';
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
|
||||
import Extrinsic from '../Extrinsic';
|
||||
|
||||
export default function Proposal ({ label, subject }: Props): React$Node {
|
||||
const extrinsic: rxjs$BehaviorSubject<EncodedParams> = new BehaviorSubject(({ isValid: false }: $Shape<EncodedParams>));
|
||||
|
||||
extrinsic.subscribe(({ data, isValid }: EncodedParams) => {
|
||||
subject.next({
|
||||
isValid,
|
||||
value: data
|
||||
});
|
||||
});
|
||||
|
||||
return (
|
||||
<Extrinsic
|
||||
isPrivate
|
||||
label={label}
|
||||
subject={extrinsic}
|
||||
/>
|
||||
);
|
||||
}
|
||||
35
packages/app-extrinsics/src/Params/Unknown.js
Normal file
35
packages/app-extrinsics/src/Params/Unknown.js
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { Props as BaseProps } from './types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import translate from '../translate';
|
||||
import Base from './Base';
|
||||
|
||||
type Props = BaseProps & {
|
||||
t: I18Next$Translate
|
||||
};
|
||||
|
||||
function Unknown ({ label, t, value: { type } }: Props): React$Node {
|
||||
return (
|
||||
<Base
|
||||
size='full'
|
||||
label={label}
|
||||
>
|
||||
<div className='extrinsics--Param-Unknown ui disabled dropdown selection'>
|
||||
{t('param.unknown', {
|
||||
defaultValue: `ERROR: Unknown input of type '{{type}}' found. No renderer exists`,
|
||||
replace: {
|
||||
type
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
</Base>
|
||||
);
|
||||
}
|
||||
|
||||
export default translate(Unknown);
|
||||
56
packages/app-extrinsics/src/Params/index.js
Normal file
56
packages/app-extrinsics/src/Params/index.js
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { Extrinsic } from '../extrinsics/types';
|
||||
import type { BaseProps, RawParam } from '../types';
|
||||
|
||||
import './Params.css';
|
||||
|
||||
import React from 'react';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
|
||||
import translate from '../translate';
|
||||
import Param from './Param';
|
||||
import createSubscriber from './subscriber';
|
||||
|
||||
type Props = BaseProps & {
|
||||
subject: rxjs$BehaviorSubject<Array<RawParam>>,
|
||||
value: Extrinsic;
|
||||
};
|
||||
|
||||
function Params ({ className, style, subject, t, value: { name, params } }: Props): React$Node {
|
||||
if (!params || !params.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const subjects = createSubscriber(params, subject);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['extrinsics--Params', 'extrinsics--split', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='full'>
|
||||
<Label>
|
||||
{t('params.intro', {
|
||||
defaultValue: 'with the supplied parameters'
|
||||
})}
|
||||
</Label>
|
||||
<div className='extrinsics--Params-Content'>
|
||||
{params.map((param, index) => (
|
||||
<Param
|
||||
className='extrinsics--Params-Param'
|
||||
key={`${name}:${param.name}:${param.type}`}
|
||||
subject={subjects[index]}
|
||||
value={param}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default translate(Params);
|
||||
25
packages/app-extrinsics/src/Params/initValue.js
Normal file
25
packages/app-extrinsics/src/Params/initValue.js
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { Extrinsic$Param } from '../extrinsics/types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
|
||||
export default function getInitValue ({ options: { initValue, minValue } = {}, type }: Extrinsic$Param): mixed {
|
||||
// flowlint-next-line sketchy-null-mixed:off
|
||||
const defaultValue = initValue || minValue;
|
||||
|
||||
switch (type) {
|
||||
case 'Balance':
|
||||
case 'BlockNumber':
|
||||
case 'u32':
|
||||
case 'u64':
|
||||
// flowlint-next-line sketchy-null-mixed:off
|
||||
return new BN(defaultValue || 0);
|
||||
|
||||
default:
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
23
packages/app-extrinsics/src/Params/subjects.js
Normal file
23
packages/app-extrinsics/src/Params/subjects.js
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { Extrinsic$Params } from '../extrinsics/types';
|
||||
import type { RawParam } from '../types';
|
||||
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
import isUndefined from '@polkadot/util/is/undefined';
|
||||
|
||||
import getInitValue from './initValue';
|
||||
|
||||
export default function createSubjects (params: Extrinsic$Params): Array<rxjs$BehaviorSubject<RawParam>> {
|
||||
return params.map((param) => {
|
||||
const value = getInitValue(param);
|
||||
|
||||
return new BehaviorSubject({
|
||||
isValid: !isUndefined(value),
|
||||
value
|
||||
});
|
||||
});
|
||||
}
|
||||
23
packages/app-extrinsics/src/Params/subscriber.js
Normal file
23
packages/app-extrinsics/src/Params/subscriber.js
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { Extrinsic$Params } from '../extrinsics/types';
|
||||
import type { RawParam } from '../types';
|
||||
|
||||
import createSubjects from './subjects';
|
||||
|
||||
export default function subscriber (params: Extrinsic$Params, subject: rxjs$BehaviorSubject<Array<RawParam>>): Array<rxjs$BehaviorSubject<RawParam>> {
|
||||
const subjects = createSubjects(params);
|
||||
|
||||
if (subject) {
|
||||
const onChange = (): void => {
|
||||
subject.next(subjects.map((s) => s.getValue()));
|
||||
};
|
||||
|
||||
subjects.forEach((s) => s.subscribe(onChange));
|
||||
}
|
||||
|
||||
return subjects;
|
||||
}
|
||||
16
packages/app-extrinsics/src/Params/types.js
Normal file
16
packages/app-extrinsics/src/Params/types.js
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { Extrinsic$Param } from '../extrinsics/types';
|
||||
import type { BareProps, RawParam } from '../types';
|
||||
|
||||
export type BaseProps = BareProps & {
|
||||
subject: rxjs$BehaviorSubject<RawParam>,
|
||||
value: Extrinsic$Param
|
||||
};
|
||||
|
||||
export type Props = BaseProps & {
|
||||
label: string
|
||||
};
|
||||
@ -1,29 +0,0 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps } from './types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import translate from './translate';
|
||||
import Account from './Account';
|
||||
import { recipientAddr } from './subjects';
|
||||
|
||||
type Props = BaseProps & {};
|
||||
|
||||
function Recipient (props: Props): React$Node {
|
||||
return (
|
||||
<Account
|
||||
{...props}
|
||||
className={['extrinsics--Recipient', props.className].join(' ')}
|
||||
label={props.t('recipient.label', {
|
||||
defaultValue: 'to the recipient'
|
||||
})}
|
||||
subject={recipientAddr}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default translate(Recipient);
|
||||
@ -1,29 +0,0 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps } from './types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import Account from './Account';
|
||||
import { senderAddr } from './subjects';
|
||||
import translate from './translate';
|
||||
|
||||
type Props = BaseProps & {};
|
||||
|
||||
function Sender (props: Props): React$Node {
|
||||
return (
|
||||
<Account
|
||||
{...props}
|
||||
className={['extrinsics--Sender', props.className].join(' ')}
|
||||
label={props.t('sender.label', {
|
||||
defaultValue: 'using the selected account'
|
||||
})}
|
||||
subject={senderAddr}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default translate(Sender);
|
||||
@ -18,7 +18,7 @@ type Props = BaseProps & {
|
||||
value: QueueTx
|
||||
};
|
||||
|
||||
function Extrinsic ({ className, style, t, value: { message, method, publicKey } }: Props): React$Node {
|
||||
function Decoded ({ className, style, t, value: { data, extrinsic, index, publicKey } }: Props): React$Node {
|
||||
const from = u8aToHexShort(publicKey);
|
||||
|
||||
return (
|
||||
@ -33,20 +33,20 @@ function Extrinsic ({ className, style, t, value: { message, method, publicKey }
|
||||
/>
|
||||
<div className='expanded'>
|
||||
<p>
|
||||
<Trans i18nkey='extrinsic.short'>
|
||||
You are about to sign a message from <span className='code'>{from}</span> calling <span className='code'>{method}</span>
|
||||
<Trans i18nkey='decoded.short'>
|
||||
You are about to sign a message from <span className='code'>{from}</span> calling <span className='code'>{extrinsic.name}</span> with an index of <span className='code'>{index.toString()}</span>
|
||||
</Trans>
|
||||
</p>
|
||||
<p>
|
||||
{t('extrinsic.data', {
|
||||
defaultValue: 'The encoded message to be signed contains the data'
|
||||
{t('decoded.data', {
|
||||
defaultValue: 'The encoded parameters contains the data'
|
||||
})}
|
||||
</p>
|
||||
<p className='code'>{u8aToHex(message)}</p>
|
||||
<p className='code'>{u8aToHex(data)}</p>
|
||||
</div>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
);
|
||||
}
|
||||
|
||||
export default translate(Extrinsic);
|
||||
export default translate(Decoded);
|
||||
@ -12,27 +12,29 @@ import React from 'react';
|
||||
import Button from 'semantic-ui-react/dist/es/elements/Button';
|
||||
import Modal from 'semantic-ui-react/dist/es/modules/Modal';
|
||||
import withApi from '@polkadot/rx-react/with/api';
|
||||
import withObservable from '@polkadot/rx-react/with/observable';
|
||||
|
||||
import { queueTx } from '../subjects';
|
||||
import translate from '../translate';
|
||||
import Extrinsic from './Extrinsic';
|
||||
import Decoded from './Decoded';
|
||||
import submitExtrinsic from './submit';
|
||||
|
||||
type Props = BaseProps & ApiProps & {
|
||||
value?: QueueTx
|
||||
subject: rxjs$BehaviorSubject<QueueTx>,
|
||||
value: QueueTx
|
||||
};
|
||||
|
||||
function Signer ({ api, className, style, t, value }: Props): React$Node {
|
||||
if (!value) {
|
||||
function Signer ({ api, className, subject, style, t, value }: Props): React$Node {
|
||||
if (value.status !== 'queued') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const onClose = () => {
|
||||
queueTx.next();
|
||||
const onClose = (): void => {
|
||||
subject.next({
|
||||
...value,
|
||||
status: 'cancelled'
|
||||
});
|
||||
};
|
||||
const onSign = () => {
|
||||
submitExtrinsic(api, value.publicKey, value.message).then(onClose);
|
||||
const onSign = (): void => {
|
||||
submitExtrinsic(api, value, subject);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -47,7 +49,7 @@ function Signer ({ api, className, style, t, value }: Props): React$Node {
|
||||
defaultValue: 'Sign and submit'
|
||||
})}
|
||||
</Modal.Header>
|
||||
<Extrinsic value={value} />
|
||||
<Decoded value={value} />
|
||||
<Modal.Actions>
|
||||
<Button onClick={onClose}>
|
||||
{t('signer.cancel', {
|
||||
@ -68,7 +70,5 @@ function Signer ({ api, className, style, t, value }: Props): React$Node {
|
||||
}
|
||||
|
||||
export default translate(
|
||||
withApi(
|
||||
withObservable(queueTx)(Signer)
|
||||
)
|
||||
withApi(Signer)
|
||||
);
|
||||
|
||||
@ -4,24 +4,36 @@
|
||||
// @flow
|
||||
|
||||
import type { RxApiInterface } from '@polkadot/rx-api/types';
|
||||
import type { QueueTx } from '../types';
|
||||
|
||||
import encodeCall from '../encode/call';
|
||||
import keyring from '../keyring';
|
||||
|
||||
import sign from './sign';
|
||||
|
||||
export default function submit (api: RxApiInterface, publicKey: Uint8Array, message: Uint8Array): Promise<void> {
|
||||
export default function submit (api: RxApiInterface, tx: QueueTx, subject: rxjs$BehaviorSubject<QueueTx>): Promise<void> {
|
||||
return api.author
|
||||
.submitExtrinsic(
|
||||
sign(
|
||||
keyring.getPair(publicKey),
|
||||
message
|
||||
keyring.getPair(tx.publicKey),
|
||||
encodeCall(tx.publicKey, tx.index, tx.data)
|
||||
)
|
||||
)
|
||||
.toPromise()
|
||||
.then((result) => {
|
||||
console.log('submitExtrinsic: result=', result);
|
||||
|
||||
subject.next({
|
||||
...tx,
|
||||
status: 'sent'
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('submitExtrinsic: error=', error);
|
||||
|
||||
subject.next({
|
||||
...tx,
|
||||
status: 'error'
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
export default function getValues (): Array<mixed> {
|
||||
return [];
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps } from '../../types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import translate from '../../translate';
|
||||
import getValues from './getValues';
|
||||
|
||||
type Props = BaseProps & {};
|
||||
|
||||
function StakingStake ({ className, style }: Props): React$Node {
|
||||
return (
|
||||
<div
|
||||
className={['extrinsics--StakingStake', className].join(' ')}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
StakingStake.getValues = getValues;
|
||||
|
||||
export default translate(StakingStake);
|
||||
@ -1,48 +0,0 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps } from '../../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React from 'react';
|
||||
import Input from 'semantic-ui-react/dist/es/elements/Input';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
|
||||
import translate from '../../translate';
|
||||
import { amount } from './subjects';
|
||||
|
||||
type Props = BaseProps & {};
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const onChange = (event: SyntheticEvent<*>, { value }): void => {
|
||||
amount.next(
|
||||
new BN(value || 0)
|
||||
);
|
||||
};
|
||||
|
||||
function Amount ({ className, style, t }: Props): React$Node {
|
||||
return (
|
||||
<div
|
||||
className={['extrinsics--split', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='small'>
|
||||
<Label>
|
||||
{t('transfer.amount', {
|
||||
defaultValue: 'sending an amount of'
|
||||
})}
|
||||
</Label>
|
||||
<Input
|
||||
defaultValue={1}
|
||||
min={1}
|
||||
onChange={onChange}
|
||||
type='number'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default translate(Amount);
|
||||
@ -1,14 +0,0 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import { recipientAddr } from '../../subjects';
|
||||
import { amount } from './subjects';
|
||||
|
||||
export default function getValues (): Array<mixed> {
|
||||
return [
|
||||
recipientAddr.getValue(),
|
||||
amount.getValue()
|
||||
];
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps } from '../../types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import translate from '../../translate';
|
||||
import Recipient from '../../Recipient';
|
||||
import Amount from './Amount';
|
||||
import getValues from './getValues';
|
||||
|
||||
type Props = BaseProps & {};
|
||||
|
||||
function StakingTransfer ({ className, style }: Props): React$Node {
|
||||
return (
|
||||
<div
|
||||
className={['extrinsics--StakingTransfer', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<Amount />
|
||||
<Recipient />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
StakingTransfer.getValues = getValues;
|
||||
|
||||
export default translate(StakingTransfer);
|
||||
@ -1,9 +0,0 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
|
||||
export const amount = new BehaviorSubject(new BN(1));
|
||||
@ -1,8 +0,0 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
export default function getValues (): Array<mixed> {
|
||||
return [];
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps } from '../../types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import translate from '../../translate';
|
||||
import getValues from './getValues';
|
||||
|
||||
type Props = BaseProps & {};
|
||||
|
||||
function StakingUnstake ({ className, style }: Props): React$Node {
|
||||
return (
|
||||
<div
|
||||
className={['extrinsics--StakingUnstake', className].join(' ')}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
StakingUnstake.getValues = getValues;
|
||||
|
||||
export default translate(StakingUnstake);
|
||||
@ -3,40 +3,36 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps } from './types';
|
||||
import type BN from 'bn.js';
|
||||
import type { BareProps } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
import RxNonce from '@polkadot/rx-react/Nonce';
|
||||
import withObservableParams from '@polkadot/rx-react/with/observableParams';
|
||||
|
||||
import translate from './translate';
|
||||
import { senderAddr, senderIndex } from './subjects';
|
||||
type Props = BareProps & {
|
||||
label: string,
|
||||
subject: rxjs$BehaviorSubject<BN>,
|
||||
value: rxjs$BehaviorSubject<Uint8Array>
|
||||
};
|
||||
|
||||
type Props = BaseProps & {};
|
||||
export default function Nonce ({ className, label, style, subject, t, value }: Props): React$Node {
|
||||
const SenderNonce = withObservableParams(value)(RxNonce);
|
||||
|
||||
const SenderNonce = withObservableParams(senderAddr)(RxNonce);
|
||||
|
||||
function Nonce ({ className, style, t }: Props): React$Node {
|
||||
return (
|
||||
<div
|
||||
className={['extrinsics--split', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='small'>
|
||||
<Label>
|
||||
{t('nonce.label', {
|
||||
defaultValue: 'with an index'
|
||||
})}
|
||||
</Label>
|
||||
<Label>{label}</Label>
|
||||
<SenderNonce
|
||||
className='ui disabled dropdown selection'
|
||||
classNameUpdated='hasUpdated'
|
||||
subject={senderIndex}
|
||||
subject={subject}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default translate(Nonce);
|
||||
15
packages/app-extrinsics/src/Submission/Submission.css
Normal file
15
packages/app-extrinsics/src/Submission/Submission.css
Normal file
@ -0,0 +1,15 @@
|
||||
/* Copyright 2017-2018 Jaco Greeff
|
||||
/* This software may be modified and distributed under the terms
|
||||
/* of the ISC license. See the LICENSE file for details. */
|
||||
|
||||
.extrinsics--Submission {}
|
||||
|
||||
.extrinsics--Submission-ButtonRow {
|
||||
margin: 1em 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.extrinsics--Submission-ButtonRow .button {
|
||||
text-align: left;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
39
packages/app-extrinsics/src/Submission/Submit.js
Normal file
39
packages/app-extrinsics/src/Submission/Submit.js
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps, QueueTx } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
import Button from 'semantic-ui-react/dist/es/elements/Button';
|
||||
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = BaseProps & {
|
||||
subject: rxjs$BehaviorSubject<QueueTx>,
|
||||
value: QueueTx;
|
||||
};
|
||||
|
||||
function Submit ({ className, subject, style, t, value }: Props): React$Node {
|
||||
const onSubmit = (): void => {
|
||||
subject.next({
|
||||
...value,
|
||||
status: 'queued'
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Button
|
||||
disabled={!value.isValid}
|
||||
onClick={onSubmit}
|
||||
primary
|
||||
>
|
||||
{t('submit.label', {
|
||||
defaultValue: 'Submit Extrinsic'
|
||||
})}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
export default translate(Submit);
|
||||
59
packages/app-extrinsics/src/Submission/index.js
Normal file
59
packages/app-extrinsics/src/Submission/index.js
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps, QueueTx } from '../types';
|
||||
|
||||
import './Submission.css';
|
||||
|
||||
import React from 'react';
|
||||
import withObservable from '@polkadot/rx-react/with/observable';
|
||||
|
||||
import Account from '../Account';
|
||||
import Extrinsic from '../Extrinsic';
|
||||
import translate from '../translate';
|
||||
import Nonce from './Nonce';
|
||||
import Submit from './Submit';
|
||||
import createSubjects from './subjects';
|
||||
|
||||
type Props = BaseProps & {
|
||||
subject: rxjs$BehaviorSubject<QueueTx>
|
||||
};
|
||||
|
||||
function Submission ({ className, subject, style, t }: Props): React$Node {
|
||||
const subjects = createSubjects();
|
||||
const Button = withObservable(subjects.call)(Submit);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['extrinsics--Submission', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<Account
|
||||
label={t('display.sender', {
|
||||
defaultValue: 'using the selected account'
|
||||
})}
|
||||
subject={subjects.sender}
|
||||
/>
|
||||
<Nonce
|
||||
label={t('display.nonce', {
|
||||
defaultValue: 'with an index'
|
||||
})}
|
||||
subject={subjects.index}
|
||||
value={subjects.sender}
|
||||
/>
|
||||
<Extrinsic
|
||||
label={t('display.method', {
|
||||
defaultValue: 'submit the following extrinsic'
|
||||
})}
|
||||
subject={subjects.method}
|
||||
/>
|
||||
<div className='extrinsics--Submission-ButtonRow'>
|
||||
<Button subject={subject} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default translate(Submission);
|
||||
46
packages/app-extrinsics/src/Submission/subjects.js
Normal file
46
packages/app-extrinsics/src/Submission/subjects.js
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { EncodedParams, QueueTx } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
|
||||
type Subjects = {
|
||||
call: rxjs$BehaviorSubject<QueueTx>,
|
||||
index: rxjs$BehaviorSubject<BN>,
|
||||
method: rxjs$BehaviorSubject<EncodedParams>,
|
||||
sender: rxjs$BehaviorSubject<Uint8Array>
|
||||
};
|
||||
|
||||
export default function createSubjects (): Subjects {
|
||||
const subjects = {
|
||||
index: new BehaviorSubject(new BN(0)),
|
||||
call: new BehaviorSubject(({ isValid: false }: $Shape<QueueTx>)),
|
||||
method: new BehaviorSubject(({ isValid: false }: $Shape<EncodedParams>)),
|
||||
sender: new BehaviorSubject(new Uint8Array([]))
|
||||
};
|
||||
|
||||
const onChange = (): void => {
|
||||
const publicKey = subjects.sender.getValue();
|
||||
const message = subjects.method.getValue();
|
||||
const index = subjects.index.getValue();
|
||||
const isValid = !!(publicKey && publicKey.length && message && message.isValid);
|
||||
|
||||
subjects.call.next({
|
||||
data: message.data,
|
||||
extrinsic: message.extrinsic,
|
||||
isValid,
|
||||
index,
|
||||
publicKey,
|
||||
status: 'incomplete'
|
||||
});
|
||||
};
|
||||
|
||||
subjects.method.subscribe(onChange);
|
||||
subjects.sender.subscribe(onChange);
|
||||
|
||||
return subjects;
|
||||
}
|
||||
19
packages/app-extrinsics/src/encode/call.js
Normal file
19
packages/app-extrinsics/src/encode/call.js
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
// TODO: Move to API
|
||||
|
||||
import type BN from 'bn.js';
|
||||
|
||||
const bnToU8a = require('@polkadot/util/bn/toU8a');
|
||||
const u8aConcat = require('@polkadot/util/u8a/concat');
|
||||
|
||||
module.exports = function encodeCall (publicKey: Uint8Array, nonce: number | BN, data: Uint8Array): Uint8Array {
|
||||
return u8aConcat(
|
||||
publicKey,
|
||||
bnToU8a(nonce, 64, true),
|
||||
data
|
||||
);
|
||||
};
|
||||
21
packages/app-extrinsics/src/encode/extrinsic.js
Normal file
21
packages/app-extrinsics/src/encode/extrinsic.js
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { Extrinsic } from '../extrinsics/types';
|
||||
|
||||
const u8aConcat = require('@polkadot/util/u8a/concat');
|
||||
|
||||
const encodeParams = require('./params');
|
||||
|
||||
module.exports = function encodeExtrinsic (extrinsic: Extrinsic, values?: Array<mixed>): Uint8Array {
|
||||
if (!extrinsic) {
|
||||
return new Uint8Array([]);
|
||||
}
|
||||
|
||||
return u8aConcat(
|
||||
extrinsic.index,
|
||||
encodeParams(extrinsic.params, values)
|
||||
);
|
||||
};
|
||||
@ -8,16 +8,13 @@
|
||||
import type BN from 'bn.js';
|
||||
import type { Extrinsic } from '../extrinsics/types';
|
||||
|
||||
const bnToU8a = require('@polkadot/util/bn/toU8a');
|
||||
const u8aConcat = require('@polkadot/util/u8a/concat');
|
||||
const encodeCall = require('./call');
|
||||
const encodeExtrinsic = require('./extrinsic');
|
||||
|
||||
const encodeParams = require('./params');
|
||||
|
||||
module.exports = function encode ({ index, params }: Extrinsic, publicKey: Uint8Array, nonce: number | BN, values: Array<mixed>): Uint8Array {
|
||||
return u8aConcat(
|
||||
module.exports = function encode (extrinsic: Extrinsic, publicKey: Uint8Array, nonce: number | BN, values?: Array<mixed>): Uint8Array {
|
||||
return encodeCall(
|
||||
publicKey,
|
||||
bnToU8a(nonce, 64, true),
|
||||
index,
|
||||
encodeParams(values, params)
|
||||
nonce,
|
||||
encodeExtrinsic(extrinsic, values)
|
||||
);
|
||||
};
|
||||
|
||||
@ -3,20 +3,31 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { Extrinsic$Type } from '../extrinsics/types';
|
||||
import type { Extrinsic$Param } from '../extrinsics/types';
|
||||
|
||||
const bnToU8a = require('@polkadot/util/bn/toU8a');
|
||||
const u8aToU8a = require('@polkadot/util/u8a/toU8a');
|
||||
|
||||
// flowlint-next-line unclear-type:off
|
||||
module.exports = function encodeValue (value: any, type: Extrinsic$Type): Uint8Array {
|
||||
module.exports = function encodeValue ({ type }: Extrinsic$Param, value: any): Uint8Array {
|
||||
switch (type) {
|
||||
case 'AccountId':
|
||||
return value;
|
||||
|
||||
case 'Balance':
|
||||
case 'BlockNumber':
|
||||
case 'u64':
|
||||
return bnToU8a(value, 64, true);
|
||||
|
||||
case 'Bytes':
|
||||
return u8aToU8a(value);
|
||||
|
||||
case 'Proposal':
|
||||
return u8aToU8a(value);
|
||||
|
||||
case 'u32':
|
||||
return bnToU8a(value, 32, true);
|
||||
|
||||
default:
|
||||
throw new Error(`Unable to encode value with type '${type}'`);
|
||||
}
|
||||
|
||||
@ -9,8 +9,8 @@ const u8aConcat = require('@polkadot/util/u8a/concat');
|
||||
|
||||
const encodeParam = require('./param');
|
||||
|
||||
module.exports = function encodeParams (values: Array<mixed>, params: Extrinsic$Params): Uint8Array {
|
||||
return u8aConcat.apply(null, values.map((value, index) => {
|
||||
return encodeParam(value, params[index]);
|
||||
module.exports = function encodeParams (params: Extrinsic$Params, values?: Array<mixed> = []): Uint8Array {
|
||||
return u8aConcat.apply(null, params.map((param, index) => {
|
||||
return encodeParam(param, values[index]);
|
||||
}));
|
||||
};
|
||||
|
||||
@ -7,5 +7,8 @@ import type { ExtrinsicsBasic } from './types';
|
||||
|
||||
module.exports = ({
|
||||
description: 'Consensus',
|
||||
methods: {}
|
||||
methods: {
|
||||
public: [],
|
||||
private: []
|
||||
}
|
||||
}: ExtrinsicsBasic);
|
||||
|
||||
@ -7,5 +7,8 @@ import type { ExtrinsicsBasic } from './types';
|
||||
|
||||
module.exports = ({
|
||||
description: 'Council',
|
||||
methods: {}
|
||||
methods: {
|
||||
public: [],
|
||||
private: []
|
||||
}
|
||||
}: ExtrinsicsBasic);
|
||||
|
||||
@ -7,5 +7,8 @@ import type { ExtrinsicsBasic } from './types';
|
||||
|
||||
module.exports = ({
|
||||
description: 'Council Voting',
|
||||
methods: {}
|
||||
methods: {
|
||||
public: [],
|
||||
private: []
|
||||
}
|
||||
}: ExtrinsicsBasic);
|
||||
|
||||
@ -7,5 +7,18 @@ import type { ExtrinsicsBasic } from './types';
|
||||
|
||||
module.exports = ({
|
||||
description: 'Democracy',
|
||||
methods: {}
|
||||
methods: {
|
||||
public: [
|
||||
{
|
||||
description: 'Propose',
|
||||
index: 0,
|
||||
name: 'propose',
|
||||
params: [
|
||||
{ name: 'proposal', type: 'Proposal' },
|
||||
{ name: 'value', type: 'Balance' }
|
||||
]
|
||||
}
|
||||
],
|
||||
private: []
|
||||
}
|
||||
}: ExtrinsicsBasic);
|
||||
|
||||
@ -5,8 +5,9 @@
|
||||
|
||||
// TODO: Move to API
|
||||
|
||||
import type { Extrinsic, Extrinsics, ExtrinsicsBasic, ExtrinsicsMap, ExtrinsicSection } from './types';
|
||||
import type { Extrinsic, Extrinsics, ExtrinsicBasic, ExtrinsicsBasic, ExtrinsicsMap, ExtrinsicSection } from './types';
|
||||
|
||||
const assert = require('@polkadot/util/assert');
|
||||
const bnToU8a = require('@polkadot/util/bn/toU8a');
|
||||
const u8aConcat = require('@polkadot/util/u8a/concat');
|
||||
|
||||
@ -25,51 +26,57 @@ const map: { [string]: ExtrinsicsBasic } = {
|
||||
council, // 4
|
||||
councilVoting // 5
|
||||
};
|
||||
const sectionNames = Object.keys(map);
|
||||
const extrinsics: Extrinsics = ({
|
||||
sections: []
|
||||
}: $Shape<Extrinsics>);
|
||||
const extrinsicsMap: ExtrinsicsMap = {};
|
||||
const extrinsics: Extrinsics = {
|
||||
sections: [],
|
||||
get: (method: string): Extrinsic => {
|
||||
const extrinsic = extrinsicsMap[method];
|
||||
|
||||
sectionNames.reduce((sections: Array<ExtrinsicSection>, sectionName: string, _index) => {
|
||||
const sectionSource = map[sectionName];
|
||||
const sectionIndex = bnToU8a(_index, 8);
|
||||
const methodNames = Object.keys(sectionSource.methods);
|
||||
assert(extrinsic, `Unable to retrieve extrinsic with name '${method}'`);
|
||||
|
||||
if (!methodNames.length) {
|
||||
return sections;
|
||||
return extrinsic;
|
||||
}
|
||||
};
|
||||
|
||||
const sectionNames = Object.keys(map);
|
||||
|
||||
function mapMethods (sectionSource: ExtrinsicsBasic, section: ExtrinsicSection, isPrivate: boolean): void {
|
||||
const methods = sectionSource.methods[isPrivate ? 'private' : 'public'];
|
||||
|
||||
methods.forEach(({ description, index, name, params }: ExtrinsicBasic) => {
|
||||
const method: Extrinsic = {
|
||||
description,
|
||||
index: u8aConcat(section.index, bnToU8a(index, 8)),
|
||||
isPrivate,
|
||||
name: `${section.name}_${name}`,
|
||||
params
|
||||
};
|
||||
|
||||
extrinsicsMap[method.name] = method;
|
||||
section[isPrivate ? 'hasPrivate' : 'hasPublic'] = true;
|
||||
|
||||
section.methods.push(method);
|
||||
});
|
||||
}
|
||||
|
||||
sectionNames.reduce((sections: Array<ExtrinsicSection>, sectionName: string, index: number) => {
|
||||
const sectionSource = map[sectionName];
|
||||
|
||||
const section: ExtrinsicSection = {
|
||||
description: sectionSource.description,
|
||||
hasPrivate: false,
|
||||
hasPublic: false,
|
||||
index: bnToU8a(index, 8),
|
||||
methods: [],
|
||||
name: sectionName
|
||||
};
|
||||
|
||||
methodNames.reduce((methods: Array<Extrinsic>, methodName: string) => {
|
||||
const methodSource = sectionSource.methods[methodName];
|
||||
const name = `${sectionName}_${methodName}`;
|
||||
const index = u8aConcat(sectionIndex, bnToU8a(methodSource.index, 8));
|
||||
const method: Extrinsic = {
|
||||
description: methodSource.description,
|
||||
index,
|
||||
name,
|
||||
params: methodSource.params
|
||||
};
|
||||
|
||||
methods.push(method);
|
||||
extrinsicsMap[name] = method;
|
||||
|
||||
return methods;
|
||||
}, section.methods);
|
||||
mapMethods(sectionSource, section, true);
|
||||
mapMethods(sectionSource, section, false);
|
||||
|
||||
sections.push(section);
|
||||
|
||||
return sections;
|
||||
}, extrinsics.sections);
|
||||
|
||||
extrinsics.get = function get (sectionMethod: string): Extrinsic {
|
||||
return extrinsicsMap[sectionMethod];
|
||||
};
|
||||
|
||||
module.exports = extrinsics;
|
||||
|
||||
@ -7,5 +7,8 @@ import type { ExtrinsicsBasic } from './types';
|
||||
|
||||
module.exports = ({
|
||||
description: 'Session',
|
||||
methods: {}
|
||||
methods: {
|
||||
public: [],
|
||||
private: []
|
||||
}
|
||||
}: ExtrinsicsBasic);
|
||||
|
||||
@ -8,20 +8,60 @@ import type { ExtrinsicsBasic } from './types';
|
||||
module.exports = ({
|
||||
description: 'Staking',
|
||||
methods: {
|
||||
transfer: {
|
||||
description: 'Transfer',
|
||||
index: 0,
|
||||
params: ['AccountId', 'Balance']
|
||||
},
|
||||
stake: {
|
||||
description: 'Stake',
|
||||
index: 1,
|
||||
params: []
|
||||
},
|
||||
unstake: {
|
||||
description: 'Unstake',
|
||||
index: 2,
|
||||
params: []
|
||||
}
|
||||
public: [
|
||||
{
|
||||
description: 'Transfer',
|
||||
index: 0,
|
||||
name: 'transfer',
|
||||
params: [
|
||||
{ name: 'recipient', type: 'AccountId' },
|
||||
{ name: 'value', type: 'Balance', options: { minValue: 1 } }
|
||||
]
|
||||
},
|
||||
{
|
||||
description: 'Stake',
|
||||
index: 1,
|
||||
name: 'stake',
|
||||
params: []
|
||||
},
|
||||
{
|
||||
description: 'Unstake',
|
||||
index: 2,
|
||||
name: 'unstake',
|
||||
params: []
|
||||
}
|
||||
],
|
||||
private: [
|
||||
{
|
||||
description: 'Set sessions per era',
|
||||
index: 0,
|
||||
name: 'setSessionsPerEra',
|
||||
params: [
|
||||
{ name: 'sessions', type: 'u64' }
|
||||
]
|
||||
},
|
||||
{
|
||||
description: 'Set bonding duration',
|
||||
index: 1,
|
||||
name: 'setBondingDuration',
|
||||
params: [
|
||||
{ name: 'duration', type: 'u64' }
|
||||
]
|
||||
},
|
||||
{
|
||||
description: 'Set validator count',
|
||||
index: 2,
|
||||
name: 'setValidatorCount',
|
||||
params: [
|
||||
{ name: 'count', type: 'u32' }
|
||||
]
|
||||
},
|
||||
{
|
||||
description: 'Force new era',
|
||||
index: 3,
|
||||
name: 'forceNewEra',
|
||||
params: []
|
||||
}
|
||||
]
|
||||
}
|
||||
}: ExtrinsicsBasic);
|
||||
|
||||
@ -3,32 +3,49 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
export type Extrinsic$Type = 'AccountId' | 'Balance' | 'BlockNumber';
|
||||
export type Extrinsic$Type = 'AccountId' | 'Balance' | 'BlockNumber' | 'Bytes' | 'Proposal' | 'u32' | 'u64';
|
||||
|
||||
export type Extrinsic$Params = Array<Extrinsic$Type>;
|
||||
export type Extrinsic$Param = {
|
||||
name: string,
|
||||
options?: {
|
||||
initValue?: mixed,
|
||||
minValue?: mixed,
|
||||
maxValue?: mixed
|
||||
},
|
||||
type: Extrinsic$Type
|
||||
};
|
||||
|
||||
export type Extrinsic$Params = Array<Extrinsic$Param>;
|
||||
|
||||
export type ExtrinsicBasic = {
|
||||
description: string,
|
||||
index: number,
|
||||
isPrivate?: boolean,
|
||||
name: string,
|
||||
params: Extrinsic$Params
|
||||
}
|
||||
|
||||
export type ExtrinsicsBasic = {
|
||||
description: string,
|
||||
methods: {
|
||||
[string]: ExtrinsicBasic
|
||||
private: Array<ExtrinsicBasic>,
|
||||
public: Array<ExtrinsicBasic>
|
||||
}
|
||||
}
|
||||
|
||||
export type Extrinsic = {
|
||||
description: string,
|
||||
index: Uint8Array,
|
||||
isPrivate: boolean,
|
||||
name: string,
|
||||
params: Extrinsic$Params
|
||||
};
|
||||
|
||||
export type ExtrinsicSection = {
|
||||
description: string,
|
||||
hasPrivate: boolean,
|
||||
hasPublic: boolean,
|
||||
index: Uint8Array,
|
||||
methods: Array<Extrinsic>,
|
||||
name: string
|
||||
};
|
||||
|
||||
@ -21,7 +21,6 @@
|
||||
|
||||
.extrinsics--split > div {
|
||||
box-sizing: border-box;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
|
||||
.extrinsics--split > div.full {
|
||||
@ -29,6 +28,12 @@
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.extrinsics--split > div.large,
|
||||
.extrinsics--split > div.medium,
|
||||
.extrinsics--split > div.small {
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
|
||||
.extrinsics--split > div.large {
|
||||
flex: 0 75%;
|
||||
min-width: 0;
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { QueueTx } from './types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
|
||||
export const extrinsicName: rxjs$BehaviorSubject<?string> = new BehaviorSubject();
|
||||
export const recipientAddr: rxjs$BehaviorSubject<?Uint8Array> = new BehaviorSubject();
|
||||
export const queueTx: rxjs$BehaviorSubject<?QueueTx> = new BehaviorSubject();
|
||||
export const senderAddr: rxjs$BehaviorSubject<?Uint8Array> = new BehaviorSubject();
|
||||
export const senderIndex: rxjs$BehaviorSubject<BN> = new BehaviorSubject(new BN(0));
|
||||
@ -3,16 +3,35 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
export type BaseProps = {
|
||||
import type BN from 'bn.js';
|
||||
import type { Extrinsic } from './extrinsics/types';
|
||||
|
||||
export type BareProps = {
|
||||
className?: string,
|
||||
style?: {
|
||||
[string]: string
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
export type BaseProps = BareProps & {
|
||||
t: I18Next$Translate
|
||||
};
|
||||
|
||||
export type QueueTx = {
|
||||
message: Uint8Array,
|
||||
method: string,
|
||||
publicKey: Uint8Array
|
||||
export type RawParam = {
|
||||
isValid: boolean,
|
||||
value: mixed,
|
||||
}
|
||||
|
||||
export type EncodedParams = {
|
||||
data: Uint8Array,
|
||||
extrinsic: Extrinsic,
|
||||
isValid: boolean
|
||||
};
|
||||
|
||||
export type QueueTx$Status = 'incomplete' | 'cancelled' | 'error' | 'queued' | 'sent';
|
||||
|
||||
export type QueueTx = EncodedParams & {
|
||||
index: BN,
|
||||
publicKey: Uint8Array,
|
||||
status: QueueTx$Status
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user