Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f431f02f11 | ||
|
|
2063183f50 | ||
|
|
8280af08a6 | ||
|
|
8029a54508 | ||
|
|
9e5478e0c0 | ||
|
|
c67c1966d7 | ||
|
|
e1aa096cef | ||
|
|
7135941b6a | ||
|
|
dc24fb82a8 | ||
|
|
32cfe3707e | ||
|
|
97378be94e | ||
|
|
db0559e9c9 | ||
|
|
94d6a900f7 | ||
|
|
d751c03d45 | ||
|
|
aef8003d50 | ||
|
|
2810b35d6c | ||
|
|
6148932389 | ||
|
|
f4889a36d4 | ||
|
|
e8879c0ffc | ||
|
|
ed64514415 | ||
|
|
fcc25ee2c8 | ||
|
|
695e19a8a7 | ||
|
|
384bf9a41a |
+2
-1
@@ -1,4 +1,5 @@
|
||||
exclude_patterns:
|
||||
- "**/*.spec.js"
|
||||
- "**/*.spec.ts"
|
||||
- "docs/**/*.js"
|
||||
- "packages/networks/src/index.ts"
|
||||
- "packages/util/src/is/utf8.ts"
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
---
|
||||
assignees: ['jacogr']
|
||||
title: SS58 registry is outdated
|
||||
labels: ['ci', '@networks']
|
||||
---
|
||||
|
||||
cc @jacogr
|
||||
cc @polkadot-js/notifications
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ jobs:
|
||||
pr:
|
||||
strategy:
|
||||
matrix:
|
||||
step: ['lint', 'test', 'build']
|
||||
step: ['lint', 'test', 'build', 'networks:crosscheck']
|
||||
name: ${{ matrix.step }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# CHANGELOG
|
||||
|
||||
## 4.0.1 Nov 8, 2020
|
||||
|
||||
- **Breaking change** Polyfills are not injected by these libraries anymore to avoid clobbering external globals, the user should provide them if their environment is missing base functionality.
|
||||
|
||||
Changes:
|
||||
|
||||
- Remove built-in utility polyfills for `Array.fill`, `String.padStart`, `String.padEnd` as well as `Object.setPrototypeOf`. These should be provided by the actual user of the libraries if so required.
|
||||
- Update `@polkadot/wasm-crypto` library (under-the-hood cleanups)
|
||||
- Remove explicit crypto polyfill injection (aligning with updated `@polkadot/wasm-crypto`)
|
||||
- Add cross-environment `@polkadot/x-randomvalues` (for use in `@polkadot/wasm-crypto`)
|
||||
|
||||
|
||||
## 3.7.1 Nov 1, 2020
|
||||
|
||||
Changes:
|
||||
|
||||
+2
-1
@@ -10,7 +10,7 @@ module.exports = Object.assign({}, config, {
|
||||
'@polkadot/util-(crypto)(.*)$': '<rootDir>/packages/util-$1/src/$2',
|
||||
// eslint-disable-next-line sort-keys
|
||||
'@polkadot/util(.*)$': '<rootDir>/packages/util/src/$1',
|
||||
'@polkadot/x-(fetch|textdecoder|textencoder|ws)(.*)$': '<rootDir>/packages/x-$1/src/node'
|
||||
'@polkadot/x-(fetch|randomvalues|textdecoder|textencoder|ws)(.*)$': '<rootDir>/packages/x-$1/src/node'
|
||||
},
|
||||
modulePathIgnorePatterns: [
|
||||
'<rootDir>/packages/keyring/build',
|
||||
@@ -18,6 +18,7 @@ module.exports = Object.assign({}, config, {
|
||||
'<rootDir>/packages/util/build',
|
||||
'<rootDir>/packages/util-crypto/build',
|
||||
'<rootDir>/packages/x-fetch/build',
|
||||
'<rootDir>/packages/x-randomvalues/build',
|
||||
'<rootDir>/packages/x-textdecoder/build',
|
||||
'<rootDir>/packages/x-textencoder/build',
|
||||
'<rootDir>/packages/x-ws/build'
|
||||
|
||||
+2
-3
@@ -7,7 +7,6 @@
|
||||
"packages/*"
|
||||
],
|
||||
"resolutions": {
|
||||
"babel-core": "^7.0.0-bridge.0",
|
||||
"typescript": "^4.0.5"
|
||||
},
|
||||
"scripts": {
|
||||
@@ -22,9 +21,9 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.3",
|
||||
"@polkadot/dev": "^0.59.12",
|
||||
"@polkadot/dev": "^0.59.20",
|
||||
"@polkadot/ts": "^0.3.53",
|
||||
"@types/jest": "^26.0.15"
|
||||
},
|
||||
"version": "3.7.1"
|
||||
"version": "4.0.1"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/keyring",
|
||||
"version": "3.7.1",
|
||||
"version": "4.0.1",
|
||||
"description": "Keyring management",
|
||||
"main": "index.js",
|
||||
"publishConfig": {
|
||||
@@ -28,7 +28,11 @@
|
||||
"homepage": "https://github.com/polkadot-js/common/tree/master/packages/keyring#readme",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.1",
|
||||
"@polkadot/util": "^3.7.1",
|
||||
"@polkadot/util-crypto": "^3.7.1"
|
||||
"@polkadot/util": "4.0.1",
|
||||
"@polkadot/util-crypto": "4.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@polkadot/util": "4.0.1",
|
||||
"@polkadot/util-crypto": "4.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,9 +34,9 @@ const TYPE_PREFIX = {
|
||||
};
|
||||
|
||||
const TYPE_SIGNATURE = {
|
||||
ecdsa: (m: Uint8Array, p: Partial<Keypair>) => secp256k1Sign(m, p, 'blake2'),
|
||||
ecdsa: (m: Uint8Array, p: Partial<Keypair>) => secp256k1Sign(m, p, { hashType: 'blake2' }),
|
||||
ed25519: naclSign,
|
||||
ethereum: (m: Uint8Array, p: Partial<Keypair>) => secp256k1Sign(m, p, 'keccak'),
|
||||
ethereum: (m: Uint8Array, p: Partial<Keypair>) => secp256k1Sign(m, p, { hashType: 'keccak' }),
|
||||
sr25519: schnorrkelSign
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/networks",
|
||||
"version": "3.7.1",
|
||||
"version": "4.0.1",
|
||||
"description": "A list of all available Substrate networks and their applicable prefixes",
|
||||
"main": "index.js",
|
||||
"publishConfig": {
|
||||
@@ -29,7 +29,7 @@
|
||||
"@babel/runtime": "^7.12.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@polkadot/util": "^3.7.1",
|
||||
"@polkadot/x-fetch": "^3.7.1"
|
||||
"@polkadot/util": "4.0.1",
|
||||
"@polkadot/x-fetch": "4.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,6 +151,15 @@ const all: NetworkFromSubstrate[] = [
|
||||
symbols: ['XTX'],
|
||||
website: 'https://totemaccounting.com'
|
||||
},
|
||||
{
|
||||
decimals: [12],
|
||||
displayName: 'Synesthesia',
|
||||
network: 'synesthesia',
|
||||
prefix: 15,
|
||||
standardAccount: '*25519',
|
||||
symbols: ['SYN'],
|
||||
website: 'https://synesthesia.network/'
|
||||
},
|
||||
{
|
||||
decimals: [12],
|
||||
displayName: 'Kulupu',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/util-crypto",
|
||||
"version": "3.7.1",
|
||||
"version": "4.0.1",
|
||||
"description": "A collection of useful crypto utilities for @polkadot",
|
||||
"main": "index.js",
|
||||
"keywords": [
|
||||
@@ -26,9 +26,10 @@
|
||||
"homepage": "https://github.com/polkadot-js/common/tree/master/packages/util-crypto#readme",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.1",
|
||||
"@polkadot/networks": "^3.7.1",
|
||||
"@polkadot/util": "^3.7.1",
|
||||
"@polkadot/wasm-crypto": "^1.4.1",
|
||||
"@polkadot/networks": "4.0.1",
|
||||
"@polkadot/util": "4.0.1",
|
||||
"@polkadot/wasm-crypto": "^2.0.1",
|
||||
"@polkadot/x-randomvalues": "4.0.1",
|
||||
"base-x": "^3.0.8",
|
||||
"blakejs": "^1.1.0",
|
||||
"bn.js": "^5.1.3",
|
||||
@@ -47,5 +48,8 @@
|
||||
"@types/pbkdf2": "^3.1.0",
|
||||
"@types/scryptsy": "^2.0.0",
|
||||
"@types/xxhashjs": "^0.2.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@polkadot/util": "4.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,14 @@
|
||||
|
||||
import validate from './validate';
|
||||
|
||||
export default function isBase32 (value?: string | null): boolean {
|
||||
export function testValidator (validate: (value?: string | null, ipfsCompat?: boolean) => boolean, value?: string | null, ipfsCompat?: boolean): boolean {
|
||||
try {
|
||||
return validate(value);
|
||||
return validate(value, ipfsCompat);
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export default function isBase32 (value?: string | null, ipfsCompat?: boolean): boolean {
|
||||
return testValidator(validate, value, ipfsCompat);
|
||||
}
|
||||
|
||||
@@ -4,12 +4,14 @@
|
||||
import { validateChars } from '../base58/validate';
|
||||
import { BASE32_ALPHABET } from './bs32';
|
||||
|
||||
const BASE_CONFIG = { alphabet: BASE32_ALPHABET, ipfsChar: 'b', type: 'base32' };
|
||||
|
||||
/**
|
||||
* @name base32Validate
|
||||
* @summary Validates a base32 value.
|
||||
* @description
|
||||
* Validates the the supplied value is valid base32
|
||||
*/
|
||||
export default function base32Validate (value?: string | null, ipfsCompat = false): true {
|
||||
return validateChars('base32', BASE32_ALPHABET, value, ipfsCompat ? 'b' : undefined);
|
||||
export default function base32Validate (value?: string | null, ipfsCompat?: boolean): true {
|
||||
return validateChars(BASE_CONFIG, value, ipfsCompat);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { testValidator } from '../base32/is';
|
||||
import validate from './validate';
|
||||
|
||||
export default function isBase58 (value?: string | null, ipfsCompat?: boolean): boolean {
|
||||
try {
|
||||
return validate(value, ipfsCompat);
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
return testValidator(validate, value, ipfsCompat);
|
||||
}
|
||||
|
||||
@@ -5,11 +5,19 @@ import { assert } from '@polkadot/util';
|
||||
|
||||
import { BASE58_ALPHABET } from './bs58';
|
||||
|
||||
export function validateChars (type: string, alphabet: string, value?: string | null, startChar?: string): true {
|
||||
assert(value, `Expected non-null, non-empty ${type} input`);
|
||||
assert(!startChar || value[0] === startChar, `Expected ${type} to start with '${startChar || ''}'`);
|
||||
interface CheckConfig {
|
||||
alphabet: string;
|
||||
ipfsChar: string;
|
||||
type: string;
|
||||
}
|
||||
|
||||
for (let i = (startChar ? 1 : 0); i < value.length; i++) {
|
||||
const BASE_CONFIG = { alphabet: BASE58_ALPHABET, ipfsChar: 'z', type: 'base58' };
|
||||
|
||||
export function validateChars ({ alphabet, ipfsChar, type }: CheckConfig, value?: string | null, ipfsCompat?: boolean): true {
|
||||
assert(value, `Expected non-null, non-empty ${type} input`);
|
||||
assert(!ipfsCompat || value[0] === ipfsChar, `Expected ${type} to start with '${ipfsChar}'`);
|
||||
|
||||
for (let i = (ipfsCompat ? 1 : 0); i < value.length; i++) {
|
||||
assert(alphabet.includes(value[i]), `Invalid ${type} character "${value[i]}" (0x${value.charCodeAt(i).toString(16)}) at index ${i}`);
|
||||
}
|
||||
|
||||
@@ -22,6 +30,6 @@ export function validateChars (type: string, alphabet: string, value?: string |
|
||||
* @description
|
||||
* Validates the the supplied value is valid base58
|
||||
*/
|
||||
export default function base58Validate (value?: string | null, ipfsCompat = false): true {
|
||||
return validateChars('base58', BASE58_ALPHABET, value, ipfsCompat ? 'z' : undefined);
|
||||
export default function base58Validate (value?: string | null, ipfsCompat?: boolean): true {
|
||||
return validateChars(BASE_CONFIG, value, ipfsCompat);
|
||||
}
|
||||
|
||||
@@ -5,15 +5,16 @@ import { u8aToHex } from '@polkadot/util';
|
||||
|
||||
import { keccakAsU8a } from '../keccak';
|
||||
|
||||
function isInvalidChar (char: string, byte: number): boolean {
|
||||
return (byte > 7 && char !== char.toUpperCase()) || (byte <= 7 && char !== char.toLowerCase());
|
||||
}
|
||||
|
||||
export default function isEthereumChecksum (_address: string): boolean {
|
||||
const address = _address.replace('0x', '');
|
||||
const hash = u8aToHex(keccakAsU8a(address.toLowerCase()), -1, false);
|
||||
|
||||
for (let index = 0; index < 40; index++) {
|
||||
const char = address[index];
|
||||
const hashval = parseInt(hash[index], 16);
|
||||
|
||||
if ((hashval > 7 && char !== char.toUpperCase()) || (hashval <= 7 && char !== char.toLowerCase())) {
|
||||
if (isInvalidChar(address[index], parseInt(hash[index], 16))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ const ADDRESS = '0x00a329c0648769A73afAc7F9381E08FB43dBEA72';
|
||||
|
||||
describe('isEthereumChecksum', () => {
|
||||
it('returns false on invalid address', () => {
|
||||
expect(isEthereumChecksum('0xinvalid')).toBe(false);
|
||||
expect(isEthereumChecksum('0x00a329c0648769')).toBe(false);
|
||||
});
|
||||
|
||||
it('returns false on non-checksum address', () => {
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// polyfills
|
||||
import './polyfill';
|
||||
|
||||
// out of order and early in the chain, this also kicks off initialization on require
|
||||
export * from './init';
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@ describe('mnemonicGenerate', (): void => {
|
||||
).toEqual(true);
|
||||
});
|
||||
|
||||
([12, 15, 18, 21, 24] as WordCount[]).forEach((num: WordCount): void => {
|
||||
it(`generates a valid mnemonic (${num} words)`, (): void => {
|
||||
[false, true].forEach((onlyJs): void => {
|
||||
[false, true].forEach((onlyJs): void => {
|
||||
([12, 15, 18, 21, 24] as WordCount[]).forEach((num: WordCount): void => {
|
||||
it(`generates a valid mnemonic (${num} words, onlyJs=${onlyJs.toString()})`, (): void => {
|
||||
const mnemonic = generate(num, onlyJs);
|
||||
const isValid = validate(mnemonic);
|
||||
|
||||
@@ -27,4 +27,17 @@ describe('mnemonicGenerate', (): void => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
[true, false].forEach((onlyJs): void => {
|
||||
it(`generates not deterministic (onlyJs=${onlyJs.toString()})`, (): void => {
|
||||
[false, true].forEach((onlyJs): void => {
|
||||
const m1 = generate(24, onlyJs);
|
||||
const m2 = generate(24, onlyJs);
|
||||
|
||||
expect(m1 === m2).toEqual(false);
|
||||
expect(validate(m1)).toEqual(true);
|
||||
expect(validate(m2)).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import '../polyfill';
|
||||
|
||||
import { bip39Generate, isReady } from '@polkadot/wasm-crypto';
|
||||
|
||||
import { generateMnemonic } from './bip39';
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import '../polyfill';
|
||||
|
||||
/**
|
||||
* @summary Create valid mnemonic strings, validate them using BIP39, and convert them to valid seeds
|
||||
*/
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import '../polyfill';
|
||||
|
||||
import { bip39ToEntropy, isReady } from '@polkadot/wasm-crypto';
|
||||
|
||||
import { mnemonicToEntropy } from './bip39';
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import '../polyfill';
|
||||
|
||||
import { pbkdf2Sync } from 'pbkdf2';
|
||||
import { bufferToU8a, stringToU8a, u8aToBuffer } from '@polkadot/util';
|
||||
import { bip39ToMiniSecret, isReady } from '@polkadot/wasm-crypto';
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import '../polyfill';
|
||||
|
||||
import { bip39Validate, isReady } from '@polkadot/wasm-crypto';
|
||||
|
||||
import { validateMnemonic } from './bip39';
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import '@polkadot/wasm-crypto/crypto-polyfill';
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import nacl from 'tweetnacl';
|
||||
import getRandomValues from '@polkadot/x-randomvalues';
|
||||
|
||||
/**
|
||||
* @name randomAsU8a
|
||||
@@ -18,5 +18,5 @@ import nacl from 'tweetnacl';
|
||||
* ```
|
||||
*/
|
||||
export default function randomAsU8a (length = 32): Uint8Array {
|
||||
return nacl.randomBytes(length);
|
||||
return getRandomValues(new Uint8Array(length));
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
import { Keypair } from '../types';
|
||||
|
||||
import '../polyfill';
|
||||
|
||||
import { sr25519DeriveKeypairHard } from '@polkadot/wasm-crypto';
|
||||
|
||||
import keypairFromU8a from './keypair/fromU8a';
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import '../polyfill';
|
||||
|
||||
import { sr25519DerivePublicSoft } from '@polkadot/wasm-crypto';
|
||||
|
||||
export default function deriveSoft (publicKey: Uint8Array, chainCode: Uint8Array): Uint8Array {
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
import { Keypair } from '../types';
|
||||
|
||||
import '../polyfill';
|
||||
|
||||
import { sr25519DeriveKeypairSoft } from '@polkadot/wasm-crypto';
|
||||
|
||||
import keypairFromU8a from './keypair/fromU8a';
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import '../polyfill';
|
||||
|
||||
export { default as schnorrkelDeriveHard } from './deriveHard';
|
||||
export { default as schnorrkelDerivePublic } from './derivePublic';
|
||||
export { default as schnorrkelDeriveSoft } from './deriveSoft';
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
import { Keypair } from '../../types';
|
||||
|
||||
import '../../polyfill';
|
||||
|
||||
import { sr25519KeypairFromSeed } from '@polkadot/wasm-crypto';
|
||||
|
||||
import keypairFromU8a from './fromU8a';
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
import { Keypair } from '../types';
|
||||
|
||||
import '../polyfill';
|
||||
|
||||
import { assert, u8aToU8a } from '@polkadot/util';
|
||||
import { sr25519Sign } from '@polkadot/wasm-crypto';
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2017-2020 @polkadot/util-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import '../polyfill';
|
||||
|
||||
import { assert, u8aToU8a } from '@polkadot/util';
|
||||
import { sr25519Verify } from '@polkadot/wasm-crypto';
|
||||
|
||||
|
||||
@@ -9,13 +9,17 @@ import { assert, bnToU8a, u8aConcat } from '@polkadot/util';
|
||||
|
||||
import hasher from './hasher';
|
||||
|
||||
interface Options {
|
||||
hashType: HashType;
|
||||
}
|
||||
|
||||
const ec = new EC('secp256k1');
|
||||
|
||||
/**
|
||||
* @name secp256k1Sign
|
||||
* @description Returns message signature of `message`, using the supplied pair
|
||||
*/
|
||||
export default function secp256k1Sign (message: Uint8Array | string, { secretKey }: Partial<Keypair>, hashType: HashType = 'blake2'): Uint8Array {
|
||||
export default function secp256k1Sign (message: Uint8Array | string, { secretKey }: Partial<Keypair>, { hashType = 'blake2' }: Partial<Options> = {}): Uint8Array {
|
||||
assert(secretKey?.length === 32, 'Expected valid secp256k1 secretKey, 32-bytes');
|
||||
|
||||
const key = ec.keyFromPrivate(secretKey);
|
||||
|
||||
@@ -36,18 +36,18 @@ describe('sign and verify', (): void => {
|
||||
|
||||
it('signs/verifies a message by random key (keccak)', (): void => {
|
||||
const pair = pairFromSeed(randomAsU8a());
|
||||
const signature = sign(MESSAGE, pair, 'keccak');
|
||||
const signature = sign(MESSAGE, pair, { hashType: 'keccak' });
|
||||
const address = hasher('keccak', pair.publicKey);
|
||||
|
||||
expect(verify(MESSAGE, signature, address, 'keccak')).toBe(true);
|
||||
expect(verify(MESSAGE, signature, address, { hashType: 'keccak' })).toBe(true);
|
||||
});
|
||||
|
||||
it('fails verification on hasher mismatches', (): void => {
|
||||
const pair = pairFromSeed(randomAsU8a());
|
||||
const signature = sign(MESSAGE, pair, 'keccak');
|
||||
const signature = sign(MESSAGE, pair, { hashType: 'keccak' });
|
||||
const address = hasher('keccak', pair.publicKey);
|
||||
|
||||
expect(verify(MESSAGE, signature, address, 'blake2')).toBe(false);
|
||||
expect(verify(MESSAGE, signature, address, { hashType: 'blake2' })).toBe(false);
|
||||
});
|
||||
|
||||
it('works over a range of random keys (blake2)', (): void => {
|
||||
@@ -55,7 +55,7 @@ describe('sign and verify', (): void => {
|
||||
const pair = pairFromSeed(randomAsU8a());
|
||||
|
||||
try {
|
||||
expect(verify(MESSAGE, sign(MESSAGE, pair, 'blake2'), hasher('blake2', pair.publicKey), 'blake2')).toBe(true);
|
||||
expect(verify(MESSAGE, sign(MESSAGE, pair, { hashType: 'blake2' }), hasher('blake2', pair.publicKey), { hashType: 'blake2' })).toBe(true);
|
||||
} catch (error) {
|
||||
console.error(`blake2 failed on #${i}`);
|
||||
throw error;
|
||||
@@ -68,7 +68,7 @@ describe('sign and verify', (): void => {
|
||||
const pair = pairFromSeed(randomAsU8a());
|
||||
|
||||
try {
|
||||
expect(verify(MESSAGE, sign(MESSAGE, pair, 'keccak'), hasher('keccak', pair.publicKey), 'keccak')).toBe(true);
|
||||
expect(verify(MESSAGE, sign(MESSAGE, pair, { hashType: 'keccak' }), hasher('keccak', pair.publicKey), { hashType: 'keccak' })).toBe(true);
|
||||
} catch (error) {
|
||||
console.error(`keccak failed on #${i}`);
|
||||
throw error;
|
||||
|
||||
@@ -9,13 +9,18 @@ import { assert, u8aEq, u8aToU8a } from '@polkadot/util';
|
||||
import secp256k1Expand from './expand';
|
||||
import hasher from './hasher';
|
||||
|
||||
interface Options {
|
||||
hashType: HashType;
|
||||
isExpanded: boolean;
|
||||
}
|
||||
|
||||
const ec = new EC('secp256k1');
|
||||
|
||||
/**
|
||||
* @name secp256k1Verify
|
||||
* @description Verifies the signature of `message`, using the supplied pair
|
||||
*/
|
||||
export default function secp256k1Verify (message: Uint8Array | string, signature: Uint8Array | string, address: Uint8Array | string, hashType: HashType = 'blake2', isExpanded = false): boolean {
|
||||
export default function secp256k1Verify (message: Uint8Array | string, signature: Uint8Array | string, address: Uint8Array | string, { hashType = 'blake2', isExpanded = false }: Partial<Options> = {}): boolean {
|
||||
const u8a = u8aToU8a(signature);
|
||||
|
||||
assert(u8a.length === 65, `Expected signature with 65 bytes, ${u8a.length} found instead`);
|
||||
|
||||
@@ -10,19 +10,21 @@ import naclVerify from '../nacl/verify';
|
||||
import schnorrkelVerify from '../schnorrkel/verify';
|
||||
import secp256k1Verify from '../secp256k1/verify';
|
||||
|
||||
type Verifier = [KeypairType, (message: Uint8Array | string, signature: Uint8Array | string, publicKey: Uint8Array | string, isExpanded?: boolean) => boolean];
|
||||
interface VerifyInput {
|
||||
message: Uint8Array | string;
|
||||
publicKey: Uint8Array;
|
||||
signature: Uint8Array;
|
||||
}
|
||||
|
||||
type Verifier = [KeypairType, (message: Uint8Array | string, signature: Uint8Array, publicKey: Uint8Array, isExpanded?: boolean) => boolean];
|
||||
|
||||
const secp256k1VerifyHasher = (hashType: 'blake2' | 'keccak') =>
|
||||
(message: Uint8Array | string, signature: Uint8Array, publicKey: Uint8Array, isExpanded?: boolean) =>
|
||||
secp256k1Verify(message, signature, publicKey, { hashType, isExpanded });
|
||||
|
||||
const VERIFIERS_ECDSA: Verifier[] = [
|
||||
[
|
||||
'ecdsa',
|
||||
(message: Uint8Array | string, signature: Uint8Array | string, publicKey: Uint8Array | string, isExpanded?: boolean) =>
|
||||
secp256k1Verify(message, signature, publicKey, 'blake2', isExpanded)
|
||||
],
|
||||
[
|
||||
'ethereum',
|
||||
(message: Uint8Array | string, signature: Uint8Array | string, publicKey: Uint8Array | string, isExpanded?: boolean) =>
|
||||
secp256k1Verify(message, signature, publicKey, 'keccak', isExpanded)
|
||||
]
|
||||
['ecdsa', secp256k1VerifyHasher('blake2')],
|
||||
['ethereum', secp256k1VerifyHasher('keccak')]
|
||||
];
|
||||
|
||||
const VERIFIERS: Verifier[] = [
|
||||
@@ -33,7 +35,7 @@ const VERIFIERS: Verifier[] = [
|
||||
|
||||
const CRYPTO_TYPES: ('ed25519' | 'sr25519' | 'ecdsa')[] = ['ed25519', 'sr25519', 'ecdsa'];
|
||||
|
||||
function verifyDetect (result: VerifyResult, message: Uint8Array | string, signature: Uint8Array, publicKey: Uint8Array, isExpanded?: boolean, verifiers = VERIFIERS): VerifyResult {
|
||||
function verifyDetect (result: VerifyResult, { message, publicKey, signature }: VerifyInput, isExpanded?: boolean, verifiers = VERIFIERS): VerifyResult {
|
||||
result.isValid = verifiers.some(([crypto, verify]): boolean => {
|
||||
try {
|
||||
if (verify(message, signature, publicKey, isExpanded)) {
|
||||
@@ -51,7 +53,7 @@ function verifyDetect (result: VerifyResult, message: Uint8Array | string, signa
|
||||
return result;
|
||||
}
|
||||
|
||||
function verifyMultisig (result: VerifyResult, message: Uint8Array | string, signature: Uint8Array, publicKey: Uint8Array, isExpanded?: boolean): VerifyResult {
|
||||
function verifyMultisig (result: VerifyResult, { message, publicKey, signature }: VerifyInput, isExpanded?: boolean): VerifyResult {
|
||||
assert([0, 1, 2].includes(signature[0]), `Unknown crypto type, expected signature prefix [0..2], found ${signature[0]}`);
|
||||
|
||||
const type = CRYPTO_TYPES[signature[0]] || 'none';
|
||||
@@ -60,7 +62,7 @@ function verifyMultisig (result: VerifyResult, message: Uint8Array | string, sig
|
||||
|
||||
try {
|
||||
result.isValid = {
|
||||
ecdsa: () => verifyDetect(result, message, signature.subarray(1), publicKey, isExpanded, VERIFIERS_ECDSA).isValid,
|
||||
ecdsa: () => verifyDetect(result, { message, publicKey, signature: signature.subarray(1) }, isExpanded, VERIFIERS_ECDSA).isValid,
|
||||
ed25519: () => naclVerify(message, signature.subarray(1), publicKey),
|
||||
none: () => { throw Error('no verify for `none` crypto type'); },
|
||||
sr25519: () => schnorrkelVerify(message, signature.subarray(1), publicKey)
|
||||
@@ -79,8 +81,9 @@ export default function signatureVerify (message: Uint8Array | string, signature
|
||||
|
||||
const result: VerifyResult = { crypto: 'none', isValid: false };
|
||||
const publicKey = addressDecode(addressOrPublicKey);
|
||||
const input = { message, publicKey, signature: signatureU8a };
|
||||
|
||||
return [0, 1, 2].includes(signatureU8a[0]) && [65, 66].includes(signatureU8a.length)
|
||||
? verifyMultisig(result, message, signatureU8a, publicKey, isExpanded)
|
||||
: verifyDetect(result, message, signatureU8a, publicKey, isExpanded);
|
||||
? verifyMultisig(result, input, isExpanded)
|
||||
: verifyDetect(result, input, isExpanded);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/util",
|
||||
"version": "3.7.1",
|
||||
"version": "4.0.1",
|
||||
"description": "A collection of useful utilities for @polkadot",
|
||||
"main": "index.js",
|
||||
"keywords": [
|
||||
@@ -26,8 +26,8 @@
|
||||
"homepage": "https://github.com/polkadot-js/common/tree/master/packages/util#readme",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.1",
|
||||
"@polkadot/x-textdecoder": "^3.7.1",
|
||||
"@polkadot/x-textencoder": "^3.7.1",
|
||||
"@polkadot/x-textdecoder": "4.0.1",
|
||||
"@polkadot/x-textencoder": "4.0.1",
|
||||
"@types/bn.js": "^4.11.6",
|
||||
"bn.js": "^5.1.3",
|
||||
"camelcase": "^5.3.1",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
import BN from 'bn.js';
|
||||
|
||||
import assert from '../assert';
|
||||
import { checkMaxMin } from './util';
|
||||
|
||||
/**
|
||||
* @name bnMax
|
||||
@@ -19,7 +19,5 @@ import assert from '../assert';
|
||||
* ```
|
||||
*/
|
||||
export default function max (...items: BN[]): BN {
|
||||
assert(items && items.length >= 1, 'Must provide one or more BN arguments');
|
||||
|
||||
return items.reduce((acc: BN, val: BN) => BN.max(acc, val), items[0]);
|
||||
return checkMaxMin('max', items);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
import BN from 'bn.js';
|
||||
|
||||
import assert from '../assert';
|
||||
import { checkMaxMin } from './util';
|
||||
|
||||
/**
|
||||
* @name bnMin
|
||||
@@ -19,7 +19,5 @@ import assert from '../assert';
|
||||
* ```
|
||||
*/
|
||||
export default function min (...items: BN[]): BN {
|
||||
assert(items && items.length >= 1, 'Must provide one or more BN arguments');
|
||||
|
||||
return items.reduce((acc: BN, val: BN) => BN.min(acc, val), items[0]);
|
||||
return checkMaxMin('min', items);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,14 @@ import isToBn from '../is/toBn';
|
||||
import isHex from '../is/hex';
|
||||
import hexToBn from '../hex/toBn';
|
||||
|
||||
function numberToBn <ExtToBn extends ToBn> (value: number | ExtToBn | BN): BN {
|
||||
return BN.isBN(value)
|
||||
? value
|
||||
: isToBn(value)
|
||||
? value.toBn()
|
||||
: new BN(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name bnToBn
|
||||
* @summary Creates a BN value from a BN, BigInt, string (base 10 or hex) or number input.
|
||||
@@ -35,9 +43,5 @@ export default function bnToBn <ExtToBn extends ToBn> (value?: ExtToBn | BN | Bi
|
||||
return new BN(value.toString());
|
||||
}
|
||||
|
||||
return BN.isBN(value)
|
||||
? value
|
||||
: isToBn(value)
|
||||
? value.toBn()
|
||||
: new BN(value);
|
||||
return numberToBn(value);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,13 @@ interface Options extends ToBnOptions {
|
||||
bitLength?: number;
|
||||
}
|
||||
|
||||
function setBn (valueBn: BN, byteLength: number, { isLe, isNegative }: Options): Uint8Array {
|
||||
function createEmpty (byteLength: number, options: Options): Uint8Array {
|
||||
return options.bitLength === -1
|
||||
? new Uint8Array()
|
||||
: new Uint8Array(byteLength);
|
||||
}
|
||||
|
||||
function createValue (valueBn: BN, byteLength: number, { isLe, isNegative }: Options): Uint8Array {
|
||||
const output = new Uint8Array(byteLength);
|
||||
const bn = isNegative ? valueBn.toTwos(byteLength * 8) : valueBn;
|
||||
|
||||
@@ -51,10 +57,8 @@ function bnToU8a <ExtToBn extends ToBn> (value?: ExtToBn | BN | BigInt | number
|
||||
: Math.ceil((options.bitLength || 0) / 8);
|
||||
|
||||
return value
|
||||
? setBn(valueBn, byteLength, options)
|
||||
: options.bitLength === -1
|
||||
? new Uint8Array()
|
||||
: new Uint8Array(byteLength);
|
||||
? createValue(valueBn, byteLength, options)
|
||||
: createEmpty(byteLength, options);
|
||||
}
|
||||
|
||||
export default bnToU8a;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright 2017-2020 @polkadot/util authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import BN from 'bn.js';
|
||||
|
||||
import assert from '../assert';
|
||||
|
||||
export function checkMaxMin (type: 'max' | 'min', items: BN[]): BN {
|
||||
assert(items.length >= 1, 'Must provide one or more BN arguments');
|
||||
|
||||
return items.reduce((acc: BN, val: BN) => BN[type](acc, val), items[0]);
|
||||
}
|
||||
@@ -23,6 +23,48 @@ function addTime (a: Time, b: Time): Time {
|
||||
|
||||
const ZERO = { days: 0, hours: 0, milliseconds: 0, minutes: 0, seconds: 0 };
|
||||
|
||||
function extractDays (milliseconds: number, hrs: number): Time {
|
||||
const days = Math.floor(hrs / 24);
|
||||
|
||||
return addTime({ ...ZERO, days }, extractTime(milliseconds - (days * DAY * 1000)));
|
||||
}
|
||||
|
||||
function extractHrs (milliseconds: number, mins: number): Time {
|
||||
const hrs = mins / 60;
|
||||
|
||||
if (hrs < 24) {
|
||||
const hours = Math.floor(hrs);
|
||||
|
||||
return addTime({ ...ZERO, hours }, extractTime(milliseconds - (hours * HRS * 1000)));
|
||||
}
|
||||
|
||||
return extractDays(milliseconds, hrs);
|
||||
}
|
||||
|
||||
function extractMins (milliseconds: number, secs: number): Time {
|
||||
const mins = secs / 60;
|
||||
|
||||
if (mins < 60) {
|
||||
const minutes = Math.floor(mins);
|
||||
|
||||
return addTime({ ...ZERO, minutes }, extractTime(milliseconds - (minutes * 60 * 1000)));
|
||||
}
|
||||
|
||||
return extractHrs(milliseconds, mins);
|
||||
}
|
||||
|
||||
function extractSecs (milliseconds: number): Time {
|
||||
const secs = milliseconds / 1000;
|
||||
|
||||
if (secs < 60) {
|
||||
const seconds = Math.floor(secs);
|
||||
|
||||
return addTime({ ...ZERO, seconds }, extractTime(milliseconds - (seconds * 1000)));
|
||||
}
|
||||
|
||||
return extractMins(milliseconds, secs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name extractTime
|
||||
* @summary Convert a quantity of seconds to Time array representing accumulated {days, minutes, hours, seconds, milliseconds}
|
||||
@@ -42,31 +84,5 @@ export default function extractTime (milliseconds?: number): Time {
|
||||
return { ...ZERO, milliseconds };
|
||||
}
|
||||
|
||||
const secs = milliseconds / 1000;
|
||||
|
||||
if (secs < 60) {
|
||||
const seconds = Math.floor(secs);
|
||||
|
||||
return addTime({ ...ZERO, seconds }, extractTime(milliseconds - (seconds * 1000)));
|
||||
}
|
||||
|
||||
const mins = secs / 60;
|
||||
|
||||
if (mins < 60) {
|
||||
const minutes = Math.floor(mins);
|
||||
|
||||
return addTime({ ...ZERO, minutes }, extractTime(milliseconds - (minutes * 60 * 1000)));
|
||||
}
|
||||
|
||||
const hrs = mins / 60;
|
||||
|
||||
if (hrs < 24) {
|
||||
const hours = Math.floor(hrs);
|
||||
|
||||
return addTime({ ...ZERO, hours }, extractTime(milliseconds - (hours * HRS * 1000)));
|
||||
}
|
||||
|
||||
const days = Math.floor(hrs / 24);
|
||||
|
||||
return addTime({ ...ZERO, days }, extractTime(milliseconds - (days * DAY * 1000)));
|
||||
return extractSecs(milliseconds);
|
||||
}
|
||||
|
||||
@@ -5,19 +5,7 @@ import { ToBn } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
|
||||
import isToBn from '../is/toBn';
|
||||
|
||||
function getValue <ExtToBn extends ToBn> (value?: BN | ExtToBn | Date | number | null): number {
|
||||
if (isToBn(value)) {
|
||||
return getValue(value.toBn());
|
||||
} else if (value instanceof Date) {
|
||||
return getValue(value.getTime());
|
||||
} else if (value instanceof BN) {
|
||||
return getValue(value.toNumber());
|
||||
}
|
||||
|
||||
return value || 0;
|
||||
}
|
||||
import bnToBn from '../bn/toBn';
|
||||
|
||||
function formatValue (elapsed: number): string {
|
||||
if (elapsed < 15) {
|
||||
@@ -31,15 +19,13 @@ function formatValue (elapsed: number): string {
|
||||
return `${elapsed / 3600 | 0}h`;
|
||||
}
|
||||
|
||||
export default function formatElapsed <ExtToBn extends ToBn> (now?: Date | null, value?: BN | ExtToBn | Date | number | null): string {
|
||||
export default function formatElapsed <ExtToBn extends ToBn> (now?: Date | null, value?: BigInt | BN | ExtToBn | Date | number | null): string {
|
||||
const tsNow = (now && now.getTime()) || 0;
|
||||
const tsValue = getValue(value);
|
||||
const tsValue = value instanceof Date
|
||||
? value.getTime()
|
||||
: bnToBn(value).toNumber();
|
||||
|
||||
if (tsNow && tsValue) {
|
||||
const elapsed = Math.max(Math.abs(tsNow - tsValue), 0) / 1000;
|
||||
|
||||
return formatValue(elapsed);
|
||||
}
|
||||
|
||||
return '0.0s';
|
||||
return (tsNow && tsValue)
|
||||
? formatValue(Math.max(Math.abs(tsNow - tsValue), 0) / 1000)
|
||||
: '0.0s';
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2017-2020 @polkadot/util authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import './polyfill';
|
||||
|
||||
/**
|
||||
* @summary Utility methods for this package are split into groups
|
||||
*/
|
||||
|
||||
@@ -22,14 +22,16 @@ const logTo = {
|
||||
warn: 'warn'
|
||||
};
|
||||
|
||||
function formatObject (value: Record<string, unknown>): Record<string, unknown> {
|
||||
const result: Record<string, unknown> = {};
|
||||
function formatOther (value: unknown): unknown {
|
||||
if (value && isObject(value) && value.constructor === Object) {
|
||||
return Object.keys(value).reduce((result: Record<string, unknown>, key): Record<string, unknown> => {
|
||||
result[key] = format(value[key]);
|
||||
|
||||
return Object.keys(value).reduce((result, key): Record<string, unknown> => {
|
||||
result[key] = format(value[key]);
|
||||
return result;
|
||||
}, {});
|
||||
}
|
||||
|
||||
return result;
|
||||
}, result);
|
||||
return value;
|
||||
}
|
||||
|
||||
export function format (value: unknown): unknown {
|
||||
@@ -39,11 +41,9 @@ export function format (value: unknown): unknown {
|
||||
return value.toString();
|
||||
} else if (isU8a(value) || isBuffer(value)) {
|
||||
return u8aToHex(u8aToU8a(value));
|
||||
} else if (value && isObject(value) && value.constructor === Object) {
|
||||
return formatObject(value);
|
||||
}
|
||||
|
||||
return value;
|
||||
return formatOther(value);
|
||||
}
|
||||
|
||||
function apply (log: LogType, type: string, values: Logger$Data): void {
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
// Copyright 2017-2020 @polkadot/util authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/* eslint-disable no-extend-native */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
|
||||
describe('Array.fill', (): void => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
let arrayFill: (value: any, start?: number | undefined, end?: number | undefined) => any[];
|
||||
let u8aFill: (value: number, start?: number | undefined, end?: number | undefined) => Uint8Array;
|
||||
|
||||
beforeEach((): void => {
|
||||
arrayFill = Array.prototype.fill;
|
||||
u8aFill = Uint8Array.prototype.fill;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
Array.prototype.fill = null;
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
Uint8Array.prototype.fill = null;
|
||||
|
||||
require('./fill');
|
||||
});
|
||||
|
||||
afterEach((): void => {
|
||||
Array.prototype.fill = arrayFill;
|
||||
Uint8Array.prototype.fill = u8aFill;
|
||||
});
|
||||
|
||||
it('uses the polyfills', (): void => {
|
||||
expect(
|
||||
[1, 2, 3, 4, 5, 6, 7, 8].fill(5, 3)
|
||||
).toEqual([1, 2, 3, 5, 5, 5, 5, 5]);
|
||||
expect(
|
||||
new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]).fill(5, 3)
|
||||
).toEqual(new Uint8Array([1, 2, 3, 5, 5, 5, 5, 5]));
|
||||
});
|
||||
});
|
||||
@@ -1,37 +0,0 @@
|
||||
// Copyright 2017-2020 @polkadot/util authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/* eslint-disable no-extend-native */
|
||||
|
||||
import assert from '../assert';
|
||||
|
||||
function getOffset (value: number, length: number): number {
|
||||
return value < 0
|
||||
? Math.max(length + value, 0)
|
||||
: Math.min(value, length);
|
||||
}
|
||||
|
||||
if (!Array.prototype.fill) {
|
||||
// eslint-disable-next-line no-extend-native
|
||||
Array.prototype.fill = function fill <T> (value: T, start = 0, end?: number): T[] {
|
||||
assert(this, 'this is null or not defined');
|
||||
|
||||
const A = Object(this) as T[];
|
||||
const relativeEnd = end ?? A.length;
|
||||
const final = getOffset(relativeEnd, A.length);
|
||||
let k = getOffset(start, A.length);
|
||||
|
||||
while (k < final) {
|
||||
A[k] = value;
|
||||
k++;
|
||||
}
|
||||
|
||||
return A;
|
||||
};
|
||||
}
|
||||
|
||||
if (!Uint8Array.prototype.fill) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
Uint8Array.prototype.fill = Array.prototype.fill;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// Copyright 2017-2020 @polkadot/util authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import './fill';
|
||||
import './padEnd';
|
||||
import './padStart';
|
||||
import './setPrototypeOf';
|
||||
@@ -1,27 +0,0 @@
|
||||
// Copyright 2017-2020 @polkadot/util authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
|
||||
describe('String padEnd', (): void => {
|
||||
let stringEnd: (length: number, fill?: string) => string;
|
||||
|
||||
beforeEach((): void => {
|
||||
stringEnd = String.prototype.padEnd;
|
||||
|
||||
// eslint-disable-next-line no-extend-native,@typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-assignment
|
||||
String.prototype.padEnd = null as any;
|
||||
|
||||
require('./padEnd');
|
||||
});
|
||||
|
||||
afterEach((): void => {
|
||||
// eslint-disable-next-line no-extend-native
|
||||
String.prototype.padEnd = stringEnd;
|
||||
});
|
||||
|
||||
it('does padding', (): void => {
|
||||
expect('test'.padEnd(8, 'A')).toEqual('testAAAA');
|
||||
expect('test'.padEnd(8)).toEqual('test ');
|
||||
});
|
||||
});
|
||||
@@ -1,17 +0,0 @@
|
||||
// Copyright 2017-2020 @polkadot/util authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/* eslint-disable no-extend-native */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
|
||||
if (!String.prototype.padEnd) {
|
||||
String.prototype.padEnd = function padEnd (length: number, char = ' '): string {
|
||||
let result = String(this);
|
||||
|
||||
while (result.length < length) {
|
||||
result = result + char;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
// Copyright 2017-2020 @polkadot/util authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
|
||||
describe('String padStart', (): void => {
|
||||
let stringStart: (length: number, fill?: string) => string;
|
||||
|
||||
beforeEach((): void => {
|
||||
stringStart = String.prototype.padStart;
|
||||
|
||||
// eslint-disable-next-line no-extend-native,@typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-assignment
|
||||
String.prototype.padStart = null as any;
|
||||
|
||||
require('./padStart');
|
||||
});
|
||||
|
||||
afterEach((): void => {
|
||||
// eslint-disable-next-line no-extend-native
|
||||
String.prototype.padStart = stringStart;
|
||||
});
|
||||
|
||||
it('does padding', (): void => {
|
||||
expect('test'.padStart(8, 'A')).toEqual('AAAAtest');
|
||||
expect('test'.padStart(8)).toEqual(' test');
|
||||
});
|
||||
});
|
||||
@@ -1,17 +0,0 @@
|
||||
// Copyright 2017-2020 @polkadot/util authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/* eslint-disable no-extend-native */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
|
||||
if (!String.prototype.padStart) {
|
||||
String.prototype.padStart = function padStart (length: number, char = ' '): string {
|
||||
let result = String(this);
|
||||
|
||||
while (result.length < length) {
|
||||
result = char + result;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
// Copyright 2017-2020 @polkadot/util authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/* eslint-disable no-proto */
|
||||
|
||||
describe('setPrototypeOf', (): void => {
|
||||
let orig: (o: Record<string, unknown>, proto: Record<string, unknown> | null) => Record<string, unknown>;
|
||||
|
||||
beforeEach((): void => {
|
||||
orig = Object.setPrototypeOf;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
Object.setPrototypeOf = null;
|
||||
|
||||
require('./setPrototypeOf');
|
||||
});
|
||||
|
||||
afterEach((): void => {
|
||||
Object.setPrototypeOf = orig;
|
||||
});
|
||||
|
||||
it('polyfills with no exceptions', (): void => {
|
||||
const obj = {};
|
||||
const proto = { foo: 'bar' };
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
expect(Object.setPrototypeOf(obj, proto).__proto__).toBe(proto);
|
||||
});
|
||||
});
|
||||
@@ -1,12 +0,0 @@
|
||||
// Copyright 2017-2020 @polkadot/util authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// React Native does not have Object.setPrototypeOf
|
||||
if (!Object.setPrototypeOf) {
|
||||
Object.setPrototypeOf = function (obj: Record<string, unknown>, proto: Record<string, unknown> | null): Record<string, unknown> {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,no-proto
|
||||
obj.__proto__ = proto;
|
||||
|
||||
return obj;
|
||||
};
|
||||
}
|
||||
@@ -1,11 +1,7 @@
|
||||
// Copyright 2017-2020 @polkadot/util authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
const ALPHABET = new Array(256) as string[];
|
||||
|
||||
for (let n = 0; n < 256; ++n) {
|
||||
ALPHABET[n] = n.toString(16).padStart(2, '0');
|
||||
}
|
||||
const ALPHABET = new Array(256).fill(0).map((_, n) => n.toString(16).padStart(2, '0'));
|
||||
|
||||
/** @internal */
|
||||
function extract (value: Uint8Array): string {
|
||||
|
||||
@@ -8,6 +8,18 @@ import bufferToU8a from '../buffer/toU8a';
|
||||
import hexToU8a from '../hex/toU8a';
|
||||
import stringToU8a from '../string/toU8a';
|
||||
|
||||
function convertArray (value: number[] | Uint8Array): Uint8Array {
|
||||
return Array.isArray(value)
|
||||
? Uint8Array.from(value)
|
||||
: value;
|
||||
}
|
||||
|
||||
function convertString (value: string): Uint8Array {
|
||||
return isHex(value)
|
||||
? hexToU8a(value)
|
||||
: stringToU8a(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name u8aToU8a
|
||||
* @summary Creates a Uint8Array value from a Uint8Array, Buffer, string or hex input.
|
||||
@@ -29,12 +41,8 @@ export default function u8aToU8a (value?: number[] | Buffer | Uint8Array | strin
|
||||
} else if (isBuffer(value)) {
|
||||
return bufferToU8a(value);
|
||||
} else if (isString(value)) {
|
||||
return isHex(value)
|
||||
? hexToU8a(value)
|
||||
: stringToU8a(value);
|
||||
return convertString(value);
|
||||
}
|
||||
|
||||
return Array.isArray(value)
|
||||
? Uint8Array.from(value)
|
||||
: value;
|
||||
return convertArray(value);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"name": "@polkadot/x-fetch",
|
||||
"version": "3.7.1",
|
||||
"version": "4.0.1",
|
||||
"description": "A cross-environment fetch replacement",
|
||||
"browser": "browser.js",
|
||||
"main": "node.js",
|
||||
"react-native": "react-native.js",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"maintainers": [
|
||||
"Jaco Greeff <jacogr@gmail.com>"
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright 2017-2020 @polkadot/x-fetch authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import browser from './browser';
|
||||
|
||||
export default browser;
|
||||
@@ -0,0 +1,3 @@
|
||||
# @polkadot/x-randomvalues
|
||||
|
||||
A cross-environment `window.crypto.getRandomValues`.
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "@polkadot/x-randomvalues",
|
||||
"version": "4.0.1",
|
||||
"description": "A cross-environment window.crypto.getRandomValues replacement",
|
||||
"browser": "browser.js",
|
||||
"main": "node.js",
|
||||
"react-native": "react-native.js",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"maintainers": [
|
||||
"Jaco Greeff <jacogr@gmail.com>"
|
||||
],
|
||||
"contributors": [],
|
||||
"license": "Apache-2.0",
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"registry": "https://registry.npmjs.org"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/polkadot-js/common.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/polkadot-js/common/issues"
|
||||
},
|
||||
"homepage": "https://github.com/polkadot-js/common/tree/master/packages/x-randomvalues#readme",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react-native": "^0.63.33"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright 2017-2020 @polkadot/x-randomvalues authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export default function getRandomValues <T extends Uint8Array> (arr: T): T {
|
||||
return crypto.getRandomValues(arr);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright 2017-2020 @polkadot/x-randomvalues authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import fallback from './fallback';
|
||||
|
||||
describe('fallback (insecure)', (): void => {
|
||||
it('subsequent results does not match', (): void => {
|
||||
expect(
|
||||
fallback(new Uint8Array(32)).toString()
|
||||
).not.toEqual(
|
||||
fallback(new Uint8Array(32)).toString()
|
||||
);
|
||||
});
|
||||
|
||||
it('generates with the supplied length', (): void => {
|
||||
expect(
|
||||
fallback(new Uint8Array(128))
|
||||
).toHaveLength(128);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2017-2020 @polkadot/x-randomvalues authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Adapted from https://github.com/LinusU/react-native-get-random-values/blob/85f48393821c23b83b89a8177f56d3a81dc8b733/index.js
|
||||
// Copyright (c) 2018, 2020 Linus Unnebäck
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
let warned = false;
|
||||
|
||||
export default function insecureRandomValues <T extends Uint8Array> (arr: T): T {
|
||||
if (!warned) {
|
||||
console.warn('Using an insecure random number generator, this should only happen when running in a debugger without support for crypto.getRandomValues');
|
||||
warned = true;
|
||||
}
|
||||
|
||||
let r = 0;
|
||||
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
if ((i & 0b11) === 0) {
|
||||
r = Math.random() * 0x100000000;
|
||||
}
|
||||
|
||||
arr[i] = (r >>> ((i & 0b11) << 3)) & 0xff;
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright 2017-2020 @polkadot/x-randomvalues authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import crypto from 'crypto';
|
||||
|
||||
export default function getRandomValues <T extends Uint8Array> (arr: T): T {
|
||||
return crypto.randomBytes(arr.length).reduce((arr, value, index) => {
|
||||
arr[index] = value;
|
||||
|
||||
return arr;
|
||||
}, arr);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright 2017-2020 @polkadot/x-randomvalues authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Adapted from https://github.com/LinusU/react-native-get-random-values/blob/85f48393821c23b83b89a8177f56d3a81dc8b733/index.js
|
||||
// Copyright (c) 2018, 2020 Linus Unnebäck
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { NativeModules } from 'react-native';
|
||||
|
||||
import insecureRandomValues from './fallback';
|
||||
|
||||
interface RNExt {
|
||||
RNGetRandomValues: {
|
||||
getRandomBase64: (length: number) => string;
|
||||
}
|
||||
}
|
||||
|
||||
function getRandomValuesNative <T extends Uint8Array> (arr: T): T {
|
||||
return Buffer
|
||||
.from((NativeModules as RNExt).RNGetRandomValues.getRandomBase64(arr.length), 'base64')
|
||||
.reduce((arr, byte, index): T => {
|
||||
arr[index] = byte;
|
||||
|
||||
return arr;
|
||||
}, arr);
|
||||
}
|
||||
|
||||
function getRandomValuesGlobal <T extends Uint8Array> (arr: T): T {
|
||||
return crypto.getRandomValues(arr);
|
||||
}
|
||||
|
||||
export default typeof global.crypto === 'object' && typeof global.crypto.getRandomValues === 'function'
|
||||
? getRandomValuesGlobal
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-explicit-any
|
||||
: (typeof (global as any).nativeCallSyncHook === 'undefined' || !NativeModules.ExpoRandom)
|
||||
? insecureRandomValues
|
||||
: getRandomValuesNative;
|
||||
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"name": "@polkadot/x-textdecoder",
|
||||
"version": "3.7.1",
|
||||
"version": "4.0.1",
|
||||
"description": "A TextDecoder replacement",
|
||||
"browser": "browser.js",
|
||||
"main": "node.js",
|
||||
"react-native": "react-native.js",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"maintainers": [
|
||||
"Jaco Greeff <jacogr@gmail.com>"
|
||||
|
||||
@@ -1,17 +1,8 @@
|
||||
// Copyright 2017-2020 @polkadot/x-textencoder authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export default typeof TextDecoder === 'undefined'
|
||||
? class {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-useless-constructor
|
||||
constructor (_: 'utf-8') {
|
||||
// nothing
|
||||
}
|
||||
import Fallback from './fallback';
|
||||
|
||||
decode (value: Uint8Array): string {
|
||||
return value.reduce((str, code): string => {
|
||||
return str + String.fromCharCode(code);
|
||||
}, '');
|
||||
}
|
||||
}
|
||||
export default typeof TextDecoder === 'undefined'
|
||||
? Fallback as unknown as typeof TextDecoder
|
||||
: TextDecoder;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// Copyright 2017-2020 @polkadot/x-textencoder authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// This is very limited, only handling Ascii values
|
||||
export default class TextDecoder {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-useless-constructor
|
||||
constructor (_: 'utf-8') {
|
||||
// nothing
|
||||
}
|
||||
|
||||
decode (value: Uint8Array): string {
|
||||
return value.reduce((str, code): string => {
|
||||
return str + String.fromCharCode(code);
|
||||
}, '');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright 2017-2020 @polkadot/x-textencoder authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import browser from './browser';
|
||||
|
||||
export default browser;
|
||||
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"name": "@polkadot/x-textencoder",
|
||||
"version": "3.7.1",
|
||||
"version": "4.0.1",
|
||||
"description": "A TextDecoder replacement",
|
||||
"browser": "browser.js",
|
||||
"main": "node.js",
|
||||
"react-native": "react-native.js",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"maintainers": [
|
||||
"Jaco Greeff <jacogr@gmail.com>"
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
// Copyright 2017-2020 @polkadot/x-textencoder authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import Fallback from './fallback';
|
||||
|
||||
export default typeof TextEncoder === 'undefined'
|
||||
? class {
|
||||
encode (value: string): Uint8Array {
|
||||
const u8a = new Uint8Array(value.length);
|
||||
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
u8a[i] = value.charCodeAt(i);
|
||||
}
|
||||
|
||||
return u8a;
|
||||
}
|
||||
}
|
||||
? Fallback as unknown as typeof TextEncoder
|
||||
: TextEncoder;
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright 2017-2020 @polkadot/x-textencoder authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// This is very limited, only handling Ascii values
|
||||
export default class TextEncoder {
|
||||
encode (value: string): Uint8Array {
|
||||
const u8a = new Uint8Array(value.length);
|
||||
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
u8a[i] = value.charCodeAt(i);
|
||||
}
|
||||
|
||||
return u8a;
|
||||
}
|
||||
}
|
||||
@@ -3,19 +3,21 @@
|
||||
|
||||
import { TextEncoder as NodeTextEncoder } from 'util';
|
||||
|
||||
class NodeFallback {
|
||||
#encoder: NodeTextEncoder;
|
||||
|
||||
constructor () {
|
||||
this.#encoder = new NodeTextEncoder();
|
||||
}
|
||||
|
||||
// For a Jest 26.0.1 environment, Buffer !== Uint8Array
|
||||
encode (value: string): Uint8Array {
|
||||
const encoded = this.#encoder.encode(value);
|
||||
|
||||
return Uint8Array.from(encoded);
|
||||
}
|
||||
}
|
||||
|
||||
export default typeof TextEncoder === 'undefined'
|
||||
? class {
|
||||
#encoder: NodeTextEncoder;
|
||||
|
||||
constructor () {
|
||||
this.#encoder = new NodeTextEncoder();
|
||||
}
|
||||
|
||||
// For a Jest 26.0.1 environment, Buffer !== Uint8Array
|
||||
encode (value: string): Uint8Array {
|
||||
const encoded = this.#encoder.encode(value);
|
||||
|
||||
return Uint8Array.from(encoded);
|
||||
}
|
||||
} as unknown as typeof TextEncoder
|
||||
? NodeFallback as unknown as typeof TextEncoder
|
||||
: TextEncoder;
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright 2017-2020 @polkadot/x-textencoder authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import browser from './browser';
|
||||
|
||||
export default browser;
|
||||
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"name": "@polkadot/x-ws",
|
||||
"version": "3.7.1",
|
||||
"version": "4.0.1",
|
||||
"description": "A cross-environment WebSocket replacement",
|
||||
"browser": "browser.js",
|
||||
"main": "node.js",
|
||||
"react-native": "react-native.js",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"maintainers": [
|
||||
"Jaco Greeff <jacogr@gmail.com>"
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright 2017-2020 @polkadot/x-ws authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import browser from './browser';
|
||||
|
||||
export default browser;
|
||||
Reference in New Issue
Block a user