Browse Source

Basic transfer app (#293)

* Update dependencies

* Add transfer app skeleton

* Basic transfer app

* Bump versions

* Remove unneeded prop

* Fix app-transfer not found (CI, due to version bump)

* Display reserved balance message

* Misplaced debug log

* Display no-effect warning

* Remove FIXME TODO (done)
Jaco Greeff 6 years ago
parent
commit
73a2aa6879
39 changed files with 795 additions and 181 deletions
  1. 1 1
      jest.config.js
  2. 1 1
      lerna.json
  3. 1 1
      package.json
  4. 2 2
      packages/app-accounts/package.json
  5. 2 2
      packages/app-addresses/package.json
  6. 5 5
      packages/app-democracy/package.json
  7. 5 5
      packages/app-example/package.json
  8. 4 4
      packages/app-explorer/package.json
  9. 4 4
      packages/app-extrinsics/package.json
  10. 4 4
      packages/app-rpc/package.json
  11. 8 8
      packages/app-staking/package.json
  12. 2 2
      packages/app-storage/package.json
  13. 3 3
      packages/app-toolbox/package.json
  14. 15 0
      packages/app-transfer/LICENSE
  15. 3 0
      packages/app-transfer/README.md
  16. 18 0
      packages/app-transfer/package.json
  17. 166 0
      packages/app-transfer/src/Fees.tsx
  18. 59 0
      packages/app-transfer/src/Submit.tsx
  19. 154 0
      packages/app-transfer/src/Transfer.tsx
  20. 42 0
      packages/app-transfer/src/index.css
  21. 54 0
      packages/app-transfer/src/index.tsx
  22. 7 0
      packages/app-transfer/src/translate.ts
  23. 15 0
      packages/app-transfer/src/types.d.ts
  24. 2 2
      packages/app-vanitygen/package.json
  25. 15 14
      packages/apps/package.json
  26. 6 6
      packages/apps/src/routing/index.ts
  27. 19 0
      packages/apps/src/routing/transfer.ts
  28. 1 0
      packages/apps/webpack.config.js
  29. 6 6
      packages/ui-app/package.json
  30. 37 9
      packages/ui-app/src/AddressSummary.tsx
  31. 2 2
      packages/ui-identicon/package.json
  32. 3 3
      packages/ui-keyring/package.json
  33. 4 4
      packages/ui-react-rx/package.json
  34. 23 2
      packages/ui-react-rx/src/ApiObservable/index.ts
  35. 11 1
      packages/ui-react-rx/src/ApiObservable/types.d.ts
  36. 3 3
      packages/ui-react/package.json
  37. 4 4
      packages/ui-signer/package.json
  38. 1 0
      tsconfig.json
  39. 83 83
      yarn.lock

+ 1 - 1
jest.config.js

@@ -2,7 +2,7 @@ const config = require('@polkadot/dev-react/config/jest');
 
 module.exports = Object.assign({}, config, {
   moduleNameMapper: {
-    '@polkadot/app-(accounts|addresses|democracy|example|explorer|extrinsics|rpc|staking|storage|toolbox|vanitygen)(.*)$': '<rootDir>/packages/ui-$1/src/$2',
+    '@polkadot/app-(accounts|addresses|democracy|example|explorer|extrinsics|rpc|staking|storage|toolbox|transfer|vanitygen)(.*)$': '<rootDir>/packages/ui-$1/src/$2',
     '@polkadot/ui-(app|identicon|keyring|react-rx|react|signer)(.*)$': '<rootDir>/packages/ui-$1/src/$2',
     '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': 'empty/object',
     '\\.(css|less)$': 'empty/object'

+ 1 - 1
lerna.json

@@ -10,5 +10,5 @@
   "packages": [
     "packages/*"
   ],
-  "version": "0.19.61"
+  "version": "0.20.0"
 }

+ 1 - 1
package.json

@@ -30,7 +30,7 @@
   },
   "devDependencies": {
     "@polkadot/dev-react": "^0.20.19",
-    "@polkadot/ts": "^0.1.25",
+    "@polkadot/ts": "^0.1.27",
     "autoprefixer": "^9.1.5",
     "babel-loader": "^8.0.2",
     "css-loader": "^1.0.0",

+ 2 - 2
packages/app-accounts/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@polkadot/app-accounts",
-  "version": "0.19.61",
+  "version": "0.20.0",
   "main": "index.js",
   "repository": "https://github.com/polkadot-js/apps.git",
   "author": "Jaco Greeff <jacogr@gmail.com>",
@@ -11,6 +11,6 @@
   "license": "ISC",
   "dependencies": {
     "@babel/runtime": "^7.0.0",
-    "@polkadot/ui-app": "^0.19.61"
+    "@polkadot/ui-app": "^0.20.0"
   }
 }

+ 2 - 2
packages/app-addresses/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@polkadot/app-addresses",
-  "version": "0.19.61",
+  "version": "0.20.0",
   "main": "index.js",
   "repository": "https://github.com/polkadot-js/apps.git",
   "author": "Jaco Greeff <jacogr@gmail.com>",
@@ -11,6 +11,6 @@
   "license": "ISC",
   "dependencies": {
     "@babel/runtime": "^7.0.0",
-    "@polkadot/ui-app": "^0.19.61"
+    "@polkadot/ui-app": "^0.20.0"
   }
 }

+ 5 - 5
packages/app-democracy/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@polkadot/app-democracy",
-  "version": "0.19.61",
+  "version": "0.20.0",
   "description": "A referendum & proposal app",
   "main": "index.js",
   "scripts": {},
@@ -11,9 +11,9 @@
   "license": "ISC",
   "dependencies": {
     "@babel/runtime": "^7.0.0",
-    "@polkadot/storage": "^0.28.28",
-    "@polkadot/ui-react": "^0.19.61",
-    "@polkadot/ui-react-rx": "^0.19.61",
-    "@polkadot/util-keyring": "^0.29.32"
+    "@polkadot/storage": "^0.28.29",
+    "@polkadot/ui-react": "^0.20.0",
+    "@polkadot/ui-react-rx": "^0.20.0",
+    "@polkadot/util-keyring": "^0.29.33"
   }
 }

+ 5 - 5
packages/app-example/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@polkadot/app-example",
-  "version": "0.19.61",
+  "version": "0.20.0",
   "description": "A basic example app",
   "main": "index.js",
   "scripts": {},
@@ -11,9 +11,9 @@
   "license": "ISC",
   "dependencies": {
     "@babel/runtime": "^7.0.0",
-    "@polkadot/storage": "^0.28.28",
-    "@polkadot/ui-react": "^0.19.61",
-    "@polkadot/ui-react-rx": "^0.19.61",
-    "@polkadot/util-keyring": "^0.29.32"
+    "@polkadot/storage": "^0.28.29",
+    "@polkadot/ui-react": "^0.20.0",
+    "@polkadot/ui-react-rx": "^0.20.0",
+    "@polkadot/util-keyring": "^0.29.33"
   }
 }

+ 4 - 4
packages/app-explorer/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@polkadot/app-explorer",
-  "version": "0.19.61",
+  "version": "0.20.0",
   "main": "index.js",
   "repository": "https://github.com/polkadot-js/apps.git",
   "author": "Jaco Greeff <jacogr@gmail.com>",
@@ -11,8 +11,8 @@
   "license": "ISC",
   "dependencies": {
     "@babel/runtime": "^7.0.0",
-    "@polkadot/primitives": "^0.28.28",
-    "@polkadot/ui-app": "^0.19.61",
-    "@polkadot/util-crypto": "^0.29.32"
+    "@polkadot/primitives": "^0.28.29",
+    "@polkadot/ui-app": "^0.20.0",
+    "@polkadot/util-crypto": "^0.29.33"
   }
 }

+ 4 - 4
packages/app-extrinsics/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@polkadot/app-extrinsics",
-  "version": "0.19.61",
+  "version": "0.20.0",
   "main": "index.js",
   "repository": "https://github.com/polkadot-js/apps.git",
   "author": "Jaco Greeff <jacogr@gmail.com>",
@@ -11,8 +11,8 @@
   "license": "ISC",
   "dependencies": {
     "@babel/runtime": "^7.0.0",
-    "@polkadot/extrinsics": "^0.28.28",
-    "@polkadot/ui-app": "^0.19.61",
-    "@polkadot/ui-signer": "^0.19.61"
+    "@polkadot/extrinsics": "^0.28.29",
+    "@polkadot/ui-app": "^0.20.0",
+    "@polkadot/ui-signer": "^0.20.0"
   }
 }

+ 4 - 4
packages/app-rpc/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@polkadot/app-rpc",
-  "version": "0.19.61",
+  "version": "0.20.0",
   "main": "index.js",
   "repository": "https://github.com/polkadot-js/apps.git",
   "author": "Jaco Greeff <jacogr@gmail.com>",
@@ -11,8 +11,8 @@
   "license": "ISC",
   "dependencies": {
     "@babel/runtime": "^7.0.0",
-    "@polkadot/ui-app": "^0.19.61",
-    "@polkadot/ui-keyring": "^0.19.61",
-    "@polkadot/ui-signer": "^0.19.61"
+    "@polkadot/ui-app": "^0.20.0",
+    "@polkadot/ui-keyring": "^0.20.0",
+    "@polkadot/ui-signer": "^0.20.0"
   }
 }

+ 8 - 8
packages/app-staking/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@polkadot/app-staking",
-  "version": "0.19.61",
+  "version": "0.20.0",
   "description": "A basic staking app",
   "main": "index.js",
   "scripts": {},
@@ -11,12 +11,12 @@
   "license": "ISC",
   "dependencies": {
     "@babel/runtime": "^7.0.0",
-    "@polkadot/app-extrinsics": "^0.19.61",
-    "@polkadot/storage": "^0.28.28",
-    "@polkadot/ui-app": "^0.19.61",
-    "@polkadot/ui-keyring": "^0.19.61",
-    "@polkadot/ui-react": "^0.19.61",
-    "@polkadot/ui-react-rx": "^0.19.61",
-    "@polkadot/util-keyring": "^0.29.32"
+    "@polkadot/app-extrinsics": "^0.20.0",
+    "@polkadot/storage": "^0.28.29",
+    "@polkadot/ui-app": "^0.20.0",
+    "@polkadot/ui-keyring": "^0.20.0",
+    "@polkadot/ui-react": "^0.20.0",
+    "@polkadot/ui-react-rx": "^0.20.0",
+    "@polkadot/util-keyring": "^0.29.33"
   }
 }

+ 2 - 2
packages/app-storage/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@polkadot/app-storage",
-  "version": "0.19.61",
+  "version": "0.20.0",
   "main": "index.js",
   "repository": "https://github.com/polkadot-js/apps.git",
   "author": "Jaco Greeff <jacogr@gmail.com>",
@@ -11,6 +11,6 @@
   "license": "ISC",
   "dependencies": {
     "@babel/runtime": "^7.0.0",
-    "@polkadot/ui-app": "^0.19.61"
+    "@polkadot/ui-app": "^0.20.0"
   }
 }

+ 3 - 3
packages/app-toolbox/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@polkadot/app-toolbox",
-  "version": "0.19.61",
+  "version": "0.20.0",
   "main": "index.js",
   "repository": "https://github.com/polkadot-js/apps.git",
   "author": "Jaco Greeff <jacogr@gmail.com>",
@@ -11,7 +11,7 @@
   "license": "ISC",
   "dependencies": {
     "@babel/runtime": "^7.0.0",
-    "@polkadot/ui-app": "^0.19.61",
-    "@polkadot/ui-keyring": "^0.19.61"
+    "@polkadot/ui-app": "^0.20.0",
+    "@polkadot/ui-keyring": "^0.20.0"
   }
 }

+ 15 - 0
packages/app-transfer/LICENSE

@@ -0,0 +1,15 @@
+ISC License (ISC)
+
+Copyright 2017-2018 @polkadot/app-transfer authors & contributors
+
+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.

+ 3 - 0
packages/app-transfer/README.md

@@ -0,0 +1,3 @@
+# @polkadot/app-transfer
+
+A basic DOT transfer application, allowing the movement of funds from one account to another.

+ 18 - 0
packages/app-transfer/package.json

@@ -0,0 +1,18 @@
+{
+  "name": "@polkadot/app-transfer",
+  "version": "0.20.0",
+  "description": "A basic transfer app",
+  "main": "index.js",
+  "scripts": {},
+  "author": "Jaco Greeff <jacogr@gmail.com>",
+  "maintainers": [
+    "Jaco Greeff <jacogr@gmail.com>"
+  ],
+  "license": "ISC",
+  "dependencies": {
+    "@babel/runtime": "^7.0.0",
+    "@polkadot/ui-app": "^0.20.0",
+    "@polkadot/ui-keyring": "^0.20.0",
+    "@polkadot/ui-react-rx": "^0.20.0"
+  }
+}

+ 166 - 0
packages/app-transfer/src/Fees.tsx

@@ -0,0 +1,166 @@
+// Copyright 2017-2018 @polkadot/app-transfer authors & contributors
+// This software may be modified and distributed under the terms
+// of the ISC license. See the LICENSE file for details.
+
+import { I18nProps } from '@polkadot/ui-app/types';
+import { RxBalance, RxFees } from '@polkadot/ui-react-rx/ApiObservable/types';
+import { Fees } from './types';
+
+import BN from 'bn.js';
+import React from 'react';
+import Static from '@polkadot/ui-app/Static';
+import withMulti from '@polkadot/ui-react-rx/with/multi';
+import withObservable from '@polkadot/ui-react-rx/with/observable';
+
+import translate from './translate';
+
+type State = Fees;
+
+type Props = I18nProps & {
+  amount: BN,
+  balanceFrom?: RxBalance,
+  balanceTo?: RxBalance,
+  fees: RxFees,
+  from?: Uint8Array | null,
+  to?: Uint8Array | null,
+  onChange: (fees: Fees) => void
+};
+
+const ZERO = new BN(0);
+const ZERO_BALANCE = {
+  freeBalance: ZERO,
+  votingBalance: ZERO
+} as RxBalance;
+
+// FIXME Ok, this is really not cool. Based on the actual transaction we should calculate the size. However currently bacause of the "fully distant" nature of the signer component, we cannot really properly calculate the final size. So count it... and then fix it. (This needs to be sorted)
+const TRANSFER_SIZE = 156;
+
+class FeeDisplay extends React.PureComponent<Props, State> {
+  constructor (props: Props) {
+    super(props);
+
+    this.state = {
+      hasAvailable: false,
+      isCreation: false,
+      isNoEffect: false,
+      isRemovable: false,
+      isReserved: false,
+      txfees: ZERO,
+      txtotal: ZERO
+    };
+  }
+
+  static getDerivedStateFromProps ({ amount, to, from, fees, balanceTo = ZERO_BALANCE, balanceFrom = ZERO_BALANCE }: Props): State | null {
+    if (!from || !to) {
+      return null;
+    }
+
+    let txfees = fees.baseFee
+      .add(fees.transferFee)
+      .add(fees.byteFee.muln(TRANSFER_SIZE));
+
+    if (balanceTo.votingBalance.isZero()) {
+      txfees = txfees.add(fees.creationFee);
+    }
+
+    const txtotal = amount.add(txfees);
+    const hasAvailable = balanceFrom.freeBalance.gte(txtotal);
+    const isCreation = balanceTo.votingBalance.isZero();
+    const isNoEffect = amount.add(balanceTo.votingBalance).lte(fees.existentialDeposit);
+    const isRemovable = balanceFrom.votingBalance.sub(txtotal).lte(fees.existentialDeposit);
+    const isReserved = balanceFrom.freeBalance.isZero() && balanceFrom.reservedBalance.gtn(0);
+
+    return {
+      hasAvailable,
+      isCreation,
+      isNoEffect,
+      isRemovable,
+      isReserved,
+      txfees,
+      txtotal
+    };
+  }
+
+  componentDidUpdate () {
+    const { onChange } = this.props;
+
+    onChange(this.state);
+  }
+
+  render () {
+    const { className, fees, from, to, t } = this.props;
+    const { hasAvailable, isCreation, isNoEffect, isRemovable, isReserved, txfees, txtotal } = this.state;
+
+    if (!from || !to) {
+      return null;
+    }
+
+    return [
+      <Static
+        className={className}
+        key='txfees'
+        label={t('fees', {
+          defaultValue: 'with fees totalling'
+        })}
+        value={txfees.toString()}
+      />,
+      <article
+        className={hasAvailable ? ((isRemovable || isNoEffect) ? 'warning' : '') : 'error'}
+        key='txinfo'
+      >
+        {
+          isRemovable && hasAvailable
+              ? t('fees.remove', {
+                defaultValue: 'Submitting this transaction will drop the account balance to below the existential amount, removing the account from the chain state and burning associated funds. '
+              })
+            : undefined
+        }{
+          isNoEffect && hasAvailable
+            ? t('fees.noeffect', {
+              defaultValue: 'The final recipient amount is less than the existential amount, hence the total will be deducted from the sender, however the recipient account will not reflect the amount sent. '
+            })
+            : undefined
+        }{
+          hasAvailable
+            ? undefined
+            : t('fees.available', {
+              defaultValue: 'The account does not have the required funds available for this transaction with the current values. '
+            })
+        }{
+          isReserved
+          ? t('fees.reserved', {
+            defaultValue: '(This account does have a reserved/locked balance, staking locks up the available funds) '
+          })
+          : undefined
+        }{
+          t('fees.explain', {
+            defaultValue: 'Fees includes the transaction fee and the per-byte fee. '
+          })
+        }{
+          isCreation && fees.creationFee.gtn(0)
+            ? t('fees.create', {
+              defaultValue: 'A fee of {{creationFee}} will be deducted from the sender since the destination account does not exist.',
+              replace: {
+                creationFee: fees.creationFee.toString()
+              }
+            })
+          : undefined
+        }
+      </article>,
+      <Static
+        className='medium'
+        key='txtotal'
+        label={t('total', {
+          defaultValue: 'total transaction amount (fees + value)'
+        })}
+        value={txtotal.toString()}
+    />
+    ];
+  }
+}
+
+export default withMulti(
+  translate(FeeDisplay),
+  withObservable('votingBalance', { paramProp: 'from', propName: 'balanceFrom' }),
+  withObservable('votingBalance', { paramProp: 'to', propName: 'balanceTo' })
+);

+ 59 - 0
packages/app-transfer/src/Submit.tsx

@@ -0,0 +1,59 @@
+// Copyright 2017-2018 @polkadot/app-transfer authors & contributors
+// This software may be modified and distributed under the terms
+// of the ISC license. See the LICENSE file for details.
+
+import { I18nProps } from '@polkadot/ui-app/types';
+import { QueueTx$ExtrinsicAdd } from '@polkadot/ui-signer/types';
+
+import BN from 'bn.js';
+import React from 'react';
+import extrinsics from '@polkadot/extrinsics';
+import Button from '@polkadot/ui-app/Button';
+import withMulti from '@polkadot/ui-react-rx/with/multi';
+import withObservable from '@polkadot/ui-react-rx/with/observable';
+
+import translate from './translate';
+
+type Props = I18nProps & {
+  isDisabled: boolean,
+  accountIndex?: BN,
+  amount: BN,
+  from: Uint8Array,
+  to: Uint8Array,
+  queueExtrinsic: QueueTx$ExtrinsicAdd
+};
+
+class Submit extends React.PureComponent<Props> {
+  render () {
+    const { isDisabled, t } = this.props;
+
+    return (
+      <Button.Group>
+        <Button
+          isDisabled={isDisabled}
+          isPrimary
+          onClick={this.onMakeTransfer}
+          text={t('maketransfer', {
+            defaultValue: 'Make Transfer'
+          })}
+        />
+      </Button.Group>
+    );
+  }
+
+  private onMakeTransfer = () => {
+    const { accountIndex, amount, from, to, queueExtrinsic } = this.props;
+
+    queueExtrinsic({
+      extrinsic: extrinsics.staking.public.transfer,
+      nonce: accountIndex || new BN(0),
+      publicKey: from,
+      values: [to, amount]
+    });
+  }
+}
+
+export default withMulti(
+  translate(Submit),
+  withObservable('systemAccountIndexOf', { paramProp: 'from', propName: 'accountIndex' })
+);

+ 154 - 0
packages/app-transfer/src/Transfer.tsx

@@ -0,0 +1,154 @@
+// Copyright 2017-2018 @polkadot/app-transfer authors & contributors
+// This software may be modified and distributed under the terms
+// of the ISC license. See the LICENSE file for details.
+
+import { I18nProps } from '@polkadot/ui-app/types';
+import { RxFees } from '@polkadot/ui-react-rx/ApiObservable/types';
+import { QueueProps } from '@polkadot/ui-signer/types';
+import { Fees } from './types';
+
+import BN from 'bn.js';
+import React from 'react';
+import AddressSummary from '@polkadot/ui-app/AddressSummary';
+import InputAddress from '@polkadot/ui-app/InputAddress';
+import Input from '@polkadot/ui-app/Input';
+import withMulti from '@polkadot/ui-react-rx/with/multi';
+import withObservable from '@polkadot/ui-react-rx/with/observable';
+import { QueueConsumer } from '@polkadot/ui-signer/Context';
+
+import FeeDisplay from './Fees';
+import Submit from './Submit';
+import translate from './translate';
+
+type Props = I18nProps & {
+  fees: RxFees
+};
+
+type State = {
+  amount: BN,
+  from: Uint8Array | null,
+  to: Uint8Array | null,
+  txfees: Fees
+};
+
+const ZERO = new BN(0);
+
+class Transfer extends React.PureComponent<Props, State> {
+  state: State;
+
+  constructor (props: Props) {
+    super(props);
+
+    this.state = {
+      amount: ZERO,
+      from: null,
+      to: null,
+      txfees: {
+        hasAvailable: false,
+        txtotal: ZERO
+      } as Fees
+    };
+  }
+
+  render () {
+    const { fees, t } = this.props;
+    const { amount, from, to, txfees: { hasAvailable } } = this.state;
+
+    return (
+      <div className='transfer--Transfer'>
+        <div className='transfer--Transfer-selection'>
+          <div className='transfer--Transfer-data'>
+            <InputAddress
+              label={t('from', {
+                defaultValue: 'transfer from my account'
+              })}
+              onChange={this.onChangeFrom}
+              type='account'
+            />
+          </div>
+          <div className='transfer--Transfer-mid'>>></div>
+          <div className='transfer--Transfer-data'>
+            <InputAddress
+              label={t('to', {
+                defaultValue: 'to the recipient address'
+              })}
+              onChange={this.onChangeTo}
+              type='all'
+            />
+          </div>
+        </div>
+        <div className='transfer--Transfer-info'>
+          {this.renderAddress(from)}
+          <div className='transfer--Transfer-data'>
+            <Input
+              defaultValue='0'
+              isError={!hasAvailable}
+              label={t('amount', {
+                defaultValue: 'send a value of'
+              })}
+              min={0}
+              onChange={this.onChangeAmount}
+              type='number'
+            />
+            <FeeDisplay
+              className='medium'
+              amount={amount}
+              fees={fees}
+              from={from}
+              to={to}
+              onChange={this.onChangeFees}
+            />
+            <QueueConsumer>
+              {({ queueExtrinsic }: QueueProps) => (
+                <Submit
+                  isDisabled={!hasAvailable}
+                  amount={amount}
+                  from={from}
+                  to={to}
+                  queueExtrinsic={queueExtrinsic}
+                />
+              )}
+            </QueueConsumer>
+          </div>
+          {this.renderAddress(to)}
+        </div>
+      </div>
+    );
+  }
+
+  private renderAddress (publicKey: Uint8Array | null) {
+    if (!publicKey) {
+      return null;
+    }
+
+    return (
+      <div className='transfer--Transfer-address'>
+        <AddressSummary
+          value={publicKey}
+          withCopy={false}
+        />
+      </div>
+    );
+  }
+
+  private onChangeAmount = (amount: string) => {
+    this.setState({ amount: new BN(amount || 0) });
+  }
+
+  private onChangeFrom = (from: Uint8Array) => {
+    this.setState({ from });
+  }
+
+  private onChangeTo = (to: Uint8Array) => {
+    this.setState({ to });
+  }
+
+  private onChangeFees = (txfees: Fees) => {
+    this.setState({ txfees });
+  }
+}
+
+export default withMulti(
+  translate(Transfer),
+  withObservable('fees', { propName: 'fees' })
+);

+ 42 - 0
packages/app-transfer/src/index.css

@@ -0,0 +1,42 @@
+/* Copyright 2017-2018 @polkadot/app-transfer authors & contributors
+/* This software may be modified and distributed under the terms
+/* of the ISC license. See the LICENSE file for details. */
+
+.transfer--Transfer-selection,
+.transfer--Transfer-info {
+  display: flex;
+  flex-direction: row;
+}
+
+.transfer--Transfer-data,
+.transfer--Transfer-mid {
+  flex: 1 1;
+}
+
+.transfer--Transfer-mid {
+  padding: 2.5em 0.5em;
+  text-align: center;
+}
+
+.transfer--Transfer-address {
+  flex: 0 1;
+  padding: 2em 0;
+}
+
+.transfer--Transfer-address .ui--AddressSummary {
+  text-align: center;
+}
+
+.transfer--Transfer-amounts {
+  padding: 0 26%;
+}
+
+.error {
+  background-color: #fff6f6;
+  border-color: #e0b4b4;
+  color: #9f3a38;
+}
+
+.warning {
+  background: #ffffe0;
+}

+ 54 - 0
packages/app-transfer/src/index.tsx

@@ -0,0 +1,54 @@
+// Copyright 2017-2018 @polkadot/app-transfer authors & contributors
+// This software may be modified and distributed under the terms
+// of the ISC license. See the LICENSE file for details.
+
+import { I18nProps } from '@polkadot/ui-app/types';
+
+import React from 'react';
+import { Trans } from 'react-i18next';
+import accountObservable from '@polkadot/ui-keyring/observable/accounts';
+import withObservableBase from '@polkadot/ui-react-rx/with/observableBase';
+
+import './index.css';
+
+import Transfer from './Transfer';
+import translate from './translate';
+
+type Props = I18nProps & {
+  allAccounts?: Array<any>
+};
+
+type State = {
+};
+
+class App extends React.PureComponent<Props, State> {
+  render () {
+    return (
+      <main className='transfer--App'>
+        {this.renderBody()}
+      </main>
+    );
+  }
+
+  private renderBody () {
+    const { allAccounts } = this.props;
+
+    if (!allAccounts || !Object.keys(allAccounts).length) {
+      return (
+        <div className='transfer--App-no-accounts'>
+          <Trans i18nKey='no-accounts'>
+            You currently have no active accounts. Before you are able to transfer, add <a href='#/accounts'>an account</a>.
+          </Trans>
+        </div>
+      );
+    }
+
+    return (
+      <Transfer />
+    );
+  }
+}
+
+export default withObservableBase(
+  accountObservable.subject, { propName: 'allAccounts' }
+)(translate(App));

+ 7 - 0
packages/app-transfer/src/translate.ts

@@ -0,0 +1,7 @@
+// Copyright 2017-2018 @polkadot/app-toolbox authors & contributors
+// This software may be modified and distributed under the terms
+// of the ISC license. See the LICENSE file for details.
+
+import { translate } from 'react-i18next';
+
+export default translate(['transfer', 'ui']);

+ 15 - 0
packages/app-transfer/src/types.d.ts

@@ -0,0 +1,15 @@
+// Copyright 2017-2018 @polkadot/app-toolbox authors & contributors
+// This software may be modified and distributed under the terms
+// of the ISC license. See the LICENSE file for details.
+
+import BN from 'bn.js';
+
+export type Fees = {
+  hasAvailable: boolean,
+  isCreation: boolean,
+  isNoEffect: boolean,
+  isRemovable: boolean,
+  isReserved: boolean,
+  txfees: BN,
+  txtotal: BN
+};

+ 2 - 2
packages/app-vanitygen/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@polkadot/app-vanitygen",
-  "version": "0.19.61",
+  "version": "0.20.0",
   "main": "index.js",
   "repository": "https://github.com/polkadot-js/apps.git",
   "author": "Jaco Greeff <jacogr@gmail.com>",
@@ -11,7 +11,7 @@
   "license": "ISC",
   "dependencies": {
     "@babel/runtime": "^7.0.0",
-    "@polkadot/ui-app": "^0.19.61",
+    "@polkadot/ui-app": "^0.20.0",
     "@types/yargs": "^11.1.1",
     "babel-plugin-module-resolver": "^3.1.1",
     "libsodium-wrappers": "^0.7.3",

+ 15 - 14
packages/apps/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@polkadot/apps",
-  "version": "0.19.61",
+  "version": "0.20.0",
   "description": "An Apps portal into the Polkadot network",
   "main": "index.js",
   "homepage": ".",
@@ -13,19 +13,20 @@
   "license": "ISC",
   "dependencies": {
     "@babel/runtime": "^7.0.0",
-    "@polkadot/app-accounts": "^0.19.61",
-    "@polkadot/app-addresses": "^0.19.61",
-    "@polkadot/app-democracy": "^0.19.61",
-    "@polkadot/app-example": "^0.19.61",
-    "@polkadot/app-explorer": "^0.19.61",
-    "@polkadot/app-extrinsics": "^0.19.61",
-    "@polkadot/app-rpc": "^0.19.61",
-    "@polkadot/app-staking": "^0.19.61",
-    "@polkadot/app-storage": "^0.19.61",
-    "@polkadot/app-toolbox": "^0.19.61",
-    "@polkadot/app-vanitygen": "^0.19.61",
-    "@polkadot/ui-app": "^0.19.61",
-    "@polkadot/ui-signer": "^0.19.61"
+    "@polkadot/app-accounts": "^0.20.0",
+    "@polkadot/app-addresses": "^0.20.0",
+    "@polkadot/app-democracy": "^0.20.0",
+    "@polkadot/app-example": "^0.20.0",
+    "@polkadot/app-explorer": "^0.20.0",
+    "@polkadot/app-extrinsics": "^0.20.0",
+    "@polkadot/app-rpc": "^0.20.0",
+    "@polkadot/app-staking": "^0.20.0",
+    "@polkadot/app-storage": "^0.20.0",
+    "@polkadot/app-toolbox": "^0.20.0",
+    "@polkadot/app-transfer": "^0.20.0",
+    "@polkadot/app-vanitygen": "^0.20.0",
+    "@polkadot/ui-app": "^0.20.0",
+    "@polkadot/ui-signer": "^0.20.0"
   },
   "devDependencies": {
     "copy-webpack-plugin": "^4.5.1",

+ 6 - 6
packages/apps/src/routing/index.ts

@@ -10,12 +10,11 @@ import democracy from './democracy';
 import example from './example';
 import explorer from './explorer';
 import extrinsics from './extrinsics';
-// import home from './home';
 import rpc from './rpc';
-// import settings from './settings';
 import staking from './staking';
 import storage from './storage';
 import toolbox from './toolbox';
+import transfer from './transfer';
 import vanitygen from './vanitygen';
 
 export default ({
@@ -23,16 +22,17 @@ export default ({
   routes: ([] as Routes).concat(
     example,
     explorer,
+    transfer,
     staking,
     democracy,
     null,
-    extrinsics,
-    storage,
-    null,
     accounts,
     addresses,
-    vanitygen,
     null,
+    storage,
+    extrinsics,
+    null,
+    vanitygen,
     rpc,
     toolbox
   )

+ 19 - 0
packages/apps/src/routing/transfer.ts

@@ -0,0 +1,19 @@
+// Copyright 2017-2018 @polkadot/apps authors & contributors
+// This software may be modified and distributed under the terms
+// of the ISC license. See the LICENSE file for details.
+
+import { Routes } from '../types';
+
+import Transfer from '@polkadot/app-transfer/index';
+
+export default ([
+  {
+    Component: Transfer,
+    i18n: {
+      defaultValue: 'Transfer'
+    },
+    icon: 'angle double right',
+    isHidden: false,
+    name: 'transfer'
+  }
+] as Routes);

+ 1 - 0
packages/apps/webpack.config.js

@@ -21,6 +21,7 @@ const packages = [
   'app-staking',
   'app-storage',
   'app-toolbox',
+  'app-transfer',
   'app-vanitygen',
   'ui-app',
   'ui-identicon',

+ 6 - 6
packages/ui-app/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@polkadot/ui-app",
-  "version": "0.19.61",
+  "version": "0.20.0",
   "main": "index.js",
   "repository": "https://github.com/polkadot-js/apps.git",
   "author": "Jaco Greeff <jacogr@gmail.com>",
@@ -11,11 +11,11 @@
   "license": "ISC",
   "dependencies": {
     "@babel/runtime": "^7.0.0",
-    "@polkadot/extrinsics": "^0.28.28",
-    "@polkadot/storage": "^0.28.28",
-    "@polkadot/ui-keyring": "^0.19.61",
-    "@polkadot/ui-react": "^0.19.61",
-    "@polkadot/ui-react-rx": "^0.19.61",
+    "@polkadot/extrinsics": "^0.28.29",
+    "@polkadot/storage": "^0.28.29",
+    "@polkadot/ui-keyring": "^0.20.0",
+    "@polkadot/ui-react": "^0.20.0",
+    "@polkadot/ui-react-rx": "^0.20.0",
     "@types/chart.js": "^2.7.32",
     "@types/i18next-browser-languagedetector": "^2.0.1",
     "@types/i18next-xhr-backend": "^1.4.1",

+ 37 - 9
packages/ui-app/src/AddressSummary.tsx

@@ -21,8 +21,10 @@ export type Props = I18nProps & {
   balance?: BN | Array<BN>,
   children?: React.ReactNode,
   name?: string,
-  value: string,
+  value: string | Uint8Array,
   withBalance?: boolean,
+  withCopy?: boolean,
+  withIcon?: boolean,
   withNonce?: boolean
 };
 
@@ -60,7 +62,7 @@ class AddressSummary extends React.PureComponent<Props, State> {
 
   render () {
     const { className, style } = this.props;
-    const { address, isValid } = this.state;
+    const { isValid } = this.state;
 
     return (
       <div
@@ -68,11 +70,7 @@ class AddressSummary extends React.PureComponent<Props, State> {
         style={style}
       >
         <div className='ui--AddressSummary-base'>
-          <IdentityIcon
-            className='ui--AddressSummary-icon'
-            size={96}
-            value={address}
-          />
+          {this.renderIcon()}
           {this.renderAddress()}
           {this.renderBalance()}
           {this.renderNonce()}
@@ -84,7 +82,7 @@ class AddressSummary extends React.PureComponent<Props, State> {
 
   protected renderAddress () {
     const { name } = this.props;
-    const { address, shortValue } = this.state;
+    const { shortValue } = this.state;
 
     return (
       <div className='ui--AddressSummary-data'>
@@ -94,7 +92,7 @@ class AddressSummary extends React.PureComponent<Props, State> {
         <div className='ui--AddressSummary-address'>
           {shortValue}
         </div>
-        <CopyButton value={address} />
+        {this.renderCopy()}
       </div>
     );
   }
@@ -119,6 +117,36 @@ class AddressSummary extends React.PureComponent<Props, State> {
     );
   }
 
+  protected renderCopy () {
+    const { withCopy = true } = this.props;
+    const { address } = this.state;
+
+    if (!withCopy) {
+      return null;
+    }
+
+    return (
+      <CopyButton value={address} />
+    );
+  }
+
+  protected renderIcon () {
+    const { withIcon = true } = this.props;
+    const { address } = this.state;
+
+    if (!withIcon) {
+      return null;
+    }
+
+    return (
+      <IdentityIcon
+        className='ui--AddressSummary-icon'
+        size={96}
+        value={address}
+      />
+    );
+  }
+
   protected renderNonce () {
     const { isValid, publicKey } = this.state;
     const { t, withNonce = true } = this.props;

+ 2 - 2
packages/ui-identicon/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@polkadot/ui-identicon",
-  "version": "0.19.61",
+  "version": "0.20.0",
   "description": "Renders an SVG picture representing an address",
   "main": "index.js",
   "scripts": {
@@ -22,7 +22,7 @@
     "color": "^3.0.0"
   },
   "devDependencies": {
-    "@polkadot/util-crypto": "^0.29.32",
+    "@polkadot/util-crypto": "^0.29.33",
     "xmlserializer": "^0.6.1"
   }
 }

+ 3 - 3
packages/ui-keyring/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@polkadot/ui-keyring",
-  "version": "0.19.61",
+  "version": "0.20.0",
   "main": "index.js",
   "repository": "https://github.com/polkadot-js/apps.git",
   "author": "Jaco Greeff <jacogr@gmail.com>",
@@ -11,8 +11,8 @@
   "license": "ISC",
   "dependencies": {
     "@babel/runtime": "^7.0.0",
-    "@polkadot/ui-react": "^0.19.61",
-    "@polkadot/util-keyring": "^0.29.32",
+    "@polkadot/ui-react": "^0.20.0",
+    "@polkadot/util-keyring": "^0.29.33",
     "store": "^2.0.12"
   },
   "peerDependencies": {

+ 4 - 4
packages/ui-react-rx/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@polkadot/ui-react-rx",
-  "version": "0.19.61",
+  "version": "0.20.0",
   "description": "A collection of RxJs React components the Polkadot JS API",
   "main": "index.js",
   "keywords": [
@@ -31,9 +31,9 @@
   "homepage": "https://github.com/polkadot-js/ui/tree/master/packages/ui-react-rx#readme",
   "dependencies": {
     "@babel/runtime": "^7.0.0",
-    "@polkadot/api-rx": "^0.28.28",
-    "@polkadot/extrinsics": "^0.28.28",
-    "@polkadot/storage": "^0.28.28",
+    "@polkadot/api-rx": "^0.28.29",
+    "@polkadot/extrinsics": "^0.28.29",
+    "@polkadot/storage": "^0.28.29",
     "rxjs-compat": "^6.3.2"
   },
   "devDependencies": {

+ 23 - 2
packages/ui-react-rx/src/ApiObservable/index.ts

@@ -7,7 +7,7 @@ import { RxApiInterface, RxApiInterface$Method } from '@polkadot/api-rx/types';
 import { Interfaces } from '@polkadot/jsonrpc/types';
 import { BlockDecoded, ExtrinsicDecoded, SectionItem } from '@polkadot/params/types';
 import { Storages } from '@polkadot/storage/types';
-import { RxBalance, RxBalanceMap, RxProposal, RxProposalDeposits, RxReferendum, ObservableApiInterface, KeyWithParams, RxReferendumVote } from './types';
+import { RxBalance, RxBalanceMap, RxFees, RxProposal, RxProposalDeposits, RxReferendum, ObservableApiInterface, KeyWithParams, KeyWithoutParams, RxReferendumVote } from './types';
 
 import BN from 'bn.js';
 import { EMPTY, Observable, combineLatest } from 'rxjs';
@@ -66,7 +66,7 @@ export default class ObservableApi implements ObservableApiInterface {
       );
   }
 
-  rawStorageMulti = <T> (...keys: Array<KeyWithParams>): Observable<T> => {
+  rawStorageMulti = <T> (...keys: Array<KeyWithParams | KeyWithoutParams>): Observable<T> => {
     return this.api.state
       .storage(keys)
       .pipe(
@@ -328,6 +328,27 @@ export default class ObservableApi implements ObservableApiInterface {
     );
   }
 
+  fees = (): Observable<RxFees> => {
+    return this
+      .rawStorageMulti(
+        [storage.staking.public.transactionBaseFee],
+        [storage.staking.public.transactionByteFee],
+        [storage.staking.public.creationFee],
+        [storage.staking.public.existentialDeposit ],
+        [storage.staking.public.transferFee ]
+      )
+      .pipe(
+        // @ts-ignore After upgrade to 6.3.2
+        map(([baseFee = new BN(0), byteFee = new BN(0), creationFee = new BN(0), existentialDeposit = new BN(0), transferFee = new BN(0)]: [OptBN, OptBN, OptBN, OptBN, OptBN]) => ({
+          baseFee,
+          byteFee,
+          creationFee,
+          existentialDeposit,
+          transferFee
+        }))
+      );
+  }
+
   eraLastLengthChange = (): Observable<OptBN> => {
     return this.rawStorage(storage.staking.public.lastEraLengthChange);
   }

+ 11 - 1
packages/ui-react-rx/src/ApiObservable/types.d.ts

@@ -19,6 +19,14 @@ export type RxBalance = {
   nominators?: Array<RxBalance>
 }
 
+export type RxFees = {
+  baseFee: BN,
+  byteFee: BN,
+  creationFee: BN,
+  existentialDeposit: BN,
+  transferFee: BN,
+};
+
 export type RxProposal = {
   address: string,
   id: BN,
@@ -47,12 +55,13 @@ export type RxBalanceMap = {
   [index: string]: RxBalance
 }
 
+export type KeyWithoutParams = [SectionItem<Storages>];
 export type KeyWithParams = [SectionItem<Storages>, any];
 
 export interface ObservableApiInterface {
   rawCall: <T> ({ name, section }: SectionItem<Interfaces>, ...params: Array<any>) => Observable<T>,
   rawStorage: <T> (key: SectionItem<Storages>, ...params: Array<any>) => Observable<T>,
-  rawStorageMulti: <T> (...keys: Array<[SectionItem<Storages>, any]>) => Observable<T>,
+  rawStorageMulti: <T> (...keys: Array<KeyWithParams | KeyWithoutParams>) => Observable<T>,
   bestNumber: () => Observable<BN | undefined>,
   chainGetBlock: (hash: Uint8Array) => Observable<BlockDecoded | undefined>,
   chainNewHead: () => Observable<Header | undefined>,
@@ -68,6 +77,7 @@ export interface ObservableApiInterface {
   eraBlockLength: () => Observable<BN | undefined>,
   eraBlockProgress: () => Observable<BN | undefined>,
   eraBlockRemaining: () => Observable<BN | undefined>,
+  fees: () => Observable<RxFees | undefined>,
   sessionBlockProgress: () => Observable<BN | undefined>,
   sessionBlockRemaining: () => Observable<BN | undefined>,
   sessionBrokenPercentLate: () => Observable<BN | undefined>,

+ 3 - 3
packages/ui-react/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@polkadot/ui-react",
-  "version": "0.19.61",
+  "version": "0.20.0",
   "description": "A collection of base React components",
   "main": "index.js",
   "author": "Jaco Greeff <jacogr@gmail.com>",
@@ -11,11 +11,11 @@
   "license": "ISC",
   "dependencies": {
     "@babel/runtime": "^7.0.0",
-    "@polkadot/ui-identicon": "^0.19.61",
+    "@polkadot/ui-identicon": "^0.20.0",
     "polkadot-identicon": "^1.0.2"
   },
   "devDependencies": {
-    "@polkadot/util-keyring": "^0.29.32",
+    "@polkadot/util-keyring": "^0.29.33",
     "empty": "^0.10.1",
     "react": "^16.5.0",
     "react-dom": "^16.5.0"

+ 4 - 4
packages/ui-signer/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@polkadot/ui-signer",
-  "version": "0.19.61",
+  "version": "0.20.0",
   "main": "index.js",
   "repository": "https://github.com/polkadot-js/apps.git",
   "author": "Jaco Greeff <jacogr@gmail.com>",
@@ -11,9 +11,9 @@
   "license": "ISC",
   "dependencies": {
     "@babel/runtime": "^7.0.0",
-    "@polkadot/extrinsics": "^0.28.28",
-    "@polkadot/ui-app": "^0.19.61",
-    "@polkadot/ui-keyring": "^0.19.61"
+    "@polkadot/extrinsics": "^0.28.29",
+    "@polkadot/ui-app": "^0.20.0",
+    "@polkadot/ui-keyring": "^0.20.0"
   },
   "peerDependencies": {
     "react": "^16.5.0",

+ 1 - 0
tsconfig.json

@@ -13,6 +13,7 @@
       "@polkadot/app-staking/*": [ "packages/app-staking/src/*" ],
       "@polkadot/app-storage/*": [ "packages/app-storage/src/*" ],
       "@polkadot/app-toolbox/*": [ "packages/app-toolbox/src/*" ],
+      "@polkadot/app-transfer/*": [ "packages/app-transfer/src/*" ],
       "@polkadot/app-vanitygen/*": [ "packages/app-vanitygen/src/*" ],
       "@polkadot/apps/*": [ "packages/apps/src/*" ],
       "@polkadot/ui-app/*": [ "packages/ui-app/src/*" ],

+ 83 - 83
yarn.lock

@@ -1348,50 +1348,50 @@
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.0.tgz#50c1e2260ac0ed9439a181de3725a0168d59c48a"
 
-"@polkadot/api-format@^0.28.28":
-  version "0.28.28"
-  resolved "https://registry.yarnpkg.com/@polkadot/api-format/-/api-format-0.28.28.tgz#41fbf386c2eb583d160da5425502e259f664eebd"
+"@polkadot/api-format@^0.28.29":
+  version "0.28.29"
+  resolved "https://registry.yarnpkg.com/@polkadot/api-format/-/api-format-0.28.29.tgz#dd0ac95a6211743c4f918926549044e574424f75"
   dependencies:
     "@babel/runtime" "^7.0.0"
-    "@polkadot/jsonrpc" "^0.28.28"
-    "@polkadot/primitives" "^0.28.28"
-    "@polkadot/util" "^0.29.32"
-    "@polkadot/util-keyring" "^0.29.32"
+    "@polkadot/jsonrpc" "^0.28.29"
+    "@polkadot/primitives" "^0.28.29"
+    "@polkadot/util" "^0.29.33"
+    "@polkadot/util-keyring" "^0.29.33"
 
-"@polkadot/api-provider@^0.28.28":
-  version "0.28.28"
-  resolved "https://registry.yarnpkg.com/@polkadot/api-provider/-/api-provider-0.28.28.tgz#8e6baebffd1f62bb189179e4feac981082fa00b5"
+"@polkadot/api-provider@^0.28.29":
+  version "0.28.29"
+  resolved "https://registry.yarnpkg.com/@polkadot/api-provider/-/api-provider-0.28.29.tgz#94c7cb7d3add29740796059cfcf99d16cf968227"
   dependencies:
     "@babel/runtime" "^7.0.0"
-    "@polkadot/storage" "^0.28.28"
-    "@polkadot/util" "^0.29.32"
-    "@polkadot/util-crypto" "^0.29.32"
-    "@polkadot/util-keyring" "^0.29.32"
+    "@polkadot/storage" "^0.28.29"
+    "@polkadot/util" "^0.29.33"
+    "@polkadot/util-crypto" "^0.29.33"
+    "@polkadot/util-keyring" "^0.29.33"
     "@types/nock" "^9.1.3"
     eventemitter3 "^3.1.0"
     isomorphic-fetch "^2.2.1"
     websocket "^1.0.25"
 
-"@polkadot/api-rx@^0.28.28":
-  version "0.28.28"
-  resolved "https://registry.yarnpkg.com/@polkadot/api-rx/-/api-rx-0.28.28.tgz#66ba2fb82bd3a325d808e8d19282ba20f11a4540"
+"@polkadot/api-rx@^0.28.29":
+  version "0.28.29"
+  resolved "https://registry.yarnpkg.com/@polkadot/api-rx/-/api-rx-0.28.29.tgz#68bdcc82bf6b6deefdab4550c341d7a6b66c5f25"
   dependencies:
     "@babel/runtime" "^7.0.0"
-    "@polkadot/api" "^0.28.28"
-    "@polkadot/api-provider" "^0.28.28"
+    "@polkadot/api" "^0.28.29"
+    "@polkadot/api-provider" "^0.28.29"
     "@types/rx" "^4.1.1"
     rxjs "^6.3.2"
 
-"@polkadot/api@^0.28.28":
-  version "0.28.28"
-  resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-0.28.28.tgz#5a7b10e4f6adfa8af08aa14c759e56aea42832a9"
+"@polkadot/api@^0.28.29":
+  version "0.28.29"
+  resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-0.28.29.tgz#fdbf97c11cbb901b0bb175c8e146f88a19f08710"
   dependencies:
     "@babel/runtime" "^7.0.0"
-    "@polkadot/api-format" "^0.28.28"
-    "@polkadot/api-provider" "^0.28.28"
-    "@polkadot/jsonrpc" "^0.28.28"
-    "@polkadot/params" "^0.28.28"
-    "@polkadot/util" "^0.29.32"
+    "@polkadot/api-format" "^0.28.29"
+    "@polkadot/api-provider" "^0.28.29"
+    "@polkadot/jsonrpc" "^0.28.29"
+    "@polkadot/params" "^0.28.29"
+    "@polkadot/util" "^0.29.33"
 
 "@polkadot/dev-react@^0.20.19":
   version "0.20.19"
@@ -1461,96 +1461,96 @@
     typedoc-plugin-markdown "^1.1.15"
     typescript "^3.0.1"
 
-"@polkadot/extrinsics@^0.28.28":
-  version "0.28.28"
-  resolved "https://registry.yarnpkg.com/@polkadot/extrinsics/-/extrinsics-0.28.28.tgz#62f5ff8084822d751d636b8a100a07bda1046348"
+"@polkadot/extrinsics@^0.28.29":
+  version "0.28.29"
+  resolved "https://registry.yarnpkg.com/@polkadot/extrinsics/-/extrinsics-0.28.29.tgz#6b4909a641b21b7b3a57d41e29021dc203a8a98c"
   dependencies:
     "@babel/runtime" "^7.0.0"
-    "@polkadot/params" "^0.28.28"
-    "@polkadot/primitives" "^0.28.28"
-    "@polkadot/util" "^0.29.32"
+    "@polkadot/params" "^0.28.29"
+    "@polkadot/primitives" "^0.28.29"
+    "@polkadot/util" "^0.29.33"
 
-"@polkadot/jsonrpc@^0.28.28":
-  version "0.28.28"
-  resolved "https://registry.yarnpkg.com/@polkadot/jsonrpc/-/jsonrpc-0.28.28.tgz#c161e2e1939c88a0b446981851eb109fc89f1861"
+"@polkadot/jsonrpc@^0.28.29":
+  version "0.28.29"
+  resolved "https://registry.yarnpkg.com/@polkadot/jsonrpc/-/jsonrpc-0.28.29.tgz#d6169dacf02f7d24d7e948219b36f2f2c449206e"
   dependencies:
-    "@polkadot/params" "^0.28.28"
+    "@polkadot/params" "^0.28.29"
     babel-runtime "^6.26.0"
 
-"@polkadot/params@^0.28.28":
-  version "0.28.28"
-  resolved "https://registry.yarnpkg.com/@polkadot/params/-/params-0.28.28.tgz#22b12d3aa0a11ad4586b5a7f9080302cb20baf96"
+"@polkadot/params@^0.28.29":
+  version "0.28.29"
+  resolved "https://registry.yarnpkg.com/@polkadot/params/-/params-0.28.29.tgz#d079b827c604c5f32663ffbfacdd5d4e4a28021a"
   dependencies:
     "@babel/runtime" "^7.0.0"
-    "@polkadot/extrinsics" "^0.28.28"
-    "@polkadot/params" "^0.28.28"
-    "@polkadot/primitives" "^0.28.28"
-    "@polkadot/util" "^0.29.32"
-    "@polkadot/util-keyring" "^0.29.32"
+    "@polkadot/extrinsics" "^0.28.29"
+    "@polkadot/params" "^0.28.29"
+    "@polkadot/primitives" "^0.28.29"
+    "@polkadot/util" "^0.29.33"
+    "@polkadot/util-keyring" "^0.29.33"
 
-"@polkadot/primitives@^0.28.28":
-  version "0.28.28"
-  resolved "https://registry.yarnpkg.com/@polkadot/primitives/-/primitives-0.28.28.tgz#76a705568eec1cd3da2afd4d31f71150e2505574"
+"@polkadot/primitives@^0.28.29":
+  version "0.28.29"
+  resolved "https://registry.yarnpkg.com/@polkadot/primitives/-/primitives-0.28.29.tgz#0b0b99242048e606701a8b33cd12c2eeff7d7857"
   dependencies:
     "@babel/runtime" "^7.0.0"
-    "@polkadot/trie-hash" "^0.29.32"
-    "@polkadot/util" "^0.29.32"
+    "@polkadot/trie-hash" "^0.29.33"
+    "@polkadot/util" "^0.29.33"
 
-"@polkadot/storage@^0.28.28":
-  version "0.28.28"
-  resolved "https://registry.yarnpkg.com/@polkadot/storage/-/storage-0.28.28.tgz#dc5d522a3438eb9afc16c63bd704782975a1513d"
+"@polkadot/storage@^0.28.29":
+  version "0.28.29"
+  resolved "https://registry.yarnpkg.com/@polkadot/storage/-/storage-0.28.29.tgz#a96ea7ad7db953788beaa1b1b2d59cd303313b1d"
   dependencies:
     "@babel/runtime" "^7.0.0"
-    "@polkadot/params" "^0.28.28"
-    "@polkadot/primitives" "^0.28.28"
-    "@polkadot/util" "^0.29.32"
-    "@polkadot/util-crypto" "^0.29.32"
-    "@polkadot/util-keyring" "^0.29.32"
+    "@polkadot/params" "^0.28.29"
+    "@polkadot/primitives" "^0.28.29"
+    "@polkadot/util" "^0.29.33"
+    "@polkadot/util-crypto" "^0.29.33"
+    "@polkadot/util-keyring" "^0.29.33"
 
-"@polkadot/trie-hash@^0.29.32":
-  version "0.29.32"
-  resolved "https://registry.yarnpkg.com/@polkadot/trie-hash/-/trie-hash-0.29.32.tgz#b2d7339b834c56dbffd9e0db4f3c6b53a2a74cf0"
+"@polkadot/trie-hash@^0.29.33":
+  version "0.29.33"
+  resolved "https://registry.yarnpkg.com/@polkadot/trie-hash/-/trie-hash-0.29.33.tgz#530757d2a080620175fb1907fe3d56a1970dc415"
   dependencies:
     "@babel/runtime" "^7.0.0"
-    "@polkadot/util" "^0.29.32"
-    "@polkadot/util-crypto" "^0.29.32"
-    "@polkadot/util-rlp" "^0.29.32"
+    "@polkadot/util" "^0.29.33"
+    "@polkadot/util-crypto" "^0.29.33"
+    "@polkadot/util-rlp" "^0.29.33"
 
-"@polkadot/ts@^0.1.25":
-  version "0.1.25"
-  resolved "https://registry.yarnpkg.com/@polkadot/ts/-/ts-0.1.25.tgz#a88c5242ae02975acce7128b5a84a6df8ca9d7b7"
+"@polkadot/ts@^0.1.27":
+  version "0.1.27"
+  resolved "https://registry.yarnpkg.com/@polkadot/ts/-/ts-0.1.27.tgz#88ddd9e90f4c5c98996ecd433670839eaf530d73"
 
-"@polkadot/util-crypto@^0.29.32":
-  version "0.29.32"
-  resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-0.29.32.tgz#f92cfc35310007f5ab78acb087e4b3c2c7f18f45"
+"@polkadot/util-crypto@^0.29.33":
+  version "0.29.33"
+  resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-0.29.33.tgz#299136ce92bb68d616f8b2b00cb5c4630a4fee67"
   dependencies:
     "@babel/runtime" "^7.0.0"
-    "@polkadot/util" "^0.29.32"
+    "@polkadot/util" "^0.29.33"
     blakejs "^1.1.0"
     js-sha3 "^0.8.0"
     tweetnacl "^1.0.0"
     xxhashjs "^0.2.2"
 
-"@polkadot/util-keyring@^0.29.32":
-  version "0.29.32"
-  resolved "https://registry.yarnpkg.com/@polkadot/util-keyring/-/util-keyring-0.29.32.tgz#a75918c18268ca8ec729c9f0dfba8b2802c67ea5"
+"@polkadot/util-keyring@^0.29.33":
+  version "0.29.33"
+  resolved "https://registry.yarnpkg.com/@polkadot/util-keyring/-/util-keyring-0.29.33.tgz#c6fd3325c08fb103cf0a4f49aa74977722ab16ee"
   dependencies:
     "@babel/runtime" "^7.0.0"
-    "@polkadot/util" "^0.29.32"
-    "@polkadot/util-crypto" "^0.29.32"
+    "@polkadot/util" "^0.29.33"
+    "@polkadot/util-crypto" "^0.29.33"
     "@types/bs58" "^3.0.30"
     bs58 "^4.0.1"
 
-"@polkadot/util-rlp@^0.29.32":
-  version "0.29.32"
-  resolved "https://registry.yarnpkg.com/@polkadot/util-rlp/-/util-rlp-0.29.32.tgz#0c27b6d05550b576e3d158dedce2acfbd7f160fe"
+"@polkadot/util-rlp@^0.29.33":
+  version "0.29.33"
+  resolved "https://registry.yarnpkg.com/@polkadot/util-rlp/-/util-rlp-0.29.33.tgz#0a5f9b2d954cc2f9cd92964f0efd0372a03ee808"
   dependencies:
     "@babel/runtime" "^7.0.0"
-    "@polkadot/util" "^0.29.32"
+    "@polkadot/util" "^0.29.33"
 
-"@polkadot/util@^0.29.32":
-  version "0.29.32"
-  resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-0.29.32.tgz#9cc5824b070f461e88417ffe604bb4ec9239def5"
+"@polkadot/util@^0.29.33":
+  version "0.29.33"
+  resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-0.29.33.tgz#b8e59146584c4649ca9308aa636d63d0b2ea2db3"
   dependencies:
     "@babel/runtime" "^7.0.0"
     "@types/bn.js" "^4.11.1"