Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f24a2758e | ||
|
|
3230663ae1 | ||
|
|
4a0fa7f615 | ||
|
|
0f05954dc5 | ||
|
|
55f442f9fa | ||
|
|
7e5edc46a3 | ||
|
|
d500f98fb4 | ||
|
|
7b8902ce3f | ||
|
|
98b3ad642f | ||
|
|
14466e27ac | ||
|
|
16ffd1b467 | ||
|
|
ca52fd7e5b | ||
|
|
ea5d3df64c | ||
|
|
b51ed71796 | ||
|
|
bf28507ae8 | ||
|
|
6715bef24a | ||
|
|
badbbd76cb | ||
|
|
253776a510 | ||
|
|
e1ef295bfa | ||
|
|
73c89f4e3c | ||
|
|
a52e0dfb16 | ||
|
|
9f8ed7bb50 | ||
|
|
a932f9408a | ||
|
|
7907ce6dbf | ||
|
|
230d510491 | ||
|
|
415fd1b2d1 | ||
|
|
89c954216d | ||
|
|
b689796b25 | ||
|
|
c4c18d324b | ||
|
|
b7bf500343 | ||
|
|
e5c6baf425 | ||
|
|
0127899c5e | ||
|
|
f23611cad6 | ||
|
|
a74df109b0 | ||
|
|
9582013bfa | ||
|
|
6c148dcb3b | ||
|
|
65488bbff8 | ||
|
|
40cbb81d1e | ||
|
|
77b896054f | ||
|
|
89c717bd11 | ||
|
|
b22f5643a9 | ||
|
|
8d68ed3117 | ||
|
|
65b1c81c21 | ||
|
|
28cd140cfb | ||
|
|
73b553fbd2 | ||
|
|
f12075798d | ||
|
|
323db21306 | ||
|
|
d54302eacc | ||
|
|
9a98d5b6e4 | ||
|
|
5ec613adf9 | ||
|
|
567ce7955a | ||
|
|
b185dcb072 | ||
|
|
79010f83dc | ||
|
|
5354f93946 | ||
|
|
e787e66ef9 | ||
|
|
440e826fed | ||
|
|
d2e5e1d441 | ||
|
|
32fc32f414 | ||
|
|
0a7b2a7a9f | ||
|
|
c315e6fdaa | ||
|
|
b5d9ed36e1 | ||
|
|
f24c7983c8 | ||
|
|
3447cd40bf | ||
|
|
95f4702e26 | ||
|
|
506142da8a | ||
|
|
34f6eac538 | ||
|
|
ae1a37cdf7 | ||
|
|
fab087bbe5 | ||
|
|
8608098996 | ||
|
|
220f4029b1 | ||
|
|
d21daf1434 | ||
|
|
1a4c16f797 | ||
|
|
975103fd3c | ||
|
|
fb84ac7c25 | ||
|
|
13ae8665d5 | ||
|
|
4e8b2beb0b | ||
|
|
dd1220ac97 |
@@ -1,4 +0,0 @@
|
|||||||
// Copyright 2017-2020 @polkadot/util authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
module.exports = require('./babel.config.js');
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
.eslintrc.js
|
|
||||||
**/build/*
|
|
||||||
**/coverage/*
|
|
||||||
**/node_modules/*
|
|
||||||
@@ -5,6 +5,15 @@ const base = require('@polkadot/dev/config/eslint');
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
...base,
|
...base,
|
||||||
|
ignorePatterns: [
|
||||||
|
'.eslintrc.js',
|
||||||
|
'.github/**',
|
||||||
|
'.vscode/**',
|
||||||
|
'.yarn/**',
|
||||||
|
'**/build/*',
|
||||||
|
'**/coverage/*',
|
||||||
|
'**/node_modules/*'
|
||||||
|
],
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
...base.parserOptions,
|
...base.parserOptions,
|
||||||
project: [
|
project: [
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
assignees: ['jacogr']
|
||||||
|
title: SS58 registry is outdated
|
||||||
|
labels: ['ci', '@networks']
|
||||||
|
---
|
||||||
|
|
||||||
|
cc @jacogr
|
||||||
|
|
||||||
|
Discrepancies detected between https://github.com/paritytech/substrate/blob/master/ss58-registry.json and https://github.com/polkadot-js/common/blob/master/packages/networks/src/index.ts
|
||||||
|
|
||||||
|
Check the nightly cron output or run `yarn networks:crosscheck` locally. The output as found from the test includes:
|
||||||
@@ -5,11 +5,11 @@ jobs:
|
|||||||
pr:
|
pr:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
step: ['lint', 'test', 'build', 'docs']
|
step: ['lint', 'test', 'build']
|
||||||
name: ${{ matrix.step }}
|
name: ${{ matrix.step }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
- name: ${{ matrix.step }}
|
- name: ${{ matrix.step }}
|
||||||
env:
|
env:
|
||||||
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
||||||
|
|||||||
@@ -8,18 +8,17 @@ jobs:
|
|||||||
master:
|
master:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
step: ['build:release', 'docs:release']
|
step: ['build:release']
|
||||||
name: ${{ matrix.step }}
|
name: ${{ matrix.step }}
|
||||||
if: "! startsWith(github.event.head_commit.message, '[CI Skip]') && github.repository == 'polkadot-js/common'"
|
if: "! startsWith(github.event.head_commit.message, '[CI Skip]') && github.repository == 'polkadot-js/common'"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GH_PAT }}
|
token: ${{ secrets.GH_PAT }}
|
||||||
- name: ${{ matrix.step }}
|
- name: ${{ matrix.step }}
|
||||||
env:
|
env:
|
||||||
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
||||||
GH_PAGES_SRC: build-docs
|
|
||||||
GH_PAT: ${{ secrets.GH_PAT }}
|
GH_PAT: ${{ secrets.GH_PAT }}
|
||||||
GH_RELEASE_GITHUB_API_TOKEN: ${{ secrets.GH_PAT }}
|
GH_RELEASE_GITHUB_API_TOKEN: ${{ secrets.GH_PAT }}
|
||||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
name: SS58
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '45 3 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ss58:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: check
|
||||||
|
env:
|
||||||
|
CI_LOG: 123
|
||||||
|
run: |
|
||||||
|
yarn install --immutable | grep -v 'YN0013'
|
||||||
|
yarn networks:crosscheck
|
||||||
|
|
||||||
|
- name: issue
|
||||||
|
if: ${{ failure() }}
|
||||||
|
uses: JasonEtco/create-an-issue@v2
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
|
||||||
|
with:
|
||||||
|
filename: .github/ss58-check.md
|
||||||
+52
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
-55
File diff suppressed because one or more lines are too long
+55
File diff suppressed because one or more lines are too long
+5
-1
@@ -7,5 +7,9 @@ nodeLinker: node-modules
|
|||||||
plugins:
|
plugins:
|
||||||
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
|
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
|
||||||
spec: "@yarnpkg/plugin-interactive-tools"
|
spec: "@yarnpkg/plugin-interactive-tools"
|
||||||
|
- path: .yarn/plugins/@yarnpkg/plugin-version.cjs
|
||||||
|
spec: "@yarnpkg/plugin-version"
|
||||||
|
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
|
||||||
|
spec: "@yarnpkg/plugin-workspace-tools"
|
||||||
|
|
||||||
yarnPath: .yarn/releases/yarn-2.2.2.cjs
|
yarnPath: .yarn/releases/yarn-2.3.3.cjs
|
||||||
|
|||||||
@@ -1,5 +1,32 @@
|
|||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
|
||||||
|
## 3.7.1 Nov 1, 2020
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Remove the use of `chalk` (logger) for less overall dependencies
|
||||||
|
- `string*` utilities now also allows `String` (class) inputs
|
||||||
|
- Align bip39 use with wasm-crypto for English-only wordlist, default, non supplied)
|
||||||
|
- Adjust elliptic imports for explicit paths (allows tree-shaking)
|
||||||
|
- Add Totem (ss58 prefix 14) into `@polkadot/networks`
|
||||||
|
- Move `@polkadot/x-{fetch,textdecoder,textencoder,ws}` into `common` repo
|
||||||
|
|
||||||
|
|
||||||
|
## 3.6.1 Oct 18, 2020
|
||||||
|
|
||||||
|
Contributed:
|
||||||
|
|
||||||
|
- Add evmToAddress and addressToEvm `@polkadot/util-crypto` (Thanks to https://github.com/jnaviask)
|
||||||
|
- Remove invalid link to docs (thanks to https://github.com/roccomuso)
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Rename `mnemonicToBip39` to `mnemonicToLegacySeed` (used in non-Substrate compatible fashion)
|
||||||
|
- Update pair signature verification to handle MultiSignature results
|
||||||
|
- Move documentation to docs repo
|
||||||
|
- Added `@polkadot/networks` for a list of known networks and their identifying information
|
||||||
|
|
||||||
|
|
||||||
## 3.5.1 Sep 27, 2020
|
## 3.5.1 Sep 27, 2020
|
||||||
|
|
||||||
Contributed:
|
Contributed:
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Copyright 2017-2020 @polkadot/util authors & contributors
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
function copy_folder () {
|
|
||||||
SRC="packages/$1/build"
|
|
||||||
DST="../apps/node_modules/@polkadot/$1"
|
|
||||||
|
|
||||||
echo "** Copying $SRC to $DST"
|
|
||||||
|
|
||||||
rm -rf $DST
|
|
||||||
cp -r $SRC $DST
|
|
||||||
}
|
|
||||||
|
|
||||||
yarn polkadot-dev-build-ts
|
|
||||||
|
|
||||||
copy_folder "keyring"
|
|
||||||
copy_folder "util"
|
|
||||||
copy_folder "util-crypto"
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
base: '/common/',
|
|
||||||
title: 'polkadot-js/common',
|
|
||||||
description: 'Common utilities and libraries that are in use accross all @polkadot projects',
|
|
||||||
markdown: {
|
|
||||||
lineNumbers: true
|
|
||||||
},
|
|
||||||
themeConfig: {
|
|
||||||
displayAllHeaders: true,
|
|
||||||
nav: [
|
|
||||||
{ text: 'Polkadot/Substrate Apps', link: 'https://polkadot.js.org/apps/' },
|
|
||||||
{ text: 'Project family', link: 'https://polkadot.js.org/' },
|
|
||||||
{
|
|
||||||
text: 'Documentation',
|
|
||||||
items: [
|
|
||||||
{ text: 'API Reference', link: 'https://polkadot.js.org/api/' },
|
|
||||||
{ text: 'Utility Reference (this)', link: 'https://polkadot.js.org/common/' },
|
|
||||||
{ text: 'UI Libs Reference', link: 'https://polkadot.js.org/ui/' },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ text: 'GitHub', link: 'https://github.com/polkadot-js/common' }
|
|
||||||
],
|
|
||||||
search: false,
|
|
||||||
sidebar: [
|
|
||||||
{
|
|
||||||
title: 'Examples (keyring)',
|
|
||||||
path: '/examples/keyring/',
|
|
||||||
collapsable: false,
|
|
||||||
sidebarDepth: 1,
|
|
||||||
children: [
|
|
||||||
['/examples/keyring/01_create_account/', 'Create account'],
|
|
||||||
['/examples/keyring/02_load_accounts/', 'Load Accounts']
|
|
||||||
]
|
|
||||||
},
|
|
||||||
['/util/', '@polkadot/util'],
|
|
||||||
['/util-crypto/', '@polkadot/util-crypto'],
|
|
||||||
['/keyring/', '@polkadot/keyring'],
|
|
||||||
'/CONTRIBUTING.md'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
$accentColor = #fd8824
|
|
||||||
$textColor = #2c3e50
|
|
||||||
|
|
||||||
.home .hero .description,
|
|
||||||
.home .feature h2,
|
|
||||||
.home .feature p {
|
|
||||||
color: $textColor
|
|
||||||
opacity: 0.75
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="initial-scale=0.5, maximum-scale=1">
|
||||||
|
<meta http-equiv="refresh" content="0;URL='https://polkadot.js.org/docs/'" />
|
||||||
|
<title>Redirecting to https://polkadot.js.org/docs/</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
Redirecting to <a href="https://polkadot.js.org/docs/">https://polkadot.js.org/docs/</a>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
---
|
|
||||||
home: true
|
|
||||||
heroText:
|
|
||||||
tagline:
|
|
||||||
# Bringing JavaScript to the Polkadot world.
|
|
||||||
# actionText: Repository Overview
|
|
||||||
# actionLink: /REPOS.md
|
|
||||||
features:
|
|
||||||
- title: Keyring
|
|
||||||
details: Manage user keys allowing for signing, encryption and decryption.
|
|
||||||
- title: Utilities
|
|
||||||
details: Various user utilities to work with data and perform check on it.
|
|
||||||
- title: Crypto
|
|
||||||
details: A thin and easy-to-use wrapper around cryptographic and hashing libraries.
|
|
||||||
|
|
||||||
footer: Apache-2 Licensed | Copyright © 2017-2019 polkadot-js authors and contributors
|
|
||||||
---
|
|
||||||
|
|
||||||
## Welcome
|
|
||||||
|
|
||||||
Various useful utility functions that are used across all projects in the [@polkadot](https://polkadot.js.org) namespace. It provides utility functions with additional safety checks, allowing not only for consistent coding, but also reducing the general boilerplate.
|
|
||||||
|
|
||||||
::: tip Examples
|
|
||||||
In a rush and just want examples? [Jump right in](/examples/keyring/) and get a handle on using the various components in your projects.
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Available packages
|
|
||||||
|
|
||||||
It is split up into a number of internal packages, namely utilities -
|
|
||||||
|
|
||||||
- [keyring](keyring/README.md) Keyring management
|
|
||||||
- [util](util/README.md) General utilities
|
|
||||||
- [util-crypto](util-crypto/README.md) Crypto and hashing utilities
|
|
||||||
|
|
||||||
## The Polkadot Project
|
|
||||||
|
|
||||||
You can read more about the Polkadot Network at [https://polkadot.network/](https://polkadot.network/)
|
|
||||||
|
|
||||||
## Github repositories
|
|
||||||
|
|
||||||
You can find the Polkadot repositories at:
|
|
||||||
|
|
||||||
- [https://github.com/polkadot-js](https://github.com/polkadot-js)
|
|
||||||
- [https://github.com/paritytech/polkadot](https://github.com/paritytech/polkadot)
|
|
||||||
- [https://github.com/paritytech/substrate](https://github.com/paritytech/substrate)
|
|
||||||
|
|
||||||
This documentation is generated from [https://github.com/polkadot-js/common](https://github.com/polkadot-js/common)
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
Contribution to Polkadot JS Common are more than welcome. You can [report issues](https://github.com/polkadot-js/common/issues/new) and [log feature requests](https://github.com/polkadot-js/common/issues/new).
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
yarn.lock
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# Create Account
|
|
||||||
|
|
||||||
The following example shows how to create and account with keyring.
|
|
||||||
|
|
||||||
<<< @/docs/examples/keyring/01_create_account/index.js
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
/* eslint-disable header/header */
|
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
|
||||||
|
|
||||||
// Import Keyring class and utility function
|
|
||||||
const Keyring = require('@polkadot/keyring').default;
|
|
||||||
const stringToU8a = require('@polkadot/util/string/toU8a').default;
|
|
||||||
|
|
||||||
async function main () {
|
|
||||||
// Create account seed for Alice
|
|
||||||
const ALICE_SEED = 'Alice'.padEnd(32, ' ');
|
|
||||||
|
|
||||||
// Create an instance of the Keyring
|
|
||||||
const keyring = new Keyring();
|
|
||||||
|
|
||||||
// Create pair and add Alice to keyring pair dictionary (with account seed)
|
|
||||||
const pairAlice = keyring.addFromSeed(stringToU8a(ALICE_SEED));
|
|
||||||
|
|
||||||
console.log(`Created keyring pair for Alice with address: ${keyring.getPair(pairAlice.address).address}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
main().catch(console.error).finally(() => process.exit());
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "01_create_account",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"description": "Example showing how to create an account",
|
|
||||||
"main": "index.js",
|
|
||||||
"author": "ltfschoen",
|
|
||||||
"license": "MIT",
|
|
||||||
"scripts": {
|
|
||||||
"clean": "rimraf node_modules",
|
|
||||||
"start": "node index.js"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@polkadot/util": "^0.32.10",
|
|
||||||
"@polkadot/keyring": "^0.32.10"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"rimraf": "^2.6.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# Load Accounts
|
|
||||||
|
|
||||||
The following example shows how to load all accounts from the keyring as pairs and convert them into JSON format.
|
|
||||||
|
|
||||||
<<< @/docs/examples/keyring/02_load_accounts/index.js
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
/* eslint-disable header/header */
|
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
|
||||||
|
|
||||||
// Import Keyring class and utility function
|
|
||||||
const Keyring = require('@polkadot/keyring').default;
|
|
||||||
const stringToU8a = require('@polkadot/util/string/toU8a').default;
|
|
||||||
|
|
||||||
async function main () {
|
|
||||||
// Create account seed for Alice and Bob
|
|
||||||
const ALICE_SEED = 'Alice'.padEnd(32, ' ');
|
|
||||||
const BOB_SEED = 'Bob'.padEnd(32, ' ');
|
|
||||||
|
|
||||||
// Create an instance of the Keyring
|
|
||||||
const keyring = new Keyring();
|
|
||||||
|
|
||||||
// Create their pairs with account seeds. Add to keyring pair dictionary
|
|
||||||
keyring.addFromSeed(stringToU8a(ALICE_SEED));
|
|
||||||
keyring.addFromSeed(stringToU8a(BOB_SEED));
|
|
||||||
|
|
||||||
// Note that we did not use `addFromAddress` since it does not add the
|
|
||||||
// secret key to memory so we cannot later retrieve it with `getPairs`
|
|
||||||
|
|
||||||
// Retrieve all keyring pairs from the keyring pair dictionary
|
|
||||||
keyring
|
|
||||||
.getPairs()
|
|
||||||
.forEach((pair, index) => {
|
|
||||||
const { address } = pair;
|
|
||||||
|
|
||||||
console.log(`\nAccount with index #${index} has json: `, JSON.stringify(keyring.toJson(address), null, 2));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
main().catch(console.error).finally(() => process.exit());
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "02_load_accounts",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"description": "Example showing how to load accounts",
|
|
||||||
"main": "index.js",
|
|
||||||
"author": "ltfschoen",
|
|
||||||
"license": "MIT",
|
|
||||||
"scripts": {
|
|
||||||
"clean": "rimraf node_modules",
|
|
||||||
"start": "node index.js"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@polkadot/util": "^0.32.10",
|
|
||||||
"@polkadot/keyring": "^0.32.10"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"rimraf": "^2.6.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# Validate Adress
|
|
||||||
|
|
||||||
- This function will return true if the address is a legitamate Polkadot address and false if it is not
|
|
||||||
|
|
||||||
- Works both with Ed25519 and Sr25519 key types
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
/* 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)
|
|
||||||
);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (error) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const isValid = isValidAddressPolkadotAddress();
|
|
||||||
|
|
||||||
console.log(isValid);
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "03_validate_address",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"description": "Example showing how to validate a polkadot address",
|
|
||||||
"main": "index.js",
|
|
||||||
"author": "Jesse",
|
|
||||||
"license": "MIT",
|
|
||||||
"scripts": {
|
|
||||||
"clean": "rimraf node_modules",
|
|
||||||
"start": "node index.js"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@polkadot/keyring": "*"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"rimraf": "^2.6.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# Keyring Examples
|
|
||||||
|
|
||||||
Here you will find a list of examples that takes you through the basics of connecting to a local node, retrieving data from the Node and chain and execute transactions on the chain.
|
|
||||||
|
|
||||||
## Running the examples
|
|
||||||
|
|
||||||
From within each folder run the following to install required dependencies and to execute the example:
|
|
||||||
```shell
|
|
||||||
yarn;
|
|
||||||
yarn start
|
|
||||||
```
|
|
||||||
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# Encrypt & Decrypt Message using NaCl
|
|
||||||
|
|
||||||
The following example shows how to encrypt and decrypt a message with NaCl (pronouced "salt"), which is a Networking and Cryptography library used in util-crypto.
|
|
||||||
|
|
||||||
[include](index.js)
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
/* eslint-disable header/header */
|
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
|
||||||
|
|
||||||
const { naclDecrypt, naclEncrypt } = require('@polkadot/util-crypto');
|
|
||||||
|
|
||||||
async function main () {
|
|
||||||
const secret = new Uint8Array(32);
|
|
||||||
const messagePreEncryption = new Uint8Array([1, 2, 3, 4, 5, 4, 3, 2, 1]);
|
|
||||||
const noncePreEncryption = new Uint8Array(24);
|
|
||||||
|
|
||||||
// Encrypt the message
|
|
||||||
const { encrypted, nonce } = naclEncrypt(messagePreEncryption, secret, noncePreEncryption);
|
|
||||||
|
|
||||||
// Show contents of the encrypted message
|
|
||||||
console.log(`Encrypted message: ${JSON.stringify(encrypted, null, 2)}`);
|
|
||||||
|
|
||||||
// Decrypt the message
|
|
||||||
const messageDecrypted = naclDecrypt(encrypted, nonce, secret);
|
|
||||||
// Convert each Uint8Array to a string for comparison
|
|
||||||
const isMatch = messagePreEncryption.toString === messageDecrypted.toString;
|
|
||||||
|
|
||||||
// Verify that the decrypted message matches the original message
|
|
||||||
console.log(`Does the decrypted message match the original message? ${isMatch}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
main().catch(console.error).finally(() => process.exit());
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "01_encrypt_decrypt_message_nacl",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"description": "Example showing how to encrypt and decrypt a message using NaCl",
|
|
||||||
"main": "index.js",
|
|
||||||
"author": "ltfschoen",
|
|
||||||
"license": "MIT",
|
|
||||||
"scripts": {
|
|
||||||
"clean": "rimraf node_modules",
|
|
||||||
"start": "node index.js"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@polkadot/util-crypto": "^0.32.10"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"rimraf": "^2.6.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# Sign & Verify Message using NaCl
|
|
||||||
|
|
||||||
The following example shows how to sign and verify a message with NaCl (pronouced "salt"), which is a Networking and Cryptography library used in util-crypto.
|
|
||||||
|
|
||||||
[include](index.js)
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/* eslint-disable header/header */
|
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
|
||||||
|
|
||||||
const { stringToU8a, u8aToHex } = require('@polkadot/util');
|
|
||||||
const { naclEncrypt, naclKeypairFromSeed, naclSign, naclVerify, randomAsU8a } = require('@polkadot/util-crypto');
|
|
||||||
|
|
||||||
async function main () {
|
|
||||||
// Create account seed for Alice as fallback if generated mnemonic not valid
|
|
||||||
const seedAlice = 'Alice'.padEnd(32, ' ');
|
|
||||||
|
|
||||||
// Generate new public/secret keypair for Alice from the supplied seed
|
|
||||||
const { publicKey, secretKey } = naclKeypairFromSeed(stringToU8a(seedAlice));
|
|
||||||
|
|
||||||
// Encrypt message. Create Uint8Array's filled with random bytes of specified length
|
|
||||||
const secret = randomAsU8a(32);
|
|
||||||
const messagePreEncryption = stringToU8a('please send me DOTs');
|
|
||||||
const noncePreEncryption = randomAsU8a(24);
|
|
||||||
|
|
||||||
const { encrypted } = naclEncrypt(messagePreEncryption, secret, noncePreEncryption);
|
|
||||||
|
|
||||||
// Sign the message with a valid signature
|
|
||||||
const messageSignature = naclSign(encrypted, secretKey);
|
|
||||||
|
|
||||||
console.log(`Message signature: ${u8aToHex(messageSignature)}`);
|
|
||||||
|
|
||||||
// Validate that the message was correctly signed
|
|
||||||
const isValidSignature = naclVerify(encrypted, messageSignature, publicKey);
|
|
||||||
|
|
||||||
console.log(`Was the message correctly signed? ${isValidSignature}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
main().catch(console.error).finally(() => process.exit());
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "02_sign_verify_message_nacl",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"description": "Example showing how to sign and verify a message using NaCl",
|
|
||||||
"main": "index.js",
|
|
||||||
"author": "ltfschoen",
|
|
||||||
"license": "MIT",
|
|
||||||
"scripts": {
|
|
||||||
"clean": "rimraf node_modules",
|
|
||||||
"start": "node index.js"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@polkadot/util-crypto": "^0.32.10"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"rimraf": "^2.6.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# Create & Generate Mnemonic using BIP39
|
|
||||||
|
|
||||||
The following example shows how to create and generate mnemonics using BIP39.
|
|
||||||
|
|
||||||
[include](index.js)
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
/* eslint-disable header/header */
|
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
||||||
|
|
||||||
const { mnemonicGenerate, mnemonicToSeed, mnemonicValidate, naclKeypairFromSeed } = require('@polkadot/util-crypto');
|
|
||||||
|
|
||||||
async function main () {
|
|
||||||
// Create mnemonic string for Alice using BIP39
|
|
||||||
const mnemonicAlice = mnemonicGenerate();
|
|
||||||
|
|
||||||
console.log(`Generated mnemonic: ${mnemonicAlice}`);
|
|
||||||
|
|
||||||
// Validate the mnemic string that was generated
|
|
||||||
const isValidMnemonic = mnemonicValidate(mnemonicAlice);
|
|
||||||
|
|
||||||
console.log(`isValidMnemonic: ${isValidMnemonic}`);
|
|
||||||
|
|
||||||
// Create valid seed from mnemonic as u8a and convert it to a string
|
|
||||||
// FIXME - Replace with mnemonicToSeed once exposed
|
|
||||||
const seedAlice = mnemonicToSeed(mnemonicAlice);
|
|
||||||
|
|
||||||
// Generate new public/secret keypair for Alice from the supplied seed
|
|
||||||
const { publicKey, secretKey } = naclKeypairFromSeed(seedAlice);
|
|
||||||
|
|
||||||
// Encrypt, Sign and Validate the message. See Example 'Sign & Verify Message'
|
|
||||||
}
|
|
||||||
|
|
||||||
main().catch(console.error).finally(() => process.exit());
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "03_mnemonic_generate_validate_bip39",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"description": "Example showing how to sign and verify a message using NaCl",
|
|
||||||
"main": "index.js",
|
|
||||||
"author": "ltfschoen",
|
|
||||||
"license": "MIT",
|
|
||||||
"scripts": {
|
|
||||||
"clean": "rimraf node_modules",
|
|
||||||
"start": "node index.js"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@polkadot/util-crypto": "^0.32.10"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"rimraf": "^2.6.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
/* 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();
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# Util-Crypto Examples
|
|
||||||
|
|
||||||
Here you will find a list of examples that takes you through the basics of encrypting and decrypting messages using NaCl, signing a message with a seed and verifying it using NaCl, and generating and validating mnemonics for account seeds.
|
|
||||||
|
|
||||||
## Running the examples
|
|
||||||
|
|
||||||
From within each folder run the following to install required dependencies and to execute the example:
|
|
||||||
```shell
|
|
||||||
yarn;
|
|
||||||
yarn start
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="initial-scale=0.5, maximum-scale=1">
|
||||||
|
<meta http-equiv="refresh" content="0;URL='https://polkadot.js.org/docs/'" />
|
||||||
|
<title>Redirecting to https://polkadot.js.org/docs/</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
Redirecting to <a href="https://polkadot.js.org/docs/">https://polkadot.js.org/docs/</a>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 7.3 KiB |
+10
-3
@@ -6,14 +6,21 @@ const config = require('@polkadot/dev/config/jest');
|
|||||||
module.exports = Object.assign({}, config, {
|
module.exports = Object.assign({}, config, {
|
||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
'@polkadot/keyring(.*)$': '<rootDir>/packages/keyring/src/$1',
|
'@polkadot/keyring(.*)$': '<rootDir>/packages/keyring/src/$1',
|
||||||
|
'@polkadot/networks(.*)$': '<rootDir>/packages/networks/src/$1',
|
||||||
'@polkadot/util-(crypto)(.*)$': '<rootDir>/packages/util-$1/src/$2',
|
'@polkadot/util-(crypto)(.*)$': '<rootDir>/packages/util-$1/src/$2',
|
||||||
// eslint-disable-next-line sort-keys
|
// eslint-disable-next-line sort-keys
|
||||||
'@polkadot/util(.*)$': '<rootDir>/packages/util/src/$1'
|
'@polkadot/util(.*)$': '<rootDir>/packages/util/src/$1',
|
||||||
|
'@polkadot/x-(fetch|textdecoder|textencoder|ws)(.*)$': '<rootDir>/packages/x-$1/src/node'
|
||||||
},
|
},
|
||||||
modulePathIgnorePatterns: [
|
modulePathIgnorePatterns: [
|
||||||
'<rootDir>/packages/keyring/build',
|
'<rootDir>/packages/keyring/build',
|
||||||
|
'<rootDir>/packages/networks/build',
|
||||||
'<rootDir>/packages/util/build',
|
'<rootDir>/packages/util/build',
|
||||||
'<rootDir>/packages/util-crypto/build'
|
'<rootDir>/packages/util-crypto/build',
|
||||||
|
'<rootDir>/packages/x-fetch/build',
|
||||||
|
'<rootDir>/packages/x-textdecoder/build',
|
||||||
|
'<rootDir>/packages/x-textencoder/build',
|
||||||
|
'<rootDir>/packages/x-ws/build'
|
||||||
],
|
],
|
||||||
resolver: './jest.resolver.js'
|
resolver: '@polkadot/dev/config/jest-resolver'
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
// Copyright 2017-2020 @polkadot/util authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
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);
|
|
||||||
};
|
|
||||||
-13
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"npmClient": "yarn",
|
|
||||||
"useWorkspaces": true,
|
|
||||||
"command": {
|
|
||||||
"publish": {
|
|
||||||
"allowBranch": "master"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"packages": [
|
|
||||||
"packages/*"
|
|
||||||
],
|
|
||||||
"version": "3.5.1"
|
|
||||||
}
|
|
||||||
+8
-12
@@ -8,27 +8,23 @@
|
|||||||
],
|
],
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"babel-core": "^7.0.0-bridge.0",
|
"babel-core": "^7.0.0-bridge.0",
|
||||||
"typescript": "^4.0.3"
|
"typescript": "^4.0.5"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "polkadot-dev-build-ts",
|
"build": "polkadot-dev-build-ts",
|
||||||
"build:release": "polkadot-ci-ghact-build",
|
"build:release": "polkadot-ci-ghact-build",
|
||||||
"docs": "polkadot-dev-build-docs",
|
|
||||||
"docs:release": "polkadot-ci-ghact-docs",
|
|
||||||
"lint": "polkadot-dev-run-lint",
|
"lint": "polkadot-dev-run-lint",
|
||||||
"clean": "polkadot-dev-clean-build",
|
"clean": "polkadot-dev-clean-build",
|
||||||
|
"networks:crosscheck": "polkadot-dev-run-test packages/networks/src/crosscheck",
|
||||||
"postinstall": "polkadot-dev-yarn-only",
|
"postinstall": "polkadot-dev-yarn-only",
|
||||||
"test": "polkadot-dev-run-test --coverage --runInBand",
|
"test": "polkadot-dev-run-test --coverage --runInBand --testPathIgnorePatterns crosscheck",
|
||||||
"test:one": "polkadot-dev-run-test"
|
"test:one": "polkadot-dev-run-test"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.11.6",
|
"@babel/core": "^7.12.3",
|
||||||
"@polkadot/dev": "^0.55.54",
|
"@polkadot/dev": "^0.59.12",
|
||||||
"@polkadot/ts": "^0.3.47",
|
"@polkadot/ts": "^0.3.53",
|
||||||
"@types/jest": "^26.0.14",
|
"@types/jest": "^26.0.15"
|
||||||
"typedoc": "^0.19.2",
|
|
||||||
"typedoc-plugin-markdown": "^3.0.2",
|
|
||||||
"typedoc-plugin-no-inherit": "^1.2.0"
|
|
||||||
},
|
},
|
||||||
"version": "3.5.1"
|
"version": "3.7.1"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,3 @@ Classes and Functions can be imported as follows:
|
|||||||
```js
|
```js
|
||||||
import Keyring from '@polkadot/keyring';
|
import Keyring from '@polkadot/keyring';
|
||||||
```
|
```
|
||||||
|
|
||||||
## Utilities
|
|
||||||
|
|
||||||
[Utilities](SUMMARY.md)
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@polkadot/keyring",
|
"name": "@polkadot/keyring",
|
||||||
"version": "3.5.1",
|
"version": "3.7.1",
|
||||||
"description": "Keyring management",
|
"description": "Keyring management",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
@@ -27,8 +27,8 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/polkadot-js/common/tree/master/packages/keyring#readme",
|
"homepage": "https://github.com/polkadot-js/common/tree/master/packages/keyring#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.11.2",
|
"@babel/runtime": "^7.12.1",
|
||||||
"@polkadot/util": "3.5.1",
|
"@polkadot/util": "^3.7.1",
|
||||||
"@polkadot/util-crypto": "3.5.1"
|
"@polkadot/util-crypto": "^3.7.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,6 +84,16 @@ describe('keypair', (): void => {
|
|||||||
const signature = pair.sign(MESSAGE);
|
const signature = pair.sign(MESSAGE);
|
||||||
|
|
||||||
expect(pair.verify(MESSAGE, signature)).toBe(true);
|
expect(pair.verify(MESSAGE, signature)).toBe(true);
|
||||||
|
expect(pair.verify(new Uint8Array(), signature)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('signs and verifies (withType)', (): void => {
|
||||||
|
const MESSAGE = stringToU8a('this is a message');
|
||||||
|
const pair = keyring.getPair(publicKeyOne);
|
||||||
|
const signature = pair.sign(MESSAGE, { withType: true });
|
||||||
|
|
||||||
|
expect(pair.verify(MESSAGE, signature)).toBe(true);
|
||||||
|
expect(pair.verify(new Uint8Array(), signature)).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -150,6 +160,16 @@ describe('keypair', (): void => {
|
|||||||
const signature = pair.sign(MESSAGE);
|
const signature = pair.sign(MESSAGE);
|
||||||
|
|
||||||
expect(pair.verify(MESSAGE, signature)).toBe(true);
|
expect(pair.verify(MESSAGE, signature)).toBe(true);
|
||||||
|
expect(pair.verify(new Uint8Array(), signature)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('signs and verifies (withType)', (): void => {
|
||||||
|
const MESSAGE = stringToU8a('this is a message');
|
||||||
|
const pair = keyring.getPair(publicKeyOne);
|
||||||
|
const signature = pair.sign(MESSAGE, { withType: true });
|
||||||
|
|
||||||
|
expect(pair.verify(MESSAGE, signature)).toBe(true);
|
||||||
|
expect(pair.verify(new Uint8Array(), signature)).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -245,6 +265,16 @@ describe('keypair', (): void => {
|
|||||||
const signature = pair.sign(MESSAGE);
|
const signature = pair.sign(MESSAGE);
|
||||||
|
|
||||||
expect(pair.verify(MESSAGE, signature)).toBe(true);
|
expect(pair.verify(MESSAGE, signature)).toBe(true);
|
||||||
|
expect(pair.verify(new Uint8Array(), signature)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('signs and verifies (withType)', (): void => {
|
||||||
|
const MESSAGE = stringToU8a('this is a message');
|
||||||
|
const pair = keyring.getPair(addressKeyOne);
|
||||||
|
const signature = pair.sign(MESSAGE, { withType: true });
|
||||||
|
|
||||||
|
expect(pair.verify(MESSAGE, signature)).toBe(true);
|
||||||
|
expect(pair.verify(new Uint8Array(), signature)).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -300,6 +330,20 @@ describe('keypair', (): void => {
|
|||||||
const signature = signer.sign(MESSAGE);
|
const signature = signer.sign(MESSAGE);
|
||||||
|
|
||||||
expect(verifier.verify(MESSAGE, signature)).toBe(true);
|
expect(verifier.verify(MESSAGE, signature)).toBe(true);
|
||||||
|
expect(verifier.verify(new Uint8Array(), signature)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows for signing/verification (withType)', (): 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, { withType: true });
|
||||||
|
|
||||||
|
expect(verifier.verify(MESSAGE, signature)).toBe(true);
|
||||||
|
expect(verifier.verify(new Uint8Array(), signature)).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { KeypairType, Keypair } from '@polkadot/util-crypto/types';
|
|||||||
import { KeyringInstance, KeyringPair, KeyringPair$Json, KeyringPair$JsonEncodingTypes, KeyringPair$Meta, KeyringOptions } from './types';
|
import { KeyringInstance, KeyringPair, KeyringPair$Json, KeyringPair$JsonEncodingTypes, KeyringPair$Meta, KeyringOptions } from './types';
|
||||||
|
|
||||||
import { assert, hexToU8a, isHex, isUndefined, stringToU8a } from '@polkadot/util';
|
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 { base64Decode, decodeAddress, encodeAddress, keyExtractSuri, keyFromPath, naclKeypairFromSeed as naclFromSeed, schnorrkelKeypairFromSeed as schnorrkelFromSeed, secp256k1KeypairFromSeed as secp256k1FromSeed, mnemonicToLegacySeed, mnemonicToMiniSecret } from '@polkadot/util-crypto';
|
||||||
|
|
||||||
import { DEV_PHRASE } from './defaults';
|
import { DEV_PHRASE } from './defaults';
|
||||||
import createPair from './pair';
|
import createPair from './pair';
|
||||||
@@ -183,7 +183,7 @@ export default class Keyring implements KeyringInstance {
|
|||||||
|
|
||||||
if ([12, 15, 18, 21, 24].includes(parts.length)) {
|
if ([12, 15, 18, 21, 24].includes(parts.length)) {
|
||||||
seed = type === 'ethereum'
|
seed = type === 'ethereum'
|
||||||
? mnemonicToBip39(phrase)
|
? mnemonicToLegacySeed(phrase)
|
||||||
: mnemonicToMiniSecret(phrase, password);
|
: mnemonicToMiniSecret(phrase, password);
|
||||||
} else {
|
} else {
|
||||||
assert(str.length <= 32, 'specified phrase is not a valid mnemonic and is invalid as a raw seed at > 32 bytes');
|
assert(str.length <= 32, 'specified phrase is not a valid mnemonic and is invalid as a raw seed at > 32 bytes');
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { KeyringPair, KeyringPair$Json, KeyringPair$JsonEncodingTypes, KeyringPa
|
|||||||
import { PairInfo } from './types';
|
import { PairInfo } from './types';
|
||||||
|
|
||||||
import { assert, u8aConcat, u8aToHex } from '@polkadot/util';
|
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 { blake2AsU8a, ethereumEncode, keccakAsU8a, keyExtractPath, keyFromPath, naclKeypairFromSeed as naclFromSeed, naclSign, schnorrkelKeypairFromSeed as schnorrkelFromSeed, schnorrkelSign, secp256k1Expand, secp256k1KeypairFromSeed as secp256k1FromSeed, secp256k1Sign, secp256k1Compress, signatureVerify } from '@polkadot/util-crypto';
|
||||||
|
|
||||||
import decode from './decode';
|
import decode from './decode';
|
||||||
import encode from './encode';
|
import encode from './encode';
|
||||||
@@ -47,13 +47,6 @@ const TYPE_ADDRESS = {
|
|||||||
sr25519: (p: Uint8Array) => 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 {
|
function isEmpty (u8a: Uint8Array): boolean {
|
||||||
return u8a.reduce((count, u8) => count + u8, 0) === 0;
|
return u8a.reduce((count, u8) => count + u8, 0) === 0;
|
||||||
}
|
}
|
||||||
@@ -185,6 +178,6 @@ export default function createPair ({ toSS58, type }: Setup, { publicKey, secret
|
|||||||
return toJson(type, { address, meta }, recode(passphrase), !!passphrase);
|
return toJson(type, { address, meta }, recode(passphrase), !!passphrase);
|
||||||
},
|
},
|
||||||
verify: (message: Uint8Array, signature: Uint8Array): boolean =>
|
verify: (message: Uint8Array, signature: Uint8Array): boolean =>
|
||||||
TYPE_VERIFY[type](message, signature, publicKey)
|
signatureVerify(message, signature, TYPE_ADDRESS[type](publicKey), type === 'ethereum').isValid
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# @polkadot/networks
|
||||||
|
|
||||||
|
A list of all available Substrate networks and their applicable prefixes.
|
||||||
|
|
||||||
|
This list is periodically checked against the master list available at https://github.com/paritytech/substrate/blob/master/ss58-registry.json
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "@polkadot/networks",
|
||||||
|
"version": "3.7.1",
|
||||||
|
"description": "A list of all available Substrate networks and their applicable prefixes",
|
||||||
|
"main": "index.js",
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public",
|
||||||
|
"registry": "https://registry.npmjs.org"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/polkadot-js/common.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"Polkadot",
|
||||||
|
"ss58"
|
||||||
|
],
|
||||||
|
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||||
|
"maintainers": [
|
||||||
|
"Jaco Greeff <jacogr@gmail.com>"
|
||||||
|
],
|
||||||
|
"contributors": [],
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/polkadot-js/common/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/polkadot-js/common/tree/master/packages/networks#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.12.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@polkadot/util": "^3.7.1",
|
||||||
|
"@polkadot/x-fetch": "^3.7.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
// Copyright 2017-2020 @polkadot/networks authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import { Ss58Registry } from './types';
|
||||||
|
|
||||||
|
import fs from 'fs';
|
||||||
|
import fetch from '@polkadot/x-fetch';
|
||||||
|
|
||||||
|
import { all } from './';
|
||||||
|
|
||||||
|
const ORIGINAL = 'https://raw.githubusercontent.com/paritytech/substrate/master/ss58-registry.json';
|
||||||
|
const OUTPUT = './.github/ss58-check.md';
|
||||||
|
|
||||||
|
function assertAndLog (check: boolean, error: string): void {
|
||||||
|
if (!check) {
|
||||||
|
process.env.CI_LOG && fs.appendFileSync(OUTPUT, `
|
||||||
|
|
||||||
|
${error}
|
||||||
|
`);
|
||||||
|
|
||||||
|
throw new Error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('check latest Substrate ss58 registry', (): void => {
|
||||||
|
let original: Ss58Registry;
|
||||||
|
|
||||||
|
beforeAll(async (): Promise<void> => {
|
||||||
|
original = (await (await fetch(ORIGINAL)).json()) as Ss58Registry;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has the same number as the original', (): void => {
|
||||||
|
assertAndLog(all.length === original.registry.length, `Number of entries mismatched:: Expected ${original.registry.length} found ${all.length}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has no missing any entries', (): void => {
|
||||||
|
const missing = original.registry
|
||||||
|
.filter(({ prefix }) => !all.some((n) => n.prefix === prefix))
|
||||||
|
.map(({ displayName, prefix }) => `${displayName} (${prefix})`);
|
||||||
|
|
||||||
|
assertAndLog(!missing.length, `Missing entries found: ${JSON.stringify(missing, null, 2)}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has no extra entries', (): void => {
|
||||||
|
const missing = all
|
||||||
|
.filter(({ prefix }) => !original.registry.some((n) => n.prefix === prefix))
|
||||||
|
.map(({ displayName, prefix }) => `${displayName} (${prefix})`);
|
||||||
|
|
||||||
|
assertAndLog(!missing.length, `Extra entries found: ${JSON.stringify(missing, null, 2)}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has the same values as the original', (): void => {
|
||||||
|
const fields = Object.keys(original.schema);
|
||||||
|
const errors = original.registry
|
||||||
|
.map((n): [string, string[]] => {
|
||||||
|
const other = all.find(({ prefix }) => prefix === n.prefix);
|
||||||
|
|
||||||
|
return [
|
||||||
|
`${n.displayName} (${n.prefix})`,
|
||||||
|
other
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
? fields.filter((f) => JSON.stringify(n[f]) !== JSON.stringify(other[f]))
|
||||||
|
: []
|
||||||
|
];
|
||||||
|
})
|
||||||
|
.filter(([, fields]) => fields.length);
|
||||||
|
|
||||||
|
assertAndLog(!errors.length, `Mismatches found: ${JSON.stringify(errors.map(([name, m]) => `${name}:: ${m.join(', ')}`), null, 2)}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// Copyright 2017-2020 @polkadot/networks authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import filtered from './';
|
||||||
|
|
||||||
|
describe('filtered', (): void => {
|
||||||
|
it('has the correct starting order', (): void => {
|
||||||
|
expect(filtered.slice(0, 3).map(({ prefix }) => prefix)).toEqual([0, 2, 42]);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,367 @@
|
|||||||
|
// Copyright 2017-2020 @polkadot/networks authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import { Network, NetworkFromSubstrate } from './types';
|
||||||
|
|
||||||
|
// These are known prefixes that are not sorted
|
||||||
|
const UNSORTED = [0, 2, 42];
|
||||||
|
|
||||||
|
// NOTE: In the case where the network was hard-spooned and multiple genesisHashes
|
||||||
|
// are provided, it needs to be in reverse order, i.e. most-recent first, oldest
|
||||||
|
// last. This make lookups for the current a simple genesisHash[0]
|
||||||
|
// (See Kusama as an example)
|
||||||
|
|
||||||
|
const createReserved = (prefix: number, displayName = 'This prefix is reserved.'): NetworkFromSubstrate => ({
|
||||||
|
decimals: null,
|
||||||
|
displayName,
|
||||||
|
network: `reserved${prefix}`,
|
||||||
|
prefix,
|
||||||
|
standardAccount: null,
|
||||||
|
symbols: null,
|
||||||
|
website: null
|
||||||
|
});
|
||||||
|
|
||||||
|
const all: NetworkFromSubstrate[] = [
|
||||||
|
{
|
||||||
|
decimals: [10],
|
||||||
|
displayName: 'Polkadot Relay Chain',
|
||||||
|
genesisHash: ['0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3'],
|
||||||
|
icon: 'polkadot',
|
||||||
|
network: 'polkadot',
|
||||||
|
prefix: 0,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['DOT'],
|
||||||
|
website: 'https://polkadot.network'
|
||||||
|
},
|
||||||
|
createReserved(1),
|
||||||
|
{
|
||||||
|
decimals: [12],
|
||||||
|
displayName: 'Kusama Relay Chain',
|
||||||
|
genesisHash: [
|
||||||
|
'0xb0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafe', // Kusama CC3,
|
||||||
|
'0xe3777fa922cafbff200cadeaea1a76bd7898ad5b89f7848999058b50e715f636', // Kusama CC2
|
||||||
|
'0x3fd7b9eb6a00376e5be61f01abb429ffb0b104be05eaff4d458da48fcd425baf' // Kusama CC1
|
||||||
|
],
|
||||||
|
icon: 'polkadot',
|
||||||
|
network: 'kusama',
|
||||||
|
prefix: 2,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['KSM'],
|
||||||
|
website: 'https://kusama.network'
|
||||||
|
},
|
||||||
|
createReserved(3),
|
||||||
|
{
|
||||||
|
decimals: null,
|
||||||
|
displayName: 'Katal Chain',
|
||||||
|
network: 'katalchain',
|
||||||
|
prefix: 4,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: null,
|
||||||
|
website: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: null,
|
||||||
|
displayName: 'Plasm Network',
|
||||||
|
genesisHash: ['0x3e86364d4b4894021cb2a0390bcf2feb5517d5292f2de2bb9404227e908b0b8b'],
|
||||||
|
network: 'plasm',
|
||||||
|
prefix: 5,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['PLM'],
|
||||||
|
website: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: [12],
|
||||||
|
displayName: 'Bifrost',
|
||||||
|
network: 'bifrost',
|
||||||
|
prefix: 6,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['BNC'],
|
||||||
|
website: 'https://bifrost.finance/'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: [18],
|
||||||
|
displayName: 'Edgeware',
|
||||||
|
genesisHash: ['0x742a2ca70c2fda6cee4f8df98d64c4c670a052d9568058982dad9d5a7a135c5b'],
|
||||||
|
network: 'edgeware',
|
||||||
|
prefix: 7,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['EDG'],
|
||||||
|
website: 'https://edgewa.re'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: [18],
|
||||||
|
displayName: 'Acala Karura Canary',
|
||||||
|
network: 'karura',
|
||||||
|
prefix: 8,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['KAR'],
|
||||||
|
website: 'https://acala.network/'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: [18],
|
||||||
|
displayName: 'Laminar Reynolds Canary',
|
||||||
|
network: 'reynolds',
|
||||||
|
prefix: 9,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['REY'],
|
||||||
|
website: 'http://laminar.network/'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: [18],
|
||||||
|
displayName: 'Acala',
|
||||||
|
network: 'acala',
|
||||||
|
prefix: 10,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['ACA'],
|
||||||
|
website: 'https://acala.network/'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: [18],
|
||||||
|
displayName: 'Laminar',
|
||||||
|
network: 'laminar',
|
||||||
|
prefix: 11,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['LAMI'],
|
||||||
|
website: 'http://laminar.network/'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: null,
|
||||||
|
displayName: 'Polymath',
|
||||||
|
network: 'polymath',
|
||||||
|
prefix: 12,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: null,
|
||||||
|
website: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: null,
|
||||||
|
displayName: 'SubstraTEE',
|
||||||
|
network: 'substratee',
|
||||||
|
prefix: 13,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: null,
|
||||||
|
website: 'https://www.substratee.com'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: [0],
|
||||||
|
displayName: 'Totem',
|
||||||
|
network: 'totem',
|
||||||
|
prefix: 14,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['XTX'],
|
||||||
|
website: 'https://totemaccounting.com'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: [12],
|
||||||
|
displayName: 'Kulupu',
|
||||||
|
genesisHash: ['0xf7a99d3cb92853d00d5275c971c132c074636256583fee53b3bbe60d7b8769ba'],
|
||||||
|
network: 'kulupu',
|
||||||
|
prefix: 16,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['KLP'],
|
||||||
|
website: 'https://kulupu.network/'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: null,
|
||||||
|
displayName: 'Dark Mainnet',
|
||||||
|
network: 'dark',
|
||||||
|
prefix: 17,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: null,
|
||||||
|
website: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: [9, 9],
|
||||||
|
displayName: 'Darwinia Network',
|
||||||
|
network: 'darwinia',
|
||||||
|
prefix: 18,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['RING', 'KTON'],
|
||||||
|
website: 'https://darwinia.network/'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: [12],
|
||||||
|
displayName: 'GeekCash',
|
||||||
|
network: 'geek',
|
||||||
|
prefix: 19,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['GEEK'],
|
||||||
|
website: 'https://geekcash.org'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: [12],
|
||||||
|
displayName: 'Stafi',
|
||||||
|
genesisHash: ['0x290a4149f09ea0e402c74c1c7e96ae4239588577fe78932f94f5404c68243d80'],
|
||||||
|
network: 'stafi',
|
||||||
|
prefix: 20,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['FIS'],
|
||||||
|
website: 'https://stafi.io'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: [6],
|
||||||
|
displayName: 'Dock Testnet',
|
||||||
|
genesisHash: ['0x3f0608444cf5d7eec977430483ffef31ff86dfa6bfc6d7114023ee80cc03ea3f'],
|
||||||
|
network: 'dock-testnet',
|
||||||
|
prefix: 21,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['DCK'],
|
||||||
|
website: 'https://dock.io'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: [6],
|
||||||
|
displayName: 'Dock Mainnet',
|
||||||
|
genesisHash: ['0xf73467c6544aa68df2ee546b135f955c46b90fa627e9b5d7935f41061bb8a5a9'],
|
||||||
|
network: 'dock-mainnet',
|
||||||
|
prefix: 22,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['DCK'],
|
||||||
|
website: 'https://dock.io'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: null,
|
||||||
|
displayName: 'ShiftNrg',
|
||||||
|
network: 'shift',
|
||||||
|
prefix: 23,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: null,
|
||||||
|
website: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: [18],
|
||||||
|
displayName: 'ZERO',
|
||||||
|
network: 'zero',
|
||||||
|
prefix: 24,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['PLAY'],
|
||||||
|
website: 'https://zero.io'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: [18],
|
||||||
|
displayName: 'ZERO Alphaville',
|
||||||
|
network: 'zero-alphaville',
|
||||||
|
prefix: 25,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['PLAY'],
|
||||||
|
website: 'https://zero.io'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: null,
|
||||||
|
displayName: 'Subsocial',
|
||||||
|
genesisHash: ['0x0bd72c1c305172e1275278aaeb3f161e02eccb7a819e63f62d47bd53a28189f8'],
|
||||||
|
network: 'subsocial',
|
||||||
|
prefix: 28,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: null,
|
||||||
|
website: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: null,
|
||||||
|
displayName: 'Phala Network',
|
||||||
|
network: 'phala',
|
||||||
|
prefix: 30,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: null,
|
||||||
|
website: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: null,
|
||||||
|
displayName: 'Robonomics Network',
|
||||||
|
network: 'robonomics',
|
||||||
|
prefix: 32,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: null,
|
||||||
|
website: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: null,
|
||||||
|
displayName: 'DataHighway',
|
||||||
|
network: 'datahighway',
|
||||||
|
prefix: 33,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: null,
|
||||||
|
website: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: [18],
|
||||||
|
displayName: 'Centrifuge Chain',
|
||||||
|
network: 'centrifuge',
|
||||||
|
prefix: 36,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['RAD'],
|
||||||
|
website: 'https://centrifuge.io/'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: [18],
|
||||||
|
displayName: 'Nodle Chain',
|
||||||
|
network: 'nodle',
|
||||||
|
prefix: 37,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['NODL'],
|
||||||
|
website: 'https://nodle.io/'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: [18],
|
||||||
|
displayName: 'MathChain mainnet',
|
||||||
|
network: 'mathchain',
|
||||||
|
prefix: 39,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['MATH'],
|
||||||
|
website: 'https://mathwallet.org'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: [18],
|
||||||
|
displayName: 'MathChain testnet',
|
||||||
|
network: 'mathchain-testnet',
|
||||||
|
prefix: 40,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['MATH'],
|
||||||
|
website: 'https://mathwallet.org'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
decimals: null,
|
||||||
|
displayName: 'Substrate',
|
||||||
|
network: 'substrate',
|
||||||
|
prefix: 42,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: null,
|
||||||
|
website: 'https://substrate.dev/'
|
||||||
|
},
|
||||||
|
createReserved(43),
|
||||||
|
{
|
||||||
|
decimals: [8],
|
||||||
|
displayName: 'ChainX',
|
||||||
|
network: 'chainx',
|
||||||
|
prefix: 44,
|
||||||
|
standardAccount: '*25519',
|
||||||
|
symbols: ['PCX'],
|
||||||
|
website: 'https://chainx.org/'
|
||||||
|
},
|
||||||
|
createReserved(46),
|
||||||
|
createReserved(47),
|
||||||
|
createReserved(48, 'All prefixes 48 and higher are reserved and cannot be allocated.')
|
||||||
|
];
|
||||||
|
|
||||||
|
// The list of available/claimed prefixes
|
||||||
|
// - we only include those where we have a standardAccount
|
||||||
|
// - when no icon has been specified, default to substrate
|
||||||
|
// - sort by name, however we keep 0, 2, 42 first in the list
|
||||||
|
const available: Network[] = all
|
||||||
|
.filter((n) => n.standardAccount === '*25519')
|
||||||
|
.map((n) => ({ ...n, genesisHash: n.genesisHash || [], icon: n.icon || 'substrate' }))
|
||||||
|
.sort((a, b) =>
|
||||||
|
UNSORTED.includes(a.prefix) && UNSORTED.includes(b.prefix)
|
||||||
|
? 0
|
||||||
|
: UNSORTED.includes(a.prefix)
|
||||||
|
? -1
|
||||||
|
: UNSORTED.includes(b.prefix)
|
||||||
|
? 1
|
||||||
|
: a.displayName.localeCompare(b.displayName)
|
||||||
|
);
|
||||||
|
|
||||||
|
// A filtered list of those chains we have details about (genesisHashes)
|
||||||
|
const filtered: Network[] = available.filter((n) => n.genesisHash.length || n.prefix === 42);
|
||||||
|
|
||||||
|
export { all, available };
|
||||||
|
|
||||||
|
export default filtered;
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2017-2020 @polkadot/keyring authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
export type Icon = 'beachball' | 'empty' | 'jdenticon' | 'polkadot' | 'substrate';
|
||||||
|
|
||||||
|
export interface NetworkFromSubstrate {
|
||||||
|
decimals: number[] | null,
|
||||||
|
displayName: string;
|
||||||
|
network: string;
|
||||||
|
prefix: number;
|
||||||
|
genesisHash?: string[] | null;
|
||||||
|
icon?: Icon | null;
|
||||||
|
standardAccount: '*25519' | null;
|
||||||
|
symbols: string[] | null;
|
||||||
|
website: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Network extends NetworkFromSubstrate {
|
||||||
|
genesisHash: string[];
|
||||||
|
icon: Icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Ss58Registry {
|
||||||
|
registry: NetworkFromSubstrate[];
|
||||||
|
specification: string;
|
||||||
|
schema: Record<string, string>;
|
||||||
|
}
|
||||||
@@ -15,7 +15,3 @@ Functions can be imported as follows:
|
|||||||
```js
|
```js
|
||||||
import { mnemonicGenerate } from '@polkadot/util-crypto';
|
import { mnemonicGenerate } from '@polkadot/util-crypto';
|
||||||
```
|
```
|
||||||
|
|
||||||
## Utilities
|
|
||||||
|
|
||||||
[Utilities](SUMMARY.md)
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@polkadot/util-crypto",
|
"name": "@polkadot/util-crypto",
|
||||||
"version": "3.5.1",
|
"version": "3.7.1",
|
||||||
"description": "A collection of useful crypto utilities for @polkadot",
|
"description": "A collection of useful crypto utilities for @polkadot",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@@ -25,13 +25,14 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/polkadot-js/common/tree/master/packages/util-crypto#readme",
|
"homepage": "https://github.com/polkadot-js/common/tree/master/packages/util-crypto#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.11.2",
|
"@babel/runtime": "^7.12.1",
|
||||||
"@polkadot/util": "3.5.1",
|
"@polkadot/networks": "^3.7.1",
|
||||||
|
"@polkadot/util": "^3.7.1",
|
||||||
"@polkadot/wasm-crypto": "^1.4.1",
|
"@polkadot/wasm-crypto": "^1.4.1",
|
||||||
"base-x": "^3.0.8",
|
"base-x": "^3.0.8",
|
||||||
"bip39": "^3.0.2",
|
|
||||||
"blakejs": "^1.1.0",
|
"blakejs": "^1.1.0",
|
||||||
"bn.js": "^5.1.3",
|
"bn.js": "^5.1.3",
|
||||||
|
"create-hash": "^1.2.0",
|
||||||
"elliptic": "^6.5.3",
|
"elliptic": "^6.5.3",
|
||||||
"js-sha3": "^0.8.0",
|
"js-sha3": "^0.8.0",
|
||||||
"pbkdf2": "^3.1.1",
|
"pbkdf2": "^3.1.1",
|
||||||
@@ -41,6 +42,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bn.js": "^4.11.6",
|
"@types/bn.js": "^4.11.6",
|
||||||
|
"@types/create-hash": "^1.2.2",
|
||||||
"@types/elliptic": "^6.4.12",
|
"@types/elliptic": "^6.4.12",
|
||||||
"@types/pbkdf2": "^3.1.0",
|
"@types/pbkdf2": "^3.1.0",
|
||||||
"@types/scryptsy": "^2.0.0",
|
"@types/scryptsy": "^2.0.0",
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import { hexToU8a } from '@polkadot/util';
|
||||||
|
|
||||||
|
import addressToEvm from './addressToEvm';
|
||||||
|
|
||||||
|
describe('addressToEvm', (): void => {
|
||||||
|
it('creates a valid known EVM address', (): void => {
|
||||||
|
expect(
|
||||||
|
addressToEvm('KWCv1L3QX9LDPwY4VzvLmarEmXjVJidUzZcinvVnmxAJJCBou')
|
||||||
|
).toEqual(hexToU8a('0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee9'));
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import decode from './decode';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name addressToEvm
|
||||||
|
* @summary Converts an SS58 address to its corresponding EVM address.
|
||||||
|
*/
|
||||||
|
export default function addressToEvm (address: string | Uint8Array, ignoreChecksum?: boolean): Uint8Array {
|
||||||
|
const decoded = decode(address, ignoreChecksum);
|
||||||
|
|
||||||
|
return decoded.subarray(0, 20);
|
||||||
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import { allowedSS58 } from './ss58';
|
import { available } from '@polkadot/networks';
|
||||||
|
|
||||||
const defaults = {
|
const defaults = {
|
||||||
allowedDecodedLengths: [1, 2, 4, 8, 32, 33],
|
allowedDecodedLengths: [1, 2, 4, 8, 32, 33],
|
||||||
// publicKey has prefix + 2 checksum bytes, short only prefix + 1 checksum byte
|
// publicKey has prefix + 2 checksum bytes, short only prefix + 1 checksum byte
|
||||||
allowedEncodedLengths: [3, 4, 6, 10, 35, 36],
|
allowedEncodedLengths: [3, 4, 6, 10, 35, 36],
|
||||||
allowedPrefix: allowedSS58,
|
allowedPrefix: available.map(({ prefix }) => prefix),
|
||||||
prefix: 42
|
prefix: 42
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import evmToAddress from './evmToAddress';
|
||||||
|
|
||||||
|
describe('evmToAddress', (): void => {
|
||||||
|
it('creates a valid known SS58 address', (): void => {
|
||||||
|
expect(
|
||||||
|
evmToAddress('0xd43593c715fdd31c61141abd04a99fd6822c8558', 42, 'blake2')
|
||||||
|
).toEqual('5FrLxJsyJ5x9n2rmxFwosFraxFCKcXZDngRLNectCn64UjtZ');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fails when length is invalid', (): void => {
|
||||||
|
expect(
|
||||||
|
() => evmToAddress('0x1234567890ABCDEF1234567890ABCDEF')
|
||||||
|
).toThrow(/address length/);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import encode from './encode';
|
||||||
|
import { Prefix } from './types';
|
||||||
|
|
||||||
|
import hasher from '../secp256k1/hasher';
|
||||||
|
import { HashType } from '../secp256k1/types';
|
||||||
|
|
||||||
|
import { u8aConcat } from '@polkadot/util';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name evmToAddress
|
||||||
|
* @summary Converts an EVM address to its corresponding SS58 address.
|
||||||
|
*/
|
||||||
|
export default function evmToAddress (evmAddress: string | Uint8Array, ss58Format?: Prefix, hashType: HashType = 'blake2'): string {
|
||||||
|
const wrapError = (message: string) => `Converting ${evmAddress as string}: ${message}`;
|
||||||
|
|
||||||
|
const message = u8aConcat('evm:', evmAddress);
|
||||||
|
|
||||||
|
if (message.length !== 24) {
|
||||||
|
throw new Error(wrapError('Invalid evm address length'));
|
||||||
|
}
|
||||||
|
|
||||||
|
const address = hasher(hashType, message);
|
||||||
|
|
||||||
|
return encode(address, ss58Format);
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import addressToEvm from './addressToEvm';
|
||||||
import checkAddress from './check';
|
import checkAddress from './check';
|
||||||
import checkAddressChecksum from './checkChecksum';
|
import checkAddressChecksum from './checkChecksum';
|
||||||
import createKeyMulti from './keyMulti';
|
import createKeyMulti from './keyMulti';
|
||||||
@@ -10,12 +11,14 @@ import deriveAddress from './derive';
|
|||||||
import encodeAddress from './encode';
|
import encodeAddress from './encode';
|
||||||
import encodeDerivedAddress from './encodeDerived';
|
import encodeDerivedAddress from './encodeDerived';
|
||||||
import encodeMultiAddress from './encodeMulti';
|
import encodeMultiAddress from './encodeMulti';
|
||||||
|
import evmToAddress from './evmToAddress';
|
||||||
import addressEq from './eq';
|
import addressEq from './eq';
|
||||||
import setSS58Format from './setSS58Format';
|
import setSS58Format from './setSS58Format';
|
||||||
import sortAddresses from './sort';
|
import sortAddresses from './sort';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
addressEq,
|
addressEq,
|
||||||
|
addressToEvm,
|
||||||
checkAddress,
|
checkAddress,
|
||||||
checkAddressChecksum,
|
checkAddressChecksum,
|
||||||
createKeyDerived,
|
createKeyDerived,
|
||||||
@@ -25,6 +28,7 @@ export {
|
|||||||
encodeAddress,
|
encodeAddress,
|
||||||
encodeDerivedAddress,
|
encodeDerivedAddress,
|
||||||
encodeMultiAddress,
|
encodeMultiAddress,
|
||||||
|
evmToAddress,
|
||||||
setSS58Format,
|
setSS58Format,
|
||||||
sortAddresses
|
sortAddresses
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
export const allowedSS58 = [
|
|
||||||
// Polkadot
|
|
||||||
0, 1,
|
|
||||||
// Kusama
|
|
||||||
2, 3,
|
|
||||||
// Katal Chain
|
|
||||||
4,
|
|
||||||
// Kulupu
|
|
||||||
16, 17,
|
|
||||||
// Dothereum
|
|
||||||
20,
|
|
||||||
// Dock testnet and mainnet
|
|
||||||
21, 22,
|
|
||||||
// Substrate default
|
|
||||||
42, 43,
|
|
||||||
// Substrate BBQ (deprecated)
|
|
||||||
68, 69
|
|
||||||
];
|
|
||||||
@@ -17,6 +17,25 @@ const LOOKUP = BASE32_ALPHABET
|
|||||||
return lookup;
|
return lookup;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
function decode (output: Uint8Array, input: string, offset: number): [Uint8Array, number, number] {
|
||||||
|
let bits = 0;
|
||||||
|
let buffer = 0;
|
||||||
|
let written = 0;
|
||||||
|
|
||||||
|
for (let i = offset; i < input.length; i++) {
|
||||||
|
buffer = (buffer << BITS_PER_CHAR) | LOOKUP[input[i]];
|
||||||
|
bits += BITS_PER_CHAR;
|
||||||
|
|
||||||
|
if (bits >= 8) {
|
||||||
|
bits -= 8;
|
||||||
|
output[written++] = 0xff & (buffer >> bits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [output, bits, buffer];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name base32Decode
|
* @name base32Decode
|
||||||
* @summary Delookup a base32 value.
|
* @summary Delookup a base32 value.
|
||||||
@@ -26,22 +45,14 @@ const LOOKUP = BASE32_ALPHABET
|
|||||||
export default function base32Decode (value: string, ipfsCompat = false): Uint8Array {
|
export default function base32Decode (value: string, ipfsCompat = false): Uint8Array {
|
||||||
validate(value, ipfsCompat);
|
validate(value, ipfsCompat);
|
||||||
|
|
||||||
const out = new Uint8Array(((value.length - (ipfsCompat ? 1 : 0)) * BITS_PER_CHAR / 8) | 0);
|
const offset = (ipfsCompat ? 1 : 0);
|
||||||
let bits = 0;
|
const [output, bits, buffer] = decode(
|
||||||
let buffer = 0;
|
new Uint8Array(((value.length - offset) * BITS_PER_CHAR / 8) | 0),
|
||||||
let written = 0;
|
value,
|
||||||
|
offset
|
||||||
for (let i = (ipfsCompat ? 1 : 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');
|
assert(!(bits >= BITS_PER_CHAR || 0xff & (buffer << (8 - bits))), 'Unexpected end of data');
|
||||||
|
|
||||||
return out;
|
return output;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,124 @@
|
|||||||
|
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
// Adapted from the bitcoinjs/bip39 source
|
||||||
|
// https://github.com/bitcoinjs/bip39/blob/1d063b6a6aee4145b34d701037cd3e67f5446ff9/ts_src/index.ts
|
||||||
|
// Copyright (c) 2014, Wei Lu <luwei.here@gmail.com> and Daniel Cousens <email@dcousens.com>
|
||||||
|
// ISC Licence
|
||||||
|
//
|
||||||
|
// Change made in this version -
|
||||||
|
// - Adjust formatting (just eslint differences)
|
||||||
|
// - Only English wordlist (this aligns with the wasm-crypto implementation)
|
||||||
|
// - Use util-crypto randomAsU8a (instead of randombytes)
|
||||||
|
// - Remove setting of wordlost passing of wordlist in functions
|
||||||
|
// - Remove mnemonicToSeed (we only use the sync variant)
|
||||||
|
|
||||||
|
import createHash from 'create-hash';
|
||||||
|
import { pbkdf2Sync } from 'pbkdf2';
|
||||||
|
import { assert, u8aToU8a } from '@polkadot/util';
|
||||||
|
|
||||||
|
import randomAsU8a from '../random/asU8a';
|
||||||
|
import DEFAULT_WORDLIST from './bip39-en';
|
||||||
|
|
||||||
|
const INVALID_MNEMONIC = 'Invalid mnemonic';
|
||||||
|
const INVALID_ENTROPY = 'Invalid entropy';
|
||||||
|
const INVALID_CHECKSUM = 'Invalid mnemonic checksum';
|
||||||
|
|
||||||
|
function normalize (str?: string): string {
|
||||||
|
return (str || '').normalize('NFKD');
|
||||||
|
}
|
||||||
|
|
||||||
|
function binaryToByte (bin: string): number {
|
||||||
|
return parseInt(bin, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function bytesToBinary (bytes: number[]): string {
|
||||||
|
return bytes.map((x: number) => x.toString(2).padStart(8, '0')).join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
function deriveChecksumBits (entropyBuffer: Uint8Array): string {
|
||||||
|
const ENT = entropyBuffer.length * 8;
|
||||||
|
const CS = ENT / 32;
|
||||||
|
const hash = createHash('sha256')
|
||||||
|
.update(entropyBuffer)
|
||||||
|
.digest();
|
||||||
|
|
||||||
|
return bytesToBinary(Array.from(hash)).slice(0, CS);
|
||||||
|
}
|
||||||
|
|
||||||
|
function salt (password?: string): string {
|
||||||
|
return 'mnemonic' + (password || '');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mnemonicToSeedSync (mnemonic: string, password?: string): Buffer {
|
||||||
|
const mnemonicBuffer = Buffer.from(normalize(mnemonic), 'utf8');
|
||||||
|
const saltBuffer = Buffer.from(salt(normalize(password)), 'utf8');
|
||||||
|
|
||||||
|
return pbkdf2Sync(mnemonicBuffer, saltBuffer, 2048, 64, 'sha512');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mnemonicToEntropy (mnemonic: string): Uint8Array {
|
||||||
|
const words = normalize(mnemonic).split(' ');
|
||||||
|
|
||||||
|
assert(words.length % 3 === 0, INVALID_MNEMONIC);
|
||||||
|
|
||||||
|
// convert word indices to 11 bit binary strings
|
||||||
|
const bits = words
|
||||||
|
.map((word): string => {
|
||||||
|
const index = DEFAULT_WORDLIST.indexOf(word);
|
||||||
|
|
||||||
|
assert(index !== -1, INVALID_MNEMONIC);
|
||||||
|
|
||||||
|
return index.toString(2).padStart(11, '0');
|
||||||
|
})
|
||||||
|
.join('');
|
||||||
|
|
||||||
|
// split the binary string into ENT/CS
|
||||||
|
const dividerIndex = Math.floor(bits.length / 33) * 32;
|
||||||
|
const entropyBits = bits.slice(0, dividerIndex);
|
||||||
|
const checksumBits = bits.slice(dividerIndex);
|
||||||
|
|
||||||
|
// calculate the checksum and compare
|
||||||
|
const entropyBytes = entropyBits.match(/(.{1,8})/g)?.map(binaryToByte);
|
||||||
|
|
||||||
|
assert(entropyBytes && entropyBytes.length % 4 === 0 && entropyBytes.length >= 16 && entropyBytes.length <= 32, INVALID_ENTROPY);
|
||||||
|
|
||||||
|
const entropy = u8aToU8a(entropyBytes);
|
||||||
|
const newChecksum = deriveChecksumBits(entropy);
|
||||||
|
|
||||||
|
assert(newChecksum === checksumBits, INVALID_CHECKSUM);
|
||||||
|
|
||||||
|
return entropy;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function entropyToMnemonic (entropy: Uint8Array): string {
|
||||||
|
// 128 <= ENT <= 256
|
||||||
|
assert(entropy.length % 4 === 0 && entropy.length >= 16 && entropy.length <= 32, INVALID_ENTROPY);
|
||||||
|
|
||||||
|
const entropyBits = bytesToBinary(Array.from(entropy));
|
||||||
|
const checksumBits = deriveChecksumBits(entropy);
|
||||||
|
|
||||||
|
// we just set it prior, so this is a safe check
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
return (entropyBits + checksumBits).match(/(.{1,11})/g)!
|
||||||
|
.map((binary) => DEFAULT_WORDLIST[binaryToByte(binary)])
|
||||||
|
.join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateMnemonic (strength?: number): string {
|
||||||
|
strength = strength || 128;
|
||||||
|
|
||||||
|
assert(strength % 32 === 0, INVALID_ENTROPY);
|
||||||
|
|
||||||
|
return entropyToMnemonic(randomAsU8a(strength / 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validateMnemonic (mnemonic: string): boolean {
|
||||||
|
try {
|
||||||
|
mnemonicToEntropy(mnemonic);
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -11,24 +11,20 @@ describe('mnemonicGenerate', (): void => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('generates a valid mnemonic (default strength)', (): void => {
|
it('generates a valid mnemonic (default strength)', (): void => {
|
||||||
const mnemonic = generate();
|
|
||||||
|
|
||||||
console.error(mnemonic);
|
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
validate(mnemonic)
|
validate(generate())
|
||||||
).toEqual(true);
|
).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
([12, 15, 18, 21, 24] as WordCount[]).forEach((num: WordCount): void => {
|
([12, 15, 18, 21, 24] as WordCount[]).forEach((num: WordCount): void => {
|
||||||
it(`generates a valid mnemonic (${num} words)`, (): void => {
|
it(`generates a valid mnemonic (${num} words)`, (): void => {
|
||||||
const mnemonic = generate(num);
|
[false, true].forEach((onlyJs): void => {
|
||||||
const isValid = validate(mnemonic);
|
const mnemonic = generate(num, onlyJs);
|
||||||
|
const isValid = validate(mnemonic);
|
||||||
|
|
||||||
console.error(mnemonic);
|
expect(mnemonic.split(' ')).toHaveLength(num);
|
||||||
|
expect(isValid).toEqual(true);
|
||||||
expect(mnemonic.split(' ')).toHaveLength(num);
|
});
|
||||||
expect(isValid).toEqual(true);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,9 +3,10 @@
|
|||||||
|
|
||||||
import '../polyfill';
|
import '../polyfill';
|
||||||
|
|
||||||
import { generateMnemonic } from 'bip39';
|
|
||||||
import { bip39Generate, isReady } from '@polkadot/wasm-crypto';
|
import { bip39Generate, isReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
|
import { generateMnemonic } from './bip39';
|
||||||
|
|
||||||
export type WordCount = 12 | 15 | 18 | 21 | 24;
|
export type WordCount = 12 | 15 | 18 | 21 | 24;
|
||||||
|
|
||||||
// mapping of words to the actual strength (as expected)
|
// mapping of words to the actual strength (as expected)
|
||||||
@@ -29,8 +30,8 @@ const STRENGTH_MAP = {
|
|||||||
* const mnemonic = mnemonicGenerate(); // => string
|
* const mnemonic = mnemonicGenerate(); // => string
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export default function mnemonicGenerate (numWords: WordCount = 12): string {
|
export default function mnemonicGenerate (numWords: WordCount = 12, onlyJs = false): string {
|
||||||
return isReady()
|
return isReady() && !onlyJs
|
||||||
? bip39Generate(numWords)
|
? bip39Generate(numWords)
|
||||||
: generateMnemonic(STRENGTH_MAP[numWords]);
|
: generateMnemonic(STRENGTH_MAP[numWords]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import '../polyfill';
|
|||||||
/**
|
/**
|
||||||
* @summary Create valid mnemonic strings, validate them using BIP39, and convert them to valid seeds
|
* @summary Create valid mnemonic strings, validate them using BIP39, and convert them to valid seeds
|
||||||
*/
|
*/
|
||||||
export { default as mnemonicToBip39 } from './toBip39';
|
|
||||||
export { default as mnemonicGenerate } from './generate';
|
export { default as mnemonicGenerate } from './generate';
|
||||||
export { default as mnemonicToEntropy } from './toEntropy';
|
export { default as mnemonicToEntropy } from './toEntropy';
|
||||||
|
export { default as mnemonicToLegacySeed } from './toLegacySeed';
|
||||||
export { default as mnemonicToMiniSecret } from './toMiniSecret';
|
export { default as mnemonicToMiniSecret } from './toMiniSecret';
|
||||||
export { default as mnemonicValidate } from './validate';
|
export { default as mnemonicValidate } from './validate';
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
import { u8aToHex } from '@polkadot/util';
|
|
||||||
import { waitReady } from '@polkadot/wasm-crypto';
|
|
||||||
|
|
||||||
import { mnemonicToBip39 } from './';
|
|
||||||
|
|
||||||
describe('mnemonicToBip39Seed', (): void => {
|
|
||||||
it('generates a valid seed', (): void => {
|
|
||||||
expect(
|
|
||||||
u8aToHex(
|
|
||||||
mnemonicToBip39('seed sock milk update focus rotate barely fade car face mechanic mercy')
|
|
||||||
)
|
|
||||||
).toEqual('0x3c121e20de068083b49c2315697fb59a2d9e8643c24e5ea7628132c58969a027');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('generates the seed via WASM', async (): Promise<void> => {
|
|
||||||
await waitReady();
|
|
||||||
|
|
||||||
expect(
|
|
||||||
u8aToHex(
|
|
||||||
mnemonicToBip39('seed sock milk update focus rotate barely fade car face mechanic mercy')
|
|
||||||
)
|
|
||||||
).toEqual('0x3c121e20de068083b49c2315697fb59a2d9e8643c24e5ea7628132c58969a027');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -15,6 +15,7 @@ describe('mnemonicToEntropy', (): void => {
|
|||||||
tests.forEach(([mnemonic, entropy], index): void => {
|
tests.forEach(([mnemonic, entropy], index): void => {
|
||||||
it(`Created correct entropy for ${index}`, (): void => {
|
it(`Created correct entropy for ${index}`, (): void => {
|
||||||
expect(u8aToHex(toEntropy(mnemonic))).toEqual(entropy);
|
expect(u8aToHex(toEntropy(mnemonic))).toEqual(entropy);
|
||||||
|
expect(u8aToHex(toEntropy(mnemonic, true))).toEqual(entropy);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,16 +3,12 @@
|
|||||||
|
|
||||||
import '../polyfill';
|
import '../polyfill';
|
||||||
|
|
||||||
import { mnemonicToEntropy } from 'bip39';
|
|
||||||
import { hexAddPrefix, hexToU8a } from '@polkadot/util';
|
|
||||||
import { bip39ToEntropy, isReady } from '@polkadot/wasm-crypto';
|
import { bip39ToEntropy, isReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
export default function toEntropy (mnemonic: string): Uint8Array {
|
import { mnemonicToEntropy } from './bip39';
|
||||||
return isReady()
|
|
||||||
|
export default function toEntropy (mnemonic: string, onlyJs = false): Uint8Array {
|
||||||
|
return isReady() && !onlyJs
|
||||||
? bip39ToEntropy(mnemonic)
|
? bip39ToEntropy(mnemonic)
|
||||||
: hexToU8a(
|
: mnemonicToEntropy(mnemonic);
|
||||||
hexAddPrefix(
|
|
||||||
mnemonicToEntropy(mnemonic)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import { u8aToHex } from '@polkadot/util';
|
||||||
|
import { waitReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
|
import { mnemonicToLegacySeed } from './';
|
||||||
|
|
||||||
|
const MENMONIC = 'seed sock milk update focus rotate barely fade car face mechanic mercy';
|
||||||
|
const SEED = '0x3c121e20de068083b49c2315697fb59a2d9e8643c24e5ea7628132c58969a027';
|
||||||
|
|
||||||
|
describe('mnemonicToLegacySeed', (): void => {
|
||||||
|
beforeEach(async (): Promise<void> => {
|
||||||
|
await waitReady();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('generates a valid seed', (): void => {
|
||||||
|
expect(
|
||||||
|
u8aToHex(mnemonicToLegacySeed(MENMONIC))
|
||||||
|
).toEqual(SEED);
|
||||||
|
expect(
|
||||||
|
u8aToHex(mnemonicToLegacySeed(MENMONIC, undefined, true))
|
||||||
|
).toEqual(SEED);
|
||||||
|
});
|
||||||
|
});
|
||||||
+4
-3
@@ -1,11 +1,12 @@
|
|||||||
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import { mnemonicToSeedSync } from 'bip39';
|
|
||||||
import { bufferToU8a } from '@polkadot/util';
|
import { bufferToU8a } from '@polkadot/util';
|
||||||
|
|
||||||
import { bip39ToSeed, isReady } from '@polkadot/wasm-crypto';
|
import { bip39ToSeed, isReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
|
import { mnemonicToSeedSync } from './bip39';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name toSeed
|
* @name toSeed
|
||||||
* @summary Creates a valid Ethereum/Bitcoin-compatible seed from a mnemonic input
|
* @summary Creates a valid Ethereum/Bitcoin-compatible seed from a mnemonic input
|
||||||
@@ -23,8 +24,8 @@ import { bip39ToSeed, isReady } from '@polkadot/wasm-crypto';
|
|||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export default function toBip39 (mnemonic: string, password = ''): Uint8Array {
|
export default function toLegacy (mnemonic: string, password = '', onlyJs = false): Uint8Array {
|
||||||
return isReady()
|
return isReady() && !onlyJs
|
||||||
? bip39ToSeed(mnemonic, password)
|
? bip39ToSeed(mnemonic, password)
|
||||||
: bufferToU8a(mnemonicToSeedSync(mnemonic, password)).subarray(0, 32);
|
: bufferToU8a(mnemonicToSeedSync(mnemonic, password)).subarray(0, 32);
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,9 @@ import mnemonicToMiniSecret from './toMiniSecret';
|
|||||||
import tests from '../schnorrkel/keypair/testing';
|
import tests from '../schnorrkel/keypair/testing';
|
||||||
import { cryptoWaitReady } from '..';
|
import { cryptoWaitReady } from '..';
|
||||||
|
|
||||||
|
const MNEMONIC = 'seed sock milk update focus rotate barely fade car face mechanic mercy';
|
||||||
|
const SEED = '0x4d1ab2a57929edfd018aaa974e62ed557e3f54b4104acabedf73c8f5a1dbb029';
|
||||||
|
|
||||||
describe('mnemonicToMiniSecret', (): void => {
|
describe('mnemonicToMiniSecret', (): void => {
|
||||||
beforeEach(async (): Promise<void> => {
|
beforeEach(async (): Promise<void> => {
|
||||||
await cryptoWaitReady();
|
await cryptoWaitReady();
|
||||||
@@ -14,8 +17,11 @@ describe('mnemonicToMiniSecret', (): void => {
|
|||||||
|
|
||||||
it('generates a valid seed', (): void => {
|
it('generates a valid seed', (): void => {
|
||||||
expect(
|
expect(
|
||||||
u8aToHex(mnemonicToMiniSecret('seed sock milk update focus rotate barely fade car face mechanic mercy'))
|
u8aToHex(mnemonicToMiniSecret(MNEMONIC))
|
||||||
).toEqual('0x4d1ab2a57929edfd018aaa974e62ed557e3f54b4104acabedf73c8f5a1dbb029');
|
).toEqual(SEED);
|
||||||
|
expect(
|
||||||
|
u8aToHex(mnemonicToMiniSecret(MNEMONIC, undefined, true))
|
||||||
|
).toEqual(SEED);
|
||||||
});
|
});
|
||||||
|
|
||||||
tests.forEach(([mnemonic, , seed], index): void => {
|
tests.forEach(([mnemonic, , seed], index): void => {
|
||||||
@@ -26,6 +32,12 @@ describe('mnemonicToMiniSecret', (): void => {
|
|||||||
// mini returned here, only check first 32-bytes (64 hex + 2 prefix)
|
// mini returned here, only check first 32-bytes (64 hex + 2 prefix)
|
||||||
seed.substr(0, 66)
|
seed.substr(0, 66)
|
||||||
);
|
);
|
||||||
|
expect(
|
||||||
|
u8aToHex(mnemonicToMiniSecret(mnemonic, 'Substrate', true))
|
||||||
|
).toEqual(
|
||||||
|
// mini returned here, only check first 32-bytes (64 hex + 2 prefix)
|
||||||
|
seed.substr(0, 66)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import { bip39ToMiniSecret, isReady } from '@polkadot/wasm-crypto';
|
|||||||
|
|
||||||
import toEntropy from './toEntropy';
|
import toEntropy from './toEntropy';
|
||||||
|
|
||||||
export default function toMiniSecret (mnemonic: string, password = ''): Uint8Array {
|
export default function toMiniSecret (mnemonic: string, password = '', onlyJs = false): Uint8Array {
|
||||||
if (isReady()) {
|
if (isReady() && !onlyJs) {
|
||||||
return bip39ToMiniSecret(mnemonic, password);
|
return bip39ToMiniSecret(mnemonic, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,11 +13,17 @@ describe('mnemonicValidate', (): void => {
|
|||||||
expect(
|
expect(
|
||||||
validate('seed sock milk update focus rotate barely fade car face mechanic mercy')
|
validate('seed sock milk update focus rotate barely fade car face mechanic mercy')
|
||||||
).toEqual(true);
|
).toEqual(true);
|
||||||
|
expect(
|
||||||
|
validate('seed sock milk update focus rotate barely fade car face mechanic mercy', true)
|
||||||
|
).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns false on invalid', (): void => {
|
it('returns false on invalid', (): void => {
|
||||||
expect(
|
expect(
|
||||||
validate('wine photo extra cushion basket dwarf humor cloud truck job boat submit')
|
validate('wine photo extra cushion basket dwarf humor cloud truck job boat submit')
|
||||||
).toEqual(false);
|
).toEqual(false);
|
||||||
|
expect(
|
||||||
|
validate('wine photo extra cushion basket dwarf humor cloud truck job boat submit', true)
|
||||||
|
).toEqual(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,9 +3,10 @@
|
|||||||
|
|
||||||
import '../polyfill';
|
import '../polyfill';
|
||||||
|
|
||||||
import { validateMnemonic } from 'bip39';
|
|
||||||
import { bip39Validate, isReady } from '@polkadot/wasm-crypto';
|
import { bip39Validate, isReady } from '@polkadot/wasm-crypto';
|
||||||
|
|
||||||
|
import { validateMnemonic } from './bip39';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name mnemonicValidate
|
* @name mnemonicValidate
|
||||||
* @summary Validates a mnemonic input using [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki).
|
* @summary Validates a mnemonic input using [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki).
|
||||||
@@ -19,8 +20,8 @@ import { bip39Validate, isReady } from '@polkadot/wasm-crypto';
|
|||||||
* const isValidMnemonic = mnemonicValidate(mnemonic); // => boolean
|
* const isValidMnemonic = mnemonicValidate(mnemonic); // => boolean
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export default function mnemonicValidate (mnemonic: string): boolean {
|
export default function mnemonicValidate (mnemonic: string, onlyJs = false): boolean {
|
||||||
return isReady()
|
return isReady() && !onlyJs
|
||||||
? bip39Validate(mnemonic)
|
? bip39Validate(mnemonic)
|
||||||
: validateMnemonic(mnemonic);
|
: validateMnemonic(mnemonic);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import elliptic from 'elliptic';
|
import { ec as EC } from 'elliptic';
|
||||||
import { assert } from '@polkadot/util';
|
import { assert } from '@polkadot/util';
|
||||||
|
|
||||||
const EC = elliptic.ec;
|
|
||||||
const ec = new EC('secp256k1');
|
const ec = new EC('secp256k1');
|
||||||
|
|
||||||
export default function secp256k1Compress (publicKey: Uint8Array): Uint8Array {
|
export default function secp256k1Compress (publicKey: Uint8Array): Uint8Array {
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import elliptic from 'elliptic';
|
import { ec as EC } from 'elliptic';
|
||||||
import { assert, bnToU8a, u8aConcat } from '@polkadot/util';
|
import { assert, bnToU8a, u8aConcat } from '@polkadot/util';
|
||||||
|
|
||||||
const EC = elliptic.ec;
|
|
||||||
const ec = new EC('secp256k1');
|
const ec = new EC('secp256k1');
|
||||||
|
|
||||||
export default function secp256k1Expand (publicKey: Uint8Array): Uint8Array {
|
export default function secp256k1Expand (publicKey: Uint8Array): Uint8Array {
|
||||||
|
|||||||
@@ -3,10 +3,9 @@
|
|||||||
|
|
||||||
import { Keypair } from '../../types';
|
import { Keypair } from '../../types';
|
||||||
|
|
||||||
import elliptic from 'elliptic';
|
import { ec as EC } from 'elliptic';
|
||||||
import { assert, bnToU8a } from '@polkadot/util';
|
import { assert, bnToU8a } from '@polkadot/util';
|
||||||
|
|
||||||
const EC = elliptic.ec;
|
|
||||||
const ec = new EC('secp256k1');
|
const ec = new EC('secp256k1');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import elliptic from 'elliptic';
|
import { ec as EC } from 'elliptic';
|
||||||
|
|
||||||
const EC = elliptic.ec;
|
|
||||||
const ec = new EC('secp256k1');
|
const ec = new EC('secp256k1');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -4,12 +4,11 @@
|
|||||||
import { Keypair } from '../types';
|
import { Keypair } from '../types';
|
||||||
import { HashType } from './types';
|
import { HashType } from './types';
|
||||||
|
|
||||||
import elliptic from 'elliptic';
|
import { ec as EC } from 'elliptic';
|
||||||
import { assert, bnToU8a, u8aConcat } from '@polkadot/util';
|
import { assert, bnToU8a, u8aConcat } from '@polkadot/util';
|
||||||
|
|
||||||
import hasher from './hasher';
|
import hasher from './hasher';
|
||||||
|
|
||||||
const EC = elliptic.ec;
|
|
||||||
const ec = new EC('secp256k1');
|
const ec = new EC('secp256k1');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,13 +3,12 @@
|
|||||||
|
|
||||||
import { HashType } from './types';
|
import { HashType } from './types';
|
||||||
|
|
||||||
import elliptic from 'elliptic';
|
import { ec as EC } from 'elliptic';
|
||||||
import { assert, u8aEq, u8aToU8a } from '@polkadot/util';
|
import { assert, u8aEq, u8aToU8a } from '@polkadot/util';
|
||||||
|
|
||||||
import secp256k1Expand from './expand';
|
import secp256k1Expand from './expand';
|
||||||
import hasher from './hasher';
|
import hasher from './hasher';
|
||||||
|
|
||||||
const EC = elliptic.ec;
|
|
||||||
const ec = new EC('secp256k1');
|
const ec = new EC('secp256k1');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -10,32 +10,33 @@ import naclVerify from '../nacl/verify';
|
|||||||
import schnorrkelVerify from '../schnorrkel/verify';
|
import schnorrkelVerify from '../schnorrkel/verify';
|
||||||
import secp256k1Verify from '../secp256k1/verify';
|
import secp256k1Verify from '../secp256k1/verify';
|
||||||
|
|
||||||
const VERIFIERS: [KeypairType, (message: Uint8Array | string, signature: Uint8Array | string, publicKey: Uint8Array | string) => boolean][] = [
|
type Verifier = [KeypairType, (message: Uint8Array | string, signature: Uint8Array | string, publicKey: Uint8Array | string, isExpanded?: boolean) => boolean];
|
||||||
['ed25519', naclVerify],
|
|
||||||
['sr25519', schnorrkelVerify],
|
const VERIFIERS_ECDSA: Verifier[] = [
|
||||||
[
|
[
|
||||||
'ecdsa',
|
'ecdsa',
|
||||||
(message: Uint8Array | string, signature: Uint8Array | string, publicKey: Uint8Array | string) =>
|
(message: Uint8Array | string, signature: Uint8Array | string, publicKey: Uint8Array | string, isExpanded?: boolean) =>
|
||||||
secp256k1Verify(message, signature, publicKey, 'blake2')
|
secp256k1Verify(message, signature, publicKey, 'blake2', isExpanded)
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'ethereum',
|
'ethereum',
|
||||||
(message: Uint8Array | string, signature: Uint8Array | string, publicKey: Uint8Array | string) =>
|
(message: Uint8Array | string, signature: Uint8Array | string, publicKey: Uint8Array | string, isExpanded?: boolean) =>
|
||||||
secp256k1Verify(message, signature, publicKey, 'keccak')
|
secp256k1Verify(message, signature, publicKey, 'keccak', isExpanded)
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
const CRYPTO_TYPES: KeypairType[] = [
|
const VERIFIERS: Verifier[] = [
|
||||||
'ed25519',
|
['ed25519', naclVerify],
|
||||||
'sr25519',
|
['sr25519', schnorrkelVerify],
|
||||||
'ecdsa',
|
...VERIFIERS_ECDSA
|
||||||
'ethereum'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
function verifyDetect (result: VerifyResult, message: Uint8Array | string, signature: Uint8Array, publicKey: Uint8Array): VerifyResult {
|
const CRYPTO_TYPES: ('ed25519' | 'sr25519' | 'ecdsa')[] = ['ed25519', 'sr25519', 'ecdsa'];
|
||||||
result.isValid = VERIFIERS.some(([crypto, verify]): boolean => {
|
|
||||||
|
function verifyDetect (result: VerifyResult, message: Uint8Array | string, signature: Uint8Array, publicKey: Uint8Array, isExpanded?: boolean, verifiers = VERIFIERS): VerifyResult {
|
||||||
|
result.isValid = verifiers.some(([crypto, verify]): boolean => {
|
||||||
try {
|
try {
|
||||||
if (verify(message, signature, publicKey)) {
|
if (verify(message, signature, publicKey, isExpanded)) {
|
||||||
result.crypto = crypto;
|
result.crypto = crypto;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -50,19 +51,20 @@ function verifyDetect (result: VerifyResult, message: Uint8Array | string, signa
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function verifyMultisig (result: VerifyResult, message: Uint8Array | string, signature: Uint8Array, publicKey: Uint8Array): VerifyResult {
|
function verifyMultisig (result: VerifyResult, message: Uint8Array | string, signature: Uint8Array, publicKey: Uint8Array, isExpanded?: boolean): VerifyResult {
|
||||||
assert([0, 1, 2].includes(signature[0]), `Unknown crypto type, expected signature prefix [0..2], found ${signature[0]}`);
|
assert([0, 1, 2].includes(signature[0]), `Unknown crypto type, expected signature prefix [0..2], found ${signature[0]}`);
|
||||||
|
|
||||||
result.crypto = CRYPTO_TYPES[signature[0]] || 'none';
|
const type = CRYPTO_TYPES[signature[0]] || 'none';
|
||||||
|
|
||||||
|
result.crypto = type;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
result.isValid = {
|
result.isValid = {
|
||||||
ecdsa: (): boolean => secp256k1Verify(message, signature.subarray(1), publicKey, 'blake2'),
|
ecdsa: () => verifyDetect(result, message, signature.subarray(1), publicKey, isExpanded, VERIFIERS_ECDSA).isValid,
|
||||||
ed25519: (): boolean => naclVerify(message, signature.subarray(1), publicKey),
|
ed25519: () => naclVerify(message, signature.subarray(1), publicKey),
|
||||||
ethereum: (): boolean => secp256k1Verify(message, signature.subarray(1), publicKey, 'keccak'),
|
none: () => { throw Error('no verify for `none` crypto type'); },
|
||||||
none: (): boolean => { throw Error('no verify for `none` crypto type'); },
|
sr25519: () => schnorrkelVerify(message, signature.subarray(1), publicKey)
|
||||||
sr25519: (): boolean => schnorrkelVerify(message, signature.subarray(1), publicKey)
|
}[type]();
|
||||||
}[result.crypto]();
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// ignore, result.isValid still set to false
|
// ignore, result.isValid still set to false
|
||||||
}
|
}
|
||||||
@@ -70,18 +72,15 @@ function verifyMultisig (result: VerifyResult, message: Uint8Array | string, sig
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function signatureVerify (message: Uint8Array | string, signature: Uint8Array | string, addressOrPublicKey: Uint8Array | string): VerifyResult {
|
export default function signatureVerify (message: Uint8Array | string, signature: Uint8Array | string, addressOrPublicKey: Uint8Array | string, isExpanded?: boolean): VerifyResult {
|
||||||
const signatureU8a = u8aToU8a(signature);
|
const signatureU8a = u8aToU8a(signature);
|
||||||
|
|
||||||
assert([64, 65, 66].includes(signatureU8a.length), `Invalid signature length, expected [64..66] bytes, found ${signatureU8a.length}`);
|
assert([64, 65, 66].includes(signatureU8a.length), `Invalid signature length, expected [64..66] bytes, found ${signatureU8a.length}`);
|
||||||
|
|
||||||
const result: VerifyResult = { crypto: 'none', isValid: false };
|
const result: VerifyResult = { crypto: 'none', isValid: false };
|
||||||
const publicKey = addressDecode(addressOrPublicKey);
|
const publicKey = addressDecode(addressOrPublicKey);
|
||||||
const isMultisig = [0, 1, 2].includes(signatureU8a[0]) && [65, 66].includes(signatureU8a.length);
|
|
||||||
|
|
||||||
if (isMultisig) {
|
return [0, 1, 2].includes(signatureU8a[0]) && [65, 66].includes(signatureU8a.length)
|
||||||
return verifyMultisig(result, message, signatureU8a, publicKey);
|
? verifyMultisig(result, message, signatureU8a, publicKey, isExpanded)
|
||||||
} else {
|
: verifyDetect(result, message, signatureU8a, publicKey, isExpanded);
|
||||||
return verifyDetect(result, message, signatureU8a, publicKey);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,3 @@ Functions can be imported directly from the package, e.g.
|
|||||||
```js
|
```js
|
||||||
import { isHex } from '@polkadot/util';
|
import { isHex } from '@polkadot/util';
|
||||||
```
|
```
|
||||||
|
|
||||||
## Utilities
|
|
||||||
|
|
||||||
[Utilities](SUMMARY.md)
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@polkadot/util",
|
"name": "@polkadot/util",
|
||||||
"version": "3.5.1",
|
"version": "3.7.1",
|
||||||
"description": "A collection of useful utilities for @polkadot",
|
"description": "A collection of useful utilities for @polkadot",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@@ -25,13 +25,12 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/polkadot-js/common/tree/master/packages/util#readme",
|
"homepage": "https://github.com/polkadot-js/common/tree/master/packages/util#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.11.2",
|
"@babel/runtime": "^7.12.1",
|
||||||
"@polkadot/x-textdecoder": "^0.3.2",
|
"@polkadot/x-textdecoder": "^3.7.1",
|
||||||
"@polkadot/x-textencoder": "^0.3.2",
|
"@polkadot/x-textencoder": "^3.7.1",
|
||||||
"@types/bn.js": "^4.11.6",
|
"@types/bn.js": "^4.11.6",
|
||||||
"bn.js": "^5.1.3",
|
"bn.js": "^5.1.3",
|
||||||
"camelcase": "^5.3.1",
|
"camelcase": "^5.3.1",
|
||||||
"chalk": "^4.1.0",
|
"ip-regex": "^4.2.0"
|
||||||
"ip-regex": "^4.1.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import isFunction from './is/function';
|
import isFunction from './is/function';
|
||||||
|
import isUndefined from './is/undefined';
|
||||||
|
|
||||||
type MessageFn = () => string;
|
type MessageFn = () => string;
|
||||||
|
|
||||||
@@ -30,3 +31,13 @@ export default function assert (condition: unknown, message: string | MessageFn)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name assertReturn
|
||||||
|
* @summart Returns when the value is not undefined, otherwise throws assertion error
|
||||||
|
*/
|
||||||
|
export function assertReturn <T> (value: T | undefined, message: string | MessageFn): T {
|
||||||
|
assert(!isUndefined(value), message);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,15 @@ interface Options extends ToBnOptions {
|
|||||||
bitLength?: number;
|
bitLength?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setBn (valueBn: BN, byteLength: number, { isLe, isNegative }: Options): Uint8Array {
|
||||||
|
const output = new Uint8Array(byteLength);
|
||||||
|
const bn = isNegative ? valueBn.toTwos(byteLength * 8) : valueBn;
|
||||||
|
|
||||||
|
output.set(bn.toArray(isLe ? 'le' : 'be', byteLength), 0);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name bnToU8a
|
* @name bnToU8a
|
||||||
* @summary Creates a Uint8Array object from a BN.
|
* @summary Creates a Uint8Array object from a BN.
|
||||||
@@ -29,7 +38,7 @@ interface Options extends ToBnOptions {
|
|||||||
function bnToU8a <ExtToBn extends ToBn> (value?: ExtToBn | BN | BigInt | number | null, options?: Options): Uint8Array;
|
function bnToU8a <ExtToBn extends ToBn> (value?: ExtToBn | BN | BigInt | number | null, options?: Options): Uint8Array;
|
||||||
function bnToU8a <ExtToBn extends ToBn> (value?: ExtToBn | BN | BigInt | number | null, bitLength?: number, isLe?: boolean): Uint8Array;
|
function bnToU8a <ExtToBn extends ToBn> (value?: ExtToBn | BN | BigInt | number | null, bitLength?: number, isLe?: boolean): Uint8Array;
|
||||||
function bnToU8a <ExtToBn extends ToBn> (value?: ExtToBn | BN | BigInt | number | null, arg1: number | Options = { bitLength: -1, isLe: true, isNegative: false }, arg2?: boolean): Uint8Array {
|
function bnToU8a <ExtToBn extends ToBn> (value?: ExtToBn | BN | BigInt | number | null, arg1: number | Options = { bitLength: -1, isLe: true, isNegative: false }, arg2?: boolean): Uint8Array {
|
||||||
const _options: Options = {
|
const options: Options = {
|
||||||
bitLength: -1,
|
bitLength: -1,
|
||||||
isLe: true,
|
isLe: true,
|
||||||
isNegative: false,
|
isNegative: false,
|
||||||
@@ -37,25 +46,15 @@ function bnToU8a <ExtToBn extends ToBn> (value?: ExtToBn | BN | BigInt | number
|
|||||||
};
|
};
|
||||||
|
|
||||||
const valueBn = bnToBn(value);
|
const valueBn = bnToBn(value);
|
||||||
const byteLength = _options.bitLength === -1
|
const byteLength = options.bitLength === -1
|
||||||
? Math.ceil(valueBn.bitLength() / 8)
|
? Math.ceil(valueBn.bitLength() / 8)
|
||||||
: Math.ceil((_options.bitLength || 0) / 8);
|
: Math.ceil((options.bitLength || 0) / 8);
|
||||||
|
|
||||||
if (!value) {
|
return value
|
||||||
return _options.bitLength === -1
|
? setBn(valueBn, byteLength, options)
|
||||||
|
: options.bitLength === -1
|
||||||
? new Uint8Array()
|
? new Uint8Array()
|
||||||
: new Uint8Array(byteLength);
|
: new Uint8Array(byteLength);
|
||||||
}
|
|
||||||
|
|
||||||
const output = new Uint8Array(byteLength);
|
|
||||||
const bn = _options.isNegative ? valueBn.toTwos(byteLength * 8) : valueBn;
|
|
||||||
|
|
||||||
output.set(
|
|
||||||
bn.toArray(_options.isLe ? 'le' : 'be', byteLength),
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default bnToU8a;
|
export default bnToU8a;
|
||||||
|
|||||||
@@ -20,6 +20,12 @@ describe('formatBalance', (): void => {
|
|||||||
).toEqual('123.4567 µUnit');
|
).toEqual('123.4567 µUnit');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('formats 123,456 (decimals=0)', (): void => {
|
||||||
|
expect(
|
||||||
|
formatBalance(123456, { decimals: 0, withSi: true })
|
||||||
|
).toEqual('123.4560 kUnit');
|
||||||
|
});
|
||||||
|
|
||||||
it('formats BigInt numbers', (): void => {
|
it('formats BigInt numbers', (): void => {
|
||||||
expect(
|
expect(
|
||||||
formatBalance(123456789000n, { decimals: 15, withSi: true })
|
formatBalance(123456789000n, { decimals: 15, withSi: true })
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ function _formatBalance <ExtToBn extends ToBn> (input?: number | string | BN | B
|
|||||||
: options;
|
: options;
|
||||||
|
|
||||||
// NOTE We start at midpoint (8) minus 1 - this means that values display as
|
// NOTE We start at midpoint (8) minus 1 - this means that values display as
|
||||||
// 123.456 instead of 0.123k (so always 6 relevant). Additionally we us ceil
|
// 123.456 instead of 0.123k (so always 6 relevant). Additionally we use ceil
|
||||||
// so there are at most 3 decimal before the decimal seperator
|
// so there are at most 3 decimal before the decimal separator
|
||||||
const si = calcSi(text, decimals, forceUnit);
|
const si = calcSi(text, decimals, forceUnit);
|
||||||
const mid = text.length - (decimals + si.power);
|
const mid = text.length - (decimals + si.power);
|
||||||
const prefix = text.substr(0, mid);
|
const prefix = text.substr(0, mid);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright 2017-2020 @polkadot/util authors & contributors
|
// Copyright 2017-2020 @polkadot/util authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
// eslint-disable-next-line prefer-regex-literals
|
||||||
const NUMBER_REGEX = new RegExp('(\\d+?)(?=(\\d{3})+(?!\\d)|$)', 'g');
|
const NUMBER_REGEX = new RegExp('(\\d+?)(?=(\\d{3})+(?!\\d)|$)', 'g');
|
||||||
|
|
||||||
export default function formatDecimal (value: string): string {
|
export default function formatDecimal (value: string): string {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user