Compare commits

..
276 Commits
Author SHA1 Message Date
Github Actions b56e40ea5b [CI Skip] release/stable 3.4.1
skip-checks: true
2020-08-31 07:08:33 +00:00
Jaco Greeff 37d1bcb6eb 3.4 (#674) 2020-08-31 09:00:57 +02:00
Github Actions f2b8c1fb4e [CI Skip] release/beta 3.4.0-beta.3
skip-checks: true
2020-08-28 12:19:52 +00:00
Jaco Greeff 92cc8fc4e3 Add isWasm util (#673) 2020-08-28 14:12:22 +02:00
Github Actions 701bd9335d [CI Skip] release/beta 3.4.0-beta.2
skip-checks: true
2020-08-27 11:26:48 +00:00
Jaco Greeff d176c74715 Bump wasm to 1.4.1 (#672) 2020-08-27 13:19:36 +02:00
Github Actions 0bf7c799f3 [CI Skip] release/beta 3.4.0-beta.1
skip-checks: true
2020-08-26 08:52:16 +00:00
Jaco Greeff 2f7d5cd4e1 Bump deps (#670)
* Bump deps

* Bump crypto

* Bump berry

* Debump markdown plugin

* Explicit add of typedoc plugins

* Bump dev (typedoc exec)

* Bump md
2020-08-26 10:46:33 +02:00
Github Actions c42b517293 [CI Skip] release/beta 3.4.0-beta.0
skip-checks: true
2020-08-25 19:22:10 +00:00
Jaco Greeff e5dd55e419 Allow for WASM-as-available mnemonicToBip39 call (#669) 2020-08-25 21:16:22 +02:00
Github Actions 83fdd11c59 [CI Skip] release/stable 3.3.1
skip-checks: true
2020-08-24 07:11:21 +00:00
Jaco Greeff 08de8ce25a 3.3 (#668) 2020-08-24 09:05:24 +02:00
Github Actions 800bafc00c [CI Skip] release/beta 3.3.0-beta.2
skip-checks: true
2020-08-22 11:38:10 +00:00
Jaco Greeff 3b383b97ca Add addressRaw to keyring interface (#667)
* addressRaw to keyring interface

* Typos

* nobody

* Slice -20 for Ethereum

* addressRaw tests
2020-08-22 13:32:14 +02:00
Github Actions b381c09ecf [CI Skip] release/beta 3.3.0-beta.1
skip-checks: true
2020-08-18 09:45:16 +00:00
Jaco Greeff a53008fd67 Bump deps (#665) 2020-08-18 11:39:52 +02:00
Github Actions 899056c5a2 [CI Skip] release/beta 3.3.0-beta.0
skip-checks: true
2020-08-17 17:59:41 +00:00
Jaco Greeff 8554d47030 Ethereum keypair signing & verification (#664)
* Ethereum keypair signing & verification

* Verify against hashes expanded

* Adjust via flags

* ss58 encoding for 33-byte publicKey

* ecdsa types stores address as raw publicKey

* Adjust for hash lengths

* Adjust expand/compress specs
2020-08-17 19:52:44 +02:00
Github Actions 9808f58540 [CI Skip] release/stable 3.2.1
skip-checks: true
2020-08-17 10:23:06 +00:00
Jaco Greeff 7228100835 3.2 (#663) 2020-08-17 12:17:44 +02:00
Github Actions 08c1b413d2 [CI Skip] release/beta 3.2.0-beta.4
skip-checks: true
2020-08-17 09:34:41 +00:00
Jaco Greeff 27ae11860d Add Ethereum-compatible seed from mnemonic (#662)
* Add Ethereum-compatible seed from mnemonic

* Change encode signature to allow publicKeys

* Make CC happier
2020-08-17 11:28:59 +02:00
Github Actions 9cc984e8ae [CI Skip] release/beta 3.2.0-beta.3
skip-checks: true
2020-08-14 10:48:37 +00:00
Jaco Greeff d352782927 Ethereum keypair support (#661)
* Ethereum keypair support

* keypair support from seed

* Signature verification

* Cleanups

* Cleanup encode (no extra toLower)

* u8aToU8a

* Simulate random failure with range

* Cleanup BN conversions
2020-08-14 12:41:56 +02:00
Jaco Greeff 6e4a5281ed Bump deps (#660) 2020-08-12 17:02:26 +02:00
Github Actions d11f6d9307 [CI Skip] release/beta 3.2.0-beta.2
skip-checks: true
2020-08-11 14:49:56 +00:00
Jaco Greeff 61b57687af Ethereum address utils (#659)
* Ethereum address utils

* export in base
2020-08-11 16:46:01 +02:00
Github Actions 3ab1623a40 [CI Skip] release/beta 3.2.0-beta.1
skip-checks: true
2020-08-11 14:25:08 +00:00
Jaco Greeff f5acd60253 Actually expose base32* functions (#658) 2020-08-11 16:20:39 +02:00
Github Actions c4d368d2b5 [CI Skip] release/beta 3.2.0-beta.0
skip-checks: true
2020-08-11 06:59:01 +00:00
Jaco Greeff e487d0a454 - Allow for hasher to secp256k1 sign/verify functions (#657) 2020-08-11 08:54:52 +02:00
Github Actions 99ffcc52ec [CI Skip] release/stable 3.1.1
skip-checks: true
2020-08-10 04:51:43 +00:00
Jaco Greeff 64510af8d3 3.1 (#655) 2020-08-10 06:47:53 +02:00
Github Actions 52b14db475 [CI Skip] release/beta 3.1.0-beta.8
skip-checks: true
2020-08-09 12:45:13 +00:00
Jaco Greeff c5fe5cd8d4 Bump @polkadot/wasm (#654) 2020-08-09 14:41:40 +02:00
Github Actions bdfc614ad5 [CI Skip] release/beta 3.1.0-beta.7
skip-checks: true
2020-08-09 12:29:56 +00:00
Jaco Greeff 0d03eac307 Add deriveAddress (#653) 2020-08-09 14:26:37 +02:00
Github Actions 6c84edcb9d [CI Skip] release/beta 3.1.0-beta.6
skip-checks: true
2020-08-09 11:31:44 +00:00
Jaco Greeff 9d145e72b8 Base32 encoding/decoding (#652)
* Base32 encoding/decoding

* Attribution

* LOOKUP

* Share base32/58 alphabet validation

* Apply suggestions from code review
2020-08-09 13:27:47 +02:00
Github Actions 4529bc37b5 [CI Skip] release/beta 3.1.0-beta.5
skip-checks: true
2020-08-08 07:07:37 +00:00
Jaco Greeff 038ef42fe5 Bump deps (#651) 2020-08-08 09:03:58 +02:00
Github Actions 1871d36a97 [CI Skip] release/beta 3.1.0-beta.4
skip-checks: true
2020-08-06 12:19:34 +00:00
Jaco Greeff 45c2afae07 Bump berry (#650)
* Bump berry

* Rewrite
2020-08-06 14:15:37 +02:00
Github Actions 51edae2f67 [CI Skip] release/beta 3.1.0-beta.3
skip-checks: true
2020-08-05 14:32:25 +00:00
Jaco Greeff 437314e5ea Bump wasm-crypto (#649)
* Bump wasm-crypto

* Rewrite yarn.lock
2020-08-05 16:28:22 +02:00
Jaco Greeff ce6f9d8bc8 Scrypt via wasm-crypto (#647)
* Scrypt via wasm-crypto

* Bump wasm-crypto
2020-08-05 16:07:38 +02:00
Github Actions 0cf65e1671 [CI Skip] release/beta 3.1.0-beta.2
skip-checks: true
2020-07-31 13:52:39 +00:00
Brad Larson a0251ff650 [FIX] Adjust error message (#646)
I ran into a case where the secret value provided had trailing
whitespace, and when the code ran, it logged that secret value as part
of the stack trace.

This change will make it harder for users to accidentally leak key
material.
2020-07-31 15:48:31 +02:00
Github Actions 9696badcd1 [CI Skip] release/beta 3.1.0-beta.1
skip-checks: true
2020-07-31 08:07:03 +00:00
Jaco Greeff 08817d199d Bump deps (#645) 2020-07-31 10:02:57 +02:00
Github Actions df69a02e6f [CI Skip] release/beta 3.1.0-beta.0
skip-checks: true
2020-07-30 14:02:55 +00:00
Jaco Greeff e845132d89 Bump deps (#644) 2020-07-30 15:58:17 +02:00
Github Actions 21e9b9a033 [CI Skip] release/stable 3.0.1
skip-checks: true
2020-07-27 06:21:35 +00:00
Jaco Greeff db61ea3077 3.0 release (#643) 2020-07-27 08:17:28 +02:00
Github Actions d4a3d2392e [CI Skip] release/beta 3.0.0-beta.4
skip-checks: true
2020-07-27 06:09:08 +00:00
Jaco Greeff 88ecda706d 3.0 (#642)
* 3.0

* Bump dev
2020-07-27 08:05:04 +02:00
Github Actions 184fb1f12e [CI Skip] release/beta 3.0.0-beta.3
skip-checks: true
2020-07-22 15:45:42 +00:00
Reto Trinkler 91340577df Adding 4 as address type of ss58 for Katal Chain (#639) 2020-07-22 17:41:49 +02:00
Github Actions 36729678e2 [CI Skip] release/beta 3.0.0-beta.2
skip-checks: true
2020-07-21 07:06:23 +00:00
Jaco Greeff 1c6b4bfc34 Dev bump 2020-07-21 09:02:25 +02:00
Github Actions bbfd175579 [CI Skip] release/beta 3.0.0-beta.1
skip-checks: true
2020-07-21 06:21:56 +00:00
Jaco Greeff 0a6bd41444 Keyring JSON with kdf (#637)
* Keyring JSON with pbkdf2

* pbkdf2 from wasm

* Encode/decode defaults adjusted

* v2 decoding test

* Recode refreshes defaults

* Use scrypt for kdf

* test conversions

* Fix params

* Cleanup decoding pass

* Swap encoding to base64

* Update for base64 encoding

* 3.0.0
2020-07-21 08:17:46 +02:00
Github Actions ab21274c36 [CI Skip] release/beta 2.19.0-beta.2
skip-checks: true
2020-07-17 12:30:08 +00:00
Jaco Greeff d4e6ad5553 Bump dev 2020-07-17 14:26:11 +02:00
Github Actions 49dbd757df [CI Skip] release/beta 2.19.0-beta.1
skip-checks: true
2020-07-17 12:07:35 +00:00
Jaco Greeff 20e82cc45b Dev bump 2020-07-17 14:03:36 +02:00
Github Actions 6a7fa80c55 [CI Skip] release/beta 2.19.0-beta.0
skip-checks: true
2020-07-17 06:39:13 +00:00
Jaco Greeff 12e34cd3e8 Bump deps (#635) 2020-07-17 08:35:10 +02:00
Github Actions 0a598fdf92 [CI Skip] release/stable 2.18.1
skip-checks: true
2020-07-13 08:51:33 +00:00
Jaco Greeff 659b896ee7 2.18 (#634) 2020-07-13 10:47:53 +02:00
Github Actions 7cda007a30 [CI Skip] release/beta 2.18.0-beta.3
skip-checks: true
2020-07-09 07:19:51 +00:00
Jaco Greeff 2288c4da8a Base64 utils (#632) 2020-07-09 09:16:24 +02:00
Github Actions fbfc21be1c [CI Skip] release/beta 2.18.0-beta.2
skip-checks: true
2020-07-08 13:39:52 +00:00
Jaco Greeff 787beb2aea Add isUtf8 (#631) 2020-07-08 15:35:43 +02:00
Github Actions 6234e16c37 [CI Skip] release/beta 2.18.0-beta.1
skip-checks: true
2020-07-08 11:58:35 +00:00
Jaco Greeff e9cbc0a0d9 Bump deps (#630) 2020-07-08 13:54:57 +02:00
Github Actions 166eeb8852 [CI Skip] release/beta 2.18.0-beta.0
skip-checks: true
2020-07-08 09:18:38 +00:00
Jaco Greeff b321f92161 Add isAscii (#629) 2020-07-08 11:14:55 +02:00
Github Actions cf7d9d9ff5 [CI Skip] release/stable 2.17.1
skip-checks: true
2020-07-06 04:41:13 +00:00
Jaco Greeff fb5b3c1663 2.17 (#628) 2020-07-06 06:37:16 +02:00
Github Actions 46bbc45145 [CI Skip] release/beta 2.17.0-beta.3
skip-checks: true
2020-07-04 08:12:18 +00:00
Jaco Greeff dc8b4a6447 Add encode{Derived, Multi}Address (#627)
* Add encode{Derived, Multi}Address

* Tests for encode*

* CHANGELOG
2020-07-04 10:08:40 +02:00
Github Actions 8ec38eca4a [CI Skip] release/beta 2.17.0-beta.2
skip-checks: true
2020-07-02 05:36:03 +00:00
Jaco Greeff 24b533689c Handle 0 on numberToU8a (#626)
* Handle 0 on numberToU8a

* Remove old test (replaced)

* base58 CHANGELOG
2020-07-02 07:32:25 +02:00
Github Actions 5421e06fc9 [CI Skip] release/beta 2.17.0-beta.1
skip-checks: true
2020-07-02 05:29:40 +00:00
Jaco Greeff 7115efd94f Simplify base58 dependency tree (#624) 2020-07-02 07:26:04 +02:00
Github Actions 92f88222c4 [CI Skip] release/beta 2.17.0-beta.0
skip-checks: true
2020-07-02 05:12:02 +00:00
Jaco Greeff bc7aba71a6 Bump deps (#625) 2020-07-02 07:08:40 +02:00
Github Actions 1d8b8b3204 [CI Skip] release/stable 2.16.1
skip-checks: true
2020-06-29 05:19:13 +00:00
Jaco Greeff 4a2e090ef8 2.16 (#623) 2020-06-29 07:15:21 +02:00
Github Actions 8cf8d5b7e8 [CI Skip] release/beta 2.16.0-beta.0
skip-checks: true
2020-06-26 12:49:47 +00:00
Jaco Greeff 8d355ff6fc Local base58 alphabet check for better errors (#622)
* Local base58 alphabet check for better errors

* Rewrite yarn.lock

* Align error return values

* Split base58{Encode, Decode}

* base58Encode input types

* Function names, some docs
2020-06-26 14:46:19 +02:00
Github Actions 72456bb2bd [CI Skip] release/stable 2.15.1
skip-checks: true
2020-06-22 09:33:14 +00:00
Jaco Greeff 87f3fd2827 2.15 (#621) 2020-06-22 11:29:33 +02:00
Github Actions 7254aab68d [CI Skip] release/beta 2.15.0-beta.0
skip-checks: true
2020-06-19 15:39:36 +00:00
Jaco Greeff 95d7160ad0 Test for 0 prefix (#620)
* Test for 0 prefix

* Add test for keyring encodeAddress (& fix)

* Test other branch of ?: check
2020-06-19 17:35:48 +02:00
Github Actions 611b1be481 [CI Skip] release/stable 2.14.1
skip-checks: true
2020-06-16 06:02:06 +00:00
Jaco Greeff 73b35fc188 2.14 (#618) 2020-06-16 07:58:33 +02:00
Github Actions 6c30d5b9fd [CI Skip] release/beta 2.14.0-beta.0
skip-checks: true
2020-06-08 15:58:49 +00:00
Keith Ingram 56d151fe66 Add BN consts and timeToString (#610)
* Add BN consts and timeToString

* docs

* lint

* fixes

* lint

* lint

* add tests, ms

* fix

* test
2020-06-09 03:55:21 +12:00
Github Actions cd20fe6c8b [CI Skip] release/stable 2.13.1
skip-checks: true
2020-06-08 14:03:31 +00:00
Jaco Greeff 28f8ca73aa 2.13 (#616) 2020-06-08 15:59:47 +02:00
Github Actions f4a8bfc0c0 [CI Skip] release/beta 2.13.0-beta.5
skip-checks: true
2020-06-08 12:33:10 +00:00
Jaco Greeff 94b058d6a3 Align bnToHex signature with bnToU8a (#615) 2020-06-08 14:29:40 +02:00
Github Actions 3d7ddb85a2 [CI Skip] release/beta 2.13.0-beta.4
skip-checks: true
2020-06-08 11:35:08 +00:00
Jaco Greeff f7a2bb895f Fix blake2 U8a JS with hex inputs (#614)
* Fix blake2 U8a JS with hex inputs

* Apply suggestions from code review
2020-06-08 13:31:10 +02:00
Github Actions c1bfcc00b6 [CI Skip] release/beta 2.13.0-beta.3
skip-checks: true
2020-06-06 08:08:42 +00:00
Jaco Greeff b16d8e7c26 Bump deps (#612) 2020-06-06 10:05:02 +02:00
Github Actions 2a4b363fcd [CI Skip] release/beta 2.13.0-beta.2
skip-checks: true
2020-06-05 20:17:13 +00:00
Jaco Greeff de689b8e6f Bump deps (#611) 2020-06-05 22:13:55 +02:00
Github Actions 2e72ab920b [CI Skip] release/beta 2.13.0-beta.1
skip-checks: true
2020-06-02 09:44:29 +00:00
Jaco Greeff 565e6baecd Linting 2020-06-02 11:40:25 +02:00
Jaco Greeff 1e15203b6c Reset to beta 2020-06-02 11:24:23 +02:00
Github Actions cc8639565d [CI Skip] release/stable 2.12.2
skip-checks: true
2020-06-02 08:31:51 +00:00
Jaco Greeff b77d2e6860 Linting 2020-06-02 10:28:25 +02:00
Jaco Greeff e1fbd8ff9f 2.12.2 2020-06-02 10:22:30 +02:00
Github Actions f56dd32b4a [CI Skip] release/stable 2.12.1
skip-checks: true
2020-06-01 16:09:53 +00:00
Jaco Greeff 6077bef570 2.12 (#609) 2020-06-01 18:05:55 +02:00
Github Actions 377d83d4ed [CI Skip] release/beta 2.12.0-beta.2
skip-checks: true
2020-06-01 08:31:12 +00:00
Jaco Greeff bdb14f91a8 Pre-checks on verify input lengths (#608)
* Pre-checks on verify input lengths

* Small cleanup

* Update error signatures
2020-06-01 10:27:08 +02:00
Github Actions cc5b7ed0ad [CI Skip] release/beta 2.12.0-beta.1
skip-checks: true
2020-06-01 07:33:27 +00:00
Jaco Greeff d4491aeb7f Small cleanups, u8aConcat optimization (#607)
* Small cleanups, u8aConcat oprimizations

* Cleanup

* Pre-allocate arrays

* Don't recreate PREFIX
2020-06-01 09:29:44 +02:00
Github Actions 0f6e996799 [CI Skip] release/beta 2.12.0-beta.0
skip-checks: true
2020-05-31 12:22:47 +00:00
Jaco Greeff 1f3dd60a8d {address,u8a}Eq functions (#606)
* {addres,u8a}Eq functions

* Remove mnemonicToSeed
2020-05-31 14:19:10 +02:00
Github Actions 3351fb1cba [CI Skip] 2.11.1
skip-checks: true
2020-05-26 07:00:59 +00:00
Jaco Greeff 32d176e424 2.11 (#604) 2020-05-26 08:57:31 +02:00
Github Actions aec1e26cb9 [CI Skip] 2.11.0-beta.2
skip-checks: true
2020-05-24 17:08:04 +00:00
Jaco Greeff 7d529b6c93 Type adjustments for meta 2020-05-24 19:04:15 +02:00
Github Actions e22b39ae01 [CI Skip] 2.11.0-beta.1
skip-checks: true
2020-05-23 12:26:33 +00:00
Jaco Greeff 18a202c460 Bump dev w/ eslint (#603)
* Bump dev w/ eslint

* Mop-up remaining lint issues

* Update stringShorten expectation
2020-05-23 14:23:13 +02:00
Github Actions fd9ce319a5 [CI Skip] 2.11.0-beta.0
skip-checks: true
2020-05-15 10:37:46 +00:00
Jaco Greeff a04c0a5e82 Bump deps (#601) 2020-05-15 12:34:22 +02:00
Github Actions 06cb5e57a0 [CI Skip] 2.10.1
skip-checks: true
2020-05-14 05:42:04 +00:00
Jaco Greeff 103ea045bf 2.10 (#599) 2020-05-14 07:38:43 +02:00
Github Actions 4315c76814 [CI Skip] 2.10.0-beta.5
skip-checks: true
2020-05-11 12:01:35 +00:00
Jaco Greeff 6de6b871cd Adjust DeriveJunction (types & BigInt) (#598) 2020-05-11 13:57:59 +02:00
Github Actions 82e5d76821 [CI Skip] 2.10.0-beta.4
skip-checks: true
2020-05-11 09:58:13 +00:00
Jaco Greeff d9a18a4acf Bump berry (#597) 2020-05-11 11:54:45 +02:00
Github Actions 2d1d4f808e [CI Skip] 2.10.0-beta.3
skip-checks: true
2020-05-11 08:00:19 +00:00
Jaco Greeff d1de30907f TextEncoder allows non-Uint8Array Buffers (#596)
* TextEncoder allows non-Uint8Array Buffers

* Add eslintrc to eslintignore
2020-05-11 09:57:00 +02:00
Github Actions d3583dc432 [CI Skip] 2.10.0-beta.2
skip-checks: true
2020-05-08 18:15:33 +00:00
Wei Tang bb04fa28f7 ss58: add Kulupu prefix to the list (#595) 2020-05-08 20:12:17 +02:00
Github Actions bd8e862b62 [CI Skip] 2.10.0-beta.1
skip-checks: true
2020-04-30 06:06:24 +00:00
Jaco Greeff 0f45b7fbf3 Bump deps (#594) 2020-04-30 08:03:20 +02:00
Github Actions 03eb72f128 [CI Skip] 2.10.0-beta.0
skip-checks: true
2020-04-30 05:31:32 +00:00
Jaco Greeff f76a4a98be beta bump (#593) 2020-04-30 07:28:35 +02:00
Github Actions c2b91ad8c2 [CI Skip] 2.9.1
skip-checks: true
2020-04-29 22:42:23 +00:00
Jaco Greeff ffc6b0323b 2.9.1 2020-04-30 00:38:59 +02:00
Github Actions b666db2721 [CI Skip] 2.9.0-beta.4
skip-checks: true
2020-04-29 22:37:08 +00:00
Jaco Greeff b00d49564f Update CHANGELOG.md 2020-04-30 00:34:31 +02:00
Alexander Krupenkin 34380caf1f Added ECDSA keypair support (#589)
* Added ECDSA signature verification

* Add ECDSA keypair, sign, key derivation, fromSeed and tests

* keyring: added ECDSA keypair

* Fix lint errors
2020-04-30 00:33:10 +02:00
Github Actions 277cc2b5a8 [CI Skip] 2.9.0-beta.3
skip-checks: true
2020-04-26 20:26:19 +00:00
joe petrowski 733e9e2729 Add example for multisig address creation (#590)
* add multisig example

* typo

* lint fix

* sort addresses

* make linter happy

* clean up sorting with ss58 param
2020-04-26 22:23:15 +02:00
Github Actions 482264c615 [CI Skip] 2.9.0-beta.2
skip-checks: true
2020-04-26 12:36:41 +00:00
Jaco Greeff 5d0abef952 Sort with ss58 prefix (#591) 2020-04-26 14:33:45 +02:00
Github Actions 2397e1c5d7 [CI Skip] 2.9.0-beta.1
skip-checks: true
2020-04-24 17:18:36 +00:00
Jaco Greeff 62ebe257a6 u8aSorted & sortAddresses (#588) 2020-04-24 19:15:43 +02:00
Github Actions a2844a449c [CI Skip] 2.9.0-beta.0
skip-checks: true
2020-04-24 13:38:04 +00:00
Jaco Greeff 60a9866abe Create createKeyMulti & createKeySub for utility (util-crypto) (#587)
* Create keyMulti & keysub for utility

* Bumps
2020-04-24 15:34:47 +02:00
Github Actions b196158125 [CI Skip] 2.8.1
skip-checks: true
2020-04-09 13:12:53 +00:00
Jaco Greeff 6b1caacfb9 2.8 (#586)
* 2.8

* Typos
2020-04-09 15:10:23 +02:00
Github Actions a7679fb07c [CI Skip] 2.8.0-beta.7
skip-checks: true
2020-04-07 19:51:29 +00:00
Jaco Greeff c4acca6c7c eslint update 2020-04-07 21:48:07 +02:00
Github Actions 5012792693 [CI Skip] 2.8.0-beta.6
skip-checks: true
2020-04-07 19:26:31 +00:00
Jaco Greeff d40d6c65f7 isDevelopment regex 2020-04-07 21:23:20 +02:00
Github Actions 2c0d8e4b59 [CI Skip] 2.8.0-beta.5
skip-checks: true
2020-04-06 10:25:18 +00:00
Jaco Greeff d3d8caa0df Use bundled node (#585) 2020-04-06 12:22:31 +02:00
Github Actions a8f8525c9d [CI Skip] 2.8.0-beta.4
skip-checks: true
2020-04-05 07:55:56 +00:00
Jaco Greeff caa5a8b9e6 Bump deps (#584) 2020-04-05 09:52:59 +02:00
Github Actions ce6187f378 [CI Skip] 2.8.0-beta.3
skip-checks: true
2020-04-04 08:45:26 +00:00
Jaco Greeff fe9c7a8a80 Bump deps (#583) 2020-04-04 10:42:21 +02:00
Github Actions d5584c1837 [CI Skip] 2.8.0-beta.2
skip-checks: true
2020-04-02 06:45:50 +00:00
Jaco Greeff adb1c1fea4 Rewrite yarn.lock (#580) 2020-04-02 08:42:32 +02:00
Github Actions c87c228ab1 [CI Skip] 2.8.0-beta.1
skip-checks: true
2020-04-01 19:23:33 +00:00
Jaco Greeff cbec4add88 Bump dev (incl. lint fixes) (#579)
* Bump dev (incl. lint fixes)

* Fix failures
2020-04-01 21:20:50 +02:00
Github Actions 6429cc307c [CI Skip] 2.8.0-beta.0
skip-checks: true
2020-04-01 18:47:32 +00:00
h4x3rotab c98e994777 Throws an error when signing with a locked keypair (#578)
* Throws an error when signing with a locked keypair

Fixes #576

* Fix lint errors

* Switch to `assert` and fix nits
2020-04-01 20:44:40 +02:00
Github Actions 697a452ba6 [CI Skip] 2.7.1
skip-checks: true
2020-03-31 11:56:12 +00:00
Jaco Greeff f68294c4e7 2.7 (#575) 2020-03-31 13:53:10 +02:00
Github Actions 0130d18945 [CI Skip] 2.7.0-beta.8
skip-checks: true
2020-03-24 06:29:44 +00:00
Jaco Greeff 15c9904c96 Add bnSqrt (#574)
* Add bnSqrt function

* Bumps

* CHANGELOG

* Add extra case
2020-03-24 07:25:53 +01:00
Github Actions add2749967 [CI Skip] 2.7.0-beta.7
skip-checks: true
2020-03-24 05:58:23 +00:00
Jaco Greeff fe2f054389 wasm-crypto initNone (#573)
* wasm-crypto initNone

* noWasm to replace @polkadot/wasm-crypto interface
2020-03-24 06:55:07 +01:00
Github Actions bb1c117727 [CI Skip] 2.7.0-beta.6
skip-checks: true
2020-03-21 09:15:30 +00:00
Jaco Greeff 27c474bd78 Bump deps (#572)
* Bump deps

* @types/jest
2020-03-21 10:12:17 +01:00
Github Actions 039b5ec932 [CI Skip] 2.7.0-beta.5
skip-checks: true
2020-03-16 14:35:40 +00:00
Jaco Greeff 9eea21e0c4 Add yarn matrix (#570)
* Add yarn matrix

* Update pr-any.yml
2020-03-16 15:32:59 +01:00
Github Actions aab533f92e [CI Skip] 2.7.0-beta.4
skip-checks: true
2020-03-16 13:36:21 +00:00
Jaco Greeff 2159270d80 Remove actions matrix (#569)
* Remove actions matrix

* Bumps
2020-03-16 14:33:27 +01:00
Github Actions f1b09eb2e5 [CI Skip] 2.7.0-beta.3
skip-checks: true
2020-03-15 07:21:01 +00:00
Jaco Greeff d08cf8b5fe Remove non-working CI cache (#567) 2020-03-15 08:18:04 +01:00
Github Actions 941618b830 [CI Skip] 2.7.0-beta.2
skip-checks: true
2020-03-14 08:31:56 +00:00
Jaco Greeff 983ca718ec Bump deps (#566) 2020-03-14 09:28:16 +01:00
Github Actions 41ebdd5c59 [CI Skip] 2.7.0-beta.1
skip-checks: true
2020-03-11 06:46:07 +00:00
Jaco Greeff 8971c89081 Back to preminor (#565) 2020-03-11 07:42:45 +01:00
Github Actions d1934060e0 [CI Skip] 2.6.2
skip-checks: true
2020-03-11 06:39:27 +00:00
Jaco Greeff 6d9da39d8b Bump dev, fix publish 2020-03-11 07:35:48 +01:00
Jaco Greeff 4ed096024e typeof __dirname !== 'undefined' before using (#564)
* typeof __dirname !== 'undefined' before using

* Use as patch

* yarn.lock

* Rewrite yarn.lock

* Shorten __dirname check
2020-03-11 07:18:52 +01:00
Github Actions ae36d58802 [CI Skip] 2.6.1
skip-checks: true
2020-02-29 17:48:10 +00:00
Jaco Greeff c8100dbe43 2.6 (#560)
* 2.6

* Update CHANGELOG
2020-02-29 18:44:50 +01:00
Github Actions 28d2ce38bd [CI Skip] 2.6.0-beta.8
skip-checks: true
2020-02-29 12:57:21 +00:00
Jaco Greeff afce99ed1a Minify yarn plugins (#559) 2020-02-29 13:53:57 +01:00
Github Actions 29d13ab19c [CI Skip] 2.6.0-beta.7
skip-checks: true
2020-02-29 11:30:10 +00:00
Jaco Greeff 68a8bcb7db Remove yarn version plugin, bump dev (#558) 2020-02-29 12:27:02 +01:00
Github Actions d2ecf1730a [CI Skip] 2.6.0-beta.6
skip-checks: true
2020-02-29 10:53:59 +00:00
Jaco Greeff af56c10278 Add cryptoIsReady (#557)
* Add cryptoIsReady

* Bump yarn
2020-02-29 11:51:17 +01:00
Github Actions 42f318fcb5 [CI Skip] 2.6.0-beta.5
skip-checks: true
2020-02-29 09:29:29 +00:00
Jaco Greeff 336df0d76d yarn --immutable on CI (#556)
* yarn --immutable on CI

* dev bump
2020-02-29 10:26:32 +01:00
Github Actions d85cedf5a0 [CI Skip] 2.6.0-beta.4
skip-checks: true
2020-02-28 12:19:35 +00:00
Jaco Greeff a59187bce6 Bump dev 2020-02-28 13:16:23 +01:00
Github Actions f9a5b75e10 [CI Skip] 2.6.0-beta.3
skip-checks: true
2020-02-28 12:06:20 +00:00
Jaco Greeff 87228149d4 Explicit gh-pages dep 2020-02-28 13:03:03 +01:00
Github Actions 67f36f6a13 [CI Skip] 2.6.0-beta.2
skip-checks: true
2020-02-28 11:32:49 +00:00
Jaco Greeff 75a9898daf Update to yarn 2 (#555) 2020-02-28 12:29:25 +01:00
Jaco Greeff 0f726ce777 Small formatting cleanups (#554)
* Small formatting cleanups

* Cleanup typos
2020-02-28 12:27:27 +01:00
Github Actions 765f9baf44 [CI Skip] 2.6.0-beta.1
skip-checks: true
2020-02-24 21:25:28 +00:00
Jaco Greeff 2d181df360 Bump wasm to 1.1 (#553)
* Bump wasm to 1.1

* typo
2020-02-24 22:23:48 +01:00
Github Actions 77ff703a08 [CI Skip] 2.6.0-beta.0
skip-checks: true
2020-02-24 10:56:56 +00:00
Jaco Greeff 804ed13d0a Add signatureVerify (#552)
* Add signatureVerify

* addressOrPublicKey typo

* Flatten verify, allow extra types

* Add signatureVerify tests

* De-dup address checksum checks
2020-02-24 11:55:15 +01:00
Jaco Greeff 341a6b0c08 Add TS 3.8 breaking feature in CHANGELOG (missed) (#551) 2020-02-24 09:08:16 +01:00
Jaco Greeff 614985b8ac Remove gh-pages script (in dev) (#549) 2020-02-22 16:56:24 +01:00
Github Actions d5bfa8c3c4 [CI Skip] 2.5.1
skip-checks: true
2020-02-22 15:34:36 +00:00
Jaco Greeff 359981d2ef Add pages refresh script (#548) 2020-02-22 16:32:41 +01:00
Jaco Greeff b0ee79f90c 2.5 (#547) 2020-02-22 15:57:33 +01:00
Github Actions c2d595fb3f [CI Skip] 2.5.0-beta.3
skip-checks: true
2020-02-22 14:23:29 +00:00
Jaco Greeff f837200a73 Fix isChildClass with correct is assertion (#546)
* Fix isChildClass with correct is assertion

* Remove stray any, allow never
2020-02-22 15:21:24 +01:00
Github Actions ea7dd553a2 [CI Skip] 2.5.0-beta.2
skip-checks: true
2020-02-22 13:46:55 +00:00
Jaco Greeff 7c1ca3a5c9 Use #<varname> instead of private _<varname> (#545)
* Use #<varname> insead of private _<varname>

* Update key extraction paths
2020-02-22 14:45:31 +01:00
Github Actions 75cd547b49 [CI Skip] 2.5.0-beta.1
skip-checks: true
2020-02-22 12:27:44 +00:00
Jaco Greeff 91c4c407a9 Add isChildClass (#544)
* Add isChildClass

* isChildClass is return

* Cleanup doc example
2020-02-22 13:26:12 +01:00
Github Actions 20b46a65fa [CI Skip] 2.5.0-beta.0
skip-checks: true
2020-02-21 15:56:13 +00:00
Jaco Greeff c60459e303 Add isBigInt & bnToBn support for (#542)
* Add isBigInt & bnToBn support for

* All BN inputs allow BigInt
2020-02-21 16:54:33 +01:00
Jaco Greeff 92ab4699b3 Re-add code build 2020-02-20 20:56:31 +01:00
Jaco Greeff 932f4c25f5 Docs rebuild 2020-02-20 20:52:19 +01:00
Jaco Greeff aaa35a8198 trigger docs 2020-02-20 17:45:57 +01:00
Github Actions 9708131620 [CI Skip] 2.4.1
skip-checks: true
2020-02-18 08:02:01 +00:00
Jaco Greeff c539430a0b 2.4 (#539) 2020-02-18 09:00:08 +01:00
Github Actions 8defc792a9 [CI Skip] 2.4.0-beta.2
skip-checks: true
2020-02-17 15:25:48 +00:00
Jaco Greeff 76a0daeed6 Use ss58 format on keyring for the keyring only (#538)
* Use ss58 format on keyring for the keyring only

* Cleanup args

* Cleanup failures

* Remove deprecated addressPrefix

* Update CHANGELOG
2020-02-17 16:24:03 +01:00
Github Actions e236fdc396 [CI Skip] 2.4.0-beta.1
skip-checks: true
2020-02-17 14:07:53 +00:00
Jaco Greeff e30dd7c0d9 Add GH actions yarn cache (#537) 2020-02-17 15:06:00 +01:00
Github Actions f3ac6b2674 [CI Skip] 2.4.0-beta.0
skip-checks: true
2020-02-17 11:18:01 +00:00
Jaco Greeff 171015fbba formatBalance adjustments (#536)
* formatBalance extensions

* Fly-by any removals

* isBn updates

* Remove unneeded ()'s
2020-02-17 12:16:02 +01:00
Github Actions dca36e41fd [CI Skip] 2.3.1
skip-checks: true
2020-02-15 11:00:43 +00:00
Jaco Greeff a602b0409c 2.3 (#535) 2020-02-15 11:59:04 +01:00
Github Actions 04d79da155 [CI Skip] 2.3.0-beta.9
skip-checks: true
2020-02-15 10:26:00 +00:00
Jaco Greeff 81a31519db Move date formatter to format (#534)
* Move date formatter to format

* Cleanup padding
2020-02-15 11:24:16 +01:00
Github Actions 78e39dcf34 [CI Skip] 2.3.0-beta.8
skip-checks: true
2020-02-15 10:09:19 +00:00
Jaco Greeff 6194660b3b Bump @polkadot/wasm to 1.0 (#533) 2020-02-15 11:07:33 +01:00
AndreasGassmannandJaco Greeff 2e08018718 feat(dependencies): remove moment.js (#530)
* feat(dependencies): remove moment.js

* fix(dependencies): remove yarn from yarn.lock

* feat(log-date-formatting): rename function

Co-authored-by: Jaco Greeff <jacogr@gmail.com>
2020-02-15 11:06:45 +01:00
Github Actions b0d6ccdbd4 [CI Skip] 2.3.0-beta.7
skip-checks: true
2020-02-15 09:27:10 +00:00
Jaco Greeff 48b753b8ac CHANGELOG update (#532) 2020-02-15 10:25:23 +01:00
Github Actions 506bc59f86 [CI Skip] 2.3.0-beta.6
skip-checks: true
2020-02-14 11:33:24 +00:00
AndreasGassmann f86fcc6044 feat(dependencies): move types to dev dependencies (#531) 2020-02-14 12:31:29 +01:00
Github Actions e8d2a439d5 [CI Skip] 2.3.0-beta.5
skip-checks: true
2020-02-14 08:43:15 +00:00
Jaco Greeff 9fa6b5bffa Bump dev, CI scripts (#529) 2020-02-14 09:41:29 +01:00
Github Actions 932ef41aae [CI Skip] 2.3.0-beta.4
skip-checks: true
2020-02-14 07:41:39 +00:00
Jaco Greeff 3910853ba1 Bump dev (#528) 2020-02-14 08:39:58 +01:00
Github Actions 6956e88708 [CI Skip] 2.3.0-beta.3
skip-checks: true
2020-02-14 07:11:09 +00:00
Jaco Greeff 3769b99cd2 Bump dev (#527)
* Bump dev

* Bumps
2020-02-14 08:09:29 +01:00
Github Actions ee17054b38 [CI Skip] 2.3.0-beta.2
skip-checks: true
2020-02-13 21:50:26 +00:00
Jaco Greeff 72cfbddd4a Bump dev (#526)
* Bump dev

* Bumps

* Bump

* Bump
2020-02-13 22:48:36 +01:00
Github Actions cffb23728d [CI Skip] 2.3.0-beta.1
skip-checks: true
2020-02-13 13:57:56 +00:00
Jaco Greeff a69dc01c78 Bump dev (#525) 2020-02-13 14:56:10 +01:00
Github Actions d889c71056 [CI Skip] 2.3.0-beta.0
skip-checks: true
2020-02-12 15:20:17 +00:00
Jaco Greeff 8eef3f9989 Cleanup explicit deps & bump deps (#523) 2020-02-12 16:18:21 +01:00
Github Actions 3112e43715 [CI Skip] 2.2.1
skip-checks: true
2020-02-06 14:46:00 +00:00
Jaco Greeff fc9a5ac25f 2.2 (#520) 2020-02-06 15:44:11 +01:00
Github Actions 242b107752 [CI Skip] 2.2.0-beta.0
skip-checks: true
2020-02-06 13:51:56 +00:00
Jaco Greeff bf5ba0f405 Add resolver for jest (#519) 2020-02-06 14:49:55 +01:00
Github Actions e4de3a1339 [CI Skip] 2.1.1
skip-checks: true
2020-02-04 12:53:47 +00:00
Jaco Greeff 69279f1b81 2.1 (#518) 2020-02-04 13:51:51 +01:00
Github Actions 303c822d48 [CI Skip] 2.1.0-beta.1
skip-checks: true
2020-02-04 10:39:58 +00:00
Jaco Greeff 90ca8a0d78 Backwards compat. on detctPackage (#517) 2020-02-04 11:38:00 +01:00
Github Actions 94bbc6f2ee [CI Skip] 2.1.0-beta.0
skip-checks: true
2020-02-03 12:23:51 +00:00
Jaco Greeff f4be1fe52e Multiple versions with __dirname (#515)
* Multiple versions with __dirname

* Fallback for __dirname

* Update path

* Flatten versions extracted

* Expand display for versions
2020-02-03 13:21:46 +01:00
256 changed files with 23793 additions and 14246 deletions
+2 -1
View File
@@ -1 +1,2 @@
4
5
2.6.22.12.2
+1
View File
@@ -1,3 +1,4 @@
.eslintrc.js
**/build/*
**/coverage/*
**/node_modules/*
+5
View File
@@ -7,5 +7,10 @@ module.exports = {
project: [
'./tsconfig.json'
]
},
rules: {
...base.rules,
// this seems very broken atm, false positives
'@typescript-eslint/unbound-method': 'off'
}
};
+6 -61
View File
@@ -2,72 +2,17 @@ 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 }}
env:
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
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/common'"
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
@@ -12,6 +12,10 @@ tmp/
.env.test.local
.env.production.local
.npmrc
.yarn/*
!.yarn/releases
!.yarn/plugins
.pnp.*
cc-test-reporter
lerna-debug.log*
npm-debug.log*
File diff suppressed because one or more lines are too long
+86
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-2.1.1.cjs
+235 -26
View File
@@ -1,4 +1,149 @@
# 2.0.1
# CHANGELOG
## 3.4.1 Aug 31, 2020
- Allow for WASM-as-available `mnemonicToBip39` call (used for Ethereum-compatible keypairs)
- Add `isWasm` utility to check for valid WASM headers
- `@polkadot/wasm-crypto` 1.4.1
## 3.3.1 Aug 24, 2020
- Add `addressRaw` to Keyring interface (if address encoding is different to publicKey)
- Allow for Ethereum pair signing and verification
## 3.2.1 Aug 17, 2020
- Allow for (optional, default blake2) hasher to secp256k1 sign/verify functions
- Utilities for secp256k1 publicKey expansion and compression
- Add basic Ethereum address utils (encode with checksum & checksum verification)
- Add Ethereum-compatible `mnemonicToBip39` seed creation function
## 3.1.1 Aug 10, 2020
- Add `deriveAddress(<address>, '/<soft>/<soft-b>')` via sr25519 soft
- Use `scrypt` from WASM as available (JS fallback in place)
- Add `base32{Encode, Decode}` utilities (IPFS-compatible alphabet)
- Support IPFS compatibility flag in base58 encoding/decoding
- Update to `@polkadot/wasm-crypto` 1.3.1
## 3.0.1 Jul 27, 2020
- Add Katal ss58Format (Thanks to https://github.com/retotrinkler)
- Adjust JSON pair output with scrypt kdf (version 3 output)
## 2.18.1 Jul 13, 2020
- Add `base64{Decode, Encode, Validate}` as crypto utils
- Extract `base58Validate` from base58 decode checks
- Add `isAscii` to allow detection of printable ASCII sequences (including tab, newline)
- Add `isUtf8` to allow detection of valid Utf8 sequences
## 2.17.1 Jul 6, 2020
- Add `encode{Derived, Multi}Address` to encode derived/multi addresses
- Correctly handle 0 inputs in `numberToU8a`
- Simplify and flatten base58 dependencies
## 2.16.1 Jun 29, 2020
- Adjust `addressCheck` and `encodeAddress` function to check for valid base58 alphabets (better error reporting)
- Rename `createKeySub` to `createKeyDerived` based on changed in Substrate (sub keys now named derived)
## 2.15.1 Jun 22, 2020
- Adjust keyring to no override 0-prefix (Polkadot live) settings with keychain default
## 2.14.1 Jun 16, 2020
- Add `extractTime` utility conversion (Thanks to https://github.com/kwingram25)
## 2.13.1 Jun 8, 2020
- Fix JS blake2 fallback (non-wasm) to correctly deal with hex inputs
- Align `bnToHex` signature with `bnToU8a` (with old/new style)
- Allow `bnTo{Hex,U8a}` to take any value with `.toBn()` signatures
## 2.12.2 Jun 1, 2020
- Fix `isFunction` signature to assert `Function`
## 2.12.1 Jun 1, 2020
- **Important** Removed `mnemonicToSeed`, it is only for bip39, use `mnemonicToMiniSecret` for the Substrate variant
- Added `u8aEq` to compare two Uint8Array or hex values for an exact match
- Added `addressEq` to compare two addresses (ss58, Uint8array or hex) for an exact match
- Throw error on `{nacl,schnorrkel}Verify` on invalid input lengths
- Performance optimizations in `u8aToHex` & `u8aConcat`
## 2.11.1 May 26, 2020
- Internal cleanups on typings
- Support for latest TypeScript, eslint & typescript-eslint
## 2.10.1 May 14, 2020
- Add Kulupu ss58 prefix as an allowed value (Thanks to https://github.com/sorpaas)
- Make the `TextEncoder` polyfill handle non-compliant Buffer implementations (newer versions of Jest)
- `DeriveJunction` now also allows for BigInt values (aligning with number types elsewhere)
- Small code-flow optimizations
## 2.9.1 Apr 30, 2020
- Add support for ECDSA keypairs (Thanks to https://github.com/akru)
- Added `createKeyMulti` & `createKeySub` to create utility sub & multi keys
- Added `u8aSorted` to sort `Uint8Arrays`
- Added `sortAddresses` to sort addresses based on their internal representation
## 2.8.1 Apr 9, 2020
- Keypair will now throw an error when attempting to sign/derive using a locked pair (Thanks to https://github.com/h4x3rotab)
- Cleanup `isDevelopment` regex to cater for chains such as `Westend Development`
## 2.7.1 Mar 31, 2020
- Add `bnSqrt` to calculate the integer sqrt via Newton iteration
- Allow for optional wasm-crypto, specifically via `@polkadot/util-crypto/noWasm`
- Misc. CI infrastructure cleanups
## 2.6.1 Feb 29, 2020
- **Breaking change** Following on the 2.0 release, `@polkadot/wasm` was updated to 1.1+. sr25510 now only verifies 0.8+ signatures, closing the loop on dropping Substrate 1.x-era support
- Add `signatureVerify (message: Uint8Array | string, signature: Uint8Array | string, addressOrPublicKey: Uint8Array | string): VerifyResult` to verify any signature, regardless of type. Returns validity & detected crypto type.
- Add `cryptoIsReady (): boolean` function to check status of initialization
- Add `addressCheckChecksum (decoded: Uint8Array)` as an helper to extract and verify the ss58 checksum
- Swap to yarn 2, allow use in yarn 2 projects
## 2.5.1 Feb 22, 2020
- **Breaking change** (TypeScript only) The `*.d.ts` files now contain TypeScript 3.8 features, `#private`, which is not usable in older versions
- Add `isBigInt(value)` to allow `BigInt` checks. Also add support in `bnToBn` as well as number conversion utils
- Add `isChildClass(Parent, Child?)` to check if a class extends the parent, asserting Child is Parent
- (internal) Use `#<field>` instead of `private _<field>` for private class variables
## 2.4.1 Feb 18, 2020
- Ensure that `formatBalance` does not apply unit overrides apply when no SI is applicable
- Adjust `formatBalance(<balance>, <options>)` to take expanded `withUnit: string | boolean` option where string is an actual unit, e.g. `KSM`
- The `decimals` option to `formatBalance` should now be passed as part of the `options` (previous last-param deprecated)
- The `.setSS58Format` on keyring will now just operate on pairs created on the keyring, not globally. The global `setSS58Format` in `@polkadot/util-crypto` will be deprecated.
- The deprecated `addressPrefix` option to keyring has been belatedly removed (Use `ss58Format` rather)
## 2.3.1 Feb 15, 2020
- Remove dependency on moment.js with `formatDate` function (Thanks to https://github.com/AndreasGassmann)
- Move TypeScript `@types/*` to dev deps (Thanks to https://github.com/AndreasGassmann)
- Update to `@polkadot/wasm-crypto` 1.0
- Cleanup dependencies to pave the way for using yarn 2 (Explicit instead of implicit)
## 2.2.1 Feb 06, 2020
- Add resolver for jest requires (tests from src)
## 2.1.1 Feb 04, 2020
- Update `detectPackage(<package.json>, __dirname?)` with calling folder
## 2.0.1 Jan 30, 2020
- Update w3f/schnorrkel to 0.8.5 (Full Substrate 2.x support, no 1.x support)
- Remove Alice session (ed2551) account from testing keyring (not applicable to Substrate 2.x)
@@ -6,27 +151,27 @@
- Renamed `assertSingletonPackage` to `detectPackage` with inclusion of version listing
- Swap to elliptic library for secp2561 recovery (No node bindings)
# 1.8.1
## 1.8.1 Jan 09, 2020
- Add cross-client encryption/decryption support (Thanks to https://github.com/hskang9)
# 1.7.1
## 1.7.1 Nov 27, 2019
- `formatBalance` signature now allows to force unit displays
- Keypair now allows for derive on a pair, with `pair.derive(...)`
- `assert` now acts like a real asserts, with no return - signature adapted for new TS 3.7
# 1.6.1
## 1.6.1 Oct 24, 2019
- `pair.sign(message)` now takes an optional second `options?: SignOptions` parameter, where `SignOptions` is currently defined as `{ withType: boolean }`. Here `withType` instructs the signing to prepend the type of signature (ed2551, sr25519 or ecdsa). This is used for the new Polkadot/Substrate MultiSignature format.
# 1.5.1
## 1.5.1 Sep 25, 2019
- Fix typings on the Keyring-exposed encode & decodeAddress
- Allow ss58Format = 0 as a valid value
- Loosen type definitions for allowed ss58format values (still checked against allowed array)
# 1.4.1
## 1.4.1 Sep 12, 2019
- **Breaking change** To set the `ss58Format`, you should now use `setSS58Format` as opposed to the old `setAddressPrefix`
- Renamed `keyring.setAddressPrefix` to `keyring.setSS58Format`
@@ -34,25 +179,25 @@
- Added `stringToHex` and `hexToString` conversion utilities to `@polkadot/util`
- Swap to [Babel 7.6.0](https://babeljs.io/) for all compilation, for latest improvements in code generation
# 1.3.1
## 1.3.1 Sep 10, 2019
- Remove the `ExtError` class, always prefer the standard JS `Error` object for errors. This would bre a breaking change for any applications using `ExtError`
# 1.2.1
## 1.2.1 Sep 09, 2019
- Keyring `addFromAddress` can now be used to store external accounts, for example those provided by external signers
- Maintainability updates
# 1.1.1
## 1.1.1 Aug 09, 2019
- `assertSingletonPackage` now warns via console.warn, but does not throw. This does allow the info to come accross while still allowing the app developers using multiple libraries time to fix.
# 1.0.1
## 1.0.1 Aug 02, 2019
- `formatBalance` now allows for `Compact` inputs
- `formaBalance` now allows correct formatting of very large decimals
# 0.94.1
### 0.94.1 Jul 20, 2019
- Add `checkAddress(address, prefix)` to `@polkadot/util-crypto` that validates an ss-58 address
- Add support for the Kusama network (as a valid checked prefix)
@@ -60,7 +205,7 @@
- The ed25519 key for Alice (representing the session), now appears in the test keyrings
- Fix missing dependencies for keyring (after address moves in 0.93.1)
# 0.93.1
### 0.93.1 Jun 14, 2019
- Breaking: External pair interface for keyring has been changed. Instead of
- `getMeta` use the `meta` getter, i.e. `console.log(pair.meta.name)`
@@ -68,69 +213,133 @@
- `publicKey` use the `publicKey` getter, i.e. `console.log(pair.publicKey)`
- `Move decodeAddress`, `encodeAddress` & `setAddressPrefix` functions into `@polkadot/util-crypto` from `@polkadot/keyring`. External interfaces should not be affected at this point since it is also (still) exported and exposed on keyring
# 0.92.1
### 0.92.1 Jun 04, 2019
- Only allow integer input values into `formatBalance`
- Allow `formatBalance`, `formatDecimal` & `formatNumber` to cater for negative numbers
- Add 'Bob//stash' to testing keyring, joining the existing 'Alice//stash'
# 0.91.1
### 0.91.1 May 22, 2019
- ed25519/sr25519 sign & verify functions can now take the message input as Uint8Array/string/hex and verify allows for the signature/publicKey to be specified as Uint8Array/hex
- Update `@polkadot/wasm` to include a maintenance bump for the `w3f/schnorrkel` libraries
# 0.90.1
### 0.90.1 May 08, 2019
- Moving towards 1.0
- Added bnMin & bnMax functions
# 0.76.1
### 0.76.1 Apr 03, 2019
- Fix `addFromMnemonic` to generate using new-style derivation.
- Pull in `formatBalance`, `formatDecimal`, `formatElapsed`, `formatNumber`, `calcSi`, `findSi` & `isTestChain` utility functions from the originals in `@polkadot/ui-util`
- Swap out `wasm-schnorrkel` & `wasm-ed25519` for combined version with `wasm-crypto`
- Swap DB interfaces to optional LRU, removing `transactionAsync` (client-only changes)
# 0.75.1
### 0.75.1 Mar 29, 2019
- Start journey to 1.0
# 0.42.1
### 0.42.1 Mar 28, 2019
- Add `assertSingletonPackage` to util
- Ensure that only a single keyring instance is loaded (uses above)
# 0.41.1
### 0.41.1 Mar 25, 2019
- Extensions to the client-specific database interfaces (non-breaking for API and util users)
# 0.40.1
### 0.40.1 Mar 23, 2019
- Add additional derivation path extraction mechanisms to util-crypto
- Add createFromUri function to keypair (creates keypair, does not add it)
- Allow all crypto hashing & ed25519 to use WASM (as available, JS fallbacks)
# 0.39.1
### 0.39.1 Mar 20, 2019
- Pull in bip39 generation functions from `@poladkot/wasm-crypto` with a fallback to the pure JS versions
# 0.38.1
### 0.38.1 Mar 18, 2019
- Align with current substrate master for sr25519 keys and hard/soft derivation
- Swap default dev keys to derived (sr25519)
# 0.37.1
### 0.37.1 Mar 14, 2019
- Swap to publishing -beta.x on merge (non-breaking testing)
# 0.36.1
### 0.36.1 Mar 13, 2019
- Add `fromUri` to keyring along with hard & soft key derivation.
# 0.35.1
### 0.35.1 Mar 04, 2019
- Remove NodeJs-only `syncify` function, not exported by the package (with binary dependency for Node)
# 0.34.1
### 0.34.1 Feb 13, 2019
- Keyring now allows for ed25519 and sr25519 instances. Upon creation, you need to pass the `ed25519`or `sr25519` string to denote the type, i.e. `new Keyring({ type: 'sr25519' })`
### 0.33.1 Nov 22, 2018
### 0.32.1 Oct 18, 2018
### 0.31.1 Oct 12, 2018
### 0.30.1 Sep 11, 2018
### 0.29.1 Sep 01, 2018
### 0.28.1 Aug 11, 2018
### 0.27.1 Aug 06, 2018
### 0.26.1 Jun 27, 2018
### 0.25.1 Jun 26, 2018
### 0.24.1 Jun 22, 2018
### 0.23.1 Jun 21, 2018
### 0.22.1 May 24, 2018
### 0.21.1 May 17, 2018
### 0.20.1 May 16, 2018
### 0.19.1 Apr 19, 2018
### 0.18.1 Mar 20, 2018
### 0.17.1 Mar0 8, 2018
### 0.16.1 Feb 23, 2018
### 0.15.1 Feb 15, 2018
### 0.14.1 Feb 07, 2018
### 0.13.1 Jan 25, 2018
### 0.12.1 Jan 11, 2018
### 0.11.1 Dec 30, 2017
### 0.10.1 Dec 17, 2017
### 0.9.1 Dec 14, 2017
### 0.8.1 Dec 12, 2017
### 0.7.1 Dec 11, 2017
### 0.6.1 Nov 30, 2017
### 0.5.1 Nov 20, 2017
### 0.4.1 Nov 19, 2017
### 0.3.1 Nov 19, 2017
### 0.2.1 Nov 18, 2017
+5 -3
View File
@@ -1,3 +1,5 @@
module.exports = {
extends: '@polkadot/dev/config/babel'
};
// Copyright 2017-2020 @polkadot/util 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 = require('@polkadot/dev/config/babel');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import Keyring class and utility function
const Keyring = require('@polkadot/keyring').default;
const stringToU8a = require('@polkadot/util/string/toU8a').default;
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import Keyring class and utility function
const Keyring = require('@polkadot/keyring').default;
const stringToU8a = require('@polkadot/util/string/toU8a').default;
@@ -1,12 +1,18 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const { encodeAddress, decodeAddress } = require('@polkadot/keyring');
const { isHex, hexToU8a } = require('@polkadot/util');
/* eslint-disable header/header */
const { decodeAddress, encodeAddress } = require('@polkadot/keyring');
const { hexToU8a, isHex } = require('@polkadot/util');
const address = '5GrpknVvGGrGH3EFuURXeMrWHvbpj3VfER1oX5jFtuGbfzCE';
const isValidAddressPolkadotAddress = () => {
try {
encodeAddress(isHex(address) ? hexToU8a(address) : decodeAddress(address));
encodeAddress(
isHex(address)
? hexToU8a(address)
: decodeAddress(address)
);
return true;
} catch (error) {
return false;
@@ -1,7 +1,8 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
const { naclEncrypt, naclDecrypt } = require('@polkadot/util-crypto');
const { naclDecrypt, naclEncrypt } = require('@polkadot/util-crypto');
async function main () {
const secret = new Uint8Array(32);
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
const { stringToU8a, u8aToHex } = require('@polkadot/util');
const { naclEncrypt, naclKeypairFromSeed, naclSign, naclVerify, randomAsU8a } = require('@polkadot/util-crypto');
@@ -9,7 +10,7 @@ async function main () {
const seedAlice = 'Alice'.padEnd(32, ' ');
// Generate new public/secret keypair for Alice from the supplied seed
const { secretKey, publicKey } = naclKeypairFromSeed(stringToU8a(seedAlice));
const { publicKey, secretKey } = naclKeypairFromSeed(stringToU8a(seedAlice));
// Encrypt message. Create Uint8Array's filled with random bytes of specified length
const secret = randomAsU8a(32);
@@ -1,6 +1,8 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/no-var-requires,@typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
const { mnemonicGenerate, mnemonicToSeed, mnemonicValidate, naclKeypairFromSeed } = require('@polkadot/util-crypto');
async function main () {
@@ -19,7 +21,7 @@ async function main () {
const seedAlice = mnemonicToSeed(mnemonicAlice);
// Generate new public/secret keypair for Alice from the supplied seed
const { secretKey, publicKey } = naclKeypairFromSeed(seedAlice);
const { publicKey, secretKey } = naclKeypairFromSeed(seedAlice);
// Encrypt, Sign and Validate the message. See Example 'Sign & Verify Message'
}
@@ -0,0 +1,5 @@
# Generate a Multisig Account
Substrate provides a multisig dispatch function in its
[Utility pallet](https://crates.parity.io/pallet_utility/index.html). This example generates the
address that would correspond to a set of addresses and threshold.
@@ -0,0 +1,40 @@
/* eslint-disable header/header */
import { createKeyMulti, encodeAddress, sortAddresses } from '@polkadot/util-crypto';
const SS58Prefix = 0;
// Input the addresses that will make up the multisig account.
const addresses = [
'1nUC7afqmo7zwRFWxDjrUQu9skk6fk99pafb4SiyGSRc8z3',
'1ZX2XntfLEHrBPy73DpfQp9rG7pbLyvrFjEpi7mNKQgyga5',
'14b1kB7CrqzRUeMsKc26FJ73f8FCpxAX6sNieu9gfYSfJuoL'
];
// The number of accounts that must approve. Must be greater than 0 and less than
// or equal to the total number of addresses.
const threshold = 2;
// The address (as index in `addresses`) that will submit a transaction.
const index = 0;
function main () {
// Address as a byte array.
const multiAddress = createKeyMulti(addresses, threshold);
// Convert byte array to SS58 encoding.
const Ss58Address = encodeAddress(multiAddress, SS58Prefix);
console.log(`\nMultisig Address: ${Ss58Address}`);
// Take addresses and remove the sender.
const otherSignatories = addresses.filter((who) => who !== addresses[index]);
// Sort them by public key.
const otherSignatoriesSorted = sortAddresses(otherSignatories, SS58Prefix);
console.log(`\nOther Signatories: ${otherSignatoriesSorted}\n`);
process.exit();
}
main();
@@ -0,0 +1,14 @@
{
"name": "04_generate_multisig_address",
"version": "0.1.0",
"description": "Example showing how to generate a multisig address for Substrate's Utility pallet",
"main": "index.js",
"author": "joepetrowski",
"license": "MIT",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"@polkadot/util-crypto": "^2.9.0-beta.1"
}
}
+8 -9
View File
@@ -1,21 +1,20 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
// Copyright 2017-2020 @polkadot/util 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/keyring(.*)$': '<rootDir>/packages/keyring/src/$1',
'@polkadot/util-(crypto)(.*)$': '<rootDir>/packages/util-$1/src/$2',
// eslint-disable-next-line sort-keys
'@polkadot/util(.*)$': '<rootDir>/packages/util/src/$1'
},
modulePathIgnorePatterns: [
'<rootDir>/packages/db/build',
'<rootDir>/packages/chainspec/build',
'<rootDir>/packages/keyring/build',
'<rootDir>/packages/trie-codec/build',
'<rootDir>/packages/trie-db/build',
'<rootDir>/packages/trie-hash/build',
'<rootDir>/packages/util/build',
'<rootDir>/packages/util-crypto/build',
'<rootDir>/packages/util-rlp/build'
]
'<rootDir>/packages/util-crypto/build'
],
resolver: './jest.resolver.js'
});
+11
View File
@@ -0,0 +1,11 @@
// Copyright 2017-2020 @polkadot/util 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
@@ -9,5 +9,5 @@
"packages": [
"packages/*"
],
"version": "2.0.1"
"version": "3.4.1"
}
+18 -13
View File
@@ -1,28 +1,33 @@
{
"version": "2.0.1",
"repository": "https://github.com/polkadot-js/common",
"author": "Jaco Greeff <jacogr@gmail.com>",
"license": "Apache-2",
"private": true,
"engines": {
"yarn": "^1.10.1"
},
"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",
"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",
"@polkadot/dev": "^0.33.3",
"@polkadot/ts": "^0.2.1"
}
"@babel/core": "^7.11.4",
"@polkadot/dev": "^0.55.43",
"@polkadot/ts": "^0.3.40",
"@types/jest": "^26.0.10",
"typedoc": "^0.18.0",
"typedoc-plugin-markdown": "^2.4.2",
"typedoc-plugin-no-inherit": "^1.1.10"
},
"version": "3.4.1"
}
+4 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/keyring",
"version": "2.0.1",
"version": "3.4.1",
"description": "Keyring management",
"main": "index.js",
"publishConfig": {
@@ -26,12 +26,9 @@
"url": "https://github.com/polkadot-js/common/issues"
},
"homepage": "https://github.com/polkadot-js/common/tree/master/packages/keyring#readme",
"browser": {
"../package.json": "./package.json"
},
"dependencies": {
"@babel/runtime": "^7.8.3",
"@polkadot/util": "^2.0.1",
"@polkadot/util-crypto": "^2.0.1"
"@babel/runtime": "^7.11.2",
"@polkadot/util": "3.4.1",
"@polkadot/util-crypto": "3.4.1"
}
}
+239 -36
View File
@@ -3,7 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { hexToU8a, stringToU8a } from '@polkadot/util';
import { cryptoWaitReady, setSS58Format } from '@polkadot/util-crypto';
import { cryptoWaitReady, setSS58Format, encodeAddress } from '@polkadot/util-crypto';
import Keyring from '.';
@@ -17,57 +17,55 @@ describe('keypair', (): void => {
const publicKeyTwo = new Uint8Array([215, 90, 152, 1, 130, 177, 10, 183, 213, 75, 254, 211, 201, 100, 7, 58, 14, 225, 114, 243, 218, 166, 35, 37, 175, 2, 26, 104, 247, 7, 81, 26]);
const seedOne = stringToU8a('12345678901234567890123456789012');
const seedTwo = hexToU8a('0x9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60');
let keypair: Keyring;
let keyring: Keyring;
beforeEach((): void => {
keypair = new Keyring({ type: 'ed25519' });
keyring = new Keyring({ ss58Format: 42, type: 'ed25519' });
keypair.addFromSeed(seedOne, {});
});
afterEach((): void => {
setSS58Format(42);
keyring.addFromSeed(seedOne, {});
});
it('adds the pair', (): void => {
expect(
keypair.addFromSeed(seedTwo, {}).publicKey
keyring.addFromSeed(seedTwo, {}).publicKey
).toEqual(publicKeyTwo);
});
it('creates a ed25519 pair via mnemonicToSeed', (): void => {
expect(
keypair.addFromUri(
keyring.addFromUri(
'seed sock milk update focus rotate barely fade car face mechanic mercy'
).address
).toEqual('5DkQP32jP4DVJLWWBRBoZF2tpWjqFrcrTBo6H5NcSk7MxKCC');
});
it('adds from a mnemonic', (): void => {
setSS58Format(68);
it('adds from a mnemonic, with correct ss58', (): void => {
setSS58Format(20); // this would not be used
keyring.setSS58Format(68); // this would be used
expect(
keypair.addFromMnemonic('moral movie very draw assault whisper awful rebuild speed purity repeat card', {}).address
).toEqual('7sPsxWPE5DzAyPT3VuoJYw5NTGscx9QYN9oddQx4kALKC3hH');
const pair = keyring.addFromMnemonic('moral movie very draw assault whisper awful rebuild speed purity repeat card', {});
expect(pair.address).toEqual('7sPsxWPE5DzAyPT3VuoJYw5NTGscx9QYN9oddQx4kALKC3hH');
expect(encodeAddress(pair.publicKey)).toEqual('35cDYtPsdG1HUa2n2MaARgJyRz1WKMBZK1DL6c5cX7nugQh1');
});
it('allows publicKeys retrieval', (): void => {
keypair.addFromSeed(seedTwo, {});
keyring.addFromSeed(seedTwo, {});
expect(
keypair.getPublicKeys()
keyring.getPublicKeys()
).toEqual([publicKeyOne, publicKeyTwo]);
});
it('allows retrieval of a specific item', (): void => {
expect(
keypair.getPair(publicKeyOne).publicKey
keyring.getPair(publicKeyOne).publicKey
).toEqual(publicKeyOne);
});
it('allows adding from JSON', (): void => {
expect(
keypair.addFromJson(
keyring.addFromJson(
JSON.parse('{"address":"5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaQua","encoded":"0xb4a14995d25ab609f3686e9fa45f1fb237cd833f33f00d4b12c51858ca070d96972e47d73aae5eeb0fc06f923826cf0943fdb02c2c2ee30ef52a7912663053940d1da4da66b3a3f520ae07422c1c94b2d95690fca9d1f4a997623bb2923a8833280e19e7f72c3c5cfa343974e60e2b3dc53b404fdaf330756daad5e4e3","encoding":{"content":"pkcs8","type":"xsalsa20-poly1305","version":"0"},"meta":{"isTesting":true,"name":"alice"}}')
).publicKey
).toEqual(
@@ -77,7 +75,7 @@ describe('keypair', (): void => {
it('signs and verifies', (): void => {
const MESSAGE = stringToU8a('this is a message');
const pair = keypair.getPair(publicKeyOne);
const pair = keyring.getPair(publicKeyOne);
const signature = pair.sign(MESSAGE);
expect(pair.verify(MESSAGE, signature)).toBe(true);
@@ -89,55 +87,51 @@ describe('keypair', (): void => {
const publicKeyTwo = hexToU8a('0x44a996beb1eef7bdcab976ab6d2ca26104834164ecf28fb375600576fcc6eb0f');
const seedOne = stringToU8a('12345678901234567890123456789012');
const seedTwo = hexToU8a('0x9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60');
let keypair: Keyring;
let keyring: Keyring;
beforeEach((): void => {
keypair = new Keyring({ type: 'sr25519' });
keyring = new Keyring({ ss58Format: 42, type: 'sr25519' });
keypair.addFromSeed(seedOne, {});
});
afterEach((): void => {
setSS58Format(42);
keyring.addFromSeed(seedOne, {});
});
it('creates with dev phrase when only path specified', (): void => {
expect(
keypair.createFromUri('//Alice').address
keyring.createFromUri('//Alice').address
).toEqual('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY');
});
it('adds the pair', (): void => {
expect(
keypair.addFromSeed(seedTwo, {}).publicKey
keyring.addFromSeed(seedTwo, {}).publicKey
).toEqual(publicKeyTwo);
});
it('adds from a mnemonic', (): void => {
setSS58Format(68);
keyring.setSS58Format(68);
expect(
keypair.addFromMnemonic('moral movie very draw assault whisper awful rebuild speed purity repeat card', {}).address
keyring.addFromMnemonic('moral movie very draw assault whisper awful rebuild speed purity repeat card', {}).address
).toEqual('7qQGarA4PWjPPVHG4USn1yuuVZvEHN7XZz8o7EbAp48jayZQ');
});
it('allows publicKeys retrieval', (): void => {
keypair.addFromSeed(seedTwo, {});
keyring.addFromSeed(seedTwo, {});
expect(
keypair.getPublicKeys()
keyring.getPublicKeys()
).toEqual([publicKeyOne, publicKeyTwo]);
});
it('allows retrieval of a specific item', (): void => {
expect(
keypair.getPair(publicKeyOne).publicKey
keyring.getPair(publicKeyOne).publicKey
).toEqual(publicKeyOne);
});
it('allows adding from JSON', (): void => {
expect(
keypair.addFromJson(
keyring.addFromJson(
JSON.parse('{"address":"5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaQua","encoded":"0xb4a14995d25ab609f3686e9fa45f1fb237cd833f33f00d4b12c51858ca070d96972e47d73aae5eeb0fc06f923826cf0943fdb02c2c2ee30ef52a7912663053940d1da4da66b3a3f520ae07422c1c94b2d95690fca9d1f4a997623bb2923a8833280e19e7f72c3c5cfa343974e60e2b3dc53b404fdaf330756daad5e4e3","encoding":{"content":"pkcs8","type":"xsalsa20-poly1305","version":"0"},"meta":{"isTesting":true,"name":"alice"}}')
).publicKey
).toEqual(
@@ -147,10 +141,219 @@ describe('keypair', (): void => {
it('signs and verifies', (): void => {
const MESSAGE = stringToU8a('this is a message');
const pair = keypair.getPair(publicKeyOne);
const pair = keyring.getPair(publicKeyOne);
const signature = pair.sign(MESSAGE);
expect(pair.verify(MESSAGE, signature)).toBe(true);
});
});
describe('ecdsa', (): void => {
const seedOne = 'potato act energy ahead stone taxi receive fame gossip equip chest round';
const seedTwo = hexToU8a('0x3c74be003bd9a876be439949ccf2b292bd966c94959a689173b295b326cd6da7');
const publicKeyOne = hexToU8a('0x02c6b6c664db5ef505477bba1cf2f1789c98796b9bb5fa21abd0ac4589bed980e7');
const publicKeyTwo = hexToU8a('0x021da683b913fb28c979ba3e5f1881415cef4b1f58a5d05ed3610a2995e7b4943c');
const addressKeyOne = hexToU8a('0x0cfd0dd2c59a9987b9848919163931b6a42283ffd3d91e92c98b522525a7038f');
let keyring: Keyring;
beforeEach((): void => {
keyring = new Keyring({ ss58Format: 42, type: 'ecdsa' });
keyring.addFromMnemonic(seedOne, {});
});
it('creates with dev phrase when only path specified', (): void => {
expect(
keyring.createFromUri('//Alice').address
).toEqual('5C7C2Z5sWbytvHpuLTvzKunnnRwQxft1jiqrLD5rhucQ5S9X');
});
it('adds the pair', (): void => {
expect(
keyring.addFromSeed(seedTwo, {}).publicKey
).toEqual(publicKeyTwo);
});
it('adds from a mnemonic', (): void => {
keyring.setSS58Format(68);
expect(
keyring.addFromMnemonic('moral movie very draw assault whisper awful rebuild speed purity repeat card').address
).toEqual('7ooxHV3mz4nnWbK8v7Mxcb71QMpof268eL1A2VrYWUNWJk8P');
});
it('allows publicKeys retrieval', (): void => {
keyring.addFromSeed(seedTwo, {});
expect(
keyring.getPublicKeys()
).toEqual([publicKeyOne, publicKeyTwo]);
});
it('allows retrieval of a specific item', (): void => {
expect(
keyring.getPair(addressKeyOne).publicKey
).toEqual(publicKeyOne);
});
it('allows adding from JSON', (): void => {
expect(
keyring.addFromJson(
JSON.parse('{"address":"5DzMsaYFhmpRdErWrP6K6PD7UXzYoeETToSBUrZSvxasqWRz","encoded":"0xa192d39b42bc1601bf61df31039a554228593fadf870bc837b658a5114627aca199fff596260c95fe8994c66a47636cf0270aa08f402ba5541038753960d00e6c3af5e239ec58fb1eef3db7d6bc266f4853bdfe4ed17122d9092d879014d53980d2ee57f6f55a88c38836447d8645008e8815379626addc8f81f80cd49a2","encoding":{"content":"pkcs8","type":"xsalsa20-poly1305","version":"2"},"meta":{}}')
).address
).toEqual('5DzMsaYFhmpRdErWrP6K6PD7UXzYoeETToSBUrZSvxasqWRz');
});
it('signs and verifies', (): void => {
const MESSAGE = stringToU8a('this is a message');
const pair = keyring.getPair(addressKeyOne);
const signature = pair.sign(MESSAGE);
expect(pair.verify(MESSAGE, signature)).toBe(true);
});
});
describe('ethereum', (): void => {
const PHRASE = 'seed sock milk update focus rotate barely fade car face mechanic mercy';
let keyring: Keyring;
beforeEach((): void => {
keyring = new Keyring({ type: 'ethereum' });
});
it('adds a pair with the correct address', (): void => {
const pair = keyring.createFromUri(PHRASE);
expect(pair.publicKey).toEqual(hexToU8a('0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077'));
expect(pair.address).toEqual('0x4119b2e6c3Cb618F4f0B93ac77f9BeeC7FF02887');
});
it('encodes a pair toJSON', (): void => {
const pair = keyring.createFromUri(PHRASE);
const json = pair.toJson('password');
expect(json.address).toEqual('0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077');
expect(json.encoding).toEqual({
content: ['pkcs8', 'ethereum'],
type: ['scrypt', 'xsalsa20-poly1305'],
version: '3'
});
});
it('allows adding from JSON', (): void => {
const pair = keyring.addFromJson(
JSON.parse('{"address":"KWCv1L3QX9LDPwY4VzvLmarEmXjVJidUzZcinvVnmxAJJCBou","encoded":"U8qFEaghhmNV2PgFhjqzmhyUy37Ok7abfFU2MNsBd0sAgAAAAQAAAAgAAAA3+NniKogzNphiMNueB1X0sGA07B6CaXWfpXPx45iSXoTTprwzU5mOoSqUWO0GKHROI72LN+uJ8Yfv6Ll6JOOV3VPKfoVoFmYm+zDrrMPa0gk5E5kUuSijxADcE6zUrliPVr0Ix/qaghu5SJ7RtWDQLBf4Hp86SJ8Gg6gTSSk=","encoding":{"content":["pkcs8","ethereum"],"type":["scrypt","xsalsa20-poly1305"],"version":"3"},"meta":{}}')
);
expect(pair.publicKey).toEqual(hexToU8a('0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077'));
expect(pair.address).toEqual('0x4119b2e6c3Cb618F4f0B93ac77f9BeeC7FF02887');
pair.decodePkcs8('password');
expect(pair.isLocked).toBe(false);
expect(pair.publicKey).toEqual(hexToU8a('0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077'));
expect(pair.address).toBe('0x4119b2e6c3Cb618F4f0B93ac77f9BeeC7FF02887');
});
it('allows for signing/verification', (): void => {
const MESSAGE = stringToU8a('just some test message');
const signer = keyring.createFromUri(PHRASE);
const verifier = keyring.addFromJson(
JSON.parse('{"address":"KWCv1L3QX9LDPwY4VzvLmarEmXjVJidUzZcinvVnmxAJJCBou","encoded":"U8qFEaghhmNV2PgFhjqzmhyUy37Ok7abfFU2MNsBd0sAgAAAAQAAAAgAAAA3+NniKogzNphiMNueB1X0sGA07B6CaXWfpXPx45iSXoTTprwzU5mOoSqUWO0GKHROI72LN+uJ8Yfv6Ll6JOOV3VPKfoVoFmYm+zDrrMPa0gk5E5kUuSijxADcE6zUrliPVr0Ix/qaghu5SJ7RtWDQLBf4Hp86SJ8Gg6gTSSk=","encoding":{"content":["pkcs8","ethereum"],"type":["scrypt","xsalsa20-poly1305"],"version":"3"},"meta":{}}')
);
const signature = signer.sign(MESSAGE);
expect(verifier.verify(MESSAGE, signature)).toBe(true);
});
});
describe('util', (): void => {
let keyring: Keyring;
beforeEach((): void => {
keyring = new Keyring({ ss58Format: 42 });
});
it('can re-encode an address to Polkadot live', (): void => {
expect(
keyring.encodeAddress('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY', 0)
).toEqual('15oF4uVJwmo4TdGW7VfQxNLavjCXviqxT9S1MgbjMNHr6Sp5');
});
it('can re-encode an address to keyring default', (): void => {
expect(
keyring.encodeAddress('15oF4uVJwmo4TdGW7VfQxNLavjCXviqxT9S1MgbjMNHr6Sp5')
).toEqual('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY');
});
});
describe('version 2 JSON', (): void => {
const PAIR = '{"address":"5CczAE5AmGrZ93MeVhha3Ywam7j9dKB7cArnH7gtrXcMFJvu","encoded":"0xee8f236e2ac3217ce689692a4afc612220dc77fddaed0482f8f95136a7c3e034cccfbc495410a6e9b2439904974ed1d207abeca536ff6985ceb78edeeb3dc343e561c184c488101af8811d1331430b4ccf0e96ef507132e5132964e8564232e7100d973c5bee7b231dd0c8ad5273f3501515a422c8d7ed9d20a73c0ed17c98ee4588e54844bb73052dcad81f7a1094613d63c162fec7446c88b1fae70e","encoding":{"content":["pkcs8","sr25519"],"type":"xsalsa20-poly1305","version":"2"},"meta":{"genesisHash":"0xe143f23803ac50e8f6f8e62695d1ce9e4e1d68aa36c1cd2cfd15340213f3423e","name":"json v2","tags":[],"whenCreated":1595243159596}}';
const PASS2 = 'versionTwo';
const PASS3 = 'versionThree';
let keyring: Keyring;
beforeEach((): void => {
keyring = new Keyring({ ss58Format: 42 });
});
it('can decode from a version 2 JSON file', (): void => {
const pair = keyring.addFromJson(JSON.parse(PAIR));
pair.decodePkcs8(PASS2);
const json = pair.toJson(PASS3);
expect(pair.isLocked).toBe(false);
expect(pair.address).toBe('5CczAE5AmGrZ93MeVhha3Ywam7j9dKB7cArnH7gtrXcMFJvu');
expect(json.encoding).toEqual({
content: ['pkcs8', 'sr25519'],
type: ['scrypt', 'xsalsa20-poly1305'],
version: '3'
});
pair.decodePkcs8(PASS3);
expect(pair.address).toEqual('5CczAE5AmGrZ93MeVhha3Ywam7j9dKB7cArnH7gtrXcMFJvu');
});
});
describe('version 3 JSON (hex)', (): void => {
const PAIR = '{"address":"FLiSDPCcJ6auZUGXALLj6jpahcP6adVFDBUQznPXUQ7yoqH","encoded":"0xcd238963070cc4d6806053ee1ac500c7add9c28732bb5d434a332f84a91d9be0008000000100000008000000cf630a1113941b350ddd06697e50399183162e5e9a0e893eafc7f5f4893a223dca5055706b9925b56fdb4304192143843da718e11717daf89cf4f4781f94fb443f61432f782d54280af9eec90bd3069c3cc2d957a42b7c18dc2e9497f623735518e0e49b58f8e4db2c09da3a45dbb935659d015fc94b946cba75b606a6ff7f4e823f6b049e2e6892026b49de02d6dbbd64646fe0933f537d9ea53a70be","encoding":{"content":["pkcs8","sr25519"],"type":["scrypt","xsalsa20-poly1305"],"version":"3"},"meta":{"genesisHash":"0xb0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafe","name":"version3","tags":[],"whenCreated":1595277797639}}';
const PASS3 = 'version3';
let keyring: Keyring;
beforeEach((): void => {
keyring = new Keyring({ ss58Format: 2 });
});
it('can decode from a version 3 JSON file', (): void => {
const pair = keyring.addFromJson(JSON.parse(PAIR));
pair.decodePkcs8(PASS3);
expect(pair.isLocked).toBe(false);
expect(pair.address).toBe('FLiSDPCcJ6auZUGXALLj6jpahcP6adVFDBUQznPXUQ7yoqH');
});
});
describe('version 3 JSON (base64)', (): void => {
const PAIR = '{"address":"FLiSDPCcJ6auZUGXALLj6jpahcP6adVFDBUQznPXUQ7yoqH","encoded":"ILjSgYaGvq1zaCz/kx+aqfLaHBjLXz0Qsmr6RnkOVU4AgAAAAQAAAAgAAAB5R2hm5kgXyc0NQYFxvMU4zCdjB+ugs/ibEooqCvuudbaeKn3Ee47NkCqU1ecOJV+eeaVn4W4dRvIpj5kGmQOGsewR+MiQ/B0G9NFh7JXV0qcPlk2QMNW1/mbJrTO4miqL448BSkP7ZOhUV6HFUpMt3B9HwjiRLN8RORcFp0ID/Azs4Jl/xOpXNzbgQGIffWgCIKTxN9N1ku6tdlG4","encoding":{"content":["pkcs8","sr25519"],"type":["scrypt","xsalsa20-poly1305"],"version":"3"},"meta":{"genesisHash":"0xb0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafe","name":"version3","tags":[],"whenCreated":1595277797639,"whenEdited":1595278378596}}';
const PASS3 = 'version3';
let keyring: Keyring;
beforeEach((): void => {
keyring = new Keyring({ ss58Format: 2 });
});
it('can decode from a version 3 JSON file', (): void => {
const pair = keyring.addFromJson(JSON.parse(PAIR));
pair.decodePkcs8(PASS3);
expect(pair.isLocked).toBe(false);
expect(pair.address).toBe('FLiSDPCcJ6auZUGXALLj6jpahcP6adVFDBUQznPXUQ7yoqH');
});
});
});
+2 -9
View File
@@ -7,15 +7,8 @@ import { decodeAddress, encodeAddress, setSS58Format } from '@polkadot/util-cryp
import Keyring from './keyring';
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;
+61 -51
View File
@@ -2,16 +2,23 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { KeypairType } from '@polkadot/util-crypto/types';
import { KeyringInstance, KeyringPair, KeyringPair$Json, KeyringPair$Meta, KeyringOptions } from './types';
import { KeypairType, Keypair } from '@polkadot/util-crypto/types';
import { KeyringInstance, KeyringPair, KeyringPair$Json, KeyringPair$JsonEncodingTypes, KeyringPair$Meta, KeyringOptions } from './types';
import { assert, hexToU8a, isNumber, isHex, stringToU8a } from '@polkadot/util';
import { decodeAddress, encodeAddress, keyExtractSuri, keyFromPath, naclKeypairFromSeed as naclFromSeed, schnorrkelKeypairFromSeed as schnorrkelFromSeed, mnemonicToMiniSecret, setSS58Format } from '@polkadot/util-crypto';
import { assert, hexToU8a, isHex, isUndefined, stringToU8a } from '@polkadot/util';
import { base64Decode, decodeAddress, encodeAddress, keyExtractSuri, keyFromPath, naclKeypairFromSeed as naclFromSeed, schnorrkelKeypairFromSeed as schnorrkelFromSeed, secp256k1KeypairFromSeed as secp256k1FromSeed, mnemonicToBip39, mnemonicToMiniSecret } from '@polkadot/util-crypto';
import { DEV_PHRASE } from './defaults';
import createPair from './pair';
import Pairs from './pairs';
const keypairFromSeed = {
ecdsa: (seed: Uint8Array): Keypair => secp256k1FromSeed(seed),
ed25519: (seed: Uint8Array): Keypair => naclFromSeed(seed),
ethereum: (seed: Uint8Array): Keypair => secp256k1FromSeed(seed),
sr25519: (seed: Uint8Array): Keypair => schnorrkelFromSeed(seed)
};
/**
* # @polkadot/keyring
*
@@ -29,30 +36,22 @@ import Pairs from './pairs';
* an account may be obtained using `toJson` accompanied by the account passphrase.
*/
export default class Keyring implements KeyringInstance {
private _pairs: Pairs;
readonly #pairs: Pairs;
private _type: KeypairType;
readonly #type: KeypairType;
#ss58?: number;
public decodeAddress = decodeAddress;
public encodeAddress = encodeAddress;
public setSS58Format = setSS58Format;
constructor (options: KeyringOptions = {}) {
options.type = options.type || 'ed25519';
options.ss58Format = isNumber(options.ss58Format)
? options.addressPrefix
: options.ss58Format;
assert(options && ['ed25519', 'sr25519'].includes(options.type || 'undefined'), `Expected a keyring type of either 'ed25519' or 'sr25519', found '${options.type}`);
assert(options && ['ecdsa', 'ethereum', 'ed25519', 'sr25519'].includes(options.type || 'undefined'), `Expected a keyring type of either 'ed25519', 'sr25519' or 'ecdsa', found '${options.type}`);
this._pairs = new Pairs();
this._type = options.type;
if (isNumber(options.ss58Format)) {
setSS58Format(options.ss58Format);
}
this.#pairs = new Pairs();
this.#ss58 = options.ss58Format;
this.#type = options.type;
}
/**
@@ -70,10 +69,10 @@ export default class Keyring implements KeyringInstance {
}
/**
* @description Returns the type of the keyring, either ed25519 of sr25519
* @description Returns the type of the keyring, ed25519, sr25519 or ecdsa
*/
public get type (): KeypairType {
return this._type;
return this.#type;
}
/**
@@ -81,7 +80,7 @@ export default class Keyring implements KeyringInstance {
* @summary Stores an account, given a keyring pair, as a Key/Value (public key, pair) in Keyring Pair Dictionary
*/
public addPair (pair: KeyringPair): KeyringPair {
return this._pairs.add(pair);
return this.#pairs.add(pair);
}
/**
@@ -92,10 +91,10 @@ export default class Keyring implements KeyringInstance {
* of an account backup), and then generates a keyring pair from them that it passes to
* `addPair` to stores in a keyring pair dictionary the public key of the generated pair as a key and the pair as the associated value.
*/
public addFromAddress (address: string | Uint8Array, meta: KeyringPair$Meta = {}, encoded: Uint8Array | null = null, type: KeypairType = this.type, ignoreChecksum?: boolean): KeyringPair {
public addFromAddress (address: string | Uint8Array, meta: KeyringPair$Meta = {}, encoded: Uint8Array | null = null, type: KeypairType = this.type, ignoreChecksum?: boolean, encType?: KeyringPair$JsonEncodingTypes[]): KeyringPair {
const publicKey = this.decodeAddress(address, ignoreChecksum);
return this.addPair(createPair(type, { publicKey, secretKey: new Uint8Array(64) }, meta, encoded));
return this.addPair(createPair({ toSS58: this.encodeAddress, type }, { publicKey, secretKey: new Uint8Array() }, meta, encoded, encType));
}
/**
@@ -105,12 +104,15 @@ export default class Keyring implements KeyringInstance {
* of an account backup), and then generates a keyring pair from it that it passes to
* `addPair` to stores in a keyring pair dictionary the public key of the generated pair as a key and the pair as the associated value.
*/
public addFromJson ({ address, encoded, encoding: { content, version }, meta }: KeyringPair$Json, ignoreChecksum?: boolean): KeyringPair {
const type = version === '0' || !Array.isArray(content)
public addFromJson ({ address, encoded, encoding: { content, type, version }, meta }: KeyringPair$Json, ignoreChecksum?: boolean): KeyringPair {
const cryptoType = version === '0' || !Array.isArray(content)
? this.type
: content[1];
const encType = !Array.isArray(type)
? [type]
: type;
return this.addFromAddress(address, meta, hexToU8a(encoded), type, ignoreChecksum);
return this.addFromAddress(address, meta, isHex(encoded) ? hexToU8a(encoded) : base64Decode(encoded), cryptoType, ignoreChecksum, encType);
}
/**
@@ -133,11 +135,7 @@ export default class Keyring implements KeyringInstance {
* `addPair` to store in a keyring pair dictionary the public key of the generated pair as a key and the pair as the associated value.
*/
public addFromSeed (seed: Uint8Array, meta: KeyringPair$Meta = {}, type: KeypairType = this.type): KeyringPair {
const keypair = type === 'sr25519'
? schnorrkelFromSeed(seed)
: naclFromSeed(seed);
return this.addPair(createPair(type, keypair, meta, null));
return this.addPair(createPair({ toSS58: this.encodeAddress, type }, keypairFromSeed[type](seed), meta, null));
}
/**
@@ -153,7 +151,7 @@ export default class Keyring implements KeyringInstance {
/**
* @name createFromUri
* @summry Creates a Keypair from an suri
* @summary Creates a Keypair from an suri
* @description This creates a pair from the suri, but does not add it to the keyring
*/
public createFromUri (_suri: string, meta: KeyringPair$Meta = {}, type: KeypairType = this.type): KeyringPair {
@@ -161,8 +159,8 @@ export default class Keyring implements KeyringInstance {
const suri = _suri.startsWith('//')
? `${DEV_PHRASE}${_suri}`
: _suri;
const { password, phrase, path } = keyExtractSuri(suri);
let seed;
const { password, path, phrase } = keyExtractSuri(suri);
let seed: Uint8Array;
if (isHex(phrase, 256)) {
seed = hexToU8a(phrase);
@@ -171,11 +169,9 @@ export default class Keyring implements KeyringInstance {
const parts = str.split(' ');
if ([12, 15, 18, 21, 24].includes(parts.length)) {
// FIXME This keeps compat with older versions, but breaks compat with subkey
// seed = type === 'sr25519'
// ? mnemonicToMiniSecret(phrase, password)
// : mnemonicToSeed(phrase, password);
seed = mnemonicToMiniSecret(phrase, password);
seed = type === 'ethereum'
? mnemonicToBip39(phrase)
: mnemonicToMiniSecret(phrase, password);
} else {
assert(str.length <= 32, 'specified phrase is not a valid mnemonic and is invalid as a raw seed at > 32 bytes');
@@ -183,12 +179,18 @@ export default class Keyring implements KeyringInstance {
}
}
const keypair = type === 'sr25519'
? schnorrkelFromSeed(seed)
: naclFromSeed(seed);
const derived = keyFromPath(keypair, path, type);
// FIXME Need to support Ethereum-type derivation paths
const derived = keyFromPath(keypairFromSeed[type](seed), path, type);
return createPair(type, derived, meta, null);
return createPair({ toSS58: this.encodeAddress, type }, derived, meta, null);
}
/**
* @name encodeAddress
* @description Encodes the input into an ss58 representation
*/
public encodeAddress = (address: Uint8Array | string, ss58Format?: number): string => {
return encodeAddress(address, isUndefined(ss58Format) ? this.#ss58 : ss58Format);
}
/**
@@ -198,7 +200,7 @@ export default class Keyring implements KeyringInstance {
* a key lookup using the provided account address or public key (after decoding it).
*/
public getPair (address: string | Uint8Array): KeyringPair {
return this._pairs.get(address);
return this.#pairs.get(address);
}
/**
@@ -207,7 +209,7 @@ export default class Keyring implements KeyringInstance {
* @description Returns an array list of all the keyring pair values that are stored in the keyring pair dictionary.
*/
public getPairs (): KeyringPair[] {
return this._pairs.all();
return this.#pairs.all();
}
/**
@@ -216,7 +218,7 @@ export default class Keyring implements KeyringInstance {
* @description Returns an array list of all the public keys associated with each of the keyring pair values that are stored in the keyring pair dictionary.
*/
public getPublicKeys (): Uint8Array[] {
return this._pairs
return this.#pairs
.all()
.map(({ publicKey }): Uint8Array =>
publicKey
@@ -228,7 +230,15 @@ export default class Keyring implements KeyringInstance {
* @description Deletes the provided input address or public key from the stored Keyring Pair Dictionary.
*/
public removePair (address: string | Uint8Array): void {
this._pairs.remove(address);
this.#pairs.remove(address);
}
/**
* @name setSS58Format;
* @description Sets the ss58 format for the keyring
*/
public setSS58Format (ss58: number): void {
this.#ss58 = ss58;
}
/**
@@ -240,6 +250,6 @@ export default class Keyring implements KeyringInstance {
* may backup their account to a JSON file that contains this information.
*/
public toJson (address: string | Uint8Array, passphrase?: string): KeyringPair$Json {
return this._pairs.get(address).toJson(passphrase);
return this.#pairs.get(address).toJson(passphrase);
}
}
+36 -16
View File
@@ -2,11 +2,13 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { assert, stringToU8a, u8aFixLength } from '@polkadot/util';
import { naclDecrypt } from '@polkadot/util-crypto';
import { KeyringPair$JsonEncodingTypes } from '../types';
import { PairInfo } from './types';
import { NONCE_LENGTH, PKCS8_DIVIDER, PKCS8_HEADER, PUB_LENGTH, SEC_LENGTH, SEED_LENGTH } from './defaults';
import { assert, stringToU8a, u8aFixLength } from '@polkadot/util';
import { naclDecrypt, scryptEncode, scryptFromU8a } from '@polkadot/util-crypto';
import { ENCODING, NONCE_LENGTH, PKCS8_DIVIDER, PKCS8_HEADER, PUB_LENGTH, SEC_LENGTH, SEED_LENGTH, SCRYPT_LENGTH } from './defaults';
const SEED_OFFSET = PKCS8_HEADER.length;
@@ -14,19 +16,7 @@ type DecodeResult = PairInfo & {
secretKey: Uint8Array;
};
export default function decode (passphrase?: string, encrypted?: Uint8Array | null): DecodeResult {
assert(encrypted, 'No encrypted data available to decode');
const encoded = passphrase
? (naclDecrypt(
encrypted.subarray(NONCE_LENGTH),
encrypted.subarray(0, NONCE_LENGTH),
u8aFixLength(stringToU8a(passphrase), 256, true)
) as Uint8Array)
: encrypted;
assert(encoded, 'Unable to unencrypt using the supplied passphrase');
function decodePkcs8 (encoded: Uint8Array): DecodeResult {
const header = encoded.subarray(0, PKCS8_HEADER.length);
assert(header.toString() === PKCS8_HEADER.toString(), 'Invalid Pkcs8 header found in body');
@@ -52,3 +42,33 @@ export default function decode (passphrase?: string, encrypted?: Uint8Array | nu
secretKey
};
}
export default function decode (passphrase?: string, encrypted?: Uint8Array | null, encType: KeyringPair$JsonEncodingTypes[] = ENCODING): DecodeResult {
assert(encrypted, 'No encrypted data available to decode');
assert(passphrase || !encType.includes('xsalsa20-poly1305'), 'Password required to decode encypted data');
let encoded: Uint8Array | null = encrypted;
if (passphrase) {
let password: Uint8Array;
if (encType.includes('scrypt')) {
const { params, salt } = scryptFromU8a(encrypted);
password = scryptEncode(passphrase, salt, params).password;
encrypted = encrypted.subarray(SCRYPT_LENGTH);
} else {
password = stringToU8a(passphrase);
}
encoded = naclDecrypt(
encrypted.subarray(NONCE_LENGTH),
encrypted.subarray(0, NONCE_LENGTH),
u8aFixLength(password, 256, true)
);
}
assert(encoded, 'Unable to decode using the supplied passphrase');
return decodePkcs8(encoded);
}
+9 -1
View File
@@ -2,18 +2,26 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { KeyringPair$JsonEncodingTypes } from '../types';
const ENCODING: KeyringPair$JsonEncodingTypes[] = ['scrypt', 'xsalsa20-poly1305'];
const NONCE_LENGTH = 24;
const PKCS8_DIVIDER = new Uint8Array([161, 35, 3, 33, 0]);
const PKCS8_HEADER = new Uint8Array([48, 83, 2, 1, 1, 48, 5, 6, 3, 43, 101, 112, 4, 34, 4, 32]);
const PUB_LENGTH = 32;
const SALT_LENGTH = 32;
const SEC_LENGTH = 64;
const SEED_LENGTH = 32;
const SCRYPT_LENGTH = SALT_LENGTH + (3 * 4);
export {
ENCODING,
NONCE_LENGTH,
PKCS8_DIVIDER,
PKCS8_HEADER,
PUB_LENGTH,
SALT_LENGTH,
SEC_LENGTH,
SEED_LENGTH
SEED_LENGTH,
SCRYPT_LENGTH
};
+2 -2
View File
@@ -3,10 +3,10 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import testingPairs from '../testingPairs';
import { PKCS8_DIVIDER, PKCS8_HEADER, PUB_LENGTH, SEC_LENGTH } from './defaults';
import { PKCS8_DIVIDER, PKCS8_HEADER, NONCE_LENGTH, PUB_LENGTH, SCRYPT_LENGTH, SEC_LENGTH } from './defaults';
const PKCS8_LENGTH = PKCS8_DIVIDER.length + PKCS8_HEADER.length + PUB_LENGTH + SEC_LENGTH;
const ENCODED_LENGTH = 157;
const ENCODED_LENGTH = 16 + PKCS8_LENGTH + NONCE_LENGTH + SCRYPT_LENGTH;
const keyring = testingPairs({ type: 'ed25519' }, false);
+5 -4
View File
@@ -4,8 +4,8 @@
import { PairInfo } from './types';
import { stringToU8a, u8aConcat, u8aFixLength, assert } from '@polkadot/util';
import { naclEncrypt } from '@polkadot/util-crypto';
import { u8aConcat, assert } from '@polkadot/util';
import { naclEncrypt, scryptEncode, scryptToU8a } from '@polkadot/util-crypto';
import { PKCS8_DIVIDER, PKCS8_HEADER } from './defaults';
@@ -23,7 +23,8 @@ export default function encode ({ publicKey, secretKey }: PairInfo, passphrase?:
return encoded;
}
const { encrypted, nonce } = naclEncrypt(encoded, u8aFixLength(stringToU8a(passphrase), 256, true));
const { params, password, salt } = scryptEncode(passphrase);
const { encrypted, nonce } = naclEncrypt(encoded, password.subarray(0, 32));
return u8aConcat(nonce, encrypted);
return u8aConcat(scryptToU8a(salt, params), nonce, encrypted);
}
+29 -3
View File
@@ -2,7 +2,9 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { cryptoWaitReady, setSS58Format } from '@polkadot/util-crypto';
import { cryptoWaitReady, encodeAddress as toSS58, setSS58Format } from '@polkadot/util-crypto';
import { hexToU8a } from '@polkadot/util';
import { PAIRS } from '../testing';
import testingPairs from '../testingPairs';
@@ -23,6 +25,11 @@ describe('pair', (): void => {
).toEqual(
new Uint8Array([209, 114, 167, 76, 218, 76, 134, 89, 18, 195, 43, 160, 168, 10, 87, 174, 105, 171, 174, 65, 14, 92, 203, 89, 222, 232, 78, 47, 68, 50, 219, 79])
);
expect(
keyring.alice.addressRaw
).toEqual(
new Uint8Array([209, 114, 167, 76, 218, 76, 134, 89, 18, 195, 43, 160, 168, 10, 87, 174, 105, 171, 174, 65, 14, 92, 203, 89, 222, 232, 78, 47, 68, 50, 219, 79])
);
});
it('allows signing', (): void => {
@@ -79,18 +86,37 @@ describe('pair', (): void => {
const PASS = 'testing';
const encoded = keyring.alice.encodePkcs8(PASS);
const pair = createPair('sr25519', { publicKey: keyring.alice.publicKey });
const pair = createPair({ toSS58, type: 'sr25519' }, { publicKey: keyring.alice.publicKey });
pair.decodePkcs8(PASS, encoded);
expect(pair.isLocked).toEqual(false);
});
it('allows derivation on the pair', (): void => {
const alice = createPair('sr25519', { publicKey: PAIRS[0].publicKey, secretKey: PAIRS[0].secretKey }, {});
const alice = createPair({ toSS58, type: 'sr25519' }, { publicKey: PAIRS[0].publicKey, secretKey: PAIRS[0].secretKey }, {});
const stash = alice.derive('//stash');
const soft = alice.derive('//funding/0');
expect(stash.publicKey).toEqual(PAIRS[1].publicKey);
expect(soft.address).toEqual('5ECQNn7UueWHPFda5qUi4fTmTtyCnPvGnuoyVVSj5CboJh9J');
});
it('fails to sign when locked', (): void => {
const pair = createPair({ toSS58, type: 'sr25519' }, { publicKey: keyring.alice.publicKey });
expect(pair.isLocked).toEqual(true);
expect((): Uint8Array =>
pair.sign(new Uint8Array([0]))
).toThrow('Cannot sign with a locked key pair');
});
describe('ethereum', (): void => {
it('has a valid address from a known public', (): void => {
const pair = createPair({ toSS58, type: 'ethereum' }, { publicKey: hexToU8a('0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077') });
expect(pair.address).toEqual('0x4119b2e6c3Cb618F4f0B93ac77f9BeeC7FF02887');
expect(pair.addressRaw).toEqual(hexToU8a('0x4119b2e6c3Cb618F4f0B93ac77f9BeeC7FF02887'));
});
});
});
+101 -58
View File
@@ -3,58 +3,65 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { Keypair, KeypairType } from '@polkadot/util-crypto/types';
import { KeyringPair, KeyringPair$Json, KeyringPair$Meta, SignOptions } from '../types';
import { KeyringPair, KeyringPair$Json, KeyringPair$JsonEncodingTypes, KeyringPair$Meta, SignOptions } from '../types';
import { PairInfo } from './types';
import { u8aConcat, assert } from '@polkadot/util';
import { encodeAddress, keyExtractPath, keyFromPath, naclKeypairFromSeed as naclFromSeed, naclSign, naclVerify, schnorrkelKeypairFromSeed as schnorrkelFromSeed, schnorrkelSign, schnorrkelVerify } from '@polkadot/util-crypto';
import { assert, u8aConcat, u8aToHex } from '@polkadot/util';
import { blake2AsU8a, ethereumEncode, keccakAsU8a, keyExtractPath, keyFromPath, naclKeypairFromSeed as naclFromSeed, naclSign, naclVerify, schnorrkelKeypairFromSeed as schnorrkelFromSeed, schnorrkelSign, schnorrkelVerify, secp256k1Expand, secp256k1KeypairFromSeed as secp256k1FromSeed, secp256k1Sign, secp256k1Verify, secp256k1Compress } from '@polkadot/util-crypto';
import decode from './decode';
import encode from './encode';
import toJson from './toJson';
interface Setup {
toSS58: (publicKey: Uint8Array) => string;
type: KeypairType;
}
const SIG_TYPE_NONE = new Uint8Array();
const SIG_TYPE_ED25519 = new Uint8Array([0]);
const SIG_TYPE_SR25519 = new Uint8Array([1]);
// const SIG_TYPE_ECDSA = new Uint8Array([2]);
const TYPE_FROM_SEED = {
ecdsa: secp256k1FromSeed,
ed25519: naclFromSeed,
ethereum: secp256k1FromSeed,
sr25519: schnorrkelFromSeed
};
const TYPE_PREFIX = {
ecdsa: new Uint8Array([2]),
ed25519: new Uint8Array([0]),
ethereum: new Uint8Array([2]),
sr25519: new Uint8Array([1])
};
const TYPE_SIGNATURE = {
ecdsa: (m: Uint8Array, p: Partial<Keypair>) => secp256k1Sign(m, p, 'blake2'),
ed25519: naclSign,
ethereum: (m: Uint8Array, p: Partial<Keypair>) => secp256k1Sign(m, p, 'keccak'),
sr25519: schnorrkelSign
};
const TYPE_ADDRESS = {
ecdsa: (p: Uint8Array) => p.length > 32 ? blake2AsU8a(p) : p,
ed25519: (p: Uint8Array) => p,
ethereum: (p: Uint8Array) => keccakAsU8a(secp256k1Expand(p)),
sr25519: (p: Uint8Array) => p
};
const TYPE_VERIFY = {
ecdsa: (m: Uint8Array, s: Uint8Array, p: Uint8Array) => secp256k1Verify(m, s, TYPE_ADDRESS.ecdsa(p), 'blake2'),
ed25519: naclVerify,
ethereum: (m: Uint8Array, s: Uint8Array, p: Uint8Array) => secp256k1Verify(m, s, TYPE_ADDRESS.ethereum(p), 'keccak', true),
sr25519: schnorrkelVerify
};
function isEmpty (u8a: Uint8Array): boolean {
return u8a.reduce((count, u8): number => count + u8, 0) === 0;
return u8a.reduce((count, u8) => count + u8, 0) === 0;
}
function isSr25519 (type: KeypairType): boolean {
return type === 'sr25519';
}
function fromSeed (type: KeypairType, seed: Uint8Array): Keypair {
return isSr25519(type)
? schnorrkelFromSeed(seed)
: naclFromSeed(seed);
}
function multiSignaturePrefix (type: KeypairType): Uint8Array {
return isSr25519(type)
? SIG_TYPE_SR25519
: SIG_TYPE_ED25519;
}
function sign (type: KeypairType, message: Uint8Array, pair: Partial<Keypair>, { withType = false }: SignOptions = {}): Uint8Array {
return u8aConcat(
// for multi-signatures, i.e. with indicator, append the signature type as per
// the MultiSignature enum
withType
? multiSignaturePrefix(type)
: SIG_TYPE_NONE,
isSr25519(type)
? schnorrkelSign(message, pair)
: naclSign(message, pair)
);
}
function verify (type: KeypairType, message: Uint8Array, signature: Uint8Array, publicKey: Uint8Array): boolean {
return isSr25519(type)
? schnorrkelVerify(message, signature, publicKey)
: naclVerify(message, signature, publicKey);
// Not 100% correct, since it can be a Uint8Array, but an invalid one - just say "undefined" is anything non-valid
function isLocked (secretKey?: Uint8Array): secretKey is undefined {
return !secretKey || secretKey.length === 0 || isEmpty(secretKey);
}
/**
@@ -88,57 +95,93 @@ function verify (type: KeypairType, message: Uint8Array, signature: Uint8Array,
* an `encoded` property that is assigned with the encoded public key in hex format, and an `encoding`
* property that indicates whether the public key value of the `encoded` property is encoded or not.
*/
export default function createPair (type: KeypairType, { publicKey, secretKey }: PairInfo, meta: KeyringPair$Meta = {}, encoded: Uint8Array | null = null): KeyringPair {
export default function createPair ({ toSS58, type }: Setup, { publicKey, secretKey }: PairInfo, meta: KeyringPair$Meta = {}, encoded: Uint8Array | null = null, encTypes?: KeyringPair$JsonEncodingTypes[]): KeyringPair {
const recode = (passphrase?: string): Uint8Array => {
encoded = encode({ publicKey, secretKey }, passphrase); // re-encode, latest version
encTypes = undefined; // swap to defaults, latest version follows
return encoded;
};
const encodeAddress = (): string => {
const raw = TYPE_ADDRESS[type](publicKey);
return type === 'ethereum'
? ethereumEncode(raw)
: toSS58(raw);
};
return {
get address (): string {
return encodeAddress(publicKey);
return encodeAddress();
},
get addressRaw (): Uint8Array {
const raw = TYPE_ADDRESS[type](publicKey);
return type === 'ethereum'
? raw.slice(-20)
: raw;
},
get isLocked (): boolean {
return isLocked(secretKey);
},
get meta (): KeyringPair$Meta {
return meta;
},
get isLocked (): boolean {
return !secretKey || secretKey.length === 0 || isEmpty(secretKey);
},
get publicKey (): Uint8Array {
return publicKey;
},
get type (): KeypairType {
return type;
},
decodePkcs8: (passphrase?: string, _encoded?: Uint8Array | null): void => {
const decoded = decode(passphrase, _encoded || encoded);
// eslint-disable-next-line sort-keys
decodePkcs8: (passphrase?: string, userEncoded?: Uint8Array | null): void => {
const decoded = decode(passphrase, userEncoded || encoded, encTypes);
if (decoded.secretKey.length === 64) {
publicKey = decoded.publicKey;
secretKey = decoded.secretKey;
} else {
const pair = fromSeed(type, decoded.secretKey);
const pair = TYPE_FROM_SEED[type](decoded.secretKey);
publicKey = pair.publicKey;
secretKey = pair.secretKey;
}
},
derive: (suri: string, meta?: KeyringPair$Meta): KeyringPair => {
assert(secretKey, 'Cannot derive on a locked keypair');
assert(!isLocked(secretKey), 'Cannot derive on a locked keypair');
const { path } = keyExtractPath(suri);
const derived = keyFromPath({ publicKey, secretKey: secretKey }, path, type);
const derived = keyFromPath({ publicKey, secretKey }, path, type);
return createPair(type, derived, meta, null);
return createPair({ toSS58, type }, derived, meta, null);
},
encodePkcs8: (passphrase?: string): Uint8Array =>
encode({ publicKey, secretKey }, passphrase),
recode(passphrase),
lock: (): void => {
secretKey = new Uint8Array(0);
secretKey = new Uint8Array();
},
setMeta: (additional: KeyringPair$Meta): void => {
meta = { ...meta, ...additional };
},
sign: (message: Uint8Array, options?: SignOptions): Uint8Array =>
sign(type, message, { publicKey, secretKey }, options),
toJson: (passphrase?: string): KeyringPair$Json =>
toJson(type, { meta, publicKey }, encode({ publicKey, secretKey }, passphrase), !!passphrase),
sign: (message: Uint8Array, options: SignOptions = {}): Uint8Array => {
assert(!isLocked(secretKey), 'Cannot sign with a locked key pair');
return u8aConcat(
options.withType
? TYPE_PREFIX[type]
: SIG_TYPE_NONE,
TYPE_SIGNATURE[type](message, { publicKey, secretKey })
);
},
toJson: (passphrase?: string): KeyringPair$Json => {
const address = ['ecdsa', 'ethereum'].includes(type)
? u8aToHex(secp256k1Compress(publicKey))
: encodeAddress();
return toJson(type, { address, meta }, recode(passphrase), !!passphrase);
},
verify: (message: Uint8Array, signature: Uint8Array): boolean =>
verify(type, message, signature, publicKey)
TYPE_VERIFY[type](message, signature, publicKey)
};
}
+3 -2
View File
@@ -25,8 +25,8 @@ const json: KeyringPair$Json = {
export default function everybody (): KeyringPair {
const pair: KeyringPair = {
type: 'ed25519',
address,
addressRaw: publicKey,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
decodePkcs8: (passphrase?: string, encoded?: Uint8Array): void =>
undefined,
@@ -36,11 +36,11 @@ export default function everybody (): KeyringPair {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
encodePkcs8: (passphrase?: string): Uint8Array =>
new Uint8Array(0),
meta,
isLocked: true,
lock: (): void => {
// no locking, it is always locked
},
meta,
publicKey,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
setMeta: (meta: KeyringPair$Meta): void =>
@@ -51,6 +51,7 @@ export default function everybody (): KeyringPair {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
toJson: (passphrase?: string): KeyringPair$Json =>
json,
type: 'ed25519',
// eslint-disable-next-line @typescript-eslint/no-unused-vars
verify: (message: Uint8Array, signature: Uint8Array): boolean =>
false
+8 -8
View File
@@ -12,15 +12,15 @@ describe('toJson', (): void => {
keyring.alice.toJson()
).toMatchObject({
address: '5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaQua',
encoded: '0x3053020101300506032b657004220420416c696365202020202020202020202020202020202020202020202020202020d172a74cda4c865912c32ba0a80a57ae69abae410e5ccb59dee84e2f4432db4fa123032100d172a74cda4c865912c32ba0a80a57ae69abae410e5ccb59dee84e2f4432db4f',
encoded: 'MFMCAQEwBQYDK2VwBCIEIEFsaWNlICAgICAgICAgICAgICAgICAgICAgICAgICAg0XKnTNpMhlkSwyugqApXrmmrrkEOXMtZ3uhOL0Qy20+hIwMhANFyp0zaTIZZEsMroKgKV65pq65BDlzLWd7oTi9EMttP',
encoding: {
content: ['pkcs8', 'ed25519'],
type: 'none',
version: '2'
type: ['none'],
version: '3'
},
meta: {
name: 'alice',
isTesting: true
isTesting: true,
name: 'alice'
}
});
});
@@ -28,13 +28,13 @@ describe('toJson', (): void => {
it('creates an encoded output with passphrase', (): void => {
const json = keyring.alice.toJson('testing');
expect(json.encoded).toHaveLength(316);
expect(json.encoded).toHaveLength(268);
expect(json).toMatchObject({
address: '5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaQua',
encoding: {
content: ['pkcs8', 'ed25519'],
type: 'xsalsa20-poly1305',
version: '2'
type: ['scrypt', 'xsalsa20-poly1305'],
version: '3'
}
});
});
+20 -12
View File
@@ -3,25 +3,33 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { KeypairType } from '@polkadot/util-crypto/types';
import { KeyringPair$Json, KeyringPair$Meta } from '../types';
import { KeyringPair$Json, KeyringPair$JsonEncodingTypes, KeyringPair$Meta } from '../types';
import { u8aToHex } from '@polkadot/util';
import { encodeAddress } from '@polkadot/util-crypto';
import { base64Encode } from '@polkadot/util-crypto';
type PairStateJson = KeyringPair$Meta & {
publicKey: Uint8Array;
};
import { ENCODING } from './defaults';
export default function toJson (type: KeypairType, { publicKey, meta }: PairStateJson, encoded: Uint8Array, isEncrypted: boolean): KeyringPair$Json {
interface PairStateJson {
address: string;
meta: KeyringPair$Meta;
}
// version 2 - nonce, encoded (previous)
// version 3 - salt, nonce, encoded
const VERSION = '3';
const ENC_NONE: KeyringPair$JsonEncodingTypes[] = ['none'];
export default function toJson (type: KeypairType, { address, meta }: PairStateJson, encoded: Uint8Array, isEncrypted: boolean): KeyringPair$Json {
return {
address: encodeAddress(publicKey),
encoded: u8aToHex(encoded),
address,
encoded: base64Encode(encoded),
encoding: {
content: ['pkcs8', type],
type: isEncrypted
? 'xsalsa20-poly1305'
: 'none',
version: '2'
? ENCODING
: ENC_NONE,
version: VERSION
},
meta
};
+5 -9
View File
@@ -10,24 +10,20 @@ import { decodeAddress } from '@polkadot/util-crypto';
type KeyringPairMap = Record<string, KeyringPair>;
export default class Pairs implements KeyringPairs {
private _map: KeyringPairMap;
constructor () {
this._map = {};
}
readonly #map: KeyringPairMap = {};
public add (pair: KeyringPair): KeyringPair {
this._map[pair.publicKey.toString()] = pair;
this.#map[decodeAddress(pair.address).toString()] = pair;
return pair;
}
public all (): KeyringPair[] {
return Object.values(this._map);
return Object.values(this.#map);
}
public get (address: string | Uint8Array): KeyringPair {
const pair = this._map[decodeAddress(address).toString()];
const pair = this.#map[decodeAddress(address).toString()];
assert(pair, (): string => {
const formatted: string = isU8a(address) || isHex(address)
@@ -41,6 +37,6 @@ export default class Pairs implements KeyringPairs {
}
public remove (address: string | Uint8Array): void {
delete this._map[decodeAddress(address).toString()];
delete this.#map[decodeAddress(address).toString()];
}
}
+18 -18
View File
@@ -23,44 +23,44 @@ interface PairDef {
// adding the keys when only the keyring is used.
export const PAIRS: PairDef[] = [
{
seed: 'Alice',
publicKey: hexToU8a('0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'),
secretKey: hexToU8a('0x98319d4ff8a9508c4bb0cf0b5a78d760a0b2082c02775e6e82370816fedfff48925a225d97aa00682d6a59b95b18780c10d7032336e88f3442b42361f4a66011'),
publicKey: hexToU8a('0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d')
seed: 'Alice'
},
{
seed: 'Alice//stash',
publicKey: hexToU8a('0xbe5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f'),
secretKey: hexToU8a('0xe8da6c9d810e020f5e3c7f5af2dea314cbeaa0d72bc6421e92c0808a0c584a6046ab28e97c3ffc77fe12b5a4d37e8cd4afbfebbf2391ffc7cb07c0f38c023efd'),
publicKey: hexToU8a('0xbe5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f')
seed: 'Alice//stash'
},
{
seed: 'Bob',
publicKey: hexToU8a('0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48'),
secretKey: hexToU8a('0x081ff694633e255136bdb456c20a5fc8fed21f8b964c11bb17ff534ce80ebd5941ae88f85d0c1bfc37be41c904e1dfc01de8c8067b0d6d5df25dd1ac0894a325'),
publicKey: hexToU8a('0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48')
seed: 'Bob'
},
{
seed: 'Bob//stash',
publicKey: hexToU8a('0xfe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e'),
secretKey: hexToU8a('0xc006507cdfc267a21532394c49ca9b754ca71de21e15a1cdf807c7ceab6d0b6c3ed408d9d35311540dcd54931933e67cf1ea10d46f75408f82b789d9bd212fde'),
publicKey: hexToU8a('0xfe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e')
seed: 'Bob//stash'
},
{
seed: 'Charlie',
publicKey: hexToU8a('0x90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22'),
secretKey: hexToU8a('0xa8f2d83016052e5d6d77b2f6fd5d59418922a09024cda701b3c34369ec43a7668faf12ff39cd4e5d92bb773972f41a7a5279ebc2ed92264bed8f47d344f8f18c'),
publicKey: hexToU8a('0x90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22')
seed: 'Charlie'
},
{
seed: 'Dave',
publicKey: hexToU8a('0x306721211d5404bd9da88e0204360a1a9ab8b87c66c1bc2fcdd37f3c2222cc20'),
secretKey: hexToU8a('0x20e05482ca4677e0edbc58ae9a3a59f6ed3b1a9484ba17e64d6fe8688b2b7b5d108c4487b9323b98b11fe36cb301b084e920f7b7895536809a6d62a451b25568'),
publicKey: hexToU8a('0x306721211d5404bd9da88e0204360a1a9ab8b87c66c1bc2fcdd37f3c2222cc20')
seed: 'Dave'
},
{
seed: 'Eve',
publicKey: hexToU8a('0xe659a7a1628cdd93febc04a4e0646ea20e9f5f0ce097d9a05290d4a9e054df4e'),
secretKey: hexToU8a('0x683576abfd5dc35273e4264c23095a1bf21c14517bece57c7f0cc5c0ed4ce06a3dbf386b7828f348abe15d76973a72009e6ef86a5c91db2990cb36bb657c6587'),
publicKey: hexToU8a('0xe659a7a1628cdd93febc04a4e0646ea20e9f5f0ce097d9a05290d4a9e054df4e')
seed: 'Eve'
},
{
seed: 'Ferdie',
publicKey: hexToU8a('0x1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c'),
secretKey: hexToU8a('0xb835c20f450079cf4f513900ae9faf8df06ad86c681884122c752a4b2bf74d4303e4f21bc6cc62bb4eeed5a9cce642c25e2d2ac1464093b50f6196d78e3a7426'),
publicKey: hexToU8a('0x1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c')
seed: 'Ferdie'
}
];
@@ -73,7 +73,7 @@ export const PAIRS: PairDef[] = [
export default function testKeyring (options: KeyringOptions = {}, isDerived = true): KeyringInstance {
const keyring = new Keyring(options);
PAIRS.forEach(({ name, publicKey, secretKey, seed, type }): void => {
PAIRS.forEach(({ name, publicKey, secretKey, seed, type = 'sr25519' }): void => {
const meta = {
isTesting: true,
name: name || seed.replace('//', '_').toLowerCase()
@@ -82,7 +82,7 @@ export default function testKeyring (options: KeyringOptions = {}, isDerived = t
const pair = !isDerived && !name
? keyring.addFromUri(seed, meta, options.type)
: keyring.addPair(
createPair(type || 'sr25519', { publicKey, secretKey }, meta)
createPair({ toSS58: keyring.encodeAddress, type }, { publicKey, secretKey }, meta)
);
pair.lock = (): void => {
+6 -9
View File
@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/class-name-casing */
// Copyright 2017-2020 @polkadot/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.
@@ -7,22 +6,19 @@ import { Prefix } from '@polkadot/util-crypto/address/types';
import { KeypairType } from '@polkadot/util-crypto/types';
export interface KeyringOptions {
// @deprecated
addressPrefix?: Prefix;
ss58Format?: Prefix;
type?: KeypairType;
}
export interface KeyringPair$Meta {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[index: string]: any;
}
export type KeyringPair$Meta = Record<string, unknown>;
export type KeyringPair$JsonVersion = '0' | '1' | '2';
export type KeyringPair$JsonVersion = '0' | '1' | '2' | '3';
export type KeyringPair$JsonEncodingTypes = 'none' | 'scrypt' | 'xsalsa20-poly1305';
export interface KeyringPair$JsonEncoding {
content: ['pkcs8', KeypairType];
type: 'xsalsa20-poly1305' | 'none';
type: KeyringPair$JsonEncodingTypes | KeyringPair$JsonEncodingTypes[];
version: KeyringPair$JsonVersion;
}
@@ -39,6 +35,7 @@ export interface SignOptions {
export interface KeyringPair {
readonly address: string;
readonly addressRaw: Uint8Array;
readonly meta: KeyringPair$Meta;
readonly isLocked: boolean;
readonly publicKey: Uint8Array;
+17 -12
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/util-crypto",
"version": "2.0.1",
"version": "3.4.1",
"description": "A collection of useful crypto utilities for @polkadot",
"main": "index.js",
"keywords": [
@@ -25,20 +25,25 @@
},
"homepage": "https://github.com/polkadot-js/common/tree/master/packages/util-crypto#readme",
"dependencies": {
"@babel/runtime": "^7.8.3",
"@polkadot/util": "^2.0.1",
"@polkadot/wasm-crypto": "^0.20.1",
"@types/bs58": "^4.0.0",
"@types/elliptic": "^6.4.12",
"@types/pbkdf2": "^3.0.0",
"@types/xxhashjs": "^0.2.1",
"base-x": "^3.0.7",
"@babel/runtime": "^7.11.2",
"@polkadot/util": "3.4.1",
"@polkadot/wasm-crypto": "^1.4.1",
"base-x": "^3.0.8",
"bip39": "^3.0.2",
"blakejs": "^1.1.0",
"bs58": "^4.0.1",
"elliptic": "^6.5.2",
"bn.js": "^5.1.3",
"elliptic": "^6.5.3",
"js-sha3": "^0.8.0",
"tweetnacl": "^1.0.2",
"pbkdf2": "^3.1.1",
"scryptsy": "^2.1.0",
"tweetnacl": "^1.0.3",
"xxhashjs": "^0.2.2"
},
"devDependencies": {
"@types/bn.js": "^4.11.6",
"@types/elliptic": "^6.4.12",
"@types/pbkdf2": "^3.1.0",
"@types/scryptsy": "^2.0.0",
"@types/xxhashjs": "^0.2.2"
}
}
@@ -17,6 +17,12 @@ describe('checkAddress', (): void => {
).toEqual([true, null]);
});
it('fails when an invalid base58 character is supplied', (): void => {
expect(
checkAddress('5EnxIUmEbw8DkENKiYuZ1DwQuMoB2UWEQJZZXrTsxoz7SpgG', 2)
).toEqual([false, 'Invalid base58 character "I" (0x49) at index 4']);
});
it('fails with invalid prefix when checking Substrate against Kusama prefix', (): void => {
expect(
checkAddress('5EnxxUmEbw8DkENKiYuZ1DwQuMoB2UWEQJZZXrTsxoz7SpgG', 2)
+17 -17
View File
@@ -4,13 +4,24 @@
import { Prefix } from './types';
import bs58 from 'bs58';
import base58Decode from '../base58/decode';
import checkChecksum from './checkChecksum';
import defaults from './defaults';
import sshash from './sshash';
/**
* @name checkAddress
* @summary Validates an ss58 address.
* @description
* From the provided input, validate that the address is a valid input.
*/
export default function check (address: string, prefix: Prefix): [boolean, string | null] {
const decoded = bs58.decode(address);
let decoded;
try {
decoded = base58Decode(address);
} catch (error) {
return [false, (error as Error).message];
}
if (decoded[0] !== prefix) {
return [false, `Prefix mismatch, expected ${prefix}, found ${decoded[0]}`];
@@ -18,18 +29,7 @@ export default function check (address: string, prefix: Prefix): [boolean, strin
return [false, 'Invalid decoded address length'];
}
const isPublicKey = decoded.length === 35;
const [isValid] = checkChecksum(decoded);
// non-publicKeys has 1 byte checksums, else default to 2
const endPos = decoded.length - (isPublicKey ? 2 : 1);
// calculate the hash and do the checksum byte checks
const hash = sshash(decoded.subarray(0, endPos));
const checks = isPublicKey
? decoded[decoded.length - 2] === hash[0] && decoded[decoded.length - 1] === hash[1]
: decoded[decoded.length - 1] === hash[0];
return !checks
? [false, 'Invalid decoded address checksum']
: [true, null];
return [isValid, isValid ? null : 'Invalid decoded address checksum'];
}
@@ -0,0 +1,22 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 sshash from './sshash';
export default function checkChecksum (decoded: Uint8Array): [boolean, number] {
const isPublicKey = [35, 36].includes(decoded.length);
// non-publicKeys has 1 byte checksums, else default to 2
const length = decoded.length - (isPublicKey ? 2 : 1);
// calculate the hash and do the checksum byte checks
const hash = sshash(decoded.subarray(0, length));
// see if the hash actually matches
const isValid = isPublicKey
? decoded[decoded.length - 2] === hash[0] && decoded[decoded.length - 1] === hash[1]
: decoded[decoded.length - 1] === hash[0];
return [isValid, length];
}
@@ -2,12 +2,12 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { stringToU8a, u8aToHex } from '@polkadot/util';
import { stringToU8a, u8aToHex, hexToU8a } from '@polkadot/util';
import testingPairs, { TestKeyringMap } from '../../../keyring/src/testingPairs';
import decode from './decode';
describe('decode', (): void => {
describe('decodeAddress', (): void => {
let keyring: TestKeyringMap;
beforeAll((): void => {
@@ -74,6 +74,14 @@ describe('decode', (): void => {
).toEqual(new Uint8Array([42, 44, 10, 0, 0, 0, 0, 0]));
});
it('decodes a 33-byte address', (): void => {
expect(
decode('KWCv1L3QX9LDPwY4VzvLmarEmXjVJidUzZcinvVnmxAJJCBou')
).toEqual(
hexToU8a('0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077')
);
});
it.skip('allows invalid prefix (in list)', (): void => {
expect(
(): Uint8Array => decode('6GfvWUvHvU8otbZ7sFhXH4eYeMcKdUkL61P3nFy52efEPVUx')
@@ -94,4 +102,10 @@ describe('decode', (): void => {
(): Uint8Array => decode('5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaDwU')
).toThrow(/address checksum/);
});
it('fails when invalid base58 encoded address is found', (): void => {
expect(
() => u8aToHex(decode('F3opIRbN5ZbjJNU511Kj2TLuzFcDq9BGduA9TgiECafpg29'))
).toThrow(/Decoding F3opIRbN5ZbjJNU511Kj2TLuzFcDq9BGduA9TgiECafpg29: Invalid base58 character "I" \(0x49\) at index 4/);
});
});
+14 -18
View File
@@ -6,11 +6,11 @@ import { Prefix } from './types';
// Original implementation: https://github.com/paritytech/polka-ui/blob/4858c094684769080f5811f32b081dd7780b0880/src/polkadot.js#L6
import bs58 from 'bs58';
import { assert, bufferToU8a, isHex, isU8a, u8aToU8a } from '@polkadot/util';
import { assert, isHex, isU8a, u8aToU8a } from '@polkadot/util';
import base58Decode from '../base58/decode';
import checkChecksum from './checkChecksum';
import defaults from './defaults';
import sshash from './sshash';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export default function decode (encoded: string | Uint8Array, ignoreChecksum?: boolean, ss58Format: Prefix = 99): Uint8Array {
@@ -18,30 +18,26 @@ export default function decode (encoded: string | Uint8Array, ignoreChecksum?: b
return u8aToU8a(encoded);
}
const decoded = bufferToU8a(bs58.decode(encoded));
const error = (message: string): string =>
`Decoding ${encoded}: ${message}`;
const wrapError = (message: string) => `Decoding ${encoded as string}: ${message}`;
let decoded;
try {
decoded = base58Decode(encoded);
} catch (error) {
throw new Error(wrapError((error as Error).message));
}
// assert(defaults.allowedPrefix.includes(decoded[0] as Prefix), error('Invalid decoded address prefix'));
assert(defaults.allowedEncodedLengths.includes(decoded.length), error('Invalid decoded address length'));
assert(defaults.allowedEncodedLengths.includes(decoded.length), wrapError('Invalid decoded address length'));
// TODO Unless it is an "use everywhere" prefix, throw an error
// if (decoded[0] !== prefix) {
// console.log(`WARN: Expected ${prefix}, found ${decoded[0]}`);
// }
const isPublicKey = decoded.length === 35;
const [isValid, endPos] = checkChecksum(decoded);
// non-publicKeys has 1 byte checksums, else default to 2
const endPos = decoded.length - (isPublicKey ? 2 : 1);
// calculate the hash and do the checksum byte checks
const hash = sshash(decoded.subarray(0, endPos));
const checks = isPublicKey
? decoded[decoded.length - 2] === hash[0] && decoded[decoded.length - 1] === hash[1]
: decoded[decoded.length - 1] === hash[0];
assert(ignoreChecksum || checks, error('Invalid decoded address checksum'));
assert(ignoreChecksum || isValid, wrapError('Invalid decoded address checksum'));
return decoded.slice(1, endPos);
}
+2 -2
View File
@@ -5,9 +5,9 @@
import { allowedSS58 } from './ss58';
const defaults = {
allowedDecodedLengths: [1, 2, 4, 8, 32],
allowedDecodedLengths: [1, 2, 4, 8, 32, 33],
// publicKey has prefix + 2 checksum bytes, short only prefix + 1 checksum byte
allowedEncodedLengths: [3, 4, 6, 10, 35],
allowedEncodedLengths: [3, 4, 6, 10, 35, 36],
allowedPrefix: allowedSS58,
prefix: 42
};
@@ -0,0 +1,25 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { waitReady } from '@polkadot/wasm-crypto';
import derive from './derive';
describe('deriveAddress', (): void => {
beforeEach(async (): Promise<void> => {
await waitReady();
});
it('derives a known path', (): void => {
expect(
derive('5CZtJLXtVzrBJq1fMWfywDa6XuRwXekGdShPR4b8i9GWSbzB', '/joe/polkadot/0')
).toEqual('5GZ4srnepXvdsuNVoxCGyVZd8ScDm4gkGLTKuaGARy9akjTa');
});
it('fails on hard paths', (): void => {
expect(
() => derive('5CZtJLXtVzrBJq1fMWfywDa6XuRwXekGdShPR4b8i9GWSbzB', '//bob')
).toThrow(/Expected suri to contain a combination of non-hard paths/);
});
});
@@ -0,0 +1,29 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 './types';
import { assert } from '@polkadot/util';
import DeriveJunction from '../key/DeriveJunction';
import { keyExtractPath } from '../key';
import { schnorrkelDerivePublic } from '../schnorrkel';
import decode from './decode';
import encode from './encode';
/**
* @name deriveAddress
* @summary Creates a sr25519 derived address from the supplied and path.
* @description
* Creates a sr25519 derived address based on the input address/publicKey and the uri supplied.
*/
export default function deriveAddress (who: Uint8Array | string, suri: string, ss58Format?: Prefix): string {
const { path } = keyExtractPath(suri);
assert(path.length && !path.some((path) => path.isHard), 'Expected suri to contain a combination of non-hard paths');
return encode(path.reduce((publicKey: Uint8Array, path: DeriveJunction): Uint8Array => {
return schnorrkelDerivePublic(publicKey, path.chainCode);
}, decode(who)), ss58Format);
}
@@ -2,7 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import testingPairs from '../../../keyring/src/testingPairs';
import testingPairs from '@polkadot/keyring/testingPairs';
import encode from './encode';
const keyring = testingPairs({ type: 'ed25519' }, false);
@@ -20,6 +21,12 @@ describe('encode', (): void => {
).toEqual('7sL6eNJj5ZGV5cn3hhV2deRUsivXfBfMH76wCALCqWj1EKzv');
});
it('can re-encode an address to Polkadot live', (): void => {
expect(
encode('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY', 0)
).toEqual('15oF4uVJwmo4TdGW7VfQxNLavjCXviqxT9S1MgbjMNHr6Sp5');
});
it('fails when non-valid publicKey provided', (): void => {
expect(
(): string => encode(
@@ -60,11 +67,17 @@ describe('encode', (): void => {
).toEqual('as7QnGMf');
});
it('enodes a 8-byte address', (): void => {
it('encodes a 8-byte address', (): void => {
expect(
encode(
new Uint8Array([42, 44, 10, 0, 0, 0, 0, 0]), 68
)
).toEqual('4q7qY5RBG7Z4wv');
});
it('encodes an 33-byte address', (): void => {
expect(
encode('0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077')
).toEqual('KWCv1L3QX9LDPwY4VzvLmarEmXjVJidUzZcinvVnmxAJJCBou');
});
});
+6 -9
View File
@@ -6,9 +6,9 @@ import { Prefix } from './types';
// Original implementation: https://github.com/paritytech/polka-ui/blob/4858c094684769080f5811f32b081dd7780b0880/src/polkadot.js#L34
import bs58 from 'bs58';
import { assert, u8aConcat, u8aToBuffer } from '@polkadot/util';
import { assert, u8aConcat } from '@polkadot/util';
import base58Encode from '../base58/encode';
import decode from './decode';
import defaults from './defaults';
import sshash from './sshash';
@@ -17,16 +17,13 @@ export default function encode (_key: Uint8Array | string, ss58Format: Prefix =
// decode it, this means we can re-encode an address
const key = decode(_key);
assert(defaults.allowedDecodedLengths.includes(key.length), `Expected a valid key to convert, with length ${defaults.allowedDecodedLengths}`);
const isPublicKey = key.length === 32;
assert(defaults.allowedDecodedLengths.includes(key.length), `Expected a valid key to convert, with length ${defaults.allowedDecodedLengths.join(', ')}`);
const isPublicKey = [32, 33].includes(key.length);
const input = u8aConcat(new Uint8Array([ss58Format]), key);
const hash = sshash(input);
return bs58.encode(
u8aToBuffer(
u8aConcat(input, hash.subarray(0, isPublicKey ? 2 : 1))
)
return base58Encode(
u8aConcat(input, hash.subarray(0, isPublicKey ? 2 : 1))
);
}
@@ -0,0 +1,13 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 encodeDerivedAddress from './encodeDerived';
describe('encodeDerivedAddress', (): void => {
it('creates a valid known derived address', (): void => {
expect(
encodeDerivedAddress('5GvUh7fGKsdBEh5XpypkfkGuf7j3vXLxH9BdxjxnJNVXRYi1', 0)
).toEqual('5E5XxqPxm7QbEs6twYfp3tyjXidn4kqRrNPH4o6JK9JSLUeD');
});
});
@@ -0,0 +1,21 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 './types';
import BN from 'bn.js';
import decode from './decode';
import encode from './encode';
import keyDerived from './keyDerived';
/**
* @name encodeDerivedAddress
* @summary Creates a derived address as used in Substrate utility.
* @description
* Creates a Substrate derived address based on the input address/publicKey and the index supplied.
*/
export default function encodeDerivedAddress (who: Uint8Array | string, index: BigInt | BN | number, ss58Format?: Prefix): string {
return encode(keyDerived(decode(who), index), ss58Format);
}
@@ -0,0 +1,17 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 encodeMultiAddress from './encodeMulti';
describe('encodeMultiAddress', (): void => {
it('creates a valid known multi address', (): void => {
expect(
encodeMultiAddress([
'5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
'5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty',
'5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y'
], 2)
).toEqual('5DjYJStmdZ2rcqXbXGX7TW85JsrW6uG4y9MUcLq2BoPMpRA7');
});
});
@@ -0,0 +1,20 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 './types';
import BN from 'bn.js';
import encode from './encode';
import keyMulti from './keyMulti';
/**
* @name encodeMultiAddress
* @summary Creates a multisig address.
* @description
* Creates a Substrate multisig address based on the input address and the required threshold.
*/
export default function encodeMultiAddress (who: (Uint8Array | string)[], threshold: BigInt | BN | number, ss58Format?: Prefix): string {
return encode(keyMulti(who, threshold), ss58Format);
}
@@ -0,0 +1,46 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 testingPairs from '@polkadot/keyring/testingPairs';
import { addressEq } from '.';
describe('addressEq', (): void => {
it('returns false with non-equal', (): void => {
expect(
addressEq(
'5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
'5EnxxUmEbw8DkENKiYuZ1DwQuMoB2UWEQJZZXrTsxoz7SpgG'
)
).toEqual(false);
});
it('returns true for equal, matching prefix', (): void => {
expect(
addressEq(
'5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
'5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'
)
).toEqual(true);
});
it('returns true for equal, non-matching prefix', (): void => {
expect(
addressEq(
'5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
'7sL6eNJj5ZGV5cn3hhV2deRUsivXfBfMH76wCALCqWj1EKzv'
)
).toEqual(true);
});
it('returns true for equal, address vs publicKey', (): void => {
const keyring = testingPairs({ type: 'sr25519' });
expect(
addressEq(
'5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
keyring.alice.publicKey
)
).toEqual(true);
});
});
+25
View File
@@ -0,0 +1,25 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { u8aEq } from '@polkadot/util';
import decode from './decode';
/**
* @name addressEq
* @summary Compares two addresses, either in ss58, Uint8Array or hex format.
* @description
* For the input values, return true is the underlying public keys do match.
* @example
* <BR>
*
* ```javascript
* import { u8aEq } from '@polkadot/util';
*
* u8aEq(new Uint8Array([0x68, 0x65]), new Uint8Array([0x68, 0x65])); // true
* ```
*/
export default function addressEq (a: string | Uint8Array, b: string | Uint8Array): boolean {
return u8aEq(decode(a), decode(b));
}
+17 -1
View File
@@ -3,13 +3,29 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import checkAddress from './check';
import checkAddressChecksum from './checkChecksum';
import createKeyMulti from './keyMulti';
import createKeyDerived from './keyDerived';
import decodeAddress from './decode';
import deriveAddress from './derive';
import encodeAddress from './encode';
import encodeDerivedAddress from './encodeDerived';
import encodeMultiAddress from './encodeMulti';
import addressEq from './eq';
import setSS58Format from './setSS58Format';
import sortAddresses from './sort';
export {
addressEq,
checkAddress,
checkAddressChecksum,
createKeyDerived,
createKeyMulti,
decodeAddress,
deriveAddress,
encodeAddress,
setSS58Format
encodeDerivedAddress,
encodeMultiAddress,
setSS58Format,
sortAddresses
};
@@ -0,0 +1,23 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 createKeyDerived from './keyDerived';
describe('createKeyDerived', (): void => {
it('matches sub accounts with Rust', (): void => {
expect(
createKeyDerived(new Uint8Array([1, 0, 0, 0, 0, 0, 0, 0]), 0)
).toEqual(
new Uint8Array([234, 236, 28, 96, 177, 168, 152, 193, 71, 179, 226, 102, 179, 155, 188, 240, 90, 182, 21, 175, 47, 47, 250, 179, 178, 0, 81, 222, 70, 56, 52, 234])
);
});
it('creates a valid subkey', (): void => {
expect(
createKeyDerived('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY', 1)
).toEqual(
new Uint8Array([248, 19, 86, 209, 254, 89, 84, 48, 54, 128, 166, 239, 153, 212, 143, 34, 191, 60, 210, 50, 39, 77, 122, 71, 29, 60, 247, 198, 95, 101, 246, 83])
);
});
});
@@ -0,0 +1,21 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 BN from 'bn.js';
import { bnToU8a, stringToU8a, u8aConcat } from '@polkadot/util';
import blake2AsU8a from '../blake2/asU8a';
import decodeAddress from './decode';
const PREFIX = stringToU8a('modlpy/utilisuba');
export default function createKeyDerived (who: Uint8Array | string, index: BigInt | BN | number): Uint8Array {
return blake2AsU8a(
u8aConcat(
PREFIX,
decodeAddress(who),
bnToU8a(index, { bitLength: 16, isLe: true })
)
);
}
@@ -0,0 +1,19 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { createKeyMulti } from '.';
describe('createKeyMulti', (): void => {
it('creates a valid multikey (aligning with Rust, needs sorting)', (): void => {
expect(
createKeyMulti([
new Uint8Array([1, 0, 0, 0, 0, 0, 0, 0]),
new Uint8Array([3, 0, 0, 0, 0, 0, 0, 0]),
new Uint8Array([2, 0, 0, 0, 0, 0, 0, 0])
], 2)
).toEqual(
new Uint8Array([67, 151, 196, 155, 179, 207, 47, 123, 90, 2, 35, 54, 162, 111, 241, 226, 88, 148, 54, 193, 252, 195, 93, 101, 16, 5, 93, 101, 186, 186, 254, 79])
);
});
});
@@ -0,0 +1,22 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 BN from 'bn.js';
import { bnToU8a, compactToU8a, stringToU8a, u8aConcat, u8aSorted } from '@polkadot/util';
import blake2AsU8a from '../blake2/asU8a';
import decodeAddress from './decode';
const PREFIX = stringToU8a('modlpy/utilisuba');
export default function createKeyMulti (who: (Uint8Array | string)[], threshold: BigInt | BN | number): Uint8Array {
return blake2AsU8a(
u8aConcat(
PREFIX,
compactToU8a(who.length),
...u8aSorted(who.map((who) => decodeAddress(who))),
bnToU8a(threshold, { bitLength: 16, isLe: true })
)
);
}
@@ -6,6 +6,10 @@ import { Prefix } from './types';
import defaults from './defaults';
/**
* @description Sets the global SS58 format to use for address encoding
* @deprecated Use keyring.setSS58Format
*/
export default function setSS58Format (prefix: Prefix): void {
defaults.prefix = prefix;
}
@@ -0,0 +1,21 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { sortAddresses } from '.';
describe('sortAddresses', (): void => {
it('sorts addresses by the publicKeys', (): void => {
expect(
sortAddresses([
'5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
'5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty',
'5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y'
])
).toEqual([
'5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty',
'5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y',
'5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'
]);
});
});
+16
View File
@@ -0,0 +1,16 @@
// Copyright 2017-2020 @polkadot/util 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 './types';
import { u8aSorted } from '@polkadot/util';
import decodeAddress from './decode';
import encodeAddress from './encode';
export default function sortAddresses (addresses: (Uint8Array | string)[], ss58Format?: Prefix): string[] {
return u8aSorted(
addresses.map((who) => decodeAddress(who))
).map((u8a) => encodeAddress(u8a, ss58Format));
}
+4
View File
@@ -7,6 +7,10 @@ export const allowedSS58 = [
0, 1,
// Kusama
2, 3,
// Katal Chain
4,
// Kulupu
16, 17,
// Dothereum
20,
// Substrate default
+12
View File
@@ -0,0 +1,12 @@
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
// https://github.com/multiformats/js-multibase/blob/master/src/constants.js
const BASE32_ALPHABET = 'abcdefghijklmnopqrstuvwxyz234567';
const BITS_PER_CHAR = 5;
export {
BASE32_ALPHABET,
BITS_PER_CHAR
};
@@ -0,0 +1,25 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { u8aToString } from '@polkadot/util';
import { base32Decode } from './';
describe('base32Decode', (): void => {
it('decodes a base32', (): void => {
expect(
u8aToString(
base32Decode('irswgzloorzgc3djpjssazlwmvzhs5dinfxgoijb')
)
).toEqual('Decentralize everything!!');
});
it('decodes a base32 (ipfsCompat)', (): void => {
expect(
u8aToString(
base32Decode('birswgzloorzgc3djpjssazlwmvzhs5dinfxgoijb', true)
)
).toEqual('Decentralize everything!!');
});
});
+54
View File
@@ -0,0 +1,54 @@
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
// adapted from https://github.com/multiformats/js-multibase/blob/424709195b46ffb1d6f2f69a7707598ebe751e5e/src/rfc4648.js
import { assert } from '@polkadot/util';
import { BASE32_ALPHABET, BITS_PER_CHAR } from './bs32';
import validate from './validate';
// Build the character lookup table:
const LOOKUP = BASE32_ALPHABET
.split('')
.reduce((lookup: Record<string, number>, char: string, index: number): Record<string, number> => {
lookup[char] = index;
return lookup;
}, {});
/**
* @name base32Decode
* @summary Delookup a base32 value.
* @description
* From the provided input, decode the base32 and return the result as an `Uint8Array`.
*/
export default function base32Decode (value: string, ipfsCompat = false): Uint8Array {
if (ipfsCompat) {
assert(value[0] === 'b', "Expected IPFS base32 identifier 'b' at string start");
value = value.substr(1);
}
validate(value);
const out = new Uint8Array((value.length * BITS_PER_CHAR / 8) | 0);
let bits = 0;
let buffer = 0;
let written = 0;
for (let i = 0; i < value.length; ++i) {
buffer = (buffer << BITS_PER_CHAR) | LOOKUP[value[i]];
bits += BITS_PER_CHAR;
if (bits >= 8) {
bits -= 8;
out[written++] = 0xff & (buffer >> bits);
}
}
assert(!(bits >= BITS_PER_CHAR || 0xff & (buffer << (8 - bits))), 'Unexpected end of data');
return out;
}
@@ -0,0 +1,23 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { base58Decode } from '../base58';
import { base32Encode } from './';
describe('base32Encode', (): void => {
it('encodes to a base32', (): void => {
expect(
base32Encode('Decentralize everything!!')
).toEqual('irswgzloorzgc3djpjssazlwmvzhs5dinfxgoijb');
});
it('encodes a base58 to a base32', (): void => {
expect(
base32Encode(
base58Decode('zb2rhk6GMPQF3hfzwXTaNYFLKomMeC6UXdUt6jZKPpeVirLtV', true),
true
)
).toEqual('bafkreigh2akiscaildcqabsyg3dfr6chu3fgpregiymsck7e7aqa4s52zy');
});
});
+42
View File
@@ -0,0 +1,42 @@
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
// adapted from https://github.com/multiformats/js-multibase/blob/424709195b46ffb1d6f2f69a7707598ebe751e5e/src/rfc4648.js
import { u8aToU8a } from '@polkadot/util';
import { BASE32_ALPHABET, BITS_PER_CHAR } from './bs32';
const MASK = (1 << BITS_PER_CHAR) - 1;
/**
* @name base32Encode
* @summary Creates a base32 value.
* @description
* From the provided input, create the base32 and return the result as a string.
*/
export default function base32Encode (value: Uint8Array | string | Buffer | number[], ipfsCompat = false): string {
const u8a = u8aToU8a(value);
let out = '';
let bits = 0;
let buffer = 0;
for (let i = 0; i < u8a.length; ++i) {
buffer = (buffer << 8) | u8a[i];
bits += 8;
while (bits > BITS_PER_CHAR) {
bits -= BITS_PER_CHAR;
out += BASE32_ALPHABET[MASK & (buffer >> bits)];
}
}
if (bits) {
out += BASE32_ALPHABET[MASK & (buffer << (BITS_PER_CHAR - bits))];
}
return ipfsCompat
? `b${out}`
: out;
}
+11
View File
@@ -0,0 +1,11 @@
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
/**
* @summary Encode and decode base32 values
*/
export { default as base32Decode } from './decode';
export { default as base32Encode } from './encode';
export { default as base32Validate } from './validate';
@@ -0,0 +1,16 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { validateChars } from '../base58/validate';
import { BASE32_ALPHABET } from './bs32';
/**
* @name base32Validate
* @summary Validates a base32 value.
* @description
* Validates the the supplied value is valid base32
*/
export default function base32Validate (value: string): true {
return validateChars('base32', BASE32_ALPHABET, value);
}
+15
View File
@@ -0,0 +1,15 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 baseX from 'base-x';
// https://github.com/cryptocoinjs/base-x#alphabets
const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
const bs58 = baseX(BASE58_ALPHABET);
export {
BASE58_ALPHABET,
bs58
};
+26
View File
@@ -0,0 +1,26 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { assert, bufferToU8a } from '@polkadot/util';
import { bs58 } from './bs58';
import validate from './validate';
/**
* @name base58Decode
* @summary Decodes a base58 value.
* @description
* From the provided input, decode the base58 and return the result as an `Uint8Array`.
*/
export default function base58Decode (value: string, ipfsCompat = false): Uint8Array {
if (ipfsCompat) {
assert(value[0] === 'z', "Expected IPFS base32 identifier 'z' at string start");
value = value.substr(1);
}
validate(value);
return bufferToU8a(bs58.decode(value));
}
@@ -0,0 +1,17 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { base32Decode } from '../base32';
import { base58Encode } from './';
describe('base58Encode', (): void => {
it('encodes a base32 to a base38', (): void => {
expect(
base58Encode(
base32Decode('bafkreigh2akiscaildcqabsyg3dfr6chu3fgpregiymsck7e7aqa4s52zy', true),
true
)
).toEqual('zb2rhk6GMPQF3hfzwXTaNYFLKomMeC6UXdUt6jZKPpeVirLtV');
});
});
+23
View File
@@ -0,0 +1,23 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { u8aToBuffer, u8aToU8a } from '@polkadot/util';
import { bs58 } from './bs58';
/**
* @name base58Encode
* @summary Creates a base58 value.
* @description
* From the provided input, create the base58 and return the result as a string.
*/
export default function base58Encode (value: Uint8Array | string | Buffer | number[], ipfsCompat = false): string {
const out = bs58.encode(
u8aToBuffer(u8aToU8a(value))
);
return ipfsCompat
? `z${out}`
: out;
}
+11
View File
@@ -0,0 +1,11 @@
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
/**
* @summary Encode and decode base58 values
*/
export { default as base58Decode } from './decode';
export { default as base58Encode } from './encode';
export { default as base58Validate } from './validate';
@@ -0,0 +1,25 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { BASE58_ALPHABET } from './bs58';
export function validateChars (type: string, alphabet: string, value: string): true {
for (let i = 0; i < value.length; i++) {
if (!alphabet.includes(value[i])) {
throw new TypeError(`Invalid ${type} character "${value[i]}" (0x${value.charCodeAt(i).toString(16)}) at index ${i}`);
}
}
return true;
}
/**
* @name base58Validate
* @summary Validates a base58 value.
* @description
* Validates the the supplied value is valid base58
*/
export default function base58Validate (value: string): true {
return validateChars('base58', BASE58_ALPHABET, value);
}
@@ -0,0 +1,17 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { stringToU8a } from '@polkadot/util';
import { base64Decode } from '.';
describe('base64Decode', (): void => {
it('decodes a mixed base64 utf8 string', (): void => {
expect(
base64Decode('aGVsbG8gd29ybGQg0J/RgNC40LLQtdGC0YHRgtCy0YPRjiDQvNC4IOS9oOWlvQ==')
).toEqual(
stringToU8a('hello world Приветствую ми 你好')
);
});
});
+19
View File
@@ -0,0 +1,19 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { bufferToU8a } from '@polkadot/util';
import validate from './validate';
/**
* @name base64Decode
* @summary Decodes a base64 value.
* @description
* From the provided input, decode the base64 and return the result as an `Uint8Array`.
*/
export default function base64Decode (value: string): Uint8Array {
validate(value);
return bufferToU8a(Buffer.from(value, 'base64'));
}
@@ -0,0 +1,13 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { base64Encode } from '.';
describe('base64Encode', (): void => {
it('encodes a mixed base64 utf8 string', (): void => {
expect(
base64Encode('hello world Приветствую ми 你好')
).toEqual('aGVsbG8gd29ybGQg0J/RgNC40LLQtdGC0YHRgtCy0YPRjiDQvNC4IOS9oOWlvQ==');
});
});
+15
View File
@@ -0,0 +1,15 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { u8aToBuffer, u8aToU8a } from '@polkadot/util';
/**
* @name base64Encode
* @summary Creates a base64 value.
* @description
* From the provided input, create the base64 and return the result as a string.
*/
export default function base58Encode (value: Uint8Array | string | Buffer | number[]): string {
return u8aToBuffer(u8aToU8a(value)).toString('base64');
}
+11
View File
@@ -0,0 +1,11 @@
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
/**
* @summary Encode and decode base64 values
*/
export { default as base64Decode } from './decode';
export { default as base64Encode } from './encode';
export { default as base64Validate } from './validate';
@@ -0,0 +1,13 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { base64Validate } from '.';
describe('base64Validate', (): void => {
it('decodes a mixed base64 utf8 string', (): void => {
expect(
() => base64Validate('aGVsbG8gd29ybGQg0J/RgNC40LLQtd^GC0YHRgtCy0YPRjiDQvNC4IOS9oOWlvQ==')
).toThrow(/Invalid base64 encoding/);
});
});
@@ -0,0 +1,17 @@
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
/**
* @name base64Validate
* @summary Validates a base64 value.
* @description
* Validates the the supplied value is valid base64
*/
export default function base64Validate (value: string): true {
if (!(/^(?:[A-Za-z0-9+/]{2}[A-Za-z0-9+/]{2})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(value))) {
throw new TypeError('Invalid base64 encoding');
}
return true;
}
@@ -43,4 +43,18 @@ describe('blake2AsU8a', (): void => {
hexToU8a('0xba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923')
);
});
it('has equivalent Wasm/Js outputs on hex inputs', (): void => {
const a = blake2AsU8a('0x123456', 256, null, false);
const b = blake2AsU8a('0x123456', 256, null, true);
expect(a).toEqual(b);
});
it('has equivalent Wasm/Js outputs with key inputs', (): void => {
const a = blake2AsU8a('0x123456', 256, new Uint8Array([1, 2]), false);
const b = blake2AsU8a('0x123456', 256, new Uint8Array([1, 2]), true);
expect(a).toEqual(b);
});
});
+3 -3
View File
@@ -20,10 +20,10 @@ import { blake2b, isReady } from '@polkadot/wasm-crypto';
* blake2AsU8a('abc'); // => [0xba, 0x80, 0xa53, 0xf98, 0x1c, 0x4d, 0x0d]
* ```
*/
export default function blake2AsU8a (data: Uint8Array | string, bitLength = 256, key: Uint8Array | null = null): Uint8Array {
export default function blake2AsU8a (data: Uint8Array | string, bitLength = 256, key: Uint8Array | null = null, onlyJs = false): Uint8Array {
const byteLength = Math.ceil(bitLength / 8);
return isReady()
return isReady() && !onlyJs
? blake2b(u8aToU8a(data), u8aToU8a(key), byteLength)
: blakejs.blake2b(data, key, byteLength);
: blakejs.blake2b(u8aToU8a(data), key, byteLength);
}
@@ -0,0 +1,58 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { keccakAsU8a } from '../keccak';
import { ethereumEncode } from './';
describe('formatAddress', () => {
describe('address to address encoding', (): void => {
const ADDRESS = '0x00a329c0648769A73afAc7F9381E08FB43dBEA72';
it('returns 0x for no address', () => {
expect(ethereumEncode()).toBe('0x');
});
it('returns fails on invalid address', () => {
expect(
() => ethereumEncode('0xnotaddress')
).toThrow(/Invalid address or publicKey passed/);
});
it('converts lowercase to the checksummed address', () => {
expect(ethereumEncode(ADDRESS.toLowerCase())).toBe(ADDRESS);
});
it('converts uppercase to the checksummed address', () => {
expect(ethereumEncode(ADDRESS.toUpperCase().replace('0X', '0x'))).toBe(ADDRESS);
});
it('returns formatted address on checksum input', () => {
expect(ethereumEncode(ADDRESS)).toBe(ADDRESS);
});
});
describe('from publicKey', (): void => {
const ADDRESS = '0x4119b2e6c3Cb618F4f0B93ac77f9BeeC7FF02887';
it('encodes a compressed publicKey', (): void => {
expect(
ethereumEncode('0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077')
).toEqual(ADDRESS);
});
it('encodes an expanded publicKey', (): void => {
expect(
ethereumEncode('0x04b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb1307763fe926c273235fd979a134076d00fd1683cbd35868cb485d4a3a640e52184af')
).toEqual(ADDRESS);
});
it('encodes a pre-hashed key', (): void => {
expect(
ethereumEncode(
keccakAsU8a('0xb9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb1307763fe926c273235fd979a134076d00fd1683cbd35868cb485d4a3a640e52184af')
)
).toEqual(ADDRESS);
});
});
});
@@ -0,0 +1,36 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { assert, u8aToHex, u8aToU8a } from '@polkadot/util';
import { keccakAsU8a } from '../keccak';
import { secp256k1Expand } from '../secp256k1';
function getH160 (u8a: Uint8Array): Uint8Array {
if ([33, 65].includes(u8a.length)) {
u8a = keccakAsU8a(secp256k1Expand(u8a));
}
return u8a.slice(-20);
}
export default function ethereumEncode (addressOrPublic?: string | Uint8Array): string {
if (!addressOrPublic) {
return '0x';
}
const u8aAddress = u8aToU8a(addressOrPublic);
assert([20, 32, 33, 65].includes(u8aAddress.length), 'Invalid address or publicKey passed');
const address = u8aToHex(getH160(u8aAddress), -1, false);
const hash = u8aToHex(keccakAsU8a(address), -1, false);
let result = '';
for (let index = 0; index < 40; index++) {
result = `${result}${parseInt(hash[index], 16) > 7 ? address[index].toUpperCase() : address[index]}`;
}
return `0x${result}`;
}
@@ -0,0 +1,7 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { default as ethereumEncode } from './encode';
export { default as isEthereumAddress } from './isAddress';
export { default as isEthereumChecksum } from './isChecksum';
@@ -0,0 +1,33 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { isEthereumAddress } from './';
const ADDRESS = '0x00a329c0648769A73afAc7F9381E08FB43dBEA72';
describe('isEthereumAddress', () => {
it('returns true when fully lowercase', () => {
expect(isEthereumAddress(ADDRESS.toLowerCase())).toBe(true);
});
it('returns true when fully uppercase', () => {
expect(isEthereumAddress(ADDRESS.toUpperCase().replace('0X', '0x'))).toBe(true);
});
it('returns true when checksummed', () => {
expect(isEthereumAddress(ADDRESS)).toBe(true);
});
it('returns false when empty address', () => {
expect(isEthereumAddress()).toBe(false);
});
it('returns false when invalid address', () => {
expect(isEthereumAddress('0xinvalid')).toBe(false);
});
it('returns false when invalid address of correct length', () => {
expect(isEthereumAddress('0xinvalid000123456789012345678901234567890')).toBe(false);
});
});
@@ -0,0 +1,19 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { isHex } from '@polkadot/util';
import isEthereumChecksum from './isChecksum';
export default function isEthereumAddress (address?: string): boolean {
if (!address || address.length !== 42 || !isHex(address)) {
return false;
}
if (/^(0x)?[0-9a-f]{40}$/.test(address) || /^(0x)?[0-9A-F]{40}$/.test(address)) {
return true;
}
return isEthereumChecksum(address);
}
@@ -0,0 +1,23 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { u8aToHex } from '@polkadot/util';
import { keccakAsU8a } from '../keccak';
export default function isEthereumChecksum (_address: string): boolean {
const address = _address.replace('0x', '');
const hash = u8aToHex(keccakAsU8a(address.toLowerCase()), -1, false);
for (let index = 0; index < 40; index++) {
const char = address[index];
const hashval = parseInt(hash[index], 16);
if ((hashval > 7 && char !== char.toUpperCase()) || (hashval <= 7 && char !== char.toLowerCase())) {
return false;
}
}
return true;
}
@@ -0,0 +1,29 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 { isEthereumChecksum } from './';
const ADDRESS = '0x00a329c0648769A73afAc7F9381E08FB43dBEA72';
describe('isEthereumChecksum', () => {
it('returns false on invalid address', () => {
expect(isEthereumChecksum('0xinvalid')).toBe(false);
});
it('returns false on non-checksum address', () => {
expect(isEthereumChecksum('0x1234567890abcdeedcba1234567890abcdeedcba')).toBe(false);
});
it('returns false when fully lowercase', () => {
expect(isEthereumChecksum(ADDRESS.toLowerCase())).toBe(false);
});
it('returns false when fully uppercase', () => {
expect(isEthereumChecksum(ADDRESS.toUpperCase().replace('0X', '0x'))).toBe(false);
});
it('returns true on a checksummed address', () => {
expect(isEthereumChecksum(ADDRESS)).toBe(true);
});
});
+11 -17
View File
@@ -2,34 +2,28 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
// polyfills
import './polyfill';
import wasmCrypto from '@polkadot/wasm-crypto';
// out of order and early in the chain, this also kicks off initialization on require
export * from './init';
// all internal exports
export * from './address';
export * from './base32';
export * from './base58';
export * from './base64';
export * from './blake2';
export * from './ethereum';
export * from './keccak';
export * from './key';
export * from './mnemonic';
export * from './nacl';
export * from './pbkdf2';
export * from './random';
export * from './schnorrkel';
export * from './scrypt';
export * from './secp256k1';
export * from './sha512';
export * from './signature';
export * from './xxhash';
export function cryptoWaitReady (): Promise<boolean> {
return wasmCrypto
.waitReady()
.then((): boolean => true)
.catch((error): boolean => {
console.error('Unable to initialize @polkadot/util-crypto', error);
return false;
});
}
// start init process immediately
cryptoWaitReady().catch((): void => {
// shouldn't happen, logged above
});
+25
View File
@@ -0,0 +1,25 @@
// Copyright 2017-2020 @polkadot/util-crypto 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 wasmCrypto from '@polkadot/wasm-crypto';
export function cryptoIsReady (): boolean {
return wasmCrypto.isReady();
}
export function cryptoWaitReady (): Promise<boolean> {
return wasmCrypto
.waitReady()
.then((): boolean => true)
.catch((error): boolean => {
console.error('Unable to initialize @polkadot/util-crypto', error);
return false;
});
}
// start init process immediately
cryptoWaitReady().catch((): void => {
// shouldn't happen, logged above
});
+1 -1
View File
@@ -24,6 +24,6 @@ export default function keccakAsU8a (value: Buffer | Uint8Array | string): Uint8
return isReady()
? keccak256(u8aToU8a(value))
: new Uint8Array(
jssha3.keccak256.update(value).arrayBuffer()
jssha3.keccak256.update(u8aToU8a(value)).arrayBuffer()
);
}
+16 -15
View File
@@ -2,8 +2,9 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import BN from 'bn.js';
import { bnToHex, compactAddLength, hexToU8a, isBn, isHex, isNumber, isString, stringToU8a } from '@polkadot/util';
import type BN from 'bn.js';
import { bnToHex, compactAddLength, hexToU8a, isBigInt, isBn, isHex, isNumber, isString, stringToU8a } from '@polkadot/util';
import blake2AsU8a from '../blake2/asU8a';
@@ -16,15 +17,15 @@ const BN_OPTIONS = {
};
export default class DeriveJunction {
private _chainCode: Uint8Array = new Uint8Array(32);
readonly #chainCode: Uint8Array = new Uint8Array(32);
private _isHard = false;
#isHard = false;
public static from (value: string): DeriveJunction {
const result = new DeriveJunction();
const [code, isHard] = value.startsWith('/')
? [value.substr(1), true]
: [value, false];
const result = new DeriveJunction();
result.soft(
RE_NUMBER.test(code)
@@ -38,29 +39,29 @@ export default class DeriveJunction {
}
public get chainCode (): Uint8Array {
return this._chainCode;
return this.#chainCode;
}
public get isHard (): boolean {
return this._isHard;
return this.#isHard;
}
public get isSoft (): boolean {
return !this._isHard;
return !this.#isHard;
}
public hard (value: number | BN | string | Uint8Array): DeriveJunction {
public hard (value: number | string | BigInt | BN | Uint8Array): DeriveJunction {
return this.soft(value).harden();
}
public harden (): DeriveJunction {
this._isHard = true;
this.#isHard = true;
return this;
}
public soft (value: number | BN | string | Uint8Array): DeriveJunction {
if (isNumber(value) || isBn(value)) {
public soft (value: number | string | BigInt | BN | Uint8Array): DeriveJunction {
if (isNumber(value) || isBn(value) || isBigInt(value)) {
return this.soft(bnToHex(value, BN_OPTIONS));
} else if (isString(value)) {
return isHex(value)
@@ -72,14 +73,14 @@ export default class DeriveJunction {
return this.soft(blake2AsU8a(value));
}
this._chainCode.fill(0);
this._chainCode.set(value, 0);
this.#chainCode.fill(0);
this.#chainCode.set(value, 0);
return this;
}
public soften (): DeriveJunction {
this._isHard = false;
this.#isHard = false;
return this;
}
@@ -6,37 +6,32 @@ import keyExtractPath, { ExtractResult } from './extractPath';
describe('keyExtractPath', (): void => {
it('extracts properly from soft', (): void => {
expect(
keyExtractPath('/1')
).toEqual({
parts: ['/1'],
path: [
{ _isHard: false, _chainCode: Uint8Array.from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) }
]
});
const test = keyExtractPath('/1');
expect(test.parts).toEqual(['/1']);
expect(test.path.length).toEqual(1);
expect(test.path[0].isHard).toEqual(false);
expect(test.path[0].chainCode).toEqual(Uint8Array.from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]));
});
it('extracts properly from hard', (): void => {
expect(
keyExtractPath('//1')
).toEqual({
parts: ['//1'],
path: [
{ _isHard: true, _chainCode: Uint8Array.from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) }
]
});
const test = keyExtractPath('//1');
expect(test.parts).toEqual(['//1']);
expect(test.path.length).toEqual(1);
expect(test.path[0].isHard).toEqual(true);
expect(test.path[0].chainCode).toEqual(Uint8Array.from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]));
});
it('extracts properly from hard/soft', (): void => {
expect(
keyExtractPath('//1/2')
).toEqual({
parts: ['//1', '/2'],
path: [
{ _isHard: true, _chainCode: Uint8Array.from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) },
{ _isHard: false, _chainCode: Uint8Array.from([2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) }
]
});
const test = keyExtractPath('//1/2');
expect(test.parts).toEqual(['//1', '/2']);
expect(test.path.length).toEqual(2);
expect(test.path[0].isHard).toEqual(true);
expect(test.path[0].chainCode).toEqual(Uint8Array.from([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]));
expect(test.path[1].isHard).toEqual(false);
expect(test.path[1].chainCode).toEqual(Uint8Array.from([2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]));
});
it('does not extract from invalid paths', (): void => {

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