Compare commits

...
66 Commits
Author SHA1 Message Date
github-actions[bot] 50b494ee2e [CI Skip] release/stable 9.5.1
skip-checks: true
2022-06-18 11:21:50 +00:00
Jaco 5b551ca976 9.5.1 (#1545) 2022-06-18 14:18:04 +03:00
github-actions[bot] 5f2a0e25f9 [CI Skip] release/beta 9.4.2-25
skip-checks: true
2022-06-18 10:35:02 +00:00
Jaco 4edb0f00b6 Adjust asserts (#1544) 2022-06-18 13:31:25 +03:00
github-actions[bot] 096c772d7d [CI Skip] release/beta 9.4.2-24
skip-checks: true
2022-06-18 06:02:51 +00:00
Jaco d771d4c243 Performance test for isCodec vs instanceof (#1543) 2022-06-18 08:58:59 +03:00
github-actions[bot] e038c36719 [CI Skip] release/beta 9.4.2-23
skip-checks: true
2022-06-17 06:28:47 +00:00
Jaco 19c8799986 Additional property tests (#1542) 2022-06-17 09:25:01 +03:00
github-actions[bot] e7f642e7fb [CI Skip] release/beta 9.4.2-22
skip-checks: true
2022-06-17 04:59:00 +00:00
Jaco 90e05a7907 Adjust objectProperties with key in that check (#1541) 2022-06-17 07:55:08 +03:00
github-actions[bot] 1ad961eb93 [CI Skip] release/beta 9.4.2-21
skip-checks: true
2022-06-16 18:38:27 +00:00
Jaco 8549f1fe89 Adjust isAscii str vs u8a loops (#1540) 2022-06-16 21:34:35 +03:00
github-actions[bot] 0be212bd49 [CI Skip] release/beta 9.4.2-20
skip-checks: true
2022-06-16 14:18:23 +00:00
Jaco 2dd2f78f7e Use \d in regex (as applicable) (#1539)
* Use \d in regex (as applicable)

* Adjust
2022-06-16 17:13:34 +03:00
github-actions[bot] d5ce0ff4d1 [CI Skip] release/beta 9.4.2-19
skip-checks: true
2022-06-16 13:52:39 +00:00
Jaco 4d887e889a Adjust testing for uppercase words in stringCamelCase (#1538)
* Adjust testing for uppercase words in stringCamelCase

* Use \d

* Revert
2022-06-16 16:47:52 +03:00
github-actions[bot] 1113d09315 [CI Skip] release/beta 9.4.2-18
skip-checks: true
2022-06-16 13:12:24 +00:00
Jaco b774b7804b Small camelCase conversion adjustments (#1537)
* Small camelCase conversion adjustments

* Remove unused exports

* Extract formatRuns
2022-06-16 16:07:45 +03:00
github-actions[bot] 6c1b0e7346 [CI Skip] release/beta 9.4.2-17
skip-checks: true
2022-06-16 11:56:18 +00:00
Jaco 68ba664c4c hexToU8a adjustments (#1536)
* hexToU8a adjustments

* Adjust test
2022-06-16 14:51:34 +03:00
github-actions[bot] c3c4ceab8b [CI Skip] release/beta 9.4.2-16
skip-checks: true
2022-06-16 08:34:08 +00:00
Jaco fff30601a0 Unroll u8aToBn loops (#1535)
* Unroll u8aToBn loops

* Adjust with additional xor shortcuts

* Adjust mult -> shift (where below u32)

* assertUnreachable

* Add u8aToNumber
2022-06-16 11:29:23 +03:00
github-actions[bot] cfb5d24a87 [CI Skip] release/beta 9.4.2-15
skip-checks: true
2022-06-15 18:51:31 +00:00
Jaco 7ce4ed1504 Cleanup comments (#1534) 2022-06-15 21:47:23 +03:00
github-actions[bot] 5a00b146fc [CI Skip] release/beta 9.4.2-14
skip-checks: true
2022-06-15 18:22:28 +00:00
Jaco 1a73a3407e Adjust option extraction for helpers (#1533)
* Adjust option extraction for helpers

* Adjust
2022-06-15 21:17:07 +03:00
github-actions[bot] 0db66346a6 [CI Skip] release/beta 9.4.2-13
skip-checks: true
2022-06-14 04:28:47 +00:00
Jaco a07bfe1234 Bump dev (#1532) 2022-06-14 07:24:11 +03:00
github-actions[bot] 5feb233abc [CI Skip] release/beta 9.4.2-12
skip-checks: true
2022-06-13 05:15:51 +00:00
Jaco 16951c6feb Bump 3rd-party deps 2022-06-13 08:11:43 +03:00
github-actions[bot] 22aa8d7adb [CI Skip] release/beta 9.4.2-11
skip-checks: true
2022-06-12 08:16:35 +00:00
Jaco dfaf954f75 Update issue template (#1530) 2022-06-12 11:12:07 +03:00
github-actions[bot] 78911607e8 [CI Skip] release/beta 9.4.2-10
skip-checks: true
2022-06-12 06:15:23 +00:00
Jaco cdcc331e6e Additional internal comments for exposed functions (#1529) 2022-06-12 09:11:12 +03:00
github-actions[bot] 882b29eebd [CI Skip] release/beta 9.4.2-9
skip-checks: true
2022-06-11 20:37:42 +00:00
Jaco de5c9a1594 Inline function for min/max creator (#1528) 2022-06-11 23:33:42 +03:00
github-actions[bot] 2fc26b5533 [CI Skip] release/beta 9.4.2-8
skip-checks: true
2022-06-11 15:21:18 +00:00
Jaco 6d795ecc5d Shared helper function for bn/bi min/max compares (#1527)
* Shared helper function for bn/bi min/max compares

* min/max test
2022-06-11 18:17:21 +03:00
github-actions[bot] a0c3aa3059 [CI Skip] release/beta 9.4.2-7
skip-checks: true
2022-06-11 14:32:46 +00:00
Jaco e30bac1ed6 Test for sqrt(MAX_SAFE_INT) (w/ comments for excluded functions) (#1526)
* Test for sqrt(MAX_SAFE_INT) (w/ comments for excluded functions)

* Adjust {bi, bn}{Max, Min} with factory
2022-06-11 17:28:55 +03:00
github-actions[bot] 50a061eab3 [CI Skip] release/beta 9.4.2-6
skip-checks: true
2022-06-11 07:52:58 +00:00
Jaco f2064f059f Additional @internal markers (#1525) 2022-06-11 10:48:51 +03:00
github-actions[bot] 768cd68146 [CI Skip] release/beta 9.4.2-5
skip-checks: true
2022-06-11 05:43:44 +00:00
Jaco 0a5bfdca5e Bump deps (& issue template) (#1524) 2022-06-11 08:39:52 +03:00
github-actions[bot] 3ec2f6dcb2 [CI Skip] release/beta 9.4.2-4
skip-checks: true
2022-06-10 11:53:05 +00:00
Jaco 0f2a3a142f CHANGELOG (#1523) 2022-06-10 14:48:56 +03:00
github-actions[bot] 6f5a706ec9 [CI Skip] release/beta 9.4.2-3
skip-checks: true
2022-06-10 10:56:44 +00:00
pan 7e0f917c2b update bifrost genesis hash (#1521) 2022-06-10 13:52:50 +03:00
github-actions[bot] 99731a6664 [CI Skip] release/beta 9.4.2-2
skip-checks: true
2022-06-07 06:02:06 +00:00
Jaco 7765476a26 Use bitwise not as Math.floor replacement (#1518)
* Use bitwise not as Math.floor replacement

* No objectSpread in extractTime

* Flatten extractTime calls
2022-06-07 08:58:11 +03:00
github-actions[bot] 2cd9633afe [CI Skip] release/beta 9.4.2-1
skip-checks: true
2022-06-07 05:47:38 +00:00
Jaco 72749d083f Bump deps (#1519) 2022-06-07 08:43:50 +03:00
github-actions[bot] 9ede85f99a [CI Skip] release/beta 9.4.2-0
skip-checks: true
2022-06-06 06:00:31 +00:00
Carlo SalaandJaco d6a390beb4 add Composable support for ledger (#1515)
* fix(networks): move centrifuge to new parachain chain

* feat: add composable support for ledger

* Update packages/networks/src/defaults/genesis.ts

Co-authored-by: Jaco <jacogr@gmail.com>
2022-06-06 08:55:46 +03:00
github-actions[bot] a14bec79f8 [CI Skip] release/stable 9.4.1
skip-checks: true
2022-06-04 05:10:26 +00:00
Jaco c0de5ac3c8 9.4.1 (#1514) 2022-06-04 08:05:32 +03:00
github-actions[bot] 8d7f810556 [CI Skip] release/beta 9.3.2-4
skip-checks: true
2022-06-04 04:48:08 +00:00
Jaco 5c6526a6bd Bump deps (#1513) 2022-06-04 07:44:30 +03:00
github-actions[bot] e9635ab75b [CI Skip] release/beta 9.3.2-3
skip-checks: true
2022-06-03 15:57:54 +00:00
Jaco e946243b6f Additional performance tests (#1512) 2022-06-03 18:53:57 +03:00
github-actions[bot] ca6a4177b5 [CI Skip] release/beta 9.3.2-2
skip-checks: true
2022-06-03 07:24:22 +00:00
Jaco 7817311f84 Bump dev deps (#1511) 2022-06-03 10:20:26 +03:00
github-actions[bot] 77659aae2a [CI Skip] release/beta 9.3.2-1
skip-checks: true
2022-06-01 05:18:41 +00:00
Jaco 7cc619fbb0 Add nextTick (#1510)
* Add nextTick

* ss58Registry test results
2022-06-01 08:14:42 +03:00
github-actions[bot] 887654049e [CI Skip] release/beta 9.3.2-0
skip-checks: true
2022-05-30 07:51:32 +00:00
Jaco d07b79f578 Bump TS (#1508)
* Bump TS

* Override
2022-05-30 10:46:38 +03:00
105 changed files with 1879 additions and 1132 deletions
+50
View File
@@ -0,0 +1,50 @@
<!--
For general support, howto, coding and bundling questions, please use the Substrate & Polkadot StackExchange at https://substrate.stackexchange.com/ and get other ecosystem developers involved. This issues in this repository are meant for the tracking of feature requests and bug reports.
While all issues are looked at non-bug and non-features would take quite a bit longer to get to and may yield less than satisfactory responses in this format.
Additionally, please ensure you have done a search on the existing and closed issues before logging a new request. This saves time on all sides.
-->
* **I'm submitting a ...**
<!--- Try and classify your actual report -->
- [ ] Bug report
- [ ] Feature request
- [ ] Support request (please bear the comments above in mind)
- [ ] Other
* **What is the current behavior and expected behavior?**
<!--- If you're describing a bug, tell us what should happen -->
<!--- If you're suggesting a change/improvement, tell us how it should work -->
* **What is the motivation for changing the behavior?**
<!--- Not obligatory, but suggest a motivation for the request -->
<!--- or ideas how to implement the addition or change -->
* **Please tell us about your environment:**
<!--- Include as many relevant details about the environment you experienced the issue in -->
<!--- Also snsure that you have tested against the latest stable releases if a bug -->
- Version:
- Environment:
- [ ] Node.js
- [ ] Browser
- [ ] Other (limited support for other environments available)
- Language:
- [ ] JavaScript
- [ ] TypeScript
- [ ] Other
+27
View File
@@ -1,5 +1,32 @@
# CHANGELOG # CHANGELOG
## 9.5.1 Jun 18, 2022
Contributed:
- Update Bifrost genesisHash (Thanks to https://github.com/awesomepan)
- Add Ledger support for Composable (Thanks to https://github.com/carlosala)
Changes:
- Add `u8aToNumber` (limited, <= 48 bits) function
- Use `~~` as bitwise/faster `Math.floor` replacement
- Remove unneeded `objectSpread` option expansions
- Optimize `hexToU8a` operations
- Optimize `stringCamelCase` operations
- Optimize `u8aToBn` operations
- Additional internal/external comments (as missing)
- Upgrade dependencies to latest stable versions
## 9.4.1 Jun 4, 2022
Changes:
- Add `nextTick` to `@polkadot/util` to defer execution to the queue
- Upgrade dependencies to latest stable versions
## 9.3.1 May 29, 2022 ## 9.3.1 May 29, 2022
Contributed: Contributed:
+3 -3
View File
@@ -1,11 +1,12 @@
1332 Jaco 9.3.1 (#1507) 1363 Jaco 9.5.1 (#1545)
9 Antoine Estienne Add eth uri keyring test (#1291) 9 Antoine Estienne Add eth uri keyring test (#1291)
6 Amaury Martiny Add tests from Rust (#283) 6 Amaury Martiny Add tests from Rust (#283)
5 kwingram25 Add BN consts and timeToString (#610) 5 kwingram25 Add BN consts and timeToString (#610)
4 Adam Dossa Update Polymesh Genesis Hash (#1193) 4 Adam Dossa Update Polymesh Genesis Hash (#1193)
4 Carlo Sala add Composable support for ledger (#1515)
4 Jakub Pánik Add basilisk 🐍 (#1396) 4 Jakub Pánik Add basilisk 🐍 (#1396)
3 Carlo Sala some changes to KnownLedger (#1497)
3 Luke Schoen docs: Fix example in readme since we use default imports (#243) 3 Luke Schoen docs: Fix example in readme since we use default imports (#243)
3 pan update bifrost genesis hash (#1521)
2 AndreasGassmann feat(dependencies): remove moment.js (#530) 2 AndreasGassmann feat(dependencies): remove moment.js (#530)
2 Gav Wood Fix stake:unstake (#182) 2 Gav Wood Fix stake:unstake (#182)
2 Hyungsuk Kang Add cross client Encryption/Decryption (#496) 2 Hyungsuk Kang Add cross client Encryption/Decryption (#496)
@@ -13,7 +14,6 @@
2 Kami Adding Westend genesis. (#1429) 2 Kami Adding Westend genesis. (#1429)
2 Lovesh Harchandani Update genesis hash of Dock mainnet (#1436) 2 Lovesh Harchandani Update genesis hash of Dock mainnet (#1436)
2 Nantian fix bigint type (#1079) 2 Nantian fix bigint type (#1079)
2 pan add bifrost (#1296)
2 Stefanie Doll Add missing dependencies to util-crypto (#424) 2 Stefanie Doll Add missing dependencies to util-crypto (#424)
1 Agustinus Theodorus docs: fix typo in naclSeal docs. (#1005) 1 Agustinus Theodorus docs: fix typo in naclSeal docs. (#1005)
1 Alexander Krupenkin Added ECDSA keypair support (#589) 1 Alexander Krupenkin Added ECDSA keypair support (#589)
+5 -5
View File
@@ -10,7 +10,7 @@
"url": "https://github.com/polkadot-js/common.git" "url": "https://github.com/polkadot-js/common.git"
}, },
"sideEffects": false, "sideEffects": false,
"version": "9.3.1", "version": "9.5.1",
"workspaces": [ "workspaces": [
"packages/*" "packages/*"
], ],
@@ -27,11 +27,11 @@
"test:one": "polkadot-dev-run-test --runInBand" "test:one": "polkadot-dev-run-test --runInBand"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.18.2", "@babel/core": "^7.18.5",
"@polkadot/dev": "^0.66.30", "@polkadot/dev": "^0.67.4",
"@types/jest": "^27.5.1" "@types/jest": "^28.1.2"
}, },
"resolutions": { "resolutions": {
"typescript": "^4.6.4" "typescript": "^4.7.3"
} }
} }
+2 -2
View File
@@ -16,7 +16,7 @@
}, },
"sideEffects": false, "sideEffects": false,
"type": "module", "type": "module",
"version": "9.3.1", "version": "9.5.1",
"browser": "browser.js", "browser": "browser.js",
"main": "node.js", "main": "node.js",
"react-native": "react-native.js", "react-native": "react-native.js",
@@ -25,7 +25,7 @@
"@ledgerhq/hw-transport": "^6.27.1", "@ledgerhq/hw-transport": "^6.27.1",
"@ledgerhq/hw-transport-webhid": "^6.27.1", "@ledgerhq/hw-transport-webhid": "^6.27.1",
"@ledgerhq/hw-transport-webusb": "^6.27.1", "@ledgerhq/hw-transport-webusb": "^6.27.1",
"@polkadot/util": "9.3.1" "@polkadot/util": "9.5.1"
}, },
"optionalDependencies": { "optionalDependencies": {
"@ledgerhq/hw-transport-node-hid-singleton": "^6.27.1" "@ledgerhq/hw-transport-node-hid-singleton": "^6.27.1"
@@ -3,4 +3,4 @@
// Do not edit, auto-generated by @polkadot/dev // Do not edit, auto-generated by @polkadot/dev
export const packageInfo = { name: '@polkadot/hw-ledger-transports', path: 'auto', type: 'auto', version: '9.3.1' }; export const packageInfo = { name: '@polkadot/hw-ledger-transports', path: 'auto', type: 'auto', version: '9.5.1' };
+4 -4
View File
@@ -19,13 +19,13 @@
"./detectPackage.cjs" "./detectPackage.cjs"
], ],
"type": "module", "type": "module",
"version": "9.3.1", "version": "9.5.1",
"main": "index.js", "main": "index.js",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.18.3", "@babel/runtime": "^7.18.3",
"@ledgerhq/hw-transport": "^6.27.1", "@ledgerhq/hw-transport": "^6.27.1",
"@polkadot/hw-ledger-transports": "9.3.1", "@polkadot/hw-ledger-transports": "9.5.1",
"@polkadot/util": "9.3.1", "@polkadot/util": "9.5.1",
"@zondax/ledger-substrate": "^0.29.0" "@zondax/ledger-substrate": "^0.31.0"
} }
} }
+2 -1
View File
@@ -4,7 +4,7 @@
import type Transport from '@ledgerhq/hw-transport'; import type Transport from '@ledgerhq/hw-transport';
import type { SubstrateApp } from '@zondax/ledger-substrate'; import type { SubstrateApp } from '@zondax/ledger-substrate';
import { newAcalaApp, newAstarApp, newBifrostApp, newCentrifugeApp, newDockApp, newEdgewareApp, newEquilibriumApp, newGenshiroApp, newKaruraApp, newKusamaApp, newNodleApp, newParallelApp, newPolkadexApp, newPolkadotApp, newPolymeshApp, newSoraApp, newStatemineApp, newStatemintApp, newXXNetworkApp } from '@zondax/ledger-substrate'; import { newAcalaApp, newAstarApp, newBifrostApp, newCentrifugeApp, newComposableApp, newDockApp, newEdgewareApp, newEquilibriumApp, newGenshiroApp, newKaruraApp, newKusamaApp, newNodleApp, newParallelApp, newPolkadexApp, newPolkadotApp, newPolymeshApp, newSoraApp, newStatemineApp, newStatemintApp, newXXNetworkApp } from '@zondax/ledger-substrate';
// These match up with the keys of the knownLedger object in the @polkadot/networks/defaults/ledger.ts // These match up with the keys of the knownLedger object in the @polkadot/networks/defaults/ledger.ts
export const ledgerApps: Record<string, (transport: Transport) => SubstrateApp> = { export const ledgerApps: Record<string, (transport: Transport) => SubstrateApp> = {
@@ -12,6 +12,7 @@ export const ledgerApps: Record<string, (transport: Transport) => SubstrateApp>
astar: newAstarApp, astar: newAstarApp,
bifrost: newBifrostApp, bifrost: newBifrostApp,
centrifuge: newCentrifugeApp, centrifuge: newCentrifugeApp,
composable: newComposableApp,
'dock-mainnet': newDockApp, 'dock-mainnet': newDockApp,
edgeware: newEdgewareApp, edgeware: newEdgewareApp,
equilibrium: newEquilibriumApp, equilibrium: newEquilibriumApp,
+1 -1
View File
@@ -3,4 +3,4 @@
// Do not edit, auto-generated by @polkadot/dev // Do not edit, auto-generated by @polkadot/dev
export const packageInfo = { name: '@polkadot/hw-ledger', path: 'auto', type: 'auto', version: '9.3.1' }; export const packageInfo = { name: '@polkadot/hw-ledger', path: 'auto', type: 'auto', version: '9.5.1' };
+5 -5
View File
@@ -20,15 +20,15 @@
"./detectPackage.cjs" "./detectPackage.cjs"
], ],
"type": "module", "type": "module",
"version": "9.3.1", "version": "9.5.1",
"main": "index.js", "main": "index.js",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.18.3", "@babel/runtime": "^7.18.3",
"@polkadot/util": "9.3.1", "@polkadot/util": "9.5.1",
"@polkadot/util-crypto": "9.3.1" "@polkadot/util-crypto": "9.5.1"
}, },
"peerDependencies": { "peerDependencies": {
"@polkadot/util": "9.3.1", "@polkadot/util": "9.5.1",
"@polkadot/util-crypto": "9.3.1" "@polkadot/util-crypto": "9.5.1"
} }
} }
+1 -1
View File
@@ -3,4 +3,4 @@
// Do not edit, auto-generated by @polkadot/dev // Do not edit, auto-generated by @polkadot/dev
export const packageInfo = { name: '@polkadot/keyring', path: 'auto', type: 'auto', version: '9.3.1' }; export const packageInfo = { name: '@polkadot/keyring', path: 'auto', type: 'auto', version: '9.5.1' };
+5 -5
View File
@@ -17,15 +17,15 @@
}, },
"sideEffects": false, "sideEffects": false,
"type": "module", "type": "module",
"version": "9.3.1", "version": "9.5.1",
"main": "index.js", "main": "index.js",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.18.3", "@babel/runtime": "^7.18.3",
"@polkadot/util": "9.3.1", "@polkadot/util": "9.5.1",
"@substrate/ss58-registry": "^1.20.0" "@substrate/ss58-registry": "^1.22.0"
}, },
"devDependencies": { "devDependencies": {
"@polkadot/hw-ledger": "9.3.1", "@polkadot/hw-ledger": "9.5.1",
"@polkadot/x-fetch": "9.3.1" "@polkadot/x-fetch": "9.5.1"
} }
} }
+5 -1
View File
@@ -18,11 +18,15 @@ export const knownGenesis: KnownGenesis = {
'0xa85cfb9b9fd4d622a5b28289a02347af987d8f73fa3108450e2b4a11c1ce5755' '0xa85cfb9b9fd4d622a5b28289a02347af987d8f73fa3108450e2b4a11c1ce5755'
], ],
bifrost: [ bifrost: [
'0x9f28c6a68e0fc9646eff64935684f6eeeece527e37bbe1f213d22caa1d9d6bed' '0x262e1b2ad728475fd6fe88e62d34c200abe6fd693931ddad144059b1eb884e5b'
], ],
centrifuge: [ centrifuge: [
'0xb3db41421702df9a7fcac62b53ffeac85f7853cc4e689e0b93aeb3db18c09d82',
'0x67dddf2673b69e5f875f6f25277495834398eafd67f492e09f3f3345e003d1b5' '0x67dddf2673b69e5f875f6f25277495834398eafd67f492e09f3f3345e003d1b5'
], ],
composable: [
'0xdaab8df776eb52ec604a5df5d388bb62a050a0aaec4556a64265b9d42755552d'
],
'dock-mainnet': [ 'dock-mainnet': [
'0x6bfe24dca2a3be10f22212678ac13a6446ec764103c0f3471c71609eac384aae', '0x6bfe24dca2a3be10f22212678ac13a6446ec764103c0f3471c71609eac384aae',
'0xf73467c6544aa68df2ee546b135f955c46b90fa627e9b5d7935f41061bb8a5a9' '0xf73467c6544aa68df2ee546b135f955c46b90fa627e9b5d7935f41061bb8a5a9'
+1
View File
@@ -12,6 +12,7 @@ export const knownLedger: KnownLedger = {
astar: 0x0000032a, astar: 0x0000032a,
bifrost: 0x00000314, bifrost: 0x00000314,
centrifuge: 0x000002eb, centrifuge: 0x000002eb,
composable: 0x00000162,
'dock-mainnet': 0x00000252, 'dock-mainnet': 0x00000252,
edgeware: 0x0000020b, edgeware: 0x0000020b,
equilibrium: 0x05f5e0fd, equilibrium: 0x05f5e0fd,
+1 -1
View File
@@ -3,4 +3,4 @@
// Do not edit, auto-generated by @polkadot/dev // Do not edit, auto-generated by @polkadot/dev
export const packageInfo = { name: '@polkadot/networks', path: 'auto', type: 'auto', version: '9.3.1' }; export const packageInfo = { name: '@polkadot/networks', path: 'auto', type: 'auto', version: '9.5.1' };
@@ -633,6 +633,19 @@
"standardAccount": "*25519", "standardAccount": "*25519",
"website": "https://dico.io" "website": "https://dico.io"
}, },
{
"prefix": 54,
"network": "cere",
"displayName": "Cere Network",
"symbols": [
"CERE"
],
"decimals": [
10
],
"standardAccount": "*25519",
"website": "https://cere.network"
},
{ {
"prefix": 55, "prefix": 55,
"network": "xxnetwork", "network": "xxnetwork",
@@ -1140,6 +1153,19 @@
"standardAccount": "*25519", "standardAccount": "*25519",
"website": "https://subspace.network" "website": "https://subspace.network"
}, },
{
"prefix": 7007,
"network": "tidefi",
"displayName": "Tidefi",
"symbols": [
"TIFI"
],
"decimals": [
12
],
"standardAccount": "*25519",
"website": "https://tidefi.com"
},
{ {
"prefix": 7391, "prefix": 7391,
"network": "unique_mainnet", "network": "unique_mainnet",
@@ -1153,6 +1179,19 @@
"standardAccount": "*25519", "standardAccount": "*25519",
"website": "https://unique.network" "website": "https://unique.network"
}, },
{
"prefix": 9807,
"network": "dentnet",
"displayName": "DENTNet",
"symbols": [
"DENTX"
],
"decimals": [
18
],
"standardAccount": "*25519",
"website": "https://www.dentnet.io"
},
{ {
"prefix": 10041, "prefix": 10041,
"network": "basilisk", "network": "basilisk",
@@ -1204,5 +1243,18 @@
], ],
"standardAccount": "*25519", "standardAccount": "*25519",
"website": "https://ata.network" "website": "https://ata.network"
},
{
"prefix": 12191,
"network": "nftmart",
"displayName": "NFTMart",
"symbols": [
"NMT"
],
"decimals": [
12
],
"standardAccount": "*25519",
"website": "https://nftmart.io"
} }
] ]
+9 -9
View File
@@ -22,7 +22,7 @@
"./detectPackage.cjs" "./detectPackage.cjs"
], ],
"type": "module", "type": "module",
"version": "9.3.1", "version": "9.5.1",
"browser": { "browser": {
"crypto": false, "crypto": false,
"stream": false "stream": false
@@ -30,14 +30,14 @@
"main": "index.js", "main": "index.js",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.18.3", "@babel/runtime": "^7.18.3",
"@noble/hashes": "1.0.0", "@noble/hashes": "1.1.1",
"@noble/secp256k1": "1.5.5", "@noble/secp256k1": "1.6.0",
"@polkadot/networks": "9.3.1", "@polkadot/networks": "9.5.1",
"@polkadot/util": "9.3.1", "@polkadot/util": "9.5.1",
"@polkadot/wasm-crypto": "^6.1.1", "@polkadot/wasm-crypto": "^6.1.1",
"@polkadot/x-bigint": "9.3.1", "@polkadot/x-bigint": "9.5.1",
"@polkadot/x-randomvalues": "9.3.1", "@polkadot/x-randomvalues": "9.5.1",
"@scure/base": "1.0.0", "@scure/base": "1.1.1",
"ed2curve": "^0.3.0", "ed2curve": "^0.3.0",
"tweetnacl": "^1.0.3" "tweetnacl": "^1.0.3"
}, },
@@ -45,6 +45,6 @@
"@types/ed2curve": "^0.2.2" "@types/ed2curve": "^0.2.2"
}, },
"peerDependencies": { "peerDependencies": {
"@polkadot/util": "9.3.1" "@polkadot/util": "9.5.1"
} }
} }
@@ -27,6 +27,7 @@ type EncodeFn = (value: U8aLike, ipfsCompat?: boolean) => string;
type ValidateFn = (value?: unknown, ipfsCompat?: boolean) => value is string; type ValidateFn = (value?: unknown, ipfsCompat?: boolean) => value is string;
/** @internal */
export function createDecode ({ coder, ipfs }: Config, validate: ValidateFn): DecodeFn { export function createDecode ({ coder, ipfs }: Config, validate: ValidateFn): DecodeFn {
return (value: string, ipfsCompat?: boolean): Uint8Array => { return (value: string, ipfsCompat?: boolean): Uint8Array => {
validate(value, ipfsCompat); validate(value, ipfsCompat);
@@ -39,6 +40,7 @@ export function createDecode ({ coder, ipfs }: Config, validate: ValidateFn): De
}; };
} }
/** @internal */
export function createEncode ({ coder, ipfs }: Config): EncodeFn { export function createEncode ({ coder, ipfs }: Config): EncodeFn {
return (value: U8aLike, ipfsCompat?: boolean): string => { return (value: U8aLike, ipfsCompat?: boolean): string => {
const out = coder.encode(u8aToU8a(value)); const out = coder.encode(u8aToU8a(value));
@@ -49,6 +51,7 @@ export function createEncode ({ coder, ipfs }: Config): EncodeFn {
}; };
} }
/** @internal */
export function createIs (validate: ValidateFn): ValidateFn { export function createIs (validate: ValidateFn): ValidateFn {
return (value?: unknown, ipfsCompat?: boolean): value is string => { return (value?: unknown, ipfsCompat?: boolean): value is string => {
try { try {
@@ -59,6 +62,7 @@ export function createIs (validate: ValidateFn): ValidateFn {
}; };
} }
/** @internal */
export function createValidate ({ chars, ipfs, type }: Config): ValidateFn { export function createValidate ({ chars, ipfs, type }: Config): ValidateFn {
return (value?: unknown, ipfsCompat?: boolean): value is string => { return (value?: unknown, ipfsCompat?: boolean): value is string => {
assert(value && typeof value === 'string', () => `Expected non-null, non-empty ${type} string input`); assert(value && typeof value === 'string', () => `Expected non-null, non-empty ${type} string input`);
+3
View File
@@ -14,16 +14,19 @@ interface DualHash {
512: (u8a: Uint8Array) => Uint8Array; 512: (u8a: Uint8Array) => Uint8Array;
} }
/** @internal */
export function createAsHex <T extends (...args: never[]) => Uint8Array> (fn: T): (...args: Parameters<T>) => HexString { export function createAsHex <T extends (...args: never[]) => Uint8Array> (fn: T): (...args: Parameters<T>) => HexString {
return (...args: Parameters<T>): HexString => return (...args: Parameters<T>): HexString =>
u8aToHex(fn(...args)); u8aToHex(fn(...args));
} }
/** @internal */
export function createBitHasher (bitLength: 256 | 512, fn: (data: HexString | Buffer | Uint8Array | string, bitLength: 256 | 512, onlyJs?: boolean) => Uint8Array): (data: HexString | Buffer | Uint8Array | string, onlyJs?: boolean) => Uint8Array { export function createBitHasher (bitLength: 256 | 512, fn: (data: HexString | Buffer | Uint8Array | string, bitLength: 256 | 512, onlyJs?: boolean) => Uint8Array): (data: HexString | Buffer | Uint8Array | string, onlyJs?: boolean) => Uint8Array {
return (data: HexString | Buffer | Uint8Array | string, onlyJs?: boolean): Uint8Array => return (data: HexString | Buffer | Uint8Array | string, onlyJs?: boolean): Uint8Array =>
fn(data, bitLength, onlyJs); fn(data, bitLength, onlyJs);
} }
/** @internal */
export function createDualHasher (wa: DualHash, js: DualHash): (value: HexString | Buffer | Uint8Array | string, bitLength?: 256 | 512, onlyJs?: boolean) => Uint8Array { export function createDualHasher (wa: DualHash, js: DualHash): (value: HexString | Buffer | Uint8Array | string, bitLength?: 256 | 512, onlyJs?: boolean) => Uint8Array {
return (value: HexString | Buffer | Uint8Array | string, bitLength: 256 | 512 = 256, onlyJs?: boolean): Uint8Array => { return (value: HexString | Buffer | Uint8Array | string, bitLength: 256 | 512 = 256, onlyJs?: boolean): Uint8Array => {
const u8a = u8aToU8a(value); const u8a = u8aToU8a(value);
+1 -1
View File
@@ -3,4 +3,4 @@
// Do not edit, auto-generated by @polkadot/dev // Do not edit, auto-generated by @polkadot/dev
export const packageInfo = { name: '@polkadot/util-crypto', path: 'auto', type: 'auto', version: '9.3.1' }; export const packageInfo = { name: '@polkadot/util-crypto', path: 'auto', type: 'auto', version: '9.5.1' };
+6 -6
View File
@@ -34,19 +34,19 @@
"./detectPackage.cjs" "./detectPackage.cjs"
], ],
"type": "module", "type": "module",
"version": "9.3.1", "version": "9.5.1",
"main": "index.js", "main": "index.js",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.18.3", "@babel/runtime": "^7.18.3",
"@polkadot/x-bigint": "9.3.1", "@polkadot/x-bigint": "9.5.1",
"@polkadot/x-global": "9.3.1", "@polkadot/x-global": "9.5.1",
"@polkadot/x-textdecoder": "9.3.1", "@polkadot/x-textdecoder": "9.5.1",
"@polkadot/x-textencoder": "9.3.1", "@polkadot/x-textencoder": "9.5.1",
"@types/bn.js": "^5.1.0", "@types/bn.js": "^5.1.0",
"bn.js": "^5.2.1", "bn.js": "^5.2.1",
"ip-regex": "^4.3.0" "ip-regex": "^4.3.0"
}, },
"devDependencies": { "devDependencies": {
"@polkadot/x-randomvalues": "9.3.1" "@polkadot/x-randomvalues": "9.5.1"
} }
} }
+4 -1
View File
@@ -1,7 +1,8 @@
// Copyright 2017-2022 @polkadot/util authors & contributors // Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { arrayChunk } from '.'; import { performance } from '../test/performance';
import { arrayChunk, arrayRange } from '.';
describe('arrayChunk', (): void => { describe('arrayChunk', (): void => {
it('chunks arrays', (): void => { it('chunks arrays', (): void => {
@@ -9,4 +10,6 @@ describe('arrayChunk', (): void => {
arrayChunk([1, 2, 3, 4, 5, 6, 7], 3) arrayChunk([1, 2, 3, 4, 5, 6, 7], 3)
).toEqual([[1, 2, 3], [4, 5, 6], [7]]); ).toEqual([[1, 2, 3], [4, 5, 6], [7]]);
}); });
performance('arrayChunk', 200_000, [[arrayRange(500), 50]], arrayChunk);
}); });
+6
View File
@@ -17,6 +17,12 @@
*/ */
export function arrayChunk <T> (array: T[], chunkSize: number): T[][] { export function arrayChunk <T> (array: T[], chunkSize: number): T[][] {
const outputSize = Math.ceil(array.length / chunkSize); const outputSize = Math.ceil(array.length / chunkSize);
// noop for the single-split case
if (outputSize === 1) {
return [array];
}
const output = Array<T[]>(outputSize); const output = Array<T[]>(outputSize);
for (let i = 0; i < outputSize; i++) { for (let i = 0; i < outputSize; i++) {
+2 -3
View File
@@ -19,9 +19,8 @@ import { isUndefined } from '../is/undefined';
* arrayFilter([0, void 0, true, null, false, ''], false); // [0, true, false, ''] * arrayFilter([0, void 0, true, null, false, ''], false); // [0, true, false, '']
* ``` * ```
*/ */
// eslint-disable-next-line @typescript-eslint/no-explicit-any export function arrayFilter <T = unknown> (array: (T | null | undefined)[], allowNulls = true): T[] {
export function arrayFilter <T = any> (array: T[], allowNulls = true): T[] { return array.filter((v): v is T =>
return array.filter((v) =>
!isUndefined(v) && !isUndefined(v) &&
(allowNulls || !isNull(v)) (allowNulls || !isNull(v))
); );
+5
View File
@@ -19,6 +19,11 @@
* ``` * ```
*/ */
export function arrayFlatten <T> (arrays: T[][]): T[] { export function arrayFlatten <T> (arrays: T[][]): T[] {
// noop for the single-entry case
if (arrays.length === 1) {
return arrays[0];
}
// pre-allocate based on the combined size // pre-allocate based on the combined size
let size = 0; let size = 0;
+3 -3
View File
@@ -1,8 +1,6 @@
// Copyright 2017-2022 @polkadot/util authors & contributors // Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { assert } from '../assert';
/** /**
* @name arrayRange * @name arrayRange
* @summary Returns a range of numbers ith the size and the specified offset * @summary Returns a range of numbers ith the size and the specified offset
@@ -19,7 +17,9 @@ import { assert } from '../assert';
* ``` * ```
*/ */
export function arrayRange (size: number, startAt = 0): number[] { export function arrayRange (size: number, startAt = 0): number[] {
assert(size > 0, 'Expected non-zero, positive number as a range size'); if (size <= 0) {
throw new Error('Expected non-zero, positive number as a range size');
}
const result = new Array<number>(size); const result = new Array<number>(size);
+5
View File
@@ -1,8 +1,11 @@
// Copyright 2017-2022 @polkadot/util authors & contributors // Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { performance } from '../test/performance';
import { arrayRange, arrayShuffle } from '.'; import { arrayRange, arrayShuffle } from '.';
const ptest = arrayRange(16284);
describe('arrayShuffle', (): void => { describe('arrayShuffle', (): void => {
it('returns an empty array as-is', (): void => { it('returns an empty array as-is', (): void => {
expect( expect(
@@ -28,4 +31,6 @@ describe('arrayShuffle', (): void => {
JSON.stringify(inp) JSON.stringify(inp)
).not.toEqual(JSON.stringify(out)); ).not.toEqual(JSON.stringify(out));
}); });
performance('arrayShuffle', 1000, [[ptest]], arrayShuffle);
}); });
+7 -1
View File
@@ -1,16 +1,22 @@
// Copyright 2017-2022 @polkadot/util authors & contributors // Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
/**
* @name arrayShuffle
* @description Shuffles the input array (unlike sort, this is not done in-place)
*/
export function arrayShuffle <T> (input: T[]): T[] { export function arrayShuffle <T> (input: T[]): T[] {
const result = input.slice(); const result = input.slice();
let curr = result.length; let curr = result.length;
// noop for the single entry
if (curr === 1) { if (curr === 1) {
return result; return result;
} }
while (curr !== 0) { while (curr !== 0) {
const rand = Math.floor(Math.random() * curr); // ~~ is more performant than Math.floor
const rand = ~~(Math.random() * curr);
curr--; curr--;
+4
View File
@@ -1,6 +1,10 @@
// Copyright 2017-2022 @polkadot/util authors & contributors // Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
/**
* @name arrayZip
* @description Combines 2 distinct key/value arrays into a single [K, V] array
*/
export function arrayZip <K, V> (keys: K[], values: V[]): [K, V][] { export function arrayZip <K, V> (keys: K[], values: V[]): [K, V][] {
const result = new Array<[K, V]>(keys.length); const result = new Array<[K, V]>(keys.length);
+21
View File
@@ -0,0 +1,21 @@
// Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
/** @internal */
export function createCmp <T> (cmp: (a: T, b: T) => boolean): (...items: T[]) => T {
return (...items: T[]): T => {
if (items.length === 0) {
throw new Error('Must provide one or more arguments');
}
let result = items[0];
for (let i = 1; i < items.length; i++) {
if (cmp(items[i], result)) {
result = items[i];
}
}
return result;
};
}
+1 -1
View File
@@ -25,6 +25,6 @@ describe('nMax', (): void => {
it('fails when no items are available', (): void => { it('fails when no items are available', (): void => {
expect( expect(
() => nMax() () => nMax()
).toThrow(/Must provide one or more bigint arguments/); ).toThrow(/Must provide one or more arguments/);
}); });
}); });
+1 -1
View File
@@ -19,6 +19,6 @@ describe('nMin', (): void => {
it('fails when no items are available', (): void => { it('fails when no items are available', (): void => {
expect( expect(
() => nMin() () => nMin()
).toThrow(/Must provide one or more bigint arguments/); ).toThrow(/Must provide one or more arguments/);
}); });
}); });
+3 -29
View File
@@ -1,42 +1,16 @@
// Copyright 2017-2022 @polkadot/util authors & contributors // Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { assert } from '../assert'; import { createCmp } from './helpers';
function gt (a: bigint, b: bigint): boolean {
return a > b;
}
function lt (a: bigint, b: bigint): boolean {
return a < b;
}
function find (items: bigint[], cmp: (a: bigint, b: bigint) => boolean): bigint {
assert(items.length >= 1, 'Must provide one or more bigint arguments');
let result = items[0];
for (let i = 1; i < items.length; i++) {
if (cmp(items[i], result)) {
result = items[i];
}
}
return result;
}
/** /**
* @name nMax * @name nMax
* @summary Finds and returns the highest value in an array of bigint. * @summary Finds and returns the highest value in an array of bigint.
*/ */
export function nMax (...items: bigint[]): bigint { export const nMax = createCmp<bigint>((a, b) => a > b);
return find(items, gt);
}
/** /**
* @name nMin * @name nMin
* @summary Finds and returns the lowest value in an array of bigint. * @summary Finds and returns the lowest value in an array of bigint.
*/ */
export function nMin (...items: bigint[]): bigint { export const nMin = createCmp<bigint>((a, b) => a < b);
return find(items, lt);
}
+14 -1
View File
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { BN } from '../bn'; import { BN } from '../bn';
import { SQRT_MAX_SAFE_INTEGER } from './sqrt';
import { nSqrt } from '.'; import { nSqrt } from '.';
const TESTS: [string | number | BN | bigint, string | number][] = [ const TESTS: [string | number | BN | bigint, string | number][] = [
@@ -34,9 +35,21 @@ describe('nSqrt', (): void => {
).toThrow(/negative numbers is not supported/); ).toThrow(/negative numbers is not supported/);
}); });
it('has the correct constant for sqrt(Number.MAX_SAFE_INTEGER)', (): void => {
expect(
BigInt(
~~Math.sqrt(
Number.MAX_SAFE_INTEGER
)
) === SQRT_MAX_SAFE_INTEGER
).toEqual(true);
});
TESTS.forEach(([value, expected], index): void => { TESTS.forEach(([value, expected], index): void => {
it(`calcs for test #${index}`, (): void => { it(`calcs for test #${index}`, (): void => {
expect(nSqrt(value) === BigInt(expected)).toEqual(true); expect(
nSqrt(value) === BigInt(expected)
).toEqual(true);
}); });
}); });
}); });
+8 -5
View File
@@ -6,11 +6,11 @@ import type { ToBigInt, ToBn } from '../types';
import { BigInt } from '@polkadot/x-bigint'; import { BigInt } from '@polkadot/x-bigint';
import { assert } from '../assert';
import { _0n, _1n, _2pow53n } from './consts'; import { _0n, _1n, _2pow53n } from './consts';
import { nToBigInt } from './toBigInt'; import { nToBigInt } from './toBigInt';
const _sqrt2pow53n = BigInt(94906265); /** @internal */
export const SQRT_MAX_SAFE_INTEGER = BigInt(94906265);
/** /**
* @name nSqrt * @name nSqrt
@@ -19,17 +19,20 @@ const _sqrt2pow53n = BigInt(94906265);
export function nSqrt <ExtToBn extends ToBn | ToBigInt> (value: ExtToBn | BN | bigint | string | number | null): bigint { export function nSqrt <ExtToBn extends ToBn | ToBigInt> (value: ExtToBn | BN | bigint | string | number | null): bigint {
const n = nToBigInt(value); const n = nToBigInt(value);
assert(n >= _0n, 'square root of negative numbers is not supported'); if (n < _0n) {
throw new Error('square root of negative numbers is not supported');
}
// https://stackoverflow.com/questions/53683995/javascript-big-integer-square-root/ // https://stackoverflow.com/questions/53683995/javascript-big-integer-square-root/
// shortcut <= 2^53 - 1 to use the JS utils // shortcut <= 2^53 - 1 to use the JS utils
if (n <= _2pow53n) { if (n <= _2pow53n) {
return BigInt(Math.floor(Math.sqrt(Number(n)))); // ~~ is more performant that Math.floor
return BigInt(~~Math.sqrt(Number(n)));
} }
// Use sqrt(MAX_SAFE_INTEGER) as starting point. since we already know the // Use sqrt(MAX_SAFE_INTEGER) as starting point. since we already know the
// output will be larger than this, we expect this to be a safe start // output will be larger than this, we expect this to be a safe start
let x0 = _sqrt2pow53n; let x0 = SQRT_MAX_SAFE_INTEGER;
while (true) { while (true) {
const x1 = ((n / x0) + x0) >> _1n; const x1 = ((n / x0) + x0) >> _1n;
+1
View File
@@ -8,6 +8,7 @@ import { objectSpread } from '../object/spread';
import { u8aToHex } from '../u8a'; import { u8aToHex } from '../u8a';
import { nToU8a } from './toU8a'; import { nToU8a } from './toU8a';
/** @internal */
const ZERO_STR = '0x00'; const ZERO_STR = '0x00';
/** /**
+1 -1
View File
@@ -25,6 +25,6 @@ describe('bnMax', (): void => {
it('fails when no items are available', (): void => { it('fails when no items are available', (): void => {
expect( expect(
() => bnMax() () => bnMax()
).toThrow(/Must provide one or more BN arguments/); ).toThrow(/Must provide one or more arguments/);
}); });
}); });
+6
View File
@@ -15,4 +15,10 @@ describe('bnMin', (): void => {
bnMin(new BN(1)) bnMin(new BN(1))
).toEqual(new BN(1)); ).toEqual(new BN(1));
}); });
it('fails when no items are available', (): void => {
expect(
() => bnMin()
).toThrow(/Must provide one or more arguments/);
});
}); });
+3 -19
View File
@@ -1,21 +1,9 @@
// Copyright 2017-2022 @polkadot/util authors & contributors // Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { assert } from '../assert'; import { createCmp } from '../bi/helpers';
import { BN } from './bn'; import { BN } from './bn';
export function find (items: BN[], cmp: (a: BN, b: BN) => BN): BN {
assert(items.length >= 1, 'Must provide one or more BN arguments');
let result = items[0];
for (let i = 1; i < items.length; i++) {
result = cmp(result, items[i]);
}
return result;
}
/** /**
* @name bnMax * @name bnMax
* @summary Finds and returns the highest value in an array of BNs. * @summary Finds and returns the highest value in an array of BNs.
@@ -29,9 +17,7 @@ export function find (items: BN[], cmp: (a: BN, b: BN) => BN): BN {
* bnMax([new BN(1), new BN(3), new BN(2)]).toString(); // => '3' * bnMax([new BN(1), new BN(3), new BN(2)]).toString(); // => '3'
* ``` * ```
*/ */
export function bnMax (...items: BN[]): BN { export const bnMax = createCmp<BN>((a, b) => a.gt(b));
return find(items, BN.max);
}
/** /**
* @name bnMin * @name bnMin
@@ -46,6 +32,4 @@ export function bnMax (...items: BN[]): BN {
* bnMin([new BN(1), new BN(3), new BN(2)]).toString(); // => '1' * bnMin([new BN(1), new BN(3), new BN(2)]).toString(); // => '1'
* ``` * ```
*/ */
export function bnMin (...items: BN[]): BN { export const bnMin = createCmp<BN>((a, b) => a.lt(b));
return find(items, BN.min);
}
+16 -1
View File
@@ -1,6 +1,7 @@
// Copyright 2017-2022 @polkadot/util authors & contributors // Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { SQRT_MAX_SAFE_INTEGER } from './sqrt';
import { BN, bnSqrt } from '.'; import { BN, bnSqrt } from '.';
const TESTS: [string | number | BN | bigint, string | number][] = [ const TESTS: [string | number | BN | bigint, string | number][] = [
@@ -33,9 +34,23 @@ describe('bnSqrt', (): void => {
).toThrow(/negative numbers is not supported/); ).toThrow(/negative numbers is not supported/);
}); });
it('has the correct constant for sqrt(Number.MAX_SAFE_INTEGER)', (): void => {
expect(
SQRT_MAX_SAFE_INTEGER.eq(
new BN(
~~Math.sqrt(
Number.MAX_SAFE_INTEGER
)
)
)
).toEqual(true);
});
TESTS.forEach(([value, expected], index): void => { TESTS.forEach(([value, expected], index): void => {
it(`calcs for test #${index}`, (): void => { it(`calcs for test #${index}`, (): void => {
expect(bnSqrt(value).eq(new BN(expected))).toEqual(true); expect(
bnSqrt(value).eq(new BN(expected))
).toEqual(true);
}); });
}); });
}); });
+8 -5
View File
@@ -3,12 +3,12 @@
import type { ToBn } from '../types'; import type { ToBn } from '../types';
import { assert } from '../assert';
import { BN } from './bn'; import { BN } from './bn';
import { BN_MAX_INTEGER, BN_ONE, BN_ZERO } from './consts'; import { BN_MAX_INTEGER, BN_ONE } from './consts';
import { bnToBn } from './toBn'; import { bnToBn } from './toBn';
const SQRT_MAX_SAFE_INTEGER = new BN(94906265); /** @internal */
export const SQRT_MAX_SAFE_INTEGER = new BN(94906265);
/** /**
* @name bnSqrt * @name bnSqrt
@@ -26,12 +26,15 @@ const SQRT_MAX_SAFE_INTEGER = new BN(94906265);
export function bnSqrt <ExtToBn extends ToBn> (value: ExtToBn | BN | bigint | string | number | null): BN { export function bnSqrt <ExtToBn extends ToBn> (value: ExtToBn | BN | bigint | string | number | null): BN {
const n = bnToBn(value); const n = bnToBn(value);
assert(n.gte(BN_ZERO), 'square root of negative numbers is not supported'); if (n.isNeg()) {
throw new Error('square root of negative numbers is not supported');
}
// https://stackoverflow.com/questions/53683995/javascript-big-integer-square-root/ // https://stackoverflow.com/questions/53683995/javascript-big-integer-square-root/
// shortcut <= 2^53 - 1 to use the JS utils // shortcut <= 2^53 - 1 to use the JS utils
if (n.lte(BN_MAX_INTEGER)) { if (n.lte(BN_MAX_INTEGER)) {
return new BN(Math.floor(Math.sqrt(n.toNumber()))); // ~~ More performant version of Math.floor
return new BN(~~Math.sqrt(n.toNumber()));
} }
// Use sqrt(MAX_SAFE_INTEGER) as starting point. since we already know the // Use sqrt(MAX_SAFE_INTEGER) as starting point. since we already know the
+1 -1
View File
@@ -31,7 +31,7 @@ function bnToHex <ExtToBn extends ToBn> (value?: ExtToBn | BN | bigint | number
/** @deprecated Use bnToHex (value?: ExtToBn | BN | bigint | number | null, options?: NumberOptions) */ /** @deprecated Use bnToHex (value?: ExtToBn | BN | bigint | number | null, options?: NumberOptions) */
function bnToHex <ExtToBn extends ToBn> (value?: ExtToBn | BN | bigint | number | null, bitLength?: number, isLe?: boolean): HexString; function bnToHex <ExtToBn extends ToBn> (value?: ExtToBn | BN | bigint | number | null, bitLength?: number, isLe?: boolean): HexString;
/** @deprecated Use bnToHex (value?: ExtToBn | BN | bigint | number | null, options?: NumberOptions) */ /** @deprecated Use bnToHex (value?: ExtToBn | BN | bigint | number | null, options?: NumberOptions) */
function bnToHex <ExtToBn extends ToBn> (value?: ExtToBn | BN | bigint | number | null, arg1: number | NumberOptions = DEFAULT_OPTS, arg2?: boolean): HexString { function bnToHex <ExtToBn extends ToBn> (value?: ExtToBn | BN | bigint | number | null, arg1: number | NumberOptions = DEFAULT_OPTS, arg2 = false): HexString {
return !value return !value
? ZERO_STR ? ZERO_STR
: u8aToHex( : u8aToHex(
+62 -24
View File
@@ -38,30 +38,6 @@ describe('bnToU8a', (): void => {
).toEqual(new Uint8Array([0x56, 0x34, 0x12, 0x00])); ).toEqual(new Uint8Array([0x56, 0x34, 0x12, 0x00]));
}); });
it('converts negative numbers', (): void => {
expect(
bnToU8a(new BN(-1234), { isNegative: true })
).toEqual(new Uint8Array([46, 251]));
});
it('converts negative numbers (BE)', (): void => {
expect(
bnToU8a(new BN(-1234), { isLe: false, isNegative: true })
).toEqual(new Uint8Array([251, 46]));
});
it('converts negative numbers (LE)', (): void => {
expect(
bnToU8a(new BN(-1234), { bitLength: 32, isNegative: true })
).toEqual(new Uint8Array([46, 251, 255, 255]));
});
it('converts negative numbers (LE, bitLength)', (): void => {
expect(
bnToU8a(new BN(-123456), { bitLength: 32, isNegative: true })
).toEqual(new Uint8Array([192, 29, 254, 255]));
});
it('handles backwards compatibility', (): void => { it('handles backwards compatibility', (): void => {
expect( expect(
bnToU8a(new BN(1234), 32, false) bnToU8a(new BN(1234), 32, false)
@@ -70,5 +46,67 @@ describe('bnToU8a', (): void => {
); );
}); });
describe('signed', (): void => {
it('converts negative numbers (BE)', (): void => {
expect(
bnToU8a(new BN(-1234), { isLe: false, isNegative: true })
).toEqual(new Uint8Array([251, 46]));
});
it('converts negative numbers (LE, i8)', (): void => {
expect(
bnToU8a(new BN(-12), { isNegative: true })
).toEqual(new Uint8Array([244]));
});
it('converts negative numbers (LE, i16)', (): void => {
expect(
bnToU8a(new BN(-1234), { isNegative: true })
).toEqual(new Uint8Array([46, 251]));
});
it('converts negative numbers (LE, i24)', (): void => {
expect(
bnToU8a(new BN(-123456), { isNegative: true })
).toEqual(new Uint8Array([192, 29, 254]));
});
it('converts negative numbers (LE, i32)', (): void => {
expect(
bnToU8a(new BN(-123456789), { isNegative: true })
).toEqual(new Uint8Array([235, 50, 164, 248]));
});
it('converts negative numbers (LE, i40)', (): void => {
expect(
bnToU8a(new BN(-5678999999), { isNegative: true })
).toEqual(new Uint8Array([65, 86, 129, 173, 254]));
});
it('converts negative numbers (LE, i48)', (): void => {
expect(
bnToU8a(new BN(-9999999999999), { isNegative: true })
).toEqual(new Uint8Array([1, 96, 141, 177, 231, 246]));
});
it('converts negative numbers (LE, i64)', (): void => {
expect(
bnToU8a(new BN('-999999999999999999'), { isNegative: true })
).toEqual(new Uint8Array([1, 0, 156, 88, 76, 73, 31, 242]));
});
it('converts negative numbers (LE, bitLength)', (): void => {
expect(
bnToU8a(new BN(-1234), { bitLength: 32, isNegative: true })
).toEqual(new Uint8Array([46, 251, 255, 255]));
});
it('converts negative numbers (LE, bitLength)', (): void => {
expect(
bnToU8a(new BN(-123456), { bitLength: 32, isNegative: true })
).toEqual(new Uint8Array([192, 29, 254, 255]));
});
});
performance('bnToU8a', 250000, ptest, bnToU8a); performance('bnToU8a', 250000, ptest, bnToU8a);
}); });
+4 -8
View File
@@ -5,7 +5,6 @@ import type { NumberOptions, ToBn } from '../types';
import type { BN } from './bn'; import type { BN } from './bn';
import { isNumber } from '../is/number'; import { isNumber } from '../is/number';
import { objectSpread } from '../object/spread';
import { bnToBn } from './toBn'; import { bnToBn } from './toBn';
const DEFAULT_OPTS: NumberOptions = { bitLength: -1, isLe: true, isNegative: false }; const DEFAULT_OPTS: NumberOptions = { bitLength: -1, isLe: true, isNegative: false };
@@ -28,13 +27,10 @@ function bnToU8a <ExtToBn extends ToBn> (value?: ExtToBn | BN | bigint | number
/** @deprecated Use bnToU8a(value?: ExtToBn | BN | bigint | number | null, options?: NumberOptions) */ /** @deprecated Use bnToU8a(value?: ExtToBn | BN | bigint | number | null, options?: NumberOptions) */
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;
/** @deprecated Use bnToU8a(value?: ExtToBn | BN | bigint | number | null, options?: NumberOptions) */ /** @deprecated Use bnToU8a(value?: ExtToBn | BN | bigint | number | null, options?: NumberOptions) */
function bnToU8a <ExtToBn extends ToBn> (value?: ExtToBn | BN | bigint | number | null, arg1: number | NumberOptions = DEFAULT_OPTS, arg2?: boolean): Uint8Array { function bnToU8a <ExtToBn extends ToBn> (value?: ExtToBn | BN | bigint | number | null, arg1: number | NumberOptions = DEFAULT_OPTS, arg2 = true): Uint8Array {
const { bitLength, isLe, isNegative }: NumberOptions = objectSpread( const { bitLength = -1, isLe = true, isNegative = false } = isNumber(arg1)
{ bitLength: -1, isLe: true, isNegative: false }, ? { bitLength: arg1, isLe: arg2 }
isNumber(arg1) : arg1;
? { bitLength: arg1, isLe: arg2 }
: arg1
);
const valueBn = bnToBn(value); const valueBn = bnToBn(value);
const byteLength = bitLength === -1 const byteLength = bitLength === -1
+1
View File
@@ -20,6 +20,7 @@ export * from './is';
export * from './lazy'; export * from './lazy';
export * from './logger'; export * from './logger';
export * from './memoize'; export * from './memoize';
export * from './nextTick';
export * from './number'; export * from './number';
export * from './object'; export * from './object';
export * from './promisify'; export * from './promisify';
+1
View File
@@ -3,4 +3,5 @@
import type { BitLength } from './types'; import type { BitLength } from './types';
/** @internal */
export const DEFAULT_BITLENGTH: BitLength = 32; export const DEFAULT_BITLENGTH: BitLength = 32;
+45 -43
View File
@@ -30,35 +30,38 @@ export function compactFromU8a (input: U8aLike): [number, BN] {
return [1, new BN(u8a[0] >>> 2)]; return [1, new BN(u8a[0] >>> 2)];
case 0b01: case 0b01:
return [2, new BN((u8a[0] + (u8a[1] * 0x1_00)) >>> 2)]; return [2, new BN((u8a[0] + (u8a[1] << 8)) >>> 2)];
case 0b10: case 0b10:
return [4, new BN((u8a[0] + (u8a[1] * 0x1_00) + (u8a[2] * 0x1_00_00) + (u8a[3] * 0x1_00_00_00)) >>> 2)]; // for the 3rd byte, we don't << 24 - since JS converts all bitwise operators to
// 32-bit, in the case where the top-most bit is set this yields a negative value
return [4, new BN((u8a[0] + (u8a[1] << 8) + (u8a[2] << 16) + (u8a[3] * 0x1_00_00_00)) >>> 2)];
// 0b11 // 0b11
default: default: {
break; // add 5 to shifted (4 for base length, 1 for this byte)
} const offset = (u8a[0] >>> 2) + 5;
// add 5 to shifted (4 for base length, 1 for this byte) // we unroll the loop
const offset = (u8a[0] >>> 2) + 5; switch (offset) {
// there still could be 4 bytes data, similar to 0b10 above (with offsets)
case 5:
// for the 3rd byte, we don't << 24 - since JS converts all bitwise operators to
// 32-bit, in the case where the top-most bit is set this yields a negative value
return [5, new BN(u8a[1] + (u8a[2] << 8) + (u8a[3] << 16) + (u8a[4] * 0x1_00_00_00))];
// we unroll the loop case 6:
switch (offset) { return [6, new BN(u8a[1] + (u8a[2] << 8) + (u8a[3] << 16) + ((u8a[4] + (u8a[5] << 8)) * 0x1_00_00_00))];
// there still could be 4 bytes data, similar to 0b10 above (with offsets)
case 5:
return [5, new BN(u8a[1] + (u8a[2] * 0x1_00) + (u8a[3] * 0x1_00_00) + (u8a[4] * 0x1_00_00_00))];
case 6: // 6 bytes data is the maximum, 48 bits (56 would overflow)
return [6, new BN(u8a[1] + (u8a[2] * 0x1_00) + (u8a[3] * 0x1_00_00) + (u8a[4] * 0x1_00_00_00) + (u8a[5] * 0x1_00_00_00_00))]; case 7:
return [7, new BN(u8a[1] + (u8a[2] << 8) + (u8a[3] << 16) + ((u8a[4] + (u8a[5] << 8) + (u8a[6] << 16)) * 0x1_00_00_00))];
// 6 bytes data is the maximum, 48 bits (56 would overflow) // for anything else, use the non-unrolled version
case 7: default:
return [7, new BN(u8a[1] + (u8a[2] * 0x1_00) + (u8a[3] * 0x1_00_00) + (u8a[4] * 0x1_00_00_00) + (u8a[5] * 0x1_00_00_00_00) + (u8a[6] * 0x1_00_00_00_00_00))]; return [offset, u8aToBn(u8a.subarray(1, offset))];
}
// for anything else, use the non-unrolled version }
default:
return [offset, u8aToBn(u8a.subarray(1, offset))];
} }
} }
@@ -74,34 +77,33 @@ export function compactFromU8aLim (u8a: Uint8Array): [number, number] {
return [1, u8a[0] >>> 2]; return [1, u8a[0] >>> 2];
case 0b01: case 0b01:
return [2, (u8a[0] + (u8a[1] * 0x1_00)) >>> 2]; return [2, (u8a[0] + (u8a[1] << 8)) >>> 2];
case 0b10: case 0b10:
return [4, (u8a[0] + (u8a[1] * 0x1_00) + (u8a[2] * 0x1_00_00) + (u8a[3] * 0x1_00_00_00)) >>> 2]; // for the 3rd byte, we don't << 24 - since JS converts all bitwise operators to
// 32-bit, in the case where the top-most bit is set this yields a negative value
return [4, (u8a[0] + (u8a[1] << 8) + (u8a[2] << 16) + (u8a[3] * 0x1_00_00_00)) >>> 2];
// 0b11 // 0b11
default: default: {
break; // add 5 to shifted (4 for base length, 1 for this byte)
} // we unroll the loop
switch ((u8a[0] >>> 2) + 5) {
// there still could be 4 bytes data, similar to 0b10 above (with offsets)
case 5:
return [5, u8a[1] + (u8a[2] << 8) + (u8a[3] << 16) + (u8a[4] * 0x1_00_00_00)];
// add 5 to shifted (4 for base length, 1 for this byte) case 6:
const offset = (u8a[0] >>> 2) + 5; return [6, u8a[1] + (u8a[2] << 8) + (u8a[3] << 16) + ((u8a[4] + (u8a[5] << 8)) * 0x1_00_00_00)];
// we unroll the loop // 6 bytes data is the maximum, 48 bits (56 would overflow)
switch (offset) { case 7:
// there still could be 4 bytes data, similar to 0b10 above (with offsets) return [7, u8a[1] + (u8a[2] << 8) + (u8a[3] << 16) + ((u8a[4] + (u8a[5] << 8) + (u8a[6] << 16)) * 0x1_00_00_00)];
case 5:
return [5, u8a[1] + (u8a[2] * 0x1_00) + (u8a[3] * 0x1_00_00) + (u8a[4] * 0x1_00_00_00)];
case 6: // for anything else, we are above the actual MAX_SAFE_INTEGER - bail out
return [6, u8a[1] + (u8a[2] * 0x1_00) + (u8a[3] * 0x1_00_00) + (u8a[4] * 0x1_00_00_00) + (u8a[5] * 0x1_00_00_00_00)]; default:
throw new Error('Compact input is > Number.MAX_SAFE_INTEGER');
// 6 bytes data is the maximum, 48 bits (56 would overflow) }
case 7: }
return [7, u8a[1] + (u8a[2] * 0x1_00) + (u8a[3] * 0x1_00_00) + (u8a[4] * 0x1_00_00_00) + (u8a[5] * 0x1_00_00_00_00) + (u8a[6] * 0x1_00_00_00_00_00)];
// for anything else, use the non-unrolled version
default:
throw new Error('Compact input is > Number.MAX_SAFE_INTEGER');
} }
} }
+3 -2
View File
@@ -1,7 +1,6 @@
// Copyright 2017-2022 @polkadot/util authors & contributors // Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { assert } from '../assert';
import { BN, BN_ONE, BN_TWO, bnToBn, bnToU8a } from '../bn'; import { BN, BN_ONE, BN_TWO, bnToBn, bnToU8a } from '../bn';
import { u8aConcatStrict } from '../u8a'; import { u8aConcatStrict } from '../u8a';
@@ -42,7 +41,9 @@ export function compactToU8a (value: BN | bigint | number): Uint8Array {
length--; length--;
} }
assert(length >= 4, 'Invalid length, previous checks match anything less than 2^30'); if (length < 4) {
throw new Error('Invalid length, previous checks match anything less than 2^30');
}
return u8aConcatStrict([ return u8aConcatStrict([
// subtract 4 as minimum (also catered for in decoding) // subtract 4 as minimum (also catered for in decoding)
+28 -44
View File
@@ -3,67 +3,51 @@
import type { Time } from './types'; import type { Time } from './types';
import { objectSpread } from './object/spread'; const MIN_MS = 60 * 1000;
const HR_MS = MIN_MS * 60;
const HRS = 60 * 60; const DAY_MS = HR_MS * 24;
const DAY = HRS * 24;
const ZERO: Time = { days: 0, hours: 0, milliseconds: 0, minutes: 0, seconds: 0 }; const ZERO: Time = { days: 0, hours: 0, milliseconds: 0, minutes: 0, seconds: 0 };
/** /** @internal */
* @name addTime function add (a: Partial<Time>, b: Time): Time {
* @summary Add together two Time arrays
*/
function addTime (a: Time, b: Time): Time {
return { return {
days: a.days + b.days, days: (a.days || 0) + b.days,
hours: a.hours + b.hours, hours: (a.hours || 0) + b.hours,
milliseconds: a.milliseconds + b.milliseconds, milliseconds: (a.milliseconds || 0) + b.milliseconds,
minutes: a.minutes + b.minutes, minutes: (a.minutes || 0) + b.minutes,
seconds: a.seconds + b.seconds seconds: (a.seconds || 0) + b.seconds
}; };
} }
function extractDays (milliseconds: number, hrs: number): Time { /** @internal */
const days = Math.floor(hrs / 24); function extractSecs (ms: number): Time {
const s = ms / 1000;
return addTime(objectSpread({}, ZERO, { days }), extractTime(milliseconds - (days * DAY * 1000))); if (s < 60) {
} const seconds = ~~s;
function extractHrs (milliseconds: number, mins: number): Time { return add({ seconds }, extractTime(ms - (seconds * 1000)));
const hrs = mins / 60;
if (hrs < 24) {
const hours = Math.floor(hrs);
return addTime(objectSpread({}, ZERO, { hours }), extractTime(milliseconds - (hours * HRS * 1000)));
} }
return extractDays(milliseconds, hrs); const m = s / 60;
}
function extractMins (milliseconds: number, secs: number): Time { if (m < 60) {
const mins = secs / 60; const minutes = ~~m;
if (mins < 60) { return add({ minutes }, extractTime(ms - (minutes * MIN_MS)));
const minutes = Math.floor(mins);
return addTime(objectSpread({}, ZERO, { minutes }), extractTime(milliseconds - (minutes * 60 * 1000)));
} }
return extractHrs(milliseconds, mins); const h = m / 60;
}
function extractSecs (milliseconds: number): Time { if (h < 24) {
const secs = milliseconds / 1000; const hours = ~~h;
if (secs < 60) { return add({ hours }, extractTime(ms - (hours * HR_MS)));
const seconds = Math.floor(secs);
return addTime(objectSpread({}, ZERO, { seconds }), extractTime(milliseconds - (seconds * 1000)));
} }
return extractMins(milliseconds, secs); const days = ~~(h / 24);
return add({ days }, extractTime(ms - (days * DAY_MS)));
} }
/** /**
@@ -82,6 +66,6 @@ export function extractTime (milliseconds?: number): Time {
return !milliseconds return !milliseconds
? ZERO ? ZERO
: milliseconds < 1000 : milliseconds < 1000
? objectSpread({}, ZERO, { milliseconds }) ? add({ milliseconds }, ZERO)
: extractSecs(milliseconds); : extractSecs(milliseconds);
} }
+4
View File
@@ -6,6 +6,10 @@ function zeroPad (value: number): string {
return value.toString().padStart(2, '0'); return value.toString().padStart(2, '0');
} }
/**
* @name formatDate
* @description Formats a date in CCYY-MM-DD HH:MM:SS format
*/
export function formatDate (date: Date): string { export function formatDate (date: Date): string {
const year = date.getFullYear().toString(); const year = date.getFullYear().toString();
const month = zeroPad((date.getMonth() + 1)); const month = zeroPad((date.getMonth() + 1));
@@ -4,6 +4,10 @@
// eslint-disable-next-line prefer-regex-literals // 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');
/**
* @name formatDecimal
* @description Formats a number into string format with thousand seperators
*/
export function formatDecimal (value: string): string { export function formatDecimal (value: string): string {
// We can do this by adjusting the regx, however for the sake of clarity // We can do this by adjusting the regx, however for the sake of clarity
// we rather strip and re-add the negative sign in the output // we rather strip and re-add the negative sign in the output
@@ -6,6 +6,7 @@ import type { ToBn } from '../types';
import { bnToBn } from '../bn/toBn'; import { bnToBn } from '../bn/toBn';
/** @internal */
function formatValue (elapsed: number): string { function formatValue (elapsed: number): string {
if (elapsed < 15) { if (elapsed < 15) {
return `${elapsed.toFixed(1)}s`; return `${elapsed.toFixed(1)}s`;
@@ -18,6 +19,10 @@ function formatValue (elapsed: number): string {
return `${elapsed / 3600 | 0}h`; return `${elapsed / 3600 | 0}h`;
} }
/**
* @name formatElapsed
* @description Formats an elapsed value into s, m, h or day segments
*/
export function formatElapsed <ExtToBn extends ToBn> (now?: Date | null, value?: bigint | BN | ExtToBn | Date | number | null): string { export function formatElapsed <ExtToBn extends ToBn> (now?: Date | null, value?: bigint | BN | ExtToBn | Date | number | null): string {
const tsNow = (now && now.getTime()) || 0; const tsNow = (now && now.getTime()) || 0;
const tsValue = value instanceof Date const tsValue = value instanceof Date
+4
View File
@@ -7,6 +7,10 @@ import type { ToBn } from '../types';
import { bnToBn } from '../bn/toBn'; import { bnToBn } from '../bn/toBn';
import { formatDecimal } from './formatDecimal'; import { formatDecimal } from './formatDecimal';
/**
* @name formatNumber
* @description Formats a number into string format with thousand seperators
*/
export function formatNumber <ExtToBn extends ToBn> (value?: ExtToBn | BN | bigint | number | null): string { export function formatNumber <ExtToBn extends ToBn> (value?: ExtToBn | BN | bigint | number | null): string {
return formatDecimal(bnToBn(value).toString()); return formatDecimal(bnToBn(value).toString());
} }
+4
View File
@@ -3,8 +3,10 @@
import type { SiDef } from '../types'; import type { SiDef } from '../types';
/** @internal */
export const SI_MID = 8; export const SI_MID = 8;
/** @internal */
export const SI: SiDef[] = [ export const SI: SiDef[] = [
{ power: -24, text: 'yocto', value: 'y' }, { power: -24, text: 'yocto', value: 'y' },
{ power: -21, text: 'zepto', value: 'z' }, { power: -21, text: 'zepto', value: 'z' },
@@ -26,6 +28,7 @@ export const SI: SiDef[] = [
]; ];
// Given a SI type (e.g. k, m, Y) find the SI definition // Given a SI type (e.g. k, m, Y) find the SI definition
/** @internal */
export function findSi (type: string): SiDef { export function findSi (type: string): SiDef {
// use a loop here, better RN support (which doesn't have [].find) // use a loop here, better RN support (which doesn't have [].find)
for (let i = 0; i < SI.length; i++) { for (let i = 0; i < SI.length; i++) {
@@ -37,6 +40,7 @@ export function findSi (type: string): SiDef {
return SI[SI_MID]; return SI[SI_MID];
} }
/** @internal */
export function calcSi (text: string, decimals: number, forceUnit?: string): SiDef { export function calcSi (text: string, decimals: number, forceUnit?: string): SiDef {
if (forceUnit) { if (forceUnit) {
return findSi(forceUnit); return findSi(forceUnit);
+13
View File
@@ -3,10 +3,23 @@
import { BigInt } from '@polkadot/x-bigint'; import { BigInt } from '@polkadot/x-bigint';
/** true if the environment has proper BigInt support */
export const hasBigInt = typeof BigInt === 'function' && typeof BigInt.asIntN === 'function'; export const hasBigInt = typeof BigInt === 'function' && typeof BigInt.asIntN === 'function';
/** true if the environment has support for Buffer */
export const hasBuffer = typeof Buffer !== 'undefined'; export const hasBuffer = typeof Buffer !== 'undefined';
/** true if the environment is CJS */
export const hasCjs = typeof require === 'function' && typeof module !== 'undefined'; export const hasCjs = typeof require === 'function' && typeof module !== 'undefined';
/** true if the environment has __dirname available */
export const hasDirname = typeof __dirname !== 'undefined'; export const hasDirname = typeof __dirname !== 'undefined';
/** true if the environment is ESM */
export const hasEsm = !hasCjs; export const hasEsm = !hasCjs;
/** true if the environment has process available (typically Node.js) */
export const hasProcess = typeof process === 'object'; export const hasProcess = typeof process === 'object';
/** true if the environment has WebAssembly available */
export const hasWasm = typeof WebAssembly !== 'undefined'; export const hasWasm = typeof WebAssembly !== 'undefined';
-27
View File
@@ -1,27 +0,0 @@
// Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
const U8_TO_HEX = new Array<string>(256);
const U16_TO_HEX = new Array<string>(256 * 256);
const HEX_TO_U8: Record<string, number> = {};
const HEX_TO_U16: Record<string, number> = {};
for (let n = 0; n < 256; n++) {
const hex = n.toString(16).padStart(2, '0');
U8_TO_HEX[n] = hex;
HEX_TO_U8[hex] = n;
}
for (let i = 0; i < 256; i++) {
for (let j = 0; j < 256; j++) {
const hex = U8_TO_HEX[i] + U8_TO_HEX[j];
const n = (i << 8) | j;
U16_TO_HEX[n] = hex;
HEX_TO_U16[hex] = n;
}
}
export { HEX_TO_U16, HEX_TO_U8, U16_TO_HEX, U8_TO_HEX };
+3 -7
View File
@@ -5,7 +5,6 @@ import type { ToBnOptions } from '../types';
import { BN } from '../bn/bn'; import { BN } from '../bn/bn';
import { isBoolean } from '../is/boolean'; import { isBoolean } from '../is/boolean';
import { objectSpread } from '../object/spread';
import { hexStripPrefix } from './stripPrefix'; import { hexStripPrefix } from './stripPrefix';
/** /**
@@ -36,12 +35,9 @@ function hexToBn (value?: string | null, options: ToBnOptions | boolean = {}): B
} }
// For hex, default to BE // For hex, default to BE
const { isLe, isNegative } = objectSpread<ToBnOptions>( const { isLe = false, isNegative = false } = isBoolean(options)
{ isLe: false, isNegative: false }, ? { isLe: options }
isBoolean(options) : options;
? { isLe: options }
: options
);
const stripped = hexStripPrefix(value); const stripped = hexStripPrefix(value);
const bn = new BN(stripped, 16, isLe ? 'le' : 'be'); const bn = new BN(stripped, 16, isLe ? 'le' : 'be');
+3 -4
View File
@@ -2,14 +2,13 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { performanceCmp } from '../test/performance'; import { performanceCmp } from '../test/performance';
import { U16_TO_HEX } from './alphabet';
import { hexToU8a as hexToU8aBuffer } from './toU8aBuffer'; import { hexToU8a as hexToU8aBuffer } from './toU8aBuffer';
import { hexToU8a } from '.'; import { hexToU8a } from '.';
let ptest = '0x'; let ptest = '0x';
for (let i = 0; i < 500000; i++) { for (let i = 0; i < 1_000_000; i++) {
ptest += U16_TO_HEX[i % (256 * 256)]; ptest += (i % 256).toString(16);
} }
describe('hexToU8a', (): void => { describe('hexToU8a', (): void => {
@@ -55,7 +54,7 @@ describe('hexToU8a', (): void => {
).toThrow(/hex value to convert/); ).toThrow(/hex value to convert/);
}); });
performanceCmp('hexToU8a', ['hexToU8aBuffer', 'hexToU8a'], 10, [[ptest]], (s: string, isSecond) => performanceCmp('hexToU8a', ['hexToU8aBuffer', 'hexToU8a'], 20, [[ptest]], (s: string, isSecond) =>
isSecond isSecond
? hexToU8a(s) ? hexToU8a(s)
: hexToU8aBuffer(s) : hexToU8aBuffer(s)
+24 -19
View File
@@ -3,9 +3,19 @@
import type { HexString } from '../types'; import type { HexString } from '../types';
import { HEX_TO_U8, HEX_TO_U16 } from './alphabet';
import { hexStripPrefix } from './stripPrefix'; import { hexStripPrefix } from './stripPrefix';
const CHARS = '0123456789abcdef';
const UNHEX = new Array<number>(256);
for (let i = 0; i < CHARS.length; i++) {
UNHEX[CHARS[i].charCodeAt(0)] = i;
if (i > 9) {
UNHEX[CHARS[i].toUpperCase().charCodeAt(0)] = i;
}
}
/** /**
* @name hexToU8a * @name hexToU8a
* @summary Creates a Uint8Array object from a hex string. * @summary Creates a Uint8Array object from a hex string.
@@ -21,34 +31,29 @@ import { hexStripPrefix } from './stripPrefix';
* hexToU8a('0x80001f', 32); // Uint8Array([0x00, 0x80, 0x00, 0x1f]) * hexToU8a('0x80001f', 32); // Uint8Array([0x00, 0x80, 0x00, 0x1f])
* ``` * ```
*/ */
export function hexToU8a (_value?: HexString | string | null, bitLength = -1): Uint8Array { export function hexToU8a (value?: HexString | string | null, bitLength = -1): Uint8Array {
if (!_value) { if (!value) {
return new Uint8Array(); return new Uint8Array();
} }
const value = hexStripPrefix(_value).toLowerCase(); const str = hexStripPrefix(value);
const valLength = value.length / 2; const strLength = str.length / 2;
const endLength = Math.ceil( const endLength = Math.ceil(
bitLength === -1 bitLength === -1
? valLength ? strLength
: bitLength / 8 : bitLength / 8
); );
const result = new Uint8Array(endLength); const result = new Uint8Array(endLength);
const offset = endLength > valLength const offset = endLength > strLength
? endLength - valLength ? endLength - strLength
: 0; : 0;
const dv = new DataView(result.buffer, offset);
const mod = (endLength - offset) % 2;
const length = endLength - offset - mod;
for (let i = 0; i < length; i += 2) { for (let i = offset, s = 0; i < endLength; i++, s += 2) {
const idx = i * 2; // The big factor here is actually the string lookups. If we do
// HEX_TO_U16[value.substring()] we get an 10x slowdown. In the
dv.setUint16(i, HEX_TO_U16[value.substring(idx, idx + 4)]); // same vein using charCodeAt (as opposed to value[s] or value.charAt(s)) is
} // also the faster operation by at least 2x with the character map above
result[i] = ((UNHEX[str.charCodeAt(s)] << 4) + UNHEX[str.charCodeAt(s + 1)]) | 0;
if (mod) {
dv.setUint8(length, HEX_TO_U8[value.substring(value.length - 2)]);
} }
return result; return result;
+3
View File
@@ -1,6 +1,7 @@
// Copyright 2017-2022 @polkadot/util authors & contributors // Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { performance } from '../test/performance';
import { isAscii } from '.'; import { isAscii } from '.';
describe('isAscii', (): void => { describe('isAscii', (): void => {
@@ -35,4 +36,6 @@ describe('isAscii', (): void => {
it('returns false for hex input, non-ascii', (): void => { it('returns false for hex input, non-ascii', (): void => {
expect(isAscii('0x010203')).toEqual(false); expect(isAscii('0x010203')).toEqual(false);
}); });
performance('isAscii', 100_000, [[[0x31, 0x32, 0x20, 10, 9, 13, 65, 66, 67, 68, 69, 70]]], isAscii);
}); });
+33 -19
View File
@@ -1,24 +1,42 @@
// Copyright 2017-2022 @polkadot/util authors & contributors // Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import type { U8aLike } from '../types'; import type { AnyString, U8aLike } from '../types';
import { u8aToU8a } from '../u8a/toU8a'; import { u8aToU8a } from '../u8a/toU8a';
import { isHex } from './hex'; import { isHex } from './hex';
import { isString } from './string'; import { isString } from './string';
const FORMAT = [9, 10, 13];
/** @internal */ /** @internal */
function isAsciiByte (b: number): boolean { function isAsciiStr (str: AnyString): boolean {
return (b < 127) && ( const count = str.length;
(b >= 32) ||
FORMAT.includes(b) for (let i = 0; i < count; i++) {
); const b = str.charCodeAt(i);
// check is inlined here, it is faster than making a call
if (!((b < 127) && ((b >= 32) || (b === 10) || (b === 9) || (b === 13)))) {
return false;
}
}
return true;
} }
function isAsciiChar (s: string): boolean { /** @internal */
return isAsciiByte(s.charCodeAt(0)); function isAsciiU8a (u8a: Uint8Array): boolean {
const count = u8a.length;
for (let i = 0; i < count; i++) {
const b = u8a[i];
// check is inlined here, it is faster than making a call
if (!((b < 127) && ((b >= 32) || (b === 10) || (b === 9) || (b === 13)))) {
return false;
}
}
return true;
} }
/** /**
@@ -28,13 +46,9 @@ function isAsciiChar (s: string): boolean {
* Checks to see if the input string or Uint8Array is printable ASCII, 32-127 + formatters * Checks to see if the input string or Uint8Array is printable ASCII, 32-127 + formatters
*/ */
export function isAscii (value?: U8aLike | null): boolean { export function isAscii (value?: U8aLike | null): boolean {
const isStringIn = isString(value); return isString(value) && !isHex(value)
? isAsciiStr(value)
if (value) { : value
return isStringIn && !isHex(value) ? isAsciiU8a(u8aToU8a(value))
? value.toString().split('').every(isAsciiChar) : false;
: u8aToU8a(value).every(isAsciiByte);
}
return isStringIn;
} }
+15
View File
@@ -1,8 +1,17 @@
// Copyright 2017-2022 @polkadot/util authors & contributors // Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { performanceCmp } from '../test/performance';
import { isCodec } from '.'; import { isCodec } from '.';
const ptest = {
registry: {
get: () => null
},
toHex: () => '0x',
toU8a: () => new Uint8Array()
};
describe('isCodec', (): void => { describe('isCodec', (): void => {
it('is false on no value', (): void => { it('is false on no value', (): void => {
expect(isCodec()).toEqual(false); expect(isCodec()).toEqual(false);
@@ -37,4 +46,10 @@ describe('isCodec', (): void => {
}) })
).toEqual(false); ).toEqual(false);
}); });
performanceCmp('isCodec', ['isCodec', 'instanceof'], 500_000, [[ptest]], (v: unknown, isSecond) =>
isSecond
? !(v instanceof String)
: isCodec(v)
);
}); });
+10
View File
@@ -7,6 +7,11 @@ type AnyFn = (...args: unknown[]) => unknown;
type WithToString = { toString: () => string }; type WithToString = { toString: () => string };
/**
* @name lazyMethod
* @description
* Creates a lazy, on-demand getter for the specific value. Upon get the value will be evaluated.
*/
export function lazyMethod <T, K> (result: Record<string, T> | AnyFn, item: K, creator: (d: K) => T, getName?: (d: K) => string): void { export function lazyMethod <T, K> (result: Record<string, T> | AnyFn, item: K, creator: (d: K) => T, getName?: (d: K) => string): void {
const name = getName const name = getName
? getName(item) ? getName(item)
@@ -46,6 +51,11 @@ export function lazyMethod <T, K> (result: Record<string, T> | AnyFn, item: K, c
}); });
} }
/**
* @name lazyMethods
* @description
* Creates lazy, on-demand getters for the specific values.
*/
export function lazyMethods <T, K> (result: Record<string, T>, items: K[], creator: (v: K) => T, getName?: (m: K) => string): Record<string, T> { export function lazyMethods <T, K> (result: Record<string, T>, items: K[], creator: (v: K) => T, getName?: (m: K) => string): Record<string, T> {
for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {
lazyMethod(result, items[i], creator, getName); lazyMethod(result, items[i], creator, getName);
+4
View File
@@ -14,6 +14,10 @@ function defaultGetId (): string {
return 'none'; return 'none';
} }
/**
* @name memoize
* @description Memomize the function with a specific instanceId
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
export function memoize <T, F extends (...args: any[]) => T> (fn: F, { getInstanceId = defaultGetId }: Options = {}): Memoized<F> { export function memoize <T, F extends (...args: any[]) => T> (fn: F, { getInstanceId = defaultGetId }: Options = {}): Memoized<F> {
const cache: Record<string, Record<string, T>> = {}; const cache: Record<string, Record<string, T>> = {};
+21
View File
@@ -0,0 +1,21 @@
// Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
/**
* @name nextTick
* @description Defer the operation to the queue for evaluation on the next tick
*/
export function nextTick (onExec: () => unknown, onError?: (error: Error) => unknown): void {
Promise
.resolve()
.then((): void => {
onExec();
})
.catch((error): void => {
if (onError) {
onError(error as Error);
} else {
console.error(error);
}
});
}
+28 -1
View File
@@ -1,6 +1,7 @@
// Copyright 2017-2022 @polkadot/util authors & contributors // Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { performance } from '../test/performance';
import { objectProperties, objectProperty } from '.'; import { objectProperties, objectProperty } from '.';
describe('objectProperty/objectProperties', (): void => { describe('objectProperty/objectProperties', (): void => {
@@ -11,10 +12,12 @@ describe('objectProperty/objectProperties', (): void => {
objectProperty(test, 'a', () => 2); objectProperty(test, 'a', () => 2);
expect(Object.prototype.hasOwnProperty.call(test, 'a')).toBe(true);
expect('a' in test).toEqual(true);
expect(test.a).toEqual(2); expect(test.a).toEqual(2);
}); });
it('does not override an existing property', (): void => { it('does not override an existing property (record)', (): void => {
const test: Record<string, unknown> = { a: 1 }; const test: Record<string, unknown> = { a: 1 };
expect(test.a).toEqual(1); expect(test.a).toEqual(1);
@@ -24,6 +27,27 @@ describe('objectProperty/objectProperties', (): void => {
expect(test.a).toEqual(1); expect(test.a).toEqual(1);
}); });
it('does not override an existing property (class)', (): void => {
class Test {
b = 1;
get a () {
return 1;
}
}
const test = new Test();
expect(test.a).toEqual(1);
expect(test.b).toEqual(1);
objectProperty(test, 'a', () => 2);
objectProperty(test, 'b', () => 2);
expect(test.a).toEqual(1);
expect(test.b).toEqual(1);
});
it('does not override an existing property (inherited)', (): void => { it('does not override an existing property (inherited)', (): void => {
class Parent extends Map<string, unknown> { class Parent extends Map<string, unknown> {
constructor () { constructor () {
@@ -117,4 +141,7 @@ describe('objectProperty/objectProperties', (): void => {
expect(test.b).toEqual(123); expect(test.b).toEqual(123);
expect(getter).toHaveBeenCalledWith('b', 1); expect(getter).toHaveBeenCalledWith('b', 1);
}); });
performance('objectProperties (obj)', 50_000, [[]], () => objectProperties({}, ['foo', 'bar', 'baz'], (k) => k));
performance('objectProperties (map)', 50_000, [[]], () => objectProperties(new Map(), ['foo', 'bar', 'baz'], (k) => k));
}); });
+7 -6
View File
@@ -1,19 +1,20 @@
// Copyright 2017-2022 @polkadot/util authors & contributors // Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { isUndefined } from '../is/undefined';
/** /**
* @name objectProperty * @name objectProperty
* @summary Assign a get property on the input object * @summary Assign a get property on the input object
*/ */
export function objectProperty (that: object, key: string, getter: (k: string) => unknown): void { export function objectProperty (that: object, key: string, getter: (k: string) => unknown): void {
// We use both the hasOwnProperty as well as isUndefined checks here, since it may be set // There are 3 approaches here -
// in inherited classes and _Own_ properties refers to the class only, not only parents // - Object.prototype.hasOwnProperty.call(that, key) - this only checks the current class, i.e
if (!Object.prototype.hasOwnProperty.call(that, key) && isUndefined((that as Record<string, unknown>)[key])) { // will retuirn false if the property is set in the parent class
// - isUndefined(...) - this may yield a false positive when the property is there, but not set.
// Additionally, on pre-defined getters it may make a call
// - key in that - Does not need to be combined with either of the above and checks the full chain
if (!(key in that)) {
Object.defineProperty(that, key, { Object.defineProperty(that, key, {
enumerable: true, enumerable: true,
// Since we don't use any additional this internally, we can use arrow (unlike lazy)
// Unlike in lazy, we always call into the upper function, i.e. this method // Unlike in lazy, we always call into the upper function, i.e. this method
// does not cache old values (it is expected to be used for dynamic values) // does not cache old values (it is expected to be used for dynamic values)
get: () => getter(key) get: () => getter(key)
+3
View File
@@ -1,6 +1,7 @@
// Copyright 2017-2022 @polkadot/util authors & contributors // Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { performance } from '../test/performance';
import { objectSpread } from '.'; import { objectSpread } from '.';
describe('objectSpread', (): void => { describe('objectSpread', (): void => {
@@ -15,4 +16,6 @@ describe('objectSpread', (): void => {
objectSpread({ a: 1 }, null, { b: 2 }, undefined, { a: 2, c: { d: 3, e: 4 } }) objectSpread({ a: 1 }, null, { b: 2 }, undefined, { a: 2, c: { d: 3, e: 4 } })
).toEqual({ a: 2, b: 2, c: { d: 3, e: 4 } }); ).toEqual({ a: 2, b: 2, c: { d: 3, e: 4 } });
}); });
performance('objectSpread', 500_000, [[]], () => objectSpread({}, { a: 1, b: 2, c: 3 }, { d: 4, e: 7, f: 6 }));
}); });
+1 -9
View File
@@ -1,8 +1,6 @@
// Copyright 2017-2022 @polkadot/util authors & contributors // Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { objectKeys } from './keys';
/** /**
* @name objectSpread * @name objectSpread
* @summary Concats all sources into the destination * @summary Concats all sources into the destination
@@ -12,13 +10,7 @@ export function objectSpread <T extends object> (dest: object, ...sources: (obje
const src = sources[i]; const src = sources[i];
if (src) { if (src) {
const keys = objectKeys(src); Object.assign(dest, src);
for (let j = 0; j < keys.length; j++) {
const key = keys[j];
dest[key] = src[key];
}
} }
} }
+1 -1
View File
@@ -3,4 +3,4 @@
// Do not edit, auto-generated by @polkadot/dev // Do not edit, auto-generated by @polkadot/dev
export const packageInfo = { name: '@polkadot/util', path: 'auto', type: 'auto', version: '9.3.1' }; export const packageInfo = { name: '@polkadot/util', path: 'auto', type: 'auto', version: '9.5.1' };
+5 -1
View File
@@ -53,6 +53,9 @@ describe('stringCamelCase', (): void => {
expect( expect(
stringCamelCase('DEDUP_KEY_PREFIX') stringCamelCase('DEDUP_KEY_PREFIX')
).toEqual('dedupKeyPrefix'); ).toEqual('dedupKeyPrefix');
expect(
stringCamelCase(String('DEDUP_KEY_PREFIX'))
).toEqual('dedupKeyPrefix');
expect( expect(
stringCamelCase('SOMETHING') stringCamelCase('SOMETHING')
).toEqual('something'); ).toEqual('something');
@@ -109,5 +112,6 @@ describe('stringCamelCase', (): void => {
).toEqual('aBCDef'); ).toEqual('aBCDef');
}); });
performance('stringCamelCase', 100_000, randomWords, stringCamelCase); performance('stringCamelCase (random)', 100_000, randomWords, stringCamelCase);
performance('stringCamelCase (NFTOrder)', 100_000, [['NFTOrder']], stringCamelCase);
}); });
+33 -18
View File
@@ -3,41 +3,56 @@
import type { AnyString } from '../types'; import type { AnyString } from '../types';
// Inspired from https://stackoverflow.com/a/2970667 export const CC_TO_UP = new Array<string>(256);
// export const CC_TO_LO = new Array<string>(256);
// this is not as optimal as the original answer (we split into multiple),
// however it does pass the tests (which the original doesn't) and it is still
// a major improvement over the original camelcase npm package (at running)
//
// original: 20.88 μs/op
// this: 1.20 μs/op
//
// Caveat of this: only Ascii, but acceptable for the intended usecase
function converter (format: (w: string, i: number) => string): (value: AnyString) => string {
const formatRuns = (w: string) => w.slice(0, w.length - 1).toLowerCase() + w.slice(-1).toUpperCase();
for (let i = 0; i < CC_TO_UP.length; i++) {
CC_TO_LO[i] = String.fromCharCode(i).toLowerCase();
CC_TO_UP[i] = String.fromCharCode(i).toUpperCase();
}
/** @internal */
function formatAllCaps (w: string): string {
return w.slice(0, w.length - 1).toLowerCase() + CC_TO_UP[w.charCodeAt(w.length - 1)];
}
/**
* @internal
*
* Inspired by https://stackoverflow.com/a/2970667
*
* This is not as optimal as the original SO answer (we split into per-word),
* however it does pass the tests (which the SO version doesn't) and is still
* a major improvement over the original camelcase npm package -
*
* camelcase: 20.88 μs/op
* this: 1.00 μs/op
*
* Caveat of this: only Ascii, but acceptable for the intended usecase
*/
function converter (format: (w: string, i: number) => string): (value: AnyString) => string {
return (value: AnyString): string => { return (value: AnyString): string => {
const parts = value const parts = value
.toString()
// replace all seperators (including consequtive) with spaces // replace all seperators (including consequtive) with spaces
.replace(/[-_., ]+/g, ' ') .replace(/[-_., ]+/g, ' ')
// we don't want leading or trailing spaces // we don't want leading or trailing spaces
.trim() .trim()
// split into words // split into words
.split(' '); .split(' ');
const count = parts.length;
let result = ''; let result = '';
for (let i = 0; i < parts.length; i++) { for (let i = 0; i < count; i++) {
const w = parts[i]; const w = parts[i];
// apply the formatting // apply the formatting
result += format( result += format(
w.toUpperCase() === w /^[\dA-Z]+$/.test(w)
// all full uppercase + letters are changed to lowercase // all full uppercase + letters are changed to lowercase
? w.toLowerCase() ? w.toLowerCase()
// all consecutive capitals + letters are changed to lowercase // all consecutive capitals + letters are changed to lowercase
// e.g. UUID64 -> uuid64, while preserving splits, eg. NFTOrder -> nftOrder // e.g. UUID64 -> uuid64, while preserving splits, eg. NFTOrder -> nftOrder
: w.replace(/^[A-Z0-9]{2,}[^a-z]/, formatRuns), : w.replace(/^[\dA-Z]{2,}[^a-z]/, formatAllCaps),
i i
); );
} }
@@ -52,7 +67,7 @@ function converter (format: (w: string, i: number) => string): (value: AnyString
*/ */
export const stringCamelCase = converter((w, i) => export const stringCamelCase = converter((w, i) =>
// lowercase for first letter/first word, else uppercase first, rest unchanged // lowercase for first letter/first word, else uppercase first, rest unchanged
(i ? w[0].toUpperCase() : w[0].toLowerCase()) + w.slice(1) (i ? CC_TO_UP[w.charCodeAt(0)] : CC_TO_LO[w.charCodeAt(0)]) + w.slice(1)
); );
/** /**
@@ -61,5 +76,5 @@ export const stringCamelCase = converter((w, i) =>
*/ */
export const stringPascalCase = converter((w) => export const stringPascalCase = converter((w) =>
// uppercase the first character, leave the rest unchanged // uppercase the first character, leave the rest unchanged
w[0].toUpperCase() + w.slice(1) CC_TO_UP[w.charCodeAt(0)] + w.slice(1)
); );
@@ -1,6 +1,7 @@
// Copyright 2017-2022 @polkadot/util authors & contributors // Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { performance } from '../test/performance';
import { stringLowerFirst } from '.'; import { stringLowerFirst } from '.';
describe('stringLowerFirst', (): void => { describe('stringLowerFirst', (): void => {
@@ -33,4 +34,6 @@ describe('stringLowerFirst', (): void => {
stringLowerFirst(null) stringLowerFirst(null)
).toBe(''); ).toBe('');
}); });
performance('stringLowerFirst', 1_000_000, [['HelloWorldSomething']], stringLowerFirst);
}); });
+7 -4
View File
@@ -3,10 +3,13 @@
import type { AnyString } from '../types'; import type { AnyString } from '../types';
function converter (fn: (value: string) => string): (value?: AnyString | null) => string { import { CC_TO_LO, CC_TO_UP } from './camelCase';
/** @internal */
function converter (map: string[]): (value?: AnyString | null) => string {
return (value?: AnyString | null): string => return (value?: AnyString | null): string =>
value value
? fn(value[0]) + value.slice(1) ? map[value.charCodeAt(0)] + value.slice(1)
: ''; : '';
} }
@@ -24,7 +27,7 @@ function converter (fn: (value: string) => string): (value?: AnyString | null) =
* stringLowerFirst('ABC'); // => 'aBC' * stringLowerFirst('ABC'); // => 'aBC'
* ``` * ```
*/ */
export const stringLowerFirst = converter((s) => s.toLowerCase()); export const stringLowerFirst = converter(CC_TO_LO);
/** /**
* @name stringUpperFirst * @name stringUpperFirst
@@ -40,4 +43,4 @@ export const stringLowerFirst = converter((s) => s.toLowerCase());
* stringUpperFirst('abc'); // => 'Abc' * stringUpperFirst('abc'); // => 'Abc'
* ``` * ```
*/ */
export const stringUpperFirst = converter((s) => s.toUpperCase()); export const stringUpperFirst = converter(CC_TO_UP);
@@ -1,6 +1,7 @@
// Copyright 2017-2022 @polkadot/util authors & contributors // Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { performance } from '../test/performance';
import { stringUpperFirst } from '.'; import { stringUpperFirst } from '.';
describe('stringUpperFirst', (): void => { describe('stringUpperFirst', (): void => {
@@ -33,4 +34,6 @@ describe('stringUpperFirst', (): void => {
stringUpperFirst(null) stringUpperFirst(null)
).toBe(''); ).toBe('');
}); });
performance('stringUpperFirst', 1_000_000, [['helloWorldSomething']], stringUpperFirst);
}); });
+1 -1
View File
@@ -40,7 +40,7 @@ export interface ToBnOptions {
*/ */
isLe?: boolean; isLe?: boolean;
/** /**
* @description Number is negative, apply two's complement * @description Number is signed, apply two's complement
*/ */
isNegative?: boolean; isNegative?: boolean;
} }
+16 -4
View File
@@ -4,10 +4,20 @@
import { performance } from '../test/performance'; import { performance } from '../test/performance';
import { u8aEq } from '.'; import { u8aEq } from '.';
const ptest = new Uint8Array(32768); const ltest = new Uint8Array(32768);
const stest = new Uint8Array(256);
const ztest = new Uint8Array(64);
for (let i = 0; i < ptest.length; i++) { for (let i = 0; i < ltest.length; i++) {
ptest[i] = i % 256; if (i < ztest.length) {
ztest[i] = i % 256;
}
if (i < stest.length) {
stest[i] = i % 256;
}
ltest[i] = i % 256;
} }
describe('u8aEq', (): void => { describe('u8aEq', (): void => {
@@ -95,5 +105,7 @@ describe('u8aEq', (): void => {
).toEqual(true); ).toEqual(true);
}); });
performance('u8aEq (32k cmp)', 50000, [[ptest, ptest]], u8aEq); performance('u8aEq (64 cmp)', 200_000, [[ztest, ztest]], u8aEq);
performance('u8aEq (256 cmp)', 200_000, [[stest, stest]], u8aEq);
performance('u8aEq (32k cmp)', 10_000, [[ltest, ltest]], u8aEq);
}); });
+1
View File
@@ -15,6 +15,7 @@ export { u8aToBigInt } from './toBigInt';
export { u8aToBn } from './toBn'; export { u8aToBn } from './toBn';
export { u8aToBuffer } from './toBuffer'; export { u8aToBuffer } from './toBuffer';
export { u8aToHex } from './toHex'; export { u8aToHex } from './toHex';
export { u8aToNumber } from './toNumber';
export { u8aToString } from './toString'; export { u8aToString } from './toString';
export { u8aToU8a } from './toU8a'; export { u8aToU8a } from './toU8a';
export { U8A_WRAP_ETHEREUM, U8A_WRAP_POSTFIX, U8A_WRAP_PREFIX, u8aIsWrapped, u8aWrapBytes, u8aUnwrapBytes } from './wrap'; export { U8A_WRAP_ETHEREUM, U8A_WRAP_POSTFIX, U8A_WRAP_PREFIX, u8aIsWrapped, u8aWrapBytes, u8aUnwrapBytes } from './wrap';
+29 -42
View File
@@ -6,61 +6,48 @@ import type { ToBnOptions } from '../types';
import { BigInt } from '@polkadot/x-bigint'; import { BigInt } from '@polkadot/x-bigint';
import { _1n } from '../bi/consts'; import { _1n } from '../bi/consts';
import { objectSpread } from '../object/spread';
const U8_MAX = BigInt(256); const U8_MAX = BigInt(256);
const U16_MAX = BigInt(256 * 256); const U16_MAX = BigInt(256 * 256);
function xor (input: Uint8Array): Uint8Array {
const result = new Uint8Array(input.length);
const dvI = new DataView(input.buffer, input.byteOffset);
const dvO = new DataView(result.buffer);
const mod = input.length % 2;
const length = input.length - mod;
for (let i = 0; i < length; i += 2) {
dvO.setUint16(i, dvI.getUint16(i) ^ 0xffff);
}
if (mod) {
dvO.setUint8(length, dvI.getUint8(length) ^ 0xff);
}
return result;
}
function toBigInt (input: Uint8Array): bigint {
const dvI = new DataView(input.buffer, input.byteOffset);
const mod = input.length % 2;
const length = input.length - mod;
let result = BigInt(0);
for (let i = 0; i < length; i += 2) {
result = (result * U16_MAX) + BigInt(dvI.getUint16(i));
}
if (mod) {
result = (result * U8_MAX) + BigInt(dvI.getUint8(length));
}
return result;
}
/** /**
* @name u8aToBigInt * @name u8aToBigInt
* @summary Creates a BigInt from a Uint8Array object. * @summary Creates a BigInt from a Uint8Array object.
*/ */
export function u8aToBigInt (value: Uint8Array, options: ToBnOptions = {}): bigint { export function u8aToBigInt (value: Uint8Array, { isLe = true, isNegative = false }: ToBnOptions = {}): bigint {
if (!value || !value.length) { if (!value || !value.length) {
return BigInt(0); return BigInt(0);
} }
const { isLe, isNegative } = objectSpread<ToBnOptions>({ isLe: true, isNegative: false }, options);
const u8a = isLe const u8a = isLe
? value.reverse() ? value
: value; : value.reverse();
const dvI = new DataView(u8a.buffer, u8a.byteOffset);
const mod = u8a.length % 2;
let result = BigInt(0);
// This is mostly written for readability (with the single isNegative shortcut),
// as opposed to performance, e.g. `u8aToBn` does loop unrolling, etc.
if (isNegative) {
for (let i = u8a.length - 2; i >= mod; i -= 2) {
result = (result * U16_MAX) + BigInt(dvI.getUint16(i, true) ^ 0xffff);
}
if (mod) {
result = (result * U8_MAX) + BigInt(dvI.getUint8(0) ^ 0xff);
}
} else {
for (let i = u8a.length - 2; i >= mod; i -= 2) {
result = (result * U16_MAX) + BigInt(dvI.getUint16(i, true));
}
if (mod) {
result = (result * U8_MAX) + BigInt(dvI.getUint8(0));
}
}
return isNegative return isNegative
? ((toBigInt(xor(u8a)) * -_1n) - _1n) ? ((result * -_1n) - _1n)
: toBigInt(u8a); : result;
} }
+192 -55
View File
@@ -28,49 +28,183 @@ describe('u8aToBn', (): void => {
).toBe('3412'); ).toBe('3412');
}); });
it('converts values (big-endian)', (): void => { describe('LE', (): void => {
expect( describe('unsigned', (): void => {
u8aToBn( it('converts values (u8)', (): void => {
new Uint8Array([0x12, 0x34]), expect(
{ isLe: false } u8aToBn(
).toString(16) new Uint8Array([0x12]),
).toBe('1234'); { isLe: true }
).toString(16)
).toBe('12');
});
it('converts values (u16)', (): void => {
expect(
u8aToBn(
new Uint8Array([0x12, 0x34]),
{ isLe: true }
).toString(16)
).toBe('3412');
});
it('converts values (u24)', (): void => {
expect(
u8aToBn(
new Uint8Array([0x12, 0x34, 0x56]),
{ isLe: true }
).toString(16)
).toBe('563412');
});
it('converts values (u32)', (): void => {
expect(
u8aToBn(
new Uint8Array([0x12, 0x34, 0x56, 0x78]),
{ isLe: true }
).toString(16)
).toBe('78563412');
});
it('converts values (u40)', (): void => {
expect(
u8aToBn(
new Uint8Array([0x12, 0x34, 0x56, 0x78, 0x9a]),
{ isLe: true }
).toString(16)
).toBe('9a78563412');
});
it('converts values (u48)', (): void => {
expect(
u8aToBn(
new Uint8Array([0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc]),
{ isLe: true }
).toString(16)
).toBe('bc9a78563412');
});
});
describe('signed', (): void => {
it('converts values (i8)', (): void => {
expect(
u8aToBn(
new Uint8Array([244]),
{ isLe: true, isNegative: true }
).toString()
).toBe('-12');
});
it('converts values (i16)', (): void => {
expect(
u8aToBn(
new Uint8Array([46, 251]),
{ isLe: true, isNegative: true }
).toString()
).toBe('-1234');
});
it('converts values (i24)', (): void => {
expect(
u8aToBn(
new Uint8Array([192, 29, 254]),
{ isLe: true, isNegative: true }
).toString()
).toBe('-123456');
});
it('converts values (i32)', (): void => {
expect(
u8aToBn(
new Uint8Array([235, 50, 164, 248]),
{ isLe: true, isNegative: true }
).toString()
).toBe('-123456789');
});
it('converts values (i40)', (): void => {
expect(
u8aToBn(
new Uint8Array([65, 86, 129, 173, 254]),
{ isLe: true, isNegative: true }
).toString()
).toBe('-5678999999');
});
it('converts values (i48)', (): void => {
expect(
u8aToBn(
new Uint8Array([1, 96, 141, 177, 231, 246]),
{ isLe: true, isNegative: true }
).toString()
).toBe('-9999999999999');
});
it('converts values (i64)', (): void => {
expect(
u8aToBn(
new Uint8Array([1, 0, 156, 88, 76, 73, 31, 242]),
{ isLe: true, isNegative: true }
).toString()
).toBe('-999999999999999999');
});
});
}); });
it('converts values (little-endian, u16)', (): void => { describe('BE', (): void => {
expect( it('converts values (u8)', (): void => {
u8aToBn( expect(
new Uint8Array([0x12, 0x34]), u8aToBn(
{ isLe: true } new Uint8Array([0x12]),
).toString(16) { isLe: false }
).toBe('3412'); ).toString(16)
}); ).toBe('12');
});
it('converts values (little-endian, u32)', (): void => { it('converts values (u16)', (): void => {
expect( expect(
u8aToBn( u8aToBn(
new Uint8Array([0x12, 0x34, 0x56, 0x78]), new Uint8Array([0x12, 0x34]),
{ isLe: true } { isLe: false }
).toString(16) ).toString(16)
).toBe('78563412'); ).toBe('1234');
}); });
it('converts values (big-endian, u16)', (): void => { it('converts values (u24)', (): void => {
expect( expect(
u8aToBn( u8aToBn(
new Uint8Array([0x12, 0x34]), new Uint8Array([0x12, 0x34, 0x56]),
{ isLe: false } { isLe: false }
).toString(16) ).toString(16)
).toBe('1234'); ).toBe('123456');
}); });
it('converts values (big-endian, u32)', (): void => { it('converts values (u32)', (): void => {
expect( expect(
u8aToBn( u8aToBn(
new Uint8Array([0x12, 0x34, 0x56, 0x78]), new Uint8Array([0x12, 0x34, 0x56, 0x78]),
{ isLe: false } { isLe: false }
).toString(16) ).toString(16)
).toBe('12345678'); ).toBe('12345678');
});
it('converts values (u40)', (): void => {
expect(
u8aToBn(
new Uint8Array([0x12, 0x34, 0x56, 0x78, 0x9a]),
{ isLe: false }
).toString(16)
).toBe('123456789a');
});
it('converts values (u48)', (): void => {
expect(
u8aToBn(
new Uint8Array([0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc]),
{ isLe: false }
).toString(16)
).toBe('123456789abc');
});
}); });
describe('empty creation', (): void => { describe('empty creation', (): void => {
@@ -111,22 +245,24 @@ describe('u8aToBn', (): void => {
}); });
}); });
it('handles negative numbers (little-endian)', (): void => { describe('negative', (): void => {
expect( it('handles negative numbers (little-endian)', (): void => {
u8aToBn( expect(
new Uint8Array([46, 251]), u8aToBn(
{ isLe: true, isNegative: true } new Uint8Array([46, 251]),
).toNumber() { isLe: true, isNegative: true }
).toBe(-1234); ).toNumber()
}); ).toBe(-1234);
});
it('handles negative numbers (big-endian)', (): void => { it('handles negative numbers (big-endian)', (): void => {
expect( expect(
u8aToBn( u8aToBn(
new Uint8Array([251, 46]), new Uint8Array([251, 46]),
{ isLe: false, isNegative: true } { isLe: false, isNegative: true }
).toNumber() ).toNumber()
).toBe(-1234); ).toBe(-1234);
});
}); });
it('handles overflows correctly (little-endian)', (): void => { it('handles overflows correctly (little-endian)', (): void => {
@@ -163,6 +299,7 @@ describe('u8aToBn', (): void => {
).toBe(true); ).toBe(true);
}); });
performance('u8aToBn (u32)', 500000, [[new Uint8Array([0x68, 0x65, 0x6c, 0x6c])]], u8aToBn); performance('u8aToBn (u32)', 1_000_000, [[new Uint8Array([0x68, 0x65, 0x6c, 0x6c])]], u8aToBn);
performance('u8aToBn (u64)', 500000, [[new Uint8Array([0x68, 0x65, 0x6c, 0x6c, 0x68, 0x65, 0x6c, 0x6c])]], u8aToBn); performance('u8aToBn (i32)', 1_000_000, [[new Uint8Array([0x68, 0x65, 0x6c, 0x6c])]], (v: Uint8Array) => u8aToBn(v, { isNegative: true }));
performance('u8aToBn (u64)', 500_000, [[new Uint8Array([0x68, 0x65, 0x6c, 0x6c, 0x68, 0x65, 0x6c, 0x6c])]], u8aToBn);
}); });
+90 -24
View File
@@ -5,7 +5,6 @@ import type { ToBnOptions } from '../types';
import { BN } from '../bn/bn'; import { BN } from '../bn/bn';
import { isBoolean } from '../is/boolean'; import { isBoolean } from '../is/boolean';
import { objectSpread } from '../object/spread';
/** /**
* @name u8aToBn * @name u8aToBn
@@ -28,41 +27,108 @@ import { objectSpread } from '../object/spread';
function u8aToBn (value: Uint8Array, options?: ToBnOptions): BN; function u8aToBn (value: Uint8Array, options?: ToBnOptions): BN;
/** @deprecated Use u8aToBn(value: Uint8Array, options?: ToBnOptions) */ /** @deprecated Use u8aToBn(value: Uint8Array, options?: ToBnOptions) */
function u8aToBn (value: Uint8Array, options?: boolean): BN; function u8aToBn (value: Uint8Array, options?: boolean): BN;
/** @deprecated Use hexToBn (value?: string | null, options?: ToBnOptions) */ /** @deprecated Use u8aToBn (value?: string | null, options?: ToBnOptions) */
function u8aToBn (value: Uint8Array, options: ToBnOptions | boolean = {}): BN { function u8aToBn (value: Uint8Array, options: ToBnOptions | boolean = {}): BN {
// NOTE: This is the same process as followed in the hexToBn conversion // NOTE: This is the same process as followed in the hexToBn conversion
// For Uint8Array, default to LE // For Uint8Array, default to LE
const { isLe, isNegative } = objectSpread<ToBnOptions>( const { isLe = true, isNegative = false } = isBoolean(options)
{ isLe: true, isNegative: false }, ? { isLe: options }
isBoolean(options) : options;
? { isLe: options }
: options
);
const count = value.length; const count = value.length;
let bn: BN;
// shortcut for <= u48 values - in this case the manual conversion // shortcut for <= u48 values - in this case the manual conversion
// here seems to be more efficient than passing the full array // here seems to be more efficient than passing the full array
// (and yes, it can be u48, e.g. in compacts with variable lengths)
if (count <= 6) { if (count <= 6) {
let result = 0; if (isNegative) {
let result = 0;
for (let i = 0; i < count; i++) { if (isLe) {
result = (result * 0x1_00) + ( // Most common case i{8, 16, 32} default LE SCALE-encoded
isLe // For <= 32, we also optimize the xor to a single op
? value[count - 1 - i] // (see the comments around unrolling in the next section)
: value[i] switch (count) {
); case 0:
return new BN(0);
case 1:
result = value[0] ^ 0x0000_00ff;
break;
case 2:
result = (value[0] + (value[1] << 8)) ^ 0x0000_ffff;
break;
case 3:
result = (value[0] + (value[1] << 8) + (value[2] << 16)) ^ 0x00ff_ffff;
break;
case 4:
// for the 3rd byte, we don't << 24 - since JS converts all bitwise operators to
// 32-bit, in the case where the top-most bit is set this yields a negative value
result = (value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 0x1_00_00_00)) ^ 0xffff_ffff;
break;
case 5:
result = ((value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 0x1_00_00_00)) ^ 0xffff_ffff) + ((value[4] ^ 0xff) * 0x1_00_00_00_00);
break;
default: // 6
result = ((value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 0x1_00_00_00)) ^ 0xffff_ffff) + (((value[4] + (value[5] << 8)) ^ 0x0000_ffff) * 0x1_00_00_00_00);
break;
}
} else {
for (let i = 0; i < count; i++) {
result = (result * 0x1_00) + (value[i] ^ 0xff);
}
}
return count
? new BN((result * -1) - 1)
: new BN(0);
} else if (isLe) {
// Most common case - u{8, 16, 32} default LE SCALE-encoded
//
// There are some slight benefits in unrolling this specific loop,
// however it comes with diminishing returns since here the actual
// `new BN` does seem to take up the bulk of the time
switch (count) {
case 0:
return new BN(0);
case 1:
return new BN(value[0]);
case 2:
return new BN(value[0] + (value[1] << 8));
case 3:
return new BN(value[0] + (value[1] << 8) + (value[2] << 16));
case 4:
// for the 3rd byte, we don't << 24 - since JS converts all bitwise operators to
// 32-bit, in the case where the top-most bit is set this yields a negative value
return new BN(value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 0x1_00_00_00));
case 5:
return new BN(value[0] + (value[1] << 8) + (value[2] << 16) + ((value[3] + (value[4] << 8)) * 0x1_00_00_00));
default: // 6
return new BN(value[0] + (value[1] << 8) + (value[2] << 16) + ((value[3] + (value[4] << 8) + (value[5] << 16)) * 0x1_00_00_00));
}
} else {
let result = 0;
for (let i = 0; i < count; i++) {
result = (result * 0x1_00) + value[i];
}
return new BN(result);
} }
bn = new BN(result);
} else {
bn = new BN(value, isLe ? 'le' : 'be');
} }
return isNegative && value.length return isNegative
? bn.fromTwos(value.length * 8) ? new BN(value, isLe ? 'le' : 'be').fromTwos(value.length * 8)
: bn; : new BN(value, isLe ? 'le' : 'be');
} }
export { u8aToBn }; export { u8aToBn };
+16 -3
View File
@@ -3,7 +3,20 @@
import type { HexString } from '../types'; import type { HexString } from '../types';
import { U8_TO_HEX, U16_TO_HEX } from '../hex/alphabet'; const U8 = new Array<string>(256);
const U16 = new Array<string>(256 * 256);
for (let n = 0; n < 256; n++) {
U8[n] = n.toString(16).padStart(2, '0');
}
for (let i = 0; i < 256; i++) {
const s = i << 8;
for (let j = 0; j < 256; j++) {
U16[s | j] = U8[i] + U8[j];
}
}
/** @internal */ /** @internal */
function hex (value: Uint8Array): string { function hex (value: Uint8Array): string {
@@ -15,11 +28,11 @@ function hex (value: Uint8Array): string {
for (let i = 0; i < length; i += 2) { for (let i = 0; i < length; i += 2) {
// we only use getUint16 here instead of getUint32 - at least in our // we only use getUint16 here instead of getUint32 - at least in our
// tests this is faster to execute (both long & short strings tested) // tests this is faster to execute (both long & short strings tested)
result += U16_TO_HEX[dv.getUint16(i)]; result += U16[dv.getUint16(i)];
} }
if (mod) { if (mod) {
result += U8_TO_HEX[dv.getUint8(length)]; result += U8[dv.getUint8(length)];
} }
return result; return result;
+135
View File
@@ -0,0 +1,135 @@
// Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { performance } from '../test/performance';
import { u8aToNumber } from '.';
describe('u8aToNumber', (): void => {
describe('unsigned', (): void => {
it('converts values (u8)', (): void => {
expect(
u8aToNumber(
new Uint8Array([0x12])
)
).toBe(18);
});
it('converts values (u16)', (): void => {
expect(
u8aToNumber(
new Uint8Array([0x12, 0x34])
)
).toBe(13330);
});
it('converts values (u24)', (): void => {
expect(
u8aToNumber(
new Uint8Array([0x12, 0x34, 0x56])
)
).toBe(5649426);
});
it('converts values (u32)', (): void => {
expect(
u8aToNumber(
new Uint8Array([0x12, 0x34, 0x56, 0x78])
)
).toBe(2018915346);
});
it('converts values (u40)', (): void => {
expect(
u8aToNumber(
new Uint8Array([0x12, 0x34, 0x56, 0x78, 0x9a])
)
).toBe(663443878930);
});
it('converts values (u48)', (): void => {
expect(
u8aToNumber(
new Uint8Array([0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc])
)
).toBe(207371629900818);
});
});
describe('signed', (): void => {
it('converts values (i8)', (): void => {
expect(
u8aToNumber(
new Uint8Array([244]),
{ isNegative: true }
)
).toBe(-12);
});
it('converts values (i16)', (): void => {
expect(
u8aToNumber(
new Uint8Array([46, 251]),
{ isNegative: true }
)
).toBe(-1234);
});
it('converts values (i24)', (): void => {
expect(
u8aToNumber(
new Uint8Array([192, 29, 254]),
{ isNegative: true }
)
).toBe(-123456);
});
it('converts values (i32)', (): void => {
expect(
u8aToNumber(
new Uint8Array([235, 50, 164, 248]),
{ isNegative: true }
)
).toBe(-123456789);
});
it('converts values (i40)', (): void => {
expect(
u8aToNumber(
new Uint8Array([65, 86, 129, 173, 254]),
{ isNegative: true }
)
).toBe(-5678999999);
});
it('converts values (i48)', (): void => {
expect(
u8aToNumber(
new Uint8Array([1, 96, 141, 177, 231, 246]),
{ isNegative: true }
)
).toBe(-9999999999999);
});
});
describe('empty creation', (): void => {
it('handles unsigned (le)', (): void => {
expect(
u8aToNumber(
new Uint8Array()
)
).toBe(0);
});
it('handles signed (le)', (): void => {
expect(
u8aToNumber(
new Uint8Array(),
{ isNegative: true }
)
).toBe(0);
});
});
performance('u8aToNumber (u32)', 1_000_000, [[new Uint8Array([0x68, 0x65, 0x6c, 0x6c])]], u8aToNumber);
performance('u8aToNumber (i32)', 1_000_000, [[new Uint8Array([0x68, 0x65, 0x6c, 0x6c])]], (v: Uint8Array) => u8aToNumber(v, { isNegative: true }));
});
+85
View File
@@ -0,0 +1,85 @@
// Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
interface ToNumberOptions {
/**
* @description Number is signed, apply two's complement
*/
isNegative?: boolean;
}
/**
* @name u8aToNumber
* @summary Creates a number from a Uint8Array object.
*/
export function u8aToNumber (value: Uint8Array, { isNegative = false }: ToNumberOptions = {}): number {
const count = value.length;
if (isNegative) {
let result = 0;
switch (count) {
case 0:
return 0;
case 1:
result = value[0] ^ 0x0000_00ff;
break;
case 2:
result = (value[0] + (value[1] << 8)) ^ 0x0000_ffff;
break;
case 3:
result = (value[0] + (value[1] << 8) + (value[2] << 16)) ^ 0x00ff_ffff;
break;
case 4:
// for the 3rd byte, we don't << 24 - since JS converts all bitwise operators to
// 32-bit, in the case where the top-most bit is set this yields a negative value
result = (value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 0x1_00_00_00)) ^ 0xffff_ffff;
break;
case 5:
result = ((value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 0x1_00_00_00)) ^ 0xffff_ffff) + ((value[4] ^ 0xff) * 0x1_00_00_00_00);
break;
case 6:
result = ((value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 0x1_00_00_00)) ^ 0xffff_ffff) + (((value[4] + (value[5] << 8)) ^ 0x0000_ffff) * 0x1_00_00_00_00);
break;
default:
throw new Error('Value more than 48-bits cannot be reliably converted');
}
return (result * -1) - 1;
}
switch (count) {
case 0:
return 0;
case 1:
return value[0];
case 2:
return value[0] + (value[1] << 8);
case 3:
return value[0] + (value[1] << 8) + (value[2] << 16);
case 4:
// for the 3rd byte, we don't << 24 - since JS converts all bitwise operators to
// 32-bit, in the case where the top-most bit is set this yields a negative value
return value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 0x1_00_00_00);
case 5:
return value[0] + (value[1] << 8) + (value[2] << 16) + ((value[3] + (value[4] << 8)) * 0x1_00_00_00);
case 6:
return value[0] + (value[1] << 8) + (value[2] << 16) + ((value[3] + (value[4] << 8) + (value[5] << 16)) * 0x1_00_00_00);
default:
throw new Error('Value more than 48-bits cannot be reliably converted');
}
}
+10 -2
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2022 @polkadot/util authors & contributors // Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { u8aToString } from '..'; import { u8aToString } from '.';
describe('u8aToString', (): void => { describe('u8aToString', (): void => {
it('decodes to an empty string for undefined', (): void => { it('decodes to an empty string for undefined', (): void => {
@@ -16,11 +16,19 @@ describe('u8aToString', (): void => {
).toEqual(''); ).toEqual('');
}); });
it('decodes the buffer correctly', (): void => { it('decodes the Uint8Array correctly', (): void => {
expect( expect(
u8aToString( u8aToString(
new Uint8Array([208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130, 44, 32, 208, 188, 208, 184, 209, 128, 33]) new Uint8Array([208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130, 44, 32, 208, 188, 208, 184, 209, 128, 33])
) )
).toEqual('Привет, мир!'); ).toEqual('Привет, мир!');
}); });
it('decodes the Uint8Array correctly', (): void => {
expect(
u8aToString(
new Uint8Array([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64])
)
).toEqual('hello world');
});
}); });
+14
View File
@@ -9,12 +9,18 @@ import { u8aConcatStrict } from './concat';
import { u8aEq } from './eq'; import { u8aEq } from './eq';
import { u8aToU8a } from './toU8a'; import { u8aToU8a } from './toU8a';
/** @internal */
export const U8A_WRAP_ETHEREUM = u8aToU8a('\x19Ethereum Signed Message:\n'); export const U8A_WRAP_ETHEREUM = u8aToU8a('\x19Ethereum Signed Message:\n');
/** @internal */
export const U8A_WRAP_PREFIX = u8aToU8a('<Bytes>'); export const U8A_WRAP_PREFIX = u8aToU8a('<Bytes>');
/** @internal */
export const U8A_WRAP_POSTFIX = u8aToU8a('</Bytes>'); export const U8A_WRAP_POSTFIX = u8aToU8a('</Bytes>');
const WRAP_LEN = U8A_WRAP_PREFIX.length + U8A_WRAP_POSTFIX.length; const WRAP_LEN = U8A_WRAP_PREFIX.length + U8A_WRAP_POSTFIX.length;
/** @internal */
export function u8aIsWrapped (u8a: Uint8Array, withEthereum: boolean): boolean { export function u8aIsWrapped (u8a: Uint8Array, withEthereum: boolean): boolean {
return ( return (
( (
@@ -30,6 +36,10 @@ export function u8aIsWrapped (u8a: Uint8Array, withEthereum: boolean): boolean {
); );
} }
/**
* @name u8aUnwrapBytes
* @description Removes all <Bytes>...</Bytes> wrappers from the supplied value
*/
export function u8aUnwrapBytes (bytes: U8aLike): Uint8Array { export function u8aUnwrapBytes (bytes: U8aLike): Uint8Array {
const u8a = u8aToU8a(bytes); const u8a = u8aToU8a(bytes);
@@ -39,6 +49,10 @@ export function u8aUnwrapBytes (bytes: U8aLike): Uint8Array {
: u8a; : u8a;
} }
/**
* @name u8aWrapBytes
* @description Adds a <Bytes>...</Bytes> wrapper to the supplied value (if not already existing)
*/
export function u8aWrapBytes (bytes: U8aLike): Uint8Array { export function u8aWrapBytes (bytes: U8aLike): Uint8Array {
const u8a = u8aToU8a(bytes); const u8a = u8aToU8a(bytes);
+3 -2
View File
@@ -4,7 +4,6 @@
import { xglobal } from '@polkadot/x-global'; import { xglobal } from '@polkadot/x-global';
import { isFunction } from './is/function'; import { isFunction } from './is/function';
import { assert } from './assert';
type This = typeof globalThis; type This = typeof globalThis;
@@ -112,7 +111,9 @@ function warn <T extends { version: string }> (pre: string, all: T[], fmt: (vers
* @description A `@polkadot/*` version detection utility, checking for one occurence of a package in addition to checking for ddependency versions. * @description A `@polkadot/*` version detection utility, checking for one occurence of a package in addition to checking for ddependency versions.
*/ */
export function detectPackage ({ name, path, type, version }: PackageJson, pathOrFn?: FnString | string | false | null, deps: PackageJson[] = []): void { export function detectPackage ({ name, path, type, version }: PackageJson, pathOrFn?: FnString | string | false | null, deps: PackageJson[] = []): void {
assert(name.startsWith('@polkadot'), () => `Invalid package descriptor ${name}`); if (!name.startsWith('@polkadot')) {
throw new Error(`Invalid package descriptor ${name}`);
}
const entry = getEntry(name); const entry = getEntry(name);
+2 -2
View File
@@ -20,9 +20,9 @@
"./shim.cjs" "./shim.cjs"
], ],
"type": "module", "type": "module",
"version": "9.3.1", "version": "9.5.1",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.18.3", "@babel/runtime": "^7.18.3",
"@polkadot/x-global": "9.3.1" "@polkadot/x-global": "9.5.1"
} }
} }
+1 -1
View File
@@ -3,4 +3,4 @@
// Do not edit, auto-generated by @polkadot/dev // Do not edit, auto-generated by @polkadot/dev
export const packageInfo = { name: '@polkadot/x-bigint', path: 'auto', type: 'auto', version: '9.3.1' }; export const packageInfo = { name: '@polkadot/x-bigint', path: 'auto', type: 'auto', version: '9.5.1' };
+2 -2
View File
@@ -17,11 +17,11 @@
}, },
"sideEffects": false, "sideEffects": false,
"type": "module", "type": "module",
"version": "9.3.1", "version": "9.5.1",
"main": "index.js", "main": "index.js",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.18.3", "@babel/runtime": "^7.18.3",
"@polkadot/util": "9.3.1", "@polkadot/util": "9.5.1",
"buffer-es6": "^4.9.3" "buffer-es6": "^4.9.3"
} }
} }
+1 -1
View File
@@ -3,4 +3,4 @@
// Do not edit, auto-generated by @polkadot/dev // Do not edit, auto-generated by @polkadot/dev
export const packageInfo = { name: '@polkadot/x-bundle', path: 'auto', type: 'auto', version: '9.3.1' }; export const packageInfo = { name: '@polkadot/x-bundle', path: 'auto', type: 'auto', version: '9.5.1' };
+3 -3
View File
@@ -17,14 +17,14 @@
}, },
"sideEffects": false, "sideEffects": false,
"type": "module", "type": "module",
"version": "9.3.1", "version": "9.5.1",
"browser": "browser.js", "browser": "browser.js",
"main": "node.js", "main": "node.js",
"react-native": "react-native.js", "react-native": "react-native.js",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.18.3", "@babel/runtime": "^7.18.3",
"@polkadot/x-global": "9.3.1", "@polkadot/x-global": "9.5.1",
"@types/node-fetch": "^2.6.1", "@types/node-fetch": "^2.6.2",
"node-fetch": "^2.6.7" "node-fetch": "^2.6.7"
} }
} }
+1 -1
View File
@@ -3,4 +3,4 @@
// Do not edit, auto-generated by @polkadot/dev // Do not edit, auto-generated by @polkadot/dev
export const packageInfo = { name: '@polkadot/x-fetch', path: 'auto', type: 'auto', version: '9.3.1' }; export const packageInfo = { name: '@polkadot/x-fetch', path: 'auto', type: 'auto', version: '9.5.1' };
+1 -1
View File
@@ -17,7 +17,7 @@
}, },
"sideEffects": false, "sideEffects": false,
"type": "module", "type": "module",
"version": "9.3.1", "version": "9.5.1",
"main": "index.js", "main": "index.js",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.18.3" "@babel/runtime": "^7.18.3"
+4
View File
@@ -26,6 +26,10 @@ export const xglobal = (
); );
export function extractGlobal <N extends GlobalNames, T extends GlobalType<N>> (name: N, fallback: unknown): T { export function extractGlobal <N extends GlobalNames, T extends GlobalType<N>> (name: N, fallback: unknown): T {
// Not quite sure why this is here - snuck in with TS 4.7.2 with no real idea
// (as of now) as to why this looks like an "any" when we do cast it to a T
//
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return typeof xglobal[name as 'undefined'] === 'undefined' return typeof xglobal[name as 'undefined'] === 'undefined'
? fallback as T ? fallback as T
: xglobal[name as 'undefined'] as unknown as T; : xglobal[name as 'undefined'] as unknown as T;
+1 -1
View File
@@ -3,4 +3,4 @@
// Do not edit, auto-generated by @polkadot/dev // Do not edit, auto-generated by @polkadot/dev
export const packageInfo = { name: '@polkadot/x-global', path: 'auto', type: 'auto', version: '9.3.1' }; export const packageInfo = { name: '@polkadot/x-global', path: 'auto', type: 'auto', version: '9.5.1' };
+3 -3
View File
@@ -17,15 +17,15 @@
}, },
"sideEffects": false, "sideEffects": false,
"type": "module", "type": "module",
"version": "9.3.1", "version": "9.5.1",
"browser": "browser.js", "browser": "browser.js",
"main": "node.js", "main": "node.js",
"react-native": "react-native.js", "react-native": "react-native.js",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.18.3", "@babel/runtime": "^7.18.3",
"@polkadot/x-global": "9.3.1" "@polkadot/x-global": "9.5.1"
}, },
"devDependencies": { "devDependencies": {
"@types/react-native": "^0.67.7" "@types/react-native": "^0.67.8"
} }
} }
+1 -1
View File
@@ -3,4 +3,4 @@
// Do not edit, auto-generated by @polkadot/dev // Do not edit, auto-generated by @polkadot/dev
export const packageInfo = { name: '@polkadot/x-randomvalues', path: 'auto', type: 'auto', version: '9.3.1' }; export const packageInfo = { name: '@polkadot/x-randomvalues', path: 'auto', type: 'auto', version: '9.5.1' };
+2 -2
View File
@@ -17,12 +17,12 @@
}, },
"sideEffects": false, "sideEffects": false,
"type": "module", "type": "module",
"version": "9.3.1", "version": "9.5.1",
"browser": "browser.js", "browser": "browser.js",
"main": "node.js", "main": "node.js",
"react-native": "react-native.js", "react-native": "react-native.js",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.18.3", "@babel/runtime": "^7.18.3",
"@polkadot/x-global": "9.3.1" "@polkadot/x-global": "9.5.1"
} }
} }
+1 -1
View File
@@ -3,4 +3,4 @@
// Do not edit, auto-generated by @polkadot/dev // Do not edit, auto-generated by @polkadot/dev
export const packageInfo = { name: '@polkadot/x-textdecoder', path: 'auto', type: 'auto', version: '9.3.1' }; export const packageInfo = { name: '@polkadot/x-textdecoder', path: 'auto', type: 'auto', version: '9.5.1' };

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