Просмотр исходного кода

Merge pull request #2514 from shamil-gadelshin/storage_node_v2

Storage node v2
Mokhtar Naamani 3 лет назад
Родитель
Сommit
cbc8b51352
77 измененных файлов с 11305 добавлено и 757 удалено
  1. 1 0
      build-npm-packages.sh
  2. 1 0
      package.json
  3. 34 11
      runtime-modules/storage/src/lib.rs
  4. 5 5
      runtime-modules/storage/src/tests/fixtures.rs
  5. 2 0
      storage-node-v2/.eslintignore
  6. 15 0
      storage-node-v2/.eslintrc.js
  7. 10 0
      storage-node-v2/.gitignore
  8. 2 0
      storage-node-v2/.prettierignore
  9. 533 0
      storage-node-v2/README.md
  10. 5 0
      storage-node-v2/bin/run
  11. 3 0
      storage-node-v2/bin/run.cmd
  12. 115 0
      storage-node-v2/package.json
  13. 30 0
      storage-node-v2/scripts/create-auth-request-signature.ts
  14. 17 0
      storage-node-v2/scripts/init-dev-bucket.sh
  15. 47 0
      storage-node-v2/scripts/run-all-commands.sh
  16. 223 0
      storage-node-v2/src/api-spec/openapi.yaml
  17. 171 0
      storage-node-v2/src/command-base/ApiCommandBase.ts
  18. 15 0
      storage-node-v2/src/command-base/ExitCodes.ts
  19. 21 0
      storage-node-v2/src/commands/dev/init.ts
  20. 39 0
      storage-node-v2/src/commands/dev/multihash.ts
  21. 49 0
      storage-node-v2/src/commands/dev/upload.ts
  22. 47 0
      storage-node-v2/src/commands/dev/verify-bag-id.ts
  23. 43 0
      storage-node-v2/src/commands/leader/cancel-invite.ts
  24. 65 0
      storage-node-v2/src/commands/leader/create-bucket.ts
  25. 43 0
      storage-node-v2/src/commands/leader/delete-bucket.ts
  26. 49 0
      storage-node-v2/src/commands/leader/invite-operator.ts
  27. 43 0
      storage-node-v2/src/commands/leader/remove-operator.ts
  28. 54 0
      storage-node-v2/src/commands/leader/set-bucket-limits.ts
  29. 45 0
      storage-node-v2/src/commands/leader/set-global-uploading-status.ts
  30. 42 0
      storage-node-v2/src/commands/leader/update-bag-limit.ts
  31. 87 0
      storage-node-v2/src/commands/leader/update-bag.ts
  32. 56 0
      storage-node-v2/src/commands/leader/update-blacklist.ts
  33. 59 0
      storage-node-v2/src/commands/leader/update-bucket-status.ts
  34. 43 0
      storage-node-v2/src/commands/leader/update-data-fee.ts
  35. 57 0
      storage-node-v2/src/commands/leader/update-dynamic-bag-policy.ts
  36. 49 0
      storage-node-v2/src/commands/leader/update-voucher-limits.ts
  37. 50 0
      storage-node-v2/src/commands/operator/accept-invitation.ts
  38. 55 0
      storage-node-v2/src/commands/operator/set-metadata.ts
  39. 59 0
      storage-node-v2/src/commands/server.ts
  40. 1 0
      storage-node-v2/src/index.ts
  41. 136 0
      storage-node-v2/src/services/helpers/auth.ts
  42. 154 0
      storage-node-v2/src/services/helpers/bagTypes.ts
  43. 50 0
      storage-node-v2/src/services/helpers/fileInfo.ts
  44. 30 0
      storage-node-v2/src/services/helpers/hashing.ts
  45. 47 0
      storage-node-v2/src/services/helpers/tokenNonceKeeper.ts
  46. 111 0
      storage-node-v2/src/services/logger.ts
  47. 83 0
      storage-node-v2/src/services/runtime/accounts.ts
  48. 208 0
      storage-node-v2/src/services/runtime/api.ts
  49. 506 0
      storage-node-v2/src/services/runtime/extrinsics.ts
  50. 91 0
      storage-node-v2/src/services/runtime/hireLead.ts
  51. 34 0
      storage-node-v2/src/services/runtime/transactionNonceKeeper.ts
  52. 152 0
      storage-node-v2/src/services/webApi/app.ts
  53. 397 0
      storage-node-v2/src/services/webApi/controllers/publicApi.ts
  54. 26 0
      storage-node-v2/tsconfig.json
  55. 3550 0
      storage-node-v2/yarn.lock
  56. 1 1
      types/augment-codec/all.ts
  57. 48 3
      types/augment-codec/augment-api-consts.ts
  58. 593 27
      types/augment-codec/augment-api-errors.ts
  59. 384 43
      types/augment-codec/augment-api-events.ts
  60. 105 32
      types/augment-codec/augment-api-query.ts
  61. 183 52
      types/augment-codec/augment-api-tx.ts
  62. 0 0
      types/augment-codec/augment-types.ts
  63. 117 30
      types/augment/all/defs.json
  64. 158 34
      types/augment/all/types.ts
  65. 48 3
      types/augment/augment-api-consts.ts
  66. 593 27
      types/augment/augment-api-errors.ts
  67. 384 43
      types/augment/augment-api-events.ts
  68. 105 32
      types/augment/augment-api-query.ts
  69. 183 52
      types/augment/augment-api-tx.ts
  70. 0 0
      types/augment/augment-types.ts
  71. 3 3
      types/package.json
  72. 2 1
      types/src/common.ts
  73. 4 3
      types/src/index.ts
  74. 0 82
      types/src/media.ts
  75. 2 2
      types/src/scripts/generateAugmentCodec.ts
  76. 245 0
      types/src/storage.ts
  77. 287 271
      yarn.lock

+ 1 - 0
build-npm-packages.sh

@@ -9,4 +9,5 @@ yarn workspace @joystream/cd-schemas build
 yarn workspace query-node-root build
 yarn workspace @joystream/cli build
 yarn workspace storage-node build
+yarn workspace storage-node-v2 build
 yarn workspace pioneer build

+ 1 - 0
package.json

@@ -16,6 +16,7 @@
     "tests/network-tests",
     "cli",
     "types",
+    "storage-node-v2",
     "storage-node",
     "storage-node/packages/*",
     "devops/eslint-config",

+ 34 - 11
runtime-modules/storage/src/lib.rs

@@ -129,6 +129,7 @@ use codec::{Codec, Decode, Encode};
 use frame_support::dispatch::{DispatchError, DispatchResult};
 use frame_support::traits::{Currency, ExistenceRequirement, Get, Randomness};
 use frame_support::{decl_error, decl_event, decl_module, decl_storage, ensure, Parameter};
+use frame_system::ensure_root;
 #[cfg(feature = "std")]
 use serde::{Deserialize, Serialize};
 use sp_arithmetic::traits::{BaseArithmetic, One, Zero};
@@ -432,8 +433,8 @@ pub type DistributionBucketsPerBagValueConstraint = BoundedValueConstraint<u64>;
 /// Local module account handler.
 pub type StorageTreasury<T> = ModuleAccountHandler<T, <T as Trait>::ModuleId>;
 
-/// IPFS hash type alias.
-pub type ContentId = Vec<u8>;
+/// IPFS hash type alias (content ID).
+pub type Cid = Vec<u8>;
 
 // Alias for the Substrate balances pallet.
 type Balances<T> = balances::Module<T>;
@@ -911,7 +912,7 @@ decl_storage! {
             T::StorageBucketId => StorageBucket<WorkerId<T>>;
 
         /// Blacklisted data object hashes.
-        pub Blacklist get (fn blacklist): map hasher(blake2_128_concat) ContentId => ();
+        pub Blacklist get (fn blacklist): map hasher(blake2_128_concat) Cid => ();
 
         /// Blacklist collection counter.
         pub CurrentBlacklistSize get (fn current_blacklist_size): u64;
@@ -1084,7 +1085,7 @@ decl_event! {
         /// Params
         /// - hashes to remove from the blacklist
         /// - hashes to add to the blacklist
-        UpdateBlacklist(BTreeSet<ContentId>, BTreeSet<ContentId>),
+        UpdateBlacklist(BTreeSet<Cid>, BTreeSet<Cid>),
 
         /// Emits on deleting a dynamic bag.
         /// Params
@@ -1601,8 +1602,8 @@ decl_module! {
         #[weight = 10_000_000] // TODO: adjust weight
         pub fn update_blacklist(
             origin,
-            remove_hashes: BTreeSet<ContentId>,
-            add_hashes: BTreeSet<ContentId>
+            remove_hashes: BTreeSet<Cid>,
+            add_hashes: BTreeSet<Cid>
         ){
             T::ensure_storage_working_group_leader_origin(origin)?;
 
@@ -2485,6 +2486,28 @@ decl_module! {
                 )
             );
         }
+
+        // ===== Sudo actions (development mode) =====
+
+        /// Upload new data objects. Development mode.
+        #[weight = 10_000_000] // TODO: adjust weight
+        pub fn sudo_upload_data_objects(origin, params: UploadParameters<T>) {
+            ensure_root(origin)?;
+
+            Self::upload_data_objects(params)?;
+        }
+
+        /// Create a dynamic bag. Development mode.
+        #[weight = 10_000_000] // TODO: adjust weight
+        pub fn sudo_create_dynamic_bag(
+            origin,
+            bag_id: DynamicBagId<T>,
+            deletion_prize: Option<DynamicBagDeletionPrize<T>>,
+        ) {
+            ensure_root(origin)?;
+
+            Self::create_dynamic_bag(bag_id, deletion_prize)?;
+        }
     }
 }
 
@@ -3009,20 +3032,20 @@ impl<T: Trait> Module<T> {
 
     // Returns only existing hashes in the blacklist from the original collection.
     #[allow(clippy::redundant_closure)] // doesn't work with Substrate storage functions.
-    fn get_existing_hashes(hashes: &BTreeSet<ContentId>) -> BTreeSet<ContentId> {
+    fn get_existing_hashes(hashes: &BTreeSet<Cid>) -> BTreeSet<Cid> {
         Self::get_hashes_by_predicate(hashes, |cid| Blacklist::contains_key(cid))
     }
 
     // Returns only nonexisting hashes in the blacklist from the original collection.
-    fn get_nonexisting_hashes(hashes: &BTreeSet<ContentId>) -> BTreeSet<ContentId> {
+    fn get_nonexisting_hashes(hashes: &BTreeSet<Cid>) -> BTreeSet<Cid> {
         Self::get_hashes_by_predicate(hashes, |cid| !Blacklist::contains_key(cid))
     }
 
     // Returns hashes from the original collection selected by predicate.
-    fn get_hashes_by_predicate<P: FnMut(&&ContentId) -> bool>(
-        hashes: &BTreeSet<ContentId>,
+    fn get_hashes_by_predicate<P: FnMut(&&Cid) -> bool>(
+        hashes: &BTreeSet<Cid>,
         predicate: P,
-    ) -> BTreeSet<ContentId> {
+    ) -> BTreeSet<Cid> {
         hashes
             .iter()
             .filter(predicate)

+ 5 - 5
runtime-modules/storage/src/tests/fixtures.rs

@@ -14,7 +14,7 @@ use crate::tests::mocks::{
     DEFAULT_DISTRIBUTION_PROVIDER_ACCOUNT_ID, DISTRIBUTION_WG_LEADER_ACCOUNT_ID,
 };
 use crate::{
-    BagId, ContentId, DataObjectCreationParameters, DataObjectStorage, DistributionBucketFamily,
+    BagId, Cid, DataObjectCreationParameters, DataObjectStorage, DistributionBucketFamily,
     DynamicBagDeletionPrize, DynamicBagId, DynamicBagType, RawEvent, StaticBagId,
     StorageBucketOperatorStatus, UploadParameters,
 };
@@ -720,8 +720,8 @@ impl UpdateStorageBucketStatusFixture {
 
 pub struct UpdateBlacklistFixture {
     origin: RawOrigin<u64>,
-    remove_hashes: BTreeSet<ContentId>,
-    add_hashes: BTreeSet<ContentId>,
+    remove_hashes: BTreeSet<Cid>,
+    add_hashes: BTreeSet<Cid>,
 }
 
 impl UpdateBlacklistFixture {
@@ -737,11 +737,11 @@ impl UpdateBlacklistFixture {
         Self { origin, ..self }
     }
 
-    pub fn with_add_hashes(self, add_hashes: BTreeSet<ContentId>) -> Self {
+    pub fn with_add_hashes(self, add_hashes: BTreeSet<Cid>) -> Self {
         Self { add_hashes, ..self }
     }
 
-    pub fn with_remove_hashes(self, remove_hashes: BTreeSet<ContentId>) -> Self {
+    pub fn with_remove_hashes(self, remove_hashes: BTreeSet<Cid>) -> Self {
         Self {
             remove_hashes,
             ..self

+ 2 - 0
storage-node-v2/.eslintignore

@@ -0,0 +1,2 @@
+/lib
+.eslintrc.js

+ 15 - 0
storage-node-v2/.eslintrc.js

@@ -0,0 +1,15 @@
+module.exports = {
+  env: {
+    mocha: true,
+  },
+  parserOptions: {
+    project: './tsconfig.json'
+  },
+  extends: ['@joystream/eslint-config'],
+  rules: {
+    'no-console': 'warn', // use dedicated logger
+    'no-unused-vars': 'off', // Required by the typescript rule below
+    '@typescript-eslint/no-unused-vars': ['error'],
+    '@typescript-eslint/no-floating-promises': 'error',
+  },
+}

+ 10 - 0
storage-node-v2/.gitignore

@@ -0,0 +1,10 @@
+*-debug.log
+*-error.log
+/.nyc_output
+/dist
+/lib
+/package-lock.json
+/tmp
+node_modules
+/uploads
+/docs

+ 2 - 0
storage-node-v2/.prettierignore

@@ -0,0 +1,2 @@
+/lib/
+.nyc_output

+ 533 - 0
storage-node-v2/README.md

@@ -0,0 +1,533 @@
+storage-node-v2
+===============
+
+Jostream storage subsystem.
+
+[![oclif](https://img.shields.io/badge/cli-oclif-brightgreen.svg)](https://oclif.io)
+[![Version](https://img.shields.io/npm/v/storage-node-v2.svg)](https://npmjs.org/package/storage-node-v2)
+[![Downloads/week](https://img.shields.io/npm/dw/storage-node-v2.svg)](https://npmjs.org/package/storage-node-v2)
+[![License](https://img.shields.io/npm/l/storage-node-v2.svg)](https://github.com/shamil-gadelshin/storage-node-v2/blob/master/package.json)
+
+<!-- toc -->
+* [Usage](#usage)
+* [Commands](#commands)
+<!-- tocstop -->
+# Usage
+<!-- usage -->
+```sh-session
+$ npm install -g storage-node-v2
+$ storage-node COMMAND
+running command...
+$ storage-node (-v|--version|version)
+storage-node-v2/0.1.0 darwin-x64 node-v14.17.0
+$ storage-node --help [COMMAND]
+USAGE
+  $ storage-node COMMAND
+...
+```
+<!-- usagestop -->
+# Commands
+<!-- commands -->
+* [`storage-node dev:init`](#storage-node-devinit)
+* [`storage-node dev:multihash`](#storage-node-devmultihash)
+* [`storage-node dev:upload`](#storage-node-devupload)
+* [`storage-node dev:verify-bag-id`](#storage-node-devverify-bag-id)
+* [`storage-node help [COMMAND]`](#storage-node-help-command)
+* [`storage-node leader:cancel-invite`](#storage-node-leadercancel-invite)
+* [`storage-node leader:create-bucket`](#storage-node-leadercreate-bucket)
+* [`storage-node leader:delete-bucket`](#storage-node-leaderdelete-bucket)
+* [`storage-node leader:invite-operator`](#storage-node-leaderinvite-operator)
+* [`storage-node leader:remove-operator`](#storage-node-leaderremove-operator)
+* [`storage-node leader:set-bucket-limits`](#storage-node-leaderset-bucket-limits)
+* [`storage-node leader:set-global-uploading-status`](#storage-node-leaderset-global-uploading-status)
+* [`storage-node leader:update-bag`](#storage-node-leaderupdate-bag)
+* [`storage-node leader:update-bag-limit`](#storage-node-leaderupdate-bag-limit)
+* [`storage-node leader:update-blacklist`](#storage-node-leaderupdate-blacklist)
+* [`storage-node leader:update-bucket-status`](#storage-node-leaderupdate-bucket-status)
+* [`storage-node leader:update-data-fee`](#storage-node-leaderupdate-data-fee)
+* [`storage-node leader:update-dynamic-bag-policy`](#storage-node-leaderupdate-dynamic-bag-policy)
+* [`storage-node leader:update-voucher-limits`](#storage-node-leaderupdate-voucher-limits)
+* [`storage-node operator:accept-invitation`](#storage-node-operatoraccept-invitation)
+* [`storage-node operator:set-metadata`](#storage-node-operatorset-metadata)
+* [`storage-node server`](#storage-node-server)
+
+## `storage-node dev:init`
+
+Initialize development environment. Sets Alice as storage working group leader.
+
+```
+USAGE
+  $ storage-node dev:init
+
+OPTIONS
+  -h, --help               show CLI help
+  -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                Use development mode
+  -p, --password=password  Key file password (optional).
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
+```
+
+_See code: [src/commands/dev/init.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/dev/init.ts)_
+
+## `storage-node dev:multihash`
+
+Creates a multihash (blake3) for a file.
+
+```
+USAGE
+  $ storage-node dev:multihash
+
+OPTIONS
+  -f, --file=file  (required) Path for a hashing file.
+  -h, --help       show CLI help
+```
+
+_See code: [src/commands/dev/multihash.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/dev/multihash.ts)_
+
+## `storage-node dev:upload`
+
+Upload data object (development mode only).
+
+```
+USAGE
+  $ storage-node dev:upload
+
+OPTIONS
+  -c, --cid=cid            (required) Data object IPFS content ID.
+  -h, --help               show CLI help
+  -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                Use development mode
+  -p, --password=password  Key file password (optional).
+  -s, --size=size          (required) Data object size.
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
+```
+
+_See code: [src/commands/dev/upload.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/dev/upload.ts)_
+
+## `storage-node dev:verify-bag-id`
+
+The command verifies bag id supported by the storage node. Requires chain connection.
+
+```
+USAGE
+  $ storage-node dev:verify-bag-id
+
+OPTIONS
+  -h, --help
+      show CLI help
+
+  -i, --bagId=bagId
+      (required) 
+             Bag ID. Format: {bag_type}:{sub_type}:{id}.
+             - Bag types: 'static', 'dynamic'
+             - Sub types: 'static:council', 'static:wg', 'dynamic:member', 'dynamic:channel'
+             - Id: 
+               - absent for 'static:council'
+               - working group name for 'static:wg'
+               - integer for 'dynamic:member' and 'dynamic:channel'
+             Examples:
+             - static:council
+             - static:wg:storage
+             - dynamic:member:4
+
+  -k, --keyfile=keyfile
+      Key file for the account. Mandatory in non-dev environment.
+
+  -m, --dev
+      Use development mode
+
+  -p, --password=password
+      Key file password (optional).
+
+  -u, --apiUrl=apiUrl
+      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
+```
+
+_See code: [src/commands/dev/verify-bag-id.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/dev/verify-bag-id.ts)_
+
+## `storage-node help [COMMAND]`
+
+display help for storage-node
+
+```
+USAGE
+  $ storage-node help [COMMAND]
+
+ARGUMENTS
+  COMMAND  command to show help for
+
+OPTIONS
+  --all  see all commands in CLI
+```
+
+_See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v3.0.1/src/commands/help.ts)_
+
+## `storage-node leader:cancel-invite`
+
+Cancel a storage bucket operator invite. Requires storage working group leader permissions.
+
+```
+USAGE
+  $ storage-node leader:cancel-invite
+
+OPTIONS
+  -h, --help               show CLI help
+  -i, --bucketId=bucketId  (required) Storage bucket ID
+  -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                Use development mode
+  -p, --password=password  Key file password (optional).
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
+```
+
+_See code: [src/commands/leader/cancel-invite.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/leader/cancel-invite.ts)_
+
+## `storage-node leader:create-bucket`
+
+Create new storage bucket. Requires storage working group leader permissions.
+
+```
+USAGE
+  $ storage-node leader:create-bucket
+
+OPTIONS
+  -a, --allow              Accepts new bags
+  -h, --help               show CLI help
+  -i, --invited=invited    Invited storage operator ID (storage WG worker ID)
+  -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                Use development mode
+  -n, --number=number      Storage bucket max total objects number
+  -p, --password=password  Key file password (optional).
+  -s, --size=size          Storage bucket max total objects size
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
+```
+
+_See code: [src/commands/leader/create-bucket.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/leader/create-bucket.ts)_
+
+## `storage-node leader:delete-bucket`
+
+Delete a storage bucket. Requires storage working group leader permissions.
+
+```
+USAGE
+  $ storage-node leader:delete-bucket
+
+OPTIONS
+  -h, --help               show CLI help
+  -i, --bucketId=bucketId  (required) Storage bucket ID
+  -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                Use development mode
+  -p, --password=password  Key file password (optional).
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
+```
+
+_See code: [src/commands/leader/delete-bucket.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/leader/delete-bucket.ts)_
+
+## `storage-node leader:invite-operator`
+
+Invite a storage bucket operator. Requires storage working group leader permissions.
+
+```
+USAGE
+  $ storage-node leader:invite-operator
+
+OPTIONS
+  -h, --help                   show CLI help
+  -i, --bucketId=bucketId      (required) Storage bucket ID
+  -k, --keyfile=keyfile        Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                    Use development mode
+  -p, --password=password      Key file password (optional).
+  -u, --apiUrl=apiUrl          Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
+  -w, --operatorId=operatorId  (required) Storage bucket operator ID (storage group worker ID)
+```
+
+_See code: [src/commands/leader/invite-operator.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/leader/invite-operator.ts)_
+
+## `storage-node leader:remove-operator`
+
+Remove a storage bucket operator. Requires storage working group leader permissions.
+
+```
+USAGE
+  $ storage-node leader:remove-operator
+
+OPTIONS
+  -h, --help               show CLI help
+  -i, --bucketId=bucketId  (required) Storage bucket ID
+  -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                Use development mode
+  -p, --password=password  Key file password (optional).
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
+```
+
+_See code: [src/commands/leader/remove-operator.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/leader/remove-operator.ts)_
+
+## `storage-node leader:set-bucket-limits`
+
+Set VoucherObjectsSizeLimit and VoucherObjectsNumberLimit for the storage bucket.
+
+```
+USAGE
+  $ storage-node leader:set-bucket-limits
+
+OPTIONS
+  -h, --help               show CLI help
+  -i, --bucketId=bucketId  (required) Storage bucket ID
+  -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                Use development mode
+  -o, --objects=objects    (required) New 'voucher object number limit' value
+  -p, --password=password  Key file password (optional).
+  -s, --size=size          (required) New 'voucher object size limit' value
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
+```
+
+_See code: [src/commands/leader/set-bucket-limits.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/leader/set-bucket-limits.ts)_
+
+## `storage-node leader:set-global-uploading-status`
+
+Set global uploading block. Requires storage working group leader permissions.
+
+```
+USAGE
+  $ storage-node leader:set-global-uploading-status
+
+OPTIONS
+  -h, --help               show CLI help
+  -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                Use development mode
+  -p, --password=password  Key file password (optional).
+  -s, --set=(on|off)       (required) Sets global uploading block (on/off).
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
+```
+
+_See code: [src/commands/leader/set-global-uploading-status.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/leader/set-global-uploading-status.ts)_
+
+## `storage-node leader:update-bag`
+
+Add/remove a storage bucket from a bag (adds by default).
+
+```
+USAGE
+  $ storage-node leader:update-bag
+
+OPTIONS
+  -a, --add=add
+      [default: ] ID of a bucket to add to bag
+
+  -h, --help
+      show CLI help
+
+  -i, --bagId=bagId
+      (required) 
+             Bag ID. Format: {bag_type}:{sub_type}:{id}.
+             - Bag types: 'static', 'dynamic'
+             - Sub types: 'static:council', 'static:wg', 'dynamic:member', 'dynamic:channel'
+             - Id: 
+               - absent for 'static:council'
+               - working group name for 'static:wg'
+               - integer for 'dynamic:member' and 'dynamic:channel'
+             Examples:
+             - static:council
+             - static:wg:storage
+             - dynamic:member:4
+
+  -k, --keyfile=keyfile
+      Key file for the account. Mandatory in non-dev environment.
+
+  -m, --dev
+      Use development mode
+
+  -p, --password=password
+      Key file password (optional).
+
+  -r, --remove=remove
+      [default: ] ID of a bucket to remove from bag
+
+  -u, --apiUrl=apiUrl
+      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
+```
+
+_See code: [src/commands/leader/update-bag.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/leader/update-bag.ts)_
+
+## `storage-node leader:update-bag-limit`
+
+Update StorageBucketsPerBagLimit variable in the Joystream node storage.
+
+```
+USAGE
+  $ storage-node leader:update-bag-limit
+
+OPTIONS
+  -h, --help               show CLI help
+  -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
+  -l, --limit=limit        (required) New StorageBucketsPerBagLimit value
+  -m, --dev                Use development mode
+  -p, --password=password  Key file password (optional).
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
+```
+
+_See code: [src/commands/leader/update-bag-limit.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/leader/update-bag-limit.ts)_
+
+## `storage-node leader:update-blacklist`
+
+Add/remove a content ID from the blacklist (adds by default).
+
+```
+USAGE
+  $ storage-node leader:update-blacklist
+
+OPTIONS
+  -a, --add=add            [default: ] Content ID to add
+  -h, --help               show CLI help
+  -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                Use development mode
+  -p, --password=password  Key file password (optional).
+  -r, --remove=remove      [default: ] Content ID to remove
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
+```
+
+_See code: [src/commands/leader/update-blacklist.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/leader/update-blacklist.ts)_
+
+## `storage-node leader:update-bucket-status`
+
+Update storage bucket status (accepting new bags).
+
+```
+USAGE
+  $ storage-node leader:update-bucket-status
+
+OPTIONS
+  -d, --disable            Disables accepting new bags.
+  -e, --enable             Enables accepting new bags (default).
+  -h, --help               show CLI help
+  -i, --bucketId=bucketId  (required) Storage bucket ID
+  -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                Use development mode
+  -p, --password=password  Key file password (optional).
+  -s, --set=(on|off)       (required) Sets 'accepting new bags' parameter for the bucket (on/off).
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
+```
+
+_See code: [src/commands/leader/update-bucket-status.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/leader/update-bucket-status.ts)_
+
+## `storage-node leader:update-data-fee`
+
+Update data size fee. Requires storage working group leader permissions.
+
+```
+USAGE
+  $ storage-node leader:update-data-fee
+
+OPTIONS
+  -f, --fee=fee            (required) New data size fee
+  -h, --help               show CLI help
+  -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                Use development mode
+  -p, --password=password  Key file password (optional).
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
+```
+
+_See code: [src/commands/leader/update-data-fee.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/leader/update-data-fee.ts)_
+
+## `storage-node leader:update-dynamic-bag-policy`
+
+Update number of storage buckets used in the dynamic bag creation policy.
+
+```
+USAGE
+  $ storage-node leader:update-dynamic-bag-policy
+
+OPTIONS
+  -h, --help                      show CLI help
+  -k, --keyfile=keyfile           Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                       Use development mode
+  -n, --number=number             (required) New storage buckets number
+  -p, --password=password         Key file password (optional).
+  -t, --bagType=(Channel|Member)  (required) Dynamic bag type (Channel, Member).
+  -u, --apiUrl=apiUrl             Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
+```
+
+_See code: [src/commands/leader/update-dynamic-bag-policy.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/leader/update-dynamic-bag-policy.ts)_
+
+## `storage-node leader:update-voucher-limits`
+
+Update VoucherMaxObjectsSizeLimit and VoucherMaxObjectsNumberLimit for the Joystream node storage.
+
+```
+USAGE
+  $ storage-node leader:update-voucher-limits
+
+OPTIONS
+  -h, --help               show CLI help
+  -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                Use development mode
+  -o, --objects=objects    (required) New 'max voucher object number limit' value
+  -p, --password=password  Key file password (optional).
+  -s, --size=size          (required) New 'max voucher object size limit' value
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
+```
+
+_See code: [src/commands/leader/update-voucher-limits.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/leader/update-voucher-limits.ts)_
+
+## `storage-node operator:accept-invitation`
+
+Accept pending storage bucket invitation.
+
+```
+USAGE
+  $ storage-node operator:accept-invitation
+
+OPTIONS
+  -h, --help               show CLI help
+  -i, --bucketId=bucketId  (required) Storage bucket ID
+  -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                Use development mode
+  -p, --password=password  Key file password (optional).
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
+  -w, --workerId=workerId  (required) Storage operator worker ID
+```
+
+_See code: [src/commands/operator/accept-invitation.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/operator/accept-invitation.ts)_
+
+## `storage-node operator:set-metadata`
+
+Accept pending storage bucket invitation.
+
+```
+USAGE
+  $ storage-node operator:set-metadata
+
+OPTIONS
+  -h, --help                   show CLI help
+  -i, --bucketId=bucketId      (required) Storage bucket ID
+  -k, --keyfile=keyfile        Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                    Use development mode
+  -m, --metadata=metadata      Storage bucket operator metadata
+  -p, --password=password      Key file password (optional).
+  -u, --apiUrl=apiUrl          Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
+  -w, --operatorId=operatorId  (required) Storage bucket operator ID (storage group worker ID)
+```
+
+_See code: [src/commands/operator/set-metadata.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/operator/set-metadata.ts)_
+
+## `storage-node server`
+
+Starts the storage node server.
+
+```
+USAGE
+  $ storage-node server
+
+OPTIONS
+  -d, --uploads=uploads    (required) Data uploading directory (absolute path).
+  -h, --help               show CLI help
+  -k, --keyfile=keyfile    Key file for the account. Mandatory in non-dev environment.
+  -m, --dev                Use development mode
+  -o, --port=port          (required) Server port.
+  -p, --password=password  Key file password (optional).
+  -u, --apiUrl=apiUrl      Runtime API URL. Mandatory in non-dev environment. Default is ws://localhost:9944
+  -w, --worker=worker      (required) Storage provider worker ID
+```
+
+_See code: [src/commands/server.ts](https://github.com/Joystream/joystream/blob/v0.1.0/src/commands/server.ts)_
+
+<!-- commandsstop -->

+ 5 - 0
storage-node-v2/bin/run

@@ -0,0 +1,5 @@
+#!/usr/bin/env node
+
+require('@oclif/command').run()
+.then(require('@oclif/command/flush'))
+.catch(require('@oclif/errors/handle'))

+ 3 - 0
storage-node-v2/bin/run.cmd

@@ -0,0 +1,3 @@
+@echo off
+
+node "%~dp0\run" %*

+ 115 - 0
storage-node-v2/package.json

@@ -0,0 +1,115 @@
+{
+  "name": "storage-node-v2",
+  "description": "Jostream storage subsystem.",
+  "version": "0.1.0",
+  "author": "Joystream contributors",
+  "bin": {
+    "storage-node": "./bin/run"
+  },
+  "bugs": "https://github.com/Joystream/joystream/issues",
+  "dependencies": {
+    "@joystream/types": "^0.17.0",
+    "@oclif/command": "^1",
+    "@oclif/config": "^1",
+    "@oclif/plugin-help": "^3",
+    "@polkadot/api": "4.2.1",
+    "@types/base64url": "^2.0.0",
+    "@types/express": "4.17.1",
+    "@types/file-type": "^10.9.1",
+    "@types/multer": "^1.4.5",
+    "@types/node-cache": "^4.2.5",
+    "@types/read-chunk": "^3.1.0",
+    "@types/send": "^0.17.0",
+    "@types/winston": "^2.4.4",
+    "await-lock": "^2.1.0",
+    "base64url": "^3.0.1",
+    "blake3": "^2.1.4",
+    "express": "4.17.1",
+    "express-openapi-validator": "^4.12.4",
+    "express-winston": "^4.1.0",
+    "file-type": "^16.5.0",
+    "lodash": "^4.17.21",
+    "multihashes": "^4.0.2",
+    "node-cache": "^5.1.2",
+    "openapi-editor": "^0.3.0",
+    "read-chunk": "^3.2.0",
+    "send": "^0.17.1",
+    "tslib": "^1",
+    "winston": "^3.3.3"
+  },
+  "devDependencies": {
+    "@joystream/eslint-config": "^1.0.0",
+    "@oclif/dev-cli": "^1",
+    "@oclif/test": "^1",
+    "@types/chai": "^4",
+    "@types/mocha": "^5",
+    "@types/node": "^10",
+    "@types/swagger-ui-express": "^4.1.2",
+    "@typescript-eslint/eslint-plugin": "3.8.0",
+    "@typescript-eslint/parser": "3.8.0",
+    "chai": "^4",
+    "eslint": "^7.6.0",
+    "eslint-config-oclif": "^3.1",
+    "eslint-config-oclif-typescript": "^0.1",
+    "globby": "^10",
+    "mocha": "^5",
+    "nyc": "^14",
+    "prettier": "^2.3.0",
+    "sinon": "^11.1.1",
+    "swagger-ui-express": "^4.1.6",
+    "ts-node": "^8.8.2",
+    "type-doc": "^0.1.41",
+    "typescript": "^3.3"
+  },
+  "engines": {
+    "node": ">=8.0.0"
+  },
+  "volta": {
+    "node": "12.18.2",
+    "yarn": "1.22.4"
+  },
+  "files": [
+    "/bin",
+    "/lib",
+    "/npm-shrinkwrap.json",
+    "/oclif.manifest.json"
+  ],
+  "homepage": "https://github.com/Joystream/joystream",
+  "keywords": [
+    "joystream",
+    "storage-node"
+  ],
+  "license": "GPL-3.0-only",
+  "main": "lib/index.js",
+  "oclif": {
+    "commands": "./lib/commands",
+    "bin": "storage-node",
+    "plugins": [
+      "@oclif/plugin-help"
+    ],
+    "topics": {
+      "wg": {
+        "description": "Storage working group commands."
+      },
+      "wg:leader": {
+        "description": "Storage working group leader commands."
+      }
+    }
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/Joystream/joystream",
+    "directory": "storage-node-v2"
+  },
+  "scripts": {
+    "postpack": "rm -f oclif.manifest.json",
+    "posttest": "yarn lint",
+    "prepack": "rm -rf lib && tsc -b && oclif-dev manifest && oclif-dev readme",
+    "version": "oclif-dev readme && git add README.md",
+    "build": "tsc --build tsconfig.json",
+    "format": "prettier ./src --write",
+    "lint": "eslint ./src --ext .ts",
+    "api:edit": "openapi-editor --file ./src/api-spec/openapi.yaml --port 10021"
+  },
+  "types": "lib/index.d.ts"
+}

+ 30 - 0
storage-node-v2/scripts/create-auth-request-signature.ts

@@ -0,0 +1,30 @@
+#!/usr/bin/env ts-node
+
+import { getAlicePair } from '../src/services/runtime/accounts'
+import { cryptoWaitReady } from '@polkadot/util-crypto'
+import { UploadTokenRequestBody, signTokenBody, UploadTokenRequest } from '../src/services/helpers/auth'
+import { exit } from 'process'
+
+//Wasm init
+cryptoWaitReady().then(() => {
+
+  const alice = getAlicePair()
+
+  const tokenRequestBody: UploadTokenRequestBody = {
+    memberId: 0,
+    accountId: alice.address,
+    dataObjectId: 0,
+    storageBucketId: 0,
+    bagId: 'static:council'
+  }
+  
+  const signature = signTokenBody(tokenRequestBody, alice)
+  const tokenRequest: UploadTokenRequest = {
+    data: tokenRequestBody,
+    signature
+  }
+
+  console.log(JSON.stringify(tokenRequest))
+
+  exit(0)
+})

+ 17 - 0
storage-node-v2/scripts/init-dev-bucket.sh

@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+
+# Must be run on the clean development chain.
+# It prepares an environment, creates a storage bucket and links it to the
+# 'static council bag'.
+
+SCRIPT_PATH="$(dirname "${BASH_SOURCE[0]}")"
+cd $SCRIPT_PATH
+
+CLI=../bin/run
+
+${CLI} dev:init
+${CLI} leader:update-bag-limit -l 7 --dev
+${CLI} leader:update-voucher-limits -o 100 -s 10000000 --dev
+BUCKET_ID=`${CLI} leader:create-bucket -i=0 -a -n=100 -s=10000000  --dev` 
+${CLI} operator:accept-invitation -w=0 -i=${BUCKET_ID} --dev
+${CLI} leader:update-bag -a=${BUCKET_ID} -i static:council --dev 

+ 47 - 0
storage-node-v2/scripts/run-all-commands.sh

@@ -0,0 +1,47 @@
+#!/usr/bin/env bash
+
+
+# Must be run on the clean development chain.
+# It tests all leader and operator commands.
+
+
+SCRIPT_PATH="$(dirname "${BASH_SOURCE[0]}")"
+cd $SCRIPT_PATH
+
+CLI=../bin/run
+
+# Set Alice as leader
+${CLI}  dev:init # leader workerId = 0
+
+# Update limits and constants
+${CLI} leader:update-bag-limit -l 7 --dev
+${CLI} leader:update-voucher-limits -o 100 -s 10000000 --dev
+${CLI} leader:update-data-fee -f 10000 --dev
+${CLI} leader:update-dynamic-bag-policy -n 10 -t Member --dev
+
+# Create and configure a bucket.
+BUCKET_ID=`${CLI} leader:create-bucket -i=0 --dev` # bucketId = 0
+${CLI} operator:accept-invitation -w=0 -i=${BUCKET_ID} --dev
+${CLI} leader:set-bucket-limits -i=${BUCKET_ID} -o=100 -s=10000000 --dev
+${CLI} leader:update-bucket-status -i=${BUCKET_ID} --set on --dev
+${CLI} leader:update-bag -a=${BUCKET_ID} -i static:council --dev 
+${CLI} operator:set-metadata -w=0 -i=${BUCKET_ID} -m=http://google.com --dev
+
+# Create and delete a bucket
+BUCKET_ID=`${CLI} leader:create-bucket -a -n=100 -s=10000000  --dev` # bucketId = 1
+${CLI} leader:delete-bucket -i=${BUCKET_ID}  --dev 
+
+# Create a bucket, invite operator, cancel invite, accept invitation and remove operator.
+BUCKET_ID=`${CLI} leader:create-bucket -a -n=100 -s=10000000  --dev` # bucketId = 2
+${CLI} leader:invite-operator -i=${BUCKET_ID} -w=0  --dev 
+${CLI} leader:cancel-invite -i=${BUCKET_ID} --dev 
+${CLI} leader:invite-operator -i=${BUCKET_ID} -w=0  --dev 
+${CLI} operator:accept-invitation -i=${BUCKET_ID} -w=0 --dev
+${CLI} leader:remove-operator -i=${BUCKET_ID}   --dev 
+
+# Toggle uploading block.
+${CLI} leader:set-global-uploading-status --set on --dev 
+${CLI} leader:set-global-uploading-status --set off --dev 
+
+# Blacklist.
+${CLI} leader:update-blacklist -a BLACKLISTED_CID -r SOME_CID --dev

+ 223 - 0
storage-node-v2/src/api-spec/openapi.yaml

@@ -0,0 +1,223 @@
+openapi: 3.0.3
+info:
+  title: Storage node API
+  description: Storage node API
+  contact:
+    email: info@joystream.org
+  license:
+    name: GPL-3.0-only
+    url: https://opensource.org/licenses/GPL-3.0
+  version: 0.1.0
+externalDocs:
+  description: Storage node API
+  url: https://github.com/Joystream/joystream/issues/2224
+servers:
+  - url: http://localhost:3333/api/v1/
+
+tags:
+  - name: public
+    description: Public storage node API
+
+paths:
+  /files/{cid}:
+    get:
+      operationId: publicApi.getFile
+      description: Returns a media file.
+      tags:
+        - public
+      parameters:
+        - name: cid
+          required: true
+          in: path
+          description: Content ID
+          schema:
+            type: string
+      responses:
+        200:
+          description: Ok
+          content:
+            video/*:
+              schema:
+                type: string
+                format: binary
+            audio/*:
+              schema:
+                type: string
+                format: binary
+            image/*:
+              schema:
+                type: string
+                format: binary
+            application/octet-stream:
+              schema:
+                type: string
+                format: binary
+        400:
+          description: Bad request
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+        401:
+          description: Unauthorized
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+        404:
+          description: File not found
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+        500:
+          description: Unknown server error
+    head:
+      operationId: publicApi.getFileHeaders
+      description: Returns a media file headers.
+      tags:
+        - public
+      parameters:
+        - name: cid
+          required: true
+          in: path
+          description: Content ID
+          schema:
+            type: string
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+        404:
+          description: File not found
+        500:
+          description: Unknown server error
+  /files:
+    post:
+      security:
+        - UploadAuth: []
+      description: Upload data
+      operationId: publicApi.uploadFile
+      tags:
+        - public
+      requestBody:
+        content:
+          multipart/form-data:
+            schema:
+              type: object
+              required:
+                - dataObjectId
+                - storageBucketId
+                - bagId
+              properties:
+                file:
+                  description: Data file
+                  type: string
+                  format: binary
+                dataObjectId:
+                  description: Data object runtime ID
+                  type: string
+                  pattern: '^\d+$' #integer
+                storageBucketId:
+                  description: Storage bucket ID
+                  type: string
+                  pattern: '^\d+$' #integer
+                bagId:
+                  description: Bag ID
+                  type: string
+        required: true
+      responses:
+        201:
+          description: Created
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  id:
+                    type: string
+        400:
+          description: Bad request
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+        401:
+          description: Unauthorized
+
+  /authToken:
+    post:
+      description: Get auth token from a server.
+      operationId: publicApi.authTokenForUploading
+      tags:
+        - public
+      requestBody:
+        description: Token request parameters,
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/TokenRequest'
+      responses:
+        201:
+          description: Created
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  token:
+                    type: string
+        400:
+          description: Bad request
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+
+components:
+  securitySchemes:
+    UploadAuth:
+      type: apiKey
+      in: header
+      name: x-api-key
+  schemas:
+    TokenRequest:
+      type: object
+      required:
+        - data
+        - signature
+      properties:
+        data:
+          type: object
+          required:
+            - memberId
+            - accountId
+            - dataObjectId
+            - storageBucketId
+            - bagId
+          properties:
+            memberId:
+              type: integer
+              format: int64
+            accountId:
+              type: string
+            dataObjectId:
+              type: integer
+              format: int64
+            storageBucketId:
+              type: integer
+              format: int64
+            bagId:
+              type: string
+        signature:
+          type: string
+    ErrorResponse:
+      type: object
+      required:
+        - message
+      properties:
+        type:
+          type: string
+        message:
+          type: string

+ 171 - 0
storage-node-v2/src/command-base/ApiCommandBase.ts

@@ -0,0 +1,171 @@
+import { Command, flags } from '@oclif/command'
+import { createApi } from '../services/runtime/api'
+import { getAccountFromJsonFile, getAlicePair, getAccountFromUri } from '../services/runtime/accounts'
+import { KeyringPair } from '@polkadot/keyring/types'
+import { ApiPromise } from '@polkadot/api'
+import logger from '../services/logger'
+import ExitCodes from './ExitCodes'
+import { CLIError } from '@oclif/errors'
+import { Input } from '@oclif/parser'
+import _ from 'lodash'
+
+/**
+ * Parent class for all runtime-based commands. Defines common functions.
+ */
+export default abstract class ApiCommandBase extends Command {
+  private api: ApiPromise | null = null
+
+  static flags = {
+    help: flags.help({ char: 'h' }),
+    dev: flags.boolean({ char: 'm', description: 'Use development mode', default: false }),
+    apiUrl: flags.string({
+      char: 'u',
+      description: 'Runtime API URL. Mandatory in non-dev environment.',
+      default: 'ws://localhost:9944',
+    }),
+    keyfile: flags.string({
+      char: 'k',
+      description: 'Key file for the account. Mandatory in non-dev environment.',
+    }),
+    password: flags.string({
+      char: 'p',
+      description: 'Key file password (optional). Could be overriden by ACCOUNT_PWD environment variable.',
+    }),
+    accountURI: flags.string({
+      char: 'y',
+      description:
+        'Account URI (optional). Has a priority over the keyfile and password flags. Could be overriden by ACCOUNT_URI environment variable.',
+    }),
+  }
+
+  /**
+   * Returns the runtime API promise.
+   *
+   * @returns void promise.
+   */
+  async finally(err: Error | undefined): Promise<void> {
+    // called after run and catch regardless of whether or not the command errored
+    // We'll force exit here, in case there is no error, to prevent console.log from hanging the process
+    if (!err) this.exit(0)
+    super.finally(err)
+  }
+
+  /**
+   * Returns the runtime API promise.
+   */
+  protected async getApi(): Promise<ApiPromise> {
+    if (this.api === null) {
+      throw new CLIError('Runtime Api is uninitialized.', {
+        exit: ExitCodes.ApiError,
+      })
+    }
+
+    return this.api
+  }
+
+  /**
+   * Initilizes the runtime API using the URL from the command line or the
+   * default value (ws://localhost:9944)
+   */
+  async init(): Promise<void> {
+    // Oclif hack: https://github.com/oclif/oclif/issues/225#issuecomment-490555119
+    /* eslint-disable @typescript-eslint/no-explicit-any */
+    const { flags } = this.parse(<Input<any>>this.constructor)
+
+    // Some dev commands doesn't contain flags variables.
+    const apiUrl = flags.apiUrl ?? 'ws://localhost:9944'
+    this.api = await createApi(apiUrl)
+
+    logger.info(`Initialized runtime connection: ${apiUrl}`)
+
+    await this.getApi()
+  }
+
+  /**
+   * Read the chain name from the runtime and throws an error if it's
+   * not 'Development' chain.
+   */
+  async ensureDevelopmentChain(): Promise<void> {
+    const api = await this.getApi()
+
+    const chainType = await api.rpc.system.chainType()
+
+    if (!chainType.isDevelopment && !chainType.isLocal) {
+      throw new CLIError('This command should only be run on a Development chain.', {
+        exit: ExitCodes.DevelopmentModeOnly,
+      })
+    }
+
+    logger.info('Development mode is ON.')
+  }
+
+  /**
+   * Returns the intialized account KeyringPair instance. Loads the account
+   * JSON-file or loads 'Alice' Keypair when in the development mode.
+   *
+   * @param dev - indicates the development mode (optional).
+   * @param keyfile - key file path (optional).
+   * @param password - password for the key file (optional).
+   * @param accountURI - accountURI (optional). Overrides keyfile and password flags.
+   * @returns KeyringPair instance.
+   */
+  getAccount(flags: { dev: boolean; keyfile?: string; password?: string; accountURI?: string }): KeyringPair {
+    // Select account URI variable from flags key and environment variable.
+    let accountURI = flags.accountURI ?? ''
+    if (!_.isEmpty(process.env.ACCOUNT_URI)) {
+      if (!_.isEmpty(flags.accountURI)) {
+        logger.warn(
+          `Both enviroment variable and command line argument were provided for the account URI. Environment variable has a priority.`
+        )
+      }
+      accountURI = process.env.ACCOUNT_URI ?? ''
+    }
+
+    // Select password variable from flags key and environment variable.
+    let password = flags.password
+    if (!_.isEmpty(process.env.ACCOUNT_PWD)) {
+      if (!_.isEmpty(flags.password)) {
+        logger.warn(
+          `Both enviroment variable and command line argument were provided for the password. Environment variable has a priority.`
+        )
+      }
+      password = process.env.ACCOUNT_PWD ?? ''
+    }
+
+    const keyfile = flags.keyfile ?? ''
+    // Create the Alice account for development mode.
+    if (flags.dev) {
+      return getAlicePair()
+    }
+    // Create an account using account URI
+    else if (!_.isEmpty(accountURI)) {
+      return getAccountFromUri(accountURI)
+    }
+    // Create an account using the keyfile and password.
+    else if (!_.isEmpty(keyfile)) {
+      const account = getAccountFromJsonFile(keyfile)
+      account.unlock(password)
+
+      return account
+    }
+    // Cannot create any account for these parameters.
+    else {
+      this.error('Keyfile or account URI must be set.')
+    }
+  }
+
+  /**
+   * Helper-function for exit after the CLI command. It changes the exit code
+   * depending on the previous extrinsic call success.
+   *
+   * @returns never returns.
+   */
+  exitAfterRuntimeCall(success: boolean): never {
+    let exitCode = ExitCodes.OK
+    if (!success) {
+      exitCode = ExitCodes.UnsuccessfulRuntimeCall
+    }
+
+    this.exit(exitCode)
+  }
+}

+ 15 - 0
storage-node-v2/src/command-base/ExitCodes.ts

@@ -0,0 +1,15 @@
+/**
+ * CLI process exit codes.
+ *
+ */
+enum ExitCodes {
+  OK = 0,
+
+  InvalidParameters = 100,
+  DevelopmentModeOnly,
+  FileError,
+  ApiError = 200,
+  UnsuccessfulRuntimeCall,
+}
+
+export = ExitCodes

+ 21 - 0
storage-node-v2/src/commands/dev/init.ts

@@ -0,0 +1,21 @@
+import { hireStorageWorkingGroupLead } from '../../services/runtime/hireLead'
+import ApiCommandBase from '../../command-base/ApiCommandBase'
+/**
+ * CLI command:
+ * Initialize development environment. Sets Alice as storage working group
+ * leader.
+ *
+ * @remarks
+ * Should be run only during the development.
+ * Shell command: "dev:init"
+ */
+export default class DevInit extends ApiCommandBase {
+  static description = 'Initialize development environment. Sets Alice as storage working group leader.'
+
+  async run(): Promise<void> {
+    await this.ensureDevelopmentChain()
+
+    const api = await this.getApi()
+    await hireStorageWorkingGroupLead(api)
+  }
+}

+ 39 - 0
storage-node-v2/src/commands/dev/multihash.ts

@@ -0,0 +1,39 @@
+import { Command, flags } from '@oclif/command'
+import { hashFile } from '../../services/helpers/hashing'
+import logger, { createStdConsoleLogger } from '../../services/logger'
+
+/**
+ * CLI command:
+ * Hashes the file using blake3 algorithm, convert the hash in the multihash
+ * format.
+ *
+ * @remarks
+ * Should be run only during the development.
+ * Shell command: "dev:multihash"
+ */
+export default class DevMultihash extends Command {
+  static description = 'Creates a multihash (blake3) for a file.'
+
+  static flags = {
+    help: flags.help({ char: 'h' }),
+    file: flags.string({
+      char: 'f',
+      required: true,
+      description: 'Path for a hashing file.',
+    }),
+  }
+
+  async run(): Promise<void> {
+    const { flags } = this.parse(DevMultihash)
+
+    logger.info(`Hashing ${flags.file} ....`)
+
+    const multi = await hashFile(flags.file)
+
+    logger.info(`Hash: ${multi}`)
+
+    const stdConsoleLogger = createStdConsoleLogger()
+
+    stdConsoleLogger.info(multi)
+  }
+}

+ 49 - 0
storage-node-v2/src/commands/dev/upload.ts

@@ -0,0 +1,49 @@
+import { flags } from '@oclif/command'
+import { uploadDataObjects } from '../../services/runtime/extrinsics'
+import ApiCommandBase from '../../command-base/ApiCommandBase'
+import logger from '../../services/logger'
+
+/**
+ * CLI command:
+ * Registers the data object (content ID and its size) in the runtime.
+ *
+ * @remarks
+ * Should be run only during the development.
+ * Shell command: "dev:upload"
+ */
+export default class DevUpload extends ApiCommandBase {
+  static description = 'Upload data object (development mode only).'
+
+  static flags = {
+    size: flags.integer({
+      char: 's',
+      required: true,
+      description: 'Data object size.',
+    }),
+    cid: flags.string({
+      char: 'c',
+      required: true,
+      description: 'Data object IPFS content ID.',
+    }),
+    ...ApiCommandBase.flags,
+  }
+
+  async run(): Promise<void> {
+    const { flags } = this.parse(DevUpload)
+
+    await this.ensureDevelopmentChain()
+
+    const objectSize = flags.size
+    const objectCid = flags.cid
+
+    logger.info('Uploading data objects...')
+
+    const api = await this.getApi()
+
+    const dataFee = await api.query.storage.dataObjectPerMegabyteFee()
+
+    logger.info(`Current data fee: ${dataFee}`)
+
+    await uploadDataObjects(api, objectSize, objectCid, dataFee.toNumber())
+  }
+}

+ 47 - 0
storage-node-v2/src/commands/dev/verify-bag-id.ts

@@ -0,0 +1,47 @@
+import { flags } from '@oclif/command'
+import ApiCommandBase from '../../command-base/ApiCommandBase'
+import { parseBagId } from '../../services/helpers/bagTypes'
+import logger from '../../services/logger'
+
+/**
+ * CLI command:
+ * Verifies supported bag ID types in the string format.
+ *
+ * @remarks
+ * Should be run only during the development.
+ * Shell command: "dev:verify-bag-id"
+ */
+export default class DevVerifyBagId extends ApiCommandBase {
+  static description = 'The command verifies bag id supported by the storage node. Requires chain connection.'
+
+  static flags = {
+    bagId: flags.string({
+      char: 'i',
+      required: true,
+      description: `
+      Bag ID. Format: {bag_type}:{sub_type}:{id}.
+      - Bag types: 'static', 'dynamic'
+      - Sub types: 'static:council', 'static:wg', 'dynamic:member', 'dynamic:channel'
+      - Id: 
+        - absent for 'static:council'
+        - working group name for 'static:wg'
+        - integer for 'dynamic:member' and 'dynamic:channel'
+      Examples:
+      - static:council
+      - static:wg:storage
+      - dynamic:member:4
+      `,
+    }),
+    ...ApiCommandBase.flags,
+  }
+
+  async run(): Promise<void> {
+    const { flags } = this.parse(DevVerifyBagId)
+
+    const api = await this.getApi()
+    const parsedBagId = parseBagId(api, flags.bagId)
+
+    logger.info(`Correct bag id: ${flags.bagId}`)
+    logger.info(`Parsed: ${parsedBagId}`)
+  }
+}

+ 43 - 0
storage-node-v2/src/commands/leader/cancel-invite.ts

@@ -0,0 +1,43 @@
+import { cancelStorageBucketOperatorInvite } from '../../services/runtime/extrinsics'
+import { flags } from '@oclif/command'
+import ApiCommandBase from '../../command-base/ApiCommandBase'
+import logger from '../../services/logger'
+
+/**
+ * CLI command:
+ * Updates the storage bucket status (accept new bags).
+ *
+ * @remarks
+ * Storage working group leader command. Requires storage WG leader priviliges.
+ * Shell command: "leader:cancel-invite"
+ */
+export default class LeaderCancelInvite extends ApiCommandBase {
+  static description = `Cancel a storage bucket operator invite. Requires storage working group leader permissions.`
+
+  static flags = {
+    bucketId: flags.integer({
+      char: 'i',
+      required: true,
+      description: 'Storage bucket ID',
+    }),
+    ...ApiCommandBase.flags,
+  }
+
+  async run(): Promise<void> {
+    const { flags } = this.parse(LeaderCancelInvite)
+
+    const storageBucketId = flags.bucketId
+
+    logger.info('Canceling storage bucket operator invite...')
+    if (flags.dev) {
+      await this.ensureDevelopmentChain()
+    }
+
+    const account = this.getAccount(flags)
+    const api = await this.getApi()
+
+    const success = await cancelStorageBucketOperatorInvite(api, account, storageBucketId)
+
+    this.exitAfterRuntimeCall(success)
+  }
+}

+ 65 - 0
storage-node-v2/src/commands/leader/create-bucket.ts

@@ -0,0 +1,65 @@
+import { createStorageBucket } from '../../services/runtime/extrinsics'
+import { flags } from '@oclif/command'
+import ApiCommandBase from '../../command-base/ApiCommandBase'
+import logger, { createStdConsoleLogger } from '../../services/logger'
+
+/**
+ * CLI command:
+ * Creates a storage bucket.
+ *
+ * @remarks
+ * Storage working group leader command. Requires storage WG leader priviliges.
+ * Shell command: "leader:create-bucket"
+ */
+export default class LeaderCreateBucket extends ApiCommandBase {
+  static description = `Create new storage bucket. Requires storage working group leader permissions.`
+
+  static flags = {
+    size: flags.integer({
+      char: 's',
+      description: 'Storage bucket max total objects size',
+    }),
+    number: flags.integer({
+      char: 'n',
+      description: 'Storage bucket max total objects number',
+    }),
+    invited: flags.integer({
+      char: 'i',
+      description: 'Invited storage operator ID (storage WG worker ID)',
+    }),
+    allow: flags.boolean({ char: 'a', description: 'Accepts new bags' }),
+    ...ApiCommandBase.flags,
+  }
+
+  async run(): Promise<void> {
+    const { flags } = this.parse(LeaderCreateBucket)
+
+    const objectSize = flags.size ?? 0
+    const objectNumber = flags.number ?? 0
+    const allowNewBags = flags.allow
+    const invitedWorker = flags.invited
+
+    logger.info('Creating storage bucket...')
+    if (flags.dev) {
+      await this.ensureDevelopmentChain()
+    }
+
+    const account = this.getAccount(flags)
+    const api = await this.getApi()
+
+    const [success, bucketId] = await createStorageBucket(
+      api,
+      account,
+      invitedWorker,
+      allowNewBags,
+      objectSize,
+      objectNumber
+    )
+    if (success) {
+      const stdConsoleLogger = createStdConsoleLogger()
+
+      stdConsoleLogger.info(bucketId)
+    }
+    this.exitAfterRuntimeCall(success)
+  }
+}

+ 43 - 0
storage-node-v2/src/commands/leader/delete-bucket.ts

@@ -0,0 +1,43 @@
+import { deleteStorageBucket } from '../../services/runtime/extrinsics'
+import { flags } from '@oclif/command'
+import ApiCommandBase from '../../command-base/ApiCommandBase'
+import logger from '../../services/logger'
+
+/**
+ * CLI command:
+ * Deletes a storage bucket.
+ *
+ * @remarks
+ * Storage working group leader command. Requires storage WG leader priviliges.
+ * Shell command: "leader:delete-bucket"
+ */
+export default class LeaderDeleteBucket extends ApiCommandBase {
+  static description = `Delete a storage bucket. Requires storage working group leader permissions.`
+
+  static flags = {
+    bucketId: flags.integer({
+      char: 'i',
+      required: true,
+      description: 'Storage bucket ID',
+    }),
+    ...ApiCommandBase.flags,
+  }
+
+  async run(): Promise<void> {
+    const { flags } = this.parse(LeaderDeleteBucket)
+
+    const storageBucketId = flags.bucketId
+
+    logger.info('Deleting storage bucket...')
+    if (flags.dev) {
+      await this.ensureDevelopmentChain()
+    }
+
+    const account = this.getAccount(flags)
+    const api = await this.getApi()
+
+    const success = await deleteStorageBucket(api, account, storageBucketId)
+
+    this.exitAfterRuntimeCall(success)
+  }
+}

+ 49 - 0
storage-node-v2/src/commands/leader/invite-operator.ts

@@ -0,0 +1,49 @@
+import { inviteStorageBucketOperator } from '../../services/runtime/extrinsics'
+import { flags } from '@oclif/command'
+import ApiCommandBase from '../../command-base/ApiCommandBase'
+import logger from '../../services/logger'
+
+/**
+ * CLI command:
+ * Invites a storage bucket operator.
+ *
+ * @remarks
+ * Storage working group leader command. Requires storage WG leader priviliges.
+ * Shell command: "leader:invite-operator"
+ */
+export default class LeaderInviteOperator extends ApiCommandBase {
+  static description = `Invite a storage bucket operator. Requires storage working group leader permissions.`
+
+  static flags = {
+    bucketId: flags.integer({
+      char: 'i',
+      required: true,
+      description: 'Storage bucket ID',
+    }),
+    operatorId: flags.integer({
+      char: 'w',
+      required: true,
+      description: 'Storage bucket operator ID (storage group worker ID)',
+    }),
+    ...ApiCommandBase.flags,
+  }
+
+  async run(): Promise<void> {
+    const { flags } = this.parse(LeaderInviteOperator)
+
+    const storageBucketId = flags.bucketId
+    const operatorId = flags.operatorId
+
+    logger.info('Inviting storage bucket operator...')
+    if (flags.dev) {
+      await this.ensureDevelopmentChain()
+    }
+
+    const account = this.getAccount(flags)
+    const api = await this.getApi()
+
+    const success = await inviteStorageBucketOperator(api, account, storageBucketId, operatorId)
+
+    this.exitAfterRuntimeCall(success)
+  }
+}

+ 43 - 0
storage-node-v2/src/commands/leader/remove-operator.ts

@@ -0,0 +1,43 @@
+import { removeStorageBucketOperator } from '../../services/runtime/extrinsics'
+import { flags } from '@oclif/command'
+import ApiCommandBase from '../../command-base/ApiCommandBase'
+import logger from '../../services/logger'
+
+/**
+ * CLI command:
+ * Removes invited storage bucket operator.
+ *
+ * @remarks
+ * Storage working group leader command. Requires storage WG leader priviliges.
+ * Shell command: "leader:remove-operator"
+ */
+export default class LeaderRemoveOperator extends ApiCommandBase {
+  static description = `Remove a storage bucket operator. Requires storage working group leader permissions.`
+
+  static flags = {
+    bucketId: flags.integer({
+      char: 'i',
+      required: true,
+      description: 'Storage bucket ID',
+    }),
+    ...ApiCommandBase.flags,
+  }
+
+  async run(): Promise<void> {
+    const { flags } = this.parse(LeaderRemoveOperator)
+
+    const storageBucketId = flags.bucketId
+
+    logger.info('Removing storage bucket operator...')
+    if (flags.dev) {
+      await this.ensureDevelopmentChain()
+    }
+
+    const account = this.getAccount(flags)
+    const api = await this.getApi()
+
+    const success = await removeStorageBucketOperator(api, account, storageBucketId)
+
+    this.exitAfterRuntimeCall(success)
+  }
+}

+ 54 - 0
storage-node-v2/src/commands/leader/set-bucket-limits.ts

@@ -0,0 +1,54 @@
+import ApiCommandBase from '../../command-base/ApiCommandBase'
+import { setStorageBucketVoucherLimits } from '../../services/runtime/extrinsics'
+import { flags } from '@oclif/command'
+import logger from '../../services/logger'
+
+/**
+ * CLI command:
+ * Sets voucher limits for the storage bucket.
+ *
+ * @remarks
+ * Storage working group leader command. Requires storage WG leader priviliges.
+ * Shell command: "leader:set-bucket-limits"
+ */
+export default class LeaderSetBucketLimits extends ApiCommandBase {
+  static description = 'Set VoucherObjectsSizeLimit and VoucherObjectsNumberLimit for the storage bucket.'
+
+  static flags = {
+    bucketId: flags.integer({
+      char: 'i',
+      required: true,
+      description: 'Storage bucket ID',
+    }),
+    objects: flags.integer({
+      char: 'o',
+      required: true,
+      description: `New 'voucher object number limit' value`,
+    }),
+    size: flags.integer({
+      char: 's',
+      required: true,
+      description: `New 'voucher object size limit' value`,
+    }),
+    ...ApiCommandBase.flags,
+  }
+
+  async run(): Promise<void> {
+    const { flags } = this.parse(LeaderSetBucketLimits)
+
+    logger.info('Setting storage bucket limits....')
+    if (flags.dev) {
+      await this.ensureDevelopmentChain()
+    }
+
+    const account = this.getAccount(flags)
+    const bucket = flags.bucketId
+    const objectsLimit = flags.objects
+    const sizeLimit = flags.size
+
+    const api = await this.getApi()
+    const success = await setStorageBucketVoucherLimits(api, account, bucket, sizeLimit, objectsLimit)
+
+    this.exitAfterRuntimeCall(success)
+  }
+}

+ 45 - 0
storage-node-v2/src/commands/leader/set-global-uploading-status.ts

@@ -0,0 +1,45 @@
+import { updateUploadingBlockedStatus } from '../../services/runtime/extrinsics'
+import { flags } from '@oclif/command'
+import ApiCommandBase from '../../command-base/ApiCommandBase'
+import logger from '../../services/logger'
+
+/**
+ * CLI command:
+ * Manages global uploading block in the runtime.
+ *
+ * @remarks
+ * Storage working group leader command. Requires storage WG leader priviliges.
+ * Shell command: "leader:set-global-uploading-status"
+ */
+export default class LeaderSetGlobalUploadingStatus extends ApiCommandBase {
+  static description = `Set global uploading block. Requires storage working group leader permissions.`
+
+  static flags = {
+    set: flags.enum({
+      char: 's',
+      description: 'Sets global uploading block (on/off).',
+      options: ['on', 'off'],
+      required: true,
+    }),
+    ...ApiCommandBase.flags,
+  }
+
+  async run(): Promise<void> {
+    const { flags } = this.parse(LeaderSetGlobalUploadingStatus)
+
+    // Enable blocking?
+    const newStatus = flags.set === 'on'
+
+    logger.info('Setting global uploading block...')
+    if (flags.dev) {
+      await this.ensureDevelopmentChain()
+    }
+
+    const account = this.getAccount(flags)
+    const api = await this.getApi()
+
+    const success = await updateUploadingBlockedStatus(api, account, newStatus)
+
+    this.exitAfterRuntimeCall(success)
+  }
+}

+ 42 - 0
storage-node-v2/src/commands/leader/update-bag-limit.ts

@@ -0,0 +1,42 @@
+import ApiCommandBase from '../../command-base/ApiCommandBase'
+import { updateStorageBucketsPerBagLimit } from '../../services/runtime/extrinsics'
+import { flags } from '@oclif/command'
+import logger from '../../services/logger'
+
+/**
+ * CLI command:
+ * Sets new storage-buckets-per-bag limit.
+ *
+ * @remarks
+ * Storage working group leader command. Requires storage WG leader priviliges.
+ * Shell command: "leader:update-bag-limit"
+ */
+export default class LeaderUpdateBagLimit extends ApiCommandBase {
+  static description = 'Update StorageBucketsPerBagLimit variable in the Joystream node storage.'
+
+  static flags = {
+    limit: flags.integer({
+      char: 'l',
+      required: true,
+      description: 'New StorageBucketsPerBagLimit value',
+    }),
+    ...ApiCommandBase.flags,
+  }
+
+  async run(): Promise<void> {
+    const { flags } = this.parse(LeaderUpdateBagLimit)
+
+    logger.info('Update "Storage buckets per bag" number limit....')
+    if (flags.dev) {
+      await this.ensureDevelopmentChain()
+    }
+
+    const account = this.getAccount(flags)
+    const limit = flags.limit
+
+    const api = await this.getApi()
+    const success = await updateStorageBucketsPerBagLimit(api, account, limit)
+
+    this.exitAfterRuntimeCall(success)
+  }
+}

+ 87 - 0
storage-node-v2/src/commands/leader/update-bag.ts

@@ -0,0 +1,87 @@
+import { flags } from '@oclif/command'
+import { updateStorageBucketsForBag } from '../../services/runtime/extrinsics'
+import ApiCommandBase from '../../command-base/ApiCommandBase'
+import { parseBagId } from '../../services/helpers/bagTypes'
+import logger from '../../services/logger'
+import ExitCodes from '../../command-base/ExitCodes'
+import _ from 'lodash'
+
+// Custom 'integer array' oclif flag.
+const integerArrFlags = {
+  integerArr: flags.build({
+    parse: (value: string) => {
+      const arr: number[] = value.split(',').map((v) => {
+        if (!/^-?\d+$/.test(v)) {
+          throw new Error(`Expected comma-separated integers, but received: ${value}`)
+        }
+        return parseInt(v)
+      })
+      return arr
+    },
+  }),
+}
+
+/**
+ * CLI command:
+ * Updates bags-to-buckets relationships.
+ *
+ * @remarks
+ * Storage working group leader command. Requires storage WG leader priviliges.
+ * Shell command: "leader:update-bag"
+ */
+export default class LeaderUpdateBag extends ApiCommandBase {
+  static description = 'Add/remove a storage bucket from a bag (adds by default).'
+
+  static flags = {
+    add: integerArrFlags.integerArr({
+      char: 'a',
+      description: 'ID of a bucket to add to bag',
+      default: [],
+    }),
+    remove: integerArrFlags.integerArr({
+      char: 'r',
+      description: 'ID of a bucket to remove from bag',
+      default: [],
+    }),
+    bagId: flags.string({
+      char: 'i',
+      required: true,
+      description: `
+      Bag ID. Format: {bag_type}:{sub_type}:{id}.
+      - Bag types: 'static', 'dynamic'
+      - Sub types: 'static:council', 'static:wg', 'dynamic:member', 'dynamic:channel'
+      - Id: 
+        - absent for 'static:council'
+        - working group name for 'static:wg'
+        - integer for 'dynamic:member' and 'dynamic:channel'
+      Examples:
+      - static:council
+      - static:wg:storage
+      - dynamic:member:4
+      `,
+    }),
+    ...ApiCommandBase.flags,
+  }
+
+  async run(): Promise<void> {
+    const { flags } = this.parse(LeaderUpdateBag)
+
+    logger.info('Updating the bag...')
+    if (flags.dev) {
+      await this.ensureDevelopmentChain()
+    }
+
+    if (_.isEmpty(flags.add) && _.isEmpty(flags.remove)) {
+      logger.error('No bucket ID provided.')
+      this.exit(ExitCodes.InvalidParameters)
+    }
+
+    const account = this.getAccount(flags)
+    const api = await this.getApi()
+    const bagId = parseBagId(api, flags.bagId)
+
+    const success = await updateStorageBucketsForBag(api, bagId, account, flags.add, flags.remove)
+
+    this.exitAfterRuntimeCall(success)
+  }
+}

+ 56 - 0
storage-node-v2/src/commands/leader/update-blacklist.ts

@@ -0,0 +1,56 @@
+import { flags } from '@oclif/command'
+import { updateBlacklist } from '../../services/runtime/extrinsics'
+import ApiCommandBase from '../../command-base/ApiCommandBase'
+import ExitCodes from '../../command-base/ExitCodes'
+import logger from '../../services/logger'
+import _ from 'lodash'
+
+/**
+ * CLI command:
+ * Updates content ID blacklist. The CID blacklist block data object
+ * runtim registration.
+ *
+ * @remarks
+ * Storage working group leader command. Requires storage WG leader priviliges.
+ * Shell command: "leader:update-blacklist"
+ */
+export default class LeaderUpdateBlacklist extends ApiCommandBase {
+  static description = 'Add/remove a content ID from the blacklist (adds by default).'
+
+  static flags = {
+    add: flags.string({
+      char: 'a',
+      multiple: true,
+      description: 'Content ID to add',
+      default: [],
+    }),
+    remove: flags.string({
+      char: 'r',
+      description: 'Content ID to remove',
+      multiple: true,
+      default: [],
+    }),
+    ...ApiCommandBase.flags,
+  }
+
+  async run(): Promise<void> {
+    const { flags } = this.parse(LeaderUpdateBlacklist)
+
+    logger.info('Updating the blacklist...')
+    if (flags.dev) {
+      await this.ensureDevelopmentChain()
+    }
+
+    if (_.isEmpty(flags.add) && _.isEmpty(flags.remove)) {
+      logger.error('No Content ID provided.')
+      this.exit(ExitCodes.InvalidParameters)
+    }
+
+    const account = this.getAccount(flags)
+    const api = await this.getApi()
+
+    const success = await updateBlacklist(api, account, flags.add, flags.remove)
+
+    this.exitAfterRuntimeCall(success)
+  }
+}

+ 59 - 0
storage-node-v2/src/commands/leader/update-bucket-status.ts

@@ -0,0 +1,59 @@
+import { flags } from '@oclif/command'
+import { updateStorageBucketStatus } from '../../services/runtime/extrinsics'
+import ApiCommandBase from '../../command-base/ApiCommandBase'
+import logger from '../../services/logger'
+
+/**
+ * CLI command:
+ * Updates the storage bucket status (accept new bags).
+ *
+ * @remarks
+ * Storage working group leader command. Requires storage WG leader priviliges.
+ * Shell command: "leader:update-bucket-status"
+ */
+export default class LeaderUpdateStorageBucketStatus extends ApiCommandBase {
+  static description = 'Update storage bucket status (accepting new bags).'
+
+  static flags = {
+    bucketId: flags.integer({
+      char: 'i',
+      required: true,
+      description: 'Storage bucket ID',
+    }),
+    enable: flags.boolean({
+      char: 'e',
+      description: 'Enables accepting new bags (default).',
+    }),
+    disable: flags.boolean({
+      char: 'd',
+      description: 'Disables accepting new bags.',
+    }),
+    set: flags.enum({
+      char: 's',
+      description: `Sets 'accepting new bags' parameter for the bucket (on/off).`,
+      options: ['on', 'off'],
+      required: true,
+    }),
+    ...ApiCommandBase.flags,
+  }
+
+  async run(): Promise<void> {
+    const { flags } = this.parse(LeaderUpdateStorageBucketStatus)
+
+    const bucket = flags.bucketId
+    // Accept new bags?
+    const newStatus = flags.set === 'on'
+
+    logger.info('Updating the storage bucket status...')
+    if (flags.dev) {
+      await this.ensureDevelopmentChain()
+    }
+
+    const account = this.getAccount(flags)
+
+    const api = await this.getApi()
+    const success = await updateStorageBucketStatus(api, account, bucket, newStatus)
+
+    this.exitAfterRuntimeCall(success)
+  }
+}

+ 43 - 0
storage-node-v2/src/commands/leader/update-data-fee.ts

@@ -0,0 +1,43 @@
+import { updateDataSizeFee } from '../../services/runtime/extrinsics'
+import { flags } from '@oclif/command'
+import ApiCommandBase from '../../command-base/ApiCommandBase'
+import logger from '../../services/logger'
+
+/**
+ * CLI command:
+ * Updates storage data fee in the runtime.
+ *
+ * @remarks
+ * Storage working group leader command. Requires storage WG leader priviliges.
+ * Shell command: "leader:update-data-fee"
+ */
+export default class LeaderUpdateDataFee extends ApiCommandBase {
+  static description = `Update data size fee. Requires storage working group leader permissions.`
+
+  static flags = {
+    fee: flags.integer({
+      char: 'f',
+      required: true,
+      description: 'New data size fee',
+    }),
+    ...ApiCommandBase.flags,
+  }
+
+  async run(): Promise<void> {
+    const { flags } = this.parse(LeaderUpdateDataFee)
+
+    const fee = flags.fee
+
+    logger.info('Updating data size fee...')
+    if (flags.dev) {
+      await this.ensureDevelopmentChain()
+    }
+
+    const account = this.getAccount(flags)
+    const api = await this.getApi()
+
+    const success = await updateDataSizeFee(api, account, fee)
+
+    this.exitAfterRuntimeCall(success)
+  }
+}

+ 57 - 0
storage-node-v2/src/commands/leader/update-dynamic-bag-policy.ts

@@ -0,0 +1,57 @@
+import ApiCommandBase from '../../command-base/ApiCommandBase'
+import { updateNumberOfStorageBucketsInDynamicBagCreationPolicy } from '../../services/runtime/extrinsics'
+import { flags } from '@oclif/command'
+import logger from '../../services/logger'
+import { parseDynamicBagType } from '../../services/helpers/bagTypes'
+import { DynamicBagTypeKey } from '@joystream/types/storage'
+
+/**
+ * CLI command:
+ * Updates dynamic bag creation policy - storage bucket number for new dynamic
+ * bag.
+ *
+ * @remarks
+ * Storage working group leader command. Requires storage WG leader priviliges.
+ * Shell command: "leader:update-dynamic-bag-policy"
+ */
+export default class LeaderUpdateDynamicBagPolicy extends ApiCommandBase {
+  static description = 'Update number of storage buckets used in the dynamic bag creation policy.'
+
+  static flags = {
+    number: flags.integer({
+      char: 'n',
+      required: true,
+      description: 'New storage buckets number',
+    }),
+    bagType: flags.enum<DynamicBagTypeKey>({
+      char: 't',
+      description: 'Dynamic bag type (Channel, Member).',
+      options: ['Channel', 'Member'],
+      required: true,
+    }),
+    ...ApiCommandBase.flags,
+  }
+
+  async run(): Promise<void> {
+    const { flags } = this.parse(LeaderUpdateDynamicBagPolicy)
+
+    logger.info('Update dynamic bag creation policy....')
+    if (flags.dev) {
+      await this.ensureDevelopmentChain()
+    }
+
+    const account = this.getAccount(flags)
+    const newNumber = flags.number
+
+    const api = await this.getApi()
+    const dynamicBagType = parseDynamicBagType(api, flags.bagType)
+    const success = await updateNumberOfStorageBucketsInDynamicBagCreationPolicy(
+      api,
+      account,
+      dynamicBagType,
+      newNumber
+    )
+
+    this.exitAfterRuntimeCall(success)
+  }
+}

+ 49 - 0
storage-node-v2/src/commands/leader/update-voucher-limits.ts

@@ -0,0 +1,49 @@
+import ApiCommandBase from '../../command-base/ApiCommandBase'
+import { updateStorageBucketsVoucherMaxLimits } from '../../services/runtime/extrinsics'
+import { flags } from '@oclif/command'
+import logger from '../../services/logger'
+
+/**
+ * CLI command:
+ * Updates maximum values for storage bucket voucher limits.
+ *
+ * @remarks
+ * Storage working group leader command. Requires storage WG leader priviliges.
+ * Shell command: "leader:update-voucher-limits"
+ */
+export default class LeaderUpdateVoucherLimits extends ApiCommandBase {
+  static description =
+    'Update VoucherMaxObjectsSizeLimit and VoucherMaxObjectsNumberLimit for the Joystream node storage.'
+
+  static flags = {
+    objects: flags.integer({
+      char: 'o',
+      required: true,
+      description: `New 'max voucher object number limit' value`,
+    }),
+    size: flags.integer({
+      char: 's',
+      required: true,
+      description: `New 'max voucher object size limit' value`,
+    }),
+    ...ApiCommandBase.flags,
+  }
+
+  async run(): Promise<void> {
+    const { flags } = this.parse(LeaderUpdateVoucherLimits)
+
+    logger.info('Updating global storage bucket voucher limits....')
+    if (flags.dev) {
+      await this.ensureDevelopmentChain()
+    }
+
+    const account = this.getAccount(flags)
+    const objectsLimit = flags.objects
+    const sizeLimit = flags.size
+
+    const api = await this.getApi()
+    const success = await updateStorageBucketsVoucherMaxLimits(api, account, sizeLimit, objectsLimit)
+
+    this.exitAfterRuntimeCall(success)
+  }
+}

+ 50 - 0
storage-node-v2/src/commands/operator/accept-invitation.ts

@@ -0,0 +1,50 @@
+import { flags } from '@oclif/command'
+import { acceptStorageBucketInvitation } from '../../services/runtime/extrinsics'
+import ApiCommandBase from '../../command-base/ApiCommandBase'
+import logger from '../../services/logger'
+
+/**
+ * CLI command:
+ * Accepts pending invitation for the storage bucket.
+ *
+ * @remarks
+ * Storage provider (operator) command. Requires an additional worker ID for
+ * runtime verification.
+ * Shell command: "operator:accept-invitation"
+ */
+export default class OperatorAcceptInvitation extends ApiCommandBase {
+  static description = 'Accept pending storage bucket invitation.'
+
+  static flags = {
+    workerId: flags.integer({
+      char: 'w',
+      required: true,
+      description: 'Storage operator worker ID',
+    }),
+    bucketId: flags.integer({
+      char: 'i',
+      required: true,
+      description: 'Storage bucket ID',
+    }),
+    ...ApiCommandBase.flags,
+  }
+
+  async run(): Promise<void> {
+    const { flags } = this.parse(OperatorAcceptInvitation)
+
+    const worker = flags.workerId
+    const bucket = flags.bucketId
+
+    logger.info('Accepting pending storage bucket invitation...')
+    if (flags.dev) {
+      await this.ensureDevelopmentChain()
+    }
+
+    const account = this.getAccount(flags)
+
+    const api = await this.getApi()
+    const success = await acceptStorageBucketInvitation(api, account, worker, bucket)
+
+    this.exitAfterRuntimeCall(success)
+  }
+}

+ 55 - 0
storage-node-v2/src/commands/operator/set-metadata.ts

@@ -0,0 +1,55 @@
+import { flags } from '@oclif/command'
+import { setStorageOperatorMetadata } from '../../services/runtime/extrinsics'
+import ApiCommandBase from '../../command-base/ApiCommandBase'
+import logger from '../../services/logger'
+
+/**
+ * CLI command:
+ * Sets metadata for the storage bucket.
+ *
+ * @remarks
+ * Storage provider (operator) command. Requires an additional worker ID for
+ * runtime verification.
+ * Shell command: "operator:set-metadata"
+ */
+export default class OperatorSetMetadata extends ApiCommandBase {
+  static description = 'Accept pending storage bucket invitation.'
+
+  static flags = {
+    bucketId: flags.integer({
+      char: 'i',
+      required: true,
+      description: 'Storage bucket ID',
+    }),
+    operatorId: flags.integer({
+      char: 'w',
+      required: true,
+      description: 'Storage bucket operator ID (storage group worker ID)',
+    }),
+    metadata: flags.string({
+      char: 'm',
+      description: 'Storage bucket operator metadata',
+    }),
+    ...ApiCommandBase.flags,
+  }
+
+  async run(): Promise<void> {
+    const { flags } = this.parse(OperatorSetMetadata)
+
+    const operator = flags.operatorId
+    const bucket = flags.bucketId
+    const metadata = flags.metadata ?? ''
+
+    logger.info('Setting the storage operator metadata...')
+    if (flags.dev) {
+      await this.ensureDevelopmentChain()
+    }
+
+    const account = this.getAccount(flags)
+
+    const api = await this.getApi()
+    const success = await setStorageOperatorMetadata(api, account, operator, bucket, metadata)
+
+    this.exitAfterRuntimeCall(success)
+  }
+}

+ 59 - 0
storage-node-v2/src/commands/server.ts

@@ -0,0 +1,59 @@
+import { flags } from '@oclif/command'
+import { createApp } from '../services/webApi/app'
+import ApiCommandBase from '../command-base/ApiCommandBase'
+import logger from '../services/logger'
+
+/**
+ * CLI command:
+ * Starts the storage node server.
+ *
+ * @remarks
+ * Shell command: "server"
+ */
+export default class Server extends ApiCommandBase {
+  static description = 'Starts the storage node server.'
+
+  static flags = {
+    worker: flags.integer({
+      char: 'w',
+      required: true,
+      description: 'Storage provider worker ID',
+    }),
+    uploads: flags.string({
+      char: 'd',
+      required: true,
+      description: 'Data uploading directory (absolute path).',
+    }),
+    port: flags.integer({
+      char: 'o',
+      required: true,
+      description: 'Server port.',
+    }),
+    ...ApiCommandBase.flags,
+  }
+
+  async run(): Promise<void> {
+    const { flags } = this.parse(Server)
+
+    if (flags.dev) {
+      await this.ensureDevelopmentChain()
+    }
+
+    const account = this.getAccount(flags)
+    const api = await this.getApi()
+
+    try {
+      const port = flags.port
+      const workerId = flags.worker ?? 0
+      const app = await createApp(api, account, workerId, flags.uploads)
+      logger.info(`Listening on http://localhost:${port}`)
+      app.listen(port)
+    } catch (err) {
+      logger.error(`Error: ${err}`)
+    }
+  }
+
+  // Override exiting.
+  /* eslint-disable @typescript-eslint/no-empty-function */
+  async finally(): Promise<void> {}
+}

+ 1 - 0
storage-node-v2/src/index.ts

@@ -0,0 +1 @@
+export { run } from '@oclif/command'

+ 136 - 0
storage-node-v2/src/services/helpers/auth.ts

@@ -0,0 +1,136 @@
+import { KeyringPair } from '@polkadot/keyring/types'
+import { u8aToHex } from '@polkadot/util'
+import { signatureVerify } from '@polkadot/util-crypto'
+import base64url from 'base64url'
+
+/**
+ * Represents an upload token request.
+ */
+export interface UploadTokenRequest {
+  /**
+   * Request data to sign.
+   */
+  data: UploadTokenRequestBody
+  /**
+   * Request body signature.
+   */
+  signature: string
+}
+
+/**
+ * Represents upload token request data.
+ */
+export interface UploadTokenRequestBody extends RequestData {
+  /**
+   * Joystream runtime Member ID (number).
+   */
+  memberId: number
+
+  /**
+   * Joystream runtime Account ID (public key).
+   */
+  accountId: string
+}
+
+/**
+ * Represents request data.
+ */
+export interface RequestData {
+  /**
+   * Runtime data object ID.
+   */
+  dataObjectId: number
+  /**
+   * Runtime storage bucket ID.
+   */
+  storageBucketId: number
+  /**
+   * Bag ID in the string format.
+   */
+  bagId: string
+}
+
+/**
+ * Represents upload token data.
+ */
+export interface UploadTokenBody extends RequestData {
+  /**
+   * Expiration time for the token (timestamp).
+   */
+  validUntil: number
+  /**
+   * Nonce for the request.
+   */
+  nonce: string
+}
+
+/**
+ * Represents an upload token.
+ */
+export interface UploadToken {
+  /**
+   * Upload token data to sign.
+   */
+  data: UploadTokenBody
+  /**
+   * Upload token data signature.
+   */
+  signature: string
+}
+
+/**
+ * Parses upload token from the token string.
+ *
+ * @param tokenString - token string
+ * @param bagType - dynamic bag type string
+ * @returns The UploadToken instance.
+ */
+export function parseUploadToken(tokenString: string): UploadToken {
+  return JSON.parse(base64url.decode(tokenString))
+}
+
+/**
+ * Verifies UploadToken or UploadTokenRequest using its signatures.
+ *
+ * @param token - object to verify
+ * @param address - public key(account ID)
+ * @returns The UploadToken instance.
+ */
+export function verifyTokenSignature(token: UploadToken | UploadTokenRequest, address: string): boolean {
+  const message = JSON.stringify(token.data)
+  const { isValid } = signatureVerify(message, token.signature, address)
+
+  return isValid
+}
+
+/**
+ * Signs UploadToken or UploadTokenRequest.
+ *
+ * @param token - object to verify
+ * @param account - KeyringPair instance
+ * @returns object signature.
+ */
+export function signTokenBody(tokenBody: UploadTokenBody | UploadTokenRequestBody, account: KeyringPair): string {
+  const message = JSON.stringify(tokenBody)
+  const signature = u8aToHex(account.sign(message))
+
+  return signature
+}
+
+/**
+ * Creates an upload token.
+ *
+ * @param tokenBody - upload token data
+ * @param account - KeyringPair instance
+ * @returns object signature.
+ */
+export function createUploadToken(tokenBody: UploadTokenBody, account: KeyringPair): string {
+  const signature = signTokenBody(tokenBody, account)
+
+  const token = {
+    data: tokenBody,
+    signature,
+  }
+
+  return base64url.encode(JSON.stringify(token))
+}

+ 154 - 0
storage-node-v2/src/services/helpers/bagTypes.ts

@@ -0,0 +1,154 @@
+import { BagId, DynamicBagType, DynamicBagTypeKey, Static, Dynamic } from '@joystream/types/storage'
+import { WorkingGroup } from '@joystream/types/common'
+import { ApiPromise } from '@polkadot/api'
+import ExitCodes from '../../command-base/ExitCodes'
+import { CLIError } from '@oclif/errors'
+
+/**
+ * Parses the type string and returns the DynamicBagType instance.
+ *
+ * @remarks
+ * This method uses runtime API for type construction.
+ *
+ * @param api - runtime API promise
+ * @param bagType - dynamic bag type string
+ * @returns The DynamicBagType instance.
+ */
+export function parseDynamicBagType(api: ApiPromise, bagType: DynamicBagTypeKey): DynamicBagType {
+  return api.createType('DynamicBagType', bagType)
+}
+
+/**
+ * Parses the type string and returns the BagId instance.
+ *
+ * @remarks
+ * This method uses runtime API for type construction. It throws an exception
+ * on invalid string format.
+ *
+ * @param api - runtime API promise
+ * @param bagId - bag ID in string format
+ * @returns The BagId instance.
+ */
+export function parseBagId(api: ApiPromise, bagId: string): BagId {
+  const parser = new BagIdParser(api, bagId)
+
+  return parser.parse()
+}
+
+/**
+ * Class-helper for actual bag ID parsing.
+ */
+class BagIdParser {
+  bagId: string
+  api: ApiPromise
+  bagIdParts: string[]
+
+  constructor(api: ApiPromise, bagId: string) {
+    this.bagId = bagId
+    this.api = api
+
+    this.bagIdParts = bagId.trim().toLowerCase().split(':')
+
+    if (this.bagIdParts.length > 3 || this.bagIdParts.length < 2) {
+      throw new CLIError(`Invalid bagId: ${bagId}`, {
+        exit: ExitCodes.InvalidParameters,
+      })
+    }
+  }
+
+  /**
+   * Tries to parse the bag ID using given bag ID in string format, throws an
+   * exception on failure.
+   */
+  parse(): BagId {
+    if (this.bagIdParts[0] === 'static') {
+      return this.parseStaticBagId()
+    }
+
+    if (this.bagIdParts[0] === 'dynamic') {
+      return this.parseDynamicBagId()
+    }
+
+    throw new CLIError(`Invalid bagId: ${this.bagId}`, {
+      exit: ExitCodes.InvalidParameters,
+    })
+  }
+
+  /**
+   * Tries to parse the static bag ID, throws an exception on failure.
+   */
+  parseStaticBagId(): BagId {
+    // Try to construct static council bag ID.
+    if (this.bagIdParts[1] === 'council') {
+      if (this.bagIdParts.length === 2) {
+        const staticBagId: Static = this.api.createType('Static', 'Council')
+        const constructedBagId: BagId = this.api.createType('BagId', {
+          'Static': staticBagId,
+        })
+
+        return constructedBagId
+      }
+    }
+
+    // Try to construct static working group bag ID.
+    if (this.bagIdParts[1] === 'wg') {
+      if (this.bagIdParts.length === 3) {
+        const groups = Object.keys(WorkingGroup.typeDefinitions)
+        const actualGroup = this.bagIdParts[2]
+
+        for (const group of groups) {
+          if (group.toLowerCase() === actualGroup) {
+            const workingGroup: WorkingGroup = this.api.createType('WorkingGroup', group)
+            const staticBagId: Static = this.api.createType('Static', {
+              'WorkingGroup': workingGroup,
+            })
+            const constructedBagId: BagId = this.api.createType('BagId', {
+              'Static': staticBagId,
+            })
+
+            return constructedBagId
+          }
+        }
+      }
+    }
+
+    throw new CLIError(`Invalid static bagId: ${this.bagId}`, {
+      exit: ExitCodes.InvalidParameters,
+    })
+  }
+
+  /**
+   * Tries to parse the dynamic bag ID, throws an exception on failure.
+   */
+  parseDynamicBagId(): BagId {
+    if (this.bagIdParts.length === 3) {
+      const idString = this.bagIdParts[2]
+      const parsedId = parseInt(idString)
+
+      // Verify successful entity ID parsing
+      if (!isNaN(parsedId)) {
+        const dynamicBagTypes = Object.keys(DynamicBagType.typeDefinitions)
+        const actualType = this.bagIdParts[1]
+
+        // Try to construct dynamic bag ID.
+        for (const dynamicBagType of dynamicBagTypes) {
+          if (dynamicBagType.toLowerCase() === actualType) {
+            const dynamic = {} as Record<DynamicBagTypeKey, number>
+            dynamic[dynamicBagType as DynamicBagTypeKey] = parsedId
+
+            const dynamicBagId: Dynamic = this.api.createType('Dynamic', dynamic)
+            const constructedBagId: BagId = this.api.createType('BagId', {
+              'Dynamic': dynamicBagId,
+            })
+
+            return constructedBagId
+          }
+        }
+      }
+    }
+
+    throw new CLIError(`Invalid dynamic bagId: ${this.bagId}`, {
+      exit: ExitCodes.InvalidParameters,
+    })
+  }
+}

+ 50 - 0
storage-node-v2/src/services/helpers/fileInfo.ts

@@ -0,0 +1,50 @@
+import FileType from 'file-type'
+import readChunk from 'read-chunk'
+
+/**
+ * Represents information about the file.
+ */
+export type FileInfo = {
+  /**
+   * File MIME-type.
+   */
+  mimeType: string
+
+  /**
+   * Possible file extension.
+   */
+  ext: string
+}
+
+// Number in bytes to read. Minimum number for file info detection.
+const MINIMUM_FILE_CHUNK = 4100
+
+/**
+ * Returns MIME-type and file extension by file content.
+ *
+ * @remarks
+ * It reads the file chunck and tries to determine its MIME-type and extension.
+ * It returns 'application/octet-stream' and 'bin' as default values.
+ *
+ * @param fullPath - file path
+ * @returns promise with file information.
+ */
+export async function getFileInfo(fullPath: string): Promise<FileInfo> {
+  // Default file info if nothing could be detected.
+  const DEFAULT_FILE_INFO = {
+    mimeType: 'application/octet-stream',
+    ext: 'bin',
+  }
+
+  const buffer = readChunk.sync(fullPath, 0, MINIMUM_FILE_CHUNK)
+  const fileType = await FileType.fromBuffer(buffer)
+
+  if (fileType === undefined) {
+    return DEFAULT_FILE_INFO
+  }
+
+  return {
+    mimeType: fileType.mime.toString(),
+    ext: fileType.ext.toString(),
+  }
+}

+ 30 - 0
storage-node-v2/src/services/helpers/hashing.ts

@@ -0,0 +1,30 @@
+import * as multihash from 'multihashes'
+import fs from 'fs'
+import { createHash } from 'blake3'
+
+/**
+ * Reads the file and calculates its hash. It uses the blake3 hashing algorithm
+ * and multihash format.
+ *
+ * @param filename - file name
+ * @returns hash promise.
+ */
+export function hashFile(filename: string): Promise<string> {
+  const fileStream = fs.createReadStream(filename).pipe(createHash())
+
+  return new Promise((resolve, reject) => {
+    let hash: Uint8Array
+    fileStream.on('data', function (chunk) {
+      hash = chunk
+    })
+    fileStream.on('end', function () {
+      const encoded = multihash.encode(hash, 'blake3')
+      const result = multihash.toB58String(encoded)
+
+      resolve(result)
+    })
+    fileStream.on('error', function (err) {
+      reject(err)
+    })
+  })
+}

+ 47 - 0
storage-node-v2/src/services/helpers/tokenNonceKeeper.ts

@@ -0,0 +1,47 @@
+import NodeCache from 'node-cache'
+
+// Expiration period in seconds for the local nonce cache.
+const TokenExpirationPeriod: number = 30 * 1000 // seconds
+
+// Max nonce number in local cache
+const MaxNonces = 100000
+
+// Local in-memory cache for nonces.
+const nonceCache = new NodeCache({
+  stdTTL: TokenExpirationPeriod,
+  deleteOnExpire: true,
+  maxKeys: MaxNonces,
+})
+
+/**
+ * Constructs and returns an expiration time for a token.
+ */
+export function getTokenExpirationTime(): number {
+  return Date.now() + TokenExpirationPeriod
+}
+
+/**
+ * Creates nonce string using the high precision process time and registers
+ * it in the local in-memory cache with expiration time.
+ *
+ * @returns nonce string.
+ */
+export function createNonce(): string {
+  const nonce = process.hrtime.bigint().toString()
+
+  nonceCache.set(nonce, null, TokenExpirationPeriod)
+
+  return nonce
+}
+
+/**
+ * Removes the nonce from the local cache.
+ *
+ * @param nonce - nonce string.
+ * @returns true if nonce was present in local cache.
+ */
+export function checkRemoveNonce(nonce: string): boolean {
+  const deletedEntries = nonceCache.del(nonce)
+
+  return deletedEntries > 0
+}

+ 111 - 0
storage-node-v2/src/services/logger.ts

@@ -0,0 +1,111 @@
+import winston from 'winston'
+import expressWinston from 'express-winston'
+import { Handler, ErrorRequestHandler } from 'express'
+
+/**
+ * Creates basic Winston logger. Console output redirected to the stderr.
+ *
+ * @returns Winston logger
+ *
+ */
+function createDefaultLogger(): winston.Logger {
+  const levels = {
+    error: 0,
+    warn: 1,
+    info: 2,
+    http: 3,
+    debug: 4,
+  }
+
+  const level = () => {
+    const env = process.env.NODE_ENV || 'development'
+    const isDevelopment = env === 'development'
+    return isDevelopment ? 'debug' : 'warn'
+  }
+
+  const colors = {
+    error: 'red',
+    warn: 'yellow',
+    info: 'green',
+    http: 'magenta',
+    debug: 'white',
+  }
+
+  winston.addColors(colors)
+
+  const format = winston.format.combine(
+    winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss:ms' }),
+    winston.format.colorize({ all: true }),
+    winston.format.printf((info) => `${info.timestamp} ${info.level}: ${info.message}`)
+  )
+
+  // Redirect all logs to the stderr
+  const transports = [new winston.transports.Console({ stderrLevels: Object.keys(levels) })]
+
+  return winston.createLogger({
+    level: level(),
+    levels,
+    format,
+    transports,
+  })
+}
+
+const Logger = createDefaultLogger()
+
+export default Logger
+/**
+ * Creates Express-Winston logger handler.
+ *
+ * @returns  Express-Winston logger handler
+ *
+ */
+export function httpLogger(): Handler {
+  const opts: expressWinston.LoggerOptions = {
+    transports: [new winston.transports.Console()],
+    format: winston.format.combine(winston.format.json()),
+    meta: true,
+    msg: 'HTTP {{req.method}} {{req.url}}',
+    expressFormat: true,
+    colorize: false,
+  }
+
+  return expressWinston.logger(opts)
+}
+
+/**
+ * Creates Express-Winston error logger.
+ *
+ * @returns  Express-Winston error logger
+ *
+ */
+export function errorLogger(): ErrorRequestHandler {
+  return expressWinston.errorLogger({
+    transports: [new winston.transports.Console()],
+    format: winston.format.combine(winston.format.json()),
+  })
+}
+
+/**
+ * Creates clean Console Winston logger for standard output.
+ *
+ * @returns Winston logger
+ *
+ */
+export function createStdConsoleLogger(): winston.Logger {
+  const levels = {
+    error: 0,
+    warn: 1,
+    info: 2,
+    http: 3,
+    debug: 4,
+  }
+  const format = winston.format.printf((info) => `${info.message}`)
+
+  const transports = [new winston.transports.Console()]
+
+  return winston.createLogger({
+    levels,
+    format,
+    transports,
+  })
+}

+ 83 - 0
storage-node-v2/src/services/runtime/accounts.ts

@@ -0,0 +1,83 @@
+import fs from 'fs'
+import path from 'path'
+import { CLIError } from '@oclif/errors'
+import { Keyring } from '@polkadot/keyring'
+import { KeyringPair, KeyringPair$Json } from '@polkadot/keyring/types'
+import ExitCodes from '../../command-base/ExitCodes'
+
+/**
+ * Parses the JSON file with account data and KeyPair instance.
+ *
+ * @param jsonBackupFilePath - JSON-file path
+ * @returns KeyPair instance.
+ */
+export function getAccountFromJsonFile(jsonBackupFilePath: string): KeyringPair {
+  if (!fs.existsSync(jsonBackupFilePath)) {
+    throw new CLIError('Input file does not exist!', {
+      exit: ExitCodes.FileError,
+    })
+  }
+  if (path.extname(jsonBackupFilePath) !== '.json') {
+    throw new CLIError('Invalid input file: File extension should be .json', {
+      exit: ExitCodes.FileError,
+    })
+  }
+  let accountJsonObj: KeyringPair$Json
+  try {
+    const accountJson = fs.readFileSync(jsonBackupFilePath)
+    accountJsonObj = JSON.parse(accountJson.toString())
+  } catch (e) {
+    throw new CLIError('Provided backup file is not valid or cannot be accessed', { exit: ExitCodes.FileError })
+  }
+  if (typeof accountJsonObj !== 'object' || accountJsonObj === null) {
+    throw new CLIError('Provided backup file is not valid', {
+      exit: ExitCodes.FileError,
+    })
+  }
+
+  const keyring = configureKeyring()
+  let account: KeyringPair
+  try {
+    // Try adding and retrieving the keys in order to validate that the backup file is correct
+    keyring.addFromJson(accountJsonObj)
+    account = keyring.getPair(accountJsonObj.address)
+  } catch (e) {
+    throw new CLIError('Provided backup file is not valid', {
+      exit: ExitCodes.FileError,
+    })
+  }
+
+  return account
+}
+
+/**
+ * Returns 'Alice' KeyPair instance.
+ *
+ * @remarks
+ * This method should be used in the development mode only.
+ *
+ * @returns 'Alice' KeyPair instance.
+ */
+export function getAlicePair(): KeyringPair {
+  return getAccountFromUri('//Alice')
+}
+
+/**
+ * Create KeyPair instance from the account URI.
+ *
+ * @param accountURI - account URI (//Alice)
+ * @returns KeyPair instance.
+ */
+export function getAccountFromUri(accountURI: string): KeyringPair {
+  const keyring = configureKeyring()
+  return keyring.addFromUri(accountURI)
+}
+
+/**
+ * Configures the Keyring with the proper account type.
+ *
+ * @returns configured Keyring.
+ */
+function configureKeyring(): Keyring {
+  return new Keyring({ type: 'sr25519' })
+}

+ 208 - 0
storage-node-v2/src/services/runtime/api.ts

@@ -0,0 +1,208 @@
+import { ApiPromise, WsProvider, SubmittableResult } from '@polkadot/api'
+import type { Index } from '@polkadot/types/interfaces/runtime'
+import { ISubmittableResult, IEvent } from '@polkadot/types/types'
+import { types } from '@joystream/types/'
+import { TypeRegistry } from '@polkadot/types'
+import { KeyringPair } from '@polkadot/keyring/types'
+import { SubmittableExtrinsic, AugmentedEvent } from '@polkadot/api/types'
+import { DispatchError, DispatchResult } from '@polkadot/types/interfaces/system'
+import { getNonce } from './transactionNonceKeeper'
+import logger from '../../services/logger'
+import ExitCodes from '../../command-base/ExitCodes'
+import { CLIError } from '@oclif/errors'
+
+/**
+ * Dedicated error for the failed extrinsics.
+ */
+export class ExtrinsicFailedError extends CLIError {}
+
+/**
+ * Initializes the runtime API and Joystream runtime types.
+ *
+ * @param apiUrl - API URL string
+ * @returns runtime API promise
+ */
+export async function createApi(apiUrl: string): Promise<ApiPromise> {
+  const provider = new WsProvider(apiUrl)
+
+  return await ApiPromise.create({ provider, types })
+}
+
+/**
+ * Sends an extrinsic to the runtime and follows the result.
+ *
+ * @param api - API promise
+ * @param account - KeyPair instance
+ * @param tx - runtime transaction object to send
+ * @param nonce - transaction nonce for a given account.
+ * @returns extrinsic result promise.
+ */
+function sendExtrinsic(
+  api: ApiPromise,
+  account: KeyringPair,
+  tx: SubmittableExtrinsic<'promise'>,
+  nonce: Index
+): Promise<ISubmittableResult> {
+  return new Promise((resolve, reject) => {
+    let unsubscribe: () => void
+    tx.signAndSend(account, { nonce }, (result) => {
+      // Implementation loosely based on /pioneer/packages/react-signer/src/Modal.tsx
+      if (!result || !result.status) {
+        return
+      }
+
+      if (result.status.isInBlock) {
+        unsubscribe()
+        result.events
+          .filter(({ event }) => event.section === 'system')
+          .forEach(({ event }) => {
+            if (event.method === 'ExtrinsicFailed') {
+              const dispatchError = event.data[0] as DispatchError
+              let errorMsg = dispatchError.toString()
+              if (dispatchError.isModule) {
+                try {
+                  errorMsg = formatDispatchError(api, dispatchError)
+                } catch (e) {
+                  // This probably means we don't have this error in the metadata
+                  // In this case - continue (we'll just display dispatchError.toString())
+                }
+              }
+              reject(
+                new ExtrinsicFailedError(`Extrinsic execution error: ${errorMsg}`, {
+                  exit: ExitCodes.ApiError,
+                })
+              )
+            } else if (event.method === 'ExtrinsicSuccess') {
+              const sudid = result.findRecord('sudo', 'Sudid')
+
+              if (sudid) {
+                const dispatchResult = sudid.event.data[0] as DispatchResult
+                if (dispatchResult.isOk) {
+                  resolve(result)
+                } else {
+                  const errorMsg = formatDispatchError(api, dispatchResult.asErr)
+                  reject(
+                    new ExtrinsicFailedError(`Sudo extrinsic execution error! ${errorMsg}`, {
+                      exit: ExitCodes.ApiError,
+                    })
+                  )
+                }
+              } else {
+                resolve(result)
+              }
+            }
+          })
+      } else if (result.isError) {
+        reject(
+          new ExtrinsicFailedError('Extrinsic execution error!', {
+            exit: ExitCodes.ApiError,
+          })
+        )
+      }
+    })
+      .then((unsubFunc) => (unsubscribe = unsubFunc))
+      .catch((e) =>
+        reject(
+          new ExtrinsicFailedError(`Cannot send the extrinsic: ${e.message ? e.message : JSON.stringify(e)}`, {
+            exit: ExitCodes.ApiError,
+          })
+        )
+      )
+  })
+}
+
+/**
+ * Helper function for formatting dispatch error.
+ *
+ * @param api - API promise
+ * @param error - DispatchError instance
+ * @returns error string.
+ */
+function formatDispatchError(api: ApiPromise, error: DispatchError): string {
+  // Need to assert that registry is of TypeRegistry type, since Registry intefrace
+  // seems outdated and doesn't include DispatchErrorModule as possible argument for "findMetaError"
+  const typeRegistry = api.registry as TypeRegistry
+  const { name, documentation } = typeRegistry.findMetaError(error.asModule)
+  const errorMsg = `${name} (${documentation})`
+
+  return errorMsg
+}
+
+/**
+ * Helper function for sending an extrinsic to the runtime. It constructs an
+ * actual transaction object.
+ *
+ * @param api - API promise
+ * @param account - KeyPair instance
+ * @param tx - prepared extrinsic with arguments
+ * @param sudoCall - defines whether the transaction call should be wrapped in
+ * the sudo call (false by default).
+ * @param eventParser - defines event parsing function (null by default) for
+ * getting any information from the successful extrinsic events.
+ * @returns void or event parsing result promise.
+ */
+export async function sendAndFollowNamedTx<T>(
+  api: ApiPromise,
+  account: KeyringPair,
+  tx: SubmittableExtrinsic<'promise'>,
+  sudoCall = false,
+  eventParser: ((result: ISubmittableResult) => T) | null = null
+): Promise<T | void> {
+  logger.debug(`Sending ${tx.method.section}.${tx.method.method} extrinsic...`)
+
+  if (sudoCall) {
+    tx = api.tx.sudo.sudo(tx)
+  }
+  const nonce = await getNonce(api, account)
+
+  const result = await sendExtrinsic(api, account, tx, nonce)
+
+  let eventResult: T | void
+  if (eventParser) {
+    eventResult = eventParser(result)
+  }
+  logger.debug(`Extrinsic successful!`)
+
+  return eventResult
+}
+
+/**
+ * Helper function for sending an extrinsic to the runtime. It constructs an
+ * actual transaction object and sends a transactions wrapped in sudo call.
+ *
+ * @param api - API promise
+ * @param account - KeyPair instance
+ * @param tx - prepared extrinsic with arguments
+ * @param eventParser - defines event parsing function (null by default) for
+ * getting any information from the successful extrinsic events.
+ * @returns void promise.
+ */
+export async function sendAndFollowSudoNamedTx<T>(
+  api: ApiPromise,
+  account: KeyringPair,
+  tx: SubmittableExtrinsic<'promise'>,
+  eventParser: ((result: ISubmittableResult) => T) | null = null
+): Promise<T | void> {
+  return sendAndFollowNamedTx(api, account, tx, true, eventParser)
+}
+
+/**
+ * Helper function for parsing the successful extrinsic result for event.
+ *
+ * @param result - extrinsic result
+ * @param section - pallet name
+ * @param eventName - event name
+ * @returns void promise.
+ */
+export function getEvent<
+  S extends keyof ApiPromise['events'] & string,
+  M extends keyof ApiPromise['events'][S] & string,
+  EventType = ApiPromise['events'][S][M] extends AugmentedEvent<'promise', infer T> ? IEvent<T> : never
+>(result: SubmittableResult, section: S, eventName: M): EventType {
+  const event = result.findRecord(section, eventName)?.event as EventType | undefined
+
+  if (!event) {
+    throw new Error(`Cannot find expected ${section}.${eventName} event in result: ${result.toHuman()}`)
+  }
+  return event as EventType
+}

+ 506 - 0
storage-node-v2/src/services/runtime/extrinsics.ts

@@ -0,0 +1,506 @@
+import { sendAndFollowSudoNamedTx, sendAndFollowNamedTx, getEvent } from './api'
+import { getAlicePair } from './accounts'
+import { KeyringPair } from '@polkadot/keyring/types'
+import { ApiPromise } from '@polkadot/api'
+import { BagId, DynamicBagType } from '@joystream/types/storage'
+import logger from '../../services/logger'
+
+/**
+ * Creates storage bucket.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param invitedWorker - defines whether the storage provider should be
+ * invited on the bucket creation (optional)
+ * @param allowedNewBags - bucket allows new bag assignments
+ * @param sizeLimit - size limit in bytes for the new bucket (default 0)
+ * @param objectsLimit - object number limit for the new bucket (default 0)
+ * @returns promise with a success flag and the bucket id (on success).
+ */
+export async function createStorageBucket(
+  api: ApiPromise,
+  account: KeyringPair,
+  invitedWorker: number | null = null,
+  allowedNewBags = true,
+  sizeLimit = 0,
+  objectsLimit = 0
+): Promise<[boolean, number | void]> {
+  let bucketId: number | void = 0
+  const success = await extrinsicWrapper(async () => {
+    const invitedWorkerValue = api.createType('Option<WorkerId>', invitedWorker)
+
+    const tx = api.tx.storage.createStorageBucket(invitedWorkerValue, allowedNewBags, sizeLimit, objectsLimit)
+    bucketId = await sendAndFollowNamedTx(api, account, tx, false, (result) => {
+      const event = getEvent(result, 'storage', 'StorageBucketCreated')
+      const bucketId = event?.data[0]
+
+      return bucketId.toNumber()
+    })
+  })
+
+  return [success, bucketId]
+}
+
+/**
+ * Accepts the storage provider invitation for a bucket.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param workerId - runtime storage provider ID (worker ID)
+ * @param storageBucketId - runtime storage bucket ID
+ * @returns promise with a success flag.
+ */
+export async function acceptStorageBucketInvitation(
+  api: ApiPromise,
+  account: KeyringPair,
+  workerId: number,
+  storageBucketId: number
+): Promise<boolean> {
+  return await extrinsicWrapper(() => {
+    const tx = api.tx.storage.acceptStorageBucketInvitation(workerId, storageBucketId)
+
+    return sendAndFollowNamedTx(api, account, tx)
+  })
+}
+
+/**
+ * Updates storage bucket to bags relationships.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param bagId - BagId instance
+ * @param account - KeyringPair instance
+ * @param add - runtime storage bucket IDs to add
+ * @param remove - runtime storage bucket IDs to remove
+ * @returns promise with a success flag.
+ */
+export async function updateStorageBucketsForBag(
+  api: ApiPromise,
+  bagId: BagId,
+  account: KeyringPair,
+  add: number[],
+  remove: number[]
+): Promise<boolean> {
+  return await extrinsicWrapper(() => {
+    const removeBuckets = api.createType('StorageBucketIdSet', remove)
+    const addBuckets = api.createType('StorageBucketIdSet', add)
+
+    const tx = api.tx.storage.updateStorageBucketsForBag(bagId, addBuckets, removeBuckets)
+
+    return sendAndFollowNamedTx(api, account, tx)
+  })
+}
+
+/**
+ * Uploads a data object info.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param objectSize - object size in bytes
+ * @param objectCid - object CID (Content ID - multihash)
+ * @param dataFee - expected 'DataObjectPerMegabyteFee' runtime value
+ * @returns promise with a success flag.
+ */
+export async function uploadDataObjects(
+  api: ApiPromise,
+  objectSize: number,
+  objectCid: string,
+  dataFee: number
+): Promise<boolean> {
+  return await extrinsicWrapper(() => {
+    const alice = getAlicePair()
+
+    const data = api.createType('UploadParameters', {
+      deletionPrizeSourceAccountId: alice.address,
+      objectCreationList: [
+        {
+          Size: objectSize,
+          IpfsContentId: objectCid,
+        },
+      ],
+      expectedDataSizeFee: dataFee,
+    })
+
+    const tx = api.tx.storage.sudoUploadDataObjects(data)
+
+    return sendAndFollowSudoNamedTx(api, alice, tx)
+  })
+}
+
+/**
+ * Accepts pending data objects by storage provider.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param bagId - BagId instance
+ * @param account - KeyringPair instance
+ * @param workerId - runtime storage provider ID (worker ID)
+ * @param storageBucketId - runtime storage bucket ID
+ * @param dataObjects - runtime data objects IDs
+ * @returns promise with a success flag.
+ */
+export async function acceptPendingDataObjects(
+  api: ApiPromise,
+  bagId: BagId,
+  account: KeyringPair,
+  workerId: number,
+  storageBucketId: number,
+  dataObjects: number[]
+): Promise<boolean> {
+  return await extrinsicWrapper(() => {
+    const dataObjectSet = api.createType('DataObjectIdSet', dataObjects)
+
+    const tx = api.tx.storage.acceptPendingDataObjects(workerId, storageBucketId, bagId, dataObjectSet)
+
+    return sendAndFollowNamedTx(api, account, tx)
+  }, true)
+}
+
+/**
+ * Updates a 'StorageBucketsPerBag' limit.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param bagId - BagId instance
+ * @param newLimit - new limit
+ * @returns promise with a success flag.
+ */
+export async function updateStorageBucketsPerBagLimit(
+  api: ApiPromise,
+  account: KeyringPair,
+  newLimit: number
+): Promise<boolean> {
+  return await extrinsicWrapper(() => {
+    const tx = api.tx.storage.updateStorageBucketsPerBagLimit(newLimit)
+
+    return sendAndFollowNamedTx(api, account, tx)
+  })
+}
+
+/**
+ * Updates a 'StorageBucketsVoucherMaxLimits' variables.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param bagId - BagId instance
+ * @param newSizeLimit - new size limit
+ * @param newObjectLimit - new object limit
+ * @returns promise with a success flag.
+ */
+export async function updateStorageBucketsVoucherMaxLimits(
+  api: ApiPromise,
+  account: KeyringPair,
+  newSizeLimit: number,
+  newObjectLimit: number
+): Promise<boolean> {
+  return await extrinsicWrapper(() => {
+    const tx = api.tx.storage.updateStorageBucketsVoucherMaxLimits(newSizeLimit, newObjectLimit)
+
+    return sendAndFollowNamedTx(api, account, tx)
+  })
+}
+
+/**
+ * Deletes a storage bucket.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param bucketId - runtime storage bucket ID
+ * @returns promise with a success flag.
+ */
+export async function deleteStorageBucket(api: ApiPromise, account: KeyringPair, bucketId: number): Promise<boolean> {
+  return await extrinsicWrapper(() => {
+    const tx = api.tx.storage.deleteStorageBucket(bucketId)
+
+    return sendAndFollowNamedTx(api, account, tx)
+  })
+}
+
+/**
+ * Invites a storage provider for a bucket.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param bucketId - runtime storage bucket ID
+ * @param operatorId - runtime storage operator ID (worker ID)
+ * @returns promise with a success flag.
+ */
+export async function inviteStorageBucketOperator(
+  api: ApiPromise,
+  account: KeyringPair,
+  bucketId: number,
+  operatorId: number
+): Promise<boolean> {
+  return await extrinsicWrapper(() => {
+    const tx = api.tx.storage.inviteStorageBucketOperator(bucketId, operatorId)
+
+    return sendAndFollowNamedTx(api, account, tx)
+  })
+}
+
+/**
+ * Helper-function. It catches the error, logs it and returns a success flag.
+ *
+ * @param extrinsic - extrinsic promise
+ * @param throwErr - disables the default error catch and rethrows an error
+ * after logging.
+ * @returns promise with a success flag.
+ */
+async function extrinsicWrapper(extrinsic: () => Promise<void>, throwErr = false): Promise<boolean> {
+  try {
+    await extrinsic()
+  } catch (err) {
+    logger.error(`Api Error: ${err}`)
+
+    if (throwErr) {
+      throw err
+    }
+    return false
+  }
+
+  return true
+}
+
+/**
+ * Cancels the invite for the storage provider.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param bucketId - runtime storage bucket ID
+ * @returns promise with a success flag.
+ */
+export async function cancelStorageBucketOperatorInvite(
+  api: ApiPromise,
+  account: KeyringPair,
+  bucketId: number
+): Promise<boolean> {
+  return await extrinsicWrapper(() => {
+    const tx = api.tx.storage.cancelStorageBucketOperatorInvite(bucketId)
+
+    return sendAndFollowNamedTx(api, account, tx)
+  })
+}
+
+/**
+ * Removes a storage provider association with a bucket.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param bucketId - runtime storage bucket ID
+ * @returns promise with a success flag.
+ */
+export async function removeStorageBucketOperator(
+  api: ApiPromise,
+  account: KeyringPair,
+  bucketId: number
+): Promise<boolean> {
+  return await extrinsicWrapper(() => {
+    const tx = api.tx.storage.removeStorageBucketOperator(bucketId)
+
+    return sendAndFollowNamedTx(api, account, tx)
+  })
+}
+
+/**
+ * Updates a 'DataSizeFee' variable.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param bagId - BagId instance
+ * @param fee - new fee
+ * @returns promise with a success flag.
+ */
+export async function updateDataSizeFee(api: ApiPromise, account: KeyringPair, fee: number): Promise<boolean> {
+  return await extrinsicWrapper(() => {
+    const tx = api.tx.storage.updateDataSizeFee(fee)
+
+    return sendAndFollowNamedTx(api, account, tx)
+  })
+}
+
+/**
+ * Sets a metadata for the storage provider.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param operatorId - runtime storage operator ID (worker ID)
+ * @param bucketId - runtime storage bucket ID
+ * @param metadata - new metadata
+ * @returns promise with a success flag.
+ */
+export async function setStorageOperatorMetadata(
+  api: ApiPromise,
+  account: KeyringPair,
+  operatorId: number,
+  bucketId: number,
+  metadata: string
+): Promise<boolean> {
+  return await extrinsicWrapper(() => {
+    const tx = api.tx.storage.setStorageOperatorMetadata(operatorId, bucketId, metadata)
+
+    return sendAndFollowNamedTx(api, account, tx)
+  })
+}
+
+/**
+ * Updates the 'UploadingBlocked' variable.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param newStatus - new block status
+ * @returns promise with a success flag.
+ */
+export async function updateUploadingBlockedStatus(
+  api: ApiPromise,
+  account: KeyringPair,
+  newStatus: boolean
+): Promise<boolean> {
+  return await extrinsicWrapper(() => {
+    const tx = api.tx.storage.updateUploadingBlockedStatus(newStatus)
+
+    return sendAndFollowNamedTx(api, account, tx)
+  })
+}
+
+/**
+ * Updates the storage bucket status (whether it accepts new bags).
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param storageBucketId - runtime storage bucket ID
+ * @param newStatus - new storage bucket status status (accepts new bag)
+ * @returns promise with a success flag.
+ */
+export async function updateStorageBucketStatus(
+  api: ApiPromise,
+  account: KeyringPair,
+  storageBucketId: number,
+  newStatus: boolean
+): Promise<boolean> {
+  return await extrinsicWrapper(() => {
+    const tx = api.tx.storage.updateStorageBucketStatus(storageBucketId, newStatus)
+
+    return sendAndFollowNamedTx(api, account, tx)
+  })
+}
+
+/**
+ * Updates a 'StorageBucketVoucherLimits' variable for a storage bucket.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param workerId - runtime storage provider ID (worker ID)
+ * @param storageBucketId - runtime storage bucket ID
+ * @param newSizeLimit - new size limit
+ * @param newObjectLimit - new object limit
+ * @returns promise with a success flag.
+ */
+export async function setStorageBucketVoucherLimits(
+  api: ApiPromise,
+  account: KeyringPair,
+  storageBucketId: number,
+  newSizeLimit: number,
+  newObjectLimit: number
+): Promise<boolean> {
+  return await extrinsicWrapper(() => {
+    const tx = api.tx.storage.setStorageBucketVoucherLimits(storageBucketId, newSizeLimit, newObjectLimit)
+
+    return sendAndFollowNamedTx(api, account, tx)
+  })
+}
+
+/**
+ * Updates the number of storage buckets in the dynamic bag creation policy.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param dynamicBagType - dynamic bag type
+ * @param newNumber - new number
+ * @returns promise with a success flag.
+ */
+export async function updateNumberOfStorageBucketsInDynamicBagCreationPolicy(
+  api: ApiPromise,
+  account: KeyringPair,
+  dynamicBagType: DynamicBagType,
+  newNumber: number
+): Promise<boolean> {
+  return await extrinsicWrapper(() => {
+    const tx = api.tx.storage.updateNumberOfStorageBucketsInDynamicBagCreationPolicy(dynamicBagType, newNumber)
+
+    return sendAndFollowNamedTx(api, account, tx)
+  })
+}
+
+/**
+ * Updates the blacklist for the storage.
+ *
+ * @remarks
+ * It sends an extrinsic to the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param add - content IDs (multihash) to add
+ * @param remove - content IDs (multihash) to add
+ * @returns promise with a success flag.
+ */
+export async function updateBlacklist(
+  api: ApiPromise,
+  account: KeyringPair,
+  add: string[],
+  remove: string[]
+): Promise<boolean> {
+  return await extrinsicWrapper(() => {
+    const removeHashes = api.createType('ContentIdSet', remove)
+    const addHashes = api.createType('ContentIdSet', add)
+
+    const tx = api.tx.storage.updateBlacklist(removeHashes, addHashes)
+
+    return sendAndFollowNamedTx(api, account, tx)
+  })
+}

+ 91 - 0
storage-node-v2/src/services/runtime/hireLead.ts

@@ -0,0 +1,91 @@
+import { sendAndFollowSudoNamedTx, sendAndFollowNamedTx, getEvent } from './api'
+import { getAlicePair } from './accounts'
+import { MemberId } from '@joystream/types/members'
+import { ApiPromise } from '@polkadot/api'
+import logger from '../../services/logger'
+
+/**
+ * Hires the leader for the Storage working group.
+ *
+ * @remarks
+ * This method should be used in the development mode only.
+ *
+ * @param api - runtime API promise
+ * @return void promise
+ *
+ */
+export async function hireStorageWorkingGroupLead(api: ApiPromise): Promise<void> {
+  const SudoKeyPair = getAlicePair()
+  const LeadKeyPair = getAlicePair()
+
+  // Create membership if not already created
+  const members = await api.query.members.memberIdsByControllerAccountId(LeadKeyPair.address)
+
+  let memberId: MemberId | undefined = members.toArray()[0]
+
+  if (memberId === undefined) {
+    logger.info('Preparing member account creation extrinsic...')
+    memberId = await api.query.members.nextMemberId()
+    const tx = api.tx.members.buyMembership(0, 'alice', null, null)
+    await sendAndFollowNamedTx(api, LeadKeyPair, tx)
+  }
+
+  // Create a new lead opening.
+  const currentLead = await api.query.storageWorkingGroup.currentLead()
+  if (currentLead.isSome) {
+    logger.info('Storage lead already exists, skipping...')
+    return
+  }
+
+  logger.info(`Making member id: ${memberId} the content lead.`)
+
+  // Create curator lead opening
+  logger.info('Preparing Create Storage Lead Opening extrinsic...')
+  let tx = api.tx.storageWorkingGroup.addOpening(
+    { CurrentBlock: null }, // activate_at
+    { max_review_period_length: 9999 }, // OpeningPolicyCommitment
+    'storage opening', // human_readable_text
+    'Leader' // opening_type
+  )
+  const newOpeningId = await sendAndFollowSudoNamedTx(api, SudoKeyPair, tx, (result) => {
+    const event = getEvent(result, 'storageWorkingGroup', 'OpeningAdded')
+    const openingId = event?.data[0]
+
+    return openingId.toNumber()
+  })
+
+  if (typeof newOpeningId !== 'number') {
+    throw Error('Cannot create opening.')
+  }
+
+  // Apply to lead opening
+  logger.info('Preparing Apply to Storage Lead Opening extrinsic...')
+  tx = api.tx.storageWorkingGroup.applyOnOpening(
+    memberId, // member id
+    newOpeningId, // opening id
+    LeadKeyPair.address, // address
+    null, // opt role stake
+    null, // opt appl. stake
+    'bootstrap opening' // human_readable_text
+  )
+  const newApplicationId = await sendAndFollowNamedTx(api, LeadKeyPair, tx, false, (result) => {
+    const event = getEvent(result, 'storageWorkingGroup', 'AppliedOnOpening')
+    const applicationId = event?.data[1]
+
+    return applicationId.toNumber()
+  })
+
+  // Begin review period
+  logger.info('Preparing Begin Applicant Review extrinsic...')
+  tx = api.tx.storageWorkingGroup.beginApplicantReview(newOpeningId)
+  await sendAndFollowSudoNamedTx(api, SudoKeyPair, tx)
+
+  // Fill opening
+  logger.info('Preparing Fill Opening extrinsic...')
+  tx = api.tx.storageWorkingGroup.fillOpening(
+    newOpeningId, // opening id
+    api.createType('ApplicationIdSet', [newApplicationId]), // successful applicants
+    null // reward policy
+  )
+  await sendAndFollowSudoNamedTx(api, SudoKeyPair, tx)
+}

+ 34 - 0
storage-node-v2/src/services/runtime/transactionNonceKeeper.ts

@@ -0,0 +1,34 @@
+import { KeyringPair } from '@polkadot/keyring/types'
+import type { Index } from '@polkadot/types/interfaces/runtime'
+import BN from 'bn.js'
+import AwaitLock from 'await-lock'
+import { ApiPromise } from '@polkadot/api'
+import logger from '../logger'
+
+let nonce: Index | null = null
+const lock = new AwaitLock()
+
+/**
+ * Return the current transaction nonce for an account from the runtime.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyPair instance
+ * @returns promise with transaction nonce for a given account.
+ *
+ */
+export async function getNonce(api: ApiPromise, account: KeyringPair): Promise<Index> {
+  await lock.acquireAsync()
+  try {
+    if (nonce === null) {
+      nonce = await api.rpc.system.accountNextIndex(account.address)
+    } else {
+      nonce = nonce.add(new BN(1)) as Index
+    }
+  } finally {
+    lock.release()
+  }
+
+  logger.debug(`Last transaction nonce:${nonce}`)
+
+  return nonce as Index
+}

+ 152 - 0
storage-node-v2/src/services/webApi/app.ts

@@ -0,0 +1,152 @@
+import express from 'express'
+import path from 'path'
+import cors from 'cors'
+import { Express, NextFunction } from 'express-serve-static-core'
+import * as OpenApiValidator from 'express-openapi-validator'
+import { HttpError, OpenAPIV3 } from 'express-openapi-validator/dist/framework/types'
+import { KeyringPair } from '@polkadot/keyring/types'
+import { ApiPromise } from '@polkadot/api'
+import { RequestData, verifyTokenSignature, parseUploadToken, UploadToken } from '../helpers/auth'
+import { checkRemoveNonce } from '../../services/helpers/tokenNonceKeeper'
+import { httpLogger, errorLogger } from '../../services/logger'
+
+/**
+ * Creates Express web application. Uses the OAS spec file for the API.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @param workerId - storage provider ID (worker ID)
+ * @param uploadsDir - directory for the file uploading
+ * @returns Express promise.
+ */
+export async function createApp(
+  api: ApiPromise,
+  account: KeyringPair,
+  workerId: number,
+  uploadsDir: string
+): Promise<Express> {
+  const spec = path.join(__dirname, './../../api-spec/openapi.yaml')
+
+  const app = express()
+
+  app.use(cors())
+  app.use(express.json())
+  app.use(httpLogger())
+
+  app.use(
+    // Set parameters for each request.
+    (req: express.Request, res: express.Response, next: NextFunction) => {
+      res.locals.uploadsDir = uploadsDir
+      res.locals.storageProviderAccount = account
+      res.locals.workerId = workerId
+      res.locals.api = api
+      next()
+    },
+    // Setup OpenAPiValidator
+    OpenApiValidator.middleware({
+      apiSpec: spec,
+      validateApiSpec: true,
+      validateResponses: true,
+      validateRequests: true,
+      operationHandlers: {
+        basePath: path.join(__dirname, './controllers'),
+        resolver: OpenApiValidator.resolvers.modulePathResolver,
+      },
+      fileUploader: { dest: uploadsDir },
+      validateSecurity: {
+        handlers: {
+          UploadAuth: validateUpload(api, account),
+        },
+      },
+    })
+  ) // Required signature.
+
+  app.use(errorLogger())
+
+  /* eslint-disable @typescript-eslint/no-unused-vars */
+  app.use((err: Error, req: express.Request, res: express.Response, next: express.NextFunction) => {
+    // Request validation error handler.
+    if (err instanceof HttpError) {
+      res.status(err.status).json({
+        type: 'request_validation',
+        message: err.message,
+        errors: err.errors,
+      })
+    } else {
+      res.status(500).json({
+        type: 'unknown_error',
+        message: err.message,
+      })
+    }
+
+    next()
+  })
+
+  return app
+}
+
+// Defines a signature for a upload validation function.
+type ValidateUploadFunction = (
+  req: express.Request,
+  scopes: string[],
+  schema: OpenAPIV3.SecuritySchemeObject
+) => boolean | Promise<boolean>
+
+/**
+ * Creates upload validation function with captured parameters from the request.
+ *
+ * @param api - runtime API promise
+ * @param account - KeyringPair instance
+ * @returns ValidateUploadFunction.
+ */
+function validateUpload(api: ApiPromise, account: KeyringPair): ValidateUploadFunction {
+  // We don't use these variables yet.
+  /* eslint-disable @typescript-eslint/no-unused-vars */
+  return (req: express.Request, scopes: string[], schema: OpenAPIV3.SecuritySchemeObject) => {
+    const tokenString = req.headers['x-api-key'] as string
+    const token = parseUploadToken(tokenString)
+
+    const sourceTokenRequest: RequestData = {
+      dataObjectId: parseInt(req.body.dataObjectId),
+      storageBucketId: parseInt(req.body.storageBucketId),
+      bagId: req.body.bagId,
+    }
+
+    verifyUploadTokenData(account.address, token, sourceTokenRequest)
+
+    return true
+  }
+}
+
+/**
+ * Verifies upload request token. Throws exceptions on errors.
+ *
+ * @param accountAddress - account address (public key)
+ * @param token - token object
+ * @param request - data from the request to validate token
+ */
+function verifyUploadTokenData(accountAddress: string, token: UploadToken, request: RequestData): void {
+  if (!verifyTokenSignature(token, accountAddress)) {
+    throw new Error('Invalid signature')
+  }
+
+  if (token.data.dataObjectId !== request.dataObjectId) {
+    throw new Error('Unexpected dataObjectId')
+  }
+
+  if (token.data.storageBucketId !== request.storageBucketId) {
+    throw new Error('Unexpected storageBucketId')
+  }
+
+  if (token.data.bagId !== request.bagId) {
+    throw new Error('Unexpected bagId')
+  }
+
+  if (token.data.validUntil < Date.now()) {
+    throw new Error('Token expired')
+  }
+
+  if (!checkRemoveNonce(token.data.nonce)) {
+    throw new Error('Nonce not found')
+  }
+}

+ 397 - 0
storage-node-v2/src/services/webApi/controllers/publicApi.ts

@@ -0,0 +1,397 @@
+import { acceptPendingDataObjects } from '../../runtime/extrinsics'
+import { ExtrinsicFailedError } from '../../runtime/api'
+import {
+  RequestData,
+  UploadTokenRequest,
+  UploadTokenBody,
+  createUploadToken,
+  verifyTokenSignature,
+} from '../../helpers/auth'
+import { hashFile } from '../../../services/helpers/hashing'
+import { createNonce, getTokenExpirationTime } from '../../../services/helpers/tokenNonceKeeper'
+import { getFileInfo } from '../../../services/helpers/fileInfo'
+import { parseBagId } from '../../helpers/bagTypes'
+import logger from '../../../services/logger'
+import { KeyringPair } from '@polkadot/keyring/types'
+import { ApiPromise } from '@polkadot/api'
+import * as express from 'express'
+import fs from 'fs'
+import path from 'path'
+import send from 'send'
+import { CLIError } from '@oclif/errors'
+const fsPromises = fs.promises
+
+/**
+ * Dedicated error for the web api requests.
+ */
+export class WebApiError extends CLIError {
+  httpStatusCode: number
+
+  constructor(err: string, httpStatusCode: number) {
+    super(err)
+
+    this.httpStatusCode = httpStatusCode
+  }
+}
+
+/**
+ * Dedicated server error for the web api requests.
+ */
+export class ServerError extends WebApiError {
+  constructor(err: string) {
+    super(err, 500)
+  }
+}
+
+/**
+ * A public endpoint: serves files by CID.
+ */
+export async function getFile(req: express.Request, res: express.Response): Promise<void> {
+  try {
+    const cid = getCid(req)
+    const uploadsDir = getUploadsDir(res)
+    const fullPath = path.resolve(uploadsDir, cid)
+
+    const fileInfo = await getFileInfo(fullPath)
+    const fileStats = await fsPromises.stat(fullPath)
+
+    const stream = send(req, fullPath)
+
+    stream.on('headers', (res) => {
+      // serve all files for download
+      res.setHeader('Content-Disposition', 'inline')
+      res.setHeader('Content-Type', fileInfo.mimeType)
+      res.setHeader('Content-Length', fileStats.size)
+    })
+
+    stream.on('error', (err) => {
+      sendResponseWithError(res, err, 'files')
+    })
+
+    stream.pipe(res)
+  } catch (err) {
+    sendResponseWithError(res, err, 'files')
+  }
+}
+
+/**
+ * A public endpoint: sends file headers by CID.
+ */
+export async function getFileHeaders(req: express.Request, res: express.Response): Promise<void> {
+  try {
+    const cid = getCid(req)
+    const uploadsDir = getUploadsDir(res)
+    const fullPath = path.resolve(uploadsDir, cid)
+    const fileInfo = await getFileInfo(fullPath)
+    const fileStats = await fsPromises.stat(fullPath)
+
+    res.setHeader('Content-Disposition', 'inline')
+    res.setHeader('Content-Type', fileInfo.mimeType)
+    res.setHeader('Content-Length', fileStats.size)
+
+    res.status(200).send()
+  } catch (err) {
+    res.status(getHttpStatusCodeByError(err)).send()
+  }
+}
+
+/**
+ * A public endpoint: receives file.
+ */
+export async function uploadFile(req: express.Request, res: express.Response): Promise<void> {
+  const uploadRequest: RequestData = req.body
+
+  // saved filename to delete on verification or extrinsic errors
+  let cleanupFileName = ''
+  try {
+    const fileObj = getFileObject(req)
+    cleanupFileName = fileObj.path
+
+    verifyFileSize(fileObj.size)
+    await verifyFileMimeType(fileObj.path)
+
+    const hash = await hashFile(fileObj.path)
+
+    // Prepare new file name
+    const newPath = fileObj.path.replace(fileObj.filename, hash)
+
+    // Overwrites existing file.
+    await fsPromises.rename(fileObj.path, newPath)
+    cleanupFileName = newPath
+
+    const api = getApi(res)
+    const bagId = parseBagId(api, uploadRequest.bagId)
+    await acceptPendingDataObjects(api, bagId, getAccount(res), getWorkerId(res), uploadRequest.storageBucketId, [
+      uploadRequest.dataObjectId,
+    ])
+    res.status(201).json({
+      id: hash,
+    })
+  } catch (err) {
+    await cleanupFileOnError(cleanupFileName, err.toString())
+
+    sendResponseWithError(res, err, 'upload')
+  }
+}
+
+/**
+ * A public endpoint: creates auth token for file uploads.
+ */
+export async function authTokenForUploading(req: express.Request, res: express.Response): Promise<void> {
+  try {
+    const account = getAccount(res)
+    const tokenRequest = getTokenRequest(req)
+    const api = getApi(res)
+
+    await validateTokenRequest(api, tokenRequest)
+
+    const tokenBody: UploadTokenBody = {
+      nonce: createNonce(),
+      validUntil: getTokenExpirationTime(),
+      ...tokenRequest.data,
+    }
+    const signedToken = createUploadToken(tokenBody, account)
+
+    res.status(201).json({
+      token: signedToken,
+    })
+  } catch (err) {
+    sendResponseWithError(res, err, 'authtoken')
+  }
+}
+
+/**
+ * Returns Multer.File object from the request.
+ *
+ * @remarks
+ * This is a helper function. It parses the request object for a variable and
+ * throws an error on failier.
+ */
+function getFileObject(req: express.Request): Express.Multer.File {
+  if (req.file) {
+    return req.file
+  }
+
+  const files = req.files as Express.Multer.File[]
+  if (files && files.length > 0) {
+    return files[0]
+  }
+
+  throw new WebApiError('No file uploaded', 400)
+}
+
+/**
+ * Returns worker ID from the response.
+ *
+ * @remarks
+ * This is a helper function. It parses the response object for a variable and
+ * throws an error on failure.
+ */
+function getWorkerId(res: express.Response): number {
+  if (res.locals.workerId || res.locals.workerId === 0) {
+    return res.locals.workerId
+  }
+
+  throw new ServerError('No Joystream worker ID loaded.')
+}
+
+/**
+ * Returns a directory for file uploading from the response.
+ *
+ * @remarks
+ * This is a helper function. It parses the response object for a variable and
+ * throws an error on failier.
+ */
+function getUploadsDir(res: express.Response): string {
+  if (res.locals.uploadsDir) {
+    return res.locals.uploadsDir
+  }
+
+  throw new ServerError('No upload directory path loaded.')
+}
+
+/**
+ * Returns a KeyPair instance from the response.
+ *
+ * @remarks
+ * This is a helper function. It parses the response object for a variable and
+ * throws an error on failier.
+ */
+function getAccount(res: express.Response): KeyringPair {
+  if (res.locals.storageProviderAccount) {
+    return res.locals.storageProviderAccount
+  }
+
+  throw new ServerError('No Joystream account loaded.')
+}
+
+/**
+ * Returns API promise from the response.
+ *
+ * @remarks
+ * This is a helper function. It parses the response object for a variable and
+ * throws an error on failier.
+ */
+function getApi(res: express.Response): ApiPromise {
+  if (res.locals.api) {
+    return res.locals.api
+  }
+
+  throw new ServerError('No Joystream API loaded.')
+}
+
+/**
+ * Returns Content ID from the request.
+ *
+ * @remarks
+ * This is a helper function. It parses the request object for a variable and
+ * throws an error on failier.
+ */
+function getCid(req: express.Request): string {
+  const cid = req.params.cid || ''
+  if (cid.length > 0) {
+    return cid
+  }
+
+  throw new WebApiError('No CID provided.', 400)
+}
+
+/**
+ * Returns UploadTokenRequest object from the request.
+ *
+ * @remarks
+ * This is a helper function. It parses the request object for a variable and
+ * throws an error on failier.
+ */
+function getTokenRequest(req: express.Request): UploadTokenRequest {
+  const tokenRequest = req.body as UploadTokenRequest
+  if (tokenRequest) {
+    return tokenRequest
+  }
+
+  throw new WebApiError('No token request provided.', 401)
+}
+
+/**
+ * Validates token request. It verifies token signature and compares the
+ * member ID and account ID from the runtime with token data.
+ *
+ * @param api - runtime API promise
+ * @param tokenRequest - UploadTokenRequest instance
+ * @returns void promise.
+ */
+async function validateTokenRequest(api: ApiPromise, tokenRequest: UploadTokenRequest): Promise<void> {
+  const result = verifyTokenSignature(tokenRequest, tokenRequest.data.accountId)
+
+  if (!result) {
+    throw new WebApiError('Invalid upload token request signature.', 401)
+  }
+
+  const membership = await api.query.members.membershipById(tokenRequest.data.memberId)
+  if (membership.controller_account.toString() !== tokenRequest.data.accountId) {
+    throw new WebApiError(`Provided controller account and member id don't match.`, 401)
+  }
+}
+
+/**
+ * Validates file size. It throws an error when file size exceeds the limit
+ *
+ * @param fileSize - runtime API promise
+ * @returns void promise.
+ */
+function verifyFileSize(fileSize: number) {
+  const MAX_FILE_SIZE = 1000000 // TODO: Get this const from the runtime
+
+  if (fileSize > MAX_FILE_SIZE) {
+    throw new WebApiError('Max file size exceeded.', 400)
+  }
+}
+
+/**
+ * Tries to remove file on error. It silences possible IO error and logs it.
+ *
+ * @param cleanupFileName - file path to delete
+ * @param error - external error
+ * @returns void promise.
+ */
+async function cleanupFileOnError(cleanupFileName: string, error: string): Promise<void> {
+  if (cleanupFileName) {
+    try {
+      await fsPromises.unlink(cleanupFileName)
+    } catch (err) {
+      logger.error(`Cannot delete the file (${cleanupFileName}) on error: ${error}. IO error: ${err}`)
+    }
+  }
+}
+
+/**
+ * Verifies the mime type of the file by its content. It throws an exception
+ * if the mime type differs from allowed list ('image/', 'video/', 'audio/').
+ *
+ * @param filePath - file path to detect mime types
+ * @param error - external error
+ * @returns void promise.
+ */
+async function verifyFileMimeType(filePath: string): Promise<void> {
+  const allowedMimeTypes = ['image/', 'video/', 'audio/']
+
+  const fileInfo = await getFileInfo(filePath)
+  const correctMimeType = allowedMimeTypes.some((allowedType) => fileInfo.mimeType.startsWith(allowedType))
+
+  if (!correctMimeType) {
+    throw new WebApiError(`Incorrect mime type detected: ${fileInfo.mimeType}`, 400)
+  }
+}
+
+/**
+ * Handles errors and sends a response.
+ *
+ * @param res - Response instance
+ * @param err - error
+ * @param errorType - defines request type
+ * @returns void promise.
+ */
+function sendResponseWithError(res: express.Response, err: Error, errorType: string): void {
+  const message = isNofileError(err) ? `File not found.` : err.toString()
+
+  res.status(getHttpStatusCodeByError(err)).json({
+    type: errorType,
+    message,
+  })
+}
+
+/**
+ * Checks the error for 'no-file' error (ENOENT).
+ *
+ * @param err - error
+ * @returns true when error code contains 'ENOENT'.
+ */
+function isNofileError(err: Error): boolean {
+  return err.toString().includes('ENOENT')
+}
+
+/**
+ * Get the status code by error.
+ *
+ * @param err - error
+ * @returns HTTP status code
+ */
+function getHttpStatusCodeByError(err: Error): number {
+  if (isNofileError(err)) {
+    return 404
+  }
+
+  if (err instanceof ExtrinsicFailedError) {
+    return 400
+  }
+
+  if (err instanceof WebApiError) {
+    return err.httpStatusCode
+  }
+
+  if (err instanceof CLIError) {
+    return 400
+  }
+
+  return 500
+}

+ 26 - 0
storage-node-v2/tsconfig.json

@@ -0,0 +1,26 @@
+{
+  "compilerOptions": {
+    "declaration": true,
+    "importHelpers": true,
+    "module": "commonjs",
+    "outDir": "lib",
+    "rootDir": "src",
+    "strict": true,
+    "target": "es2017",
+    "skipLibCheck": true,
+    "baseUrl": ".",
+    "paths": {
+      "@polkadot/types/augment": ["../types/augment-codec/augment-types.ts"],
+      "@polkadot/api/augment": ["../types/augment-codec/augment-api.ts"],
+    },
+    "esModuleInterop": true,
+    "types" : [ "node", "mocha" ],
+    "noUnusedLocals": true,
+    "resolveJsonModule": true
+  },
+  "include": [
+    "src/**/*"
+  ]
+}
+
+

+ 3550 - 0
storage-node-v2/yarn.lock

@@ -0,0 +1,3550 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13":
+  version "7.12.13"
+  resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658"
+  integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==
+  dependencies:
+    "@babel/highlight" "^7.12.13"
+
+"@babel/generator@^7.14.2", "@babel/generator@^7.4.0":
+  version "7.14.3"
+  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.14.3.tgz#0c2652d91f7bddab7cccc6ba8157e4f40dcedb91"
+  integrity sha512-bn0S6flG/j0xtQdz3hsjJ624h3W0r3llttBMfyHX3YrZ/KtLYr15bjA0FXkgW7FpvrDuTuElXeVjiKlYRpnOFA==
+  dependencies:
+    "@babel/types" "^7.14.2"
+    jsesc "^2.5.1"
+    source-map "^0.5.0"
+
+"@babel/helper-function-name@^7.14.2":
+  version "7.14.2"
+  resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.14.2.tgz#397688b590760b6ef7725b5f0860c82427ebaac2"
+  integrity sha512-NYZlkZRydxw+YT56IlhIcS8PAhb+FEUiOzuhFTfqDyPmzAhRge6ua0dQYT/Uh0t/EDHq05/i+e5M2d4XvjgarQ==
+  dependencies:
+    "@babel/helper-get-function-arity" "^7.12.13"
+    "@babel/template" "^7.12.13"
+    "@babel/types" "^7.14.2"
+
+"@babel/helper-get-function-arity@^7.12.13":
+  version "7.12.13"
+  resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz#bc63451d403a3b3082b97e1d8b3fe5bd4091e583"
+  integrity sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==
+  dependencies:
+    "@babel/types" "^7.12.13"
+
+"@babel/helper-split-export-declaration@^7.12.13":
+  version "7.12.13"
+  resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz#e9430be00baf3e88b0e13e6f9d4eaf2136372b05"
+  integrity sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==
+  dependencies:
+    "@babel/types" "^7.12.13"
+
+"@babel/helper-validator-identifier@^7.14.0":
+  version "7.14.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz#d26cad8a47c65286b15df1547319a5d0bcf27288"
+  integrity sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==
+
+"@babel/highlight@^7.12.13":
+  version "7.14.0"
+  resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.0.tgz#3197e375711ef6bf834e67d0daec88e4f46113cf"
+  integrity sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==
+  dependencies:
+    "@babel/helper-validator-identifier" "^7.14.0"
+    chalk "^2.0.0"
+    js-tokens "^4.0.0"
+
+"@babel/parser@^7.12.13", "@babel/parser@^7.14.2", "@babel/parser@^7.4.3":
+  version "7.14.3"
+  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.3.tgz#9b530eecb071fd0c93519df25c5ff9f14759f298"
+  integrity sha512-7MpZDIfI7sUC5zWo2+foJ50CSI5lcqDehZ0lVgIhSi4bFEk94fLAKlF3Q0nzSQQ+ca0lm+O6G9ztKVBeu8PMRQ==
+
+"@babel/runtime@^7.13.10", "@babel/runtime@^7.13.9", "@babel/runtime@^7.14.0":
+  version "7.14.0"
+  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6"
+  integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==
+  dependencies:
+    regenerator-runtime "^0.13.4"
+
+"@babel/template@^7.12.13", "@babel/template@^7.4.0":
+  version "7.12.13"
+  resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327"
+  integrity sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==
+  dependencies:
+    "@babel/code-frame" "^7.12.13"
+    "@babel/parser" "^7.12.13"
+    "@babel/types" "^7.12.13"
+
+"@babel/traverse@^7.4.3":
+  version "7.14.2"
+  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.14.2.tgz#9201a8d912723a831c2679c7ebbf2fe1416d765b"
+  integrity sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA==
+  dependencies:
+    "@babel/code-frame" "^7.12.13"
+    "@babel/generator" "^7.14.2"
+    "@babel/helper-function-name" "^7.14.2"
+    "@babel/helper-split-export-declaration" "^7.12.13"
+    "@babel/parser" "^7.14.2"
+    "@babel/types" "^7.14.2"
+    debug "^4.1.0"
+    globals "^11.1.0"
+
+"@babel/types@^7.12.13", "@babel/types@^7.14.2", "@babel/types@^7.4.0":
+  version "7.14.2"
+  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.2.tgz#4208ae003107ef8a057ea8333e56eb64d2f6a2c3"
+  integrity sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==
+  dependencies:
+    "@babel/helper-validator-identifier" "^7.14.0"
+    to-fast-properties "^2.0.0"
+
+"@joystream/types@link:../types":
+  version "0.0.0"
+  uid ""
+
+"@nodelib/fs.scandir@2.1.4":
+  version "2.1.4"
+  resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69"
+  integrity sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==
+  dependencies:
+    "@nodelib/fs.stat" "2.0.4"
+    run-parallel "^1.1.9"
+
+"@nodelib/fs.stat@2.0.4", "@nodelib/fs.stat@^2.0.2":
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz#a3f2dd61bab43b8db8fa108a121cfffe4c676655"
+  integrity sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==
+
+"@nodelib/fs.walk@^1.2.3":
+  version "1.2.6"
+  resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz#cce9396b30aa5afe9e3756608f5831adcb53d063"
+  integrity sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==
+  dependencies:
+    "@nodelib/fs.scandir" "2.1.4"
+    fastq "^1.6.0"
+
+"@oclif/command@^1", "@oclif/command@^1.5.20", "@oclif/command@^1.6.0", "@oclif/command@^1.8.0":
+  version "1.8.0"
+  resolved "https://registry.yarnpkg.com/@oclif/command/-/command-1.8.0.tgz#c1a499b10d26e9d1a611190a81005589accbb339"
+  integrity sha512-5vwpq6kbvwkQwKqAoOU3L72GZ3Ta8RRrewKj9OJRolx28KLJJ8Dg9Rf7obRwt5jQA9bkYd8gqzMTrI7H3xLfaw==
+  dependencies:
+    "@oclif/config" "^1.15.1"
+    "@oclif/errors" "^1.3.3"
+    "@oclif/parser" "^3.8.3"
+    "@oclif/plugin-help" "^3"
+    debug "^4.1.1"
+    semver "^7.3.2"
+
+"@oclif/config@^1", "@oclif/config@^1.15.1", "@oclif/config@^1.17.0":
+  version "1.17.0"
+  resolved "https://registry.yarnpkg.com/@oclif/config/-/config-1.17.0.tgz#ba8639118633102a7e481760c50054623d09fcab"
+  integrity sha512-Lmfuf6ubjQ4ifC/9bz1fSCHc6F6E653oyaRXxg+lgT4+bYf9bk+nqrUpAbrXyABkCqgIBiFr3J4zR/kiFdE1PA==
+  dependencies:
+    "@oclif/errors" "^1.3.3"
+    "@oclif/parser" "^3.8.0"
+    debug "^4.1.1"
+    globby "^11.0.1"
+    is-wsl "^2.1.1"
+    tslib "^2.0.0"
+
+"@oclif/dev-cli@^1":
+  version "1.26.0"
+  resolved "https://registry.yarnpkg.com/@oclif/dev-cli/-/dev-cli-1.26.0.tgz#e3ec294b362c010ffc8948003d3770955c7951fd"
+  integrity sha512-272udZP+bG4qahoAcpWcMTJKiA+V42kRMqQM7n4tgW35brYb2UP5kK+p08PpF8sgSfRTV8MoJVJG9ax5kY82PA==
+  dependencies:
+    "@oclif/command" "^1.8.0"
+    "@oclif/config" "^1.17.0"
+    "@oclif/errors" "^1.3.3"
+    "@oclif/plugin-help" "^3.2.0"
+    cli-ux "^5.2.1"
+    debug "^4.1.1"
+    find-yarn-workspace-root "^2.0.0"
+    fs-extra "^8.1"
+    github-slugger "^1.2.1"
+    lodash "^4.17.11"
+    normalize-package-data "^3.0.0"
+    qqjs "^0.3.10"
+    tslib "^2.0.3"
+
+"@oclif/errors@^1.2.1", "@oclif/errors@^1.2.2", "@oclif/errors@^1.3.3":
+  version "1.3.4"
+  resolved "https://registry.yarnpkg.com/@oclif/errors/-/errors-1.3.4.tgz#a96f94536b4e25caa72eff47e8b3ed04f6995f55"
+  integrity sha512-pJKXyEqwdfRTUdM8n5FIHiQQHg5ETM0Wlso8bF9GodczO40mF5Z3HufnYWJE7z8sGKxOeJCdbAVZbS8Y+d5GCw==
+  dependencies:
+    clean-stack "^3.0.0"
+    fs-extra "^8.1"
+    indent-string "^4.0.0"
+    strip-ansi "^6.0.0"
+    wrap-ansi "^7.0.0"
+
+"@oclif/linewrap@^1.0.0":
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/@oclif/linewrap/-/linewrap-1.0.0.tgz#aedcb64b479d4db7be24196384897b5000901d91"
+  integrity sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw==
+
+"@oclif/parser@^3.8.0", "@oclif/parser@^3.8.3":
+  version "3.8.5"
+  resolved "https://registry.yarnpkg.com/@oclif/parser/-/parser-3.8.5.tgz#c5161766a1efca7343e1f25d769efbefe09f639b"
+  integrity sha512-yojzeEfmSxjjkAvMRj0KzspXlMjCfBzNRPkWw8ZwOSoNWoJn+OCS/m/S+yfV6BvAM4u2lTzX9Y5rCbrFIgkJLg==
+  dependencies:
+    "@oclif/errors" "^1.2.2"
+    "@oclif/linewrap" "^1.0.0"
+    chalk "^2.4.2"
+    tslib "^1.9.3"
+
+"@oclif/plugin-help@^3", "@oclif/plugin-help@^3.2.0":
+  version "3.2.2"
+  resolved "https://registry.yarnpkg.com/@oclif/plugin-help/-/plugin-help-3.2.2.tgz#063ee08cee556573a5198fbdfdaa32796deba0ed"
+  integrity sha512-SPZ8U8PBYK0n4srFjCLedk0jWU4QlxgEYLCXIBShJgOwPhTTQknkUlsEwaMIevvCU4iCQZhfMX+D8Pz5GZjFgA==
+  dependencies:
+    "@oclif/command" "^1.5.20"
+    "@oclif/config" "^1.15.1"
+    "@oclif/errors" "^1.2.2"
+    chalk "^4.1.0"
+    indent-string "^4.0.0"
+    lodash.template "^4.4.0"
+    string-width "^4.2.0"
+    strip-ansi "^6.0.0"
+    widest-line "^3.1.0"
+    wrap-ansi "^4.0.0"
+
+"@oclif/screen@^1.0.3":
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/@oclif/screen/-/screen-1.0.4.tgz#b740f68609dfae8aa71c3a6cab15d816407ba493"
+  integrity sha512-60CHpq+eqnTxLZQ4PGHYNwUX572hgpMHGPtTWMjdTMsAvlm69lZV/4ly6O3sAYkomo4NggGcomrDpBe34rxUqw==
+
+"@oclif/test@^1":
+  version "1.2.8"
+  resolved "https://registry.yarnpkg.com/@oclif/test/-/test-1.2.8.tgz#a5b2ebd747832217d9af65ac30b58780c4c17c5e"
+  integrity sha512-HCh0qPge1JCqTEw4s2ScnicEZd4Ro4/0VvdjpsfCiX6fuDV53fRZ2uqLTgxKGHrVoqOZnVrRZHyhFyEsFGs+zQ==
+  dependencies:
+    fancy-test "^1.4.3"
+
+"@polkadot/api-derive@4.2.1":
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/api-derive/-/api-derive-4.2.1.tgz#848a2a9ef947f08660af2571f72ca2b06969f2e3"
+  integrity sha512-TQqhK356IEk7ksMDE/tA3ZKqFEI8O8virZItd/w+RFaBs/HfbDNP8p+xPM5+6Rif3kuBzdubMv3Bdq/OIAJc6g==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@polkadot/api" "4.2.1"
+    "@polkadot/rpc-core" "4.2.1"
+    "@polkadot/types" "4.2.1"
+    "@polkadot/util" "^6.0.5"
+    "@polkadot/util-crypto" "^6.0.5"
+    "@polkadot/x-rxjs" "^6.0.5"
+    bn.js "^4.11.9"
+
+"@polkadot/api@4.2.1":
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-4.2.1.tgz#8eb0997dc148a34a4aca3a0dcaabad9954565909"
+  integrity sha512-PbXwcLnZr5V5LfKsovMS0TRG+rfJp8lJxluCyOSABDpaz2h1B5R8rdYEZCmXI3qSrT0yu2C6Pp8AjTQHRd7SAA==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@polkadot/api-derive" "4.2.1"
+    "@polkadot/keyring" "^6.0.5"
+    "@polkadot/metadata" "4.2.1"
+    "@polkadot/rpc-core" "4.2.1"
+    "@polkadot/rpc-provider" "4.2.1"
+    "@polkadot/types" "4.2.1"
+    "@polkadot/types-known" "4.2.1"
+    "@polkadot/util" "^6.0.5"
+    "@polkadot/util-crypto" "^6.0.5"
+    "@polkadot/x-rxjs" "^6.0.5"
+    bn.js "^4.11.9"
+    eventemitter3 "^4.0.7"
+
+"@polkadot/keyring@^6.0.5":
+  version "6.4.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-6.4.1.tgz#769c5f0613a27e18726b51e6539fa56f161f6160"
+  integrity sha512-47QMmGLDgj1ztgn/f2Pjx/RUo49xNv/4MhqDCHce/zQRk5Lb3jRqBhaukerp2hJYt2nVly0AucXc4QWml4fPHg==
+  dependencies:
+    "@babel/runtime" "^7.14.0"
+    "@polkadot/util" "6.4.1"
+    "@polkadot/util-crypto" "6.4.1"
+
+"@polkadot/metadata@4.2.1":
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/metadata/-/metadata-4.2.1.tgz#7bff99e44992708469e7b2aa70d0865637d8febe"
+  integrity sha512-oXuKOrKTU0wys5pedKd1OVUDWK8/NoBRCrUYN8fxq3Qq/J9Sz6lF4ZbgX3w22C75l1z2+acsebiZBwlpWgKeqw==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@polkadot/types" "4.2.1"
+    "@polkadot/types-known" "4.2.1"
+    "@polkadot/util" "^6.0.5"
+    "@polkadot/util-crypto" "^6.0.5"
+    bn.js "^4.11.9"
+
+"@polkadot/networks@6.4.1", "@polkadot/networks@^6.0.5":
+  version "6.4.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/networks/-/networks-6.4.1.tgz#0f933c4af10a2bfe8f072e2c7e8357ef03b2e37e"
+  integrity sha512-YGFeGJf8lIgiAL8U7XzRYZVWDKHhZbll6LSnRynzsox9CCqUa4oWyIBxymnsWBk13jj5KZZN24IsnyVURvBYiA==
+  dependencies:
+    "@babel/runtime" "^7.14.0"
+
+"@polkadot/rpc-core@4.2.1":
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/rpc-core/-/rpc-core-4.2.1.tgz#249f2e8f359450e365b0784d494814c7348e9a3e"
+  integrity sha512-A67Rt7lFpdauj7O7fRGn9yhII0SpCRJ/NkHWKo/whj8RwIAuOdxLnekGC9Qr26FPi0mAqN5DBQ8vYSDUiLFXxA==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@polkadot/metadata" "4.2.1"
+    "@polkadot/rpc-provider" "4.2.1"
+    "@polkadot/types" "4.2.1"
+    "@polkadot/util" "^6.0.5"
+    "@polkadot/x-rxjs" "^6.0.5"
+
+"@polkadot/rpc-provider@4.2.1":
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/rpc-provider/-/rpc-provider-4.2.1.tgz#2dbb217773a57fde2a70fc15628e2682e3ac81f8"
+  integrity sha512-Gwfs6JAD4Sp+Uz1kEtBSt1P6C3Lwn9xZ64CupU1/6w3qj9QzTFOKHKoznnekiH5HXSh53qVz2c2OSXptSrwL0Q==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@polkadot/types" "4.2.1"
+    "@polkadot/util" "^6.0.5"
+    "@polkadot/util-crypto" "^6.0.5"
+    "@polkadot/x-fetch" "^6.0.5"
+    "@polkadot/x-global" "^6.0.5"
+    "@polkadot/x-ws" "^6.0.5"
+    bn.js "^4.11.9"
+    eventemitter3 "^4.0.7"
+
+"@polkadot/types-known@4.2.1":
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/types-known/-/types-known-4.2.1.tgz#0f1ccef363359de0370cd5b3cc3e6dfe51a18f38"
+  integrity sha512-/zbvzcCiv6yLhnikVWrN03uJk/3Vuer+sbK8G/pVtLOUhRYdDLOet7VPmRnjH9CGsEGJDQebu0zqW77npg5V2Q==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@polkadot/networks" "^6.0.5"
+    "@polkadot/types" "4.2.1"
+    "@polkadot/util" "^6.0.5"
+    bn.js "^4.11.9"
+
+"@polkadot/types@4.2.1":
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/types/-/types-4.2.1.tgz#7be97d3abda4bb3f9031b43602062ed464596696"
+  integrity sha512-xl8QnbXiJmSm6MUZH/U/ov3ZSXMN+KgNjsTCCzfz2xR5B3eK9ClYcstYYkNSyF12K90Gut9bnNSGZvaCfT2hNQ==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@polkadot/metadata" "4.2.1"
+    "@polkadot/util" "^6.0.5"
+    "@polkadot/util-crypto" "^6.0.5"
+    "@polkadot/x-rxjs" "^6.0.5"
+    "@types/bn.js" "^4.11.6"
+    bn.js "^4.11.9"
+
+"@polkadot/util-crypto@6.4.1", "@polkadot/util-crypto@^6.0.5":
+  version "6.4.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-6.4.1.tgz#b567d824598bf8f4587364c1d7234bafe805f1c5"
+  integrity sha512-s75fjO1Duq+2N9btj6yw/1+iBssQTtbwkD/LHXNGttrVKdfHxpQoJyud8rJ1hzl+ELAMawat6humPuAVtM0DaA==
+  dependencies:
+    "@babel/runtime" "^7.14.0"
+    "@polkadot/networks" "6.4.1"
+    "@polkadot/util" "6.4.1"
+    "@polkadot/wasm-crypto" "^4.0.2"
+    "@polkadot/x-randomvalues" "6.4.1"
+    base-x "^3.0.8"
+    base64-js "^1.5.1"
+    blakejs "^1.1.0"
+    bn.js "^4.11.9"
+    create-hash "^1.2.0"
+    elliptic "^6.5.4"
+    hash.js "^1.1.7"
+    js-sha3 "^0.8.0"
+    scryptsy "^2.1.0"
+    tweetnacl "^1.0.3"
+    xxhashjs "^0.2.2"
+
+"@polkadot/util@6.4.1", "@polkadot/util@^6.0.5":
+  version "6.4.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-6.4.1.tgz#f40fdc91ae49396d7930e37dbd31747769555b7a"
+  integrity sha512-+vnmUFz/HR/BMqG4qxONMcbnwNovShIxmrfJIhAJK4NghZC6pSioj+EtY4itQDA5psgUbur5WEWMFX1Q4TT9Bw==
+  dependencies:
+    "@babel/runtime" "^7.14.0"
+    "@polkadot/x-textdecoder" "6.4.1"
+    "@polkadot/x-textencoder" "6.4.1"
+    "@types/bn.js" "^4.11.6"
+    bn.js "^4.11.9"
+    camelcase "^5.3.1"
+    ip-regex "^4.3.0"
+
+"@polkadot/wasm-crypto-asmjs@^4.0.2":
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-4.0.2.tgz#f42c353a64e1243841daf90e4bd54eff01a4e3cf"
+  integrity sha512-hlebqtGvfjg2ZNm4scwBGVHwOwfUhy2yw5RBHmPwkccUif3sIy4SAzstpcVBIVMdAEvo746bPWEInA8zJRcgJA==
+  dependencies:
+    "@babel/runtime" "^7.13.9"
+
+"@polkadot/wasm-crypto-wasm@^4.0.2":
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-4.0.2.tgz#89f9e0a1e4d076784d4a42bea37fc8b06bdd8bb6"
+  integrity sha512-de/AfNPZ0uDKFWzOZ1rJCtaUbakGN29ks6IRYu6HZTRg7+RtqvE1rIkxabBvYgQVHIesmNwvEA9DlIkS6hYRFQ==
+  dependencies:
+    "@babel/runtime" "^7.13.9"
+
+"@polkadot/wasm-crypto@^4.0.2":
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto/-/wasm-crypto-4.0.2.tgz#9649057adee8383cc86433d107ba526b718c5a3b"
+  integrity sha512-2h9FuQFkBc+B3TwSapt6LtyPvgtd0Hq9QsHW8g8FrmKBFRiiFKYRpfJKHCk0aCZzuRf9h95bQl/X6IXAIWF2ng==
+  dependencies:
+    "@babel/runtime" "^7.13.9"
+    "@polkadot/wasm-crypto-asmjs" "^4.0.2"
+    "@polkadot/wasm-crypto-wasm" "^4.0.2"
+
+"@polkadot/x-fetch@^6.0.5":
+  version "6.4.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/x-fetch/-/x-fetch-6.4.1.tgz#12b9e6d42e71deceff44c324ba41baed879093c1"
+  integrity sha512-qHMVmi35lDJqp4BFEa09zfk4t9GidOPOvv1Zd2FwDEIi+sSUh4ZoW74Oqatbi1dN9lKzjhLQMxwV+Yyp5M0x4A==
+  dependencies:
+    "@babel/runtime" "^7.14.0"
+    "@polkadot/x-global" "6.4.1"
+    "@types/node-fetch" "^2.5.10"
+    node-fetch "^2.6.1"
+
+"@polkadot/x-global@6.4.1", "@polkadot/x-global@^6.0.5":
+  version "6.4.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/x-global/-/x-global-6.4.1.tgz#546e019e0c7f72a92a2612cacf90e8797c94709f"
+  integrity sha512-u6y2KWAYw/lEyvFBEj17zyxTZAsXDbYdewF9Wr26dpPIhkx5XqCqAJtzX8/7tOhJEn7C4tRJz2nXpboL3pEStA==
+  dependencies:
+    "@babel/runtime" "^7.14.0"
+    "@types/node-fetch" "^2.5.10"
+    node-fetch "^2.6.1"
+
+"@polkadot/x-randomvalues@6.4.1":
+  version "6.4.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/x-randomvalues/-/x-randomvalues-6.4.1.tgz#bb30d309e03ab63196504f53962e47ec7b97fac9"
+  integrity sha512-1hsup7303d3bsW0HJsLroorrhpxf3xte/ZGOlOi6LtntHzzOZibteepQ+Oa7Ksy+nmCANpUcWGemm3Q9kGKW2g==
+  dependencies:
+    "@babel/runtime" "^7.14.0"
+    "@polkadot/x-global" "6.4.1"
+
+"@polkadot/x-rxjs@^6.0.5":
+  version "6.4.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/x-rxjs/-/x-rxjs-6.4.1.tgz#c6e8cef8dc3f20b4c7468bd6976d843947da1f15"
+  integrity sha512-msblJoRdM+Wz8Bn118z1oBDMC1nRTNvFigSRrRFVLaa675ztnMIvoOWzuaAg6G9touEbdmCDN4nKwKj5Rl8udg==
+  dependencies:
+    "@babel/runtime" "^7.14.0"
+    rxjs "^6.6.7"
+
+"@polkadot/x-textdecoder@6.4.1":
+  version "6.4.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/x-textdecoder/-/x-textdecoder-6.4.1.tgz#f33b81267d8de313e851cc699b9dfa6e8f109cde"
+  integrity sha512-sE/3QHAYS17qgCHBk2Ajn/FMubYsG+WTsnFW+MaoO6BZKxQuE+Gux/Up6HS/yJdJUfxhdoHUY0DcQCsw0vzU/Q==
+  dependencies:
+    "@babel/runtime" "^7.14.0"
+    "@polkadot/x-global" "6.4.1"
+
+"@polkadot/x-textencoder@6.4.1":
+  version "6.4.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/x-textencoder/-/x-textencoder-6.4.1.tgz#f34bcc1c1a60d723ea8ce84e10a1efbbf6c1371a"
+  integrity sha512-OeOEt6Mr/jSonzMkTw6haD10YHhwKSty1haIw/5Ahvs6fQe/ix0bZ8ECx/VHVsb98XOEKLm97p0K6n8t0w4n+Q==
+  dependencies:
+    "@babel/runtime" "^7.14.0"
+    "@polkadot/x-global" "6.4.1"
+
+"@polkadot/x-ws@^6.0.5":
+  version "6.4.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/x-ws/-/x-ws-6.4.1.tgz#e03295907a50f74ec220d9dc9aa6d45370f67554"
+  integrity sha512-DXEk9BUnxm/XW9xZt0+5EFA1X/TTwZgXr9kFJCACPepLZNrjq4EbbLjIj0n+hre96gOMS1fGKZTQFjUDuoVW0g==
+  dependencies:
+    "@babel/runtime" "^7.14.0"
+    "@polkadot/x-global" "6.4.1"
+    "@types/websocket" "^1.0.2"
+    websocket "^1.0.34"
+
+"@sinonjs/commons@^1.7.0":
+  version "1.8.3"
+  resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d"
+  integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==
+  dependencies:
+    type-detect "4.0.8"
+
+"@sinonjs/fake-timers@^7.0.4":
+  version "7.0.5"
+  resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-7.0.5.tgz#558a7f8145a01366c44b3dcbdd7172c05c461564"
+  integrity sha512-fUt6b15bjV/VW93UP5opNXJxdwZSbK1EdiwnhN7XrQrcpaOhMJpZ/CjwFpM3THpxwA+YviBUJKSuEqKlCK5alw==
+  dependencies:
+    "@sinonjs/commons" "^1.7.0"
+
+"@types/bn.js@^4.11.6":
+  version "4.11.6"
+  resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c"
+  integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==
+  dependencies:
+    "@types/node" "*"
+
+"@types/chai@*", "@types/chai@^4":
+  version "4.2.18"
+  resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.18.tgz#0c8e298dbff8205e2266606c1ea5fbdba29b46e4"
+  integrity sha512-rS27+EkB/RE1Iz3u0XtVL5q36MGDWbgYe7zWiodyKNUnthxY0rukK5V36eiUCtCisB7NN8zKYH6DO2M37qxFEQ==
+
+"@types/eslint-visitor-keys@^1.0.0":
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
+  integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==
+
+"@types/glob@^7.1.1":
+  version "7.1.3"
+  resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183"
+  integrity sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==
+  dependencies:
+    "@types/minimatch" "*"
+    "@types/node" "*"
+
+"@types/json-schema@^7.0.3":
+  version "7.0.7"
+  resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad"
+  integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==
+
+"@types/lodash@*", "@types/lodash@^4.14.157":
+  version "4.14.169"
+  resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.169.tgz#83c217688f07a4d9ef8f28a3ebd1d318f6ff4cbb"
+  integrity sha512-DvmZHoHTFJ8zhVYwCLWbQ7uAbYQEk52Ev2/ZiQ7Y7gQGeV9pjBqjnQpECMHfKS1rCYAhMI7LHVxwyZLZinJgdw==
+
+"@types/minimatch@*":
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.4.tgz#f0ec25dbf2f0e4b18647313ac031134ca5b24b21"
+  integrity sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==
+
+"@types/mocha@^5":
+  version "5.2.7"
+  resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea"
+  integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==
+
+"@types/node-fetch@^2.5.10":
+  version "2.5.10"
+  resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.10.tgz#9b4d4a0425562f9fcea70b12cb3fcdd946ca8132"
+  integrity sha512-IpkX0AasN44hgEad0gEF/V6EgR5n69VEqPEgnmoM8GsIGro3PowbWs4tR6IhxUTyPLpOn+fiGG6nrQhcmoCuIQ==
+  dependencies:
+    "@types/node" "*"
+    form-data "^3.0.0"
+
+"@types/node@*":
+  version "15.3.0"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-15.3.0.tgz#d6fed7d6bc6854306da3dea1af9f874b00783e26"
+  integrity sha512-8/bnjSZD86ZfpBsDlCIkNXIvm+h6wi9g7IqL+kmFkQ+Wvu3JrasgLElfiPgoo8V8vVfnEi0QVS12gbl94h9YsQ==
+
+"@types/node@^10":
+  version "10.17.60"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b"
+  integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==
+
+"@types/sinon@*":
+  version "10.0.0"
+  resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.0.tgz#eecc3847af03d45ffe53d55aaaaf6ecb28b5e584"
+  integrity sha512-jDZ55oCKxqlDmoTBBbBBEx+N8ZraUVhggMZ9T5t+6/Dh8/4NiOjSUfpLrPiEwxQDlAe3wpAkoXhWvE6LibtsMQ==
+  dependencies:
+    "@sinonjs/fake-timers" "^7.0.4"
+
+"@types/unist@^2.0.0":
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e"
+  integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==
+
+"@types/vfile@^4.0.0":
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/@types/vfile/-/vfile-4.0.0.tgz#c32d13cbda319bc9f4ab3cacc0263b4ba1dd1ea3"
+  integrity sha512-eleP0/Cz8uVWxARDLi3Axq2+fDdN4ibAXoC6Pv8p6s7znXaUL7XvhgeIhjCiNMnvlLNP+tmCLd+RuCryGgmtEg==
+  dependencies:
+    vfile "*"
+
+"@types/websocket@^1.0.2":
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-1.0.2.tgz#d2855c6a312b7da73ed16ba6781815bf30c6187a"
+  integrity sha512-B5m9aq7cbbD/5/jThEr33nUY8WEfVi6A2YKCTOvw5Ldy7mtsOkqRvGjnzy6g7iMMDsgu7xREuCzqATLDLQVKcQ==
+  dependencies:
+    "@types/node" "*"
+
+"@typescript-eslint/eslint-plugin@^2.6.1":
+  version "2.34.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.34.0.tgz#6f8ce8a46c7dea4a6f1d171d2bb8fbae6dac2be9"
+  integrity sha512-4zY3Z88rEE99+CNvTbXSyovv2z9PNOVffTWD2W8QF5s2prBQtwN2zadqERcrHpcR7O/+KMI3fcTAmUUhK/iQcQ==
+  dependencies:
+    "@typescript-eslint/experimental-utils" "2.34.0"
+    functional-red-black-tree "^1.0.1"
+    regexpp "^3.0.0"
+    tsutils "^3.17.1"
+
+"@typescript-eslint/experimental-utils@2.34.0":
+  version "2.34.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.34.0.tgz#d3524b644cdb40eebceca67f8cf3e4cc9c8f980f"
+  integrity sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA==
+  dependencies:
+    "@types/json-schema" "^7.0.3"
+    "@typescript-eslint/typescript-estree" "2.34.0"
+    eslint-scope "^5.0.0"
+    eslint-utils "^2.0.0"
+
+"@typescript-eslint/parser@^2.6.1":
+  version "2.34.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.34.0.tgz#50252630ca319685420e9a39ca05fe185a256bc8"
+  integrity sha512-03ilO0ucSD0EPTw2X4PntSIRFtDPWjrVq7C3/Z3VQHRC7+13YB55rcJI3Jt+YgeHbjUdJPcPa7b23rXCBokuyA==
+  dependencies:
+    "@types/eslint-visitor-keys" "^1.0.0"
+    "@typescript-eslint/experimental-utils" "2.34.0"
+    "@typescript-eslint/typescript-estree" "2.34.0"
+    eslint-visitor-keys "^1.1.0"
+
+"@typescript-eslint/typescript-estree@2.34.0":
+  version "2.34.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz#14aeb6353b39ef0732cc7f1b8285294937cf37d5"
+  integrity sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg==
+  dependencies:
+    debug "^4.1.1"
+    eslint-visitor-keys "^1.1.0"
+    glob "^7.1.6"
+    is-glob "^4.0.1"
+    lodash "^4.17.15"
+    semver "^7.3.2"
+    tsutils "^3.17.1"
+
+acorn-jsx@^5.0.0:
+  version "5.3.1"
+  resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b"
+  integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==
+
+acorn@^6.0.7:
+  version "6.4.2"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
+  integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
+
+ajv@^6.10.2, ajv@^6.11.0, ajv@^6.9.1:
+  version "6.12.6"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
+  integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
+  dependencies:
+    fast-deep-equal "^3.1.1"
+    fast-json-stable-stringify "^2.0.0"
+    json-schema-traverse "^0.4.1"
+    uri-js "^4.2.2"
+
+ansi-escapes@^3.1.0, ansi-escapes@^3.2.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b"
+  integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==
+
+ansi-escapes@^4.3.0:
+  version "4.3.2"
+  resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
+  integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
+  dependencies:
+    type-fest "^0.21.3"
+
+ansi-regex@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
+  integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
+
+ansi-regex@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
+  integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
+
+ansi-regex@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
+  integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
+
+ansi-styles@^3.2.0, ansi-styles@^3.2.1:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
+  integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+  dependencies:
+    color-convert "^1.9.0"
+
+ansi-styles@^4.0.0, ansi-styles@^4.1.0, ansi-styles@^4.2.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
+  integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
+  dependencies:
+    color-convert "^2.0.1"
+
+ansicolors@~0.3.2:
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979"
+  integrity sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=
+
+append-transform@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab"
+  integrity sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==
+  dependencies:
+    default-require-extensions "^2.0.0"
+
+archy@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40"
+  integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=
+
+arg@^4.1.0:
+  version "4.1.3"
+  resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
+  integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
+
+argparse@^1.0.7:
+  version "1.0.10"
+  resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
+  integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
+  dependencies:
+    sprintf-js "~1.0.2"
+
+array-union@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
+  integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
+
+assertion-error@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b"
+  integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==
+
+astral-regex@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
+  integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==
+
+asynckit@^0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+  integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
+
+balanced-match@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
+  integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+
+base-x@^3.0.8:
+  version "3.0.8"
+  resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.8.tgz#1e1106c2537f0162e8b52474a557ebb09000018d"
+  integrity sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==
+  dependencies:
+    safe-buffer "^5.0.1"
+
+base64-js@^1.3.1, base64-js@^1.5.1:
+  version "1.5.1"
+  resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
+  integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
+
+bl@^4.0.3:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
+  integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==
+  dependencies:
+    buffer "^5.5.0"
+    inherits "^2.0.4"
+    readable-stream "^3.4.0"
+
+blakejs@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.0.tgz#69df92ef953aa88ca51a32df6ab1c54a155fc7a5"
+  integrity sha1-ad+S75U6qIylGjLfarHFShVfx6U=
+
+bn.js@^4.11.9:
+  version "4.12.0"
+  resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88"
+  integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==
+
+brace-expansion@^1.1.7:
+  version "1.1.11"
+  resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+  integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+  dependencies:
+    balanced-match "^1.0.0"
+    concat-map "0.0.1"
+
+braces@^3.0.1:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
+  integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
+  dependencies:
+    fill-range "^7.0.1"
+
+brorand@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
+  integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=
+
+browser-stdout@1.3.1:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
+  integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
+
+buffer-from@^1.0.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
+  integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
+
+buffer@^5.5.0:
+  version "5.7.1"
+  resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
+  integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
+  dependencies:
+    base64-js "^1.3.1"
+    ieee754 "^1.1.13"
+
+bufferutil@^4.0.1:
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.3.tgz#66724b756bed23cd7c28c4d306d7994f9943cc6b"
+  integrity sha512-yEYTwGndELGvfXsImMBLop58eaGW+YdONi1fNjTINSY98tmMmFijBG6WXgdkfuLNt4imzQNtIE+eBp1PVpMCSw==
+  dependencies:
+    node-gyp-build "^4.2.0"
+
+caching-transform@^3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-3.0.2.tgz#601d46b91eca87687a281e71cef99791b0efca70"
+  integrity sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==
+  dependencies:
+    hasha "^3.0.0"
+    make-dir "^2.0.0"
+    package-hash "^3.0.0"
+    write-file-atomic "^2.4.2"
+
+callsites@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
+  integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
+
+camelcase@^5.0.0, camelcase@^5.3.1:
+  version "5.3.1"
+  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
+  integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
+
+cardinal@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/cardinal/-/cardinal-2.1.1.tgz#7cc1055d822d212954d07b085dea251cc7bc5505"
+  integrity sha1-fMEFXYItISlU0HsIXeolHMe8VQU=
+  dependencies:
+    ansicolors "~0.3.2"
+    redeyed "~2.1.0"
+
+chai@^4:
+  version "4.3.4"
+  resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.4.tgz#b55e655b31e1eac7099be4c08c21964fce2e6c49"
+  integrity sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==
+  dependencies:
+    assertion-error "^1.1.0"
+    check-error "^1.0.2"
+    deep-eql "^3.0.1"
+    get-func-name "^2.0.0"
+    pathval "^1.1.1"
+    type-detect "^4.0.5"
+
+chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2:
+  version "2.4.2"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
+  integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
+  dependencies:
+    ansi-styles "^3.2.1"
+    escape-string-regexp "^1.0.5"
+    supports-color "^5.3.0"
+
+chalk@^4.1.0:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad"
+  integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==
+  dependencies:
+    ansi-styles "^4.1.0"
+    supports-color "^7.1.0"
+
+chardet@^0.7.0:
+  version "0.7.0"
+  resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
+  integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
+
+check-error@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
+  integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=
+
+chownr@^1.1.1:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
+  integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
+
+cipher-base@^1.0.1:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
+  integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==
+  dependencies:
+    inherits "^2.0.1"
+    safe-buffer "^5.0.1"
+
+clean-regexp@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/clean-regexp/-/clean-regexp-1.0.0.tgz#8df7c7aae51fd36874e8f8d05b9180bc11a3fed7"
+  integrity sha1-jffHquUf02h06PjQW5GAvBGj/tc=
+  dependencies:
+    escape-string-regexp "^1.0.5"
+
+clean-stack@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-3.0.1.tgz#155bf0b2221bf5f4fba89528d24c5953f17fe3a8"
+  integrity sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg==
+  dependencies:
+    escape-string-regexp "4.0.0"
+
+cli-cursor@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
+  integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=
+  dependencies:
+    restore-cursor "^2.0.0"
+
+cli-progress@^3.4.0:
+  version "3.9.0"
+  resolved "https://registry.yarnpkg.com/cli-progress/-/cli-progress-3.9.0.tgz#25db83447deb812e62d05bac1af9aec5387ef3d4"
+  integrity sha512-g7rLWfhAo/7pF+a/STFH/xPyosaL1zgADhI0OM83hl3c7S43iGvJWEAV2QuDOnQ8i6EMBj/u4+NTd0d5L+4JfA==
+  dependencies:
+    colors "^1.1.2"
+    string-width "^4.2.0"
+
+cli-ux@^5.2.1:
+  version "5.5.1"
+  resolved "https://registry.yarnpkg.com/cli-ux/-/cli-ux-5.5.1.tgz#99d28dae0c3ef7845fa2ea56e066a1d5fcceca9e"
+  integrity sha512-t3DT1U1C3rArLGYLpKa3m9dr/8uKZRI8HRm/rXKL7UTjm4c+Yd9zHNWg1tP8uaJkUbhmvx5SQHwb3VWpPUVdHQ==
+  dependencies:
+    "@oclif/command" "^1.6.0"
+    "@oclif/errors" "^1.2.1"
+    "@oclif/linewrap" "^1.0.0"
+    "@oclif/screen" "^1.0.3"
+    ansi-escapes "^4.3.0"
+    ansi-styles "^4.2.0"
+    cardinal "^2.1.1"
+    chalk "^4.1.0"
+    clean-stack "^3.0.0"
+    cli-progress "^3.4.0"
+    extract-stack "^2.0.0"
+    fs-extra "^8.1"
+    hyperlinker "^1.0.0"
+    indent-string "^4.0.0"
+    is-wsl "^2.2.0"
+    js-yaml "^3.13.1"
+    lodash "^4.17.11"
+    natural-orderby "^2.0.1"
+    object-treeify "^1.1.4"
+    password-prompt "^1.1.2"
+    semver "^7.3.2"
+    string-width "^4.2.0"
+    strip-ansi "^6.0.0"
+    supports-color "^7.1.0"
+    supports-hyperlinks "^2.1.0"
+    tslib "^2.0.0"
+
+cli-width@^2.0.0:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48"
+  integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==
+
+cliui@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5"
+  integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==
+  dependencies:
+    string-width "^3.1.0"
+    strip-ansi "^5.2.0"
+    wrap-ansi "^5.1.0"
+
+color-convert@^1.9.0:
+  version "1.9.3"
+  resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
+  integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
+  dependencies:
+    color-name "1.1.3"
+
+color-convert@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
+  integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+  dependencies:
+    color-name "~1.1.4"
+
+color-name@1.1.3:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+  integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
+
+color-name@~1.1.4:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
+  integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+
+colors@^1.1.2:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
+  integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
+
+combined-stream@^1.0.8:
+  version "1.0.8"
+  resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
+  integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+  dependencies:
+    delayed-stream "~1.0.0"
+
+commander@2.15.1:
+  version "2.15.1"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
+  integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==
+
+commondir@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
+  integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=
+
+concat-map@0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+  integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
+
+content-type@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
+  integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
+
+convert-source-map@^1.6.0:
+  version "1.7.0"
+  resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
+  integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
+  dependencies:
+    safe-buffer "~5.1.1"
+
+cp-file@^6.2.0:
+  version "6.2.0"
+  resolved "https://registry.yarnpkg.com/cp-file/-/cp-file-6.2.0.tgz#40d5ea4a1def2a9acdd07ba5c0b0246ef73dc10d"
+  integrity sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==
+  dependencies:
+    graceful-fs "^4.1.2"
+    make-dir "^2.0.0"
+    nested-error-stacks "^2.0.0"
+    pify "^4.0.1"
+    safe-buffer "^5.0.1"
+
+create-hash@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
+  integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==
+  dependencies:
+    cipher-base "^1.0.1"
+    inherits "^2.0.1"
+    md5.js "^1.3.4"
+    ripemd160 "^2.0.1"
+    sha.js "^2.4.0"
+
+cross-spawn@^4:
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41"
+  integrity sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=
+  dependencies:
+    lru-cache "^4.0.1"
+    which "^1.2.9"
+
+cross-spawn@^6.0.0, cross-spawn@^6.0.5:
+  version "6.0.5"
+  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
+  integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
+  dependencies:
+    nice-try "^1.0.4"
+    path-key "^2.0.1"
+    semver "^5.5.0"
+    shebang-command "^1.2.0"
+    which "^1.2.9"
+
+cuint@^0.2.2:
+  version "0.2.2"
+  resolved "https://registry.yarnpkg.com/cuint/-/cuint-0.2.2.tgz#408086d409550c2631155619e9fa7bcadc3b991b"
+  integrity sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=
+
+d@1, d@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a"
+  integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==
+  dependencies:
+    es5-ext "^0.10.50"
+    type "^1.0.1"
+
+debug@3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
+  integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
+  dependencies:
+    ms "2.0.0"
+
+debug@^2.2.0:
+  version "2.6.9"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+  integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
+  dependencies:
+    ms "2.0.0"
+
+debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
+  version "4.3.1"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
+  integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
+  dependencies:
+    ms "2.1.2"
+
+decamelize@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+  integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
+
+deep-eql@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df"
+  integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==
+  dependencies:
+    type-detect "^4.0.0"
+
+deep-is@~0.1.3:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
+  integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
+
+default-require-extensions@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz#f5f8fbb18a7d6d50b21f641f649ebb522cfe24f7"
+  integrity sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=
+  dependencies:
+    strip-bom "^3.0.0"
+
+delayed-stream@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+  integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
+
+detect-indent@^6.0.0:
+  version "6.0.0"
+  resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.0.0.tgz#0abd0f549f69fc6659a254fe96786186b6f528fd"
+  integrity sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==
+
+diff@3.5.0:
+  version "3.5.0"
+  resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
+  integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
+
+diff@^4.0.1:
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
+  integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
+
+dir-glob@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
+  integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
+  dependencies:
+    path-type "^4.0.0"
+
+doctrine@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
+  integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==
+  dependencies:
+    esutils "^2.0.2"
+
+elliptic@^6.5.4:
+  version "6.5.4"
+  resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
+  integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==
+  dependencies:
+    bn.js "^4.11.9"
+    brorand "^1.1.0"
+    hash.js "^1.0.0"
+    hmac-drbg "^1.0.1"
+    inherits "^2.0.4"
+    minimalistic-assert "^1.0.1"
+    minimalistic-crypto-utils "^1.0.1"
+
+"emoji-regex@>=6.0.0 <=6.1.1":
+  version "6.1.1"
+  resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.1.1.tgz#c6cd0ec1b0642e2a3c67a1137efc5e796da4f88e"
+  integrity sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4=
+
+emoji-regex@^7.0.1:
+  version "7.0.3"
+  resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
+  integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
+
+emoji-regex@^8.0.0:
+  version "8.0.0"
+  resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
+  integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
+
+end-of-stream@^1.1.0, end-of-stream@^1.4.1:
+  version "1.4.4"
+  resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
+  integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
+  dependencies:
+    once "^1.4.0"
+
+error-ex@^1.3.1:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
+  integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
+  dependencies:
+    is-arrayish "^0.2.1"
+
+es5-ext@^0.10.35, es5-ext@^0.10.50:
+  version "0.10.53"
+  resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1"
+  integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==
+  dependencies:
+    es6-iterator "~2.0.3"
+    es6-symbol "~3.1.3"
+    next-tick "~1.0.0"
+
+es6-error@^4.0.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d"
+  integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==
+
+es6-iterator@~2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7"
+  integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c=
+  dependencies:
+    d "1"
+    es5-ext "^0.10.35"
+    es6-symbol "^3.1.1"
+
+es6-symbol@^3.1.1, es6-symbol@~3.1.3:
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18"
+  integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==
+  dependencies:
+    d "^1.0.1"
+    ext "^1.1.2"
+
+escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+  integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
+
+escape-string-regexp@4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
+  integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
+
+eslint-ast-utils@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/eslint-ast-utils/-/eslint-ast-utils-1.1.0.tgz#3d58ba557801cfb1c941d68131ee9f8c34bd1586"
+  integrity sha512-otzzTim2/1+lVrlH19EfQQJEhVJSu0zOb9ygb3iapN6UlyaDtyRq4b5U1FuW0v1lRa9Fp/GJyHkSwm6NqABgCA==
+  dependencies:
+    lodash.get "^4.4.2"
+    lodash.zip "^4.2.0"
+
+eslint-config-oclif-typescript@^0.1:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/eslint-config-oclif-typescript/-/eslint-config-oclif-typescript-0.1.0.tgz#c310767c5ee8916ea5d08cf027d0317dd52ed8ba"
+  integrity sha512-BjXNJcH2F02MdaSFml9vJskviUFVkLHbTPGM5tinIt98H6klFNKP7/lQ+fB/Goc2wB45usEuuw6+l/fwAv9i7g==
+  dependencies:
+    "@typescript-eslint/eslint-plugin" "^2.6.1"
+    "@typescript-eslint/parser" "^2.6.1"
+    eslint-config-oclif "^3.1.0"
+    eslint-config-xo-space "^0.20.0"
+    eslint-plugin-mocha "^5.2.0"
+    eslint-plugin-node "^7.0.1"
+    eslint-plugin-unicorn "^6.0.1"
+
+eslint-config-oclif@^3.1, eslint-config-oclif@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/eslint-config-oclif/-/eslint-config-oclif-3.1.0.tgz#cbc207ced09e31676dcee2f724fc509cd20eb0bd"
+  integrity sha512-Tqgy43cNXsSdhTLWW4RuDYGFhV240sC4ISSv/ZiUEg/zFxExSEUpRE6J+AGnkKY9dYwIW4C9b2YSUVv8z/miMA==
+  dependencies:
+    eslint-config-xo-space "^0.20.0"
+    eslint-plugin-mocha "^5.2.0"
+    eslint-plugin-node "^7.0.1"
+    eslint-plugin-unicorn "^6.0.1"
+
+eslint-config-xo-space@^0.20.0:
+  version "0.20.0"
+  resolved "https://registry.yarnpkg.com/eslint-config-xo-space/-/eslint-config-xo-space-0.20.0.tgz#75e1fb86d1b052fc1cc3036ca2fa441fa92b85e4"
+  integrity sha512-bOsoZA8M6v1HviDUIGVq1fLVnSu3mMZzn85m2tqKb73tSzu4GKD4Jd2Py4ZKjCgvCbRRByEB5HPC3fTMnnJ1uw==
+  dependencies:
+    eslint-config-xo "^0.24.0"
+
+eslint-config-xo@^0.24.0:
+  version "0.24.2"
+  resolved "https://registry.yarnpkg.com/eslint-config-xo/-/eslint-config-xo-0.24.2.tgz#f61b8ce692e9f9519bdb6edc4ed7ebcd5be48f48"
+  integrity sha512-ivQ7qISScW6gfBp+p31nQntz1rg34UCybd3uvlngcxt5Utsf4PMMi9QoAluLFcPUM5Tvqk4JGraR9qu3msKPKQ==
+
+eslint-plugin-es@^1.3.1:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-1.4.1.tgz#12acae0f4953e76ba444bfd1b2271081ac620998"
+  integrity sha512-5fa/gR2yR3NxQf+UXkeLeP8FBBl6tSgdrAz1+cF84v1FMM4twGwQoqTnn+QxFLcPOrF4pdKEJKDB/q9GoyJrCA==
+  dependencies:
+    eslint-utils "^1.4.2"
+    regexpp "^2.0.1"
+
+eslint-plugin-mocha@^5.2.0:
+  version "5.3.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-mocha/-/eslint-plugin-mocha-5.3.0.tgz#cf3eb18ae0e44e433aef7159637095a7cb19b15b"
+  integrity sha512-3uwlJVLijjEmBeNyH60nzqgA1gacUWLUmcKV8PIGNvj1kwP/CTgAWQHn2ayyJVwziX+KETkr9opNwT1qD/RZ5A==
+  dependencies:
+    ramda "^0.26.1"
+
+eslint-plugin-node@^7.0.1:
+  version "7.0.1"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-7.0.1.tgz#a6e054e50199b2edd85518b89b4e7b323c9f36db"
+  integrity sha512-lfVw3TEqThwq0j2Ba/Ckn2ABdwmL5dkOgAux1rvOk6CO7A6yGyPI2+zIxN6FyNkp1X1X/BSvKOceD6mBWSj4Yw==
+  dependencies:
+    eslint-plugin-es "^1.3.1"
+    eslint-utils "^1.3.1"
+    ignore "^4.0.2"
+    minimatch "^3.0.4"
+    resolve "^1.8.1"
+    semver "^5.5.0"
+
+eslint-plugin-unicorn@^6.0.1:
+  version "6.0.1"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-6.0.1.tgz#4a97f0bc9449e20b82848dad12094ee2ba72347e"
+  integrity sha512-hjy9LhTdtL7pz8WTrzS0CGXRkWK3VAPLDjihofj8JC+uxQLfXm0WwZPPPB7xKmcjRyoH+jruPHOCrHNEINpG/Q==
+  dependencies:
+    clean-regexp "^1.0.0"
+    eslint-ast-utils "^1.0.0"
+    import-modules "^1.1.0"
+    lodash.camelcase "^4.1.1"
+    lodash.kebabcase "^4.0.1"
+    lodash.snakecase "^4.0.1"
+    lodash.upperfirst "^4.2.0"
+    safe-regex "^1.1.0"
+
+eslint-scope@^4.0.3:
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848"
+  integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==
+  dependencies:
+    esrecurse "^4.1.0"
+    estraverse "^4.1.1"
+
+eslint-scope@^5.0.0:
+  version "5.1.1"
+  resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
+  integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
+  dependencies:
+    esrecurse "^4.3.0"
+    estraverse "^4.1.1"
+
+eslint-utils@^1.3.1, eslint-utils@^1.4.2:
+  version "1.4.3"
+  resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f"
+  integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==
+  dependencies:
+    eslint-visitor-keys "^1.1.0"
+
+eslint-utils@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
+  integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==
+  dependencies:
+    eslint-visitor-keys "^1.1.0"
+
+eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
+  integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
+
+eslint@^5.13:
+  version "5.16.0"
+  resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea"
+  integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==
+  dependencies:
+    "@babel/code-frame" "^7.0.0"
+    ajv "^6.9.1"
+    chalk "^2.1.0"
+    cross-spawn "^6.0.5"
+    debug "^4.0.1"
+    doctrine "^3.0.0"
+    eslint-scope "^4.0.3"
+    eslint-utils "^1.3.1"
+    eslint-visitor-keys "^1.0.0"
+    espree "^5.0.1"
+    esquery "^1.0.1"
+    esutils "^2.0.2"
+    file-entry-cache "^5.0.1"
+    functional-red-black-tree "^1.0.1"
+    glob "^7.1.2"
+    globals "^11.7.0"
+    ignore "^4.0.6"
+    import-fresh "^3.0.0"
+    imurmurhash "^0.1.4"
+    inquirer "^6.2.2"
+    js-yaml "^3.13.0"
+    json-stable-stringify-without-jsonify "^1.0.1"
+    levn "^0.3.0"
+    lodash "^4.17.11"
+    minimatch "^3.0.4"
+    mkdirp "^0.5.1"
+    natural-compare "^1.4.0"
+    optionator "^0.8.2"
+    path-is-inside "^1.0.2"
+    progress "^2.0.0"
+    regexpp "^2.0.1"
+    semver "^5.5.1"
+    strip-ansi "^4.0.0"
+    strip-json-comments "^2.0.1"
+    table "^5.2.3"
+    text-table "^0.2.0"
+
+espree@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a"
+  integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==
+  dependencies:
+    acorn "^6.0.7"
+    acorn-jsx "^5.0.0"
+    eslint-visitor-keys "^1.0.0"
+
+esprima@^4.0.0, esprima@~4.0.0:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
+  integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
+
+esquery@^1.0.1:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5"
+  integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==
+  dependencies:
+    estraverse "^5.1.0"
+
+esrecurse@^4.1.0, esrecurse@^4.3.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
+  integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
+  dependencies:
+    estraverse "^5.2.0"
+
+estraverse@^4.1.1:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
+  integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
+
+estraverse@^5.1.0, estraverse@^5.2.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880"
+  integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==
+
+esutils@^2.0.2:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
+  integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
+
+eventemitter3@^4.0.7:
+  version "4.0.7"
+  resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
+  integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
+
+execa@^0.10.0:
+  version "0.10.0"
+  resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50"
+  integrity sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==
+  dependencies:
+    cross-spawn "^6.0.0"
+    get-stream "^3.0.0"
+    is-stream "^1.1.0"
+    npm-run-path "^2.0.0"
+    p-finally "^1.0.0"
+    signal-exit "^3.0.0"
+    strip-eof "^1.0.0"
+
+ext@^1.1.2:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244"
+  integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==
+  dependencies:
+    type "^2.0.0"
+
+external-editor@^3.0.3:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
+  integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==
+  dependencies:
+    chardet "^0.7.0"
+    iconv-lite "^0.4.24"
+    tmp "^0.0.33"
+
+extract-stack@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/extract-stack/-/extract-stack-2.0.0.tgz#11367bc865bfcd9bc0db3123e5edb57786f11f9b"
+  integrity sha512-AEo4zm+TenK7zQorGK1f9mJ8L14hnTDi2ZQPR+Mub1NX8zimka1mXpV5LpH8x9HoUmFSHZCfLHqWvp0Y4FxxzQ==
+
+fancy-test@^1.4.3:
+  version "1.4.10"
+  resolved "https://registry.yarnpkg.com/fancy-test/-/fancy-test-1.4.10.tgz#310be93d4aa45d788bce56a573ae4d1b92b2e1a0"
+  integrity sha512-AaUX6wKS7D5OP2YK2q5G7c8PGx2lgoyLUD7Bbg8z323sb9aebBqzb9UN6phzI73UgO/ViihmNfOxF3kdfZLhew==
+  dependencies:
+    "@types/chai" "*"
+    "@types/lodash" "*"
+    "@types/node" "*"
+    "@types/sinon" "*"
+    lodash "^4.17.13"
+    mock-stdin "^1.0.0"
+    nock "^13.0.0"
+    stdout-stderr "^0.1.9"
+
+fast-deep-equal@^3.1.1:
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
+  integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+
+fast-glob@^3.0.3, fast-glob@^3.1.1:
+  version "3.2.5"
+  resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.5.tgz#7939af2a656de79a4f1901903ee8adcaa7cb9661"
+  integrity sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==
+  dependencies:
+    "@nodelib/fs.stat" "^2.0.2"
+    "@nodelib/fs.walk" "^1.2.3"
+    glob-parent "^5.1.0"
+    merge2 "^1.3.0"
+    micromatch "^4.0.2"
+    picomatch "^2.2.1"
+
+fast-json-stable-stringify@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
+  integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
+
+fast-levenshtein@~2.0.6:
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
+  integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
+
+fastq@^1.6.0:
+  version "1.11.0"
+  resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.0.tgz#bb9fb955a07130a918eb63c1f5161cc32a5d0858"
+  integrity sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==
+  dependencies:
+    reusify "^1.0.4"
+
+figures@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
+  integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=
+  dependencies:
+    escape-string-regexp "^1.0.5"
+
+file-entry-cache@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c"
+  integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==
+  dependencies:
+    flat-cache "^2.0.1"
+
+fill-range@^7.0.1:
+  version "7.0.1"
+  resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
+  integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
+  dependencies:
+    to-regex-range "^5.0.1"
+
+find-cache-dir@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7"
+  integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==
+  dependencies:
+    commondir "^1.0.1"
+    make-dir "^2.0.0"
+    pkg-dir "^3.0.0"
+
+find-up@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
+  integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==
+  dependencies:
+    locate-path "^3.0.0"
+
+find-up@^4.0.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
+  integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
+  dependencies:
+    locate-path "^5.0.0"
+    path-exists "^4.0.0"
+
+find-yarn-workspace-root@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd"
+  integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==
+  dependencies:
+    micromatch "^4.0.2"
+
+flat-cache@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0"
+  integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==
+  dependencies:
+    flatted "^2.0.0"
+    rimraf "2.6.3"
+    write "1.0.3"
+
+flatted@^2.0.0:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138"
+  integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==
+
+foreground-child@^1.5.6:
+  version "1.5.6"
+  resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-1.5.6.tgz#4fd71ad2dfde96789b980a5c0a295937cb2f5ce9"
+  integrity sha1-T9ca0t/elnibmApcCilZN8svXOk=
+  dependencies:
+    cross-spawn "^4"
+    signal-exit "^3.0.0"
+
+form-data@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f"
+  integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==
+  dependencies:
+    asynckit "^0.4.0"
+    combined-stream "^1.0.8"
+    mime-types "^2.1.12"
+
+fs-constants@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
+  integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
+
+fs-extra@^6.0.1:
+  version "6.0.1"
+  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-6.0.1.tgz#8abc128f7946e310135ddc93b98bddb410e7a34b"
+  integrity sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==
+  dependencies:
+    graceful-fs "^4.1.2"
+    jsonfile "^4.0.0"
+    universalify "^0.1.0"
+
+fs-extra@^8.1:
+  version "8.1.0"
+  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
+  integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
+  dependencies:
+    graceful-fs "^4.2.0"
+    jsonfile "^4.0.0"
+    universalify "^0.1.0"
+
+fs.realpath@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+  integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
+
+function-bind@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
+  integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+
+functional-red-black-tree@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
+  integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
+
+get-caller-file@^2.0.1:
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
+  integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
+
+get-func-name@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41"
+  integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=
+
+get-stream@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
+  integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=
+
+get-stream@^5.1.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
+  integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
+  dependencies:
+    pump "^3.0.0"
+
+github-slugger@^1.2.1:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.3.0.tgz#9bd0a95c5efdfc46005e82a906ef8e2a059124c9"
+  integrity sha512-gwJScWVNhFYSRDvURk/8yhcFBee6aFjye2a7Lhb2bUyRulpIoek9p0I9Kt7PT67d/nUlZbFu8L9RLiA0woQN8Q==
+  dependencies:
+    emoji-regex ">=6.0.0 <=6.1.1"
+
+glob-parent@^5.1.0:
+  version "5.1.2"
+  resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
+  integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+  dependencies:
+    is-glob "^4.0.1"
+
+glob@7.1.2:
+  version "7.1.2"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
+  integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==
+  dependencies:
+    fs.realpath "^1.0.0"
+    inflight "^1.0.4"
+    inherits "2"
+    minimatch "^3.0.4"
+    once "^1.3.0"
+    path-is-absolute "^1.0.0"
+
+glob@^7.1.2, glob@^7.1.3, glob@^7.1.6:
+  version "7.1.7"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
+  integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==
+  dependencies:
+    fs.realpath "^1.0.0"
+    inflight "^1.0.4"
+    inherits "2"
+    minimatch "^3.0.4"
+    once "^1.3.0"
+    path-is-absolute "^1.0.0"
+
+globals@^11.1.0, globals@^11.7.0:
+  version "11.12.0"
+  resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
+  integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
+
+globby@^10, globby@^10.0.1:
+  version "10.0.2"
+  resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543"
+  integrity sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==
+  dependencies:
+    "@types/glob" "^7.1.1"
+    array-union "^2.1.0"
+    dir-glob "^3.0.1"
+    fast-glob "^3.0.3"
+    glob "^7.1.3"
+    ignore "^5.1.1"
+    merge2 "^1.2.3"
+    slash "^3.0.0"
+
+globby@^11.0.1:
+  version "11.0.3"
+  resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.3.tgz#9b1f0cb523e171dd1ad8c7b2a9fb4b644b9593cb"
+  integrity sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==
+  dependencies:
+    array-union "^2.1.0"
+    dir-glob "^3.0.1"
+    fast-glob "^3.1.1"
+    ignore "^5.1.4"
+    merge2 "^1.3.0"
+    slash "^3.0.0"
+
+graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0:
+  version "4.2.6"
+  resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee"
+  integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==
+
+growl@1.10.5:
+  version "1.10.5"
+  resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
+  integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==
+
+has-flag@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
+  integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
+
+has-flag@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
+  integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+
+has@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
+  integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
+  dependencies:
+    function-bind "^1.1.1"
+
+hash-base@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33"
+  integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==
+  dependencies:
+    inherits "^2.0.4"
+    readable-stream "^3.6.0"
+    safe-buffer "^5.2.0"
+
+hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7:
+  version "1.1.7"
+  resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42"
+  integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==
+  dependencies:
+    inherits "^2.0.3"
+    minimalistic-assert "^1.0.1"
+
+hasha@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/hasha/-/hasha-3.0.0.tgz#52a32fab8569d41ca69a61ff1a214f8eb7c8bd39"
+  integrity sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=
+  dependencies:
+    is-stream "^1.0.1"
+
+he@1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
+  integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0=
+
+hmac-drbg@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
+  integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=
+  dependencies:
+    hash.js "^1.0.3"
+    minimalistic-assert "^1.0.0"
+    minimalistic-crypto-utils "^1.0.1"
+
+hosted-git-info@^2.1.4:
+  version "2.8.9"
+  resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
+  integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
+
+hosted-git-info@^4.0.1:
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.0.2.tgz#5e425507eede4fea846b7262f0838456c4209961"
+  integrity sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==
+  dependencies:
+    lru-cache "^6.0.0"
+
+html-escaper@^2.0.0:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
+  integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==
+
+http-call@^5.1.2:
+  version "5.3.0"
+  resolved "https://registry.yarnpkg.com/http-call/-/http-call-5.3.0.tgz#4ded815b13f423de176eb0942d69c43b25b148db"
+  integrity sha512-ahwimsC23ICE4kPl9xTBjKB4inbRaeLyZeRunC/1Jy/Z6X8tv22MEAjK+KBOMSVLaqXPTTmd8638waVIKLGx2w==
+  dependencies:
+    content-type "^1.0.4"
+    debug "^4.1.1"
+    is-retry-allowed "^1.1.0"
+    is-stream "^2.0.0"
+    parse-json "^4.0.0"
+    tunnel-agent "^0.6.0"
+
+hyperlinker@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/hyperlinker/-/hyperlinker-1.0.0.tgz#23dc9e38a206b208ee49bc2d6c8ef47027df0c0e"
+  integrity sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ==
+
+iconv-lite@^0.4.24:
+  version "0.4.24"
+  resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
+  integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
+  dependencies:
+    safer-buffer ">= 2.1.2 < 3"
+
+ieee754@^1.1.13:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
+  integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
+
+ignore@^4.0.2, ignore@^4.0.6:
+  version "4.0.6"
+  resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
+  integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
+
+ignore@^5.1.1, ignore@^5.1.4:
+  version "5.1.8"
+  resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57"
+  integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==
+
+import-fresh@^3.0.0:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
+  integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
+  dependencies:
+    parent-module "^1.0.0"
+    resolve-from "^4.0.0"
+
+import-modules@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/import-modules/-/import-modules-1.1.0.tgz#748db79c5cc42bb9701efab424f894e72600e9dc"
+  integrity sha1-dI23nFzEK7lwHvq0JPiU5yYA6dw=
+
+imurmurhash@^0.1.4:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
+  integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
+
+indent-string@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
+  integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
+
+inflight@^1.0.4:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+  integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
+  dependencies:
+    once "^1.3.0"
+    wrappy "1"
+
+inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+  integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+inquirer@^6.2.2:
+  version "6.5.2"
+  resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca"
+  integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==
+  dependencies:
+    ansi-escapes "^3.2.0"
+    chalk "^2.4.2"
+    cli-cursor "^2.1.0"
+    cli-width "^2.0.0"
+    external-editor "^3.0.3"
+    figures "^2.0.0"
+    lodash "^4.17.12"
+    mute-stream "0.0.7"
+    run-async "^2.2.0"
+    rxjs "^6.4.0"
+    string-width "^2.1.0"
+    strip-ansi "^5.1.0"
+    through "^2.3.6"
+
+ip-regex@^4.3.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5"
+  integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==
+
+is-arrayish@^0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
+  integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
+
+is-buffer@^2.0.0:
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191"
+  integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==
+
+is-core-module@^2.2.0:
+  version "2.4.0"
+  resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.4.0.tgz#8e9fc8e15027b011418026e98f0e6f4d86305cc1"
+  integrity sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==
+  dependencies:
+    has "^1.0.3"
+
+is-docker@^2.0.0:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa"
+  integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==
+
+is-extglob@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+  integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
+
+is-fullwidth-code-point@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
+  integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
+
+is-fullwidth-code-point@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
+  integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
+
+is-glob@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
+  integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
+  dependencies:
+    is-extglob "^2.1.1"
+
+is-number@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
+  integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+is-plain-obj@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287"
+  integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==
+
+is-retry-allowed@^1.1.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4"
+  integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==
+
+is-stream@^1.0.1, is-stream@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
+  integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
+
+is-stream@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3"
+  integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==
+
+is-typedarray@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
+  integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
+
+is-wsl@^2.1.1, is-wsl@^2.2.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271"
+  integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==
+  dependencies:
+    is-docker "^2.0.0"
+
+isexe@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+  integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
+
+istanbul-lib-coverage@^2.0.5:
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49"
+  integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==
+
+istanbul-lib-hook@^2.0.7:
+  version "2.0.7"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz#c95695f383d4f8f60df1f04252a9550e15b5b133"
+  integrity sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==
+  dependencies:
+    append-transform "^1.0.0"
+
+istanbul-lib-instrument@^3.3.0:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz#a5f63d91f0bbc0c3e479ef4c5de027335ec6d630"
+  integrity sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==
+  dependencies:
+    "@babel/generator" "^7.4.0"
+    "@babel/parser" "^7.4.3"
+    "@babel/template" "^7.4.0"
+    "@babel/traverse" "^7.4.3"
+    "@babel/types" "^7.4.0"
+    istanbul-lib-coverage "^2.0.5"
+    semver "^6.0.0"
+
+istanbul-lib-report@^2.0.8:
+  version "2.0.8"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz#5a8113cd746d43c4889eba36ab10e7d50c9b4f33"
+  integrity sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==
+  dependencies:
+    istanbul-lib-coverage "^2.0.5"
+    make-dir "^2.1.0"
+    supports-color "^6.1.0"
+
+istanbul-lib-source-maps@^3.0.6:
+  version "3.0.6"
+  resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8"
+  integrity sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==
+  dependencies:
+    debug "^4.1.1"
+    istanbul-lib-coverage "^2.0.5"
+    make-dir "^2.1.0"
+    rimraf "^2.6.3"
+    source-map "^0.6.1"
+
+istanbul-reports@^2.2.4:
+  version "2.2.7"
+  resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.7.tgz#5d939f6237d7b48393cc0959eab40cd4fd056931"
+  integrity sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==
+  dependencies:
+    html-escaper "^2.0.0"
+
+js-sha3@^0.8.0:
+  version "0.8.0"
+  resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"
+  integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==
+
+js-tokens@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
+  integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
+
+js-yaml@^3.13.0, js-yaml@^3.13.1:
+  version "3.14.1"
+  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
+  integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
+  dependencies:
+    argparse "^1.0.7"
+    esprima "^4.0.0"
+
+jsesc@^2.5.1:
+  version "2.5.2"
+  resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
+  integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
+
+json-parse-better-errors@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
+  integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
+
+json-parse-even-better-errors@^2.3.0:
+  version "2.3.1"
+  resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
+  integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
+
+json-schema-traverse@^0.4.1:
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
+  integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
+
+json-stable-stringify-without-jsonify@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
+  integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=
+
+json-stringify-safe@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
+  integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
+
+jsonfile@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
+  integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
+  optionalDependencies:
+    graceful-fs "^4.1.6"
+
+levn@^0.3.0, levn@~0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
+  integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=
+  dependencies:
+    prelude-ls "~1.1.2"
+    type-check "~0.3.2"
+
+lines-and-columns@^1.1.6:
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
+  integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
+
+load-json-file@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
+  integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs=
+  dependencies:
+    graceful-fs "^4.1.2"
+    parse-json "^4.0.0"
+    pify "^3.0.0"
+    strip-bom "^3.0.0"
+
+load-json-file@^6.2.0:
+  version "6.2.0"
+  resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-6.2.0.tgz#5c7770b42cafa97074ca2848707c61662f4251a1"
+  integrity sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==
+  dependencies:
+    graceful-fs "^4.1.15"
+    parse-json "^5.0.0"
+    strip-bom "^4.0.0"
+    type-fest "^0.6.0"
+
+locate-path@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
+  integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==
+  dependencies:
+    p-locate "^3.0.0"
+    path-exists "^3.0.0"
+
+locate-path@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
+  integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
+  dependencies:
+    p-locate "^4.1.0"
+
+lodash._reinterpolate@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
+  integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=
+
+lodash.camelcase@^4.1.1:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
+  integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY=
+
+lodash.flattendeep@^4.4.0:
+  version "4.4.0"
+  resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2"
+  integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=
+
+lodash.get@^4.4.2:
+  version "4.4.2"
+  resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
+  integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
+
+lodash.kebabcase@^4.0.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36"
+  integrity sha1-hImxyw0p/4gZXM7KRI/21swpXDY=
+
+lodash.set@^4.3.2:
+  version "4.3.2"
+  resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23"
+  integrity sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=
+
+lodash.snakecase@^4.0.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d"
+  integrity sha1-OdcUo1NXFHg3rv1ktdy7Fr7Nj40=
+
+lodash.template@^4.4.0:
+  version "4.5.0"
+  resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab"
+  integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==
+  dependencies:
+    lodash._reinterpolate "^3.0.0"
+    lodash.templatesettings "^4.0.0"
+
+lodash.templatesettings@^4.0.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33"
+  integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==
+  dependencies:
+    lodash._reinterpolate "^3.0.0"
+
+lodash.upperfirst@^4.2.0:
+  version "4.3.1"
+  resolved "https://registry.yarnpkg.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz#1365edf431480481ef0d1c68957a5ed99d49f7ce"
+  integrity sha1-E2Xt9DFIBIHvDRxolXpe2Z1J984=
+
+lodash.zip@^4.2.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/lodash.zip/-/lodash.zip-4.2.0.tgz#ec6662e4896408ed4ab6c542a3990b72cc080020"
+  integrity sha1-7GZi5IlkCO1KtsVCo5kLcswIACA=
+
+lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15:
+  version "4.17.21"
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
+  integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
+
+lru-cache@^4.0.1:
+  version "4.1.5"
+  resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
+  integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
+  dependencies:
+    pseudomap "^1.0.2"
+    yallist "^2.1.2"
+
+lru-cache@^6.0.0:
+  version "6.0.0"
+  resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
+  integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
+  dependencies:
+    yallist "^4.0.0"
+
+make-dir@^2.0.0, make-dir@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
+  integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==
+  dependencies:
+    pify "^4.0.1"
+    semver "^5.6.0"
+
+make-dir@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
+  integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==
+  dependencies:
+    semver "^6.0.0"
+
+make-error@^1.1.1:
+  version "1.3.6"
+  resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
+  integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
+
+md5.js@^1.3.4:
+  version "1.3.5"
+  resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
+  integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==
+  dependencies:
+    hash-base "^3.0.0"
+    inherits "^2.0.1"
+    safe-buffer "^5.1.2"
+
+merge-source-map@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646"
+  integrity sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==
+  dependencies:
+    source-map "^0.6.1"
+
+merge2@^1.2.3, merge2@^1.3.0:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
+  integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
+
+micromatch@^4.0.2:
+  version "4.0.4"
+  resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9"
+  integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==
+  dependencies:
+    braces "^3.0.1"
+    picomatch "^2.2.3"
+
+mime-db@1.47.0:
+  version "1.47.0"
+  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.47.0.tgz#8cb313e59965d3c05cfbf898915a267af46a335c"
+  integrity sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==
+
+mime-types@^2.1.12:
+  version "2.1.30"
+  resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.30.tgz#6e7be8b4c479825f85ed6326695db73f9305d62d"
+  integrity sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==
+  dependencies:
+    mime-db "1.47.0"
+
+mimic-fn@^1.0.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
+  integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
+
+minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
+  integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
+
+minimalistic-crypto-utils@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
+  integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
+
+minimatch@3.0.4, minimatch@^3.0.4:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
+  integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
+  dependencies:
+    brace-expansion "^1.1.7"
+
+minimist@0.0.8:
+  version "0.0.8"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
+  integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
+
+minimist@^1.2.5:
+  version "1.2.5"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
+  integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
+
+mkdirp-classic@^0.5.2:
+  version "0.5.3"
+  resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
+  integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
+
+mkdirp@0.5.1:
+  version "0.5.1"
+  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
+  integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
+  dependencies:
+    minimist "0.0.8"
+
+mkdirp@^0.5.0, mkdirp@^0.5.1:
+  version "0.5.5"
+  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
+  integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
+  dependencies:
+    minimist "^1.2.5"
+
+mocha@^5:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6"
+  integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==
+  dependencies:
+    browser-stdout "1.3.1"
+    commander "2.15.1"
+    debug "3.1.0"
+    diff "3.5.0"
+    escape-string-regexp "1.0.5"
+    glob "7.1.2"
+    growl "1.10.5"
+    he "1.1.1"
+    minimatch "3.0.4"
+    mkdirp "0.5.1"
+    supports-color "5.4.0"
+
+mock-stdin@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/mock-stdin/-/mock-stdin-1.0.0.tgz#efcfaf4b18077e14541742fd758b9cae4e5365ea"
+  integrity sha512-tukRdb9Beu27t6dN+XztSRHq9J0B/CoAOySGzHfn8UTfmqipA5yNT/sDUEyYdAV3Hpka6Wx6kOMxuObdOex60Q==
+
+moment@^2.24.0:
+  version "2.29.1"
+  resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
+  integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
+
+ms@2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+  integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
+
+ms@2.1.2:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
+  integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
+mute-stream@0.0.7:
+  version "0.0.7"
+  resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
+  integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
+
+natural-compare@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
+  integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
+
+natural-orderby@^2.0.1:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/natural-orderby/-/natural-orderby-2.0.3.tgz#8623bc518ba162f8ff1cdb8941d74deb0fdcc016"
+  integrity sha512-p7KTHxU0CUrcOXe62Zfrb5Z13nLvPhSWR/so3kFulUQU0sgUll2Z0LwpsLN351eOOD+hRGu/F1g+6xDfPeD++Q==
+
+nested-error-stacks@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz#0fbdcf3e13fe4994781280524f8b96b0cdff9c61"
+  integrity sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==
+
+next-tick@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
+  integrity sha1-yobR/ogoFpsBICCOPchCS524NCw=
+
+nice-try@^1.0.4:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
+  integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
+
+nock@^13.0.0:
+  version "13.0.11"
+  resolved "https://registry.yarnpkg.com/nock/-/nock-13.0.11.tgz#ba733252e720897ca50033205c39db0c7470f331"
+  integrity sha512-sKZltNkkWblkqqPAsjYW0bm3s9DcHRPiMOyKO/PkfJ+ANHZ2+LA2PLe22r4lLrKgXaiSaDQwW3qGsJFtIpQIeQ==
+  dependencies:
+    debug "^4.1.0"
+    json-stringify-safe "^5.0.1"
+    lodash.set "^4.3.2"
+    propagate "^2.0.0"
+
+node-fetch@^2.6.1:
+  version "2.6.1"
+  resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
+  integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
+
+node-gyp-build@^4.2.0:
+  version "4.2.3"
+  resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.2.3.tgz#ce6277f853835f718829efb47db20f3e4d9c4739"
+  integrity sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==
+
+normalize-package-data@^2.3.2:
+  version "2.5.0"
+  resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
+  integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
+  dependencies:
+    hosted-git-info "^2.1.4"
+    resolve "^1.10.0"
+    semver "2 || 3 || 4 || 5"
+    validate-npm-package-license "^3.0.1"
+
+normalize-package-data@^3.0.0:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.2.tgz#cae5c410ae2434f9a6c1baa65d5bc3b9366c8699"
+  integrity sha512-6CdZocmfGaKnIHPVFhJJZ3GuR8SsLKvDANFp47Jmy51aKIr8akjAWTSxtpI+MBgBFdSMRyo4hMpDlT6dTffgZg==
+  dependencies:
+    hosted-git-info "^4.0.1"
+    resolve "^1.20.0"
+    semver "^7.3.4"
+    validate-npm-package-license "^3.0.1"
+
+npm-run-path@^2.0.0:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
+  integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=
+  dependencies:
+    path-key "^2.0.0"
+
+nyc@^14:
+  version "14.1.1"
+  resolved "https://registry.yarnpkg.com/nyc/-/nyc-14.1.1.tgz#151d64a6a9f9f5908a1b73233931e4a0a3075eeb"
+  integrity sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==
+  dependencies:
+    archy "^1.0.0"
+    caching-transform "^3.0.2"
+    convert-source-map "^1.6.0"
+    cp-file "^6.2.0"
+    find-cache-dir "^2.1.0"
+    find-up "^3.0.0"
+    foreground-child "^1.5.6"
+    glob "^7.1.3"
+    istanbul-lib-coverage "^2.0.5"
+    istanbul-lib-hook "^2.0.7"
+    istanbul-lib-instrument "^3.3.0"
+    istanbul-lib-report "^2.0.8"
+    istanbul-lib-source-maps "^3.0.6"
+    istanbul-reports "^2.2.4"
+    js-yaml "^3.13.1"
+    make-dir "^2.1.0"
+    merge-source-map "^1.1.0"
+    resolve-from "^4.0.0"
+    rimraf "^2.6.3"
+    signal-exit "^3.0.2"
+    spawn-wrap "^1.4.2"
+    test-exclude "^5.2.3"
+    uuid "^3.3.2"
+    yargs "^13.2.2"
+    yargs-parser "^13.0.0"
+
+object-treeify@^1.1.4:
+  version "1.1.33"
+  resolved "https://registry.yarnpkg.com/object-treeify/-/object-treeify-1.1.33.tgz#f06fece986830a3cba78ddd32d4c11d1f76cdf40"
+  integrity sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A==
+
+once@^1.3.0, once@^1.3.1, once@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+  integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
+  dependencies:
+    wrappy "1"
+
+onetime@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
+  integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=
+  dependencies:
+    mimic-fn "^1.0.0"
+
+optionator@^0.8.2:
+  version "0.8.3"
+  resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
+  integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
+  dependencies:
+    deep-is "~0.1.3"
+    fast-levenshtein "~2.0.6"
+    levn "~0.3.0"
+    prelude-ls "~1.1.2"
+    type-check "~0.3.2"
+    word-wrap "~1.2.3"
+
+os-homedir@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
+  integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
+
+os-tmpdir@~1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
+  integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
+
+p-finally@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
+  integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
+
+p-limit@^2.0.0, p-limit@^2.2.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
+  integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
+  dependencies:
+    p-try "^2.0.0"
+
+p-locate@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
+  integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==
+  dependencies:
+    p-limit "^2.0.0"
+
+p-locate@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
+  integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
+  dependencies:
+    p-limit "^2.2.0"
+
+p-try@^2.0.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
+  integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
+
+package-hash@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-3.0.0.tgz#50183f2d36c9e3e528ea0a8605dff57ce976f88e"
+  integrity sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==
+  dependencies:
+    graceful-fs "^4.1.15"
+    hasha "^3.0.0"
+    lodash.flattendeep "^4.4.0"
+    release-zalgo "^1.0.0"
+
+parent-module@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
+  integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
+  dependencies:
+    callsites "^3.0.0"
+
+parse-json@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
+  integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=
+  dependencies:
+    error-ex "^1.3.1"
+    json-parse-better-errors "^1.0.1"
+
+parse-json@^5.0.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
+  integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
+  dependencies:
+    "@babel/code-frame" "^7.0.0"
+    error-ex "^1.3.1"
+    json-parse-even-better-errors "^2.3.0"
+    lines-and-columns "^1.1.6"
+
+password-prompt@^1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/password-prompt/-/password-prompt-1.1.2.tgz#85b2f93896c5bd9e9f2d6ff0627fa5af3dc00923"
+  integrity sha512-bpuBhROdrhuN3E7G/koAju0WjVw9/uQOG5Co5mokNj0MiOSBVZS1JTwM4zl55hu0WFmIEFvO9cU9sJQiBIYeIA==
+  dependencies:
+    ansi-escapes "^3.1.0"
+    cross-spawn "^6.0.5"
+
+path-exists@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
+  integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
+
+path-exists@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
+  integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+
+path-is-absolute@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+  integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
+
+path-is-inside@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
+  integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=
+
+path-key@^2.0.0, path-key@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
+  integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
+
+path-parse@^1.0.6:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
+  integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
+
+path-type@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
+  integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==
+  dependencies:
+    pify "^3.0.0"
+
+path-type@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
+  integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+
+pathval@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d"
+  integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==
+
+picomatch@^2.2.1, picomatch@^2.2.3:
+  version "2.2.3"
+  resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.3.tgz#465547f359ccc206d3c48e46a1bcb89bf7ee619d"
+  integrity sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==
+
+pify@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
+  integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
+
+pify@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
+  integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
+
+pkg-dir@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3"
+  integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==
+  dependencies:
+    find-up "^3.0.0"
+
+pkg-dir@^4.2.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
+  integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==
+  dependencies:
+    find-up "^4.0.0"
+
+prelude-ls@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
+  integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
+
+prettier@^2.3.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.0.tgz#b6a5bf1284026ae640f17f7ff5658a7567fc0d18"
+  integrity sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==
+
+progress@^2.0.0:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
+  integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
+
+propagate@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45"
+  integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==
+
+pseudomap@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
+  integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
+
+pump@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
+  integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
+  dependencies:
+    end-of-stream "^1.1.0"
+    once "^1.3.1"
+
+punycode@^2.1.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
+  integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
+
+qqjs@^0.3.10:
+  version "0.3.11"
+  resolved "https://registry.yarnpkg.com/qqjs/-/qqjs-0.3.11.tgz#795b9f7d00807d75c391b1241b5be3077143d9ea"
+  integrity sha512-pB2X5AduTl78J+xRSxQiEmga1jQV0j43jOPs/MTgTLApGFEOn6NgdE2dEjp7nvDtjkIOZbvFIojAiYUx6ep3zg==
+  dependencies:
+    chalk "^2.4.1"
+    debug "^4.1.1"
+    execa "^0.10.0"
+    fs-extra "^6.0.1"
+    get-stream "^5.1.0"
+    glob "^7.1.2"
+    globby "^10.0.1"
+    http-call "^5.1.2"
+    load-json-file "^6.2.0"
+    pkg-dir "^4.2.0"
+    tar-fs "^2.0.0"
+    tmp "^0.1.0"
+    write-json-file "^4.1.1"
+
+queue-microtask@^1.2.2:
+  version "1.2.3"
+  resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
+  integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+
+ramda@^0.26.1:
+  version "0.26.1"
+  resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.26.1.tgz#8d41351eb8111c55353617fc3bbffad8e4d35d06"
+  integrity sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==
+
+read-pkg-up@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978"
+  integrity sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==
+  dependencies:
+    find-up "^3.0.0"
+    read-pkg "^3.0.0"
+
+read-pkg@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389"
+  integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=
+  dependencies:
+    load-json-file "^4.0.0"
+    normalize-package-data "^2.3.2"
+    path-type "^3.0.0"
+
+readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0:
+  version "3.6.0"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
+  integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
+  dependencies:
+    inherits "^2.0.3"
+    string_decoder "^1.1.1"
+    util-deprecate "^1.0.1"
+
+redeyed@~2.1.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/redeyed/-/redeyed-2.1.1.tgz#8984b5815d99cb220469c99eeeffe38913e6cc0b"
+  integrity sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=
+  dependencies:
+    esprima "~4.0.0"
+
+regenerator-runtime@^0.13.4:
+  version "0.13.7"
+  resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55"
+  integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==
+
+regexpp@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f"
+  integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==
+
+regexpp@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2"
+  integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==
+
+release-zalgo@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730"
+  integrity sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=
+  dependencies:
+    es6-error "^4.0.1"
+
+require-directory@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
+  integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
+
+require-main-filename@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
+  integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
+
+resolve-from@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
+  integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
+
+resolve@^1.10.0, resolve@^1.20.0, resolve@^1.8.1:
+  version "1.20.0"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
+  integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
+  dependencies:
+    is-core-module "^2.2.0"
+    path-parse "^1.0.6"
+
+restore-cursor@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
+  integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368=
+  dependencies:
+    onetime "^2.0.0"
+    signal-exit "^3.0.2"
+
+ret@~0.1.10:
+  version "0.1.15"
+  resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
+  integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
+
+reusify@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
+  integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+
+rimraf@2.6.3:
+  version "2.6.3"
+  resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
+  integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
+  dependencies:
+    glob "^7.1.3"
+
+rimraf@^2.6.2, rimraf@^2.6.3:
+  version "2.7.1"
+  resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
+  integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
+  dependencies:
+    glob "^7.1.3"
+
+ripemd160@^2.0.1:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c"
+  integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==
+  dependencies:
+    hash-base "^3.0.0"
+    inherits "^2.0.1"
+
+run-async@^2.2.0:
+  version "2.4.1"
+  resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
+  integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
+
+run-parallel@^1.1.9:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
+  integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
+  dependencies:
+    queue-microtask "^1.2.2"
+
+rxjs@^6.4.0, rxjs@^6.6.7:
+  version "6.6.7"
+  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
+  integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
+  dependencies:
+    tslib "^1.9.0"
+
+safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
+  version "5.2.1"
+  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
+  integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+
+safe-buffer@~5.1.1:
+  version "5.1.2"
+  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
+  integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
+
+safe-regex@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
+  integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4=
+  dependencies:
+    ret "~0.1.10"
+
+"safer-buffer@>= 2.1.2 < 3":
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
+  integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
+
+scryptsy@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-2.1.0.tgz#8d1e8d0c025b58fdd25b6fa9a0dc905ee8faa790"
+  integrity sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w==
+
+"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
+  version "5.7.1"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
+  integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
+
+semver@^6.0.0:
+  version "6.3.0"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
+  integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
+
+semver@^7.3.2, semver@^7.3.4:
+  version "7.3.5"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
+  integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
+  dependencies:
+    lru-cache "^6.0.0"
+
+set-blocking@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
+  integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
+
+sha.js@^2.4.0:
+  version "2.4.11"
+  resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
+  integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==
+  dependencies:
+    inherits "^2.0.1"
+    safe-buffer "^5.0.1"
+
+shebang-command@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
+  integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=
+  dependencies:
+    shebang-regex "^1.0.0"
+
+shebang-regex@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
+  integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
+
+signal-exit@^3.0.0, signal-exit@^3.0.2:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
+  integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
+
+slash@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
+  integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
+
+slice-ansi@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636"
+  integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==
+  dependencies:
+    ansi-styles "^3.2.0"
+    astral-regex "^1.0.0"
+    is-fullwidth-code-point "^2.0.0"
+
+sort-keys@^4.0.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-4.2.0.tgz#6b7638cee42c506fff8c1cecde7376d21315be18"
+  integrity sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==
+  dependencies:
+    is-plain-obj "^2.0.0"
+
+source-map-support@^0.5.17:
+  version "0.5.19"
+  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
+  integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
+  dependencies:
+    buffer-from "^1.0.0"
+    source-map "^0.6.0"
+
+source-map@^0.5.0:
+  version "0.5.7"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
+  integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
+
+source-map@^0.6.0, source-map@^0.6.1:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+  integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+
+spawn-wrap@^1.4.2:
+  version "1.4.3"
+  resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.4.3.tgz#81b7670e170cca247d80bf5faf0cfb713bdcf848"
+  integrity sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==
+  dependencies:
+    foreground-child "^1.5.6"
+    mkdirp "^0.5.0"
+    os-homedir "^1.0.1"
+    rimraf "^2.6.2"
+    signal-exit "^3.0.2"
+    which "^1.3.0"
+
+spdx-correct@^3.0.0:
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9"
+  integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==
+  dependencies:
+    spdx-expression-parse "^3.0.0"
+    spdx-license-ids "^3.0.0"
+
+spdx-exceptions@^2.1.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d"
+  integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==
+
+spdx-expression-parse@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
+  integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
+  dependencies:
+    spdx-exceptions "^2.1.0"
+    spdx-license-ids "^3.0.0"
+
+spdx-license-ids@^3.0.0:
+  version "3.0.8"
+  resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.8.tgz#eb1e97ad99b11bf3f82a3b71a0472dd9a00f2ecf"
+  integrity sha512-NDgA96EnaLSvtbM7trJj+t1LUR3pirkDCcz9nOUlPb5DMBGsH7oES6C3hs3j7R9oHEa1EMvReS/BUAIT5Tcr0g==
+
+sprintf-js@~1.0.2:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
+  integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
+
+stdout-stderr@^0.1.9:
+  version "0.1.13"
+  resolved "https://registry.yarnpkg.com/stdout-stderr/-/stdout-stderr-0.1.13.tgz#54e3450f3d4c54086a49c0c7f8786a44d1844b6f"
+  integrity sha512-Xnt9/HHHYfjZ7NeQLvuQDyL1LnbsbddgMFKCuaQKwGCdJm8LnstZIXop+uOY36UR1UXXoHXfMbC1KlVdVd2JLA==
+  dependencies:
+    debug "^4.1.1"
+    strip-ansi "^6.0.0"
+
+"storage-node-v2@file:.":
+  version "0.1.0"
+  dependencies:
+    "@joystream/types" "link:../../../../Library/Caches/Yarn/v6/npm-storage-node-v2-0.1.0-1efa87d5-7b5a-4299-b05e-f3900311e907-1622039443083/node_modules/types"
+    "@oclif/command" "^1"
+    "@oclif/config" "^1"
+    "@oclif/plugin-help" "^3"
+    "@polkadot/api" "4.2.1"
+    storage-node-v2 "file:../../../../Library/Caches/Yarn/v6/npm-storage-node-v2-0.1.0-1efa87d5-7b5a-4299-b05e-f3900311e907-1622039443083/node_modules/storage-node-v2"
+    tslib "^1"
+
+string-width@^2.1.0, string-width@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
+  integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
+  dependencies:
+    is-fullwidth-code-point "^2.0.0"
+    strip-ansi "^4.0.0"
+
+string-width@^3.0.0, string-width@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
+  integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==
+  dependencies:
+    emoji-regex "^7.0.1"
+    is-fullwidth-code-point "^2.0.0"
+    strip-ansi "^5.1.0"
+
+string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0:
+  version "4.2.2"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5"
+  integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==
+  dependencies:
+    emoji-regex "^8.0.0"
+    is-fullwidth-code-point "^3.0.0"
+    strip-ansi "^6.0.0"
+
+string_decoder@^1.1.1:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
+  integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
+  dependencies:
+    safe-buffer "~5.2.0"
+
+strip-ansi@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
+  integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8=
+  dependencies:
+    ansi-regex "^3.0.0"
+
+strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
+  integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
+  dependencies:
+    ansi-regex "^4.1.0"
+
+strip-ansi@^6.0.0:
+  version "6.0.0"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
+  integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==
+  dependencies:
+    ansi-regex "^5.0.0"
+
+strip-bom@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
+  integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=
+
+strip-bom@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878"
+  integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==
+
+strip-eof@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
+  integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
+
+strip-json-comments@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
+  integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
+
+supports-color@5.4.0:
+  version "5.4.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54"
+  integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==
+  dependencies:
+    has-flag "^3.0.0"
+
+supports-color@^5.3.0:
+  version "5.5.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
+  integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
+  dependencies:
+    has-flag "^3.0.0"
+
+supports-color@^6.1.0:
+  version "6.1.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3"
+  integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==
+  dependencies:
+    has-flag "^3.0.0"
+
+supports-color@^7.0.0, supports-color@^7.1.0:
+  version "7.2.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
+  integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
+  dependencies:
+    has-flag "^4.0.0"
+
+supports-hyperlinks@^2.1.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb"
+  integrity sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==
+  dependencies:
+    has-flag "^4.0.0"
+    supports-color "^7.0.0"
+
+table@^5.2.3:
+  version "5.4.6"
+  resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e"
+  integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==
+  dependencies:
+    ajv "^6.10.2"
+    lodash "^4.17.14"
+    slice-ansi "^2.1.0"
+    string-width "^3.0.0"
+
+tar-fs@^2.0.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784"
+  integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==
+  dependencies:
+    chownr "^1.1.1"
+    mkdirp-classic "^0.5.2"
+    pump "^3.0.0"
+    tar-stream "^2.1.4"
+
+tar-stream@^2.1.4:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287"
+  integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==
+  dependencies:
+    bl "^4.0.3"
+    end-of-stream "^1.4.1"
+    fs-constants "^1.0.0"
+    inherits "^2.0.3"
+    readable-stream "^3.1.1"
+
+test-exclude@^5.2.3:
+  version "5.2.3"
+  resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.3.tgz#c3d3e1e311eb7ee405e092dac10aefd09091eac0"
+  integrity sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==
+  dependencies:
+    glob "^7.1.3"
+    minimatch "^3.0.4"
+    read-pkg-up "^4.0.0"
+    require-main-filename "^2.0.0"
+
+text-table@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
+  integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
+
+through@^2.3.6:
+  version "2.3.8"
+  resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
+  integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
+
+tmp@^0.0.33:
+  version "0.0.33"
+  resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
+  integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
+  dependencies:
+    os-tmpdir "~1.0.2"
+
+tmp@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877"
+  integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==
+  dependencies:
+    rimraf "^2.6.3"
+
+to-fast-properties@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
+  integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
+
+to-regex-range@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
+  integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+  dependencies:
+    is-number "^7.0.0"
+
+ts-node@^8:
+  version "8.10.2"
+  resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.10.2.tgz#eee03764633b1234ddd37f8db9ec10b75ec7fb8d"
+  integrity sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==
+  dependencies:
+    arg "^4.1.0"
+    diff "^4.0.1"
+    make-error "^1.1.1"
+    source-map-support "^0.5.17"
+    yn "3.1.1"
+
+tslib@^1, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
+  version "1.14.1"
+  resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
+  integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
+
+tslib@^2.0.0, tslib@^2.0.3:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c"
+  integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==
+
+tsutils@^3.17.1:
+  version "3.21.0"
+  resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
+  integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==
+  dependencies:
+    tslib "^1.8.1"
+
+tunnel-agent@^0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
+  integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
+  dependencies:
+    safe-buffer "^5.0.1"
+
+tweetnacl@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596"
+  integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==
+
+type-check@~0.3.2:
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
+  integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=
+  dependencies:
+    prelude-ls "~1.1.2"
+
+type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5:
+  version "4.0.8"
+  resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
+  integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
+
+type-fest@^0.21.3:
+  version "0.21.3"
+  resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
+  integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
+
+type-fest@^0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b"
+  integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==
+
+type@^1.0.1:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0"
+  integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==
+
+type@^2.0.0:
+  version "2.5.0"
+  resolved "https://registry.yarnpkg.com/type/-/type-2.5.0.tgz#0a2e78c2e77907b252abe5f298c1b01c63f0db3d"
+  integrity sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==
+
+typedarray-to-buffer@^3.1.5:
+  version "3.1.5"
+  resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"
+  integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==
+  dependencies:
+    is-typedarray "^1.0.0"
+
+typescript@^3.3:
+  version "3.9.9"
+  resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.9.tgz#e69905c54bc0681d0518bd4d587cc6f2d0b1a674"
+  integrity sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==
+
+unist-util-stringify-position@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.0.tgz#d517d2883d74d0daa0b565adc3d10a02b4a8cde9"
+  integrity sha512-SdfAl8fsDclywZpfMDTVDxA2V7LjtRDTOFd44wUJamgl6OlVngsqWjxvermMYf60elWHbxhuRCZml7AnuXCaSA==
+  dependencies:
+    "@types/unist" "^2.0.0"
+
+universalify@^0.1.0:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
+  integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
+
+uri-js@^4.2.2:
+  version "4.4.1"
+  resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
+  integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
+  dependencies:
+    punycode "^2.1.0"
+
+utf-8-validate@^5.0.2:
+  version "5.0.5"
+  resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.5.tgz#dd32c2e82c72002dc9f02eb67ba6761f43456ca1"
+  integrity sha512-+pnxRYsS/axEpkrrEpzYfNZGXp0IjC/9RIxwM5gntY4Koi8SHmUGSfxfWqxZdRxrtaoVstuOzUp/rbs3JSPELQ==
+  dependencies:
+    node-gyp-build "^4.2.0"
+
+util-deprecate@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+  integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
+
+uuid@^3.3.2:
+  version "3.4.0"
+  resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
+  integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
+
+validate-npm-package-license@^3.0.1:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
+  integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
+  dependencies:
+    spdx-correct "^3.0.0"
+    spdx-expression-parse "^3.0.0"
+
+vfile-message@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-3.0.1.tgz#b9bcf87cb5525e61777e0c6df07e816a577588a3"
+  integrity sha512-gYmSHcZZUEtYpTmaWaFJwsuUD70/rTY4v09COp8TGtOkix6gGxb/a8iTQByIY9ciTk9GwAwIXd/J9OPfM4Bvaw==
+  dependencies:
+    "@types/unist" "^2.0.0"
+    unist-util-stringify-position "^3.0.0"
+
+vfile@*:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/vfile/-/vfile-5.0.1.tgz#41c6d50d419e700424ef577fbc00dd6bc6487b7e"
+  integrity sha512-lbcf0k66x96Syy36HG+nIBFaSD/fAk589q4nETZTr0JW7eRRmrVo1vHwbD8NlHszUM5ICtFSWQ5xHC292hYZ/w==
+  dependencies:
+    "@types/unist" "^2.0.0"
+    is-buffer "^2.0.0"
+    unist-util-stringify-position "^3.0.0"
+    vfile-message "^3.0.0"
+
+websocket@^1.0.34:
+  version "1.0.34"
+  resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111"
+  integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==
+  dependencies:
+    bufferutil "^4.0.1"
+    debug "^2.2.0"
+    es5-ext "^0.10.50"
+    typedarray-to-buffer "^3.1.5"
+    utf-8-validate "^5.0.2"
+    yaeti "^0.0.6"
+
+which-module@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
+  integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
+
+which@^1.2.9, which@^1.3.0:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
+  integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
+  dependencies:
+    isexe "^2.0.0"
+
+widest-line@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca"
+  integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==
+  dependencies:
+    string-width "^4.0.0"
+
+word-wrap@~1.2.3:
+  version "1.2.3"
+  resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
+  integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
+
+wrap-ansi@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-4.0.0.tgz#b3570d7c70156159a2d42be5cc942e957f7b1131"
+  integrity sha512-uMTsj9rDb0/7kk1PbcbCcwvHUxp60fGDB/NNXpVa0Q+ic/e7y5+BwTxKfQ33VYgDppSwi/FBzpetYzo8s6tfbg==
+  dependencies:
+    ansi-styles "^3.2.0"
+    string-width "^2.1.1"
+    strip-ansi "^4.0.0"
+
+wrap-ansi@^5.1.0:
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09"
+  integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==
+  dependencies:
+    ansi-styles "^3.2.0"
+    string-width "^3.0.0"
+    strip-ansi "^5.0.0"
+
+wrap-ansi@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+  integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+  dependencies:
+    ansi-styles "^4.0.0"
+    string-width "^4.1.0"
+    strip-ansi "^6.0.0"
+
+wrappy@1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+  integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
+
+write-file-atomic@^2.4.2:
+  version "2.4.3"
+  resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481"
+  integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==
+  dependencies:
+    graceful-fs "^4.1.11"
+    imurmurhash "^0.1.4"
+    signal-exit "^3.0.2"
+
+write-file-atomic@^3.0.0:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8"
+  integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==
+  dependencies:
+    imurmurhash "^0.1.4"
+    is-typedarray "^1.0.0"
+    signal-exit "^3.0.2"
+    typedarray-to-buffer "^3.1.5"
+
+write-json-file@^4.1.1:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-4.3.0.tgz#908493d6fd23225344af324016e4ca8f702dd12d"
+  integrity sha512-PxiShnxf0IlnQuMYOPPhPkhExoCQuTUNPOa/2JWCYTmBquU9njyyDuwRKN26IZBlp4yn1nt+Agh2HOOBl+55HQ==
+  dependencies:
+    detect-indent "^6.0.0"
+    graceful-fs "^4.1.15"
+    is-plain-obj "^2.0.0"
+    make-dir "^3.0.0"
+    sort-keys "^4.0.0"
+    write-file-atomic "^3.0.0"
+
+write@1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3"
+  integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==
+  dependencies:
+    mkdirp "^0.5.1"
+
+xxhashjs@^0.2.2:
+  version "0.2.2"
+  resolved "https://registry.yarnpkg.com/xxhashjs/-/xxhashjs-0.2.2.tgz#8a6251567621a1c46a5ae204da0249c7f8caa9d8"
+  integrity sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==
+  dependencies:
+    cuint "^0.2.2"
+
+y18n@^4.0.0:
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
+  integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==
+
+yaeti@^0.0.6:
+  version "0.0.6"
+  resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577"
+  integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=
+
+yallist@^2.1.2:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
+  integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
+
+yallist@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
+  integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
+
+yargs-parser@^13.0.0, yargs-parser@^13.1.2:
+  version "13.1.2"
+  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38"
+  integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==
+  dependencies:
+    camelcase "^5.0.0"
+    decamelize "^1.2.0"
+
+yargs@^13.2.2:
+  version "13.3.2"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd"
+  integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==
+  dependencies:
+    cliui "^5.0.0"
+    find-up "^3.0.0"
+    get-caller-file "^2.0.1"
+    require-directory "^2.1.1"
+    require-main-filename "^2.0.0"
+    set-blocking "^2.0.0"
+    string-width "^3.0.0"
+    which-module "^2.0.0"
+    y18n "^4.0.0"
+    yargs-parser "^13.1.2"
+
+yn@3.1.1:
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
+  integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
types/augment-codec/all.ts


+ 48 - 3
types/augment-codec/augment-api-consts.ts

@@ -2,6 +2,7 @@
 /* eslint-disable */
 
 import type { Vec, u32, u64 } from '@polkadot/types';
+import type { StorageBucketsPerBagValueConstraint } from './all';
 import type { Balance, BalanceOf, BlockNumber, Moment, Perbill, RuntimeDbWeight, Weight } from '@polkadot/types/interfaces/runtime';
 import type { SessionIndex } from '@polkadot/types/interfaces/session';
 import type { EraIndex } from '@polkadot/types/interfaces/staking';
@@ -37,11 +38,11 @@ declare module '@polkadot/api/types/consts' {
        **/
       maxWorkerNumberLimit: u32 & AugmentedConst<ApiType>;
     };
-    dataDirectory: {
+    distributionWorkingGroup: {
       /**
-       * Maximum objects allowed per inject_data_objects() transaction
+       * Exports const -  max simultaneous active worker number.
        **/
-      maxObjectsPerInjection: u32 & AugmentedConst<ApiType>;
+      maxWorkerNumberLimit: u32 & AugmentedConst<ApiType>;
     };
     finalityTracker: {
       /**
@@ -148,6 +149,50 @@ declare module '@polkadot/api/types/consts' {
        **/
       slashDeferDuration: EraIndex & AugmentedConst<ApiType>;
     };
+    storage: {
+      /**
+       * Exports const - maximum size of the "hash blacklist" collection.
+       **/
+      blacklistSizeLimit: u64 & AugmentedConst<ApiType>;
+      /**
+       * Exports const - a prize for a data object deletion.
+       **/
+      dataObjectDeletionPrize: BalanceOf & AugmentedConst<ApiType>;
+      /**
+       * Exports const - the default dynamic bag creation policy for channels (storage bucket
+       * number).
+       **/
+      defaultChannelDynamicBagNumberOfStorageBuckets: u64 & AugmentedConst<ApiType>;
+      /**
+       * Exports const - the default dynamic bag creation policy for members (storage bucket
+       * number).
+       **/
+      defaultMemberDynamicBagNumberOfStorageBuckets: u64 & AugmentedConst<ApiType>;
+      /**
+       * Exports const - "Distribution buckets per bag" value constraint.
+       **/
+      distributionBucketsPerBagValueConstraint: StorageBucketsPerBagValueConstraint & AugmentedConst<ApiType>;
+      /**
+       * Exports const - max allowed distribution bucket family number.
+       **/
+      maxDistributionBucketFamilyNumber: u64 & AugmentedConst<ApiType>;
+      /**
+       * Exports const - max allowed distribution bucket number per family.
+       **/
+      maxDistributionBucketNumberPerFamily: u64 & AugmentedConst<ApiType>;
+      /**
+       * Exports const - max number of data objects per bag.
+       **/
+      maxNumberOfDataObjectsPerBag: u64 & AugmentedConst<ApiType>;
+      /**
+       * Exports const - max number of pending invitations per distribution bucket.
+       **/
+      maxNumberOfPendingInvitationsPerDistributionBucket: u64 & AugmentedConst<ApiType>;
+      /**
+       * Exports const - "Storage buckets per bag" value constraint.
+       **/
+      storageBucketsPerBagValueConstraint: StorageBucketsPerBagValueConstraint & AugmentedConst<ApiType>;
+    };
     storageWorkingGroup: {
       /**
        * Exports const -  max simultaneous active worker number.

+ 593 - 27
types/augment-codec/augment-api-errors.ts

@@ -763,59 +763,399 @@ declare module '@polkadot/api/types/errors' {
        **/
       WorkerHasNoReward: AugmentedError<ApiType>;
     };
-    dataDirectory: {
+    distributionWorkingGroup: {
       /**
-       * Content with this ID not found.
+       * Opening does not exist.
+       **/
+      AcceptWorkerApplicationsOpeningDoesNotExist: AugmentedError<ApiType>;
+      /**
+       * Opening Is Not in Waiting to begin.
+       **/
+      AcceptWorkerApplicationsOpeningIsNotWaitingToBegin: AugmentedError<ApiType>;
+      /**
+       * Opening does not activate in the future.
+       **/
+      AddWorkerOpeningActivatesInThePast: AugmentedError<ApiType>;
+      /**
+       * Add worker opening application stake cannot be zero.
+       **/
+      AddWorkerOpeningApplicationStakeCannotBeZero: AugmentedError<ApiType>;
+      /**
+       * Application stake amount less than minimum currency balance.
+       **/
+      AddWorkerOpeningAppliicationStakeLessThanMinimum: AugmentedError<ApiType>;
+      /**
+       * New application was crowded out.
+       **/
+      AddWorkerOpeningNewApplicationWasCrowdedOut: AugmentedError<ApiType>;
+      /**
+       * Opening does not exist.
+       **/
+      AddWorkerOpeningOpeningDoesNotExist: AugmentedError<ApiType>;
+      /**
+       * Opening is not in accepting applications stage.
+       **/
+      AddWorkerOpeningOpeningNotInAcceptingApplicationStage: AugmentedError<ApiType>;
+      /**
+       * Add worker opening role stake cannot be zero.
+       **/
+      AddWorkerOpeningRoleStakeCannotBeZero: AugmentedError<ApiType>;
+      /**
+       * Role stake amount less than minimum currency balance.
+       **/
+      AddWorkerOpeningRoleStakeLessThanMinimum: AugmentedError<ApiType>;
+      /**
+       * Stake amount too low.
+       **/
+      AddWorkerOpeningStakeAmountTooLow: AugmentedError<ApiType>;
+      /**
+       * Stake missing when required.
+       **/
+      AddWorkerOpeningStakeMissingWhenRequired: AugmentedError<ApiType>;
+      /**
+       * Stake provided when redundant.
+       **/
+      AddWorkerOpeningStakeProvidedWhenRedundant: AugmentedError<ApiType>;
+      /**
+       * Application rationing has zero max active applicants.
+       **/
+      AddWorkerOpeningZeroMaxApplicantCount: AugmentedError<ApiType>;
+      /**
+       * Invalid OpeningPolicyCommitment parameter (application_rationing_policy):
+       * max_active_applicants should be non-zero.
+       **/
+      ApplicationRationingPolicyMaxActiveApplicantsIsZero: AugmentedError<ApiType>;
+      /**
+       * Invalid OpeningPolicyCommitment parameter (application_staking_policy):
+       * crowded_out_unstaking_period_length should be non-zero.
+       **/
+      ApplicationStakingPolicyCrowdedOutUnstakingPeriodIsZero: AugmentedError<ApiType>;
+      /**
+       * Invalid OpeningPolicyCommitment parameter (application_staking_policy):
+       * review_period_expired_unstaking_period_length should be non-zero.
+       **/
+      ApplicationStakingPolicyReviewPeriodUnstakingPeriodIsZero: AugmentedError<ApiType>;
+      /**
+       * Signer does not match controller account.
+       **/
+      ApplyOnWorkerOpeningSignerNotControllerAccount: AugmentedError<ApiType>;
+      /**
+       * Opening does not exist.
        **/
-      CidNotFound: AugmentedError<ApiType>;
+      BeginWorkerApplicantReviewOpeningDoesNotExist: AugmentedError<ApiType>;
       /**
-       * "Data object already added under this content id".
+       * Opening Is Not in Waiting.
+       **/
+      BeginWorkerApplicantReviewOpeningOpeningIsNotWaitingToBegin: AugmentedError<ApiType>;
+      /**
+       * Cannot find mint in the minting module.
+       **/
+      CannotFindMint: AugmentedError<ApiType>;
+      /**
+       * There is leader already, cannot hire another one.
+       **/
+      CannotHireLeaderWhenLeaderExists: AugmentedError<ApiType>;
+      /**
+       * Cannot fill opening with multiple applications.
+       **/
+      CannotHireMultipleLeaders: AugmentedError<ApiType>;
+      /**
+       * Current lead is not set.
+       **/
+      CurrentLeadNotSet: AugmentedError<ApiType>;
+      /**
+       * Invalid OpeningPolicyCommitment parameter:
+       * exit_role_application_stake_unstaking_period should be non-zero.
+       **/
+      ExitRoleApplicationStakeUnstakingPeriodIsZero: AugmentedError<ApiType>;
+      /**
+       * Invalid OpeningPolicyCommitment parameter:
+       * exit_role_stake_unstaking_period should be non-zero.
+       **/
+      ExitRoleStakeUnstakingPeriodIsZero: AugmentedError<ApiType>;
+      /**
+       * Invalid OpeningPolicyCommitment parameter:
+       * fill_opening_failed_applicant_application_stake_unstaking_period should be non-zero.
+       **/
+      FillOpeningFailedApplicantApplicationStakeUnstakingPeriodIsZero: AugmentedError<ApiType>;
+      /**
+       * Invalid OpeningPolicyCommitment parameter:
+       * fill_opening_failed_applicant_role_stake_unstaking_period should be non-zero.
+       **/
+      FillOpeningFailedApplicantRoleStakeUnstakingPeriodIsZero: AugmentedError<ApiType>;
+      /**
+       * Reward policy has invalid next payment block number.
+       **/
+      FillOpeningInvalidNextPaymentBlock: AugmentedError<ApiType>;
+      /**
+       * Working group mint does not exist.
+       **/
+      FillOpeningMintDoesNotExist: AugmentedError<ApiType>;
+      /**
+       * Invalid OpeningPolicyCommitment parameter:
+       * fill_opening_successful_applicant_application_stake_unstaking_period should be non-zero.
+       **/
+      FillOpeningSuccessfulApplicantApplicationStakeUnstakingPeriodIsZero: AugmentedError<ApiType>;
+      /**
+       * Applications not for opening.
+       **/
+      FillWorkerOpeningApplicationForWrongOpening: AugmentedError<ApiType>;
+      /**
+       * Application does not exist.
+       **/
+      FullWorkerOpeningApplicationDoesNotExist: AugmentedError<ApiType>;
+      /**
+       * Application not in active stage.
+       **/
+      FullWorkerOpeningApplicationNotActive: AugmentedError<ApiType>;
+      /**
+       * OpeningDoesNotExist.
+       **/
+      FullWorkerOpeningOpeningDoesNotExist: AugmentedError<ApiType>;
+      /**
+       * Opening not in review period stage.
+       **/
+      FullWorkerOpeningOpeningNotInReviewPeriodStage: AugmentedError<ApiType>;
+      /**
+       * Application stake unstaking period for successful applicants redundant.
+       **/
+      FullWorkerOpeningSuccessfulApplicationStakeUnstakingPeriodRedundant: AugmentedError<ApiType>;
+      /**
+       * Application stake unstaking period for failed applicants too short.
+       **/
+      FullWorkerOpeningSuccessfulApplicationStakeUnstakingPeriodTooShort: AugmentedError<ApiType>;
+      /**
+       * Role stake unstaking period for successful applicants redundant.
+       **/
+      FullWorkerOpeningSuccessfulRoleStakeUnstakingPeriodRedundant: AugmentedError<ApiType>;
+      /**
+       * Role stake unstaking period for successful applicants too short.
+       **/
+      FullWorkerOpeningSuccessfulRoleStakeUnstakingPeriodTooShort: AugmentedError<ApiType>;
+      /**
+       * Application stake unstaking period for failed applicants redundant.
+       **/
+      FullWorkerOpeningUnsuccessfulApplicationStakeUnstakingPeriodRedundant: AugmentedError<ApiType>;
+      /**
+       * Application stake unstaking period for successful applicants too short.
+       **/
+      FullWorkerOpeningUnsuccessfulApplicationStakeUnstakingPeriodTooShort: AugmentedError<ApiType>;
+      /**
+       * Role stake unstaking period for failed applicants redundant.
+       **/
+      FullWorkerOpeningUnsuccessfulRoleStakeUnstakingPeriodRedundant: AugmentedError<ApiType>;
+      /**
+       * Role stake unstaking period for failed applicants too short.
+       **/
+      FullWorkerOpeningUnsuccessfulRoleStakeUnstakingPeriodTooShort: AugmentedError<ApiType>;
+      /**
+       * Insufficient balance to apply.
+       **/
+      InsufficientBalanceToApply: AugmentedError<ApiType>;
+      /**
+       * Insufficient balance to cover stake.
+       **/
+      InsufficientBalanceToCoverStake: AugmentedError<ApiType>;
+      /**
+       * Not a lead account.
+       **/
+      IsNotLeadAccount: AugmentedError<ApiType>;
+      /**
+       * Working group size limit exceeded.
+       **/
+      MaxActiveWorkerNumberExceeded: AugmentedError<ApiType>;
+      /**
+       * Member already has an active application on the opening.
+       **/
+      MemberHasActiveApplicationOnOpening: AugmentedError<ApiType>;
+      /**
+       * Member id is invalid.
+       **/
+      MembershipInvalidMemberId: AugmentedError<ApiType>;
+      /**
+       * Unsigned origin.
+       **/
+      MembershipUnsignedOrigin: AugmentedError<ApiType>;
+      /**
+       * Minting error: NextAdjustmentInPast
+       **/
+      MintingErrorNextAdjustmentInPast: AugmentedError<ApiType>;
+      /**
+       * Cannot get the worker stake profile.
+       **/
+      NoWorkerStakeProfile: AugmentedError<ApiType>;
+      /**
+       * Opening does not exist.
+       **/
+      OpeningDoesNotExist: AugmentedError<ApiType>;
+      /**
+       * Opening text too long.
+       **/
+      OpeningTextTooLong: AugmentedError<ApiType>;
+      /**
+       * Opening text too short.
+       **/
+      OpeningTextTooShort: AugmentedError<ApiType>;
+      /**
+       * Origin must be controller or root account of member.
+       **/
+      OriginIsNeitherMemberControllerOrRoot: AugmentedError<ApiType>;
+      /**
+       * Origin is not applicant.
+       **/
+      OriginIsNotApplicant: AugmentedError<ApiType>;
+      /**
+       * Next payment is not in the future.
+       **/
+      RecurringRewardsNextPaymentNotInFuture: AugmentedError<ApiType>;
+      /**
+       * Recipient not found.
        **/
-      DataObjectAlreadyAdded: AugmentedError<ApiType>;
+      RecurringRewardsRecipientNotFound: AugmentedError<ApiType>;
       /**
-       * DataObject Injection Failed. Too Many DataObjects.
+       * Reward relationship not found.
        **/
-      DataObjectsInjectionExceededLimit: AugmentedError<ApiType>;
+      RecurringRewardsRewardRelationshipNotFound: AugmentedError<ApiType>;
       /**
-       * Cannot create content for inactive or missing data object type.
+       * Recipient reward source not found.
        **/
-      DataObjectTypeMustBeActive: AugmentedError<ApiType>;
+      RecurringRewardsRewardSourceNotFound: AugmentedError<ApiType>;
       /**
-       * Only the liaison for the content may modify its status.
+       * Relationship must exist.
        **/
-      LiaisonRequired: AugmentedError<ApiType>;
+      RelationshipMustExist: AugmentedError<ApiType>;
       /**
        * Require root origin in extrinsics.
        **/
       RequireRootOrigin: AugmentedError<ApiType>;
-    };
-    dataObjectStorageRegistry: {
       /**
-       * Content with this ID not found.
+       * Require signed origin in extrinsics.
        **/
-      CidNotFound: AugmentedError<ApiType>;
+      RequireSignedOrigin: AugmentedError<ApiType>;
       /**
-       * No data object storage relationship found for this ID.
+       * Invalid OpeningPolicyCommitment parameter (role_staking_policy):
+       * crowded_out_unstaking_period_length should be non-zero.
        **/
-      DataObjectStorageRelationshipNotFound: AugmentedError<ApiType>;
+      RoleStakingPolicyCrowdedOutUnstakingPeriodIsZero: AugmentedError<ApiType>;
       /**
-       * Only the storage provider in a DOSR can decide whether they're ready.
+       * Invalid OpeningPolicyCommitment parameter (role_staking_policy):
+       * review_period_expired_unstaking_period_length should be non-zero.
        **/
-      OnlyStorageProviderMayClaimReady: AugmentedError<ApiType>;
+      RoleStakingPolicyReviewPeriodUnstakingPeriodIsZero: AugmentedError<ApiType>;
       /**
-       * Require root origin in extrinsics
+       * Signer is not worker role account.
        **/
-      RequireRootOrigin: AugmentedError<ApiType>;
-    };
-    dataObjectTypeRegistry: {
+      SignerIsNotWorkerRoleAccount: AugmentedError<ApiType>;
       /**
-       * Data Object Type with the given ID not found.
+       * Provided stake balance cannot be zero.
        **/
-      DataObjectTypeNotFound: AugmentedError<ApiType>;
+      StakeBalanceCannotBeZero: AugmentedError<ApiType>;
       /**
-       * Require root origin in extrinsics
+       * Already unstaking.
        **/
-      RequireRootOrigin: AugmentedError<ApiType>;
+      StakingErrorAlreadyUnstaking: AugmentedError<ApiType>;
+      /**
+       * Cannot change stake by zero.
+       **/
+      StakingErrorCannotChangeStakeByZero: AugmentedError<ApiType>;
+      /**
+       * Cannot decrease stake while slashes ongoing.
+       **/
+      StakingErrorCannotDecreaseWhileSlashesOngoing: AugmentedError<ApiType>;
+      /**
+       * Cannot increase stake while unstaking.
+       **/
+      StakingErrorCannotIncreaseStakeWhileUnstaking: AugmentedError<ApiType>;
+      /**
+       * Cannot unstake while slashes ongoing.
+       **/
+      StakingErrorCannotUnstakeWhileSlashesOngoing: AugmentedError<ApiType>;
+      /**
+       * Insufficient balance in source account.
+       **/
+      StakingErrorInsufficientBalanceInSourceAccount: AugmentedError<ApiType>;
+      /**
+       * Insufficient stake to decrease.
+       **/
+      StakingErrorInsufficientStake: AugmentedError<ApiType>;
+      /**
+       * Not staked.
+       **/
+      StakingErrorNotStaked: AugmentedError<ApiType>;
+      /**
+       * Slash amount should be greater than zero.
+       **/
+      StakingErrorSlashAmountShouldBeGreaterThanZero: AugmentedError<ApiType>;
+      /**
+       * Stake not found.
+       **/
+      StakingErrorStakeNotFound: AugmentedError<ApiType>;
+      /**
+       * Unstaking period should be greater than zero.
+       **/
+      StakingErrorUnstakingPeriodShouldBeGreaterThanZero: AugmentedError<ApiType>;
+      /**
+       * Successful worker application does not exist.
+       **/
+      SuccessfulWorkerApplicationDoesNotExist: AugmentedError<ApiType>;
+      /**
+       * Invalid OpeningPolicyCommitment parameter:
+       * terminate_application_stake_unstaking_period should be non-zero.
+       **/
+      TerminateApplicationStakeUnstakingPeriodIsZero: AugmentedError<ApiType>;
+      /**
+       * Invalid OpeningPolicyCommitment parameter:
+       * terminate_role_stake_unstaking_period should be non-zero.
+       **/
+      TerminateRoleStakeUnstakingPeriodIsZero: AugmentedError<ApiType>;
+      /**
+       * Application does not exist.
+       **/
+      WithdrawWorkerApplicationApplicationDoesNotExist: AugmentedError<ApiType>;
+      /**
+       * Application is not active.
+       **/
+      WithdrawWorkerApplicationApplicationNotActive: AugmentedError<ApiType>;
+      /**
+       * Opening not accepting applications.
+       **/
+      WithdrawWorkerApplicationOpeningNotAcceptingApplications: AugmentedError<ApiType>;
+      /**
+       * Redundant unstaking period provided
+       **/
+      WithdrawWorkerApplicationRedundantUnstakingPeriod: AugmentedError<ApiType>;
+      /**
+       * UnstakingPeriodTooShort .... // <== SHOULD REALLY BE TWO SEPARATE, ONE FOR EACH STAKING PURPOSE
+       **/
+      WithdrawWorkerApplicationUnstakingPeriodTooShort: AugmentedError<ApiType>;
+      /**
+       * Worker application does not exist.
+       **/
+      WorkerApplicationDoesNotExist: AugmentedError<ApiType>;
+      /**
+       * Worker application text too long.
+       **/
+      WorkerApplicationTextTooLong: AugmentedError<ApiType>;
+      /**
+       * Worker application text too short.
+       **/
+      WorkerApplicationTextTooShort: AugmentedError<ApiType>;
+      /**
+       * Worker does not exist.
+       **/
+      WorkerDoesNotExist: AugmentedError<ApiType>;
+      /**
+       * Worker exit rationale text is too long.
+       **/
+      WorkerExitRationaleTextTooLong: AugmentedError<ApiType>;
+      /**
+       * Worker exit rationale text is too short.
+       **/
+      WorkerExitRationaleTextTooShort: AugmentedError<ApiType>;
+      /**
+       * Worker has no recurring reward.
+       **/
+      WorkerHasNoReward: AugmentedError<ApiType>;
     };
     finalityTracker: {
       /**
@@ -1202,6 +1542,232 @@ declare module '@polkadot/api/types/errors' {
        **/
       SnapshotUnavailable: AugmentedError<ApiType>;
     };
+    storage: {
+      /**
+       * Blacklist size limit exceeded.
+       **/
+      BlacklistSizeLimitExceeded: AugmentedError<ApiType>;
+      /**
+       * Cannot delete non empty dynamic bag.
+       **/
+      CannotDeleteNonEmptyDynamicBag: AugmentedError<ApiType>;
+      /**
+       * Cannot delete a non-empty storage bucket.
+       **/
+      CannotDeleteNonEmptyStorageBucket: AugmentedError<ApiType>;
+      /**
+       * Data object hash is part of the blacklist.
+       **/
+      DataObjectBlacklisted: AugmentedError<ApiType>;
+      /**
+       * Data object doesn't exist.
+       **/
+      DataObjectDoesntExist: AugmentedError<ApiType>;
+      /**
+       * Data object id collection is empty.
+       **/
+      DataObjectIdCollectionIsEmpty: AugmentedError<ApiType>;
+      /**
+       * The `data_object_ids` extrinsic parameter collection is empty.
+       **/
+      DataObjectIdParamsAreEmpty: AugmentedError<ApiType>;
+      /**
+       * Upload data error: data objects per bag limit exceeded.
+       **/
+      DataObjectsPerBagLimitExceeded: AugmentedError<ApiType>;
+      /**
+       * Invalid extrinsic call: data size fee changed.
+       **/
+      DataSizeFeeChanged: AugmentedError<ApiType>;
+      /**
+       * Invalid operation with invites: another storage provider was invited.
+       **/
+      DifferentStorageProviderInvited: AugmentedError<ApiType>;
+      /**
+       * Distribution bucket doesn't accept new bags.
+       **/
+      DistributionBucketDoesntAcceptNewBags: AugmentedError<ApiType>;
+      /**
+       * Distribution bucket doesn't exist.
+       **/
+      DistributionBucketDoesntExist: AugmentedError<ApiType>;
+      /**
+       * Distribution bucket family doesn't exist.
+       **/
+      DistributionBucketFamilyDoesntExist: AugmentedError<ApiType>;
+      /**
+       * Distribution bucket id collections are empty.
+       **/
+      DistributionBucketIdCollectionsAreEmpty: AugmentedError<ApiType>;
+      /**
+       * Distribution bucket is bound to a bag.
+       **/
+      DistributionBucketIsBoundToBag: AugmentedError<ApiType>;
+      /**
+       * Distribution bucket is not bound to a bag.
+       **/
+      DistributionBucketIsNotBoundToBag: AugmentedError<ApiType>;
+      /**
+       * The new `DistributionBucketsPerBagLimit` number is too high.
+       **/
+      DistributionBucketsPerBagLimitTooHigh: AugmentedError<ApiType>;
+      /**
+       * The new `DistributionBucketsPerBagLimit` number is too low.
+       **/
+      DistributionBucketsPerBagLimitTooLow: AugmentedError<ApiType>;
+      /**
+       * Distribution family bound to a bag creation policy.
+       **/
+      DistributionFamilyBoundToBagCreationPolicy: AugmentedError<ApiType>;
+      /**
+       * Distribution provider operator already invited.
+       **/
+      DistributionProviderOperatorAlreadyInvited: AugmentedError<ApiType>;
+      /**
+       * Distribution provider operator doesn't exist.
+       **/
+      DistributionProviderOperatorDoesntExist: AugmentedError<ApiType>;
+      /**
+       * Distribution provider operator already set.
+       **/
+      DistributionProviderOperatorSet: AugmentedError<ApiType>;
+      /**
+       * Dynamic bag doesn't exist.
+       **/
+      DynamicBagDoesntExist: AugmentedError<ApiType>;
+      /**
+       * Cannot create the dynamic bag: dynamic bag exists.
+       **/
+      DynamicBagExists: AugmentedError<ApiType>;
+      /**
+       * Upload data error: empty content ID provided.
+       **/
+      EmptyContentId: AugmentedError<ApiType>;
+      /**
+       * Insufficient balance for an operation.
+       **/
+      InsufficientBalance: AugmentedError<ApiType>;
+      /**
+       * Insufficient module treasury balance for an operation.
+       **/
+      InsufficientTreasuryBalance: AugmentedError<ApiType>;
+      /**
+       * Upload data error: invalid deletion prize source account.
+       **/
+      InvalidDeletionPrizeSourceAccount: AugmentedError<ApiType>;
+      /**
+       * Invalid storage provider for bucket.
+       **/
+      InvalidStorageProvider: AugmentedError<ApiType>;
+      /**
+       * Invalid operation with invites: storage provider was already invited.
+       **/
+      InvitedStorageProvider: AugmentedError<ApiType>;
+      /**
+       * Max distribution bucket family number limit exceeded.
+       **/
+      MaxDistributionBucketFamilyNumberLimitExceeded: AugmentedError<ApiType>;
+      /**
+       * Max distribution bucket number per bag limit exceeded.
+       **/
+      MaxDistributionBucketNumberPerBagLimitExceeded: AugmentedError<ApiType>;
+      /**
+       * Max distribution bucket number per family limit exceeded.
+       **/
+      MaxDistributionBucketNumberPerFamilyLimitExceeded: AugmentedError<ApiType>;
+      /**
+       * Max number of pending invitations limit for a distribution bucket reached.
+       **/
+      MaxNumberOfPendingInvitationsLimitForDistributionBucketReached: AugmentedError<ApiType>;
+      /**
+       * Invalid operations: must be a distribution provider operator for a bucket.
+       **/
+      MustBeDistributionProviderOperatorForBucket: AugmentedError<ApiType>;
+      /**
+       * No distribution bucket invitation.
+       **/
+      NoDistributionBucketInvitation: AugmentedError<ApiType>;
+      /**
+       * Empty "data object creation" collection.
+       **/
+      NoObjectsOnUpload: AugmentedError<ApiType>;
+      /**
+       * Invalid operation with invites: there is no storage bucket invitation.
+       **/
+      NoStorageBucketInvitation: AugmentedError<ApiType>;
+      /**
+       * Cannot move objects within the same bag.
+       **/
+      SourceAndDestinationBagsAreEqual: AugmentedError<ApiType>;
+      /**
+       * The storage bucket doesn't accept new bags.
+       **/
+      StorageBucketDoesntAcceptNewBags: AugmentedError<ApiType>;
+      /**
+       * The requested storage bucket doesn't exist.
+       **/
+      StorageBucketDoesntExist: AugmentedError<ApiType>;
+      /**
+       * Storage bucket id collections are empty.
+       **/
+      StorageBucketIdCollectionsAreEmpty: AugmentedError<ApiType>;
+      /**
+       * The requested storage bucket is already bound to a bag.
+       **/
+      StorageBucketIsBoundToBag: AugmentedError<ApiType>;
+      /**
+       * The requested storage bucket is not bound to a bag.
+       **/
+      StorageBucketIsNotBoundToBag: AugmentedError<ApiType>;
+      /**
+       * Object number limit for the storage bucket reached.
+       **/
+      StorageBucketObjectNumberLimitReached: AugmentedError<ApiType>;
+      /**
+       * Objects total size limit for the storage bucket reached.
+       **/
+      StorageBucketObjectSizeLimitReached: AugmentedError<ApiType>;
+      /**
+       * `StorageBucketsPerBagLimit` was exceeded for a bag.
+       **/
+      StorageBucketPerBagLimitExceeded: AugmentedError<ApiType>;
+      /**
+       * The new `StorageBucketsPerBagLimit` number is too high.
+       **/
+      StorageBucketsPerBagLimitTooHigh: AugmentedError<ApiType>;
+      /**
+       * The new `StorageBucketsPerBagLimit` number is too low.
+       **/
+      StorageBucketsPerBagLimitTooLow: AugmentedError<ApiType>;
+      /**
+       * Invalid operation with invites: storage provider was already set.
+       **/
+      StorageProviderAlreadySet: AugmentedError<ApiType>;
+      /**
+       * Storage provider must be set.
+       **/
+      StorageProviderMustBeSet: AugmentedError<ApiType>;
+      /**
+       * Storage provider operator doesn't exist.
+       **/
+      StorageProviderOperatorDoesntExist: AugmentedError<ApiType>;
+      /**
+       * Uploading of the new object is blocked.
+       **/
+      UploadingBlocked: AugmentedError<ApiType>;
+      /**
+       * Max object number limit exceeded for voucher.
+       **/
+      VoucherMaxObjectNumberLimitExceeded: AugmentedError<ApiType>;
+      /**
+       * Max object size limit exceeded for voucher.
+       **/
+      VoucherMaxObjectSizeLimitExceeded: AugmentedError<ApiType>;
+      /**
+       * Upload data error: zero object size.
+       **/
+      ZeroObjectSize: AugmentedError<ApiType>;
+    };
     storageWorkingGroup: {
       /**
        * Opening does not exist.

+ 384 - 43
types/augment-codec/augment-api-events.ts

@@ -1,8 +1,8 @@
 // Auto-generated via `yarn polkadot-types-from-chain`, do not edit
 /* eslint-disable */
 
-import type { Option, Vec, bool, u16, u32, u64 } from '@polkadot/types';
-import type { Actor, ApplicationId, ApplicationIdToWorkerIdMap, CategoryId, ChannelId, ClassId, ContentId, CuratorApplicationId, CuratorApplicationIdToCuratorIdMap, CuratorGroupId, CuratorId, CuratorOpeningId, DataObjectStorageRelationshipId, DataObjectTypeId, EntityController, EntityCreationVoucher, EntityId, FailedAt, IPNSIdentity, LeadId, MemberId, MintBalanceOf, MintId, Nonce, OpeningId, PostId, PropertyId, ProposalId, ProposalStatus, RationaleText, SchemaId, SideEffect, SideEffects, Status, StorageProviderId, ThreadId, VecMaxLength, VoteKind, WorkerId } from './all';
+import type { BTreeMap, BTreeSet, Bytes, Option, Vec, bool, u16, u32, u64 } from '@polkadot/types';
+import type { Actor, ApplicationId, ApplicationIdToWorkerIdMap, BagId, CategoryId, ChannelId, Cid, ClassId, CuratorApplicationId, CuratorApplicationIdToCuratorIdMap, CuratorGroupId, CuratorId, CuratorOpeningId, DataObjectId, DistributionBucketFamilyId, DistributionBucketId, DynamicBagDeletionPrizeRecord, DynamicBagId, DynamicBagType, EntityController, EntityCreationVoucher, EntityId, FailedAt, LeadId, MemberId, MintBalanceOf, MintId, Nonce, OpeningId, PostId, PropertyId, ProposalId, ProposalStatus, RationaleText, SchemaId, SideEffect, SideEffects, Status, StorageBucketId, ThreadId, UploadParameters, VecMaxLength, VoteKind, Voucher, WorkerId } from './all';
 import type { BalanceStatus } from '@polkadot/types/interfaces/balances';
 import type { AuthorityId } from '@polkadot/types/interfaces/consensus';
 import type { AuthorityList } from '@polkadot/types/interfaces/grandpa';
@@ -243,74 +243,128 @@ declare module '@polkadot/api/types/events' {
       VotingEnded: AugmentedEvent<ApiType, []>;
       VotingStarted: AugmentedEvent<ApiType, []>;
     };
-    dataDirectory: {
+    distributionWorkingGroup: {
       /**
-       * Emits when the storage provider accepts a content.
+       * Emits on accepting application for the worker opening.
        * Params:
-       * - Id of the relationship.
-       * - Id of the storage provider.
+       * - Opening id
        **/
-      ContentAccepted: AugmentedEvent<ApiType, [ContentId, StorageProviderId]>;
+      AcceptedApplications: AugmentedEvent<ApiType, [OpeningId]>;
       /**
-       * Emits on adding of the content.
+       * Emits on terminating the application for the worker/lead opening.
        * Params:
-       * - Id of the relationship.
-       * - Id of the member.
+       * - Worker application id
        **/
-      ContentAdded: AugmentedEvent<ApiType, [ContentId, MemberId]>;
+      ApplicationTerminated: AugmentedEvent<ApiType, [ApplicationId]>;
       /**
-       * Emits when the storage provider rejects a content.
+       * Emits on withdrawing the application for the worker/lead opening.
        * Params:
-       * - Id of the relationship.
-       * - Id of the storage provider.
+       * - Worker application id
        **/
-      ContentRejected: AugmentedEvent<ApiType, [ContentId, StorageProviderId]>;
-    };
-    dataObjectStorageRegistry: {
+      ApplicationWithdrawn: AugmentedEvent<ApiType, [ApplicationId]>;
       /**
-       * Emits on adding of the data object storage relationship.
+       * Emits on adding the application for the worker opening.
        * Params:
-       * - Id of the relationship.
-       * - Id of the content.
-       * - Id of the storage provider.
+       * - Opening id
+       * - Application id
        **/
-      DataObjectStorageRelationshipAdded: AugmentedEvent<ApiType, [DataObjectStorageRelationshipId, ContentId, StorageProviderId]>;
+      AppliedOnOpening: AugmentedEvent<ApiType, [OpeningId, ApplicationId]>;
       /**
-       * Emits on adding of the data object storage relationship.
+       * Emits on beginning the application review for the worker/lead opening.
        * Params:
-       * - Id of the relationship.
-       * - Current state of the relationship (True=Active).
+       * - Opening id
        **/
-      DataObjectStorageRelationshipReadyUpdated: AugmentedEvent<ApiType, [DataObjectStorageRelationshipId, bool]>;
-    };
-    dataObjectTypeRegistry: {
+      BeganApplicationReview: AugmentedEvent<ApiType, [OpeningId]>;
+      /**
+       * Emits on setting the leader.
+       * Params:
+       * - Worker id.
+       **/
+      LeaderSet: AugmentedEvent<ApiType, [WorkerId]>;
       /**
-       * Emits on the data object type registration.
+       * Emits on un-setting the leader.
        * Params:
-       * - Id of the new data object type.
        **/
-      DataObjectTypeRegistered: AugmentedEvent<ApiType, [DataObjectTypeId]>;
+      LeaderUnset: AugmentedEvent<ApiType, []>;
       /**
-       * Emits on the data object type update.
+       * Emits on changing working group mint capacity.
        * Params:
-       * - Id of the updated data object type.
+       * - mint id.
+       * - new mint balance.
        **/
-      DataObjectTypeUpdated: AugmentedEvent<ApiType, [DataObjectTypeId]>;
-    };
-    discovery: {
+      MintCapacityChanged: AugmentedEvent<ApiType, [MintId, MintBalanceOf]>;
+      /**
+       * Emits on adding new worker opening.
+       * Params:
+       * - Opening id
+       **/
+      OpeningAdded: AugmentedEvent<ApiType, [OpeningId]>;
+      /**
+       * Emits on filling the worker opening.
+       * Params:
+       * - Worker opening id
+       * - Worker application id to the worker id dictionary
+       **/
+      OpeningFilled: AugmentedEvent<ApiType, [OpeningId, ApplicationIdToWorkerIdMap]>;
+      /**
+       * Emits on decreasing the worker/lead stake.
+       * Params:
+       * - worker/lead id.
+       **/
+      StakeDecreased: AugmentedEvent<ApiType, [WorkerId]>;
+      /**
+       * Emits on increasing the worker/lead stake.
+       * Params:
+       * - worker/lead id.
+       **/
+      StakeIncreased: AugmentedEvent<ApiType, [WorkerId]>;
+      /**
+       * Emits on slashing the worker/lead stake.
+       * Params:
+       * - worker/lead id.
+       **/
+      StakeSlashed: AugmentedEvent<ApiType, [WorkerId]>;
+      /**
+       * Emits on terminating the leader.
+       * Params:
+       * - leader worker id.
+       * - termination rationale text
+       **/
+      TerminatedLeader: AugmentedEvent<ApiType, [WorkerId, RationaleText]>;
+      /**
+       * Emits on terminating the worker.
+       * Params:
+       * - worker id.
+       * - termination rationale text
+       **/
+      TerminatedWorker: AugmentedEvent<ApiType, [WorkerId, RationaleText]>;
+      /**
+       * Emits on exiting the worker.
+       * Params:
+       * - worker id.
+       * - exit rationale text
+       **/
+      WorkerExited: AugmentedEvent<ApiType, [WorkerId, RationaleText]>;
+      /**
+       * Emits on updating the reward account of the worker.
+       * Params:
+       * - Member id of the worker.
+       * - Reward account id of the worker.
+       **/
+      WorkerRewardAccountUpdated: AugmentedEvent<ApiType, [WorkerId, AccountId]>;
       /**
-       * Emits on removing of the account info.
+       * Emits on updating the reward amount of the worker.
        * Params:
-       * - Id of the storage provider.
+       * - Id of the worker.
        **/
-      AccountInfoRemoved: AugmentedEvent<ApiType, [StorageProviderId]>;
+      WorkerRewardAmountUpdated: AugmentedEvent<ApiType, [WorkerId]>;
       /**
-       * Emits on updating of the account info.
+       * Emits on updating the role account of the worker.
        * Params:
-       * - Id of the storage provider.
-       * - Id of the IPNS.
+       * - Id of the worker.
+       * - Role account id of the worker.
        **/
-      AccountInfoUpdated: AugmentedEvent<ApiType, [StorageProviderId, IPNSIdentity]>;
+      WorkerRoleAccountUpdated: AugmentedEvent<ApiType, [WorkerId, AccountId]>;
     };
     forum: {
       /**
@@ -488,6 +542,293 @@ declare module '@polkadot/api/types/events' {
        **/
       Withdrawn: AugmentedEvent<ApiType, [AccountId, Balance]>;
     };
+    storage: {
+      /**
+       * Bag objects changed.
+       * Params
+       * - bag id
+       * - new total objects size
+       * - new total objects number
+       **/
+      BagObjectsChanged: AugmentedEvent<ApiType, [BagId, u64, u64]>;
+      /**
+       * Emits on changing the size-based pricing of new objects uploaded.
+       * Params
+       * - new data size fee
+       **/
+      DataObjectPerMegabyteFeeUpdated: AugmentedEvent<ApiType, [Balance]>;
+      /**
+       * Emits on data objects deletion from bags.
+       * Params
+       * - account ID for the deletion prize
+       * - bag ID
+       * - data object IDs
+       **/
+      DataObjectsDeleted: AugmentedEvent<ApiType, [AccountId, BagId, BTreeSet<DataObjectId>]>;
+      /**
+       * Emits on moving data objects between bags.
+       * Params
+       * - source bag ID
+       * - destination bag ID
+       * - data object IDs
+       **/
+      DataObjectsMoved: AugmentedEvent<ApiType, [BagId, BagId, BTreeSet<DataObjectId>]>;
+      /**
+       * Emits on uploading data objects.
+       * Params
+       * - data objects IDs
+       * - initial uploading parameters
+       **/
+      DataObjectsUploaded: AugmentedEvent<ApiType, [Vec<DataObjectId>, UploadParameters]>;
+      /**
+       * Emits on creating distribution bucket.
+       * Params
+       * - distribution bucket family ID
+       * - accepting new bags
+       * - distribution bucket ID
+       **/
+      DistributionBucketCreated: AugmentedEvent<ApiType, [DistributionBucketFamilyId, bool, DistributionBucketId]>;
+      /**
+       * Emits on deleting distribution bucket.
+       * Params
+       * - distribution bucket family ID
+       * - distribution bucket ID
+       **/
+      DistributionBucketDeleted: AugmentedEvent<ApiType, [DistributionBucketFamilyId, DistributionBucketId]>;
+      /**
+       * Emits on creating distribution bucket family.
+       * Params
+       * - distribution family bucket ID
+       **/
+      DistributionBucketFamilyCreated: AugmentedEvent<ApiType, [DistributionBucketFamilyId]>;
+      /**
+       * Emits on deleting distribution bucket family.
+       * Params
+       * - distribution family bucket ID
+       **/
+      DistributionBucketFamilyDeleted: AugmentedEvent<ApiType, [DistributionBucketFamilyId]>;
+      /**
+       * Emits on setting the metadata by a distribution bucket family.
+       * Params
+       * - distribution bucket family ID
+       * - metadata
+       **/
+      DistributionBucketFamilyMetadataSet: AugmentedEvent<ApiType, [DistributionBucketFamilyId, Bytes]>;
+      /**
+       * Emits on accepting a distribution bucket invitation for the operator.
+       * Params
+       * - worker ID
+       * - distribution bucket family ID
+       * - distribution bucket ID
+       **/
+      DistributionBucketInvitationAccepted: AugmentedEvent<ApiType, [WorkerId, DistributionBucketFamilyId, DistributionBucketId]>;
+      /**
+       * Emits on canceling a distribution bucket invitation for the operator.
+       * Params
+       * - distribution bucket family ID
+       * - distribution bucket ID
+       * - operator worker ID
+       **/
+      DistributionBucketInvitationCancelled: AugmentedEvent<ApiType, [DistributionBucketFamilyId, DistributionBucketId, WorkerId]>;
+      /**
+       * Emits on setting the metadata by a distribution bucket operator.
+       * Params
+       * - worker ID
+       * - distribution bucket family ID
+       * - distribution bucket ID
+       * - metadata
+       **/
+      DistributionBucketMetadataSet: AugmentedEvent<ApiType, [WorkerId, DistributionBucketFamilyId, DistributionBucketId, Bytes]>;
+      /**
+       * Emits on storage bucket mode update (distributing flag).
+       * Params
+       * - distribution bucket family ID
+       * - distribution bucket ID
+       * - distributing
+       **/
+      DistributionBucketModeUpdated: AugmentedEvent<ApiType, [DistributionBucketFamilyId, DistributionBucketId, bool]>;
+      /**
+       * Emits on creating a distribution bucket invitation for the operator.
+       * Params
+       * - distribution bucket family ID
+       * - distribution bucket ID
+       * - worker ID
+       **/
+      DistributionBucketOperatorInvited: AugmentedEvent<ApiType, [DistributionBucketFamilyId, DistributionBucketId, WorkerId]>;
+      /**
+       * Emits on the distribution bucket operator removal.
+       * Params
+       * - distribution bucket family ID
+       * - distribution bucket ID
+       * - distribution bucket operator ID
+       **/
+      DistributionBucketOperatorRemoved: AugmentedEvent<ApiType, [DistributionBucketFamilyId, DistributionBucketId, WorkerId]>;
+      /**
+       * Emits on changing the "Distribution buckets per bag" number limit.
+       * Params
+       * - new limit
+       **/
+      DistributionBucketsPerBagLimitUpdated: AugmentedEvent<ApiType, [u64]>;
+      /**
+       * Emits on storage bucket status update (accepting new bags).
+       * Params
+       * - distribution bucket family ID
+       * - distribution bucket ID
+       * - new status (accepting new bags)
+       **/
+      DistributionBucketStatusUpdated: AugmentedEvent<ApiType, [DistributionBucketFamilyId, DistributionBucketId, bool]>;
+      /**
+       * Emits on updating distribution buckets for bag.
+       * Params
+       * - bag ID
+       * - storage buckets to add ID collection
+       * - storage buckets to remove ID collection
+       **/
+      DistributionBucketsUpdatedForBag: AugmentedEvent<ApiType, [BagId, DistributionBucketFamilyId, BTreeSet<DistributionBucketId>, BTreeSet<DistributionBucketId>]>;
+      /**
+       * Emits on creating a dynamic bag.
+       * Params
+       * - dynamic bag ID
+       * - optional DynamicBagDeletionPrize instance
+       **/
+      DynamicBagCreated: AugmentedEvent<ApiType, [DynamicBagId, Option<DynamicBagDeletionPrizeRecord>]>;
+      /**
+       * Emits on deleting a dynamic bag.
+       * Params
+       * - account ID for the deletion prize
+       * - dynamic bag ID
+       **/
+      DynamicBagDeleted: AugmentedEvent<ApiType, [AccountId, DynamicBagId]>;
+      /**
+       * Emits on dynamic bag creation policy update (distribution bucket families).
+       * Params
+       * - dynamic bag type
+       * - families and bucket numbers
+       **/
+      FamiliesInDynamicBagCreationPolicyUpdated: AugmentedEvent<ApiType, [DynamicBagType, BTreeMap<DistributionBucketFamilyId, u32>]>;
+      /**
+       * Emits on updating the number of storage buckets in dynamic bag creation policy.
+       * Params
+       * - dynamic bag type
+       * - new number of storage buckets
+       **/
+      NumberOfStorageBucketsInDynamicBagCreationPolicyUpdated: AugmentedEvent<ApiType, [DynamicBagType, u64]>;
+      /**
+       * Emits on accepting pending data objects.
+       * Params
+       * - storage bucket ID
+       * - worker ID (storage provider ID)
+       * - bag ID
+       * - pending data objects
+       **/
+      PendingDataObjectsAccepted: AugmentedEvent<ApiType, [StorageBucketId, WorkerId, BagId, BTreeSet<DataObjectId>]>;
+      /**
+       * Emits on creating the storage bucket.
+       * Params
+       * - storage bucket ID
+       * - invited worker
+       * - flag "accepting_new_bags"
+       * - size limit for voucher,
+       * - objects limit for voucher,
+       **/
+      StorageBucketCreated: AugmentedEvent<ApiType, [StorageBucketId, Option<WorkerId>, bool, u64, u64]>;
+      /**
+       * Emits on storage bucket deleting.
+       * Params
+       * - storage bucket ID
+       **/
+      StorageBucketDeleted: AugmentedEvent<ApiType, [StorageBucketId]>;
+      /**
+       * Emits on accepting the storage bucket invitation.
+       * Params
+       * - storage bucket ID
+       * - invited worker ID
+       **/
+      StorageBucketInvitationAccepted: AugmentedEvent<ApiType, [StorageBucketId, WorkerId]>;
+      /**
+       * Emits on cancelling the storage bucket invitation.
+       * Params
+       * - storage bucket ID
+       **/
+      StorageBucketInvitationCancelled: AugmentedEvent<ApiType, [StorageBucketId]>;
+      /**
+       * Emits on the storage bucket operator invitation.
+       * Params
+       * - storage bucket ID
+       * - operator worker ID (storage provider ID)
+       **/
+      StorageBucketOperatorInvited: AugmentedEvent<ApiType, [StorageBucketId, WorkerId]>;
+      /**
+       * Emits on the storage bucket operator removal.
+       * Params
+       * - storage bucket ID
+       **/
+      StorageBucketOperatorRemoved: AugmentedEvent<ApiType, [StorageBucketId]>;
+      /**
+       * Emits on changing the "Storage buckets per bag" number limit.
+       * Params
+       * - new limit
+       **/
+      StorageBucketsPerBagLimitUpdated: AugmentedEvent<ApiType, [u64]>;
+      /**
+       * Emits on storage bucket status update.
+       * Params
+       * - storage bucket ID
+       * - new status
+       **/
+      StorageBucketStatusUpdated: AugmentedEvent<ApiType, [StorageBucketId, bool]>;
+      /**
+       * Emits on updating storage buckets for bag.
+       * Params
+       * - bag ID
+       * - storage buckets to add ID collection
+       * - storage buckets to remove ID collection
+       **/
+      StorageBucketsUpdatedForBag: AugmentedEvent<ApiType, [BagId, BTreeSet<StorageBucketId>, BTreeSet<StorageBucketId>]>;
+      /**
+       * Emits on changing the "Storage buckets voucher max limits".
+       * Params
+       * - new objects size limit
+       * - new objects number limit
+       **/
+      StorageBucketsVoucherMaxLimitsUpdated: AugmentedEvent<ApiType, [u64, u64]>;
+      /**
+       * Emits on setting the storage bucket voucher limits.
+       * Params
+       * - storage bucket ID
+       * - new total objects size limit
+       * - new total objects number limit
+       **/
+      StorageBucketVoucherLimitsSet: AugmentedEvent<ApiType, [StorageBucketId, u64, u64]>;
+      /**
+       * Emits on setting the storage operator metadata.
+       * Params
+       * - storage bucket ID
+       * - invited worker ID
+       * - metadata
+       **/
+      StorageOperatorMetadataSet: AugmentedEvent<ApiType, [StorageBucketId, WorkerId, Bytes]>;
+      /**
+       * Emits on updating the blacklist with data hashes.
+       * Params
+       * - hashes to remove from the blacklist
+       * - hashes to add to the blacklist
+       **/
+      UpdateBlacklist: AugmentedEvent<ApiType, [BTreeSet<Cid>, BTreeSet<Cid>]>;
+      /**
+       * Emits on changing the size-based pricing of new objects uploaded.
+       * Params
+       * - new status
+       **/
+      UploadingBlockStatusUpdated: AugmentedEvent<ApiType, [bool]>;
+      /**
+       * Emits on changing the voucher for a storage bucket.
+       * Params
+       * - storage bucket ID
+       * - new voucher
+       **/
+      VoucherChanged: AugmentedEvent<ApiType, [StorageBucketId, Voucher]>;
+    };
     storageWorkingGroup: {
       /**
        * Emits on accepting application for the worker opening.

+ 105 - 32
types/augment-codec/augment-api-query.ts

@@ -3,7 +3,7 @@
 
 import type { Bytes, Option, Vec, bool, u32, u64 } from '@polkadot/types';
 import type { AnyNumber, ITuple, Observable } from '@polkadot/types/types';
-import type { Application, ApplicationId, ApplicationOf, Category, CategoryId, Channel, ChannelId, Class, ClassId, ClassOf, ClassPermissionsType, ContentId, Credential, Curator, CuratorApplication, CuratorApplicationId, CuratorGroup, CuratorGroupId, CuratorId, CuratorOpening, CuratorOpeningId, DataObject, DataObjectStorageRelationship, DataObjectStorageRelationshipId, DataObjectType, DataObjectTypeId, DiscussionPost, DiscussionThread, ElectionStage, ElectionStake, Entity, EntityController, EntityCreationVoucher, EntityId, EntityOf, HiringApplicationId, InputValidationLengthConstraint, Lead, LeadId, MemberId, Membership, MemoText, Mint, MintId, Opening, OpeningId, OpeningOf, PaidMembershipTerms, PaidTermId, Post, PostId, Principal, PrincipalId, PropertyId, ProposalDetailsOf, ProposalId, ProposalOf, Recipient, RecipientId, RewardRelationship, RewardRelationshipId, SealedVote, Seats, ServiceProviderRecord, Stake, StakeId, StorageProviderId, Thread, ThreadCounter, ThreadId, TransferableStake, Url, VoteKind, WorkerId, WorkerOf, WorkingGroupUnstaker } from './all';
+import type { Application, ApplicationId, ApplicationOf, Bag, BagId, Category, CategoryId, Channel, ChannelId, Cid, Class, ClassId, ClassOf, ClassPermissionsType, Credential, Curator, CuratorApplication, CuratorApplicationId, CuratorGroup, CuratorGroupId, CuratorId, CuratorOpening, CuratorOpeningId, DataObject, DataObjectId, DiscussionPost, DiscussionThread, DistributionBucketFamily, DistributionBucketFamilyId, DistributionBucketId, DynamicBagCreationPolicy, DynamicBagType, ElectionStage, ElectionStake, Entity, EntityController, EntityCreationVoucher, EntityId, EntityOf, HiringApplicationId, InputValidationLengthConstraint, Lead, LeadId, MemberId, Membership, MemoText, Mint, MintId, Opening, OpeningId, OpeningOf, PaidMembershipTerms, PaidTermId, Post, PostId, Principal, PrincipalId, PropertyId, ProposalDetailsOf, ProposalId, ProposalOf, Recipient, RecipientId, RewardRelationship, RewardRelationshipId, SealedVote, Seats, Stake, StakeId, StorageBucket, StorageBucketId, Thread, ThreadCounter, ThreadId, TransferableStake, VoteKind, WorkerId, WorkerOf, WorkingGroupUnstaker } from './all';
 import type { UncleEntryItem } from '@polkadot/types/interfaces/authorship';
 import type { BabeAuthorityWeight, MaybeRandomness, NextConfigDescriptor, Randomness } from '@polkadot/types/interfaces/babe';
 import type { AccountData, BalanceLock } from '@polkadot/types/interfaces/balances';
@@ -331,61 +331,60 @@ declare module '@polkadot/api/types/storage' {
       votes: AugmentedQuery<ApiType, (arg: Hash | string | Uint8Array) => Observable<SealedVote>, [Hash]>;
       votingPeriod: AugmentedQuery<ApiType, () => Observable<BlockNumber>, []>;
     };
-    dataDirectory: {
+    distributionWorkingGroup: {
       /**
-       * Maps data objects by their content id.
+       * Count of active workers.
        **/
-      dataObjectByContentId: AugmentedQuery<ApiType, (arg: ContentId | string | Uint8Array) => Observable<Option<DataObject>>, [ContentId]>;
+      activeWorkerCount: AugmentedQuery<ApiType, () => Observable<u32>, []>;
       /**
-       * List of ids known to the frame_system.
+       * Maps identifier to worker application on opening.
        **/
-      knownContentIds: AugmentedQuery<ApiType, () => Observable<Vec<ContentId>>, []>;
-    };
-    dataObjectStorageRegistry: {
+      applicationById: AugmentedQuery<ApiType, (arg: ApplicationId | AnyNumber | Uint8Array) => Observable<ApplicationOf>, [ApplicationId]>;
       /**
-       * Defines first relationship id.
+       * The current lead.
        **/
-      firstRelationshipId: AugmentedQuery<ApiType, () => Observable<DataObjectStorageRelationshipId>, []>;
+      currentLead: AugmentedQuery<ApiType, () => Observable<Option<WorkerId>>, []>;
       /**
-       * Defines next relationship id.
+       * Map member id by hiring application id.
+       * Required by StakingEventsHandler callback call to refund the balance on unstaking.
        **/
-      nextRelationshipId: AugmentedQuery<ApiType, () => Observable<DataObjectStorageRelationshipId>, []>;
+      memberIdByHiringApplicationId: AugmentedQuery<ApiType, (arg: HiringApplicationId | AnyNumber | Uint8Array) => Observable<MemberId>, [HiringApplicationId]>;
       /**
-       * Mapping of Data object types
+       * The mint currently funding the rewards for this module.
        **/
-      relationships: AugmentedQuery<ApiType, (arg: DataObjectStorageRelationshipId | AnyNumber | Uint8Array) => Observable<Option<DataObjectStorageRelationship>>, [DataObjectStorageRelationshipId]>;
+      mint: AugmentedQuery<ApiType, () => Observable<MintId>, []>;
       /**
-       * Keeps a list of storage relationships per content id.
+       * Next identifier value for new worker application.
        **/
-      relationshipsByContentId: AugmentedQuery<ApiType, (arg: ContentId | string | Uint8Array) => Observable<Vec<DataObjectStorageRelationshipId>>, [ContentId]>;
-    };
-    dataObjectTypeRegistry: {
+      nextApplicationId: AugmentedQuery<ApiType, () => Observable<ApplicationId>, []>;
       /**
-       * Mapping of Data object types.
+       * Next identifier value for new worker opening.
        **/
-      dataObjectTypes: AugmentedQuery<ApiType, (arg: DataObjectTypeId | AnyNumber | Uint8Array) => Observable<Option<DataObjectType>>, [DataObjectTypeId]>;
+      nextOpeningId: AugmentedQuery<ApiType, () => Observable<OpeningId>, []>;
       /**
-       * Data object type ids should start at this value.
+       * Next identifier for new worker.
        **/
-      firstDataObjectTypeId: AugmentedQuery<ApiType, () => Observable<DataObjectTypeId>, []>;
+      nextWorkerId: AugmentedQuery<ApiType, () => Observable<WorkerId>, []>;
       /**
-       * Provides id counter for the data object types.
+       * Maps identifier to worker opening.
        **/
-      nextDataObjectTypeId: AugmentedQuery<ApiType, () => Observable<DataObjectTypeId>, []>;
-    };
-    discovery: {
+      openingById: AugmentedQuery<ApiType, (arg: OpeningId | AnyNumber | Uint8Array) => Observable<OpeningOf>, [OpeningId]>;
       /**
-       * Mapping of service providers' storage provider id to their ServiceProviderRecord
+       * Opening human readable text length limits
        **/
-      accountInfoByStorageProviderId: AugmentedQuery<ApiType, (arg: StorageProviderId | AnyNumber | Uint8Array) => Observable<ServiceProviderRecord>, [StorageProviderId]>;
+      openingHumanReadableText: AugmentedQuery<ApiType, () => Observable<InputValidationLengthConstraint>, []>;
       /**
-       * Bootstrap endpoints maintained by root
+       * Worker application human readable text length limits
        **/
-      bootstrapEndpoints: AugmentedQuery<ApiType, () => Observable<Vec<Url>>, []>;
+      workerApplicationHumanReadableText: AugmentedQuery<ApiType, () => Observable<InputValidationLengthConstraint>, []>;
       /**
-       * Lifetime of an ServiceProviderRecord record in AccountInfoByAccountId map
+       * Maps identifier to corresponding worker.
        **/
-      defaultLifetime: AugmentedQuery<ApiType, () => Observable<BlockNumber>, []>;
+      workerById: AugmentedQuery<ApiType, (arg: WorkerId | AnyNumber | Uint8Array) => Observable<WorkerOf>, [WorkerId]>;
+      /**
+       * Worker exit rationale text length limits.
+       **/
+      workerExitRationaleText: AugmentedQuery<ApiType, () => Observable<InputValidationLengthConstraint>, []>;
     };
     forum: {
       /**
@@ -1012,6 +1011,80 @@ declare module '@polkadot/api/types/storage' {
        **/
       validatorSlashInEra: AugmentedQueryDoubleMap<ApiType, (key1: EraIndex | AnyNumber | Uint8Array, key2: AccountId | string | Uint8Array) => Observable<Option<ITuple<[Perbill, BalanceOf]>>>, [EraIndex, AccountId]>;
     };
+    storage: {
+      /**
+       * Bags storage map.
+       **/
+      bags: AugmentedQuery<ApiType, (arg: BagId | { Static: any } | { Dynamic: any } | string | Uint8Array) => Observable<Bag>, [BagId]>;
+      /**
+       * Blacklisted data object hashes.
+       **/
+      blacklist: AugmentedQuery<ApiType, (arg: Cid | string | Uint8Array) => Observable<ITuple<[]>>, [Cid]>;
+      /**
+       * Blacklist collection counter.
+       **/
+      currentBlacklistSize: AugmentedQuery<ApiType, () => Observable<u64>, []>;
+      /**
+       * Size based pricing of new objects uploaded.
+       **/
+      dataObjectPerMegabyteFee: AugmentedQuery<ApiType, () => Observable<BalanceOf>, []>;
+      /**
+       * 'Data objects for bags' storage double map.
+       **/
+      dataObjectsById: AugmentedQueryDoubleMap<ApiType, (key1: BagId | { Static: any } | { Dynamic: any } | string | Uint8Array, key2: DataObjectId | AnyNumber | Uint8Array) => Observable<DataObject>, [BagId, DataObjectId]>;
+      /**
+       * Distribution bucket families.
+       **/
+      distributionBucketFamilyById: AugmentedQuery<ApiType, (arg: DistributionBucketFamilyId | AnyNumber | Uint8Array) => Observable<DistributionBucketFamily>, [DistributionBucketFamilyId]>;
+      /**
+       * Total number of distribution bucket families in the system.
+       **/
+      distributionBucketFamilyNumber: AugmentedQuery<ApiType, () => Observable<u64>, []>;
+      /**
+       * "Distribution buckets per bag" number limit.
+       **/
+      distributionBucketsPerBagLimit: AugmentedQuery<ApiType, () => Observable<u64>, []>;
+      /**
+       * DynamicBagCreationPolicy by bag type storage map.
+       **/
+      dynamicBagCreationPolicies: AugmentedQuery<ApiType, (arg: DynamicBagType | 'Member' | 'Channel' | number | Uint8Array) => Observable<DynamicBagCreationPolicy>, [DynamicBagType]>;
+      /**
+       * Data object id counter. Starts at zero.
+       **/
+      nextDataObjectId: AugmentedQuery<ApiType, () => Observable<DataObjectId>, []>;
+      /**
+       * Distribution bucket family id counter. Starts at zero.
+       **/
+      nextDistributionBucketFamilyId: AugmentedQuery<ApiType, () => Observable<DistributionBucketFamilyId>, []>;
+      /**
+       * Distribution bucket id counter. Starts at zero.
+       **/
+      nextDistributionBucketId: AugmentedQuery<ApiType, () => Observable<DistributionBucketId>, []>;
+      /**
+       * Storage bucket id counter. Starts at zero.
+       **/
+      nextStorageBucketId: AugmentedQuery<ApiType, () => Observable<StorageBucketId>, []>;
+      /**
+       * Storage buckets.
+       **/
+      storageBucketById: AugmentedQuery<ApiType, (arg: StorageBucketId | AnyNumber | Uint8Array) => Observable<StorageBucket>, [StorageBucketId]>;
+      /**
+       * "Storage buckets per bag" number limit.
+       **/
+      storageBucketsPerBagLimit: AugmentedQuery<ApiType, () => Observable<u64>, []>;
+      /**
+       * Defines whether all new uploads blocked
+       **/
+      uploadingBlocked: AugmentedQuery<ApiType, () => Observable<bool>, []>;
+      /**
+       * "Max objects number for a storage bucket voucher" number limit.
+       **/
+      voucherMaxObjectsNumberLimit: AugmentedQuery<ApiType, () => Observable<u64>, []>;
+      /**
+       * "Max objects size for a storage bucket voucher" number limit.
+       **/
+      voucherMaxObjectsSizeLimit: AugmentedQuery<ApiType, () => Observable<u64>, []>;
+    };
     storageWorkingGroup: {
       /**
        * Count of active workers.

+ 183 - 52
types/augment-codec/augment-api-tx.ts

@@ -3,7 +3,7 @@
 
 import type { BTreeMap, BTreeSet, Bytes, Compact, Option, Vec, bool, u16, u32, u64 } from '@polkadot/types';
 import type { AnyNumber, ITuple } from '@polkadot/types/types';
-import type { ActivateOpeningAt, Actor, AddOpeningParameters, ApplicationId, ApplicationIdSet, BalanceOfMint, CategoryId, ChannelContentType, ChannelCurationStatus, ChannelId, ChannelPublicationStatus, ClassId, ClassPermissions, ClassPermissionsType, ClassPropertyValue, ContentId, Credential, CredentialSet, CurationActor, CuratorApplicationId, CuratorApplicationIdSet, CuratorGroupId, CuratorId, CuratorOpeningId, DataObjectStorageRelationshipId, DataObjectType, DataObjectTypeId, DataObjectsMap, ElectionParameters, EntityController, EntityId, EntityPermissions, FillOpeningParameters, InputPropertyValue, InputValue, MemberId, MemoText, Nonce, OpeningId, OpeningPolicyCommitment, OpeningType, Operation, OperationType, OptionalText, PaidTermId, PostId, Property, PropertyId, ProposalId, ReferenceConstraint, RewardPolicy, SchemaId, StorageProviderId, TerminateRoleParameters, ThreadId, Url, VecMaxLength, VoteKind, WorkerId, WorkingGroup } from './all';
+import type { ActivateOpeningAt, Actor, AddOpeningParameters, ApplicationId, ApplicationIdSet, BagId, BalanceOfMint, CategoryId, ChannelContentType, ChannelCurationStatus, ChannelId, ChannelPublicationStatus, Cid, ClassId, ClassPermissions, ClassPermissionsType, ClassPropertyValue, Credential, CredentialSet, CurationActor, CuratorApplicationId, CuratorApplicationIdSet, CuratorGroupId, CuratorId, CuratorOpeningId, DataObjectId, DistributionBucketFamilyId, DistributionBucketId, DynamicBagDeletionPrize, DynamicBagId, DynamicBagType, ElectionParameters, EntityController, EntityId, EntityPermissions, FillOpeningParameters, InputPropertyValue, InputValue, MemberId, MemoText, Nonce, OpeningId, OpeningPolicyCommitment, OpeningType, Operation, OperationType, OptionalText, PaidTermId, PostId, Property, PropertyId, ProposalId, ReferenceConstraint, RewardPolicy, SchemaId, StorageBucketId, TerminateRoleParameters, ThreadId, UploadParameters, VecMaxLength, VoteKind, WorkerId, WorkingGroup } from './all';
 import type { BabeEquivocationProof } from '@polkadot/types/interfaces/babe';
 import type { Extrinsic, Signature } from '@polkadot/types/interfaces/extrinsics';
 import type { GrandpaEquivocationProof, KeyOwnerProof } from '@polkadot/types/interfaces/grandpa';
@@ -430,89 +430,82 @@ declare module '@polkadot/api/types/submittable' {
       setStageVoting: AugmentedSubmittable<(endsAt: BlockNumber | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [BlockNumber]>;
       vote: AugmentedSubmittable<(commitment: Hash | string | Uint8Array, stake: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [Hash, BalanceOf]>;
     };
-    dataDirectory: {
+    distributionWorkingGroup: {
       /**
-       * Storage provider accepts a content. Requires signed storage provider account and its id.
-       * The LiaisonJudgement can be updated, but only by the liaison.
+       * Begin accepting worker applications to an opening that is active.
+       * Require signed leader origin or the root (to accept applications for the leader position).
        **/
-      acceptContent: AugmentedSubmittable<(storageProviderId: StorageProviderId | AnyNumber | Uint8Array, contentId: ContentId | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageProviderId, ContentId]>;
+      acceptApplications: AugmentedSubmittable<(openingId: OpeningId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [OpeningId]>;
       /**
-       * Adds the content to the frame_system. Member id should match its origin. The created DataObject
-       * awaits liaison to accept or reject it.
+       * Add an opening for a worker role.
+       * Require signed leader origin or the root (to add opening for the leader position).
        **/
-      addContent: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, contentId: ContentId | string | Uint8Array, typeId: DataObjectTypeId | AnyNumber | Uint8Array, size: u64 | AnyNumber | Uint8Array, ipfsContentId: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, ContentId, DataObjectTypeId, u64, Bytes]>;
+      addOpening: AugmentedSubmittable<(activateAt: ActivateOpeningAt | { CurrentBlock: any } | { ExactBlock: any } | string | Uint8Array, commitment: OpeningPolicyCommitment | { application_rationing_policy?: any; max_review_period_length?: any; application_staking_policy?: any; role_staking_policy?: any; role_slashing_terms?: any; fill_opening_successful_applicant_application_stake_unstaking_period?: any; fill_opening_failed_applicant_application_stake_unstaking_period?: any; fill_opening_failed_applicant_role_stake_unstaking_period?: any; terminate_curator_application_stake_unstaking_period?: any; terminate_curator_role_stake_unstaking_period?: any; exit_curator_role_application_stake_unstaking_period?: any; exit_curator_role_stake_unstaking_period?: any } | string | Uint8Array, humanReadableText: Bytes | string | Uint8Array, openingType: OpeningType | 'Leader' | 'Worker' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [ActivateOpeningAt, OpeningPolicyCommitment, Bytes, OpeningType]>;
       /**
-       * Injects a set of data objects and their corresponding content id into the directory.
-       * The operation is "silent" - no events will be emitted as objects are added.
-       * The number of objects that can be added per call is limited to prevent the dispatch
-       * from causing the block production to fail if it takes too much time to process.
-       * Existing data objects will be overwritten.
+       * Apply on a worker opening.
        **/
-      injectDataObjects: AugmentedSubmittable<(objects: DataObjectsMap) => SubmittableExtrinsic<ApiType>, [DataObjectsMap]>;
+      applyOnOpening: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, openingId: OpeningId | AnyNumber | Uint8Array, roleAccountId: AccountId | string | Uint8Array, optRoleStakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, optApplicationStakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, humanReadableText: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, OpeningId, AccountId, Option<BalanceOf>, Option<BalanceOf>, Bytes]>;
       /**
-       * Storage provider rejects a content. Requires signed storage provider account and its id.
-       * The LiaisonJudgement can be updated, but only by the liaison.
+       * Begin reviewing, and therefore not accepting new applications.
+       * Require signed leader origin or the root (to begin review applications for the leader position).
        **/
-      rejectContent: AugmentedSubmittable<(storageProviderId: StorageProviderId | AnyNumber | Uint8Array, contentId: ContentId | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageProviderId, ContentId]>;
+      beginApplicantReview: AugmentedSubmittable<(openingId: OpeningId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [OpeningId]>;
       /**
-       * Removes the content id from the list of known content ids. Requires root privileges.
+       * Decreases the worker/lead stake and returns the remainder to the worker role_account_id.
+       * Can be decreased to zero, no actions on zero stake.
+       * Require signed leader origin or the root (to decrease the leader stake).
        **/
-      removeKnownContentId: AugmentedSubmittable<(contentId: ContentId | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentId]>;
-    };
-    dataObjectStorageRegistry: {
+      decreaseStake: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, balance: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOf]>;
       /**
-       * Add storage provider-to-content relationship. The storage provider should be registered
-       * in the storage working group.
+       * Fill opening for worker/lead.
+       * Require signed leader origin or the root (to fill opening for the leader position).
        **/
-      addRelationship: AugmentedSubmittable<(storageProviderId: StorageProviderId | AnyNumber | Uint8Array, cid: ContentId | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageProviderId, ContentId]>;
+      fillOpening: AugmentedSubmittable<(openingId: OpeningId | AnyNumber | Uint8Array, successfulApplicationIds: ApplicationIdSet, rewardPolicy: Option<RewardPolicy> | null | object | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [OpeningId, ApplicationIdSet, Option<RewardPolicy>]>;
       /**
-       * Activates storage provider-to-content relationship. The storage provider should be registered
-       * in the storage working group. A storage provider may flip their own ready state, but nobody else.
+       * Increases the worker/lead stake, demands a worker origin. Transfers tokens from the worker
+       * role_account_id to the stake. No limits on the stake.
        **/
-      setRelationshipReady: AugmentedSubmittable<(storageProviderId: StorageProviderId | AnyNumber | Uint8Array, id: DataObjectStorageRelationshipId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageProviderId, DataObjectStorageRelationshipId]>;
+      increaseStake: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, balance: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOf]>;
       /**
-       * Deactivates storage provider-to-content relationship. The storage provider should be registered
-       * in the storage working group. A storage provider may flip their own ready state, but nobody else.
+       * Leave the role by the active worker.
        **/
-      unsetRelationshipReady: AugmentedSubmittable<(storageProviderId: StorageProviderId | AnyNumber | Uint8Array, id: DataObjectStorageRelationshipId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageProviderId, DataObjectStorageRelationshipId]>;
-    };
-    dataObjectTypeRegistry: {
+      leaveRole: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, rationaleText: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, Bytes]>;
       /**
-       * Activates existing data object type. Requires leader privileges.
+       * Sets the capacity to enable working group budget. Requires root origin.
        **/
-      activateDataObjectType: AugmentedSubmittable<(id: DataObjectTypeId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [DataObjectTypeId]>;
+      setMintCapacity: AugmentedSubmittable<(newCapacity: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [BalanceOf]>;
       /**
-       * Deactivates existing data object type. Requires leader privileges.
+       * Slashes the worker stake, demands a leader origin. No limits, no actions on zero stake.
+       * If slashing balance greater than the existing stake - stake is slashed to zero.
+       * Require signed leader origin or the root (to slash the leader stake).
        **/
-      deactivateDataObjectType: AugmentedSubmittable<(id: DataObjectTypeId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [DataObjectTypeId]>;
+      slashStake: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, balance: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOf]>;
       /**
-       * Registers the new data object type. Requires leader privileges.
+       * Terminate the worker application. Can be done by the lead only.
        **/
-      registerDataObjectType: AugmentedSubmittable<(dataObjectType: DataObjectType | { description?: any; active?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [DataObjectType]>;
+      terminateApplication: AugmentedSubmittable<(applicationId: ApplicationId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ApplicationId]>;
       /**
-       * Updates existing data object type. Requires leader privileges.
+       * Terminate the active worker by the lead.
+       * Require signed leader origin or the root (to terminate the leader role).
        **/
-      updateDataObjectType: AugmentedSubmittable<(id: DataObjectTypeId | AnyNumber | Uint8Array, dataObjectType: DataObjectType | { description?: any; active?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [DataObjectTypeId, DataObjectType]>;
-    };
-    discovery: {
+      terminateRole: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, rationaleText: Bytes | string | Uint8Array, slashStake: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, Bytes, bool]>;
       /**
-       * Sets bootstrap endpoints for the Colossus. Requires root privileges.
+       * Update the reward account associated with a set reward relationship for the active worker.
        **/
-      setBootstrapEndpoints: AugmentedSubmittable<(endpoints: Vec<Url> | (Url | string)[]) => SubmittableExtrinsic<ApiType>, [Vec<Url>]>;
+      updateRewardAccount: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, newRewardAccountId: AccountId | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, AccountId]>;
       /**
-       * Sets default lifetime for storage providers accounts info. Requires root privileges.
+       * Update the reward amount associated with a set reward relationship for the active worker.
+       * Require signed leader origin or the root (to update leader reward amount).
        **/
-      setDefaultLifetime: AugmentedSubmittable<(lifetime: BlockNumber | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [BlockNumber]>;
+      updateRewardAmount: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, newAmount: BalanceOfMint | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOfMint]>;
       /**
-       * Creates the ServiceProviderRecord to save an IPNS identity for the storage provider.
-       * Requires signed storage provider credentials.
+       * Update the associated role account of the active worker/lead.
        **/
-      setIpnsId: AugmentedSubmittable<(storageProviderId: StorageProviderId | AnyNumber | Uint8Array, id: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageProviderId, Bytes]>;
+      updateRoleAccount: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, newRoleAccountId: AccountId | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, AccountId]>;
       /**
-       * Deletes the ServiceProviderRecord with the IPNS identity for the storage provider.
-       * Requires signed storage provider credentials.
+       * Withdraw the worker application. Can be done by the worker itself only.
        **/
-      unsetIpnsId: AugmentedSubmittable<(storageProviderId: StorageProviderId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageProviderId]>;
+      withdrawApplication: AugmentedSubmittable<(applicationId: ApplicationId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ApplicationId]>;
     };
     finalityTracker: {
       /**
@@ -1244,6 +1237,144 @@ declare module '@polkadot/api/types/submittable' {
        **/
       withdrawUnbonded: AugmentedSubmittable<(numSlashingSpans: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
     };
+    storage: {
+      /**
+       * Accept pending invite.
+       **/
+      acceptDistributionBucketInvitation: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, distributionBucketId: DistributionBucketId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, DistributionBucketFamilyId, DistributionBucketId]>;
+      /**
+       * A storage provider signals that the data object was successfully uploaded to its storage.
+       **/
+      acceptPendingDataObjects: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, storageBucketId: StorageBucketId | AnyNumber | Uint8Array, bagId: BagId | { Static: any } | { Dynamic: any } | string | Uint8Array, dataObjects: BTreeSet<DataObjectId>) => SubmittableExtrinsic<ApiType>, [WorkerId, StorageBucketId, BagId, BTreeSet<DataObjectId>]>;
+      /**
+       * Accept the storage bucket invitation. An invitation must match the worker_id parameter.
+       **/
+      acceptStorageBucketInvitation: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, storageBucketId: StorageBucketId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, StorageBucketId]>;
+      /**
+       * Cancel pending invite. Must be pending.
+       **/
+      cancelDistributionBucketOperatorInvite: AugmentedSubmittable<(familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, distributionBucketId: DistributionBucketId | AnyNumber | Uint8Array, operatorWorkerId: WorkerId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [DistributionBucketFamilyId, DistributionBucketId, WorkerId]>;
+      /**
+       * Cancel pending storage bucket invite. An invitation must be pending.
+       **/
+      cancelStorageBucketOperatorInvite: AugmentedSubmittable<(storageBucketId: StorageBucketId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageBucketId]>;
+      /**
+       * Create a distribution bucket.
+       **/
+      createDistributionBucket: AugmentedSubmittable<(familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, acceptingNewBags: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [DistributionBucketFamilyId, bool]>;
+      /**
+       * Create a distribution bucket family.
+       **/
+      createDistributionBucketFamily: AugmentedSubmittable<() => SubmittableExtrinsic<ApiType>, []>;
+      /**
+       * Create storage bucket.
+       **/
+      createStorageBucket: AugmentedSubmittable<(inviteWorker: Option<WorkerId> | null | object | string | Uint8Array, acceptingNewBags: bool | boolean | Uint8Array, sizeLimit: u64 | AnyNumber | Uint8Array, objectsLimit: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [Option<WorkerId>, bool, u64, u64]>;
+      /**
+       * Delete distribution bucket. Must be empty.
+       **/
+      deleteDistributionBucket: AugmentedSubmittable<(familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, distributionBucketId: DistributionBucketId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [DistributionBucketFamilyId, DistributionBucketId]>;
+      /**
+       * Deletes a distribution bucket family.
+       **/
+      deleteDistributionBucketFamily: AugmentedSubmittable<(familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [DistributionBucketFamilyId]>;
+      /**
+       * Delete storage bucket. Must be empty. Storage operator must be missing.
+       **/
+      deleteStorageBucket: AugmentedSubmittable<(storageBucketId: StorageBucketId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageBucketId]>;
+      /**
+       * Invite an operator. Must be missing.
+       **/
+      inviteDistributionBucketOperator: AugmentedSubmittable<(familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, distributionBucketId: DistributionBucketId | AnyNumber | Uint8Array, operatorWorkerId: WorkerId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [DistributionBucketFamilyId, DistributionBucketId, WorkerId]>;
+      /**
+       * Invite storage bucket operator. Must be missing.
+       **/
+      inviteStorageBucketOperator: AugmentedSubmittable<(storageBucketId: StorageBucketId | AnyNumber | Uint8Array, operatorId: WorkerId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageBucketId, WorkerId]>;
+      /**
+       * Removes distribution bucket operator.
+       **/
+      removeDistributionBucketOperator: AugmentedSubmittable<(familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, distributionBucketId: DistributionBucketId | AnyNumber | Uint8Array, operatorWorkerId: WorkerId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [DistributionBucketFamilyId, DistributionBucketId, WorkerId]>;
+      /**
+       * Removes storage bucket operator.
+       **/
+      removeStorageBucketOperator: AugmentedSubmittable<(storageBucketId: StorageBucketId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageBucketId]>;
+      /**
+       * Set distribution bucket family metadata.
+       **/
+      setDistributionBucketFamilyMetadata: AugmentedSubmittable<(familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, metadata: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [DistributionBucketFamilyId, Bytes]>;
+      /**
+       * Set distribution operator metadata for the distribution bucket.
+       **/
+      setDistributionOperatorMetadata: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, distributionBucketId: DistributionBucketId | AnyNumber | Uint8Array, metadata: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, DistributionBucketFamilyId, DistributionBucketId, Bytes]>;
+      /**
+       * Sets storage bucket voucher limits.
+       **/
+      setStorageBucketVoucherLimits: AugmentedSubmittable<(storageBucketId: StorageBucketId | AnyNumber | Uint8Array, newObjectsSizeLimit: u64 | AnyNumber | Uint8Array, newObjectsNumberLimit: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageBucketId, u64, u64]>;
+      /**
+       * Sets storage operator metadata (eg.: storage node URL).
+       **/
+      setStorageOperatorMetadata: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, storageBucketId: StorageBucketId | AnyNumber | Uint8Array, metadata: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, StorageBucketId, Bytes]>;
+      /**
+       * Create a dynamic bag. Development mode.
+       **/
+      sudoCreateDynamicBag: AugmentedSubmittable<(bagId: DynamicBagId | { Member: any } | { Channel: any } | string | Uint8Array, deletionPrize: Option<DynamicBagDeletionPrize> | null | object | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [DynamicBagId, Option<DynamicBagDeletionPrize>]>;
+      /**
+       * Upload new data objects. Development mode.
+       **/
+      sudoUploadDataObjects: AugmentedSubmittable<(params: UploadParameters | { authenticationKey?: any; bagId?: any; objectCreationList?: any; deletionPrizeSourceAccountId?: any; expectedDataSizeFee?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [UploadParameters]>;
+      /**
+       * Add and remove hashes to the current blacklist.
+       **/
+      updateBlacklist: AugmentedSubmittable<(removeHashes: BTreeSet<Cid>, addHashes: BTreeSet<Cid>) => SubmittableExtrinsic<ApiType>, [BTreeSet<Cid>, BTreeSet<Cid>]>;
+      /**
+       * Updates size-based pricing of new objects uploaded.
+       **/
+      updateDataSizeFee: AugmentedSubmittable<(newDataSizeFee: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [BalanceOf]>;
+      /**
+       * Updates 'distributing' flag for the distributing flag.
+       **/
+      updateDistributionBucketMode: AugmentedSubmittable<(familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, distributionBucketId: DistributionBucketId | AnyNumber | Uint8Array, distributing: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [DistributionBucketFamilyId, DistributionBucketId, bool]>;
+      /**
+       * Updates a distribution bucket 'accepts new bags' flag.
+       **/
+      updateDistributionBucketStatus: AugmentedSubmittable<(familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, distributionBucketId: DistributionBucketId | AnyNumber | Uint8Array, acceptingNewBags: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [DistributionBucketFamilyId, DistributionBucketId, bool]>;
+      /**
+       * Updates distribution buckets for a bag.
+       **/
+      updateDistributionBucketsForBag: AugmentedSubmittable<(bagId: BagId | { Static: any } | { Dynamic: any } | string | Uint8Array, familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, addBuckets: BTreeSet<DistributionBucketId>, removeBuckets: BTreeSet<DistributionBucketId>) => SubmittableExtrinsic<ApiType>, [BagId, DistributionBucketFamilyId, BTreeSet<DistributionBucketId>, BTreeSet<DistributionBucketId>]>;
+      /**
+       * Updates "Distribution buckets per bag" number limit.
+       **/
+      updateDistributionBucketsPerBagLimit: AugmentedSubmittable<(newLimit: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u64]>;
+      /**
+       * Update number of distributed buckets used in given dynamic bag creation policy.
+       **/
+      updateFamiliesInDynamicBagCreationPolicy: AugmentedSubmittable<(dynamicBagType: DynamicBagType | 'Member' | 'Channel' | number | Uint8Array, families: BTreeMap<DistributionBucketFamilyId, u32>) => SubmittableExtrinsic<ApiType>, [DynamicBagType, BTreeMap<DistributionBucketFamilyId, u32>]>;
+      /**
+       * Update number of storage buckets used in given dynamic bag creation policy.
+       **/
+      updateNumberOfStorageBucketsInDynamicBagCreationPolicy: AugmentedSubmittable<(dynamicBagType: DynamicBagType | 'Member' | 'Channel' | number | Uint8Array, numberOfStorageBuckets: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [DynamicBagType, u64]>;
+      /**
+       * Update whether new bags are being accepted for storage.
+       **/
+      updateStorageBucketStatus: AugmentedSubmittable<(storageBucketId: StorageBucketId | AnyNumber | Uint8Array, acceptingNewBags: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageBucketId, bool]>;
+      /**
+       * Updates storage buckets for a bag..
+       **/
+      updateStorageBucketsForBag: AugmentedSubmittable<(bagId: BagId | { Static: any } | { Dynamic: any } | string | Uint8Array, addBuckets: BTreeSet<StorageBucketId>, removeBuckets: BTreeSet<StorageBucketId>) => SubmittableExtrinsic<ApiType>, [BagId, BTreeSet<StorageBucketId>, BTreeSet<StorageBucketId>]>;
+      /**
+       * Updates "Storage buckets per bag" number limit.
+       **/
+      updateStorageBucketsPerBagLimit: AugmentedSubmittable<(newLimit: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u64]>;
+      /**
+       * Updates "Storage buckets voucher max limits".
+       **/
+      updateStorageBucketsVoucherMaxLimits: AugmentedSubmittable<(newObjectsSize: u64 | AnyNumber | Uint8Array, newObjectsNumber: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u64, u64]>;
+      /**
+       * Updates global uploading flag.
+       **/
+      updateUploadingBlockedStatus: AugmentedSubmittable<(newStatus: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [bool]>;
+    };
     storageWorkingGroup: {
       /**
        * Begin accepting worker applications to an opening that is active.

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
types/augment-codec/augment-types.ts


+ 117 - 30
types/augment/all/defs.json

@@ -552,35 +552,6 @@
         "identity": "IPNSIdentity",
         "expires_at": "u32"
     },
-    "ContentId": "[u8;32]",
-    "LiaisonJudgement": {
-        "_enum": [
-            "Pending",
-            "Accepted",
-            "Rejected"
-        ]
-    },
-    "DataObject": {
-        "owner": "MemberId",
-        "added_at": "BlockAndTime",
-        "type_id": "DataObjectTypeId",
-        "size": "u64",
-        "liaison": "StorageProviderId",
-        "liaison_judgement": "LiaisonJudgement",
-        "ipfs_content_id": "Text"
-    },
-    "DataObjectStorageRelationshipId": "u64",
-    "DataObjectStorageRelationship": {
-        "content_id": "ContentId",
-        "storage_provider": "StorageProviderId",
-        "ready": "bool"
-    },
-    "DataObjectTypeId": "u64",
-    "DataObjectType": {
-        "description": "Text",
-        "active": "bool"
-    },
-    "DataObjectsMap": "BTreeMap<ContentId,DataObject>",
     "ProposalId": "u32",
     "ProposalStatus": {
         "_enum": {
@@ -971,5 +942,121 @@
     "ClassPropertyValue": "Null",
     "Operation": "Null",
     "ReferenceConstraint": "Null",
-    "FailedAt": "u32"
+    "FailedAt": "u32",
+    "StorageBucketId": "u64",
+    "StorageBucketsPerBagValueConstraint": {
+        "min": "u64",
+        "max_min_diff": "u64"
+    },
+    "DataObjectId": "u64",
+    "DynamicBagId": {
+        "_enum": {
+            "Member": "MemberId",
+            "Channel": "u64"
+        }
+    },
+    "Voucher": {
+        "sizeLimit": "u64",
+        "objectsLimit": "u64",
+        "sizeUsed": "u64",
+        "objectsUsed": "u64"
+    },
+    "DynamicBagType": {
+        "_enum": [
+            "Member",
+            "Channel"
+        ]
+    },
+    "DynamicBagCreationPolicy": {
+        "numberOfStorageBuckets": "u64"
+    },
+    "DynamicBagDeletionPrize": {
+        "account_id": "GenericAccountId",
+        "prize": "u128"
+    },
+    "DynamicBagDeletionPrizeRecord": {
+        "account_id": "GenericAccountId",
+        "prize": "u128"
+    },
+    "Bag": {
+        "objects": "BTreeMap<DataObjectId,DataObject>",
+        "stored_by": "StorageBucketIdSet",
+        "distributed_by": "Vec<DistributionBucketId>",
+        "deletion_prize": "Option<u128>"
+    },
+    "StorageBucket": {
+        "operator_status": "StorageBucketOperatorStatus",
+        "accepting_new_bags": "bool",
+        "voucher": "Voucher",
+        "metadata": "Bytes"
+    },
+    "StaticBagId": {
+        "_enum": {
+            "Council": "Null",
+            "WorkingGroup": "WorkingGroup"
+        }
+    },
+    "Static": {
+        "_enum": {
+            "Council": "Null",
+            "WorkingGroup": "WorkingGroup"
+        }
+    },
+    "Dynamic": {
+        "_enum": {
+            "Member": "MemberId",
+            "Channel": "u64"
+        }
+    },
+    "BagId": {
+        "_enum": {
+            "Static": "Static",
+            "Dynamic": "Dynamic"
+        }
+    },
+    "DataObjectCreationParameters": {
+        "size": "u64",
+        "ipfsContentId": "Bytes"
+    },
+    "BagIdType": {
+        "_enum": {
+            "Static": "Static",
+            "Dynamic": "Dynamic"
+        }
+    },
+    "UploadParameters": {
+        "authenticationKey": "Bytes",
+        "bagId": "BagId",
+        "objectCreationList": "Vec<DataObjectCreationParameters>",
+        "deletionPrizeSourceAccountId": "GenericAccountId",
+        "expectedDataSizeFee": "u128"
+    },
+    "StorageBucketIdSet": "BTreeSet<StorageBucketId>",
+    "DataObjectIdSet": "BTreeSet<DataObjectId>",
+    "ContentIdSet": "BTreeSet<Cid>",
+    "Cid": "Bytes",
+    "StorageBucketOperatorStatus": {
+        "_enum": {
+            "Missing": "Null",
+            "InvitedStorageWorker": "WorkerId",
+            "StorageWorker": "WorkerId"
+        }
+    },
+    "DataObject": {
+        "accepted": "bool",
+        "deletion_prize": "u128",
+        "size": "u64"
+    },
+    "DistributionBucketId": "u64",
+    "DistributionBucketFamilyId": "u64",
+    "DistributionBucket": {
+        "accepting_new_bags": "bool",
+        "distributing": "bool",
+        "pending_invitations": "Vec<WorkerId>",
+        "operators": "Vec<WorkerId>",
+        "assigned_bags": "u64"
+    },
+    "DistributionBucketFamily": {
+        "distribution_buckets": "BTreeMap<DistributionBucketId,DistributionBucket>"
+    }
 }

+ 158 - 34
types/augment/all/types.ts

@@ -1,7 +1,7 @@
 // Auto-generated via `yarn polkadot-types-from-defs`, do not edit
 /* eslint-disable */
 
-import type { BTreeMap, BTreeSet, Bytes, Enum, GenericAccountId, Null, Option, Struct, Text, U8aFixed, Vec, bool, i16, i32, i64, u128, u16, u32, u64 } from '@polkadot/types';
+import type { BTreeMap, BTreeSet, Bytes, Enum, GenericAccountId, Null, Option, Struct, Text, Vec, bool, i16, i32, i64, u128, u16, u32, u64 } from '@polkadot/types';
 import type { ITuple } from '@polkadot/types/types';
 import type { AccountId, Balance, Hash } from '@polkadot/types/interfaces/runtime';
 
@@ -158,6 +158,30 @@ export interface Backer extends Struct {
 /** @name Backers */
 export interface Backers extends Vec<Backer> {}
 
+/** @name Bag */
+export interface Bag extends Struct {
+  readonly objects: BTreeMap<DataObjectId, DataObject>;
+  readonly stored_by: StorageBucketIdSet;
+  readonly distributed_by: Vec<DistributionBucketId>;
+  readonly deletion_prize: Option<u128>;
+}
+
+/** @name BagId */
+export interface BagId extends Enum {
+  readonly isStatic: boolean;
+  readonly asStatic: Static;
+  readonly isDynamic: boolean;
+  readonly asDynamic: Dynamic;
+}
+
+/** @name BagIdType */
+export interface BagIdType extends Enum {
+  readonly isStatic: boolean;
+  readonly asStatic: Static;
+  readonly isDynamic: boolean;
+  readonly asDynamic: Dynamic;
+}
+
 /** @name BalanceOfMint */
 export interface BalanceOfMint extends u128 {}
 
@@ -230,6 +254,9 @@ export interface ChildPositionInParentCategory extends Struct {
   readonly child_nr_in_parent_category: u32;
 }
 
+/** @name Cid */
+export interface Cid extends Bytes {}
+
 /** @name Class */
 export interface Class extends Struct {
   readonly class_permissions: ClassPermissions;
@@ -271,8 +298,8 @@ export interface ClassPermissionsType extends Null {}
 /** @name ClassPropertyValue */
 export interface ClassPropertyValue extends Null {}
 
-/** @name ContentId */
-export interface ContentId extends U8aFixed {}
+/** @name ContentIdSet */
+export interface ContentIdSet extends BTreeSet<Cid> {}
 
 /** @name CreateEntityOperation */
 export interface CreateEntityOperation extends Struct {
@@ -380,35 +407,20 @@ export interface CuratorRoleStakeProfile extends Struct {
 
 /** @name DataObject */
 export interface DataObject extends Struct {
-  readonly owner: MemberId;
-  readonly added_at: BlockAndTime;
-  readonly type_id: DataObjectTypeId;
-  readonly liaison: StorageProviderId;
-  readonly liaison_judgement: LiaisonJudgement;
-  readonly ipfs_content_id: Text;
+  readonly accepted: bool;
+  readonly deletion_prize: u128;
 }
 
-/** @name DataObjectsMap */
-export interface DataObjectsMap extends BTreeMap<ContentId, DataObject> {}
-
-/** @name DataObjectStorageRelationship */
-export interface DataObjectStorageRelationship extends Struct {
-  readonly content_id: ContentId;
-  readonly storage_provider: StorageProviderId;
-  readonly ready: bool;
+/** @name DataObjectCreationParameters */
+export interface DataObjectCreationParameters extends Struct {
+  readonly ipfsContentId: Bytes;
 }
 
-/** @name DataObjectStorageRelationshipId */
-export interface DataObjectStorageRelationshipId extends u64 {}
+/** @name DataObjectId */
+export interface DataObjectId extends u64 {}
 
-/** @name DataObjectType */
-export interface DataObjectType extends Struct {
-  readonly description: Text;
-  readonly active: bool;
-}
-
-/** @name DataObjectTypeId */
-export interface DataObjectTypeId extends u64 {}
+/** @name DataObjectIdSet */
+export interface DataObjectIdSet extends BTreeSet<DataObjectId> {}
 
 /** @name Deactivated */
 export interface Deactivated extends Struct {
@@ -435,6 +447,65 @@ export interface DiscussionThread extends Struct {
   readonly author_id: MemberId;
 }
 
+/** @name DistributionBucket */
+export interface DistributionBucket extends Struct {
+  readonly accepting_new_bags: bool;
+  readonly distributing: bool;
+  readonly pending_invitations: Vec<WorkerId>;
+  readonly operators: Vec<WorkerId>;
+  readonly assigned_bags: u64;
+}
+
+/** @name DistributionBucketFamily */
+export interface DistributionBucketFamily extends Struct {
+  readonly distribution_buckets: BTreeMap<DistributionBucketId, DistributionBucket>;
+}
+
+/** @name DistributionBucketFamilyId */
+export interface DistributionBucketFamilyId extends u64 {}
+
+/** @name DistributionBucketId */
+export interface DistributionBucketId extends u64 {}
+
+/** @name Dynamic */
+export interface Dynamic extends Enum {
+  readonly isMember: boolean;
+  readonly asMember: MemberId;
+  readonly isChannel: boolean;
+  readonly asChannel: u64;
+}
+
+/** @name DynamicBagCreationPolicy */
+export interface DynamicBagCreationPolicy extends Struct {
+  readonly numberOfStorageBuckets: u64;
+}
+
+/** @name DynamicBagDeletionPrize */
+export interface DynamicBagDeletionPrize extends Struct {
+  readonly account_id: GenericAccountId;
+  readonly prize: u128;
+}
+
+/** @name DynamicBagDeletionPrizeRecord */
+export interface DynamicBagDeletionPrizeRecord extends Struct {
+  readonly account_id: GenericAccountId;
+  readonly prize: u128;
+}
+
+/** @name DynamicBagId */
+export interface DynamicBagId extends Enum {
+  readonly isMember: boolean;
+  readonly asMember: MemberId;
+  readonly isChannel: boolean;
+  readonly asChannel: u64;
+}
+
+/** @name DynamicBagType */
+export interface DynamicBagType extends Enum {
+  readonly isMember: boolean;
+  readonly isChannel: boolean;
+}
+
 /** @name ElectionParameters */
 export interface ElectionParameters extends Struct {
   readonly announcing_period: u32;
@@ -629,13 +700,6 @@ export interface LeadRoleState extends Enum {
   readonly asExited: ExitedLeadRole;
 }
 
-/** @name LiaisonJudgement */
-export interface LiaisonJudgement extends Enum {
-  readonly isPending: boolean;
-  readonly isAccepted: boolean;
-  readonly isRejected: boolean;
-}
-
 /** @name LookupSource */
 export interface LookupSource extends AccountId {}
 
@@ -1191,9 +1255,52 @@ export interface StakingStatus extends Enum {
   readonly asStaked: Staked;
 }
 
+/** @name Static */
+export interface Static extends Enum {
+  readonly isCouncil: boolean;
+  readonly isWorkingGroup: boolean;
+  readonly asWorkingGroup: WorkingGroup;
+}
+
+/** @name StaticBagId */
+export interface StaticBagId extends Enum {
+  readonly isCouncil: boolean;
+  readonly isWorkingGroup: boolean;
+  readonly asWorkingGroup: WorkingGroup;
+}
+
 /** @name Status */
 export interface Status extends bool {}
 
+/** @name StorageBucket */
+export interface StorageBucket extends Struct {
+  readonly operator_status: StorageBucketOperatorStatus;
+  readonly accepting_new_bags: bool;
+  readonly voucher: Voucher;
+  readonly metadata: Bytes;
+}
+
+/** @name StorageBucketId */
+export interface StorageBucketId extends u64 {}
+
+/** @name StorageBucketIdSet */
+export interface StorageBucketIdSet extends BTreeSet<StorageBucketId> {}
+
+/** @name StorageBucketOperatorStatus */
+export interface StorageBucketOperatorStatus extends Enum {
+  readonly isMissing: boolean;
+  readonly isInvitedStorageWorker: boolean;
+  readonly asInvitedStorageWorker: WorkerId;
+  readonly isStorageWorker: boolean;
+  readonly asStorageWorker: WorkerId;
+}
+
+/** @name StorageBucketsPerBagValueConstraint */
+export interface StorageBucketsPerBagValueConstraint extends Struct {
+  readonly min: u64;
+  readonly max_min_diff: u64;
+}
+
 /** @name StorageProviderId */
 export interface StorageProviderId extends u64 {}
 
@@ -1290,6 +1397,15 @@ export interface UpdatePropertyValuesOperation extends Struct {
   readonly new_parametrized_property_values: Vec<ParametrizedClassPropertyValue>;
 }
 
+/** @name UploadParameters */
+export interface UploadParameters extends Struct {
+  readonly authenticationKey: Bytes;
+  readonly bagId: BagId;
+  readonly objectCreationList: Vec<DataObjectCreationParameters>;
+  readonly deletionPrizeSourceAccountId: GenericAccountId;
+  readonly expectedDataSizeFee: u128;
+}
+
 /** @name Url */
 export interface Url extends Text {}
 
@@ -1366,6 +1482,14 @@ export interface VotingResults extends Struct {
   readonly slashes: u32;
 }
 
+/** @name Voucher */
+export interface Voucher extends Struct {
+  readonly sizeLimit: u64;
+  readonly objectsLimit: u64;
+  readonly sizeUsed: u64;
+  readonly objectsUsed: u64;
+}
+
 /** @name WaitingToBeingOpeningStageVariant */
 export interface WaitingToBeingOpeningStageVariant extends Struct {
   readonly begins_at_block: u32;

+ 48 - 3
types/augment/augment-api-consts.ts

@@ -2,6 +2,7 @@
 /* eslint-disable */
 
 import type { Vec, u32, u64 } from '@polkadot/types';
+import type { StorageBucketsPerBagValueConstraint } from './all';
 import type { Balance, BalanceOf, BlockNumber, Moment, Perbill, RuntimeDbWeight, Weight } from '@polkadot/types/interfaces/runtime';
 import type { SessionIndex } from '@polkadot/types/interfaces/session';
 import type { EraIndex } from '@polkadot/types/interfaces/staking';
@@ -37,11 +38,11 @@ declare module '@polkadot/api/types/consts' {
        **/
       maxWorkerNumberLimit: u32 & AugmentedConst<ApiType>;
     };
-    dataDirectory: {
+    distributionWorkingGroup: {
       /**
-       * Maximum objects allowed per inject_data_objects() transaction
+       * Exports const -  max simultaneous active worker number.
        **/
-      maxObjectsPerInjection: u32 & AugmentedConst<ApiType>;
+      maxWorkerNumberLimit: u32 & AugmentedConst<ApiType>;
     };
     finalityTracker: {
       /**
@@ -148,6 +149,50 @@ declare module '@polkadot/api/types/consts' {
        **/
       slashDeferDuration: EraIndex & AugmentedConst<ApiType>;
     };
+    storage: {
+      /**
+       * Exports const - maximum size of the "hash blacklist" collection.
+       **/
+      blacklistSizeLimit: u64 & AugmentedConst<ApiType>;
+      /**
+       * Exports const - a prize for a data object deletion.
+       **/
+      dataObjectDeletionPrize: BalanceOf & AugmentedConst<ApiType>;
+      /**
+       * Exports const - the default dynamic bag creation policy for channels (storage bucket
+       * number).
+       **/
+      defaultChannelDynamicBagNumberOfStorageBuckets: u64 & AugmentedConst<ApiType>;
+      /**
+       * Exports const - the default dynamic bag creation policy for members (storage bucket
+       * number).
+       **/
+      defaultMemberDynamicBagNumberOfStorageBuckets: u64 & AugmentedConst<ApiType>;
+      /**
+       * Exports const - "Distribution buckets per bag" value constraint.
+       **/
+      distributionBucketsPerBagValueConstraint: StorageBucketsPerBagValueConstraint & AugmentedConst<ApiType>;
+      /**
+       * Exports const - max allowed distribution bucket family number.
+       **/
+      maxDistributionBucketFamilyNumber: u64 & AugmentedConst<ApiType>;
+      /**
+       * Exports const - max allowed distribution bucket number per family.
+       **/
+      maxDistributionBucketNumberPerFamily: u64 & AugmentedConst<ApiType>;
+      /**
+       * Exports const - max number of data objects per bag.
+       **/
+      maxNumberOfDataObjectsPerBag: u64 & AugmentedConst<ApiType>;
+      /**
+       * Exports const - max number of pending invitations per distribution bucket.
+       **/
+      maxNumberOfPendingInvitationsPerDistributionBucket: u64 & AugmentedConst<ApiType>;
+      /**
+       * Exports const - "Storage buckets per bag" value constraint.
+       **/
+      storageBucketsPerBagValueConstraint: StorageBucketsPerBagValueConstraint & AugmentedConst<ApiType>;
+    };
     storageWorkingGroup: {
       /**
        * Exports const -  max simultaneous active worker number.

+ 593 - 27
types/augment/augment-api-errors.ts

@@ -763,59 +763,399 @@ declare module '@polkadot/api/types/errors' {
        **/
       WorkerHasNoReward: AugmentedError<ApiType>;
     };
-    dataDirectory: {
+    distributionWorkingGroup: {
       /**
-       * Content with this ID not found.
+       * Opening does not exist.
+       **/
+      AcceptWorkerApplicationsOpeningDoesNotExist: AugmentedError<ApiType>;
+      /**
+       * Opening Is Not in Waiting to begin.
+       **/
+      AcceptWorkerApplicationsOpeningIsNotWaitingToBegin: AugmentedError<ApiType>;
+      /**
+       * Opening does not activate in the future.
+       **/
+      AddWorkerOpeningActivatesInThePast: AugmentedError<ApiType>;
+      /**
+       * Add worker opening application stake cannot be zero.
+       **/
+      AddWorkerOpeningApplicationStakeCannotBeZero: AugmentedError<ApiType>;
+      /**
+       * Application stake amount less than minimum currency balance.
+       **/
+      AddWorkerOpeningAppliicationStakeLessThanMinimum: AugmentedError<ApiType>;
+      /**
+       * New application was crowded out.
+       **/
+      AddWorkerOpeningNewApplicationWasCrowdedOut: AugmentedError<ApiType>;
+      /**
+       * Opening does not exist.
+       **/
+      AddWorkerOpeningOpeningDoesNotExist: AugmentedError<ApiType>;
+      /**
+       * Opening is not in accepting applications stage.
+       **/
+      AddWorkerOpeningOpeningNotInAcceptingApplicationStage: AugmentedError<ApiType>;
+      /**
+       * Add worker opening role stake cannot be zero.
+       **/
+      AddWorkerOpeningRoleStakeCannotBeZero: AugmentedError<ApiType>;
+      /**
+       * Role stake amount less than minimum currency balance.
+       **/
+      AddWorkerOpeningRoleStakeLessThanMinimum: AugmentedError<ApiType>;
+      /**
+       * Stake amount too low.
+       **/
+      AddWorkerOpeningStakeAmountTooLow: AugmentedError<ApiType>;
+      /**
+       * Stake missing when required.
+       **/
+      AddWorkerOpeningStakeMissingWhenRequired: AugmentedError<ApiType>;
+      /**
+       * Stake provided when redundant.
+       **/
+      AddWorkerOpeningStakeProvidedWhenRedundant: AugmentedError<ApiType>;
+      /**
+       * Application rationing has zero max active applicants.
+       **/
+      AddWorkerOpeningZeroMaxApplicantCount: AugmentedError<ApiType>;
+      /**
+       * Invalid OpeningPolicyCommitment parameter (application_rationing_policy):
+       * max_active_applicants should be non-zero.
+       **/
+      ApplicationRationingPolicyMaxActiveApplicantsIsZero: AugmentedError<ApiType>;
+      /**
+       * Invalid OpeningPolicyCommitment parameter (application_staking_policy):
+       * crowded_out_unstaking_period_length should be non-zero.
+       **/
+      ApplicationStakingPolicyCrowdedOutUnstakingPeriodIsZero: AugmentedError<ApiType>;
+      /**
+       * Invalid OpeningPolicyCommitment parameter (application_staking_policy):
+       * review_period_expired_unstaking_period_length should be non-zero.
+       **/
+      ApplicationStakingPolicyReviewPeriodUnstakingPeriodIsZero: AugmentedError<ApiType>;
+      /**
+       * Signer does not match controller account.
+       **/
+      ApplyOnWorkerOpeningSignerNotControllerAccount: AugmentedError<ApiType>;
+      /**
+       * Opening does not exist.
        **/
-      CidNotFound: AugmentedError<ApiType>;
+      BeginWorkerApplicantReviewOpeningDoesNotExist: AugmentedError<ApiType>;
       /**
-       * "Data object already added under this content id".
+       * Opening Is Not in Waiting.
+       **/
+      BeginWorkerApplicantReviewOpeningOpeningIsNotWaitingToBegin: AugmentedError<ApiType>;
+      /**
+       * Cannot find mint in the minting module.
+       **/
+      CannotFindMint: AugmentedError<ApiType>;
+      /**
+       * There is leader already, cannot hire another one.
+       **/
+      CannotHireLeaderWhenLeaderExists: AugmentedError<ApiType>;
+      /**
+       * Cannot fill opening with multiple applications.
+       **/
+      CannotHireMultipleLeaders: AugmentedError<ApiType>;
+      /**
+       * Current lead is not set.
+       **/
+      CurrentLeadNotSet: AugmentedError<ApiType>;
+      /**
+       * Invalid OpeningPolicyCommitment parameter:
+       * exit_role_application_stake_unstaking_period should be non-zero.
+       **/
+      ExitRoleApplicationStakeUnstakingPeriodIsZero: AugmentedError<ApiType>;
+      /**
+       * Invalid OpeningPolicyCommitment parameter:
+       * exit_role_stake_unstaking_period should be non-zero.
+       **/
+      ExitRoleStakeUnstakingPeriodIsZero: AugmentedError<ApiType>;
+      /**
+       * Invalid OpeningPolicyCommitment parameter:
+       * fill_opening_failed_applicant_application_stake_unstaking_period should be non-zero.
+       **/
+      FillOpeningFailedApplicantApplicationStakeUnstakingPeriodIsZero: AugmentedError<ApiType>;
+      /**
+       * Invalid OpeningPolicyCommitment parameter:
+       * fill_opening_failed_applicant_role_stake_unstaking_period should be non-zero.
+       **/
+      FillOpeningFailedApplicantRoleStakeUnstakingPeriodIsZero: AugmentedError<ApiType>;
+      /**
+       * Reward policy has invalid next payment block number.
+       **/
+      FillOpeningInvalidNextPaymentBlock: AugmentedError<ApiType>;
+      /**
+       * Working group mint does not exist.
+       **/
+      FillOpeningMintDoesNotExist: AugmentedError<ApiType>;
+      /**
+       * Invalid OpeningPolicyCommitment parameter:
+       * fill_opening_successful_applicant_application_stake_unstaking_period should be non-zero.
+       **/
+      FillOpeningSuccessfulApplicantApplicationStakeUnstakingPeriodIsZero: AugmentedError<ApiType>;
+      /**
+       * Applications not for opening.
+       **/
+      FillWorkerOpeningApplicationForWrongOpening: AugmentedError<ApiType>;
+      /**
+       * Application does not exist.
+       **/
+      FullWorkerOpeningApplicationDoesNotExist: AugmentedError<ApiType>;
+      /**
+       * Application not in active stage.
+       **/
+      FullWorkerOpeningApplicationNotActive: AugmentedError<ApiType>;
+      /**
+       * OpeningDoesNotExist.
+       **/
+      FullWorkerOpeningOpeningDoesNotExist: AugmentedError<ApiType>;
+      /**
+       * Opening not in review period stage.
+       **/
+      FullWorkerOpeningOpeningNotInReviewPeriodStage: AugmentedError<ApiType>;
+      /**
+       * Application stake unstaking period for successful applicants redundant.
+       **/
+      FullWorkerOpeningSuccessfulApplicationStakeUnstakingPeriodRedundant: AugmentedError<ApiType>;
+      /**
+       * Application stake unstaking period for failed applicants too short.
+       **/
+      FullWorkerOpeningSuccessfulApplicationStakeUnstakingPeriodTooShort: AugmentedError<ApiType>;
+      /**
+       * Role stake unstaking period for successful applicants redundant.
+       **/
+      FullWorkerOpeningSuccessfulRoleStakeUnstakingPeriodRedundant: AugmentedError<ApiType>;
+      /**
+       * Role stake unstaking period for successful applicants too short.
+       **/
+      FullWorkerOpeningSuccessfulRoleStakeUnstakingPeriodTooShort: AugmentedError<ApiType>;
+      /**
+       * Application stake unstaking period for failed applicants redundant.
+       **/
+      FullWorkerOpeningUnsuccessfulApplicationStakeUnstakingPeriodRedundant: AugmentedError<ApiType>;
+      /**
+       * Application stake unstaking period for successful applicants too short.
+       **/
+      FullWorkerOpeningUnsuccessfulApplicationStakeUnstakingPeriodTooShort: AugmentedError<ApiType>;
+      /**
+       * Role stake unstaking period for failed applicants redundant.
+       **/
+      FullWorkerOpeningUnsuccessfulRoleStakeUnstakingPeriodRedundant: AugmentedError<ApiType>;
+      /**
+       * Role stake unstaking period for failed applicants too short.
+       **/
+      FullWorkerOpeningUnsuccessfulRoleStakeUnstakingPeriodTooShort: AugmentedError<ApiType>;
+      /**
+       * Insufficient balance to apply.
+       **/
+      InsufficientBalanceToApply: AugmentedError<ApiType>;
+      /**
+       * Insufficient balance to cover stake.
+       **/
+      InsufficientBalanceToCoverStake: AugmentedError<ApiType>;
+      /**
+       * Not a lead account.
+       **/
+      IsNotLeadAccount: AugmentedError<ApiType>;
+      /**
+       * Working group size limit exceeded.
+       **/
+      MaxActiveWorkerNumberExceeded: AugmentedError<ApiType>;
+      /**
+       * Member already has an active application on the opening.
+       **/
+      MemberHasActiveApplicationOnOpening: AugmentedError<ApiType>;
+      /**
+       * Member id is invalid.
+       **/
+      MembershipInvalidMemberId: AugmentedError<ApiType>;
+      /**
+       * Unsigned origin.
+       **/
+      MembershipUnsignedOrigin: AugmentedError<ApiType>;
+      /**
+       * Minting error: NextAdjustmentInPast
+       **/
+      MintingErrorNextAdjustmentInPast: AugmentedError<ApiType>;
+      /**
+       * Cannot get the worker stake profile.
+       **/
+      NoWorkerStakeProfile: AugmentedError<ApiType>;
+      /**
+       * Opening does not exist.
+       **/
+      OpeningDoesNotExist: AugmentedError<ApiType>;
+      /**
+       * Opening text too long.
+       **/
+      OpeningTextTooLong: AugmentedError<ApiType>;
+      /**
+       * Opening text too short.
+       **/
+      OpeningTextTooShort: AugmentedError<ApiType>;
+      /**
+       * Origin must be controller or root account of member.
+       **/
+      OriginIsNeitherMemberControllerOrRoot: AugmentedError<ApiType>;
+      /**
+       * Origin is not applicant.
+       **/
+      OriginIsNotApplicant: AugmentedError<ApiType>;
+      /**
+       * Next payment is not in the future.
+       **/
+      RecurringRewardsNextPaymentNotInFuture: AugmentedError<ApiType>;
+      /**
+       * Recipient not found.
        **/
-      DataObjectAlreadyAdded: AugmentedError<ApiType>;
+      RecurringRewardsRecipientNotFound: AugmentedError<ApiType>;
       /**
-       * DataObject Injection Failed. Too Many DataObjects.
+       * Reward relationship not found.
        **/
-      DataObjectsInjectionExceededLimit: AugmentedError<ApiType>;
+      RecurringRewardsRewardRelationshipNotFound: AugmentedError<ApiType>;
       /**
-       * Cannot create content for inactive or missing data object type.
+       * Recipient reward source not found.
        **/
-      DataObjectTypeMustBeActive: AugmentedError<ApiType>;
+      RecurringRewardsRewardSourceNotFound: AugmentedError<ApiType>;
       /**
-       * Only the liaison for the content may modify its status.
+       * Relationship must exist.
        **/
-      LiaisonRequired: AugmentedError<ApiType>;
+      RelationshipMustExist: AugmentedError<ApiType>;
       /**
        * Require root origin in extrinsics.
        **/
       RequireRootOrigin: AugmentedError<ApiType>;
-    };
-    dataObjectStorageRegistry: {
       /**
-       * Content with this ID not found.
+       * Require signed origin in extrinsics.
        **/
-      CidNotFound: AugmentedError<ApiType>;
+      RequireSignedOrigin: AugmentedError<ApiType>;
       /**
-       * No data object storage relationship found for this ID.
+       * Invalid OpeningPolicyCommitment parameter (role_staking_policy):
+       * crowded_out_unstaking_period_length should be non-zero.
        **/
-      DataObjectStorageRelationshipNotFound: AugmentedError<ApiType>;
+      RoleStakingPolicyCrowdedOutUnstakingPeriodIsZero: AugmentedError<ApiType>;
       /**
-       * Only the storage provider in a DOSR can decide whether they're ready.
+       * Invalid OpeningPolicyCommitment parameter (role_staking_policy):
+       * review_period_expired_unstaking_period_length should be non-zero.
        **/
-      OnlyStorageProviderMayClaimReady: AugmentedError<ApiType>;
+      RoleStakingPolicyReviewPeriodUnstakingPeriodIsZero: AugmentedError<ApiType>;
       /**
-       * Require root origin in extrinsics
+       * Signer is not worker role account.
        **/
-      RequireRootOrigin: AugmentedError<ApiType>;
-    };
-    dataObjectTypeRegistry: {
+      SignerIsNotWorkerRoleAccount: AugmentedError<ApiType>;
       /**
-       * Data Object Type with the given ID not found.
+       * Provided stake balance cannot be zero.
        **/
-      DataObjectTypeNotFound: AugmentedError<ApiType>;
+      StakeBalanceCannotBeZero: AugmentedError<ApiType>;
       /**
-       * Require root origin in extrinsics
+       * Already unstaking.
        **/
-      RequireRootOrigin: AugmentedError<ApiType>;
+      StakingErrorAlreadyUnstaking: AugmentedError<ApiType>;
+      /**
+       * Cannot change stake by zero.
+       **/
+      StakingErrorCannotChangeStakeByZero: AugmentedError<ApiType>;
+      /**
+       * Cannot decrease stake while slashes ongoing.
+       **/
+      StakingErrorCannotDecreaseWhileSlashesOngoing: AugmentedError<ApiType>;
+      /**
+       * Cannot increase stake while unstaking.
+       **/
+      StakingErrorCannotIncreaseStakeWhileUnstaking: AugmentedError<ApiType>;
+      /**
+       * Cannot unstake while slashes ongoing.
+       **/
+      StakingErrorCannotUnstakeWhileSlashesOngoing: AugmentedError<ApiType>;
+      /**
+       * Insufficient balance in source account.
+       **/
+      StakingErrorInsufficientBalanceInSourceAccount: AugmentedError<ApiType>;
+      /**
+       * Insufficient stake to decrease.
+       **/
+      StakingErrorInsufficientStake: AugmentedError<ApiType>;
+      /**
+       * Not staked.
+       **/
+      StakingErrorNotStaked: AugmentedError<ApiType>;
+      /**
+       * Slash amount should be greater than zero.
+       **/
+      StakingErrorSlashAmountShouldBeGreaterThanZero: AugmentedError<ApiType>;
+      /**
+       * Stake not found.
+       **/
+      StakingErrorStakeNotFound: AugmentedError<ApiType>;
+      /**
+       * Unstaking period should be greater than zero.
+       **/
+      StakingErrorUnstakingPeriodShouldBeGreaterThanZero: AugmentedError<ApiType>;
+      /**
+       * Successful worker application does not exist.
+       **/
+      SuccessfulWorkerApplicationDoesNotExist: AugmentedError<ApiType>;
+      /**
+       * Invalid OpeningPolicyCommitment parameter:
+       * terminate_application_stake_unstaking_period should be non-zero.
+       **/
+      TerminateApplicationStakeUnstakingPeriodIsZero: AugmentedError<ApiType>;
+      /**
+       * Invalid OpeningPolicyCommitment parameter:
+       * terminate_role_stake_unstaking_period should be non-zero.
+       **/
+      TerminateRoleStakeUnstakingPeriodIsZero: AugmentedError<ApiType>;
+      /**
+       * Application does not exist.
+       **/
+      WithdrawWorkerApplicationApplicationDoesNotExist: AugmentedError<ApiType>;
+      /**
+       * Application is not active.
+       **/
+      WithdrawWorkerApplicationApplicationNotActive: AugmentedError<ApiType>;
+      /**
+       * Opening not accepting applications.
+       **/
+      WithdrawWorkerApplicationOpeningNotAcceptingApplications: AugmentedError<ApiType>;
+      /**
+       * Redundant unstaking period provided
+       **/
+      WithdrawWorkerApplicationRedundantUnstakingPeriod: AugmentedError<ApiType>;
+      /**
+       * UnstakingPeriodTooShort .... // <== SHOULD REALLY BE TWO SEPARATE, ONE FOR EACH STAKING PURPOSE
+       **/
+      WithdrawWorkerApplicationUnstakingPeriodTooShort: AugmentedError<ApiType>;
+      /**
+       * Worker application does not exist.
+       **/
+      WorkerApplicationDoesNotExist: AugmentedError<ApiType>;
+      /**
+       * Worker application text too long.
+       **/
+      WorkerApplicationTextTooLong: AugmentedError<ApiType>;
+      /**
+       * Worker application text too short.
+       **/
+      WorkerApplicationTextTooShort: AugmentedError<ApiType>;
+      /**
+       * Worker does not exist.
+       **/
+      WorkerDoesNotExist: AugmentedError<ApiType>;
+      /**
+       * Worker exit rationale text is too long.
+       **/
+      WorkerExitRationaleTextTooLong: AugmentedError<ApiType>;
+      /**
+       * Worker exit rationale text is too short.
+       **/
+      WorkerExitRationaleTextTooShort: AugmentedError<ApiType>;
+      /**
+       * Worker has no recurring reward.
+       **/
+      WorkerHasNoReward: AugmentedError<ApiType>;
     };
     finalityTracker: {
       /**
@@ -1202,6 +1542,232 @@ declare module '@polkadot/api/types/errors' {
        **/
       SnapshotUnavailable: AugmentedError<ApiType>;
     };
+    storage: {
+      /**
+       * Blacklist size limit exceeded.
+       **/
+      BlacklistSizeLimitExceeded: AugmentedError<ApiType>;
+      /**
+       * Cannot delete non empty dynamic bag.
+       **/
+      CannotDeleteNonEmptyDynamicBag: AugmentedError<ApiType>;
+      /**
+       * Cannot delete a non-empty storage bucket.
+       **/
+      CannotDeleteNonEmptyStorageBucket: AugmentedError<ApiType>;
+      /**
+       * Data object hash is part of the blacklist.
+       **/
+      DataObjectBlacklisted: AugmentedError<ApiType>;
+      /**
+       * Data object doesn't exist.
+       **/
+      DataObjectDoesntExist: AugmentedError<ApiType>;
+      /**
+       * Data object id collection is empty.
+       **/
+      DataObjectIdCollectionIsEmpty: AugmentedError<ApiType>;
+      /**
+       * The `data_object_ids` extrinsic parameter collection is empty.
+       **/
+      DataObjectIdParamsAreEmpty: AugmentedError<ApiType>;
+      /**
+       * Upload data error: data objects per bag limit exceeded.
+       **/
+      DataObjectsPerBagLimitExceeded: AugmentedError<ApiType>;
+      /**
+       * Invalid extrinsic call: data size fee changed.
+       **/
+      DataSizeFeeChanged: AugmentedError<ApiType>;
+      /**
+       * Invalid operation with invites: another storage provider was invited.
+       **/
+      DifferentStorageProviderInvited: AugmentedError<ApiType>;
+      /**
+       * Distribution bucket doesn't accept new bags.
+       **/
+      DistributionBucketDoesntAcceptNewBags: AugmentedError<ApiType>;
+      /**
+       * Distribution bucket doesn't exist.
+       **/
+      DistributionBucketDoesntExist: AugmentedError<ApiType>;
+      /**
+       * Distribution bucket family doesn't exist.
+       **/
+      DistributionBucketFamilyDoesntExist: AugmentedError<ApiType>;
+      /**
+       * Distribution bucket id collections are empty.
+       **/
+      DistributionBucketIdCollectionsAreEmpty: AugmentedError<ApiType>;
+      /**
+       * Distribution bucket is bound to a bag.
+       **/
+      DistributionBucketIsBoundToBag: AugmentedError<ApiType>;
+      /**
+       * Distribution bucket is not bound to a bag.
+       **/
+      DistributionBucketIsNotBoundToBag: AugmentedError<ApiType>;
+      /**
+       * The new `DistributionBucketsPerBagLimit` number is too high.
+       **/
+      DistributionBucketsPerBagLimitTooHigh: AugmentedError<ApiType>;
+      /**
+       * The new `DistributionBucketsPerBagLimit` number is too low.
+       **/
+      DistributionBucketsPerBagLimitTooLow: AugmentedError<ApiType>;
+      /**
+       * Distribution family bound to a bag creation policy.
+       **/
+      DistributionFamilyBoundToBagCreationPolicy: AugmentedError<ApiType>;
+      /**
+       * Distribution provider operator already invited.
+       **/
+      DistributionProviderOperatorAlreadyInvited: AugmentedError<ApiType>;
+      /**
+       * Distribution provider operator doesn't exist.
+       **/
+      DistributionProviderOperatorDoesntExist: AugmentedError<ApiType>;
+      /**
+       * Distribution provider operator already set.
+       **/
+      DistributionProviderOperatorSet: AugmentedError<ApiType>;
+      /**
+       * Dynamic bag doesn't exist.
+       **/
+      DynamicBagDoesntExist: AugmentedError<ApiType>;
+      /**
+       * Cannot create the dynamic bag: dynamic bag exists.
+       **/
+      DynamicBagExists: AugmentedError<ApiType>;
+      /**
+       * Upload data error: empty content ID provided.
+       **/
+      EmptyContentId: AugmentedError<ApiType>;
+      /**
+       * Insufficient balance for an operation.
+       **/
+      InsufficientBalance: AugmentedError<ApiType>;
+      /**
+       * Insufficient module treasury balance for an operation.
+       **/
+      InsufficientTreasuryBalance: AugmentedError<ApiType>;
+      /**
+       * Upload data error: invalid deletion prize source account.
+       **/
+      InvalidDeletionPrizeSourceAccount: AugmentedError<ApiType>;
+      /**
+       * Invalid storage provider for bucket.
+       **/
+      InvalidStorageProvider: AugmentedError<ApiType>;
+      /**
+       * Invalid operation with invites: storage provider was already invited.
+       **/
+      InvitedStorageProvider: AugmentedError<ApiType>;
+      /**
+       * Max distribution bucket family number limit exceeded.
+       **/
+      MaxDistributionBucketFamilyNumberLimitExceeded: AugmentedError<ApiType>;
+      /**
+       * Max distribution bucket number per bag limit exceeded.
+       **/
+      MaxDistributionBucketNumberPerBagLimitExceeded: AugmentedError<ApiType>;
+      /**
+       * Max distribution bucket number per family limit exceeded.
+       **/
+      MaxDistributionBucketNumberPerFamilyLimitExceeded: AugmentedError<ApiType>;
+      /**
+       * Max number of pending invitations limit for a distribution bucket reached.
+       **/
+      MaxNumberOfPendingInvitationsLimitForDistributionBucketReached: AugmentedError<ApiType>;
+      /**
+       * Invalid operations: must be a distribution provider operator for a bucket.
+       **/
+      MustBeDistributionProviderOperatorForBucket: AugmentedError<ApiType>;
+      /**
+       * No distribution bucket invitation.
+       **/
+      NoDistributionBucketInvitation: AugmentedError<ApiType>;
+      /**
+       * Empty "data object creation" collection.
+       **/
+      NoObjectsOnUpload: AugmentedError<ApiType>;
+      /**
+       * Invalid operation with invites: there is no storage bucket invitation.
+       **/
+      NoStorageBucketInvitation: AugmentedError<ApiType>;
+      /**
+       * Cannot move objects within the same bag.
+       **/
+      SourceAndDestinationBagsAreEqual: AugmentedError<ApiType>;
+      /**
+       * The storage bucket doesn't accept new bags.
+       **/
+      StorageBucketDoesntAcceptNewBags: AugmentedError<ApiType>;
+      /**
+       * The requested storage bucket doesn't exist.
+       **/
+      StorageBucketDoesntExist: AugmentedError<ApiType>;
+      /**
+       * Storage bucket id collections are empty.
+       **/
+      StorageBucketIdCollectionsAreEmpty: AugmentedError<ApiType>;
+      /**
+       * The requested storage bucket is already bound to a bag.
+       **/
+      StorageBucketIsBoundToBag: AugmentedError<ApiType>;
+      /**
+       * The requested storage bucket is not bound to a bag.
+       **/
+      StorageBucketIsNotBoundToBag: AugmentedError<ApiType>;
+      /**
+       * Object number limit for the storage bucket reached.
+       **/
+      StorageBucketObjectNumberLimitReached: AugmentedError<ApiType>;
+      /**
+       * Objects total size limit for the storage bucket reached.
+       **/
+      StorageBucketObjectSizeLimitReached: AugmentedError<ApiType>;
+      /**
+       * `StorageBucketsPerBagLimit` was exceeded for a bag.
+       **/
+      StorageBucketPerBagLimitExceeded: AugmentedError<ApiType>;
+      /**
+       * The new `StorageBucketsPerBagLimit` number is too high.
+       **/
+      StorageBucketsPerBagLimitTooHigh: AugmentedError<ApiType>;
+      /**
+       * The new `StorageBucketsPerBagLimit` number is too low.
+       **/
+      StorageBucketsPerBagLimitTooLow: AugmentedError<ApiType>;
+      /**
+       * Invalid operation with invites: storage provider was already set.
+       **/
+      StorageProviderAlreadySet: AugmentedError<ApiType>;
+      /**
+       * Storage provider must be set.
+       **/
+      StorageProviderMustBeSet: AugmentedError<ApiType>;
+      /**
+       * Storage provider operator doesn't exist.
+       **/
+      StorageProviderOperatorDoesntExist: AugmentedError<ApiType>;
+      /**
+       * Uploading of the new object is blocked.
+       **/
+      UploadingBlocked: AugmentedError<ApiType>;
+      /**
+       * Max object number limit exceeded for voucher.
+       **/
+      VoucherMaxObjectNumberLimitExceeded: AugmentedError<ApiType>;
+      /**
+       * Max object size limit exceeded for voucher.
+       **/
+      VoucherMaxObjectSizeLimitExceeded: AugmentedError<ApiType>;
+      /**
+       * Upload data error: zero object size.
+       **/
+      ZeroObjectSize: AugmentedError<ApiType>;
+    };
     storageWorkingGroup: {
       /**
        * Opening does not exist.

+ 384 - 43
types/augment/augment-api-events.ts

@@ -1,8 +1,8 @@
 // Auto-generated via `yarn polkadot-types-from-chain`, do not edit
 /* eslint-disable */
 
-import type { Option, Vec, bool, u16, u32, u64 } from '@polkadot/types';
-import type { Actor, ApplicationId, ApplicationIdToWorkerIdMap, CategoryId, ChannelId, ClassId, ContentId, CuratorApplicationId, CuratorApplicationIdToCuratorIdMap, CuratorGroupId, CuratorId, CuratorOpeningId, DataObjectStorageRelationshipId, DataObjectTypeId, EntityController, EntityCreationVoucher, EntityId, FailedAt, IPNSIdentity, LeadId, MemberId, MintBalanceOf, MintId, Nonce, OpeningId, PostId, PropertyId, ProposalId, ProposalStatus, RationaleText, SchemaId, SideEffect, SideEffects, Status, StorageProviderId, ThreadId, VecMaxLength, VoteKind, WorkerId } from './all';
+import type { BTreeMap, BTreeSet, Bytes, Option, Vec, bool, u16, u32, u64 } from '@polkadot/types';
+import type { Actor, ApplicationId, ApplicationIdToWorkerIdMap, BagId, CategoryId, ChannelId, Cid, ClassId, CuratorApplicationId, CuratorApplicationIdToCuratorIdMap, CuratorGroupId, CuratorId, CuratorOpeningId, DataObjectId, DistributionBucketFamilyId, DistributionBucketId, DynamicBagDeletionPrizeRecord, DynamicBagId, DynamicBagType, EntityController, EntityCreationVoucher, EntityId, FailedAt, LeadId, MemberId, MintBalanceOf, MintId, Nonce, OpeningId, PostId, PropertyId, ProposalId, ProposalStatus, RationaleText, SchemaId, SideEffect, SideEffects, Status, StorageBucketId, ThreadId, UploadParameters, VecMaxLength, VoteKind, Voucher, WorkerId } from './all';
 import type { BalanceStatus } from '@polkadot/types/interfaces/balances';
 import type { AuthorityId } from '@polkadot/types/interfaces/consensus';
 import type { AuthorityList } from '@polkadot/types/interfaces/grandpa';
@@ -243,74 +243,128 @@ declare module '@polkadot/api/types/events' {
       VotingEnded: AugmentedEvent<ApiType, []>;
       VotingStarted: AugmentedEvent<ApiType, []>;
     };
-    dataDirectory: {
+    distributionWorkingGroup: {
       /**
-       * Emits when the storage provider accepts a content.
+       * Emits on accepting application for the worker opening.
        * Params:
-       * - Id of the relationship.
-       * - Id of the storage provider.
+       * - Opening id
        **/
-      ContentAccepted: AugmentedEvent<ApiType, [ContentId, StorageProviderId]>;
+      AcceptedApplications: AugmentedEvent<ApiType, [OpeningId]>;
       /**
-       * Emits on adding of the content.
+       * Emits on terminating the application for the worker/lead opening.
        * Params:
-       * - Id of the relationship.
-       * - Id of the member.
+       * - Worker application id
        **/
-      ContentAdded: AugmentedEvent<ApiType, [ContentId, MemberId]>;
+      ApplicationTerminated: AugmentedEvent<ApiType, [ApplicationId]>;
       /**
-       * Emits when the storage provider rejects a content.
+       * Emits on withdrawing the application for the worker/lead opening.
        * Params:
-       * - Id of the relationship.
-       * - Id of the storage provider.
+       * - Worker application id
        **/
-      ContentRejected: AugmentedEvent<ApiType, [ContentId, StorageProviderId]>;
-    };
-    dataObjectStorageRegistry: {
+      ApplicationWithdrawn: AugmentedEvent<ApiType, [ApplicationId]>;
       /**
-       * Emits on adding of the data object storage relationship.
+       * Emits on adding the application for the worker opening.
        * Params:
-       * - Id of the relationship.
-       * - Id of the content.
-       * - Id of the storage provider.
+       * - Opening id
+       * - Application id
        **/
-      DataObjectStorageRelationshipAdded: AugmentedEvent<ApiType, [DataObjectStorageRelationshipId, ContentId, StorageProviderId]>;
+      AppliedOnOpening: AugmentedEvent<ApiType, [OpeningId, ApplicationId]>;
       /**
-       * Emits on adding of the data object storage relationship.
+       * Emits on beginning the application review for the worker/lead opening.
        * Params:
-       * - Id of the relationship.
-       * - Current state of the relationship (True=Active).
+       * - Opening id
        **/
-      DataObjectStorageRelationshipReadyUpdated: AugmentedEvent<ApiType, [DataObjectStorageRelationshipId, bool]>;
-    };
-    dataObjectTypeRegistry: {
+      BeganApplicationReview: AugmentedEvent<ApiType, [OpeningId]>;
+      /**
+       * Emits on setting the leader.
+       * Params:
+       * - Worker id.
+       **/
+      LeaderSet: AugmentedEvent<ApiType, [WorkerId]>;
       /**
-       * Emits on the data object type registration.
+       * Emits on un-setting the leader.
        * Params:
-       * - Id of the new data object type.
        **/
-      DataObjectTypeRegistered: AugmentedEvent<ApiType, [DataObjectTypeId]>;
+      LeaderUnset: AugmentedEvent<ApiType, []>;
       /**
-       * Emits on the data object type update.
+       * Emits on changing working group mint capacity.
        * Params:
-       * - Id of the updated data object type.
+       * - mint id.
+       * - new mint balance.
        **/
-      DataObjectTypeUpdated: AugmentedEvent<ApiType, [DataObjectTypeId]>;
-    };
-    discovery: {
+      MintCapacityChanged: AugmentedEvent<ApiType, [MintId, MintBalanceOf]>;
+      /**
+       * Emits on adding new worker opening.
+       * Params:
+       * - Opening id
+       **/
+      OpeningAdded: AugmentedEvent<ApiType, [OpeningId]>;
+      /**
+       * Emits on filling the worker opening.
+       * Params:
+       * - Worker opening id
+       * - Worker application id to the worker id dictionary
+       **/
+      OpeningFilled: AugmentedEvent<ApiType, [OpeningId, ApplicationIdToWorkerIdMap]>;
+      /**
+       * Emits on decreasing the worker/lead stake.
+       * Params:
+       * - worker/lead id.
+       **/
+      StakeDecreased: AugmentedEvent<ApiType, [WorkerId]>;
+      /**
+       * Emits on increasing the worker/lead stake.
+       * Params:
+       * - worker/lead id.
+       **/
+      StakeIncreased: AugmentedEvent<ApiType, [WorkerId]>;
+      /**
+       * Emits on slashing the worker/lead stake.
+       * Params:
+       * - worker/lead id.
+       **/
+      StakeSlashed: AugmentedEvent<ApiType, [WorkerId]>;
+      /**
+       * Emits on terminating the leader.
+       * Params:
+       * - leader worker id.
+       * - termination rationale text
+       **/
+      TerminatedLeader: AugmentedEvent<ApiType, [WorkerId, RationaleText]>;
+      /**
+       * Emits on terminating the worker.
+       * Params:
+       * - worker id.
+       * - termination rationale text
+       **/
+      TerminatedWorker: AugmentedEvent<ApiType, [WorkerId, RationaleText]>;
+      /**
+       * Emits on exiting the worker.
+       * Params:
+       * - worker id.
+       * - exit rationale text
+       **/
+      WorkerExited: AugmentedEvent<ApiType, [WorkerId, RationaleText]>;
+      /**
+       * Emits on updating the reward account of the worker.
+       * Params:
+       * - Member id of the worker.
+       * - Reward account id of the worker.
+       **/
+      WorkerRewardAccountUpdated: AugmentedEvent<ApiType, [WorkerId, AccountId]>;
       /**
-       * Emits on removing of the account info.
+       * Emits on updating the reward amount of the worker.
        * Params:
-       * - Id of the storage provider.
+       * - Id of the worker.
        **/
-      AccountInfoRemoved: AugmentedEvent<ApiType, [StorageProviderId]>;
+      WorkerRewardAmountUpdated: AugmentedEvent<ApiType, [WorkerId]>;
       /**
-       * Emits on updating of the account info.
+       * Emits on updating the role account of the worker.
        * Params:
-       * - Id of the storage provider.
-       * - Id of the IPNS.
+       * - Id of the worker.
+       * - Role account id of the worker.
        **/
-      AccountInfoUpdated: AugmentedEvent<ApiType, [StorageProviderId, IPNSIdentity]>;
+      WorkerRoleAccountUpdated: AugmentedEvent<ApiType, [WorkerId, AccountId]>;
     };
     forum: {
       /**
@@ -488,6 +542,293 @@ declare module '@polkadot/api/types/events' {
        **/
       Withdrawn: AugmentedEvent<ApiType, [AccountId, Balance]>;
     };
+    storage: {
+      /**
+       * Bag objects changed.
+       * Params
+       * - bag id
+       * - new total objects size
+       * - new total objects number
+       **/
+      BagObjectsChanged: AugmentedEvent<ApiType, [BagId, u64, u64]>;
+      /**
+       * Emits on changing the size-based pricing of new objects uploaded.
+       * Params
+       * - new data size fee
+       **/
+      DataObjectPerMegabyteFeeUpdated: AugmentedEvent<ApiType, [Balance]>;
+      /**
+       * Emits on data objects deletion from bags.
+       * Params
+       * - account ID for the deletion prize
+       * - bag ID
+       * - data object IDs
+       **/
+      DataObjectsDeleted: AugmentedEvent<ApiType, [AccountId, BagId, BTreeSet<DataObjectId>]>;
+      /**
+       * Emits on moving data objects between bags.
+       * Params
+       * - source bag ID
+       * - destination bag ID
+       * - data object IDs
+       **/
+      DataObjectsMoved: AugmentedEvent<ApiType, [BagId, BagId, BTreeSet<DataObjectId>]>;
+      /**
+       * Emits on uploading data objects.
+       * Params
+       * - data objects IDs
+       * - initial uploading parameters
+       **/
+      DataObjectsUploaded: AugmentedEvent<ApiType, [Vec<DataObjectId>, UploadParameters]>;
+      /**
+       * Emits on creating distribution bucket.
+       * Params
+       * - distribution bucket family ID
+       * - accepting new bags
+       * - distribution bucket ID
+       **/
+      DistributionBucketCreated: AugmentedEvent<ApiType, [DistributionBucketFamilyId, bool, DistributionBucketId]>;
+      /**
+       * Emits on deleting distribution bucket.
+       * Params
+       * - distribution bucket family ID
+       * - distribution bucket ID
+       **/
+      DistributionBucketDeleted: AugmentedEvent<ApiType, [DistributionBucketFamilyId, DistributionBucketId]>;
+      /**
+       * Emits on creating distribution bucket family.
+       * Params
+       * - distribution family bucket ID
+       **/
+      DistributionBucketFamilyCreated: AugmentedEvent<ApiType, [DistributionBucketFamilyId]>;
+      /**
+       * Emits on deleting distribution bucket family.
+       * Params
+       * - distribution family bucket ID
+       **/
+      DistributionBucketFamilyDeleted: AugmentedEvent<ApiType, [DistributionBucketFamilyId]>;
+      /**
+       * Emits on setting the metadata by a distribution bucket family.
+       * Params
+       * - distribution bucket family ID
+       * - metadata
+       **/
+      DistributionBucketFamilyMetadataSet: AugmentedEvent<ApiType, [DistributionBucketFamilyId, Bytes]>;
+      /**
+       * Emits on accepting a distribution bucket invitation for the operator.
+       * Params
+       * - worker ID
+       * - distribution bucket family ID
+       * - distribution bucket ID
+       **/
+      DistributionBucketInvitationAccepted: AugmentedEvent<ApiType, [WorkerId, DistributionBucketFamilyId, DistributionBucketId]>;
+      /**
+       * Emits on canceling a distribution bucket invitation for the operator.
+       * Params
+       * - distribution bucket family ID
+       * - distribution bucket ID
+       * - operator worker ID
+       **/
+      DistributionBucketInvitationCancelled: AugmentedEvent<ApiType, [DistributionBucketFamilyId, DistributionBucketId, WorkerId]>;
+      /**
+       * Emits on setting the metadata by a distribution bucket operator.
+       * Params
+       * - worker ID
+       * - distribution bucket family ID
+       * - distribution bucket ID
+       * - metadata
+       **/
+      DistributionBucketMetadataSet: AugmentedEvent<ApiType, [WorkerId, DistributionBucketFamilyId, DistributionBucketId, Bytes]>;
+      /**
+       * Emits on storage bucket mode update (distributing flag).
+       * Params
+       * - distribution bucket family ID
+       * - distribution bucket ID
+       * - distributing
+       **/
+      DistributionBucketModeUpdated: AugmentedEvent<ApiType, [DistributionBucketFamilyId, DistributionBucketId, bool]>;
+      /**
+       * Emits on creating a distribution bucket invitation for the operator.
+       * Params
+       * - distribution bucket family ID
+       * - distribution bucket ID
+       * - worker ID
+       **/
+      DistributionBucketOperatorInvited: AugmentedEvent<ApiType, [DistributionBucketFamilyId, DistributionBucketId, WorkerId]>;
+      /**
+       * Emits on the distribution bucket operator removal.
+       * Params
+       * - distribution bucket family ID
+       * - distribution bucket ID
+       * - distribution bucket operator ID
+       **/
+      DistributionBucketOperatorRemoved: AugmentedEvent<ApiType, [DistributionBucketFamilyId, DistributionBucketId, WorkerId]>;
+      /**
+       * Emits on changing the "Distribution buckets per bag" number limit.
+       * Params
+       * - new limit
+       **/
+      DistributionBucketsPerBagLimitUpdated: AugmentedEvent<ApiType, [u64]>;
+      /**
+       * Emits on storage bucket status update (accepting new bags).
+       * Params
+       * - distribution bucket family ID
+       * - distribution bucket ID
+       * - new status (accepting new bags)
+       **/
+      DistributionBucketStatusUpdated: AugmentedEvent<ApiType, [DistributionBucketFamilyId, DistributionBucketId, bool]>;
+      /**
+       * Emits on updating distribution buckets for bag.
+       * Params
+       * - bag ID
+       * - storage buckets to add ID collection
+       * - storage buckets to remove ID collection
+       **/
+      DistributionBucketsUpdatedForBag: AugmentedEvent<ApiType, [BagId, DistributionBucketFamilyId, BTreeSet<DistributionBucketId>, BTreeSet<DistributionBucketId>]>;
+      /**
+       * Emits on creating a dynamic bag.
+       * Params
+       * - dynamic bag ID
+       * - optional DynamicBagDeletionPrize instance
+       **/
+      DynamicBagCreated: AugmentedEvent<ApiType, [DynamicBagId, Option<DynamicBagDeletionPrizeRecord>]>;
+      /**
+       * Emits on deleting a dynamic bag.
+       * Params
+       * - account ID for the deletion prize
+       * - dynamic bag ID
+       **/
+      DynamicBagDeleted: AugmentedEvent<ApiType, [AccountId, DynamicBagId]>;
+      /**
+       * Emits on dynamic bag creation policy update (distribution bucket families).
+       * Params
+       * - dynamic bag type
+       * - families and bucket numbers
+       **/
+      FamiliesInDynamicBagCreationPolicyUpdated: AugmentedEvent<ApiType, [DynamicBagType, BTreeMap<DistributionBucketFamilyId, u32>]>;
+      /**
+       * Emits on updating the number of storage buckets in dynamic bag creation policy.
+       * Params
+       * - dynamic bag type
+       * - new number of storage buckets
+       **/
+      NumberOfStorageBucketsInDynamicBagCreationPolicyUpdated: AugmentedEvent<ApiType, [DynamicBagType, u64]>;
+      /**
+       * Emits on accepting pending data objects.
+       * Params
+       * - storage bucket ID
+       * - worker ID (storage provider ID)
+       * - bag ID
+       * - pending data objects
+       **/
+      PendingDataObjectsAccepted: AugmentedEvent<ApiType, [StorageBucketId, WorkerId, BagId, BTreeSet<DataObjectId>]>;
+      /**
+       * Emits on creating the storage bucket.
+       * Params
+       * - storage bucket ID
+       * - invited worker
+       * - flag "accepting_new_bags"
+       * - size limit for voucher,
+       * - objects limit for voucher,
+       **/
+      StorageBucketCreated: AugmentedEvent<ApiType, [StorageBucketId, Option<WorkerId>, bool, u64, u64]>;
+      /**
+       * Emits on storage bucket deleting.
+       * Params
+       * - storage bucket ID
+       **/
+      StorageBucketDeleted: AugmentedEvent<ApiType, [StorageBucketId]>;
+      /**
+       * Emits on accepting the storage bucket invitation.
+       * Params
+       * - storage bucket ID
+       * - invited worker ID
+       **/
+      StorageBucketInvitationAccepted: AugmentedEvent<ApiType, [StorageBucketId, WorkerId]>;
+      /**
+       * Emits on cancelling the storage bucket invitation.
+       * Params
+       * - storage bucket ID
+       **/
+      StorageBucketInvitationCancelled: AugmentedEvent<ApiType, [StorageBucketId]>;
+      /**
+       * Emits on the storage bucket operator invitation.
+       * Params
+       * - storage bucket ID
+       * - operator worker ID (storage provider ID)
+       **/
+      StorageBucketOperatorInvited: AugmentedEvent<ApiType, [StorageBucketId, WorkerId]>;
+      /**
+       * Emits on the storage bucket operator removal.
+       * Params
+       * - storage bucket ID
+       **/
+      StorageBucketOperatorRemoved: AugmentedEvent<ApiType, [StorageBucketId]>;
+      /**
+       * Emits on changing the "Storage buckets per bag" number limit.
+       * Params
+       * - new limit
+       **/
+      StorageBucketsPerBagLimitUpdated: AugmentedEvent<ApiType, [u64]>;
+      /**
+       * Emits on storage bucket status update.
+       * Params
+       * - storage bucket ID
+       * - new status
+       **/
+      StorageBucketStatusUpdated: AugmentedEvent<ApiType, [StorageBucketId, bool]>;
+      /**
+       * Emits on updating storage buckets for bag.
+       * Params
+       * - bag ID
+       * - storage buckets to add ID collection
+       * - storage buckets to remove ID collection
+       **/
+      StorageBucketsUpdatedForBag: AugmentedEvent<ApiType, [BagId, BTreeSet<StorageBucketId>, BTreeSet<StorageBucketId>]>;
+      /**
+       * Emits on changing the "Storage buckets voucher max limits".
+       * Params
+       * - new objects size limit
+       * - new objects number limit
+       **/
+      StorageBucketsVoucherMaxLimitsUpdated: AugmentedEvent<ApiType, [u64, u64]>;
+      /**
+       * Emits on setting the storage bucket voucher limits.
+       * Params
+       * - storage bucket ID
+       * - new total objects size limit
+       * - new total objects number limit
+       **/
+      StorageBucketVoucherLimitsSet: AugmentedEvent<ApiType, [StorageBucketId, u64, u64]>;
+      /**
+       * Emits on setting the storage operator metadata.
+       * Params
+       * - storage bucket ID
+       * - invited worker ID
+       * - metadata
+       **/
+      StorageOperatorMetadataSet: AugmentedEvent<ApiType, [StorageBucketId, WorkerId, Bytes]>;
+      /**
+       * Emits on updating the blacklist with data hashes.
+       * Params
+       * - hashes to remove from the blacklist
+       * - hashes to add to the blacklist
+       **/
+      UpdateBlacklist: AugmentedEvent<ApiType, [BTreeSet<Cid>, BTreeSet<Cid>]>;
+      /**
+       * Emits on changing the size-based pricing of new objects uploaded.
+       * Params
+       * - new status
+       **/
+      UploadingBlockStatusUpdated: AugmentedEvent<ApiType, [bool]>;
+      /**
+       * Emits on changing the voucher for a storage bucket.
+       * Params
+       * - storage bucket ID
+       * - new voucher
+       **/
+      VoucherChanged: AugmentedEvent<ApiType, [StorageBucketId, Voucher]>;
+    };
     storageWorkingGroup: {
       /**
        * Emits on accepting application for the worker opening.

+ 105 - 32
types/augment/augment-api-query.ts

@@ -3,7 +3,7 @@
 
 import type { Bytes, Option, Vec, bool, u32, u64 } from '@polkadot/types';
 import type { AnyNumber, ITuple, Observable } from '@polkadot/types/types';
-import type { Application, ApplicationId, ApplicationOf, Category, CategoryId, Channel, ChannelId, Class, ClassId, ClassOf, ClassPermissionsType, ContentId, Credential, Curator, CuratorApplication, CuratorApplicationId, CuratorGroup, CuratorGroupId, CuratorId, CuratorOpening, CuratorOpeningId, DataObject, DataObjectStorageRelationship, DataObjectStorageRelationshipId, DataObjectType, DataObjectTypeId, DiscussionPost, DiscussionThread, ElectionStage, ElectionStake, Entity, EntityController, EntityCreationVoucher, EntityId, EntityOf, HiringApplicationId, InputValidationLengthConstraint, Lead, LeadId, MemberId, Membership, MemoText, Mint, MintId, Opening, OpeningId, OpeningOf, PaidMembershipTerms, PaidTermId, Post, PostId, Principal, PrincipalId, PropertyId, ProposalDetailsOf, ProposalId, ProposalOf, Recipient, RecipientId, RewardRelationship, RewardRelationshipId, SealedVote, Seats, ServiceProviderRecord, Stake, StakeId, StorageProviderId, Thread, ThreadCounter, ThreadId, TransferableStake, Url, VoteKind, WorkerId, WorkerOf, WorkingGroupUnstaker } from './all';
+import type { Application, ApplicationId, ApplicationOf, Bag, BagId, Category, CategoryId, Channel, ChannelId, Cid, Class, ClassId, ClassOf, ClassPermissionsType, Credential, Curator, CuratorApplication, CuratorApplicationId, CuratorGroup, CuratorGroupId, CuratorId, CuratorOpening, CuratorOpeningId, DataObject, DataObjectId, DiscussionPost, DiscussionThread, DistributionBucketFamily, DistributionBucketFamilyId, DistributionBucketId, DynamicBagCreationPolicy, DynamicBagType, ElectionStage, ElectionStake, Entity, EntityController, EntityCreationVoucher, EntityId, EntityOf, HiringApplicationId, InputValidationLengthConstraint, Lead, LeadId, MemberId, Membership, MemoText, Mint, MintId, Opening, OpeningId, OpeningOf, PaidMembershipTerms, PaidTermId, Post, PostId, Principal, PrincipalId, PropertyId, ProposalDetailsOf, ProposalId, ProposalOf, Recipient, RecipientId, RewardRelationship, RewardRelationshipId, SealedVote, Seats, Stake, StakeId, StorageBucket, StorageBucketId, Thread, ThreadCounter, ThreadId, TransferableStake, VoteKind, WorkerId, WorkerOf, WorkingGroupUnstaker } from './all';
 import type { UncleEntryItem } from '@polkadot/types/interfaces/authorship';
 import type { BabeAuthorityWeight, MaybeRandomness, NextConfigDescriptor, Randomness } from '@polkadot/types/interfaces/babe';
 import type { AccountData, BalanceLock } from '@polkadot/types/interfaces/balances';
@@ -331,61 +331,60 @@ declare module '@polkadot/api/types/storage' {
       votes: AugmentedQuery<ApiType, (arg: Hash | string | Uint8Array) => Observable<SealedVote>, [Hash]>;
       votingPeriod: AugmentedQuery<ApiType, () => Observable<BlockNumber>, []>;
     };
-    dataDirectory: {
+    distributionWorkingGroup: {
       /**
-       * Maps data objects by their content id.
+       * Count of active workers.
        **/
-      dataObjectByContentId: AugmentedQuery<ApiType, (arg: ContentId | string | Uint8Array) => Observable<Option<DataObject>>, [ContentId]>;
+      activeWorkerCount: AugmentedQuery<ApiType, () => Observable<u32>, []>;
       /**
-       * List of ids known to the frame_system.
+       * Maps identifier to worker application on opening.
        **/
-      knownContentIds: AugmentedQuery<ApiType, () => Observable<Vec<ContentId>>, []>;
-    };
-    dataObjectStorageRegistry: {
+      applicationById: AugmentedQuery<ApiType, (arg: ApplicationId | AnyNumber | Uint8Array) => Observable<ApplicationOf>, [ApplicationId]>;
       /**
-       * Defines first relationship id.
+       * The current lead.
        **/
-      firstRelationshipId: AugmentedQuery<ApiType, () => Observable<DataObjectStorageRelationshipId>, []>;
+      currentLead: AugmentedQuery<ApiType, () => Observable<Option<WorkerId>>, []>;
       /**
-       * Defines next relationship id.
+       * Map member id by hiring application id.
+       * Required by StakingEventsHandler callback call to refund the balance on unstaking.
        **/
-      nextRelationshipId: AugmentedQuery<ApiType, () => Observable<DataObjectStorageRelationshipId>, []>;
+      memberIdByHiringApplicationId: AugmentedQuery<ApiType, (arg: HiringApplicationId | AnyNumber | Uint8Array) => Observable<MemberId>, [HiringApplicationId]>;
       /**
-       * Mapping of Data object types
+       * The mint currently funding the rewards for this module.
        **/
-      relationships: AugmentedQuery<ApiType, (arg: DataObjectStorageRelationshipId | AnyNumber | Uint8Array) => Observable<Option<DataObjectStorageRelationship>>, [DataObjectStorageRelationshipId]>;
+      mint: AugmentedQuery<ApiType, () => Observable<MintId>, []>;
       /**
-       * Keeps a list of storage relationships per content id.
+       * Next identifier value for new worker application.
        **/
-      relationshipsByContentId: AugmentedQuery<ApiType, (arg: ContentId | string | Uint8Array) => Observable<Vec<DataObjectStorageRelationshipId>>, [ContentId]>;
-    };
-    dataObjectTypeRegistry: {
+      nextApplicationId: AugmentedQuery<ApiType, () => Observable<ApplicationId>, []>;
       /**
-       * Mapping of Data object types.
+       * Next identifier value for new worker opening.
        **/
-      dataObjectTypes: AugmentedQuery<ApiType, (arg: DataObjectTypeId | AnyNumber | Uint8Array) => Observable<Option<DataObjectType>>, [DataObjectTypeId]>;
+      nextOpeningId: AugmentedQuery<ApiType, () => Observable<OpeningId>, []>;
       /**
-       * Data object type ids should start at this value.
+       * Next identifier for new worker.
        **/
-      firstDataObjectTypeId: AugmentedQuery<ApiType, () => Observable<DataObjectTypeId>, []>;
+      nextWorkerId: AugmentedQuery<ApiType, () => Observable<WorkerId>, []>;
       /**
-       * Provides id counter for the data object types.
+       * Maps identifier to worker opening.
        **/
-      nextDataObjectTypeId: AugmentedQuery<ApiType, () => Observable<DataObjectTypeId>, []>;
-    };
-    discovery: {
+      openingById: AugmentedQuery<ApiType, (arg: OpeningId | AnyNumber | Uint8Array) => Observable<OpeningOf>, [OpeningId]>;
       /**
-       * Mapping of service providers' storage provider id to their ServiceProviderRecord
+       * Opening human readable text length limits
        **/
-      accountInfoByStorageProviderId: AugmentedQuery<ApiType, (arg: StorageProviderId | AnyNumber | Uint8Array) => Observable<ServiceProviderRecord>, [StorageProviderId]>;
+      openingHumanReadableText: AugmentedQuery<ApiType, () => Observable<InputValidationLengthConstraint>, []>;
       /**
-       * Bootstrap endpoints maintained by root
+       * Worker application human readable text length limits
        **/
-      bootstrapEndpoints: AugmentedQuery<ApiType, () => Observable<Vec<Url>>, []>;
+      workerApplicationHumanReadableText: AugmentedQuery<ApiType, () => Observable<InputValidationLengthConstraint>, []>;
       /**
-       * Lifetime of an ServiceProviderRecord record in AccountInfoByAccountId map
+       * Maps identifier to corresponding worker.
        **/
-      defaultLifetime: AugmentedQuery<ApiType, () => Observable<BlockNumber>, []>;
+      workerById: AugmentedQuery<ApiType, (arg: WorkerId | AnyNumber | Uint8Array) => Observable<WorkerOf>, [WorkerId]>;
+      /**
+       * Worker exit rationale text length limits.
+       **/
+      workerExitRationaleText: AugmentedQuery<ApiType, () => Observable<InputValidationLengthConstraint>, []>;
     };
     forum: {
       /**
@@ -1012,6 +1011,80 @@ declare module '@polkadot/api/types/storage' {
        **/
       validatorSlashInEra: AugmentedQueryDoubleMap<ApiType, (key1: EraIndex | AnyNumber | Uint8Array, key2: AccountId | string | Uint8Array) => Observable<Option<ITuple<[Perbill, BalanceOf]>>>, [EraIndex, AccountId]>;
     };
+    storage: {
+      /**
+       * Bags storage map.
+       **/
+      bags: AugmentedQuery<ApiType, (arg: BagId | { Static: any } | { Dynamic: any } | string | Uint8Array) => Observable<Bag>, [BagId]>;
+      /**
+       * Blacklisted data object hashes.
+       **/
+      blacklist: AugmentedQuery<ApiType, (arg: Cid | string | Uint8Array) => Observable<ITuple<[]>>, [Cid]>;
+      /**
+       * Blacklist collection counter.
+       **/
+      currentBlacklistSize: AugmentedQuery<ApiType, () => Observable<u64>, []>;
+      /**
+       * Size based pricing of new objects uploaded.
+       **/
+      dataObjectPerMegabyteFee: AugmentedQuery<ApiType, () => Observable<BalanceOf>, []>;
+      /**
+       * 'Data objects for bags' storage double map.
+       **/
+      dataObjectsById: AugmentedQueryDoubleMap<ApiType, (key1: BagId | { Static: any } | { Dynamic: any } | string | Uint8Array, key2: DataObjectId | AnyNumber | Uint8Array) => Observable<DataObject>, [BagId, DataObjectId]>;
+      /**
+       * Distribution bucket families.
+       **/
+      distributionBucketFamilyById: AugmentedQuery<ApiType, (arg: DistributionBucketFamilyId | AnyNumber | Uint8Array) => Observable<DistributionBucketFamily>, [DistributionBucketFamilyId]>;
+      /**
+       * Total number of distribution bucket families in the system.
+       **/
+      distributionBucketFamilyNumber: AugmentedQuery<ApiType, () => Observable<u64>, []>;
+      /**
+       * "Distribution buckets per bag" number limit.
+       **/
+      distributionBucketsPerBagLimit: AugmentedQuery<ApiType, () => Observable<u64>, []>;
+      /**
+       * DynamicBagCreationPolicy by bag type storage map.
+       **/
+      dynamicBagCreationPolicies: AugmentedQuery<ApiType, (arg: DynamicBagType | 'Member' | 'Channel' | number | Uint8Array) => Observable<DynamicBagCreationPolicy>, [DynamicBagType]>;
+      /**
+       * Data object id counter. Starts at zero.
+       **/
+      nextDataObjectId: AugmentedQuery<ApiType, () => Observable<DataObjectId>, []>;
+      /**
+       * Distribution bucket family id counter. Starts at zero.
+       **/
+      nextDistributionBucketFamilyId: AugmentedQuery<ApiType, () => Observable<DistributionBucketFamilyId>, []>;
+      /**
+       * Distribution bucket id counter. Starts at zero.
+       **/
+      nextDistributionBucketId: AugmentedQuery<ApiType, () => Observable<DistributionBucketId>, []>;
+      /**
+       * Storage bucket id counter. Starts at zero.
+       **/
+      nextStorageBucketId: AugmentedQuery<ApiType, () => Observable<StorageBucketId>, []>;
+      /**
+       * Storage buckets.
+       **/
+      storageBucketById: AugmentedQuery<ApiType, (arg: StorageBucketId | AnyNumber | Uint8Array) => Observable<StorageBucket>, [StorageBucketId]>;
+      /**
+       * "Storage buckets per bag" number limit.
+       **/
+      storageBucketsPerBagLimit: AugmentedQuery<ApiType, () => Observable<u64>, []>;
+      /**
+       * Defines whether all new uploads blocked
+       **/
+      uploadingBlocked: AugmentedQuery<ApiType, () => Observable<bool>, []>;
+      /**
+       * "Max objects number for a storage bucket voucher" number limit.
+       **/
+      voucherMaxObjectsNumberLimit: AugmentedQuery<ApiType, () => Observable<u64>, []>;
+      /**
+       * "Max objects size for a storage bucket voucher" number limit.
+       **/
+      voucherMaxObjectsSizeLimit: AugmentedQuery<ApiType, () => Observable<u64>, []>;
+    };
     storageWorkingGroup: {
       /**
        * Count of active workers.

+ 183 - 52
types/augment/augment-api-tx.ts

@@ -3,7 +3,7 @@
 
 import type { BTreeMap, BTreeSet, Bytes, Compact, Option, Vec, bool, u16, u32, u64 } from '@polkadot/types';
 import type { AnyNumber, ITuple } from '@polkadot/types/types';
-import type { ActivateOpeningAt, Actor, AddOpeningParameters, ApplicationId, ApplicationIdSet, BalanceOfMint, CategoryId, ChannelContentType, ChannelCurationStatus, ChannelId, ChannelPublicationStatus, ClassId, ClassPermissions, ClassPermissionsType, ClassPropertyValue, ContentId, Credential, CredentialSet, CurationActor, CuratorApplicationId, CuratorApplicationIdSet, CuratorGroupId, CuratorId, CuratorOpeningId, DataObjectStorageRelationshipId, DataObjectType, DataObjectTypeId, DataObjectsMap, ElectionParameters, EntityController, EntityId, EntityPermissions, FillOpeningParameters, InputPropertyValue, InputValue, MemberId, MemoText, Nonce, OpeningId, OpeningPolicyCommitment, OpeningType, Operation, OperationType, OptionalText, PaidTermId, PostId, Property, PropertyId, ProposalId, ReferenceConstraint, RewardPolicy, SchemaId, StorageProviderId, TerminateRoleParameters, ThreadId, Url, VecMaxLength, VoteKind, WorkerId, WorkingGroup } from './all';
+import type { ActivateOpeningAt, Actor, AddOpeningParameters, ApplicationId, ApplicationIdSet, BagId, BalanceOfMint, CategoryId, ChannelContentType, ChannelCurationStatus, ChannelId, ChannelPublicationStatus, Cid, ClassId, ClassPermissions, ClassPermissionsType, ClassPropertyValue, Credential, CredentialSet, CurationActor, CuratorApplicationId, CuratorApplicationIdSet, CuratorGroupId, CuratorId, CuratorOpeningId, DataObjectId, DistributionBucketFamilyId, DistributionBucketId, DynamicBagDeletionPrize, DynamicBagId, DynamicBagType, ElectionParameters, EntityController, EntityId, EntityPermissions, FillOpeningParameters, InputPropertyValue, InputValue, MemberId, MemoText, Nonce, OpeningId, OpeningPolicyCommitment, OpeningType, Operation, OperationType, OptionalText, PaidTermId, PostId, Property, PropertyId, ProposalId, ReferenceConstraint, RewardPolicy, SchemaId, StorageBucketId, TerminateRoleParameters, ThreadId, UploadParameters, VecMaxLength, VoteKind, WorkerId, WorkingGroup } from './all';
 import type { BabeEquivocationProof } from '@polkadot/types/interfaces/babe';
 import type { Extrinsic, Signature } from '@polkadot/types/interfaces/extrinsics';
 import type { GrandpaEquivocationProof, KeyOwnerProof } from '@polkadot/types/interfaces/grandpa';
@@ -430,89 +430,82 @@ declare module '@polkadot/api/types/submittable' {
       setStageVoting: AugmentedSubmittable<(endsAt: BlockNumber | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [BlockNumber]>;
       vote: AugmentedSubmittable<(commitment: Hash | string | Uint8Array, stake: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [Hash, BalanceOf]>;
     };
-    dataDirectory: {
+    distributionWorkingGroup: {
       /**
-       * Storage provider accepts a content. Requires signed storage provider account and its id.
-       * The LiaisonJudgement can be updated, but only by the liaison.
+       * Begin accepting worker applications to an opening that is active.
+       * Require signed leader origin or the root (to accept applications for the leader position).
        **/
-      acceptContent: AugmentedSubmittable<(storageProviderId: StorageProviderId | AnyNumber | Uint8Array, contentId: ContentId | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageProviderId, ContentId]>;
+      acceptApplications: AugmentedSubmittable<(openingId: OpeningId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [OpeningId]>;
       /**
-       * Adds the content to the frame_system. Member id should match its origin. The created DataObject
-       * awaits liaison to accept or reject it.
+       * Add an opening for a worker role.
+       * Require signed leader origin or the root (to add opening for the leader position).
        **/
-      addContent: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, contentId: ContentId | string | Uint8Array, typeId: DataObjectTypeId | AnyNumber | Uint8Array, size: u64 | AnyNumber | Uint8Array, ipfsContentId: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, ContentId, DataObjectTypeId, u64, Bytes]>;
+      addOpening: AugmentedSubmittable<(activateAt: ActivateOpeningAt | { CurrentBlock: any } | { ExactBlock: any } | string | Uint8Array, commitment: OpeningPolicyCommitment | { application_rationing_policy?: any; max_review_period_length?: any; application_staking_policy?: any; role_staking_policy?: any; role_slashing_terms?: any; fill_opening_successful_applicant_application_stake_unstaking_period?: any; fill_opening_failed_applicant_application_stake_unstaking_period?: any; fill_opening_failed_applicant_role_stake_unstaking_period?: any; terminate_curator_application_stake_unstaking_period?: any; terminate_curator_role_stake_unstaking_period?: any; exit_curator_role_application_stake_unstaking_period?: any; exit_curator_role_stake_unstaking_period?: any } | string | Uint8Array, humanReadableText: Bytes | string | Uint8Array, openingType: OpeningType | 'Leader' | 'Worker' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [ActivateOpeningAt, OpeningPolicyCommitment, Bytes, OpeningType]>;
       /**
-       * Injects a set of data objects and their corresponding content id into the directory.
-       * The operation is "silent" - no events will be emitted as objects are added.
-       * The number of objects that can be added per call is limited to prevent the dispatch
-       * from causing the block production to fail if it takes too much time to process.
-       * Existing data objects will be overwritten.
+       * Apply on a worker opening.
        **/
-      injectDataObjects: AugmentedSubmittable<(objects: DataObjectsMap) => SubmittableExtrinsic<ApiType>, [DataObjectsMap]>;
+      applyOnOpening: AugmentedSubmittable<(memberId: MemberId | AnyNumber | Uint8Array, openingId: OpeningId | AnyNumber | Uint8Array, roleAccountId: AccountId | string | Uint8Array, optRoleStakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, optApplicationStakeBalance: Option<BalanceOf> | null | object | string | Uint8Array, humanReadableText: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [MemberId, OpeningId, AccountId, Option<BalanceOf>, Option<BalanceOf>, Bytes]>;
       /**
-       * Storage provider rejects a content. Requires signed storage provider account and its id.
-       * The LiaisonJudgement can be updated, but only by the liaison.
+       * Begin reviewing, and therefore not accepting new applications.
+       * Require signed leader origin or the root (to begin review applications for the leader position).
        **/
-      rejectContent: AugmentedSubmittable<(storageProviderId: StorageProviderId | AnyNumber | Uint8Array, contentId: ContentId | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageProviderId, ContentId]>;
+      beginApplicantReview: AugmentedSubmittable<(openingId: OpeningId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [OpeningId]>;
       /**
-       * Removes the content id from the list of known content ids. Requires root privileges.
+       * Decreases the worker/lead stake and returns the remainder to the worker role_account_id.
+       * Can be decreased to zero, no actions on zero stake.
+       * Require signed leader origin or the root (to decrease the leader stake).
        **/
-      removeKnownContentId: AugmentedSubmittable<(contentId: ContentId | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [ContentId]>;
-    };
-    dataObjectStorageRegistry: {
+      decreaseStake: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, balance: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOf]>;
       /**
-       * Add storage provider-to-content relationship. The storage provider should be registered
-       * in the storage working group.
+       * Fill opening for worker/lead.
+       * Require signed leader origin or the root (to fill opening for the leader position).
        **/
-      addRelationship: AugmentedSubmittable<(storageProviderId: StorageProviderId | AnyNumber | Uint8Array, cid: ContentId | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageProviderId, ContentId]>;
+      fillOpening: AugmentedSubmittable<(openingId: OpeningId | AnyNumber | Uint8Array, successfulApplicationIds: ApplicationIdSet, rewardPolicy: Option<RewardPolicy> | null | object | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [OpeningId, ApplicationIdSet, Option<RewardPolicy>]>;
       /**
-       * Activates storage provider-to-content relationship. The storage provider should be registered
-       * in the storage working group. A storage provider may flip their own ready state, but nobody else.
+       * Increases the worker/lead stake, demands a worker origin. Transfers tokens from the worker
+       * role_account_id to the stake. No limits on the stake.
        **/
-      setRelationshipReady: AugmentedSubmittable<(storageProviderId: StorageProviderId | AnyNumber | Uint8Array, id: DataObjectStorageRelationshipId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageProviderId, DataObjectStorageRelationshipId]>;
+      increaseStake: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, balance: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOf]>;
       /**
-       * Deactivates storage provider-to-content relationship. The storage provider should be registered
-       * in the storage working group. A storage provider may flip their own ready state, but nobody else.
+       * Leave the role by the active worker.
        **/
-      unsetRelationshipReady: AugmentedSubmittable<(storageProviderId: StorageProviderId | AnyNumber | Uint8Array, id: DataObjectStorageRelationshipId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageProviderId, DataObjectStorageRelationshipId]>;
-    };
-    dataObjectTypeRegistry: {
+      leaveRole: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, rationaleText: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, Bytes]>;
       /**
-       * Activates existing data object type. Requires leader privileges.
+       * Sets the capacity to enable working group budget. Requires root origin.
        **/
-      activateDataObjectType: AugmentedSubmittable<(id: DataObjectTypeId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [DataObjectTypeId]>;
+      setMintCapacity: AugmentedSubmittable<(newCapacity: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [BalanceOf]>;
       /**
-       * Deactivates existing data object type. Requires leader privileges.
+       * Slashes the worker stake, demands a leader origin. No limits, no actions on zero stake.
+       * If slashing balance greater than the existing stake - stake is slashed to zero.
+       * Require signed leader origin or the root (to slash the leader stake).
        **/
-      deactivateDataObjectType: AugmentedSubmittable<(id: DataObjectTypeId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [DataObjectTypeId]>;
+      slashStake: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, balance: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOf]>;
       /**
-       * Registers the new data object type. Requires leader privileges.
+       * Terminate the worker application. Can be done by the lead only.
        **/
-      registerDataObjectType: AugmentedSubmittable<(dataObjectType: DataObjectType | { description?: any; active?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [DataObjectType]>;
+      terminateApplication: AugmentedSubmittable<(applicationId: ApplicationId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ApplicationId]>;
       /**
-       * Updates existing data object type. Requires leader privileges.
+       * Terminate the active worker by the lead.
+       * Require signed leader origin or the root (to terminate the leader role).
        **/
-      updateDataObjectType: AugmentedSubmittable<(id: DataObjectTypeId | AnyNumber | Uint8Array, dataObjectType: DataObjectType | { description?: any; active?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [DataObjectTypeId, DataObjectType]>;
-    };
-    discovery: {
+      terminateRole: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, rationaleText: Bytes | string | Uint8Array, slashStake: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, Bytes, bool]>;
       /**
-       * Sets bootstrap endpoints for the Colossus. Requires root privileges.
+       * Update the reward account associated with a set reward relationship for the active worker.
        **/
-      setBootstrapEndpoints: AugmentedSubmittable<(endpoints: Vec<Url> | (Url | string)[]) => SubmittableExtrinsic<ApiType>, [Vec<Url>]>;
+      updateRewardAccount: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, newRewardAccountId: AccountId | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, AccountId]>;
       /**
-       * Sets default lifetime for storage providers accounts info. Requires root privileges.
+       * Update the reward amount associated with a set reward relationship for the active worker.
+       * Require signed leader origin or the root (to update leader reward amount).
        **/
-      setDefaultLifetime: AugmentedSubmittable<(lifetime: BlockNumber | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [BlockNumber]>;
+      updateRewardAmount: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, newAmount: BalanceOfMint | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, BalanceOfMint]>;
       /**
-       * Creates the ServiceProviderRecord to save an IPNS identity for the storage provider.
-       * Requires signed storage provider credentials.
+       * Update the associated role account of the active worker/lead.
        **/
-      setIpnsId: AugmentedSubmittable<(storageProviderId: StorageProviderId | AnyNumber | Uint8Array, id: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageProviderId, Bytes]>;
+      updateRoleAccount: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, newRoleAccountId: AccountId | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, AccountId]>;
       /**
-       * Deletes the ServiceProviderRecord with the IPNS identity for the storage provider.
-       * Requires signed storage provider credentials.
+       * Withdraw the worker application. Can be done by the worker itself only.
        **/
-      unsetIpnsId: AugmentedSubmittable<(storageProviderId: StorageProviderId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageProviderId]>;
+      withdrawApplication: AugmentedSubmittable<(applicationId: ApplicationId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [ApplicationId]>;
     };
     finalityTracker: {
       /**
@@ -1244,6 +1237,144 @@ declare module '@polkadot/api/types/submittable' {
        **/
       withdrawUnbonded: AugmentedSubmittable<(numSlashingSpans: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
     };
+    storage: {
+      /**
+       * Accept pending invite.
+       **/
+      acceptDistributionBucketInvitation: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, distributionBucketId: DistributionBucketId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, DistributionBucketFamilyId, DistributionBucketId]>;
+      /**
+       * A storage provider signals that the data object was successfully uploaded to its storage.
+       **/
+      acceptPendingDataObjects: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, storageBucketId: StorageBucketId | AnyNumber | Uint8Array, bagId: BagId | { Static: any } | { Dynamic: any } | string | Uint8Array, dataObjects: BTreeSet<DataObjectId>) => SubmittableExtrinsic<ApiType>, [WorkerId, StorageBucketId, BagId, BTreeSet<DataObjectId>]>;
+      /**
+       * Accept the storage bucket invitation. An invitation must match the worker_id parameter.
+       **/
+      acceptStorageBucketInvitation: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, storageBucketId: StorageBucketId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, StorageBucketId]>;
+      /**
+       * Cancel pending invite. Must be pending.
+       **/
+      cancelDistributionBucketOperatorInvite: AugmentedSubmittable<(familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, distributionBucketId: DistributionBucketId | AnyNumber | Uint8Array, operatorWorkerId: WorkerId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [DistributionBucketFamilyId, DistributionBucketId, WorkerId]>;
+      /**
+       * Cancel pending storage bucket invite. An invitation must be pending.
+       **/
+      cancelStorageBucketOperatorInvite: AugmentedSubmittable<(storageBucketId: StorageBucketId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageBucketId]>;
+      /**
+       * Create a distribution bucket.
+       **/
+      createDistributionBucket: AugmentedSubmittable<(familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, acceptingNewBags: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [DistributionBucketFamilyId, bool]>;
+      /**
+       * Create a distribution bucket family.
+       **/
+      createDistributionBucketFamily: AugmentedSubmittable<() => SubmittableExtrinsic<ApiType>, []>;
+      /**
+       * Create storage bucket.
+       **/
+      createStorageBucket: AugmentedSubmittable<(inviteWorker: Option<WorkerId> | null | object | string | Uint8Array, acceptingNewBags: bool | boolean | Uint8Array, sizeLimit: u64 | AnyNumber | Uint8Array, objectsLimit: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [Option<WorkerId>, bool, u64, u64]>;
+      /**
+       * Delete distribution bucket. Must be empty.
+       **/
+      deleteDistributionBucket: AugmentedSubmittable<(familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, distributionBucketId: DistributionBucketId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [DistributionBucketFamilyId, DistributionBucketId]>;
+      /**
+       * Deletes a distribution bucket family.
+       **/
+      deleteDistributionBucketFamily: AugmentedSubmittable<(familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [DistributionBucketFamilyId]>;
+      /**
+       * Delete storage bucket. Must be empty. Storage operator must be missing.
+       **/
+      deleteStorageBucket: AugmentedSubmittable<(storageBucketId: StorageBucketId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageBucketId]>;
+      /**
+       * Invite an operator. Must be missing.
+       **/
+      inviteDistributionBucketOperator: AugmentedSubmittable<(familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, distributionBucketId: DistributionBucketId | AnyNumber | Uint8Array, operatorWorkerId: WorkerId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [DistributionBucketFamilyId, DistributionBucketId, WorkerId]>;
+      /**
+       * Invite storage bucket operator. Must be missing.
+       **/
+      inviteStorageBucketOperator: AugmentedSubmittable<(storageBucketId: StorageBucketId | AnyNumber | Uint8Array, operatorId: WorkerId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageBucketId, WorkerId]>;
+      /**
+       * Removes distribution bucket operator.
+       **/
+      removeDistributionBucketOperator: AugmentedSubmittable<(familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, distributionBucketId: DistributionBucketId | AnyNumber | Uint8Array, operatorWorkerId: WorkerId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [DistributionBucketFamilyId, DistributionBucketId, WorkerId]>;
+      /**
+       * Removes storage bucket operator.
+       **/
+      removeStorageBucketOperator: AugmentedSubmittable<(storageBucketId: StorageBucketId | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageBucketId]>;
+      /**
+       * Set distribution bucket family metadata.
+       **/
+      setDistributionBucketFamilyMetadata: AugmentedSubmittable<(familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, metadata: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [DistributionBucketFamilyId, Bytes]>;
+      /**
+       * Set distribution operator metadata for the distribution bucket.
+       **/
+      setDistributionOperatorMetadata: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, distributionBucketId: DistributionBucketId | AnyNumber | Uint8Array, metadata: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, DistributionBucketFamilyId, DistributionBucketId, Bytes]>;
+      /**
+       * Sets storage bucket voucher limits.
+       **/
+      setStorageBucketVoucherLimits: AugmentedSubmittable<(storageBucketId: StorageBucketId | AnyNumber | Uint8Array, newObjectsSizeLimit: u64 | AnyNumber | Uint8Array, newObjectsNumberLimit: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageBucketId, u64, u64]>;
+      /**
+       * Sets storage operator metadata (eg.: storage node URL).
+       **/
+      setStorageOperatorMetadata: AugmentedSubmittable<(workerId: WorkerId | AnyNumber | Uint8Array, storageBucketId: StorageBucketId | AnyNumber | Uint8Array, metadata: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [WorkerId, StorageBucketId, Bytes]>;
+      /**
+       * Create a dynamic bag. Development mode.
+       **/
+      sudoCreateDynamicBag: AugmentedSubmittable<(bagId: DynamicBagId | { Member: any } | { Channel: any } | string | Uint8Array, deletionPrize: Option<DynamicBagDeletionPrize> | null | object | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [DynamicBagId, Option<DynamicBagDeletionPrize>]>;
+      /**
+       * Upload new data objects. Development mode.
+       **/
+      sudoUploadDataObjects: AugmentedSubmittable<(params: UploadParameters | { authenticationKey?: any; bagId?: any; objectCreationList?: any; deletionPrizeSourceAccountId?: any; expectedDataSizeFee?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [UploadParameters]>;
+      /**
+       * Add and remove hashes to the current blacklist.
+       **/
+      updateBlacklist: AugmentedSubmittable<(removeHashes: BTreeSet<Cid>, addHashes: BTreeSet<Cid>) => SubmittableExtrinsic<ApiType>, [BTreeSet<Cid>, BTreeSet<Cid>]>;
+      /**
+       * Updates size-based pricing of new objects uploaded.
+       **/
+      updateDataSizeFee: AugmentedSubmittable<(newDataSizeFee: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [BalanceOf]>;
+      /**
+       * Updates 'distributing' flag for the distributing flag.
+       **/
+      updateDistributionBucketMode: AugmentedSubmittable<(familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, distributionBucketId: DistributionBucketId | AnyNumber | Uint8Array, distributing: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [DistributionBucketFamilyId, DistributionBucketId, bool]>;
+      /**
+       * Updates a distribution bucket 'accepts new bags' flag.
+       **/
+      updateDistributionBucketStatus: AugmentedSubmittable<(familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, distributionBucketId: DistributionBucketId | AnyNumber | Uint8Array, acceptingNewBags: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [DistributionBucketFamilyId, DistributionBucketId, bool]>;
+      /**
+       * Updates distribution buckets for a bag.
+       **/
+      updateDistributionBucketsForBag: AugmentedSubmittable<(bagId: BagId | { Static: any } | { Dynamic: any } | string | Uint8Array, familyId: DistributionBucketFamilyId | AnyNumber | Uint8Array, addBuckets: BTreeSet<DistributionBucketId>, removeBuckets: BTreeSet<DistributionBucketId>) => SubmittableExtrinsic<ApiType>, [BagId, DistributionBucketFamilyId, BTreeSet<DistributionBucketId>, BTreeSet<DistributionBucketId>]>;
+      /**
+       * Updates "Distribution buckets per bag" number limit.
+       **/
+      updateDistributionBucketsPerBagLimit: AugmentedSubmittable<(newLimit: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u64]>;
+      /**
+       * Update number of distributed buckets used in given dynamic bag creation policy.
+       **/
+      updateFamiliesInDynamicBagCreationPolicy: AugmentedSubmittable<(dynamicBagType: DynamicBagType | 'Member' | 'Channel' | number | Uint8Array, families: BTreeMap<DistributionBucketFamilyId, u32>) => SubmittableExtrinsic<ApiType>, [DynamicBagType, BTreeMap<DistributionBucketFamilyId, u32>]>;
+      /**
+       * Update number of storage buckets used in given dynamic bag creation policy.
+       **/
+      updateNumberOfStorageBucketsInDynamicBagCreationPolicy: AugmentedSubmittable<(dynamicBagType: DynamicBagType | 'Member' | 'Channel' | number | Uint8Array, numberOfStorageBuckets: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [DynamicBagType, u64]>;
+      /**
+       * Update whether new bags are being accepted for storage.
+       **/
+      updateStorageBucketStatus: AugmentedSubmittable<(storageBucketId: StorageBucketId | AnyNumber | Uint8Array, acceptingNewBags: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [StorageBucketId, bool]>;
+      /**
+       * Updates storage buckets for a bag..
+       **/
+      updateStorageBucketsForBag: AugmentedSubmittable<(bagId: BagId | { Static: any } | { Dynamic: any } | string | Uint8Array, addBuckets: BTreeSet<StorageBucketId>, removeBuckets: BTreeSet<StorageBucketId>) => SubmittableExtrinsic<ApiType>, [BagId, BTreeSet<StorageBucketId>, BTreeSet<StorageBucketId>]>;
+      /**
+       * Updates "Storage buckets per bag" number limit.
+       **/
+      updateStorageBucketsPerBagLimit: AugmentedSubmittable<(newLimit: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u64]>;
+      /**
+       * Updates "Storage buckets voucher max limits".
+       **/
+      updateStorageBucketsVoucherMaxLimits: AugmentedSubmittable<(newObjectsSize: u64 | AnyNumber | Uint8Array, newObjectsNumber: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u64, u64]>;
+      /**
+       * Updates global uploading flag.
+       **/
+      updateUploadingBlockedStatus: AugmentedSubmittable<(newStatus: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [bool]>;
+    };
     storageWorkingGroup: {
       /**
        * Begin accepting worker applications to an opening that is active.

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
types/augment/augment-types.ts


+ 3 - 3
types/package.json

@@ -1,7 +1,7 @@
 {
   "name": "@joystream/types",
-  "version": "0.15.0",
-  "description": "Types for Joystream Substrate Runtime - Antioch release",
+  "version": "0.17.0",
+  "description": "Types for Joystream Substrate Runtime - Giza release",
   "main": "index.js",
   "types": "index.d.ts",
   "scripts": {
@@ -33,7 +33,7 @@
   },
   "devDependencies": {
     "@polkadot/typegen": "4.2.1",
-    "ts-node": "^8.6.2",
+    "ts-node": "^8.8.2",
     "typescript": "^3.7.2",
     "madge": "^3.9.2",
     "json-schema-to-typescript": "^9.1.1"

+ 2 - 1
types/src/common.ts

@@ -1,4 +1,4 @@
-import { Struct, Option, Text, bool, u16, u32, u64, Null, U8aFixed, BTreeSet, UInt } from '@polkadot/types'
+import { Struct, Option, Text, bool, u16, u32, u64, Null, U8aFixed, BTreeSet, UInt, u128 } from '@polkadot/types'
 import { BlockNumber, Hash as PolkadotHash, Moment } from '@polkadot/types/interfaces'
 import { Codec, Constructor, RegistryTypes } from '@polkadot/types/types'
 import { u8aConcat, u8aToHex, compactToU8a } from '@polkadot/util'
@@ -135,6 +135,7 @@ export class MemoText extends Text {}
 // see: https://polkadot.js.org/api/start/FAQ.html#the-node-returns-a-could-not-convert-error-on-send
 export class Address extends AccountId {}
 export class LookupSource extends AccountId {}
+export class BalanceOf extends u128 {}
 
 export const commonTypes: RegistryTypes = {
   Credential,

+ 4 - 3
types/src/index.ts

@@ -11,9 +11,10 @@ import hiring from './hiring'
 import contentWorkingGroup from './content-working-group'
 import workingGroup from './working-group'
 import discovery from './discovery'
-import media from './media'
 import proposals from './proposals'
 import contentDirectory from './content-directory'
+import storage from './storage'
+
 import { InterfaceTypes } from '@polkadot/types/types/registry'
 import { TypeRegistry, Text, UInt, Null, bool, Option, Vec, BTreeSet, BTreeMap } from '@polkadot/types'
 import { ExtendedEnum } from './JoyEnum'
@@ -33,9 +34,9 @@ export {
   contentWorkingGroup,
   workingGroup,
   discovery,
-  media,
   proposals,
   contentDirectory,
+  storage,
 }
 
 export const types: RegistryTypes = {
@@ -51,9 +52,9 @@ export const types: RegistryTypes = {
   ...contentWorkingGroup,
   ...workingGroup,
   ...discovery,
-  ...media,
   ...proposals,
   ...contentDirectory,
+  ...storage,
 }
 
 // Allows creating types without api instance (it's not a recommended way though, so should be used just for mocks)

+ 0 - 82
types/src/media.ts

@@ -1,82 +0,0 @@
-import { Option, Vec as Vector, BTreeMap, u64, bool, Text, Null } from '@polkadot/types'
-import { BlockAndTime, JoyEnum, JoyStructDecorated, Hash } from './common'
-import { MemberId } from './members'
-import { StorageProviderId } from './working-group' // this should be in discovery really
-import { randomAsU8a } from '@polkadot/util-crypto'
-import { encodeAddress, decodeAddress } from '@polkadot/keyring'
-import { RegistryTypes, Registry } from '@polkadot/types/types'
-
-export class ContentId extends Hash {
-  static generate(registry: Registry): ContentId {
-    // randomAsU8a uses https://www.npmjs.com/package/tweetnacl#random-bytes-generation
-    return new ContentId(registry, randomAsU8a())
-  }
-
-  static decode(registry: Registry, contentId: string): ContentId {
-    return new ContentId(registry, decodeAddress(contentId))
-  }
-
-  static encode(contentId: Uint8Array): string {
-    // console.log('contentId:', Buffer.from(contentId).toString('hex'))
-    return encodeAddress(contentId)
-  }
-
-  encode(): string {
-    return ContentId.encode(this)
-  }
-}
-
-export class DataObjectTypeId extends u64 {}
-export class DataObjectStorageRelationshipId extends u64 {}
-
-export class VecContentId extends Vector.with(ContentId) {}
-export class OptionVecContentId extends Option.with(VecContentId) {}
-
-export const LiaisonJudgementDef = {
-  Pending: Null,
-  Accepted: Null,
-  Rejected: Null,
-} as const
-export type LiaisonJudgementKey = keyof typeof LiaisonJudgementDef
-export class LiaisonJudgement extends JoyEnum(LiaisonJudgementDef) {}
-
-export class DataObject extends JoyStructDecorated({
-  owner: MemberId,
-  added_at: BlockAndTime,
-  type_id: DataObjectTypeId,
-  size: u64,
-  liaison: StorageProviderId,
-  liaison_judgement: LiaisonJudgement,
-  ipfs_content_id: Text,
-}) {
-  /** Actually it's 'size', but 'size' is already reserved by a parent class. */
-  get size_in_bytes(): u64 {
-    return this.get('size') as u64
-  }
-}
-
-export class DataObjectStorageRelationship extends JoyStructDecorated({
-  content_id: ContentId,
-  storage_provider: StorageProviderId,
-  ready: bool,
-}) {}
-
-export class DataObjectType extends JoyStructDecorated({
-  description: Text,
-  active: bool,
-}) {}
-
-export class DataObjectsMap extends BTreeMap.with(ContentId, DataObject) {}
-
-export const mediaTypes: RegistryTypes = {
-  ContentId,
-  LiaisonJudgement,
-  DataObject,
-  DataObjectStorageRelationshipId,
-  DataObjectStorageRelationship,
-  DataObjectTypeId,
-  DataObjectType,
-  DataObjectsMap,
-}
-
-export default mediaTypes

+ 2 - 2
types/src/scripts/generateAugmentCodec.ts

@@ -20,9 +20,9 @@ import hiring from '../hiring'
 import contentWorkingGroup from '../content-working-group'
 import workingGroup from '../working-group'
 import discovery from '../discovery'
-import media from '../media'
 import proposals from '../proposals'
 import contentDirectory from '../content-directory'
+import storage from '../storage'
 
 const AUGMENT_INTERFACES_PATH = path.join(__dirname, '../../augment')
 const AUGMENT_CODEC_PATH = path.join(__dirname, '../../augment-codec')
@@ -42,9 +42,9 @@ const typesByModule = {
   'content-working-group': contentWorkingGroup,
   'working-group': workingGroup,
   'discovery': discovery,
-  'media': media,
   'proposals': proposals,
   'content-directory': contentDirectory,
+  'storage': storage,
 }
 
 type Imports = { [moduleName: string]: string[] }

+ 245 - 0
types/src/storage.ts

@@ -0,0 +1,245 @@
+import { Null, u64, Bytes, Vec, bool, GenericAccountId as AccountId, BTreeSet, BTreeMap, Option } from '@polkadot/types'
+import { RegistryTypes } from '@polkadot/types/types'
+import { JoyBTreeSet, JoyEnum, JoyStructDecorated, WorkingGroup, BalanceOf } from './common'
+import { MemberId } from './members'
+import { WorkerId } from './working-group'
+
+export class DataObjectId extends u64 {}
+export class StorageBucketId extends u64 {}
+
+export type IStorageBucketsPerBagValueConstraint = {
+  min: u64
+  max_min_diff: u64
+}
+
+export class StorageBucketsPerBagValueConstraint
+  extends JoyStructDecorated({
+    min: u64,
+    max_min_diff: u64,
+  })
+  implements IStorageBucketsPerBagValueConstraint {}
+
+export type IDataObject = {
+  accepted: bool
+  deletion_prize: BalanceOf
+  size: u64
+}
+
+export class DataObject
+  extends JoyStructDecorated({
+    accepted: bool,
+    deletion_prize: BalanceOf,
+    size: u64,
+  })
+  implements IDataObject {}
+
+export class DataObjectIdSet extends JoyBTreeSet(DataObjectId) {}
+export class DistributionBucketId extends u64 {}
+export class DistributionBucketFamilyId extends u64 {}
+export class StorageBucketIdSet extends JoyBTreeSet(StorageBucketId) {}
+export class DistributionBucketSet extends JoyBTreeSet(DistributionBucketId) {}
+
+export type IDynamicBagDeletionPrize = {
+  account_id: AccountId
+  prize: BalanceOf
+}
+
+export class DynamicBagDeletionPrize
+  extends JoyStructDecorated({
+    account_id: AccountId,
+    prize: BalanceOf,
+  })
+  implements IDynamicBagDeletionPrize {}
+
+export class DynamicBagDeletionPrizeRecord extends DynamicBagDeletionPrize {}
+
+export type IBag = {
+  objects: BTreeMap<DataObjectId, DataObject>
+  stored_by: StorageBucketIdSet
+  distributed_by: DistributionBucketSet
+  deletion_prize: Option<BalanceOf>
+}
+
+export class Bag
+  extends JoyStructDecorated({
+    objects: BTreeMap.with(DataObjectId, DataObject),
+    stored_by: StorageBucketIdSet,
+    distributed_by: DistributionBucketSet,
+    deletion_prize: Option.with(BalanceOf),
+  })
+  implements IBag {}
+
+export type IDynamicBagCreationPolicy = {
+  numberOfStorageBuckets: u64
+}
+
+export class DynamicBagCreationPolicy
+  extends JoyStructDecorated({
+    numberOfStorageBuckets: u64,
+  })
+  implements IDynamicBagCreationPolicy {}
+
+export const DynamicBagTypeDef = {
+  Member: Null,
+  Channel: Null,
+} as const
+export type DynamicBagTypeKey = keyof typeof DynamicBagTypeDef
+export class DynamicBagType extends JoyEnum(DynamicBagTypeDef) {}
+
+export const StaticBagIdDef = {
+  Council: Null,
+  WorkingGroup: WorkingGroup,
+} as const
+export class StaticBagId extends JoyEnum(StaticBagIdDef) {}
+export class Static extends StaticBagId {}
+
+// This type should be imported from content-directory/common types once the Olympia release is merged.
+export class ChannelId extends u64 {}
+
+export const DynamicBagIdDef = {
+  Member: MemberId,
+  Channel: ChannelId,
+} as const
+export class DynamicBagId extends JoyEnum(DynamicBagIdDef) {}
+export class Dynamic extends DynamicBagId {}
+
+export const BagIdDef = {
+  Static,
+  Dynamic,
+} as const
+export class BagId extends JoyEnum(BagIdDef) {}
+
+// Alias
+export class BagIdType extends BagId {}
+
+export type IVoucher = {
+  sizeLimit: u64
+  objectsLimit: u64
+  sizeUsed: u64
+  objectsUsed: u64
+}
+
+export class Voucher
+  extends JoyStructDecorated({
+    sizeLimit: u64,
+    objectsLimit: u64,
+    sizeUsed: u64,
+    objectsUsed: u64,
+  })
+  implements IVoucher {}
+
+export const StorageBucketOperatorStatusDef = {
+  Missing: Null,
+  InvitedStorageWorker: WorkerId,
+  StorageWorker: WorkerId,
+} as const
+export class StorageBucketOperatorStatus extends JoyEnum(StorageBucketOperatorStatusDef) {}
+
+export type IStorageBucket = {
+  operator_status: StorageBucketOperatorStatus
+  accepting_new_bags: bool
+  voucher: Voucher
+  metadata: Bytes
+}
+
+export class StorageBucket
+  extends JoyStructDecorated({
+    operator_status: StorageBucketOperatorStatus,
+    accepting_new_bags: bool,
+    voucher: Voucher,
+    metadata: Bytes,
+  })
+  implements IStorageBucket {}
+
+export type IDataObjectCreationParameters = {
+  size: u64
+  ipfsContentId: Bytes
+}
+
+export class DataObjectCreationParameters
+  extends JoyStructDecorated({
+    size: u64,
+    ipfsContentId: Bytes,
+  })
+  implements IDataObjectCreationParameters {}
+
+export type IUploadParameters = {
+  authenticationKey: Bytes
+  bagId: BagId
+  objectCreationList: Vec<DataObjectCreationParameters>
+  deletionPrizeSourceAccountId: AccountId
+  expectedDataSizeFee: BalanceOf
+}
+
+export class UploadParameters
+  extends JoyStructDecorated({
+    authenticationKey: Bytes,
+    bagId: BagId,
+    objectCreationList: Vec.with(DataObjectCreationParameters),
+    deletionPrizeSourceAccountId: AccountId,
+    expectedDataSizeFee: BalanceOf,
+  })
+  implements IUploadParameters {}
+
+export class Cid extends Bytes {}
+export class ContentIdSet extends BTreeSet.with(Cid) {}
+
+export type IDistributionBucket = {
+  accepting_new_bags: bool
+  distributing: bool
+  pending_invitations: BTreeSet<WorkerId>
+  operators: BTreeSet<WorkerId>
+  assigned_bags: u64
+}
+
+export class DistributionBucket
+  extends JoyStructDecorated({
+    accepting_new_bags: bool,
+    distributing: bool,
+    pending_invitations: BTreeSet.with(WorkerId),
+    operators: BTreeSet.with(WorkerId),
+    assigned_bags: u64,
+  })
+  implements IDistributionBucket {}
+
+export type IDistributionBucketFamily = {
+  distribution_buckets: BTreeMap<DistributionBucketId, DistributionBucket>
+}
+
+export class DistributionBucketFamily
+  extends JoyStructDecorated({
+    distribution_buckets: BTreeMap.with(DistributionBucketId, DistributionBucket),
+  })
+  implements IDistributionBucketFamily {}
+
+export const storageTypes: RegistryTypes = {
+  StorageBucketId,
+  StorageBucketsPerBagValueConstraint,
+  DataObjectId,
+  DynamicBagId,
+  Voucher,
+  DynamicBagType,
+  DynamicBagCreationPolicy,
+  DynamicBagDeletionPrize,
+  DynamicBagDeletionPrizeRecord,
+  Bag,
+  StorageBucket,
+  StaticBagId,
+  Static,
+  Dynamic,
+  BagId,
+  DataObjectCreationParameters,
+  BagIdType,
+  UploadParameters,
+  StorageBucketIdSet,
+  DataObjectIdSet,
+  ContentIdSet,
+  Cid,
+  StorageBucketOperatorStatus,
+  DataObject,
+  DistributionBucketId,
+  DistributionBucketFamilyId,
+  DistributionBucket,
+  DistributionBucketFamily,
+}
+export default storageTypes

Разница между файлами не показана из-за своего большого размера
+ 287 - 271
yarn.lock


Некоторые файлы не были показаны из-за большого количества измененных файлов