App for realtime storage queries (#11)
* Create app-storage structure * Split shared components into ui-react-app * Cleanup @flow issues * Rename apps classes * Split with ui-react-app operational * Import es semantic-ui * Selection section/key split into 2 * Basic storage queries (no-params) in-place * Upgrades * No-param queries operational * Default values operational (dropdown) * Additional cleanups, constrolled value * @flow updates * @flow fixes * Move Params to ui-react-app (future-use in app-storage) * Fix final @flow issues * Query removal * Cleanups * Update README * Upgrades * Fixup cached components * Bump @polkadot/rx-react * Simple explorer animations * Additional (final) cleanups
This commit is contained in:
parent
3d17f951ab
commit
a5607ac90e
@ -14,5 +14,4 @@ all=warn
|
||||
include_warnings=true
|
||||
module.name_mapper='^@polkadot/app-\(accounts\|explorer\|extrinsics\|home\|rpc\|settings\|storage\)\(.*\)$' -> '<PROJECT_ROOT>/packages/app-\1/src\2'
|
||||
module.name_mapper='^@polkadot/apps\(.*\)$' -> '<PROJECT_ROOT>/packages/apps/src\1'
|
||||
module.name_mapper='^@polkadot/extrinsics-\(codec\|polkadot\|substrate\)\(.*\)$' -> '<PROJECT_ROOT>/packages/extrinsics-\1/src\2'
|
||||
module.name_mapper='^@polkadot/extrinsics\(.*\)$' -> '<PROJECT_ROOT>/packages/extrinsics/src\1'
|
||||
module.name_mapper='^@polkadot/ui-react-app\(.*\)$' -> '<PROJECT_ROOT>/packages/ui-react-app/src\1'
|
||||
|
||||
13
README.md
13
README.md
@ -12,3 +12,16 @@
|
||||
A Portal into the Polkadot network. Provides a view and interaction layer from a browser.
|
||||
|
||||
This can be accessed as a hosted application via [https://polkadot.js.org/apps/](https://polkadot.js.org/apps/).
|
||||
|
||||
## overview
|
||||
|
||||
The repo is split into a number of packages, each representing an application. These are -
|
||||
|
||||
- [apps](packages/apps/) This is the main entry point. It handles the selection sidebar and routing to the specific application being displayed.
|
||||
- [app-explorer](packages/app-explorer/) A simple block explorer. It only shows the most recent blocks, updating as they become available.
|
||||
- [app-extrinsics](packages/app-extrinsics/) Submission of extrinsics to a node.
|
||||
- [app-storage](packages/app-storage/) A simple node storage query application. Multiple queries can be queued and updates as new values become available.
|
||||
|
||||
In addition the following libraries are also included in the repo -
|
||||
|
||||
- [ui-react-app](packages/ui-react-app/) A reactive (using RxJS) application framework with a number of useful shared components. This will be moved to the [@polkadot/ui](https://github.com/polkadot-js/ui/) repository once it reaches a base level of stability and usability. (At this point with the framework being tested on the apps above, it makes development easier having it close)
|
||||
|
||||
3
flow-typed/react-dropzone.js
vendored
3
flow-typed/react-dropzone.js
vendored
@ -1,5 +1,6 @@
|
||||
// @flow
|
||||
|
||||
declare module 'react-dropzone' {
|
||||
declare module.exports: React$StatelessFunctionalComponent<*>
|
||||
declare type Dropzone = React$StatelessFunctionalComponent<*>;
|
||||
declare module.exports: Dropzone;
|
||||
}
|
||||
|
||||
14
flow-typed/semantic-ui-react.js
vendored
14
flow-typed/semantic-ui-react.js
vendored
@ -3,23 +3,23 @@
|
||||
declare module 'semantic-ui-react/dist/es/collections/Menu' {
|
||||
declare module.exports: React$StatelessFunctionalComponent<*> & {
|
||||
Item: React$StatelessFunctionalComponent<*>
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
declare module 'semantic-ui-react/dist/es/elements/Button' {
|
||||
declare module.exports: React$StatelessFunctionalComponent<*>
|
||||
declare module.exports: React$StatelessFunctionalComponent<*>;
|
||||
}
|
||||
|
||||
declare module 'semantic-ui-react/dist/es/elements/Icon' {
|
||||
declare module.exports: React$StatelessFunctionalComponent<*>
|
||||
declare module.exports: React$StatelessFunctionalComponent<*>;
|
||||
}
|
||||
|
||||
declare module 'semantic-ui-react/dist/es/elements/Input' {
|
||||
declare module.exports: React$StatelessFunctionalComponent<*>
|
||||
declare module.exports: React$StatelessFunctionalComponent<*>;
|
||||
}
|
||||
|
||||
declare module 'semantic-ui-react/dist/es/elements/Label' {
|
||||
declare module.exports: React$StatelessFunctionalComponent<*>
|
||||
declare module.exports: React$StatelessFunctionalComponent<*>;
|
||||
}
|
||||
|
||||
declare module 'semantic-ui-react/dist/es/modules/Dropdown' {
|
||||
@ -27,7 +27,7 @@ declare module 'semantic-ui-react/dist/es/modules/Dropdown' {
|
||||
Divider: React$StatelessFunctionalComponent<*>,
|
||||
Header: React$StatelessFunctionalComponent<*>,
|
||||
Item: React$StatelessFunctionalComponent<*>
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
declare module 'semantic-ui-react/dist/es/modules/Modal' {
|
||||
@ -35,5 +35,5 @@ declare module 'semantic-ui-react/dist/es/modules/Modal' {
|
||||
Actions: React$StatelessFunctionalComponent<*>,
|
||||
Content: React$StatelessFunctionalComponent<*>,
|
||||
Header: React$StatelessFunctionalComponent<*>
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
"test": "echo 'no tests executed'"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@polkadot/dev": "^0.17.12",
|
||||
"@polkadot/dev": "^0.17.13",
|
||||
"babel-preset-react": "^6.24.1",
|
||||
"gh-pages": "^1.1.0",
|
||||
"lerna": "^2.5.1",
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"name": "@polkadot/app-explorer",
|
||||
"version": "0.1.6",
|
||||
"main": "index.js",
|
||||
"repository": "https://github.com/polkadot-js/portal.git",
|
||||
"repository": "https://github.com/polkadot-js/apps.git",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"license": "ISC",
|
||||
"scripts": {
|
||||
@ -11,16 +11,10 @@
|
||||
"test": "jest --coverage"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@polkadot/primitives": "^0.10.4",
|
||||
"@polkadot/primitives-codec": "^0.10.4",
|
||||
"@polkadot/primitives-json": "^0.10.4",
|
||||
"@polkadot/rx-react": "^0.4.7",
|
||||
"@polkadot/util": "^0.19.4",
|
||||
"@polkadot/util-crypto": "^0.19.4",
|
||||
"react": "^16.3.1",
|
||||
"react-dom": "^16.3.1",
|
||||
"react-i18next": "^7.5.1",
|
||||
"semantic-ui-css": "^2.3.1",
|
||||
"semantic-ui-react": "^0.79.1"
|
||||
"@polkadot/primitives": "^0.12.4",
|
||||
"@polkadot/primitives-codec": "^0.12.4",
|
||||
"@polkadot/primitives-json": "^0.12.4",
|
||||
"@polkadot/ui-react-app": "^0.1.6",
|
||||
"@polkadot/util-crypto": "^0.19.4"
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,18 +3,16 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps } from '../types';
|
||||
|
||||
import './App.css';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
|
||||
import React from 'react';
|
||||
import BestNumber from '@polkadot/rx-react/BestNumber';
|
||||
|
||||
import translate from '../translate';
|
||||
import BestHash from '../BestHash';
|
||||
import BlockHeaders from '../BlockHeaders';
|
||||
import BestHash from './BestHash';
|
||||
import BlockHeaders from './BlockHeaders';
|
||||
import translate from './translate';
|
||||
|
||||
type Props = BaseProps & {};
|
||||
type Props = I18nProps & {};
|
||||
|
||||
function App ({ className, style, t }: Props): React$Node {
|
||||
return (
|
||||
@ -23,12 +21,12 @@ function App ({ className, style, t }: Props): React$Node {
|
||||
style={style}
|
||||
>
|
||||
<BestNumber
|
||||
className='explorer--App-BestNumber'
|
||||
className='explorer--BestNumber'
|
||||
label={t('app.bestNumber', {
|
||||
defaultValue: 'best #'
|
||||
})}
|
||||
/>
|
||||
<BestHash className='explorer--App-BestHash' />
|
||||
<BestHash />
|
||||
<BlockHeaders />
|
||||
</div>
|
||||
);
|
||||
@ -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. */
|
||||
|
||||
.explorer--App {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.explorer--App-BestNumber {
|
||||
font-size: 3rem;
|
||||
font-weight: 100;
|
||||
line-height: 3rem;
|
||||
opacity: 0.5;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.explorer--App-BestHash {
|
||||
font-size: 1.5em;
|
||||
font-weight: 100;
|
||||
line-height: 1.5em;
|
||||
margin-bottom: 1em;
|
||||
opacity: 0.5;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.explorer--App-BlockHeaders {
|
||||
}
|
||||
@ -4,37 +4,18 @@
|
||||
// @flow
|
||||
|
||||
import type { Header } from '@polkadot/primitives/header';
|
||||
import type { BaseProps } from './types';
|
||||
|
||||
import React from 'react';
|
||||
import headerHash from '@polkadot/primitives-codec/header/hash';
|
||||
import Div from '@polkadot/rx-react/Div';
|
||||
import withApiCall from '@polkadot/rx-react/with/apiCall';
|
||||
import u8aToHexShort from '@polkadot/util/u8a/toHexShort';
|
||||
|
||||
import translate from './translate';
|
||||
|
||||
type Props = BaseProps & {
|
||||
value?: Header
|
||||
};
|
||||
|
||||
function BestHash ({ className, style, value }: Props): React$Node {
|
||||
if (!value) {
|
||||
return null;
|
||||
export default withApiCall({ method: 'newHead', section: 'chain' })(
|
||||
Div, {
|
||||
className: 'explorer--BestHash',
|
||||
format: (value?: Header): ?string =>
|
||||
value
|
||||
? u8aToHexShort(headerHash(value))
|
||||
: value
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['explorer--BestHash', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
{u8aToHexShort(headerHash(value))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default translate(
|
||||
withApiCall({
|
||||
method: 'newHead',
|
||||
section: 'chain'
|
||||
})(BestHash)
|
||||
);
|
||||
|
||||
@ -3,9 +3,15 @@
|
||||
/* of the ISC license. See the LICENSE file for details. */
|
||||
|
||||
.explorer--BlockHeader {
|
||||
animation: fadein 1.5s;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@keyframes fadein {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
.explorer--BlockHeader:nth-child(even) {
|
||||
background: #f9f9f9;
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
// @flow
|
||||
|
||||
import type { Header } from '@polkadot/primitives/header';
|
||||
import type { BaseProps } from '../types';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
|
||||
import './BlockHeader.css';
|
||||
|
||||
@ -14,7 +14,7 @@ import u8aToHex from '@polkadot/util/u8a/toHex';
|
||||
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = BaseProps & {
|
||||
type Props = I18nProps & {
|
||||
label?: string,
|
||||
value?: Header
|
||||
};
|
||||
|
||||
@ -4,47 +4,32 @@
|
||||
// @flow
|
||||
|
||||
import type { Header } from '@polkadot/primitives/header';
|
||||
import type { BaseProps } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
import Div from '@polkadot/rx-react/Div';
|
||||
import withApiCall from '@polkadot/rx-react/with/apiCall';
|
||||
|
||||
import translate from '../translate';
|
||||
import BlockHeader from '../BlockHeader';
|
||||
import { blockHeaders } from '../subjects';
|
||||
import { blockHeaders as subject } from '../subjects';
|
||||
import transform from './transform';
|
||||
|
||||
type Props = BaseProps & {
|
||||
value: Array<Header>
|
||||
const apiMethod = {
|
||||
method: 'newHead',
|
||||
section: 'chain'
|
||||
};
|
||||
|
||||
function BlockHeaders ({ className, style, value }: Props): React$Node {
|
||||
return (
|
||||
<div
|
||||
className={['explorer--BlockHeaders', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
{
|
||||
(value || []).map((header) => (
|
||||
<BlockHeader
|
||||
value={header}
|
||||
key={header.number.toString()}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const apiOptions = {
|
||||
subject,
|
||||
transform
|
||||
};
|
||||
|
||||
export default translate(
|
||||
withApiCall(
|
||||
{
|
||||
method: 'newHead',
|
||||
section: 'chain'
|
||||
},
|
||||
{
|
||||
subject: blockHeaders,
|
||||
transform
|
||||
}
|
||||
)(BlockHeaders)
|
||||
);
|
||||
export default withApiCall(apiMethod, apiOptions)(Div, {
|
||||
className: 'explorer--BlockHeaders',
|
||||
format: (value?: Array<Header> = []): React$Node =>
|
||||
value.map((value) => (
|
||||
<BlockHeader
|
||||
key={value.number.toString()}
|
||||
value={value}
|
||||
/>
|
||||
))
|
||||
});
|
||||
|
||||
@ -14,11 +14,11 @@ export default function transform (header: Header): Array<Header> {
|
||||
return prev;
|
||||
}
|
||||
|
||||
return prev.reduce((next, value, index) => {
|
||||
if (index < 9) {
|
||||
return prev
|
||||
.filter((value, index) => index < 9)
|
||||
.reduce((next, value, index) => {
|
||||
next.push(value);
|
||||
}
|
||||
|
||||
return next;
|
||||
}, [header]);
|
||||
return next;
|
||||
}, [header]);
|
||||
}
|
||||
|
||||
@ -1,3 +1,36 @@
|
||||
/* 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. */
|
||||
|
||||
.explorer--App {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.explorer--App .rx--updated {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.explorer--BestHash,
|
||||
.explorer--BestNumber {
|
||||
font-weight: 100;
|
||||
text-align: right;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.explorer--BestHash.rx--updated,
|
||||
.explorer--BestNumber.rx--updated {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.explorer--BestHash {
|
||||
font-size: 1.5em;
|
||||
line-height: 1.5em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.explorer--BestNumber {
|
||||
font-size: 3rem;
|
||||
line-height: 3rem;
|
||||
}
|
||||
|
||||
.explorer--BlockHeaders {}
|
||||
|
||||
@ -5,4 +5,4 @@
|
||||
|
||||
import { translate } from 'react-i18next';
|
||||
|
||||
export default translate(['explorer']);
|
||||
export default translate(['explorer', 'ui']);
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"name": "@polkadot/app-extrinsics",
|
||||
"version": "0.1.6",
|
||||
"main": "index.js",
|
||||
"repository": "https://github.com/polkadot-js/portal.git",
|
||||
"repository": "https://github.com/polkadot-js/apps.git",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"license": "ISC",
|
||||
"scripts": {
|
||||
@ -11,18 +11,9 @@
|
||||
"test": "jest --coverage"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@polkadot/extrinsics": "^0.1.6",
|
||||
"@polkadot/extrinsics-codec": "^0.1.6",
|
||||
"@polkadot/extrinsics-polkadot": "^0.1.6",
|
||||
"@polkadot/rx-react": "^0.4.7",
|
||||
"@polkadot/ui-react": "^0.9.12",
|
||||
"@polkadot/util": "^0.19.4",
|
||||
"@polkadot/util-keyring": "^0.19.4",
|
||||
"react": "^16.3.1",
|
||||
"react-dom": "^16.3.1",
|
||||
"react-dropzone": "^4.2.9",
|
||||
"react-i18next": "^7.5.1",
|
||||
"semantic-ui-css": "^2.3.1",
|
||||
"semantic-ui-react": "^0.79.1"
|
||||
"@polkadot/extrinsics": "^0.12.4",
|
||||
"@polkadot/extrinsics-codec": "^0.12.4",
|
||||
"@polkadot/ui-react-app": "^0.1.6",
|
||||
"react-dropzone": "^4.2.9"
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,50 +3,60 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps } from './types';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
|
||||
import React from 'react';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
import Balance from '@polkadot/rx-react/Balance';
|
||||
import withObservableParams from '@polkadot/rx-react/with/observableParams';
|
||||
import InputAddress from '@polkadot/ui-react-app/src/InputAddress';
|
||||
|
||||
import translate from './translate';
|
||||
import InputAddress from './InputAddress';
|
||||
|
||||
type Props = BaseProps & {
|
||||
type Props = I18nProps & {
|
||||
isError?: boolean,
|
||||
label: string,
|
||||
subject: rxjs$BehaviorSubject<Uint8Array>
|
||||
};
|
||||
|
||||
function Account ({ className, isError, label, subject, style, t }: Props): React$Node {
|
||||
const AccountBalance = withObservableParams(subject)(Balance);
|
||||
class Account extends React.PureComponent<Props> {
|
||||
Balance: React$ComponentType<*>;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['extrinsics--Account', 'extrinsics--split', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='large'>
|
||||
<Label>{label}</Label>
|
||||
<InputAddress
|
||||
placeholder='0x...'
|
||||
subject={subject}
|
||||
/>
|
||||
constructor (props: Props) {
|
||||
super(props);
|
||||
|
||||
this.Balance = withObservableParams(props.subject)(Balance, {
|
||||
className: 'ui disabled dropdown selection'
|
||||
});
|
||||
}
|
||||
|
||||
render (): React$Node {
|
||||
const { className, label, subject, style, t } = this.props;
|
||||
const Balance = this.Balance;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['extrinsics--Account', 'ui--form', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='large'>
|
||||
<InputAddress
|
||||
label={label}
|
||||
placeholder='0x...'
|
||||
subject={subject}
|
||||
/>
|
||||
</div>
|
||||
<div className='small'>
|
||||
<Label>
|
||||
{t('account.balance', {
|
||||
defaultValue: 'with an available balance of'
|
||||
})}
|
||||
</Label>
|
||||
<Balance />
|
||||
</div>
|
||||
</div>
|
||||
<div className='small'>
|
||||
<Label>
|
||||
{t('account.balance', {
|
||||
defaultValue: 'with an available balance of'
|
||||
})}
|
||||
</Label>
|
||||
<AccountBalance
|
||||
className='ui disabled dropdown selection'
|
||||
classNameUpdated='hasUpdated'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(Account);
|
||||
|
||||
@ -3,7 +3,8 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps, QueueTx } from './types';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { QueueTx } from './types';
|
||||
|
||||
import React from 'react';
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
@ -13,7 +14,7 @@ import Submission from './Submission';
|
||||
import Signer from './Signer';
|
||||
import translate from './translate';
|
||||
|
||||
type Props = BaseProps & {};
|
||||
type Props = I18nProps & {};
|
||||
|
||||
const queue: rxjs$BehaviorSubject<QueueTx> = new BehaviorSubject(({
|
||||
isValid: false,
|
||||
|
||||
@ -3,43 +3,99 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BareProps, EncodedParams } from '../types';
|
||||
import type { BareProps } from '@polkadot/ui-react-app/types';
|
||||
import type { EncodedParams } from '../types';
|
||||
import type { Subjects } from './types';
|
||||
|
||||
import React from 'react';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
import encodeExtrinsic from '@polkadot/extrinsics-codec/encode/extrinsic';
|
||||
import withObservable from '@polkadot/rx-react/with/observable';
|
||||
import InputExtrinsic from '@polkadot/ui-react-app/src/InputExtrinsic';
|
||||
import Params from '@polkadot/ui-react-app/src/Params';
|
||||
import isUndefined from '@polkadot/util/is/undefined';
|
||||
|
||||
import InputExtrinsic from '../InputExtrinsic';
|
||||
import Params from '../Params';
|
||||
import paramComponents from '../Params';
|
||||
import createSubjects from './subjects';
|
||||
|
||||
type Props = BareProps & {
|
||||
isError?: boolean,
|
||||
isPrivate?: boolean,
|
||||
label: string,
|
||||
labelMethod?: string,
|
||||
labelSection?: string,
|
||||
subject: rxjs$BehaviorSubject<EncodedParams>
|
||||
};
|
||||
|
||||
export default function Extrinsic ({ className, isError, isPrivate, label, style, subject }: Props): React$Node {
|
||||
const subjects = createSubjects(subject);
|
||||
const MethodParams = withObservable(subjects.method)(Params);
|
||||
export default class Extrinsic extends React.PureComponent<Props> {
|
||||
subjects: Subjects;
|
||||
subscriptions: Array<rxjs$ISubscription>;
|
||||
Params: React$ComponentType<*>;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['extrinsics--Extrinsic', 'extrinsics--split', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='full'>
|
||||
<Label>{label}</Label>
|
||||
<InputExtrinsic
|
||||
isError={isError}
|
||||
isPrivate={isPrivate}
|
||||
subject={subjects.method}
|
||||
constructor (props: Props) {
|
||||
super(props);
|
||||
|
||||
this.subjects = createSubjects(props.subject);
|
||||
this.Params = withObservable(this.subjects.method)(Params);
|
||||
this.subscriptions = [];
|
||||
}
|
||||
|
||||
componentWillMount () {
|
||||
this.subscriptions = [
|
||||
this.subjects.params.subscribe(this.onChange),
|
||||
this.subjects.method.subscribe(this.onChange)
|
||||
];
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
this.subscriptions.forEach((s) =>
|
||||
s.unsubscribe()
|
||||
);
|
||||
}
|
||||
|
||||
onChange = (): void => {
|
||||
const extrinsic = this.subjects.method.getValue();
|
||||
const values = this.subjects.params.getValue();
|
||||
const isValid = !!extrinsic.params &&
|
||||
Object
|
||||
.values(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);
|
||||
|
||||
this.props.subject.next({
|
||||
data,
|
||||
extrinsic,
|
||||
isValid
|
||||
});
|
||||
};
|
||||
|
||||
render (): React$Node {
|
||||
const { className, isError, isPrivate, labelMethod, labelSection, style } = this.props;
|
||||
const { Params, subjects } = this;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['extrinsics--Extrinsic', 'ui--form', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='full'>
|
||||
<InputExtrinsic
|
||||
isError={isError}
|
||||
isPrivate={isPrivate}
|
||||
labelMethod={labelMethod}
|
||||
labelSection={labelSection}
|
||||
subject={subjects.method}
|
||||
/>
|
||||
</div>
|
||||
<Params
|
||||
overrides={paramComponents}
|
||||
subject={subjects.params}
|
||||
/>
|
||||
</div>
|
||||
<MethodParams
|
||||
subject={subjects.params}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,40 +4,16 @@
|
||||
// @flow
|
||||
|
||||
import type { Extrinsic } from '@polkadot/extrinsics/types';
|
||||
import type { EncodedParams, RawParam } from '../types';
|
||||
import type { EncodedParams } from '../types';
|
||||
import type { Subjects } from './types';
|
||||
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
import encodeExtrinsic from '@polkadot/extrinsics-codec/src/encode/extrinsic';
|
||||
import isUndefined from '@polkadot/util/is/undefined';
|
||||
|
||||
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>)),
|
||||
const extrinsic = subject.getValue().extrinsic || ({}: $Shape<Extrinsic>);
|
||||
|
||||
return {
|
||||
method: new BehaviorSubject(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.params.subscribe(onChange);
|
||||
|
||||
return subjects;
|
||||
}
|
||||
|
||||
12
packages/app-extrinsics/src/Extrinsic/types.js
Normal file
12
packages/app-extrinsics/src/Extrinsic/types.js
Normal file
@ -0,0 +1,12 @@
|
||||
// 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 '@polkadot/extrinsics/types';
|
||||
import type { RawParam } from '@polkadot/ui-react-app/Params/types';
|
||||
|
||||
export type Subjects = {
|
||||
method: rxjs$BehaviorSubject<Extrinsic>,
|
||||
params: rxjs$BehaviorSubject<Array<RawParam>>
|
||||
};
|
||||
@ -1,63 +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
|
||||
|
||||
// TODO: This is a useful, shared component, move out
|
||||
|
||||
import type { Extrinsic } from '@polkadot/extrinsics/types';
|
||||
|
||||
import './InputExtrinsic.css';
|
||||
|
||||
import React from 'react';
|
||||
import Dropdown from 'semantic-ui-react/dist/es/modules/Dropdown';
|
||||
import extrinsics from '@polkadot/extrinsics-polkadot/src';
|
||||
|
||||
import options from './options';
|
||||
|
||||
type Props = {
|
||||
className?: string,
|
||||
isError?: boolean,
|
||||
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.isError;
|
||||
delete _props.isPrivate;
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
selection
|
||||
{..._props}
|
||||
className={['ui--InputExtrinsic', props.className].join(' ')}
|
||||
error={props.isError}
|
||||
onChange={onChange}
|
||||
options={
|
||||
// flowlint-next-line sketchy-null-bool:off
|
||||
props.isPrivate
|
||||
? options.private
|
||||
: options.public
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -1,60 +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 React from 'react';
|
||||
import Dropdown from 'semantic-ui-react/dist/es/modules/Dropdown';
|
||||
import extrinsics from '@polkadot/extrinsics-polkadot/src';
|
||||
|
||||
const options = {
|
||||
private: [],
|
||||
public: []
|
||||
};
|
||||
|
||||
const sortByName = (a, b) =>
|
||||
a.name.localeCompare(b.name);
|
||||
|
||||
const addHeader = (shouldAdd, to, name, description) => {
|
||||
if (shouldAdd) {
|
||||
if (to.length) {
|
||||
to.push(<Dropdown.Divider key={`${name}:divider`} />);
|
||||
}
|
||||
|
||||
to.push(
|
||||
<Dropdown.Header key={`${name}:header`}>
|
||||
{description}
|
||||
</Dropdown.Header>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
extrinsics.sections.sort(sortByName).forEach(({ description, hasPrivate, hasPublic, methods, name }) => {
|
||||
addHeader(hasPublic, options.public, name, description);
|
||||
addHeader(hasPrivate, options.private, name, description);
|
||||
|
||||
methods.sort(sortByName).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}:name`}
|
||||
>
|
||||
{description || name}
|
||||
</div>,
|
||||
<div
|
||||
className='ui--InputExtrinsic-Item-call'
|
||||
key={`${name}:call`}
|
||||
>
|
||||
{name}({inputs})
|
||||
</div>
|
||||
],
|
||||
value: name
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
export default options;
|
||||
51
packages/app-extrinsics/src/Params/Account.js
Normal file
51
packages/app-extrinsics/src/Params/Account.js
Normal file
@ -0,0 +1,51 @@
|
||||
// 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 '@polkadot/ui-react-app/Params/types';
|
||||
|
||||
import React from 'react';
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
|
||||
import BaseAccount from '../Account';
|
||||
|
||||
export default class Account extends React.PureComponent<Props> {
|
||||
account: rxjs$BehaviorSubject<Uint8Array>;
|
||||
subscriptions: Array<rxjs$ISubscription>
|
||||
|
||||
constructor (props: Props) {
|
||||
super(props);
|
||||
|
||||
this.account = new BehaviorSubject(new Uint8Array([]));
|
||||
}
|
||||
|
||||
componentWillMount () {
|
||||
this.subscriptions = [
|
||||
this.account.subscribe((value: Uint8Array) =>
|
||||
this.props.subject.next({
|
||||
isValid: !!value && value.length === 32,
|
||||
value
|
||||
})
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
this.subscriptions.forEach((s) =>
|
||||
s.unsubscribe()
|
||||
);
|
||||
}
|
||||
|
||||
render (): React$Node {
|
||||
const { isError, label } = this.props;
|
||||
|
||||
return (
|
||||
<BaseAccount
|
||||
isError={isError}
|
||||
label={label}
|
||||
subject={this.account}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,30 +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 { Props } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
|
||||
import BaseAccount from '../../Account';
|
||||
|
||||
export default function Account ({ isError, 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
|
||||
isError={isError}
|
||||
label={label}
|
||||
subject={account}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -1,32 +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 { 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 ({ isError, 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
|
||||
isError={isError}
|
||||
isPrivate
|
||||
label={label}
|
||||
subject={extrinsic}
|
||||
/>
|
||||
);
|
||||
}
|
||||
70
packages/app-extrinsics/src/Params/Proposal.js
Normal file
70
packages/app-extrinsics/src/Params/Proposal.js
Normal file
@ -0,0 +1,70 @@
|
||||
// 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 '@polkadot/ui-react-app/Params/types';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { EncodedParams } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
|
||||
import Extrinsic from '../Extrinsic';
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = BaseProps & I18nProps;
|
||||
|
||||
class Proposal extends React.PureComponent<Props> {
|
||||
extrinsic: rxjs$BehaviorSubject<EncodedParams>;
|
||||
subscriptions: Array<rxjs$ISubscription>
|
||||
|
||||
constructor (props: Props) {
|
||||
super(props);
|
||||
|
||||
this.extrinsic = new BehaviorSubject(({ isValid: false }: $Shape<EncodedParams>));
|
||||
}
|
||||
|
||||
componentWillMount () {
|
||||
this.subscriptions = [
|
||||
this.extrinsic.subscribe(({ data, isValid }: EncodedParams) =>
|
||||
this.props.subject.next({
|
||||
isValid,
|
||||
value: data
|
||||
})
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
this.subscriptions.forEach((s) =>
|
||||
s.unsubscribe()
|
||||
);
|
||||
}
|
||||
|
||||
render (): React$Node {
|
||||
const { isError, label, t } = this.props;
|
||||
|
||||
return (
|
||||
<Extrinsic
|
||||
isError={isError}
|
||||
isPrivate
|
||||
labelMethod={t('proposal.method', {
|
||||
defaultValue: '{{label}} (extrinsic)',
|
||||
replace: {
|
||||
label
|
||||
}
|
||||
})}
|
||||
labelSection={t('proposal.method', {
|
||||
defaultValue: '{{label}} (section)',
|
||||
replace: {
|
||||
label
|
||||
}
|
||||
})}
|
||||
subject={this.extrinsic}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(Proposal);
|
||||
@ -1,43 +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 { Extrinsic$Type } from '@polkadot/extrinsics/types';
|
||||
|
||||
import Account from './Param/Account';
|
||||
import Amount from './Param/Amount';
|
||||
import Bool from './Param/Bool';
|
||||
import Bytes from './Param/Bytes';
|
||||
import Hash from './Param/Hash';
|
||||
import Proposal from './Param/Proposal';
|
||||
import Unknown from './Param/Unknown';
|
||||
import VoteThreshold from './Param/VoteThreshold';
|
||||
import Wasm from './Param/Wasm';
|
||||
|
||||
const Components = {
|
||||
'AccountId': Account,
|
||||
'Balance': Amount,
|
||||
'BlockNumber': Amount,
|
||||
'bool': Bool,
|
||||
'Bytes': Bytes,
|
||||
'Hash': Hash,
|
||||
'MisbehaviorReport': Unknown,
|
||||
'Proposal': Proposal,
|
||||
'SessionKey': Unknown,
|
||||
'u32': Amount,
|
||||
'u64': Amount,
|
||||
'VoteThreshold': VoteThreshold,
|
||||
'Wasm': Wasm
|
||||
};
|
||||
|
||||
export default function findComponent (type: Extrinsic$Type): React$ComponentType<*> {
|
||||
if (Array.isArray(type)) {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const [outer, inner] = type;
|
||||
|
||||
return findComponent(inner);
|
||||
}
|
||||
|
||||
return Components[type];
|
||||
}
|
||||
@ -3,52 +3,14 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { Extrinsic } from '@polkadot/extrinsics/types';
|
||||
import type { BaseProps, RawParam } from '../types';
|
||||
import type { ComponentMap } from '@polkadot/ui-react-app/Params/types';
|
||||
|
||||
import './Params.css';
|
||||
import Account from './Account';
|
||||
import Proposal from './Proposal';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import translate from '../translate';
|
||||
import findComponent from './findComponent';
|
||||
import createSubjects from './subjects';
|
||||
import typeToText from './typeToText';
|
||||
|
||||
type Props = BaseProps & {
|
||||
subject: rxjs$BehaviorSubject<Array<RawParam>>,
|
||||
value: Extrinsic;
|
||||
const components: ComponentMap = {
|
||||
'AccountId': Account,
|
||||
'Proposal': Proposal
|
||||
};
|
||||
|
||||
function Params ({ className, style, subject, value: { name, params } }: Props): React$Node {
|
||||
if (!params || !params.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const subjects = createSubjects(params, subject);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['extrinsics--Params', 'extrinsics--split', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='extrinsics--Params-Content'>
|
||||
{params.map((value, index) => {
|
||||
const Component = findComponent(value.type);
|
||||
|
||||
return (
|
||||
<Component
|
||||
className='extrinsics--Param'
|
||||
key={`${name}:${value.name}:${index}`}
|
||||
label={`${value.name}: ${typeToText(value.type)}`}
|
||||
subject={subjects[index]}
|
||||
value={value}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default translate(Params);
|
||||
export default components;
|
||||
|
||||
@ -3,7 +3,8 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps, QueueTx } from '../types';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { QueueTx } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
import { Trans } from 'react-i18next';
|
||||
@ -13,7 +14,7 @@ import u8aToHexShort from '@polkadot/util/u8a/toHexShort';
|
||||
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = BaseProps & {
|
||||
type Props = I18nProps & {
|
||||
value: QueueTx
|
||||
};
|
||||
|
||||
@ -33,7 +34,7 @@ function Decoded ({ className, style, t, value: { data, extrinsic, index, public
|
||||
<div className='expanded'>
|
||||
<p>
|
||||
<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>
|
||||
You are about to sign a message from <span className='code'>{from}</span> calling <span className='code'>{extrinsic.section}_{extrinsic.name}</span> with an index of <span className='code'>{index.toString()}</span>
|
||||
</Trans>
|
||||
</p>
|
||||
<p>
|
||||
|
||||
@ -4,7 +4,8 @@
|
||||
// @flow
|
||||
|
||||
import type { ApiProps } from '@polkadot/rx-react/types';
|
||||
import type { BaseProps, QueueTx } from '../types';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { QueueTx } from '../types';
|
||||
|
||||
import './Signer.css';
|
||||
|
||||
@ -17,7 +18,7 @@ import translate from '../translate';
|
||||
import Decoded from './Decoded';
|
||||
import submitExtrinsic from './submit';
|
||||
|
||||
type Props = BaseProps & ApiProps & {
|
||||
type Props = I18nProps & ApiProps & {
|
||||
subject: rxjs$BehaviorSubject<QueueTx>,
|
||||
value: QueueTx
|
||||
};
|
||||
|
||||
@ -6,12 +6,11 @@
|
||||
import type { RxApiInterface } from '@polkadot/rx-api/types';
|
||||
import type { QueueTx } from '../types';
|
||||
|
||||
import encodeCall from '@polkadot/extrinsics-codec/src/encode/call';
|
||||
import encodeCall from '@polkadot/extrinsics-codec/encode/call';
|
||||
import keyring from '@polkadot/ui-react-app/src/keyring';
|
||||
import u8aConcat from '@polkadot/util/u8a/concat';
|
||||
import u8aToHex from '@polkadot/util/u8a/toHex';
|
||||
|
||||
import keyring from '../keyring';
|
||||
|
||||
export default function submit (api: RxApiInterface, tx: QueueTx, subject: rxjs$BehaviorSubject<QueueTx>): Promise<void> {
|
||||
const message = encodeCall(tx.publicKey, tx.index, tx.data);
|
||||
const signature = keyring.getPair(tx.publicKey).sign(message);
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
// @flow
|
||||
|
||||
import type BN from 'bn.js';
|
||||
import type { BareProps } from '../types';
|
||||
import type { BareProps } from '@polkadot/ui-react-app/types';
|
||||
|
||||
import React from 'react';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
@ -17,22 +17,33 @@ type Props = BareProps & {
|
||||
value: rxjs$BehaviorSubject<Uint8Array>
|
||||
};
|
||||
|
||||
export default function Nonce ({ className, label, style, subject, t, value }: Props): React$Node {
|
||||
const SenderNonce = withObservableParams(value)(RxNonce);
|
||||
export default class Nonce extends React.PureComponent<Props> {
|
||||
Nonce: React$ComponentType<*>;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['extrinsics--split', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='small'>
|
||||
<Label>{label}</Label>
|
||||
<SenderNonce
|
||||
className='ui disabled dropdown selection'
|
||||
classNameUpdated='hasUpdated'
|
||||
subject={subject}
|
||||
/>
|
||||
constructor (props: Props) {
|
||||
super(props);
|
||||
|
||||
// NOTE we basically get away with not checking updates since the parent is only created once
|
||||
this.Nonce = withObservableParams(props.value)(RxNonce);
|
||||
}
|
||||
|
||||
render (): React$Node {
|
||||
const { className, label, style, subject } = this.props;
|
||||
const Nonce = this.Nonce;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['ui--form', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='small'>
|
||||
<Label>{label}</Label>
|
||||
<Nonce
|
||||
className='ui disabled dropdown selection'
|
||||
subject={subject}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,6 +10,6 @@
|
||||
}
|
||||
|
||||
.extrinsics--Submission-ButtonRow .button {
|
||||
margin-right: 0.5rem;
|
||||
margin-left: 0.5rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
@ -3,14 +3,15 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps, QueueTx } from '../types';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { QueueTx } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
import Button from 'semantic-ui-react/dist/es/elements/Button';
|
||||
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = BaseProps & {
|
||||
type Props = I18nProps & {
|
||||
subject: rxjs$BehaviorSubject<QueueTx>,
|
||||
value: QueueTx;
|
||||
};
|
||||
|
||||
@ -3,7 +3,9 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps, QueueTx } from '../types';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { QueueTx } from '../types';
|
||||
import type { Subjects } from './types';
|
||||
|
||||
import './Submission.css';
|
||||
|
||||
@ -17,43 +19,76 @@ import Nonce from './Nonce';
|
||||
import Submit from './Submit';
|
||||
import createSubjects from './subjects';
|
||||
|
||||
type Props = BaseProps & {
|
||||
type Props = I18nProps & {
|
||||
subject: rxjs$BehaviorSubject<QueueTx>
|
||||
};
|
||||
|
||||
function Submission ({ className, subject, style, t }: Props): React$Node {
|
||||
const subjects = createSubjects();
|
||||
const Button = withObservable(subjects.call)(Submit);
|
||||
class Submission extends React.PureComponent<Props> {
|
||||
Submit: React$ComponentType<*>;
|
||||
subjects: Subjects;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['extrinsics--Submission', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<Account
|
||||
label={t('display.sender', {
|
||||
defaultValue: 'using the selected account'
|
||||
})}
|
||||
subject={subjects.sender}
|
||||
/>
|
||||
<Extrinsic
|
||||
label={t('display.method', {
|
||||
defaultValue: 'submit the following extrinsic'
|
||||
})}
|
||||
subject={subjects.method}
|
||||
/>
|
||||
<Nonce
|
||||
label={t('display.nonce', {
|
||||
defaultValue: 'with an index'
|
||||
})}
|
||||
subject={subjects.index}
|
||||
value={subjects.sender}
|
||||
/>
|
||||
<div className='extrinsics--Submission-ButtonRow'>
|
||||
<Button subject={subject} />
|
||||
constructor (props: Props) {
|
||||
super(props);
|
||||
|
||||
this.subjects = createSubjects();
|
||||
this.Submit = withObservable(this.subjects.call)(Submit);
|
||||
}
|
||||
|
||||
componentWillMount () {
|
||||
this.subjects.method.subscribe(this.onChange);
|
||||
this.subjects.sender.subscribe(this.onChange);
|
||||
}
|
||||
|
||||
onChange = (): void => {
|
||||
const publicKey = this.subjects.sender.getValue();
|
||||
const message = this.subjects.method.getValue();
|
||||
const index = this.subjects.index.getValue();
|
||||
const isValid = !!(publicKey && publicKey.length && message && message.isValid);
|
||||
|
||||
this.subjects.call.next({
|
||||
data: message.data,
|
||||
extrinsic: message.extrinsic,
|
||||
isValid,
|
||||
index,
|
||||
publicKey,
|
||||
status: 'incomplete'
|
||||
});
|
||||
};
|
||||
|
||||
render (): React$Node {
|
||||
const { className, subject, style, t } = this.props;
|
||||
const { Submit, subjects } = this;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['extrinsics--Submission', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<Account
|
||||
label={t('display.sender', {
|
||||
defaultValue: 'using the selected account'
|
||||
})}
|
||||
subject={subjects.sender}
|
||||
/>
|
||||
<Extrinsic
|
||||
labelMethod={t('display.method', {
|
||||
defaultValue: 'submit the following extrinsic'
|
||||
})}
|
||||
subject={subjects.method}
|
||||
/>
|
||||
<Nonce
|
||||
label={t('display.nonce', {
|
||||
defaultValue: 'with an index'
|
||||
})}
|
||||
subject={subjects.index}
|
||||
value={subjects.sender}
|
||||
/>
|
||||
<div className='extrinsics--Submission-ButtonRow'>
|
||||
<Submit subject={subject} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(Submission);
|
||||
|
||||
@ -4,47 +4,22 @@
|
||||
// @flow
|
||||
|
||||
import type { EncodedParams, QueueTx } from '../types';
|
||||
import type { Subjects } 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>
|
||||
};
|
||||
import map from '@polkadot/extrinsics-substrate';
|
||||
|
||||
export default function createSubjects (): Subjects {
|
||||
const subjects = {
|
||||
return {
|
||||
index: new BehaviorSubject(new BN(0)),
|
||||
call: new BehaviorSubject(({
|
||||
isValid: false
|
||||
}: $Shape<QueueTx>)),
|
||||
method: new BehaviorSubject(({
|
||||
extrinsic: map.staking.methods.public.transfer,
|
||||
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;
|
||||
}
|
||||
|
||||
14
packages/app-extrinsics/src/Submission/types.js
Normal file
14
packages/app-extrinsics/src/Submission/types.js
Normal file
@ -0,0 +1,14 @@
|
||||
// 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 BN from 'bn.js';
|
||||
import type { EncodedParams, QueueTx } from '../types';
|
||||
|
||||
export type Subjects = {
|
||||
call: rxjs$BehaviorSubject<QueueTx>,
|
||||
index: rxjs$BehaviorSubject<BN>,
|
||||
method: rxjs$BehaviorSubject<EncodedParams>,
|
||||
sender: rxjs$BehaviorSubject<Uint8Array>
|
||||
};
|
||||
@ -5,50 +5,3 @@
|
||||
.extrinsics--App {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.extrinsics--full,
|
||||
.extrinsics--split {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.extrinsics--split {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.extrinsics--split > div {
|
||||
box-sizing: border-box;
|
||||
min-width: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.extrinsics--split > div.full,
|
||||
.extrinsics--split > div.large,
|
||||
.extrinsics--split > div.medium,
|
||||
.extrinsics--split > div.small {
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
|
||||
.extrinsics--split > div.full {
|
||||
flex: 0 100%;
|
||||
}
|
||||
|
||||
.extrinsics--split > div.large {
|
||||
flex: 0 75%;
|
||||
}
|
||||
|
||||
.extrinsics--split > div.medium {
|
||||
flex: 0 50%;
|
||||
}
|
||||
|
||||
.extrinsics--split > div.small {
|
||||
flex: 0 25%;
|
||||
}
|
||||
|
||||
.hasUpdated {
|
||||
background: #ffffe0 !important;
|
||||
transition: all 0.7s ease-in-out;
|
||||
}
|
||||
|
||||
@ -5,4 +5,4 @@
|
||||
|
||||
import { translate } from 'react-i18next';
|
||||
|
||||
export default translate(['extrinsics']);
|
||||
export default translate(['extrinsics', 'ui']);
|
||||
|
||||
@ -6,24 +6,6 @@
|
||||
import type BN from 'bn.js';
|
||||
import type { Extrinsic } from '@polkadot/extrinsics/types';
|
||||
|
||||
export type BareProps = {
|
||||
className?: string,
|
||||
style?: {
|
||||
[string]: string
|
||||
}
|
||||
};
|
||||
|
||||
export type BaseProps = BareProps & {
|
||||
t: I18Next$Translate
|
||||
};
|
||||
|
||||
export type RawParam = {
|
||||
// flowlint-next-line unclear-type:off
|
||||
data?: any,
|
||||
isValid: boolean,
|
||||
value: mixed,
|
||||
}
|
||||
|
||||
export type EncodedParams = {
|
||||
data: Uint8Array,
|
||||
extrinsic: Extrinsic,
|
||||
|
||||
1
packages/app-storage/README.md
Normal file
1
packages/app-storage/README.md
Normal file
@ -0,0 +1 @@
|
||||
# @polkadot/app-storage
|
||||
@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "@polkadot/extrinsics",
|
||||
"name": "@polkadot/app-storage",
|
||||
"version": "0.1.6",
|
||||
"main": "index.js",
|
||||
"repository": "https://github.com/polkadot-js/portal.git",
|
||||
"repository": "https://github.com/polkadot-js/apps.git",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"license": "ISC",
|
||||
"scripts": {
|
||||
@ -10,8 +10,7 @@
|
||||
"check": "stylelint 'src/**/*.css' && eslint src && flow check",
|
||||
"test": "jest --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"@polkadot/util": "^0.19.4",
|
||||
"babel-runtime": "^6.26.0"
|
||||
"devDependencies": {
|
||||
"@polkadot/ui-react-app": "^0.1.6"
|
||||
}
|
||||
}
|
||||
28
packages/app-storage/src/App.js
Normal file
28
packages/app-storage/src/App.js
Normal file
@ -0,0 +1,28 @@
|
||||
// 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 { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import Queries from './Queries';
|
||||
import Selection from './Selection';
|
||||
import translate from './translate';
|
||||
|
||||
type Props = I18nProps & {};
|
||||
|
||||
function App ({ className, style, t }: Props): React$Node {
|
||||
return (
|
||||
<div
|
||||
className={['storage--App', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<Selection />
|
||||
<Queries />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default translate(App);
|
||||
61
packages/app-storage/src/Queries/Query.js
Normal file
61
packages/app-storage/src/Queries/Query.js
Normal file
@ -0,0 +1,61 @@
|
||||
// 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 { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { StorageQuery } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
import Div from '@polkadot/rx-react/Div';
|
||||
import withStorage from '@polkadot/rx-react/with/storage';
|
||||
|
||||
import translate from '../translate';
|
||||
import Remove from './Remove';
|
||||
import cache from './cache';
|
||||
import createTransform from './transform';
|
||||
|
||||
type Props = I18nProps & {
|
||||
value: StorageQuery
|
||||
};
|
||||
|
||||
function Query ({ className, style, value: { id, key, params } }: Props): React$Node {
|
||||
const CachedQuery = (() => {
|
||||
if (!cache[id]) {
|
||||
const transform = createTransform(key);
|
||||
|
||||
cache[id] = withStorage(key, { params, transform })(
|
||||
Div, { className: 'ui disabled dropdown selection' }
|
||||
);
|
||||
}
|
||||
|
||||
return cache[id];
|
||||
})();
|
||||
|
||||
const inputs = Object
|
||||
.keys(key.params || {})
|
||||
// $FlowFixMe key.params exists
|
||||
.map((name) => `${name}: ${key.params[name].type}`)
|
||||
.join(', ');
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['storage--Queries-Query', 'storage--actionrow', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='storage--actionrow-value'>
|
||||
<Label>
|
||||
{key.section}_{key.name}({inputs}): {key.type}
|
||||
</Label>
|
||||
<CachedQuery />
|
||||
</div>
|
||||
<div className='storage--actionrow-button'>
|
||||
<Label> </Label>
|
||||
<Remove value={id} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default translate(Query);
|
||||
46
packages/app-storage/src/Queries/Remove.js
Normal file
46
packages/app-storage/src/Queries/Remove.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 { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
|
||||
import React from 'react';
|
||||
import Button from 'semantic-ui-react/dist/es/elements/Button';
|
||||
|
||||
import subjects from '../subjects';
|
||||
import translate from '../translate';
|
||||
import cache from './cache';
|
||||
|
||||
type Props = I18nProps & {
|
||||
value: number;
|
||||
};
|
||||
|
||||
function Remove ({ className, style, value }: Props): React$Node {
|
||||
const onRemove = (): void => {
|
||||
const current = subjects.queries.getValue();
|
||||
|
||||
delete cache[value];
|
||||
|
||||
subjects.queries.next(
|
||||
current
|
||||
.filter(({ id }) => id !== value)
|
||||
.reduce((next, item) => {
|
||||
next.push(item);
|
||||
|
||||
return next;
|
||||
}, [])
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Button
|
||||
disabled={!value}
|
||||
icon='close'
|
||||
negative
|
||||
onClick={onRemove}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default translate(Remove);
|
||||
@ -3,10 +3,6 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
export type BaseProps = {
|
||||
className?: string,
|
||||
style?: {
|
||||
[string]: string
|
||||
},
|
||||
t: I18Next$Translate
|
||||
};
|
||||
const cache = {};
|
||||
|
||||
export default cache;
|
||||
42
packages/app-storage/src/Queries/index.js
Normal file
42
packages/app-storage/src/Queries/index.js
Normal file
@ -0,0 +1,42 @@
|
||||
// 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 { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { StorageQuery } from '../types';
|
||||
|
||||
import React from 'react';
|
||||
import withObservable from '@polkadot/rx-react/with/observable';
|
||||
|
||||
import subjects from '../subjects';
|
||||
import translate from '../translate';
|
||||
import Query from './Query';
|
||||
|
||||
type Props = I18nProps & {
|
||||
value?: Array<StorageQuery>
|
||||
};
|
||||
|
||||
function Queries ({ className, style, value }: Props): React$Node {
|
||||
if (!value || !value.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['storage--Queries', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
{value.map((query) => (
|
||||
<Query
|
||||
key={query.id}
|
||||
value={query}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default translate(
|
||||
withObservable(subjects.queries)(Queries)
|
||||
);
|
||||
33
packages/app-storage/src/Queries/transform.js
Normal file
33
packages/app-storage/src/Queries/transform.js
Normal file
@ -0,0 +1,33 @@
|
||||
// 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 BN from 'bn.js';
|
||||
import type { StorageDef$Key } from '@polkadot/storage/types';
|
||||
|
||||
import u8aToHexShort from '@polkadot/util/u8a/toHexShort';
|
||||
import isU8a from '@polkadot/util/is/u8a';
|
||||
|
||||
type Formatter = (value: boolean | BN | Date | Uint8Array) => string;
|
||||
|
||||
export default function transform ({ type }: StorageDef$Key): Formatter {
|
||||
return (value: boolean | BN | Date | Uint8Array): string => {
|
||||
if (typeof value === typeof true) {
|
||||
return value
|
||||
? 'Yes'
|
||||
: 'No';
|
||||
}
|
||||
|
||||
if (!value) {
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
if (isU8a(value)) {
|
||||
// $FlowFixMe type has been determined
|
||||
return u8aToHexShort(value, 256);
|
||||
}
|
||||
|
||||
return value.toString();
|
||||
};
|
||||
}
|
||||
56
packages/app-storage/src/Selection/Add.js
Normal file
56
packages/app-storage/src/Selection/Add.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 { StorageDef$Key } from '@polkadot/storage/types';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
|
||||
import React from 'react';
|
||||
import Button from 'semantic-ui-react/dist/es/elements/Button';
|
||||
import withObservable from '@polkadot/rx-react/with/observable';
|
||||
|
||||
import subjects from '../subjects';
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = I18nProps & {
|
||||
value: StorageDef$Key;
|
||||
};
|
||||
|
||||
let id = 0;
|
||||
|
||||
function Add ({ className, style, value }: Props): React$Node {
|
||||
const onAdd = (): void => {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
const current = subjects.queries.getValue();
|
||||
const next = [{
|
||||
id: ++id,
|
||||
key: value,
|
||||
params: subjects.params.getValue().map((s) => s.getValue())
|
||||
}];
|
||||
|
||||
subjects.queries.next(
|
||||
current.reduce((next, item) => {
|
||||
next.push(item);
|
||||
|
||||
return next;
|
||||
}, next)
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Button
|
||||
disabled={!value}
|
||||
icon='plus'
|
||||
onClick={onAdd}
|
||||
primary
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default translate(
|
||||
withObservable(subjects.next)(Add)
|
||||
);
|
||||
44
packages/app-storage/src/Selection/index.js
Normal file
44
packages/app-storage/src/Selection/index.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 type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
|
||||
import React from 'react';
|
||||
import Label from 'semantic-ui-react/dist/es/elements/Label';
|
||||
import InputStorage from '@polkadot/ui-react-app/src/InputStorage';
|
||||
|
||||
import subjects from '../subjects';
|
||||
import translate from '../translate';
|
||||
import Add from './Add';
|
||||
|
||||
type Props = I18nProps & {};
|
||||
|
||||
function Selection ({ className, style, t }: Props): React$Node {
|
||||
return (
|
||||
<div
|
||||
className={['storage--Selection', 'storage--actionrow', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='storage--actionrow-value'>
|
||||
<div className='ui--form'>
|
||||
<div className='full'>
|
||||
<InputStorage
|
||||
labelSection={t('selection.section', {
|
||||
defaultValue: 'query storage area'
|
||||
})}
|
||||
subject={subjects.next}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='storage--actionrow-button'>
|
||||
<Label> </Label>
|
||||
<Add />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default translate(Selection);
|
||||
25
packages/app-storage/src/index.css
Normal file
25
packages/app-storage/src/index.css
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. */
|
||||
|
||||
.storage--App {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.storage--Queries {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.storage--actionrow {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.storage--actionrow-value {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.storage--actionrow-button {
|
||||
flex: 0;
|
||||
padding-left: 0.5rem;
|
||||
}
|
||||
@ -3,6 +3,8 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
// HACK: Only here because of CRA's lack of proper workspace + src/* support
|
||||
import './index.css';
|
||||
|
||||
module.exports = require('./src');
|
||||
import App from './App';
|
||||
|
||||
export default App;
|
||||
29
packages/app-storage/src/subjects.js
Normal file
29
packages/app-storage/src/subjects.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 { StorageDef$Key } from '@polkadot/storage/types';
|
||||
import type { StorageQuery } from './types';
|
||||
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
import storage from '@polkadot/storage-substrate/keys';
|
||||
|
||||
type ValueSubject = rxjs$BehaviorSubject<*>;
|
||||
type ValueSubjects = Array<ValueSubject>;
|
||||
|
||||
type Subjects = {
|
||||
next: rxjs$BehaviorSubject<StorageDef$Key>,
|
||||
params: rxjs$BehaviorSubject<ValueSubjects>,
|
||||
queries: rxjs$BehaviorSubject<Array<StorageQuery>>
|
||||
};
|
||||
|
||||
function createSubjects (): Subjects {
|
||||
return {
|
||||
next: new BehaviorSubject(storage.timestamp.keys.current),
|
||||
params: new BehaviorSubject([]),
|
||||
queries: new BehaviorSubject([])
|
||||
};
|
||||
}
|
||||
|
||||
export default createSubjects();
|
||||
8
packages/app-storage/src/translate.js
Normal file
8
packages/app-storage/src/translate.js
Normal file
@ -0,0 +1,8 @@
|
||||
// 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 { translate } from 'react-i18next';
|
||||
|
||||
export default translate(['storage', 'ui']);
|
||||
12
packages/app-storage/src/types.js
Normal file
12
packages/app-storage/src/types.js
Normal file
@ -0,0 +1,12 @@
|
||||
// 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 { StorageDef$Key } from '@polkadot/storage/types';
|
||||
|
||||
export type StorageQuery = {
|
||||
id: number,
|
||||
key: StorageDef$Key,
|
||||
params: Array<*>
|
||||
}
|
||||
@ -4,7 +4,7 @@
|
||||
"description": "An Apps portal into the Polkadot network",
|
||||
"main": "index.js",
|
||||
"homepage": ".",
|
||||
"repository": "https://github.com/polkadot-js/portal.git",
|
||||
"repository": "https://github.com/polkadot-js/apps.git",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"license": "ISC",
|
||||
"scripts": {
|
||||
@ -16,17 +16,8 @@
|
||||
"devDependencies": {
|
||||
"@polkadot/app-explorer": "^0.1.6",
|
||||
"@polkadot/app-extrinsics": "^0.1.6",
|
||||
"@polkadot/rx-react": "^0.4.7",
|
||||
"@polkadot/ui-react": "^0.9.12",
|
||||
"i18next": "^11.1.1",
|
||||
"i18next-browser-languagedetector": "^2.2.0",
|
||||
"i18next-xhr-backend": "^1.5.1",
|
||||
"react": "^16.3.1",
|
||||
"react-dom": "^16.3.1",
|
||||
"react-i18next": "^7.5.1",
|
||||
"react-remarkable": "^1.1.3",
|
||||
"react-router-dom": "^4.2.2",
|
||||
"semantic-ui-css": "^2.3.1",
|
||||
"semantic-ui-react": "^0.79.1"
|
||||
"@polkadot/app-storage": "^0.1.6",
|
||||
"@polkadot/ui-react-app": "^0.1.6",
|
||||
"react-remarkable": "^1.1.3"
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,13 +2,13 @@
|
||||
/* This software may be modified and distributed under the terms
|
||||
/* of the ISC license. See the LICENSE file for details. */
|
||||
|
||||
.portal--App {
|
||||
.apps--App {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.portal--App-column {
|
||||
.apps--App-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
|
||||
@ -3,27 +3,27 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps } from '../types';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
|
||||
import './App.css';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import translate from '../translate';
|
||||
import Connecting from '../Connecting';
|
||||
import Content from '../Content';
|
||||
import SideBar from '../SideBar';
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = BaseProps & {};
|
||||
type Props = I18nProps & {};
|
||||
|
||||
function App ({ className, style }: Props): React$Node {
|
||||
return (
|
||||
<div
|
||||
className={['portal--App', className].join(' ')}
|
||||
className={['apps--App', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<SideBar className='portal--App-column' />
|
||||
<Content className='portal--App-column' />
|
||||
<SideBar className='apps--App-column' />
|
||||
<Content className='apps--App-column' />
|
||||
<Connecting />
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -2,15 +2,18 @@
|
||||
/* This software may be modified and distributed under the terms
|
||||
/* of the ISC license. See the LICENSE file for details. */
|
||||
|
||||
.portal--Connecting {
|
||||
.apps--Connecting {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.portal--Connecting-text {
|
||||
.apps--Connecting-text {
|
||||
background: red;
|
||||
bottom: 0;
|
||||
color: white;
|
||||
display: inline-block;
|
||||
line-height: 1.5em;
|
||||
padding: 1em 2em;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps } from '../types';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
|
||||
import './Connecting.css';
|
||||
|
||||
@ -12,7 +12,7 @@ import withApiCall from '@polkadot/rx-react/with/apiCall';
|
||||
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = BaseProps & {
|
||||
type Props = I18nProps & {
|
||||
value: boolean
|
||||
};
|
||||
|
||||
@ -21,12 +21,13 @@ function Connecting ({ className, style, value, t }: Props): React$Node {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 'ui inverted page modals dimmer transition visible active'
|
||||
return (
|
||||
<div
|
||||
className={['portal--Connecting', 'ui inverted page modals dimmer transition visible active', className].join(' ')}
|
||||
className={['apps--Connecting', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<div className='portal--Connecting-text'>
|
||||
<div className='apps--Connecting-text'>
|
||||
{t('connecting.disconnected', {
|
||||
defaultValue: 'You are disconnected from the node. Check that your node is running and that the Websocket endpoint is reachable.'
|
||||
})}
|
||||
@ -36,7 +37,7 @@ function Connecting ({ className, style, value, t }: Props): React$Node {
|
||||
}
|
||||
|
||||
export default translate(
|
||||
withApiCall({
|
||||
method: 'isConnected'
|
||||
})(Connecting)
|
||||
withApiCall({ method: 'isConnected' })(
|
||||
Connecting
|
||||
)
|
||||
);
|
||||
|
||||
@ -2,12 +2,12 @@
|
||||
/* This software may be modified and distributed under the terms
|
||||
/* of the ISC license. See the LICENSE file for details. */
|
||||
|
||||
.portal--Content {
|
||||
.apps--Content {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.portal--Content-Frame {
|
||||
.apps--Content-Frame {
|
||||
border: none;
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
// @flow
|
||||
|
||||
import type { Location } from 'react-router-dom';
|
||||
import type { BaseProps } from '../types';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
|
||||
import './Content.css';
|
||||
|
||||
@ -14,7 +14,7 @@ import { withRouter } from 'react-router';
|
||||
import routing from '../routing';
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = BaseProps & {
|
||||
type Props = I18nProps & {
|
||||
location: Location
|
||||
};
|
||||
|
||||
@ -23,11 +23,11 @@ function Content ({ className, location, style }: Props): React$Node {
|
||||
|
||||
return (
|
||||
<div
|
||||
className={['portal--Content', className].join(' ')}
|
||||
className={['apps--Content', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<iframe
|
||||
className='portal--Content-Frame'
|
||||
className='apps--Content-Frame'
|
||||
src={`index.html?app=${app}`}
|
||||
title={app}
|
||||
/>
|
||||
|
||||
@ -2,6 +2,6 @@
|
||||
/* This software may be modified and distributed under the terms
|
||||
/* of the ISC license. See the LICENSE file for details. */
|
||||
|
||||
.portal--NotFound {
|
||||
.apps--NotFound {
|
||||
color: red;
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps } from '../types';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
|
||||
import './NotFound.css';
|
||||
|
||||
@ -11,10 +11,12 @@ import React from 'react';
|
||||
|
||||
import translate from '../translate';
|
||||
|
||||
function NotFound ({ className, style, t }: BaseProps): React$Node {
|
||||
type Props = I18nProps & {};
|
||||
|
||||
function NotFound ({ className, style, t }: Props): React$Node {
|
||||
return (
|
||||
<div
|
||||
className={['portal--NotFound', className].join(' ')}
|
||||
className={['apps--NotFound', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
{t('notfound.error', {
|
||||
|
||||
@ -2,12 +2,12 @@
|
||||
/* This software may be modified and distributed under the terms
|
||||
/* of the ISC license. See the LICENSE file for details. */
|
||||
|
||||
.portal--SideBar-Item {}
|
||||
.apps--SideBar-Item {}
|
||||
|
||||
.portal--SideBar-Item-NavLink {
|
||||
.apps--SideBar-Item-NavLink {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.portal--SideBar-Item-NavLink-active {
|
||||
.apps--SideBar-Item-NavLink-active {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
@ -3,7 +3,8 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps, Route } from '../types';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
import type { Route } from '../types';
|
||||
|
||||
import './Item.css';
|
||||
|
||||
@ -12,23 +13,20 @@ import { NavLink } from 'react-router-dom';
|
||||
import Icon from 'semantic-ui-react/dist/es/elements/Icon';
|
||||
import Menu from 'semantic-ui-react/dist/es/collections/Menu';
|
||||
|
||||
type Props = BaseProps & Route & {};
|
||||
|
||||
export default function Item ({ className, i18n, icon, isExact, name, path, style, t }: Props): React$Node {
|
||||
// flowlint-next-line sketchy-null-string:off
|
||||
const to = path || `/${name}`;
|
||||
type Props = I18nProps & Route & {};
|
||||
|
||||
export default function Item ({ className, i18n, icon, isExact, name, path = '', style, t }: Props): React$Node {
|
||||
return (
|
||||
<Menu.Item
|
||||
className={['portal--SideBar-Item', className].join(' ')}
|
||||
className={['apps--SideBar-Item', className].join(' ')}
|
||||
name={name}
|
||||
style={style}
|
||||
>
|
||||
<NavLink
|
||||
activeClassName='portal--SideBar-Item-NavLink-active'
|
||||
className='portal--SideBar-Item-NavLink'
|
||||
activeClassName='apps--SideBar-Item-NavLink-active'
|
||||
className='apps--SideBar-Item-NavLink'
|
||||
exact={isExact}
|
||||
to={to}
|
||||
to={path || `/${name}`}
|
||||
>
|
||||
<Icon name={icon} /> {t(`sidebar.${name}`, i18n)}
|
||||
</NavLink>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
/* This software may be modified and distributed under the terms
|
||||
/* of the ISC license. See the LICENSE file for details. */
|
||||
|
||||
.portal--SideBar {
|
||||
.apps--SideBar {
|
||||
flex-shrink: 0;
|
||||
min-width: 12em;
|
||||
padding: 0.75em;
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { BaseProps } from '../types';
|
||||
import type { I18nProps } from '@polkadot/ui-react-app/types';
|
||||
|
||||
import './SideBar.css';
|
||||
|
||||
@ -14,12 +14,12 @@ import routing from '../routing';
|
||||
import translate from '../translate';
|
||||
import Item from './Item';
|
||||
|
||||
type Props = BaseProps & {};
|
||||
type Props = I18nProps & {};
|
||||
|
||||
function SideBar ({ className, style, t }: Props): React$Node {
|
||||
return (
|
||||
<div
|
||||
className={['portal--SideBar', className].join(' ')}
|
||||
className={['apps--SideBar', className].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<Menu
|
||||
@ -27,11 +27,12 @@ function SideBar ({ className, style, t }: Props): React$Node {
|
||||
vertical
|
||||
>
|
||||
{
|
||||
routing.routes.map((props) => (
|
||||
routing.routes.map((route) => (
|
||||
<Item
|
||||
key={props.name}
|
||||
key={route.name}
|
||||
t={t}
|
||||
{...props}
|
||||
// flowlint-next-line inexact-spread:off
|
||||
{...route}
|
||||
/>
|
||||
))
|
||||
}
|
||||
|
||||
@ -3,24 +3,14 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import 'semantic-ui-css/semantic.min.css';
|
||||
import './semantic.css';
|
||||
import './index.css';
|
||||
import createApp from '@polkadot/ui-react-app/src';
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { I18nextProvider } from 'react-i18next';
|
||||
import { HashRouter } from 'react-router-dom';
|
||||
import Api from '@polkadot/rx-react/Api';
|
||||
|
||||
import i18n from './i18n';
|
||||
|
||||
import Portal from './App';
|
||||
import App from './App';
|
||||
import NotFound from './NotFound';
|
||||
import routing from './routing';
|
||||
import urlParams from './urlParams';
|
||||
|
||||
const Component = (() => {
|
||||
createApp((() => {
|
||||
const { app } = urlParams();
|
||||
|
||||
if (app) {
|
||||
@ -31,17 +21,5 @@ const Component = (() => {
|
||||
: NotFound;
|
||||
}
|
||||
|
||||
return Portal;
|
||||
})();
|
||||
|
||||
ReactDOM.render(
|
||||
<Api>
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<HashRouter>
|
||||
<Component />
|
||||
</HashRouter>
|
||||
</I18nextProvider>
|
||||
</Api>,
|
||||
// flowlint-next-line unclear-type:off
|
||||
((document.getElementById('root'): any): Element)
|
||||
);
|
||||
return App;
|
||||
})());
|
||||
|
||||
@ -10,10 +10,11 @@ import explorer from './explorer';
|
||||
import extrinsics from './extrinsics';
|
||||
// import home from './home';
|
||||
// import settings from './settings';
|
||||
import storage from './storage';
|
||||
|
||||
export default ({
|
||||
default: 'explorer',
|
||||
routes: [].concat(
|
||||
explorer, extrinsics
|
||||
explorer, extrinsics, storage
|
||||
)
|
||||
}: Routing);
|
||||
|
||||
21
packages/apps/src/routing/storage.js
Normal file
21
packages/apps/src/routing/storage.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 { Routes } from '../types';
|
||||
|
||||
import Storage from '@polkadot/app-storage/src';
|
||||
|
||||
export default ([
|
||||
{
|
||||
component: Storage,
|
||||
i18n: {
|
||||
defaultValue: 'Storage'
|
||||
},
|
||||
icon: 'database',
|
||||
isExact: false,
|
||||
isHidden: false,
|
||||
name: 'storage'
|
||||
}
|
||||
]: Routes);
|
||||
@ -5,4 +5,4 @@
|
||||
|
||||
import { translate } from 'react-i18next';
|
||||
|
||||
export default translate(['portal']);
|
||||
export default translate(['apps', 'ui']);
|
||||
|
||||
@ -3,26 +3,6 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { RxApiInterface } from '@polkadot/rx-api/types';
|
||||
|
||||
export type BaseProps = {
|
||||
className?: string,
|
||||
style?: {
|
||||
[string]: string
|
||||
},
|
||||
t: I18Next$Translate
|
||||
};
|
||||
|
||||
export type BaseContext = {
|
||||
api: RxApiInterface,
|
||||
// TODO: Set the correct/full type
|
||||
router: {
|
||||
route: {
|
||||
location: Location
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export type Route = {
|
||||
component: React$StatelessFunctionalComponent<*>,
|
||||
i18n: I18Next$Translate$Config,
|
||||
|
||||
@ -1 +0,0 @@
|
||||
# @polkadot/extrinsics-codec
|
||||
@ -1,21 +0,0 @@
|
||||
{
|
||||
"name": "@polkadot/extrinsics-codec",
|
||||
"version": "0.1.6",
|
||||
"main": "index.js",
|
||||
"repository": "https://github.com/polkadot-js/portal.git",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"license": "ISC",
|
||||
"scripts": {
|
||||
"build": "polkadot-dev-build-babel",
|
||||
"check": "stylelint 'src/**/*.css' && eslint src && flow check",
|
||||
"test": "jest --coverage"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@polkadot/extrinsics": "^0.1.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@polkadot/util": "^0.19.4",
|
||||
"babel-runtime": "^6.26.0",
|
||||
"bn.js": "^4.11.8"
|
||||
}
|
||||
}
|
||||
@ -1,17 +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 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
|
||||
);
|
||||
};
|
||||
@ -1,21 +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 { Extrinsic } from '@polkadot/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)
|
||||
);
|
||||
};
|
||||
@ -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.
|
||||
// @flow
|
||||
|
||||
import type BN from 'bn.js';
|
||||
import type { Extrinsic } from '@polkadot/extrinsics/types';
|
||||
|
||||
const encodeCall = require('./call');
|
||||
const encodeExtrinsic = require('./extrinsic');
|
||||
|
||||
module.exports = function encode (extrinsic: Extrinsic, publicKey: Uint8Array, nonce: number | BN, values?: Array<mixed>): Uint8Array {
|
||||
return encodeCall(
|
||||
publicKey,
|
||||
nonce,
|
||||
encodeExtrinsic(extrinsic, values)
|
||||
);
|
||||
};
|
||||
@ -1,32 +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 { Extrinsic$Param } from '@polkadot/extrinsics/types';
|
||||
|
||||
const u8aConcat = require('@polkadot/util/u8a/concat');
|
||||
const bnToU8a = require('@polkadot/util/bn/toU8a');
|
||||
|
||||
const encodeType = require('./type');
|
||||
|
||||
// flowlint-next-line unclear-type:off
|
||||
module.exports = function encodeParam (param: Extrinsic$Param, value: any): Uint8Array {
|
||||
if (Array.isArray(param.type)) {
|
||||
const [outer, inner] = param.type;
|
||||
|
||||
switch (outer) {
|
||||
case 'Array':
|
||||
return u8aConcat(
|
||||
bnToU8a((value: Array<*>).length, 32, true),
|
||||
u8aConcat.apply(null, (value: Array<*>).map((v) =>
|
||||
encodeType(inner, v)
|
||||
))
|
||||
);
|
||||
|
||||
default:
|
||||
return encodeType(inner, value);
|
||||
}
|
||||
}
|
||||
return encodeType(param.type, value);
|
||||
};
|
||||
@ -1,16 +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 { Extrinsic$Params } from '@polkadot/extrinsics/types';
|
||||
|
||||
const u8aConcat = require('@polkadot/util/u8a/concat');
|
||||
|
||||
const encodeParam = require('./param');
|
||||
|
||||
module.exports = function encodeParams (params: Extrinsic$Params, values?: Array<mixed> = []): Uint8Array {
|
||||
return u8aConcat.apply(null, params.map((param, index) => {
|
||||
return encodeParam(param, values[index]);
|
||||
}));
|
||||
};
|
||||
@ -1,47 +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 { Extrinsic$TypeName } from '@polkadot/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 encodeType (type: Extrinsic$TypeName, value: any): Uint8Array {
|
||||
try {
|
||||
switch (type) {
|
||||
case 'AccountId':
|
||||
return value;
|
||||
|
||||
case 'Balance':
|
||||
case 'BlockNumber':
|
||||
case 'u64':
|
||||
return bnToU8a(value, 64, true);
|
||||
|
||||
case 'Bytes':
|
||||
case 'Hash':
|
||||
return u8aToU8a(value);
|
||||
|
||||
case 'bool':
|
||||
return bnToU8a(value ? 1 : 0, 8, true);
|
||||
|
||||
case 'Proposal':
|
||||
return u8aToU8a(value);
|
||||
|
||||
case 'u32':
|
||||
return bnToU8a(value, 32, true);
|
||||
|
||||
case 'VoteThreshold':
|
||||
return bnToU8a(value || 0, 8, true);
|
||||
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error, 'with', value, 'encoded with', type);
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
@ -1 +0,0 @@
|
||||
# @polkadot/extrinsics
|
||||
@ -1,17 +0,0 @@
|
||||
{
|
||||
"name": "@polkadot/extrinsics-polkadot",
|
||||
"version": "0.1.6",
|
||||
"main": "index.js",
|
||||
"repository": "https://github.com/polkadot-js/portal.git",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"license": "ISC",
|
||||
"scripts": {
|
||||
"build": "polkadot-dev-build-babel",
|
||||
"check": "stylelint 'src/**/*.css' && eslint src && flow check",
|
||||
"test": "jest --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"@polkadot/extrinsics": "^0.1.6",
|
||||
"babel-runtime": "^6.26.0"
|
||||
}
|
||||
}
|
||||
@ -1,30 +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 { ExtrinsicsBaseSection } from '@polkadot/extrinsics/types';
|
||||
|
||||
module.exports = ({
|
||||
description: 'Consensus',
|
||||
methods: {
|
||||
public: {
|
||||
reportMisbehavior: {
|
||||
description: 'Report misbehavior',
|
||||
index: 0,
|
||||
params: {
|
||||
report: { type: 'MisbehaviorReport' }
|
||||
}
|
||||
}
|
||||
},
|
||||
private: {
|
||||
setCode: {
|
||||
description: 'Set new code',
|
||||
index: 0,
|
||||
params: {
|
||||
code: { type: 'Wasm' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}: ExtrinsicsBaseSection);
|
||||
@ -1,85 +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 { ExtrinsicsBaseSection } from '@polkadot/extrinsics/types';
|
||||
|
||||
module.exports = ({
|
||||
description: 'Council',
|
||||
methods: {
|
||||
public: {
|
||||
setApprovals: {
|
||||
description: 'Set approvals',
|
||||
index: 0,
|
||||
params: {
|
||||
votes: { type: ['Array', 'bool'] },
|
||||
index: { type: 'u32' }
|
||||
}
|
||||
},
|
||||
reapInactiveVoter: {
|
||||
description: 'Remove insactive voter',
|
||||
index: 1,
|
||||
params: {
|
||||
signedIndex: { type: 'u32' },
|
||||
who: { type: 'AccountId' },
|
||||
whoIndex: { type: 'u32' },
|
||||
assumedVoteIndex: { type: 'u32' }
|
||||
}
|
||||
},
|
||||
retractVoter: {
|
||||
description: 'Retract voter',
|
||||
index: 2,
|
||||
params: {
|
||||
index: { type: 'u32' }
|
||||
}
|
||||
},
|
||||
submitCandidacy: {
|
||||
description: 'Submit candidacy',
|
||||
index: 3,
|
||||
params: {
|
||||
slot: { type: 'u32' }
|
||||
}
|
||||
},
|
||||
presentWinner: {
|
||||
description: 'Present winner',
|
||||
index: 4,
|
||||
params: {
|
||||
candidate: { type: 'AccountId' },
|
||||
total: { type: 'Balance' },
|
||||
index: { type: 'u32' }
|
||||
}
|
||||
}
|
||||
},
|
||||
private: {
|
||||
setDesiredSeats: {
|
||||
description: 'Set desired seats',
|
||||
index: 0,
|
||||
params: {
|
||||
count: { type: 'u32' }
|
||||
}
|
||||
},
|
||||
removeMember: {
|
||||
description: 'Remove member',
|
||||
index: 1,
|
||||
params: {
|
||||
member: { type: 'AccountId' }
|
||||
}
|
||||
},
|
||||
setPresentationDuration: {
|
||||
description: 'Set presentation duration',
|
||||
index: 2,
|
||||
params: {
|
||||
duration: { type: 'u64' }
|
||||
}
|
||||
},
|
||||
setTermDuration: {
|
||||
description: 'Set term duration',
|
||||
index: 3,
|
||||
params: {
|
||||
duration: { type: 'u64' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}: ExtrinsicsBaseSection);
|
||||
@ -1,52 +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 { ExtrinsicsBaseSection } from '@polkadot/extrinsics/types';
|
||||
|
||||
module.exports = ({
|
||||
description: 'Council Voting',
|
||||
methods: {
|
||||
public: {
|
||||
propose: {
|
||||
description: 'Propose',
|
||||
index: 0,
|
||||
params: {
|
||||
proposal: { type: 'Proposal' }
|
||||
}
|
||||
},
|
||||
vote: {
|
||||
description: 'Vote',
|
||||
index: 1,
|
||||
params: {
|
||||
proposal: { type: 'Hash' },
|
||||
approve: { type: 'bool' }
|
||||
}
|
||||
},
|
||||
veto: {
|
||||
description: 'Veto',
|
||||
index: 2,
|
||||
params: {
|
||||
proposal: { type: 'Hash' }
|
||||
}
|
||||
}
|
||||
},
|
||||
private: {
|
||||
setCooloffPeriod: {
|
||||
description: 'Set cooloff period',
|
||||
index: 0,
|
||||
params: {
|
||||
blocks: { type: 'BlockNumber' }
|
||||
}
|
||||
},
|
||||
setVotingPeriod: {
|
||||
description: 'Set voting period',
|
||||
index: 1,
|
||||
params: {
|
||||
blocks: { type: 'BlockNumber' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}: ExtrinsicsBaseSection);
|
||||
@ -1,54 +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 { ExtrinsicsBaseSection } from '@polkadot/extrinsics/types';
|
||||
|
||||
module.exports = ({
|
||||
description: 'Democracy',
|
||||
methods: {
|
||||
public: {
|
||||
propose: {
|
||||
description: 'Propose',
|
||||
index: 0,
|
||||
params: {
|
||||
proposal: { type: 'Proposal' },
|
||||
value: { type: 'Balance' }
|
||||
}
|
||||
},
|
||||
second: {
|
||||
description: 'Second',
|
||||
index: 1,
|
||||
params: {
|
||||
proposal: { type: 'u32' }
|
||||
}
|
||||
},
|
||||
vote: {
|
||||
description: 'Vote',
|
||||
index: 2,
|
||||
params: {
|
||||
referendumIndex: { type: 'u32' },
|
||||
vote: { type: 'bool' }
|
||||
}
|
||||
}
|
||||
},
|
||||
private: {
|
||||
startReferendum: {
|
||||
description: 'Start referendum',
|
||||
index: 0,
|
||||
params: {
|
||||
proposal: { type: 'Proposal' },
|
||||
voteThreshold: { type: 'VoteThreshold' }
|
||||
}
|
||||
},
|
||||
cancelReferendum: {
|
||||
description: 'Cancel referendum',
|
||||
index: 1,
|
||||
params: {
|
||||
referendumIndex: { type: 'u32' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}: ExtrinsicsBaseSection);
|
||||
@ -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 { ExtrinsicsBaseMap } from '@polkadot/extrinsics/types';
|
||||
|
||||
const init = require('@polkadot/extrinsics');
|
||||
|
||||
const consensus = require('./consensus');
|
||||
const council = require('./council');
|
||||
const councilVoting = require('./councilVoting');
|
||||
const democracy = require('./democracy');
|
||||
const session = require('./session');
|
||||
const staking = require('./staking');
|
||||
|
||||
const map: ExtrinsicsBaseMap = {
|
||||
consensus,
|
||||
council,
|
||||
councilVoting,
|
||||
democracy,
|
||||
session,
|
||||
staking
|
||||
};
|
||||
|
||||
module.exports = init(map);
|
||||
@ -1,35 +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 { ExtrinsicsBaseSection } from '@polkadot/extrinsics/types';
|
||||
|
||||
module.exports = ({
|
||||
description: 'Session',
|
||||
methods: {
|
||||
public: {
|
||||
setKey: {
|
||||
description: 'Set session key',
|
||||
index: 0,
|
||||
params: {
|
||||
key: { type: 'SessionKey' }
|
||||
}
|
||||
}
|
||||
},
|
||||
private: {
|
||||
setLength: {
|
||||
description: 'Set session length',
|
||||
index: 0,
|
||||
params: {
|
||||
length: { type: 'u64' }
|
||||
}
|
||||
},
|
||||
forceNewSession: {
|
||||
description: 'Force new session',
|
||||
index: 1,
|
||||
params: {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}: ExtrinsicsBaseSection);
|
||||
@ -1,60 +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 { ExtrinsicsBaseSection } from '@polkadot/extrinsics/types';
|
||||
|
||||
module.exports = ({
|
||||
description: 'Staking',
|
||||
methods: {
|
||||
public: {
|
||||
transfer: {
|
||||
description: 'Transfer',
|
||||
index: 0,
|
||||
params: {
|
||||
recipient: { type: 'AccountId' },
|
||||
value: { type: 'Balance', options: { minValue: 1 } }
|
||||
}
|
||||
},
|
||||
stake: {
|
||||
description: 'Stake',
|
||||
index: 1,
|
||||
params: {}
|
||||
},
|
||||
unstake: {
|
||||
description: 'Unstake',
|
||||
index: 2,
|
||||
params: {}
|
||||
}
|
||||
},
|
||||
private: {
|
||||
setSessionsPerEra: {
|
||||
description: 'Set sessions per era',
|
||||
index: 0,
|
||||
params: {
|
||||
sessions: { type: 'u64' }
|
||||
}
|
||||
},
|
||||
setBondingDuration: {
|
||||
description: 'Set bonding duration',
|
||||
index: 1,
|
||||
params: {
|
||||
duration: { type: 'u64' }
|
||||
}
|
||||
},
|
||||
setValidatorCount: {
|
||||
description: 'Set validator count',
|
||||
index: 2,
|
||||
params: {
|
||||
count: { type: 'u32' }
|
||||
}
|
||||
},
|
||||
forceNewEra: {
|
||||
description: 'Force new era',
|
||||
index: 3,
|
||||
params: {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}: ExtrinsicsBaseSection);
|
||||
@ -1,15 +0,0 @@
|
||||
ISC License (ISC)
|
||||
|
||||
Copyright 2017-2018 Jaco Greeff <jacogr@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
@ -1 +0,0 @@
|
||||
# @polkadot/extrinsics
|
||||
@ -1,46 +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 { Extrinsic, Extrinsics, ExtrinsicsBaseMap, ExtrinsicSectionName, ExtrinsicsMap, ExtrinsicSection } from './types';
|
||||
|
||||
const assert = require('@polkadot/util/assert');
|
||||
|
||||
const expandSection = require('./section');
|
||||
|
||||
// NOTE: Order here is important, counts as an index
|
||||
const BASIC_KEYS: Array<ExtrinsicSectionName> = ['consensus', 'session', 'staking', 'democracy', 'council', 'councilVoting'];
|
||||
|
||||
module.exports = function init (baseMap: ExtrinsicsBaseMap): Extrinsics {
|
||||
const map: ExtrinsicsMap = {};
|
||||
|
||||
const get = (method: string): Extrinsic => {
|
||||
const extrinsic = map[method];
|
||||
|
||||
assert(extrinsic, `Unable to retrieve extrinsic with name '${method}'`);
|
||||
|
||||
return extrinsic;
|
||||
};
|
||||
|
||||
const sections: Array<ExtrinsicSection> = BASIC_KEYS.reduce((sections: Array<ExtrinsicSection>, sectionName: ExtrinsicSectionName, sectionIndex: number) => {
|
||||
const sectionSource = baseMap[sectionName];
|
||||
|
||||
if (sectionSource) {
|
||||
const section = expandSection(sectionSource, sectionName, sectionIndex);
|
||||
|
||||
section.methods.forEach((method) => {
|
||||
map[method.name] = method;
|
||||
});
|
||||
|
||||
sections.push(section);
|
||||
}
|
||||
|
||||
return sections;
|
||||
}, []);
|
||||
|
||||
return {
|
||||
get,
|
||||
sections
|
||||
};
|
||||
};
|
||||
@ -1,35 +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 { Extrinsic, ExtrinsicsBaseSection, ExtrinsicSectionName } from './types';
|
||||
|
||||
const bnToU8a = require('@polkadot/util/bn/toU8a');
|
||||
const u8aConcat = require('@polkadot/util/u8a/concat');
|
||||
|
||||
const expandParams = require('./params');
|
||||
|
||||
const TYPES = ['private', 'public'];
|
||||
|
||||
module.exports = function expandMethods (sectionSource: ExtrinsicsBaseSection, sectionName: ExtrinsicSectionName, sectionIndex: Uint8Array): Array<Extrinsic> {
|
||||
const [priMethods, pubMethods] = TYPES.map((type) => {
|
||||
const isPrivate = type === 'private';
|
||||
const methods = sectionSource.methods[type];
|
||||
const methodNames = Object.keys(methods);
|
||||
|
||||
return methodNames.map((name: string): Extrinsic => {
|
||||
const { description, index, params } = methods[name];
|
||||
|
||||
return {
|
||||
description,
|
||||
index: u8aConcat(sectionIndex, bnToU8a(index, 8)),
|
||||
isPrivate,
|
||||
name: `${sectionName}_${name}`,
|
||||
params: expandParams(params)
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
return [].concat(priMethods, pubMethods);
|
||||
};
|
||||
@ -1,19 +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 { ExtrinsicBase$Params, Extrinsic$Param, Extrinsic$Params } from './types';
|
||||
|
||||
module.exports = function expandParams (base: ExtrinsicBase$Params): Extrinsic$Params {
|
||||
const paramNames = Object.keys(base);
|
||||
|
||||
return paramNames.map((name: string): Extrinsic$Param => {
|
||||
const source = base[name];
|
||||
|
||||
return {
|
||||
...source,
|
||||
name
|
||||
};
|
||||
});
|
||||
};
|
||||
@ -1,23 +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 { ExtrinsicSectionName, ExtrinsicsBaseSection, ExtrinsicSection } from './types';
|
||||
|
||||
const bnToU8a = require('@polkadot/util/bn/toU8a');
|
||||
|
||||
const expandMethods = require('./methods');
|
||||
|
||||
module.exports = function expandSection (sectionSource: ExtrinsicsBaseSection, name: ExtrinsicSectionName, sectionIndex: number): ExtrinsicSection {
|
||||
const index = bnToU8a(sectionIndex, 8);
|
||||
|
||||
return {
|
||||
description: sectionSource.description || name,
|
||||
hasPrivate: !!Object.keys(sectionSource.methods.private).length,
|
||||
hasPublic: !!Object.keys(sectionSource.methods.public).length,
|
||||
index,
|
||||
methods: expandMethods(sectionSource, name, index),
|
||||
name
|
||||
};
|
||||
};
|
||||
@ -1,84 +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 type Extrinsic$TypeName = 'AccountId' | 'Balance' | 'BlockNumber' | 'bool' | 'Bytes' | 'Hash' | 'MisbehaviorReport' | 'Proposal' | 'SessionKey' | 'u32' | 'u64' | 'VoteThreshold' | 'Wasm';
|
||||
|
||||
export type Extrinsic$Type =
|
||||
Extrinsic$TypeName |
|
||||
['Array', Extrinsic$TypeName];
|
||||
|
||||
export type ExtrinsicBase$Param = {
|
||||
options?: {
|
||||
initValue?: mixed,
|
||||
minValue?: mixed,
|
||||
maxValue?: mixed
|
||||
},
|
||||
type: Extrinsic$Type
|
||||
};
|
||||
|
||||
export type ExtrinsicBase$Params = {
|
||||
[string]: ExtrinsicBase$Param
|
||||
};
|
||||
|
||||
export type ExtrinsicBase = {
|
||||
description: string,
|
||||
index: number,
|
||||
params: ExtrinsicBase$Params
|
||||
}
|
||||
|
||||
export type ExtrinsicSectionName = 'consensus' | 'council' | 'councilVoting' | 'democracy' | 'session' | 'staking';
|
||||
|
||||
export type ExtrinsicsBaseSection = {
|
||||
description: string,
|
||||
methods: {
|
||||
private: {
|
||||
[string]: ExtrinsicBase
|
||||
},
|
||||
public: {
|
||||
[string]: ExtrinsicBase
|
||||
}
|
||||
}
|
||||
}
|
||||
export type ExtrinsicsBaseMap = {
|
||||
[ExtrinsicSectionName]: ExtrinsicsBaseSection
|
||||
};
|
||||
|
||||
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 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: ExtrinsicSectionName
|
||||
};
|
||||
|
||||
export type Extrinsics = {
|
||||
sections: Array<ExtrinsicSection>,
|
||||
get: (sectionMethod: string) => Extrinsic
|
||||
}
|
||||
|
||||
export type ExtrinsicsMap = {
|
||||
[string]: Extrinsic
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user