Compare commits

..
150 Commits
Author SHA1 Message Date
Github Actions 51dece8b0f [CI Skip] release/stable 0.55.1
skip-checks: true
2020-07-02 11:49:16 +00:00
Jaco Greeff 2452470163 0.55 (#341) 2020-07-02 13:44:36 +02:00
Github Actions edbdb4f239 [CI Skip] release/beta 0.55.0-beta.6
skip-checks: true
2020-07-02 09:54:25 +00:00
Jaco Greeff 43da3b50de Assert of single key 2020-07-02 11:49:54 +02:00
yuhui1208 a3658de7c2 [Stores] make FileStroe read key safely (#338)
* safely readKey

* fix ci

* fix

* fix type error

* Modify judgment

* fix

* fix

* fix lint
2020-07-02 11:44:04 +02:00
Github Actions 74315ec825 [CI Skip] release/beta 0.55.0-beta.5
skip-checks: true
2020-07-02 06:07:03 +00:00
Jaco Greeff 4c58f48645 Bump deps (#340)
* Bump deps

* Adjust for new eslint parser
2020-07-02 08:01:50 +02:00
Github Actions c8f4983946 [CI Skip] release/beta 0.55.0-beta.4
skip-checks: true
2020-07-01 11:44:59 +00:00
Jaco Greeff ea7fad63a6 Ignore .DS_Store (#339)
As per https://github.com/polkadot-js/ui/issues/337#issuecomment-651617556
2020-07-01 13:39:41 +02:00
Github Actions 65352f4253 [CI Skip] release/beta 0.55.0-beta.3
skip-checks: true
2020-06-28 05:40:43 +00:00
Jaco Greeff 11922b1b02 Only apply before on highlight for icons (#336) 2020-06-28 07:35:17 +02:00
Github Actions 47752593b0 [CI Skip] release/beta 0.55.0-beta.2
skip-checks: true
2020-06-25 10:20:37 +00:00
Jaco Greeff 8dfaea2bfc Dep cleanups (#335) 2020-06-25 12:15:27 +02:00
Github Actions b288773d15 [CI Skip] release/beta 0.55.0-beta.1
skip-checks: true
2020-06-24 07:34:57 +00:00
Jaco Greeff 25d9da3144 Bump dependencies (#334)
* Bump dependencies

* QR display component to functional

* Small adjustments
2020-06-24 09:29:43 +02:00
Github Actions 841819d249 [CI Skip] release/beta 0.55.0-beta.0
skip-checks: true
2020-06-22 19:35:29 +00:00
Jaco Greeff 47fa7f9f0e Ledger dependencies bump (#332)
* Bump Ledger deps, adjust interfaces

* Cleanup with correct ledger exports

* Align deps

* 0.10.4
2020-06-22 21:31:17 +02:00
Jaco Greeff ed2c9e5c41 Bumps 2020-06-22 20:42:21 +02:00
Jaco Greeff 985177dd96 Bump deps (#333) 2020-06-22 20:37:44 +02:00
Github Actions 95a1a4f9a2 [CI Skip] release/stable 0.54.1
skip-checks: true
2020-06-16 07:06:08 +00:00
Jaco Greeff e142284713 0.54 (#331)
* 0.54

* 0.54
2020-06-16 09:01:20 +02:00
Github Actions be246413fa [CI Skip] release/beta 0.54.0-beta.7
skip-checks: true
2020-06-12 21:00:11 +00:00
Hanwen Cheng c7bf1d2ec9 allow qr to scan seed qr (#330)
* allow qr to scan seed qr

* simplify flow

* use original orders

* remove trailing spaces
2020-06-12 22:54:40 +02:00
Github Actions 48327feb34 [CI Skip] release/beta 0.54.0-beta.6
skip-checks: true
2020-06-05 20:35:31 +00:00
Jaco Greeff afa6950f0c Rewrite yarn (#329) 2020-06-05 22:30:09 +02:00
Github Actions 2adedba064 [CI Skip] release/beta 0.54.0-beta.5
skip-checks: true
2020-06-05 20:24:11 +00:00
Jaco Greeff 2309998889 Bump deps (#328) 2020-06-05 22:19:38 +02:00
Github Actions a8f906a15e [CI Skip] 0.54.0-beta.4
skip-checks: true
2020-05-30 07:08:00 +00:00
Jaco Greeff 990d4394af Rename Substrate entry to "generic" (#327)
* Rename Substrate entry to "generic"

* Rewrite yarn.lock

* Linting (base package update)
2020-05-30 09:03:08 +02:00
Github Actions 66f65052f6 [CI Skip] 0.54.0-beta.3
skip-checks: true
2020-05-27 15:53:51 +00:00
Jaco GreeffandHanwen Cheng 9252de79d4 Add genesisHash to signer payload (#323)
* Add genesisHash to signer payload

* fix order and add tests (#324)

* fix order and add tests

* Update packages/react-qr/src/util.spec.ts

* Update packages/react-qr/src/util.spec.ts

Co-authored-by: Jaco Greeff <jacogr@gmail.com>

* Apply suggestions from code review

Co-authored-by: Hanwen Cheng <heawen.cheng@gmail.com>
2020-05-27 17:48:32 +02:00
Github Actions a31ef816bd [CI Skip] 0.54.0-beta.2
skip-checks: true
2020-05-24 07:40:05 +00:00
Jaco Greeff 2df46e88ce Bump deps w/ eslint (#322)
* Bump deps w/ eslint

* theme default
2020-05-24 09:35:43 +02:00
Github Actions 050d1966c6 [CI Skip] 0.54.0-beta.1
skip-checks: true
2020-05-19 10:22:31 +00:00
Jaco Greeff b38301efae Ordering for crypto types (#321) 2020-05-19 12:18:06 +02:00
Github Actions 90aa4bad13 [CI Skip] 0.54.0-beta.0
skip-checks: true
2020-05-15 11:02:52 +00:00
Jaco Greeff b6909b132a Bump deps (#320) 2020-05-15 12:57:38 +02:00
Github Actions 47dede29c3 [CI Skip] 0.53.1
skip-checks: true
2020-05-14 14:51:40 +00:00
Jaco Greeff be5ee1a71b 0.53 (#319) 2020-05-14 16:47:09 +02:00
Github Actions 2b1d612528 [CI Skip] 0.53.0-beta.6
skip-checks: true
2020-05-14 09:55:18 +00:00
Alexander Krupenkin 82315bd349 Added ECDSA crypto type (#313) 2020-05-14 11:50:25 +02:00
Github Actions 0fa2fe3b32 [CI Skip] 0.53.0-beta.5
skip-checks: true
2020-05-14 06:08:42 +00:00
Jaco Greeff a60d8fa005 Bump deps (#318)
* Bump deps

* @polkadot/util bump
2020-05-14 08:04:12 +02:00
Github Actions e5b53991f2 [CI Skip] 0.53.0-beta.4
skip-checks: true
2020-05-12 15:37:19 +00:00
Jake Naviasky 8d39fabad7 Add Edgeware chain prefix to settings. (#317) 2020-05-12 17:31:59 +02:00
Github Actions ee6efc5bf8 [CI Skip] 0.53.0-beta.3
skip-checks: true
2020-05-11 09:47:22 +00:00
Jaco Greeff 435a9b3cd4 Bump deps (#316)
* Bump deps

* Remove unused deps

* Bump berry

* Bump berry
2020-05-11 11:43:05 +02:00
Github Actions e84758440f [CI Skip] 0.53.0-beta.2
skip-checks: true
2020-05-06 09:19:02 +00:00
Jaco Greeff e320d943a6 Bump deps (#315) 2020-05-06 11:14:20 +02:00
Github Actions 9b0de9f9fb [CI Skip] 0.53.0-beta.1
skip-checks: true
2020-04-24 17:54:57 +00:00
Jaco Greeff dd55faec48 Sort who on multisig (#312) 2020-04-24 19:50:09 +02:00
Github Actions c32343671a [CI Skip] 0.53.0-beta.0
skip-checks: true
2020-04-24 16:06:56 +00:00
Jaco Greeff e88351e994 addMultisig for ui-keyring (#311)
* addMultisig for ui-keyring

* Bumps

* Spelling.
2020-04-24 18:02:13 +02:00
Github Actions 2e323be1c3 [CI Skip] 0.52.1
skip-checks: true
2020-04-16 05:46:28 +00:00
Jaco Greeff 8111ce1ce6 0.52 (#310)
* 0.52

* Actual date ;)
2020-04-16 07:42:57 +02:00
Github Actions f946b7d8fe [CI Skip] 0.52.0-beta.32
skip-checks: true
2020-04-12 07:11:28 +00:00
Jaco Greeff 7251b1f763 Cleanup shared, consistency with standards (#309)
* Cleanup shared, consistency with standards

* Re-add item

* Cleanup webpack demos
2020-04-12 09:06:32 +02:00
Github Actions a1aa280cb9 [CI Skip] 0.52.0-beta.31
skip-checks: true
2020-04-12 05:32:53 +00:00
Jaco Greeff a268160ffd isAlternative (#308) 2020-04-12 07:28:16 +02:00
Github Actions 87187649d1 [CI Skip] 0.52.0-beta.30
skip-checks: true
2020-04-07 20:01:23 +00:00
Jaco Greeff b2ba6aa7ae Bumps 2020-04-07 21:56:19 +02:00
Jaco Greeff e95dc3932b Bump common 2020-04-07 21:36:04 +02:00
Github Actions 68579a0b86 [CI Skip] 0.52.0-beta.29
skip-checks: true
2020-04-06 11:01:24 +00:00
Jaco Greeff ae447e52c9 Trigger 2020-04-06 12:56:23 +02:00
Github Actions 1d66e071e9 [CI Skip] 0.52.0-beta.28
skip-checks: true
2020-04-06 10:31:46 +00:00
Jaco Greeff e26f9aedb6 Use bundled node (#307) 2020-04-06 12:27:46 +02:00
Github Actions d83c45cb2f [CI Skip] 0.52.0-beta.27
skip-checks: true
2020-04-06 08:38:43 +00:00
Jaco Greeff b695647acf Remove extension store (#306) 2020-04-06 10:16:07 +02:00
Github Actions 0d179f9d0b [CI Skip] 0.52.0-beta.26
skip-checks: true
2020-04-05 08:01:42 +00:00
Jaco Greeff 6e60311ba7 Bump deps (#305) 2020-04-05 09:57:04 +02:00
Github Actions a6a7ef040f [CI Skip] 0.52.0-beta.25
skip-checks: true
2020-04-04 08:52:06 +00:00
Jaco Greeff e2637b06a0 Bump deps (#304) 2020-04-04 10:47:33 +02:00
Github Actions ec5caf8fe1 [CI Skip] 0.52.0-beta.24
skip-checks: true
2020-04-01 21:01:46 +00:00
Jaco Greeff 7428ef8eb7 Bump dev (#303) 2020-04-01 22:57:30 +02:00
Github Actions d29edf679e [CI Skip] 0.52.0-beta.23
skip-checks: true
2020-04-01 19:29:10 +00:00
Jaco Greeff 175f876101 Bump dev (incl. eslint fixes) (#302)
* Bump dev (incl. eslint fixes)

* Ordering fixes
2020-04-01 21:24:45 +02:00
Github Actions cc4fa53339 [CI Skip] 0.52.0-beta.22
skip-checks: true
2020-04-01 11:23:17 +00:00
Jaco Greeff 371262d056 Bump dev, apply JSX rules (#301) 2020-04-01 13:18:28 +02:00
Github Actions cd5a881f32 [CI Skip] 0.52.0-beta.21
skip-checks: true
2020-03-27 07:57:05 +00:00
Jaco Greeff 95882ea875 Exhaustive hooks (#300) 2020-03-27 08:52:52 +01:00
Github Actions 3edeae30a0 [CI Skip] 0.52.0-beta.20
skip-checks: true
2020-03-26 12:21:29 +00:00
Hanwen Cheng 44f7e6a436 Add qr support for networkSpecs (#299)
* add qr support for networkSpecs

* make lint happy with spaces

* make lint happier

* remove path id in networkspecs type

* Update tsconfig.json
2020-03-26 13:16:47 +01:00
Github Actions 03033b8d7c [CI Skip] 0.52.0-beta.19
skip-checks: true
2020-03-22 18:16:13 +00:00
Jaco Greeff a25f813f6b Bump API (#298) 2020-03-22 19:11:54 +01:00
Github Actions 873ac2a3ee [CI Skip] 0.52.0-beta.18
skip-checks: true
2020-03-21 10:41:38 +00:00
Jaco Greeff ee613b1578 Bump dev (#297) 2020-03-21 11:37:03 +01:00
Github Actions 6f5adca0cc [CI Skip] 0.52.0-beta.17
skip-checks: true
2020-03-21 09:32:10 +00:00
Jaco Greeff 49c4c592f1 Bump deps (#296)
* Bump deps

* @types/jest

* TS 3.8.3
2020-03-21 10:27:57 +01:00
Github Actions b5882bf3a4 [CI Skip] 0.52.0-beta.16
skip-checks: true
2020-03-16 14:36:11 +00:00
Jaco Greeff 5ad56a9520 Add yarn matrix (#295) 2020-03-16 15:31:37 +01:00
Github Actions 0afc9908ed [CI Skip] 0.52.0-beta.15
skip-checks: true
2020-03-16 13:47:13 +00:00
Jaco Greeff 6c55f6ea53 Collapse actions matrix (#294) 2020-03-16 14:42:33 +01:00
Github Actions 1eef52e286 [CI Skip] 0.52.0-beta.14
skip-checks: true
2020-03-15 07:25:14 +00:00
Jaco Greeff c1644287e1 Remove non-working CI cache (#293) 2020-03-15 08:21:31 +01:00
Github Actions 1ceee77b27 [CI Skip] 0.52.0-beta.13
skip-checks: true
2020-03-15 05:15:01 +00:00
Jaco Greeff faea66eed8 rxjs to dependency 2020-03-15 06:10:47 +01:00
Github Actions f211a19eab [CI Skip] 0.52.0-beta.12
skip-checks: true
2020-03-15 05:04:43 +00:00
Jaco Greeff ad9abfb0d8 Missing peerDependencies 2020-03-15 06:00:31 +01:00
Github Actions 204b0b46ef [CI Skip] 0.52.0-beta.11
skip-checks: true
2020-03-14 17:40:52 +00:00
Jaco Greeff 5ddcec777f Missing explicit deps 2020-03-14 18:36:31 +01:00
Github Actions 0055d7573b [CI Skip] 0.52.0-beta.10
skip-checks: true
2020-03-14 17:25:26 +00:00
Jaco Greeff 92998eb817 Add missing peerDependency 2020-03-14 18:21:12 +01:00
Github Actions a11dc52cfe [CI Skip] 0.52.0-beta.9
skip-checks: true
2020-03-14 12:24:57 +00:00
Jaco Greeff b2175a60cd Some additional functional wrappers (#292) 2020-03-14 13:20:39 +01:00
Github Actions 9bba6b0c28 [CI Skip] 0.52.0-beta.8
skip-checks: true
2020-03-14 11:46:18 +00:00
Jaco Greeff 8865d2a2c5 Some functional components (#291)
* Some functional components

* Pass param to useCallback

* Bump berry

* Scan -> functional
2020-03-14 12:41:57 +01:00
Github Actions 067f1a4fa7 [CI Skip] 0.52.0-beta.7
skip-checks: true
2020-03-14 09:05:57 +00:00
Jaco Greeff 15c6b1cef6 Bump deps (#290) 2020-03-14 10:01:47 +01:00
Github Actions f49b5a0389 [CI Skip] 0.52.0-beta.6
skip-checks: true
2020-03-09 07:29:31 +00:00
Keith Ingram 5e86263fe3 fix ff api url issue (#289) 2020-03-09 08:24:45 +01:00
Github Actions 9fce0e2d51 [CI Skip] 0.52.0-beta.5
skip-checks: true
2020-02-29 12:56:01 +00:00
Jaco Greeff 6cbabfbe80 Minify yarn plugins (#288) 2020-02-29 13:50:27 +01:00
Github Actions 32c1ca8abf [CI Skip] 0.52.0-beta.4
skip-checks: true
2020-02-28 13:24:53 +00:00
Jaco Greeff 31e8904f7a Swap to yarn 2 (#287) 2020-02-28 14:19:03 +01:00
Github Actions 1229bedffb [CI Skip] 0.52.0-beta.3
skip-checks: true
2020-02-22 17:21:23 +00:00
Jaco Greeff e69e98182b Control priv access via # (#286) 2020-02-22 18:19:35 +01:00
Github Actions 3b71f10d1e [CI Skip] 0.52.0-beta.2
skip-checks: true
2020-02-19 20:07:15 +00:00
Jaco Greeff 992eed1bfc Centrifuge logo (#285) 2020-02-19 21:05:32 +01:00
Github Actions 873b1c40e8 [CI Skip] 0.52.0-beta.1
skip-checks: true
2020-02-19 17:07:38 +00:00
Jaco Greeff 7e0171bb9f Add Centrifuge logo (#284) 2020-02-19 18:05:22 +01:00
Github Actions 309f652ce6 [CI Skip] 0.52.0-beta.0
skip-checks: true
2020-02-18 16:09:45 +00:00
Jaco Greeff 2ba4444ca4 Internal ss58Format handling (#283) 2020-02-18 17:07:53 +01:00
Github Actions 826de3ddf0 [CI Skip] 0.51.1
skip-checks: true
2020-02-18 09:00:43 +00:00
Jaco Greeff 1e4148f2cf 0.51 (#282) 2020-02-18 09:58:35 +01:00
Github Actions 5827a9702c [CI Skip] 0.51.0-beta.1
skip-checks: true
2020-02-17 20:05:29 +00:00
Jaco Greeff fd11071566 Bump deps (#281) 2020-02-17 21:02:55 +01:00
Github Actions 7b7d467143 [CI Skip] 0.51.0-beta.0
skip-checks: true
2020-02-17 14:09:48 +00:00
Jaco Greeff 170b778dcf Add GH actions yarn cache (#280) 2020-02-17 15:07:46 +01:00
Github Actions bc5be9e382 [CI Skip] 0.50.1
skip-checks: true
2020-02-16 08:20:07 +00:00
Jaco Greeff 6fb91e2e56 0.50 (#279)
* 0.50

* Dep bumps
2020-02-16 09:18:04 +01:00
Github Actions c29613faed [CI Skip] 0.50.0-beta.4
skip-checks: true
2020-02-14 15:31:51 +00:00
Jaco Greeff 7b6ff51186 Bump deps (& @types to dev deps) (#278) 2020-02-14 16:30:08 +01:00
Github Actions 44043a9374 [CI Skip] 0.50.0-beta.3
skip-checks: true
2020-02-14 08:51:34 +00:00
Jaco Greeff e4159028ae Bump dev (#277) 2020-02-14 09:49:29 +01:00
Github Actions b6424bdb15 [CI Skip] 0.50.0-beta.2
skip-checks: true
2020-02-13 15:09:53 +00:00
Jaco Greeff 9e5a2ac7c5 Bump dev (#276)
* Bump dev

* Fix linting
2020-02-13 16:07:21 +01:00
Github Actions 924e69bc7b [CI Skip] 0.50.0-beta.1
skip-checks: true
2020-02-12 16:11:31 +00:00
Jaco Greeff 4f025cb9ec Explicit deps & bumps (#275) 2020-02-12 17:08:52 +01:00
Github Actions 9902c9351d [CI Skip] 0.50.0-beta.0
skip-checks: true
2020-02-10 17:39:21 +00:00
Drew Stone 536a6dd877 Add Edgeware testnet and mainnet updated endpoints (#274) 2020-02-10 18:37:11 +01:00
Github Actions 00e702e24f [CI Skip] 0.49.1
skip-checks: true
2020-02-06 16:00:42 +00:00
Jaco Greeff 7c39f68a1a 0.49 (#273) 2020-02-06 16:58:25 +01:00
Github Actions ba9f571c83 [CI Skip] 0.49.0-beta.3
skip-checks: true
2020-02-06 14:27:45 +00:00
Jaco Greeff d12387f4ae Add a resolver for jest (#272) 2020-02-06 15:25:08 +01:00
Github Actions 4bed02e395 [CI Skip] 0.49.0-beta.2
skip-checks: true
2020-02-05 17:35:37 +00:00
Nikhil Ranjan ee23a50c06 Updated to valid javascript (#271)
; cannot be used with => .
2020-02-05 18:33:19 +01:00
Github Actions 7f383fffc9 [CI Skip] 0.49.0-beta.1
skip-checks: true
2020-02-04 11:37:49 +00:00
Jaco Greeff 42b421be44 Bump deps (#270) 2020-02-04 12:35:32 +01:00
Github Actions 121fe3008a [CI Skip] 0.49.0-beta.0
skip-checks: true
2020-02-03 12:59:24 +00:00
Jaco Greeff 55fd797707 Bump deps (#269) 2020-02-03 13:56:45 +01:00
123 changed files with 24143 additions and 18002 deletions
+1
View File
@@ -0,0 +1 @@
1
+1
View File
@@ -1,3 +1,4 @@
.eslintrc.js
**/build/*
**/coverage/*
**/node_modules/*
+1 -1
View File
@@ -1,4 +1,4 @@
const base = require('@polkadot/dev-react/config/eslint');
const base = require('@polkadot/dev/config/eslint');
module.exports = {
...base,
+6 -61
View File
@@ -2,70 +2,15 @@ name: PR
on: [pull_request]
jobs:
lint:
name: Linting
runs-on: ubuntu-latest
pr:
strategy:
matrix:
node-version: [12.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: lint
run: |
yarn install --frozen-lockfile
yarn lint
test:
name: Testing
step: ['lint', 'test', 'build', 'docs']
name: ${{ matrix.step }}
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: test
- name: ${{ matrix.step }}
run: |
yarn install --frozen-lockfile
yarn test
build_code:
name: Build Code
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: build
run: |
yarn install --frozen-lockfile
yarn build
build_docs:
name: Build Docs
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: build
run: |
yarn install --frozen-lockfile
yarn docs
yarn install --immutable | grep -v 'YN0013'
yarn ${{ matrix.step }}
+10 -42
View File
@@ -5,62 +5,30 @@ on:
- master
jobs:
build_code:
name: Build Code
if: "! contains(github.event.head_commit.message, '[CI Skip]')"
runs-on: ubuntu-latest
master:
strategy:
matrix:
node-version: [12.x]
step: ['build:release', 'docs:release']
name: ${{ matrix.step }}
if: "! startsWith(github.event.head_commit.message, '[CI Skip]') && github.repository == 'polkadot-js/ui'"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
with:
token: ${{ secrets.GH_PAT }}
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: build
- name: ${{ matrix.step }}
env:
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
GH_PAGES_SRC: build-docs
GH_PAT: ${{ secrets.GH_PAT }}
GH_TOKEN: ${{ secrets.GH_PAT }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_RELEASE_GITHUB_API_TOKEN: ${{ secrets.GH_PAT }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
yarn install --frozen-lockfile
yarn polkadot-dev-ghact-build
build_docs:
name: Build Docs
if: "! contains(github.event.head_commit.message, '[CI Skip]')"
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: build
env:
GH_PAT: ${{ secrets.GH_PAT }}
GH_TOKEN: ${{ secrets.GH_PAT }}
GH_PAGES_SRC: build-docs
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
yarn install --frozen-lockfile
yarn polkadot-dev-ghact-docs
yarn install --immutable | grep -v 'YN0013'
yarn ${{ matrix.step }}
dummy:
name: Dummy
if: "contains(github.event.head_commit.message, '[CI Skip]')"
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
steps:
- name: dummy
run: |
+4
View File
@@ -9,6 +9,10 @@ tmp/
.env.test.local
.env.production.local
.npmrc
.yarn/*
!.yarn/releases
!.yarn/plugins
.pnp.*
cc-test-reporter
package-lock.json
npm-debug.log*
+11
View File
@@ -0,0 +1,11 @@
{
"editor.tabSize": 2,
"files.eol": "\n",
"npm.packageManager": "yarn",
"eslint.enable": true,
"eslint.validate": [
"javascript",
"typescript",
"typescriptreact"
]
}
File diff suppressed because one or more lines are too long
Vendored Executable
+56
View File
File diff suppressed because one or more lines are too long
+11
View File
@@ -0,0 +1,11 @@
enableImmutableInstalls: false
enableProgressBars: false
nodeLinker: node-modules
plugins:
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.js
spec: "@yarnpkg/plugin-interactive-tools"
yarnPath: .yarn/releases/yarn-rc.js
+91 -23
View File
@@ -1,17 +1,77 @@
# 0.47.1
# CHANGELOG
## 0.55.1 Jul 2, 2020
- Better error-handling for invalid FileStore accounts (Thanks to https://github.com/yuhui1208)
- Adjust react-qr `Scan*` making `onScan` callbacks required
- Rework the react-qr display to use functional components
- Bump to `@polkadot/api` 1.21.1
- Bump to `@polkadot/util` 2.15.1
## 0.54.1 Jun 16, 2020
- Add genesisHash to signer payload (Thanks to https://github.com/hanwencheng)
- Allow QR scanning to parse mini keys (Thanks to https://github.com/hanwencheng)
- Adjust ordering of available crypto types (native first)
- Rename Substrate prefix entry (42) to "generic"
- Bump to `@polkadot/api` 1.19.1
- Bump to `@polkadot/util` 2.14.1
## 0.53.1 May 14, 2020
- Add Ecdsa to the supported crypto types options (Thanks to https://github.com/akru)
- Add Egedware to network prefix settings (Thanks to https://github.com/jnaviask)
- Add `addMultisig` into keyring (with all options to re-create address)
- Bump to `@polkadot/api` 1.14.1
- Bump to `@polkadot/util` 2.10.1
## 0.52.1 Apr 15, 2020
- **Breaking change** (TypeScript only) The `*.d.ts` files now contain TypeScript 3.8 features, `#private`, which is not usable in older versions
- Allow for the encoding of chain-settings via QR (Thanks to https://github.com/hanwencheng)
- Enhance checks for ws url in settings (Thanks to https://github.com/kwingram25)
- Start of `isAlternative` implementations for identicons to react, react-native & vue (currently only Polkadot sixPoint)
- Bump to `@polkadot/api` 1.10 & `@polkadot/util` 2.8
- Convert `private <field>` to `#<field>`
- Remove internal/duplicated ui-keyring ss58Format mapping, rather set it directly on wrapped keyring
## 0.51.1 Feb 18, 2020
- Support formatting of addresses via createPair base on latest upstream keyring
- Bump to `@polkadot/api` 1.3.1
- Bump to `@polkadot/util` 2.4.1
## 0.50.1 Feb 16, 2020
- ui-settings does not expose pre-configured endpoints by default (only local dev node)
- Bump to `@polkadot/api` 1.2.1
- Bump to `@polkadot/util` 2.3.1
## 0.49.1 Feb 06, 2020
- Add resolver for jest requires (tests from src)
## 0.48.1 Jan 30, 2020
- Add Westend & Kulupulu, remove Alexander
- Update Edgeware wss uri
- Change display name for Kusama
- Mirror QR scanning display
## 0.47.1 Nov 29, 2019
- Support for Kusama CC3 (network endpoints)
- Genesis hashes for accounts can now lookup against a range (so CC2-locked accounts will show on CC3)
- Language options have been removed from settings (these will be app-specific)
- QR display loops now have a timeout decay (slower as it loops)
# 0.46.1
## 0.46.1 Oct 25, 2019
- Add an example for using React Native (thanks to https://github.com/cameronfr)
- Add base documentation for getting started
- Add camera access to the setting structure
# 0.45.1
## 0.45.1 Sep 26, 2019
- Support for Kusama CC2
- **Breaking change** The subscription subject for `ui-keyring` does not return a pre-formatted React object anymore. This is SUI-specific, so had limited use and therefore should not even be split into a `react-keyring` component. Rather users of this functionality should construct their own options for their framework.
@@ -21,12 +81,12 @@
- Adjust `react-identicon` highlights (validators)
- Add `example-{react, vue}` highlighting simple use with `ui-keyring`, `ui-settings` & `*-identicon` components
# 0.44.1
## 0.44.1 Sep 12, 2019
- Update `@polkadot/util` to 1.4.1
- Upddate to Babel 7.6
# 0.43.1
## 0.43.1 Sep 10, 2019
- Add W3F Node for Kusama
- Add extended info to ui-settings, i.e. info on each option
@@ -34,7 +94,7 @@
- ui-keyring now check the genesisHash on all load operations (if supplied)
- react-qr is now operational and integrated in the polkadot-js/extension and apps repos
# 0.42.1
## 0.42.1 Aug 24, 2019
- **Breaking Change** The `@polkadot/ui-identicon` package has been renamed to `@polkadot/react-identicon`
- **Breaking change** For `@polkadot/ui-keyring` the stores are now not exported from the index, imports should be changed to either `ui-keyring/stores` or explicitly to `ui-keyring/stores/Extension`
@@ -44,7 +104,7 @@
- `@polkadot/ui-settings` has UNfrastructure added as an RPC provider for Alex
- `@polkadot/ui-settings` exposes a dropdown with address prefix options
# 0.41.1
## 0.41.1 Jun 14, 2019
- Adapt interface to cater for new `@polkadot/keyring`, where pairs -
- expose `address` getter instead of `address()`
@@ -56,16 +116,16 @@
- Remove previously deprecated kering functions, `createAccount`, `createAccountExternal` & `createAccountMnemonic`
- Remove (previously deprecated), `@polkadot/ui-util`, all these functions have been incorporated in `@polkadot/util`
# 0.40.1
## 0.40.1 Jun 04, 2019
- Address encoding changes, use encoded address instead of supplied
# 0.39.1
## 0.39.1 May 22, 2019
- Allow for externally injected accounts
- @polkadot/util 0.91.1 & @polkadot/api 0.79.1
# 0.38.1
## 0.38.1 May 08, 2019
- Sorting of keyring addresses
- Fix JSON import defaults (previously detection was not working for old accounts)
@@ -73,62 +133,70 @@
- Ensure only a single instance of ui-keyring is loaded
- Adjust short address option display (keyring options)
# 0.37.1
## 0.37.1 Apr 03, 2019
- Add Emberic Elm (Dried Danta discontinued)
- @polkadot/util & @polkadot/api 0.75.1
# 0.36.1
## 0.36.1 Mar 29, 2019
- Small fixes, latest @polkadot/wasm-* packages
# 0.35.1
## 0.35.1 Mar 29, 2019
- @polkadot/util & @polkadot/api 0.75.1
# 0.34.1
## 0.34.1 Mar 28, 2019
- Fix for blake2 in Polkadot identicon generation
# 0.33.1
## 0.33.1 Mar 23, 2019
- Rename createUri and createExternal to addExternal and addUri
- Rename addAccountPair to addPair
- Add additional createFromUri function to create pair, but not add it
- Latest api, util & util-crypto (this with WASM and JS fallbacks)
# 0.32.1
## 0.32.1 Mar 20, 2019
- Add createUri to create an account from a path uri
- Add createExternal as an alias for createAccountExternal
- Deprecate createAccount, createAccountExternal and createAccountMnemonic
- Fix styled-component dependencies when used in a non-@polkadot project
# 0.31.1
## 0.31.1 Mar 18, 2019
- Allow for latest keyring with sr25519 derived support
- When using dev mode, it assumes the substrate node has sr25519 derived keys
# 0.30.1
## 0.30.1 Mar 14, 2019
- Swap to publishing -beta.x on merge (non-breaking testing)
# 0.29.1
## 0.29.1 Mar 13, 2019
Swap to using a dev HDKD keyring (only available on latest substrate master, only affects nodes running with --dev, normal operation unaffected)
# 0.28.1
## 0.28.1 Feb 21, 2019
Default Substrate icon is Jdenticon
# 0.27.1
## 0.27.1 Feb 20, 2019
Replace Charred Cherry with Dried Danta, remove old decimals and token name configs
# 0.26.1
## 0.26.1 Feb 14, 2019
Add keyring support for sd25519 (schnorrkel)
# 0.25.1
## 0.25.1 Jan 09, 2019
Add `@polkadot/{keyring,util,util-crypto,types}` as peerDependencies for the various packages as used. Thie should allow less churn on this repo with version bumps, although it does add some extra effort onto the users of these libraries. (But the assumption is that they use these anyway)
## 0.24.1 Dec 19, 2018
## 0.23.1 Dec 14, 2018
## 0.22.1 Dec 05, 2018
- Split from apps
+5 -2
View File
@@ -1,5 +1,8 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const base = require('@polkadot/dev-react/config/babel');
// Copyright 2017-2020 @polkadot/ui authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
const base = require('@polkadot/dev/config/babel');
module.exports = Object.keys(base).reduce((config, key) => {
config[key] = base[key];
+1 -1
View File
@@ -13,7 +13,7 @@ import { u8aToHex } from '@polkadot/util';
const accounts = keyring.getAccounts();
accounts.forEach(({ address, meta, publicKey }) =>
console.log(address, JSON.stringify(meta), u8aToHex(publicKey));
console.log(address, JSON.stringify(meta), u8aToHex(publicKey))
);
```
+9 -5
View File
@@ -1,12 +1,16 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const config = require('@polkadot/dev-react/config/jest');
// Copyright 2017-2020 @polkadot/ui authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
const config = require('@polkadot/dev/config/jest');
module.exports = Object.assign({}, config, {
moduleNameMapper: {
'@polkadot/react-(identicon|qr)(.*)$': '<rootDir>/packages/react-$1/src/$2',
'@polkadot/reactnative-(identicon)(.*)$': '<rootDir>/packages/reactnative-$1/src/$2',
'@polkadot/ui-(assets|keyring|settings|shared)(.*)$': '<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'
}
'\\.(css|less)$': 'empty/object',
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': 'empty/object'
},
resolver: './jest.resolver.js'
});
+11
View File
@@ -0,0 +1,11 @@
// Copyright 2017-2020 @polkadot/ui authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
const path = require('path');
module.exports = function resolver (file, config) {
return file.includes('package.json')
? path.join(config.basedir.replace('/src', '/'), file)
: config.defaultResolver(file, config);
};
+1 -1
View File
@@ -10,5 +10,5 @@
"packages": [
"packages/*"
],
"version": "0.48.1"
"version": "0.55.1"
}
+27 -20
View File
@@ -1,40 +1,47 @@
{
"version": "0.48.1",
"repository": "https://github.com/polkadot-js/ui",
"author": "Jaco Greeff <jacogr@gmail.com>",
"license": "Apache-2",
"private": true,
"engines": {
"yarn": "^1.10.1"
},
"homepage": ".",
"workspaces": [
"packages/*"
],
"resolutions": {
"babel-core": "^7.0.0-bridge.0",
"typescript": "^3.7.5"
"babel-core": "^7.0.0-bridge.0"
},
"scripts": {
"build": "polkadot-dev-build-ts",
"build:release": "polkadot-ci-ghact-build",
"docs": "polkadot-dev-build-docs",
"lint": "eslint --ext .js,.jsx,.ts,.tsx . && tsc --noEmit --pretty",
"docs:release": "polkadot-ci-ghact-docs",
"lint": "polkadot-dev-run-lint",
"clean": "polkadot-dev-clean-build",
"demo:identicon:react": "yarn build:ts && webpack-serve --config packages/react-identicon/webpack.config.js --content packages/react-identicon --port 8080",
"demo:identicon:vue": "yarn build:ts && webpack-serve --config packages/vue-identicon/webpack.config.js --content packages/vue-identicon --port 8080",
"example:rn:packager": "yarn build:split:code && cd packages/exampleReactNative && yarn copy-workspace-packages && yarn start",
"demo:identicon:react": "yarn build && webpack-serve --config packages/react-identicon/webpack.config.js --content packages/react-identicon --port 8080",
"demo:identicon:vue": "yarn build && webpack-serve --config packages/vue-identicon/webpack.config.js --content packages/vue-identicon --port 8080",
"example:rn:packager": "yarn build && cd packages/exampleReactNative && yarn copy-workspace-packages && yarn start",
"example:rn:ios": "cd packages/exampleReactNative && cd ios && pod install && cd .. && yarn ios",
"example:rn:android": "cd packages/exampleReactNative && yarn android",
"example:react": "yarn build:ts && cd packages/example-react && webpack --config webpack.config.js",
"example:vue": "yarn build:ts && cd packages/example-vue && webpack --config webpack.config.js",
"example:react": "yarn build && cd packages/example-react && webpack --config webpack.config.js",
"example:vue": "yarn build && cd packages/example-vue && webpack --config webpack.config.js",
"postinstall": "polkadot-dev-yarn-only",
"test": "jest --coverage --runInBand",
"test:one": "jest"
"test": "polkadot-dev-run-test --coverage --runInBand",
"test:one": "polkadot-dev-run-test"
},
"devDependencies": {
"@babel/core": "^7.8.3",
"@babel/runtime": "^7.8.3",
"@polkadot/dev-react": "^0.33.3",
"@polkadot/ts": "^0.2.1",
"@babel/core": "^7.10.4",
"@babel/runtime": "^7.10.4",
"@polkadot/dev": "^0.55.18",
"@polkadot/ts": "^0.3.27",
"@types/jest": "^26.0.3",
"babel-plugin-transform-vue-template": "^0.4.2",
"empty": "^0.10.1",
"react-native": "^0.61.4"
}
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-is": "^16.13.1",
"react-native": "^0.62.2",
"vue-template-compiler": "^2.6.11",
"webpack-serve": "^3.2.0"
},
"version": "0.55.1"
}
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/example-react",
"version": "0.48.1",
"version": "0.55.1",
"description": "A very basic example with ui-* & react-* packages",
"main": "index.js",
"author": "Jaco Greeff <jacogr@gmail.com>",
@@ -9,6 +9,6 @@
],
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.8.3"
"@babel/runtime": "^7.10.4"
}
}
+54 -20
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import React, { useEffect, useState } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import ReactDOM from 'react-dom';
import Identicon from '@polkadot/react-identicon';
import keyring from '@polkadot/ui-keyring';
@@ -24,19 +24,27 @@ function App ({ className }: Props): React.ReactElement<Props> | null {
const [phrase, setPhrase] = useState<string | null>(null);
const [ss58Format, setSS58Format] = useState(42);
const _onClickNew = (): void => {
const phrase = mnemonicGenerate(12);
const { address } = keyring.createFromUri(phrase);
const _onClickNew = useCallback(
(): void => {
const phrase = mnemonicGenerate(12);
const { address } = keyring.createFromUri(phrase);
setAddress(keyring.encodeAddress(address, ss58Format));
setPhrase(phrase);
};
const _onChangeSS58Format = ({ currentTarget: { value } }: React.SyntheticEvent<HTMLSelectElement>): void => {
setSS58Format(parseInt(value, 10));
};
setAddress(keyring.encodeAddress(address, ss58Format));
setPhrase(phrase);
},
[ss58Format]
);
const _onChangeSS58Format = useCallback(
({ currentTarget: { value } }: React.SyntheticEvent<HTMLSelectElement>): void => {
setSS58Format(parseInt(value, 10));
},
[]
);
useEffect((): void => {
_onClickNew();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect((): void => {
@@ -54,13 +62,29 @@ function App ({ className }: Props): React.ReactElement<Props> | null {
</section>
<section>
<label>phrase</label>
<textarea cols={40} rows={4} readOnly value={phrase} />
<textarea
cols={40}
readOnly
rows={4}
value={phrase}
/>
</section>
<section>
<label>icons</label>
<Identicon className='icon' value={address} />
<Identicon className='icon' value={address} theme='polkadot' />
<Identicon className='icon' value={address} theme='beachball' />
<Identicon
className='icon'
value={address}
/>
<Identicon
className='icon'
theme='polkadot'
value={address}
/>
<Identicon
className='icon'
theme='beachball'
value={address}
/>
</section>
<section>
<label>address</label>
@@ -68,11 +92,19 @@ function App ({ className }: Props): React.ReactElement<Props> | null {
</section>
<section>
<label>ss58 format</label>
<select onChange={_onChangeSS58Format} value={ss58Format}>
<select
onChange={_onChangeSS58Format}
value={ss58Format}
>
{settings.availablePrefixes
.filter((_, index): boolean => index !== 0)
.map(({ text, value }): React.ReactNode => (
<option key={value} value={value}>{text}</option>
<option
key={value}
value={value}
>
{text}
</option>
))
}
</select>
@@ -81,7 +113,9 @@ function App ({ className }: Props): React.ReactElement<Props> | null {
);
}
cryptoWaitReady().then((): void => {
keyring.loadAll({ ss58Format: 42, type: 'sr25519' });
ReactDOM.render(<App />, rootElement);
});
cryptoWaitReady()
.then((): void => {
keyring.loadAll({ ss58Format: 42, type: 'sr25519' });
ReactDOM.render(<App />, rootElement);
})
.catch(console.error);
+17 -18
View File
@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-var-requires */
// Copyright 2017-2020 @polkadot/example-react authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
@@ -11,26 +10,11 @@ module.exports = {
devtool: 'cheap-eval-source-map',
entry: './src/index.tsx',
mode: 'development',
output: {
chunkFilename: '[name].[chunkhash:8].js',
globalObject: '(typeof self !== \'undefined\' ? self : this)',
filename: '[name].js',
path: path.join(__dirname, 'build')
},
resolve: {
alias: {
'@polkadot/react-identicon': path.resolve(__dirname, '../react-identicon/build'),
'@polkadot/ui-keyring': path.resolve(__dirname, '../ui-keyring/build'),
'@polkadot/ui-settings': path.resolve(__dirname, '../ui-settings/build'),
'@polkadot/ui-shared': path.resolve(__dirname, '../ui-shared/build')
},
extensions: ['.js', '.ts', '.tsx']
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
exclude: /(node_modules)/,
test: /\.(ts|tsx)$/,
use: [
{
loader: 'babel-loader',
@@ -40,14 +24,29 @@ module.exports = {
}
]
},
output: {
chunkFilename: '[name].[chunkhash:8].js',
filename: '[name].js',
globalObject: '(typeof self !== \'undefined\' ? self : this)',
path: path.join(__dirname, 'build')
},
plugins: [
new WebpackPluginServe({
hmr: false, // switch off, Chrome WASM memory leak
liveReload: false, // explict off, overrides hmr
progress: false, // since we have hmr off, disable
port: 8080,
progress: false, // since we have hmr off, disable
static: __dirname
})
],
resolve: {
alias: {
'@polkadot/react-identicon': path.resolve(__dirname, '../react-identicon/build'),
'@polkadot/ui-keyring': path.resolve(__dirname, '../ui-keyring/build'),
'@polkadot/ui-settings': path.resolve(__dirname, '../ui-settings/build'),
'@polkadot/ui-shared': path.resolve(__dirname, '../ui-shared/build')
},
extensions: ['.js', '.ts', '.tsx']
},
watch: true
};
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/example-vue",
"version": "0.48.1",
"version": "0.55.1",
"description": "A very basic example with ui-* & vue-* packages",
"main": "index.js",
"author": "Jaco Greeff <jacogr@gmail.com>",
@@ -9,6 +9,6 @@
],
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.8.3"
"@babel/runtime": "^7.10.4"
}
}
+27 -25
View File
@@ -33,6 +33,25 @@ function generateAccount (ss58Format: Prefix = 42): Account {
}
const Example = Vue.extend({
components: {
Identicon
},
data: function (): Data {
return {
...generateAccount(),
ss58Format: 42,
ss58Options
};
},
methods: {
onClickNew: function (): void {
const { address, phrase } = generateAccount(this.ss58Format);
this.address = address;
this.phrase = phrase;
}
},
name: 'Example',
template: `
<div id="example">
<section>
@@ -62,25 +81,6 @@ const Example = Vue.extend({
</section>
</div>
`,
name: 'Example',
components: {
Identicon
},
data: function (): Data {
return {
...generateAccount(),
ss58Format: 42,
ss58Options
};
},
methods: {
onClickNew: function (): void {
const { address, phrase } = generateAccount(this.ss58Format);
this.address = address;
this.phrase = phrase;
}
},
watch: {
ss58Format: function (): void {
this.address = keyring.encodeAddress(this.address, this.ss58Format);
@@ -88,10 +88,12 @@ const Example = Vue.extend({
}
});
cryptoWaitReady().then((): void => {
keyring.loadAll({ ss58Format: 42, type: 'sr25519' });
cryptoWaitReady()
.then((): void => {
keyring.loadAll({ ss58Format: 42, type: 'sr25519' });
new Vue({
render: (h): VNode => h(Example)
}).$mount('#example');
});
new Vue({
render: (h): VNode => h(Example)
}).$mount('#example');
})
.catch(console.error);
+29 -31
View File
@@ -1,9 +1,7 @@
/* eslint-disable @typescript-eslint/no-var-requires */
// Copyright 2017-2020 @polkadot/example-vue authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
// eslint-disable-next-line @typescript-eslint/no-var-requires
const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const { WebpackPluginServe } = require('webpack-plugin-serve');
@@ -13,12 +11,40 @@ module.exports = {
devtool: 'cheap-eval-source-map',
entry: './src/index.ts',
mode: 'development',
module: {
rules: [
{
exclude: /(node_modules)/,
test: /\.(ts|tsx)$/,
use: [
{
loader: 'babel-loader',
options: require('../../babel.config.js')
}
]
},
{
loader: 'vue-loader',
test: /\.vue$/
}
]
},
output: {
chunkFilename: '[name].[chunkhash:8].js',
globalObject: '(typeof self !== \'undefined\' ? self : this)',
filename: '[name].js',
globalObject: '(typeof self !== \'undefined\' ? self : this)',
path: path.join(__dirname, 'build')
},
plugins: [
new WebpackPluginServe({
hmr: false, // switch off, Chrome WASM memory leak
liveReload: false, // explict off, overrides hmr
port: 8080,
progress: false, // since we have hmr off, disable
static: __dirname
}),
new VueLoaderPlugin()
],
resolve: {
alias: {
'@polkadot/ui-keyring': path.resolve(__dirname, '../ui-keyring/build'),
@@ -28,33 +54,5 @@ module.exports = {
},
extensions: ['.js', '.ts', '.tsx']
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
exclude: /(node_modules)/,
use: [
{
loader: 'babel-loader',
options: require('../../babel.config.js')
}
]
},
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
plugins: [
new WebpackPluginServe({
hmr: false, // switch off, Chrome WASM memory leak
liveReload: false, // explict off, overrides hmr
progress: false, // since we have hmr off, disable
port: 8080,
static: __dirname
}),
new VueLoaderPlugin()
],
watch: true
};
+46 -30
View File
@@ -11,43 +11,48 @@ import settings from '@polkadot/ui-settings';
import { mnemonicGenerate, cryptoWaitReady } from '@polkadot/util-crypto';
const styles = StyleSheet.create({
scrollView: {
backgroundColor: Colors.lighter
},
body: {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
backgroundColor: Colors.white
},
buttonContainer: {
alignItems: 'flex-start',
flex: 1,
flexDirection: 'column'
},
mainTitle: {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
color: Colors.black,
fontSize: 28,
fontWeight: '600'
},
scrollView: {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
backgroundColor: Colors.lighter
},
sectionContainer: {
marginTop: 32,
paddingHorizontal: 24
},
sectionTitle: {
fontSize: 24,
fontWeight: '600',
color: Colors.black
},
mainTitle: {
fontSize: 28,
fontWeight: '600',
color: Colors.black
},
sectionDescription: {
marginTop: 8,
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
color: Colors.dark,
fontSize: 18,
fontWeight: '400',
color: Colors.dark
marginTop: 8
},
buttonContainer: {
flex: 1,
flexDirection: 'column',
alignItems: 'flex-start'
sectionTitle: {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
color: Colors.black,
fontSize: 24,
fontWeight: '600'
}
});
const globalAny = global as unknown as Window;
export default function App (): React.ReactElement<{}> | null {
const [ready, setReady] = useState(false);
export default function App (): React.ReactElement | null {
const [isReady, setReady] = useState(false);
const [address, setAddress] = useState<string | null>(null);
const [phrase, setPhrase] = useState<string | null>(null);
const [ss58Format, setSS58Format] = useState(42);
@@ -65,12 +70,13 @@ export default function App (): React.ReactElement<{}> | null {
};
useEffect((): void => {
ready && _onClickNew();
}, []);
isReady && _onClickNew();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isReady]);
useEffect((): void => {
ready && address && setAddress(keyring.encodeAddress(address, ss58Format));
}, [address, ss58Format]);
isReady && address && setAddress(keyring.encodeAddress(address, ss58Format));
}, [address, isReady, ss58Format]);
const initialize = async (): Promise<void> => {
try {
@@ -78,17 +84,21 @@ export default function App (): React.ReactElement<{}> | null {
} catch (e) {
console.log('Error loading keyring ', e);
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
await globalAny.localStorage.init();
await cryptoWaitReady();
setReady(true);
_onClickNew();
};
if (!ready) {
if (!isReady) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
initialize();
}
if (!ready || !address || !phrase) {
if (!isReady || !address || !phrase) {
return null;
}
@@ -104,11 +114,17 @@ export default function App (): React.ReactElement<{}> | null {
<Text style={styles.mainTitle}>React-Native Example</Text>
</View>
<View style={styles.sectionContainer}>
<Button title='Generate Address' onPress={_onClickNew}></Button>
<Button
onPress={_onClickNew}
title='Generate Address'
/>
</View>
<View style={styles.sectionContainer}>
<Text style={styles.sectionTitle}>Phrase</Text>
<Text selectable={true} style={styles.sectionDescription}>
<Text
selectable={true}
style={styles.sectionDescription}
>
{phrase}
</Text>
</View>
@@ -128,8 +144,8 @@ export default function App (): React.ReactElement<{}> | null {
.map(({ text, value }): React.ReactNode => (
<Button
key={value}
title={text}
onPress={(): void => _onChangeSS58Format(value.toString())}
title={text}
/>
))
}
@@ -1,3 +1,7 @@
// Copyright 2017-2020 @polkadot/example-reactnative authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
module.exports = {
presets: ['module:metro-react-native-babel-preset']
};
+19 -18
View File
@@ -1,31 +1,27 @@
/* eslint-disable @typescript-eslint/no-var-requires */
// Copyright 2017-2020 @polkadot/example-reactnative authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
const path = require('path');
const getWorkspaces = require('get-yarn-workspaces');
const workspaces = getWorkspaces(__dirname).filter(item => {
return path.normalize(item) !== path.normalize(__dirname);
});
let workspacesBuildDirs = workspaces.map(workspace => path.join(workspace, 'build/'));
workspacesBuildDirs = workspacesBuildDirs.filter(item => item !== path.join(__dirname, '../reactnative-identicon/build/'));
const workspaces = getWorkspaces(__dirname).filter((item) =>
path.normalize(item) !== path.normalize(__dirname)
);
let workspacesBuildDirs = workspaces.map((workspace) => path.join(workspace, 'build/'));
workspacesBuildDirs = workspacesBuildDirs.filter((item) => item !== path.join(__dirname, '../reactnative-identicon/build/'));
module.exports = {
// watch other packages as well as root node_modules
watchFolders: [
path.resolve(__dirname, '../../node_modules'),
...workspacesBuildDirs
],
// remap node packages to react-native packages
resolver: {
extraNodeModules: {
crypto: require.resolve('react-native-crypto'),
stream: require.resolve('stream-http'),
vm: require.resolve('vm-browserify'),
os: require.resolve('os-browserify'),
process: require.resolve('process'),
os: require.resolve('os-browserify')
stream: require.resolve('stream-http'),
vm: require.resolve('vm-browserify')
}
},
transformer: {
getTransformOptions: () => ({
transform: {
@@ -33,5 +29,10 @@ module.exports = {
inlineRequires: false
}
})
}
},
// watch other packages as well as root node_modules
watchFolders: [
path.resolve(__dirname, '../../node_modules'),
...workspacesBuildDirs
]
};
+10 -4
View File
@@ -1,7 +1,9 @@
// Copyright 2017-2020 @polkadot/example-react authors & contributors
// Copyright 2017-2020 @polkadot/example-reactnative authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
/* eslint-disable no-global-assign */
import 'fast-text-encoding';
import AsyncStorage from '@react-native-community/async-storage';
@@ -14,26 +16,30 @@ class Storage {
init = async () => {
const keys = await AsyncStorage.getAllKeys();
const data = await AsyncStorage.multiGet(keys);
data.forEach(this.saveItem.bind(this));
this.loading = false;
return [...data];
}
getItem = key => {
getItem = (key) => {
return this.dataMap.get(key);
}
setItem = (key, value) => {
this.dataMap.set(key, value);
return AsyncStorage.setItem(key, value);
}
remove = key => {
remove = (key) => {
this.dataMap.delete(key);
return AsyncStorage.removeItem(key);
}
saveItem = item => {
saveItem = (item) => {
this.dataMap.set(item[0], item[1]);
}
}
+23 -15
View File
@@ -1,6 +1,6 @@
{
"name": "exampleReactNative",
"version": "0.48.1",
"version": "0.55.1",
"private": true,
"workspaces": {
"nohoist": [
@@ -23,28 +23,36 @@
"test": "jest"
},
"dependencies": {
"@polkadot/reactnative-identicon": "^0.48.1",
"@polkadot/ui-keyring": "^0.48.1",
"@polkadot/ui-settings": "^0.48.1",
"@react-native-community/async-storage": "^1.7.1",
"fast-text-encoding": "^1.0.0",
"@polkadot/reactnative-identicon": "0.55.1",
"@polkadot/ui-keyring": "0.55.1",
"@polkadot/ui-settings": "0.55.1",
"@react-native-community/async-storage": "^1.11.0",
"fast-text-encoding": "^1.0.3",
"get-yarn-workspaces": "^1.0.2",
"os-browserify": "^0.3.0",
"process": "^0.11.10",
"react": "16.12.0",
"react-native": "^0.61.4",
"react": "16.13.1",
"react-native": "^0.62.2",
"react-native-crypto": "^2.2.0",
"react-native-randombytes": "^3.5.3",
"stream-http": "^3.1.0"
"stream-http": "^3.1.1"
},
"devDependencies": {
"@babel/core": "^7.8.3",
"@babel/runtime": "^7.8.3",
"@react-native-community/cli-platform-ios": "^3.0.0",
"@babel/core": "^7.10.4",
"@babel/runtime": "^7.10.4",
"@polkadot/keyring": "^2.16.1",
"@polkadot/util": "^2.16.1",
"@polkadot/util-crypto": "^2.16.1",
"@react-native-community/cli-platform-ios": "^4.10.1",
"@types/react-test-renderer": "16.9.2",
"babel-jest": "^25.1.0",
"metro-react-native-babel-preset": "^0.58.0",
"react-test-renderer": "16.12.0"
"babel-jest": "^26.1.0",
"metro-react-native-babel-preset": "^0.60.0",
"react-test-renderer": "16.13.1"
},
"peerDependencies": {
"@polkadot/keyring": "*",
"@polkadot/util": "*",
"@polkadot/util-crypto": "*"
},
"jest": {
"preset": "react-native",
+1 -1
View File
@@ -12,6 +12,6 @@
</head>
<body>
<div id="demo"></div>
<script src="./demo.js"></script>
<script src="./build/Demo.js"></script>
</body>
</html>
+17 -10
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/react-identicon",
"version": "0.48.1",
"version": "0.55.1",
"description": "Renders an SVG picture representing an address",
"main": "index.js",
"author": "Jaco Greeff <jacogr@gmail.com>",
@@ -9,23 +9,30 @@
],
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.8.3",
"@polkadot/ui-settings": "^0.48.1",
"@polkadot/ui-shared": "^0.48.1",
"@types/react-copy-to-clipboard": "^4.3.0",
"@babel/runtime": "^7.10.4",
"@polkadot/ui-settings": "0.55.1",
"@polkadot/ui-shared": "0.55.1",
"color": "^3.1.2",
"jdenticon": "2.2.0",
"react-copy-to-clipboard": "^5.0.2",
"styled-components": "^5.0.0"
"react-copy-to-clipboard": "^5.0.2"
},
"peerDependencies": {
"@polkadot/keyring": "*",
"@polkadot/util": "*",
"@polkadot/util-crypto": "*",
"react": "*"
"react": "*",
"react-dom": "*",
"react-is": "*",
"styled-components": "*"
},
"devDependencies": {
"@polkadot/keyring": "^2.0.1",
"@polkadot/util-crypto": "^2.0.1",
"@polkadot/keyring": "^2.16.1",
"@polkadot/util": "^2.16.1",
"@polkadot/util-crypto": "^2.16.1",
"@types/react-copy-to-clipboard": "^4.3.0",
"@types/react-dom": "^16.9.8",
"@types/styled-components": "^5.1.0",
"styled-components": "^5.1.1",
"xmlserializer": "^0.6.1"
}
}
+22 -7
View File
@@ -20,13 +20,28 @@ export default class Demo extends React.PureComponent {
);
}
return identities.map((value, index): React.ReactNode => (
<IdentityIcon
key={value.toString()}
theme={THEMES[index % THEMES.length] as 'empty'}
value={value}
/>
));
return (
<div>
<div>
{identities.map((value, index): React.ReactNode => (
<IdentityIcon
key={value.toString()}
theme={THEMES[index % THEMES.length] as 'empty'}
value={value}
/>
))}
</div>
<div>
{THEMES.map((theme): React.ReactNode => (
<IdentityIcon
key={theme}
theme={theme as 'empty'}
value='5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'
/>
))}
</div>
</div>
);
}
}
+14 -11
View File
@@ -43,24 +43,20 @@ const Wrapper = styled.div`
position: relative;
}
&:before {
&.highlight:before {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 50%;
box-shadow: 0 0 5px 2px #e0e0e0;
content: '';
}
&.highlight:before {
box-shadow: 0 0 5px 2px #aaa;
content: '';
}
}
`;
export default class IdentityIcon extends React.PureComponent<Props, State> {
class BaseIcon extends React.PureComponent<Props, State> {
public state: State = {
address: '',
publicKey: '0x'
@@ -69,10 +65,10 @@ export default class IdentityIcon extends React.PureComponent<Props, State> {
private static prefix?: Prefix = undefined;
public static setDefaultPrefix (prefix: Prefix): void {
IdentityIcon.prefix = prefix;
BaseIcon.prefix = prefix;
}
public static getDerivedStateFromProps ({ prefix = IdentityIcon.prefix, value }: Props, prevState: State): State | null {
public static getDerivedStateFromProps ({ prefix = BaseIcon.prefix, value }: Props, prevState: State): State | null {
try {
const address = isU8a(value) || isHex(value)
? encodeAddress(value, prefix)
@@ -110,20 +106,21 @@ export default class IdentityIcon extends React.PureComponent<Props, State> {
}
private getWrapped ({ address, publicKey }: State): React.ReactNode {
const { className, isHighlight = false, size = DEFAULT_SIZE, style, theme = settings.icon } = this.props;
const { className = '', isAlternative, isHighlight, size = DEFAULT_SIZE, style, theme = settings.icon } = this.props;
const Component = !address
? Empty
: Components[theme === 'default' ? ICON_DEFAULT_HOST : theme] || Fallback;
return (
<Wrapper
className={`ui--IdentityIcon ${className}`}
className={`ui--IdentityIcon ${className}`}
key={address}
style={style}
>
<Component
address={address}
className={isHighlight ? 'highlight' : ''}
isAlternative={isAlternative}
publicKey={publicKey}
size={size}
/>
@@ -140,3 +137,9 @@ export default class IdentityIcon extends React.PureComponent<Props, State> {
}
}
}
function Identicon (props: Props): React.ReactElement<Props> {
return <BaseIcon {...props} />;
}
export default React.memo(Identicon);
@@ -4,29 +4,26 @@
import { Props } from '../types';
import React from 'react';
import generate from '@polkadot/ui-shared/beachballIcon';
import React, { useCallback } from 'react';
import { beachballIcon } from '@polkadot/ui-shared';
export default class Beachball extends React.PureComponent<Props> {
public render (): React.ReactNode {
const { className, style } = this.props;
return (
<div
className={`container ${className}`}
ref={this.appendIcon}
style={style}
/>
);
}
private appendIcon = (node: Element | null): void => {
const { address, size } = this.props;
if (node) {
node.appendChild(
generate(address, size)
function Beachball ({ address, className = '', size, style }: Props): React.ReactElement<Props> {
const updateElem = useCallback(
(node: HTMLDivElement): void => {
node && node.appendChild(
beachballIcon(address, { isAlternative: false, size })
);
}
}
},
[address, size]
);
return (
<div
className={`container ${className}`}
ref={updateElem}
style={style}
/>
);
}
export default React.memo(Beachball);
+15 -17
View File
@@ -6,21 +6,19 @@ import { Props } from '../types';
import React from 'react';
export default class Empty extends React.PureComponent<Props> {
public render (): React.ReactNode {
const { className, size, style } = this.props;
return (
<div
className={`container ${className}`}
style={style}
>
<svg
height={size}
viewBox='0 0 64 64'
width={size}
/>
</div>
);
}
function Empty ({ className = '', size, style }: Props): React.ReactElement<Props> {
return (
<div
className={`container ${className}`}
style={style}
>
<svg
height={size}
viewBox='0 0 64 64'
width={size}
/>
</div>
);
}
export default React.memo(Empty);
@@ -7,18 +7,16 @@ import { Props } from '../types';
import React from 'react';
import jdenticon from 'jdenticon';
export default class Jdenticon extends React.PureComponent<Props> {
public render (): React.ReactNode {
const { className, publicKey, size, style } = this.props;
return (
<div
className={`container ${className}`}
style={style}
dangerouslySetInnerHTML={ {
__html: jdenticon.toSvg(publicKey.substr(2), size)
} }
/>
);
}
function Jdenticon ({ className = '', publicKey, size, style }: Props): React.ReactElement<Props> {
return (
<div
className={`container ${className}`}
dangerouslySetInnerHTML={{
__html: jdenticon.toSvg(publicKey.substr(2), size)
}}
style={style}
/>
);
}
export default React.memo(Jdenticon);
+32 -37
View File
@@ -1,5 +1,5 @@
// Copyright 2018 Paritytech via paritytech/oo7/polkadot-identicon
// Copyright 2018 @polkadot/react-identicon authors & contributors
// Copyright 2018-2020 @polkadot/react-identicon authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
@@ -16,46 +16,41 @@
// - Move constants to file-level
// - Overall it is now just a static component, expecting an address as an input value
import { Props as BaseProps } from '../types';
import { Circle } from '@polkadot/ui-shared/icons/types';
import { Props } from '../types';
import React from 'react';
import generateIcon, { Circle } from '@polkadot/ui-shared/polkadotIcon';
import { polkadotIcon } from '@polkadot/ui-shared';
interface Props extends BaseProps {
sixPoint?: boolean;
function renderCircle ({ cx, cy, fill, r }: Circle, key: number): React.ReactNode {
return (
<circle
cx={cx}
cy={cy}
fill={fill}
key={key}
r={r}
/>
);
}
export default class Identicon extends React.PureComponent<Props> {
public render (): React.ReactNode {
const { address, className, sixPoint, size, style } = this.props;
return (
<div
className={`container ${className}`}
style={style}
function Identicon ({ address, className = '', isAlternative = false, size, style }: Props): React.ReactElement<Props> {
return (
<div
className={`container ${className}`}
style={style}
>
<svg
height={size}
id={address}
name={address}
viewBox='0 0 64 64'
width={size}
>
<svg
id={address}
name={address}
width={size}
height={size}
viewBox='0 0 64 64'
>
{generateIcon(address, sixPoint).map(this.renderCircle)}
</svg>
</div>
);
}
private renderCircle = ({ cx, cy, r, fill }: Circle, key: number): React.ReactNode => {
return (
<circle
key={key}
cx={cx}
cy={cy}
r={r}
fill={fill}
/>
);
}
{polkadotIcon(address, { isAlternative }).map(renderCircle)}
</svg>
</div>
);
}
export default React.memo(Identicon);
+7 -2
View File
@@ -1,21 +1,26 @@
// Copyright 2018 @polkadot/react-identicon authors & contributors
// Copyright 2018-2020 @polkadot/react-identicon authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Prefix } from '@polkadot/util-crypto/address/types';
import React from 'react';
export interface BaseProps {
className?: string;
style?: Record<string, string | number>;
style?: React.CSSProperties;
}
export interface Props extends BaseProps {
address: string;
isAlternative?: boolean;
className?: string;
publicKey: string;
size: number;
style?: React.CSSProperties;
}
export interface IdentityProps extends BaseProps {
isAlternative?: boolean;
isHighlight?: boolean;
onCopy?: (value: string) => void;
prefix?: Prefix;
+13 -14
View File
@@ -2,7 +2,6 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
// eslint-disable-next-line @typescript-eslint/no-var-requires
const path = require('path');
const ENV = process.env.NODE_ENV || 'development';
@@ -13,27 +12,27 @@ module.exports = {
devtool: isProd ? 'source-map' : 'cheap-eval-source-map',
entry: './src/Demo.tsx',
mode: ENV,
output: {
path: __dirname,
filename: './demo.js'
},
resolve: {
alias: {
'@polkadot/ui-settings': path.resolve(__dirname, '../ui-settings/build'),
'@polkadot/ui-shared': path.resolve(__dirname, '../ui-shared/build')
},
extensions: ['.js', '.jsx', '.ts', '.tsx']
},
module: {
rules: [
{
test: /\.(js|ts|tsx)$/,
exclude: /(node_modules)/,
test: /\.(js|ts|tsx)$/,
use: [
'babel-loader'
]
}
]
},
plugins: []
output: {
filename: './Demo.js',
path: path.join(__dirname, 'build')
},
plugins: [],
resolve: {
alias: {
'@polkadot/ui-settings': path.resolve(__dirname, '../ui-settings/build'),
'@polkadot/ui-shared': path.resolve(__dirname, '../ui-shared/build')
},
extensions: ['.js', '.jsx', '.ts', '.tsx']
}
};
+13 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/react-qr",
"version": "0.48.1",
"version": "0.55.1",
"description": "Generates and reads QR codes",
"main": "index.js",
"author": "Jaco Greeff <jacogr@gmail.com>",
@@ -9,9 +9,19 @@
],
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.8.3",
"@types/react-qr-reader": "^2.1.1",
"@babel/runtime": "^7.10.4",
"qrcode-generator": "^1.4.4",
"react-qr-reader": "^2.2.1"
},
"devDependencies": {
"@types/react-qr-reader": "^2.1.3",
"@types/styled-components": "^5.1.0"
},
"peerDependencies": {
"@polkadot/util": "*",
"@polkadot/util-crypto": "*",
"react": "*",
"react-dom": "*",
"styled-components": "*"
}
}
+85 -86
View File
@@ -2,27 +2,31 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { BaseProps } from './types';
import React from 'react';
import React, { useEffect, useRef, useState } from 'react';
import styled from 'styled-components';
import { xxhashAsHex } from '@polkadot/util-crypto';
import qrcode from './qrcode';
import { createFrames, createImgSize } from './util';
interface Props extends BaseProps {
interface Props {
className?: string;
size?: string | number;
skipEncoding?: boolean;
style?: React.CSSProperties;
value: Uint8Array;
}
interface State {
interface FrameState {
frames: Uint8Array[];
frameIdx: number;
image: string | null;
valueHash: string | null;
}
interface TimerState {
timerDelay: number;
timerId: number | null;
valueHash: string | null;
}
const FRAME_DELAY = 2500;
@@ -40,99 +44,94 @@ function getDataUrl (value: Uint8Array): string {
return qr.createDataURL(16, 0);
}
class Display extends React.PureComponent<Props, State> {
public state: State = {
frames: [],
frameIdx: 0,
image: null,
timerDelay: FRAME_DELAY,
timerId: null,
valueHash: null
};
function Display ({ className, size, skipEncoding, style, value }: Props): React.ReactElement<Props> | null {
const [{ image }, setFrameState] = useState<FrameState>({ frameIdx: 0, frames: [], image: null, valueHash: null });
const [containerStyle, setContainerStyle] = useState(createImgSize(size));
const timerRef = useRef<TimerState>({ timerDelay: FRAME_DELAY, timerId: null });
public static getDerivedStateFromProps ({ value, skipEncoding = false }: Props, prevState: State): Pick<State, never> | null {
const valueHash = xxhashAsHex(value);
// run on initial load to setup the global timer and provide and unsubscribe
useEffect((): () => void => {
const nextFrame = () => setFrameState((state): FrameState => {
// when we have a single frame, we only ever fire once
if (state.frames.length <= 1) {
return state;
}
if (valueHash === prevState.valueHash) {
return null;
}
let frameIdx = state.frameIdx + 1;
const frames: Uint8Array[] = skipEncoding
? [value]
: createFrames(value);
// when we overflow, skip to the first and slightly increase the delay between frames
if (frameIdx === state.frames.length) {
frameIdx = 0;
timerRef.current.timerDelay = timerRef.current.timerDelay + TIMER_INC;
}
// encode on demand
return {
frames,
frameIdx: 0,
image: getDataUrl(frames[0]),
valueHash
timerRef.current.timerId = setTimeout(nextFrame, timerRef.current.timerDelay);
// only encode the frames on demand, not above as part of the
// state derivation - in the case of large payloads, this should
// be slightly more responsive on initial load
return {
...state,
frameIdx,
image: getDataUrl(state.frames[frameIdx])
};
});
timerRef.current.timerId = window.setTimeout(nextFrame, FRAME_DELAY);
return (): void => {
// eslint-disable-next-line react-hooks/exhaustive-deps
timerRef.current.timerId && clearTimeout(timerRef.current.timerId);
};
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
public componentDidMount (): void {
this.setState({
timerId: window.setTimeout(this.nextFrame, FRAME_DELAY)
useEffect((): void => {
setContainerStyle(createImgSize(size));
}, [size]);
useEffect((): void => {
setFrameState((state): FrameState => {
const valueHash = xxhashAsHex(value);
if (valueHash === state.valueHash) {
return state;
}
const frames: Uint8Array[] = skipEncoding
? [value]
: createFrames(value);
// encode on demand
return {
frameIdx: 0,
frames,
image: getDataUrl(frames[0]),
valueHash
};
});
}, [skipEncoding, value]);
if (!image) {
return null;
}
public componentWillUnmount (): void {
const { timerId } = this.state;
if (timerId) {
clearTimeout(timerId);
}
}
public render (): React.ReactNode {
const { className, size, style } = this.props;
const { image } = this.state;
if (!image) {
return null;
}
return (
return (
<div
className={className}
style={containerStyle}
>
<div
className={className}
style={createImgSize(size)}
className='ui--qr-Display'
style={style}
>
<div
className='ui--qr-Display'
style={style}
>
<img src={image} />
</div>
<img src={image} />
</div>
);
}
private nextFrame = (): void => {
const { frames, frameIdx, timerDelay } = this.state;
if (!frames || frames.length <= 1) {
return;
}
const nextIdx = frameIdx === frames.length - 1
? 0
: frameIdx + 1;
const nextDelay = timerDelay + ((nextIdx === 0) ? TIMER_INC : 0);
const timerId = setTimeout(this.nextFrame, nextDelay);
// only encode the frames on demand, not above as part of the
// state derivation - in the case of large payloads, this should
// be slightly more responsive on initial load
this.setState({
frameIdx: nextIdx,
image: getDataUrl(frames[nextIdx]),
timerId,
timerDelay: nextDelay
});
}
</div>
);
}
export default styled(Display as React.ComponentClass<Props>)`
export default React.memo(styled(Display)`
.ui--qr-Display {
height: 100%;
width: 100%;
@@ -146,4 +145,4 @@ export default styled(Display as React.ComponentClass<Props>)`
width: auto !important;
}
}
`;
`);
+23 -41
View File
@@ -2,57 +2,39 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { BaseProps } from './types';
import React from 'react';
import { xxhashAsHex } from '@polkadot/util-crypto';
import React, { useEffect, useState } from 'react';
import { createAddressPayload } from './util';
import QrDisplay from './Display';
interface Props extends BaseProps {
interface Props {
address: string;
genesisHash: string;
className?: string;
size?: string | number;
style?: React.CSSProperties;
}
interface State {
data: Uint8Array | null;
dataHash: string | null;
}
function DisplayExtrinsic ({ address, className, genesisHash, size, style }: Props): React.ReactElement<Props> | null {
const [data, setData] = useState<Uint8Array | null>(null);
export default class DisplayExtrinsic extends React.PureComponent<Props, State> {
public state: State = {
data: null,
dataHash: null
};
useEffect((): void => {
setData(createAddressPayload(address, genesisHash));
}, [address, genesisHash]);
public static getDerivedStateFromProps ({ address, genesisHash }: Props, prevState: State): State | null {
const data = createAddressPayload(address, genesisHash);
const dataHash = xxhashAsHex(data);
if (dataHash === prevState.dataHash) {
return null;
}
return { data, dataHash };
if (!data) {
return null;
}
public render (): React.ReactNode {
const { className, size, style } = this.props;
const { data } = this.state;
if (!data) {
return null;
}
return (
<QrDisplay
className={className}
skipEncoding={true}
size={size}
style={style}
value={data}
/>
);
}
return (
<QrDisplay
className={className}
size={size}
skipEncoding
style={style}
value={data}
/>
);
}
export default React.memo(DisplayExtrinsic);
+23 -40
View File
@@ -2,57 +2,40 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { BaseProps } from './types';
import React from 'react';
import { xxhashAsHex } from '@polkadot/util-crypto';
import React, { useEffect, useState } from 'react';
import { createSignPayload } from './util';
import QrDisplay from './Display';
interface Props extends BaseProps {
interface Props {
address: string;
className?: string;
cmd: number;
genesisHash: Uint8Array | string;
payload: Uint8Array;
size?: string | number;
style?: React.CSSProperties;
}
interface State {
data: Uint8Array | null;
dataHash: string | null;
}
function DisplayPayload ({ address, className, cmd, genesisHash, payload, size, style }: Props): React.ReactElement<Props> | null {
const [data, setData] = useState<Uint8Array | null>(null);
export default class DisplayPayload extends React.PureComponent<Props, State> {
public state: State = {
data: null,
dataHash: null
};
useEffect((): void => {
setData(createSignPayload(address, cmd, payload, genesisHash));
}, [address, cmd, payload, genesisHash]);
public static getDerivedStateFromProps ({ address, cmd, payload }: Props, prevState: State): State | null {
const data = createSignPayload(address, cmd, payload);
const dataHash = xxhashAsHex(data);
if (dataHash === prevState.dataHash) {
return null;
}
return { data, dataHash };
if (!data) {
return null;
}
public render (): React.ReactNode {
const { className, size, style } = this.props;
const { data } = this.state;
if (!data) {
return null;
}
return (
<QrDisplay
className={className}
size={size}
style={style}
value={data}
/>
);
}
return (
<QrDisplay
className={className}
size={size}
style={style}
value={data}
/>
);
}
export default React.memo(DisplayPayload);
+41
View File
@@ -0,0 +1,41 @@
// Copyright 2017-2020 @polkadot/react-qr authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { NetworkSpecsStruct } from '@polkadot/ui-settings';
import React, { useEffect, useState } from 'react';
import QrDisplay from './Display';
import { encodeString } from './util';
interface Props {
className?: string;
networkSpecs: NetworkSpecsStruct;
size?: string | number;
style?: React.CSSProperties;
}
function DisplayNetworkSpecs ({ className, networkSpecs, size, style }: Props): React.ReactElement<Props> | null {
const [data, setData] = useState<Uint8Array | null>(null);
useEffect((): void => {
setData(encodeString(JSON.stringify(networkSpecs)));
}, [networkSpecs]);
if (!data) {
return null;
}
return (
<QrDisplay
className={className}
size={size}
skipEncoding
style={style}
value={data}
/>
);
}
export default React.memo(DisplayNetworkSpecs);
+36 -38
View File
@@ -2,63 +2,61 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { BaseProps } from './types';
import React from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import Reader from 'react-qr-reader';
import styled from 'styled-components';
import { createImgSize } from './util';
interface Props extends BaseProps {
interface Props {
className?: string;
delay?: number;
onError?: (error: Error) => void;
onScan?: (data: string) => void;
onScan: (data: string) => void;
size?: string | number;
style?: React.CSSProperties;
}
const DEFAULT_DELAY = 150;
const DEFAULT_ERROR = (error: Error): void => {
console.error('@polkadot/react-qr:Scan', error.message);
};
class Scan extends React.PureComponent<Props> {
public render (): React.ReactNode {
const { className, delay = DEFAULT_DELAY, size, style } = this.props;
function Scan ({ className, delay = DEFAULT_DELAY, onError = DEFAULT_ERROR, onScan, size, style }: Props): React.ReactElement<Props> {
const [containerStyle, setContainerStyle] = useState(createImgSize(size));
return (
<div
className={className}
style={createImgSize(size)}
>
<Reader
className='ui--qr-Scan'
delay={delay}
onError={this.onError}
onScan={this.onScan}
style={style}
/>
</div>
);
}
useEffect((): void => {
setContainerStyle(createImgSize(size));
}, [size]);
private onError = (error: Error): void => {
const { onError = DEFAULT_ERROR } = this.props;
const _onError = useCallback(
(error: Error) => onError(error),
[onError]
);
onError(error);
}
const _onScan = useCallback(
(data: string | null) => data && onScan(data),
[onScan]
);
private onScan = (data: string | null): void => {
const { onScan } = this.props;
if (!data || !onScan) {
return;
}
onScan(data);
}
return (
<div
className={className}
style={containerStyle}
>
<Reader
className='ui--qr-Scan'
delay={delay}
onError={_onError}
onScan={_onScan}
style={style}
/>
</div>
);
}
export default styled(Scan)`
export default React.memo(styled(Scan)`
.ui--qr-Scan {
display: inline-block;
height: 100%;
@@ -69,4 +67,4 @@ export default styled(Scan)`
margin: 0;
}
}
`;
`);
+42 -37
View File
@@ -2,57 +2,62 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { BaseProps } from './types';
import React from 'react';
import React, { useCallback } from 'react';
import { assert } from '@polkadot/util';
import { ADDRESS_PREFIX } from './constants';
import QrScan from './Scan';
import { decodeAddress } from '@polkadot/util-crypto';
import { ADDRESS_PREFIX, SEED_PREFIX } from './constants';
import QrScan from './Scan';
interface ScanType {
address: string;
isAddress: boolean;
content: string;
genesisHash: string;
name?: string;
}
interface Props extends BaseProps {
interface Props {
className?: string;
onError?: (error: Error) => void;
onScan?: (scanned: ScanType) => void;
onScan: (scanned: ScanType) => void;
size?: string | number;
style?: React.CSSProperties;
}
export default class ScanAddress extends React.PureComponent<Props> {
public render (): React.ReactNode {
const { className, onError, size, style } = this.props;
function ScanAddress ({ className, onError, onScan, size, style }: Props): React.ReactElement<Props> {
const _onScan = useCallback(
(data: string | null): void => {
if (data) {
try {
const [prefix, content, genesisHash, name] = data.split(':');
const isValidPrefix = prefix === ADDRESS_PREFIX || prefix === SEED_PREFIX;
return (
<QrScan
className={className}
onError={onError}
onScan={this.onScan}
size={size}
style={style}
/>
);
}
assert(isValidPrefix, `Invalid prefix received, expected '${ADDRESS_PREFIX}/${SEED_PREFIX}' , found '${prefix}'`);
private onScan = (data: string | null): void => {
const { onScan } = this.props;
const isAddress = prefix === ADDRESS_PREFIX;
if (!data || !onScan) {
return;
}
if (isAddress) {
decodeAddress(content);
}
try {
const [prefix, address, genesisHash, name] = data.split(':');
onScan({ content, genesisHash, isAddress, name });
} catch (error) {
console.error('@polkadot/react-qr:QrScanAddress', (error as Error).message, data);
}
}
},
[onScan]
);
assert(prefix === ADDRESS_PREFIX, `Invalid address received, expected '${ADDRESS_PREFIX}', found '${prefix}'`);
decodeAddress(address);
onScan({ address, genesisHash, name });
} catch (error) {
console.error('@polkadot/react-qr:QrScanAddress', error.message, data);
}
}
return (
<QrScan
className={className}
onError={onError}
onScan={_onScan}
size={size}
style={style}
/>
);
}
export default React.memo(ScanAddress);
+22 -28
View File
@@ -2,9 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { BaseProps } from './types';
import React from 'react';
import React, { useCallback } from 'react';
import QrScan from './Scan';
@@ -12,33 +10,29 @@ interface ScanType {
signature: string;
}
interface Props extends BaseProps {
interface Props {
className?: string;
onError?: (error: Error) => void;
onScan?: (scanned: ScanType) => void;
onScan: (scanned: ScanType) => void;
size?: string | number;
style?: React.CSSProperties;
}
export default class ScanSignature extends React.PureComponent<Props> {
public render (): React.ReactNode {
const { className, onError, size, style } = this.props;
function ScanSignature ({ className, onError, onScan, size, style }: Props): React.ReactElement<Props> {
const _onScan = useCallback(
(signature: string | null) => signature && onScan({ signature: `0x${signature}` }),
[onScan]
);
return (
<QrScan
className={className}
onError={onError}
onScan={this.onScan}
size={size}
style={style}
/>
);
}
private onScan = (signature: string | null): void => {
const { onScan } = this.props;
if (!signature || !onScan) {
return;
}
onScan({ signature: `0x${signature}` });
}
return (
<QrScan
className={className}
onError={onError}
onScan={_onScan}
size={size}
style={style}
/>
);
}
export default React.memo(ScanSignature);
+2
View File
@@ -3,6 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
const ADDRESS_PREFIX = 'substrate';
const SEED_PREFIX = 'secret';
const FRAME_SIZE = 1024;
const SUBSTRATE_ID = new Uint8Array([0x53]);
const CRYPTO_SR25519 = new Uint8Array([0x01]);
@@ -19,5 +20,6 @@ export {
CMD_SIGN_MSG,
CRYPTO_SR25519,
FRAME_SIZE,
SEED_PREFIX,
SUBSTRATE_ID
};
+1
View File
@@ -6,3 +6,4 @@ export { default as QrDisplayAddress } from './DisplayAddress';
export { default as QrDisplayPayload } from './DisplayPayload';
export { default as QrScanAddress } from './ScanAddress';
export { default as QrScanSignature } from './ScanSignature';
export { default as QrNetworkSpecs } from './NetworkSpecs';
+1 -1
View File
@@ -9,7 +9,7 @@ const qrcode: typeof _qrcode = _qrcode;
// HACK The default function take string -> number[], the Uint8array is compatible
// with that signature and the use thereof
// eslint-disable-next-line @typescript-eslint/no-explicit-any
// eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-member-access
(qrcode as any).stringToBytes = (data: Uint8Array): Uint8Array =>
data;
-9
View File
@@ -1,9 +0,0 @@
// Copyright 2017-2020 @polkadot/react-qr authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
export interface BaseProps {
className?: string;
size?: string | number;
style?: Record<string, string | number>;
}
+6 -4
View File
@@ -64,7 +64,7 @@ describe('util', (): void => {
it('encodes a payload properly', (): void => {
expect(
u8aToHex(
createSignPayload('5HbgaJEuVN5qGbkhgtuDQANivSWwHXWsC2erP1SQUXgciTVq', 3, 'THIS IS SPARTA!')
createSignPayload('5HbgaJEuVN5qGbkhgtuDQANivSWwHXWsC2erP1SQUXgciTVq', 3, 'THIS IS SPARTA!', '0xb0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafe')
)
).toEqual(
'0x' + // prefix
@@ -72,7 +72,8 @@ describe('util', (): void => {
'01' + // sr25519
'03' + // sign tx
'f4cd755672a8f9542ca9da4fbf2182e79135d94304002e6a09ffc96fef6e6c4c' + // publickey
'544849532049532053504152544121' // THIS IS SPARTA!
'544849532049532053504152544121' + // THIS IS SPARTA!
'b0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafe' // genesisHash
);
});
});
@@ -81,7 +82,7 @@ describe('util', (): void => {
it('encodes frames properly', (): void => {
expect(
createFrames(
createSignPayload('5HbgaJEuVN5qGbkhgtuDQANivSWwHXWsC2erP1SQUXgciTVq', 0, '0x12345678')
createSignPayload('5HbgaJEuVN5qGbkhgtuDQANivSWwHXWsC2erP1SQUXgciTVq', 0, '0x12345678', '0xb0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafe')
).map((u8a): string => u8aToHex(u8a))
).toEqual([
'0x' +
@@ -90,7 +91,8 @@ describe('util', (): void => {
'0000' + // index
'530100' + // payload info, substrate + sr25519 + signtx
'f4cd755672a8f9542ca9da4fbf2182e79135d94304002e6a09ffc96fef6e6c4c' + // publicKey
'12345678' // data
'12345678' + // data
'b0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafe' // genesisHash
]);
});
});
+3 -2
View File
@@ -33,13 +33,14 @@ export function createAddressPayload (address: string, genesisHash: string): Uin
return encodeString(`${ADDRESS_PREFIX}:${address}:${genesisHash}`);
}
export function createSignPayload (address: string, cmd: number, payload: string | Uint8Array): Uint8Array {
export function createSignPayload (address: string, cmd: number, payload: string | Uint8Array, genesisHash: string | Uint8Array): Uint8Array {
return u8aConcat(
SUBSTRATE_ID,
CRYPTO_SR25519,
new Uint8Array([cmd]),
decodeAddress(address),
u8aToU8a(payload)
u8aToU8a(payload),
u8aToU8a(genesisHash)
);
}
+9 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/reactnative-identicon",
"version": "0.48.1",
"version": "0.55.1",
"description": "Renders an SVG picture representing an address",
"main": "index.js",
"author": "Jaco Greeff <jacogr@gmail.com>",
@@ -9,12 +9,17 @@
],
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.8.3",
"@polkadot/ui-shared": "^0.48.1",
"react-native-svg": "^11.0.1"
"@babel/runtime": "^7.10.4",
"@polkadot/ui-shared": "0.55.1",
"react-native-svg": "^12.1.0"
},
"peerDependencies": {
"@polkadot/util-crypto": "*",
"react": "*",
"react-native": "*"
},
"devDependencies": {
"@polkadot/util-crypto": "^2.16.1",
"@types/react-native": "^0.62.16"
}
}
@@ -19,8 +19,8 @@ export default function Empty ({ size }: Props): React.ReactElement<Props> {
<Circle
cx='32'
cy='32'
r='32'
fill='#eee'
r='32'
/>
</Svg>
</View>
@@ -1,40 +1,37 @@
// Copyright 2018 @polkadot/reactnative-identicon authors & contributors
// Copyright 2018-2020 @polkadot/reactnative-identicon authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Props as BaseProps } from '../types';
import { Circle as CircleType } from '@polkadot/ui-shared/icons/types';
import { Props } from '../types';
import React from 'react';
import { View } from 'react-native';
import Svg, { Circle as SvgCircle } from 'react-native-svg';
import generateIcon, { Circle as CircleType } from '@polkadot/ui-shared/polkadotIcon';
import { polkadotIcon } from '@polkadot/ui-shared';
interface Props extends BaseProps {
sixPoint?: boolean;
}
function renderCircle ({ cx, cy, r, fill }: CircleType, key: number): React.ReactNode {
function renderCircle ({ cx, cy, fill, r }: CircleType, key: number): React.ReactNode {
return (
<SvgCircle
key={key}
cx={cx}
cy={cy}
r={r}
fill={fill}
key={key}
r={r}
/>
);
}
export default function Identicon ({ address, sixPoint, size }: Props): React.ReactElement<Props> {
export default function Identicon ({ address, isAlternative = false, size }: Props): React.ReactElement<Props> {
return (
<View>
<Svg
height={size}
id={address}
width={size}
viewBox='0 0 64 64'
width={size}
>
{generateIcon(address, sixPoint).map(renderCircle)}
{polkadotIcon(address, { isAlternative }).map(renderCircle)}
</Svg>
</View>
);
+2 -1
View File
@@ -1,9 +1,10 @@
// Copyright 2018 @polkadot/reactnative-identicon authors & contributors
// Copyright 2018-2020 @polkadot/reactnative-identicon authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
export interface Props {
address: string;
isAlternative?: boolean;
publicKey: string;
size: number;
}
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/ui-assets",
"version": "0.48.1",
"version": "0.55.1",
"description": "Static assets shared accross projects",
"main": "index.js",
"author": "Jaco Greeff <jacogr@gmail.com>",
@@ -9,6 +9,6 @@
],
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.8.3"
"@babel/runtime": "^7.10.4"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

+17 -18
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/ui-keyring",
"version": "0.48.1",
"version": "0.55.1",
"main": "index.js",
"repository": "https://github.com/polkadot-js/apps.git",
"author": "Jaco Greeff <jacogr@gmail.com>",
@@ -10,36 +10,35 @@
"contributors": [],
"license": "Apache-2.0",
"browser": {
"../package.json": "./package.json",
"./ledger/transportsNode": "./ledger/transportsEmpty"
},
"react-native": {
"../package.json": "./package.json",
"./ledger/transportsNode": "./ledger/transportsEmpty",
"./ledger/transportsWeb": "./ledger/transportsEmpty"
},
"dependencies": {
"@babel/runtime": "^7.8.3",
"@ledgerhq/hw-transport-u2f": "^5.7.0",
"@ledgerhq/hw-transport-webusb": "^5.7.0",
"@types/ledgerhq__hw-transport-node-hid": "^4.21.1",
"@types/ledgerhq__hw-transport-u2f": "^4.21.1",
"@types/mkdirp": "^0.5.2",
"@types/store": "^2.0.2",
"extensionizer": "^1.0.1",
"ledger-polkadot": "^0.7.0",
"mkdirp": "^1.0.3",
"@babel/runtime": "^7.10.4",
"@ledgerhq/hw-transport-webusb": "^5.17.0",
"@zondax/ledger-polkadot": "^0.10.4",
"mkdirp": "^1.0.4",
"rxjs": "^6.6.0",
"store": "^2.0.12"
},
"devDependencies": {
"@polkadot/keyring": "^2.0.1",
"@polkadot/types": "^1.0.1",
"@polkadot/util": "^2.0.1"
"@polkadot/keyring": "^2.16.1",
"@polkadot/types": "^1.23.0-beta.3",
"@polkadot/util": "^2.16.1",
"@types/ledgerhq__hw-transport-node-hid": "^4.22.1",
"@types/ledgerhq__hw-transport-webusb": "^4.70.0",
"@types/mkdirp": "^1.0.1",
"@types/store": "^2.0.2"
},
"optionalDependencies": {
"@ledgerhq/hw-transport-node-hid": "^5.7.0"
"@ledgerhq/hw-transport-node-hid": "^5.18.0"
},
"peerDependencies": {
"@polkadot/keyring": "*"
"@polkadot/keyring": "*",
"@polkadot/ui-settings": "*",
"@polkadot/util": "*"
}
}
+22 -22
View File
@@ -18,42 +18,40 @@ import BrowserStore from './stores/Browser'; // direct import (skip index with a
import { MAX_PASS_LEN } from './defaults';
export default class Base {
private _accounts: AddressSubject;
#accounts: AddressSubject;
private _addresses: AddressSubject;
#addresses: AddressSubject;
private _contracts: AddressSubject;
#contracts: AddressSubject;
private _keyring?: KeyringInstance;
#keyring?: KeyringInstance;
protected _store: KeyringStore;
protected _genesisHash?: string;
protected _store!: KeyringStore;
private _ss58Format?: Prefix;
constructor () {
this._accounts = accounts;
this._addresses = addresses;
this._contracts = contracts;
this._keyring = undefined;
this.#accounts = accounts;
this.#addresses = addresses;
this.#contracts = contracts;
this._store = new BrowserStore();
}
public get accounts (): AddressSubject {
return this._accounts;
return this.#accounts;
}
public get addresses (): AddressSubject {
return this._addresses;
return this.#addresses;
}
public get contracts (): AddressSubject {
return this._contracts;
return this.#contracts;
}
public get keyring (): KeyringInstance {
if (this._keyring) {
return this._keyring;
if (this.#keyring) {
return this.#keyring;
}
throw new Error('Keyring should be initialised via \'loadAll\' before use');
@@ -96,8 +94,10 @@ export default class Base {
return password.length > 0 && password.length <= MAX_PASS_LEN;
}
public setSS58Format (ss58Format: Prefix): void {
this._ss58Format = ss58Format;
public setSS58Format (ss58Format?: Prefix): void {
if (this.#keyring && ss58Format) {
this.#keyring.setSS58Format(ss58Format);
}
}
public setDevMode (isDevelopment: boolean): void {
@@ -105,15 +105,15 @@ export default class Base {
}
protected initKeyring (options: KeyringOptions): void {
const keyring = testKeyring({ ss58Format: this._ss58Format, ...options }, true);
const keyring = testKeyring(options, true);
if (isBoolean(options.isDevelopment)) {
this.setDevMode(options.isDevelopment);
}
this._keyring = keyring;
this.#keyring = keyring;
this._genesisHash = options.genesisHash && options.genesisHash.toHex();
this._store = options.store || new BrowserStore();
this._store = options.store || this._store;
this.addAccountPairs();
}
+23 -14
View File
@@ -7,9 +7,11 @@ import { KeypairType } from '@polkadot/util-crypto/types';
import { AddressSubject, SingleAddress } from './observable/types';
import { CreateResult, KeyringAddress, KeyringAddressType, KeyringItemType, KeyringJson, KeyringJson$Meta, KeyringOptions, KeyringStruct } from './types';
import BN from 'bn.js';
import createPair from '@polkadot/keyring/pair';
import chains from '@polkadot/ui-settings/defaults/chains';
import { hexToU8a, isHex, isString } from '@polkadot/util';
import { bnToBn, hexToU8a, isHex, isString, u8aSorted } from '@polkadot/util';
import { createKeyMulti } from '@polkadot/util-crypto';
import env from './observable/development';
import Base from './Base';
@@ -22,10 +24,10 @@ const RECENT_EXPIRY = 24 * 60 * 60;
// Chain determination occurs outside of Keyring. Loading `keyring.loadAll({ type: 'ed25519' | 'sr25519' })` is triggered
// from the API after the chain is received
export class Keyring extends Base implements KeyringStruct {
private stores = {
#stores = {
account: (): AddressSubject => this.accounts,
address: (): AddressSubject => this.addresses,
contract: (): AddressSubject => this.contracts,
account: (): AddressSubject => this.accounts
contract: (): AddressSubject => this.contracts
};
public addExternal (address: string | Uint8Array, meta: KeyringPair$Meta = {}): CreateResult {
@@ -41,6 +43,15 @@ export class Keyring extends Base implements KeyringStruct {
return this.addExternal(address, { ...meta, hardwareType, isHardware: true });
}
public addMultisig (addresses: (string | Uint8Array)[], threshold: BigInt | BN | number, meta: KeyringPair$Meta = {}): CreateResult {
const address = createKeyMulti(addresses, threshold);
// we could use `sortAddresses`, but rather use internal encode/decode so we are 100%
const who = u8aSorted(addresses.map((who) => this.decodeAddress(who))).map((who) => this.encodeAddress(who));
return this.addExternal(address, { ...meta, isMultisig: true, threshold: bnToBn(threshold).toNumber(), who });
}
public addPair (pair: KeyringPair, password: string): CreateResult {
this.keyring.addPair(pair);
@@ -114,16 +125,16 @@ export class Keyring extends Base implements KeyringStruct {
: this.encodeAddress(_address);
const publicKey = this.decodeAddress(address);
const stores = type
? [this.stores[type]]
: Object.values(this.stores);
? [this.#stores[type]]
: Object.values(this.#stores);
const info = stores.reduce<SingleAddress | undefined>((lastInfo, store): SingleAddress | undefined =>
(store().subject.getValue()[address] || lastInfo), undefined);
return info && {
address,
publicKey,
meta: info.json.meta
meta: info.json.meta,
publicKey
};
}
@@ -177,6 +188,7 @@ export class Keyring extends Base implements KeyringStruct {
if (isRecent && (Date.now() - whenCreated) > RECENT_EXPIRY) {
this._store.remove(key);
return;
}
@@ -263,11 +275,8 @@ export class Keyring extends Base implements KeyringStruct {
public restoreAccount (json: KeyringPair$Json, password: string): KeyringPair {
const type = Array.isArray(json.encoding.content) ? json.encoding.content[1] : 'ed25519';
const pair = createPair(
type,
{
// FIXME Just for the transition period (ignoreChecksum)
publicKey: this.decodeAddress(json.address, true)
},
{ toSS58: this.encodeAddress, type },
{ publicKey: this.decodeAddress(json.address, true) },
json.meta,
hexToU8a(json.encoded)
);
@@ -319,7 +328,7 @@ export class Keyring extends Base implements KeyringStruct {
delete json.meta.isRecent;
this.stores[type]().add(this._store, address, json);
this.#stores[type]().add(this._store, address, json);
return json as KeyringPair$Json;
}
+2 -9
View File
@@ -7,15 +7,8 @@ import { detectPackage } from '@polkadot/util';
import keyring, { Keyring } from './Keyring';
import Ledger from './ledger';
let pkgJson;
try {
pkgJson = require('./package.json');
} catch (error) {
pkgJson = require('../package.json');
}
detectPackage(pkgJson);
// eslint-disable-next-line @typescript-eslint/no-var-requires
detectPackage(require('./package.json'), typeof __dirname !== 'undefined' && __dirname);
export default keyring;
+36 -22
View File
@@ -2,9 +2,10 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import Transport from '@ledgerhq/hw-transport';
import { LedgerAddress, LedgerSignature, LedgerTypes, LedgerVersion } from './types';
import LedgerApp, { ResponseBase } from 'ledger-polkadot';
import { ResponseBase, SubstrateApp, newKusamaApp, newPolkadotApp } from '@zondax/ledger-polkadot';
import { assert, bufferToU8a, u8aToBuffer, u8aToHex } from '@polkadot/util';
import allNode from './transportsNode';
@@ -20,46 +21,59 @@ const SUCCESS_CODE = 0x9000;
const transports = allNode.concat(allWeb);
const APPS: Record<string, (transport: Transport) => SubstrateApp> = {
kusama: newKusamaApp,
polkadot: newPolkadotApp
};
type Chain = keyof typeof APPS;
// A very basic wrapper for a ledger app -
// - it connects automatically, creating an app as required
// - Promises return errors (instead of wrapper errors)
export default class Ledger {
private app: LedgerApp | null = null;
private type: LedgerTypes;
#app: SubstrateApp | null = null;
constructor (type: LedgerTypes) {
assert(['hid', 'u2f', 'webusb'].includes(type), `Unsupported transport ${type}`);
#chain: Chain;
this.type = type;
#transport: LedgerTypes;
constructor (transport: LedgerTypes, chain: Chain) {
// u2f is deprecated
assert(['hid', 'webusb'].includes(transport), `Unsupported transport ${transport}`);
assert(Object.keys(APPS).includes(chain), `Unsupported chain ${chain}`);
this.#chain = chain;
this.#transport = transport;
}
private async getApp (): Promise<LedgerApp> {
if (!this.app) {
const def = transports.find(({ type }): boolean => type === this.type);
private async _getApp (): Promise<SubstrateApp> {
if (!this.#app) {
const def = transports.find(({ type }) => type === this.#transport);
assert(def, `Unable to find a transport for ${this.type}`);
assert(def, `Unable to find a transport for ${this.#transport}`);
const transport = await def.create();
this.app = new LedgerApp(transport);
this.#app = APPS[this.#chain](transport);
}
return this.app;
return this.#app;
}
private async withApp <T> (fn: (app: LedgerApp) => Promise<T>): Promise<T> {
private async _withApp <T> (fn: (app: SubstrateApp) => Promise<T>): Promise<T> {
try {
const app = await this.getApp();
const app = await this._getApp();
return await fn(app);
} catch (error) {
this.app = null;
this.#app = null;
throw error;
}
}
private async wrapError <T extends ResponseBase> (promise: Promise<T>): Promise<T> {
private async _wrapError <T extends ResponseBase> (promise: Promise<T>): Promise<T> {
const result = await promise;
assert(result.return_code === SUCCESS_CODE, result.error_message);
@@ -68,8 +82,8 @@ export default class Ledger {
}
public async getAddress (confirm = false, account = LEDGER_DEFAULT_ACCOUNT, change = LEDGER_DEFAULT_CHANGE, addressIndex = LEDGER_DEFAULT_INDEX): Promise<LedgerAddress> {
return this.withApp(async (app: LedgerApp): Promise<LedgerAddress> => {
const { address, pubKey } = await this.wrapError(app.getAddress(account, change, addressIndex, confirm));
return this._withApp(async (app: SubstrateApp): Promise<LedgerAddress> => {
const { address, pubKey } = await this._wrapError(app.getAddress(account, change, addressIndex, confirm));
return {
address,
@@ -79,8 +93,8 @@ export default class Ledger {
}
public async getVersion (): Promise<LedgerVersion> {
return this.withApp(async (app: LedgerApp): Promise<LedgerVersion> => {
const { device_locked: isLocked, major, minor, patch, test_mode: isTestMode } = await this.wrapError(app.getVersion());
return this._withApp(async (app: SubstrateApp): Promise<LedgerVersion> => {
const { device_locked: isLocked, major, minor, patch, test_mode: isTestMode } = await this._wrapError(app.getVersion());
return {
isLocked,
@@ -91,9 +105,9 @@ export default class Ledger {
}
public async sign (message: Uint8Array, account = LEDGER_DEFAULT_ACCOUNT, change = LEDGER_DEFAULT_CHANGE, addressIndex = LEDGER_DEFAULT_INDEX): Promise<LedgerSignature> {
return this.withApp(async (app: LedgerApp): Promise<LedgerSignature> => {
return this._withApp(async (app: SubstrateApp): Promise<LedgerSignature> => {
const buffer = u8aToBuffer(message);
const { signature } = await this.wrapError(app.sign(account, change, addressIndex, buffer));
const { signature } = await this._wrapError(app.sign(account, change, addressIndex, buffer));
return {
signature: u8aToHex(bufferToU8a(signature))
@@ -1 +0,0 @@
declare module '@ledgerhq/hw-transport-webusb';
@@ -5,15 +5,16 @@
import { TransportDef } from './types';
import Transport from '@ledgerhq/hw-transport';
import LedgerU2F from '@ledgerhq/hw-transport-u2f';
import LedgerWebUSB from '@ledgerhq/hw-transport-webusb';
const transports: TransportDef[] = [
{
create: (): Promise<Transport> =>
LedgerU2F.create(),
type: 'u2f'
},
// deprecated
// import LedgerU2F from '@ledgerhq/hw-transport-u2f';
// {
// create: (): Promise<Transport> =>
// LedgerU2F.create(),
// type: 'u2f'
// },
{
create: (): Promise<Transport> =>
LedgerWebUSB.create(),
+2 -2
View File
@@ -40,8 +40,8 @@ class KeyringOption implements KeyringOptionInstance {
public createOptionHeader (name: string): KeyringSectionOption {
return {
name,
key: `header-${name.toLowerCase()}`,
name,
value: null
};
}
@@ -131,9 +131,9 @@ class KeyringOption implements KeyringOptionInstance {
return {
account: [],
address: [],
contract: [],
all: [],
allPlus: [],
contract: [],
recent: [],
testing: []
};
-2
View File
@@ -5,8 +5,6 @@
import { KeyringItemType, KeyringStruct } from '../types';
export interface KeyringSectionOption {
className?: string;
disabled?: boolean;
key: string | null;
name: string;
value: string | null;
@@ -1,62 +0,0 @@
// Copyright 2019 @polkadot/ui-keyring authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { KeyringStore, KeyringJson } from '../types';
import extension from 'extensionizer';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type StoreValue = Record<string, any>;
const lastError = (type: string): void => {
const error = extension.runtime.lastError;
if (error) {
console.error(`ExtensionStore.${type}:: runtime.lastError:`, error);
}
};
export default class ExtensionStore implements KeyringStore {
public all (cb: (key: string, value: KeyringJson) => void): void {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
extension.storage.local.get(null, (result: StoreValue): void => {
lastError('all');
Object.entries(result).forEach(([key, value]): void => {
cb(key, value);
});
});
}
public get (key: string, cb: (value: KeyringJson) => void): void {
extension.storage.local.get([key], (result: StoreValue): void => {
lastError('get');
cb(result[key]);
});
}
public remove (key: string, cb?: () => void): void {
extension.storage.local.remove(key, (): void => {
lastError('remove');
cb && cb();
});
}
public set (key: string, value: KeyringJson, cb?: () => void): void {
// shortcut, don't save testing accounts in extension storage
if (key.startsWith('account:') && value.meta && value.meta.isTesting) {
cb && cb();
return;
}
extension.storage.local.set({ [key]: value }, (): void => {
lastError('set');
cb && cb();
});
}
}
+24 -11
View File
@@ -7,30 +7,37 @@ import { KeyringStore, KeyringJson } from '../types';
import fs from 'fs';
import mkdirp from 'mkdirp';
import path from 'path';
import { assert } from '@polkadot/util';
// NOTE untested and unused by any known apps, probably broken in various mysterious ways
export default class FileStore implements KeyringStore {
private _path: string;
#path: string;
constructor (path: string) {
if (!fs.existsSync(path)) {
mkdirp.sync(path);
}
this._path = path;
this.#path = path;
}
public all (cb: (key: string, value: KeyringJson) => void): void {
fs
.readdirSync(this._path)
.filter((key): boolean => !['.', '..'].includes(key))
.readdirSync(this.#path)
.filter((key): boolean => !['.', '..', '.DS_Store'].includes(key))
.forEach((key): void => {
cb(key, this._readKey(key));
const value = this._readKey(key);
value?.address && cb(key, value);
});
}
public get (key: string, cb: (value: KeyringJson) => void): void {
cb(this._readKey(key));
const value = this._readKey(key);
assert(value?.address, `Invalid JSON found for ${key}`);
cb(value);
}
public remove (key: string, cb?: () => void): void {
@@ -44,12 +51,18 @@ export default class FileStore implements KeyringStore {
}
private _getPath (key: string): string {
return path.join(this._path, key);
return path.join(this.#path, key);
}
private _readKey (key: string): KeyringJson {
return JSON.parse(
fs.readFileSync(this._getPath(key)).toString('utf-8')
);
private _readKey (key: string): KeyringJson | undefined {
try {
return JSON.parse(
fs.readFileSync(this._getPath(key)).toString('utf-8')
) as KeyringJson;
} catch (error) {
console.error(error);
}
return undefined;
}
}
-1
View File
@@ -3,5 +3,4 @@
// of the Apache-2.0 license. See the LICENSE file for details.
export { default as BrowserStore } from './Browser';
export { default as ExtensionStore } from './Extension';
export { default as FileStore } from './File';
+1 -3
View File
@@ -26,7 +26,6 @@ export interface KeyringOptions extends KeyringOptionsBase {
store?: KeyringStore;
}
// eslint-disable-next-line @typescript-eslint/class-name-casing
export interface KeyringJson$Meta {
contract?: ContractMeta;
genesisHash?: string | null;
@@ -39,8 +38,7 @@ export interface KeyringJson$Meta {
whenCreated?: number;
whenEdited?: number;
whenUsed?: number;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[index: string]: any;
[index: string]: unknown;
}
export interface KeyringJson {
+5 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/ui-settings",
"version": "0.48.1",
"version": "0.55.1",
"description": "Manages app settings",
"main": "index.js",
"author": "Jaco Greeff <jacogr@gmail.com>",
@@ -9,12 +9,13 @@
],
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.8.3",
"@types/store": "^2.0.2",
"@babel/runtime": "^7.10.4",
"eventemitter3": "^4.0.4",
"store": "^2.0.12"
},
"devDependencies": {
"@polkadot/util": "^2.0.1"
"@polkadot/util": "^2.16.1",
"@types/store": "^2.0.2"
},
"peerDependencies": {
"@polkadot/util": "*"
+58 -50
View File
@@ -12,77 +12,85 @@ import { Option, SettingsStruct } from './types';
type ChangeCallback = (settings: SettingsStruct) => void;
type OnTypes = 'change';
function withDefault (options: Option[], option: string | undefined, fallback: string): string {
const _option = option || fallback;
return options.some(({ value }) => value === _option)
? _option
: fallback;
}
export class Settings implements SettingsStruct {
private _apiUrl: string;
readonly #emitter: EventEmitter;
private _camera: string;
#apiUrl: string;
private _emitter: EventEmitter;
#camera: string;
private _i18nLang: string;
#i18nLang: string;
private _icon: string;
#icon: string;
private _ledgerConn: string;
#ledgerConn: string;
private _locking: string;
#locking: string;
private _prefix: number;
#prefix: number;
private _uiMode: string;
#uiMode: string;
private _uiTheme: string;
#uiTheme: string;
constructor () {
const settings = store.get('settings') || {};
const settings = (store.get('settings') as SettingsStruct) || {};
this._emitter = new EventEmitter();
this.#emitter = new EventEmitter();
this._apiUrl = settings.apiUrl || process.env.WS_URL || ENDPOINT_DEFAULT;
this._camera = settings.camera || CAMERA_DEFAULT;
this._ledgerConn = settings.ledgerConn || LEDGER_CONN_DEFAULT;
this._i18nLang = settings.i18nLang || LANGUAGE_DEFAULT;
this._icon = settings.icon || ICON_DEFAULT;
this._locking = settings.locking || LOCKING_DEFAULT;
this._prefix = isUndefined(settings.prefix) ? PREFIX_DEFAULT : settings.prefix;
this._uiMode = settings.uiMode || UIMODE_DEFAULT;
this._uiTheme = settings.uiTheme || UITHEME_DEFAULT;
this.#apiUrl = (typeof settings.apiUrl === 'string' && settings.apiUrl) || process.env.WS_URL || (ENDPOINT_DEFAULT.value as string);
this.#camera = withDefault(CAMERA, settings.camera, CAMERA_DEFAULT);
this.#ledgerConn = withDefault(LEDGER_CONN, settings.ledgerConn, LEDGER_CONN_DEFAULT);
this.#i18nLang = settings.i18nLang || LANGUAGE_DEFAULT;
this.#icon = settings.icon || ICON_DEFAULT;
this.#locking = settings.locking || LOCKING_DEFAULT;
this.#prefix = isUndefined(settings.prefix) ? PREFIX_DEFAULT : settings.prefix;
this.#uiMode = settings.uiMode || UIMODE_DEFAULT;
this.#uiTheme = settings.uiTheme || UITHEME_DEFAULT;
}
public get camera (): string {
return this._camera;
return this.#camera;
}
public get apiUrl (): string {
return this._apiUrl;
return this.#apiUrl;
}
public get i18nLang (): string {
return this._i18nLang;
return this.#i18nLang;
}
public get icon (): string {
return this._icon;
return this.#icon;
}
public get ledgerConn (): string {
return this._ledgerConn;
return this.#ledgerConn;
}
public get locking (): string {
return this._locking;
return this.#locking;
}
public get prefix (): number {
return this._prefix;
return this.#prefix;
}
public get uiMode (): string {
return this._uiMode;
return this.#uiMode;
}
public get uiTheme (): string {
return this._uiTheme;
return this.#uiTheme;
}
public get availableCamera (): Option[] {
@@ -123,37 +131,37 @@ export class Settings implements SettingsStruct {
public get (): SettingsStruct {
return {
apiUrl: this._apiUrl,
camera: this._camera,
i18nLang: this._i18nLang,
icon: this._icon,
ledgerConn: this._ledgerConn,
locking: this._locking,
prefix: this._prefix,
uiMode: this._uiMode,
uiTheme: this._uiTheme
apiUrl: this.#apiUrl,
camera: this.#camera,
i18nLang: this.#i18nLang,
icon: this.#icon,
ledgerConn: this.#ledgerConn,
locking: this.#locking,
prefix: this.#prefix,
uiMode: this.#uiMode,
uiTheme: this.#uiTheme
};
}
public set (settings: Partial<SettingsStruct>): void {
this._apiUrl = settings.apiUrl || this._apiUrl;
this._camera = settings.camera || this._camera;
this._ledgerConn = settings.ledgerConn || this._ledgerConn;
this._i18nLang = settings.i18nLang || this._i18nLang;
this._icon = settings.icon || this._icon;
this._locking = settings.locking || this._locking;
this._prefix = isUndefined(settings.prefix) ? this._prefix : settings.prefix;
this._uiMode = settings.uiMode || this._uiMode;
this._uiTheme = settings.uiTheme || this._uiTheme;
this.#apiUrl = settings.apiUrl || this.#apiUrl;
this.#camera = settings.camera || this.#camera;
this.#ledgerConn = settings.ledgerConn || this.#ledgerConn;
this.#i18nLang = settings.i18nLang || this.#i18nLang;
this.#icon = settings.icon || this.#icon;
this.#locking = settings.locking || this.#locking;
this.#prefix = isUndefined(settings.prefix) ? this.#prefix : settings.prefix;
this.#uiMode = settings.uiMode || this.#uiMode;
this.#uiTheme = settings.uiTheme || this.#uiTheme;
const newValues = this.get();
store.set('settings', newValues);
this._emitter.emit('change', newValues);
this.#emitter.emit('change', newValues);
}
public on (type: OnTypes, cb: ChangeCallback): void {
this._emitter.on(type, cb);
this.#emitter.on(type, cb);
}
}
@@ -9,6 +9,9 @@ const chains: Record<string, ChainDef> = {
'0x3fd7b9eb6a00376e5be61f01abb429ffb0b104be05eaff4d458da48fcd425baf', // Kusama CC1
'0xe3777fa922cafbff200cadeaea1a76bd7898ad5b89f7848999058b50e715f636', // Kusama CC2
'0xb0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafe' // Kusama CC3
],
polkadot: [
'0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3' // Polkadot CC1
]
};
+9 -4
View File
@@ -5,14 +5,19 @@
import { Option } from '../types';
export const CRYPTOS: Option[] = [
{
info: 'sr25519',
text: 'Schnorrkel (sr25519, recommended)',
value: 'sr25519'
},
{
info: 'ed25519',
text: 'Edwards (ed25519)',
text: 'Edwards (ed25519, alternative)',
value: 'ed25519'
},
{
info: 'sr25519',
text: 'Schnorrkel (sr25519)',
value: 'sr25519'
info: 'ecdsa',
text: 'ECDSA (BTC/ETH compatible)',
value: 'ecdsa'
}
];
+4 -126
View File
@@ -4,132 +4,10 @@
import { Option } from '../types';
import { isPolkadot } from './type';
type ChainName = 'alexander' | 'edgeware' | 'edgewareTest' | 'flamingFir' | 'kusama' | 'kulupu' | 'westend';
interface ChainData {
chainDisplay: string;
logo: 'alexander' | 'edgeware' | 'kusama' | 'polkadot' | 'substrate';
type: string;
}
type ProviderName = 'commonwealth' | 'parity' | 'unfrastructure' | 'w3f' | 'kulupu';
interface PoviderData {
providerDisplay: string;
nodes: Partial<Record<ChainName, string>>;
}
// we use this to give an ordering to the chains available
const ORDER_CHAINS: ChainName[] = ['kusama', 'edgeware', 'westend', 'edgewareTest', 'flamingFir', 'kulupu'];
// we use this to order the providers inside the chains
const ORDER_PROVIDERS: ProviderName[] = ['parity', 'w3f', 'unfrastructure', 'commonwealth', 'kulupu'];
// some suplementary info on a per-chain basis
const CHAIN_INFO: Record<ChainName, ChainData> = {
alexander: {
chainDisplay: 'Alexander',
logo: 'alexander',
type: 'Polkadot Testnet'
},
edgeware: {
chainDisplay: 'Edgeware',
logo: 'edgeware',
type: 'Edgeware Mainnet'
},
edgewareTest: {
chainDisplay: 'Edgeware Testnet',
logo: 'edgeware',
type: 'Edgeware Testnet'
},
flamingFir: {
chainDisplay: 'Flaming Fir',
logo: 'substrate',
type: 'Substrate Testnet'
},
kusama: {
chainDisplay: 'Kusama',
logo: 'kusama',
type: 'Polkadot Canary'
},
kulupu: {
chainDisplay: 'Kulupu',
logo: 'substrate',
type: 'Kulupu Mainnet'
},
westend: {
chainDisplay: 'Westend',
logo: 'alexander',
type: 'Polkadot Testnet'
}
};
// the actual providers with all the nodes they provide
const PROVIDERS: Record<ProviderName, PoviderData> = {
commonwealth: {
providerDisplay: 'Commonwealth Labs',
nodes: {
// edgeware: 'wss://mainnet1.edgewa.re',
edgewareTest: 'wss://testnet4.edgewa.re'
}
},
parity: {
providerDisplay: 'Parity',
nodes: {
// alexander: 'wss://poc3-rpc.polkadot.io/',
flamingFir: 'wss://substrate-rpc.parity.io/',
kusama: 'wss://kusama-rpc.polkadot.io/',
westend: 'wss://westend-rpc.polkadot.io'
}
},
unfrastructure: {
providerDisplay: 'Centrality UNfrastructure',
nodes: {
// alexander: 'wss://alex.unfrastructure.io/public/ws'
}
},
w3f: {
providerDisplay: 'Web3 Foundation',
nodes: {
kusama: 'wss://cc3-5.kusama.network/'
}
},
kulupu: {
providerDisplay: 'Kulupu',
nodes: {
kulupu: 'wss://rpc.kulupu.network/ws'
}
}
};
export const ENDPOINT_DEFAULT = isPolkadot
? PROVIDERS.parity.nodes.kusama
: PROVIDERS.parity.nodes.flamingFir;
export const ENDPOINTS: Option[] = ORDER_CHAINS.reduce((endpoints: Option[], chainName): Option[] => {
const { chainDisplay, logo, type } = CHAIN_INFO[chainName];
return ORDER_PROVIDERS.reduce((endpoints: Option[], providerName): Option[] => {
const { providerDisplay, nodes } = PROVIDERS[providerName];
const wssUrl = nodes[chainName];
if (wssUrl) {
endpoints.push({
info: logo,
text: `${chainDisplay} (${type}, hosted by ${providerDisplay})`,
value: wssUrl
});
}
return endpoints;
}, endpoints);
}, []);
// add a local node right at the end
ENDPOINTS.push({
export const ENDPOINTS: Option[] = [{
info: 'local',
text: 'Local Node (Own, 127.0.0.1:9944)',
value: 'ws://127.0.0.1:9944/'
});
}];
export const ENDPOINT_DEFAULT = ENDPOINTS[0];
+6 -5
View File
@@ -12,11 +12,12 @@ export const LEDGER_CONN: Option[] = [
text: 'Do not attach Ledger devices',
value: 'none'
},
{
info: 'u2f',
text: 'Attach Ledger via U2F',
value: 'u2f'
},
// Deprecated
// {
// info: 'u2f',
// text: 'Attach Ledger via U2F',
// value: 'u2f'
// },
{
info: 'webusb',
text: 'Attach Ledger via WebUSB',
+11 -4
View File
@@ -12,19 +12,26 @@ export const PREFIXES: Option[] = [
text: 'Default for the connected node',
value: -1
},
// keep as first (well, after default)
{
info: 'substrate',
text: 'Substrate (development)',
text: 'Substrate (generic)',
value: 42
},
// all in ascending order based on value
{
info: 'polkadot',
text: 'Polkadot (live)',
value: 0
},
{
info: 'kusama',
text: 'Kusama (canary)',
value: 2
},
{
info: 'polkadot',
text: 'Polkadot (live)',
value: 0
info: 'edgeware',
text: 'Edgeware (live)',
value: 7
}
];
+1 -1
View File
@@ -4,7 +4,7 @@
import settings, { Settings } from './Settings';
export { ENDPOINT_DEFAULT, ICON_DEFAULT, ICON_DEFAULT_HOST, LANGUAGE_DEFAULT, LOCKING_DEFAULT, PREFIX_DEFAULT, UIMODE_DEFAULT, UITHEME_DEFAULT } from './defaults';
export { SettingsStruct } from './types';
export { SettingsStruct, NetworkSpecsStruct } from './types';
export default settings;
+9
View File
@@ -20,3 +20,12 @@ export interface SettingsStruct {
uiMode: string;
uiTheme: string;
}
export interface NetworkSpecsStruct {
color: string;
decimals: number;
genesisHash: string;
prefix: number;
title: string;
unit: string;
}
+1 -1
View File
@@ -1,3 +1,3 @@
# @polkadot/ui-shared
Shared logic for various logic, i.e. for identicon generation
Shared logic for various logic. For identicon generation used inside the `@polkadot/{react, reactnative, vue}-identicon` icons.
+7 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/ui-shared",
"version": "0.48.1",
"version": "0.55.1",
"description": "Shared logic that is usable accross all frameworks-specific areas",
"main": "index.js",
"author": "Jaco Greeff <jacogr@gmail.com>",
@@ -9,14 +9,17 @@
],
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.8.3",
"@types/color": "^3.0.1",
"@babel/runtime": "^7.10.4",
"color": "^3.1.2"
},
"peerDependencies": {
"@polkadot/util": "*",
"@polkadot/util-crypto": "*"
},
"devDependencies": {
"@polkadot/util-crypto": "^2.0.1"
"@polkadot/util": "^2.16.1",
"@polkadot/util-crypto": "^2.16.1",
"@types/color": "^3.0.1",
"@types/xmlserializer": "^0.6.0"
}
}
@@ -7,7 +7,7 @@ import container from './container';
describe('container', (): void => {
it('applies default styles', (): void => {
expect(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
// eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-member-access
(container(100).style as any)._values
).toMatchObject({
background: 'white',
@@ -23,7 +23,7 @@ describe('container', (): void => {
it('overrides with supplied styles', (): void => {
expect(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
// eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-member-access
(container(50, 'black', '', { display: 'block' }).style as any)._values
).toMatchObject({
background: 'black',
@@ -18,7 +18,7 @@ function generateIcon (seed: string = encodeAddress(randomAsU8a(32))): void {
}
element.appendChild(
identicon(seed, 100, 'padded')
identicon(seed, { isAlternative: false, size: 100 }, 'padded')
);
console.log(`Icon generated in ${(Date.now() - start)}ms`);
@@ -4,13 +4,13 @@
import xmlserializer from 'xmlserializer';
import identicon from '.';
import generate from '.';
describe('identicon', (): void => {
it('generates a basic [0,..,0] identicon', (): void => {
expect(
xmlserializer.serializeToString(
identicon(new Uint8Array(32))
generate(new Uint8Array(32), { isAlternative: false, size: 256 })
)
).toEqual(
'<div xmlns="http://www.w3.org/1999/xhtml" class="" style="background: white; border-radius: 128px; display: inline-block; height: 256px; margin: 0px; overflow: hidden; padding: 0px; width: 256px;"><div class="" style="background: rgb(20, 20, 20); border-radius: 128px; display: inline-block; height: 256px; margin: 0px; overflow: hidden; padding: 0px; width: 256px;"><svg xmlns="http://www.w3.org/2000/svg" x="0" y="0" width="256" height="256"><circle cx="128" cy="140.8" r="128" fill="hsl(212.10000000000002, 65.6%, 55.5%)"/><circle cx="128" cy="153.6" r="102.4" fill="hsl(9.800000000000011, 90.7%, 57.6%)"/><circle cx="128" cy="166.4" r="76.8" fill="hsl(345, 85.7%, 86.3%)"/><circle cx="128" cy="179.2" r="51.2" fill="hsl(261.9, 100%, 87.3%)"/><circle cx="128" cy="192" r="25.6" fill="hsl(345, 100%, 25.1%)"/></svg></div></div>'
@@ -20,7 +20,7 @@ describe('identicon', (): void => {
it('allows overrides', (): void => {
expect(
xmlserializer.serializeToString(
identicon(new Uint8Array(32), 100, 'testClass', { display: 'block' })
generate(new Uint8Array(32), { isAlternative: false, size: 100 }, 'testClass', { display: 'block' })
)
).toEqual(
'<div xmlns="http://www.w3.org/1999/xhtml" class="testClass" style="background: white; border-radius: 50px; display: block; height: 100px; margin: 0px; overflow: hidden; padding: 0px; width: 100px;"><div class="" style="background: rgb(20, 20, 20); border-radius: 50px; display: inline-block; height: 100px; margin: 0px; overflow: hidden; padding: 0px; width: 100px;"><svg xmlns="http://www.w3.org/2000/svg" x="0" y="0" width="100" height="100"><circle cx="50" cy="55" r="50" fill="hsl(212.10000000000002, 65.6%, 55.5%)"/><circle cx="50" cy="60" r="40" fill="hsl(9.800000000000011, 90.7%, 57.6%)"/><circle cx="50" cy="65" r="30" fill="hsl(345, 85.7%, 86.3%)"/><circle cx="50" cy="70" r="20" fill="hsl(261.9, 100%, 87.3%)"/><circle cx="50" cy="75" r="10" fill="hsl(345, 100%, 25.1%)"/></svg></div></div>'
@@ -3,6 +3,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Options } from '../types';
import colors from './colors';
import newContainer from './container';
import newSeeder from './seeder';
@@ -10,19 +12,19 @@ import newShape from './shape/circle';
import newElement from './svg/element';
import { SHAPE_COUNT } from './defaults';
export default function identicon (seed: string | Uint8Array, diameter = 256, className = '', style?: { [index: string]: string }): HTMLElement {
export default function generate (seed: string | Uint8Array, { size = 256 }: Options, className = '', style?: { [index: string]: string }): HTMLElement {
const seeder = newSeeder(seed);
const colorGen = colors(seeder);
const outer = newContainer(diameter, 'white', className, style);
const container = newContainer(diameter, colorGen());
const svg = newElement(diameter);
const outer = newContainer(size, 'white', className, style);
const container = newContainer(size, colorGen());
const svg = newElement(size);
outer.appendChild(container);
container.appendChild(svg);
for (let count = 0; count < SHAPE_COUNT; count++) {
const fill = colorGen();
const shape = newShape(seeder, fill, diameter, count);
const shape = newShape(seeder, fill, size, count);
svg.appendChild(shape);
}

Some files were not shown because too many files have changed in this diff Show More